@bundle-stats/ui 4.22.2-beta.1 → 4.22.3

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 (89) hide show
  1. package/.babelrc.js +65 -24
  2. package/globals.d.ts +13 -0
  3. package/lib/components/bundle-modules/index.js.map +1 -1
  4. package/lib/components/index.js.map +1 -1
  5. package/lib/components/metrics-table-header/metrics-table-header.js +2 -2
  6. package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -1
  7. package/lib/css/default.css +1 -1
  8. package/lib/hooks/rows-sort.js +13 -12
  9. package/lib/hooks/rows-sort.js.map +1 -1
  10. package/lib/ui/button/button.js.map +1 -1
  11. package/lib/ui/empty-set/empty-set.js +3 -3
  12. package/lib/ui/empty-set/empty-set.js.map +1 -1
  13. package/lib-esm/components/bundle-modules/index.js.map +1 -1
  14. package/lib-esm/components/index.js.map +1 -1
  15. package/lib-esm/components/metrics-table-header/metrics-table-header.js +2 -2
  16. package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -1
  17. package/lib-esm/css/default.css +1 -1
  18. package/lib-esm/hooks/rows-sort.js +10 -8
  19. package/lib-esm/hooks/rows-sort.js.map +1 -1
  20. package/lib-esm/ui/button/button.js.map +1 -1
  21. package/lib-esm/ui/empty-set/empty-set.js +3 -3
  22. package/lib-esm/ui/empty-set/empty-set.js.map +1 -1
  23. package/package.json +26 -15
  24. package/src/app/app.stories.tsx +2 -2
  25. package/src/components/asset-info/asset-info.stories.tsx +47 -39
  26. package/src/components/asset-name/asset-name.stories.tsx +1 -3
  27. package/src/components/asset-not-predictive/asset-not-predictive.stories.tsx +22 -15
  28. package/src/components/browsertime-table/browsertime-table.stories.tsx +45 -0
  29. package/src/components/bundle-assets-totals/bundle-assets-totals.stories.tsx +47 -0
  30. package/src/components/bundle-modules/bundle-modules.stories.tsx +191 -0
  31. package/src/components/bundle-modules/bundle-modules.tsx +1 -1
  32. package/src/components/bundle-modules/index.tsx +4 -0
  33. package/src/components/bundle-packages/bundle-packages.stories.tsx +87 -0
  34. package/src/components/delta/delta.stories.tsx +57 -0
  35. package/src/components/entry-info/entry-info.stories.tsx +49 -54
  36. package/src/components/{index.js → index.ts} +4 -2
  37. package/src/components/insights/insights.stories.tsx +36 -33
  38. package/src/components/job-name/job-name.stories.tsx +46 -0
  39. package/src/components/jobs-header/jobs-header.stories.tsx +19 -15
  40. package/src/components/lighthouse-table/lighthouse-table.stories.tsx +30 -0
  41. package/src/components/metric/metric.stories.tsx +24 -22
  42. package/src/components/metric-run-info/metric-run-info.stories.tsx +45 -41
  43. package/src/components/metrics-table/metrics-table.stories.tsx +33 -13
  44. package/src/components/metrics-table/metrics-table.tsx +1 -1
  45. package/src/components/metrics-table-header/metrics-table-header.tsx +9 -4
  46. package/src/components/module-info/module-info.stories.tsx +41 -30
  47. package/src/components/package-info/package-info.stories.tsx +20 -15
  48. package/src/components/run-info/run-info.stories.tsx +39 -37
  49. package/src/components/summary/summary.stories.tsx +26 -32
  50. package/src/css/default.css +1 -1
  51. package/src/hooks/rows-sort.ts +9 -6
  52. package/src/layout/box/box.stories.tsx +35 -28
  53. package/src/layout/flex-stack/flex-stack.stories.tsx +79 -48
  54. package/src/layout/footer/footer.stories.tsx +30 -0
  55. package/src/layout/stack/stack.stories.tsx +68 -44
  56. package/src/ui/alert/alert.stories.tsx +25 -21
  57. package/src/ui/button/button.stories.tsx +181 -176
  58. package/src/ui/button/button.tsx +8 -1
  59. package/src/ui/container/container.stories.tsx +28 -21
  60. package/src/ui/control-group/control-group.stories.tsx +23 -16
  61. package/src/ui/dropdown/dropdown.stories.tsx +23 -15
  62. package/src/ui/empty-set/empty-set.jsx +16 -4
  63. package/src/ui/empty-set/empty-set.stories.tsx +41 -0
  64. package/src/ui/file-name/file-name.stories.tsx +45 -0
  65. package/src/ui/filters/filters.stories.tsx +29 -26
  66. package/src/ui/hover-card/hover-card.stories.tsx +35 -26
  67. package/src/ui/icon/icon.stories.tsx +36 -28
  68. package/src/ui/input/input.stories.tsx +17 -5
  69. package/src/ui/input-search/input-search.stories.tsx +31 -0
  70. package/src/ui/loader/loader.stories.tsx +22 -0
  71. package/src/ui/skeleton/skeleton.stories.tsx +42 -0
  72. package/src/ui/table/table.stories.tsx +244 -218
  73. package/src/ui/tag/tag.stories.tsx +11 -10
  74. package/src/ui/toolbar/toolbar.stories.tsx +41 -0
  75. package/types/components/bundle-modules/bundle-modules.d.ts +1 -1
  76. package/types/components/bundle-modules/index.d.ts +2 -1
  77. package/types/components/index.d.ts +22 -20
  78. package/types/components/metrics-table/metrics-table.d.ts +1 -1
  79. package/types/components/metrics-table-header/metrics-table-header.d.ts +1 -1
  80. package/types/hooks/rows-sort.d.ts +2 -2
  81. package/types/ui/button/button.d.ts +1 -1
  82. package/vitest.config.ts +47 -0
  83. package/vitest.setup.ts +26 -0
  84. package/lib/assets/icons.svg.js +0 -100
  85. package/lib/assets/icons.svg.js.map +0 -1
  86. package/lib-esm/assets/icons.svg.js +0 -63
  87. package/lib-esm/assets/icons.svg.js.map +0 -1
  88. package/src/assets/icons.svg.jsx +0 -279
  89. package/types/assets/icons.svg.d.ts +0 -2
@@ -1,23 +1,20 @@
1
- import React from 'react';
2
- import { Meta, Story } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react';
3
2
  import { action } from 'storybook/actions';
4
3
 
5
4
  import { getWrapperDecorator } from '../../stories';
6
5
  import { AssetInfo } from '.';
7
6
 
8
- export default {
9
- title: 'Components/AssetInfo',
10
- component: AssetInfo,
11
- decorators: [getWrapperDecorator()],
12
- } as Meta;
13
-
14
7
  const ITEM = {
8
+ key: 'static/vendor.js',
15
9
  label: 'static/vendor.js',
10
+ biggerIsBetter: false,
16
11
  changed: true,
12
+ isAsset: true,
17
13
  isChunk: true,
18
14
  isEntry: true,
19
15
  isInitial: true,
20
16
  isNotPredictive: false,
17
+ fileType: '',
21
18
  runs: [
22
19
  {
23
20
  name: 'static/vendor.abcd1234.js',
@@ -33,42 +30,53 @@ const ITEM = {
33
30
  ],
34
31
  };
35
32
 
36
- const Template = (props: Pick<React.ComponentProps<typeof AssetInfo>, 'chunks'>) => (
37
- <AssetInfo item={ITEM} labels={['Job #2', 'Job #1']} onClose={action('CLOSE')} {...props} />
38
- );
33
+ const meta = {
34
+ title: 'Components/AssetInfo',
35
+ component: AssetInfo,
36
+ decorators: [getWrapperDecorator()],
37
+ args: {
38
+ item: ITEM,
39
+ labels: ['Job #2', 'Job #1'],
40
+ onClose: action('CLOSE'),
41
+ },
42
+ } satisfies Meta<typeof AssetInfo>;
39
43
 
40
- export const Default: Story = Template.bind({});
44
+ export default meta;
41
45
 
42
- export const WithChunks: Story = Template.bind({});
46
+ type Story = StoryObj<typeof meta>;
43
47
 
44
- WithChunks.args = {
45
- chunks: [
46
- {
47
- id: '1',
48
- name: 'vendor',
49
- },
50
- {
51
- id: '2',
52
- name: 'app~common~utils~shared',
53
- },
54
- ],
55
- };
48
+ export const Default: Story = {};
56
49
 
57
- export const WithFileType: Story = Template.bind({});
50
+ export const WithChunks: Story = {
51
+ args: {
52
+ chunks: [
53
+ {
54
+ id: '1',
55
+ name: 'vendor',
56
+ },
57
+ {
58
+ id: '2',
59
+ name: 'app~common~utils~shared',
60
+ },
61
+ ],
62
+ },
63
+ };
58
64
 
59
- WithFileType.args = {
60
- chunks: [
61
- {
62
- id: '1',
63
- name: 'vendor',
65
+ export const WithFileType: Story = {
66
+ args: {
67
+ chunks: [
68
+ {
69
+ id: '1',
70
+ name: 'vendor',
71
+ },
72
+ {
73
+ id: '2',
74
+ name: 'app~common~utils~shared',
75
+ },
76
+ ],
77
+ item: {
78
+ ...ITEM,
79
+ fileType: 'JS',
64
80
  },
65
- {
66
- id: '2',
67
- name: 'app~common~utils~shared',
68
- },
69
- ],
70
- item: {
71
- ...ITEM,
72
- fileType: 'JS',
73
81
  },
74
82
  };
@@ -23,9 +23,7 @@ const meta = {
23
23
  title: 'Components/AssetName',
24
24
  component: AssetName,
25
25
  args: {
26
- customComponentLink: 'span',
27
- filters: {},
28
- search: '',
26
+ EntryComponentLink: 'span',
29
27
  },
30
28
  } as Meta<typeof AssetName>;
31
29
 
@@ -1,23 +1,30 @@
1
- import React from 'react';
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import { AssetNotPredictive } from '.';
4
4
 
5
- export default {
5
+ const meta = {
6
6
  title: 'Components/AssetNotPredictive',
7
7
  component: AssetNotPredictive,
8
- };
8
+ } satisfies Meta<typeof AssetNotPredictive>;
9
9
 
10
- export const Default = () => <AssetNotPredictive />;
10
+ export default meta;
11
11
 
12
- const RUNS = [
13
- {
14
- name: 'static/vendor.abcd1234.js',
15
- value: 1024 * 1024 - 1,
16
- },
17
- {
18
- name: 'static/vendor.abcd1234.js',
19
- value: 1024 * 1024,
20
- },
21
- ] as any;
12
+ type Story = StoryObj<typeof meta>;
22
13
 
23
- export const WithRuns = () => <AssetNotPredictive runs={RUNS} labels={['Job 2', 'Job 1']} />;
14
+ export const Default: Story = {};
15
+
16
+ export const WithRuns: Story = {
17
+ args: {
18
+ runs: [
19
+ {
20
+ name: 'static/vendor.abcd1234.js',
21
+ value: 1024 * 1024 - 1,
22
+ },
23
+ {
24
+ name: 'static/vendor.abcd1234.js',
25
+ value: 1024 * 1024,
26
+ },
27
+ ] as any,
28
+ labels: ['Job 2', 'Job 1'],
29
+ },
30
+ };
@@ -0,0 +1,45 @@
1
+ import type React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { createJobs, Job } from '@bundle-stats/utils';
4
+ import * as browsertime from '@bundle-stats/utils/lib-esm/browsertime';
5
+
6
+ // eslint-disable-next-line import/no-relative-packages
7
+ import browsertimeSourceFixtures from '../../../../../fixtures/browsertime.json';
8
+ import { getWrapperDecorator } from '../../stories';
9
+ import { BrowsertimeTable } from '.';
10
+
11
+ const browsertimeFixtures = browsertime.filter(browsertimeSourceFixtures);
12
+
13
+ const JOBS = createJobs([
14
+ { browsertime: browsertimeFixtures },
15
+ { browsertime: browsertimeFixtures },
16
+ ]);
17
+
18
+ // BrowsertimeTable is a plain .jsx component with defaultProps instead of
19
+ // inline destructuring defaults, so TS can't infer its props as optional on its own.
20
+ const TypedBrowsertimeTable = BrowsertimeTable as unknown as React.ComponentType<{
21
+ className?: string;
22
+ jobs?: Array<Job>;
23
+ }>;
24
+
25
+ const meta = {
26
+ title: 'Components/BrowsertimeTable',
27
+ component: TypedBrowsertimeTable,
28
+ decorators: [getWrapperDecorator()],
29
+ } satisfies Meta<typeof TypedBrowsertimeTable>;
30
+
31
+ export default meta;
32
+
33
+ type Story = StoryObj<typeof meta>;
34
+
35
+ export const Default: Story = {
36
+ args: {
37
+ jobs: JOBS,
38
+ },
39
+ };
40
+
41
+ export const NoBaseline: Story = {
42
+ args: {
43
+ jobs: [JOBS[1]],
44
+ },
45
+ };
@@ -0,0 +1,47 @@
1
+ import type React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { createJobs, Job } from '@bundle-stats/utils';
4
+
5
+ /* eslint-disable import/no-relative-packages */
6
+ import baselineStats from '../../../../../fixtures/webpack-stats.baseline.json';
7
+ import currentStats from '../../../../../fixtures/webpack-stats.current.json';
8
+ /* eslint-enable import/no-relative-packages */
9
+ import { getWrapperDecorator } from '../../stories';
10
+ import { BundleAssetsTotals } from '.';
11
+
12
+ // BundleAssetsTotals is a plain .jsx component with defaultProps instead of
13
+ // inline destructuring defaults, so TS can't infer its props as optional on its own.
14
+ const TypedBundleAssetsTotals = BundleAssetsTotals as unknown as React.ComponentType<{
15
+ className?: string;
16
+ jobs?: Array<Job>;
17
+ customComponentLink?: React.ElementType;
18
+ onTreemapItemClick?: (entryId: string) => void;
19
+ }>;
20
+
21
+ const meta = {
22
+ title: 'Components/BundleAssetsTotals',
23
+ component: TypedBundleAssetsTotals,
24
+ decorators: [getWrapperDecorator()],
25
+ } satisfies Meta<typeof TypedBundleAssetsTotals>;
26
+
27
+ export default meta;
28
+
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ export const SingleJob: Story = {
32
+ args: {
33
+ jobs: createJobs([{ webpack: currentStats }]),
34
+ },
35
+ };
36
+
37
+ export const MultipleJobs: Story = {
38
+ args: {
39
+ jobs: createJobs([{ webpack: currentStats }, { webpack: baselineStats }]),
40
+ },
41
+ };
42
+
43
+ export const EmptyBaseline: Story = {
44
+ args: {
45
+ jobs: createJobs([{ webpack: currentStats }, {}]),
46
+ },
47
+ };
@@ -0,0 +1,191 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { createJobs } from '@bundle-stats/utils';
3
+
4
+ /* eslint-disable import/no-relative-packages */
5
+ import baselineStatsFixtures from '../../../../../fixtures/webpack-stats.baseline.json';
6
+ import currentStatsFixtures from '../../../../../fixtures/webpack-stats.current.json';
7
+ /* eslint-enable import/no-relative-packages */
8
+ import { getWrapperDecorator } from '../../stories';
9
+ import { BundleModules } from '.';
10
+
11
+ // Limit the side of the modules when not in dev mode (chromatic limit, snapshot too large)
12
+ const { baselineStats, currentStats } =
13
+ process.env.NODE_ENV !== 'development'
14
+ ? {
15
+ // eslint-disable-next-line prefer-object-spread
16
+ baselineStats: Object.assign({}, baselineStatsFixtures, {
17
+ modules: baselineStatsFixtures.modules.slice(0, 100),
18
+ }),
19
+ // eslint-disable-next-line prefer-object-spread
20
+ currentStats: Object.assign({}, currentStatsFixtures, {
21
+ modules: currentStatsFixtures.modules.slice(0, 100),
22
+ }),
23
+ }
24
+ : { baselineStats: baselineStatsFixtures, currentStats: currentStatsFixtures };
25
+
26
+ const JOBS = createJobs([{ webpack: currentStats }, { webpack: baselineStats }]);
27
+
28
+ const meta = {
29
+ title: 'Components/BundleModules',
30
+ component: BundleModules,
31
+ decorators: [getWrapperDecorator()],
32
+ args: {
33
+ filters: {},
34
+ setState: () => {},
35
+ },
36
+ } satisfies Meta<typeof BundleModules>;
37
+
38
+ export default meta;
39
+
40
+ type Story = StoryObj<typeof meta>;
41
+
42
+ export const Default: Story = {
43
+ args: {
44
+ jobs: [JOBS[1]],
45
+ },
46
+ };
47
+
48
+ export const MultipleJobs: Story = {
49
+ args: {
50
+ jobs: JOBS,
51
+ },
52
+ };
53
+
54
+ const JOBS_EMPTY_BASELINE = createJobs([{ webpack: currentStats }, {}]);
55
+
56
+ export const EmptyBaseline: Story = {
57
+ args: {
58
+ jobs: JOBS_EMPTY_BASELINE,
59
+ },
60
+ };
61
+
62
+ // Module moved between chunks
63
+ const JOBS_MOVED_MODULE = createJobs([
64
+ {
65
+ webpack: {
66
+ chunks: [
67
+ {
68
+ id: 1,
69
+ names: ['chunk-1'],
70
+ },
71
+ {
72
+ id: 2,
73
+ names: ['chunk-2'],
74
+ },
75
+ ],
76
+ modules: [
77
+ {
78
+ name: 'module-1a.js',
79
+ size: 1100,
80
+ chunks: [1],
81
+ },
82
+ {
83
+ name: 'module-1b.js',
84
+ size: 1200,
85
+ chunks: [1],
86
+ },
87
+ {
88
+ name: 'module-moved-from-chunk-2-to-1.js',
89
+ size: 2300,
90
+ chunks: [1],
91
+ },
92
+ {
93
+ name: 'module-2b.js',
94
+ size: 2200,
95
+ chunks: [2],
96
+ },
97
+ {
98
+ name: 'module-moved-from-chunk-3-to-1.js',
99
+ size: 3300,
100
+ chunks: [1],
101
+ },
102
+ ],
103
+ },
104
+ },
105
+ {
106
+ webpack: {
107
+ chunks: [
108
+ {
109
+ id: 1,
110
+ names: ['chunk-1'],
111
+ },
112
+ {
113
+ id: 2,
114
+ names: ['chunk-2'],
115
+ },
116
+ {
117
+ id: 3,
118
+ names: ['chunk-3'],
119
+ },
120
+ ],
121
+ modules: [
122
+ {
123
+ name: 'module-1a.js',
124
+ size: 1000,
125
+ chunks: [1],
126
+ },
127
+ {
128
+ name: 'module-1b.js',
129
+ size: 1100,
130
+ chunks: [1],
131
+ },
132
+ {
133
+ name: 'module-moved-from-chunk-2-to-1.js',
134
+ size: 2000,
135
+ chunks: [2],
136
+ },
137
+ {
138
+ name: 'module-2b.js',
139
+ size: 2200,
140
+ chunks: [2],
141
+ },
142
+ {
143
+ name: 'module-moved-from-chunk-3-to-1.js',
144
+ size: 3300,
145
+ chunks: [3],
146
+ },
147
+ {
148
+ name: 'module-removed-from-all-chunks.js',
149
+ size: 3300,
150
+ chunks: [3],
151
+ },
152
+ ],
153
+ },
154
+ },
155
+ ]);
156
+
157
+ export const ChunkFiltersWithModuleMovedIn: Story = {
158
+ args: {
159
+ filters: {
160
+ changed: false,
161
+ 'c.1': true,
162
+ 'c.2': false,
163
+ 'c.3': false,
164
+ },
165
+ jobs: [...JOBS_MOVED_MODULE],
166
+ },
167
+ };
168
+
169
+ export const ChunkFiltersWithModuleMovedOut: Story = {
170
+ args: {
171
+ filters: {
172
+ changed: false,
173
+ 'c.1': false,
174
+ 'c.2': true,
175
+ 'c.3': false,
176
+ },
177
+ jobs: [...JOBS_MOVED_MODULE],
178
+ },
179
+ };
180
+
181
+ export const ChunkFiltersWithRemovedChunk: Story = {
182
+ args: {
183
+ filters: {
184
+ changed: false,
185
+ 'c.1': false,
186
+ 'c.2': false,
187
+ 'c.3': true,
188
+ },
189
+ jobs: [...JOBS_MOVED_MODULE],
190
+ },
191
+ };
@@ -164,7 +164,7 @@ interface BundleModulesProps extends React.ComponentProps<'div'> {
164
164
  moduleMetric: ModuleSizeMetric;
165
165
  setModuleMetric: (newValue: ModuleSizeMetric) => void;
166
166
 
167
- customComponentLink: React.ElementType;
167
+ customComponentLink?: React.ElementType;
168
168
  }
169
169
 
170
170
  export const BundleModules = (props: BundleModulesProps) => {
@@ -65,6 +65,9 @@ interface BundleModulesProps extends Omit<
65
65
  | 'totalRowCount'
66
66
  | 'hideEntryInfo'
67
67
  | 'showEntryInfo'
68
+ | 'moduleMetric'
69
+ | 'setModuleMetric'
70
+ | 'customComponentLink'
68
71
  > {
69
72
  jobs: Array<Job>;
70
73
  filters: Record<string, boolean>;
@@ -73,6 +76,7 @@ interface BundleModulesProps extends Omit<
73
76
  setState: (params: any) => void;
74
77
  sortBy?: string;
75
78
  direction?: SortAction['direction'];
79
+ customComponentLink?: React.ElementType;
76
80
  }
77
81
 
78
82
  export const BundleModules = (props: BundleModulesProps) => {
@@ -0,0 +1,87 @@
1
+ import type React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import merge from 'lodash/merge';
4
+ import set from 'lodash/set';
5
+ import { PACKAGE_FILTERS, createJobs, Job } from '@bundle-stats/utils';
6
+
7
+ /* eslint-disable import/no-relative-packages */
8
+ import baselineStats from '../../../../../fixtures/webpack-stats.baseline.json';
9
+ import currentStats from '../../../../../fixtures/webpack-stats.current.json';
10
+ /* eslint-enable import/no-relative-packages */
11
+ import { getWrapperDecorator } from '../../stories';
12
+ import { BundlePackages } from '.';
13
+
14
+ const JOBS = createJobs([{ webpack: currentStats }, { webpack: baselineStats }]);
15
+ const [currentJob, baselineJob] = JOBS;
16
+
17
+ // BundlePackages is a plain .jsx component with no inline destructuring
18
+ // defaults, so TS can't infer its optional props on its own.
19
+ const TypedBundlePackages = BundlePackages as unknown as React.ComponentType<{
20
+ jobs: Array<Job>;
21
+ filters?: Record<string, boolean>;
22
+ search?: string;
23
+ sortBy?: string;
24
+ direction?: string;
25
+ setState: (params: any) => void;
26
+ }>;
27
+
28
+ const meta = {
29
+ title: 'Components/BundlePackages',
30
+ component: TypedBundlePackages,
31
+ decorators: [getWrapperDecorator()],
32
+ args: {
33
+ setState: () => {},
34
+ },
35
+ } satisfies Meta<typeof TypedBundlePackages>;
36
+
37
+ export default meta;
38
+
39
+ type Story = StoryObj<typeof meta>;
40
+
41
+ export const Default: Story = {
42
+ args: {
43
+ jobs: [baselineJob],
44
+ },
45
+ };
46
+
47
+ export const MultipleJobs: Story = {
48
+ args: {
49
+ jobs: JOBS,
50
+ },
51
+ };
52
+
53
+ export const CustomFilters: Story = {
54
+ args: {
55
+ jobs: JOBS,
56
+ filters: {
57
+ [PACKAGE_FILTERS.CHANGED]: false,
58
+ [PACKAGE_FILTERS.DUPLICATE]: true,
59
+ },
60
+ },
61
+ };
62
+
63
+ export const EmptyPackages: Story = {
64
+ args: {
65
+ jobs: [
66
+ set(merge({}, currentJob), 'metrics.webpack.packages', {}),
67
+ set(merge({}, baselineJob), 'metrics.webpack.packages', {}),
68
+ ],
69
+ },
70
+ };
71
+
72
+ export const EmptyFilteredPackages: Story = {
73
+ args: {
74
+ jobs: [
75
+ set(merge({}, currentJob), 'metrics.webpack.packages', { 'package-a': { value: 100 } }),
76
+ set(merge({}, baselineJob), 'metrics.webpack.packages', { 'package-a': { value: 100 } }),
77
+ ],
78
+ },
79
+ };
80
+
81
+ const JOBS_EMPTY_BASELINE = createJobs([{ webpack: currentStats }, { webpack: null }]);
82
+
83
+ export const EmptyBaseline: Story = {
84
+ args: {
85
+ jobs: JOBS_EMPTY_BASELINE,
86
+ },
87
+ };
@@ -0,0 +1,57 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { getWrapperDecorator } from '../../stories';
4
+ import { Delta } from '.';
5
+
6
+ const meta = {
7
+ title: 'Components/Delta',
8
+ component: Delta,
9
+ decorators: [getWrapperDecorator()],
10
+ } satisfies Meta<typeof Delta>;
11
+
12
+ export default meta;
13
+
14
+ type Story = StoryObj<typeof meta>;
15
+
16
+ export const Default: Story = {
17
+ args: {
18
+ displayValue: '20%',
19
+ deltaType: 'POSITIVE',
20
+ },
21
+ };
22
+
23
+ export const Negative: Story = {
24
+ args: {
25
+ displayValue: '20%',
26
+ deltaType: 'NEGATIVE',
27
+ },
28
+ };
29
+
30
+ export const SlightlyNegative: Story = {
31
+ args: {
32
+ displayValue: '1%',
33
+ deltaType: 'LOW_NEGATIVE',
34
+ },
35
+ };
36
+
37
+ export const SlightlyPositive: Story = {
38
+ args: {
39
+ displayValue: '1%',
40
+ deltaType: 'LOW_POSITIVE',
41
+ },
42
+ };
43
+
44
+ export const Empty: Story = {
45
+ args: {
46
+ displayValue: '0%',
47
+ deltaType: 'NO_CHANGE',
48
+ },
49
+ };
50
+
51
+ export const Inverted: Story = {
52
+ args: {
53
+ displayValue: '1%',
54
+ deltaType: 'LOW_NEGATIVE',
55
+ inverted: true,
56
+ },
57
+ };