react-cheminfo 0.57.0 → 0.59.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 (63) hide show
  1. package/lib/chart/ui/ChartTrackingLayer.js +3 -1
  2. package/lib/chart/ui/ChartTrackingLayer.js.map +1 -1
  3. package/lib/chart/ui/useChartSize.d.ts +16 -0
  4. package/lib/chart/ui/useChartSize.d.ts.map +1 -1
  5. package/lib/chart/ui/useChartSize.js +34 -1
  6. package/lib/chart/ui/useChartSize.js.map +1 -1
  7. package/lib/core.d.ts +1 -0
  8. package/lib/core.d.ts.map +1 -1
  9. package/lib/core.js +1 -0
  10. package/lib/core.js.map +1 -1
  11. package/lib/ecosystem/core/types.d.ts +1 -1
  12. package/lib/ecosystem/core/types.d.ts.map +1 -1
  13. package/lib/ecosystem/core/unlistedSites.d.ts.map +1 -1
  14. package/lib/ecosystem/core/unlistedSites.js +19 -3
  15. package/lib/ecosystem/core/unlistedSites.js.map +1 -1
  16. package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
  17. package/lib/ecosystem/ui/glyphs.js +4 -1
  18. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  19. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  20. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  21. package/lib/locales/de.json +26 -1
  22. package/lib/locales/en.json +26 -1
  23. package/lib/locales/es.json +26 -1
  24. package/lib/locales/fr.json +26 -1
  25. package/lib/locales/it.json +26 -1
  26. package/lib/moleculesToken/core/index.d.ts +3 -0
  27. package/lib/moleculesToken/core/index.d.ts.map +1 -0
  28. package/lib/moleculesToken/core/index.js +2 -0
  29. package/lib/moleculesToken/core/index.js.map +1 -0
  30. package/lib/moleculesToken/core/moleculesToken.d.ts +101 -0
  31. package/lib/moleculesToken/core/moleculesToken.d.ts.map +1 -0
  32. package/lib/moleculesToken/core/moleculesToken.js +137 -0
  33. package/lib/moleculesToken/core/moleculesToken.js.map +1 -0
  34. package/lib/moleculesToken/ui/MoleculesTokenTable.d.ts +32 -0
  35. package/lib/moleculesToken/ui/MoleculesTokenTable.d.ts.map +1 -0
  36. package/lib/moleculesToken/ui/MoleculesTokenTable.js +124 -0
  37. package/lib/moleculesToken/ui/MoleculesTokenTable.js.map +1 -0
  38. package/lib/moleculesToken/ui/index.d.ts +3 -0
  39. package/lib/moleculesToken/ui/index.d.ts.map +1 -0
  40. package/lib/moleculesToken/ui/index.js +2 -0
  41. package/lib/moleculesToken/ui/index.js.map +1 -0
  42. package/lib/ui.d.ts +1 -0
  43. package/lib/ui.d.ts.map +1 -1
  44. package/lib/ui.js +1 -0
  45. package/lib/ui.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/chart/ui/ChartTrackingLayer.tsx +3 -1
  48. package/src/chart/ui/useChartSize.ts +44 -1
  49. package/src/core.ts +1 -0
  50. package/src/ecosystem/core/types.ts +3 -2
  51. package/src/ecosystem/core/unlistedSites.ts +19 -3
  52. package/src/ecosystem/ui/glyphs.tsx +11 -1
  53. package/src/locales/de.json +26 -1
  54. package/src/locales/en.json +26 -1
  55. package/src/locales/es.json +26 -1
  56. package/src/locales/fr.json +26 -1
  57. package/src/locales/it.json +26 -1
  58. package/src/moleculesToken/core/index.ts +11 -0
  59. package/src/moleculesToken/core/moleculesToken.ts +256 -0
  60. package/src/moleculesToken/ui/MoleculesTokenTable.tsx +249 -0
  61. package/src/moleculesToken/ui/index.ts +2 -0
  62. package/src/ui.ts +1 -0
  63. package/styles/chrome.css +35 -0
@@ -593,5 +593,30 @@
593
593
  "taxonomy.rank.noRank": "senza rango",
594
594
  "taxonomy.rank.clade": "clade",
595
595
  "taxonomy.rank.cellularRoot": "radice cellulare",
596
- "taxonomy.rank.acellularRoot": "radice acellulare"
596
+ "taxonomy.rank.acellularRoot": "radice acellulare",
597
+ "moleculesToken.title": "Token per molecules.cheminfo.org",
598
+ "moleculesToken.checkedAt": "Verificati il {when}",
599
+ "moleculesToken.checkAgain": "Verifica di nuovo",
600
+ "moleculesToken.notChecked": "Non ancora verificati: il servizio che scrive in molecules.cheminfo.org verifica i suoi token all'avvio.",
601
+ "moleculesToken.column.variable": "Variabile",
602
+ "moleculesToken.column.source": "Fonte",
603
+ "moleculesToken.column.status": "Stato",
604
+ "moleculesToken.column.details": "Dettagli",
605
+ "moleculesToken.anySource": "qualsiasi fonte",
606
+ "moleculesToken.verdict.ok": "valido",
607
+ "moleculesToken.verdict.otherSource": "di un'altra fonte",
608
+ "moleculesToken.verdict.refused": "rifiutato",
609
+ "moleculesToken.verdict.unset": "non impostato",
610
+ "moleculesToken.verdict.uncheckable": "non verificabile",
611
+ "moleculesToken.verdict.unanswered": "nessuna risposta",
612
+ "moleculesToken.forSource": "per {source}",
613
+ "moleculesToken.issued": "emesso il {when}",
614
+ "moleculesToken.issuedTo": "emesso per {email} il {when}",
615
+ "moleculesToken.lastUsed": "usato l'ultima volta il {when}",
616
+ "moleculesToken.neverUsed": "mai usato",
617
+ "moleculesToken.otherSourceDetail": "emesso per {source}: ciò che invia è attribuito a quella fonte",
618
+ "moleculesToken.refusedDetail": "mai emesso, o revocato",
619
+ "moleculesToken.unsetDetail": "Impostare {variable} nel file .env del server.",
620
+ "moleculesToken.uncheckableDetail": "Questo molecules.cheminfo.org non sa ancora verificare un token.",
621
+ "moleculesToken.howToChange": "Un token si cambia nel file .env del server e viene riletto al riavvio del servizio. molecules.cheminfo.org ne emette uno nuovo con"
597
622
  }
@@ -0,0 +1,3 @@
1
+ export type { CheckMoleculesTokenOptions, MoleculesTokenCheck, MoleculesTokenToCheck, MoleculesTokenVerdict, } from './moleculesToken.ts';
2
+ export { checkMoleculesToken, checkMoleculesTokens, publicTokenCheck, } from './moleculesToken.ts';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/moleculesToken/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { checkMoleculesToken, checkMoleculesTokens, publicTokenCheck, } from "./moleculesToken.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/moleculesToken/core/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * What molecules.cheminfo.org says of a token a site holds:
3
+ *
4
+ * - `ok`: issued for a source the site writes, and not revoked;
5
+ * - `otherSource`: valid, but issued for another source, so what the site
6
+ * sends is credited to that one;
7
+ * - `refused`: never issued, or revoked;
8
+ * - `unset`: the site holds none;
9
+ * - `uncheckable`: molecules.cheminfo.org answers, but cannot check a token
10
+ * yet;
11
+ * - `unanswered`: it did not answer, or failed.
12
+ */
13
+ export type MoleculesTokenVerdict = 'ok' | 'otherSource' | 'refused' | 'unset' | 'uncheckable' | 'unanswered';
14
+ /** A token a site holds, to be checked. */
15
+ export interface MoleculesTokenToCheck {
16
+ /** The environment variable it is read from, e.g. `MOLECULES_TOKEN_LOTUS`. */
17
+ variable: string;
18
+ /** The token, or undefined when the variable is unset or blank. */
19
+ token: string | undefined;
20
+ /**
21
+ * The sources it may have been issued for, as molecules.cheminfo.org names
22
+ * them: any one of them is right, whatever its case.
23
+ * @default [] — any source
24
+ */
25
+ sources?: readonly string[];
26
+ }
27
+ /** A token, as molecules.cheminfo.org checked it. Never the token itself. */
28
+ export interface MoleculesTokenCheck {
29
+ /** The environment variable it is read from. */
30
+ variable: string;
31
+ /** The sources it may have been issued for; empty for any source. */
32
+ sources: string[];
33
+ /** What molecules.cheminfo.org says of it. */
34
+ verdict: MoleculesTokenVerdict;
35
+ /**
36
+ * What molecules.cheminfo.org said, or why it could not be asked; null when
37
+ * the verdict says it all.
38
+ */
39
+ message: string | null;
40
+ /** The source molecules.cheminfo.org knows it for, once it answered. */
41
+ source: string | null;
42
+ /**
43
+ * Its first characters, as molecules.cheminfo.org shows them: what tells two
44
+ * tokens apart without showing either.
45
+ */
46
+ hint: string | null;
47
+ /** Who it was issued to. */
48
+ email: string | null;
49
+ /** When it was issued, in epoch milliseconds. */
50
+ issuedAt: number | null;
51
+ /** When it last read or wrote, in epoch milliseconds, to within a minute. */
52
+ lastUsedAt: number | null;
53
+ /** When it was checked, in epoch milliseconds. */
54
+ checkedAt: number;
55
+ }
56
+ /** Where molecules.cheminfo.org answers, and how patiently it is asked. */
57
+ export interface CheckMoleculesTokenOptions {
58
+ /** Where it answers, e.g. `https://molecules.cheminfo.org`. */
59
+ baseUrl: string;
60
+ /**
61
+ * How long one check may take.
62
+ * @default 5000
63
+ */
64
+ timeoutMs?: number;
65
+ /**
66
+ * The fetch to use, for tests.
67
+ * @default globalThis.fetch
68
+ */
69
+ fetch?: typeof fetch;
70
+ /**
71
+ * The clock the checks are stamped with, for tests.
72
+ * @default Date.now
73
+ */
74
+ now?: () => number;
75
+ }
76
+ /**
77
+ * Ask molecules.cheminfo.org about a token: `GET /v1/token`, which says which
78
+ * source it was issued for and never counts as using it. A token pasted in
79
+ * another source's place, revoked, or never issued shows here before an import
80
+ * sends anything with it. Never throws: a molecules.cheminfo.org that does not
81
+ * answer is a verdict too.
82
+ * @param entry - The token, where it is read from, and the sources it may be for.
83
+ * @param options - Where molecules.cheminfo.org answers, and how patiently.
84
+ * @returns What it says of the token.
85
+ */
86
+ export declare function checkMoleculesToken(entry: MoleculesTokenToCheck, options: CheckMoleculesTokenOptions): Promise<MoleculesTokenCheck>;
87
+ /**
88
+ * Check every token a site holds, all at once.
89
+ * @param entries - The tokens. See {@link checkMoleculesToken}.
90
+ * @param options - See {@link CheckMoleculesTokenOptions}.
91
+ * @returns What molecules.cheminfo.org says of each, in the order given.
92
+ */
93
+ export declare function checkMoleculesTokens(entries: readonly MoleculesTokenToCheck[], options: CheckMoleculesTokenOptions): Promise<MoleculesTokenCheck[]>;
94
+ /**
95
+ * What a page anyone can open may show of a check: the verdict and the source,
96
+ * without who the token was issued to or its first characters.
97
+ * @param check - The check.
98
+ * @returns The check, without them.
99
+ */
100
+ export declare function publicTokenCheck(check: MoleculesTokenCheck): MoleculesTokenCheck;
101
+ //# sourceMappingURL=moleculesToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moleculesToken.d.ts","sourceRoot":"","sources":["../../../src/moleculesToken/core/moleculesToken.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,GAC/B,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,CAAC;AAE5E,2CAA2C;AAC3C,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,8CAA8C;IAC9C,OAAO,EAAE,qBAAqB,CAAC;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wEAAwE;IACxE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,2EAA2E;AAC3E,MAAM,WAAW,0BAA0B;IACzC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,qBAAqB,EAC5B,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CA0E9B;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAIhC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,mBAAmB,GACzB,mBAAmB,CAErB"}
@@ -0,0 +1,137 @@
1
+ import { trimTrailingSlash } from "../../router/core/address.js";
2
+ /**
3
+ * Ask molecules.cheminfo.org about a token: `GET /v1/token`, which says which
4
+ * source it was issued for and never counts as using it. A token pasted in
5
+ * another source's place, revoked, or never issued shows here before an import
6
+ * sends anything with it. Never throws: a molecules.cheminfo.org that does not
7
+ * answer is a verdict too.
8
+ * @param entry - The token, where it is read from, and the sources it may be for.
9
+ * @param options - Where molecules.cheminfo.org answers, and how patiently.
10
+ * @returns What it says of the token.
11
+ */
12
+ export async function checkMoleculesToken(entry, options) {
13
+ const { baseUrl, timeoutMs = 5000, fetch: fetchImplementation = globalThis.fetch, now = Date.now, } = options;
14
+ const sources = entry.sources === undefined ? [] : [...entry.sources];
15
+ const verdict = (value, message = null) => ({
16
+ variable: entry.variable,
17
+ sources,
18
+ verdict: value,
19
+ message,
20
+ source: null,
21
+ hint: null,
22
+ email: null,
23
+ issuedAt: null,
24
+ lastUsedAt: null,
25
+ checkedAt: now(),
26
+ });
27
+ const token = entry.token?.trim();
28
+ if (!token)
29
+ return verdict('unset');
30
+ let response;
31
+ try {
32
+ response = await fetchImplementation(`${trimTrailingSlash(baseUrl)}/v1/token`, {
33
+ headers: {
34
+ accept: 'application/json',
35
+ authorization: `Bearer ${token}`,
36
+ },
37
+ signal: AbortSignal.timeout(timeoutMs),
38
+ });
39
+ }
40
+ catch (error) {
41
+ return verdict('unanswered', whyUnanswered(error, timeoutMs));
42
+ }
43
+ if (response.status === 401) {
44
+ return verdict('refused', await messageOf(response));
45
+ }
46
+ if (response.status === 404) {
47
+ await response.body?.cancel();
48
+ return verdict('uncheckable', 'GET /v1/token answered 404');
49
+ }
50
+ if (!response.ok) {
51
+ await response.body?.cancel();
52
+ return verdict('unanswered', `GET /v1/token answered ${response.status}`);
53
+ }
54
+ const record = await recordOf(response);
55
+ if (record === null) {
56
+ return verdict('unanswered', 'GET /v1/token answered no token');
57
+ }
58
+ const known = {
59
+ source: record.source,
60
+ hint: record.hint,
61
+ email: record.email,
62
+ issuedAt: record.createdAt * 1000,
63
+ lastUsedAt: record.lastUsedAt === null ? null : record.lastUsedAt * 1000,
64
+ };
65
+ if (record.revokedAt !== null) {
66
+ return { ...verdict('refused', 'this token was revoked'), ...known };
67
+ }
68
+ const wanted = record.source.toLowerCase();
69
+ const expected = sources.length === 0 ||
70
+ sources.some((source) => source.toLowerCase() === wanted);
71
+ return { ...verdict(expected ? 'ok' : 'otherSource'), ...known };
72
+ }
73
+ /**
74
+ * Check every token a site holds, all at once.
75
+ * @param entries - The tokens. See {@link checkMoleculesToken}.
76
+ * @param options - See {@link CheckMoleculesTokenOptions}.
77
+ * @returns What molecules.cheminfo.org says of each, in the order given.
78
+ */
79
+ export async function checkMoleculesTokens(entries, options) {
80
+ return Promise.all(entries.map((entry) => checkMoleculesToken(entry, options)));
81
+ }
82
+ /**
83
+ * What a page anyone can open may show of a check: the verdict and the source,
84
+ * without who the token was issued to or its first characters.
85
+ * @param check - The check.
86
+ * @returns The check, without them.
87
+ */
88
+ export function publicTokenCheck(check) {
89
+ return { ...check, email: null, hint: null };
90
+ }
91
+ async function recordOf(response) {
92
+ let body;
93
+ try {
94
+ body = await response.json();
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ if (typeof body !== 'object' || body === null)
100
+ return null;
101
+ const record = body;
102
+ if (typeof record.source !== 'string' ||
103
+ typeof record.email !== 'string' ||
104
+ typeof record.hint !== 'string' ||
105
+ typeof record.createdAt !== 'number' ||
106
+ !isOptionalNumber(record.lastUsedAt) ||
107
+ !isOptionalNumber(record.revokedAt)) {
108
+ return null;
109
+ }
110
+ return {
111
+ source: record.source,
112
+ email: record.email,
113
+ hint: record.hint,
114
+ createdAt: record.createdAt,
115
+ lastUsedAt: record.lastUsedAt,
116
+ revokedAt: record.revokedAt,
117
+ };
118
+ }
119
+ function isOptionalNumber(value) {
120
+ return value === null || typeof value === 'number';
121
+ }
122
+ async function messageOf(response) {
123
+ try {
124
+ const body = (await response.json());
125
+ return typeof body.message === 'string' ? body.message : null;
126
+ }
127
+ catch {
128
+ return null;
129
+ }
130
+ }
131
+ function whyUnanswered(error, timeoutMs) {
132
+ if (error?.name === 'TimeoutError') {
133
+ return `no answer within ${timeoutMs} ms`;
134
+ }
135
+ return error instanceof Error ? error.message : String(error);
136
+ }
137
+ //# sourceMappingURL=moleculesToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moleculesToken.js","sourceRoot":"","sources":["../../../src/moleculesToken/core/moleculesToken.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { MoleculesTokenCheck } from '../core/moleculesToken.ts';
2
+ /** What {@link MoleculesTokenTable} shows. */
3
+ export interface MoleculesTokenTableProps {
4
+ /** The last checks, or null before the first one was made. */
5
+ checks: readonly MoleculesTokenCheck[] | null;
6
+ /**
7
+ * Whether a check was asked for and is not made yet.
8
+ * @default false
9
+ */
10
+ pending?: boolean;
11
+ /**
12
+ * Asks for every token to be checked again. Left out, there is no button:
13
+ * a page anyone can open shows the last checks and asks for none.
14
+ * @default undefined
15
+ */
16
+ onCheckAgain?: () => void;
17
+ /**
18
+ * Why asking for a check failed.
19
+ * @default undefined
20
+ */
21
+ error?: string;
22
+ }
23
+ /**
24
+ * The tokens a site holds for molecules.cheminfo.org, one row each, with what
25
+ * molecules.cheminfo.org said of it when it was last checked: valid, another
26
+ * source's, refused, not set. A token is changed in the server's `.env`, never
27
+ * here, so the table says where.
28
+ * @param props - See {@link MoleculesTokenTableProps}.
29
+ * @returns The table.
30
+ */
31
+ export declare function MoleculesTokenTable(props: MoleculesTokenTableProps): import("react").JSX.Element;
32
+ //# sourceMappingURL=MoleculesTokenTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MoleculesTokenTable.d.ts","sourceRoot":"","sources":["../../../src/moleculesToken/ui/MoleculesTokenTable.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,mBAAmB,EAEpB,MAAM,2BAA2B,CAAC;AAEnC,8CAA8C;AAC9C,MAAM,WAAW,wBAAwB;IACvC,8DAA8D;IAC9D,MAAM,EAAE,SAAS,mBAAmB,EAAE,GAAG,IAAI,CAAC;IAC9C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,+BAgGlE"}
@@ -0,0 +1,124 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Callout, HTMLTable, Tag } from '@blueprintjs/core';
3
+ import { useMemo } from 'react';
4
+ import { useLanguage } from "../../i18n/ui/useLanguage.js";
5
+ import { useChromeT } from "../../i18n/ui/useT.js";
6
+ const INTENT = {
7
+ ok: 'success',
8
+ otherSource: 'danger',
9
+ refused: 'danger',
10
+ unset: 'warning',
11
+ uncheckable: 'warning',
12
+ unanswered: 'warning',
13
+ };
14
+ /** How each verdict reads in the table. */
15
+ const LABEL = {
16
+ ok: 'moleculesToken.verdict.ok',
17
+ otherSource: 'moleculesToken.verdict.otherSource',
18
+ refused: 'moleculesToken.verdict.refused',
19
+ unset: 'moleculesToken.verdict.unset',
20
+ uncheckable: 'moleculesToken.verdict.uncheckable',
21
+ unanswered: 'moleculesToken.verdict.unanswered',
22
+ };
23
+ /** The command a token is issued with, on molecules.cheminfo.org. */
24
+ const ISSUE_COMMAND = 'npm run tokens -- issue SOURCE EMAIL';
25
+ /**
26
+ * The tokens a site holds for molecules.cheminfo.org, one row each, with what
27
+ * molecules.cheminfo.org said of it when it was last checked: valid, another
28
+ * source's, refused, not set. A token is changed in the server's `.env`, never
29
+ * here, so the table says where.
30
+ * @param props - See {@link MoleculesTokenTableProps}.
31
+ * @returns The table.
32
+ */
33
+ export function MoleculesTokenTable(props) {
34
+ const { checks, pending = false, onCheckAgain, error } = props;
35
+ const t = useChromeT();
36
+ const language = useLanguage();
37
+ const formats = useMemo(() => ({
38
+ instant: new Intl.DateTimeFormat(language, {
39
+ dateStyle: 'medium',
40
+ timeStyle: 'short',
41
+ }),
42
+ sources: new Intl.ListFormat(language, { type: 'disjunction' }),
43
+ }), [language]);
44
+ const checkedAt = checks === null || checks.length === 0
45
+ ? null
46
+ : Math.min(...checks.map((check) => check.checkedAt));
47
+ return (_jsxs("section", { className: "molecules-tokens", "aria-label": t('moleculesToken.title'), "data-testid": "molecules-tokens", children: [_jsxs("div", { className: "molecules-tokens__head", children: [_jsx("span", { className: "molecules-tokens__title", children: t('moleculesToken.title') }), checkedAt !== null && (_jsx("span", { className: "molecules-tokens__muted", children: t('moleculesToken.checkedAt', {
48
+ when: formats.instant.format(checkedAt),
49
+ }) })), onCheckAgain !== undefined && (_jsx(Button, { size: "small", variant: "minimal", icon: "refresh", loading: pending, text: t('moleculesToken.checkAgain'), onClick: onCheckAgain, "data-testid": "molecules-tokens-check" }))] }), error !== undefined && (_jsx(Callout, { compact: true, intent: "danger", children: error })), checks === null ? (_jsx("p", { className: "molecules-tokens__muted", children: t('moleculesToken.notChecked') })) : (_jsx("div", { className: "molecules-tokens__scroll", children: _jsxs(HTMLTable, { compact: true, striped: true, className: "molecules-tokens__table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: t('moleculesToken.column.variable') }), _jsx("th", { children: t('moleculesToken.column.source') }), _jsx("th", { children: t('moleculesToken.column.status') }), _jsx("th", { children: t('moleculesToken.column.details') })] }) }), _jsx("tbody", { children: checks.map((check) => (_jsxs("tr", { "data-verdict": check.verdict, children: [_jsx("td", { children: _jsx("code", { children: check.variable }) }), _jsx("td", { children: check.sources.length === 0
50
+ ? t('moleculesToken.anySource')
51
+ : formats.sources.format(check.sources) }), _jsx("td", { children: _jsx(Tag, { minimal: true, intent: INTENT[check.verdict], children: t(LABEL[check.verdict]) }) }), _jsx("td", { children: details(check, t, formats.instant) })] }, check.variable))) })] }) })), _jsxs("p", { className: "molecules-tokens__muted", children: [t('moleculesToken.howToChange'), " ", _jsx("code", { children: ISSUE_COMMAND })] })] }));
52
+ }
53
+ /**
54
+ * What a row says besides its verdict.
55
+ * @param check - The check.
56
+ * @param t - The chrome's translator.
57
+ * @param instant - How an instant is written.
58
+ * @returns The cell's content.
59
+ */
60
+ function details(check, t, instant) {
61
+ const hint = check.hint === null
62
+ ? null
63
+ : ['hint', _jsxs("code", { children: [check.hint, "\u2026"] }, "hint")];
64
+ switch (check.verdict) {
65
+ case 'ok':
66
+ return facts([
67
+ check.sources.length === 1 || check.source === null
68
+ ? null
69
+ : ['source', t('moleculesToken.forSource', { source: check.source })],
70
+ check.issuedAt === null
71
+ ? null
72
+ : [
73
+ 'issued',
74
+ check.email === null
75
+ ? t('moleculesToken.issued', {
76
+ when: instant.format(check.issuedAt),
77
+ })
78
+ : t('moleculesToken.issuedTo', {
79
+ email: check.email,
80
+ when: instant.format(check.issuedAt),
81
+ }),
82
+ ],
83
+ [
84
+ 'used',
85
+ check.lastUsedAt === null
86
+ ? t('moleculesToken.neverUsed')
87
+ : t('moleculesToken.lastUsed', {
88
+ when: instant.format(check.lastUsedAt),
89
+ }),
90
+ ],
91
+ hint,
92
+ ]);
93
+ case 'otherSource':
94
+ return facts([
95
+ [
96
+ 'source',
97
+ t('moleculesToken.otherSourceDetail', {
98
+ source: check.source ?? '',
99
+ }),
100
+ ],
101
+ hint,
102
+ ]);
103
+ case 'refused':
104
+ return check.message ?? t('moleculesToken.refusedDetail');
105
+ case 'unset':
106
+ return t('moleculesToken.unsetDetail', { variable: check.variable });
107
+ case 'uncheckable':
108
+ return t('moleculesToken.uncheckableDetail');
109
+ case 'unanswered':
110
+ return check.message;
111
+ default:
112
+ return null;
113
+ }
114
+ }
115
+ /**
116
+ * Facts about a token, one after the other.
117
+ * @param parts - The facts; null ones are left out.
118
+ * @returns The facts, separated by a middle dot.
119
+ */
120
+ function facts(parts) {
121
+ const shown = parts.filter((part) => part !== null);
122
+ return shown.map(([key, content], index) => (_jsxs("span", { children: [index > 0 && ' · ', content] }, key)));
123
+ }
124
+ //# sourceMappingURL=MoleculesTokenTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MoleculesTokenTable.js","sourceRoot":"","sources":["../../../src/moleculesToken/ui/MoleculesTokenTable.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type { MoleculesTokenTableProps } from './MoleculesTokenTable.tsx';
2
+ export { MoleculesTokenTable } from './MoleculesTokenTable.tsx';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/moleculesToken/ui/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { MoleculesTokenTable } from "./MoleculesTokenTable.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/moleculesToken/ui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAC"}
package/lib/ui.d.ts CHANGED
@@ -18,6 +18,7 @@ export * from './help/ui/index.ts';
18
18
  export * from './hooks/ui/index.ts';
19
19
  export * from './i18n/ui/index.ts';
20
20
  export * from './language/ui/index.ts';
21
+ export * from './moleculesToken/ui/index.ts';
21
22
  export * from './number/ui/index.ts';
22
23
  export * from './overlay/ui/index.ts';
23
24
  export * from './panel/ui/index.ts';
package/lib/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AAKvC,YAAY,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AAKvC,YAAY,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,oCAAoC,CAAC"}
package/lib/ui.js CHANGED
@@ -18,6 +18,7 @@ export * from "./help/ui/index.js";
18
18
  export * from "./hooks/ui/index.js";
19
19
  export * from "./i18n/ui/index.js";
20
20
  export * from "./language/ui/index.js";
21
+ export * from "./moleculesToken/ui/index.js";
21
22
  export * from "./number/ui/index.js";
22
23
  export * from "./overlay/ui/index.js";
23
24
  export * from "./panel/ui/index.js";
package/lib/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AAMvC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAmC,CAAC;AAEnE,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AAMvC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAmC,CAAC;AAEnE,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,oCAAoC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-cheminfo",
3
- "version": "0.57.0",
3
+ "version": "0.59.0",
4
4
  "license": "MIT",
5
5
  "description": "React components, hooks and framework-free helpers shared by the cheminfo sites: site chrome, citations, sharing, routing, pedagogy, charts, and the structure, orbital and 3D molecule viewers",
6
6
  "author": "Luc Patiny",
@@ -180,9 +180,11 @@ const LAYER_STYLE = {
180
180
  pointerEvents: 'none',
181
181
  } as const satisfies CSSProperties;
182
182
 
183
+ // The slots run along x, so only a sideways finger tracks them: a vertical
184
+ // swipe that starts on the chart still scrolls the page or the card around it.
183
185
  const SLIDER_STYLE = {
184
186
  pointerEvents: 'auto',
185
- touchAction: 'none',
187
+ touchAction: 'pan-y',
186
188
  cursor: 'crosshair',
187
189
  } as const satisfies CSSProperties;
188
190
 
@@ -89,6 +89,34 @@ export function nextChartSize(
89
89
  return { width: nextWidth, height: nextHeight };
90
90
  }
91
91
 
92
+ /**
93
+ * The size an element is laid out at, which no CSS transform changes.
94
+ *
95
+ * `getBoundingClientRect` reports the box as painted: inside a popover that
96
+ * opens by scaling up from 30 %, a chart measured on its first frame is drawn
97
+ * at 30 % of its width, and stays so, since a transform never resizes the
98
+ * layout and the observer never fires again. `offsetWidth` is the laid-out
99
+ * size but rounded to a whole pixel, so the precise rectangle is kept unless a
100
+ * transform has visibly scaled it.
101
+ * @param element - The wrapper the chart is drawn in.
102
+ * @returns Its laid-out width and height.
103
+ */
104
+ export function layoutSize(element: Element): {
105
+ width: number;
106
+ height: number;
107
+ } {
108
+ const rect = element.getBoundingClientRect();
109
+ if (!hasOffsetSize(element)) {
110
+ return { width: rect.width, height: rect.height };
111
+ }
112
+ const { offsetWidth, offsetHeight } = element;
113
+ return {
114
+ width: Math.abs(rect.width - offsetWidth) < 1 ? rect.width : offsetWidth,
115
+ height:
116
+ Math.abs(rect.height - offsetHeight) < 1 ? rect.height : offsetHeight,
117
+ };
118
+ }
119
+
92
120
  /** What a chart is given before its element has ever been laid out. */
93
121
  const NO_SIZE: ChartSize = { width: 0, height: 0 };
94
122
 
@@ -101,10 +129,25 @@ function read(
101
129
  element: Element,
102
130
  setSize: Dispatch<SetStateAction<ChartSize>>,
103
131
  ): void {
104
- const { width, height } = element.getBoundingClientRect();
132
+ const { width, height } = layoutSize(element);
105
133
  setSize((current) => nextChartSize(current, width, height));
106
134
  }
107
135
 
136
+ /**
137
+ * Whether an element has a laid-out size of its own, as an HTML element does
138
+ * and an SVG one does not. Checked by shape, so it holds outside a browser.
139
+ * @param element - The element.
140
+ * @returns True when `offsetWidth` and `offsetHeight` are numbers.
141
+ */
142
+ function hasOffsetSize(
143
+ element: Element,
144
+ ): element is Element & { offsetWidth: number; offsetHeight: number } {
145
+ return (
146
+ typeof (element as Partial<HTMLElement>).offsetWidth === 'number' &&
147
+ typeof (element as Partial<HTMLElement>).offsetHeight === 'number'
148
+ );
149
+ }
150
+
108
151
  /**
109
152
  * One side of a measurement, as a size rather than as a number.
110
153
  * @param value - What the element was measured at.
package/src/core.ts CHANGED
@@ -14,6 +14,7 @@ export * from './error/core/index.ts';
14
14
  export * from './format/core/index.ts';
15
15
  export * from './i18n/core/index.ts';
16
16
  export * from './language/core/index.ts';
17
+ export * from './moleculesToken/core/index.ts';
17
18
  export * from './number/core/index.ts';
18
19
  export * from './orbital/core/index.ts';
19
20
  export * from './overlay/core/index.ts';
@@ -31,8 +31,9 @@ export type SiteId =
31
31
  | 'moles'
32
32
  | 'inorganic'
33
33
  | 'powerpoint'
34
- | 'naturals'
35
- | 'wikidata';
34
+ | 'chembio'
35
+ | 'wikidata'
36
+ | 'mz';
36
37
 
37
38
  /** A site's name, split the way its own wordmark splits it. */
38
39
  export interface SiteName {