@bundle-stats/ui 4.16.0-beta.0 → 4.16.0-beta.1
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/lib/assets/icons.svg +6 -1
- package/lib/assets/icons.svg.js +3 -0
- package/lib/assets/icons.svg.js.map +1 -1
- package/lib/components/bundle-assets/bundle-assets.js +9 -2
- package/lib/components/bundle-assets/bundle-assets.js.map +1 -1
- package/lib/components/bundle-assets-totals/bundle-assets-totals.js +21 -9
- package/lib/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
- package/lib/components/bundle-modules/bundle-modules.js +9 -2
- package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
- package/lib/components/bundle-packages/bundle-packages.js +9 -2
- package/lib/components/bundle-packages/bundle-packages.js.map +1 -1
- package/lib/components/entry-info/entry-info.js +2 -2
- package/lib/components/entry-info/entry-info.js.map +1 -1
- package/lib/components/metrics-table-export/index.js +18 -0
- package/lib/components/metrics-table-export/index.js.map +1 -0
- package/lib/components/metrics-table-export/metrics-table-export.js +86 -0
- package/lib/components/metrics-table-export/metrics-table-export.js.map +1 -0
- package/lib/components/metrics-table-export/metrics-table-export.module.css +8 -0
- package/lib/components/metrics-table-options/index.js.map +1 -1
- package/lib/components/metrics-table-options/metrics-table-options.js +7 -15
- package/lib/components/metrics-table-options/metrics-table-options.js.map +1 -1
- package/lib/components/preview-source/index.js +18 -0
- package/lib/components/preview-source/index.js.map +1 -0
- package/lib/components/preview-source/preview-source.js +25 -0
- package/lib/components/preview-source/preview-source.js.map +1 -0
- package/lib/components/preview-source/preview-source.module.css +28 -0
- package/lib/css/variables.css +1 -0
- package/lib/i18n.js +3 -0
- package/lib/i18n.js.map +1 -1
- package/lib/ui/button/button.js +2 -1
- package/lib/ui/button/button.js.map +1 -1
- package/lib/ui/copy-to-clipboard/copy-to-clipboard.js +2 -6
- package/lib/ui/copy-to-clipboard/copy-to-clipboard.js.map +1 -1
- package/lib/ui/copy-to-clipboard/copy-to-clipboard.module.css +5 -48
- package/lib/ui/dialog/dialog.js +27 -0
- package/lib/ui/dialog/dialog.js.map +1 -0
- package/lib/ui/dialog/dialog.module.css +89 -0
- package/lib/ui/dialog/index.js +18 -0
- package/lib/ui/dialog/index.js.map +1 -0
- package/lib/ui/icon/icon.js +1 -0
- package/lib/ui/icon/icon.js.map +1 -1
- package/lib/ui/index.js +5 -1
- package/lib/ui/index.js.map +1 -1
- package/lib/ui/tabs/tabs.js +2 -2
- package/lib/ui/tabs/tabs.js.map +1 -1
- package/lib/ui/textarea/index.js +18 -0
- package/lib/ui/textarea/index.js.map +1 -0
- package/lib/ui/textarea/textarea.js +16 -0
- package/lib/ui/textarea/textarea.js.map +1 -0
- package/lib/ui/textarea/textarea.module.css +64 -0
- package/lib-esm/assets/icons.svg +6 -1
- package/lib-esm/assets/icons.svg.js +3 -0
- package/lib-esm/assets/icons.svg.js.map +1 -1
- package/lib-esm/components/bundle-assets/bundle-assets.js +9 -2
- package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
- package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js +21 -9
- package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
- package/lib-esm/components/bundle-modules/bundle-modules.js +9 -2
- package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
- package/lib-esm/components/bundle-packages/bundle-packages.js +9 -2
- package/lib-esm/components/bundle-packages/bundle-packages.js.map +1 -1
- package/lib-esm/components/entry-info/entry-info.js +2 -2
- package/lib-esm/components/entry-info/entry-info.js.map +1 -1
- package/lib-esm/components/metrics-table-export/index.js +2 -0
- package/lib-esm/components/metrics-table-export/index.js.map +1 -0
- package/lib-esm/components/metrics-table-export/metrics-table-export.js +61 -0
- package/lib-esm/components/metrics-table-export/metrics-table-export.js.map +1 -0
- package/lib-esm/components/metrics-table-export/metrics-table-export.module.css +8 -0
- package/lib-esm/components/metrics-table-options/index.js.map +1 -1
- package/lib-esm/components/metrics-table-options/metrics-table-options.js +7 -15
- package/lib-esm/components/metrics-table-options/metrics-table-options.js.map +1 -1
- package/lib-esm/components/preview-source/index.js +2 -0
- package/lib-esm/components/preview-source/index.js.map +1 -0
- package/lib-esm/components/preview-source/preview-source.js +18 -0
- package/lib-esm/components/preview-source/preview-source.js.map +1 -0
- package/lib-esm/components/preview-source/preview-source.module.css +28 -0
- package/lib-esm/css/variables.css +1 -0
- package/lib-esm/i18n.js +3 -0
- package/lib-esm/i18n.js.map +1 -1
- package/lib-esm/ui/button/button.js +1 -0
- package/lib-esm/ui/button/button.js.map +1 -1
- package/lib-esm/ui/copy-to-clipboard/copy-to-clipboard.js +2 -6
- package/lib-esm/ui/copy-to-clipboard/copy-to-clipboard.js.map +1 -1
- package/lib-esm/ui/copy-to-clipboard/copy-to-clipboard.module.css +5 -48
- package/lib-esm/ui/dialog/dialog.js +19 -0
- package/lib-esm/ui/dialog/dialog.js.map +1 -0
- package/lib-esm/ui/dialog/dialog.module.css +89 -0
- package/lib-esm/ui/dialog/index.js +2 -0
- package/lib-esm/ui/dialog/index.js.map +1 -0
- package/lib-esm/ui/icon/icon.js +1 -0
- package/lib-esm/ui/icon/icon.js.map +1 -1
- package/lib-esm/ui/index.js +2 -0
- package/lib-esm/ui/index.js.map +1 -1
- package/lib-esm/ui/tabs/tabs.js +2 -2
- package/lib-esm/ui/tabs/tabs.js.map +1 -1
- package/lib-esm/ui/textarea/index.js +2 -0
- package/lib-esm/ui/textarea/index.js.map +1 -0
- package/lib-esm/ui/textarea/textarea.js +9 -0
- package/lib-esm/ui/textarea/textarea.js.map +1 -0
- package/lib-esm/ui/textarea/textarea.module.css +64 -0
- package/package.json +11 -11
- package/src/assets/icons/download.svg +4 -0
- package/src/assets/icons.svg +6 -1
- package/src/assets/icons.svg.jsx +9 -0
- package/src/components/bundle-assets/bundle-assets.jsx +15 -2
- package/src/components/bundle-assets-totals/bundle-assets-totals.jsx +54 -35
- package/src/components/bundle-modules/bundle-modules.tsx +15 -2
- package/src/components/bundle-packages/bundle-packages.jsx +15 -2
- package/src/components/entry-info/entry-info.tsx +2 -2
- package/src/components/metrics-table-export/index.ts +1 -0
- package/src/components/metrics-table-export/metrics-table-export.module.css +8 -0
- package/src/components/metrics-table-export/metrics-table-export.stories.tsx +30 -0
- package/src/components/metrics-table-export/metrics-table-export.tsx +103 -0
- package/src/components/metrics-table-options/metrics-table-options.stories.tsx +22 -0
- package/src/components/metrics-table-options/metrics-table-options.tsx +25 -0
- package/src/components/preview-source/index.ts +1 -0
- package/src/components/preview-source/preview-source.module.css +28 -0
- package/src/components/preview-source/preview-source.stories.tsx +35 -0
- package/src/components/preview-source/preview-source.tsx +47 -0
- package/src/css/variables.css +1 -0
- package/src/i18n.js +4 -0
- package/src/ui/button/button.tsx +2 -1
- package/src/ui/copy-to-clipboard/copy-to-clipboard.module.css +5 -48
- package/src/ui/copy-to-clipboard/copy-to-clipboard.tsx +4 -8
- package/src/ui/dialog/dialog.module.css +89 -0
- package/src/ui/dialog/dialog.stories.tsx +67 -0
- package/src/ui/dialog/dialog.tsx +62 -0
- package/src/ui/dialog/index.ts +1 -0
- package/src/ui/icon/icon.tsx +1 -0
- package/src/ui/index.js +2 -0
- package/src/ui/tabs/tabs.jsx +2 -2
- package/src/ui/textarea/index.ts +1 -0
- package/src/ui/textarea/textarea.module.css +64 -0
- package/src/ui/textarea/textarea.stories.tsx +37 -0
- package/src/ui/textarea/textarea.tsx +23 -0
- package/types/components/metrics-table-export/index.d.ts +1 -0
- package/types/components/metrics-table-export/metrics-table-export.d.ts +10 -0
- package/types/components/metrics-table-options/index.d.ts +1 -1
- package/types/components/metrics-table-options/metrics-table-options.d.ts +9 -17
- package/types/components/preview-source/index.d.ts +1 -0
- package/types/components/preview-source/preview-source.d.ts +8 -0
- package/types/i18n.d.ts +3 -0
- package/types/ui/button/button.d.ts +26 -0
- package/types/ui/dialog/dialog.d.ts +13 -0
- package/types/ui/dialog/index.d.ts +1 -0
- package/types/ui/icon/icon.d.ts +2 -0
- package/types/ui/index.d.ts +2 -0
- package/types/ui/tabs/tabs.d.ts +3 -3
- package/types/ui/textarea/index.d.ts +1 -0
- package/types/ui/textarea/textarea.d.ts +7 -0
- package/src/components/metrics-table-options/metrics-table-options.jsx +0 -30
- /package/src/components/metrics-table-options/{index.js → index.ts} +0 -0
|
@@ -19,6 +19,7 @@ import { useMetricsDisplayType } from '../../hooks/metrics-display-type';
|
|
|
19
19
|
import { Box } from '../../layout/box';
|
|
20
20
|
import { FlexStack } from '../../layout/flex-stack';
|
|
21
21
|
import { Stack } from '../../layout/stack';
|
|
22
|
+
import { Dialog, useDialogState } from '../../ui/dialog';
|
|
22
23
|
import { Icon } from '../../ui/icon';
|
|
23
24
|
import { InputSearch } from '../../ui/input-search';
|
|
24
25
|
import { FileName } from '../../ui/file-name';
|
|
@@ -32,6 +33,7 @@ import { AssetInfo } from '../asset-info';
|
|
|
32
33
|
import { AssetNotPredictive } from '../asset-not-predictive';
|
|
33
34
|
import { ComponentLink } from '../component-link';
|
|
34
35
|
import { MetricsTable } from '../metrics-table';
|
|
36
|
+
import { MetricsTableExport } from '../metrics-table-export';
|
|
35
37
|
import { MetricsTableOptions } from '../metrics-table-options';
|
|
36
38
|
import { MetricsTableTitle } from '../metrics-table-title';
|
|
37
39
|
import { MetricsDisplaySelector } from '../metrics-display-selector';
|
|
@@ -313,6 +315,12 @@ export const BundleAssets = (props) => {
|
|
|
313
315
|
return allItems.find(({ key }) => key === entryId);
|
|
314
316
|
}, [allItems, entryId]);
|
|
315
317
|
|
|
318
|
+
const exportDialog = useDialogState();
|
|
319
|
+
|
|
320
|
+
const handleExportClick = useCallback(() => {
|
|
321
|
+
exportDialog.toggle();
|
|
322
|
+
}, []);
|
|
323
|
+
|
|
316
324
|
return (
|
|
317
325
|
<>
|
|
318
326
|
<Stack space="xsmall" as="section" className={cx(css.root, className)}>
|
|
@@ -326,8 +334,9 @@ export const BundleAssets = (props) => {
|
|
|
326
334
|
onSelect={setDisplayType}
|
|
327
335
|
/>
|
|
328
336
|
<MetricsTableOptions
|
|
329
|
-
|
|
330
|
-
|
|
337
|
+
onViewAllClick={resetAllFilters}
|
|
338
|
+
onResetClick={resetFilters}
|
|
339
|
+
onExportClick={handleExportClick}
|
|
331
340
|
/>
|
|
332
341
|
</FlexStack>
|
|
333
342
|
)}
|
|
@@ -385,6 +394,10 @@ export const BundleAssets = (props) => {
|
|
|
385
394
|
onClose={hideEntryInfo}
|
|
386
395
|
/>
|
|
387
396
|
)}
|
|
397
|
+
|
|
398
|
+
<Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
|
|
399
|
+
{exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--assets"/>}
|
|
400
|
+
</Dialog>
|
|
388
401
|
</>
|
|
389
402
|
);
|
|
390
403
|
};
|
|
@@ -15,12 +15,16 @@ import { Toolbar } from '../../ui/toolbar';
|
|
|
15
15
|
import { Table } from '../../ui/table';
|
|
16
16
|
import { Box } from '../../layout/box';
|
|
17
17
|
import { Stack } from '../../layout/stack';
|
|
18
|
+
import { Dialog, useDialogState } from '../../ui/dialog';
|
|
18
19
|
import { MetricsDisplaySelector } from '../metrics-display-selector';
|
|
19
20
|
import { MetricsTable } from '../metrics-table';
|
|
20
|
-
import {
|
|
21
|
+
import { MetricsTableExport } from '../metrics-table-export';
|
|
21
22
|
import { MetricsTableHeader } from '../metrics-table-header';
|
|
23
|
+
import { MetricsTableOptions } from '../metrics-table-options';
|
|
24
|
+
import { MetricsTableTitle } from '../metrics-table-title';
|
|
22
25
|
import { MetricsTreemap, getTreemapNodes } from '../metrics-treemap';
|
|
23
26
|
import { ComponentLink } from '../component-link';
|
|
27
|
+
import { FlexStack } from '../../layout';
|
|
24
28
|
|
|
25
29
|
const metricsTableTitle = (
|
|
26
30
|
<MetricsTableTitle
|
|
@@ -68,42 +72,57 @@ export const BundleAssetsTotals = ({
|
|
|
68
72
|
[history],
|
|
69
73
|
);
|
|
70
74
|
|
|
75
|
+
const exportDialog = useDialogState();
|
|
76
|
+
|
|
77
|
+
const handleExportClick = useCallback(() => {
|
|
78
|
+
exportDialog.toggle();
|
|
79
|
+
}, []);
|
|
80
|
+
|
|
71
81
|
return (
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<Table compact>
|
|
92
|
-
<MetricsTableHeader
|
|
93
|
-
metricTitle={metricsTableTitle}
|
|
94
|
-
showSum
|
|
95
|
-
jobs={jobs}
|
|
96
|
-
rows={items}
|
|
97
|
-
/>
|
|
98
|
-
</Table>
|
|
99
|
-
<MetricsTreemap
|
|
100
|
-
treeNodes={getTreemapNodes(items)}
|
|
101
|
-
onItemClick={onTreemapItemClick || handleMetricsTreemapItemClick}
|
|
82
|
+
<>
|
|
83
|
+
<Stack space="xsmall" as="section" className={className}>
|
|
84
|
+
<Toolbar
|
|
85
|
+
renderActions={() => (
|
|
86
|
+
<FlexStack space="xxsmall">
|
|
87
|
+
<MetricsDisplaySelector onSelect={setDisplayType} value={displayType.value} />
|
|
88
|
+
<MetricsTableOptions onExportClick={handleExportClick} />
|
|
89
|
+
</FlexStack>
|
|
90
|
+
)}
|
|
91
|
+
/>
|
|
92
|
+
<Box outline as="main">
|
|
93
|
+
{displayType.value === MetricsDisplayType.TABLE && (
|
|
94
|
+
<MetricsTable
|
|
95
|
+
title={metricsTableTitle}
|
|
96
|
+
runs={jobs}
|
|
97
|
+
items={items}
|
|
98
|
+
renderRowHeader={renderRowHeader}
|
|
99
|
+
showHeaderSum
|
|
100
|
+
{...restProps}
|
|
102
101
|
/>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
)}
|
|
103
|
+
{displayType.value === MetricsDisplayType.TREEMAP && (
|
|
104
|
+
<>
|
|
105
|
+
<Table compact>
|
|
106
|
+
<MetricsTableHeader
|
|
107
|
+
metricTitle={metricsTableTitle}
|
|
108
|
+
showSum
|
|
109
|
+
jobs={jobs}
|
|
110
|
+
rows={items}
|
|
111
|
+
/>
|
|
112
|
+
</Table>
|
|
113
|
+
<MetricsTreemap
|
|
114
|
+
treeNodes={getTreemapNodes(items)}
|
|
115
|
+
onItemClick={onTreemapItemClick || handleMetricsTreemapItemClick}
|
|
116
|
+
/>
|
|
117
|
+
</>
|
|
118
|
+
)}
|
|
119
|
+
</Box>
|
|
120
|
+
</Stack>
|
|
121
|
+
|
|
122
|
+
<Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
|
|
123
|
+
{exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--totals" />}
|
|
124
|
+
</Dialog>
|
|
125
|
+
</>
|
|
107
126
|
);
|
|
108
127
|
};
|
|
109
128
|
|
|
@@ -13,6 +13,7 @@ import { FlexStack } from '../../layout/flex-stack';
|
|
|
13
13
|
import { Stack } from '../../layout/stack';
|
|
14
14
|
import { Button } from '../../ui/button';
|
|
15
15
|
import { ControlGroup } from '../../ui/control-group';
|
|
16
|
+
import { Dialog, useDialogState } from '../../ui/dialog';
|
|
16
17
|
import { EmptySet } from '../../ui/empty-set';
|
|
17
18
|
import { FileName } from '../../ui/file-name';
|
|
18
19
|
import { Filters } from '../../ui/filters';
|
|
@@ -23,6 +24,7 @@ import { Toolbar } from '../../ui/toolbar';
|
|
|
23
24
|
import { Tooltip } from '../../ui/tooltip';
|
|
24
25
|
import { ComponentLink } from '../component-link';
|
|
25
26
|
import { MetricsTable } from '../metrics-table';
|
|
27
|
+
import { MetricsTableExport } from '../metrics-table-export';
|
|
26
28
|
import { MetricsTableHeader } from '../metrics-table-header';
|
|
27
29
|
import { MetricsTreemap, getTreemapNodes, getTreemapNodesGroupedByPath } from '../metrics-treemap';
|
|
28
30
|
import { MetricsTableOptions } from '../metrics-table-options';
|
|
@@ -252,6 +254,12 @@ export const BundleModules = (props: BundleModulesProps) => {
|
|
|
252
254
|
return allItems.find(({ key }) => key === entryId);
|
|
253
255
|
}, [allItems, entryId]);
|
|
254
256
|
|
|
257
|
+
const exportDialog = useDialogState();
|
|
258
|
+
|
|
259
|
+
const handleExportClick = useCallback(() => {
|
|
260
|
+
exportDialog.toggle();
|
|
261
|
+
}, []);
|
|
262
|
+
|
|
255
263
|
return (
|
|
256
264
|
<>
|
|
257
265
|
<Stack space="xsmall" as="section" className={rootClassName}>
|
|
@@ -266,8 +274,9 @@ export const BundleModules = (props: BundleModulesProps) => {
|
|
|
266
274
|
groups={DISPLAY_TYPE_GROUPS}
|
|
267
275
|
/>
|
|
268
276
|
<MetricsTableOptions
|
|
269
|
-
|
|
270
|
-
|
|
277
|
+
onViewAllClick={resetAllFilters}
|
|
278
|
+
onResetClick={resetFilters}
|
|
279
|
+
onExportClick={handleExportClick}
|
|
271
280
|
/>
|
|
272
281
|
</FlexStack>
|
|
273
282
|
)}
|
|
@@ -363,6 +372,10 @@ export const BundleModules = (props: BundleModulesProps) => {
|
|
|
363
372
|
onClose={hideEntryInfo}
|
|
364
373
|
/>
|
|
365
374
|
)}
|
|
375
|
+
|
|
376
|
+
<Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
|
|
377
|
+
{exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--modules"/>}
|
|
378
|
+
</Dialog>
|
|
366
379
|
</>
|
|
367
380
|
);
|
|
368
381
|
};
|
|
@@ -9,6 +9,7 @@ import I18N from '../../i18n';
|
|
|
9
9
|
import { Box } from '../../layout/box';
|
|
10
10
|
import { FlexStack } from '../../layout/flex-stack';
|
|
11
11
|
import { Stack } from '../../layout/stack';
|
|
12
|
+
import { Dialog, useDialogState } from '../../ui/dialog';
|
|
12
13
|
import { InputSearch } from '../../ui/input-search';
|
|
13
14
|
import { EmptySet } from '../../ui/empty-set';
|
|
14
15
|
import { Filters } from '../../ui/filters';
|
|
@@ -17,6 +18,7 @@ import { Table } from '../../ui/table';
|
|
|
17
18
|
import { Toolbar } from '../../ui/toolbar';
|
|
18
19
|
import { ComponentLink } from '../component-link';
|
|
19
20
|
import { MetricsTable } from '../metrics-table';
|
|
21
|
+
import { MetricsTableExport } from '../metrics-table-export';
|
|
20
22
|
import { MetricsTableHeader } from '../metrics-table-header';
|
|
21
23
|
import { MetricsTableOptions } from '../metrics-table-options';
|
|
22
24
|
import { MetricsTableTitle } from '../metrics-table-title';
|
|
@@ -261,6 +263,12 @@ export const BundlePackages = (props) => {
|
|
|
261
263
|
return allItems.find(({ key }) => key === entryId)
|
|
262
264
|
}, [allItems, entryId]);
|
|
263
265
|
|
|
266
|
+
const exportDialog = useDialogState();
|
|
267
|
+
|
|
268
|
+
const handleExportClick = useCallback(() => {
|
|
269
|
+
exportDialog.toggle();
|
|
270
|
+
}, []);
|
|
271
|
+
|
|
264
272
|
return (
|
|
265
273
|
<>
|
|
266
274
|
<Stack space="xsmall" as="section" className={cx(css.root, className)}>
|
|
@@ -270,8 +278,9 @@ export const BundlePackages = (props) => {
|
|
|
270
278
|
<FlexStack space="xxsmall" className={cx(css.dropdown, actionClassName)}>
|
|
271
279
|
<MetricsDisplaySelector onSelect={setDisplayType} value={displayType.value} groupBy={displayType.groupBy} groups={DISPLAY_TYPE_GROUPS} />
|
|
272
280
|
<MetricsTableOptions
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
onViewAllClick={resetAllFilters}
|
|
282
|
+
onResetClick={resetFilters}
|
|
283
|
+
onExportClick={handleExportClick}
|
|
275
284
|
/>
|
|
276
285
|
</FlexStack>
|
|
277
286
|
)}
|
|
@@ -327,6 +336,10 @@ export const BundlePackages = (props) => {
|
|
|
327
336
|
onClose={hideEntryInfo}
|
|
328
337
|
/>
|
|
329
338
|
)}
|
|
339
|
+
|
|
340
|
+
<Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
|
|
341
|
+
{exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--packages"/>}
|
|
342
|
+
</Dialog>
|
|
330
343
|
</>
|
|
331
344
|
);
|
|
332
345
|
};
|
|
@@ -105,7 +105,7 @@ export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) =
|
|
|
105
105
|
<Stack space="small">
|
|
106
106
|
<FlexStack space="xxxsmall" alignItems="center" as="h3" className={css.label}>
|
|
107
107
|
<FileName as="code" name={itemTitle || item.label} className={css.fileName} />
|
|
108
|
-
<CopyToClipboard text={item.label} />
|
|
108
|
+
<CopyToClipboard text={item.label} size="small" />
|
|
109
109
|
</FlexStack>
|
|
110
110
|
<div>{renderRunInfo(item)}</div>
|
|
111
111
|
</Stack>
|
|
@@ -156,7 +156,7 @@ export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) =
|
|
|
156
156
|
name={rowRun[runNameSelector]}
|
|
157
157
|
className={css.fileName}
|
|
158
158
|
/>
|
|
159
|
-
<CopyToClipboard text={item.label} />
|
|
159
|
+
<CopyToClipboard text={item.label} size="small" />
|
|
160
160
|
</FlexStack>
|
|
161
161
|
) : (
|
|
162
162
|
'-'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './metrics-table-export';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { getWrapperDecorator } from '../../stories';
|
|
4
|
+
import { MetricsTableExport } from '.';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof MetricsTableExport> = {
|
|
7
|
+
title: 'Components/MetricsTableExport',
|
|
8
|
+
component: MetricsTableExport,
|
|
9
|
+
decorators: [getWrapperDecorator()],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
|
|
16
|
+
const ITEMS = [
|
|
17
|
+
{
|
|
18
|
+
label: 'Hey',
|
|
19
|
+
runs: [
|
|
20
|
+
{ value: 1, name: 'a' },
|
|
21
|
+
{ value: 2, name: 'b' },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export const Default: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
items: ITEMS,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import type { ReportMetricRow } from '@bundle-stats/utils';
|
|
4
|
+
|
|
5
|
+
import { Stack } from '../../layout/stack';
|
|
6
|
+
import { Tabs } from '../../ui/tabs';
|
|
7
|
+
import { PreviewSource } from '../preview-source';
|
|
8
|
+
import css from './metrics-table-export.module.css';
|
|
9
|
+
|
|
10
|
+
const generateSourceJSON = (items: Array<ReportMetricRow>): string => {
|
|
11
|
+
const output = items.map((item) => ({
|
|
12
|
+
name: item.label,
|
|
13
|
+
runs: item.runs?.map((itemRun) => ({
|
|
14
|
+
name: itemRun?.name || '',
|
|
15
|
+
size: itemRun?.value || 0,
|
|
16
|
+
})),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
return JSON.stringify(output, null, 2);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const CSV_SEPARATOR = ', ';
|
|
23
|
+
|
|
24
|
+
const generateSourceCSV = (items: Array<ReportMetricRow>): string => {
|
|
25
|
+
const output = [];
|
|
26
|
+
|
|
27
|
+
output.push(
|
|
28
|
+
[
|
|
29
|
+
'Name',
|
|
30
|
+
...(items?.[0]?.runs?.map((_, index) => {
|
|
31
|
+
if (index === 0) {
|
|
32
|
+
return `Run ${index + 1}(current)`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return `Run ${index + 1}(baseline)`;
|
|
36
|
+
}) || []),
|
|
37
|
+
].join(CSV_SEPARATOR),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
items?.forEach((item) => {
|
|
41
|
+
const row: Array<string | number> = [item.label];
|
|
42
|
+
|
|
43
|
+
item.runs?.forEach((itemRun) => {
|
|
44
|
+
row.push(itemRun?.value || 0);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
output.push(row.join(CSV_SEPARATOR));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return output.join('\r');
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const SOURCES = [
|
|
54
|
+
{
|
|
55
|
+
label: 'CSV',
|
|
56
|
+
transformFn: generateSourceCSV,
|
|
57
|
+
extension: '.csv',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label: 'JSON',
|
|
61
|
+
transformFn: generateSourceJSON,
|
|
62
|
+
extension: '.json',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
type MetricsTableExportProps = {
|
|
67
|
+
items: Array<ReportMetricRow>;
|
|
68
|
+
download: string;
|
|
69
|
+
} & ComponentProps<typeof Stack>;
|
|
70
|
+
|
|
71
|
+
export const MetricsTableExport = (props: MetricsTableExportProps) => {
|
|
72
|
+
const { items, download, ...restProps } = props;
|
|
73
|
+
const [selectedId, setSelectedId] = useState(SOURCES[0].label);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Stack space="small" {...restProps}>
|
|
77
|
+
<Tabs>
|
|
78
|
+
{SOURCES.map((source) => (
|
|
79
|
+
<Tabs.Item
|
|
80
|
+
onClick={() => setSelectedId(source.label)}
|
|
81
|
+
isTabActive={selectedId === source.label}
|
|
82
|
+
key={source.label}
|
|
83
|
+
>
|
|
84
|
+
{source.label}
|
|
85
|
+
</Tabs.Item>
|
|
86
|
+
))}
|
|
87
|
+
</Tabs>
|
|
88
|
+
<div className={css.panels}>
|
|
89
|
+
{SOURCES.map(
|
|
90
|
+
(source) =>
|
|
91
|
+
selectedId === source.label && (
|
|
92
|
+
<PreviewSource
|
|
93
|
+
source={source.transformFn(items)}
|
|
94
|
+
download={`${download}.${source.extension}`}
|
|
95
|
+
className={css.panel}
|
|
96
|
+
key={source.label}
|
|
97
|
+
/>
|
|
98
|
+
),
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
</Stack>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
3
|
+
import { action } from '@storybook/addon-actions';
|
|
4
|
+
|
|
5
|
+
import { getWrapperDecorator } from '../../stories';
|
|
6
|
+
import { MetricsTableOptions } from '.';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof MetricsTableOptions> = {
|
|
9
|
+
title: 'Components/MetricsTableOptions',
|
|
10
|
+
component: MetricsTableOptions,
|
|
11
|
+
decorators: [getWrapperDecorator()],
|
|
12
|
+
args: {
|
|
13
|
+
onResetClick: action('RESET'),
|
|
14
|
+
onViewAllClick: action('VIEW_ALL'),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import I18N from '../../i18n';
|
|
5
|
+
import { Dropdown, DropdownItem } from '../../ui/dropdown';
|
|
6
|
+
import { Separator } from '../../layout/separator';
|
|
7
|
+
|
|
8
|
+
type MetricsTableOptionsProps = {
|
|
9
|
+
onViewAllClick?: () => void;
|
|
10
|
+
onResetClick?: () => void;
|
|
11
|
+
onExportClick?: () => void;
|
|
12
|
+
} & ComponentProps<typeof Dropdown>;
|
|
13
|
+
|
|
14
|
+
export const MetricsTableOptions = (props: MetricsTableOptionsProps) => {
|
|
15
|
+
const { onViewAllClick, onResetClick, onExportClick, ...restProps } = props;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Dropdown glyph="more-vertical" {...restProps}>
|
|
19
|
+
{onResetClick && <DropdownItem onClick={onResetClick}>{I18N.RESET_FILTERS}</DropdownItem>}
|
|
20
|
+
{onViewAllClick && <DropdownItem onClick={onViewAllClick}>{I18N.VIEW_ALL}</DropdownItem>}
|
|
21
|
+
{((onResetClick || onViewAllClick) && onExportClick) && <Separator />}
|
|
22
|
+
{onExportClick && <DropdownItem onClick={onExportClick}>{I18N.EXPORT}</DropdownItem>}
|
|
23
|
+
</Dropdown>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './preview-source';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.toolbar {
|
|
6
|
+
position: absolute;
|
|
7
|
+
z-index: 2;
|
|
8
|
+
top: var(--space-xsmall);
|
|
9
|
+
right: var(--space-xsmall);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** fix control group with nested components */
|
|
13
|
+
.downloadTooltip > a {
|
|
14
|
+
border-top-left-radius: inherit;
|
|
15
|
+
border-bottom-left-radius: inherit;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.downloadTooltip > a:hover,
|
|
19
|
+
.downloadTooltip > a:active,
|
|
20
|
+
.downloadTooltip > a:focus {
|
|
21
|
+
box-shadow: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.content {
|
|
25
|
+
position: relative;
|
|
26
|
+
z-index: 1;
|
|
27
|
+
height: 100%;
|
|
28
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { getWrapperDecorator } from '../../stories';
|
|
4
|
+
import { PreviewSource } from '.';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof PreviewSource> = {
|
|
7
|
+
title: 'Components/PreviewSource',
|
|
8
|
+
component: PreviewSource,
|
|
9
|
+
decorators: [getWrapperDecorator()],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
|
|
16
|
+
const SOURCE = JSON.stringify(
|
|
17
|
+
[
|
|
18
|
+
{
|
|
19
|
+
label: 'Hey',
|
|
20
|
+
runs: [
|
|
21
|
+
{ value: 1, name: 'a' },
|
|
22
|
+
{ value: 2, name: 'b' },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
null,
|
|
27
|
+
2,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const Default: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
source: SOURCE,
|
|
33
|
+
download: 'bundle-stats--assets.json',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import cx from 'classnames';
|
|
4
|
+
|
|
5
|
+
import { Button, BUTTON_GLYPHS } from '../../ui/button';
|
|
6
|
+
import { CopyToClipboard } from '../../ui/copy-to-clipboard';
|
|
7
|
+
import { ControlGroup } from '../../ui/control-group';
|
|
8
|
+
import { Tooltip } from '../../ui/tooltip';
|
|
9
|
+
import { Textarea } from '../../ui/textarea';
|
|
10
|
+
import css from './preview-source.module.css';
|
|
11
|
+
|
|
12
|
+
type PreviewSourceProps = {
|
|
13
|
+
source: string;
|
|
14
|
+
/**
|
|
15
|
+
* Link download attribute
|
|
16
|
+
* @example
|
|
17
|
+
* bundle-stats--assets.json
|
|
18
|
+
*/
|
|
19
|
+
download?: string;
|
|
20
|
+
} & ComponentProps<'div'>;
|
|
21
|
+
|
|
22
|
+
export const PreviewSource = (props: PreviewSourceProps) => {
|
|
23
|
+
const { className = '', source, download = false, ...restProps } = props;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className={cx(css.root, className)} {...restProps}>
|
|
27
|
+
<ControlGroup className={css.toolbar}>
|
|
28
|
+
<CopyToClipboard outline size="small" text={source} />
|
|
29
|
+
{download && (
|
|
30
|
+
<Tooltip title={`Download ${download}`} className={css.downloadTooltip}>
|
|
31
|
+
<Button
|
|
32
|
+
outline
|
|
33
|
+
rightGlyph={BUTTON_GLYPHS.DOWNLOAD}
|
|
34
|
+
size="small"
|
|
35
|
+
as="a"
|
|
36
|
+
href={`data:application/json,${encodeURIComponent(source)}`}
|
|
37
|
+
download={download}
|
|
38
|
+
/>
|
|
39
|
+
</Tooltip>
|
|
40
|
+
)}
|
|
41
|
+
</ControlGroup>
|
|
42
|
+
<Textarea previewSource readOnly rows={12} className={css.content}>
|
|
43
|
+
{source}
|
|
44
|
+
</Textarea>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
package/src/css/variables.css
CHANGED
package/src/i18n.js
CHANGED
|
@@ -21,6 +21,10 @@ export default {
|
|
|
21
21
|
|
|
22
22
|
RESET_FILTERS: 'Reset filters',
|
|
23
23
|
VIEW_ALL: 'View all entries',
|
|
24
|
+
EXPORT: 'Export',
|
|
25
|
+
|
|
26
|
+
COPY_TO_CLIPBOARD: 'Copy to clipboard',
|
|
27
|
+
COPY_TO_CLIPBOARD_DONE: 'Copied to clipboard',
|
|
24
28
|
|
|
25
29
|
GITHUB_LINK_TITLE: 'View BundleStats project on GitHub',
|
|
26
30
|
REPORT_ISSUE: 'Report issue',
|
package/src/ui/button/button.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
2
|
import cx from 'classnames';
|
|
4
3
|
import { Button as ButtonBaseComponent } from 'ariakit/button';
|
|
5
4
|
|
|
@@ -21,6 +20,8 @@ export const BUTTON_KIND = {
|
|
|
21
20
|
SUCCES: 'success',
|
|
22
21
|
} as const;
|
|
23
22
|
|
|
23
|
+
export const BUTTON_GLYPHS = BaseIcon.ICONS;
|
|
24
|
+
|
|
24
25
|
type Size = (typeof BUTTON_SIZE)[keyof typeof BUTTON_SIZE];
|
|
25
26
|
type Kind = (typeof BUTTON_KIND)[keyof typeof BUTTON_KIND];
|
|
26
27
|
|