react-cheminfo 0.41.0 → 0.43.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/bin/check-deploy.mjs +3 -1
- package/lib/chrome/ui/AboutButton.d.ts +59 -0
- package/lib/chrome/ui/AboutButton.d.ts.map +1 -0
- package/lib/chrome/ui/AboutButton.js +29 -0
- package/lib/chrome/ui/AboutButton.js.map +1 -0
- package/lib/chrome/ui/index.d.ts +2 -0
- package/lib/chrome/ui/index.d.ts.map +1 -1
- package/lib/chrome/ui/index.js +1 -0
- package/lib/chrome/ui/index.js.map +1 -1
- package/lib/deploy/core/buildGate.d.ts.map +1 -1
- package/lib/deploy/core/buildGate.js +4 -34
- package/lib/deploy/core/buildGate.js.map +1 -1
- package/lib/deploy/core/checkDeploy.d.ts.map +1 -1
- package/lib/deploy/core/checkDeploy.js +2 -0
- package/lib/deploy/core/checkDeploy.js.map +1 -1
- package/lib/deploy/core/index.d.ts +1 -0
- package/lib/deploy/core/index.d.ts.map +1 -1
- package/lib/deploy/core/index.js +1 -0
- package/lib/deploy/core/index.js.map +1 -1
- package/lib/deploy/core/json.d.ts +27 -0
- package/lib/deploy/core/json.d.ts.map +1 -0
- package/lib/deploy/core/json.js +56 -0
- package/lib/deploy/core/json.js.map +1 -0
- package/lib/deploy/core/reactCopies.d.ts +32 -0
- package/lib/deploy/core/reactCopies.d.ts.map +1 -0
- package/lib/deploy/core/reactCopies.js +212 -0
- package/lib/deploy/core/reactCopies.js.map +1 -0
- package/lib/deploy/core/types.d.ts +1 -1
- package/lib/deploy/core/types.d.ts.map +1 -1
- package/lib/deploy/core/types.js.map +1 -1
- package/lib/ecosystem/core/sites.d.ts.map +1 -1
- package/lib/ecosystem/core/sites.js +12 -0
- package/lib/ecosystem/core/sites.js.map +1 -1
- package/lib/ecosystem/core/types.d.ts +1 -1
- package/lib/ecosystem/core/types.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.js +4 -0
- package/lib/ecosystem/ui/glyphs.js.map +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/locales/de.json +2 -0
- package/lib/locales/en.json +2 -0
- package/lib/locales/es.json +2 -0
- package/lib/locales/fr.json +2 -0
- package/lib/locales/it.json +2 -0
- package/lib/periodic/ui/ElementCell.d.ts +22 -2
- package/lib/periodic/ui/ElementCell.d.ts.map +1 -1
- package/lib/periodic/ui/ElementCell.js +20 -145
- package/lib/periodic/ui/ElementCell.js.map +1 -1
- package/lib/periodic/ui/PeriodicTable.d.ts +7 -0
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +21 -3
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/periodic/ui/cellStyles.d.ts +79 -0
- package/lib/periodic/ui/cellStyles.d.ts.map +1 -0
- package/lib/periodic/ui/cellStyles.js +90 -0
- package/lib/periodic/ui/cellStyles.js.map +1 -0
- package/lib/periodic/ui/cellType.d.ts +106 -0
- package/lib/periodic/ui/cellType.d.ts.map +1 -0
- package/lib/periodic/ui/cellType.js +181 -0
- package/lib/periodic/ui/cellType.js.map +1 -0
- package/lib/periodic/ui/glyphWidths.d.ts +11 -0
- package/lib/periodic/ui/glyphWidths.d.ts.map +1 -0
- package/lib/periodic/ui/glyphWidths.js +69 -0
- package/lib/periodic/ui/glyphWidths.js.map +1 -0
- package/package.json +9 -1
- package/src/chrome/ui/AboutButton.tsx +90 -0
- package/src/chrome/ui/index.ts +2 -0
- package/src/deploy/core/buildGate.ts +4 -35
- package/src/deploy/core/checkDeploy.ts +7 -0
- package/src/deploy/core/index.ts +1 -0
- package/src/deploy/core/json.ts +53 -0
- package/src/deploy/core/reactCopies.ts +243 -0
- package/src/deploy/core/types.ts +5 -1
- package/src/ecosystem/core/sites.ts +13 -0
- package/src/ecosystem/core/types.ts +2 -1
- package/src/ecosystem/ui/glyphs.tsx +16 -0
- package/src/locales/de.json +2 -0
- package/src/locales/en.json +2 -0
- package/src/locales/es.json +2 -0
- package/src/locales/fr.json +2 -0
- package/src/locales/it.json +2 -0
- package/src/periodic/ui/ElementCell.tsx +69 -160
- package/src/periodic/ui/PeriodicTable.tsx +37 -2
- package/src/periodic/ui/cellStyles.ts +100 -0
- package/src/periodic/ui/cellType.ts +223 -0
- package/src/periodic/ui/glyphWidths.ts +68 -0
- package/styles/chrome.css +10 -2
package/src/locales/fr.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"language.label": "Langue",
|
|
3
3
|
"chrome.pages": "Pages",
|
|
4
|
+
"chrome.about": "À propos",
|
|
5
|
+
"chrome.aboutTitle": "Ce qu'est ce site, sur quoi il est bâti et comment le citer",
|
|
4
6
|
"account.signIn": "Se connecter",
|
|
5
7
|
"account.signOut": "Se déconnecter",
|
|
6
8
|
"account.signedInAs": "Connecté comme {name}",
|
package/src/locales/it.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"language.label": "Lingua",
|
|
3
3
|
"chrome.pages": "Pagine",
|
|
4
|
+
"chrome.about": "Informazioni",
|
|
5
|
+
"chrome.aboutTitle": "Cosa è questo sito, su cosa si basa e come citarlo",
|
|
4
6
|
"account.signIn": "Accedi",
|
|
5
7
|
"account.signOut": "Esci",
|
|
6
8
|
"account.signedInAs": "Accesso effettuato come {name}",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One cell of the periodic table: the atomic number, the symbol,
|
|
3
|
-
*
|
|
2
|
+
* One cell of the periodic table: the atomic number, the symbol, whatever the
|
|
3
|
+
* tool asked to be written under it, and — when the tool asks for them — the
|
|
4
|
+
* electrons of each shell down the right-hand edge.
|
|
4
5
|
*
|
|
5
6
|
* A cell is a real `<button>`, so Tab reaches it, Enter and Space activate it,
|
|
6
7
|
* and a screen reader reads the element's name rather than its symbol.
|
|
@@ -10,13 +11,33 @@
|
|
|
10
11
|
* screen — the table a class reads is the same drawing, larger.
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
|
-
import type {
|
|
14
|
+
import type { ReactElement } from 'react';
|
|
14
15
|
import { useState } from 'react';
|
|
15
16
|
|
|
16
17
|
import type { Swatch } from '../../color/core/interpolate.ts';
|
|
17
18
|
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
18
19
|
|
|
19
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
SHELLS_AIR,
|
|
22
|
+
SHELLS_COLUMN,
|
|
23
|
+
cellStyle,
|
|
24
|
+
detailStyle,
|
|
25
|
+
numberStyle,
|
|
26
|
+
shellsStyle,
|
|
27
|
+
symbolStyle,
|
|
28
|
+
} from './cellStyles.ts';
|
|
29
|
+
import type { DetailType } from './cellType.ts';
|
|
30
|
+
import {
|
|
31
|
+
SHELLS_RESERVED,
|
|
32
|
+
SYMBOL_CAP,
|
|
33
|
+
condensedScale,
|
|
34
|
+
detailType,
|
|
35
|
+
scaleX,
|
|
36
|
+
shellFontSize,
|
|
37
|
+
symbolFontSize,
|
|
38
|
+
textWidthInEm,
|
|
39
|
+
} from './cellType.ts';
|
|
40
|
+
import { ofWidth } from './unit.ts';
|
|
20
41
|
|
|
21
42
|
/** What {@link ElementCell} needs to draw one element. */
|
|
22
43
|
export interface ElementCellProps {
|
|
@@ -39,6 +60,24 @@ export interface ElementCellProps {
|
|
|
39
60
|
* @default '' — nothing is written
|
|
40
61
|
*/
|
|
41
62
|
detail?: string;
|
|
63
|
+
/**
|
|
64
|
+
* The size that line is written at, from {@link detailType}, so a whole
|
|
65
|
+
* table writes it at one size rather than each cell at its own.
|
|
66
|
+
* @default the largest size this cell's own line fits at
|
|
67
|
+
*/
|
|
68
|
+
detailType?: DetailType;
|
|
69
|
+
/**
|
|
70
|
+
* Electrons in each shell, innermost first, written down the right-hand
|
|
71
|
+
* edge.
|
|
72
|
+
* @default undefined — nothing is written there
|
|
73
|
+
*/
|
|
74
|
+
shells?: readonly number[];
|
|
75
|
+
/**
|
|
76
|
+
* The size they are written at, so the deepest stack in the table fits its
|
|
77
|
+
* cell and every other is written to match.
|
|
78
|
+
* @default the size this cell's own stack fits at
|
|
79
|
+
*/
|
|
80
|
+
shellSize?: string;
|
|
42
81
|
/**
|
|
43
82
|
* Whether the cell is the one the tools are pointed at.
|
|
44
83
|
* @default false
|
|
@@ -78,6 +117,7 @@ export function ElementCell(props: ElementCellProps): ReactElement {
|
|
|
78
117
|
row,
|
|
79
118
|
onSelect,
|
|
80
119
|
detail = '',
|
|
120
|
+
shells,
|
|
81
121
|
isSelected = false,
|
|
82
122
|
isIncluded = true,
|
|
83
123
|
onHover,
|
|
@@ -85,6 +125,11 @@ export function ElementCell(props: ElementCellProps): ReactElement {
|
|
|
85
125
|
const t = useChromeT();
|
|
86
126
|
const [isHovered, setIsHovered] = useState(false);
|
|
87
127
|
|
|
128
|
+
const detailWidth = textWidthInEm(detail);
|
|
129
|
+
const reserved = shells === undefined ? 0 : SHELLS_RESERVED;
|
|
130
|
+
const type = props.detailType ?? detailType([detailWidth], reserved);
|
|
131
|
+
const shellSize = props.shellSize ?? shellFontSize(shells?.length ?? 0);
|
|
132
|
+
|
|
88
133
|
return (
|
|
89
134
|
<button
|
|
90
135
|
type="button"
|
|
@@ -113,6 +158,11 @@ export function ElementCell(props: ElementCellProps): ReactElement {
|
|
|
113
158
|
...cellStyle,
|
|
114
159
|
gridColumn: column,
|
|
115
160
|
gridRow: row,
|
|
161
|
+
// The electrons stand in a column of their own, so the symbol keeps
|
|
162
|
+
// the left of the cell rather than being pushed off its centre.
|
|
163
|
+
gridTemplateColumns:
|
|
164
|
+
shells === undefined ? '1fr' : `1fr ${SHELLS_COLUMN}`,
|
|
165
|
+
columnGap: shells === undefined ? undefined : SHELLS_AIR,
|
|
116
166
|
background: swatch.background,
|
|
117
167
|
color: swatch.foreground,
|
|
118
168
|
opacity: isIncluded ? 1 : 0.28,
|
|
@@ -132,170 +182,29 @@ export function ElementCell(props: ElementCellProps): ReactElement {
|
|
|
132
182
|
<span
|
|
133
183
|
style={{
|
|
134
184
|
...symbolStyle,
|
|
135
|
-
fontSize: symbolFontSize(symbol),
|
|
185
|
+
fontSize: symbolFontSize(symbol, SYMBOL_CAP, reserved),
|
|
136
186
|
}}
|
|
137
187
|
>
|
|
138
188
|
{symbol}
|
|
139
189
|
</span>
|
|
140
190
|
{detail === '' ? null : (
|
|
141
|
-
<span
|
|
191
|
+
<span
|
|
192
|
+
style={{
|
|
193
|
+
...detailStyle,
|
|
194
|
+
fontSize: type.size,
|
|
195
|
+
// Condensed rather than written smaller, so every cell of the
|
|
196
|
+
// table says its name and its value in one type.
|
|
197
|
+
transform: scaleX(condensedScale(detailWidth, type, reserved)),
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
142
200
|
{detail}
|
|
143
201
|
</span>
|
|
144
202
|
)}
|
|
203
|
+
{shells === undefined ? null : (
|
|
204
|
+
<span style={{ ...shellsStyle, fontSize: shellSize }}>
|
|
205
|
+
{shells.join('\n')}
|
|
206
|
+
</span>
|
|
207
|
+
)}
|
|
145
208
|
</button>
|
|
146
209
|
);
|
|
147
210
|
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* The size the symbol is written at.
|
|
151
|
-
*
|
|
152
|
-
* Every symbol is written at the same size, except the widest of them — the
|
|
153
|
-
* ones whose second letter is an `m` — which are written a tenth smaller
|
|
154
|
-
* rather than run into the edges of their cell.
|
|
155
|
-
* @param symbol - The chemical symbol.
|
|
156
|
-
* @returns A CSS length.
|
|
157
|
-
*/
|
|
158
|
-
function symbolFontSize(symbol: string): string {
|
|
159
|
-
return fitted(symbolWidthInEm(symbol), SYMBOL_CAP, '0.5rem');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* The size the third line takes so the whole of it is written.
|
|
164
|
-
*
|
|
165
|
-
* A value cut short by an ellipsis is a wrong value — `0.0899` read as `0.0…`
|
|
166
|
-
* is worse than not writing it at all — so a long string is written smaller
|
|
167
|
-
* rather than trimmed.
|
|
168
|
-
* @param detail - What the third line says.
|
|
169
|
-
* @returns A CSS length.
|
|
170
|
-
*/
|
|
171
|
-
function detailFontSize(detail: string): string {
|
|
172
|
-
return fitted(detailWidthInEm(detail), DETAIL_CAP, '0.25rem');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* The largest size a string of the given width fits its cell at.
|
|
177
|
-
*
|
|
178
|
-
* The room a cell leaves is a share of the table's width less its border and
|
|
179
|
-
* its padding, which are the same few pixels at every size — hence the two
|
|
180
|
-
* units in one expression.
|
|
181
|
-
* @param widthInEm - How wide the string is, in ems of its own size.
|
|
182
|
-
* @param cap - The size it is written at when it has room to spare.
|
|
183
|
-
* @param floor - The size under which it is not shrunk any further.
|
|
184
|
-
* @returns A CSS length.
|
|
185
|
-
*/
|
|
186
|
-
function fitted(widthInEm: number, cap: string, floor: string): string {
|
|
187
|
-
const room = `calc((${UNIT} * ${String(CELL_SHARE)} - ${CELL_CHROME}) / ${widthInEm.toFixed(2)})`;
|
|
188
|
-
return `max(${floor}, min(${cap}, ${room}))`;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* How wide a symbol is, in ems of its own size.
|
|
193
|
-
* @param symbol - The chemical symbol.
|
|
194
|
-
* @returns Its width, never zero.
|
|
195
|
-
*/
|
|
196
|
-
function symbolWidthInEm(symbol: string): number {
|
|
197
|
-
let width = 0;
|
|
198
|
-
for (const character of symbol) {
|
|
199
|
-
if (character === 'm' || character === 'w') {
|
|
200
|
-
width += 0.95;
|
|
201
|
-
} else if (character >= 'a' && character <= 'z') {
|
|
202
|
-
width += 0.63;
|
|
203
|
-
} else {
|
|
204
|
-
width += 0.85;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return Math.max(width, 0.85);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* How wide the third line is, in ems of its own size.
|
|
212
|
-
*
|
|
213
|
-
* It is written with tabular figures, where every glyph — the decimal point
|
|
214
|
-
* and the minus of an exponent included — advances the same width, so counting
|
|
215
|
-
* the characters is the measurement.
|
|
216
|
-
* @param detail - What the third line says.
|
|
217
|
-
* @returns Its width, never zero.
|
|
218
|
-
*/
|
|
219
|
-
function detailWidthInEm(detail: string): number {
|
|
220
|
-
return Math.max(detail.length, 1) * TABULAR_EM;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** What one tabular glyph advances, as a share of its own size. */
|
|
224
|
-
const TABULAR_EM = 0.6;
|
|
225
|
-
|
|
226
|
-
/** The size the symbol is written at wherever it fits, as a share of the table. */
|
|
227
|
-
const SYMBOL_CAP = ofWidth(2.4);
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* The tallest the third line is ever written, as a share of the table.
|
|
231
|
-
*
|
|
232
|
-
* Close to two thirds of the symbol: the symbol is how a cell is found, but
|
|
233
|
-
* the value is what the table is being read for, and a value half the size of
|
|
234
|
-
* the symbol is the one thing on the cell a class cannot make out.
|
|
235
|
-
*/
|
|
236
|
-
const DETAIL_CAP = ofWidth(1.6);
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* The band at each end of a cell: the atomic number at the top, whatever the
|
|
240
|
-
* tool writes at the bottom.
|
|
241
|
-
*
|
|
242
|
-
* They are one length, not two, and that is what makes the symbol between them
|
|
243
|
-
* sit at the centre of the cell rather than near it — a bottom band wider than
|
|
244
|
-
* the top one by a third lifted every symbol in the table two pixels.
|
|
245
|
-
*/
|
|
246
|
-
const EDGE_BAND = ofWidth(1.8);
|
|
247
|
-
|
|
248
|
-
/** How wide one column is, in per cent of the table's width. */
|
|
249
|
-
const CELL_SHARE = 4.85;
|
|
250
|
-
|
|
251
|
-
/** What the border and the padding of a cell take off that width. */
|
|
252
|
-
const CELL_CHROME = '4px';
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* A cell is three bands of its own, and every cell has all three.
|
|
256
|
-
*
|
|
257
|
-
* The atomic number is in the top band, against its left edge; the symbol is
|
|
258
|
-
* centred in the middle one; whatever the tool writes is centred in the
|
|
259
|
-
* bottom one. The bands keep their height whether or not anything is written
|
|
260
|
-
* in the last of them, so a number sits at one height across the whole table
|
|
261
|
-
* and a symbol at one other — before this, both rode on a stack the cell
|
|
262
|
-
* centred and moved whenever a neighbour's value was written smaller.
|
|
263
|
-
*/
|
|
264
|
-
const cellStyle = {
|
|
265
|
-
border: '1px solid rgb(255 255 255 / 0.55)',
|
|
266
|
-
borderRadius: 3,
|
|
267
|
-
cursor: 'pointer',
|
|
268
|
-
display: 'grid',
|
|
269
|
-
font: 'inherit',
|
|
270
|
-
gridTemplateRows: `${EDGE_BAND} 1fr ${EDGE_BAND}`,
|
|
271
|
-
justifyItems: 'center',
|
|
272
|
-
minWidth: 0,
|
|
273
|
-
overflow: 'hidden',
|
|
274
|
-
padding: '1px',
|
|
275
|
-
transition: 'opacity 120ms ease, filter 120ms ease',
|
|
276
|
-
} as const satisfies CSSProperties;
|
|
277
|
-
|
|
278
|
-
const numberStyle = {
|
|
279
|
-
alignSelf: 'start',
|
|
280
|
-
fontSize: `max(0.33rem, ${ofWidth(1.1)})`,
|
|
281
|
-
fontVariantNumeric: 'tabular-nums',
|
|
282
|
-
justifySelf: 'start',
|
|
283
|
-
lineHeight: 1,
|
|
284
|
-
opacity: 0.8,
|
|
285
|
-
} as const satisfies CSSProperties;
|
|
286
|
-
|
|
287
|
-
const symbolStyle = {
|
|
288
|
-
alignSelf: 'center',
|
|
289
|
-
fontWeight: 700,
|
|
290
|
-
letterSpacing: '-0.02em',
|
|
291
|
-
lineHeight: 1.02,
|
|
292
|
-
} as const satisfies CSSProperties;
|
|
293
|
-
|
|
294
|
-
const detailStyle = {
|
|
295
|
-
alignSelf: 'center',
|
|
296
|
-
fontVariantNumeric: 'tabular-nums',
|
|
297
|
-
lineHeight: 1,
|
|
298
|
-
maxWidth: '100%',
|
|
299
|
-
overflow: 'hidden',
|
|
300
|
-
whiteSpace: 'nowrap',
|
|
301
|
-
} as const satisfies CSSProperties;
|
|
@@ -37,6 +37,13 @@ import {
|
|
|
37
37
|
HeaderStrips,
|
|
38
38
|
InnerTransitionMarkers,
|
|
39
39
|
} from './PeriodicTableChrome.tsx';
|
|
40
|
+
import {
|
|
41
|
+
ROW_SHARE,
|
|
42
|
+
SHELLS_RESERVED,
|
|
43
|
+
detailType,
|
|
44
|
+
shellFontSize,
|
|
45
|
+
textWidthInEm,
|
|
46
|
+
} from './cellType.ts';
|
|
40
47
|
import { UNIT_PROPERTY, ofWidth, unitValue } from './unit.ts';
|
|
41
48
|
|
|
42
49
|
/** What {@link PeriodicTable} needs. */
|
|
@@ -68,6 +75,13 @@ export interface PeriodicTableProps {
|
|
|
68
75
|
* @default the English name
|
|
69
76
|
*/
|
|
70
77
|
nameOf?: (element: PeriodicElement) => string;
|
|
78
|
+
/**
|
|
79
|
+
* Electrons in each shell of an element, innermost first, written down the
|
|
80
|
+
* right-hand edge of its cell. The energy levels, which a table is also read
|
|
81
|
+
* for: none of ours knows them, so the tool that does says so here.
|
|
82
|
+
* @default undefined — no cell writes any
|
|
83
|
+
*/
|
|
84
|
+
shellsOf?: (element: PeriodicElement) => readonly number[] | undefined;
|
|
71
85
|
/**
|
|
72
86
|
* Whether an element is inside the set the tool is showing. Everything
|
|
73
87
|
* outside it is dimmed rather than removed, so the table keeps its shape.
|
|
@@ -137,6 +151,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
137
151
|
swatchOf = defaultSwatchOf,
|
|
138
152
|
detailOf,
|
|
139
153
|
nameOf = defaultNameOf,
|
|
154
|
+
shellsOf,
|
|
140
155
|
isIncluded,
|
|
141
156
|
inset,
|
|
142
157
|
headers = false,
|
|
@@ -184,6 +199,23 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
184
199
|
onSelect(next.symbol);
|
|
185
200
|
}
|
|
186
201
|
|
|
202
|
+
// One size for the whole table rather than one per cell: a column of values
|
|
203
|
+
// written at eleven sizes is read as eleven things, and a name shrunk to a
|
|
204
|
+
// third of its neighbour's is the one a class cannot make out. The size is
|
|
205
|
+
// what the widest of them fits at, and anything wider than that is condensed
|
|
206
|
+
// by the cell rather than written smaller still.
|
|
207
|
+
const placed = placedElements();
|
|
208
|
+
const widths: number[] = [];
|
|
209
|
+
let deepest = 0;
|
|
210
|
+
for (const { element } of placed) {
|
|
211
|
+
widths.push(textWidthInEm(detailOf?.(element) ?? ''));
|
|
212
|
+
const stack = shellsOf?.(element);
|
|
213
|
+
if (stack !== undefined && stack.length > deepest) deepest = stack.length;
|
|
214
|
+
}
|
|
215
|
+
const reserved = deepest === 0 ? 0 : SHELLS_RESERVED;
|
|
216
|
+
const type = detailType(widths, reserved);
|
|
217
|
+
const shellSize = shellFontSize(deepest);
|
|
218
|
+
|
|
187
219
|
return (
|
|
188
220
|
<div ref={rootRef} className={className} style={rootStyle}>
|
|
189
221
|
<div
|
|
@@ -199,13 +231,16 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
199
231
|
<div style={insetStyle(offset)}>{inset}</div>
|
|
200
232
|
)}
|
|
201
233
|
{markers ? <InnerTransitionMarkers offset={offset} /> : null}
|
|
202
|
-
{
|
|
234
|
+
{placed.map(({ element, cell }) => (
|
|
203
235
|
<ElementCell
|
|
204
236
|
key={element.symbol}
|
|
205
237
|
atomicNumber={element.atomicNumber}
|
|
206
238
|
symbol={element.symbol}
|
|
207
239
|
name={nameOf(element)}
|
|
208
240
|
detail={detailOf?.(element)}
|
|
241
|
+
detailType={type}
|
|
242
|
+
shells={shellsOf?.(element)}
|
|
243
|
+
shellSize={shellSize}
|
|
209
244
|
swatch={swatchOf(element)}
|
|
210
245
|
isSelected={element.symbol === selected}
|
|
211
246
|
isIncluded={isIncluded?.(element)}
|
|
@@ -270,7 +305,7 @@ const MIN_WIDTH = 280;
|
|
|
270
305
|
* table: a cell keeps the band it writes a value in whether or not that table
|
|
271
306
|
* writes one.
|
|
272
307
|
*/
|
|
273
|
-
const ROW_HEIGHT = ofWidth(
|
|
308
|
+
const ROW_HEIGHT = ofWidth(ROW_SHARE);
|
|
274
309
|
|
|
275
310
|
/** The band the two inner-transition series were lifted out across. */
|
|
276
311
|
const SERIES_GAP = `max(6px, ${ofWidth(1.1)})`;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three bands a cell is laid out as, and the column the electrons stand in.
|
|
3
|
+
*
|
|
4
|
+
* Kept beside the cell rather than inside it, because what they say — where the
|
|
5
|
+
* atomic number sits, how tall a band is — is read far more often than the
|
|
6
|
+
* markup that carries them.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { CSSProperties } from 'react';
|
|
10
|
+
|
|
11
|
+
import { SHELLS_GAP, SHELLS_SHARE, SHELL_LEADING } from './cellType.ts';
|
|
12
|
+
import { ofWidth } from './unit.ts';
|
|
13
|
+
|
|
14
|
+
/** The column the electron counts stand in, as a CSS length. */
|
|
15
|
+
export const SHELLS_COLUMN = ofWidth(SHELLS_SHARE);
|
|
16
|
+
|
|
17
|
+
/** The air between the symbol and that column, as a CSS length. */
|
|
18
|
+
export const SHELLS_AIR = ofWidth(SHELLS_GAP);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The band at each end of a cell: the atomic number at the top, whatever the
|
|
22
|
+
* tool writes at the bottom.
|
|
23
|
+
*
|
|
24
|
+
* They are one length, not two, and that is what makes the symbol between them
|
|
25
|
+
* sit at the centre of the cell rather than near it — a bottom band wider than
|
|
26
|
+
* the top one by a third lifted every symbol in the table two pixels.
|
|
27
|
+
*/
|
|
28
|
+
const EDGE_BAND = ofWidth(1.8);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A cell is three bands of its own, and every cell has all three.
|
|
32
|
+
*
|
|
33
|
+
* The atomic number is in the top band, against its left edge; the symbol is
|
|
34
|
+
* centred in the middle one; whatever the tool writes is centred in the
|
|
35
|
+
* bottom one. The bands keep their height whether or not anything is written
|
|
36
|
+
* in the last of them, so a number sits at one height across the whole table
|
|
37
|
+
* and a symbol at one other — before this, both rode on a stack the cell
|
|
38
|
+
* centred and moved whenever a neighbour's value was written smaller.
|
|
39
|
+
*/
|
|
40
|
+
export const cellStyle = {
|
|
41
|
+
border: '1px solid rgb(255 255 255 / 0.55)',
|
|
42
|
+
borderRadius: 3,
|
|
43
|
+
cursor: 'pointer',
|
|
44
|
+
display: 'grid',
|
|
45
|
+
font: 'inherit',
|
|
46
|
+
gridTemplateRows: `${EDGE_BAND} 1fr ${EDGE_BAND}`,
|
|
47
|
+
justifyItems: 'center',
|
|
48
|
+
minWidth: 0,
|
|
49
|
+
overflow: 'hidden',
|
|
50
|
+
padding: '1px',
|
|
51
|
+
transition: 'opacity 120ms ease, filter 120ms ease',
|
|
52
|
+
} as const satisfies CSSProperties;
|
|
53
|
+
|
|
54
|
+
export const numberStyle = {
|
|
55
|
+
alignSelf: 'start',
|
|
56
|
+
gridColumn: 1,
|
|
57
|
+
gridRow: 1,
|
|
58
|
+
fontSize: `max(0.33rem, ${ofWidth(1.1)})`,
|
|
59
|
+
fontVariantNumeric: 'tabular-nums',
|
|
60
|
+
justifySelf: 'start',
|
|
61
|
+
lineHeight: 1,
|
|
62
|
+
opacity: 0.8,
|
|
63
|
+
} as const satisfies CSSProperties;
|
|
64
|
+
|
|
65
|
+
export const symbolStyle = {
|
|
66
|
+
alignSelf: 'center',
|
|
67
|
+
gridColumn: 1,
|
|
68
|
+
gridRow: 2,
|
|
69
|
+
fontWeight: 700,
|
|
70
|
+
letterSpacing: '-0.02em',
|
|
71
|
+
lineHeight: 1.02,
|
|
72
|
+
} as const satisfies CSSProperties;
|
|
73
|
+
|
|
74
|
+
export const detailStyle = {
|
|
75
|
+
alignSelf: 'center',
|
|
76
|
+
gridColumn: 1,
|
|
77
|
+
gridRow: 3,
|
|
78
|
+
fontVariantNumeric: 'tabular-nums',
|
|
79
|
+
lineHeight: 1,
|
|
80
|
+
overflow: 'hidden',
|
|
81
|
+
whiteSpace: 'nowrap',
|
|
82
|
+
} as const satisfies CSSProperties;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The electrons of each shell, innermost at the top, down the right-hand edge
|
|
86
|
+
* of the whole cell: the stack is as tall as the three bands together, which
|
|
87
|
+
* is what lets seven of them be read.
|
|
88
|
+
*/
|
|
89
|
+
export const shellsStyle = {
|
|
90
|
+
alignSelf: 'center',
|
|
91
|
+
gridColumn: 2,
|
|
92
|
+
gridRow: '1 / span 3',
|
|
93
|
+
fontVariantNumeric: 'tabular-nums',
|
|
94
|
+
justifySelf: 'end',
|
|
95
|
+
lineHeight: SHELL_LEADING,
|
|
96
|
+
opacity: 0.85,
|
|
97
|
+
paddingInlineEnd: `max(0.5px, ${ofWidth(0.15)})`,
|
|
98
|
+
textAlign: 'right',
|
|
99
|
+
whiteSpace: 'pre-line',
|
|
100
|
+
} as const satisfies CSSProperties;
|