@classytic/stage 0.2.0 → 0.4.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 +1 -1
- package/README.md +5 -1
- package/dist/_virtual/_rolldown/runtime.mjs +18 -0
- package/dist/assets/index.mjs +0 -1
- package/dist/atomic/aufbau.d.mts +144 -0
- package/dist/atomic/aufbau.mjs +384 -0
- package/dist/atomic/elements.d.mts +67 -0
- package/dist/atomic/elements.mjs +785 -0
- package/dist/atomic/emission.d.mts +112 -0
- package/dist/atomic/emission.mjs +179 -0
- package/dist/atomic/index.d.mts +8 -0
- package/dist/atomic/index.mjs +9 -0
- package/dist/atomic/periodic.d.mts +82 -0
- package/dist/atomic/periodic.mjs +231 -0
- package/dist/atomic/properties.d.mts +100 -0
- package/dist/atomic/properties.mjs +574 -0
- package/dist/atomic/shells.d.mts +137 -0
- package/dist/atomic/shells.mjs +170 -0
- package/dist/atomic/trends.d.mts +148 -0
- package/dist/atomic/trends.mjs +225 -0
- package/dist/builder/Palette.mjs +50 -89
- package/dist/builder/SceneBuilder.mjs +15 -73
- package/dist/chem/chromatography.d.mts +66 -0
- package/dist/chem/chromatography.mjs +63 -0
- package/dist/chem/complex.d.mts +114 -0
- package/dist/chem/complex.mjs +234 -0
- package/dist/chem/cycle.d.mts +75 -0
- package/dist/chem/cycle.mjs +145 -0
- package/dist/chem/equation.d.mts +86 -0
- package/dist/chem/equation.mjs +168 -0
- package/dist/chem/formula.d.mts +90 -0
- package/dist/chem/formula.mjs +201 -0
- package/dist/chem/functional-groups.d.mts +31 -0
- package/dist/chem/functional-groups.mjs +187 -0
- package/dist/chem/hazard.d.mts +94 -0
- package/dist/chem/hazard.mjs +329 -0
- package/dist/chem/index.d.mts +34 -33
- package/dist/chem/index.mjs +34 -28
- package/dist/chem/ionic.d.mts +98 -0
- package/dist/chem/ionic.mjs +156 -0
- package/dist/chem/layout.d.mts +46 -0
- package/dist/chem/layout.mjs +342 -0
- package/dist/chem/lewis.d.mts +79 -0
- package/dist/chem/lewis.mjs +163 -0
- package/dist/chem/molecular-orbital.d.mts +114 -0
- package/dist/chem/molecular-orbital.mjs +201 -0
- package/dist/chem/molecule.d.mts +154 -0
- package/dist/chem/molecule.mjs +282 -0
- package/dist/chem/nmr.d.mts +153 -0
- package/dist/chem/nmr.mjs +165 -0
- package/dist/chem/polymer.d.mts +65 -0
- package/dist/chem/polymer.mjs +179 -0
- package/dist/chem/redox.d.mts +138 -0
- package/dist/chem/redox.mjs +328 -0
- package/dist/chem/relations.d.mts +183 -0
- package/dist/chem/relations.mjs +299 -0
- package/dist/chem/skeleton.d.mts +51 -0
- package/dist/chem/skeleton.mjs +186 -0
- package/dist/chem/solution.d.mts +116 -0
- package/dist/chem/solution.mjs +186 -0
- package/dist/chem/species.d.mts +47 -0
- package/dist/chem/species.mjs +128 -0
- package/dist/chem/stereo.d.mts +108 -0
- package/dist/chem/stereo.mjs +286 -0
- package/dist/chem/stoichiometry.d.mts +95 -0
- package/dist/chem/stoichiometry.mjs +145 -0
- package/dist/chem/synthesis.d.mts +113 -0
- package/dist/chem/synthesis.mjs +281 -0
- package/dist/chem/vsepr.d.mts +80 -0
- package/dist/chem/vsepr.mjs +247 -0
- package/dist/circuit/ac.d.mts +163 -0
- package/dist/circuit/ac.mjs +452 -0
- package/dist/circuit/dc.d.mts +92 -0
- package/dist/circuit/dc.mjs +333 -0
- package/dist/circuit/index.d.mts +5 -92
- package/dist/circuit/index.mjs +5 -332
- package/dist/circuit/network.d.mts +99 -0
- package/dist/circuit/network.mjs +440 -0
- package/dist/circuit/topology.d.mts +102 -0
- package/dist/circuit/topology.mjs +143 -0
- package/dist/colour/absorption.d.mts +79 -0
- package/dist/colour/absorption.mjs +137 -0
- package/dist/colour/index.d.mts +6 -0
- package/dist/colour/index.mjs +7 -0
- package/dist/colour/name.d.mts +14 -0
- package/dist/colour/name.mjs +76 -0
- package/dist/colour/observer.d.mts +31 -0
- package/dist/colour/observer.mjs +46 -0
- package/dist/colour/spectrum.d.mts +61 -0
- package/dist/colour/spectrum.mjs +108 -0
- package/dist/colour/srgb.d.mts +49 -0
- package/dist/colour/srgb.mjs +108 -0
- package/dist/core/constants.d.mts +138 -0
- package/dist/core/constants.mjs +139 -0
- package/dist/core/index.d.mts +4 -1
- package/dist/core/index.mjs +4 -1
- package/dist/core/math.d.mts +26 -0
- package/dist/core/math.mjs +37 -0
- package/dist/core/vec3.d.mts +94 -0
- package/dist/core/vec3.mjs +123 -0
- package/dist/core/worked.d.mts +35 -0
- package/dist/core/worked.mjs +44 -0
- package/dist/electro/cell.d.mts +102 -0
- package/dist/electro/cell.mjs +170 -0
- package/dist/electro/conductivity.d.mts +157 -0
- package/dist/electro/conductivity.mjs +156 -0
- package/dist/electro/couples.d.mts +114 -0
- package/dist/electro/couples.mjs +334 -0
- package/dist/electro/electrolysis.d.mts +96 -0
- package/dist/electro/electrolysis.mjs +274 -0
- package/dist/electro/faraday.d.mts +150 -0
- package/dist/electro/faraday.mjs +118 -0
- package/dist/electro/index.d.mts +6 -0
- package/dist/electro/index.mjs +7 -0
- package/dist/finance/accounting/adjustments.d.mts +17 -0
- package/dist/finance/accounting/adjustments.mjs +202 -0
- package/dist/finance/accounting/analysis.d.mts +8 -0
- package/dist/finance/accounting/analysis.mjs +205 -0
- package/dist/finance/accounting/clubs.d.mts +21 -0
- package/dist/finance/accounting/clubs.mjs +217 -0
- package/dist/finance/accounting/company-statements.d.mts +7 -0
- package/dist/finance/accounting/company-statements.mjs +150 -0
- package/dist/finance/accounting/harness.d.mts +7 -0
- package/dist/finance/accounting/harness.mjs +45 -0
- package/dist/finance/accounting/index.d.mts +18 -0
- package/dist/finance/accounting/index.mjs +18 -0
- package/dist/finance/accounting/journalize.d.mts +16 -0
- package/dist/finance/accounting/journalize.mjs +128 -0
- package/dist/finance/accounting/manufacturing.d.mts +8 -0
- package/dist/finance/accounting/manufacturing.mjs +236 -0
- package/dist/finance/accounting/partnership.d.mts +7 -0
- package/dist/finance/accounting/partnership.mjs +152 -0
- package/dist/finance/accounting/period-case.d.mts +6 -0
- package/dist/finance/accounting/period-case.mjs +71 -0
- package/dist/finance/accounting/post.d.mts +9 -0
- package/dist/finance/accounting/post.mjs +84 -0
- package/dist/finance/accounting/precision.d.mts +9 -0
- package/dist/finance/accounting/precision.mjs +15 -0
- package/dist/finance/accounting/rules.d.mts +21 -0
- package/dist/finance/accounting/rules.mjs +37 -0
- package/dist/finance/accounting/solve.d.mts +28 -0
- package/dist/finance/accounting/solve.mjs +92 -0
- package/dist/finance/accounting/statements.d.mts +7 -0
- package/dist/finance/accounting/statements.mjs +142 -0
- package/dist/finance/accounting/types.d.mts +649 -0
- package/dist/finance/accounting/validate.d.mts +7 -0
- package/dist/finance/accounting/validate.mjs +67 -0
- package/dist/finance/accounting/verification.d.mts +24 -0
- package/dist/finance/accounting/verification.mjs +386 -0
- package/dist/finance/bizsim.d.mts +75 -0
- package/dist/finance/bizsim.mjs +296 -0
- package/dist/finance/index.d.mts +95 -0
- package/dist/finance/index.mjs +145 -0
- package/dist/finance/investment-math.d.mts +7 -0
- package/dist/finance/investment-math.mjs +18 -0
- package/dist/finance/management-accounting/budgeting.d.mts +7 -0
- package/dist/finance/management-accounting/budgeting.mjs +189 -0
- package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
- package/dist/finance/management-accounting/cash-budget.mjs +154 -0
- package/dist/finance/management-accounting/costing.d.mts +8 -0
- package/dist/finance/management-accounting/costing.mjs +175 -0
- package/dist/finance/management-accounting/decisions.d.mts +8 -0
- package/dist/finance/management-accounting/decisions.mjs +164 -0
- package/dist/finance/management-accounting/index.d.mts +13 -0
- package/dist/finance/management-accounting/index.mjs +13 -0
- package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
- package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
- package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
- package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
- package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
- package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
- package/dist/finance/management-accounting/management-case.d.mts +8 -0
- package/dist/finance/management-accounting/management-case.mjs +91 -0
- package/dist/finance/management-accounting/master-budget.d.mts +7 -0
- package/dist/finance/management-accounting/master-budget.mjs +137 -0
- package/dist/finance/management-accounting/production-costing.d.mts +8 -0
- package/dist/finance/management-accounting/production-costing.mjs +214 -0
- package/dist/finance/management-accounting/types.d.mts +644 -0
- package/dist/finance/management-accounting/variances.d.mts +7 -0
- package/dist/finance/management-accounting/variances.mjs +150 -0
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +5 -5
- package/dist/interaction/MovableDot.mjs +19 -0
- package/dist/interaction/useDraggable.mjs +24 -4
- package/dist/math/analysis.d.mts +61 -0
- package/dist/math/analysis.mjs +187 -0
- package/dist/math/answer-check.d.mts +50 -0
- package/dist/math/answer-check.mjs +106 -0
- package/dist/math/calculus.d.mts +17 -1
- package/dist/math/calculus.mjs +365 -2
- package/dist/math/complex.d.mts +93 -0
- package/dist/math/complex.mjs +239 -0
- package/dist/math/expr.d.mts +23 -0
- package/dist/math/expr.mjs +36 -0
- package/dist/math/index.d.mts +9 -23
- package/dist/math/index.mjs +9 -38
- package/dist/math/latex.mjs +10 -1
- package/dist/math/parse.mjs +1 -1
- package/dist/math/poly.d.mts +55 -0
- package/dist/math/poly.mjs +273 -0
- package/dist/math/rearrange.d.mts +14 -0
- package/dist/math/rearrange.mjs +125 -0
- package/dist/math/solve.d.mts +21 -0
- package/dist/math/solve.mjs +75 -0
- package/dist/networking/addressing.d.mts +26 -0
- package/dist/networking/addressing.mjs +33 -0
- package/dist/networking/cloud/access.d.mts +36 -0
- package/dist/networking/cloud/access.mjs +95 -0
- package/dist/networking/cloud/containers.d.mts +43 -0
- package/dist/networking/cloud/containers.mjs +54 -0
- package/dist/networking/cloud/edge.d.mts +17 -0
- package/dist/networking/cloud/edge.mjs +31 -0
- package/dist/networking/cloud/failure-domains.d.mts +19 -0
- package/dist/networking/cloud/failure-domains.mjs +22 -0
- package/dist/networking/cloud/geo-routing.d.mts +22 -0
- package/dist/networking/cloud/geo-routing.mjs +64 -0
- package/dist/networking/cloud/index.d.mts +18 -0
- package/dist/networking/cloud/index.mjs +19 -0
- package/dist/networking/cloud/inference-reliability.d.mts +30 -0
- package/dist/networking/cloud/inference-reliability.mjs +76 -0
- package/dist/networking/cloud/inference.d.mts +118 -0
- package/dist/networking/cloud/inference.mjs +179 -0
- package/dist/networking/cloud/infrastructure.d.mts +45 -0
- package/dist/networking/cloud/infrastructure.mjs +96 -0
- package/dist/networking/cloud/observability.d.mts +24 -0
- package/dist/networking/cloud/observability.mjs +34 -0
- package/dist/networking/cloud/orchestration.d.mts +32 -0
- package/dist/networking/cloud/orchestration.mjs +38 -0
- package/dist/networking/cloud/recovery.d.mts +21 -0
- package/dist/networking/cloud/recovery.mjs +27 -0
- package/dist/networking/cloud/releases.d.mts +42 -0
- package/dist/networking/cloud/releases.mjs +135 -0
- package/dist/networking/cloud/scaling.d.mts +25 -0
- package/dist/networking/cloud/scaling.mjs +65 -0
- package/dist/networking/cloud/secrets.d.mts +39 -0
- package/dist/networking/cloud/secrets.mjs +68 -0
- package/dist/networking/cloud/server-deployment.d.mts +29 -0
- package/dist/networking/cloud/server-deployment.mjs +72 -0
- package/dist/networking/cloud/storage.d.mts +16 -0
- package/dist/networking/cloud/storage.mjs +58 -0
- package/dist/networking/cloud/vpc.d.mts +18 -0
- package/dist/networking/cloud/vpc.mjs +100 -0
- package/dist/networking/delivery.d.mts +34 -0
- package/dist/networking/delivery.mjs +52 -0
- package/dist/networking/index.d.mts +47 -0
- package/dist/networking/index.mjs +47 -0
- package/dist/networking/ipv6.d.mts +28 -0
- package/dist/networking/ipv6.mjs +17 -0
- package/dist/networking/journeys.d.mts +83 -0
- package/dist/networking/journeys.mjs +161 -0
- package/dist/networking/models/airtime.d.mts +87 -0
- package/dist/networking/models/airtime.mjs +130 -0
- package/dist/networking/models/cellular.d.mts +157 -0
- package/dist/networking/models/cellular.mjs +252 -0
- package/dist/networking/models/encapsulation.d.mts +98 -0
- package/dist/networking/models/encapsulation.mjs +132 -0
- package/dist/networking/models/handover.d.mts +116 -0
- package/dist/networking/models/handover.mjs +209 -0
- package/dist/networking/models/handshake.d.mts +90 -0
- package/dist/networking/models/handshake.mjs +122 -0
- package/dist/networking/models/index.d.mts +14 -0
- package/dist/networking/models/index.mjs +15 -0
- package/dist/networking/models/media.d.mts +82 -0
- package/dist/networking/models/media.mjs +188 -0
- package/dist/networking/models/satellite.d.mts +86 -0
- package/dist/networking/models/satellite.mjs +121 -0
- package/dist/networking/models/spectrum.d.mts +83 -0
- package/dist/networking/models/spectrum.mjs +235 -0
- package/dist/networking/models/switch.d.mts +80 -0
- package/dist/networking/models/switch.mjs +155 -0
- package/dist/networking/models/vlan.d.mts +62 -0
- package/dist/networking/models/vlan.mjs +100 -0
- package/dist/networking/models/vpn.d.mts +66 -0
- package/dist/networking/models/vpn.mjs +125 -0
- package/dist/networking/models/wifi-privacy.d.mts +82 -0
- package/dist/networking/models/wifi-privacy.mjs +130 -0
- package/dist/networking/models/wifi.d.mts +240 -0
- package/dist/networking/models/wifi.mjs +562 -0
- package/dist/networking/nat-traversal.d.mts +24 -0
- package/dist/networking/nat-traversal.mjs +38 -0
- package/dist/networking/protocols.d.mts +17 -0
- package/dist/networking/protocols.mjs +57 -0
- package/dist/networking/queue.d.mts +12 -0
- package/dist/networking/queue.mjs +18 -0
- package/dist/networking/route-learning.d.mts +23 -0
- package/dist/networking/route-learning.mjs +43 -0
- package/dist/networking/routing.d.mts +11 -0
- package/dist/networking/routing.mjs +25 -0
- package/dist/networking/signals.d.mts +26 -0
- package/dist/networking/signals.mjs +35 -0
- package/dist/networking/subnet.d.mts +49 -0
- package/dist/networking/subnet.mjs +89 -0
- package/dist/networking/tcp-reliability.d.mts +24 -0
- package/dist/networking/tcp-reliability.mjs +38 -0
- package/dist/networking/topology/contract.d.mts +123 -0
- package/dist/networking/topology/index.d.mts +4 -0
- package/dist/networking/topology/index.mjs +4 -0
- package/dist/networking/topology/presets.d.mts +7 -0
- package/dist/networking/topology/presets.mjs +302 -0
- package/dist/networking/topology/simulation.d.mts +8 -0
- package/dist/networking/topology/simulation.mjs +179 -0
- package/dist/networking/wireless.d.mts +11 -0
- package/dist/networking/wireless.mjs +17 -0
- package/dist/optics/imaging.d.mts +218 -0
- package/dist/optics/imaging.mjs +276 -0
- package/dist/optics/index.d.mts +7 -0
- package/dist/optics/index.mjs +8 -0
- package/dist/optics/laws.d.mts +70 -0
- package/dist/optics/laws.mjs +195 -0
- package/dist/optics/prism.d.mts +148 -0
- package/dist/optics/prism.mjs +197 -0
- package/dist/optics/refraction.d.mts +201 -0
- package/dist/optics/refraction.mjs +270 -0
- package/dist/optics/wave-optics.d.mts +171 -0
- package/dist/optics/wave-optics.mjs +259 -0
- package/dist/physics/ac/index.d.mts +183 -0
- package/dist/physics/ac/index.mjs +203 -0
- package/dist/physics/dynamics/forces.d.mts +98 -0
- package/dist/physics/dynamics/forces.mjs +153 -0
- package/dist/physics/dynamics/friction.d.mts +76 -0
- package/dist/physics/dynamics/friction.mjs +119 -0
- package/dist/physics/dynamics/system.d.mts +68 -0
- package/dist/physics/dynamics/system.mjs +125 -0
- package/dist/physics/electrostatics/index.d.mts +169 -0
- package/dist/physics/electrostatics/index.mjs +249 -0
- package/dist/physics/energy/centre-of-mass.d.mts +115 -0
- package/dist/physics/energy/centre-of-mass.mjs +180 -0
- package/dist/physics/energy/conservation.d.mts +81 -0
- package/dist/physics/energy/conservation.mjs +129 -0
- package/dist/physics/energy/power.d.mts +90 -0
- package/dist/physics/energy/power.mjs +167 -0
- package/dist/physics/energy/spring.d.mts +73 -0
- package/dist/physics/energy/spring.mjs +129 -0
- package/dist/physics/energy/store.d.mts +63 -0
- package/dist/physics/energy/store.mjs +108 -0
- package/dist/physics/energy/theorem.d.mts +65 -0
- package/dist/physics/energy/theorem.mjs +113 -0
- package/dist/physics/energy/work.d.mts +114 -0
- package/dist/physics/energy/work.mjs +219 -0
- package/dist/physics/gravitation/body.d.mts +85 -0
- package/dist/physics/gravitation/body.mjs +168 -0
- package/dist/physics/gravitation/kepler.d.mts +127 -0
- package/dist/physics/gravitation/kepler.mjs +216 -0
- package/dist/physics/gravitation/law.d.mts +117 -0
- package/dist/physics/gravitation/law.mjs +175 -0
- package/dist/physics/gravitation/orbit.d.mts +119 -0
- package/dist/physics/gravitation/orbit.mjs +202 -0
- package/dist/physics/gravitation/potential.d.mts +114 -0
- package/dist/physics/gravitation/potential.mjs +202 -0
- package/dist/physics/gravitation/variation.d.mts +97 -0
- package/dist/physics/gravitation/variation.mjs +175 -0
- package/dist/physics/index.d.mts +35 -0
- package/dist/physics/index.mjs +36 -0
- package/dist/physics/integral-sweep.d.mts +63 -0
- package/dist/physics/integral-sweep.mjs +126 -0
- package/dist/physics/kinematics/equations.d.mts +47 -0
- package/dist/physics/kinematics/equations.mjs +126 -0
- package/dist/physics/kinematics/free-fall.d.mts +53 -0
- package/dist/physics/kinematics/free-fall.mjs +71 -0
- package/dist/physics/kinematics/given.d.mts +16 -0
- package/dist/physics/kinematics/given.mjs +55 -0
- package/dist/physics/kinematics/roots.d.mts +41 -0
- package/dist/physics/kinematics/roots.mjs +72 -0
- package/dist/physics/kinematics/solve.d.mts +52 -0
- package/dist/physics/kinematics/solve.mjs +172 -0
- package/dist/physics/magnetism/biot-savart.d.mts +161 -0
- package/dist/physics/magnetism/biot-savart.mjs +353 -0
- package/dist/physics/magnetism/flux.d.mts +94 -0
- package/dist/physics/magnetism/flux.mjs +313 -0
- package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
- package/dist/physics/magnetism/geomagnetism.mjs +184 -0
- package/dist/physics/magnetism/index.d.mts +12 -0
- package/dist/physics/magnetism/index.mjs +74 -0
- package/dist/physics/magnetism/lorentz.d.mts +28 -0
- package/dist/physics/magnetism/lorentz.mjs +88 -0
- package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
- package/dist/physics/magnetism/magnetic-force.mjs +169 -0
- package/dist/physics/momentum/collide.d.mts +77 -0
- package/dist/physics/momentum/collide.mjs +115 -0
- package/dist/physics/momentum/impulse.d.mts +89 -0
- package/dist/physics/momentum/impulse.mjs +159 -0
- package/dist/physics/momentum/planar.d.mts +60 -0
- package/dist/physics/momentum/planar.mjs +110 -0
- package/dist/physics/projectile.d.mts +107 -0
- package/dist/physics/projectile.mjs +185 -0
- package/dist/physics/rotation/angular.d.mts +85 -0
- package/dist/physics/rotation/angular.mjs +130 -0
- package/dist/physics/rotation/circular.d.mts +79 -0
- package/dist/physics/rotation/circular.mjs +131 -0
- package/dist/physics/rotation/inertia.d.mts +164 -0
- package/dist/physics/rotation/inertia.mjs +332 -0
- package/dist/physics/rotation/torque.d.mts +65 -0
- package/dist/physics/rotation/torque.mjs +134 -0
- package/dist/physics/vectors.d.mts +64 -0
- package/dist/physics/vectors.mjs +114 -0
- package/dist/primitives/Dot.d.mts +2 -15
- package/dist/primitives/Dot.mjs +6 -4
- package/dist/primitives/Grid.d.mts +33 -17
- package/dist/primitives/Grid.mjs +89 -17
- package/dist/primitives/Label.d.mts +1 -14
- package/dist/primitives/Label.mjs +3 -2
- package/dist/primitives/Lines.d.mts +4 -32
- package/dist/primitives/Lines.mjs +10 -8
- package/dist/primitives/Shapes.d.mts +5 -43
- package/dist/primitives/Shapes.mjs +12 -10
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/primitives/props.mjs +31 -0
- package/dist/quantity/index.d.mts +119 -0
- package/dist/quantity/index.mjs +417 -0
- package/dist/relation/derive.d.mts +74 -0
- package/dist/relation/derive.mjs +73 -0
- package/dist/relation/index.d.mts +56 -0
- package/dist/relation/index.mjs +234 -0
- package/dist/scene/Scene.d.mts +6 -1
- package/dist/scene/Scene.mjs +15 -40
- package/dist/scene/evaluators.mjs +1 -1
- package/dist/sim/thermal.mjs +45 -20
- package/dist/thermo/calorimetry.d.mts +207 -0
- package/dist/thermo/calorimetry.mjs +345 -0
- package/dist/thermo/cycles.d.mts +142 -0
- package/dist/thermo/cycles.mjs +256 -0
- package/dist/thermo/entropy.d.mts +87 -0
- package/dist/thermo/entropy.mjs +140 -0
- package/dist/thermo/expansion.d.mts +130 -0
- package/dist/thermo/expansion.mjs +178 -0
- package/dist/thermo/gas.d.mts +197 -0
- package/dist/thermo/gas.mjs +279 -0
- package/dist/thermo/heat-transfer.d.mts +164 -0
- package/dist/thermo/heat-transfer.mjs +217 -0
- package/dist/thermo/index.d.mts +9 -82
- package/dist/thermo/index.mjs +9 -132
- package/dist/thermo/processes.d.mts +95 -0
- package/dist/thermo/processes.mjs +154 -0
- package/dist/thermo/temperature.d.mts +174 -0
- package/dist/thermo/temperature.mjs +236 -0
- package/dist/view/Stage.mjs +4 -11
- package/dist/waves/damping.d.mts +224 -0
- package/dist/waves/damping.mjs +317 -0
- package/dist/waves/doppler.d.mts +72 -0
- package/dist/waves/doppler.mjs +125 -0
- package/dist/waves/index.d.mts +10 -0
- package/dist/waves/index.mjs +10 -0
- package/dist/waves/pendulum.d.mts +130 -0
- package/dist/waves/pendulum.mjs +211 -0
- package/dist/waves/pitch.d.mts +125 -0
- package/dist/waves/pitch.mjs +158 -0
- package/dist/waves/shm.d.mts +170 -0
- package/dist/waves/shm.mjs +279 -0
- package/dist/waves/springs.d.mts +103 -0
- package/dist/waves/springs.mjs +176 -0
- package/dist/waves/superposition.d.mts +124 -0
- package/dist/waves/superposition.mjs +196 -0
- package/dist/waves/wave.d.mts +154 -0
- package/dist/waves/wave.mjs +178 -0
- package/package.json +103 -23
- package/styles.css +125 -8
- package/dist/assets/kit/index.mjs +0 -4
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../../core/worked.mjs";
|
|
2
|
+
import { toRadians } from "../vectors.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/rotation/torque.ts
|
|
5
|
+
/**
|
|
6
|
+
* Torque: the rotational analogue of force, and the couple.
|
|
7
|
+
*
|
|
8
|
+
* THE ANALOGY IS THE POINT, and it is worth stating once rather than rediscovering per topic. Every
|
|
9
|
+
* equation of rotation is a linear one with the quantities swapped:
|
|
10
|
+
*
|
|
11
|
+
* s → θ v → ω a → α m → I F → τ p → L
|
|
12
|
+
*
|
|
13
|
+
* so `F = ma` becomes `τ = Iα`, `p = mv` becomes `L = Iω`, and `½mv²` becomes `½Iω²`. A student who
|
|
14
|
+
* has that mapping has the whole chapter and does not need to memorise a second set of formulas;
|
|
15
|
+
* one who does not has to learn everything twice. {@link ROTATIONAL_ANALOGUE} exists so a lesson
|
|
16
|
+
* can print it as a table.
|
|
17
|
+
*
|
|
18
|
+
* A COUPLE is the case worth separating out: two equal and opposite forces that do not share a line
|
|
19
|
+
* of action. Their resultant FORCE is exactly zero, so the body does not accelerate anywhere, and
|
|
20
|
+
* yet it turns. That is the thing a learner needs to see, because it contradicts the reasonable
|
|
21
|
+
* belief that zero net force means nothing happens. A couple's moment is also the same about EVERY
|
|
22
|
+
* point, which is why a steering wheel turns the same whichever part of it you hold.
|
|
23
|
+
*
|
|
24
|
+
* Pure: no React, no pixels.
|
|
25
|
+
*/
|
|
26
|
+
/** The linear quantity and its rotational counterpart, for a lesson that prints the mapping. */
|
|
27
|
+
const ROTATIONAL_ANALOGUE = [
|
|
28
|
+
{
|
|
29
|
+
linear: "displacement s",
|
|
30
|
+
rotational: "angle θ",
|
|
31
|
+
relation: "s = rθ"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
linear: "velocity v",
|
|
35
|
+
rotational: "angular velocity ω",
|
|
36
|
+
relation: "v = rω"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
linear: "acceleration a",
|
|
40
|
+
rotational: "angular acceleration α",
|
|
41
|
+
relation: "a = rα"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
linear: "mass m",
|
|
45
|
+
rotational: "moment of inertia I",
|
|
46
|
+
relation: "I = Σmr²"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
linear: "force F",
|
|
50
|
+
rotational: "torque τ",
|
|
51
|
+
relation: "τ = Iα"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
linear: "momentum p = mv",
|
|
55
|
+
rotational: "angular momentum L = Iω",
|
|
56
|
+
relation: "L = mvr"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
linear: "kinetic energy ½mv²",
|
|
60
|
+
rotational: "rotational KE ½Iω²",
|
|
61
|
+
relation: ""
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* The turning effect of one force: `τ = F r sin θ`.
|
|
66
|
+
*
|
|
67
|
+
* `θ` is between the force and the line from the axis to where it acts. Only the PERPENDICULAR
|
|
68
|
+
* component turns anything; a force aimed straight at the hinge has no effect however large it is,
|
|
69
|
+
* which is why you push a door at its edge and at right angles.
|
|
70
|
+
*/
|
|
71
|
+
function torque(force, distance, angleDeg = 90, sf = 3) {
|
|
72
|
+
const value = force * distance * Math.sin(toRadians(angleDeg));
|
|
73
|
+
return {
|
|
74
|
+
value,
|
|
75
|
+
worked: calc().step("\\tau = F r \\sin\\theta", "only the component at right angles to the arm turns anything").step(`\\tau = ${texSigFigs(force, sf)} \\times ${texSigFigs(distance, sf)} \\times \\sin ${texSigFigs(angleDeg, sf)}^\\circ = ${texSigFigs(value, sf)}\\ \\mathrm{N\\,m}`, angleDeg % 180 === 0 ? "aimed straight along the arm, so it turns nothing at all however hard you push" : void 0).done(value)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The moment of a couple: `M = F d`, with `d` the perpendicular distance BETWEEN the two forces.
|
|
80
|
+
*
|
|
81
|
+
* Not `F × distance from some axis`, because there is no axis in it. The moment of a couple is the
|
|
82
|
+
* same about every point in the plane, which is the property that makes it a couple rather than two
|
|
83
|
+
* separate moments, and it is why the answer never asks you where the pivot is.
|
|
84
|
+
*/
|
|
85
|
+
function couple(force, separation, sf = 3) {
|
|
86
|
+
const value = force * separation;
|
|
87
|
+
return {
|
|
88
|
+
value,
|
|
89
|
+
worked: calc().step("M = F d", "d is the perpendicular distance between the two forces, and the moment is the same about EVERY point").step(`M = ${texSigFigs(force, sf)} \\times ${texSigFigs(separation, sf)} = ${texSigFigs(value, sf)}\\ \\mathrm{N\\,m}`, "the resultant force is zero, so it does not go anywhere. It only turns").done(value)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The force a second couple needs to balance the first.
|
|
94
|
+
*
|
|
95
|
+
* Two couples balance when their moments are equal and opposite, so a wide couple can be held by a
|
|
96
|
+
* small force and a narrow one needs a large force. That is the whole of the rectangular-plate
|
|
97
|
+
* question these chapters set.
|
|
98
|
+
*/
|
|
99
|
+
function balancingCouple(known, separation, sf = 3) {
|
|
100
|
+
if (separation <= 0) throw new Error("The second couple needs a positive separation.");
|
|
101
|
+
const force = known.force * known.separation / separation;
|
|
102
|
+
return {
|
|
103
|
+
force,
|
|
104
|
+
worked: calc().step("M_1 = M_2", "in balance the two moments are equal in size and opposite in sense").step(`${texSigFigs(known.force, sf)} \\times ${texSigFigs(known.separation, sf)} = P \\times ${texSigFigs(separation, sf)}`).step(`P = ${texSigFigs(force, sf)}\\ \\mathrm{N}`, "a couple acting over a shorter distance needs a proportionally bigger force").done(force)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* `τ = Iα`: Newton's second law, rotated.
|
|
109
|
+
*
|
|
110
|
+
* Give any two and it returns the third. The same torque produces very different accelerations on
|
|
111
|
+
* bodies of the same mass shaped differently, which is the thing moment of inertia is FOR.
|
|
112
|
+
*/
|
|
113
|
+
function angularAcceleration(torqueValue, inertia, sf = 3) {
|
|
114
|
+
if (inertia <= 0) throw new Error("Moment of inertia must be positive.");
|
|
115
|
+
const alpha = torqueValue / inertia;
|
|
116
|
+
return {
|
|
117
|
+
alpha,
|
|
118
|
+
worked: calc().step("\\tau = I\\alpha", "F = ma with every quantity replaced by its rotational counterpart").step(`\\alpha = \\frac{${texSigFigs(torqueValue, sf)}}{${texSigFigs(inertia, sf)}} = ${texSigFigs(alpha, sf)}\\ \\mathrm{rad\\,s^{-2}}`, "the same torque spins a hoop far more slowly than a disc of equal mass").done(alpha)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The torque needed to change angular momentum at a given rate: `τ = dL/dt`.
|
|
123
|
+
*
|
|
124
|
+
* The more fundamental statement, and the one that survives when the moment of inertia itself is
|
|
125
|
+
* changing, which `τ = Iα` does not. Supplied as a rate rather than as a derivative because that is
|
|
126
|
+
* how the question arrives: "the angular momentum changes by this much in this time".
|
|
127
|
+
*/
|
|
128
|
+
const torqueFromRate = (deltaL, deltaT) => {
|
|
129
|
+
if (deltaT <= 0) throw new Error("The interval must be positive.");
|
|
130
|
+
return deltaL / deltaT;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
//#endregion
|
|
134
|
+
export { ROTATIONAL_ANALOGUE, angularAcceleration, balancingCouple, couple, torque, torqueFromRate };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Worked } from "../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/vectors.d.ts
|
|
4
|
+
declare const DEG: number;
|
|
5
|
+
declare const toRadians: (deg: number) => number;
|
|
6
|
+
declare const toDegrees: (rad: number) => number;
|
|
7
|
+
/** A vector as a pair of perpendicular components, in whatever unit the magnitude was in. */
|
|
8
|
+
interface Components {
|
|
9
|
+
/** Along the horizontal. */
|
|
10
|
+
readonly x: number;
|
|
11
|
+
/** Along the vertical, positive UPWARDS. See {@link SignConvention} to reinterpret. */
|
|
12
|
+
readonly y: number;
|
|
13
|
+
}
|
|
14
|
+
/** A vector as a size and a direction. */
|
|
15
|
+
interface Polar {
|
|
16
|
+
readonly magnitude: number;
|
|
17
|
+
/** Above the horizontal, in degrees. Negative points below it. */
|
|
18
|
+
readonly angleDeg: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Split a magnitude at an angle above the horizontal into horizontal and vertical parts.
|
|
22
|
+
*
|
|
23
|
+
* Rounding matters here in a way it does not elsewhere: `Math.cos(Math.PI / 2)` is 6.1e-17, not 0,
|
|
24
|
+
* and a horizontal component of 6.1e-17 propagates into a range of 1.2e-16 m, which prints as
|
|
25
|
+
* `1.22 × 10^-16 m` in a derivation a student is reading. A vertical launch has zero range and the
|
|
26
|
+
* working should say zero.
|
|
27
|
+
*/
|
|
28
|
+
declare function resolve(magnitude: number, angleDeg: number): Components;
|
|
29
|
+
/** Components back to a magnitude and a direction: the reverse of {@link resolve}. */
|
|
30
|
+
declare function compose(x: number, y: number): Polar;
|
|
31
|
+
/**
|
|
32
|
+
* The working for a resolution, for a lesson that wants to show it rather than assert it.
|
|
33
|
+
*
|
|
34
|
+
* The first line is the definition, not the substitution, because the point being taught is that
|
|
35
|
+
* the components come from a right-angled triangle whose hypotenuse is the vector.
|
|
36
|
+
*/
|
|
37
|
+
declare function resolveSteps(magnitude: number, angleDeg: number, unit: string, sf?: number): Worked;
|
|
38
|
+
/** Which vertical direction the numbers in an equation are measured as positive. */
|
|
39
|
+
type Positive = 'up' | 'down';
|
|
40
|
+
/**
|
|
41
|
+
* A declared choice of positive direction, and the signed values that follow from it.
|
|
42
|
+
*
|
|
43
|
+
* Everything a vertical-motion question gives you arrives as a magnitude plus a direction in words
|
|
44
|
+
* ("thrown upwards at 20 m/s from 10 m up, gravity 9.8 downwards"). This turns those words into
|
|
45
|
+
* the signed numbers SUVAT needs, once, in a way that can be shown and flipped.
|
|
46
|
+
*/
|
|
47
|
+
declare class SignConvention {
|
|
48
|
+
readonly positive: Positive;
|
|
49
|
+
constructor(positive: Positive);
|
|
50
|
+
/** `+1` when the given direction is the positive one, `−1` when it opposes it. */
|
|
51
|
+
sign(direction: Positive): 1 | -1;
|
|
52
|
+
/** A magnitude, signed for the direction it acts in. */
|
|
53
|
+
signed(magnitude: number, direction: Positive): number;
|
|
54
|
+
/** Gravity's acceleration under this convention: negative if up is positive. */
|
|
55
|
+
gravity(g?: number): number;
|
|
56
|
+
/** The other choice, for a lab that lets a learner flip it. */
|
|
57
|
+
flipped(): SignConvention;
|
|
58
|
+
/** A sentence a lesson can print: "Taking up as positive, g = −9.8 m/s²." */
|
|
59
|
+
describe(g?: number): string;
|
|
60
|
+
}
|
|
61
|
+
declare const upPositive: () => SignConvention;
|
|
62
|
+
declare const downPositive: () => SignConvention;
|
|
63
|
+
//#endregion
|
|
64
|
+
export { Components, DEG, Polar, Positive, SignConvention, compose, downPositive, resolve, resolveSteps, toDegrees, toRadians, upPositive };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/vectors.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resolving a vector into components, and the sign convention that decides what the components
|
|
6
|
+
* mean.
|
|
7
|
+
*
|
|
8
|
+
* Two separate ideas live here and they are usually taught as one, which is why they confuse
|
|
9
|
+
* people.
|
|
10
|
+
*
|
|
11
|
+
* The first is geometry and has no physics in it: a magnitude at an angle is the same thing as a
|
|
12
|
+
* pair of perpendicular components, `u cos θ` along and `u sin θ` across. That is true of a
|
|
13
|
+
* velocity, a force, a displacement, or a ladder against a wall.
|
|
14
|
+
*
|
|
15
|
+
* The second is bookkeeping: before any of those components can go into an equation, somebody has
|
|
16
|
+
* to say which direction counts as positive. Nothing in the world decides this. A ball thrown
|
|
17
|
+
* upwards has `u = +20, a = −9.8` if up is positive and `u = −20, a = +9.8` if down is positive,
|
|
18
|
+
* and BOTH give the same height at the same time, because the answer is a physical fact and the
|
|
19
|
+
* sign is a choice of description. Textbook chapters that print one worked solution per convention
|
|
20
|
+
* (up-positive here, down-positive there) leave students believing there are two physics.
|
|
21
|
+
*
|
|
22
|
+
* So {@link SignConvention} is a first-class object. A lab can let a learner flip it and watch the
|
|
23
|
+
* numbers in the equation change while the trajectory does not move, which is the moment the idea
|
|
24
|
+
* lands.
|
|
25
|
+
*
|
|
26
|
+
* Pure: no React, no pixels.
|
|
27
|
+
*/
|
|
28
|
+
const DEG = Math.PI / 180;
|
|
29
|
+
const toRadians = (deg) => deg * DEG;
|
|
30
|
+
const toDegrees = (rad) => rad / DEG;
|
|
31
|
+
/**
|
|
32
|
+
* Split a magnitude at an angle above the horizontal into horizontal and vertical parts.
|
|
33
|
+
*
|
|
34
|
+
* Rounding matters here in a way it does not elsewhere: `Math.cos(Math.PI / 2)` is 6.1e-17, not 0,
|
|
35
|
+
* and a horizontal component of 6.1e-17 propagates into a range of 1.2e-16 m, which prints as
|
|
36
|
+
* `1.22 × 10^-16 m` in a derivation a student is reading. A vertical launch has zero range and the
|
|
37
|
+
* working should say zero.
|
|
38
|
+
*/
|
|
39
|
+
function resolve(magnitude, angleDeg) {
|
|
40
|
+
const a = toRadians(angleDeg);
|
|
41
|
+
return {
|
|
42
|
+
x: snap(magnitude * Math.cos(a), magnitude),
|
|
43
|
+
y: snap(magnitude * Math.sin(a), magnitude)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Components back to a magnitude and a direction: the reverse of {@link resolve}. */
|
|
47
|
+
function compose(x, y) {
|
|
48
|
+
return {
|
|
49
|
+
magnitude: Math.hypot(x, y),
|
|
50
|
+
angleDeg: toDegrees(Math.atan2(y, x))
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Kill the floating-point dust that trigonometry leaves at the quarter turns.
|
|
55
|
+
*
|
|
56
|
+
* The threshold is RELATIVE to the magnitude being resolved, and that is not a refinement. A fixed
|
|
57
|
+
* 1e-12 works for a vector of size 1 and quietly stops working as the numbers grow: `cos(pi/2)` is
|
|
58
|
+
* 6.1e-17, so a force of 1e6 N at 90 degrees leaves a horizontal component of 6.1e-11, which sails
|
|
59
|
+
* past an absolute cut-off and goes on to report that a perpendicular force did POSITIVE work. That
|
|
60
|
+
* is a visible wrong answer rather than an ugly printout, which is what the absolute version was
|
|
61
|
+
* guarding against. Scaling the threshold makes the guard hold at every size.
|
|
62
|
+
*/
|
|
63
|
+
function snap(value, scale = 1) {
|
|
64
|
+
return Math.abs(value) < Math.abs(scale) * 1e-12 ? 0 : value;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The working for a resolution, for a lesson that wants to show it rather than assert it.
|
|
68
|
+
*
|
|
69
|
+
* The first line is the definition, not the substitution, because the point being taught is that
|
|
70
|
+
* the components come from a right-angled triangle whose hypotenuse is the vector.
|
|
71
|
+
*/
|
|
72
|
+
function resolveSteps(magnitude, angleDeg, unit, sf = 3) {
|
|
73
|
+
const { x, y } = resolve(magnitude, angleDeg);
|
|
74
|
+
const u = `\\ \\mathrm{${unit}}`;
|
|
75
|
+
return calc().step(`u_x = u\\cos\\theta, \\quad u_y = u\\sin\\theta`, "the vector is the hypotenuse of a right-angled triangle").step(`u = ${texSigFigs(magnitude, sf)}${u}, \\quad \\theta = ${texSigFigs(angleDeg, sf)}^\\circ`).step(`u_x = ${texSigFigs(magnitude, sf)}\\cos ${texSigFigs(angleDeg, sf)}^\\circ = ${texSigFigs(x, sf)}${u}`).step(`u_y = ${texSigFigs(magnitude, sf)}\\sin ${texSigFigs(angleDeg, sf)}^\\circ = ${texSigFigs(y, sf)}${u}`).done(Math.hypot(x, y));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A declared choice of positive direction, and the signed values that follow from it.
|
|
79
|
+
*
|
|
80
|
+
* Everything a vertical-motion question gives you arrives as a magnitude plus a direction in words
|
|
81
|
+
* ("thrown upwards at 20 m/s from 10 m up, gravity 9.8 downwards"). This turns those words into
|
|
82
|
+
* the signed numbers SUVAT needs, once, in a way that can be shown and flipped.
|
|
83
|
+
*/
|
|
84
|
+
var SignConvention = class SignConvention {
|
|
85
|
+
positive;
|
|
86
|
+
constructor(positive) {
|
|
87
|
+
this.positive = positive;
|
|
88
|
+
}
|
|
89
|
+
/** `+1` when the given direction is the positive one, `−1` when it opposes it. */
|
|
90
|
+
sign(direction) {
|
|
91
|
+
return direction === this.positive ? 1 : -1;
|
|
92
|
+
}
|
|
93
|
+
/** A magnitude, signed for the direction it acts in. */
|
|
94
|
+
signed(magnitude, direction) {
|
|
95
|
+
return this.sign(direction) * Math.abs(magnitude);
|
|
96
|
+
}
|
|
97
|
+
/** Gravity's acceleration under this convention: negative if up is positive. */
|
|
98
|
+
gravity(g = 9.8) {
|
|
99
|
+
return this.signed(g, "down");
|
|
100
|
+
}
|
|
101
|
+
/** The other choice, for a lab that lets a learner flip it. */
|
|
102
|
+
flipped() {
|
|
103
|
+
return new SignConvention(this.positive === "up" ? "down" : "up");
|
|
104
|
+
}
|
|
105
|
+
/** A sentence a lesson can print: "Taking up as positive, g = −9.8 m/s²." */
|
|
106
|
+
describe(g = 9.8) {
|
|
107
|
+
return `Taking ${this.positive} as positive, g = ${this.gravity(g)} m/s².`;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const upPositive = () => new SignConvention("up");
|
|
111
|
+
const downPositive = () => new SignConvention("down");
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
export { DEG, SignConvention, compose, downPositive, resolve, resolveSteps, toDegrees, toRadians, upPositive };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { StyleProps } from "./props.mjs";
|
|
2
|
-
import { ReactNode } from "react";
|
|
3
2
|
|
|
4
3
|
//#region src/primitives/Dot.d.ts
|
|
5
4
|
interface DotProps extends StyleProps {
|
|
@@ -8,20 +7,8 @@ interface DotProps extends StyleProps {
|
|
|
8
7
|
/** Pixel radius (never scaled). */
|
|
9
8
|
r?: number;
|
|
10
9
|
}
|
|
11
|
-
declare
|
|
12
|
-
x,
|
|
13
|
-
y,
|
|
14
|
-
r,
|
|
15
|
-
color,
|
|
16
|
-
opacity
|
|
17
|
-
}: DotProps): ReactNode;
|
|
10
|
+
declare const Dot: import("react").NamedExoticComponent<DotProps>;
|
|
18
11
|
/** A point with a contrast ring (reads clearly over any background). */
|
|
19
|
-
declare
|
|
20
|
-
x,
|
|
21
|
-
y,
|
|
22
|
-
r,
|
|
23
|
-
color,
|
|
24
|
-
opacity
|
|
25
|
-
}: DotProps): ReactNode;
|
|
12
|
+
declare const Point: import("react").NamedExoticComponent<DotProps>;
|
|
26
13
|
//#endregion
|
|
27
14
|
export { Dot, DotProps, Point };
|
package/dist/primitives/Dot.mjs
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { fmt } from "../core/coords.mjs";
|
|
4
4
|
import { useCoords } from "../core/context.mjs";
|
|
5
|
+
import { geomPropsEqual } from "./props.mjs";
|
|
6
|
+
import { memo } from "react";
|
|
5
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
8
|
|
|
7
9
|
//#region src/primitives/Dot.tsx
|
|
8
|
-
function Dot({ x, y, r = 5, color = "var(--stage-accent)", opacity = 1 }) {
|
|
10
|
+
const Dot = memo(function Dot({ x, y, r = 5, color = "var(--stage-accent)", opacity = 1 }) {
|
|
9
11
|
const [px, py] = useCoords().toPx(x, y);
|
|
10
12
|
return /* @__PURE__ */ jsx("circle", {
|
|
11
13
|
cx: fmt(px),
|
|
@@ -14,9 +16,9 @@ function Dot({ x, y, r = 5, color = "var(--stage-accent)", opacity = 1 }) {
|
|
|
14
16
|
fill: color,
|
|
15
17
|
opacity
|
|
16
18
|
});
|
|
17
|
-
}
|
|
19
|
+
}, geomPropsEqual);
|
|
18
20
|
/** A point with a contrast ring (reads clearly over any background). */
|
|
19
|
-
function Point({ x, y, r = 6, color = "var(--stage-accent)", opacity = 1 }) {
|
|
21
|
+
const Point = memo(function Point({ x, y, r = 6, color = "var(--stage-accent)", opacity = 1 }) {
|
|
20
22
|
const [px, py] = useCoords().toPx(x, y);
|
|
21
23
|
return /* @__PURE__ */ jsxs("g", {
|
|
22
24
|
opacity,
|
|
@@ -34,7 +36,7 @@ function Point({ x, y, r = 6, color = "var(--stage-accent)", opacity = 1 }) {
|
|
|
34
36
|
strokeWidth: 1.5
|
|
35
37
|
})]
|
|
36
38
|
});
|
|
37
|
-
}
|
|
39
|
+
}, geomPropsEqual);
|
|
38
40
|
|
|
39
41
|
//#endregion
|
|
40
42
|
export { Dot, Point };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
|
|
3
1
|
//#region src/primitives/Grid.d.ts
|
|
4
2
|
/** A "nice" step (1,2,5 × 10ⁿ) so ~`target` gridlines span the range. */
|
|
5
3
|
declare function niceStep(span: number, target?: number): number;
|
|
@@ -11,12 +9,35 @@ interface GridProps {
|
|
|
11
9
|
stepY?: number;
|
|
12
10
|
color?: string;
|
|
13
11
|
}
|
|
14
|
-
declare
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
declare const Grid: import("react").NamedExoticComponent<GridProps>;
|
|
13
|
+
/**
|
|
14
|
+
* A spot the axis numbers must leave clear: a point in math coordinates, widened by a half-size and
|
|
15
|
+
* shifted by an offset, both in px. A dot drawn on an axis sits exactly where that axis prints its
|
|
16
|
+
* numbers (an intercept on the y-axis lands on the y tick labels, a focus on the x-axis on the x
|
|
17
|
+
* ones), so without this the number is half-covered by the dot and both read badly.
|
|
18
|
+
*/
|
|
19
|
+
interface ClearZone {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
/** Half-width in px (default 10, a dot plus a margin). */
|
|
23
|
+
rx?: number;
|
|
24
|
+
/** Half-height in px (default 10). */
|
|
25
|
+
ry?: number;
|
|
26
|
+
dx?: number;
|
|
27
|
+
dy?: number;
|
|
28
|
+
}
|
|
29
|
+
/** The zone a `<Label>` occupies, from the same props, so a figure can keep the axis numbers off it. */
|
|
30
|
+
declare function clearOfLabel(x: number, y: number, text: string, {
|
|
31
|
+
size,
|
|
32
|
+
anchor,
|
|
33
|
+
dx,
|
|
34
|
+
dy
|
|
35
|
+
}?: {
|
|
36
|
+
size?: number;
|
|
37
|
+
anchor?: 'start' | 'middle' | 'end';
|
|
38
|
+
dx?: number;
|
|
39
|
+
dy?: number;
|
|
40
|
+
}): ClearZone;
|
|
20
41
|
interface AxesProps {
|
|
21
42
|
color?: string;
|
|
22
43
|
ticks?: boolean;
|
|
@@ -28,14 +49,9 @@ interface AxesProps {
|
|
|
28
49
|
* can READ coordinates off the grid, needed for graphs where the answer is a
|
|
29
50
|
* point (systems, plotting). Default off (most figures want a clean axis). */
|
|
30
51
|
labels?: boolean;
|
|
52
|
+
/** Places the numbers must leave clear, such as the dots and labels the figure draws on an axis. */
|
|
53
|
+
keepClear?: readonly ClearZone[];
|
|
31
54
|
}
|
|
32
|
-
declare
|
|
33
|
-
color,
|
|
34
|
-
ticks,
|
|
35
|
-
step,
|
|
36
|
-
stepX,
|
|
37
|
-
stepY,
|
|
38
|
-
labels
|
|
39
|
-
}: AxesProps): ReactNode;
|
|
55
|
+
declare const Axes: import("react").NamedExoticComponent<AxesProps>;
|
|
40
56
|
//#endregion
|
|
41
|
-
export { Axes, AxesProps, Grid, GridProps, niceStep };
|
|
57
|
+
export { Axes, AxesProps, ClearZone, Grid, GridProps, clearOfLabel, niceStep };
|
package/dist/primitives/Grid.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useCoords } from "../core/context.mjs";
|
|
4
|
+
import { memo } from "react";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
5
6
|
|
|
6
7
|
//#region src/primitives/Grid.tsx
|
|
@@ -17,7 +18,7 @@ function tickValues(min, max, step) {
|
|
|
17
18
|
for (let v = start; v <= max + step * 1e-6; v += step) out.push(Math.round(v / step) * step);
|
|
18
19
|
return out;
|
|
19
20
|
}
|
|
20
|
-
function Grid({ step, stepX, stepY, color = "var(--stage-grid)" }) {
|
|
21
|
+
const Grid = memo(function Grid({ step, stepX, stepY, color = "var(--stage-grid)" }) {
|
|
21
22
|
const c = useCoords();
|
|
22
23
|
const sx = stepX ?? step ?? niceStep(c.view.xMax - c.view.xMin);
|
|
23
24
|
const sy = stepY ?? step ?? niceStep(c.view.yMax - c.view.yMin);
|
|
@@ -47,20 +48,49 @@ function Grid({ step, stepX, stepY, color = "var(--stage-grid)" }) {
|
|
|
47
48
|
}, `gy${y}`));
|
|
48
49
|
}
|
|
49
50
|
return /* @__PURE__ */ jsx("g", { children: lines });
|
|
51
|
+
});
|
|
52
|
+
/** Roughly how wide a label renders, in px: digits and letters average a little over half an em. */
|
|
53
|
+
const textWidth = (text, size) => text.length * size * .58;
|
|
54
|
+
/** The zone a `<Label>` occupies, from the same props, so a figure can keep the axis numbers off it. */
|
|
55
|
+
function clearOfLabel(x, y, text, { size = 14, anchor = "middle", dx = 0, dy = 0 } = {}) {
|
|
56
|
+
const w = textWidth(text, size);
|
|
57
|
+
return {
|
|
58
|
+
x,
|
|
59
|
+
y,
|
|
60
|
+
dx: dx + (anchor === "start" ? w / 2 : anchor === "end" ? -w / 2 : 0),
|
|
61
|
+
dy,
|
|
62
|
+
rx: w / 2 + 3,
|
|
63
|
+
ry: size * .5 + 2
|
|
64
|
+
};
|
|
50
65
|
}
|
|
51
66
|
const fmtTick = (v) => {
|
|
52
67
|
if (Number.isInteger(v)) return String(v);
|
|
53
68
|
const r = Math.round(v * 100) / 100;
|
|
54
69
|
return String(r);
|
|
55
70
|
};
|
|
56
|
-
|
|
71
|
+
const hits = (a, b) => a.l < b.r && b.l < a.r && a.t < b.b && b.t < a.b;
|
|
72
|
+
const Axes = memo(function Axes({ color = "var(--stage-axis)", ticks = true, step, stepX, stepY, labels = false, keepClear }) {
|
|
57
73
|
const c = useCoords();
|
|
58
74
|
const sx = stepX ?? step ?? niceStep(c.view.xMax - c.view.xMin);
|
|
59
75
|
const sy = stepY ?? step ?? niceStep(c.view.yMax - c.view.yMin);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Where the axes sit when the origin is off-screen.
|
|
78
|
+
*
|
|
79
|
+
* Drawing them at coordinate 0 unconditionally means that a view which does not contain 0 puts
|
|
80
|
+
* the axis line, every tick and every number outside the canvas, so the reader loses the scale
|
|
81
|
+
* entirely and cannot tell what they are looking at. Pin each axis to the nearest edge instead,
|
|
82
|
+
* which is what a plotting library does: the ticks and numbers stay readable, and the axis is
|
|
83
|
+
* still in the right place whenever the origin IS in view.
|
|
84
|
+
*/
|
|
85
|
+
const axisY = Math.min(c.view.yMax, Math.max(c.view.yMin, 0));
|
|
86
|
+
const axisX = Math.min(c.view.xMax, Math.max(c.view.xMin, 0));
|
|
87
|
+
const originInView = axisX === 0 && axisY === 0;
|
|
88
|
+
const yLabelsRight = axisX <= c.view.xMin;
|
|
89
|
+
const xLabelsAbove = axisY <= c.view.yMin;
|
|
90
|
+
const xAxisA = c.toPx(c.view.xMin, axisY);
|
|
91
|
+
const xAxisB = c.toPx(c.view.xMax, axisY);
|
|
92
|
+
const yAxisA = c.toPx(axisX, c.view.yMin);
|
|
93
|
+
const yAxisB = c.toPx(axisX, c.view.yMax);
|
|
64
94
|
const labelStyle = {
|
|
65
95
|
paintOrder: "stroke",
|
|
66
96
|
stroke: "var(--stage-bg)",
|
|
@@ -93,9 +123,52 @@ function Axes({ color = "var(--stage-axis)", ticks = true, step, stepX, stepY, l
|
|
|
93
123
|
strokeWidth: 1.5
|
|
94
124
|
}, "ay")];
|
|
95
125
|
if (ticks) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
126
|
+
const xs = tickValues(c.view.xMin, c.view.xMax, sx).filter((x) => !(originInView && Math.abs(x) < 1e-9));
|
|
127
|
+
const ys = tickValues(c.view.yMin, c.view.yMax, sy).filter((y) => !(originInView && Math.abs(y) < 1e-9));
|
|
128
|
+
const origin = c.toPx(0, 0);
|
|
129
|
+
const xLabelAt = (x) => {
|
|
130
|
+
const p = c.toPx(x, axisY);
|
|
131
|
+
return [p[0], p[1] + (xLabelsAbove ? -12 : 14)];
|
|
132
|
+
};
|
|
133
|
+
const yLabelAt = (y) => {
|
|
134
|
+
const p = c.toPx(axisX, y);
|
|
135
|
+
return [p[0] + (yLabelsRight ? 8 : -8), p[1]];
|
|
136
|
+
};
|
|
137
|
+
const yAnchor = yLabelsRight ? "start" : "end";
|
|
138
|
+
const shown = /* @__PURE__ */ new Set();
|
|
139
|
+
if (labels) {
|
|
140
|
+
const taken = (keepClear ?? []).map((z) => {
|
|
141
|
+
const [zx, zy] = c.toPx(z.x, z.y);
|
|
142
|
+
const px = zx + (z.dx ?? 0);
|
|
143
|
+
const py = zy + (z.dy ?? 0);
|
|
144
|
+
const rx = z.rx ?? 10;
|
|
145
|
+
const ry = z.ry ?? 10;
|
|
146
|
+
return {
|
|
147
|
+
l: px - rx,
|
|
148
|
+
r: px + rx,
|
|
149
|
+
t: py - ry,
|
|
150
|
+
b: py + ry
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
const place = (key, [px, py], text, anchor) => {
|
|
154
|
+
const w = textWidth(text, 11);
|
|
155
|
+
const l = anchor === "middle" ? px - w / 2 : anchor === "end" ? px - w : px;
|
|
156
|
+
const box = {
|
|
157
|
+
l,
|
|
158
|
+
r: l + w,
|
|
159
|
+
t: py - 5,
|
|
160
|
+
b: py + 5
|
|
161
|
+
};
|
|
162
|
+
if (taken.some((t) => hits(box, t))) return;
|
|
163
|
+
taken.push(box);
|
|
164
|
+
shown.add(key);
|
|
165
|
+
};
|
|
166
|
+
if (originInView) place("l0", [origin[0] - 8, origin[1] + 12], "0", "end");
|
|
167
|
+
for (const x of xs) place(`lx${x}`, xLabelAt(x), fmtTick(x), "middle");
|
|
168
|
+
for (const y of ys) place(`ly${y}`, yLabelAt(y), fmtTick(y), yAnchor);
|
|
169
|
+
}
|
|
170
|
+
for (const x of xs) {
|
|
171
|
+
const p = c.toPx(x, axisY);
|
|
99
172
|
nodes.push(/* @__PURE__ */ jsx("line", {
|
|
100
173
|
x1: p[0],
|
|
101
174
|
y1: p[1] - 4,
|
|
@@ -104,11 +177,10 @@ function Axes({ color = "var(--stage-axis)", ticks = true, step, stepX, stepY, l
|
|
|
104
177
|
stroke: color,
|
|
105
178
|
strokeWidth: 1.5
|
|
106
179
|
}, `tx${x}`));
|
|
107
|
-
if (
|
|
180
|
+
if (shown.has(`lx${x}`)) nodes.push(num(`lx${x}`, ...xLabelAt(x), fmtTick(x), "middle"));
|
|
108
181
|
}
|
|
109
|
-
for (const y of
|
|
110
|
-
|
|
111
|
-
const p = c.toPx(0, y);
|
|
182
|
+
for (const y of ys) {
|
|
183
|
+
const p = c.toPx(axisX, y);
|
|
112
184
|
nodes.push(/* @__PURE__ */ jsx("line", {
|
|
113
185
|
x1: p[0] - 4,
|
|
114
186
|
y1: p[1],
|
|
@@ -117,12 +189,12 @@ function Axes({ color = "var(--stage-axis)", ticks = true, step, stepX, stepY, l
|
|
|
117
189
|
stroke: color,
|
|
118
190
|
strokeWidth: 1.5
|
|
119
191
|
}, `ty${y}`));
|
|
120
|
-
if (
|
|
192
|
+
if (shown.has(`ly${y}`)) nodes.push(num(`ly${y}`, ...yLabelAt(y), fmtTick(y), yAnchor));
|
|
121
193
|
}
|
|
122
|
-
if (
|
|
194
|
+
if (shown.has("l0")) nodes.push(num("l0", origin[0] - 8, origin[1] + 12, "0", "end"));
|
|
123
195
|
}
|
|
124
196
|
return /* @__PURE__ */ jsx("g", { children: nodes });
|
|
125
|
-
}
|
|
197
|
+
});
|
|
126
198
|
|
|
127
199
|
//#endregion
|
|
128
|
-
export { Axes, Grid, niceStep };
|
|
200
|
+
export { Axes, Grid, clearOfLabel, niceStep };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
|
|
3
1
|
//#region src/primitives/Label.d.ts
|
|
4
2
|
interface LabelProps {
|
|
5
3
|
x: number;
|
|
@@ -17,17 +15,6 @@ interface LabelProps {
|
|
|
17
15
|
/** Upright pixel-space text with a background-colored outline for legibility.
|
|
18
16
|
* Renders `_`/`^` as real SVG sub/superscripts via the shared `parseRichText`
|
|
19
17
|
* grammar (the same one labs' HTML `<RichText>` uses, one source of truth). */
|
|
20
|
-
declare
|
|
21
|
-
x,
|
|
22
|
-
y,
|
|
23
|
-
text,
|
|
24
|
-
color,
|
|
25
|
-
size,
|
|
26
|
-
dx,
|
|
27
|
-
dy,
|
|
28
|
-
anchor,
|
|
29
|
-
baseline,
|
|
30
|
-
weight
|
|
31
|
-
}: LabelProps): ReactNode;
|
|
18
|
+
declare const Label: import("react").NamedExoticComponent<LabelProps>;
|
|
32
19
|
//#endregion
|
|
33
20
|
export { Label, LabelProps };
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
import { fmt } from "../core/coords.mjs";
|
|
4
4
|
import { parseRichText } from "../core/richText.mjs";
|
|
5
5
|
import { useCoords } from "../core/context.mjs";
|
|
6
|
+
import { memo } from "react";
|
|
6
7
|
import { jsx } from "react/jsx-runtime";
|
|
7
8
|
|
|
8
9
|
//#region src/primitives/Label.tsx
|
|
9
10
|
/** Upright pixel-space text with a background-colored outline for legibility.
|
|
10
11
|
* Renders `_`/`^` as real SVG sub/superscripts via the shared `parseRichText`
|
|
11
12
|
* grammar (the same one labs' HTML `<RichText>` uses, one source of truth). */
|
|
12
|
-
function Label({ x, y, text, color = "var(--stage-fg)", size = 14, dx = 0, dy = 0, anchor = "middle", baseline = "middle", weight = 600 }) {
|
|
13
|
+
const Label = memo(function Label({ x, y, text, color = "var(--stage-fg)", size = 14, dx = 0, dy = 0, anchor = "middle", baseline = "middle", weight = 600 }) {
|
|
13
14
|
const [px, py] = useCoords().toPx(x, y);
|
|
14
15
|
const spans = parseRichText(text);
|
|
15
16
|
const shift = size * .32;
|
|
@@ -39,7 +40,7 @@ function Label({ x, y, text, color = "var(--stage-fg)", size = 14, dx = 0, dy =
|
|
|
39
40
|
}, i);
|
|
40
41
|
})
|
|
41
42
|
});
|
|
42
|
-
}
|
|
43
|
+
});
|
|
43
44
|
|
|
44
45
|
//#endregion
|
|
45
46
|
export { Label };
|