@abyss-project/commons-front-core 8.1.0 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/catalog/captures-plan.ts +5 -1
- package/catalog/catalog-entries.ts +21 -1
- package/catalog/cloud-picker-fixture.tsx +97 -0
- package/catalog/pages/AccountMenu.tsx +62 -0
- package/catalog/pages/Avatar.tsx +94 -0
- package/catalog/pages/Callout.tsx +67 -0
- package/catalog/pages/CloudImport.tsx +35 -0
- package/catalog/pages/ContextSelector.tsx +103 -0
- package/catalog/pages/CopyField.tsx +29 -0
- package/catalog/pages/DropZone.tsx +37 -0
- package/catalog/pages/FormField.tsx +54 -0
- package/catalog/pages/ImportButton.tsx +45 -0
- package/catalog/pages/ImportFromCloudModal.tsx +33 -0
- package/catalog/pages/Menu.tsx +99 -98
- package/catalog/pages/NotificationsMenu.tsx +116 -0
- package/catalog/pages/NumberField.tsx +46 -0
- package/catalog/pages/QRCodeModal.tsx +26 -0
- package/catalog/pages/SettingsRow.tsx +67 -0
- package/catalog/pages/Tabs.tsx +72 -0
- package/catalog/pages/UsageMeter.tsx +58 -0
- package/catalog/pages/index.ts +34 -2
- package/catalog/specs/captures.spec.ts +7 -0
- package/catalog/specs/write-capture-index.ts +1 -0
- package/dist/{AbyssCookieConsentProvider-BhSzVu8P.js → AbyssCookieConsentProvider-B-PlGbFf.js} +815 -625
- package/dist/{CookieConsentSettings.component-DMEAuCVS.js → CookieConsentSettings.component-DEGCDEJW.js} +1 -1
- package/dist/components/business/CloudImport/CloudImport.d.ts +24 -0
- package/dist/components/business/CloudImport/cloud-import-tree.d.ts +22 -0
- package/dist/components/business/ImportFromCloudModal/ImportFromCloudModal.d.ts +21 -0
- package/dist/components/business/QRCodeModal/QRCodeModal.d.ts +18 -0
- package/dist/components/business/QRCodeModal/QRCodeModal.spec.d.ts +1 -0
- package/dist/components/business/index.d.ts +3 -0
- package/dist/components/data/DataTable/data-table.types.d.ts +10 -0
- package/dist/components/data/UsageMeter/UsageMeter.d.ts +31 -0
- package/dist/components/data/UsageMeter/UsageMeter.spec.d.ts +1 -0
- package/dist/components/data/index.d.ts +1 -0
- package/dist/components/inputs/ContextSelector/ContextSelector.d.ts +60 -0
- package/dist/components/inputs/ContextSelector/ContextSelector.spec.d.ts +1 -0
- package/dist/components/inputs/CopyField/CopyField.d.ts +19 -0
- package/dist/components/inputs/CopyField/CopyField.spec.d.ts +1 -0
- package/dist/components/inputs/DropZone/DropZone.d.ts +30 -0
- package/dist/components/inputs/DropZone/DropZone.spec.d.ts +1 -0
- package/dist/components/inputs/FormField/FormField.d.ts +29 -0
- package/dist/components/inputs/FormField/FormField.spec.d.ts +1 -0
- package/dist/components/inputs/ImportButton/ImportButton.d.ts +33 -0
- package/dist/components/inputs/ImportButton/ImportButton.spec.d.ts +1 -0
- package/dist/components/inputs/NumberField/NumberField.d.ts +21 -0
- package/dist/components/inputs/NumberField/NumberField.spec.d.ts +1 -0
- package/dist/components/inputs/NumberField/number-input.d.ts +13 -0
- package/dist/components/inputs/SettingsRow/SettingsRow.d.ts +16 -0
- package/dist/components/inputs/SettingsRow/SettingsRow.spec.d.ts +1 -0
- package/dist/components/inputs/index.d.ts +7 -0
- package/dist/components/layers/CommandPalette/CommandPalette.d.ts +27 -6
- package/dist/components/layers/CommandPalette/command-registry.d.ts +39 -9
- package/dist/components/layers/Menu/Menu.d.ts +2 -0
- package/dist/components/layers/Modal/Modal.d.ts +2 -1
- package/dist/components/meaning/Avatar/Avatar.d.ts +41 -0
- package/dist/components/meaning/Avatar/Avatar.spec.d.ts +1 -0
- package/dist/components/meaning/index.d.ts +1 -0
- package/dist/components/states/Callout/Callout.d.ts +25 -0
- package/dist/components/states/Callout/Callout.spec.d.ts +1 -0
- package/dist/components/states/PageState/PageState.d.ts +6 -1
- package/dist/components/states/index.d.ts +1 -0
- package/dist/components/structure/AccountMenu/AccountMenu.d.ts +27 -0
- package/dist/components/structure/AccountMenu/AccountMenu.spec.d.ts +1 -0
- package/dist/components/structure/AppShell/AppShell.d.ts +9 -3
- package/dist/components/structure/AppShell/ShellNavigation.d.ts +4 -2
- package/dist/components/structure/AppShell/app-shell.types.d.ts +38 -2
- package/dist/components/structure/NotificationsMenu/NotificationsMenu.d.ts +36 -0
- package/dist/components/structure/NotificationsMenu/NotificationsMenu.spec.d.ts +1 -0
- package/dist/components/structure/PageHeader/PageHeader.d.ts +2 -2
- package/dist/components/structure/Tabs/Tabs.d.ts +34 -0
- package/dist/components/structure/Tabs/Tabs.spec.d.ts +1 -0
- package/dist/components/structure/index.d.ts +3 -0
- package/dist/components/structure/test-support/structure-test-harness.d.ts +6 -0
- package/dist/cookie-consent.js +2 -2
- package/dist/design-theme-CKTz_cOa.js +15490 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-rich-intl.hook.d.ts +190 -0
- package/dist/hooks/use-scroll-overflow-cue.hook.d.ts +9 -0
- package/dist/hooks/use-scroll-overflow-cue.hook.spec.d.ts +1 -0
- package/dist/{index-D5e4uD4k.js → index-7N3J68EI.js} +2 -2
- package/dist/{index-BqIg55B3.js → index-B3rK_-T4.js} +4 -4
- package/dist/{index-6KdfKdSJ.js → index-B6qHo25Z.js} +2 -2
- package/dist/{index-BTjzj7mm.js → index-BMaAO_4e.js} +2 -2
- package/dist/{index-CHGRiRCe.js → index-B_jSh70G.js} +3 -3
- package/dist/{index-BkfBpYKR.js → index-B_yywet5.js} +3 -3
- package/dist/{index-DixNft1u.js → index-Bdtvzv-J.js} +2 -2
- package/dist/{index-ClLoBnCN.js → index-Bh2_8FCK.js} +2 -2
- package/dist/{index-D_GWBYM2.js → index-Bpg9TBMX.js} +1 -1
- package/dist/{index-GoHiFeaw.js → index-Bpnf8xKI.js} +2 -2
- package/dist/{index-bR-mnNUA.js → index-Bw2swxVq.js} +2 -2
- package/dist/{index-LdiTmDFg.js → index-BxxZgBFn.js} +2 -2
- package/dist/{index-ASLTmD1Y.js → index-Ca9tzEsn.js} +2 -2
- package/dist/{index-21vSFz6u.js → index-Csvh-AG6.js} +2 -2
- package/dist/{index-l7FAjaVB.js → index-CwuklsUK.js} +3 -3
- package/dist/{index-Ni4BmFs4.js → index-DFC9xBY9.js} +2 -2
- package/dist/{index-Btnmn1iK.js → index-DfUcsAJv.js} +4 -4
- package/dist/{index-D4Qh2Iww.js → index-DqedXp41.js} +3 -3
- package/dist/{index-BVS73U9E.js → index-DwXNHQIp.js} +4 -4
- package/dist/{index-BtsnuEJC.js → index-_UY_fqvv.js} +28415 -34554
- package/dist/{index-7HAvRXgu.js → index-dVVflNge.js} +2 -2
- package/dist/{index-C92C_oG5.js → index-sEWp0xIC.js} +2 -2
- package/dist/index.js +8273 -5009
- package/dist/legacy/components/QuotaOffer/AbyssQuotaOffer.component.d.ts +1 -1
- package/dist/legacy/components/QuotaOffer/index.d.ts +2 -2
- package/dist/legacy/theme/core-breakpoints-under-legacy-theme.spec.d.ts +1 -0
- package/dist/legacy.js +144 -144
- package/dist/theme/DesignCssVariables.d.ts +11 -0
- package/dist/theme/DesignCssVariables.spec.d.ts +1 -0
- package/dist/theme/components/shared.d.ts +4 -1
- package/dist/theme/css-variables.d.ts +7 -0
- package/dist/theme/design-media.d.ts +26 -0
- package/dist/theme/design-media.spec.d.ts +1 -0
- package/dist/theme/focus-ring.spec.d.ts +1 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/tokens/semantic.d.ts +1 -1
- package/dist/theme/use-design-breakpoint.d.ts +7 -0
- package/dist/translations/en.d.ts +95 -0
- package/dist/translations/fr.d.ts +95 -0
- package/dist/utils/cloud-accept.utils.spec.d.ts +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/quota-offer-state.utils.spec.d.ts +1 -0
- package/package.json +1 -1
- package/test-results/catalog/.last-run.json +4 -0
- package/dist/design-theme-CvLzOz3p.js +0 -9305
- /package/dist/{legacy/components/Inputs/CloudImport/cloud-accept.spec.d.ts → components/business/CloudImport/CloudImport.spec.d.ts} +0 -0
- /package/dist/{legacy/components/QuotaOffer/quota-offer-state.spec.d.ts → components/business/ImportFromCloudModal/ImportFromCloudModal.spec.d.ts} +0 -0
- /package/dist/{legacy/components/Inputs/CloudImport/cloud-accept.d.ts → utils/cloud-accept.utils.d.ts} +0 -0
- /package/dist/{legacy/components/QuotaOffer/quota-offer-state.d.ts → utils/quota-offer-state.utils.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -88,6 +88,84 @@ export const buildRumOptions = () =>
|
|
|
88
88
|
|
|
89
89
|
`ABYSS_MAIN_RUM_SESSION_ROUTE` (`/org/:orgId/project/:projectId/application/:applicationId/monitor/rum/sessions/:sessionId`) est la seule source du chemin de la page d'une session dans le front d'abyss-main, qui le monte. `abyssMainRumSessionPath({ orgId, projectId, applicationId }, sessionId, t?)` le remplit (id de session encodé) et ajoute `?t=` en secondes entières, jamais négatif.
|
|
90
90
|
|
|
91
|
+
## Changements visibles
|
|
92
|
+
|
|
93
|
+
### 8.3.0
|
|
94
|
+
|
|
95
|
+
Compte et facturation du front principal sur le design system (carte #286, zone 2). Sept pièces nouvelles, chacune
|
|
96
|
+
documentée dans le `README.md` de son dossier et montrée dans le catalogue.
|
|
97
|
+
|
|
98
|
+
- **`Tabs`** (`structure`) : rangée d'onglets liés aux routes ou boutons, variantes `TabsVariant.Primary` et
|
|
99
|
+
`Secondary`, un seul arrêt de tabulation, flèches, Début et Fin ; défilement horizontal avec fondu tant qu'il reste
|
|
100
|
+
des onglets à droite (`useScrollOverflowCue`), 44 px de haut sous 768 px.
|
|
101
|
+
- **`Callout`** (`states`) : bandeau `CalloutSeverity.Info`, `Success`, `Warning`, `Danger`, avec titre, action,
|
|
102
|
+
fermeture et icône facultatifs ; l'action passe sous le texte sous 768 px.
|
|
103
|
+
- **`FormField`** (`inputs`) : libellé, aide et erreur autour d'un `OutlinedInput`, `InputBase` ou `Select` ; `id`,
|
|
104
|
+
`aria-describedby` et `labelId` reliés, erreur et obligation passées au contrôle.
|
|
105
|
+
- **`SettingsRow`** (`inputs`) : libellé, description et contrôle à droite ; empilée sous 768 px.
|
|
106
|
+
- **`Switch` du thème** : sous 768 px, la zone tactile de tout interrupteur (38 px dessinés) est portée à 44 px de
|
|
107
|
+
haut.
|
|
108
|
+
- **`UsageMeter`** (`data`) : consommation sur un plafond, seuils en parts du plafond, jauge `meter` ; sans plafond, la
|
|
109
|
+
valeur seule.
|
|
110
|
+
- **`CopyField`** (`inputs`) : valeur masquable et copiable, résultat de la copie annoncé dans une région vivante.
|
|
111
|
+
- **`NumberField`** (`inputs`) : nombre saisi et affiché avec les séparateurs de la langue, « , » ou « . » lus comme
|
|
112
|
+
marque décimale, borné (`min`) et arrondi (`decimals`) en sortie du champ ; remplace `AbyssNumberField` du legacy
|
|
113
|
+
pour le design system.
|
|
114
|
+
- **`DataTable`** : deux options de colonne, `wrap` (la cellule passe à la ligne au lieu d'être coupée) et
|
|
115
|
+
`hideHeader` (en-tête lu par les technologies d'assistance, non dessiné, pour une colonne d'actions en icône).
|
|
116
|
+
- **`Tabs`** : l'onglet choisi est ramené à l'écran aussi quand la rangée ou un onglet change de taille.
|
|
117
|
+
- **Traductions** : clés `ds.states.callout.*`, `ds.inputs.copy-field.*` et `ds.data.usage-meter.*` (FR et EN).
|
|
118
|
+
|
|
119
|
+
Pièces que les pages de compte importaient encore de `/legacy`, refaites dans le nouveau système (les copies legacy
|
|
120
|
+
restent pour les hôtes legacy) :
|
|
121
|
+
|
|
122
|
+
- **`UserAvatar`, `OrganizationAvatar`, `ProjectAvatar`** (`meaning`) : photo ou logo, sinon l'initiale ; taille
|
|
123
|
+
`size` en px. La fiche de profil au clic du legacy n'est pas reprise (sans appelant).
|
|
124
|
+
- **`ContextSelector`** (`inputs`) : mon espace, puis un groupe par organisation et ses projets ;
|
|
125
|
+
`ContextValue.kind` est l'énumération `ContextKind`.
|
|
126
|
+
- **`DropZone`** (`inputs`) : dépôt et bouton de choix, refus (taille, type, nombre) écrits sous la zone, entrée
|
|
127
|
+
AbyssCloud avec `cloudImport`.
|
|
128
|
+
- **`ImportButton`** (`inputs`) : menu appareil, lien (adresse vérifiée, échec dit), AbyssCloud.
|
|
129
|
+
- **`CloudImport`**, **`ImportFromCloudModal`**, **`QRCodeModal`** (`business`) : le sélecteur AbyssCloud, sa
|
|
130
|
+
modale (`open`, `onClose`, `onImport`), et un lien en QR code (`open` au lieu de `isOpen`).
|
|
131
|
+
- **Jetons `paper` et `paper.on`** : une page claire et son encre dans les deux thèmes, pour ce qui est dessiné à
|
|
132
|
+
l'encre sombre (code QR, signature en PNG transparent). ADR-0174 §3 complété.
|
|
133
|
+
- **Logique pure partagée** : `deriveQuotaOfferState`, `QuotaOfferState`, `offersAction`, `shouldSuggestModule`
|
|
134
|
+
(table de décision de l'offre de quota) sortent de `legacy/` et s'exportent de la racine ; `/legacy` les
|
|
135
|
+
réexporte toujours. `isAcceptedFile` (filtre `accept` du sélecteur cloud) passe aussi hors de `legacy/`.
|
|
136
|
+
- **Traductions** : `ds.inputs.context-selector.*`, `ds.inputs.drop-zone.*`, `ds.inputs.import-button.*`,
|
|
137
|
+
`ds.business.cloud-import.*`, `ds.business.qr-code.*` (FR et EN).
|
|
138
|
+
|
|
139
|
+
### 8.2.0
|
|
140
|
+
|
|
141
|
+
Shell et tableaux de bord du front principal sur le design system (carte #286, zone 1).
|
|
142
|
+
|
|
143
|
+
- **Nouveau** : `AppShell` prend `chromeless` (plein écran sans cadre), les entrées `external` et `action`,
|
|
144
|
+
l'action de section (`NavSection.action`) et les entrées internes du pied ; `NotificationsMenu`, `AccountMenu`,
|
|
145
|
+
`DesignCssVariables` et `focusRing` sont exportés ; `CommandPalette` gagne icônes, sous-titres, récents, sources
|
|
146
|
+
asynchrones et ouverture filtrée.
|
|
147
|
+
- **Paliers** : les composants du design system basculent à 768 et 1200 px (`designMedia`, `useDesignBreakpoint`)
|
|
148
|
+
quel que soit le provider. Sous le thème legacy, l'`AppShell` montre le rail dès 768 px (et non plus à 900), la
|
|
149
|
+
`Modal` une fenêtre dès 768 px, et la bannière MFA passe son bouton sous le texte quand il ne tient plus à côté.
|
|
150
|
+
- **Largeur de `Drawer` et de `Toast` sous le thème legacy** : la largeur par défaut passe de 600 à 480 px (palier
|
|
151
|
+
`sm` des jetons, et non plus le `sm` de MUI). Un hôte qui comptait sur 600 px passe `width` explicitement au
|
|
152
|
+
`Drawer`.
|
|
153
|
+
- **Largeur de `Modal` et de `CommandPalette` sous le thème legacy** : elle reste tirée des `theme.breakpoints` de
|
|
154
|
+
MUI (prop `size` de la `Modal` passée à `maxWidth`, `sm` pour la palette). Sous le thème legacy, `md` vaut 900 px
|
|
155
|
+
et `sm` 600 px, contre 768 et 480 sous `AbyssThemeProvider` : la même `Modal` est donc plus large chez un hôte
|
|
156
|
+
legacy. Suivi : `DS-LEGACY-WIDTHS` dans `docs/internal/TECH-DEBT.md` d'abyss-main.
|
|
157
|
+
- **Sélecteur d'espace** : un espace qui porte le nom de son type (« Espace personnel ») n'a plus de seconde ligne
|
|
158
|
+
répétant ce type.
|
|
159
|
+
- **Navigation** : la liste des sections garde une barre de défilement fine et visible quand elle dépasse la
|
|
160
|
+
hauteur de la fenêtre.
|
|
161
|
+
- **`PageState`** : `forbidden.message` remplace la description générique de l’accès refusé, pour nommer à qui
|
|
162
|
+
demander l’accès (organisation, projet).
|
|
163
|
+
- **`PageState`** : le bloc d’état passe son action sous le texte dès que son emplacement fait moins de 512 px
|
|
164
|
+
(colonne latérale), et plus seulement sous 768 px d’écran.
|
|
165
|
+
- **`PageHeader`** : de 768 px à la largeur du bureau, les actions passent sous le titre dès qu'elles ne tiennent
|
|
166
|
+
plus à côté d'un titre de 256 px.
|
|
167
|
+
|
|
168
|
+
|
|
91
169
|
## Support
|
|
92
170
|
|
|
93
171
|
Pour toute demande, ouvrir un ticket depuis [l'application Abyss](https://app.abyss-project.fr/dashboard/account/tickets/create).
|
package/catalog/captures-plan.ts
CHANGED
|
@@ -33,7 +33,8 @@ export type CaptureState =
|
|
|
33
33
|
| 'arrival'
|
|
34
34
|
| 'sheet-open'
|
|
35
35
|
| 'list-open'
|
|
36
|
-
| 'calendar-open'
|
|
36
|
+
| 'calendar-open'
|
|
37
|
+
| 'panel-open';
|
|
37
38
|
|
|
38
39
|
/** File name suffix of each state. */
|
|
39
40
|
const STATE_SUFFIX: Record<CaptureState, string> = {
|
|
@@ -41,6 +42,7 @@ const STATE_SUFFIX: Record<CaptureState, string> = {
|
|
|
41
42
|
'sheet-open': '-feuille',
|
|
42
43
|
'list-open': '-liste',
|
|
43
44
|
'calendar-open': '-calendrier',
|
|
45
|
+
'panel-open': '-ouvert',
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
/** The states shown beyond arrival: what a closed control hides (options, calendar, sheet). */
|
|
@@ -48,6 +50,8 @@ const EXTRA_STATES: Record<string, CaptureState> = {
|
|
|
48
50
|
SceneMobile: 'sheet-open',
|
|
49
51
|
RichSelect: 'list-open',
|
|
50
52
|
DateField: 'calendar-open',
|
|
53
|
+
NotificationsMenu: 'panel-open',
|
|
54
|
+
AccountMenu: 'panel-open',
|
|
51
55
|
};
|
|
52
56
|
|
|
53
57
|
export interface Capture {
|
|
@@ -20,7 +20,7 @@ export interface CatalogEntry {
|
|
|
20
20
|
family: CatalogFamily;
|
|
21
21
|
/** Base name of the screenshots: `<slug>-<theme>-<width>.png`. */
|
|
22
22
|
slug: string;
|
|
23
|
-
/** Checked by `responsive.spec.ts` at 360, 768 and 1440 px
|
|
23
|
+
/** Checked by `responsive.spec.ts` at 360, 768 and 1440 px: the pages that change form below 768 px. */
|
|
24
24
|
responsive: boolean;
|
|
25
25
|
/** Also captured at 390 px: the page changes form below 768 px. */
|
|
26
26
|
mobileCapture: boolean;
|
|
@@ -51,23 +51,36 @@ export const CATALOG_ENTRIES: CatalogEntry[] = [
|
|
|
51
51
|
entry('Toolbar', 'structure', 'toolbar', RESPONSIVE),
|
|
52
52
|
entry('FilterBar', 'structure', 'filter-bar', RESPONSIVE),
|
|
53
53
|
entry('SplitView', 'structure', 'split-view', RESPONSIVE),
|
|
54
|
+
entry('Tabs', 'structure', 'tabs', RESPONSIVE),
|
|
55
|
+
entry('NotificationsMenu', 'structure', 'notifications-menu', {
|
|
56
|
+
mobileCapture: true,
|
|
57
|
+
}),
|
|
58
|
+
entry('AccountMenu', 'structure', 'account-menu'),
|
|
54
59
|
entry('MobileShell', 'mobile', 'mobile-shell', RESPONSIVE),
|
|
55
60
|
entry('BottomSheet', 'mobile', 'bottom-sheet', RESPONSIVE),
|
|
56
61
|
entry('ActionBar', 'mobile', 'action-bar', RESPONSIVE),
|
|
57
62
|
entry('SwipeDeck', 'mobile', 'swipe-deck', RESPONSIVE),
|
|
58
63
|
entry('PageState', 'states', 'page-state'),
|
|
64
|
+
entry('Callout', 'states', 'callout', RESPONSIVE),
|
|
59
65
|
entry('DataTable', 'data', 'data-table', RESPONSIVE),
|
|
60
66
|
entry('KeyValueList', 'data', 'key-value-list'),
|
|
61
67
|
entry('StatTile', 'data', 'stat-tile'),
|
|
62
68
|
entry('Sparkline', 'data', 'sparkline'),
|
|
63
69
|
entry('ChartTheme', 'data', 'chart-theme'),
|
|
70
|
+
entry('UsageMeter', 'data', 'usage-meter'),
|
|
64
71
|
entry('StatusBadge', 'meaning', 'status-badge'),
|
|
65
72
|
entry('MethodBadge', 'meaning', 'method-badge'),
|
|
66
73
|
entry('SeverityBadge', 'meaning', 'severity-badge'),
|
|
67
74
|
entry('ScanBadge', 'meaning', 'scan-badge'),
|
|
68
75
|
entry('RoleBadge', 'meaning', 'role-badge'),
|
|
69
76
|
entry('ToolIcon', 'meaning', 'tool-icon'),
|
|
77
|
+
entry('Avatar', 'meaning', 'avatar'),
|
|
70
78
|
entry('InfectedDownloadModal', 'business', 'infected-download-modal'),
|
|
79
|
+
entry('CloudImport', 'business', 'cloud-import', RESPONSIVE),
|
|
80
|
+
entry('ImportFromCloudModal', 'business', 'import-from-cloud-modal', {
|
|
81
|
+
mobileCapture: true,
|
|
82
|
+
}),
|
|
83
|
+
entry('QRCodeModal', 'business', 'qr-code-modal', { mobileCapture: true }),
|
|
71
84
|
entry('Modal', 'layers', 'modal', { mobileCapture: true }),
|
|
72
85
|
entry('ConfirmDialog', 'layers', 'confirm-dialog'),
|
|
73
86
|
entry('Drawer', 'layers', 'drawer'),
|
|
@@ -79,6 +92,13 @@ export const CATALOG_ENTRIES: CatalogEntry[] = [
|
|
|
79
92
|
entry('DateRangeField', 'inputs', 'date-range-field'),
|
|
80
93
|
entry('ColorField', 'inputs', 'color-field'),
|
|
81
94
|
entry('SegmentedControl', 'inputs', 'segmented-control'),
|
|
95
|
+
entry('FormField', 'inputs', 'form-field'),
|
|
96
|
+
entry('NumberField', 'inputs', 'number-field'),
|
|
97
|
+
entry('SettingsRow', 'inputs', 'settings-row', RESPONSIVE),
|
|
98
|
+
entry('CopyField', 'inputs', 'copy-field', RESPONSIVE),
|
|
99
|
+
entry('ContextSelector', 'inputs', 'context-selector', RESPONSIVE),
|
|
100
|
+
entry('DropZone', 'inputs', 'drop-zone', RESPONSIVE),
|
|
101
|
+
entry('ImportButton', 'inputs', 'import-button'),
|
|
82
102
|
];
|
|
83
103
|
|
|
84
104
|
export const CATALOG_THEMES = [ThemeMode.Dark, ThemeMode.Light] as const;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IFile,
|
|
3
|
+
IFolder,
|
|
4
|
+
IGetRepositoryCloudData,
|
|
5
|
+
ISpace,
|
|
6
|
+
} from '@abyss-project/cloud';
|
|
7
|
+
import type { CloudPicker } from '../src/hooks/cloud-picker.types';
|
|
8
|
+
|
|
9
|
+
// An AbyssCloud picker that answers from memory: the catalog has no network. Three Spaces (mine,
|
|
10
|
+
// an organization's, one shared with me) and a small tree in the personal one.
|
|
11
|
+
|
|
12
|
+
const space = (id: string, overrides: Partial<ISpace>): ISpace => ({
|
|
13
|
+
id,
|
|
14
|
+
userId: 'user-1',
|
|
15
|
+
organizationId: null,
|
|
16
|
+
projectId: null,
|
|
17
|
+
createdByUserId: 'user-1',
|
|
18
|
+
archivedAt: null,
|
|
19
|
+
saveVersionDefault: false,
|
|
20
|
+
versionMaxCount: null,
|
|
21
|
+
versionMaxAgeDays: null,
|
|
22
|
+
...overrides,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const PERSONAL = space('space-personal', {});
|
|
26
|
+
const ORGANIZATION = space('space-org', {
|
|
27
|
+
userId: null,
|
|
28
|
+
organizationId: 'org-1',
|
|
29
|
+
});
|
|
30
|
+
const SHARED = space('space-shared', { userId: 'user-2' });
|
|
31
|
+
|
|
32
|
+
const file = (name: string, mimeType: string, sizeOctet: number): IFile => ({
|
|
33
|
+
id: name,
|
|
34
|
+
name,
|
|
35
|
+
description: null,
|
|
36
|
+
sizeOctet,
|
|
37
|
+
isEncrypt: false,
|
|
38
|
+
thumbnailPublicAccessId: null,
|
|
39
|
+
thumbnailId: null,
|
|
40
|
+
saveVersion: false,
|
|
41
|
+
externalId: null,
|
|
42
|
+
folderId: null,
|
|
43
|
+
spaceId: 'space-personal',
|
|
44
|
+
createdByUserId: 'user-1',
|
|
45
|
+
checksum: null,
|
|
46
|
+
mimeType,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const folder = (name: string, childFile: IFile[]): IFolder => ({
|
|
50
|
+
id: name,
|
|
51
|
+
name,
|
|
52
|
+
description: null,
|
|
53
|
+
spaceId: 'space-personal',
|
|
54
|
+
folderId: null,
|
|
55
|
+
createdByUserId: 'user-1',
|
|
56
|
+
childFile,
|
|
57
|
+
childFolder: [],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const TREE: IGetRepositoryCloudData = {
|
|
61
|
+
folders: [
|
|
62
|
+
folder('Factures 2026', [
|
|
63
|
+
file('facture-septembre.pdf', 'application/pdf', 182_000),
|
|
64
|
+
file('facture-octobre.pdf', 'application/pdf', 176_000),
|
|
65
|
+
]),
|
|
66
|
+
folder('Photos', [file('portrait.png', 'image/png', 1_240_000)]),
|
|
67
|
+
],
|
|
68
|
+
files: [
|
|
69
|
+
file('signature.png', 'image/png', 24_000),
|
|
70
|
+
file('contrat-de-bail-appartement-lyon.pdf', 'application/pdf', 912_000),
|
|
71
|
+
file('notes.txt', 'text/plain', 2_000),
|
|
72
|
+
],
|
|
73
|
+
size: 2_534_000,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const CATALOG_CLOUD_PICKER: CloudPicker = {
|
|
77
|
+
abyssCloudUrl: 'https://cloud.abyss-project.fr',
|
|
78
|
+
getFileThumbnailUrl: () => '',
|
|
79
|
+
clouds: [PERSONAL, ORGANIZATION],
|
|
80
|
+
cloudShares: [SHARED],
|
|
81
|
+
isLoading: false,
|
|
82
|
+
hasError: false,
|
|
83
|
+
refresh: async () => true,
|
|
84
|
+
onCreateCloud: async () => true,
|
|
85
|
+
fetchCloudRepository: async (spaceId) =>
|
|
86
|
+
spaceId === PERSONAL.id ? TREE : { folders: [], files: [], size: 0 },
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** The same picker after a failed provisioning: nothing listed. */
|
|
90
|
+
export const CATALOG_FAILED_CLOUD_PICKER: CloudPicker = {
|
|
91
|
+
...CATALOG_CLOUD_PICKER,
|
|
92
|
+
clouds: null,
|
|
93
|
+
cloudShares: null,
|
|
94
|
+
hasError: true,
|
|
95
|
+
refresh: async () => false,
|
|
96
|
+
onCreateCloud: async () => false,
|
|
97
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import PersonOutline from '@mui/icons-material/PersonOutline';
|
|
3
|
+
import SettingsOutlined from '@mui/icons-material/SettingsOutlined';
|
|
4
|
+
import CreditCardOutlined from '@mui/icons-material/CreditCardOutlined';
|
|
5
|
+
import ForumOutlined from '@mui/icons-material/ForumOutlined';
|
|
6
|
+
import { AccountMenu } from '../../src/components/structure/AccountMenu/AccountMenu';
|
|
7
|
+
import { ThemeMode } from '../../src/theme/tokens/primitives';
|
|
8
|
+
import { Example, LastEvent, Row, Showcase, useEventLog } from '../frame';
|
|
9
|
+
|
|
10
|
+
export const AccountMenuPage = () => {
|
|
11
|
+
const { log } = useEventLog();
|
|
12
|
+
const [mode, setMode] = useState(ThemeMode.Dark);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Showcase
|
|
16
|
+
family="Structure"
|
|
17
|
+
name="AccountMenu"
|
|
18
|
+
description="Avatar de la barre du haut : identité, entrées de l'hôte, thème sombre, déconnexion."
|
|
19
|
+
>
|
|
20
|
+
<Example title="Barre du haut">
|
|
21
|
+
<Row>
|
|
22
|
+
<AccountMenu
|
|
23
|
+
user={{ name: 'Mehdi Abyss', email: 'mehdi@abyss.example' }}
|
|
24
|
+
themeMode={mode}
|
|
25
|
+
onThemeModeChange={(next) => {
|
|
26
|
+
setMode(next);
|
|
27
|
+
log(`thème ${next}`);
|
|
28
|
+
}}
|
|
29
|
+
items={[
|
|
30
|
+
{
|
|
31
|
+
id: 'account',
|
|
32
|
+
label: 'Mon compte',
|
|
33
|
+
icon: <PersonOutline />,
|
|
34
|
+
href: '/compte',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'settings',
|
|
38
|
+
label: 'Paramètres',
|
|
39
|
+
icon: <SettingsOutlined />,
|
|
40
|
+
href: '/compte/parametres',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'billing',
|
|
44
|
+
label: 'Facturation',
|
|
45
|
+
icon: <CreditCardOutlined />,
|
|
46
|
+
href: '/compte/facturation',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'discord',
|
|
50
|
+
label: 'Discord',
|
|
51
|
+
icon: <ForumOutlined />,
|
|
52
|
+
onClick: () => log('discord'),
|
|
53
|
+
},
|
|
54
|
+
]}
|
|
55
|
+
onLogout={() => log('déconnexion')}
|
|
56
|
+
/>
|
|
57
|
+
</Row>
|
|
58
|
+
</Example>
|
|
59
|
+
<LastEvent />
|
|
60
|
+
</Showcase>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OrganizationAvatar,
|
|
3
|
+
ProjectAvatar,
|
|
4
|
+
UserAvatar,
|
|
5
|
+
} from '../../src/components/meaning/Avatar/Avatar';
|
|
6
|
+
import { LogoAbyssSmall } from '../../src/assets';
|
|
7
|
+
import { Example, Row, Showcase } from '../frame';
|
|
8
|
+
|
|
9
|
+
const picture = () => LogoAbyssSmall;
|
|
10
|
+
// A picture that cannot load: the initial stays.
|
|
11
|
+
const missing = (id: string) => `/catalogue-introuvable/${id}.png`;
|
|
12
|
+
|
|
13
|
+
export const AvatarPage = () => (
|
|
14
|
+
<Showcase
|
|
15
|
+
family="Sens"
|
|
16
|
+
name="Avatar"
|
|
17
|
+
description="Personne, organisation, projet : la photo ou le logo, sinon l'initiale (ou une icône sans nom). Une personne dans un disque, une organisation et un projet dans un carré arrondi."
|
|
18
|
+
>
|
|
19
|
+
<Example title="Avec image" framed>
|
|
20
|
+
<Row>
|
|
21
|
+
<UserAvatar
|
|
22
|
+
userId="u1"
|
|
23
|
+
alias="Mehdi"
|
|
24
|
+
hasThumbnail
|
|
25
|
+
getProfilePictureUrl={picture}
|
|
26
|
+
/>
|
|
27
|
+
<OrganizationAvatar
|
|
28
|
+
orgId="o1"
|
|
29
|
+
name="Abyss"
|
|
30
|
+
hasThumbnail
|
|
31
|
+
getLogoUrl={picture}
|
|
32
|
+
/>
|
|
33
|
+
<ProjectAvatar
|
|
34
|
+
projectId="p1"
|
|
35
|
+
title="Atlas"
|
|
36
|
+
hasThumbnail
|
|
37
|
+
getProjectPictureUrl={picture}
|
|
38
|
+
/>
|
|
39
|
+
</Row>
|
|
40
|
+
</Example>
|
|
41
|
+
<Example title="Sans image, ou image introuvable" framed>
|
|
42
|
+
<Row>
|
|
43
|
+
<UserAvatar
|
|
44
|
+
userId="u2"
|
|
45
|
+
alias="camille"
|
|
46
|
+
hasThumbnail={false}
|
|
47
|
+
getProfilePictureUrl={picture}
|
|
48
|
+
/>
|
|
49
|
+
<OrganizationAvatar
|
|
50
|
+
orgId="o2"
|
|
51
|
+
name="Karbon"
|
|
52
|
+
hasThumbnail
|
|
53
|
+
getLogoUrl={missing}
|
|
54
|
+
/>
|
|
55
|
+
<ProjectAvatar
|
|
56
|
+
projectId="p2"
|
|
57
|
+
title="board"
|
|
58
|
+
hasThumbnail={false}
|
|
59
|
+
getProjectPictureUrl={picture}
|
|
60
|
+
/>
|
|
61
|
+
<OrganizationAvatar
|
|
62
|
+
orgId="o3"
|
|
63
|
+
name=""
|
|
64
|
+
hasThumbnail={false}
|
|
65
|
+
getLogoUrl={picture}
|
|
66
|
+
/>
|
|
67
|
+
</Row>
|
|
68
|
+
</Example>
|
|
69
|
+
<Example title="Tailles : 22, 32 (défaut), 64" framed>
|
|
70
|
+
<Row>
|
|
71
|
+
<UserAvatar
|
|
72
|
+
userId="u3"
|
|
73
|
+
alias="Lina"
|
|
74
|
+
hasThumbnail={false}
|
|
75
|
+
size={22}
|
|
76
|
+
getProfilePictureUrl={picture}
|
|
77
|
+
/>
|
|
78
|
+
<UserAvatar
|
|
79
|
+
userId="u4"
|
|
80
|
+
alias="Lina"
|
|
81
|
+
hasThumbnail={false}
|
|
82
|
+
getProfilePictureUrl={picture}
|
|
83
|
+
/>
|
|
84
|
+
<UserAvatar
|
|
85
|
+
userId="u5"
|
|
86
|
+
alias="Lina"
|
|
87
|
+
hasThumbnail
|
|
88
|
+
size={64}
|
|
89
|
+
getProfilePictureUrl={picture}
|
|
90
|
+
/>
|
|
91
|
+
</Row>
|
|
92
|
+
</Example>
|
|
93
|
+
</Showcase>
|
|
94
|
+
);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import Button from '@mui/material/Button';
|
|
2
|
+
import GroupsRounded from '@mui/icons-material/GroupsRounded';
|
|
3
|
+
import {
|
|
4
|
+
Callout,
|
|
5
|
+
CalloutSeverity,
|
|
6
|
+
} from '../../src/components/states/Callout/Callout';
|
|
7
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
8
|
+
|
|
9
|
+
export const CalloutPage = () => {
|
|
10
|
+
const { log } = useEventLog();
|
|
11
|
+
return (
|
|
12
|
+
<Showcase
|
|
13
|
+
family="États"
|
|
14
|
+
name="Callout"
|
|
15
|
+
description="Bandeau dans une page : information, succès, avertissement, danger ; titre, texte, action et fermeture facultatifs."
|
|
16
|
+
>
|
|
17
|
+
<Example title="Information, avec titre et fermeture">
|
|
18
|
+
<Callout
|
|
19
|
+
severity={CalloutSeverity.Info}
|
|
20
|
+
title="Essai gratuit"
|
|
21
|
+
onClose={() => log('fermer essai')}
|
|
22
|
+
>
|
|
23
|
+
Votre essai du plan Pro se termine dans 12 jours.
|
|
24
|
+
</Callout>
|
|
25
|
+
</Example>
|
|
26
|
+
<Example title="Succès">
|
|
27
|
+
<Callout severity={CalloutSeverity.Success}>
|
|
28
|
+
Votre moyen de paiement a été mis à jour.
|
|
29
|
+
</Callout>
|
|
30
|
+
</Example>
|
|
31
|
+
<Example title="Avertissement, avec action">
|
|
32
|
+
<Callout
|
|
33
|
+
severity={CalloutSeverity.Warning}
|
|
34
|
+
title="Quota bientôt atteint"
|
|
35
|
+
action={
|
|
36
|
+
<Button variant="outlined" onClick={() => log('augmenter')}>
|
|
37
|
+
Augmenter le stockage
|
|
38
|
+
</Button>
|
|
39
|
+
}
|
|
40
|
+
>
|
|
41
|
+
Vous avez utilisé 92 % de votre stockage.
|
|
42
|
+
</Callout>
|
|
43
|
+
</Example>
|
|
44
|
+
<Example title="Danger, avec action et fermeture">
|
|
45
|
+
<Callout
|
|
46
|
+
severity={CalloutSeverity.Danger}
|
|
47
|
+
title="Paiement refusé"
|
|
48
|
+
action={
|
|
49
|
+
<Button variant="contained" onClick={() => log('régler')}>
|
|
50
|
+
Régler la facture
|
|
51
|
+
</Button>
|
|
52
|
+
}
|
|
53
|
+
onClose={() => log('fermer paiement')}
|
|
54
|
+
>
|
|
55
|
+
Le prélèvement de la facture de septembre a échoué. Mettez à jour
|
|
56
|
+
votre carte pour éviter la suspension de votre abonnement.
|
|
57
|
+
</Callout>
|
|
58
|
+
</Example>
|
|
59
|
+
<Example title="Icône remplacée (famille)">
|
|
60
|
+
<Callout severity={CalloutSeverity.Info} icon={<GroupsRounded />}>
|
|
61
|
+
Votre abonnement est pris en charge par votre famille.
|
|
62
|
+
</Callout>
|
|
63
|
+
</Example>
|
|
64
|
+
<LastEvent />
|
|
65
|
+
</Showcase>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CloudImport } from '../../src/components/business/CloudImport/CloudImport';
|
|
2
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
3
|
+
import {
|
|
4
|
+
CATALOG_CLOUD_PICKER,
|
|
5
|
+
CATALOG_FAILED_CLOUD_PICKER,
|
|
6
|
+
} from '../cloud-picker-fixture';
|
|
7
|
+
|
|
8
|
+
export const CloudImportPage = () => {
|
|
9
|
+
const { log } = useEventLog();
|
|
10
|
+
return (
|
|
11
|
+
<Showcase
|
|
12
|
+
family="Métier"
|
|
13
|
+
name="CloudImport"
|
|
14
|
+
description="Le sélecteur AbyssCloud : espace (le mien, ceux des organisations, ceux partagés avec moi), arborescence, fichiers choisis, import. Les fichiers trop lourds ou d'un type refusé ne sont pas listés."
|
|
15
|
+
>
|
|
16
|
+
<Example title="Plusieurs fichiers, PDF et images" maxWidth={768}>
|
|
17
|
+
<CloudImport
|
|
18
|
+
cloudPicker={CATALOG_CLOUD_PICKER}
|
|
19
|
+
multiple
|
|
20
|
+
accept={['application/pdf', 'image/*']}
|
|
21
|
+
onImport={(_space, files) =>
|
|
22
|
+
log(`importé ${files.map((file) => file.name).join(', ')}`)
|
|
23
|
+
}
|
|
24
|
+
/>
|
|
25
|
+
</Example>
|
|
26
|
+
<Example title="Le cloud n'a pas pu être préparé" maxWidth={768}>
|
|
27
|
+
<CloudImport
|
|
28
|
+
cloudPicker={CATALOG_FAILED_CLOUD_PICKER}
|
|
29
|
+
onImport={() => undefined}
|
|
30
|
+
/>
|
|
31
|
+
</Example>
|
|
32
|
+
<LastEvent />
|
|
33
|
+
</Showcase>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ContextKind,
|
|
4
|
+
ContextSelector,
|
|
5
|
+
} from '../../src/components/inputs/ContextSelector/ContextSelector';
|
|
6
|
+
import type {
|
|
7
|
+
ContextSelectorData,
|
|
8
|
+
ContextValue,
|
|
9
|
+
} from '../../src/components/inputs/ContextSelector/ContextSelector';
|
|
10
|
+
import {
|
|
11
|
+
OrganizationAvatar,
|
|
12
|
+
ProjectAvatar,
|
|
13
|
+
UserAvatar,
|
|
14
|
+
} from '../../src/components/meaning/Avatar/Avatar';
|
|
15
|
+
import { LogoAbyssSmall } from '../../src/assets';
|
|
16
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
17
|
+
|
|
18
|
+
const AVATAR = 22;
|
|
19
|
+
const picture = () => LogoAbyssSmall;
|
|
20
|
+
|
|
21
|
+
const DATA: ContextSelectorData = {
|
|
22
|
+
personal: {
|
|
23
|
+
label: 'Mehdi',
|
|
24
|
+
avatar: (
|
|
25
|
+
<UserAvatar
|
|
26
|
+
userId="u1"
|
|
27
|
+
alias="Mehdi"
|
|
28
|
+
hasThumbnail
|
|
29
|
+
size={AVATAR}
|
|
30
|
+
getProfilePictureUrl={picture}
|
|
31
|
+
/>
|
|
32
|
+
),
|
|
33
|
+
},
|
|
34
|
+
organizations: [
|
|
35
|
+
{
|
|
36
|
+
id: 'o1',
|
|
37
|
+
name: 'Abyss',
|
|
38
|
+
avatar: (
|
|
39
|
+
<OrganizationAvatar
|
|
40
|
+
orgId="o1"
|
|
41
|
+
name="Abyss"
|
|
42
|
+
hasThumbnail={false}
|
|
43
|
+
size={AVATAR}
|
|
44
|
+
getLogoUrl={picture}
|
|
45
|
+
/>
|
|
46
|
+
),
|
|
47
|
+
projects: [
|
|
48
|
+
{
|
|
49
|
+
id: 'p1',
|
|
50
|
+
name: 'Atlas',
|
|
51
|
+
avatar: (
|
|
52
|
+
<ProjectAvatar
|
|
53
|
+
projectId="p1"
|
|
54
|
+
title="Atlas"
|
|
55
|
+
hasThumbnail={false}
|
|
56
|
+
size={AVATAR}
|
|
57
|
+
getProjectPictureUrl={picture}
|
|
58
|
+
/>
|
|
59
|
+
),
|
|
60
|
+
},
|
|
61
|
+
{ id: 'p2', name: 'Refonte du site vitrine' },
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{ id: 'o2', name: 'Karbon Studio' },
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const ContextSelectorPage = () => {
|
|
69
|
+
const { log } = useEventLog();
|
|
70
|
+
const [value, setValue] = useState<ContextValue>({
|
|
71
|
+
kind: ContextKind.Organization,
|
|
72
|
+
organizationId: 'o1',
|
|
73
|
+
});
|
|
74
|
+
return (
|
|
75
|
+
<Showcase
|
|
76
|
+
family="Saisie"
|
|
77
|
+
name="ContextSelector"
|
|
78
|
+
description="Choix de la portée d'une page : mon espace, puis un groupe par organisation (toute l'organisation, puis ses projets). La saisie filtre les entrées."
|
|
79
|
+
>
|
|
80
|
+
<Example title="Portée des ressources" maxWidth={480}>
|
|
81
|
+
<ContextSelector
|
|
82
|
+
data={DATA}
|
|
83
|
+
value={value}
|
|
84
|
+
onChange={(next) => {
|
|
85
|
+
setValue(next);
|
|
86
|
+
log(`portée ${next.kind}`);
|
|
87
|
+
}}
|
|
88
|
+
label="Espace"
|
|
89
|
+
/>
|
|
90
|
+
</Example>
|
|
91
|
+
<Example title="Inactif" maxWidth={480}>
|
|
92
|
+
<ContextSelector
|
|
93
|
+
data={DATA}
|
|
94
|
+
value={{ kind: ContextKind.Personal }}
|
|
95
|
+
onChange={() => undefined}
|
|
96
|
+
label="Espace"
|
|
97
|
+
disabled
|
|
98
|
+
/>
|
|
99
|
+
</Example>
|
|
100
|
+
<LastEvent />
|
|
101
|
+
</Showcase>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { CopyField } from '../../src/components/inputs/CopyField/CopyField';
|
|
2
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
3
|
+
|
|
4
|
+
export const CopyFieldPage = () => {
|
|
5
|
+
const { log } = useEventLog();
|
|
6
|
+
return (
|
|
7
|
+
<Showcase
|
|
8
|
+
family="Saisie"
|
|
9
|
+
name="CopyField"
|
|
10
|
+
description="Valeur à copier, masquable : bouton de copie, annonce du résultat dans une région vivante, bouton pour afficher une valeur masquée."
|
|
11
|
+
>
|
|
12
|
+
<Example title="Clé d'API, masquée" maxWidth={640}>
|
|
13
|
+
<CopyField
|
|
14
|
+
value="abyss_sk_live_5f2c9a7e1b3d4f60a8c2e9b7d1f3a5c7"
|
|
15
|
+
masked
|
|
16
|
+
onReveal={() => log('afficher la clé')}
|
|
17
|
+
copyLabel="Copier la clé"
|
|
18
|
+
/>
|
|
19
|
+
</Example>
|
|
20
|
+
<Example title="Identifiant de connexion IA" maxWidth={640}>
|
|
21
|
+
<CopyField
|
|
22
|
+
value="https://mcp.abyss-project.fr/u/7f3a9c2e"
|
|
23
|
+
copyLabel="Copier l'adresse"
|
|
24
|
+
/>
|
|
25
|
+
</Example>
|
|
26
|
+
<LastEvent />
|
|
27
|
+
</Showcase>
|
|
28
|
+
);
|
|
29
|
+
};
|