@bundle-stats/ui 3.2.1-beta.9 → 3.3.0-alpha.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 (124) hide show
  1. package/CHANGELOG.md +47 -1
  2. package/lib/app/app.js +31 -6
  3. package/lib/app/app.stories.js +31 -3
  4. package/lib/assets/icons/alert-circle.svg +1 -0
  5. package/lib/assets/icons/arrow-right-circle.svg +1 -0
  6. package/lib/assets/icons/check-circle.svg +1 -0
  7. package/lib/assets/icons/close.svg +1 -1
  8. package/lib/assets/icons.svg +50 -1
  9. package/lib/components/browsertime-table/browsertime-table.js +1 -1
  10. package/lib/components/browsertime-table/browsertime-table.stories.js +1 -1
  11. package/lib/components/budget-info/budget-info.js +53 -0
  12. package/lib/components/budget-info/budget-info.module.css +28 -0
  13. package/lib/components/budget-info/budget-info.stories.js +42 -0
  14. package/lib/components/budget-info/index.js +18 -0
  15. package/lib/components/budget-insights/budget-insights.js +200 -0
  16. package/lib/components/budget-insights/budget-insights.module.css +53 -0
  17. package/lib/components/budget-insights/budget-insights.stories.js +104 -0
  18. package/lib/components/budget-insights/index.js +18 -0
  19. package/lib/components/bundle-assets/bundle-assets.js +3 -3
  20. package/lib/components/bundle-assets/bundle-assets.utils.js +2 -2
  21. package/lib/components/bundle-assets/index.js +3 -3
  22. package/lib/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.js +1 -1
  23. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.js +45 -8
  24. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +2 -2
  25. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.stories.js +58 -43
  26. package/lib/components/bundle-modules/bundle-modules.js +3 -3
  27. package/lib/components/bundle-modules/bundle-modules.utils.js +2 -2
  28. package/lib/components/bundle-modules/index.js +3 -3
  29. package/lib/components/bundle-packages/bundle-packages.js +1 -1
  30. package/lib/components/bundle-packages/bundle-packages.utils.js +2 -2
  31. package/lib/components/bundle-packages/index.js +1 -1
  32. package/lib/components/lighthouse-table/lighthouse-table.js +1 -1
  33. package/lib/components/metrics-table/metrics-table.js +1 -1
  34. package/lib/components/metrics-table-search/metrics-table-search.js +1 -1
  35. package/lib/components/metrics-table-search/metrics-table-search.stories.js +1 -1
  36. package/lib/components/summary/summary.js +40 -62
  37. package/lib/components/summary/summary.module.css +31 -14
  38. package/lib/components/summary/summary.stories.js +29 -0
  39. package/lib/components/summary-item/summary-item.js +30 -13
  40. package/lib/components/summary-item/summary-item.module.css +18 -9
  41. package/lib/components/summary-item/summary-item.stories.js +67 -52
  42. package/lib/constants.js +6 -6
  43. package/lib/css/variables.css +15 -11
  44. package/lib/hooks/search-params.js +2 -2
  45. package/lib/layout/box/box.js +2 -2
  46. package/lib/layout/stack/stack.js +13 -3
  47. package/lib/query-state.js +1 -1
  48. package/lib/stories/wrapper.js +2 -2
  49. package/lib/ui/alert/alert.js +13 -3
  50. package/lib/ui/filters/filters.container.js +5 -5
  51. package/lib/ui/filters/filters.js +2 -2
  52. package/lib/ui/filters/filters.stories.js +3 -3
  53. package/lib/ui/horizontal-bar-chart/horizontal-bar-chart.js +3 -3
  54. package/lib/ui/icon/icon.js +3 -0
  55. package/lib/ui/icon/icon.stories.js +40 -22
  56. package/lib/ui/panels/panels.js +2 -2
  57. package/lib/ui/popover/popover.js +3 -3
  58. package/lib/ui/popover/popover.module.css +2 -1
  59. package/lib/ui/tabs/tabs.js +2 -2
  60. package/lib/ui/tooltip/tooltip.module.css +1 -0
  61. package/lib/utils.js +2 -2
  62. package/lib-esm/app/app.js +57 -31
  63. package/lib-esm/app/app.stories.js +29 -1
  64. package/lib-esm/assets/icons/alert-circle.svg +1 -0
  65. package/lib-esm/assets/icons/arrow-right-circle.svg +1 -0
  66. package/lib-esm/assets/icons/check-circle.svg +1 -0
  67. package/lib-esm/assets/icons/close.svg +1 -1
  68. package/lib-esm/assets/icons.svg +50 -1
  69. package/lib-esm/components/budget-info/budget-info.js +37 -0
  70. package/lib-esm/components/budget-info/budget-info.module.css +28 -0
  71. package/lib-esm/components/budget-info/budget-info.stories.js +26 -0
  72. package/lib-esm/components/budget-info/index.js +1 -0
  73. package/lib-esm/components/budget-insights/budget-insights.js +147 -0
  74. package/lib-esm/components/budget-insights/budget-insights.module.css +53 -0
  75. package/lib-esm/components/budget-insights/budget-insights.stories.js +84 -0
  76. package/lib-esm/components/budget-insights/index.js +1 -0
  77. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.js +24 -7
  78. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +2 -2
  79. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.stories.js +46 -21
  80. package/lib-esm/components/summary/summary.js +26 -45
  81. package/lib-esm/components/summary/summary.module.css +31 -14
  82. package/lib-esm/components/summary/summary.stories.js +27 -0
  83. package/lib-esm/components/summary-item/summary-item.js +28 -12
  84. package/lib-esm/components/summary-item/summary-item.module.css +18 -9
  85. package/lib-esm/components/summary-item/summary-item.stories.js +52 -42
  86. package/lib-esm/constants.js +4 -4
  87. package/lib-esm/css/variables.css +15 -11
  88. package/lib-esm/layout/box/box.js +2 -2
  89. package/lib-esm/layout/stack/stack.js +6 -3
  90. package/lib-esm/ui/alert/alert.js +6 -3
  91. package/lib-esm/ui/filters/filters.container.js +39 -41
  92. package/lib-esm/ui/icon/icon.js +3 -0
  93. package/lib-esm/ui/icon/icon.stories.js +22 -11
  94. package/lib-esm/ui/popover/popover.js +2 -2
  95. package/lib-esm/ui/popover/popover.module.css +2 -1
  96. package/lib-esm/ui/tooltip/tooltip.module.css +1 -0
  97. package/package.json +15 -15
  98. package/src/app/app.jsx +24 -8
  99. package/src/assets/icons/alert-circle.svg +1 -0
  100. package/src/assets/icons/arrow-right-circle.svg +1 -0
  101. package/src/assets/icons/check-circle.svg +1 -0
  102. package/src/assets/icons/close.svg +1 -1
  103. package/src/assets/icons.svg +50 -1
  104. package/src/components/budget-info/budget-info.jsx +49 -0
  105. package/src/components/budget-info/budget-info.module.css +28 -0
  106. package/src/components/budget-info/index.js +1 -0
  107. package/src/components/budget-insights/budget-insights.jsx +152 -0
  108. package/src/components/budget-insights/budget-insights.module.css +53 -0
  109. package/src/components/budget-insights/index.js +1 -0
  110. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.jsx +28 -13
  111. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +2 -2
  112. package/src/components/summary/summary.jsx +26 -44
  113. package/src/components/summary/summary.module.css +31 -14
  114. package/src/components/summary-item/summary-item.jsx +26 -24
  115. package/src/components/summary-item/summary-item.module.css +18 -9
  116. package/src/constants.js +7 -7
  117. package/src/css/variables.css +15 -11
  118. package/src/layout/box/box.jsx +1 -1
  119. package/src/layout/stack/stack.jsx +2 -2
  120. package/src/ui/alert/alert.jsx +7 -2
  121. package/src/ui/icon/icon.jsx +3 -0
  122. package/src/ui/popover/popover.jsx +3 -3
  123. package/src/ui/popover/popover.module.css +2 -1
  124. package/src/ui/tooltip/tooltip.module.css +1 -0
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { MemoryRouter } from 'react-router-dom';
3
+ import { BudgetInsights } from '.';
4
+ export default {
5
+ title: 'Components/BudgetInsights',
6
+ component: BudgetInsights,
7
+ decorators: [Story => /*#__PURE__*/React.createElement(MemoryRouter, null, /*#__PURE__*/React.createElement(Story, null))]
8
+ };
9
+
10
+ const Template = args => /*#__PURE__*/React.createElement(BudgetInsights, args);
11
+
12
+ export const Default = Template.bind();
13
+ Default.args = {
14
+ source: 'webpack',
15
+ budgets: {
16
+ totalSizeByTypeALL: {
17
+ value: 2097917,
18
+ budget: 2097152,
19
+ overBudget: true
20
+ },
21
+ totalInitialSizeJS: {
22
+ value: 1265645,
23
+ budget: 524288,
24
+ overBudget: true
25
+ },
26
+ totalInitialSizeCSS: {
27
+ value: 48866,
28
+ budget: 51200,
29
+ overBudget: false
30
+ },
31
+ chunkCount: {
32
+ value: 12,
33
+ budget: 50,
34
+ overBudget: false
35
+ },
36
+ moduleCount: {
37
+ value: 1059,
38
+ budget: 2000,
39
+ overBudget: false
40
+ },
41
+ duplicatePackagesCount: {
42
+ value: 13,
43
+ budget: 5,
44
+ overBudget: true
45
+ },
46
+ 'sizes.totalSizeByTypeJS': {
47
+ value: 1981470,
48
+ budget: 2097152,
49
+ overBudget: false
50
+ },
51
+ 'sizes.totalSizeByTypeCSS': {
52
+ value: 56091,
53
+ budget: 20480,
54
+ overBudget: true
55
+ }
56
+ }
57
+ };
58
+ export const FailedBudgets = Template.bind();
59
+ FailedBudgets.args = {
60
+ source: 'webpack',
61
+ budgets: {
62
+ totalSizeByTypeALL: {
63
+ value: 2097917,
64
+ budget: 2097152,
65
+ overBudget: true
66
+ },
67
+ totalInitialSizeJS: {
68
+ value: 1265645,
69
+ budget: 524288,
70
+ overBudget: true
71
+ }
72
+ }
73
+ };
74
+ export const SingleBudget = Template.bind();
75
+ SingleBudget.args = {
76
+ source: 'webpack',
77
+ budgets: {
78
+ totalInitialSizeJS: {
79
+ value: 524288,
80
+ budget: 1265645,
81
+ overBudget: false
82
+ }
83
+ }
84
+ };
@@ -0,0 +1 @@
1
+ export * from './budget-insights';
@@ -1,32 +1,49 @@
1
- import React from 'react';
1
+ import _get from "lodash/get";
2
+ import React, { useCallback, useMemo } from 'react';
2
3
  import PropTypes from 'prop-types';
3
4
  import { getBundleAssetsFileTypeComponentLink } from '@bundle-stats/utils';
4
5
  import * as webpack from '@bundle-stats/utils/lib-esm/webpack';
5
6
  import { ASSETS_SIZES_FILE_TYPE_MAP } from '../../constants';
7
+ import { FlexStack } from '../../layout/flex-stack';
6
8
  import { MetricsTable } from '../metrics-table';
7
9
  import { ComponentLink } from '../component-link';
10
+ import { BudgetInfo } from '../budget-info';
11
+ import css from './bundle-assets-totals-table.module.css';
8
12
  export const BundleAssetsTotalsTable = _ref => {
13
+ var _jobs$0$insights, _jobs$0$insights$webp;
14
+
9
15
  let {
10
16
  className,
11
17
  jobs,
12
18
  customComponentLink: CustomComponentLink
13
19
  } = _ref;
14
- const items = webpack.compareBySection.sizes(jobs);
15
-
16
- const renderRowHeader = item => {
20
+ const items = useMemo(() => webpack.compareBySection.sizes(jobs), [jobs]);
21
+ const budgets = (_jobs$0$insights = jobs[0].insights) == null ? void 0 : (_jobs$0$insights$webp = _jobs$0$insights.webpack) == null ? void 0 : _jobs$0$insights$webp.budgets;
22
+ const renderRowHeader = useCallback(item => {
17
23
  const fileType = ASSETS_SIZES_FILE_TYPE_MAP[item.key];
18
24
  const {
19
25
  section,
20
26
  title,
21
27
  params
22
28
  } = getBundleAssetsFileTypeComponentLink(fileType, item.label);
29
+ const [_, ...metricSlugs] = item.key.split('.');
30
+ const metricKey = metricSlugs.join('.');
31
+
32
+ const budget = _get(budgets, metricKey);
33
+
34
+ const metric = webpack.getMetricType(metricKey);
23
35
  return /*#__PURE__*/React.createElement(CustomComponentLink, {
24
36
  section: section,
25
37
  title: title,
26
38
  params: params
27
- }, item.label);
28
- };
29
-
39
+ }, /*#__PURE__*/React.createElement(FlexStack, {
40
+ space: "xxsmall",
41
+ className: css.itemTitleText
42
+ }, /*#__PURE__*/React.createElement("span", null, item.label), budget && /*#__PURE__*/React.createElement(BudgetInfo, {
43
+ budget: budget,
44
+ metric: metric
45
+ })));
46
+ }, [CustomComponentLink]);
30
47
  return /*#__PURE__*/React.createElement(MetricsTable, {
31
48
  className: className,
32
49
  runs: jobs,
@@ -1,3 +1,3 @@
1
- .title {
2
- color: var(--color-text-light);
1
+ .itemTitleText {
2
+ align-items: center;
3
3
  }
@@ -1,27 +1,52 @@
1
1
  import React from 'react';
2
- import { storiesOf } from '@storybook/react';
3
2
  import { createJobs } from '@bundle-stats/utils';
4
3
  import baselineStats from '../../../__mocks__/webpack-stats.baseline.json';
5
4
  import currentStats from '../../../__mocks__/webpack-stats.current.json';
6
5
  import { getWrapperDecorator } from '../../stories';
7
6
  import { BundleAssetsTotalsTable } from '.';
8
- const JOBS = createJobs([{
9
- webpack: currentStats
10
- }, {
11
- webpack: baselineStats
12
- }]);
13
- const [currentJob] = JOBS;
14
- const stories = storiesOf('Components/BundleAssetsTotalsTable', module);
15
- stories.addDecorator(getWrapperDecorator());
16
- stories.add('default', () => /*#__PURE__*/React.createElement(BundleAssetsTotalsTable, {
17
- jobs: [currentJob]
18
- }));
19
- stories.add('multiple jobs', () => /*#__PURE__*/React.createElement(BundleAssetsTotalsTable, {
20
- jobs: JOBS
21
- }));
22
- const JOBS_EMPTY_BASELINE = createJobs([{
23
- webpack: currentStats
24
- }, null]);
25
- stories.add('empty baseline', () => /*#__PURE__*/React.createElement(BundleAssetsTotalsTable, {
26
- jobs: JOBS_EMPTY_BASELINE
27
- }));
7
+ export default {
8
+ title: 'Components/BundleAssetsTotalsTable',
9
+ component: BundleAssetsTotalsTable,
10
+ decorators: [getWrapperDecorator()]
11
+ };
12
+
13
+ const Template = args => /*#__PURE__*/React.createElement(BundleAssetsTotalsTable, args);
14
+
15
+ export const SingleJob = Template.bind();
16
+ SingleJob.args = {
17
+ jobs: createJobs([{
18
+ webpack: currentStats
19
+ }])
20
+ };
21
+ export const MultipleJobs = Template.bind();
22
+ MultipleJobs.args = {
23
+ jobs: createJobs([{
24
+ webpack: currentStats
25
+ }, {
26
+ webpack: baselineStats
27
+ }])
28
+ };
29
+ export const EmptyBaseline = Template.bind();
30
+ EmptyBaseline.args = {
31
+ jobs: createJobs([{
32
+ webpack: currentStats
33
+ }, null])
34
+ };
35
+ export const WithBudgets = Template.bind();
36
+ WithBudgets.args = {
37
+ jobs: createJobs([{
38
+ webpack: currentStats
39
+ }, {
40
+ webpack: baselineStats
41
+ }], {
42
+ webpack: {
43
+ budgets: [{
44
+ metric: 'sizes.totalSizeByTypeJS',
45
+ value: 2 * 1024 * 1024
46
+ }, {
47
+ metric: 'sizes.totalSizeByTypeCSS',
48
+ value: 20 * 1024
49
+ }]
50
+ }
51
+ })
52
+ };
@@ -7,76 +7,59 @@ import PropTypes from 'prop-types';
7
7
  import cx from 'classnames';
8
8
  import { METRIC_COMPONENT_LINKS } from '@bundle-stats/utils';
9
9
  import { METRICS_WEBPACK_GENERAL } from '../../constants';
10
+ import { Icon } from '../../ui/icon';
10
11
  import { Box } from '../../layout/box';
11
12
  import { FlexStack } from '../../layout/flex-stack';
12
13
  import { ComponentLink } from '../component-link';
13
14
  import { SummaryItem } from '../summary-item';
14
15
  import css from './summary.module.css';
15
16
 
16
- const CustomSummaryItem = _ref => {
17
- let {
18
- className,
19
- metricOptions,
20
- SummaryItemCustomLink,
21
- ...props
22
- } = _ref;
23
- return /*#__PURE__*/React.createElement(Box, _extends({
24
- padding: ['xsmall', 'small'],
25
- className: cx(className, css.summaryItemLink)
26
- }, props, {
27
- as: SummaryItemCustomLink
28
- }, metricOptions.link));
29
- };
30
-
31
- CustomSummaryItem.propTypes = {
32
- className: PropTypes.string,
33
- metricOptions: PropTypes.shape({
34
- link: PropTypes.any // eslint-disable-line react/forbid-prop-types
17
+ const getSourceMetricId = fullMetricId => fullMetricId.split('.').slice(1).join('.');
35
18
 
36
- }).isRequired,
37
- SummaryItemCustomLink: PropTypes.elementType.isRequired
38
- };
39
- CustomSummaryItem.defaultProps = {
40
- className: ''
41
- };
42
- export const Summary = _ref2 => {
19
+ export const Summary = _ref => {
43
20
  let {
44
21
  className,
45
22
  size,
46
23
  keys,
47
24
  data,
25
+ budgets,
48
26
  loading,
49
27
  showSummaryItemDelta,
50
28
  summaryItemLink: SummaryItemCustomLink
51
- } = _ref2;
29
+ } = _ref;
52
30
  return /*#__PURE__*/React.createElement(Box, {
53
31
  outline: true,
54
32
  className: cx(css.root, className)
55
33
  }, /*#__PURE__*/React.createElement(FlexStack, {
56
34
  className: css.items
57
- }, Array.from(METRIC_COMPONENT_LINKS).filter(_ref3 => {
58
- let [metricId] = _ref3;
59
- return keys.includes(metricId);
60
- }).map(_ref4 => {
61
- let [metricId, metricOptions] = _ref4;
62
- return /*#__PURE__*/React.createElement(SummaryItem, {
63
- as: CustomSummaryItem,
64
- className: css.item,
65
- metricOptions: metricOptions,
66
- SummaryItemCustomLink: SummaryItemCustomLink,
67
- size: size,
35
+ }, Array.from(METRIC_COMPONENT_LINKS).filter(_ref2 => {
36
+ let [metricId] = _ref2;
37
+ return keys.includes(getSourceMetricId(metricId));
38
+ }).map(_ref3 => {
39
+ let [metricId, metricOptions] = _ref3;
40
+ return /*#__PURE__*/React.createElement("div", {
68
41
  key: metricId,
42
+ className: css.item
43
+ }, /*#__PURE__*/React.createElement(SummaryItem, {
44
+ size: size,
69
45
  id: metricId,
70
46
  data: _get(data, metricId),
47
+ budget: _get(budgets, getSourceMetricId(metricId)),
71
48
  loading: loading,
72
49
  showMetricDescription: true,
73
50
  showDelta: showSummaryItemDelta && metricOptions.showDelta !== false
74
- });
51
+ }), !loading && /*#__PURE__*/React.createElement(SummaryItemCustomLink, _extends({}, metricOptions.link, {
52
+ className: css.readMore
53
+ }), /*#__PURE__*/React.createElement(Icon, {
54
+ className: css.readMoreIcon,
55
+ glyph: Icon.ICONS.ARROW_RIGHT_CIRLCE
56
+ })));
75
57
  })));
76
58
  };
77
59
  Summary.defaultProps = {
78
60
  className: '',
79
61
  data: null,
62
+ budgets: null,
80
63
  loading: false,
81
64
  size: '',
82
65
  keys: METRICS_WEBPACK_GENERAL,
@@ -87,12 +70,10 @@ Summary.propTypes = {
87
70
  className: PropTypes.string,
88
71
  size: PropTypes.string,
89
72
  keys: PropTypes.arrayOf(PropTypes.string),
90
- data: PropTypes.shape({
91
- [PropTypes.string]: PropTypes.shape({
92
- baseline: PropTypes.number,
93
- current: PropTypes.number
94
- })
95
- }),
73
+ data: PropTypes.object,
74
+ // eslint-disable-line react/forbid-prop-types
75
+ budgets: PropTypes.object,
76
+ // eslint-disable-line react/forbid-prop-types
96
77
  loading: PropTypes.bool,
97
78
  showSummaryItemDelta: PropTypes.bool,
98
79
  summaryItemLink: PropTypes.elementType
@@ -3,35 +3,52 @@
3
3
  overflow: auto;
4
4
  }
5
5
 
6
- .items {}
7
-
8
6
  .item {
7
+ padding: var(--space-small);
9
8
  flex: 1 0 25%; /* force equal sizes */
10
9
  position: relative;
11
10
  z-index: 1;
12
11
  }
13
12
 
14
- .item:focus-visible {
15
- background: var(--color-highlight);
16
- outline: none;
17
- }
18
-
19
13
  .item::before {
20
14
  content: '';
21
15
  display: block;
22
16
  width: 1px;
23
17
  position: absolute;
24
18
  left: -1px;
25
- top: var(--space-xsmall);
26
- bottom: var(--space-xsmall);
19
+ top: var(--space-small);
20
+ bottom: var(--space-small);
27
21
  background: var(--color-outline);
28
22
  }
29
23
 
30
- .item:hover {
31
- background: var(--color-highlight);
24
+ .readMore {
25
+ display: block;
26
+ position: absolute;
27
+ right: 0;
28
+ bottom: 0;
29
+ padding: var(--space-small);
30
+ color: var(--color-text-ultra-light);
31
+ transition: var(--transition-out);
32
+ }
33
+
34
+ .readMore:hover,
35
+ .readMore:focus {
36
+ color: var(--color-primary);
37
+ transition: var(--transition-in);
38
+ }
39
+
40
+ .readMoreIcon {
41
+ display: block;
42
+ }
43
+
44
+ /** hover state */
45
+ .readMore {
46
+ opacity: 0;
32
47
  }
33
48
 
34
- .summaryItemLink {
35
- color: inherit;
36
- text-decoration: none;
49
+ .item:hover .readMore,
50
+ .item:active .readMore,
51
+ .item:focus .readMore {
52
+ opacity: 1;
53
+ transition: var(--transition-in);
37
54
  }
@@ -21,6 +21,33 @@ stories.addDecorator(getWrapperDecorator());
21
21
  stories.add('default', () => /*#__PURE__*/React.createElement(Summary, {
22
22
  data: MULTIPLE_JOBS[0].summary
23
23
  }));
24
+ stories.add('budgets', () => /*#__PURE__*/React.createElement(Summary, {
25
+ data: MULTIPLE_JOBS[0].summary,
26
+ budgets: {
27
+ webpack: {
28
+ totalSizeByTypeALL: {
29
+ value: MULTIPLE_JOBS[0].summary.webpack.totalSizeByTypeALL,
30
+ budget: 1024 * 1024,
31
+ overBudget: false
32
+ },
33
+ totalInitialSizeJS: {
34
+ value: MULTIPLE_JOBS[0].summary.webpack.totalInitialSizeJS,
35
+ budget: 512 * 1024,
36
+ overBudget: true
37
+ },
38
+ totalInitialSizeCSS: {
39
+ value: MULTIPLE_JOBS[0].summary.webpack.totalInitialSizeCSS,
40
+ budget: 50 * 1024,
41
+ overBudget: false
42
+ },
43
+ chunkCount: {
44
+ value: MULTIPLE_JOBS[0].summary.webpack.chunkCount,
45
+ budget: 50,
46
+ overBudget: false
47
+ }
48
+ }
49
+ }
50
+ }));
24
51
  stories.add('custom keys', () => /*#__PURE__*/React.createElement(Summary, {
25
52
  keys: METRICS_WEBPACK_ASSETS,
26
53
  data: MULTIPLE_JOBS[0].summary
@@ -10,9 +10,10 @@ import { Stack } from '../../layout/stack';
10
10
  import { FlexStack } from '../../layout/flex-stack';
11
11
  import { Metric } from '../metric';
12
12
  import { Delta } from '../delta';
13
+ import { BudgetInfo } from '../budget-info';
13
14
  import css from './summary-item.module.css';
14
15
 
15
- const MetricInfo = _ref => {
16
+ const MetricInfoPopover = _ref => {
16
17
  let {
17
18
  description,
18
19
  url
@@ -32,11 +33,11 @@ const MetricInfo = _ref => {
32
33
  }, "Read more")));
33
34
  };
34
35
 
35
- MetricInfo.propTypes = {
36
+ MetricInfoPopover.propTypes = {
36
37
  description: PropTypes.string.isRequired,
37
38
  url: PropTypes.string
38
39
  };
39
- MetricInfo.defaultProps = {
40
+ MetricInfoPopover.defaultProps = {
40
41
  url: ''
41
42
  };
42
43
  export const SummaryItem = _ref2 => {
@@ -49,6 +50,7 @@ export const SummaryItem = _ref2 => {
49
50
  loading,
50
51
  showDelta,
51
52
  showMetricDescription,
53
+ budget,
52
54
  ...props
53
55
  } = _ref2;
54
56
  const {
@@ -61,7 +63,7 @@ export const SummaryItem = _ref2 => {
61
63
  const metric = getGlobalMetricType(id);
62
64
  const runInfo = getMetricRunInfo(metric, current, baseline);
63
65
  const showMetricDescriptionTooltip = showMetricDescription && (metric == null ? void 0 : metric.description);
64
- const rootClassName = cx(css.root, className, css[size], showMetricDescription && css.showMetricDescription, showMetricDescriptionTooltip && css.showMetricDescription, showDelta && css.showDelta);
66
+ const rootClassName = cx(css.root, className, css[size], showDelta && css.showDelta);
65
67
  return /*#__PURE__*/React.createElement(Stack, _extends({
66
68
  space: "xxsmall",
67
69
  as: Component,
@@ -70,10 +72,16 @@ export const SummaryItem = _ref2 => {
70
72
  as: "h3",
71
73
  space: "xxxsmall",
72
74
  className: css.title
73
- }, /*#__PURE__*/React.createElement("span", null, metric.label), showMetricDescriptionTooltip && /*#__PURE__*/React.createElement(Popover, {
75
+ }, /*#__PURE__*/React.createElement("span", {
76
+ className: css.titleLabel
77
+ }, metric.label), showMetricDescriptionTooltip && /*#__PURE__*/React.createElement(Popover, {
74
78
  className: css.icon,
75
79
  icon: "help"
76
- }, /*#__PURE__*/React.createElement(MetricInfo, metric))), /*#__PURE__*/React.createElement(Stack, null, !loading ? /*#__PURE__*/React.createElement(Metric, {
80
+ }, /*#__PURE__*/React.createElement(MetricInfoPopover, metric)), budget && /*#__PURE__*/React.createElement(BudgetInfo, {
81
+ className: css.budgetInfo,
82
+ metric: metric,
83
+ budget: budget
84
+ })), !loading ? /*#__PURE__*/React.createElement(Stack, null, /*#__PURE__*/React.createElement(Metric, {
77
85
  className: css.currentMetric,
78
86
  value: current,
79
87
  formatter: metric.formatter,
@@ -83,13 +91,13 @@ export const SummaryItem = _ref2 => {
83
91
  className: css.delta,
84
92
  displayValue: runInfo.displayDeltaPercentage,
85
93
  deltaType: runInfo.deltaType
86
- })) : /*#__PURE__*/React.createElement(Skeleton, {
87
- className: cx(css.currentMetric, css.loading)
88
- }), !loading ? /*#__PURE__*/React.createElement(Metric, {
94
+ })), /*#__PURE__*/React.createElement(Metric, {
89
95
  className: css.baselineMetric,
90
96
  value: baseline,
91
97
  formatter: metric.formatter
92
- }) : /*#__PURE__*/React.createElement(Skeleton, {
98
+ })) : /*#__PURE__*/React.createElement(Stack, null, /*#__PURE__*/React.createElement(Skeleton, {
99
+ className: cx(css.currentMetric, css.loading)
100
+ }), /*#__PURE__*/React.createElement(Skeleton, {
93
101
  className: cx(css.baselineMetric, css.loading)
94
102
  })));
95
103
  };
@@ -100,7 +108,8 @@ SummaryItem.defaultProps = {
100
108
  size: 'medium',
101
109
  loading: false,
102
110
  showMetricDescription: false,
103
- showDelta: true
111
+ showDelta: true,
112
+ budget: undefined
104
113
  };
105
114
  SummaryItem.propTypes = {
106
115
  /** Adopted child class name */
@@ -126,5 +135,12 @@ SummaryItem.propTypes = {
126
135
  showMetricDescription: PropTypes.bool,
127
136
 
128
137
  /** Show delta */
129
- showDelta: PropTypes.bool
138
+ showDelta: PropTypes.bool,
139
+
140
+ /** Budget data */
141
+ budget: PropTypes.shape({
142
+ value: PropTypes.number,
143
+ budget: PropTypes.number,
144
+ overBudget: PropTypes.bool
145
+ })
130
146
  };
@@ -1,5 +1,9 @@
1
+ .root {
2
+ position: relative;
3
+ padding-right: var(--space-xlarge);
4
+ }
5
+
1
6
  .title {
2
- margin: 0;
3
7
  color: var(--color-text-ultra-light);
4
8
  font-weight: bold;
5
9
  font-size: var(--size-xsmall);
@@ -8,6 +12,10 @@
8
12
  white-space: nowrap;
9
13
  }
10
14
 
15
+ .titleLabel {
16
+ flex: 0 0 auto;
17
+ }
18
+
11
19
  .readMoreBtn {
12
20
  appearance: none;
13
21
  padding: 0;
@@ -27,24 +35,30 @@
27
35
  text-decoration: none;
28
36
  }
29
37
 
38
+ .budgetInfo {
39
+ position: absolute;
40
+ right: 0;
41
+ top: 0;
42
+ }
43
+
30
44
  .currentMetric {
31
45
  display: block;
32
46
  color: var(--color-heading);
33
47
  font-size: var(--size-large);
34
- line-height: 1.3;
48
+ line-height: var(--space-medium);
35
49
  white-space: nowrap;
36
50
  font-weight: bold;
37
51
  }
38
52
 
39
53
  .delta {
40
- margin: var(--space-xxxsmall) 0 0;
41
54
  font-size: var(--size-small);
55
+ line-height: var(--space-medium);
42
56
  }
43
57
 
44
58
  .baselineMetric {
45
59
  color: var(--color-text-light);
46
60
  font-size: var(--size-small);
47
- line-height: 1.3;
61
+ line-height: var(--space-small);
48
62
  }
49
63
 
50
64
  /* Loading state */
@@ -60,9 +74,4 @@
60
74
  .large .currentMetric {
61
75
  font-size: var(--size-xxxlarge);
62
76
  line-height: var(--space-medium);
63
- min-height: var(--space-medium);
64
- }
65
-
66
- .large .baselineMetric {
67
- font-size: var(--size-medium);
68
77
  }