@bundle-stats/ui 4.13.4 → 4.14.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.
Files changed (68) hide show
  1. package/lib/components/asset-info/asset-info.js +1 -1
  2. package/lib/components/asset-info/asset-info.js.map +1 -1
  3. package/lib/components/bundle-modules/bundle-modules.js +16 -9
  4. package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
  5. package/lib/components/bundle-modules/bundle-modules.utils.js +18 -4
  6. package/lib/components/bundle-modules/bundle-modules.utils.js.map +1 -1
  7. package/lib/components/bundle-modules/index.js +9 -6
  8. package/lib/components/bundle-modules/index.js.map +1 -1
  9. package/lib/components/entry-info/entry-info.js +16 -9
  10. package/lib/components/entry-info/entry-info.js.map +1 -1
  11. package/lib/components/entry-info/entry-info.module.css +34 -8
  12. package/lib/components/module-info/module-info.js +80 -16
  13. package/lib/components/module-info/module-info.js.map +1 -1
  14. package/lib/components/module-info/module-info.module.css +38 -0
  15. package/lib/components/package-info/package-info.js +1 -1
  16. package/lib/components/package-info/package-info.js.map +1 -1
  17. package/lib/components/run-info/run-info.module.css +1 -1
  18. package/lib/constants.js +21 -1
  19. package/lib/constants.js.map +1 -1
  20. package/lib/hooks/rows-sort.js.map +1 -1
  21. package/lib-esm/components/asset-info/asset-info.js +1 -1
  22. package/lib-esm/components/asset-info/asset-info.js.map +1 -1
  23. package/lib-esm/components/bundle-modules/bundle-modules.js +17 -10
  24. package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
  25. package/lib-esm/components/bundle-modules/bundle-modules.utils.js +19 -4
  26. package/lib-esm/components/bundle-modules/bundle-modules.utils.js.map +1 -1
  27. package/lib-esm/components/bundle-modules/index.js +9 -6
  28. package/lib-esm/components/bundle-modules/index.js.map +1 -1
  29. package/lib-esm/components/entry-info/entry-info.js +16 -9
  30. package/lib-esm/components/entry-info/entry-info.js.map +1 -1
  31. package/lib-esm/components/entry-info/entry-info.module.css +34 -8
  32. package/lib-esm/components/module-info/module-info.js +84 -19
  33. package/lib-esm/components/module-info/module-info.js.map +1 -1
  34. package/lib-esm/components/module-info/module-info.module.css +38 -0
  35. package/lib-esm/components/package-info/package-info.js +1 -1
  36. package/lib-esm/components/package-info/package-info.js.map +1 -1
  37. package/lib-esm/components/run-info/run-info.module.css +1 -1
  38. package/lib-esm/constants.js +20 -0
  39. package/lib-esm/constants.js.map +1 -1
  40. package/lib-esm/hooks/rows-sort.js.map +1 -1
  41. package/package.json +9 -9
  42. package/src/components/asset-info/asset-info.tsx +5 -2
  43. package/src/components/bundle-modules/bundle-modules.tsx +40 -19
  44. package/src/components/bundle-modules/bundle-modules.utils.ts +37 -14
  45. package/src/components/bundle-modules/index.tsx +19 -15
  46. package/src/components/entry-info/entry-info.module.css +34 -8
  47. package/src/components/entry-info/entry-info.tsx +47 -32
  48. package/src/components/module-info/module-info.module.css +38 -0
  49. package/src/components/module-info/module-info.stories.tsx +57 -3
  50. package/src/components/module-info/module-info.tsx +221 -40
  51. package/src/components/package-info/package-info.tsx +2 -3
  52. package/src/components/run-info/run-info.module.css +1 -1
  53. package/src/constants.ts +22 -1
  54. package/src/hooks/rows-sort.ts +17 -10
  55. package/src/types.d.ts +13 -0
  56. package/types/components/bundle-modules/bundle-modules.d.ts +4 -5
  57. package/types/components/bundle-modules/bundle-modules.utils.d.ts +3 -5
  58. package/types/components/entry-info/entry-info.d.ts +8 -10
  59. package/types/components/module-info/module-info.d.ts +4 -10
  60. package/types/constants.d.ts +21 -2
  61. package/types/hooks/rows-sort.d.ts +9 -14
  62. package/lib/components/bundle-modules/bundle-modules.constants.js +0 -9
  63. package/lib/components/bundle-modules/bundle-modules.constants.js.map +0 -1
  64. package/lib-esm/components/bundle-modules/bundle-modules.constants.js +0 -6
  65. package/lib-esm/components/bundle-modules/bundle-modules.constants.js.map +0 -1
  66. package/src/components/bundle-modules/bundle-modules.constants.ts +0 -4
  67. package/src/components/bundle-modules/bundle-modules.types.d.ts +0 -9
  68. package/types/components/bundle-modules/bundle-modules.constants.d.ts +0 -4
@@ -3,7 +3,8 @@ import type { Job } from '@bundle-stats/utils';
3
3
  // @ts-ignore
4
4
  import * as webpack from '@bundle-stats/utils/lib-esm/webpack';
5
5
 
6
- import type { SortAction } from '../../types';
6
+ import { ModuleSizeMetric } from '../../constants';
7
+ import type { ReportMetricModuleRow, SortAction } from '../../types';
7
8
  import { getJobsChunksData } from '../../utils/jobs';
8
9
  import { useRowsFilter } from '../../hooks/rows-filter';
9
10
  import { useRowsSort } from '../../hooks/rows-sort';
@@ -16,26 +17,27 @@ import {
16
17
  generateFilters,
17
18
  getCustomSort,
18
19
  } from './bundle-modules.utils';
19
- import { ModuleMetric } from './bundle-modules.constants';
20
- import * as types from './bundle-modules.types';
21
20
 
22
21
  interface UseMetricParams {
23
22
  metric?: string;
24
- setState: ({ metric }: { metric: ModuleMetric }) => void;
23
+ setState: ({ metric }: { metric: ModuleSizeMetric }) => void;
25
24
  }
26
25
 
27
- function useModuleMetric(params: UseMetricParams): [ModuleMetric, (value: ModuleMetric) => void] {
26
+ function useModuleMetric(
27
+ params: UseMetricParams,
28
+ ): [ModuleSizeMetric, (value: ModuleSizeMetric) => void] {
28
29
  const { metric, setState } = params;
29
30
 
30
- const moduleMetric: ModuleMetric = useMemo(() => {
31
- if (Object.values(ModuleMetric).includes(metric as ModuleMetric)) {
32
- return metric as ModuleMetric;
31
+ const moduleMetric: ModuleSizeMetric = useMemo(() => {
32
+ if (Object.values(ModuleSizeMetric).includes(metric as ModuleSizeMetric)) {
33
+ return metric as ModuleSizeMetric;
33
34
  }
34
- return ModuleMetric.SIZE;
35
+
36
+ return ModuleSizeMetric.TOTAL_SIZE;
35
37
  }, [metric]);
36
38
 
37
39
  const setModuleMetric = useCallback(
38
- (newModuleMetric: ModuleMetric) => {
40
+ (newModuleMetric: ModuleSizeMetric) => {
39
41
  if (newModuleMetric !== metric) {
40
42
  setState({ metric: newModuleMetric });
41
43
  }
@@ -95,12 +97,14 @@ export const BundleModules = (props: BundleModulesProps) => {
95
97
  });
96
98
 
97
99
  const { rows, totalRowCount } = useMemo(() => {
98
- let result: Array<types.ReportMetricModuleRow> = [];
100
+ let result: Array<ReportMetricModuleRow> = [];
99
101
 
100
- if (moduleMetric === ModuleMetric.TOTAL_SIZE) {
101
- result = webpack.compareModuleDuplicateSize(jobs, [addRowFlags]);
102
- } else if (moduleMetric === ModuleMetric.SIZE) {
102
+ if (moduleMetric === ModuleSizeMetric.SIZE) {
103
103
  result = webpack.compareBySection.modules(jobs, [addRowFlags]);
104
+ } else if (moduleMetric === ModuleSizeMetric.DUPLICATE_SIZE) {
105
+ result = webpack.compareModuleDuplicateSize(jobs, [addRowFlags]);
106
+ } else {
107
+ result = webpack.compareModuleTotalSize(jobs, [addRowFlags]);
104
108
  }
105
109
 
106
110
  return {
@@ -114,7 +118,7 @@ export const BundleModules = (props: BundleModulesProps) => {
114
118
  searchPattern: searchParams.searchPattern,
115
119
  filters: searchParams.filters,
116
120
  getRowFilter: generateGetRowFilter({ chunkIds }),
117
- });
121
+ }) as Array<ReportMetricModuleRow>;
118
122
 
119
123
  const sortParams = useRowsSort({
120
124
  rows: filteredRows,
@@ -71,40 +71,66 @@
71
71
 
72
72
  .runs .runsColSize {
73
73
  text-align: right;
74
+ white-space: nowrap;
74
75
  }
75
76
 
76
77
  .size {
77
78
  font-family: var(--font-family-fixed);
78
79
  }
79
80
 
81
+ /**
82
+ * Meta element
83
+ */
84
+ .meta {}
85
+
80
86
  .metaLabel {
81
- padding: 2px 0;
82
- display: inline-block;
83
87
  margin-right: var(--space-xxxsmall);
84
- min-width: 6em;
88
+ min-width: 8em;
89
+ flex: 0 1 6em;
85
90
  color: var(--color-text-light);
86
91
  }
87
92
 
93
+ .metaLabelTooltip {
94
+ margin-left: var(--space-xxxsmall);
95
+ color: var(--color-text-ultra-light);
96
+ }
97
+
98
+ .metaContent {
99
+ padding: 1px 0;
100
+ flex: 0 1 auto;
101
+ }
102
+
88
103
  .metaLink {
89
- padding: 2px var(--space-xxxsmall);
104
+ padding: 1px var(--space-xxxsmall);
105
+ display: inline-block;
106
+ line-height: var(--line-height-heading);
90
107
  border-radius: var(--radius-small);
91
108
  background: var(--color-highlight);
92
109
  transition: var(--transition-out);
93
110
 
94
- overflow-wrap: break-word;
95
111
  text-decoration: none;
96
112
  text-transform: none;
97
113
  font-weight: normal;
114
+ max-width: 16em;
115
+ overflow: hidden;
116
+ white-space: nowrap;
117
+ text-overflow: ellipsis;
98
118
  }
99
119
 
100
- .metaLink + .metaLink {
101
- margin-left: var(--space-xxsmall);
120
+ .metaLink {
121
+ margin-right: var(--space-xxxsmall);
102
122
  }
103
123
 
104
124
  .metaLink:hover,
105
125
  .metaLink:active,
106
126
  .metaLink:focus {
107
- transition: var(--transition-in);
108
127
  background: var(--color-outline);
109
128
  color: var(--color-primary-dark);
110
129
  }
130
+
131
+ @media (min-width: 640px) {
132
+ .meta {
133
+ display: flex;
134
+ align-items: flex-start;
135
+ }
136
+ }
@@ -1,7 +1,9 @@
1
+ import type { ElementType, ReactNode } from 'react';
1
2
  import React from 'react';
2
3
  import cx from 'classnames';
3
4
  import { Portal } from 'ariakit/portal';
4
- import { METRIC_TYPE_CONFIGS, MetricRunInfo, getMetricRunInfo } from '@bundle-stats/utils';
5
+ import type { MetricRunInfo, ReportMetricRow } from '@bundle-stats/utils';
6
+ import { METRIC_TYPE_CONFIGS, getMetricRunInfo } from '@bundle-stats/utils';
5
7
 
6
8
  import { Box } from '../../layout/box';
7
9
  import { Stack } from '../../layout/stack';
@@ -12,9 +14,10 @@ import { Table } from '../../ui/table';
12
14
  import { RunInfo } from '../run-info';
13
15
  import * as I18N from './entry-info.i18n';
14
16
  import css from './entry-info.module.css';
17
+ import { Tooltip } from '../../ui';
15
18
 
16
19
  interface EntryInfoMetaLinkProps {
17
- as?: React.ElementType;
20
+ as?: ElementType;
18
21
  }
19
22
 
20
23
  export const EntryInfoMetaLink = (props: EntryInfoMetaLinkProps & React.ComponentProps<'a'>) => {
@@ -24,34 +27,60 @@ export const EntryInfoMetaLink = (props: EntryInfoMetaLinkProps & React.Componen
24
27
 
25
28
  interface EntryInfoMetaProps {
26
29
  label: string;
30
+ tooltip?: ReactNode;
27
31
  }
28
32
 
29
33
  const EntryInfoMeta = ({
30
34
  className = '',
31
35
  label,
36
+ tooltip,
32
37
  children,
33
38
  }: EntryInfoMetaProps & React.ComponentProps<'p'>) => (
34
- <p className={cx(css.meta, className)}>
35
- <span className={css.metaLabel}>{label}</span>
36
- <span className={css.metaContent}>{children}</span>
37
- </p>
39
+ <div className={cx(css.meta, className)}>
40
+ <span className={css.metaLabel}>
41
+ {label}
42
+ {tooltip && (
43
+ <Tooltip title={tooltip} className={css.metaLabelTooltip}>
44
+ <Icon glyph="help" />
45
+ </Tooltip>
46
+ )}
47
+ </span>
48
+ <div className={css.metaContent}>{children}</div>
49
+ </div>
38
50
  );
39
51
 
40
- interface EntryRun {
41
- name: string;
52
+ function defaultRenderRunInfo(item: ReportMetricRow) {
53
+ const baselineRun = item.runs.length > 1 ? item.runs?.[item.runs.length - 1] : null;
54
+
55
+ // Get the metric run info to handle added/removed cases when there are more than 2 jobs
56
+ const metricRunInfo = getMetricRunInfo(
57
+ METRIC_TYPE_CONFIGS.METRIC_TYPE_FILE_SIZE,
58
+ item.runs?.[0]?.value || 0,
59
+ baselineRun?.value || 0,
60
+ ) as MetricRunInfo;
61
+
62
+ return (
63
+ <RunInfo
64
+ current={metricRunInfo.displayValue}
65
+ delta={metricRunInfo.displayDeltaPercentage}
66
+ deltaPercentage={metricRunInfo.displayDelta}
67
+ deltaType={metricRunInfo.deltaType}
68
+ baseline={baselineRun?.displayValue || '0B'}
69
+ size="large"
70
+ />
71
+ );
42
72
  }
43
73
 
44
74
  interface EntryInfoProps {
45
75
  itemTitle?: React.ReactNode;
46
- item: {
47
- label: string;
48
- runs: Array<EntryRun & MetricRunInfo>;
49
- };
76
+ item: ReportMetricRow;
50
77
  labels: Array<string>;
51
78
  runNameSelector?: string;
52
79
  runNameLabel?: string;
80
+ runSizeLabel?: string;
53
81
  tags?: React.ReactNode;
54
82
  onClose: () => void;
83
+ renderRunInfo?: (item: ReportMetricRow) => React.ReactNode;
55
84
  }
56
85
 
57
86
  export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) => {
@@ -62,38 +91,22 @@ export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) =
62
91
  labels,
63
92
  runNameSelector = 'name',
64
93
  runNameLabel = I18N.PATH,
94
+ runSizeLabel = I18N.SIZE,
65
95
  children,
66
96
  tags = null,
67
97
  onClose,
98
+ renderRunInfo = defaultRenderRunInfo,
68
99
  } = props;
69
100
 
70
- const baselineRun = item.runs.length > 1 ? item.runs?.[item.runs.length - 1] : null;
71
-
72
- // Get the metric run info to handle added/removed cases
73
- const metricRunInfo = getMetricRunInfo(
74
- METRIC_TYPE_CONFIGS.METRIC_TYPE_FILE_SIZE,
75
- item.runs?.[0]?.value,
76
- baselineRun?.value || 0,
77
- ) as MetricRunInfo;
78
-
79
101
  return (
80
102
  <Portal className={cx(css.root, className)}>
81
103
  <Box padding="medium" as="header" className={css.header}>
82
104
  <Stack space="small">
83
- {tags && <div>{tags}</div>}
84
-
85
105
  <h3 className={css.label}>
86
106
  <FileName as="code" name={itemTitle || item.label} className={css.fileName} />
87
107
  </h3>
88
108
 
89
- <RunInfo
90
- current={metricRunInfo.displayValue}
91
- delta={metricRunInfo.displayDeltaPercentage}
92
- deltaPercentage={metricRunInfo.displayDelta}
93
- deltaType={metricRunInfo.deltaType}
94
- baseline={baselineRun?.displayValue || '0B'}
95
- size="large"
96
- />
109
+ <div>{renderRunInfo(item)}</div>
97
110
  </Stack>
98
111
  <Button
99
112
  radius="circle"
@@ -107,6 +120,8 @@ export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) =
107
120
  </Box>
108
121
  <Box padding="medium" as="main" className={css.contentWrapper}>
109
122
  <Stack space="small" className={css.content}>
123
+ {tags && <div>{tags}</div>}
124
+
110
125
  {children}
111
126
 
112
127
  <Table outline compact className={css.runs}>
@@ -114,7 +129,7 @@ export const EntryInfo = (props: EntryInfoProps & React.ComponentProps<'div'>) =
114
129
  <Table.Tr>
115
130
  <Table.Th className={cx(css.runsCell, css.runsColJob)}>&nbsp;</Table.Th>
116
131
  <Table.Th className={cx(css.runsCell, css.runsColName)}>{runNameLabel}</Table.Th>
117
- <Table.Th className={cx(css.runsCell, css.runsColSize)}>{I18N.SIZE}</Table.Th>
132
+ <Table.Th className={cx(css.runsCell, css.runsColSize)}>{runSizeLabel}</Table.Th>
118
133
  </Table.Tr>
119
134
  </Table.THead>
120
135
  <Table.TBody>
@@ -1,3 +1,41 @@
1
+ .moduleSizes {
2
+ flex-wrap: wrap;
3
+ }
4
+
1
5
  .chunksItems {
2
6
  display: inline;
3
7
  }
8
+
9
+ .chunksItem-info {
10
+ color: var(--color-info);
11
+ }
12
+
13
+ .chunksItem-info:hover,
14
+ .chunksItem-info:active,
15
+ .chunksItem-info:focus {
16
+ color: var(--color-info-dark);
17
+ }
18
+
19
+ .chunksItem-danger {
20
+ color: var(--color-danger);
21
+ }
22
+
23
+ .chunksItem-danger:hover,
24
+ .chunksItem-danger:active,
25
+ .chunksItem-danger:focus {
26
+ color: var(--color-danger-dark);
27
+ }
28
+
29
+ .chunksItem-default {
30
+ color: var(--color-text-light);
31
+ }
32
+
33
+ .chunksItem-default:hover,
34
+ .chunksItem-default:active,
35
+ .chunksItem-default:focus {
36
+ color: var(--color-text);
37
+ }
38
+
39
+ .duplicateInstances {
40
+ padding: 2px 0; /* compensate for the Entry Label padding */
41
+ }
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ // eslint-disable-next-line import/no-extraneous-dependencies
3
+ import { action } from '@storybook/addon-actions';
2
4
 
3
5
  import { getWrapperDecorator } from '../../stories';
4
6
  import { ModuleInfo } from '.';
@@ -17,12 +19,12 @@ export const Default = () => (
17
19
  runs: [
18
20
  {
19
21
  name: './node_modules/lodash/fp/merge.js',
20
- chunkIds: ['1', '2'],
22
+ chunkIds: ['1'],
21
23
  value: 1024 * 4,
22
24
  },
23
25
  {
24
26
  name: './node_modules/lodash/fp/merge.js',
25
- chunkIds: ['1', '2'],
27
+ chunkIds: ['1'],
26
28
  value: 1024 * 3,
27
29
  displayValue: '3KiB',
28
30
  },
@@ -37,8 +39,60 @@ export const Default = () => (
37
39
  id: '2',
38
40
  name: 'chunk-2',
39
41
  },
42
+ {
43
+ id: '3',
44
+ name: 'chunk-3',
45
+ },
46
+ ]}
47
+ chunkIds={['1', '2', '3']}
48
+ labels={['Job #2', 'Job #1']}
49
+ onClose={action('CLOSE')}
50
+ />
51
+ );
52
+
53
+ export const Duplicates = () => (
54
+ <ModuleInfo
55
+ item={{
56
+ label: './node_modules/lodash/fp/merge.js',
57
+ duplicated: true,
58
+ runs: [
59
+ {
60
+ name: './node_modules/lodash/fp/merge.js',
61
+ chunkIds: ['1', '2', '3', '5'],
62
+ value: 1024 * 4,
63
+ },
64
+ {
65
+ name: './node_modules/lodash/fp/merge.js',
66
+ chunkIds: ['1', '2', '4'],
67
+ value: 1024 * 3,
68
+ displayValue: '3KiB',
69
+ },
70
+ ] as any,
71
+ }}
72
+ chunks={[
73
+ {
74
+ id: '1',
75
+ name: 'chunk-1',
76
+ },
77
+ {
78
+ id: '2',
79
+ name: 'chunk-2',
80
+ },
81
+ {
82
+ id: '3',
83
+ name: 'chunk-3',
84
+ },
85
+ {
86
+ id: '4',
87
+ name: 'chunk-4',
88
+ },
89
+ {
90
+ id: '5',
91
+ name: 'chunk-5',
92
+ },
40
93
  ]}
41
- chunkIds={['1', '2']}
94
+ chunkIds={['1', '2', '3', '4', '5']}
42
95
  labels={['Job #2', 'Job #1']}
96
+ onClose={action('CLOSE')}
43
97
  />
44
98
  );