@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.
Files changed (458) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -1
  3. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  4. package/dist/assets/index.mjs +0 -1
  5. package/dist/atomic/aufbau.d.mts +144 -0
  6. package/dist/atomic/aufbau.mjs +384 -0
  7. package/dist/atomic/elements.d.mts +67 -0
  8. package/dist/atomic/elements.mjs +785 -0
  9. package/dist/atomic/emission.d.mts +112 -0
  10. package/dist/atomic/emission.mjs +179 -0
  11. package/dist/atomic/index.d.mts +8 -0
  12. package/dist/atomic/index.mjs +9 -0
  13. package/dist/atomic/periodic.d.mts +82 -0
  14. package/dist/atomic/periodic.mjs +231 -0
  15. package/dist/atomic/properties.d.mts +100 -0
  16. package/dist/atomic/properties.mjs +574 -0
  17. package/dist/atomic/shells.d.mts +137 -0
  18. package/dist/atomic/shells.mjs +170 -0
  19. package/dist/atomic/trends.d.mts +148 -0
  20. package/dist/atomic/trends.mjs +225 -0
  21. package/dist/builder/Palette.mjs +50 -89
  22. package/dist/builder/SceneBuilder.mjs +15 -73
  23. package/dist/chem/chromatography.d.mts +66 -0
  24. package/dist/chem/chromatography.mjs +63 -0
  25. package/dist/chem/complex.d.mts +114 -0
  26. package/dist/chem/complex.mjs +234 -0
  27. package/dist/chem/cycle.d.mts +75 -0
  28. package/dist/chem/cycle.mjs +145 -0
  29. package/dist/chem/equation.d.mts +86 -0
  30. package/dist/chem/equation.mjs +168 -0
  31. package/dist/chem/formula.d.mts +90 -0
  32. package/dist/chem/formula.mjs +201 -0
  33. package/dist/chem/functional-groups.d.mts +31 -0
  34. package/dist/chem/functional-groups.mjs +187 -0
  35. package/dist/chem/hazard.d.mts +94 -0
  36. package/dist/chem/hazard.mjs +329 -0
  37. package/dist/chem/index.d.mts +34 -33
  38. package/dist/chem/index.mjs +34 -28
  39. package/dist/chem/ionic.d.mts +98 -0
  40. package/dist/chem/ionic.mjs +156 -0
  41. package/dist/chem/layout.d.mts +46 -0
  42. package/dist/chem/layout.mjs +342 -0
  43. package/dist/chem/lewis.d.mts +79 -0
  44. package/dist/chem/lewis.mjs +163 -0
  45. package/dist/chem/molecular-orbital.d.mts +114 -0
  46. package/dist/chem/molecular-orbital.mjs +201 -0
  47. package/dist/chem/molecule.d.mts +154 -0
  48. package/dist/chem/molecule.mjs +282 -0
  49. package/dist/chem/nmr.d.mts +153 -0
  50. package/dist/chem/nmr.mjs +165 -0
  51. package/dist/chem/polymer.d.mts +65 -0
  52. package/dist/chem/polymer.mjs +179 -0
  53. package/dist/chem/redox.d.mts +138 -0
  54. package/dist/chem/redox.mjs +328 -0
  55. package/dist/chem/relations.d.mts +183 -0
  56. package/dist/chem/relations.mjs +299 -0
  57. package/dist/chem/skeleton.d.mts +51 -0
  58. package/dist/chem/skeleton.mjs +186 -0
  59. package/dist/chem/solution.d.mts +116 -0
  60. package/dist/chem/solution.mjs +186 -0
  61. package/dist/chem/species.d.mts +47 -0
  62. package/dist/chem/species.mjs +128 -0
  63. package/dist/chem/stereo.d.mts +108 -0
  64. package/dist/chem/stereo.mjs +286 -0
  65. package/dist/chem/stoichiometry.d.mts +95 -0
  66. package/dist/chem/stoichiometry.mjs +145 -0
  67. package/dist/chem/synthesis.d.mts +113 -0
  68. package/dist/chem/synthesis.mjs +281 -0
  69. package/dist/chem/vsepr.d.mts +80 -0
  70. package/dist/chem/vsepr.mjs +247 -0
  71. package/dist/circuit/ac.d.mts +163 -0
  72. package/dist/circuit/ac.mjs +452 -0
  73. package/dist/circuit/dc.d.mts +92 -0
  74. package/dist/circuit/dc.mjs +333 -0
  75. package/dist/circuit/index.d.mts +5 -92
  76. package/dist/circuit/index.mjs +5 -332
  77. package/dist/circuit/network.d.mts +99 -0
  78. package/dist/circuit/network.mjs +440 -0
  79. package/dist/circuit/topology.d.mts +102 -0
  80. package/dist/circuit/topology.mjs +143 -0
  81. package/dist/colour/absorption.d.mts +79 -0
  82. package/dist/colour/absorption.mjs +137 -0
  83. package/dist/colour/index.d.mts +6 -0
  84. package/dist/colour/index.mjs +7 -0
  85. package/dist/colour/name.d.mts +14 -0
  86. package/dist/colour/name.mjs +76 -0
  87. package/dist/colour/observer.d.mts +31 -0
  88. package/dist/colour/observer.mjs +46 -0
  89. package/dist/colour/spectrum.d.mts +61 -0
  90. package/dist/colour/spectrum.mjs +108 -0
  91. package/dist/colour/srgb.d.mts +49 -0
  92. package/dist/colour/srgb.mjs +108 -0
  93. package/dist/core/constants.d.mts +138 -0
  94. package/dist/core/constants.mjs +139 -0
  95. package/dist/core/index.d.mts +4 -1
  96. package/dist/core/index.mjs +4 -1
  97. package/dist/core/math.d.mts +26 -0
  98. package/dist/core/math.mjs +37 -0
  99. package/dist/core/vec3.d.mts +94 -0
  100. package/dist/core/vec3.mjs +123 -0
  101. package/dist/core/worked.d.mts +35 -0
  102. package/dist/core/worked.mjs +44 -0
  103. package/dist/electro/cell.d.mts +102 -0
  104. package/dist/electro/cell.mjs +170 -0
  105. package/dist/electro/conductivity.d.mts +157 -0
  106. package/dist/electro/conductivity.mjs +156 -0
  107. package/dist/electro/couples.d.mts +114 -0
  108. package/dist/electro/couples.mjs +334 -0
  109. package/dist/electro/electrolysis.d.mts +96 -0
  110. package/dist/electro/electrolysis.mjs +274 -0
  111. package/dist/electro/faraday.d.mts +150 -0
  112. package/dist/electro/faraday.mjs +118 -0
  113. package/dist/electro/index.d.mts +6 -0
  114. package/dist/electro/index.mjs +7 -0
  115. package/dist/finance/accounting/adjustments.d.mts +17 -0
  116. package/dist/finance/accounting/adjustments.mjs +202 -0
  117. package/dist/finance/accounting/analysis.d.mts +8 -0
  118. package/dist/finance/accounting/analysis.mjs +205 -0
  119. package/dist/finance/accounting/clubs.d.mts +21 -0
  120. package/dist/finance/accounting/clubs.mjs +217 -0
  121. package/dist/finance/accounting/company-statements.d.mts +7 -0
  122. package/dist/finance/accounting/company-statements.mjs +150 -0
  123. package/dist/finance/accounting/harness.d.mts +7 -0
  124. package/dist/finance/accounting/harness.mjs +45 -0
  125. package/dist/finance/accounting/index.d.mts +18 -0
  126. package/dist/finance/accounting/index.mjs +18 -0
  127. package/dist/finance/accounting/journalize.d.mts +16 -0
  128. package/dist/finance/accounting/journalize.mjs +128 -0
  129. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  130. package/dist/finance/accounting/manufacturing.mjs +236 -0
  131. package/dist/finance/accounting/partnership.d.mts +7 -0
  132. package/dist/finance/accounting/partnership.mjs +152 -0
  133. package/dist/finance/accounting/period-case.d.mts +6 -0
  134. package/dist/finance/accounting/period-case.mjs +71 -0
  135. package/dist/finance/accounting/post.d.mts +9 -0
  136. package/dist/finance/accounting/post.mjs +84 -0
  137. package/dist/finance/accounting/precision.d.mts +9 -0
  138. package/dist/finance/accounting/precision.mjs +15 -0
  139. package/dist/finance/accounting/rules.d.mts +21 -0
  140. package/dist/finance/accounting/rules.mjs +37 -0
  141. package/dist/finance/accounting/solve.d.mts +28 -0
  142. package/dist/finance/accounting/solve.mjs +92 -0
  143. package/dist/finance/accounting/statements.d.mts +7 -0
  144. package/dist/finance/accounting/statements.mjs +142 -0
  145. package/dist/finance/accounting/types.d.mts +649 -0
  146. package/dist/finance/accounting/validate.d.mts +7 -0
  147. package/dist/finance/accounting/validate.mjs +67 -0
  148. package/dist/finance/accounting/verification.d.mts +24 -0
  149. package/dist/finance/accounting/verification.mjs +386 -0
  150. package/dist/finance/bizsim.d.mts +75 -0
  151. package/dist/finance/bizsim.mjs +296 -0
  152. package/dist/finance/index.d.mts +95 -0
  153. package/dist/finance/index.mjs +145 -0
  154. package/dist/finance/investment-math.d.mts +7 -0
  155. package/dist/finance/investment-math.mjs +18 -0
  156. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  157. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  158. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  159. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  160. package/dist/finance/management-accounting/costing.d.mts +8 -0
  161. package/dist/finance/management-accounting/costing.mjs +175 -0
  162. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  163. package/dist/finance/management-accounting/decisions.mjs +164 -0
  164. package/dist/finance/management-accounting/index.d.mts +13 -0
  165. package/dist/finance/management-accounting/index.mjs +13 -0
  166. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  167. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  168. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  169. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  170. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  171. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  172. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  173. package/dist/finance/management-accounting/management-case.mjs +91 -0
  174. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  175. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  176. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  177. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  178. package/dist/finance/management-accounting/types.d.mts +644 -0
  179. package/dist/finance/management-accounting/variances.d.mts +7 -0
  180. package/dist/finance/management-accounting/variances.mjs +150 -0
  181. package/dist/index.d.mts +9 -8
  182. package/dist/index.mjs +5 -5
  183. package/dist/interaction/MovableDot.mjs +19 -0
  184. package/dist/interaction/useDraggable.mjs +24 -4
  185. package/dist/math/analysis.d.mts +61 -0
  186. package/dist/math/analysis.mjs +187 -0
  187. package/dist/math/answer-check.d.mts +50 -0
  188. package/dist/math/answer-check.mjs +106 -0
  189. package/dist/math/calculus.d.mts +17 -1
  190. package/dist/math/calculus.mjs +365 -2
  191. package/dist/math/complex.d.mts +93 -0
  192. package/dist/math/complex.mjs +239 -0
  193. package/dist/math/expr.d.mts +23 -0
  194. package/dist/math/expr.mjs +36 -0
  195. package/dist/math/index.d.mts +9 -23
  196. package/dist/math/index.mjs +9 -38
  197. package/dist/math/latex.mjs +10 -1
  198. package/dist/math/parse.mjs +1 -1
  199. package/dist/math/poly.d.mts +55 -0
  200. package/dist/math/poly.mjs +273 -0
  201. package/dist/math/rearrange.d.mts +14 -0
  202. package/dist/math/rearrange.mjs +125 -0
  203. package/dist/math/solve.d.mts +21 -0
  204. package/dist/math/solve.mjs +75 -0
  205. package/dist/networking/addressing.d.mts +26 -0
  206. package/dist/networking/addressing.mjs +33 -0
  207. package/dist/networking/cloud/access.d.mts +36 -0
  208. package/dist/networking/cloud/access.mjs +95 -0
  209. package/dist/networking/cloud/containers.d.mts +43 -0
  210. package/dist/networking/cloud/containers.mjs +54 -0
  211. package/dist/networking/cloud/edge.d.mts +17 -0
  212. package/dist/networking/cloud/edge.mjs +31 -0
  213. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  214. package/dist/networking/cloud/failure-domains.mjs +22 -0
  215. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  216. package/dist/networking/cloud/geo-routing.mjs +64 -0
  217. package/dist/networking/cloud/index.d.mts +18 -0
  218. package/dist/networking/cloud/index.mjs +19 -0
  219. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  220. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  221. package/dist/networking/cloud/inference.d.mts +118 -0
  222. package/dist/networking/cloud/inference.mjs +179 -0
  223. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  224. package/dist/networking/cloud/infrastructure.mjs +96 -0
  225. package/dist/networking/cloud/observability.d.mts +24 -0
  226. package/dist/networking/cloud/observability.mjs +34 -0
  227. package/dist/networking/cloud/orchestration.d.mts +32 -0
  228. package/dist/networking/cloud/orchestration.mjs +38 -0
  229. package/dist/networking/cloud/recovery.d.mts +21 -0
  230. package/dist/networking/cloud/recovery.mjs +27 -0
  231. package/dist/networking/cloud/releases.d.mts +42 -0
  232. package/dist/networking/cloud/releases.mjs +135 -0
  233. package/dist/networking/cloud/scaling.d.mts +25 -0
  234. package/dist/networking/cloud/scaling.mjs +65 -0
  235. package/dist/networking/cloud/secrets.d.mts +39 -0
  236. package/dist/networking/cloud/secrets.mjs +68 -0
  237. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  238. package/dist/networking/cloud/server-deployment.mjs +72 -0
  239. package/dist/networking/cloud/storage.d.mts +16 -0
  240. package/dist/networking/cloud/storage.mjs +58 -0
  241. package/dist/networking/cloud/vpc.d.mts +18 -0
  242. package/dist/networking/cloud/vpc.mjs +100 -0
  243. package/dist/networking/delivery.d.mts +34 -0
  244. package/dist/networking/delivery.mjs +52 -0
  245. package/dist/networking/index.d.mts +47 -0
  246. package/dist/networking/index.mjs +47 -0
  247. package/dist/networking/ipv6.d.mts +28 -0
  248. package/dist/networking/ipv6.mjs +17 -0
  249. package/dist/networking/journeys.d.mts +83 -0
  250. package/dist/networking/journeys.mjs +161 -0
  251. package/dist/networking/models/airtime.d.mts +87 -0
  252. package/dist/networking/models/airtime.mjs +130 -0
  253. package/dist/networking/models/cellular.d.mts +157 -0
  254. package/dist/networking/models/cellular.mjs +252 -0
  255. package/dist/networking/models/encapsulation.d.mts +98 -0
  256. package/dist/networking/models/encapsulation.mjs +132 -0
  257. package/dist/networking/models/handover.d.mts +116 -0
  258. package/dist/networking/models/handover.mjs +209 -0
  259. package/dist/networking/models/handshake.d.mts +90 -0
  260. package/dist/networking/models/handshake.mjs +122 -0
  261. package/dist/networking/models/index.d.mts +14 -0
  262. package/dist/networking/models/index.mjs +15 -0
  263. package/dist/networking/models/media.d.mts +82 -0
  264. package/dist/networking/models/media.mjs +188 -0
  265. package/dist/networking/models/satellite.d.mts +86 -0
  266. package/dist/networking/models/satellite.mjs +121 -0
  267. package/dist/networking/models/spectrum.d.mts +83 -0
  268. package/dist/networking/models/spectrum.mjs +235 -0
  269. package/dist/networking/models/switch.d.mts +80 -0
  270. package/dist/networking/models/switch.mjs +155 -0
  271. package/dist/networking/models/vlan.d.mts +62 -0
  272. package/dist/networking/models/vlan.mjs +100 -0
  273. package/dist/networking/models/vpn.d.mts +66 -0
  274. package/dist/networking/models/vpn.mjs +125 -0
  275. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  276. package/dist/networking/models/wifi-privacy.mjs +130 -0
  277. package/dist/networking/models/wifi.d.mts +240 -0
  278. package/dist/networking/models/wifi.mjs +562 -0
  279. package/dist/networking/nat-traversal.d.mts +24 -0
  280. package/dist/networking/nat-traversal.mjs +38 -0
  281. package/dist/networking/protocols.d.mts +17 -0
  282. package/dist/networking/protocols.mjs +57 -0
  283. package/dist/networking/queue.d.mts +12 -0
  284. package/dist/networking/queue.mjs +18 -0
  285. package/dist/networking/route-learning.d.mts +23 -0
  286. package/dist/networking/route-learning.mjs +43 -0
  287. package/dist/networking/routing.d.mts +11 -0
  288. package/dist/networking/routing.mjs +25 -0
  289. package/dist/networking/signals.d.mts +26 -0
  290. package/dist/networking/signals.mjs +35 -0
  291. package/dist/networking/subnet.d.mts +49 -0
  292. package/dist/networking/subnet.mjs +89 -0
  293. package/dist/networking/tcp-reliability.d.mts +24 -0
  294. package/dist/networking/tcp-reliability.mjs +38 -0
  295. package/dist/networking/topology/contract.d.mts +123 -0
  296. package/dist/networking/topology/index.d.mts +4 -0
  297. package/dist/networking/topology/index.mjs +4 -0
  298. package/dist/networking/topology/presets.d.mts +7 -0
  299. package/dist/networking/topology/presets.mjs +302 -0
  300. package/dist/networking/topology/simulation.d.mts +8 -0
  301. package/dist/networking/topology/simulation.mjs +179 -0
  302. package/dist/networking/wireless.d.mts +11 -0
  303. package/dist/networking/wireless.mjs +17 -0
  304. package/dist/optics/imaging.d.mts +218 -0
  305. package/dist/optics/imaging.mjs +276 -0
  306. package/dist/optics/index.d.mts +7 -0
  307. package/dist/optics/index.mjs +8 -0
  308. package/dist/optics/laws.d.mts +70 -0
  309. package/dist/optics/laws.mjs +195 -0
  310. package/dist/optics/prism.d.mts +148 -0
  311. package/dist/optics/prism.mjs +197 -0
  312. package/dist/optics/refraction.d.mts +201 -0
  313. package/dist/optics/refraction.mjs +270 -0
  314. package/dist/optics/wave-optics.d.mts +171 -0
  315. package/dist/optics/wave-optics.mjs +259 -0
  316. package/dist/physics/ac/index.d.mts +183 -0
  317. package/dist/physics/ac/index.mjs +203 -0
  318. package/dist/physics/dynamics/forces.d.mts +98 -0
  319. package/dist/physics/dynamics/forces.mjs +153 -0
  320. package/dist/physics/dynamics/friction.d.mts +76 -0
  321. package/dist/physics/dynamics/friction.mjs +119 -0
  322. package/dist/physics/dynamics/system.d.mts +68 -0
  323. package/dist/physics/dynamics/system.mjs +125 -0
  324. package/dist/physics/electrostatics/index.d.mts +169 -0
  325. package/dist/physics/electrostatics/index.mjs +249 -0
  326. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  327. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  328. package/dist/physics/energy/conservation.d.mts +81 -0
  329. package/dist/physics/energy/conservation.mjs +129 -0
  330. package/dist/physics/energy/power.d.mts +90 -0
  331. package/dist/physics/energy/power.mjs +167 -0
  332. package/dist/physics/energy/spring.d.mts +73 -0
  333. package/dist/physics/energy/spring.mjs +129 -0
  334. package/dist/physics/energy/store.d.mts +63 -0
  335. package/dist/physics/energy/store.mjs +108 -0
  336. package/dist/physics/energy/theorem.d.mts +65 -0
  337. package/dist/physics/energy/theorem.mjs +113 -0
  338. package/dist/physics/energy/work.d.mts +114 -0
  339. package/dist/physics/energy/work.mjs +219 -0
  340. package/dist/physics/gravitation/body.d.mts +85 -0
  341. package/dist/physics/gravitation/body.mjs +168 -0
  342. package/dist/physics/gravitation/kepler.d.mts +127 -0
  343. package/dist/physics/gravitation/kepler.mjs +216 -0
  344. package/dist/physics/gravitation/law.d.mts +117 -0
  345. package/dist/physics/gravitation/law.mjs +175 -0
  346. package/dist/physics/gravitation/orbit.d.mts +119 -0
  347. package/dist/physics/gravitation/orbit.mjs +202 -0
  348. package/dist/physics/gravitation/potential.d.mts +114 -0
  349. package/dist/physics/gravitation/potential.mjs +202 -0
  350. package/dist/physics/gravitation/variation.d.mts +97 -0
  351. package/dist/physics/gravitation/variation.mjs +175 -0
  352. package/dist/physics/index.d.mts +35 -0
  353. package/dist/physics/index.mjs +36 -0
  354. package/dist/physics/integral-sweep.d.mts +63 -0
  355. package/dist/physics/integral-sweep.mjs +126 -0
  356. package/dist/physics/kinematics/equations.d.mts +47 -0
  357. package/dist/physics/kinematics/equations.mjs +126 -0
  358. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  359. package/dist/physics/kinematics/free-fall.mjs +71 -0
  360. package/dist/physics/kinematics/given.d.mts +16 -0
  361. package/dist/physics/kinematics/given.mjs +55 -0
  362. package/dist/physics/kinematics/roots.d.mts +41 -0
  363. package/dist/physics/kinematics/roots.mjs +72 -0
  364. package/dist/physics/kinematics/solve.d.mts +52 -0
  365. package/dist/physics/kinematics/solve.mjs +172 -0
  366. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  367. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  368. package/dist/physics/magnetism/flux.d.mts +94 -0
  369. package/dist/physics/magnetism/flux.mjs +313 -0
  370. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  371. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  372. package/dist/physics/magnetism/index.d.mts +12 -0
  373. package/dist/physics/magnetism/index.mjs +74 -0
  374. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  375. package/dist/physics/magnetism/lorentz.mjs +88 -0
  376. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  377. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  378. package/dist/physics/momentum/collide.d.mts +77 -0
  379. package/dist/physics/momentum/collide.mjs +115 -0
  380. package/dist/physics/momentum/impulse.d.mts +89 -0
  381. package/dist/physics/momentum/impulse.mjs +159 -0
  382. package/dist/physics/momentum/planar.d.mts +60 -0
  383. package/dist/physics/momentum/planar.mjs +110 -0
  384. package/dist/physics/projectile.d.mts +107 -0
  385. package/dist/physics/projectile.mjs +185 -0
  386. package/dist/physics/rotation/angular.d.mts +85 -0
  387. package/dist/physics/rotation/angular.mjs +130 -0
  388. package/dist/physics/rotation/circular.d.mts +79 -0
  389. package/dist/physics/rotation/circular.mjs +131 -0
  390. package/dist/physics/rotation/inertia.d.mts +164 -0
  391. package/dist/physics/rotation/inertia.mjs +332 -0
  392. package/dist/physics/rotation/torque.d.mts +65 -0
  393. package/dist/physics/rotation/torque.mjs +134 -0
  394. package/dist/physics/vectors.d.mts +64 -0
  395. package/dist/physics/vectors.mjs +114 -0
  396. package/dist/primitives/Dot.d.mts +2 -15
  397. package/dist/primitives/Dot.mjs +6 -4
  398. package/dist/primitives/Grid.d.mts +33 -17
  399. package/dist/primitives/Grid.mjs +89 -17
  400. package/dist/primitives/Label.d.mts +1 -14
  401. package/dist/primitives/Label.mjs +3 -2
  402. package/dist/primitives/Lines.d.mts +4 -32
  403. package/dist/primitives/Lines.mjs +10 -8
  404. package/dist/primitives/Shapes.d.mts +5 -43
  405. package/dist/primitives/Shapes.mjs +12 -10
  406. package/dist/primitives/index.d.mts +2 -2
  407. package/dist/primitives/index.mjs +2 -2
  408. package/dist/primitives/props.mjs +31 -0
  409. package/dist/quantity/index.d.mts +119 -0
  410. package/dist/quantity/index.mjs +417 -0
  411. package/dist/relation/derive.d.mts +74 -0
  412. package/dist/relation/derive.mjs +73 -0
  413. package/dist/relation/index.d.mts +56 -0
  414. package/dist/relation/index.mjs +234 -0
  415. package/dist/scene/Scene.d.mts +6 -1
  416. package/dist/scene/Scene.mjs +15 -40
  417. package/dist/scene/evaluators.mjs +1 -1
  418. package/dist/sim/thermal.mjs +45 -20
  419. package/dist/thermo/calorimetry.d.mts +207 -0
  420. package/dist/thermo/calorimetry.mjs +345 -0
  421. package/dist/thermo/cycles.d.mts +142 -0
  422. package/dist/thermo/cycles.mjs +256 -0
  423. package/dist/thermo/entropy.d.mts +87 -0
  424. package/dist/thermo/entropy.mjs +140 -0
  425. package/dist/thermo/expansion.d.mts +130 -0
  426. package/dist/thermo/expansion.mjs +178 -0
  427. package/dist/thermo/gas.d.mts +197 -0
  428. package/dist/thermo/gas.mjs +279 -0
  429. package/dist/thermo/heat-transfer.d.mts +164 -0
  430. package/dist/thermo/heat-transfer.mjs +217 -0
  431. package/dist/thermo/index.d.mts +9 -82
  432. package/dist/thermo/index.mjs +9 -132
  433. package/dist/thermo/processes.d.mts +95 -0
  434. package/dist/thermo/processes.mjs +154 -0
  435. package/dist/thermo/temperature.d.mts +174 -0
  436. package/dist/thermo/temperature.mjs +236 -0
  437. package/dist/view/Stage.mjs +4 -11
  438. package/dist/waves/damping.d.mts +224 -0
  439. package/dist/waves/damping.mjs +317 -0
  440. package/dist/waves/doppler.d.mts +72 -0
  441. package/dist/waves/doppler.mjs +125 -0
  442. package/dist/waves/index.d.mts +10 -0
  443. package/dist/waves/index.mjs +10 -0
  444. package/dist/waves/pendulum.d.mts +130 -0
  445. package/dist/waves/pendulum.mjs +211 -0
  446. package/dist/waves/pitch.d.mts +125 -0
  447. package/dist/waves/pitch.mjs +158 -0
  448. package/dist/waves/shm.d.mts +170 -0
  449. package/dist/waves/shm.mjs +279 -0
  450. package/dist/waves/springs.d.mts +103 -0
  451. package/dist/waves/springs.mjs +176 -0
  452. package/dist/waves/superposition.d.mts +124 -0
  453. package/dist/waves/superposition.mjs +196 -0
  454. package/dist/waves/wave.d.mts +154 -0
  455. package/dist/waves/wave.mjs +178 -0
  456. package/package.json +103 -23
  457. package/styles.css +125 -8
  458. package/dist/assets/kit/index.mjs +0 -4
@@ -0,0 +1,112 @@
1
+ //#region src/atomic/emission.d.ts
2
+ /**
3
+ * What an element emits when it is heated, as wavelengths rather than as a colour word.
4
+ *
5
+ * ## Why a spectrum and not a swatch
6
+ *
7
+ * A flame test is usually taught as a table of colour names: sodium golden yellow, barium apple
8
+ * green, potassium lilac. Those names are the end of the explanation rather than the start of one,
9
+ * and they cannot be checked. An electron falling between two levels emits a photon of a definite
10
+ * wavelength, and the colour is what the eye makes of the wavelengths that arrive. So this file
11
+ * holds the wavelengths, and the colour engine turns them into something to draw with. Neither
12
+ * file knows about the other: {@link emissionSpectrum} returns a plain function of wavelength,
13
+ * which is exactly the shape the colour engine already consumes.
14
+ *
15
+ * That also means the flame in a lab is the colour the element really emits, and a learner can be
16
+ * shown the lines that produced it.
17
+ *
18
+ * ## Not every flame colour is atomic, and pretending otherwise is wrong
19
+ *
20
+ * Sodium, lithium, potassium, rubidium and caesium glow from transitions in the free ATOM. The
21
+ * alkaline earths do not. Calcium, strontium and barium owe their flame colours largely to bands
22
+ * from the monohydroxide molecules CaOH, SrOH and BaOH formed in the flame, which is why their
23
+ * emission is broad where sodium's is a razor-thin pair of lines. Each entry records which it is,
24
+ * because "barium is green" and "a barium compound puts BaOH into the flame and that is green" are
25
+ * different statements and only the second explains anything.
26
+ *
27
+ * ## The lines you cannot see are the interesting ones
28
+ *
29
+ * Potassium's strongest emission is a pair of lines at 766 and 770 nm, which is infrared: the eye
30
+ * cannot see them at all. What is seen is a much weaker violet line at 404 nm, which is why
31
+ * potassium reads as a pale lilac rather than as the blazing colour its line strengths suggest.
32
+ * Caesium is the same story with its main output at 852 and 894 nm and a blue line at 455 nm doing
33
+ * all the visible work. Those lines are kept in the data with their real strengths, so the
34
+ * calculation has to discard them the way an eye does rather than having them quietly removed.
35
+ *
36
+ * Wavelengths are the standard measured values for these transitions. Relative strengths are
37
+ * approximate and are there to weight the mixture, not to be read as photometry.
38
+ *
39
+ * Pure: no React, no pixels. No dependency on the colour engine.
40
+ */
41
+ /** Where a line comes from, because it changes what the flame test is evidence of. */
42
+ type EmitterKind = 'atom' | 'molecule';
43
+ interface EmissionLine {
44
+ /** Wavelength in nanometres. */
45
+ readonly nm: number;
46
+ /** Relative strength within this element's own spectrum, largest 1. */
47
+ readonly strength: number;
48
+ /**
49
+ * How wide the feature is, in nanometres.
50
+ *
51
+ * An atomic line is essentially a single wavelength and is given a nominal width so it can be
52
+ * integrated; a molecular band is genuinely broad, and drawing it as a line would misrepresent it.
53
+ */
54
+ readonly widthNm: number;
55
+ }
56
+ interface FlameEmitter {
57
+ readonly element: string;
58
+ /** The species that actually emits: the free atom, or the molecule formed in the flame. */
59
+ readonly emitter: string;
60
+ readonly kind: EmitterKind;
61
+ readonly lines: readonly EmissionLine[];
62
+ /** What the flame is conventionally called, kept so a computed colour can be compared with it. */
63
+ readonly describedAs: string;
64
+ }
65
+ /**
66
+ * The elements a flame test identifies.
67
+ *
68
+ * Keyed by the metal, since that is what the test detects: the anion plays no part, which is why
69
+ * sodium chloride and sodium carbonate give the same flame.
70
+ */
71
+ declare const FLAME_EMITTERS: readonly FlameEmitter[];
72
+ /** The flame emitter for a metal, or undefined if this engine has no data for it. */
73
+ declare const flameEmitterFor: (element: string) => FlameEmitter | undefined;
74
+ /**
75
+ * A set of lines as a continuous spectrum: intensity against wavelength.
76
+ *
77
+ * Each line is a Gaussian of its own width, so an atomic line comes out narrow and a molecular band
78
+ * broad. The return type is a plain function of wavelength, which is deliberately the same shape
79
+ * the colour engine takes, so the two compose without either importing the other.
80
+ */
81
+ declare function emissionSpectrum(lines: readonly EmissionLine[]): (nm: number) => number;
82
+ /** The spectrum of a metal's flame, ready to hand to the colour engine. */
83
+ declare function flameSpectrum(element: string): (nm: number) => number;
84
+ /**
85
+ * The range a line has to fall in to contribute anything a viewer can see, in nanometres.
86
+ *
87
+ * Deliberately narrower than the 380 to 780 often quoted as "the visible spectrum". The eye does
88
+ * not stop at a cliff: its response tails away, and by 700 nm it is under half a per cent of its
89
+ * peak. A line at 766 nm is inside the quoted range and contributes nothing whatsoever, so treating
90
+ * that range as a yes-or-no test called potassium's brightest lines visible when the whole point of
91
+ * them is that they are not.
92
+ *
93
+ * This is a threshold for a boolean question. The colour calculation does not use it at all: there
94
+ * the CIE curves weight every wavelength by how strongly the eye actually responds, which is the
95
+ * proper treatment and needs no cutoff.
96
+ */
97
+ declare const VISIBLE_RANGE: {
98
+ readonly minNm: 380;
99
+ readonly maxNm: 700;
100
+ };
101
+ /** Whether a line lies in the range the eye responds to. */
102
+ declare const isVisible: (line: EmissionLine) => boolean;
103
+ /**
104
+ * The fraction of an element's emitted strength that the eye can see at all.
105
+ *
106
+ * Small for potassium and caesium, whose strongest output is infrared. Worth having as a number
107
+ * because "most of what potassium emits is invisible" is the explanation for why its flame looks
108
+ * so much fainter than its line strengths suggest.
109
+ */
110
+ declare function visibleFraction(element: string): number;
111
+ //#endregion
112
+ export { EmissionLine, EmitterKind, FLAME_EMITTERS, FlameEmitter, VISIBLE_RANGE, emissionSpectrum, flameEmitterFor, flameSpectrum, isVisible, visibleFraction };
@@ -0,0 +1,179 @@
1
+ //#region src/atomic/emission.ts
2
+ const atom = (nm, strength) => ({
3
+ nm,
4
+ strength,
5
+ widthNm: 2
6
+ });
7
+ const band = (nm, strength, widthNm = 18) => ({
8
+ nm,
9
+ strength,
10
+ widthNm
11
+ });
12
+ /**
13
+ * The elements a flame test identifies.
14
+ *
15
+ * Keyed by the metal, since that is what the test detects: the anion plays no part, which is why
16
+ * sodium chloride and sodium carbonate give the same flame.
17
+ */
18
+ const FLAME_EMITTERS = [
19
+ {
20
+ element: "Li",
21
+ emitter: "Li",
22
+ kind: "atom",
23
+ lines: [atom(670.8, 1), atom(610.4, .15)],
24
+ describedAs: "crimson"
25
+ },
26
+ {
27
+ element: "Na",
28
+ emitter: "Na",
29
+ kind: "atom",
30
+ lines: [atom(589, 1), atom(589.6, .9)],
31
+ describedAs: "golden yellow"
32
+ },
33
+ {
34
+ element: "K",
35
+ emitter: "K",
36
+ kind: "atom",
37
+ lines: [
38
+ atom(766.5, 1),
39
+ atom(769.9, .5),
40
+ atom(404.4, .06),
41
+ atom(404.7, .03)
42
+ ],
43
+ describedAs: "lilac"
44
+ },
45
+ {
46
+ element: "Rb",
47
+ emitter: "Rb",
48
+ kind: "atom",
49
+ lines: [
50
+ atom(780, 1),
51
+ atom(794.8, .5),
52
+ atom(420.2, .05),
53
+ atom(421.6, .03)
54
+ ],
55
+ describedAs: "red violet"
56
+ },
57
+ {
58
+ element: "Cs",
59
+ emitter: "Cs",
60
+ kind: "atom",
61
+ lines: [
62
+ atom(852.1, 1),
63
+ atom(894.3, .5),
64
+ atom(455.5, .05),
65
+ atom(459.3, .03)
66
+ ],
67
+ describedAs: "blue"
68
+ },
69
+ {
70
+ element: "Ca",
71
+ emitter: "CaOH",
72
+ kind: "molecule",
73
+ lines: [
74
+ band(622, 1),
75
+ band(554, .7),
76
+ atom(422.7, .4)
77
+ ],
78
+ describedAs: "brick red"
79
+ },
80
+ {
81
+ element: "Sr",
82
+ emitter: "SrOH",
83
+ kind: "molecule",
84
+ lines: [
85
+ band(682, 1, 22),
86
+ band(661, .8),
87
+ band(606, .5),
88
+ atom(460.7, .3)
89
+ ],
90
+ describedAs: "crimson"
91
+ },
92
+ {
93
+ element: "Ba",
94
+ emitter: "BaOH",
95
+ kind: "molecule",
96
+ lines: [
97
+ band(524, 1, 20),
98
+ band(514, .8),
99
+ band(487, .3),
100
+ atom(553.5, .5)
101
+ ],
102
+ describedAs: "apple green"
103
+ },
104
+ {
105
+ element: "Cu",
106
+ emitter: "CuCl",
107
+ kind: "molecule",
108
+ lines: [
109
+ band(535, 1, 24),
110
+ band(515, .8),
111
+ atom(510.6, .4),
112
+ atom(578.2, .3)
113
+ ],
114
+ describedAs: "blue green"
115
+ }
116
+ ];
117
+ const BY_ELEMENT = new Map(FLAME_EMITTERS.map((e) => [e.element, e]));
118
+ /** The flame emitter for a metal, or undefined if this engine has no data for it. */
119
+ const flameEmitterFor = (element) => BY_ELEMENT.get(element);
120
+ /**
121
+ * A set of lines as a continuous spectrum: intensity against wavelength.
122
+ *
123
+ * Each line is a Gaussian of its own width, so an atomic line comes out narrow and a molecular band
124
+ * broad. The return type is a plain function of wavelength, which is deliberately the same shape
125
+ * the colour engine takes, so the two compose without either importing the other.
126
+ */
127
+ function emissionSpectrum(lines) {
128
+ return (nm) => {
129
+ let total = 0;
130
+ for (const line of lines) {
131
+ const sigma = line.widthNm / 2.3548;
132
+ const offset = (nm - line.nm) / sigma;
133
+ total += line.strength * Math.exp(-.5 * offset * offset);
134
+ }
135
+ return total;
136
+ };
137
+ }
138
+ /** The spectrum of a metal's flame, ready to hand to the colour engine. */
139
+ function flameSpectrum(element) {
140
+ const emitter = flameEmitterFor(element);
141
+ if (!emitter) throw new Error(`no flame emission data for ${element}`);
142
+ return emissionSpectrum(emitter.lines);
143
+ }
144
+ /**
145
+ * The range a line has to fall in to contribute anything a viewer can see, in nanometres.
146
+ *
147
+ * Deliberately narrower than the 380 to 780 often quoted as "the visible spectrum". The eye does
148
+ * not stop at a cliff: its response tails away, and by 700 nm it is under half a per cent of its
149
+ * peak. A line at 766 nm is inside the quoted range and contributes nothing whatsoever, so treating
150
+ * that range as a yes-or-no test called potassium's brightest lines visible when the whole point of
151
+ * them is that they are not.
152
+ *
153
+ * This is a threshold for a boolean question. The colour calculation does not use it at all: there
154
+ * the CIE curves weight every wavelength by how strongly the eye actually responds, which is the
155
+ * proper treatment and needs no cutoff.
156
+ */
157
+ const VISIBLE_RANGE = {
158
+ minNm: 380,
159
+ maxNm: 700
160
+ };
161
+ /** Whether a line lies in the range the eye responds to. */
162
+ const isVisible = (line) => line.nm >= VISIBLE_RANGE.minNm && line.nm <= VISIBLE_RANGE.maxNm;
163
+ /**
164
+ * The fraction of an element's emitted strength that the eye can see at all.
165
+ *
166
+ * Small for potassium and caesium, whose strongest output is infrared. Worth having as a number
167
+ * because "most of what potassium emits is invisible" is the explanation for why its flame looks
168
+ * so much fainter than its line strengths suggest.
169
+ */
170
+ function visibleFraction(element) {
171
+ const emitter = flameEmitterFor(element);
172
+ if (!emitter) throw new Error(`no flame emission data for ${element}`);
173
+ const total = emitter.lines.reduce((sum, l) => sum + l.strength, 0);
174
+ const seen = emitter.lines.filter(isVisible).reduce((sum, l) => sum + l.strength, 0);
175
+ return total === 0 ? 0 : seen / total;
176
+ }
177
+
178
+ //#endregion
179
+ export { FLAME_EMITTERS, VISIBLE_RANGE, emissionSpectrum, flameEmitterFor, flameSpectrum, isVisible, visibleFraction };
@@ -0,0 +1,8 @@
1
+ import { ELECTRONS_PER_ORBITAL, QuantumNumbers, SUBSHELL_LETTERS, Shell, Subshell, SubshellLetter, isPauliValid, isValidQuantumNumbers, magneticNumbers, orbitalsInSubshell, orbitalsOf, quantumNumbersRefusal, shell, shellCapacity, shellLetter, subshell, subshellCapacity, subshellLetter, subshellsOf } from "./shells.mjs";
2
+ import { ANOMALIES, Anomaly, Configuration, Occupancy, OrbitalBox, anomalyFor, aufbauConfiguration, condensedConfiguration, configurationOf, fillingOrder, formatConfiguration, ionConfigurationOf, occupancyLabel, orbitalDiagram, unpairedElectrons } from "./aufbau.mjs";
3
+ import { Block, Family, GROUP_3_NOTE, Placement, TransitionVerdict, blockOf, familyOf, groupOf, isTransitionElement, periodOf, placementOf, romanGroupOf, transitionVerdict, valenceElectronsOf } from "./periodic.mjs";
4
+ import { ELEMENTS, ElementRecord, MASS_INVERSIONS, elementByName, elementBySymbol, elementOf, symbolOf } from "./elements.mjs";
5
+ import { EmissionLine, EmitterKind, FLAME_EMITTERS, FlameEmitter, VISIBLE_RANGE, emissionSpectrum, flameEmitterFor, flameSpectrum, isVisible, visibleFraction } from "./emission.mjs";
6
+ import { ElementProperties, FIRST_ELECTRON_AFFINITY, NOBLE_GAS_RADIUS_NOTE, PROPERTIES, SUCCESSIVE_IONISATION_ENERGIES, covalentRadius, electronegativity, firstIonisationEnergy, propertiesOf } from "./properties.mjs";
7
+ import { BondCharacter, DataPoint, Direction, IONISATION_ANOMALIES, IonisationAnomaly, PropertyName, ShellEvidence, Trend, acrossPeriod, bondBetween, bondCharacter, compareIonisationEnergy, downGroup, electronegativityGap, ionicCharacter, ionisationAnomalyFor, outerElectronsFromIonisation, outerElectronsOf, trendOf } from "./trends.mjs";
8
+ export { ANOMALIES, type Anomaly, type Block, type BondCharacter, type Configuration, type DataPoint, type Direction, ELECTRONS_PER_ORBITAL, ELEMENTS, type ElementProperties, type ElementRecord, type EmissionLine, type EmitterKind, FIRST_ELECTRON_AFFINITY, FLAME_EMITTERS, type Family, type FlameEmitter, GROUP_3_NOTE, IONISATION_ANOMALIES, type IonisationAnomaly, MASS_INVERSIONS, NOBLE_GAS_RADIUS_NOTE, type Occupancy, type OrbitalBox, PROPERTIES, type Placement, type PropertyName, type QuantumNumbers, SUBSHELL_LETTERS, SUCCESSIVE_IONISATION_ENERGIES, type Shell, type ShellEvidence, type Subshell, type SubshellLetter, type TransitionVerdict, type Trend, VISIBLE_RANGE, acrossPeriod, anomalyFor, aufbauConfiguration, blockOf, bondBetween, bondCharacter, compareIonisationEnergy, condensedConfiguration, configurationOf, covalentRadius, downGroup, electronegativity, electronegativityGap, elementByName, elementBySymbol, elementOf, emissionSpectrum, familyOf, fillingOrder, firstIonisationEnergy, flameEmitterFor, flameSpectrum, formatConfiguration, groupOf, ionConfigurationOf, ionicCharacter, ionisationAnomalyFor, isPauliValid, isTransitionElement, isValidQuantumNumbers, isVisible, magneticNumbers, occupancyLabel, orbitalDiagram, orbitalsInSubshell, orbitalsOf, outerElectronsFromIonisation, outerElectronsOf, periodOf, placementOf, propertiesOf, quantumNumbersRefusal, romanGroupOf, shell, shellCapacity, shellLetter, subshell, subshellCapacity, subshellLetter, subshellsOf, symbolOf, transitionVerdict, trendOf, unpairedElectrons, valenceElectronsOf, visibleFraction };
@@ -0,0 +1,9 @@
1
+ import { ELECTRONS_PER_ORBITAL, SUBSHELL_LETTERS, isPauliValid, isValidQuantumNumbers, magneticNumbers, orbitalsInSubshell, orbitalsOf, quantumNumbersRefusal, shell, shellCapacity, shellLetter, subshell, subshellCapacity, subshellLetter, subshellsOf } from "./shells.mjs";
2
+ import { ANOMALIES, anomalyFor, aufbauConfiguration, condensedConfiguration, configurationOf, fillingOrder, formatConfiguration, ionConfigurationOf, occupancyLabel, orbitalDiagram, unpairedElectrons } from "./aufbau.mjs";
3
+ import { GROUP_3_NOTE, blockOf, familyOf, groupOf, isTransitionElement, periodOf, placementOf, romanGroupOf, transitionVerdict, valenceElectronsOf } from "./periodic.mjs";
4
+ import { ELEMENTS, MASS_INVERSIONS, elementByName, elementBySymbol, elementOf, symbolOf } from "./elements.mjs";
5
+ import { FLAME_EMITTERS, VISIBLE_RANGE, emissionSpectrum, flameEmitterFor, flameSpectrum, isVisible, visibleFraction } from "./emission.mjs";
6
+ import { FIRST_ELECTRON_AFFINITY, NOBLE_GAS_RADIUS_NOTE, PROPERTIES, SUCCESSIVE_IONISATION_ENERGIES, covalentRadius, electronegativity, firstIonisationEnergy, propertiesOf } from "./properties.mjs";
7
+ import { IONISATION_ANOMALIES, acrossPeriod, bondBetween, bondCharacter, compareIonisationEnergy, downGroup, electronegativityGap, ionicCharacter, ionisationAnomalyFor, outerElectronsFromIonisation, outerElectronsOf, trendOf } from "./trends.mjs";
8
+
9
+ export { ANOMALIES, ELECTRONS_PER_ORBITAL, ELEMENTS, FIRST_ELECTRON_AFFINITY, FLAME_EMITTERS, GROUP_3_NOTE, IONISATION_ANOMALIES, MASS_INVERSIONS, NOBLE_GAS_RADIUS_NOTE, PROPERTIES, SUBSHELL_LETTERS, SUCCESSIVE_IONISATION_ENERGIES, VISIBLE_RANGE, acrossPeriod, anomalyFor, aufbauConfiguration, blockOf, bondBetween, bondCharacter, compareIonisationEnergy, condensedConfiguration, configurationOf, covalentRadius, downGroup, electronegativity, electronegativityGap, elementByName, elementBySymbol, elementOf, emissionSpectrum, familyOf, fillingOrder, firstIonisationEnergy, flameEmitterFor, flameSpectrum, formatConfiguration, groupOf, ionConfigurationOf, ionicCharacter, ionisationAnomalyFor, isPauliValid, isTransitionElement, isValidQuantumNumbers, isVisible, magneticNumbers, occupancyLabel, orbitalDiagram, orbitalsInSubshell, orbitalsOf, outerElectronsFromIonisation, outerElectronsOf, periodOf, placementOf, propertiesOf, quantumNumbersRefusal, romanGroupOf, shell, shellCapacity, shellLetter, subshell, subshellCapacity, subshellLetter, subshellsOf, symbolOf, transitionVerdict, trendOf, unpairedElectrons, valenceElectronsOf, visibleFraction };
@@ -0,0 +1,82 @@
1
+ import { Configuration } from "./aufbau.mjs";
2
+
3
+ //#region src/atomic/periodic.d.ts
4
+ type Block = 's' | 'p' | 'd' | 'f';
5
+ /** The disagreement about group 3, carried as text so a lesson can show it. */
6
+ declare const GROUP_3_NOTE = "Group 3 is unsettled. Deriving it from the filling order puts lutetium and lawrencium there, which agrees with a 2021 IUPAC provisional recommendation and makes the f-block a clean fourteen elements wide. Most syllabuses and wall charts print lanthanum and actinium there instead. Both arrangements are defended in the literature, so a lesson should show the disagreement rather than teach one as settled.";
7
+ /**
8
+ * The period, which is the ROW of the table rather than the highest occupied shell.
9
+ *
10
+ * Those two are not the same, and taking the shell was the first version's bug. Palladium is
11
+ * [Kr] 4d¹⁰ with nothing at all in its fifth shell, yet it sits in period 5: a d subshell is filled
12
+ * one row below its own shell number, and an f subshell two rows below. So the row is n for an s or
13
+ * p subshell, n+1 for a d, and n+2 for an f, which is exactly the offset that makes the table's
14
+ * blocks line up.
15
+ */
16
+ declare function periodOf(Z: number): number;
17
+ /**
18
+ * The block, from the subshell the last electron enters.
19
+ *
20
+ * Read off the FILLING order, not the written order: potassium's last electron goes into 4s even
21
+ * though 3d is written before 4s for later elements, so potassium is s-block.
22
+ */
23
+ declare function blockOf(Z: number): Block;
24
+ /**
25
+ * The group, in the modern 1 to 18 numbering.
26
+ *
27
+ * f-block elements are all reported as group 3, which is the convention: they sit in the same
28
+ * column of the main table and are drawn out beneath it.
29
+ */
30
+ declare function groupOf(Z: number): number;
31
+ /**
32
+ * The older group label still used by many syllabuses: IA, IIA, VIIB, VIII, 0.
33
+ *
34
+ * Kept because a learner meeting "group VIII" in a past paper and "group 8" in a data booklet needs
35
+ * to know they are the same column. Groups 8, 9 and 10 share the single label VIII, which is why
36
+ * the old system ran out of numbers and was replaced.
37
+ */
38
+ declare function romanGroupOf(Z: number): string;
39
+ interface TransitionVerdict {
40
+ readonly isTransition: boolean;
41
+ /** The reason, in the terms the definition is written in. */
42
+ readonly reason: string;
43
+ }
44
+ /**
45
+ * Whether an element is a transition element, and why.
46
+ *
47
+ * Returns the reasoning because "why is zinc not a transition element" and "why is copper one
48
+ * despite a full d subshell" are the questions this definition exists to answer, and a boolean
49
+ * answers neither.
50
+ */
51
+ declare function transitionVerdict(Z: number): TransitionVerdict;
52
+ /** Whether an element is a transition element by the IUPAC definition. */
53
+ declare const isTransitionElement: (Z: number) => boolean;
54
+ type Family = 'alkali metal' | 'alkaline earth metal' | 'transition element' | 'lanthanide' | 'actinide' | 'halogen' | 'noble gas' | 'other metal' | 'other nonmetal';
55
+ /**
56
+ * The family an element belongs to.
57
+ *
58
+ * Hydrogen is reported as a nonmetal rather than an alkali metal: it sits above group 1 because it
59
+ * has one s electron, and it behaves nothing like sodium.
60
+ */
61
+ declare function familyOf(Z: number): Family;
62
+ interface Placement {
63
+ readonly Z: number;
64
+ readonly period: number;
65
+ readonly group: number;
66
+ /** The older label: IA, VIII, 0. */
67
+ readonly romanGroup: string;
68
+ readonly block: Block;
69
+ readonly family: Family;
70
+ readonly configuration: Configuration;
71
+ }
72
+ /** Everything about where an element sits, from its proton number alone. */
73
+ declare function placementOf(Z: number): Placement;
74
+ /**
75
+ * The valence electrons: those outside the noble-gas core that take part in bonding.
76
+ *
77
+ * For a d-block element this counts the d electrons too, because they are close enough in energy to
78
+ * be lost, which is why iron has both a +2 and a +3 state and sodium has only +1.
79
+ */
80
+ declare function valenceElectronsOf(Z: number): number;
81
+ //#endregion
82
+ export { Block, Family, GROUP_3_NOTE, Placement, TransitionVerdict, blockOf, familyOf, groupOf, isTransitionElement, periodOf, placementOf, romanGroupOf, transitionVerdict, valenceElectronsOf };
@@ -0,0 +1,231 @@
1
+ import { subshellLetter } from "./shells.mjs";
2
+ import { aufbauConfiguration, configurationOf, fillingOrder, occupancyLabel } from "./aufbau.mjs";
3
+
4
+ //#region src/atomic/periodic.ts
5
+ /**
6
+ * Where an element sits in the periodic table, worked out from its electrons.
7
+ *
8
+ * ## Nothing here is looked up
9
+ *
10
+ * Block, group, period and classification are printed in every book as a coloured chart to be read
11
+ * off. They are not data. They are consequences of the electron configuration, which the aufbau
12
+ * engine already computes, so this file stores no table and answers for any proton number:
13
+ *
14
+ * period = the highest occupied shell
15
+ * block = the subshell the LAST electron entered, in filling order
16
+ * group = counted from the electrons outside the noble-gas core
17
+ *
18
+ * The group rule is one line per block and is worth stating because it is usually left implicit.
19
+ * An s-block element's group is its number of ns electrons. A p-block element's is 10 + its outer
20
+ * s and p electrons, which is why carbon (2s² 2p²) is group 14. A d-block element's is its d
21
+ * electrons plus its s electrons, which is why iron (3d⁶ 4s²) is group 8, and why chromium is still
22
+ * group 6 despite its anomalous 3d⁵ 4s¹.
23
+ *
24
+ * ## The transition-element definition, applied properly
25
+ *
26
+ * IUPAC defines a transition element as one whose atom has an incomplete d subshell, OR which can
27
+ * give rise to a cation with an incomplete d subshell. That second clause is the whole substance of
28
+ * it and is usually dropped:
29
+ *
30
+ * copper's atom is 3d¹⁰ 4s¹, a COMPLETE d subshell, yet Cu²⁺ is 3d⁹, so copper is a transition
31
+ * element, which is why its compounds are coloured;
32
+ *
33
+ * zinc's atom is 3d¹⁰ 4s² and its only common ion, Zn²⁺, is also 3d¹⁰, so zinc is NOT one, which
34
+ * is why zinc compounds are white.
35
+ *
36
+ * So the test is applied to the ions as well as the atom, and group 12 is named as the exception it
37
+ * is, with the reason, rather than silently special-cased.
38
+ *
39
+ * ## Where group 3 is contested, and this says so
40
+ *
41
+ * Whether lanthanum or lutetium belongs in group 3 is genuinely unsettled. Deriving it from the
42
+ * filling order lands on lutetium and lawrencium, which is IUPAC's 2021 provisional recommendation;
43
+ * most syllabuses and wall charts print lanthanum and actinium there instead. The derivation is not
44
+ * adjusted to match the more common chart, because an engine that quietly agrees with whichever
45
+ * answer is expected is no use for showing that the question is open. {@link GROUP_3_NOTE} carries
46
+ * the disagreement so a lesson can put both arrangements in front of a learner.
47
+ *
48
+ * Pure: no React, no pixels.
49
+ */
50
+ /** The disagreement about group 3, carried as text so a lesson can show it. */
51
+ const GROUP_3_NOTE = "Group 3 is unsettled. Deriving it from the filling order puts lutetium and lawrencium there, which agrees with a 2021 IUPAC provisional recommendation and makes the f-block a clean fourteen elements wide. Most syllabuses and wall charts print lanthanum and actinium there instead. Both arrangements are defended in the literature, so a lesson should show the disagreement rather than teach one as settled.";
52
+ /**
53
+ * The subshell the last electron enters, by the UNPERTURBED filling order.
54
+ *
55
+ * The plain aufbau prediction is used here, not the anomalous ground state, because block and
56
+ * period are about which column and row an element occupies and those do not move when one electron
57
+ * shifts. Chromium is in the same column as molybdenum whether or not its 4s electron has hopped
58
+ * into 3d, and cerium is a lanthanide even though its real configuration has a 5d electron in it.
59
+ */
60
+ function lastSubshellFilled(Z) {
61
+ if (Z < 1) throw new Error(`proton number must be at least 1, got ${Z}`);
62
+ const held = new Map(aufbauConfiguration(Z).map((o) => [occupancyLabel(o), o.electrons]));
63
+ let last;
64
+ let counted = 0;
65
+ for (const candidate of fillingOrder()) {
66
+ const electrons = held.get(occupancyLabel(candidate)) ?? 0;
67
+ if (electrons === 0) continue;
68
+ counted += electrons;
69
+ last = candidate;
70
+ if (counted >= Z) break;
71
+ }
72
+ if (!last) throw new Error(`no configuration for Z=${Z}`);
73
+ return last;
74
+ }
75
+ /**
76
+ * The period, which is the ROW of the table rather than the highest occupied shell.
77
+ *
78
+ * Those two are not the same, and taking the shell was the first version's bug. Palladium is
79
+ * [Kr] 4d¹⁰ with nothing at all in its fifth shell, yet it sits in period 5: a d subshell is filled
80
+ * one row below its own shell number, and an f subshell two rows below. So the row is n for an s or
81
+ * p subshell, n+1 for a d, and n+2 for an f, which is exactly the offset that makes the table's
82
+ * blocks line up.
83
+ */
84
+ function periodOf(Z) {
85
+ const { n, l } = lastSubshellFilled(Z);
86
+ return n + (l >= 2 ? l - 1 : 0);
87
+ }
88
+ /**
89
+ * The block, from the subshell the last electron enters.
90
+ *
91
+ * Read off the FILLING order, not the written order: potassium's last electron goes into 4s even
92
+ * though 3d is written before 4s for later elements, so potassium is s-block.
93
+ */
94
+ function blockOf(Z) {
95
+ return subshellLetter(lastSubshellFilled(Z).l);
96
+ }
97
+ /** Outer-shell electrons: those in the highest occupied shell. */
98
+ function outerElectrons(configuration, period) {
99
+ return configuration.filter((o) => o.n === period).reduce((total, o) => total + o.electrons, 0);
100
+ }
101
+ /** Electrons in the d subshell one shell below the outermost, which is what a d-block element has. */
102
+ function dElectrons(configuration, period) {
103
+ return configuration.find((o) => o.n === period - 1 && o.l === 2)?.electrons ?? 0;
104
+ }
105
+ /**
106
+ * The group, in the modern 1 to 18 numbering.
107
+ *
108
+ * f-block elements are all reported as group 3, which is the convention: they sit in the same
109
+ * column of the main table and are drawn out beneath it.
110
+ */
111
+ function groupOf(Z) {
112
+ const configuration = configurationOf(Z);
113
+ const period = periodOf(Z);
114
+ const block = blockOf(Z);
115
+ if (Z === 2) return 18;
116
+ if (block === "f") return 3;
117
+ if (block === "s") return outerElectrons(configuration, period);
118
+ if (block === "p") return 10 + outerElectrons(configuration, period);
119
+ return dElectrons(configuration, period) + outerElectrons(configuration, period);
120
+ }
121
+ /**
122
+ * The older group label still used by many syllabuses: IA, IIA, VIIB, VIII, 0.
123
+ *
124
+ * Kept because a learner meeting "group VIII" in a past paper and "group 8" in a data booklet needs
125
+ * to know they are the same column. Groups 8, 9 and 10 share the single label VIII, which is why
126
+ * the old system ran out of numbers and was replaced.
127
+ */
128
+ function romanGroupOf(Z) {
129
+ const group = groupOf(Z);
130
+ if (group === 18) return "0";
131
+ if (group >= 8 && group <= 10) return "VIII";
132
+ const numeral = [
133
+ "I",
134
+ "II",
135
+ "III",
136
+ "IV",
137
+ "V",
138
+ "VI",
139
+ "VII"
140
+ ];
141
+ if (group <= 2) return `${numeral[group - 1]}A`;
142
+ if (group <= 7) return `${numeral[group - 3]}B`;
143
+ if (group === 11) return "IB";
144
+ if (group === 12) return "IIB";
145
+ return `${numeral[group - 11]}A`;
146
+ }
147
+ /**
148
+ * d-block groups whose elements are NOT transition elements, with the reason.
149
+ *
150
+ * Listed rather than derived, for the same reason the aufbau anomalies are: it rests on which ions
151
+ * actually form, which the electron-filling rules do not predict. Group 12 loses only its two s
152
+ * electrons, so every common compound of zinc, cadmium and mercury has a full d subshell.
153
+ */
154
+ const NON_TRANSITION_GROUPS = { 12: "its only common ions lose the two s electrons and keep a full d¹⁰ subshell, so no ordinary compound of it has a partly filled d subshell, which is why these compounds are white rather than coloured" };
155
+ /**
156
+ * Whether an element is a transition element, and why.
157
+ *
158
+ * Returns the reasoning because "why is zinc not a transition element" and "why is copper one
159
+ * despite a full d subshell" are the questions this definition exists to answer, and a boolean
160
+ * answers neither.
161
+ */
162
+ function transitionVerdict(Z) {
163
+ const block = blockOf(Z);
164
+ if (block !== "d") return {
165
+ isTransition: false,
166
+ reason: `it is a ${block}-block element and has no d subshell being filled`
167
+ };
168
+ const period = periodOf(Z);
169
+ const atomD = dElectrons(configurationOf(Z), period);
170
+ const excluded = NON_TRANSITION_GROUPS[groupOf(Z)];
171
+ if (excluded) return {
172
+ isTransition: false,
173
+ reason: excluded
174
+ };
175
+ if (atomD >= 1 && atomD <= 9) return {
176
+ isTransition: true,
177
+ reason: `its atom has a partly filled d subshell, d${atomD}`
178
+ };
179
+ return {
180
+ isTransition: true,
181
+ reason: "its atom has a full d¹⁰ subshell, but it forms an ion with a partly filled d subshell, which is what the definition asks for and is why its compounds are coloured"
182
+ };
183
+ }
184
+ /** Whether an element is a transition element by the IUPAC definition. */
185
+ const isTransitionElement = (Z) => transitionVerdict(Z).isTransition;
186
+ /**
187
+ * The family an element belongs to.
188
+ *
189
+ * Hydrogen is reported as a nonmetal rather than an alkali metal: it sits above group 1 because it
190
+ * has one s electron, and it behaves nothing like sodium.
191
+ */
192
+ function familyOf(Z) {
193
+ if (Z === 1) return "other nonmetal";
194
+ const block = blockOf(Z);
195
+ const group = groupOf(Z);
196
+ if (group === 18) return "noble gas";
197
+ if (block === "f") return periodOf(Z) === 6 ? "lanthanide" : "actinide";
198
+ if (block === "d") return isTransitionElement(Z) ? "transition element" : "other metal";
199
+ if (group === 1) return "alkali metal";
200
+ if (group === 2) return "alkaline earth metal";
201
+ if (group === 17) return "halogen";
202
+ return (configurationOf(Z).find((o) => o.n === periodOf(Z) && o.l === 1)?.electrons ?? 0) <= periodOf(Z) - 2 ? "other metal" : "other nonmetal";
203
+ }
204
+ /** Everything about where an element sits, from its proton number alone. */
205
+ function placementOf(Z) {
206
+ return {
207
+ Z,
208
+ period: periodOf(Z),
209
+ group: groupOf(Z),
210
+ romanGroup: romanGroupOf(Z),
211
+ block: blockOf(Z),
212
+ family: familyOf(Z),
213
+ configuration: configurationOf(Z)
214
+ };
215
+ }
216
+ /**
217
+ * The valence electrons: those outside the noble-gas core that take part in bonding.
218
+ *
219
+ * For a d-block element this counts the d electrons too, because they are close enough in energy to
220
+ * be lost, which is why iron has both a +2 and a +3 state and sodium has only +1.
221
+ */
222
+ function valenceElectronsOf(Z) {
223
+ const configuration = configurationOf(Z);
224
+ const period = periodOf(Z);
225
+ const block = blockOf(Z);
226
+ const outer = outerElectrons(configuration, period);
227
+ return block === "d" ? outer + dElectrons(configuration, period) : outer;
228
+ }
229
+
230
+ //#endregion
231
+ export { GROUP_3_NOTE, blockOf, familyOf, groupOf, isTransitionElement, periodOf, placementOf, romanGroupOf, transitionVerdict, valenceElectronsOf };