react-cheminfo 0.29.0 → 0.31.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 (126) hide show
  1. package/README.md +62 -2
  2. package/lib/chrome/ui/AccountButton.d.ts +76 -0
  3. package/lib/chrome/ui/AccountButton.d.ts.map +1 -0
  4. package/lib/chrome/ui/AccountButton.js +66 -0
  5. package/lib/chrome/ui/AccountButton.js.map +1 -0
  6. package/lib/chrome/ui/index.d.ts +2 -0
  7. package/lib/chrome/ui/index.d.ts.map +1 -1
  8. package/lib/chrome/ui/index.js +1 -0
  9. package/lib/chrome/ui/index.js.map +1 -1
  10. package/lib/clipboard/ui/ClickToCopy.d.ts +6 -0
  11. package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -1
  12. package/lib/clipboard/ui/ClickToCopy.js +3 -3
  13. package/lib/clipboard/ui/ClickToCopy.js.map +1 -1
  14. package/lib/download/core/downloadFigure.d.ts +7 -5
  15. package/lib/download/core/downloadFigure.d.ts.map +1 -1
  16. package/lib/download/core/downloadFigure.js +7 -6
  17. package/lib/download/core/downloadFigure.js.map +1 -1
  18. package/lib/download/core/figureLayout.d.ts +55 -0
  19. package/lib/download/core/figureLayout.d.ts.map +1 -0
  20. package/lib/download/core/figureLayout.js +89 -0
  21. package/lib/download/core/figureLayout.js.map +1 -0
  22. package/lib/download/core/figureScale.d.ts +9 -0
  23. package/lib/download/core/figureScale.d.ts.map +1 -1
  24. package/lib/download/core/figureScale.js +10 -0
  25. package/lib/download/core/figureScale.js.map +1 -1
  26. package/lib/download/core/figureSettle.d.ts +51 -0
  27. package/lib/download/core/figureSettle.d.ts.map +1 -0
  28. package/lib/download/core/figureSettle.js +81 -0
  29. package/lib/download/core/figureSettle.js.map +1 -0
  30. package/lib/download/core/figureSvg.d.ts +7 -1
  31. package/lib/download/core/figureSvg.d.ts.map +1 -1
  32. package/lib/download/core/figureSvg.js +1 -0
  33. package/lib/download/core/figureSvg.js.map +1 -1
  34. package/lib/download/core/figureSvgDocument.d.ts +7 -0
  35. package/lib/download/core/figureSvgDocument.d.ts.map +1 -1
  36. package/lib/download/core/figureSvgDocument.js +11 -2
  37. package/lib/download/core/figureSvgDocument.js.map +1 -1
  38. package/lib/download/core/index.d.ts +5 -1
  39. package/lib/download/core/index.d.ts.map +1 -1
  40. package/lib/download/core/index.js +3 -1
  41. package/lib/download/core/index.js.map +1 -1
  42. package/lib/download/ui/FigureDownload.d.ts +18 -4
  43. package/lib/download/ui/FigureDownload.d.ts.map +1 -1
  44. package/lib/download/ui/FigureDownload.js +35 -9
  45. package/lib/download/ui/FigureDownload.js.map +1 -1
  46. package/lib/download/ui/FigureDownloadPanel.d.ts +17 -7
  47. package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
  48. package/lib/download/ui/FigureDownloadPanel.js +30 -22
  49. package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
  50. package/lib/download/ui/FigureSizeField.d.ts +27 -0
  51. package/lib/download/ui/FigureSizeField.d.ts.map +1 -0
  52. package/lib/download/ui/FigureSizeField.js +87 -0
  53. package/lib/download/ui/FigureSizeField.js.map +1 -0
  54. package/lib/download/ui/FigureSizeRows.d.ts +34 -0
  55. package/lib/download/ui/FigureSizeRows.d.ts.map +1 -0
  56. package/lib/download/ui/FigureSizeRows.js +54 -0
  57. package/lib/download/ui/FigureSizeRows.js.map +1 -0
  58. package/lib/download/ui/index.d.ts +2 -0
  59. package/lib/download/ui/index.d.ts.map +1 -1
  60. package/lib/download/ui/index.js.map +1 -1
  61. package/lib/download/ui/useFigureRedraw.d.ts +27 -0
  62. package/lib/download/ui/useFigureRedraw.d.ts.map +1 -0
  63. package/lib/download/ui/useFigureRedraw.js +78 -0
  64. package/lib/download/ui/useFigureRedraw.js.map +1 -0
  65. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  66. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  67. package/lib/locales/de.json +13 -2
  68. package/lib/locales/en.json +13 -2
  69. package/lib/locales/es.json +13 -2
  70. package/lib/locales/fr.json +13 -2
  71. package/lib/overlay/ui/OverlayValueMenu.d.ts.map +1 -1
  72. package/lib/overlay/ui/OverlayValueMenu.js +7 -1
  73. package/lib/overlay/ui/OverlayValueMenu.js.map +1 -1
  74. package/lib/structure/core/conformerBoltzmann.d.ts +56 -0
  75. package/lib/structure/core/conformerBoltzmann.d.ts.map +1 -0
  76. package/lib/structure/core/conformerBoltzmann.js +96 -0
  77. package/lib/structure/core/conformerBoltzmann.js.map +1 -0
  78. package/lib/structure/core/conformerEnergy.d.ts +69 -0
  79. package/lib/structure/core/conformerEnergy.d.ts.map +1 -0
  80. package/lib/structure/core/conformerEnergy.js +47 -0
  81. package/lib/structure/core/conformerEnergy.js.map +1 -0
  82. package/lib/structure/core/index.d.ts +3 -0
  83. package/lib/structure/core/index.d.ts.map +1 -1
  84. package/lib/structure/core/index.js +2 -0
  85. package/lib/structure/core/index.js.map +1 -1
  86. package/lib/structure/ui/ConformerTable.d.ts +73 -0
  87. package/lib/structure/ui/ConformerTable.d.ts.map +1 -0
  88. package/lib/structure/ui/ConformerTable.js +259 -0
  89. package/lib/structure/ui/ConformerTable.js.map +1 -0
  90. package/lib/structure/ui/conformerColumns.d.ts +30 -0
  91. package/lib/structure/ui/conformerColumns.d.ts.map +1 -0
  92. package/lib/structure/ui/conformerColumns.js +37 -0
  93. package/lib/structure/ui/conformerColumns.js.map +1 -0
  94. package/lib/ui.d.ts +4 -0
  95. package/lib/ui.d.ts.map +1 -1
  96. package/lib/ui.js +2 -0
  97. package/lib/ui.js.map +1 -1
  98. package/package.json +1 -1
  99. package/src/chrome/ui/AccountButton.tsx +185 -0
  100. package/src/chrome/ui/index.ts +2 -0
  101. package/src/clipboard/ui/ClickToCopy.tsx +9 -1
  102. package/src/download/core/downloadFigure.ts +12 -9
  103. package/src/download/core/figureLayout.ts +114 -0
  104. package/src/download/core/figureScale.ts +13 -0
  105. package/src/download/core/figureSettle.ts +112 -0
  106. package/src/download/core/figureSvg.ts +8 -1
  107. package/src/download/core/figureSvgDocument.ts +19 -2
  108. package/src/download/core/index.ts +13 -0
  109. package/src/download/ui/FigureDownload.tsx +88 -35
  110. package/src/download/ui/FigureDownloadPanel.tsx +45 -22
  111. package/src/download/ui/FigureSizeField.tsx +153 -0
  112. package/src/download/ui/FigureSizeRows.tsx +108 -0
  113. package/src/download/ui/index.ts +2 -0
  114. package/src/download/ui/useFigureRedraw.tsx +115 -0
  115. package/src/locales/de.json +13 -2
  116. package/src/locales/en.json +13 -2
  117. package/src/locales/es.json +13 -2
  118. package/src/locales/fr.json +13 -2
  119. package/src/overlay/ui/OverlayValueMenu.tsx +7 -1
  120. package/src/structure/core/conformerBoltzmann.ts +102 -0
  121. package/src/structure/core/conformerEnergy.ts +97 -0
  122. package/src/structure/core/index.ts +15 -0
  123. package/src/structure/ui/ConformerTable.tsx +429 -0
  124. package/src/structure/ui/conformerColumns.ts +55 -0
  125. package/src/ui.ts +12 -0
  126. package/styles/chrome.css +55 -0
package/README.md CHANGED
@@ -88,7 +88,7 @@ through a wildcard subpath exactly as `react-science` serves its own.
88
88
  | Area | `…/core` | `…/ui` |
89
89
  | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
90
  | **Site identity** | `siteById`, `findSiteByHost`, `siteTokensCss` | `SiteMark`, `Wordmark`, `SiteTheme`, `SiteTile`, `EcosystemButton`, `EcosystemLinks` |
91
- | **Chrome** | — | `SiteHeader`, `SiteFooter`, `NavLink`, `NavMenuButton`, `MenuButton`, `useCompactHeader` |
91
+ | **Chrome** | — | `SiteHeader`, `SiteFooter`, `NavLink`, `NavMenuButton`, `MenuButton`, `AccountButton`, `useCompactHeader` |
92
92
  | **Languages** | `LANGUAGES`, `DEFAULT_LANGUAGE`, `LANGUAGE_LABELS`, `isLanguage`, `MessageCatalog`, `CHROME_CATALOG`, `setMessageSession`, `loadCatalogs`, `LANGUAGE_PARAM`, `withLanguageParam` | `useT`, `useChromeT`, `useLanguage`, `LanguageSelect`, `SiteLanguage` |
93
93
  | **Citation** | `formatCitation`, `formatCitations`, `citationSegments`, `downloadCitation`, `citedReferences`, `doiUrl` | `CiteButton`, `CitationMenu`, `CitationPreview` |
94
94
  | **Share & embed** | `parseShareConfig`, `applyShareConfig`, `buildShareUrl`, `buildEmbedCode`, `isHidden`, `visibleShareParts`, `applySharePreset`, `findSharePreset`, the param codecs, `syncPreferencesWithUrl`, `applyPreferencesFromSearch`, `writePreferencesToSearch` | `ShareDialog`, `ShareButton`, `HiddenPartsProvider`, `PagePart`, `useIsHidden` |
@@ -239,6 +239,40 @@ import { EcosystemButton } from 'react-cheminfo/ui';
239
239
  - A tile **lights up in the colour of the site it opens**, so running the
240
240
  pointer down the grid is what makes the pairs of colours read.
241
241
 
242
+ ### `AccountButton`
243
+
244
+ The utility that says who a site is answering to: an invitation when nobody is
245
+ signed in, and the account's own mark when somebody is.
246
+
247
+ ```tsx
248
+ import { AccountButton } from 'react-cheminfo/ui';
249
+
250
+ <AccountButton
251
+ identity={
252
+ user === null ? null : { name: user.displayName, detail: user.email }
253
+ }
254
+ loading={loading}
255
+ signInHref="/login"
256
+ onSignIn={() => navigate({ kind: 'login' })}
257
+ onSignOut={() => void signOut()}
258
+ signInLabel="Teacher sign in"
259
+ />;
260
+ ```
261
+
262
+ - **The two states are told apart by whether an identity is on screen**, never
263
+ by the direction of an arrow. Blueprint's `log-in` and `log-out` are the same
264
+ arrow either side of the same door; at 14 px among four other monochrome
265
+ glyphs, a site drawing one reports a signed-out visitor as signed in. So the
266
+ invitation is the words _Sign in_ — it carries no glyph, which is what keeps
267
+ the bar from reducing it to a mark — and being signed in is the person's own
268
+ initials.
269
+ - `loading` draws **neither** state, at the width the mark will take. A bar that
270
+ offers to sign in and then turns into a name has told the visitor something
271
+ false, and that is the state they act on first.
272
+ - `items` are the account's own pages, listed in the menu above Sign out.
273
+ - `signInHref` keeps the invitation a real link, so a middle click opens a tab;
274
+ a site with no page for it passes `onSignIn` alone and opens a dialog.
275
+
242
276
  ### `AtomicOrbitalViewer`
243
277
 
244
278
  One hydrogen-like atomic orbital, screened by Slater's rules, sampled in the
@@ -537,6 +571,26 @@ resolved first — a `var(--border)` that left the site would draw a chart with
537
571
  axes. And the chrome floating over the picture is left behind: an `OverlayLayer`
538
572
  marks itself, so the cog in the corner never lands in the middle of the scatter.
539
573
 
574
+ The resolution applies to both formats: a PNG is painted with that many more
575
+ pixels, and an SVG, drawn the same, opens that many times larger. Neither
576
+ changes the figure's shape. Pass **`renderFigure`** and the panel also offers a
577
+ size: as shown, 4:3, 16:9, a journal column (8.5 cm, where
578
+ the text prints at the size it reads on screen) or a width × height typed in.
579
+ The figure is then drawn again off the page at that size, so its axes and labels
580
+ are laid out for the new shape rather than stretched, and saved once it has
581
+ stopped moving. Draw exactly what is on screen; only the box changes.
582
+
583
+ ```tsx
584
+ <FigureDownload
585
+ targetId="spectrum"
586
+ fileName="spectrum"
587
+ renderFigure={(size) => <Spectrum width={size.width} height={size.height} />}
588
+ />
589
+ ```
590
+
591
+ A chart that measures its own container can ignore `size`: the copy is mounted
592
+ in a box of exactly that size.
593
+
540
594
  `downloadFigure(target, options)`, `figureSvg` and `figurePng` are the same thing
541
595
  without the button, for a site saving a figure from its own menu.
542
596
 
@@ -675,11 +729,17 @@ export const SITE_CATALOG = new MessageCatalog({
675
729
  directory: 'src/locales',
676
730
  source: en,
677
731
  translations: {
678
- fr: () => import('../locales/fr.json', { with: { type: 'json' } }),
732
+ fr: () => import('../locales/fr.json'),
679
733
  },
680
734
  });
681
735
  ```
682
736
 
737
+ The lazy imports carry **no** `with { type: 'json' }`: a bundler turns a JSON
738
+ file into a JavaScript module, and the attribute makes the browser refuse the
739
+ chunk it is served for being `text/javascript`. The English import is static, so
740
+ the bundler resolves it before a browser ever sees it and may keep the
741
+ attribute.
742
+
683
743
  `const t = useT(SITE_CATALOG)` then reads it in the language of the page, typed
684
744
  by the English keys; `t.or(key, fallback)` is for a key built from the data,
685
745
  which the catalog may not have caught up with. Only the plain `{name}` argument
@@ -0,0 +1,76 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { NavItem } from './navItem.ts';
3
+ /** Who the site is answering to. */
4
+ export interface AccountIdentity {
5
+ /** What the person is called on screen. */
6
+ name: string;
7
+ /**
8
+ * What tells the account apart under that name — the address it is held at,
9
+ * the handle it was opened with.
10
+ * @default undefined
11
+ */
12
+ detail?: string;
13
+ /**
14
+ * The letters the mark is drawn with.
15
+ * @default the first letter of each of the first two words of `name`
16
+ */
17
+ initials?: string;
18
+ }
19
+ export interface AccountButtonProps {
20
+ /** Who is signed in, or `null` when nobody is. */
21
+ identity: AccountIdentity | null;
22
+ /**
23
+ * Whether the site has not heard back yet. Neither state is drawn until it
24
+ * has: a bar that offers to sign in and then turns into a name has told the
25
+ * visitor something false, and it is the state they act on first.
26
+ * @default false
27
+ */
28
+ loading?: boolean;
29
+ /**
30
+ * The address signing in happens at, for a site with a page of its own for
31
+ * it. Writing it keeps the entry a real link, so a middle click opens a tab.
32
+ * @default undefined
33
+ */
34
+ signInHref?: string;
35
+ /**
36
+ * What the site does when the invitation is picked — route to that page, or
37
+ * open a credentials dialog for a site that has no page.
38
+ * @default undefined
39
+ */
40
+ onSignIn?: () => void;
41
+ /**
42
+ * What the site does when Sign out is picked.
43
+ * @default undefined
44
+ */
45
+ onSignOut?: () => void;
46
+ /**
47
+ * What the invitation reads, for a site whose accounts are for one kind of
48
+ * person — "Teacher sign in". Two words: it is written out in the bar rather
49
+ * than folded into a glyph.
50
+ * @default the chrome's own word for it, in the language of the page
51
+ */
52
+ signInLabel?: string;
53
+ /**
54
+ * The account's own pages, listed above Sign out — a profile, a settings
55
+ * page.
56
+ * @default undefined
57
+ */
58
+ items?: readonly NavItem[];
59
+ }
60
+ /**
61
+ * The one utility of the bar that says who the site is answering to: an
62
+ * invitation when nobody is signed in, and the account's mark when somebody is.
63
+ *
64
+ * The two states are told apart by whether an identity is on screen, never by
65
+ * the direction of an arrow. Blueprint's `log-in` and `log-out` are the same
66
+ * arrow either side of the same door, and at 14 px among four other monochrome
67
+ * glyphs nobody reads which side it is on — a site drawing one reports the
68
+ * visitor as signed in while they are signed out. So the invitation is the
69
+ * words `Sign in`, which no mark can be mistaken for, and being signed in is
70
+ * the person's own initials.
71
+ * @param props - Who is signed in, what signing in and out do, and the pages
72
+ * the account's menu lists.
73
+ * @returns The entry, or nothing while the site is still asking.
74
+ */
75
+ export declare function AccountButton(props: AccountButtonProps): ReactElement | null;
76
+ //# sourceMappingURL=AccountButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountButton.d.ts","sourceRoot":"","sources":["../../../src/chrome/ui/AccountButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC5B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,GAAG,IAAI,CAgF5E"}
@@ -0,0 +1,66 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Menu, MenuDivider, MenuItem, PopoverNext } from '@blueprintjs/core';
3
+ import { useChromeT } from "../../i18n/ui/useT.js";
4
+ import { NavLink } from "./NavLink.js";
5
+ import { isModifiedClick } from "./navItem.js";
6
+ /**
7
+ * The one utility of the bar that says who the site is answering to: an
8
+ * invitation when nobody is signed in, and the account's mark when somebody is.
9
+ *
10
+ * The two states are told apart by whether an identity is on screen, never by
11
+ * the direction of an arrow. Blueprint's `log-in` and `log-out` are the same
12
+ * arrow either side of the same door, and at 14 px among four other monochrome
13
+ * glyphs nobody reads which side it is on — a site drawing one reports the
14
+ * visitor as signed in while they are signed out. So the invitation is the
15
+ * words `Sign in`, which no mark can be mistaken for, and being signed in is
16
+ * the person's own initials.
17
+ * @param props - Who is signed in, what signing in and out do, and the pages
18
+ * the account's menu lists.
19
+ * @returns The entry, or nothing while the site is still asking.
20
+ */
21
+ export function AccountButton(props) {
22
+ const { identity, loading = false, signInHref, onSignIn, onSignOut, signInLabel, items = [], } = props;
23
+ const t = useChromeT();
24
+ if (loading) {
25
+ // The width of the mark, so the bar does not jump when the answer lands.
26
+ return _jsx("span", { className: "account-button__pending", "aria-hidden": "true" });
27
+ }
28
+ if (identity === null) {
29
+ return (_jsx(NavLink, { className: "account-button account-button--out", item: {
30
+ id: 'account',
31
+ label: signInLabel ?? t('account.signIn'),
32
+ href: signInHref,
33
+ onSelect: onSignIn,
34
+ } }));
35
+ }
36
+ const { name, detail, initials = initialsOf(name) } = identity;
37
+ return (_jsx(PopoverNext, { placement: "bottom-end", content: _jsxs(Menu, { className: "nav-menu account-menu", children: [_jsxs("li", { className: "account-menu__identity", children: [_jsx("span", { className: "account-menu__name", children: name }), detail === undefined ? null : (_jsx("span", { className: "account-menu__detail", children: detail }))] }), _jsx(MenuDivider, {}), items.map((item) => (_jsx(MenuItem, { icon: item.icon, text: item.label, href: item.href, target: item.external ? '_blank' : undefined, onClick: (event) => {
38
+ if (item.onSelect === undefined || isModifiedClick(event)) {
39
+ return;
40
+ }
41
+ event.preventDefault();
42
+ item.onSelect();
43
+ } }, item.id))), items.length === 0 ? null : _jsx(MenuDivider, {}), _jsx(MenuItem, { icon: "log-out", text: t('account.signOut'), onClick: onSignOut })] }), children: _jsx("button", { type: "button", className: "nav-link nav-link--icon account-button account-button--in", title: t('account.signedInAs', { name }), "aria-label": t('account.signedInAs', { name }), children: _jsx("span", { className: "account-mark", children: initials }) }) }));
44
+ }
45
+ /**
46
+ * The letters a name is marked with: the first of each of its first two words,
47
+ * or the first two letters of a name written as one word.
48
+ * @param name - What the person is called.
49
+ * @returns One or two letters, in capitals.
50
+ */
51
+ function initialsOf(name) {
52
+ const [first, second] = name.split(/\s+/).filter((word) => word !== '');
53
+ if (first === undefined)
54
+ return '?';
55
+ if (second === undefined)
56
+ return firstWordInitials(first);
57
+ return `${first.charAt(0)}${second.charAt(0)}`.toUpperCase();
58
+ }
59
+ // A single word is usually a handle or an address, where the two letters say
60
+ // more than one does — but never the part after the `@`, which every account
61
+ // on the same domain would share.
62
+ function firstWordInitials(word) {
63
+ const [local = ''] = word.split('@');
64
+ return (local === '' ? word : local).slice(0, 2).toUpperCase();
65
+ }
66
+ //# sourceMappingURL=AccountButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountButton.js","sourceRoot":"","sources":["../../../src/chrome/ui/AccountButton.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ export type { AccountButtonProps, AccountIdentity } from './AccountButton.tsx';
2
+ export { AccountButton } from './AccountButton.tsx';
1
3
  export type { HeaderToggleOption, HeaderToggleProps } from './HeaderToggle.tsx';
2
4
  export { HeaderToggle } from './HeaderToggle.tsx';
3
5
  export type { NavItem } from './navItem.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/chrome/ui/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/chrome/ui/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,3 +1,4 @@
1
+ export { AccountButton } from "./AccountButton.js";
1
2
  export { HeaderToggle } from "./HeaderToggle.js";
2
3
  // A site drawing its own link needs the same reading of a click the shared nav
3
4
  // items use: a middle click or a modified one belongs to the browser.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/chrome/ui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAoB,CAAC;AAElD,+EAA+E;AAC/E,sEAAsE;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAe,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAkB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/chrome/ui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAoB,CAAC;AAElD,+EAA+E;AAC/E,sEAAsE;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAe,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAkB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -53,6 +53,12 @@ export interface ClickToCopyProps {
53
53
  * @default undefined
54
54
  */
55
55
  style?: CSSProperties;
56
+ /**
57
+ * `data-testid` the element carries, so an end-to-end suite can select the
58
+ * value without depending on the text inside it.
59
+ * @default undefined
60
+ */
61
+ testId?: string;
56
62
  }
57
63
  /**
58
64
  * A value that is copied by clicking it.
@@ -1 +1 @@
1
- {"version":3,"file":"ClickToCopy.d.ts","sourceRoot":"","sources":["../../../src/clipboard/ui/ClickToCopy.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EAGb,YAAY,EACZ,SAAS,EACV,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAKpE,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;AAEvE,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,KAAK,EAAE,gBAAgB,GAAG,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACnD,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,EAAE,CAAC,EAAE,kBAAkB,CAAC;IACxB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAYD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAyEjE"}
1
+ {"version":3,"file":"ClickToCopy.d.ts","sourceRoot":"","sources":["../../../src/clipboard/ui/ClickToCopy.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EAGb,YAAY,EACZ,SAAS,EACV,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAKpE,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;AAEvE,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,KAAK,EAAE,gBAAgB,GAAG,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACnD,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,EAAE,CAAC,EAAE,kBAAkB,CAAC;IACxB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAYD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CA2EjE"}
@@ -24,11 +24,11 @@ const NESTED_CONTROL = 'a[href], button, input, select, textarea, summary, label
24
24
  * @returns The copyable value.
25
25
  */
26
26
  export function ClickToCopy(props) {
27
- const { value, children, label, title, as: Element = 'span', focusable = true, disabled = false, className, style, } = props;
27
+ const { value, children, label, title, as: Element = 'span', focusable = true, disabled = false, className, style, testId, } = props;
28
28
  const t = useChromeT();
29
29
  const { copied, failed, copy } = useCopyToClipboard();
30
30
  if (disabled) {
31
- return (_jsx(Element, { className: className, style: style, children: children }));
31
+ return (_jsx(Element, { className: className, style: style, "data-testid": testId, children: children }));
32
32
  }
33
33
  function activate(event) {
34
34
  if (isOnNestedControl(event))
@@ -37,7 +37,7 @@ export function ClickToCopy(props) {
37
37
  void copy(typeof value === 'function' ? () => writeToClipboard(value()) : value);
38
38
  }
39
39
  const outcome = copied ? 'copied' : failed ? 'failed' : undefined;
40
- return (_jsxs(Element, { className: joinClassNames('click-to-copy', INLINE.has(Element) ? 'click-to-copy--inline' : 'click-to-copy--block', className), style: style, role: focusable && !CELLS.has(Element) ? 'button' : undefined, tabIndex: focusable ? 0 : undefined, title: title ?? copyTitle(value, label, t), "data-copy": outcome, onClick: activate, onKeyDown: onActivateKey(activate), children: [children, focusable ? (_jsx(Icon, { className: "click-to-copy__icon", icon: outcome === 'copied'
40
+ return (_jsxs(Element, { className: joinClassNames('click-to-copy', INLINE.has(Element) ? 'click-to-copy--inline' : 'click-to-copy--block', className), style: style, "data-testid": testId, role: focusable && !CELLS.has(Element) ? 'button' : undefined, tabIndex: focusable ? 0 : undefined, title: title ?? copyTitle(value, label, t), "data-copy": outcome, onClick: activate, onKeyDown: onActivateKey(activate), children: [children, focusable ? (_jsx(Icon, { className: "click-to-copy__icon", icon: outcome === 'copied'
41
41
  ? 'tick'
42
42
  : outcome === 'failed'
43
43
  ? 'cross'
@@ -1 +1 @@
1
- {"version":3,"file":"ClickToCopy.js","sourceRoot":"","sources":["../../../src/clipboard/ui/ClickToCopy.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClickToCopy.js","sourceRoot":"","sources":["../../../src/clipboard/ui/ClickToCopy.tsx"],"names":[],"mappings":"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"}
@@ -4,8 +4,8 @@
4
4
  * Which of the two formats a reader wants is not a question the figure can
5
5
  * answer for them: an SVG is the one to put in a paper, where it stays sharp
6
6
  * at any size and can still be edited, and a PNG is the one every chat window,
7
- * slide deck and issue tracker actually accepts. So both are offered, and the
8
- * resolution goes with the second.
7
+ * slide deck and issue tracker actually accepts. So both are offered. The
8
+ * resolution paints a PNG with more pixels, and makes an SVG open larger.
9
9
  */
10
10
  import type { FigureSvgOptions } from './figureSvg.ts';
11
11
  /** Which file a figure is saved as. */
@@ -18,9 +18,11 @@ export interface DownloadFigureOptions extends FigureSvgOptions {
18
18
  */
19
19
  format?: FigureFormat;
20
20
  /**
21
- * How many pixels are painted per pixel on screen. An SVG ignores it: it
22
- * carries no resolution of its own.
23
- * @default 2
21
+ * How many pixels are painted per pixel on screen. An SVG is drawn the same
22
+ * and opens this many times larger, which is the size a slide or a word
23
+ * processor places it at.
24
+ * @default 2 for a PNG, 1 for an SVG — which then opens at the size it has
25
+ * on screen
24
26
  */
25
27
  scale?: number;
26
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"downloadFigure.d.ts","sourceRoot":"","sources":["../../../src/download/core/downloadFigure.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,uCAAuC;AACvC,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,CAAC;AAEzC,6BAA6B;AAC7B,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,GAAG,OAAO,EACxB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAaf"}
1
+ {"version":3,"file":"downloadFigure.d.ts","sourceRoot":"","sources":["../../../src/download/core/downloadFigure.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,uCAAuC;AACvC,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,CAAC;AAEzC,6BAA6B;AAC7B,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,GAAG,OAAO,EACxB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -4,12 +4,12 @@
4
4
  * Which of the two formats a reader wants is not a question the figure can
5
5
  * answer for them: an SVG is the one to put in a paper, where it stays sharp
6
6
  * at any size and can still be edited, and a PNG is the one every chat window,
7
- * slide deck and issue tracker actually accepts. So both are offered, and the
8
- * resolution goes with the second.
7
+ * slide deck and issue tracker actually accepts. So both are offered. The
8
+ * resolution paints a PNG with more pixels, and makes an SVG open larger.
9
9
  */
10
10
  import { downloadBlob } from "./downloadBlob.js";
11
11
  import { figurePng } from "./figurePng.js";
12
- import { DEFAULT_FIGURE_SCALE } from "./figureScale.js";
12
+ import { defaultFigureScale } from "./figureScale.js";
13
13
  import { FIGURE_SVG_TYPE, figureSvg } from "./figureSvg.js";
14
14
  import { sanitizeFileName } from "./sanitizeFileName.js";
15
15
  /** What a figure is called when the caller does not say. */
@@ -21,15 +21,16 @@ const DEFAULT_FILE_NAME = 'figure';
21
21
  * @throws {Error} When the box holds no figure, or the browser cannot paint it.
22
22
  */
23
23
  export async function downloadFigure(target, options = {}) {
24
- const { format = 'png', scale = DEFAULT_FIGURE_SCALE } = options;
25
- const { fileName = DEFAULT_FILE_NAME, background } = options;
26
- const figure = figureSvg(target, { background });
24
+ const { format = 'png', fileName = DEFAULT_FILE_NAME, background } = options;
25
+ const scale = options.scale ?? defaultFigureScale(format);
27
26
  const name = sanitizeFileName(fileName, DEFAULT_FILE_NAME);
28
27
  if (format === 'svg') {
28
+ const figure = figureSvg(target, { background, scale });
29
29
  const blob = new Blob([figure.markup], { type: FIGURE_SVG_TYPE });
30
30
  downloadBlob(blob, `${name}.svg`);
31
31
  return;
32
32
  }
33
+ const figure = figureSvg(target, { background });
33
34
  downloadBlob(await figurePng(figure, scale), `${name}.png`);
34
35
  }
35
36
  //# sourceMappingURL=downloadFigure.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"downloadFigure.js","sourceRoot":"","sources":["../../../src/download/core/downloadFigure.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAyBzD,4DAA4D;AAC5D,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAwB,EACxB,UAAiC,EAAE;IAEnC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,KAAK,GAAG,oBAAoB,EAAE,GAAG,OAAO,CAAC;IACjE,MAAM,EAAE,QAAQ,GAAG,iBAAiB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAE7D,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAE3D,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,YAAY,CAAC,IAAI,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IACD,YAAY,CAAC,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"downloadFigure.js","sourceRoot":"","sources":["../../../src/download/core/downloadFigure.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AA2BzD,4DAA4D;AAC5D,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAwB,EACxB,UAAiC,EAAE;IAEnC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,GAAG,iBAAiB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC7E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE1D,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAE3D,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,YAAY,CAAC,IAAI,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IACjD,YAAY,CAAC,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The shape a figure is drawn at before it is saved.
3
+ *
4
+ * A saved figure is the drawing the reader is looking at, so its proportions
5
+ * are the proportions of the box it sits in. The resolution scales that
6
+ * drawing — more pixels for a PNG, a larger page for an SVG — but leaves its
7
+ * shape, and the size of its words against its axes, exactly as they were. A
8
+ * figure for a slide or for a journal column wants another shape, and the only
9
+ * way to give it one is to draw it again at that size, so its axes and labels
10
+ * are laid out for the new box rather than stretched into it.
11
+ */
12
+ import type { FigurePixels } from './figureScale.ts';
13
+ /** The shapes a figure can be drawn at for a file. */
14
+ export type FigureLayout = 'screen' | 'standard' | 'wide' | 'column' | 'custom';
15
+ /** The shapes, in the order they are offered. */
16
+ export declare const FIGURE_LAYOUTS: readonly ["screen", "standard", "wide", "column", "custom"];
17
+ /**
18
+ * How wide a journal's single column is, in CSS pixels: 8.5 cm at 96 pixels
19
+ * per inch. A figure laid out at that width prints its text at the size it is
20
+ * read at on screen, a 12 px label becoming a 9 pt one.
21
+ */
22
+ export declare const FIGURE_COLUMN_WIDTH = 321;
23
+ /** The narrowest side a figure is drawn at, below which no chart has room for its axes. */
24
+ export declare const FIGURE_LAYOUT_MIN = 120;
25
+ /** The widest side a figure is drawn at: past it the page would be laying out a poster. */
26
+ export declare const FIGURE_LAYOUT_MAX = 4096;
27
+ /**
28
+ * The size a figure is drawn at, in the shape the reader picked.
29
+ *
30
+ * The two slide shapes keep the width of the figure on screen and change its
31
+ * height, since the width is what a page already gave it. The journal column
32
+ * does the reverse: its width is fixed by the journal, and the figure keeps
33
+ * the proportions it has on screen.
34
+ * @param layout - The shape picked.
35
+ * @param screen - The figure as it is drawn on the page.
36
+ * @param custom - The size typed in, read only for `custom`. Defaults to the
37
+ * figure on screen.
38
+ * @returns The size to draw it at, in whole pixels.
39
+ */
40
+ export declare function figureLayoutSize(layout: FigureLayout, screen: FigurePixels, custom?: FigurePixels): FigurePixels;
41
+ /**
42
+ * One side, held to the range a figure can be drawn at.
43
+ * @param value - What was asked for, typed or computed.
44
+ * @returns A whole number of pixels, inside the range.
45
+ */
46
+ export declare function figureLayoutSide(value: number): number;
47
+ /**
48
+ * Whether a figure is drawn again for the file, rather than copied as it is.
49
+ * @param layout - The shape picked.
50
+ * @param screen - The figure as it is drawn on the page.
51
+ * @param custom - The size typed in.
52
+ * @returns Whether the size differs from the one on screen.
53
+ */
54
+ export declare function figureLayoutRedraws(layout: FigureLayout, screen: FigurePixels, custom?: FigurePixels): boolean;
55
+ //# sourceMappingURL=figureLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figureLayout.d.ts","sourceRoot":"","sources":["../../../src/download/core/figureLayout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhF,iDAAiD;AACjD,eAAO,MAAM,cAAc,6DAMiB,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,EACpB,MAAM,GAAE,YAAqB,GAC5B,YAAY,CAkBd;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAGT"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The shape a figure is drawn at before it is saved.
3
+ *
4
+ * A saved figure is the drawing the reader is looking at, so its proportions
5
+ * are the proportions of the box it sits in. The resolution scales that
6
+ * drawing — more pixels for a PNG, a larger page for an SVG — but leaves its
7
+ * shape, and the size of its words against its axes, exactly as they were. A
8
+ * figure for a slide or for a journal column wants another shape, and the only
9
+ * way to give it one is to draw it again at that size, so its axes and labels
10
+ * are laid out for the new box rather than stretched into it.
11
+ */
12
+ /** The shapes, in the order they are offered. */
13
+ export const FIGURE_LAYOUTS = [
14
+ 'screen',
15
+ 'standard',
16
+ 'wide',
17
+ 'column',
18
+ 'custom',
19
+ ];
20
+ /**
21
+ * How wide a journal's single column is, in CSS pixels: 8.5 cm at 96 pixels
22
+ * per inch. A figure laid out at that width prints its text at the size it is
23
+ * read at on screen, a 12 px label becoming a 9 pt one.
24
+ */
25
+ export const FIGURE_COLUMN_WIDTH = 321;
26
+ /** The narrowest side a figure is drawn at, below which no chart has room for its axes. */
27
+ export const FIGURE_LAYOUT_MIN = 120;
28
+ /** The widest side a figure is drawn at: past it the page would be laying out a poster. */
29
+ export const FIGURE_LAYOUT_MAX = 4096;
30
+ /**
31
+ * The size a figure is drawn at, in the shape the reader picked.
32
+ *
33
+ * The two slide shapes keep the width of the figure on screen and change its
34
+ * height, since the width is what a page already gave it. The journal column
35
+ * does the reverse: its width is fixed by the journal, and the figure keeps
36
+ * the proportions it has on screen.
37
+ * @param layout - The shape picked.
38
+ * @param screen - The figure as it is drawn on the page.
39
+ * @param custom - The size typed in, read only for `custom`. Defaults to the
40
+ * figure on screen.
41
+ * @returns The size to draw it at, in whole pixels.
42
+ */
43
+ export function figureLayoutSize(layout, screen, custom = screen) {
44
+ switch (layout) {
45
+ case 'standard':
46
+ return sized(screen.width, (screen.width * 3) / 4);
47
+ case 'wide':
48
+ return sized(screen.width, (screen.width * 9) / 16);
49
+ case 'column':
50
+ return sized(FIGURE_COLUMN_WIDTH, (FIGURE_COLUMN_WIDTH * screen.height) / Math.max(screen.width, 1));
51
+ case 'custom':
52
+ return sized(custom.width, custom.height);
53
+ case 'screen':
54
+ return { width: screen.width, height: screen.height };
55
+ default:
56
+ throw new Error(`unknown figure layout: ${String(layout)}`);
57
+ }
58
+ }
59
+ /**
60
+ * One side, held to the range a figure can be drawn at.
61
+ * @param value - What was asked for, typed or computed.
62
+ * @returns A whole number of pixels, inside the range.
63
+ */
64
+ export function figureLayoutSide(value) {
65
+ if (!Number.isFinite(value))
66
+ return FIGURE_LAYOUT_MIN;
67
+ return Math.min(FIGURE_LAYOUT_MAX, Math.max(FIGURE_LAYOUT_MIN, Math.round(value)));
68
+ }
69
+ /**
70
+ * Whether a figure is drawn again for the file, rather than copied as it is.
71
+ * @param layout - The shape picked.
72
+ * @param screen - The figure as it is drawn on the page.
73
+ * @param custom - The size typed in.
74
+ * @returns Whether the size differs from the one on screen.
75
+ */
76
+ export function figureLayoutRedraws(layout, screen, custom) {
77
+ const drawn = figureLayoutSize(layout, screen, custom);
78
+ return drawn.width !== screen.width || drawn.height !== screen.height;
79
+ }
80
+ /**
81
+ * A size, both sides held to the range.
82
+ * @param width - The width asked for.
83
+ * @param height - The height asked for.
84
+ * @returns The size.
85
+ */
86
+ function sized(width, height) {
87
+ return { width: figureLayoutSide(width), height: figureLayoutSide(height) };
88
+ }
89
+ //# sourceMappingURL=figureLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figureLayout.js","sourceRoot":"","sources":["../../../src/download/core/figureLayout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,iDAAiD;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,QAAQ;IACR,UAAU;IACV,MAAM;IACN,QAAQ;IACR,QAAQ;CACkC,CAAC;AAE7C;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,2FAA2F;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,2FAA2F;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAoB,EACpB,MAAoB,EACpB,SAAuB,MAAM;IAE7B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,UAAU;YACb,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACtD,KAAK,QAAQ;YACX,OAAO,KAAK,CACV,mBAAmB,EACnB,CAAC,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAClE,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACxD;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,iBAAiB,CAAC;IACtD,OAAO,IAAI,CAAC,GAAG,CACb,iBAAiB,EACjB,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAC/C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAoB,EACpB,MAAoB,EACpB,MAAqB;IAErB,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,OAAO,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC;AACxE,CAAC;AAED;;;;;GAKG;AACH,SAAS,KAAK,CAAC,KAAa,EAAE,MAAc;IAC1C,OAAO,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9E,CAAC"}
@@ -7,6 +7,7 @@
7
7
  * pixel count is the consequence, and is written out beside it so nobody has
8
8
  * to work it out.
9
9
  */
10
+ import type { FigureFormat } from './downloadFigure.ts';
10
11
  /** The size of a saved figure, in pixels. */
11
12
  export interface FigurePixels {
12
13
  /** Its width. */
@@ -24,6 +25,14 @@ export declare const FIGURE_SCALES: readonly number[];
24
25
  * of these files end up.
25
26
  */
26
27
  export declare const DEFAULT_FIGURE_SCALE = 2;
28
+ /**
29
+ * The multiple a figure is saved at in this format unless the reader says
30
+ * otherwise. An SVG stays sharp however large it is shown, so it opens at the
31
+ * size it has on screen; a PNG is painted twice over, for a slide.
32
+ * @param format - The file being written.
33
+ * @returns The multiple.
34
+ */
35
+ export declare function defaultFigureScale(format: FigureFormat): number;
27
36
  /**
28
37
  * The longest side a browser will paint into one canvas.
29
38
  *
@@ -1 +1 @@
1
- {"version":3,"file":"figureScale.d.ts","sourceRoot":"","sources":["../../../src/download/core/figureScale.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAAiB,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAM5E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAK1E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE/D"}
1
+ {"version":3,"file":"figureScale.d.ts","sourceRoot":"","sources":["../../../src/download/core/figureScale.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAAiB,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE/D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAM5E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAK1E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE/D"}