@bundle-stats/ui 3.1.4-alpha.0 → 3.2.1-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 (276) hide show
  1. package/.babelrc.js +3 -3
  2. package/CHANGELOG.md +18 -1
  3. package/lib/app/app.js +2 -1
  4. package/lib/app/app.stories.js +2 -1
  5. package/lib/assets/icons/arrow.svg +1 -0
  6. package/lib/assets/icons/cancel.svg +1 -0
  7. package/lib/assets/icons/clock.svg +1 -0
  8. package/lib/assets/icons/close.svg +1 -0
  9. package/lib/assets/icons/commit.svg +1 -0
  10. package/lib/assets/icons/filter.svg +1 -0
  11. package/lib/assets/icons/help.svg +1 -0
  12. package/lib/assets/icons/menu.svg +1 -0
  13. package/lib/{ui/icon/assets → assets/icons}/sort.svg +0 -0
  14. package/lib/assets/icons/warning.svg +1 -0
  15. package/lib/assets/icons.svg +1 -0
  16. package/lib/components/bundle-assets/bundle-assets.constants.js +1 -1
  17. package/lib/components/bundle-assets/bundle-assets.js +3 -3
  18. package/lib/components/bundle-assets/bundle-assets.stories.js +19 -7
  19. package/lib/components/bundle-assets/bundle-assets.utils.js +95 -28
  20. package/lib/components/bundle-assets/index.js +115 -4
  21. package/lib/components/bundle-modules/bundle-modules.constants.js +1 -1
  22. package/lib/components/bundle-modules/bundle-modules.js +3 -3
  23. package/lib/components/bundle-modules/bundle-modules.utils.js +152 -0
  24. package/lib/components/bundle-modules/index.js +135 -4
  25. package/lib/components/bundle-packages/bundle-packages.constants.js +1 -1
  26. package/lib/components/bundle-packages/bundle-packages.js +27 -7
  27. package/lib/components/bundle-packages/bundle-packages.module.css +5 -0
  28. package/lib/components/bundle-packages/{bundle-packages.container.js → bundle-packages.utils.js} +8 -42
  29. package/lib/components/bundle-packages/index.js +111 -3
  30. package/lib/components/duplicate-packages-warning/duplicate-packages-warning.js +7 -4
  31. package/lib/components/duplicate-packages-warning/duplicate-packages-warning.stories.js +4 -3
  32. package/lib/components/index.js +18 -18
  33. package/lib/components/metrics-table/metrics-table.js +3 -7
  34. package/lib/components/metrics-table-search/metrics-table-search.js +2 -1
  35. package/lib/components/metrics-table-search/metrics-table-search.module.css +2 -1
  36. package/lib/constants.js +1 -1
  37. package/lib/hooks/rows-filter.js +28 -0
  38. package/lib/hooks/rows-sort.js +54 -0
  39. package/lib/{hocs/with-search.js → hooks/search-params.js} +15 -64
  40. package/lib/layout/index.js +8 -8
  41. package/lib/ui/icon/icon.js +4 -191
  42. package/lib/ui/logo/logo.constants.js +1 -1
  43. package/lib/ui/popover/popover.js +3 -1
  44. package/lib/ui/popover/popover.module.css +3 -3
  45. package/lib/ui/sort-dropdown/sort-dropdown.js +12 -13
  46. package/lib/ui/sort-dropdown/sort-dropdown.stories.js +2 -2
  47. package/lib/ui/tooltip/tooltip.js +2 -1
  48. package/lib-esm/app/app.js +89 -108
  49. package/lib-esm/app/app.stories.js +50 -70
  50. package/lib-esm/app/header/header.js +19 -20
  51. package/lib-esm/assets/icons/arrow.svg +1 -0
  52. package/lib-esm/assets/icons/cancel.svg +1 -0
  53. package/lib-esm/assets/icons/clock.svg +1 -0
  54. package/lib-esm/assets/icons/close.svg +1 -0
  55. package/lib-esm/assets/icons/commit.svg +1 -0
  56. package/lib-esm/assets/icons/filter.svg +1 -0
  57. package/lib-esm/assets/icons/help.svg +1 -0
  58. package/lib-esm/assets/icons/menu.svg +1 -0
  59. package/lib-esm/{ui/icon/assets → assets/icons}/sort.svg +0 -0
  60. package/lib-esm/assets/icons/warning.svg +1 -0
  61. package/lib-esm/assets/icons.svg +1 -0
  62. package/lib-esm/components/asset-info/asset-info.js +20 -18
  63. package/lib-esm/components/asset-info/asset-info.stories.js +29 -33
  64. package/lib-esm/components/browsertime-table/browsertime-table.js +6 -4
  65. package/lib-esm/components/browsertime-table/browsertime-table.stories.js +9 -13
  66. package/lib-esm/components/bundle-assets/bundle-assets.constants.js +17 -15
  67. package/lib-esm/components/bundle-assets/bundle-assets.js +148 -151
  68. package/lib-esm/components/bundle-assets/bundle-assets.stories.js +58 -63
  69. package/lib-esm/components/bundle-assets/bundle-assets.utils.js +65 -21
  70. package/lib-esm/components/bundle-assets/index.js +89 -2
  71. package/lib-esm/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.js +46 -51
  72. package/lib-esm/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.stories.js +9 -13
  73. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.js +13 -13
  74. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.stories.js +13 -19
  75. package/lib-esm/components/bundle-modules/bundle-modules.constants.js +17 -15
  76. package/lib-esm/components/bundle-modules/bundle-modules.js +120 -133
  77. package/lib-esm/components/bundle-modules/bundle-modules.stories.js +46 -58
  78. package/lib-esm/components/bundle-modules/bundle-modules.utils.js +95 -0
  79. package/lib-esm/components/bundle-modules/index.js +111 -3
  80. package/lib-esm/components/bundle-packages/bundle-packages.constants.js +17 -15
  81. package/lib-esm/components/bundle-packages/bundle-packages.js +81 -77
  82. package/lib-esm/components/bundle-packages/bundle-packages.module.css +5 -0
  83. package/lib-esm/components/bundle-packages/bundle-packages.stories.js +34 -46
  84. package/lib-esm/components/bundle-packages/bundle-packages.utils.js +44 -0
  85. package/lib-esm/components/bundle-packages/index.js +87 -2
  86. package/lib-esm/components/component-link.js +9 -13
  87. package/lib-esm/components/delta/delta.js +7 -6
  88. package/lib-esm/components/delta/delta.stories.js +26 -38
  89. package/lib-esm/components/duplicate-packages-warning/duplicate-packages-warning.js +15 -10
  90. package/lib-esm/components/duplicate-packages-warning/duplicate-packages-warning.stories.js +20 -25
  91. package/lib-esm/components/job-header/job-header.js +14 -11
  92. package/lib-esm/components/job-header/job-header.stories.js +12 -18
  93. package/lib-esm/components/job-meta/job-meta.js +14 -18
  94. package/lib-esm/components/job-meta/job-meta.stories.js +10 -12
  95. package/lib-esm/components/job-name/job-name.js +11 -17
  96. package/lib-esm/components/job-name/job-name.stories.js +15 -23
  97. package/lib-esm/components/jobs-header/jobs-header.js +12 -12
  98. package/lib-esm/components/jobs-header/jobs-header.stories.js +80 -86
  99. package/lib-esm/components/lighthouse-table/lighthouse-table.js +6 -4
  100. package/lib-esm/components/lighthouse-table/lighthouse-table.stories.js +10 -14
  101. package/lib-esm/components/metric/metric.js +14 -19
  102. package/lib-esm/components/metric/metric.stories.js +36 -58
  103. package/lib-esm/components/metrics-table/metrics-table.js +128 -143
  104. package/lib-esm/components/metrics-table/metrics-table.stories.js +27 -35
  105. package/lib-esm/components/metrics-table-options/metrics-table-options.js +15 -20
  106. package/lib-esm/components/metrics-table-options/metrics-table-options.stories.js +6 -12
  107. package/lib-esm/components/metrics-table-search/metrics-table-search.js +17 -18
  108. package/lib-esm/components/metrics-table-search/metrics-table-search.module.css +2 -1
  109. package/lib-esm/components/metrics-table-search/metrics-table-search.stories.js +4 -9
  110. package/lib-esm/components/metrics-table-title/metrics-table-title.js +9 -7
  111. package/lib-esm/components/module-info/module-info.js +15 -13
  112. package/lib-esm/components/module-info/module-info.stories.js +20 -22
  113. package/lib-esm/components/summary/summary.js +38 -52
  114. package/lib-esm/components/summary/summary.stories.js +28 -46
  115. package/lib-esm/components/summary-item/summary-item.js +25 -29
  116. package/lib-esm/components/summary-item/summary-item.stories.js +40 -50
  117. package/lib-esm/components/total-size-type-title/total-size-type-title.js +14 -15
  118. package/lib-esm/constants.js +25 -30
  119. package/lib-esm/hooks/rows-filter.js +19 -0
  120. package/lib-esm/hooks/rows-sort.js +21 -0
  121. package/lib-esm/hooks/search-params.js +166 -0
  122. package/lib-esm/layout/box/box.js +12 -19
  123. package/lib-esm/layout/box/box.stories.js +34 -46
  124. package/lib-esm/layout/flex-stack/flex-stack.js +9 -12
  125. package/lib-esm/layout/flex-stack/flex-stack.stories.js +39 -49
  126. package/lib-esm/layout/footer/footer.js +34 -37
  127. package/lib-esm/layout/footer/footer.stories.js +7 -11
  128. package/lib-esm/layout/header/header.js +17 -24
  129. package/lib-esm/layout/header/header.stories.js +34 -43
  130. package/lib-esm/layout/stack/stack.js +8 -6
  131. package/lib-esm/layout/stack/stack.stories.js +39 -49
  132. package/lib-esm/layout/sub-header/sub-header.js +14 -12
  133. package/lib-esm/layout/sub-header/sub-header.stories.js +57 -69
  134. package/lib-esm/prototypes/typography.stories.js +48 -58
  135. package/lib-esm/query-state.js +13 -16
  136. package/lib-esm/stories/wrapper.js +14 -26
  137. package/lib-esm/ui/alert/alert.js +6 -4
  138. package/lib-esm/ui/alert/alert.stories.js +14 -24
  139. package/lib-esm/ui/container/container.js +9 -15
  140. package/lib-esm/ui/container/container.stories.js +15 -17
  141. package/lib-esm/ui/dropdown/dropdown.js +13 -11
  142. package/lib-esm/ui/dropdown/dropdown.stories.js +19 -26
  143. package/lib-esm/ui/empty-set/empty-set.js +12 -12
  144. package/lib-esm/ui/empty-set/empty-set.stories.js +11 -19
  145. package/lib-esm/ui/file-name/file-name.js +7 -8
  146. package/lib-esm/ui/file-name/file-name.stories.js +12 -16
  147. package/lib-esm/ui/filters/filters.container.js +52 -77
  148. package/lib-esm/ui/filters/filters.js +61 -89
  149. package/lib-esm/ui/filters/filters.stories.js +81 -100
  150. package/lib-esm/ui/filters/filters.utils.js +24 -28
  151. package/lib-esm/ui/filters/index.js +1 -1
  152. package/lib-esm/ui/horizontal-bar-chart/horizontal-bar-chart.js +67 -78
  153. package/lib-esm/ui/horizontal-bar-chart/horizontal-bar-chart.stories.js +67 -77
  154. package/lib-esm/ui/icon/icon.js +14 -206
  155. package/lib-esm/ui/icon/icon.stories.js +16 -24
  156. package/lib-esm/ui/input/input.js +6 -10
  157. package/lib-esm/ui/input/input.stories.js +8 -12
  158. package/lib-esm/ui/loader/loader.js +7 -13
  159. package/lib-esm/ui/loader/loader.stories.js +5 -9
  160. package/lib-esm/ui/logo/logo.constants.js +6 -6
  161. package/lib-esm/ui/logo/logo.js +14 -15
  162. package/lib-esm/ui/logo/logo.stories.js +14 -28
  163. package/lib-esm/ui/panels/panels.js +14 -27
  164. package/lib-esm/ui/panels/panels.stories.js +14 -16
  165. package/lib-esm/ui/popover/popover.js +13 -10
  166. package/lib-esm/ui/popover/popover.module.css +3 -3
  167. package/lib-esm/ui/popover/popover.stories.js +7 -11
  168. package/lib-esm/ui/skeleton/skeleton.js +6 -9
  169. package/lib-esm/ui/skeleton/skeleton.stories.js +2 -4
  170. package/lib-esm/ui/sort-dropdown/sort-dropdown.js +36 -39
  171. package/lib-esm/ui/sort-dropdown/sort-dropdown.stories.js +14 -16
  172. package/lib-esm/ui/table/table.js +25 -31
  173. package/lib-esm/ui/table/table.stories.js +84 -102
  174. package/lib-esm/ui/tabs/tabs.js +14 -25
  175. package/lib-esm/ui/tabs/tabs.stories.js +4 -6
  176. package/lib-esm/ui/toolbar/toolbar.js +7 -5
  177. package/lib-esm/ui/toolbar/toolbar.stories.js +11 -16
  178. package/lib-esm/ui/tooltip/tooltip.js +15 -17
  179. package/lib-esm/ui/tooltip/tooltip.stories.js +8 -12
  180. package/lib-esm/utils.js +15 -28
  181. package/package.json +19 -27
  182. package/src/app/app.jsx +4 -1
  183. package/src/assets/icons/arrow.svg +1 -0
  184. package/src/assets/icons/cancel.svg +1 -0
  185. package/src/assets/icons/clock.svg +1 -0
  186. package/src/assets/icons/close.svg +1 -0
  187. package/src/assets/icons/commit.svg +1 -0
  188. package/src/assets/icons/filter.svg +1 -0
  189. package/src/assets/icons/help.svg +1 -0
  190. package/src/assets/icons/menu.svg +1 -0
  191. package/src/{ui/icon/assets → assets/icons}/sort.svg +0 -0
  192. package/src/assets/icons/warning.svg +1 -0
  193. package/src/assets/icons.svg +1 -0
  194. package/src/components/bundle-assets/bundle-assets.jsx +3 -3
  195. package/src/components/bundle-assets/bundle-assets.utils.js +96 -17
  196. package/src/components/bundle-assets/index.jsx +89 -0
  197. package/src/components/bundle-modules/bundle-modules.jsx +3 -3
  198. package/src/components/bundle-modules/bundle-modules.utils.js +101 -0
  199. package/src/components/bundle-modules/index.jsx +107 -0
  200. package/src/components/bundle-packages/bundle-packages.jsx +21 -8
  201. package/src/components/bundle-packages/bundle-packages.module.css +5 -0
  202. package/src/components/bundle-packages/bundle-packages.utils.js +47 -0
  203. package/src/components/bundle-packages/index.jsx +84 -0
  204. package/src/components/duplicate-packages-warning/duplicate-packages-warning.jsx +9 -2
  205. package/src/components/metrics-table/metrics-table.jsx +2 -7
  206. package/src/components/metrics-table-search/metrics-table-search.jsx +1 -0
  207. package/src/components/metrics-table-search/metrics-table-search.module.css +2 -1
  208. package/src/hooks/rows-filter.js +16 -0
  209. package/src/hooks/rows-sort.js +24 -0
  210. package/src/hooks/search-params.js +153 -0
  211. package/src/ui/icon/icon.jsx +7 -42
  212. package/src/ui/popover/popover.jsx +1 -1
  213. package/src/ui/popover/popover.module.css +3 -3
  214. package/src/ui/sort-dropdown/sort-dropdown.jsx +11 -11
  215. package/src/ui/tooltip/tooltip.jsx +1 -1
  216. package/lib/components/bundle-assets/bundle-assets.container.js +0 -140
  217. package/lib/components/bundle-modules/bundle-modules.container.js +0 -222
  218. package/lib/hocs/with-custom-sort.js +0 -75
  219. package/lib/hocs/with-filtered-items.js +0 -54
  220. package/lib/ui/icon/assets/arrow.svg +0 -4
  221. package/lib/ui/icon/assets/branch.svg +0 -3
  222. package/lib/ui/icon/assets/cancel.svg +0 -4
  223. package/lib/ui/icon/assets/clock.svg +0 -3
  224. package/lib/ui/icon/assets/close.svg +0 -4
  225. package/lib/ui/icon/assets/commit.svg +0 -3
  226. package/lib/ui/icon/assets/filter.svg +0 -4
  227. package/lib/ui/icon/assets/help.svg +0 -4
  228. package/lib/ui/icon/assets/job.svg +0 -3
  229. package/lib/ui/icon/assets/menu.svg +0 -4
  230. package/lib/ui/icon/assets/package.svg +0 -3
  231. package/lib/ui/icon/assets/pull-request.svg +0 -3
  232. package/lib/ui/icon/assets/repository.svg +0 -3
  233. package/lib/ui/icon/assets/warning.svg +0 -4
  234. package/lib-esm/components/bundle-assets/bundle-assets.container.js +0 -119
  235. package/lib-esm/components/bundle-modules/bundle-modules.container.js +0 -175
  236. package/lib-esm/components/bundle-packages/bundle-packages.container.js +0 -91
  237. package/lib-esm/hocs/with-custom-sort.js +0 -43
  238. package/lib-esm/hocs/with-filtered-items.js +0 -35
  239. package/lib-esm/hocs/with-search.js +0 -214
  240. package/lib-esm/ui/icon/assets/arrow.svg +0 -4
  241. package/lib-esm/ui/icon/assets/branch.svg +0 -3
  242. package/lib-esm/ui/icon/assets/cancel.svg +0 -4
  243. package/lib-esm/ui/icon/assets/clock.svg +0 -3
  244. package/lib-esm/ui/icon/assets/close.svg +0 -4
  245. package/lib-esm/ui/icon/assets/commit.svg +0 -3
  246. package/lib-esm/ui/icon/assets/filter.svg +0 -4
  247. package/lib-esm/ui/icon/assets/help.svg +0 -4
  248. package/lib-esm/ui/icon/assets/job.svg +0 -3
  249. package/lib-esm/ui/icon/assets/menu.svg +0 -4
  250. package/lib-esm/ui/icon/assets/package.svg +0 -3
  251. package/lib-esm/ui/icon/assets/pull-request.svg +0 -3
  252. package/lib-esm/ui/icon/assets/repository.svg +0 -3
  253. package/lib-esm/ui/icon/assets/warning.svg +0 -4
  254. package/src/components/bundle-assets/bundle-assets.container.js +0 -146
  255. package/src/components/bundle-assets/index.js +0 -4
  256. package/src/components/bundle-modules/bundle-modules.container.js +0 -158
  257. package/src/components/bundle-modules/index.js +0 -4
  258. package/src/components/bundle-packages/bundle-packages.container.js +0 -93
  259. package/src/components/bundle-packages/index.js +0 -4
  260. package/src/hocs/with-custom-sort.jsx +0 -35
  261. package/src/hocs/with-filtered-items.jsx +0 -34
  262. package/src/hocs/with-search.jsx +0 -184
  263. package/src/ui/icon/assets/arrow.svg +0 -4
  264. package/src/ui/icon/assets/branch.svg +0 -3
  265. package/src/ui/icon/assets/cancel.svg +0 -4
  266. package/src/ui/icon/assets/clock.svg +0 -3
  267. package/src/ui/icon/assets/close.svg +0 -4
  268. package/src/ui/icon/assets/commit.svg +0 -3
  269. package/src/ui/icon/assets/filter.svg +0 -4
  270. package/src/ui/icon/assets/help.svg +0 -4
  271. package/src/ui/icon/assets/job.svg +0 -3
  272. package/src/ui/icon/assets/menu.svg +0 -4
  273. package/src/ui/icon/assets/package.svg +0 -3
  274. package/src/ui/icon/assets/pull-request.svg +0 -3
  275. package/src/ui/icon/assets/repository.svg +0 -3
  276. package/src/ui/icon/assets/warning.svg +0 -4
@@ -4,6 +4,7 @@ import cx from 'classnames';
4
4
  import {
5
5
  PACKAGE_FILTERS,
6
6
  PACKAGES_SEPARATOR,
7
+ PACKAGE_ID_SEPARATOR,
7
8
  getBundleModulesBySearch,
8
9
  getBundlePackagesByNameComponentLink,
9
10
  } from '@bundle-stats/utils';
@@ -27,11 +28,19 @@ import css from './bundle-packages.module.css';
27
28
 
28
29
  const PackagePopoverContent = ({ name, fullName, path, duplicate, CustomComponentLink }) => {
29
30
  const normalizedPackagePath = path || `node_modules/${fullName.split(PACKAGES_SEPARATOR).join('/node_modules/')}/`;
31
+ const [normalizedName, packageId] = name.split(PACKAGE_ID_SEPARATOR);
30
32
 
31
33
  return (
32
34
  <Stack space="xxsmall" className={css.packagePopover}>
33
35
  <Stack space="xxxsmall">
34
- <h3 className={css.packagePopoverTitle}>{name}</h3>
36
+ <h3 className={css.packagePopoverTitle}>
37
+ {normalizedName}
38
+ {packageId && (
39
+ <span className={css.packagePopoverTitleIndex}>
40
+ {`${PACKAGE_ID_SEPARATOR}${packageId}`}
41
+ </span>
42
+ )}
43
+ </h3>
35
44
  <p className={css.packagePopoverPath}>
36
45
  <FileName className={css.packagePopoverPathValue} name={normalizedPackagePath} />
37
46
  </p>
@@ -39,13 +48,17 @@ const PackagePopoverContent = ({ name, fullName, path, duplicate, CustomComponen
39
48
 
40
49
  <ul className={css.packagePopoverList}>
41
50
  <li className={css.packagePopoverItem}>
42
- <a href={`https://www.npmjs.com/package/${name}`} target="_blank" rel="noreferrer">
51
+ <a
52
+ href={`https://www.npmjs.com/package/${normalizedName}`}
53
+ target="_blank"
54
+ rel="noreferrer"
55
+ >
43
56
  npmjs.com
44
57
  </a>
45
58
  </li>
46
59
  <li className={css.packagePopoverItem}>
47
60
  <a
48
- href={`https://bundlephobia.com/result?p=${name}`}
61
+ href={`https://bundlephobia.com/result?p=${normalizedName}`}
49
62
  target="_blank"
50
63
  rel="noreferrer"
51
64
  >
@@ -57,14 +70,14 @@ const PackagePopoverContent = ({ name, fullName, path, duplicate, CustomComponen
57
70
  <Stack space="xxxsmall" className={css.packagePopover.actions}>
58
71
  {duplicate && (
59
72
  <div>
60
- <CustomComponentLink {...getBundlePackagesByNameComponentLink(name)}>
73
+ <CustomComponentLink {...getBundlePackagesByNameComponentLink(normalizedName)}>
61
74
  View all duplicate instances
62
75
  </CustomComponentLink>
63
76
  </div>
64
77
  )}
65
78
 
66
79
  <CustomComponentLink {...getBundleModulesBySearch(normalizedPackagePath)}>
67
- View package modules
80
+ Search modules by package path
68
81
  </CustomComponentLink>
69
82
  </Stack>
70
83
  </Stack>
@@ -136,7 +149,7 @@ export const BundlePackages = (props) => {
136
149
  resetAllFilters,
137
150
  totalRowCount,
138
151
  filters,
139
- sortItems,
152
+ sortFields,
140
153
  sort,
141
154
  updateSort,
142
155
  search,
@@ -165,7 +178,7 @@ export const BundlePackages = (props) => {
165
178
  className={css.toolbar}
166
179
  renderActions={({ actionClassName }) => (
167
180
  <FlexStack space="xxsmall" className={cx(css.dropdown, actionClassName)}>
168
- <SortDropdown items={sortItems} {...sort} onChange={updateSort} />
181
+ <SortDropdown fields={sortFields} {...sort} onChange={updateSort} />
169
182
  <MetricsTableOptions
170
183
  handleViewAll={resetAllFilters}
171
184
  handleResetFilters={resetFilters}
@@ -253,7 +266,7 @@ BundlePackages.propTypes = {
253
266
  changed: PropTypes.bool,
254
267
  }).isRequired,
255
268
  hasActiveFilters: PropTypes.bool,
256
- sortItems: PropTypes.shape({
269
+ sortFields: PropTypes.shape({
257
270
  [PropTypes.string]: PropTypes.shape({
258
271
  label: PropTypes.string,
259
272
  defaultDirection: PropTypes.bool,
@@ -47,6 +47,11 @@
47
47
  min-width: 320px;
48
48
  }
49
49
 
50
+ .packagePopoverTitleIndex {
51
+ color: var(--color-text-light);
52
+ font-weight: normal;
53
+ }
54
+
50
55
  .packagePopoverPathValue {
51
56
  padding: var(--space-xxxsmall);
52
57
  background: var(--color-highlight-warning);
@@ -0,0 +1,47 @@
1
+ import { get, flatten, uniq } from 'lodash';
2
+ import { PACKAGE_FILTERS } from '@bundle-stats/utils';
3
+
4
+ import { SORT_BY_NAME, SORT_BY_DELTA, SORT_BY_SIZE } from './bundle-packages.constants';
5
+
6
+ // Get a list of duplicate packages across jobs
7
+ export const getDuplicatePackages = (jobs) => {
8
+ const jobsDuplicatePackages = jobs.map((job) => {
9
+ const insightsData = job?.insights?.webpack?.duplicatePackages?.data || {};
10
+ return Object.values(insightsData).flat();
11
+ });
12
+
13
+ return uniq(flatten(jobsDuplicatePackages));
14
+ };
15
+
16
+ export const getRowFilter = (filters) => (item) => {
17
+ if (filters[PACKAGE_FILTERS.CHANGED] && !item.changed) {
18
+ return false;
19
+ }
20
+
21
+ if (filters[PACKAGE_FILTERS.DUPLICATE] && !item.duplicate) {
22
+ return false;
23
+ }
24
+
25
+ return true;
26
+ };
27
+
28
+ export const getCustomSort = (sortId) => (item) => {
29
+ if (sortId === SORT_BY_NAME) {
30
+ return item.key;
31
+ }
32
+
33
+ if (sortId === SORT_BY_DELTA) {
34
+ return get(item, 'runs[0].deltaPercentage', 0);
35
+ }
36
+
37
+ if (sortId === SORT_BY_SIZE) {
38
+ return get(item, 'runs[0].value', 0);
39
+ }
40
+
41
+ return [!item.changed, item.key];
42
+ };
43
+
44
+ export const getAddRowDuplicateFlag = (duplicateJobs) => (row) => ({
45
+ ...row,
46
+ duplicate: duplicateJobs.includes(row.key),
47
+ });
@@ -0,0 +1,84 @@
1
+ import React, { useMemo } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { PACKAGE_FILTERS } from '@bundle-stats/utils';
4
+ import * as webpack from '@bundle-stats/utils/lib-esm/webpack/compare';
5
+
6
+ import { useRowsFilter } from '../../hooks/rows-filter';
7
+ import { useRowsSort } from '../../hooks/rows-sort';
8
+ import { useSearchParams } from '../../hooks/search-params';
9
+ import { SORT_BY } from './bundle-packages.constants';
10
+ import { BundlePackages as BundlePackagesComponent } from './bundle-packages';
11
+ import { getDuplicatePackages, getAddRowDuplicateFlag, getRowFilter, getCustomSort } from './bundle-packages.utils';
12
+
13
+ export const BundlePackages = (props) => {
14
+ const { jobs, search, filters, setState, sortBy, direction, ...restProps } = props;
15
+
16
+ const { defaultFilters, allEntriesFilters } = useMemo(
17
+ () => ({
18
+ defaultFilters: {
19
+ [PACKAGE_FILTERS.CHANGED]: jobs?.length > 1,
20
+ [PACKAGE_FILTERS.DUPLICATE]: false,
21
+ },
22
+ allEntriesFilters: {
23
+ [PACKAGE_FILTERS.CHANGED]: false,
24
+ [PACKAGE_FILTERS.DUPLICATE]: false,
25
+ },
26
+ }),
27
+ [jobs],
28
+ );
29
+
30
+ const searchParams = useSearchParams({
31
+ search,
32
+ filters,
33
+ defaultFilters,
34
+ allEntriesFilters,
35
+ setState,
36
+ });
37
+
38
+ const { rows, totalRowCount } = useMemo(() => {
39
+ const duplicateJobs = getDuplicatePackages(jobs);
40
+ const result = webpack.compareBySection.packages(jobs, [getAddRowDuplicateFlag(duplicateJobs)]);
41
+ return { rows: result, totalRowCount: result.length };
42
+ }, [jobs]);
43
+
44
+ const filteredRows = useRowsFilter({
45
+ rows,
46
+ searchPattern: searchParams.searchPattern,
47
+ filters: searchParams.filters,
48
+ getRowFilter,
49
+ });
50
+
51
+ const sortParams = useRowsSort({
52
+ rows: filteredRows,
53
+ sortFields: SORT_BY,
54
+ sortBy,
55
+ sortDirection: direction,
56
+ getCustomSort,
57
+ });
58
+
59
+ return (
60
+ <BundlePackagesComponent
61
+ jobs={jobs}
62
+ {...restProps}
63
+ {...searchParams}
64
+ {...sortParams}
65
+ totalRowCount={totalRowCount}
66
+ />
67
+ );
68
+ };
69
+
70
+ BundlePackages.propTypes = {
71
+ jobs: PropTypes.arrayOf(PropTypes.object).isRequired, // eslint-disable-line react/forbid-prop-types
72
+ filters: PropTypes.object, // eslint-disable-line react/forbid-prop-types
73
+ search: PropTypes.string,
74
+ sortBy: PropTypes.string,
75
+ direction: PropTypes.string,
76
+ setState: PropTypes.func.isRequired,
77
+ };
78
+
79
+ BundlePackages.defaultProps = {
80
+ filters: undefined,
81
+ search: undefined,
82
+ sortBy: undefined,
83
+ direction: undefined,
84
+ };
@@ -11,7 +11,12 @@ import css from './duplicate-packages-warning.module.css';
11
11
  const numberMetric = METRIC_TYPES[METRIC_TYPE_NUMERIC];
12
12
 
13
13
  export const DuplicatePackagesWarning = (props) => {
14
- const { className, duplicatePackagesCount, customComponentLink: CustomComponentLink } = props;
14
+ const {
15
+ className,
16
+ duplicatePackagesCount,
17
+ customComponentLink: CustomComponentLink,
18
+ showDelta,
19
+ } = props;
15
20
 
16
21
  const metricRunInfo = getMetricRunInfo(
17
22
  numberMetric,
@@ -24,7 +29,7 @@ export const DuplicatePackagesWarning = (props) => {
24
29
  {`Bundle contains `}
25
30
  <CustomComponentLink {...BUNDLE_PACKAGES_DUPLICATE}>
26
31
  {metricRunInfo.value}
27
- {metricRunInfo.delta !== 0 && (
32
+ {showDelta && metricRunInfo.delta !== 0 && (
28
33
  <Delta
29
34
  className={css.titleDelta}
30
35
  inverted
@@ -45,9 +50,11 @@ DuplicatePackagesWarning.propTypes = {
45
50
  current: PropTypes.number,
46
51
  baseline: PropTypes.number,
47
52
  }).isRequired,
53
+ showDelta: PropTypes.bool,
48
54
  };
49
55
 
50
56
  DuplicatePackagesWarning.defaultProps = {
51
57
  className: '',
52
58
  customComponentLink: ComponentLink,
59
+ showDelta: true,
53
60
  };
@@ -1,8 +1,7 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
- import { get, isEmpty } from 'lodash';
5
- import { flow, map, sum } from 'lodash/fp';
4
+ import { get, isEmpty, sum } from 'lodash';
6
5
  import { METRIC_TYPE_FILE_SIZE, getGlobalMetricType, getMetricRunInfo } from '@bundle-stats/utils';
7
6
 
8
7
  import { Table } from '../../ui/table';
@@ -13,11 +12,7 @@ import styles from './metrics-table.module.css';
13
12
 
14
13
  const METRIC_TYPE_DATA = getGlobalMetricType(null, METRIC_TYPE_FILE_SIZE);
15
14
 
16
- const getRowsRunTotal = (rows, runIndex) =>
17
- flow(
18
- map((row) => get(row, `runs[${runIndex}].value`, 0)),
19
- sum,
20
- )(rows);
15
+ const getRowsRunTotal = (rows, runIndex) => sum(rows.map((row) => get(row, `runs[${runIndex}].value`, 0)));
21
16
 
22
17
  const getHeaderLabelCells = (rows) => (run, runIndex, runs) => {
23
18
  const isBaseline = runIndex === runs.length - 1;
@@ -48,6 +48,7 @@ export const MetricsTableSearch = (props) => {
48
48
  onChange={handleChangeValue}
49
49
  value={value}
50
50
  size="small"
51
+ autoComplete="off"
51
52
  />
52
53
  {search && (
53
54
  <button className={css.cancelButton} type="button" onClick={handleClearValue}>
@@ -5,6 +5,7 @@
5
5
  }
6
6
 
7
7
  .input {
8
+ height: var(--space-large);
8
9
  border-color: var(--color-outline);
9
10
  }
10
11
 
@@ -26,7 +27,7 @@
26
27
  padding: var(--space-xxsmall);
27
28
  width: var(--space-large);
28
29
  height: var(--space-large);
29
- background: radial-gradient(var(--color-background), transparent 75%);
30
+ background: radial-gradient(var(--color-background) 50%, transparent);
30
31
  color: var(--color-text-ultra-light);
31
32
  transition: var(--transition-in);
32
33
  }
@@ -0,0 +1,16 @@
1
+ import { useMemo } from 'react';
2
+
3
+ export const useRowsFilter = ({ rows, searchPattern, filters, getRowFilter }) => {
4
+ const filteredRows = useMemo(() => {
5
+ const filterRow = getRowFilter(filters);
6
+ return rows.filter((row) => {
7
+ if (searchPattern && !searchPattern.test(row?.key)) {
8
+ return false;
9
+ }
10
+
11
+ return filterRow(row);
12
+ });
13
+ }, [rows, searchPattern, filters, getRowFilter]);
14
+
15
+ return filteredRows;
16
+ };
@@ -0,0 +1,24 @@
1
+ import { useState, useMemo } from 'react';
2
+ import { orderBy } from 'lodash';
3
+
4
+ export const useRowsSort = ({
5
+ rows,
6
+ sortFields,
7
+ sortBy = 'size',
8
+ sortDirection = 'desc',
9
+ getCustomSort,
10
+ }) => {
11
+ const [sort, updateSort] = useState({ field: sortBy, direction: sortDirection });
12
+
13
+ const orderedRows = useMemo(
14
+ () => orderBy(rows, getCustomSort(sort.field), sort.direction),
15
+ [rows, sort],
16
+ );
17
+
18
+ return {
19
+ sortFields,
20
+ sort,
21
+ updateSort,
22
+ items: orderedRows,
23
+ };
24
+ };
@@ -0,0 +1,153 @@
1
+ import { useCallback, useLayoutEffect, useReducer } from 'react';
2
+ import { isEqual, merge } from 'lodash';
3
+
4
+ const ACTION_SET_FILTERS = 'SET_FILTERS';
5
+ const ACTION_SET_SEARCH = 'SET_SEARCH';
6
+ const ACTION_RESET_DEFAULT = 'RESET_DEFAULT';
7
+ const ACTION_RESET_ALL = 'RESET_ALL';
8
+ const ACTION_SET = 'SET';
9
+
10
+ const getSearchPattern = (search) => {
11
+ let searchPattern = new RegExp(/.*/);
12
+
13
+ if (!search || !search.trim()) {
14
+ return searchPattern;
15
+ }
16
+
17
+ try {
18
+ searchPattern = new RegExp(search, 'i');
19
+ } catch (err) {
20
+ // noop
21
+ console.error(err); // eslint-disable-line no-console
22
+ }
23
+
24
+ return searchPattern;
25
+ };
26
+
27
+ const getSearchReducer =
28
+ ({ defaultFilters, allEntriesFilters, setParentState }) => (state, action) => {
29
+ const { type, payload } = action;
30
+
31
+ switch (type) {
32
+ case ACTION_SET_FILTERS: {
33
+ setParentState({
34
+ filters: payload,
35
+ search: state.search,
36
+ });
37
+
38
+ return {
39
+ ...state,
40
+ filters: payload,
41
+ };
42
+ }
43
+
44
+ case ACTION_SET_SEARCH: {
45
+ setParentState({
46
+ filters: state.filters,
47
+ search: payload,
48
+ });
49
+
50
+ return {
51
+ ...state,
52
+ search: payload,
53
+ searchPattern: getSearchPattern(payload),
54
+ };
55
+ }
56
+
57
+ case ACTION_RESET_DEFAULT: {
58
+ setParentState({
59
+ filters: defaultFilters,
60
+ search: '',
61
+ });
62
+
63
+ return {
64
+ filters: defaultFilters,
65
+ search: '',
66
+ searchPattern: getSearchPattern(),
67
+ };
68
+ }
69
+
70
+ case ACTION_RESET_ALL: {
71
+ setParentState({
72
+ filters: allEntriesFilters,
73
+ search: '',
74
+ });
75
+
76
+ return {
77
+ filters: allEntriesFilters,
78
+ search: '',
79
+ searchPattern: getSearchPattern(),
80
+ };
81
+ }
82
+
83
+ case ACTION_SET: {
84
+ return payload;
85
+ }
86
+
87
+ default:
88
+ return state;
89
+ }
90
+ };
91
+
92
+ export const generateState = (filters, search) => ({
93
+ filters,
94
+ search,
95
+ searchPattern: getSearchPattern(search),
96
+ });
97
+
98
+ export const useSearchParams = ({
99
+ search: parentSearch,
100
+
101
+ filters: parentFilters,
102
+ defaultFilters,
103
+ allEntriesFilters,
104
+ setState: setParentState,
105
+ }) => {
106
+ // When we pass custom filters, set the other flags to true (allEntries)
107
+ const initialFilters = parentFilters
108
+ ? merge({}, allEntriesFilters, parentFilters)
109
+ : defaultFilters;
110
+
111
+ const [{ search, searchPattern, filters }, dispatch] = useReducer(
112
+ getSearchReducer({ defaultFilters, allEntriesFilters, setParentState }),
113
+ generateState(initialFilters, parentSearch),
114
+ );
115
+
116
+ // Update state when the custom filters/search are changing - initial load or route updates
117
+ useLayoutEffect(() => {
118
+ // Run a deep comparison to prevent circular setState triggering
119
+ if (parentSearch === search || isEqual(parentFilters, filters)) {
120
+ return;
121
+ }
122
+
123
+ dispatch({ type: ACTION_SET, payload: generateState(initialFilters, parentSearch) });
124
+ }, [search, filters, parentFilters, parentSearch]);
125
+
126
+ /** Callbacks */
127
+ const handleUpdateSearch = useCallback((newValue) => {
128
+ dispatch({ type: ACTION_SET_SEARCH, payload: newValue });
129
+ }, []);
130
+
131
+ const handleUpdateFilters = useCallback((newFilters) => {
132
+ dispatch({ type: ACTION_SET_FILTERS, payload: newFilters });
133
+ }, []);
134
+
135
+ const handleResetFilters = useCallback(() => {
136
+ dispatch({ type: ACTION_RESET_DEFAULT });
137
+ }, []);
138
+
139
+ const handleResetAllFilters = useCallback(() => {
140
+ dispatch({ type: ACTION_RESET_ALL });
141
+ }, []);
142
+
143
+ return {
144
+ search,
145
+ searchPattern,
146
+ filters,
147
+ hasActiveFilters: !isEqual(allEntriesFilters, filters),
148
+ updateSearch: handleUpdateSearch,
149
+ updateFilters: handleUpdateFilters,
150
+ resetFilters: handleResetFilters,
151
+ resetAllFilters: handleResetAllFilters,
152
+ };
153
+ };
@@ -2,25 +2,10 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
4
 
5
- import ArrowIcon from './assets/arrow.svg';
6
- import BranchIcon from './assets/branch.svg';
7
- import CancelIcon from './assets/cancel.svg';
8
- import ClockIcon from './assets/clock.svg';
9
- import CloseIcon from './assets/close.svg';
10
- import CommitIcon from './assets/commit.svg';
11
- import FilterIcon from './assets/filter.svg';
12
- import HelpIcon from './assets/help.svg';
13
- import MenuIcon from './assets/menu.svg';
14
- import PackageIcon from './assets/package.svg';
15
- import PullRequestIcon from './assets/pull-request.svg';
16
- import SortIcon from './assets/sort.svg';
17
- import WarningIcon from './assets/warning.svg';
18
-
19
5
  import css from './icon.module.css';
20
6
 
21
7
  const ICONS = {
22
8
  ARROW: 'arrow',
23
- BRANCH: 'branch',
24
9
  CANCEL: 'cancel',
25
10
  CLOSE: 'close',
26
11
  CLOCK: 'clock',
@@ -28,37 +13,17 @@ const ICONS = {
28
13
  FILTER: 'filter',
29
14
  HELP: 'help',
30
15
  MENU: 'menu',
31
- PACKAGE: 'package',
32
- PR: 'pr',
33
16
  SORT: 'sort',
34
17
  WARNING: 'warning',
35
18
  };
36
19
 
37
- const ICON_MAP = {
38
- [ICONS.ARROW]: ArrowIcon,
39
- [ICONS.BRANCH]: BranchIcon,
40
- [ICONS.CANCEL]: CancelIcon,
41
- [ICONS.CLOCK]: ClockIcon,
42
- [ICONS.CLOSE]: CloseIcon,
43
- [ICONS.COMMIT]: CommitIcon,
44
- [ICONS.FILTER]: FilterIcon,
45
- [ICONS.HELP]: HelpIcon,
46
- [ICONS.MENU]: MenuIcon,
47
- [ICONS.PACKAGE]: PackageIcon,
48
- [ICONS.PR]: PullRequestIcon,
49
- [ICONS.SORT]: SortIcon,
50
- [ICONS.WARNING]: WarningIcon,
51
- };
52
-
53
- export const Icon = ({ className, glyph, as: Component, size, ...restProps }) => {
54
- const Svg = typeof glyph === 'string' ? ICON_MAP[glyph] : glyph;
55
-
56
- return (
57
- <Component className={cx(css.root, className, css[size])} {...restProps}>
58
- <Svg className={css.icon} />
59
- </Component>
60
- );
61
- };
20
+ export const Icon = ({ className, glyph, as: Component, size, ...restProps }) => (
21
+ <Component className={cx(css.root, className, css[size])} {...restProps}>
22
+ <svg className={css.icon}>
23
+ <use xlinkHref={`#${glyph}`} />
24
+ </svg>
25
+ </Component>
26
+ );
62
27
 
63
28
  Icon.ICONS = ICONS;
64
29
 
@@ -47,7 +47,7 @@ export const Popover = ({ className, icon, label, ariaLabel, children }) => {
47
47
  {label && <span className={css.label}>{label}</span>}
48
48
  </UIPopoverDisclosure>
49
49
  <UIPopover className={css.popover} {...popover} tabIndex={0}>
50
- <UIPopoverArrow className={css.arrow} {...popover} />
50
+ <UIPopoverArrow className={css.arrow} {...popover} size={24} />
51
51
 
52
52
  {typeof children === 'function' ? children({ popoverToggle: popover.toggle }) : children}
53
53
 
@@ -23,7 +23,7 @@
23
23
  }
24
24
 
25
25
  .popover {
26
- padding: var(--space-xsmall) var(--space-medium) var(--space-xsmall) var(--space-small);
26
+ padding: var(--space-xsmall) var(--space-large) var(--space-xsmall) var(--space-small);
27
27
  max-width: 360px;
28
28
  outline: none;
29
29
  filter: drop-shadow(0 0 var(--space-xxxsmall) var(--color-shadow));
@@ -53,13 +53,13 @@
53
53
  background: none;
54
54
  border: none;
55
55
  cursor: pointer;
56
- color: var(--color-text-light);
56
+ color: var(--color-text-ultra-light);
57
57
  transition: var(--transition-out);
58
58
  }
59
59
 
60
60
  .closeBtn:hover,
61
61
  .closeBtn:active,
62
62
  .closeBtn:focus {
63
- color: var(--color-text);
63
+ color: var(--color-text-light);
64
64
  transition: var(--transition-in);
65
65
  }