@alveole/components 1.8.4 → 1.10.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/dist/core/Section/Section.stories.d.ts.map +1 -1
- package/dist/core/Section/Section.stories.js +9 -3
- package/dist/core/Section/Section.stories.sources.d.ts.map +1 -1
- package/dist/core/Section/Section.stories.sources.js +2 -2
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/stories/index.d.ts +1 -0
- package/dist/stories/index.d.ts.map +1 -1
- package/dist/stories/index.js +1 -0
- package/dist/ui/ActionMenu/ActionMenu.stories.d.ts +1 -0
- package/dist/ui/ActionMenu/ActionMenu.stories.d.ts.map +1 -1
- package/dist/ui/ActionMenu/ActionMenu.stories.js +2 -1
- package/dist/ui/Button/Button.d.ts +4 -2
- package/dist/ui/Button/Button.d.ts.map +1 -1
- package/dist/ui/Button/Button.js +19 -10
- package/dist/ui/Button/Button.stories.d.ts +6 -1
- package/dist/ui/Button/Button.stories.d.ts.map +1 -1
- package/dist/ui/Button/Button.stories.js +2 -0
- package/dist/ui/Button/Button.stories.sources.d.ts +2 -0
- package/dist/ui/Button/Button.stories.sources.d.ts.map +1 -1
- package/dist/ui/Button/Button.stories.sources.js +3 -0
- package/dist/ui/Button/Button.styles.d.ts +3 -0
- package/dist/ui/Button/Button.styles.d.ts.map +1 -1
- package/dist/ui/Button/Button.styles.js +3 -0
- package/dist/ui/Checkbox/Checkbox.d.ts +2 -1
- package/dist/ui/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/ui/Checkbox/Checkbox.js +3 -4
- package/dist/ui/Checkbox/Checkbox.stories.d.ts +3 -2
- package/dist/ui/Checkbox/Checkbox.stories.d.ts.map +1 -1
- package/dist/ui/Checkbox/Checkbox.stories.js +1 -1
- package/dist/ui/Checkbox/Checkbox.stories.sources.d.ts +2 -2
- package/dist/ui/Checkbox/Checkbox.stories.sources.d.ts.map +1 -1
- package/dist/ui/Checkbox/Checkbox.stories.sources.js +2 -2
- package/dist/ui/Checkbox/Checkbox.utils.d.ts +5 -0
- package/dist/ui/Checkbox/Checkbox.utils.d.ts.map +1 -0
- package/dist/ui/Checkbox/Checkbox.utils.js +7 -0
- package/dist/ui/Checkbox/CheckboxContainer.d.ts +7 -2
- package/dist/ui/Checkbox/CheckboxContainer.d.ts.map +1 -1
- package/dist/ui/Checkbox/CheckboxContainer.js +4 -2
- package/dist/ui/Checkbox/CheckboxIndicator.d.ts +4 -1
- package/dist/ui/Checkbox/CheckboxIndicator.d.ts.map +1 -1
- package/dist/ui/Checkbox/CheckboxIndicator.js +5 -3
- package/dist/ui/Checkbox/CheckboxLabel.d.ts +4 -1
- package/dist/ui/Checkbox/CheckboxLabel.d.ts.map +1 -1
- package/dist/ui/Checkbox/CheckboxLabel.js +4 -2
- package/dist/ui/DataTable/DataTable.d.ts +27 -0
- package/dist/ui/DataTable/DataTable.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTable.js +58 -0
- package/dist/ui/DataTable/DataTable.stories.d.ts +205 -0
- package/dist/ui/DataTable/DataTable.stories.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTable.stories.js +499 -0
- package/dist/ui/DataTable/DataTable.stories.sources.d.ts +25 -0
- package/dist/ui/DataTable/DataTable.stories.sources.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTable.stories.sources.js +27 -0
- package/dist/ui/DataTable/DataTable.styles.d.ts +175 -0
- package/dist/ui/DataTable/DataTable.styles.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTable.styles.js +163 -0
- package/dist/ui/DataTable/DataTable.types.d.ts +20 -0
- package/dist/ui/DataTable/DataTable.types.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTable.types.js +1 -0
- package/dist/ui/DataTable/DataTableCell.d.ts +12 -0
- package/dist/ui/DataTable/DataTableCell.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTableCell.js +18 -0
- package/dist/ui/DataTable/DataTableFooter.d.ts +8 -0
- package/dist/ui/DataTable/DataTableFooter.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTableFooter.js +26 -0
- package/dist/ui/DataTable/DataTableHeaderCell.d.ts +9 -0
- package/dist/ui/DataTable/DataTableHeaderCell.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTableHeaderCell.js +12 -0
- package/dist/ui/DataTable/DataTablePagination.d.ts +12 -0
- package/dist/ui/DataTable/DataTablePagination.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTablePagination.js +78 -0
- package/dist/ui/DataTable/DataTableRow.d.ts +16 -0
- package/dist/ui/DataTable/DataTableRow.d.ts.map +1 -0
- package/dist/ui/DataTable/DataTableRow.js +26 -0
- package/dist/ui/DataTable/index.d.ts +5 -0
- package/dist/ui/DataTable/index.d.ts.map +1 -0
- package/dist/ui/DataTable/index.js +4 -0
- package/dist/ui/Header/Header.d.ts +4 -1
- package/dist/ui/Header/Header.d.ts.map +1 -1
- package/dist/ui/Header/Header.js +4 -3
- package/dist/ui/Header/Header.stories.d.ts +1 -1
- package/dist/ui/ListItem/ListItem.stories.d.ts +1 -0
- package/dist/ui/ListItem/ListItem.stories.d.ts.map +1 -1
- package/dist/ui/ListItem/ListItem.stories.js +4 -1
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -0
- package/package.json +15 -15
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useTheme } from '@alveole/theme';
|
|
3
|
+
import { format, formatDistanceToNowStrict } from 'date-fns';
|
|
4
|
+
import { fr } from 'date-fns/locale';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { Box, Typography } from '../../core';
|
|
7
|
+
import { ActionMenu } from '../ActionMenu';
|
|
8
|
+
import { Avatar } from '../Avatar';
|
|
9
|
+
import { Badge } from '../Badge';
|
|
10
|
+
import { Button } from '../Button';
|
|
11
|
+
import { EmptyState } from '../EmptyState';
|
|
12
|
+
import { LucideIcon } from '../LucideIcon';
|
|
13
|
+
import { Popover } from '../Popover';
|
|
14
|
+
import { Tag } from '../Tag';
|
|
15
|
+
import { DataTable } from './DataTable';
|
|
16
|
+
import { useStyles } from './DataTable.styles';
|
|
17
|
+
import { DataTableFooter } from './DataTableFooter';
|
|
18
|
+
import { DataTablePagination } from './DataTablePagination';
|
|
19
|
+
export default {
|
|
20
|
+
title: 'DataTable',
|
|
21
|
+
tags: ['ui'],
|
|
22
|
+
experimental: false,
|
|
23
|
+
figmaURL: 'https://www.figma.com/design/xJz8Z6vfrnZPKTtRbuT2W8/Alveole---Composants?node-id=1037-750',
|
|
24
|
+
description: `Tableau de données inspiré du [DataTable de Primer](https://primer.style/product/components/data-table/).
|
|
25
|
+
|
|
26
|
+
Comme chez Primer, l'API est déclarative : on décrit les \`columns\` (\`id\`, \`header\`, \`renderCell\`, \`align\`, \`sortable\`, \`width\`) et on fournit les \`data\`, le composant se charge de la mise en page (bordures, alternance des cellules, alignement).
|
|
27
|
+
|
|
28
|
+
- **Tri** : cliquer sur l'en-tête d'une colonne \`sortable\` fait cycler asc → desc → aucun tri. Le tri peut être piloté par le parent via \`sort\`/\`onSortChange\` (comme Primer, le tri des données reste à la charge du parent), ou laissé en gestion interne pour un simple affichage.
|
|
29
|
+
- **Sélection** : \`selectable\` ajoute une colonne de case à cocher avec sélection multiple et case "tout sélectionner" (à 3 états). Contrôlable via \`selectedKeys\`/\`onSelectionChange\`, sinon gérée en interne.
|
|
30
|
+
- **Pagination** : contrairement à Primer, le Figma Alveole intègre un pied de tableau avec compteur + pagination. On le fournit via le slot \`footer\`, avec les composants \`DataTableFooter\` et \`DataTablePagination\` exportés séparément — le tableau reste agnostique de la pagination (page côté serveur ou client).
|
|
31
|
+
- **Densité** : \`size\` (\`sm\` par défaut, \`md\`, \`lg\`) fait varier les paddings des cellules (en-tête, corps, colonne de sélection) sans changer la mise en page.
|
|
32
|
+
- **Beaucoup de colonnes** : l'en-tête et les lignes défilent horizontalement ensemble (via un \`ScrollView\` commun) dès que la somme des largeurs de colonnes dépasse l'espace disponible. Les colonnes sans \`width\` restent flexibles (elles se partagent l'espace restant) : pour garantir le défilement horizontal, donner une \`width\` fixe à chaque colonne, comme dans l'exemple \`ManyColumns\`.`,
|
|
33
|
+
shortDescription: 'Tableau de données avec tri, sélection multiple et pagination, inspiré de Primer.',
|
|
34
|
+
component: DataTable,
|
|
35
|
+
styleFn: useStyles,
|
|
36
|
+
};
|
|
37
|
+
const repositories = [
|
|
38
|
+
{
|
|
39
|
+
id: 'repo_1',
|
|
40
|
+
name: 'codeql-dca-worker',
|
|
41
|
+
description: 'Internal',
|
|
42
|
+
visibility: 'Internal',
|
|
43
|
+
updatedAt: '2 heures',
|
|
44
|
+
owner: 'Ana Martins',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'repo_2',
|
|
48
|
+
name: 'aegir',
|
|
49
|
+
description: 'Outils de build',
|
|
50
|
+
visibility: 'Public',
|
|
51
|
+
updatedAt: '3 heures',
|
|
52
|
+
owner: 'Joe Dalton',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'repo_3',
|
|
56
|
+
name: 'strapi',
|
|
57
|
+
description: 'CMS headless',
|
|
58
|
+
visibility: 'Public',
|
|
59
|
+
updatedAt: '8 heures',
|
|
60
|
+
owner: 'Peter Parker',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'repo_4',
|
|
64
|
+
name: 'codeql-ci-nightlies',
|
|
65
|
+
description: 'Analyse de sécurité',
|
|
66
|
+
visibility: 'Public',
|
|
67
|
+
updatedAt: 'hier',
|
|
68
|
+
owner: 'John Snow',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'repo_5',
|
|
72
|
+
name: 'dependabot-updates',
|
|
73
|
+
description: 'Mises à jour auto',
|
|
74
|
+
visibility: 'Public',
|
|
75
|
+
updatedAt: 'la semaine dernière',
|
|
76
|
+
owner: 'Ana Martins',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
const baseColumns = [
|
|
80
|
+
{
|
|
81
|
+
id: 'name',
|
|
82
|
+
header: 'Repository',
|
|
83
|
+
sortable: true,
|
|
84
|
+
renderCell: repo => _jsx(Typography, { children: repo.name }),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'visibility',
|
|
88
|
+
header: 'Visibilité',
|
|
89
|
+
sortable: true,
|
|
90
|
+
renderCell: repo => (_jsx(Badge, { variant: repo.visibility === 'Public' ? 'info' : 'default', size: "sm", children: repo.visibility })),
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'updatedAt',
|
|
94
|
+
header: 'Mis à jour',
|
|
95
|
+
sortable: true,
|
|
96
|
+
renderCell: repo => _jsx(Typography, { children: repo.updatedAt }),
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
export const Default = () => _jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id });
|
|
100
|
+
export const WithSelection = () => (_jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id, selectable: true }));
|
|
101
|
+
export const Sizes = () => (_jsxs(Box, { display: "flex", flexDirection: "column", gap: '4W', children: [_jsxs(Box, { display: "flex", flexDirection: "column", gap: '1V', children: [_jsx(Typography, { style: { fontWeight: 600 }, children: "sm (d\u00E9faut)" }), _jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id, selectable: true, size: "sm" })] }), _jsxs(Box, { display: "flex", flexDirection: "column", gap: '1V', children: [_jsx(Typography, { style: { fontWeight: 600 }, children: "md" }), _jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id, selectable: true, size: "md" })] }), _jsxs(Box, { display: "flex", flexDirection: "column", gap: '1V', children: [_jsx(Typography, { style: { fontWeight: 600 }, children: "lg" }), _jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id, selectable: true, size: "lg" })] })] }));
|
|
102
|
+
const repositoriesDetailed = [
|
|
103
|
+
{
|
|
104
|
+
id: 'repo_1',
|
|
105
|
+
name: 'codeql-dca-worker',
|
|
106
|
+
description: 'Internal',
|
|
107
|
+
visibility: 'Internal',
|
|
108
|
+
updatedAt: '2 heures',
|
|
109
|
+
owner: 'Ana Martins',
|
|
110
|
+
language: 'TypeScript',
|
|
111
|
+
stars: 128,
|
|
112
|
+
forks: 12,
|
|
113
|
+
openIssues: 4,
|
|
114
|
+
pullRequests: 2,
|
|
115
|
+
lastCommit: 'a1b2c3d',
|
|
116
|
+
ciStatus: 'success',
|
|
117
|
+
coverage: '92%',
|
|
118
|
+
license: 'MIT',
|
|
119
|
+
size: '4.2 Mo',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'repo_2',
|
|
123
|
+
name: 'aegir',
|
|
124
|
+
description: 'Outils de build',
|
|
125
|
+
visibility: 'Public',
|
|
126
|
+
updatedAt: '3 heures',
|
|
127
|
+
owner: 'Joe Dalton',
|
|
128
|
+
language: 'JavaScript',
|
|
129
|
+
stars: 1042,
|
|
130
|
+
forks: 87,
|
|
131
|
+
openIssues: 21,
|
|
132
|
+
pullRequests: 6,
|
|
133
|
+
lastCommit: 'e4f5g6h',
|
|
134
|
+
ciStatus: 'success',
|
|
135
|
+
coverage: '78%',
|
|
136
|
+
license: 'Apache-2.0',
|
|
137
|
+
size: '12.8 Mo',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: 'repo_3',
|
|
141
|
+
name: 'strapi',
|
|
142
|
+
description: 'CMS headless',
|
|
143
|
+
visibility: 'Public',
|
|
144
|
+
updatedAt: '8 heures',
|
|
145
|
+
owner: 'Peter Parker',
|
|
146
|
+
language: 'JavaScript',
|
|
147
|
+
stars: 58210,
|
|
148
|
+
forks: 7420,
|
|
149
|
+
openIssues: 312,
|
|
150
|
+
pullRequests: 48,
|
|
151
|
+
lastCommit: 'i7j8k9l',
|
|
152
|
+
ciStatus: 'failure',
|
|
153
|
+
coverage: '64%',
|
|
154
|
+
license: 'MIT',
|
|
155
|
+
size: '86.4 Mo',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: 'repo_4',
|
|
159
|
+
name: 'codeql-ci-nightlies',
|
|
160
|
+
description: 'Analyse de sécurité',
|
|
161
|
+
visibility: 'Public',
|
|
162
|
+
updatedAt: 'hier',
|
|
163
|
+
owner: 'John Snow',
|
|
164
|
+
language: 'YAML',
|
|
165
|
+
stars: 34,
|
|
166
|
+
forks: 3,
|
|
167
|
+
openIssues: 1,
|
|
168
|
+
pullRequests: 0,
|
|
169
|
+
lastCommit: 'm1n2o3p',
|
|
170
|
+
ciStatus: 'pending',
|
|
171
|
+
coverage: '—',
|
|
172
|
+
license: 'MIT',
|
|
173
|
+
size: '0.8 Mo',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: 'repo_5',
|
|
177
|
+
name: 'dependabot-updates',
|
|
178
|
+
description: 'Mises à jour auto',
|
|
179
|
+
visibility: 'Public',
|
|
180
|
+
updatedAt: 'la semaine dernière',
|
|
181
|
+
owner: 'Ana Martins',
|
|
182
|
+
language: 'Ruby',
|
|
183
|
+
stars: 210,
|
|
184
|
+
forks: 18,
|
|
185
|
+
openIssues: 9,
|
|
186
|
+
pullRequests: 3,
|
|
187
|
+
lastCommit: 'q4r5s6t',
|
|
188
|
+
ciStatus: 'success',
|
|
189
|
+
coverage: '85%',
|
|
190
|
+
license: 'BSD-3-Clause',
|
|
191
|
+
size: '2.1 Mo',
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
const ciStatusLabel = {
|
|
195
|
+
success: 'Succès',
|
|
196
|
+
failure: 'Échec',
|
|
197
|
+
pending: 'En cours',
|
|
198
|
+
};
|
|
199
|
+
const ciStatusVariant = {
|
|
200
|
+
success: 'success',
|
|
201
|
+
failure: 'error',
|
|
202
|
+
pending: 'warning',
|
|
203
|
+
};
|
|
204
|
+
const manyColumns = [
|
|
205
|
+
{
|
|
206
|
+
id: 'name',
|
|
207
|
+
header: 'Repository',
|
|
208
|
+
width: 200,
|
|
209
|
+
renderCell: repo => _jsx(Typography, { children: repo.name }),
|
|
210
|
+
},
|
|
211
|
+
{ id: 'owner', header: 'Propriétaire', width: 140, renderCell: repo => _jsx(Typography, { children: repo.owner }) },
|
|
212
|
+
{
|
|
213
|
+
id: 'visibility',
|
|
214
|
+
header: 'Visibilité',
|
|
215
|
+
width: 110,
|
|
216
|
+
renderCell: repo => (_jsx(Badge, { variant: repo.visibility === 'Public' ? 'info' : 'default', size: "sm", children: repo.visibility })),
|
|
217
|
+
},
|
|
218
|
+
{ id: 'language', header: 'Langage', width: 110, renderCell: repo => _jsx(Typography, { children: repo.language }) },
|
|
219
|
+
{
|
|
220
|
+
id: 'stars',
|
|
221
|
+
header: 'Étoiles',
|
|
222
|
+
width: 100,
|
|
223
|
+
align: 'end',
|
|
224
|
+
sortable: true,
|
|
225
|
+
renderCell: repo => _jsx(Typography, { children: repo.stars.toLocaleString('fr-FR') }),
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
id: 'forks',
|
|
229
|
+
header: 'Forks',
|
|
230
|
+
width: 90,
|
|
231
|
+
align: 'end',
|
|
232
|
+
sortable: true,
|
|
233
|
+
renderCell: repo => _jsx(Typography, { children: repo.forks.toLocaleString('fr-FR') }),
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
id: 'openIssues',
|
|
237
|
+
header: 'Issues ouvertes',
|
|
238
|
+
width: 130,
|
|
239
|
+
align: 'end',
|
|
240
|
+
renderCell: repo => _jsx(Typography, { children: repo.openIssues }),
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: 'pullRequests',
|
|
244
|
+
header: 'Pull requests',
|
|
245
|
+
width: 130,
|
|
246
|
+
align: 'end',
|
|
247
|
+
renderCell: repo => _jsx(Typography, { children: repo.pullRequests }),
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
id: 'ciStatus',
|
|
251
|
+
header: 'CI',
|
|
252
|
+
width: 110,
|
|
253
|
+
renderCell: repo => (_jsx(Badge, { variant: ciStatusVariant[repo.ciStatus], size: "sm", children: ciStatusLabel[repo.ciStatus] })),
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: 'coverage',
|
|
257
|
+
header: 'Couverture',
|
|
258
|
+
width: 110,
|
|
259
|
+
align: 'end',
|
|
260
|
+
renderCell: repo => _jsx(Typography, { children: repo.coverage }),
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: 'lastCommit',
|
|
264
|
+
header: 'Dernier commit',
|
|
265
|
+
width: 130,
|
|
266
|
+
renderCell: repo => (_jsxs(Box, { display: "flex", flexDirection: "row", gap: '1V', style: { alignItems: 'center' }, children: [_jsx(LucideIcon, { name: "GitCommitHorizontal", size: "xs" }), _jsx(Typography, { style: { fontFamily: 'monospace' }, children: repo.lastCommit })] })),
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: 'updatedAt',
|
|
270
|
+
header: 'Mis à jour',
|
|
271
|
+
width: 150,
|
|
272
|
+
sortable: true,
|
|
273
|
+
renderCell: repo => _jsx(Typography, { children: repo.updatedAt }),
|
|
274
|
+
},
|
|
275
|
+
{ id: 'license', header: 'Licence', width: 130, renderCell: repo => _jsx(Typography, { children: repo.license }) },
|
|
276
|
+
{ id: 'size', header: 'Taille', width: 100, align: 'end', renderCell: repo => _jsx(Typography, { children: repo.size }) },
|
|
277
|
+
];
|
|
278
|
+
export const ManyColumns = () => (_jsx(DataTable, { data: repositoriesDetailed, columns: manyColumns, keyExtractor: repo => repo.id, selectable: true }));
|
|
279
|
+
export const WithSorting = () => {
|
|
280
|
+
const [sort, setSort] = React.useState({ columnId: 'updatedAt', direction: 'desc' });
|
|
281
|
+
const sortedData = React.useMemo(() => {
|
|
282
|
+
if (!sort)
|
|
283
|
+
return repositories;
|
|
284
|
+
const sorted = [...repositories].sort((a, b) => {
|
|
285
|
+
const left = a[sort.columnId];
|
|
286
|
+
const right = b[sort.columnId];
|
|
287
|
+
return String(left).localeCompare(String(right));
|
|
288
|
+
});
|
|
289
|
+
return sort.direction === 'asc' ? sorted : sorted.reverse();
|
|
290
|
+
}, [sort]);
|
|
291
|
+
return (_jsx(DataTable, { data: sortedData, columns: baseColumns, keyExtractor: repo => repo.id, sort: sort, onSortChange: setSort }));
|
|
292
|
+
};
|
|
293
|
+
export const WithCustomCells = () => {
|
|
294
|
+
const columns = [
|
|
295
|
+
{
|
|
296
|
+
id: 'name',
|
|
297
|
+
header: 'Repository',
|
|
298
|
+
renderCell: repo => (_jsxs(_Fragment, { children: [_jsx(Avatar, { size: "xs", fallbackText: repo.owner }), _jsx(Typography, { style: { marginLeft: 8 }, children: repo.name })] })),
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
id: 'owner',
|
|
302
|
+
header: 'Propriétaire',
|
|
303
|
+
renderCell: repo => _jsx(Typography, { children: repo.owner }),
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'description',
|
|
307
|
+
header: 'Description',
|
|
308
|
+
renderCell: repo => _jsx(Typography, { children: repo.description }),
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
id: 'visibility',
|
|
312
|
+
header: 'Visibilité',
|
|
313
|
+
align: 'end',
|
|
314
|
+
renderCell: repo => (_jsx(Badge, { variant: repo.visibility === 'Public' ? 'info' : 'default', size: "sm", children: repo.visibility })),
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
return _jsx(DataTable, { data: repositories, columns: columns, keyExtractor: repo => repo.id });
|
|
318
|
+
};
|
|
319
|
+
export const WithoutHeader = () => (_jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id, hideHeader: true }));
|
|
320
|
+
export const WithPagination = () => {
|
|
321
|
+
const [page, setPage] = React.useState(1);
|
|
322
|
+
return (_jsx(DataTable, { data: repositories, columns: baseColumns, keyExtractor: repo => repo.id, footer: _jsx(DataTableFooter, { counter: "1-5 sur 48", children: _jsx(DataTablePagination, { page: page, pageCount: 10, onPageChange: setPage }) }) }));
|
|
323
|
+
};
|
|
324
|
+
const deployments = [
|
|
325
|
+
{
|
|
326
|
+
id: 'd1',
|
|
327
|
+
message: 'Bump follow-redirects from 1.15.9 to 1.16.0',
|
|
328
|
+
status: 'error',
|
|
329
|
+
duration: '1m 51s',
|
|
330
|
+
environment: 'preview',
|
|
331
|
+
commit: 'f3c020f',
|
|
332
|
+
source: 'dependabot/npm_and_yarn/follow-redirects…',
|
|
333
|
+
date: new Date('2026-07-15T14:32:00Z'),
|
|
334
|
+
author: 'dependabot',
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
id: 'd2',
|
|
338
|
+
message: 'Bump axios from 1.8.4 to 1.15.0',
|
|
339
|
+
status: 'error',
|
|
340
|
+
duration: '1m 51s',
|
|
341
|
+
environment: 'preview',
|
|
342
|
+
commit: 'f0e960b',
|
|
343
|
+
source: 'dependabot/npm_and_yarn/axios-1.15.0',
|
|
344
|
+
date: new Date('2026-07-11T09:12:00Z'),
|
|
345
|
+
author: 'dependabot',
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
id: 'd3',
|
|
349
|
+
message: 'Bump serialize-javascript et terser-webpack-plugin',
|
|
350
|
+
status: 'error',
|
|
351
|
+
duration: '1m 43s',
|
|
352
|
+
environment: 'preview',
|
|
353
|
+
commit: '638473a',
|
|
354
|
+
source: 'dependabot/npm_and_yarn/multi-0d13b2d87f',
|
|
355
|
+
date: new Date('2026-06-29T18:47:00Z'),
|
|
356
|
+
author: 'dependabot',
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: 'd4',
|
|
360
|
+
message: 'Bump yaml',
|
|
361
|
+
status: 'error',
|
|
362
|
+
duration: '1m 55s',
|
|
363
|
+
environment: 'preview',
|
|
364
|
+
commit: 'd59cb81',
|
|
365
|
+
source: 'dependabot/npm_and_yarn/multi-c136cad177',
|
|
366
|
+
date: new Date('2026-06-26T07:58:00Z'),
|
|
367
|
+
author: 'dependabot',
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 'd5',
|
|
371
|
+
message: '✨ Merge pull request #9 — mdast-util-to-hast 13.2.1',
|
|
372
|
+
status: 'ready',
|
|
373
|
+
duration: '2m 1s',
|
|
374
|
+
environment: 'production',
|
|
375
|
+
promoted: true,
|
|
376
|
+
commit: '9d71b6c',
|
|
377
|
+
source: 'main',
|
|
378
|
+
date: new Date('2025-12-02T14:04:32Z'),
|
|
379
|
+
author: 'cprodhomme',
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
id: 'd6',
|
|
383
|
+
message: 'Bump mdast-util-to-hast from 13.2.0 à 13.2.1',
|
|
384
|
+
status: 'ready',
|
|
385
|
+
duration: '1m 58s',
|
|
386
|
+
environment: 'preview',
|
|
387
|
+
commit: '9bdc055',
|
|
388
|
+
source: 'dependabot/npm_and_yarn/mdast-util-to-ha…',
|
|
389
|
+
date: new Date('2025-12-02T13:58:00Z'),
|
|
390
|
+
author: 'dependabot',
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
id: 'd7',
|
|
394
|
+
message: '🎨 Ajoute un style sur le blog',
|
|
395
|
+
status: 'ready',
|
|
396
|
+
duration: '51s',
|
|
397
|
+
environment: 'production',
|
|
398
|
+
commit: '7c70351',
|
|
399
|
+
source: 'main',
|
|
400
|
+
date: new Date('2026-04-18T10:21:00Z'),
|
|
401
|
+
author: 'cprodhomme',
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
id: 'd8',
|
|
405
|
+
message: '✨ feat(posts): add metaDescription field',
|
|
406
|
+
status: 'ready',
|
|
407
|
+
duration: '49s',
|
|
408
|
+
environment: 'production',
|
|
409
|
+
commit: 'ff3f424',
|
|
410
|
+
source: 'main',
|
|
411
|
+
date: new Date('2026-04-18T09:47:00Z'),
|
|
412
|
+
author: 'cprodhomme',
|
|
413
|
+
},
|
|
414
|
+
];
|
|
415
|
+
const localTimeZoneLabel = (() => {
|
|
416
|
+
const offsetMinutes = -new Date().getTimezoneOffset();
|
|
417
|
+
const sign = offsetMinutes >= 0 ? '+' : '-';
|
|
418
|
+
return `GMT${sign}${Math.abs(offsetMinutes) / 60}`;
|
|
419
|
+
})();
|
|
420
|
+
const formatTimestamp = (date, timeZone) => new Intl.DateTimeFormat('fr-FR', { dateStyle: 'long', timeStyle: 'medium', timeZone }).format(date);
|
|
421
|
+
const DeploymentDateCell = ({ deployment }) => {
|
|
422
|
+
const [open, setOpen] = React.useState(false);
|
|
423
|
+
const { text, color } = useTheme();
|
|
424
|
+
return (_jsx(Popover, { placement: "left", open: open, setOpen: setOpen, renderTrigger: () => (_jsx(Box, { onHoverIn: () => setOpen(true), onHoverOut: () => setOpen(false), children: _jsx(Typography, { style: { ...text['Corps de texte'].XS.Regular, color: color.light.text['mention-grey'] }, children: format(deployment.date, 'd MMM', { locale: fr }) }) })), children: _jsxs(Box, { display: "flex", flexDirection: "column", gap: '1W', style: { minWidth: 260 }, onHoverIn: () => setOpen(true), onHoverOut: () => setOpen(false), children: [_jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: formatDistanceToNowStrict(deployment.date, { locale: fr, addSuffix: true }) }), _jsxs(Box, { display: "flex", flexDirection: "row", gap: '1W', justify: "space-between", style: { alignItems: 'center' }, children: [_jsx(Tag, { color: "default", size: "sm", children: "UTC" }), _jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: formatTimestamp(deployment.date, 'UTC') })] }), _jsxs(Box, { display: "flex", flexDirection: "row", gap: '1W', justify: "space-between", style: { alignItems: 'center' }, children: [_jsx(Tag, { color: "default", size: "sm", children: localTimeZoneLabel }), _jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: formatTimestamp(deployment.date) })] })] }) }));
|
|
425
|
+
};
|
|
426
|
+
const DeploymentActionsCell = () => {
|
|
427
|
+
const [open, setOpen] = React.useState(false);
|
|
428
|
+
return (_jsx(Box, { p: '1V', children: _jsxs(ActionMenu, { placement: "bottom-end", open: open, setOpen: setOpen, renderTrigger: () => (_jsx(Button, { variant: "tertiary", size: "sm", startIcon: "MoreHorizontal", accessibilityLabel: "Actions du d\u00E9ploiement" })), children: [_jsx(ActionMenu.Item, { title: "Voir les d\u00E9tails", icon: "Eye" }), _jsx(ActionMenu.Item, { title: "Red\u00E9ployer", icon: "RefreshCw" }), _jsx(ActionMenu.Item, { title: "Copier l'URL", icon: "Link" }), _jsx(ActionMenu.Item, { title: "Supprimer", icon: "Trash" })] }) }));
|
|
429
|
+
};
|
|
430
|
+
/**
|
|
431
|
+
* Reproduction de la vue "Deployments" de Vercel avec nos composants : `Tag` pour les pastilles
|
|
432
|
+
* d'environnement, `Badge` pour le statut, `Avatar` pour l'auteur, `ActionMenu` pour le menu contextuel
|
|
433
|
+
* "..." de chaque ligne, et `Popover` sur la date pour afficher le détail (temps relatif + horodatage
|
|
434
|
+
* UTC et fuseau local), comme chez Vercel. Le pied de page est ici un simple slot `footer` (pas
|
|
435
|
+
* `DataTableFooter`, qui sert au duo compteur+pagination) : un bouton pleine largeur, puis une note de
|
|
436
|
+
* rétention accompagnée d'une action.
|
|
437
|
+
*/
|
|
438
|
+
export const AsDeploymentList = () => {
|
|
439
|
+
const { text, color } = useTheme();
|
|
440
|
+
const deploymentColumns = [
|
|
441
|
+
{
|
|
442
|
+
id: 'message',
|
|
443
|
+
header: 'Déploiement',
|
|
444
|
+
width: 400,
|
|
445
|
+
renderCell: deployment => _jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: deployment.message }),
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
id: 'status',
|
|
449
|
+
header: 'Statut',
|
|
450
|
+
width: 140,
|
|
451
|
+
renderCell: deployment => (_jsxs(Box, { display: "flex", flexDirection: "row", gap: '1W', style: { alignItems: 'center' }, children: [_jsx(Badge, { variant: deployment.status === 'error' ? 'error' : 'success', size: "sm", children: deployment.status === 'error' ? 'Error' : 'Ready' }), _jsx(Typography, { style: { ...text['Corps de texte'].SM.Regular, color: color.light.text['mention-grey'] }, children: deployment.duration })] })),
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
id: 'environment',
|
|
455
|
+
header: 'Environnement',
|
|
456
|
+
width: 100,
|
|
457
|
+
renderCell: deployment => (_jsx(Tag, { color: deployment.promoted ? 'action' : 'default', size: "sm", children: deployment.environment === 'production' ? 'Production' : 'Preview' })),
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
id: 'commit',
|
|
461
|
+
header: 'Commit',
|
|
462
|
+
width: 110,
|
|
463
|
+
renderCell: deployment => (_jsxs(Box, { display: "flex", flexDirection: "row", gap: '1V', style: { alignItems: 'center' }, children: [_jsx(LucideIcon, { name: "GitCommitHorizontal", size: "sm" }), _jsx(Typography, { style: { ...text['Corps de texte'].SM.Regular, fontFamily: 'monospace' }, children: deployment.commit })] })),
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
id: 'source',
|
|
467
|
+
header: 'Source',
|
|
468
|
+
width: 353,
|
|
469
|
+
renderCell: deployment => (_jsxs(Box, { display: "flex", flexDirection: "row", gap: '1V', style: { alignItems: 'center', minWidth: 0 }, children: [_jsx(LucideIcon, { name: "GitBranch", size: "sm" }), _jsx(Typography, { style: {
|
|
470
|
+
...text['Corps de texte'].SM.Regular,
|
|
471
|
+
whiteSpace: 'nowrap',
|
|
472
|
+
overflow: 'hidden',
|
|
473
|
+
textOverflow: 'ellipsis',
|
|
474
|
+
}, children: deployment.source })] })),
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
id: 'date',
|
|
478
|
+
header: 'Date',
|
|
479
|
+
width: 70,
|
|
480
|
+
renderCell: deployment => _jsx(DeploymentDateCell, { deployment: deployment }),
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
id: 'author',
|
|
484
|
+
header: '',
|
|
485
|
+
width: 56,
|
|
486
|
+
renderCell: deployment => _jsx(Avatar, { size: "sm", fallbackText: deployment.author }),
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
id: 'actions',
|
|
490
|
+
header: '',
|
|
491
|
+
width: 40,
|
|
492
|
+
align: 'end',
|
|
493
|
+
renderCell: () => _jsx(DeploymentActionsCell, {}),
|
|
494
|
+
},
|
|
495
|
+
];
|
|
496
|
+
return (_jsxs(Box, { display: "flex", flexDirection: "column", gap: '3V', children: [_jsx(Typography, { style: { fontSize: 20, fontWeight: 700 }, children: "Deployments" }), _jsx(DataTable, { size: "md", data: deployments, columns: deploymentColumns, keyExtractor: deployment => deployment.id, hideHeader: true }), _jsxs(Box, { display: "flex", flexDirection: "column", gap: "1W", children: [_jsx(Box, { children: _jsx(Button, { title: "Charger plus", variant: "secondary", size: "md", fullWidth: true }) }), _jsxs(Box, { display: "flex", flexDirection: "row", style: { alignItems: 'center', justifyContent: 'space-between' }, children: [_jsx(Typography, { style: { ...text['Corps de texte'].XS.Regular, color: color.light.text['mention-grey'] }, children: "La r\u00E9tention des d\u00E9ploiements est activ\u00E9e \u2014 certains seront supprim\u00E9s apr\u00E8s un d\u00E9lai." }), _jsx(Button, { title: "Voir les supprim\u00E9s", variant: "secondary", size: "sm" })] })] })] }));
|
|
497
|
+
};
|
|
498
|
+
export const Empty = () => (_jsx(DataTable, { data: [], columns: baseColumns, keyExtractor: repo => repo.id, renderNoContent: () => (_jsx(EmptyState, { title: "Aucun repository", description: "Cr\u00E9ez votre premier repository pour le voir appara\u00EEtre ici.", iconName: "FolderGit2" })) }));
|
|
499
|
+
export * as Sources from './DataTable.stories.sources';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const Default: () => string;
|
|
2
|
+
export declare const WithSelection: () => string;
|
|
3
|
+
export declare const Sizes: () => string;
|
|
4
|
+
export declare const ManyColumns: () => string;
|
|
5
|
+
export declare const WithSorting: () => string;
|
|
6
|
+
export declare const WithCustomCells: () => string;
|
|
7
|
+
export declare const WithoutHeader: () => string;
|
|
8
|
+
export declare const WithPagination: () => string;
|
|
9
|
+
export declare const AsDeploymentList: () => string;
|
|
10
|
+
export declare const Empty: () => string;
|
|
11
|
+
export declare const storySources: {
|
|
12
|
+
readonly Default: () => string;
|
|
13
|
+
readonly WithSelection: () => string;
|
|
14
|
+
readonly Sizes: () => string;
|
|
15
|
+
readonly ManyColumns: () => string;
|
|
16
|
+
readonly WithSorting: () => string;
|
|
17
|
+
readonly WithCustomCells: () => string;
|
|
18
|
+
readonly WithoutHeader: () => string;
|
|
19
|
+
readonly WithPagination: () => string;
|
|
20
|
+
readonly AsDeploymentList: () => string;
|
|
21
|
+
readonly Empty: () => string;
|
|
22
|
+
};
|
|
23
|
+
export type StorySourceName = keyof typeof storySources;
|
|
24
|
+
export declare const storyDescriptions: Partial<Record<StorySourceName, string>>;
|
|
25
|
+
//# sourceMappingURL=DataTable.stories.sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTable.stories.sources.d.ts","sourceRoot":"","sources":["../../../src/ui/DataTable/DataTable.stories.sources.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,cAA+H,CAAC;AAEpJ,eAAO,MAAM,aAAa,cAAwJ,CAAC;AAEnL,eAAO,MAAM,KAAK,cAA43B,CAAC;AAE/4B,eAAO,MAAM,WAAW,cAA8J,CAAC;AAEvL,eAAO,MAAM,WAAW,cAA2uB,CAAC;AAEpwB,eAAO,MAAM,eAAe,cAAg/B,CAAC;AAE7gC,eAAO,MAAM,aAAa,cAAwJ,CAAC;AAEnL,eAAO,MAAM,cAAc,cAAwa,CAAC;AAEpc,eAAO,MAAM,gBAAgB,cAA+vH,CAAC;AAE7xH,eAAO,MAAM,KAAK,cAA0W,CAAC;AAE7X,eAAO,MAAM,YAAY;;;;;;;;;;;CAWf,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,YAAY,CAAC;AAExD,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAEtE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// This file is generated. Do not edit manually.
|
|
2
|
+
// Source: src/ui/DataTable/DataTable.stories.tsx
|
|
3
|
+
export const Default = () => "export const Default = () => <DataTable data={repositories} columns={baseColumns} keyExtractor={repo => repo.id} />;";
|
|
4
|
+
export const WithSelection = () => "export const WithSelection = () => (\n <DataTable data={repositories} columns={baseColumns} keyExtractor={repo => repo.id} selectable />\n);";
|
|
5
|
+
export const Sizes = () => "export const Sizes = () => (\n <Box display=\"flex\" flexDirection=\"column\" gap={'4W'}>\n <Box display=\"flex\" flexDirection=\"column\" gap={'1V'}>\n <Typography style={{ fontWeight: 600 }}>sm (défaut)</Typography>\n <DataTable data={repositories} columns={baseColumns} keyExtractor={repo => repo.id} selectable size=\"sm\" />\n </Box>\n <Box display=\"flex\" flexDirection=\"column\" gap={'1V'}>\n <Typography style={{ fontWeight: 600 }}>md</Typography>\n <DataTable data={repositories} columns={baseColumns} keyExtractor={repo => repo.id} selectable size=\"md\" />\n </Box>\n <Box display=\"flex\" flexDirection=\"column\" gap={'1V'}>\n <Typography style={{ fontWeight: 600 }}>lg</Typography>\n <DataTable data={repositories} columns={baseColumns} keyExtractor={repo => repo.id} selectable size=\"lg\" />\n </Box>\n </Box>\n);";
|
|
6
|
+
export const ManyColumns = () => "export const ManyColumns = () => (\n <DataTable data={repositoriesDetailed} columns={manyColumns} keyExtractor={repo => repo.id} selectable />\n);";
|
|
7
|
+
export const WithSorting = () => "export const WithSorting = () => {\n const [sort, setSort] = React.useState<DataTableSort | null>({ columnId: 'updatedAt', direction: 'desc' });\n\n const sortedData = React.useMemo(() => {\n if (!sort) return repositories;\n const sorted = [...repositories].sort((a, b) => {\n const left = a[sort.columnId as keyof Repository];\n const right = b[sort.columnId as keyof Repository];\n return String(left).localeCompare(String(right));\n });\n return sort.direction === 'asc' ? sorted : sorted.reverse();\n }, [sort]);\n\n return (\n <DataTable\n data={sortedData}\n columns={baseColumns}\n keyExtractor={repo => repo.id}\n sort={sort}\n onSortChange={setSort}\n />\n );\n};";
|
|
8
|
+
export const WithCustomCells = () => "export const WithCustomCells = () => {\n const columns: DataTableColumn<Repository>[] = [\n {\n id: 'name',\n header: 'Repository',\n renderCell: repo => (\n <>\n <Avatar size=\"xs\" fallbackText={repo.owner} />\n <Typography style={{ marginLeft: 8 }}>{repo.name}</Typography>\n </>\n ),\n },\n {\n id: 'owner',\n header: 'Propriétaire',\n renderCell: repo => <Typography>{repo.owner}</Typography>,\n },\n {\n id: 'description',\n header: 'Description',\n renderCell: repo => <Typography>{repo.description}</Typography>,\n },\n {\n id: 'visibility',\n header: 'Visibilité',\n align: 'end',\n renderCell: repo => (\n <Badge variant={repo.visibility === 'Public' ? 'info' : 'default'} size=\"sm\">\n {repo.visibility}\n </Badge>\n ),\n },\n ];\n\n return <DataTable data={repositories} columns={columns} keyExtractor={repo => repo.id} />;\n};";
|
|
9
|
+
export const WithoutHeader = () => "export const WithoutHeader = () => (\n <DataTable data={repositories} columns={baseColumns} keyExtractor={repo => repo.id} hideHeader />\n);";
|
|
10
|
+
export const WithPagination = () => "export const WithPagination = () => {\n const [page, setPage] = React.useState(1);\n\n return (\n <DataTable\n data={repositories}\n columns={baseColumns}\n keyExtractor={repo => repo.id}\n footer={\n <DataTableFooter counter=\"1-5 sur 48\">\n <DataTablePagination page={page} pageCount={10} onPageChange={setPage} />\n </DataTableFooter>\n }\n />\n );\n};";
|
|
11
|
+
export const AsDeploymentList = () => "export const AsDeploymentList = () => {\n const { text, color } = useTheme();\n\n const deploymentColumns: DataTableColumn<Deployment>[] = [\n {\n id: 'message',\n header: 'Déploiement',\n width: 400,\n renderCell: deployment => <Typography style={text['Corps de texte'].SM.Regular}>{deployment.message}</Typography>,\n },\n {\n id: 'status',\n header: 'Statut',\n width: 140,\n renderCell: deployment => (\n <Box display=\"flex\" flexDirection=\"row\" gap={'1W'} style={{ alignItems: 'center' }}>\n <Badge variant={deployment.status === 'error' ? 'error' : 'success'} size=\"sm\">\n {deployment.status === 'error' ? 'Error' : 'Ready'}\n </Badge>\n <Typography style={{ ...text['Corps de texte'].SM.Regular, color: color.light.text['mention-grey'] }}>\n {deployment.duration}\n </Typography>\n </Box>\n ),\n },\n {\n id: 'environment',\n header: 'Environnement',\n width: 100,\n renderCell: deployment => (\n <Tag color={deployment.promoted ? 'action' : 'default'} size=\"sm\">\n {deployment.environment === 'production' ? 'Production' : 'Preview'}\n </Tag>\n ),\n },\n {\n id: 'commit',\n header: 'Commit',\n width: 110,\n renderCell: deployment => (\n <Box display=\"flex\" flexDirection=\"row\" gap={'1V'} style={{ alignItems: 'center' }}>\n <LucideIcon name=\"GitCommitHorizontal\" size=\"sm\" />\n <Typography style={{ ...text['Corps de texte'].SM.Regular, fontFamily: 'monospace' }}>\n {deployment.commit}\n </Typography>\n </Box>\n ),\n },\n {\n id: 'source',\n header: 'Source',\n width: 353,\n renderCell: deployment => (\n <Box display=\"flex\" flexDirection=\"row\" gap={'1V'} style={{ alignItems: 'center', minWidth: 0 }}>\n <LucideIcon name=\"GitBranch\" size=\"sm\" />\n <Typography\n style={{\n ...text['Corps de texte'].SM.Regular,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {deployment.source}\n </Typography>\n </Box>\n ),\n },\n {\n id: 'date',\n header: 'Date',\n width: 70,\n renderCell: deployment => <DeploymentDateCell deployment={deployment} />,\n },\n {\n id: 'author',\n header: '',\n width: 56,\n renderCell: deployment => <Avatar size=\"sm\" fallbackText={deployment.author} />,\n },\n {\n id: 'actions',\n header: '',\n width: 40,\n align: 'end',\n renderCell: () => <DeploymentActionsCell />,\n },\n ];\n\n return (\n <Box display=\"flex\" flexDirection=\"column\" gap={'3V'}>\n <Typography style={{ fontSize: 20, fontWeight: 700 }}>Deployments</Typography>\n\n <DataTable\n size=\"md\"\n data={deployments}\n columns={deploymentColumns}\n keyExtractor={deployment => deployment.id}\n hideHeader\n />\n\n <Box display=\"flex\" flexDirection=\"column\" gap=\"1W\">\n <Box>\n <Button title=\"Charger plus\" variant=\"secondary\" size=\"md\" fullWidth />\n </Box>\n <Box display=\"flex\" flexDirection=\"row\" style={{ alignItems: 'center', justifyContent: 'space-between' }}>\n <Typography style={{ ...text['Corps de texte'].XS.Regular, color: color.light.text['mention-grey'] }}>\n La rétention des déploiements est activée — certains seront supprimés après un délai.\n </Typography>\n <Button title=\"Voir les supprimés\" variant=\"secondary\" size=\"sm\" />\n </Box>\n </Box>\n </Box>\n );\n};";
|
|
12
|
+
export const Empty = () => "export const Empty = () => (\n <DataTable\n data={[]}\n columns={baseColumns}\n keyExtractor={repo => repo.id}\n renderNoContent={() => (\n <EmptyState\n title=\"Aucun repository\"\n description=\"Créez votre premier repository pour le voir apparaître ici.\"\n iconName=\"FolderGit2\"\n />\n )}\n />\n);";
|
|
13
|
+
export const storySources = {
|
|
14
|
+
Default,
|
|
15
|
+
WithSelection,
|
|
16
|
+
Sizes,
|
|
17
|
+
ManyColumns,
|
|
18
|
+
WithSorting,
|
|
19
|
+
WithCustomCells,
|
|
20
|
+
WithoutHeader,
|
|
21
|
+
WithPagination,
|
|
22
|
+
AsDeploymentList,
|
|
23
|
+
Empty,
|
|
24
|
+
};
|
|
25
|
+
export const storyDescriptions = {
|
|
26
|
+
AsDeploymentList: "Reproduction de la vue \"Deployments\" de Vercel avec nos composants : `Tag` pour les pastilles\nd'environnement, `Badge` pour le statut, `Avatar` pour l'auteur, `ActionMenu` pour le menu contextuel\n\"...\" de chaque ligne, et `Popover` sur la date pour afficher le détail (temps relatif + horodatage\nUTC et fuseau local), comme chez Vercel. Le pied de page est ici un simple slot `footer` (pas\n`DataTableFooter`, qui sert au duo compteur+pagination) : un bouton pleine largeur, puis une note de\nrétention accompagnée d'une action.",
|
|
27
|
+
};
|