@bundle-stats/ui 4.16.0-beta.9 → 4.17.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/lib/components/asset-info/asset-info.js +4 -4
  2. package/lib/components/asset-info/asset-info.js.map +1 -1
  3. package/lib/components/asset-meta-tag/asset-meta-tag.js +17 -0
  4. package/lib/components/asset-meta-tag/asset-meta-tag.js.map +1 -0
  5. package/lib/components/asset-meta-tag/asset-meta-tag.module.css +55 -0
  6. package/lib/components/asset-meta-tag/index.js +18 -0
  7. package/lib/components/asset-meta-tag/index.js.map +1 -0
  8. package/lib/components/asset-name/asset-name.js +32 -0
  9. package/lib/components/asset-name/asset-name.js.map +1 -0
  10. package/lib/components/asset-name/asset-name.module.css +32 -0
  11. package/lib/components/asset-name/index.js +18 -0
  12. package/lib/components/asset-name/index.js.map +1 -0
  13. package/lib/components/asset-not-predictive/asset-not-predictive.js +4 -2
  14. package/lib/components/asset-not-predictive/asset-not-predictive.js.map +1 -1
  15. package/lib/components/bundle-assets/bundle-assets.js +7 -40
  16. package/lib/components/bundle-assets/bundle-assets.js.map +1 -1
  17. package/lib/components/bundle-assets/bundle-assets.module.css +0 -64
  18. package/lib/components/bundle-assets/bundle-assets.utils.js +56 -28
  19. package/lib/components/bundle-assets/bundle-assets.utils.js.map +1 -1
  20. package/lib/components/bundle-assets/index.js +1 -1
  21. package/lib/components/bundle-assets/index.js.map +1 -1
  22. package/lib/components/bundle-assets-totals/bundle-assets-totals.js +4 -2
  23. package/lib/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  24. package/lib/components/bundle-modules/bundle-modules.js +4 -2
  25. package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
  26. package/lib/components/bundle-packages/bundle-packages.js +4 -2
  27. package/lib/components/bundle-packages/bundle-packages.js.map +1 -1
  28. package/lib/components/entry-info/entry-info.js +1 -1
  29. package/lib/components/entry-info/entry-info.js.map +1 -1
  30. package/lib/components/metrics-table-export/metrics-table-export.js +12 -10
  31. package/lib/components/metrics-table-export/metrics-table-export.js.map +1 -1
  32. package/lib/components/metrics-table-options/metrics-table-options.js +7 -5
  33. package/lib/components/metrics-table-options/metrics-table-options.js.map +1 -1
  34. package/lib/components/metrics-table-options/metrics-table-options.module.css +5 -0
  35. package/lib/components/metrics-treemap/metrics-treemap.utils.js +0 -1
  36. package/lib/components/metrics-treemap/metrics-treemap.utils.js.map +1 -1
  37. package/lib/components/preview-source/preview-source.js +1 -1
  38. package/lib/components/preview-source/preview-source.js.map +1 -1
  39. package/lib/i18n.js +2 -0
  40. package/lib/i18n.js.map +1 -1
  41. package/lib/stories/wrapper.js +5 -2
  42. package/lib/stories/wrapper.js.map +1 -1
  43. package/lib/ui/tabs/index.js +15 -3
  44. package/lib/ui/tabs/index.js.map +1 -1
  45. package/lib/ui/tabs/tabs.js +9 -20
  46. package/lib/ui/tabs/tabs.js.map +1 -1
  47. package/lib/ui/tabs/tabs.module.css +6 -6
  48. package/lib/ui/tag/tag.js.map +1 -1
  49. package/lib-esm/components/asset-info/asset-info.js +4 -4
  50. package/lib-esm/components/asset-info/asset-info.js.map +1 -1
  51. package/lib-esm/components/asset-meta-tag/asset-meta-tag.js +10 -0
  52. package/lib-esm/components/asset-meta-tag/asset-meta-tag.js.map +1 -0
  53. package/lib-esm/components/asset-meta-tag/asset-meta-tag.module.css +55 -0
  54. package/lib-esm/components/asset-meta-tag/index.js +2 -0
  55. package/lib-esm/components/asset-meta-tag/index.js.map +1 -0
  56. package/lib-esm/components/asset-name/asset-name.js +25 -0
  57. package/lib-esm/components/asset-name/asset-name.js.map +1 -0
  58. package/lib-esm/components/asset-name/asset-name.module.css +32 -0
  59. package/lib-esm/components/asset-name/index.js +2 -0
  60. package/lib-esm/components/asset-name/index.js.map +1 -0
  61. package/lib-esm/components/asset-not-predictive/asset-not-predictive.js +4 -2
  62. package/lib-esm/components/asset-not-predictive/asset-not-predictive.js.map +1 -1
  63. package/lib-esm/components/bundle-assets/bundle-assets.js +8 -41
  64. package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
  65. package/lib-esm/components/bundle-assets/bundle-assets.module.css +0 -64
  66. package/lib-esm/components/bundle-assets/bundle-assets.utils.js +52 -24
  67. package/lib-esm/components/bundle-assets/bundle-assets.utils.js.map +1 -1
  68. package/lib-esm/components/bundle-assets/index.js +2 -2
  69. package/lib-esm/components/bundle-assets/index.js.map +1 -1
  70. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js +5 -3
  71. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  72. package/lib-esm/components/bundle-modules/bundle-modules.js +5 -3
  73. package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
  74. package/lib-esm/components/bundle-packages/bundle-packages.js +5 -3
  75. package/lib-esm/components/bundle-packages/bundle-packages.js.map +1 -1
  76. package/lib-esm/components/entry-info/entry-info.js +1 -1
  77. package/lib-esm/components/entry-info/entry-info.js.map +1 -1
  78. package/lib-esm/components/metrics-table-export/metrics-table-export.js +13 -11
  79. package/lib-esm/components/metrics-table-export/metrics-table-export.js.map +1 -1
  80. package/lib-esm/components/metrics-table-options/metrics-table-options.js +7 -5
  81. package/lib-esm/components/metrics-table-options/metrics-table-options.js.map +1 -1
  82. package/lib-esm/components/metrics-table-options/metrics-table-options.module.css +5 -0
  83. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js +0 -1
  84. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js.map +1 -1
  85. package/lib-esm/components/preview-source/preview-source.js +1 -1
  86. package/lib-esm/components/preview-source/preview-source.js.map +1 -1
  87. package/lib-esm/i18n.js +2 -0
  88. package/lib-esm/i18n.js.map +1 -1
  89. package/lib-esm/stories/wrapper.js +5 -2
  90. package/lib-esm/stories/wrapper.js.map +1 -1
  91. package/lib-esm/ui/tabs/index.js +1 -1
  92. package/lib-esm/ui/tabs/index.js.map +1 -1
  93. package/lib-esm/ui/tabs/tabs.js +7 -19
  94. package/lib-esm/ui/tabs/tabs.js.map +1 -1
  95. package/lib-esm/ui/tabs/tabs.module.css +6 -6
  96. package/lib-esm/ui/tag/tag.js.map +1 -1
  97. package/package.json +12 -12
  98. package/src/app/app-gladys.stories.tsx +41 -0
  99. package/src/app/app-home-assistant.stories.tsx +41 -0
  100. package/src/app/app-outline.stories.tsx +41 -0
  101. package/src/app/app.stories.tsx +127 -0
  102. package/src/components/asset-info/asset-info.tsx +14 -7
  103. package/src/components/asset-meta-tag/asset-meta-tag.module.css +55 -0
  104. package/src/components/asset-meta-tag/asset-meta-tag.tsx +34 -0
  105. package/src/components/asset-meta-tag/index.ts +1 -0
  106. package/src/components/asset-name/asset-name.module.css +32 -0
  107. package/src/components/asset-name/asset-name.stories.tsx +85 -0
  108. package/src/components/asset-name/asset-name.tsx +60 -0
  109. package/src/components/asset-name/index.ts +1 -0
  110. package/src/components/asset-not-predictive/asset-not-predictive.tsx +10 -8
  111. package/src/components/bundle-assets/__tests__/add-metric-report-asset-row-data.ts +181 -0
  112. package/src/components/bundle-assets/__tests__/get-asset-meta-status.ts +21 -0
  113. package/src/components/bundle-assets/__tests__/get-is-not-predictive.ts +119 -0
  114. package/src/components/bundle-assets/bundle-assets.jsx +26 -87
  115. package/src/components/bundle-assets/bundle-assets.module.css +0 -64
  116. package/src/components/bundle-assets/bundle-assets.utils.js +87 -26
  117. package/src/components/bundle-assets/index.jsx +2 -7
  118. package/src/components/bundle-assets-totals/bundle-assets-totals.jsx +11 -3
  119. package/src/components/bundle-modules/bundle-modules.tsx +11 -3
  120. package/src/components/bundle-packages/bundle-packages.jsx +11 -3
  121. package/src/components/entry-info/entry-info.tsx +1 -6
  122. package/src/components/metrics-table-export/metrics-table-export.tsx +28 -19
  123. package/src/components/metrics-table-options/metrics-table-options.module.css +5 -0
  124. package/src/components/metrics-table-options/metrics-table-options.tsx +14 -6
  125. package/src/components/metrics-treemap/metrics-treemap.utils.ts +0 -1
  126. package/src/components/preview-source/preview-source.stories.tsx +13 -1
  127. package/src/components/preview-source/preview-source.tsx +1 -1
  128. package/src/i18n.js +2 -0
  129. package/src/stories/wrapper.jsx +21 -15
  130. package/src/types.d.ts +30 -1
  131. package/src/ui/tabs/index.ts +1 -0
  132. package/src/ui/tabs/tabs.module.css +6 -6
  133. package/src/ui/tabs/tabs.stories.tsx +25 -0
  134. package/src/ui/tabs/tabs.tsx +32 -0
  135. package/src/ui/tag/tag.tsx +4 -3
  136. package/types/components/asset-meta-tag/asset-meta-tag.d.ts +8 -0
  137. package/types/components/asset-meta-tag/index.d.ts +1 -0
  138. package/types/components/asset-name/asset-name.d.ts +8 -0
  139. package/types/components/asset-name/index.d.ts +1 -0
  140. package/types/components/asset-not-predictive/asset-not-predictive.d.ts +4 -4
  141. package/types/components/bundle-assets/bundle-assets.utils.d.ts +3 -3
  142. package/types/components/metrics-table-export/metrics-table-export.d.ts +1 -0
  143. package/types/components/metrics-table-options/metrics-table-options.d.ts +1 -1
  144. package/types/i18n.d.ts +2 -0
  145. package/types/stories/wrapper.d.ts +1 -1
  146. package/types/ui/tabs/index.d.ts +1 -1
  147. package/types/ui/tabs/tabs.d.ts +11 -41
  148. package/types/ui/tag/tag.d.ts +4 -4
  149. package/src/ui/tabs/index.js +0 -1
  150. package/src/ui/tabs/tabs.jsx +0 -39
@@ -13,12 +13,7 @@ import { useSearchParams } from '../../hooks/search-params';
13
13
  import { useEntryInfo } from '../../hooks/entry-info';
14
14
  import { getJobsChunksData } from '../../utils/jobs';
15
15
  import { BundleAssets as BundleAssetsComponent } from './bundle-assets';
16
- import {
17
- addRowAssetFlags,
18
- addRowIsNotPredictive,
19
- getRowFilter,
20
- getCustomSort,
21
- } from './bundle-assets.utils';
16
+ import { addMetricReportAssetRowData, getRowFilter, getCustomSort } from './bundle-assets.utils';
22
17
 
23
18
  export const BundleAssets = (props) => {
24
19
  const { jobs, filters, search, setState, sortBy, direction, ...restProps } = props;
@@ -50,7 +45,7 @@ export const BundleAssets = (props) => {
50
45
  });
51
46
 
52
47
  const { rows, totalRowCount } = useMemo(() => {
53
- const result = webpack.compareBySection.assets(jobs, [addRowAssetFlags, addRowIsNotPredictive]);
48
+ const result = webpack.compareBySection.assets(jobs, [addMetricReportAssetRowData]);
54
49
  return { rows: result, totalRowCount: result.length };
55
50
  }, [jobs]);
56
51
 
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useMemo } from 'react';
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useHistory } from 'react-router-dom';
4
4
  import {
@@ -73,8 +73,10 @@ export const BundleAssetsTotals = ({
73
73
  );
74
74
 
75
75
  const exportDialog = useDialogState();
76
+ const [exportSourceType, setExportSourceType] = useState(undefined);
76
77
 
77
- const handleExportClick = useCallback(() => {
78
+ const handleExportClick = useCallback((sourceType) => {
79
+ setExportSourceType(sourceType);
78
80
  exportDialog.toggle();
79
81
  }, []);
80
82
 
@@ -120,7 +122,13 @@ export const BundleAssetsTotals = ({
120
122
  </Stack>
121
123
 
122
124
  <Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
123
- {exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--totals" />}
125
+ {exportDialog.open && (
126
+ <MetricsTableExport
127
+ items={items}
128
+ initialSourceType={exportSourceType}
129
+ download="bundle-stats--totals"
130
+ />
131
+ )}
124
132
  </Dialog>
125
133
  </>
126
134
  );
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useMemo } from 'react';
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
2
  import cx from 'classnames';
3
3
  import { SECTIONS, COMPONENT, type Job, ReportMetricRow } from '@bundle-stats/utils';
4
4
  import escapeRegExp from 'lodash/escapeRegExp';
@@ -255,8 +255,10 @@ export const BundleModules = (props: BundleModulesProps) => {
255
255
  }, [allItems, entryId]);
256
256
 
257
257
  const exportDialog = useDialogState();
258
+ const [exportSourceType, setExportSourceType] = useState<string | undefined>(undefined);
258
259
 
259
- const handleExportClick = useCallback(() => {
260
+ const handleExportClick = useCallback((sourceType: string) => {
261
+ setExportSourceType(sourceType);
260
262
  exportDialog.toggle();
261
263
  }, []);
262
264
 
@@ -374,7 +376,13 @@ export const BundleModules = (props: BundleModulesProps) => {
374
376
  )}
375
377
 
376
378
  <Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
377
- {exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--modules"/>}
379
+ {exportDialog.open && (
380
+ <MetricsTableExport
381
+ items={items}
382
+ initialSourceType={exportSourceType}
383
+ download="bundle-stats--modules"
384
+ />
385
+ )}
378
386
  </Dialog>
379
387
  </>
380
388
  );
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useMemo } from 'react';
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
4
  import escapeRegExp from 'lodash/escapeRegExp';
@@ -264,8 +264,10 @@ export const BundlePackages = (props) => {
264
264
  }, [allItems, entryId]);
265
265
 
266
266
  const exportDialog = useDialogState();
267
+ const [exportSourceType, setExportSourceType] = useState(undefined);
267
268
 
268
- const handleExportClick = useCallback(() => {
269
+ const handleExportClick = useCallback((sourceType) => {
270
+ setExportSourceType(sourceType);
269
271
  exportDialog.toggle();
270
272
  }, []);
271
273
 
@@ -338,7 +340,13 @@ export const BundlePackages = (props) => {
338
340
  )}
339
341
 
340
342
  <Dialog title={I18N.EXPORT} width="wide" state={exportDialog}>
341
- {exportDialog.open && <MetricsTableExport items={items} download="bundle-stats--packages"/>}
343
+ {exportDialog.open && (
344
+ <MetricsTableExport
345
+ items={items}
346
+ initialSourceType={exportSourceType}
347
+ download="bundle-stats--packages"
348
+ />
349
+ )}
342
350
  </Dialog>
343
351
  </>
344
352
  );
@@ -145,12 +145,7 @@ export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) =
145
145
  </Table.Th>
146
146
  <Table.Td className={cx(css.runsCell, css.runsColName)}>
147
147
  {rowRun?.[runNameSelector] ? (
148
- <FlexStack
149
- space="xxxsmall"
150
- alignItems="center"
151
- as="h3"
152
- className={css.label}
153
- >
148
+ <FlexStack space="xxxsmall" alignItems="center" className={css.label}>
154
149
  <FileName
155
150
  as="code"
156
151
  name={rowRun[runNameSelector]}
@@ -3,7 +3,7 @@ import React, { useState } from 'react';
3
3
  import type { ReportMetricRow } from '@bundle-stats/utils';
4
4
 
5
5
  import { Stack } from '../../layout/stack';
6
- import { Tabs } from '../../ui/tabs';
6
+ import { Tabs, TabItem } from '../../ui/tabs';
7
7
  import { PreviewSource } from '../preview-source';
8
8
 
9
9
  const generateSourceJSON = (items: Array<ReportMetricRow>): string => {
@@ -49,49 +49,58 @@ const generateSourceCSV = (items: Array<ReportMetricRow>): string => {
49
49
  return output.join('\r');
50
50
  };
51
51
 
52
- const SOURCES = [
53
- {
52
+ const SOURCES = {
53
+ csv: {
54
54
  label: 'CSV',
55
55
  transformFn: generateSourceCSV,
56
- extension: 'csv',
56
+ extension: '.csv',
57
57
  },
58
- {
58
+ json: {
59
59
  label: 'JSON',
60
60
  transformFn: generateSourceJSON,
61
- extension: 'json',
61
+ extension: '.json',
62
62
  },
63
- ];
63
+ };
64
+
65
+ const SOURCE_ENTRIES = Object.entries(SOURCES);
66
+ const SOURCE_KEYS = Object.keys(SOURCES);
64
67
 
65
68
  type MetricsTableExportProps = {
66
69
  items: Array<ReportMetricRow>;
70
+ initialSourceType?: string;
67
71
  download: string;
68
72
  } & ComponentProps<typeof Stack>;
69
73
 
70
74
  export const MetricsTableExport = (props: MetricsTableExportProps) => {
71
- const { items, download, ...restProps } = props;
72
- const [selectedId, setSelectedId] = useState(SOURCES[0].label);
75
+ const { initialSourceType = SOURCE_KEYS[0], items, download, ...restProps } = props;
76
+ const [selectedSourceType, setSelectedSourceType] = useState(initialSourceType);
73
77
 
74
78
  return (
75
79
  <Stack space="small" {...restProps}>
76
80
  <Tabs>
77
- {SOURCES.map((source) => (
78
- <Tabs.Item
79
- onClick={() => setSelectedId(source.label)}
80
- isTabActive={selectedId === source.label}
81
- key={source.label}
81
+ {SOURCE_ENTRIES.map(([sourceId, source]) => (
82
+ <TabItem
83
+ onClick={() => setSelectedSourceType(sourceId)}
84
+ isTabActive={selectedSourceType === sourceId}
85
+ id={`metrics-table-export-tab-${sourceId}`}
86
+ aria-controls={`metrics-table-export-panel-${sourceId}`}
87
+ key={sourceId}
82
88
  >
83
89
  {source.label}
84
- </Tabs.Item>
90
+ </TabItem>
85
91
  ))}
86
92
  </Tabs>
87
93
  <div>
88
- {SOURCES.map(
89
- (source) =>
90
- selectedId === source.label && (
94
+ {SOURCE_ENTRIES.map(
95
+ ([sourceId, source]) =>
96
+ selectedSourceType === sourceId && (
91
97
  <PreviewSource
92
98
  source={source.transformFn(items)}
93
99
  rows={20}
94
- download={`${download}.${source.extension}`}
100
+ download={`${download}${source.extension}`}
101
+ role="tabpanel"
102
+ id={`metrics-table-export-panel-${sourceId}`}
103
+ aria-labelledby={`metrics-table-export-tab-${sourceId}`}
95
104
  key={source.label}
96
105
  />
97
106
  ),
@@ -0,0 +1,5 @@
1
+ :not(.group:empty) ~ .group {
2
+ margin-top: calc(var(--space-xxxsmall) / 2);
3
+ padding-top: calc(var(--space-xxxsmall) / 2);
4
+ border-top: 1px solid var(--color-outline);
5
+ }
@@ -3,12 +3,12 @@ import React from 'react';
3
3
 
4
4
  import I18N from '../../i18n';
5
5
  import { Dropdown, DropdownItem } from '../../ui/dropdown';
6
- import { Separator } from '../../layout/separator';
6
+ import css from './metrics-table-options.module.css';
7
7
 
8
8
  type MetricsTableOptionsProps = {
9
9
  onViewAllClick?: () => void;
10
10
  onResetClick?: () => void;
11
- onExportClick?: () => void;
11
+ onExportClick?: (sourceType: string) => void;
12
12
  } & ComponentProps<typeof Dropdown>;
13
13
 
14
14
  export const MetricsTableOptions = (props: MetricsTableOptionsProps) => {
@@ -16,10 +16,18 @@ export const MetricsTableOptions = (props: MetricsTableOptionsProps) => {
16
16
 
17
17
  return (
18
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>}
19
+ <div className={css.group}>
20
+ {onResetClick && <DropdownItem onClick={onResetClick}>{I18N.RESET_FILTERS}</DropdownItem>}
21
+ {onViewAllClick && <DropdownItem onClick={onViewAllClick}>{I18N.VIEW_ALL}</DropdownItem>}
22
+ </div>
23
+ <div className={css.group}>
24
+ {onExportClick && (
25
+ <>
26
+ <DropdownItem onClick={() => onExportClick('csv')}>{I18N.EXPORT_CSV}</DropdownItem>
27
+ <DropdownItem onClick={() => onExportClick('json')}>{I18N.EXPORT_JSON}</DropdownItem>
28
+ </>
29
+ )}
30
+ </div>
23
31
  </Dropdown>
24
32
  );
25
33
  };
@@ -141,7 +141,6 @@ export function getTreemapNodesGroupedByPath(items: Array<ReportMetricRow>): Tre
141
141
  };
142
142
 
143
143
  const childrenTotal = setTreeNode(treeNodes, baseSlugs, 0, treeNode);
144
- console.log(childrenTotal);
145
144
 
146
145
  total.current += childrenTotal.current;
147
146
  total.baseline =
@@ -29,7 +29,19 @@ const SOURCE = JSON.stringify(
29
29
 
30
30
  export const Default: Story = {
31
31
  args: {
32
- source: SOURCE,
32
+ source: JSON.stringify(
33
+ [
34
+ {
35
+ label: 'Hey',
36
+ runs: [
37
+ { value: 1, name: 'a' },
38
+ { value: 2, name: 'b' },
39
+ ],
40
+ },
41
+ ],
42
+ null,
43
+ 2,
44
+ ),
33
45
  download: 'bundle-stats--assets.json',
34
46
  },
35
47
  };
@@ -50,7 +50,7 @@ export const PreviewSource = (props: PreviewSourceProps) => {
50
50
  )}
51
51
  </ControlGroup>
52
52
  )}
53
- <Textarea readOnly rows={rows} defaultValue={source} className={css.content} />
53
+ <Textarea readOnly rows={rows} value={source} className={css.content} />
54
54
  </div>
55
55
  );
56
56
  };
package/src/i18n.js CHANGED
@@ -22,6 +22,8 @@ export default {
22
22
  RESET_FILTERS: 'Reset filters',
23
23
  VIEW_ALL: 'View all entries',
24
24
  EXPORT: 'Export',
25
+ EXPORT_CSV: 'Export CSV',
26
+ EXPORT_JSON: 'Export JSON',
25
27
 
26
28
  COPY_TO_CLIPBOARD: 'Copy to clipboard',
27
29
  COPY_TO_CLIPBOARD_DONE: 'Copied to clipboard',
@@ -1,19 +1,25 @@
1
1
  import React from 'react';
2
2
  import { MemoryRouter } from 'react-router-dom';
3
3
 
4
- export const getWrapperDecorator = (customWrapperStyles = {}) => (storyFn) => {
5
- const wrapperStyles = {
6
- width: '100%',
7
- height: '100%',
8
- padding: '24px',
9
- ...customWrapperStyles,
10
- };
4
+ import { QueryStateProvider } from '../query-state';
5
+
6
+ export const getWrapperDecorator =
7
+ (customWrapperStyles = {}) =>
8
+ (Story) => {
9
+ const wrapperStyles = {
10
+ width: '100%',
11
+ height: '100%',
12
+ padding: '24px',
13
+ ...customWrapperStyles,
14
+ };
11
15
 
12
- return (
13
- <MemoryRouter initialEntries={[{ pathname: '/', key: 'home' }]}>
14
- <div style={wrapperStyles}>
15
- {storyFn()}
16
- </div>
17
- </MemoryRouter>
18
- );
19
- };
16
+ return (
17
+ <MemoryRouter initialEntries={[{ pathname: '/', key: 'home' }]}>
18
+ <QueryStateProvider>
19
+ <div style={wrapperStyles}>
20
+ <Story />
21
+ </div>
22
+ </QueryStateProvider>
23
+ </MemoryRouter>
24
+ );
25
+ };
package/src/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ReportMetricRow } from '@bundle-stats/utils';
2
- import type { Module } from '@bundle-stats/utils/types/webpack/types';
2
+ import type { Asset, Module } from '@bundle-stats/utils/types/webpack/types';
3
3
 
4
4
  export interface SortAction {
5
5
  field: string;
@@ -19,6 +19,35 @@ type FilterGroupFieldData = {
19
19
 
20
20
  type FilterFieldsData = Record<string, FilterFieldData | FilterGroupFieldData>;
21
21
 
22
+ export type ReportMetricAssetRowMetaStatus = 'added' | 'removed';
23
+
24
+ export type ReportMetricAssetRow = {
25
+ /**
26
+ * Asset isEntry - at least one run has isEntry truthy
27
+ */
28
+ isEntry: ReportMetricAssetRowMetaStatus | boolean;
29
+ /**
30
+ * Asset isInitial - at least one run has isInitial truthy
31
+ */
32
+ isInitial: ReportMetricAssetRowMetaStatus | boolean;
33
+ /**
34
+ * Asset isChunk - at least one run has isChunk truthy
35
+ */
36
+ isChunk: ReportMetricAssetRowMetaStatus | boolean;
37
+ /**
38
+ * Asset isAsset - at least one run has isAsset truthy
39
+ */
40
+ isAsset: boolean;
41
+ /**
42
+ * Asset name is not predictive
43
+ */
44
+ isNotPredictive: boolean;
45
+ /**
46
+ * Report asset row isEntry - at least one run has isEntry
47
+ */
48
+ fileType: string;
49
+ } & Omit<ReportMetricRow, 'runs'> & { runs: Array<(Asset & ReportMetricRun) | null> };
50
+
22
51
  export type ReportMetricModuleRow = {
23
52
  thirdParty: boolean;
24
53
  duplicated: boolean;
@@ -0,0 +1 @@
1
+ export * from './tabs';
@@ -4,13 +4,16 @@
4
4
  }
5
5
 
6
6
  .item {
7
+ appearance: none;
8
+ background: none;
9
+ border: 0;
7
10
  position: relative;
8
11
  display: inline-block;
9
12
  padding: var(--space-xsmall) var(--space-small);
10
13
  color: var(--color-text-ultra-light);
11
14
  font-weight: bold;
12
15
  text-decoration: none;
13
- cursor: default;
16
+ transition: var(--ui-transition-out);
14
17
  }
15
18
 
16
19
  .item::after {
@@ -27,8 +30,9 @@
27
30
  .item:hover,
28
31
  .item:active,
29
32
  .item:focus {
30
- color: var(--color-primary-dark);
33
+ color: var(--color-primary);
31
34
  outline: none;
35
+ transition: var(--ui-transition-out);
32
36
  }
33
37
 
34
38
  .item:hover::after,
@@ -44,7 +48,3 @@
44
48
  .itemActive::after {
45
49
  background: currentColor;
46
50
  }
47
-
48
- .item + .item {
49
- _margin-left: var(--space-medium);
50
- }
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { getWrapperDecorator } from '../../stories';
5
+ import { Tabs, TabItem } from '.';
6
+
7
+ const meta: Meta<typeof Tabs> = {
8
+ title: 'UI/Tabs',
9
+ component: Tabs,
10
+ decorators: [getWrapperDecorator()],
11
+ };
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ render: () => (
19
+ <Tabs>
20
+ <TabItem isTabActive>Option A</TabItem>
21
+ <TabItem>Option B</TabItem>
22
+ <TabItem>Option C</TabItem>
23
+ </Tabs>
24
+ ),
25
+ };
@@ -0,0 +1,32 @@
1
+ import type { ComponentProps, ElementType } from 'react';
2
+ import React from 'react';
3
+ import cx from 'classnames';
4
+
5
+ import css from './tabs.module.css';
6
+
7
+ export type TabItemProps<T extends ElementType> = {
8
+ isTabActive?: boolean;
9
+ as?: T;
10
+ } & ComponentProps<T>;
11
+
12
+ export const TabItem = <T extends ElementType = 'button'>(props: TabItemProps<T>) => {
13
+ const { className = '', as: Component = 'button', isTabActive = false, ...restProps } = props;
14
+
15
+ return (
16
+ <Component
17
+ role="tab"
18
+ className={cx(css.item, className, isTabActive && css.itemActive)}
19
+ {...restProps}
20
+ />
21
+ );
22
+ };
23
+
24
+ export type TabsProps = ComponentProps<'div'>;
25
+
26
+ export const Tabs = (props: TabsProps) => {
27
+ const { className = '', ...restProps } = props;
28
+
29
+ return <div role="tablist" className={cx(css.root, className)} {...restProps} />;
30
+ };
31
+
32
+ Tabs.Item = TabItem;
@@ -1,16 +1,17 @@
1
+ import type { ComponentProps } from 'react';
1
2
  import React from 'react';
2
3
  import cx from 'classnames';
3
4
 
4
5
  import { KIND, SIZE } from '../../tokens';
5
6
  import css from './tag.module.css';
6
7
 
7
- interface TagProps {
8
+ export type TagProps = {
8
9
  as?: React.ElementType;
9
10
  kind?: (typeof KIND)[keyof typeof KIND];
10
11
  size?: (typeof SIZE)[keyof typeof SIZE];
11
- }
12
+ } & ComponentProps<'span'>;
12
13
 
13
- export const Tag = (props: TagProps & React.ComponentProps<'span'>) => {
14
+ export const Tag = (props: TagProps) => {
14
15
  const {
15
16
  className = '',
16
17
  as: Component = 'span',
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { TagProps } from '../../ui/tag';
3
+ import type { ReportMetricAssetRowMetaStatus } from '../../types';
4
+ export type AssetMetaTagProps = {
5
+ tag: 'entry' | 'initial' | 'chunk';
6
+ status: ReportMetricAssetRowMetaStatus | boolean;
7
+ } & TagProps;
8
+ export declare const AssetMetaTag: (props: AssetMetaTagProps) => React.JSX.Element;
@@ -0,0 +1 @@
1
+ export * from './asset-meta-tag';
@@ -0,0 +1,8 @@
1
+ import React, { ElementType } from 'react';
2
+ import { ReportMetricAssetRow } from '../../types';
3
+ export type AssetNameProps = {
4
+ className?: string;
5
+ row: ReportMetricAssetRow;
6
+ customComponentLink: ElementType;
7
+ };
8
+ export declare const AssetName: (props: AssetNameProps) => React.JSX.Element;
@@ -0,0 +1 @@
1
+ export * from './asset-name';
@@ -1,8 +1,8 @@
1
+ import type { ComponentProps } from 'react';
1
2
  import React from 'react';
2
3
  import type { Asset } from '@bundle-stats/utils/types/webpack';
3
- interface AssetNotPredictiveProps {
4
+ export type AssetNotPredictiveProps = {
4
5
  runs?: Array<Asset>;
5
6
  labels?: Array<string>;
6
- }
7
- export declare const AssetNotPredictive: (props: AssetNotPredictiveProps & React.ComponentProps<"div">) => React.JSX.Element;
8
- export {};
7
+ } & ComponentProps<'div'>;
8
+ export declare const AssetNotPredictive: (props: AssetNotPredictiveProps) => React.JSX.Element;
@@ -1,5 +1,5 @@
1
- export function addRowAssetFlags(row: any): any;
2
- export function getIsNotPredictive(key: any, runs: any): any;
3
- export function addRowIsNotPredictive(row: any): any;
1
+ export function getIsNotPredictive(row: ReportMetricRow): boolean;
2
+ export function getAssetMetaStatus(values: any): ReportMetricAssetRowFlagStatus | boolean;
3
+ export function addMetricReportAssetRowData(row: ReportMetricRow): ReportMetricAssetRow;
4
4
  export function getRowFilter(filters: any): (item: any) => boolean;
5
5
  export function getCustomSort(item: any): any[];
@@ -4,6 +4,7 @@ import type { ReportMetricRow } from '@bundle-stats/utils';
4
4
  import { Stack } from '../../layout/stack';
5
5
  type MetricsTableExportProps = {
6
6
  items: Array<ReportMetricRow>;
7
+ initialSourceType?: string;
7
8
  download: string;
8
9
  } & ComponentProps<typeof Stack>;
9
10
  export declare const MetricsTableExport: (props: MetricsTableExportProps) => React.JSX.Element;
@@ -4,7 +4,7 @@ import { Dropdown } from '../../ui/dropdown';
4
4
  type MetricsTableOptionsProps = {
5
5
  onViewAllClick?: () => void;
6
6
  onResetClick?: () => void;
7
- onExportClick?: () => void;
7
+ onExportClick?: (sourceType: string) => void;
8
8
  } & ComponentProps<typeof Dropdown>;
9
9
  export declare const MetricsTableOptions: (props: MetricsTableOptionsProps) => React.JSX.Element;
10
10
  export {};
package/types/i18n.d.ts CHANGED
@@ -15,6 +15,8 @@ declare namespace _default {
15
15
  let RESET_FILTERS: string;
16
16
  let VIEW_ALL: string;
17
17
  let EXPORT: string;
18
+ let EXPORT_CSV: string;
19
+ let EXPORT_JSON: string;
18
20
  let COPY_TO_CLIPBOARD: string;
19
21
  let COPY_TO_CLIPBOARD_DONE: string;
20
22
  let GITHUB_LINK_TITLE: string;
@@ -1,2 +1,2 @@
1
- export function getWrapperDecorator(customWrapperStyles?: {}): (storyFn: any) => React.JSX.Element;
1
+ export function getWrapperDecorator(customWrapperStyles?: {}): (Story: any) => React.JSX.Element;
2
2
  import React from 'react';
@@ -1 +1 @@
1
- export { Tabs } from "./tabs";
1
+ export * from './tabs';