react-cheminfo 0.31.0 → 0.32.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/README.md +1 -0
- package/lib/core.d.ts +1 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +1 -0
- package/lib/core.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 +3 -1
- package/lib/locales/en.json +3 -1
- package/lib/locales/es.json +3 -1
- package/lib/locales/fr.json +3 -1
- package/lib/number/core/index.d.ts +2 -0
- package/lib/number/core/index.d.ts.map +1 -0
- package/lib/number/core/index.js +2 -0
- package/lib/number/core/index.js.map +1 -0
- package/lib/number/core/numberText.d.ts +46 -0
- package/lib/number/core/numberText.d.ts.map +1 -0
- package/lib/number/core/numberText.js +88 -0
- package/lib/number/core/numberText.js.map +1 -0
- package/lib/number/ui/NumberInput.d.ts +113 -0
- package/lib/number/ui/NumberInput.d.ts.map +1 -0
- package/lib/number/ui/NumberInput.js +100 -0
- package/lib/number/ui/NumberInput.js.map +1 -0
- package/lib/number/ui/index.d.ts +3 -0
- package/lib/number/ui/index.d.ts.map +1 -0
- package/lib/number/ui/index.js +2 -0
- package/lib/number/ui/index.js.map +1 -0
- package/lib/periodic/ui/ElementCell.d.ts +10 -0
- package/lib/periodic/ui/ElementCell.d.ts.map +1 -1
- package/lib/periodic/ui/ElementCell.js +124 -14
- package/lib/periodic/ui/ElementCell.js.map +1 -1
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +46 -19
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/periodic/ui/PeriodicTableChrome.js +2 -2
- package/lib/periodic/ui/PeriodicTableChrome.js.map +1 -1
- package/lib/spectra/ui/NumberField.d.ts +2 -5
- package/lib/spectra/ui/NumberField.d.ts.map +1 -1
- package/lib/spectra/ui/NumberField.js +4 -54
- package/lib/spectra/ui/NumberField.js.map +1 -1
- package/lib/ui.d.ts +1 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +1 -0
- package/lib/ui.js.map +1 -1
- package/package.json +1 -1
- package/src/core.ts +1 -0
- package/src/locales/de.json +3 -1
- package/src/locales/en.json +3 -1
- package/src/locales/es.json +3 -1
- package/src/locales/fr.json +3 -1
- package/src/number/core/index.ts +6 -0
- package/src/number/core/numberText.ts +91 -0
- package/src/number/ui/NumberInput.tsx +300 -0
- package/src/number/ui/index.ts +7 -0
- package/src/periodic/ui/ElementCell.tsx +153 -14
- package/src/periodic/ui/PeriodicTable.tsx +51 -22
- package/src/periodic/ui/PeriodicTableChrome.tsx +2 -2
- package/src/spectra/ui/NumberField.tsx +11 -58
- package/src/ui.ts +1 -0
|
@@ -129,6 +129,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
129
129
|
} = props;
|
|
130
130
|
|
|
131
131
|
const t = useChromeT();
|
|
132
|
+
const writesDetail = detailOf !== undefined;
|
|
132
133
|
const gridRef = useRef<HTMLDivElement>(null);
|
|
133
134
|
const cameFromKeyRef = useRef(false);
|
|
134
135
|
const offset = headers ? 1 : 0;
|
|
@@ -159,7 +160,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
159
160
|
role="grid"
|
|
160
161
|
aria-label={t('periodic.table')}
|
|
161
162
|
data-testid="periodic-table"
|
|
162
|
-
style={headers
|
|
163
|
+
style={gridStyle(headers, writesDetail)}
|
|
163
164
|
onKeyDown={handleKeyDown}
|
|
164
165
|
>
|
|
165
166
|
{headers ? <HeaderStrips onSelectRange={onSelectRange} /> : null}
|
|
@@ -171,6 +172,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
171
172
|
symbol={element.symbol}
|
|
172
173
|
name={nameOf(element)}
|
|
173
174
|
detail={detailOf?.(element)}
|
|
175
|
+
writesDetail={writesDetail}
|
|
174
176
|
swatch={swatchOf(element)}
|
|
175
177
|
isSelected={element.symbol === selected}
|
|
176
178
|
isIncluded={isIncluded?.(element)}
|
|
@@ -199,37 +201,64 @@ function noop(): void {
|
|
|
199
201
|
// keyboard and a screen reader still reach every element.
|
|
200
202
|
}
|
|
201
203
|
|
|
204
|
+
/** Narrowest the table is ever drawn; under it the type stops being readable. */
|
|
205
|
+
const MIN_WIDTH = 280;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* How tall one row of elements is, as a share of the table's width.
|
|
209
|
+
*
|
|
210
|
+
* A column is about 5.4% of that width, so a cell is a seventh taller than it
|
|
211
|
+
* is wide — the proportion of a wall chart, and the room the three lines of a
|
|
212
|
+
* cell need to be written at a size a class can read.
|
|
213
|
+
*/
|
|
214
|
+
const ROW_HEIGHT = '6.1cqw';
|
|
215
|
+
|
|
216
|
+
/** The same, in a table that writes nothing under the symbol. */
|
|
217
|
+
const ROW_HEIGHT_ALONE = '4.9cqw';
|
|
218
|
+
|
|
219
|
+
/** The band the two inner-transition series were lifted out across. */
|
|
220
|
+
const SERIES_GAP = 'max(6px, 1.1cqw)';
|
|
221
|
+
|
|
202
222
|
const rootStyle = {
|
|
203
223
|
display: 'flex',
|
|
204
224
|
flexDirection: 'column',
|
|
205
225
|
gap: 8,
|
|
226
|
+
minWidth: MIN_WIDTH,
|
|
227
|
+
// Everything inside — the height of a row as much as the type in a cell — is
|
|
228
|
+
// a share of this box rather than of the page, so the same table reads at
|
|
229
|
+
// 280px beside a chart and fills a lecture-hall screen at twice that.
|
|
230
|
+
containerType: 'inline-size',
|
|
206
231
|
} as const satisfies CSSProperties;
|
|
207
232
|
|
|
208
233
|
const baseGridStyle = {
|
|
209
234
|
display: 'grid',
|
|
210
235
|
gap: 2,
|
|
236
|
+
minWidth: MIN_WIDTH,
|
|
211
237
|
width: '100%',
|
|
212
|
-
// The cells size their type against this box rather than against the page,
|
|
213
|
-
// so the same table reads at 320px beside a chart and at 900px on its own.
|
|
214
|
-
containerType: 'inline-size',
|
|
215
238
|
} as const satisfies CSSProperties;
|
|
216
239
|
|
|
217
|
-
|
|
218
|
-
|
|
240
|
+
/**
|
|
241
|
+
* The grid the cells are placed on.
|
|
242
|
+
* @param headers - Whether a leading column and row hold the period and group
|
|
243
|
+
* numbers.
|
|
244
|
+
* @param writesDetail - Whether a cell writes a third line, which is what a
|
|
245
|
+
* row is tall enough for.
|
|
246
|
+
* @returns The style of the grid.
|
|
247
|
+
*/
|
|
248
|
+
function gridStyle(headers: boolean, writesDetail: boolean): CSSProperties {
|
|
249
|
+
const row = writesDetail ? ROW_HEIGHT : ROW_HEIGHT_ALONE;
|
|
219
250
|
// The eighth row is the gap the inner-transition series are lifted out into.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
minWidth: 280,
|
|
235
|
-
} as const satisfies CSSProperties;
|
|
251
|
+
const rows = `repeat(7, ${row}) ${SERIES_GAP} repeat(2, ${row})`;
|
|
252
|
+
if (!headers) {
|
|
253
|
+
return {
|
|
254
|
+
...baseGridStyle,
|
|
255
|
+
gridTemplateColumns: `repeat(${String(COLUMN_COUNT)}, minmax(0, 1fr))`,
|
|
256
|
+
gridTemplateRows: rows,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
...baseGridStyle,
|
|
261
|
+
gridTemplateColumns: `max(14px, 2.4cqw) repeat(${String(COLUMN_COUNT)}, minmax(0, 1fr))`,
|
|
262
|
+
gridTemplateRows: `max(12px, 2cqw) ${rows}`,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
@@ -150,7 +150,7 @@ const headerStyle = {
|
|
|
150
150
|
alignItems: 'center',
|
|
151
151
|
color: TOKEN.textMuted,
|
|
152
152
|
display: 'flex',
|
|
153
|
-
fontSize: '
|
|
153
|
+
fontSize: 'max(0.45rem, 1.35cqw)',
|
|
154
154
|
justifyContent: 'center',
|
|
155
155
|
padding: 0,
|
|
156
156
|
} as const satisfies CSSProperties;
|
|
@@ -168,6 +168,6 @@ const markerStyle = {
|
|
|
168
168
|
borderRadius: 3,
|
|
169
169
|
color: TOKEN.textMuted,
|
|
170
170
|
display: 'flex',
|
|
171
|
-
fontSize: '
|
|
171
|
+
fontSize: 'max(0.4rem, 1.15cqw)',
|
|
172
172
|
justifyContent: 'center',
|
|
173
173
|
} as const satisfies CSSProperties;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { InputGroup } from '@blueprintjs/core';
|
|
2
1
|
import type { ReactElement } from 'react';
|
|
3
|
-
|
|
2
|
+
|
|
3
|
+
import { NumberInput } from '../../number/ui/NumberInput.tsx';
|
|
4
4
|
|
|
5
5
|
import { HELP_STYLE, LABEL_STYLE, sizedFieldStyle } from './fieldStyles.ts';
|
|
6
6
|
|
|
@@ -35,77 +35,30 @@ interface NumberFieldProps {
|
|
|
35
35
|
/**
|
|
36
36
|
* One number of the settings.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* under them would make the field unusable. Nothing is handed up until the text
|
|
41
|
-
* reads as a number, and emptying the box hands up nothing at all — which is
|
|
42
|
-
* how a reader gets back to upstream's default after typing over it.
|
|
38
|
+
* Emptying the box hands up nothing at all, which is how a reader gets back to
|
|
39
|
+
* upstream's default after typing over it.
|
|
43
40
|
* @param props - See {@link NumberFieldProps}.
|
|
44
41
|
* @returns The labelled box.
|
|
45
42
|
*/
|
|
46
43
|
export function NumberField(props: NumberFieldProps): ReactElement {
|
|
47
44
|
const { label, value, placeholder, onChange, integer = false, help } = props;
|
|
48
|
-
const [draft, setDraft] = useState(() => ({
|
|
49
|
-
text: asText(value),
|
|
50
|
-
held: value,
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
// The settings changed from somewhere else — a preset, a reset, a pasted
|
|
54
|
-
// configuration — so the box has to follow rather than hold the old text.
|
|
55
|
-
// `held` is what this box last handed up, not the prop it was rendered with:
|
|
56
|
-
// comparing against the prop would make the box's own edit look external and
|
|
57
|
-
// rewrite `-0.` as `0` under the caret before the reader reaches the digits.
|
|
58
|
-
if (draft.held !== value) setDraft({ text: asText(value), held: value });
|
|
59
45
|
|
|
60
46
|
return (
|
|
61
47
|
<label style={FIELD_STYLE}>
|
|
62
48
|
<span style={LABEL_STYLE}>{label}</span>
|
|
63
|
-
<
|
|
64
|
-
|
|
49
|
+
<NumberInput
|
|
50
|
+
allowEmpty
|
|
51
|
+
buttons={false}
|
|
65
52
|
fill
|
|
66
|
-
|
|
67
|
-
value={
|
|
53
|
+
size="small"
|
|
54
|
+
value={value}
|
|
68
55
|
placeholder={placeholder}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
onValueChange={(text) => {
|
|
72
|
-
const parsed = read(text, integer);
|
|
73
|
-
const emptied = text.trim() === '';
|
|
74
|
-
setDraft({ text, held: emptied ? undefined : (parsed ?? value) });
|
|
75
|
-
if (emptied) {
|
|
76
|
-
onChange(undefined);
|
|
77
|
-
} else if (parsed !== undefined) {
|
|
78
|
-
onChange(parsed);
|
|
79
|
-
}
|
|
80
|
-
}}
|
|
56
|
+
integer={integer}
|
|
57
|
+
onChange={onChange}
|
|
81
58
|
/>
|
|
82
59
|
{help === undefined ? null : <span style={HELP_STYLE}>{help}</span>}
|
|
83
60
|
</label>
|
|
84
61
|
);
|
|
85
62
|
}
|
|
86
63
|
|
|
87
|
-
/**
|
|
88
|
-
* The number as the box shows it.
|
|
89
|
-
* @param value - What the settings hold.
|
|
90
|
-
* @returns Its text, empty when nothing is held.
|
|
91
|
-
*/
|
|
92
|
-
function asText(value: number | undefined): string {
|
|
93
|
-
return value === undefined ? '' : String(value);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* The text as a number, when it reads as one.
|
|
98
|
-
* @param text - What was typed.
|
|
99
|
-
* @param integer - Whether only whole numbers make sense.
|
|
100
|
-
* @returns The number, or undefined while the text is not one yet.
|
|
101
|
-
*/
|
|
102
|
-
function read(text: string, integer: boolean): number | undefined {
|
|
103
|
-
const trimmed = text.trim();
|
|
104
|
-
if (trimmed === '') return undefined;
|
|
105
|
-
const parsed = Number(trimmed);
|
|
106
|
-
if (!Number.isFinite(parsed)) return undefined;
|
|
107
|
-
if (integer && !Number.isInteger(parsed)) return undefined;
|
|
108
|
-
return parsed;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
64
|
const FIELD_STYLE = sizedFieldStyle(120);
|
package/src/ui.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * from './help/ui/index.ts';
|
|
|
16
16
|
export * from './hooks/ui/index.ts';
|
|
17
17
|
export * from './i18n/ui/index.ts';
|
|
18
18
|
export * from './language/ui/index.ts';
|
|
19
|
+
export * from './number/ui/index.ts';
|
|
19
20
|
export * from './overlay/ui/index.ts';
|
|
20
21
|
export * from './panel/ui/index.ts';
|
|
21
22
|
export * from './parallel/ui/index.ts';
|