@abyss-project/commons-front-core 9.1.0 → 9.2.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 (77) hide show
  1. package/README.md +43 -1
  2. package/catalog/catalog-entries.ts +7 -0
  3. package/catalog/pages/AvatarGroup.tsx +45 -0
  4. package/catalog/pages/CompanySearchField.tsx +113 -0
  5. package/catalog/pages/ConfirmDialog.tsx +43 -1
  6. package/catalog/pages/CopyField.tsx +24 -1
  7. package/catalog/pages/EntityImageField.tsx +124 -0
  8. package/catalog/pages/LineChart.tsx +118 -0
  9. package/catalog/pages/Pagination.tsx +52 -0
  10. package/catalog/pages/Section.tsx +16 -2
  11. package/catalog/pages/TeamAvatar.tsx +40 -0
  12. package/catalog/pages/UserPicker.tsx +124 -0
  13. package/catalog/pages/index.ts +14 -0
  14. package/dist/{AbyssCookieConsentProvider-B7-F6osY.js → AbyssCookieConsentProvider-DUYUEZaO.js} +94 -36
  15. package/dist/{CookieConsentSettings.component-DxQL4ULz.js → CookieConsentSettings.component-aVDMZLIs.js} +1 -1
  16. package/dist/components/data/LineChart/LineChart.d.ts +32 -0
  17. package/dist/components/data/LineChart/LineChart.spec.d.ts +1 -0
  18. package/dist/components/data/LineChart/line-chart-ticks.d.ts +31 -0
  19. package/dist/components/data/LineChart/line-chart-ticks.spec.d.ts +1 -0
  20. package/dist/components/data/Pagination/Pagination.d.ts +16 -0
  21. package/dist/components/data/Pagination/Pagination.spec.d.ts +1 -0
  22. package/dist/components/data/index.d.ts +2 -0
  23. package/dist/components/inputs/CompanySearchField/CompanySearchField.d.ts +24 -0
  24. package/dist/components/inputs/CompanySearchField/CompanySearchField.spec.d.ts +1 -0
  25. package/dist/components/inputs/CompanySearchField/pappers-company.d.ts +18 -0
  26. package/dist/components/inputs/CopyField/CopyField.d.ts +22 -6
  27. package/dist/components/inputs/EntityImageField/EntityImageField.d.ts +47 -0
  28. package/dist/components/inputs/EntityImageField/EntityImageField.spec.d.ts +1 -0
  29. package/dist/components/inputs/UserPicker/UserPicker.d.ts +50 -0
  30. package/dist/components/inputs/UserPicker/UserPicker.spec.d.ts +1 -0
  31. package/dist/components/inputs/index.d.ts +3 -0
  32. package/dist/components/layers/ConfirmDialog/useConfirmDialog.d.ts +21 -0
  33. package/dist/components/layers/ConfirmDialog/useConfirmDialog.spec.d.ts +1 -0
  34. package/dist/components/layers/index.d.ts +1 -0
  35. package/dist/components/meaning/AvatarGroup/AvatarGroup.d.ts +22 -0
  36. package/dist/components/meaning/AvatarGroup/AvatarGroup.spec.d.ts +1 -0
  37. package/dist/components/meaning/TeamAvatar/TeamAvatar.d.ts +14 -0
  38. package/dist/components/meaning/TeamAvatar/TeamAvatar.spec.d.ts +1 -0
  39. package/dist/components/meaning/index.d.ts +2 -0
  40. package/dist/components/structure/Section/Section.d.ts +10 -2
  41. package/dist/cookie-consent.js +2 -2
  42. package/dist/design-theme-DyWPbqXp.js +26515 -0
  43. package/dist/hooks/use-rich-intl.hook.d.ts +58 -0
  44. package/dist/{index-DflXNluH.js → index-77h-J0x1.js} +2 -2
  45. package/dist/{index-Bhhwuj39.js → index-BGIR-HuR.js} +2 -2
  46. package/dist/{index-DkcMwm_T.js → index-BM8u6b8w.js} +3 -3
  47. package/dist/{index-2zbZ2URx.js → index-BMgcTA0L.js} +3 -3
  48. package/dist/{index-C5OyIHCq.js → index-Bdv62RC2.js} +2 -2
  49. package/dist/{index-uGXjK3xv.js → index-BykEZXU6.js} +3 -3
  50. package/dist/{index-CsyAu658.js → index-C4plH_av.js} +2 -2
  51. package/dist/{index-uLh81uFU.js → index-C6YE_5pO.js} +2 -2
  52. package/dist/{index-BloHDADq.js → index-C6rmH0hM.js} +35694 -46623
  53. package/dist/{index-BuQlif6i.js → index-C9Vm0yCV.js} +2 -2
  54. package/dist/{index-BtzB7aR_.js → index-CAWnWyTQ.js} +2 -2
  55. package/dist/{index-CTP0QoCT.js → index-CX-2IC2j.js} +3 -3
  56. package/dist/{index-jhW25X__.js → index-CZj1-4RN.js} +2 -2
  57. package/dist/{index-RkXYGPSf.js → index-ChBWwrvm.js} +4 -4
  58. package/dist/{index-BMM6rvML.js → index-DKF4BSrW.js} +2 -2
  59. package/dist/{index-iQhqBjKY.js → index-DPsPJ7S5.js} +2 -2
  60. package/dist/{index-IooWxH41.js → index-LNg1bMNB.js} +2 -2
  61. package/dist/{index-Dew1ymFy.js → index-URaKKzT4.js} +2 -2
  62. package/dist/{index-BAcf97X_.js → index-UXYdJQT_.js} +2 -2
  63. package/dist/{index-BXtPl6pH.js → index-WINZVUn3.js} +1 -1
  64. package/dist/{index-CspGahq0.js → index-_kMEUAM7.js} +4 -4
  65. package/dist/{index-Waz6-pQr.js → index-elrbx7C5.js} +4 -4
  66. package/dist/index.js +5470 -4329
  67. package/dist/legacy/components/CompanySearchAutocomplete/CompanySearchAutocomplete.d.ts +2 -14
  68. package/dist/legacy/components/Layouts/AbyssFamilyBanner/AbyssFamilyBanner.component.d.ts +3 -7
  69. package/dist/legacy.js +61 -61
  70. package/dist/theme/tokens/semantic.d.ts +4 -1
  71. package/dist/translations/en.d.ts +29 -0
  72. package/dist/translations/fr.d.ts +29 -0
  73. package/dist/utils/family.d.ts +12 -0
  74. package/dist/utils/index.d.ts +1 -0
  75. package/package.json +1 -1
  76. package/test-results/catalog/.last-run.json +1 -1
  77. package/dist/design-theme-BztWe75w.js +0 -15490
@@ -0,0 +1,40 @@
1
+ import { useTheme } from '@mui/material/styles';
2
+
3
+ import { TeamAvatar } from '../../src/components/meaning/TeamAvatar/TeamAvatar';
4
+ import { Example, Row, Showcase } from '../frame';
5
+
6
+ export const TeamAvatarPage = () => {
7
+ // Stored team colors are user data; the catalog borrows token values so as not to hard-code any.
8
+ const { tokens } = useTheme().design;
9
+ return (
10
+ <Showcase
11
+ family="Sens"
12
+ name="TeamAvatar"
13
+ description="Équipe : l'initiale de son nom sur sa couleur, dans un carré arrondi, à l'encre claire ou sombre qui contraste le mieux. Sans couleur, ou avec une couleur que le navigateur ne sait pas lire, la teinte neutre des avatars."
14
+ >
15
+ <Example title="Couleurs d'équipe, foncées et claires" framed>
16
+ <Row>
17
+ <TeamAvatar name="Design" color={tokens['status.info']} />
18
+ <TeamAvatar name="Ops" color={tokens['status.success']} />
19
+ <TeamAvatar name="Support" color={tokens['status.warning']} />
20
+ <TeamAvatar name="Finance" color={tokens['status.highlight']} />
21
+ <TeamAvatar name="Sécurité" color={tokens['status.danger']} />
22
+ </Row>
23
+ </Example>
24
+ <Example title="Sans couleur, couleur illisible, sans nom" framed>
25
+ <Row>
26
+ <TeamAvatar name="Marketing" color={null} />
27
+ <TeamAvatar name="Ventes" color="pas-une-couleur" />
28
+ <TeamAvatar name="" color={tokens['status.info']} />
29
+ </Row>
30
+ </Example>
31
+ <Example title="Tailles : 22, 32 (défaut), 64" framed>
32
+ <Row>
33
+ <TeamAvatar name="Ops" color={tokens['status.info']} size={22} />
34
+ <TeamAvatar name="Ops" color={tokens['status.info']} />
35
+ <TeamAvatar name="Ops" color={tokens['status.info']} size={64} />
36
+ </Row>
37
+ </Example>
38
+ </Showcase>
39
+ );
40
+ };
@@ -0,0 +1,124 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { UserPicker } from '../../src/components/inputs/UserPicker/UserPicker';
3
+ import type { UserPickerOption } from '../../src/components/inputs/UserPicker/UserPicker';
4
+ import { LogoAbyssSmall } from '../../src/assets';
5
+ import { Example, LastEvent, Showcase, useEventLog } from '../frame';
6
+
7
+ const MEMBERS: UserPickerOption[] = [
8
+ {
9
+ id: 'u1',
10
+ name: 'Mehdi Benali',
11
+ email: 'mehdi@abyss.fr',
12
+ pictureUrl: LogoAbyssSmall,
13
+ },
14
+ {
15
+ id: 'u2',
16
+ name: 'Alice Martin',
17
+ email: 'alice.martin@karbon-studio.fr',
18
+ pictureUrl: null,
19
+ },
20
+ { id: 'u3', name: 'Bruno Petit', email: 'bruno@abyss.fr', pictureUrl: null },
21
+ { id: 'u4', name: 'Clara Durand', email: null, pictureUrl: null },
22
+ {
23
+ id: 'u5',
24
+ name: 'Maximilien-Alexandre de La Tour d’Auvergne',
25
+ email: 'maximilien-alexandre.delatourdauvergne@exemple-tres-long.fr',
26
+ pictureUrl: null,
27
+ },
28
+ ];
29
+
30
+ /** Delay of the simulated server search, in ms. */
31
+ const SEARCH_DELAY = 600;
32
+
33
+ /** A server search answered from memory, after a delay: the catalog has no network. */
34
+ const useSimulatedSearch = () => {
35
+ const [query, setQuery] = useState('');
36
+ const [results, setResults] = useState<UserPickerOption[]>(MEMBERS);
37
+ const [loading, setLoading] = useState(false);
38
+ useEffect(() => {
39
+ setLoading(true);
40
+ const timer = setTimeout(() => {
41
+ const text = query.trim().toLowerCase();
42
+ setResults(
43
+ MEMBERS.filter((member) =>
44
+ [member.name, member.email ?? ''].some((field) =>
45
+ field.toLowerCase().includes(text),
46
+ ),
47
+ ),
48
+ );
49
+ setLoading(false);
50
+ }, SEARCH_DELAY);
51
+ return () => clearTimeout(timer);
52
+ }, [query]);
53
+ return { results, loading, search: setQuery };
54
+ };
55
+
56
+ export const UserPickerPage = () => {
57
+ const { log } = useEventLog();
58
+ const [owner, setOwner] = useState<string | null>('u2');
59
+ const [recipients, setRecipients] = useState<string[]>(['u1', 'u3']);
60
+ const [target, setTarget] = useState<string | null>(null);
61
+ const remote = useSimulatedSearch();
62
+ return (
63
+ <Showcase
64
+ family="Saisie"
65
+ name="UserPicker"
66
+ description="Choix d'un utilisateur ou de plusieurs : avatar, nom et e-mail dans chaque option, recherche sur le nom et l'e-mail (locale, ou confiée au serveur par onSearch). En multiple, les choisis sont des puces que le clavier retire."
67
+ >
68
+ <Example title="Choix simple" maxWidth={480}>
69
+ <UserPicker
70
+ options={MEMBERS}
71
+ value={owner}
72
+ onChange={(next) => {
73
+ setOwner(next);
74
+ log(`responsable ${next ?? 'aucun'}`);
75
+ }}
76
+ label="Responsable de l’équipe"
77
+ placeholder="Choisir un membre"
78
+ noOptionsText="Aucun membre ne correspond"
79
+ />
80
+ </Example>
81
+ <Example title="Choix multiple" maxWidth={480}>
82
+ <UserPicker
83
+ multiple
84
+ options={MEMBERS}
85
+ value={recipients}
86
+ onChange={(next) => {
87
+ setRecipients(next);
88
+ log(`destinataires ${next.join(', ')}`);
89
+ }}
90
+ label="Destinataires du rapport"
91
+ placeholder="Ajouter un membre"
92
+ noOptionsText="Aucun membre ne correspond"
93
+ />
94
+ </Example>
95
+ <Example title="Recherche serveur, propriétaire exclu" maxWidth={480}>
96
+ <UserPicker
97
+ options={remote.results}
98
+ onSearch={remote.search}
99
+ loading={remote.loading}
100
+ value={target}
101
+ onChange={(next) => {
102
+ setTarget(next);
103
+ log(`nouveau propriétaire ${next ?? 'aucun'}`);
104
+ }}
105
+ disabledIds={['u1']}
106
+ label="Nouveau propriétaire"
107
+ placeholder="Rechercher un membre"
108
+ noOptionsText="Aucun membre ne correspond"
109
+ />
110
+ </Example>
111
+ <Example title="Inactif" maxWidth={480}>
112
+ <UserPicker
113
+ options={MEMBERS}
114
+ value="u1"
115
+ onChange={() => undefined}
116
+ label="Responsable de l’équipe"
117
+ noOptionsText="Aucun membre ne correspond"
118
+ disabled
119
+ />
120
+ </Example>
121
+ <LastEvent />
122
+ </Showcase>
123
+ );
124
+ };
@@ -12,6 +12,13 @@ import { CommandPalettePage } from './CommandPalette';
12
12
  import { ConfirmDialogPage } from './ConfirmDialog';
13
13
  import { ContextSelectorPage } from './ContextSelector';
14
14
  import { CopyFieldPage } from './CopyField';
15
+ import { LineChartPage } from './LineChart';
16
+ import { PaginationPage } from './Pagination';
17
+ import { AvatarGroupPage } from './AvatarGroup';
18
+ import { TeamAvatarPage } from './TeamAvatar';
19
+ import { UserPickerPage } from './UserPicker';
20
+ import { CompanySearchFieldPage } from './CompanySearchField';
21
+ import { EntityImageFieldPage } from './EntityImageField';
15
22
  import { DataTablePage } from './DataTable';
16
23
  import { DateFieldPage } from './DateField';
17
24
  import { DateRangeFieldPage } from './DateRangeField';
@@ -69,6 +76,13 @@ export const CATALOG_PAGES: Record<string, ComponentType> = {
69
76
  ConfirmDialog: ConfirmDialogPage,
70
77
  ContextSelector: ContextSelectorPage,
71
78
  CopyField: CopyFieldPage,
79
+ LineChart: LineChartPage,
80
+ Pagination: PaginationPage,
81
+ AvatarGroup: AvatarGroupPage,
82
+ TeamAvatar: TeamAvatarPage,
83
+ UserPicker: UserPickerPage,
84
+ CompanySearchField: CompanySearchFieldPage,
85
+ EntityImageField: EntityImageFieldPage,
72
86
  DataTable: DataTablePage,
73
87
  DateField: DateFieldPage,
74
88
  DateRangeField: DateRangeFieldPage,
@@ -1709,7 +1709,25 @@ const fm = {
1709
1709
  reveal: "Afficher la valeur",
1710
1710
  hide: "Masquer la valeur",
1711
1711
  copied: "Copié dans le presse-papiers",
1712
- "copy-failed": "La copie a échoué. Réessayez ou copiez la valeur à la main."
1712
+ "copy-failed": "La copie a échoué. Réessayez ou copiez la valeur à la main.",
1713
+ "load-failed": "La valeur n’a pas pu être chargée. Réessayez."
1714
+ },
1715
+ "entity-image-field": {
1716
+ uploading: "Envoi de l’image…"
1717
+ },
1718
+ "user-picker": {
1719
+ loading: "Recherche…",
1720
+ clear: "Effacer",
1721
+ open: "Ouvrir la liste",
1722
+ close: "Fermer la liste"
1723
+ },
1724
+ "company-search-field": {
1725
+ label: "Nom de l’entreprise",
1726
+ placeholder: "Rechercher une entreprise",
1727
+ loading: "Recherche…",
1728
+ error: "La recherche d’entreprise est momentanément indisponible. Réessayez dans un instant.",
1729
+ created: "Créée le {date}",
1730
+ clear: "Effacer"
1713
1731
  },
1714
1732
  "context-selector": {
1715
1733
  personal: "Mon espace",
@@ -1825,6 +1843,17 @@ const fm = {
1825
1843
  }
1826
1844
  },
1827
1845
  data: {
1846
+ pagination: {
1847
+ previous: "Précédent",
1848
+ next: "Suivant",
1849
+ page: "Page {page, number}",
1850
+ position: "Page {page, number} sur {count, number}"
1851
+ },
1852
+ "line-chart": {
1853
+ x: "Abscisse",
1854
+ "no-value": "Aucune valeur",
1855
+ empty: "Aucune donnée à afficher"
1856
+ },
1828
1857
  "data-table": {
1829
1858
  "select-all": "Sélectionner toutes les lignes",
1830
1859
  "select-row": "Sélectionner la ligne",
@@ -3475,7 +3504,25 @@ const fm = {
3475
3504
  reveal: "Show the value",
3476
3505
  hide: "Hide the value",
3477
3506
  copied: "Copied to the clipboard",
3478
- "copy-failed": "Copy failed. Try again or copy the value by hand."
3507
+ "copy-failed": "Copy failed. Try again or copy the value by hand.",
3508
+ "load-failed": "The value could not be loaded. Try again."
3509
+ },
3510
+ "entity-image-field": {
3511
+ uploading: "Uploading the image…"
3512
+ },
3513
+ "user-picker": {
3514
+ loading: "Searching…",
3515
+ clear: "Clear",
3516
+ open: "Open the list",
3517
+ close: "Close the list"
3518
+ },
3519
+ "company-search-field": {
3520
+ label: "Company name",
3521
+ placeholder: "Search for a company",
3522
+ loading: "Searching…",
3523
+ error: "Company search is temporarily unavailable. Try again in a moment.",
3524
+ created: "Founded on {date}",
3525
+ clear: "Clear"
3479
3526
  },
3480
3527
  "context-selector": {
3481
3528
  personal: "My space",
@@ -3591,6 +3638,17 @@ const fm = {
3591
3638
  }
3592
3639
  },
3593
3640
  data: {
3641
+ pagination: {
3642
+ previous: "Previous",
3643
+ next: "Next",
3644
+ page: "Page {page, number}",
3645
+ position: "Page {page, number} of {count, number}"
3646
+ },
3647
+ "line-chart": {
3648
+ x: "X value",
3649
+ "no-value": "No value",
3650
+ empty: "No data to show"
3651
+ },
3594
3652
  "data-table": {
3595
3653
  "select-all": "Select all rows",
3596
3654
  "select-row": "Select row",
@@ -8311,36 +8369,36 @@ const Ym = tl * 24 * 60 * 60 * 1e3, Hm = (p) => ({
8311
8369
  ] });
8312
8370
  };
8313
8371
  export {
8314
- Rm as $,
8372
+ Ki as $,
8315
8373
  fv as A,
8316
- Dt as B,
8374
+ uv as B,
8317
8375
  Km as C,
8318
8376
  Fm as D,
8319
- xm as E,
8320
- Pm as F,
8321
- uv as G,
8322
- cv as H,
8323
- av as I,
8324
- Fe as J,
8325
- Sm as K,
8326
- Tr as L,
8327
- Xi as M,
8328
- Em as N,
8329
- bm as O,
8330
- Tm as P,
8331
- Cm as Q,
8377
+ cv as E,
8378
+ av as F,
8379
+ Fe as G,
8380
+ Sm as H,
8381
+ Tr as I,
8382
+ Xi as J,
8383
+ Em as K,
8384
+ bm as L,
8385
+ Tm as M,
8386
+ Cm as N,
8387
+ Im as O,
8388
+ Zs as P,
8389
+ sv as Q,
8332
8390
  Zi as R,
8333
- Im as S,
8334
- Zs as T,
8335
- sv as U,
8391
+ Qs as S,
8392
+ el as T,
8393
+ lv as U,
8336
8394
  tl as V,
8337
- Qs as W,
8338
- el as X,
8339
- lv as Y,
8340
- Om as Z,
8341
- Nm as _,
8395
+ Om as W,
8396
+ Nm as X,
8397
+ Rm as Y,
8398
+ wm as Z,
8399
+ Er as _,
8342
8400
  pv as a,
8343
- wm as a0,
8401
+ iv as a0,
8344
8402
  Wm as b,
8345
8403
  Cr as c,
8346
8404
  Um as d,
@@ -8352,18 +8410,18 @@ export {
8352
8410
  mm as j,
8353
8411
  gm as k,
8354
8412
  zm as l,
8355
- rv as m,
8356
- Er as n,
8357
- Ki as o,
8358
- iv as p,
8359
- Mt as q,
8413
+ Mt as m,
8414
+ rv as n,
8415
+ he as o,
8416
+ oe as p,
8417
+ Ze as q,
8360
8418
  Mm as r,
8361
- he as s,
8419
+ Nn as s,
8362
8420
  $s as t,
8363
8421
  dv as u,
8364
- oe as v,
8422
+ Lt as v,
8365
8423
  Fs as w,
8366
- Ze as x,
8367
- Nn as y,
8368
- Lt as z
8424
+ Dt as x,
8425
+ xm as y,
8426
+ Pm as z
8369
8427
  };
@@ -1,7 +1,7 @@
1
1
  import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
2
  import { useState as m, useEffect as C } from "react";
3
3
  import { Card as v, CardContent as b, Stack as u, Typography as o, FormControlLabel as l, Box as r, Checkbox as d, Button as M } from "@mui/material";
4
- import { g as R, u as x } from "./AbyssCookieConsentProvider-B7-F6osY.js";
4
+ import { g as R, u as x } from "./AbyssCookieConsentProvider-DUYUEZaO.js";
5
5
  const B = () => {
6
6
  const t = R(), { consent: i, save: y } = x(), [h, g] = m((i == null ? void 0 : i.analytics) ?? !1), [k, f] = m((i == null ? void 0 : i.marketing) ?? !1), c = i == null ? void 0 : i.analytics, n = i == null ? void 0 : i.marketing;
7
7
  return C(() => {
@@ -0,0 +1,32 @@
1
+ export type LineChartX = Date | number;
2
+ export interface LineChartPoint {
3
+ x: LineChartX;
4
+ y: number;
5
+ }
6
+ export interface LineChartSeries {
7
+ id: string;
8
+ /** Name of the series, in the legend, the tooltip and the table of values. */
9
+ label: string;
10
+ points: LineChartPoint[];
11
+ }
12
+ export interface LineChartProps {
13
+ series: LineChartSeries[];
14
+ /** Height of the plot, in px. */
15
+ height: number;
16
+ /** Fills the area under each line at the `.soft` opacity, from a zero baseline. */
17
+ area?: boolean;
18
+ /** Text of an x value: axis ticks, tooltip, table of values. */
19
+ formatX(x: LineChartX): string;
20
+ /** Text of a y value: axis ticks, tooltip, table of values. */
21
+ formatY(y: number): string;
22
+ /** Accessible name of the figure and caption of its table: what the chart shows. */
23
+ label: string;
24
+ }
25
+ /**
26
+ * A line chart drawn by nivo under `abyssNivoTheme`: one line per series, colored in the order of
27
+ * the data series palette (`data.series.1`, `2`…, the seventh series starting over), never by the
28
+ * host. Dates give a time scale, numbers a linear one. Beyond one series, a legend names the
29
+ * colors. For screen readers the figure is named by `label` and its drawing is replaced by a table
30
+ * of every value; a chart without any point says so instead of drawing empty axes.
31
+ */
32
+ export declare function LineChart({ series, height, area, formatX, formatY, label, }: LineChartProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ /** Width in px of a tick label of the x axis: mono, at the `caption` size of `abyssNivoTheme`. */
2
+ export declare const tickLabelWidth: (text: string) => number;
3
+ /**
4
+ * Least empty space between two tick labels of the x axis, in px: wide enough that the axis reads
5
+ * as a few landmarks, not as a ruler.
6
+ */
7
+ export declare const TICK_LABEL_GAP: 40;
8
+ export declare enum XScaleKind {
9
+ /** Values are timestamps in ms, ticked on the local clock. */
10
+ Time = "time",
11
+ /** Values are plain numbers, ticked on 1, 2 and 5 times a power of ten. */
12
+ Linear = "linear"
13
+ }
14
+ export interface XTickLayout {
15
+ /** Width of the plot between its margins, in px. */
16
+ plotWidth: number;
17
+ /** Room a label may take beyond each end of the plot (the chart margins), in px. */
18
+ overflow: {
19
+ left: number;
20
+ right: number;
21
+ };
22
+ }
23
+ /**
24
+ * The tick values of the x axis of a chart whose x values are `values` (distinct, ascending, at
25
+ * least one) and whose plot is `layout.plotWidth` px wide: the finest nice step (on the local clock
26
+ * for time), never finer than the closest two values, whose labels (`labelOf`), as wide as
27
+ * `tickLabelWidth` says, keep `TICK_LABEL_GAP` between neighbors. A label that would spill past the
28
+ * margins is dropped. Without room for two labels, a single one is kept; a plot without width gets
29
+ * none.
30
+ */
31
+ export declare function xTickValues(values: number[], kind: XScaleKind, labelOf: (value: number) => string, layout: XTickLayout): number[];
@@ -0,0 +1,16 @@
1
+ export interface PaginationProps {
2
+ /** The current page, from 1. A value outside `1…pageCount` shows the nearest bound. */
3
+ page: number;
4
+ /** Number of pages; nothing is rendered below 2. */
5
+ pageCount: number;
6
+ /** Called with the page the user asks for; never with the current page. */
7
+ onChange(page: number): void;
8
+ /** Accessible name of the navigation: what is paged ("Pages des permissions"). */
9
+ label: string;
10
+ }
11
+ /**
12
+ * Page navigation for a paged list: previous, the numbered pages with gaps, next. Below 768 px it
13
+ * shrinks to previous, "Page x of y" and next, every control a 44 px target. Previous and next are
14
+ * disabled at the bounds. A single page needs no navigation: nothing is rendered.
15
+ */
16
+ export declare function Pagination({ page, pageCount, onChange, label, }: PaginationProps): import("react/jsx-runtime").JSX.Element | null;
@@ -4,3 +4,5 @@ export * from './StatTile/StatTile';
4
4
  export * from './Sparkline/Sparkline';
5
5
  export * from './chart-theme';
6
6
  export * from './UsageMeter/UsageMeter';
7
+ export * from './Pagination/Pagination';
8
+ export * from './LineChart/LineChart';
@@ -0,0 +1,24 @@
1
+ import { PappersCompany } from './pappers-company';
2
+ export type { PappersCompany };
3
+ /** Quiet time after the last keystroke before the request leaves, in ms. */
4
+ export declare const COMPANY_SEARCH_DEBOUNCE_MS = 300;
5
+ export interface CompanySearchFieldProps {
6
+ /** Text of the field, owned by the host. */
7
+ value: string;
8
+ /** Called at each keystroke, before the debounce. */
9
+ onInputChange(value: string): void;
10
+ /** Called when the user picks a suggestion; typing alone never calls it. */
11
+ onSelect(company: PappersCompany): void;
12
+ disabled?: boolean;
13
+ /** Label above the field; « Nom de l’entreprise » without it. */
14
+ label?: string;
15
+ /** « Rechercher une entreprise » without it. */
16
+ placeholder?: string;
17
+ }
18
+ /**
19
+ * A company name field that suggests French companies from Pappers as the user types: name,
20
+ * legal form, SIREN, creation date, head office and activity. The host owns the text; picking a
21
+ * suggestion hands the whole company to `onSelect`. A failed request (network, non-2xx answer)
22
+ * puts the field in error, apart from an answer without result.
23
+ */
24
+ export declare function CompanySearchField({ value, onInputChange, onSelect, disabled, label, placeholder, }: CompanySearchFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A company as the Pappers suggestions API returns it. The field names mirror the response verbatim
3
+ * (French, snake_case): hosts read them as they come, no mapping layer in between.
4
+ */
5
+ export type PappersCompany = {
6
+ siren: string;
7
+ nom_entreprise: string;
8
+ date_creation: string;
9
+ forme_juridique?: string;
10
+ domaine_activite?: string;
11
+ siege?: {
12
+ adresse?: string;
13
+ code_postal?: string;
14
+ ville?: string;
15
+ departement?: string;
16
+ pays?: string;
17
+ };
18
+ };
@@ -1,5 +1,4 @@
1
- export interface CopyFieldProps {
2
- value: string;
1
+ interface CopyFieldBaseProps {
3
2
  /** Hides the value behind dots until the user reveals it; the copy button still copies it. */
4
3
  masked?: boolean;
5
4
  /** Called each time the user reveals a masked value. */
@@ -7,13 +6,30 @@ export interface CopyFieldProps {
7
6
  /** Label of the copy button, named after what it copies ("Copier la clé"). */
8
7
  copyLabel: string;
9
8
  }
9
+ /** The value is known up front. */
10
+ interface CopyFieldValueProps extends CopyFieldBaseProps {
11
+ value: string;
12
+ loadValue?: never;
13
+ }
14
+ /**
15
+ * The value is asked for on the first « Afficher » or « Copier » only, then kept until the field
16
+ * unmounts: no request is made without a gesture.
17
+ */
18
+ interface CopyFieldLoadedProps extends CopyFieldBaseProps {
19
+ value?: never;
20
+ loadValue(): Promise<string>;
21
+ }
22
+ export type CopyFieldProps = CopyFieldValueProps | CopyFieldLoadedProps;
10
23
  /** How long the copy button shows its check mark after a copy, in ms. */
11
24
  export declare const COPY_FEEDBACK_MS = 2000;
12
25
  /**
13
26
  * A value to copy (API key, connection identifier): shown in mono in a read-only box, with a
14
27
  * button that copies it to the clipboard. Masked, the value is replaced by dots and a toggle
15
- * reveals it (calling `onReveal`). The outcome of a copy is announced in a polite live region; a
16
- * success turns the copy icon into a check mark for a moment, a failure is also written under the
17
- * field.
28
+ * reveals it (calling `onReveal`). With `loadValue` instead of `value`, the value stays masked and
29
+ * is asked for on the first reveal or copy, the button of that gesture showing the loading; a
30
+ * failed load is announced and the next gesture asks again. The outcome of a copy is announced in
31
+ * a polite live region; a success turns the copy icon into a check mark for a moment, a failure is
32
+ * also written under the field.
18
33
  */
19
- export declare function CopyField({ value, masked, onReveal, copyLabel, }: CopyFieldProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function CopyField({ value: givenValue, loadValue, masked, onReveal, copyLabel, }: CopyFieldProps): import("react/jsx-runtime").JSX.Element;
35
+ export {};
@@ -0,0 +1,47 @@
1
+ import { ReactNode } from 'react';
2
+ import { CloudImportWiring } from '../../../hooks/cloud-picker.types';
3
+ export declare enum EntityImageVariant {
4
+ /** A logo, a profile picture or a project image: the picture itself is the button. */
5
+ Avatar = "avatar",
6
+ /** A banner: the picture spans the width, a button lies over it. */
7
+ Banner = "banner"
8
+ }
9
+ export declare enum EntityImageShape {
10
+ /** A person: a disc. */
11
+ Round = "round",
12
+ /** An organization or a project: a rounded square. */
13
+ Square = "square"
14
+ }
15
+ interface EntityImageFieldBaseProps {
16
+ /** The avatar or the image shown now, rendered by the host at its size. */
17
+ picture: ReactNode;
18
+ /** What the gesture does (« Changer le logo »): the name of the button. */
19
+ label: string;
20
+ /** Accepted types, as the HTML `accept` attribute lists them. */
21
+ accept?: string[];
22
+ /** Receives the file chosen on the device. The host uploads it and reports the outcome. */
23
+ onFile(file: File): void;
24
+ /** An upload is running: the button shows it and opens nothing. */
25
+ uploading: boolean;
26
+ /** AbyssCloud picker plus the import action: with it, the button opens a menu of sources. */
27
+ cloudImport?: CloudImportWiring;
28
+ }
29
+ export interface EntityImageAvatarProps extends EntityImageFieldBaseProps {
30
+ variant: EntityImageVariant.Avatar;
31
+ /** Defaults to `EntityImageShape.Round`. */
32
+ shape?: EntityImageShape;
33
+ }
34
+ interface EntityImageBannerProps extends EntityImageFieldBaseProps {
35
+ variant: EntityImageVariant.Banner;
36
+ shape?: never;
37
+ }
38
+ export type EntityImageFieldProps = EntityImageAvatarProps | EntityImageBannerProps;
39
+ /**
40
+ * An entity's image that the user changes in place: an avatar that is itself the button (with a
41
+ * camera badge), or a banner spanning the width with a button over it. The button opens the
42
+ * device's file chooser, or, with `cloudImport`, the menu of `ImportButton` (device, AbyssCloud).
43
+ * While `uploading`, the button shows a progress indicator, opens nothing, and the upload is
44
+ * announced in a polite live region.
45
+ */
46
+ export declare function EntityImageField(props: EntityImageFieldProps): import("react/jsx-runtime").JSX.Element;
47
+ export {};