@bundle-stats/ui 4.13.0-beta.8 → 4.13.0-rc.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 (227) hide show
  1. package/lib/app/app.js +4 -8
  2. package/lib/app/app.js.map +1 -1
  3. package/lib/app/app.module.css +2 -2
  4. package/lib/assets/icons.svg +70 -67
  5. package/lib/assets/icons.svg.js +14 -12
  6. package/lib/assets/icons.svg.js.map +1 -1
  7. package/lib/components/bundle-assets/bundle-assets.js +44 -10
  8. package/lib/components/bundle-assets/bundle-assets.js.map +1 -1
  9. package/lib/components/bundle-assets/bundle-assets.module.css +0 -5
  10. package/lib/components/bundle-assets-totals/bundle-assets-totals.js +14 -12
  11. package/lib/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  12. package/lib/components/bundle-modules/bundle-modules.i18n.js +1 -1
  13. package/lib/components/bundle-modules/bundle-modules.js +39 -15
  14. package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
  15. package/lib/components/bundle-modules/bundle-modules.module.css +0 -5
  16. package/lib/components/bundle-packages/bundle-packages.js +43 -9
  17. package/lib/components/bundle-packages/bundle-packages.js.map +1 -1
  18. package/lib/components/bundle-packages/bundle-packages.module.css +0 -5
  19. package/lib/components/delta/delta.js +1 -1
  20. package/lib/components/delta/delta.js.map +1 -1
  21. package/lib/components/delta/delta.module.css +10 -1
  22. package/lib/components/jobs-header/jobs-header.module.css +0 -4
  23. package/lib/components/metrics-display-selector/metrics-display-selector.js +42 -5
  24. package/lib/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
  25. package/lib/components/metrics-display-selector/metrics-display-selector.module.css +15 -7
  26. package/lib/components/metrics-table-header/metrics-table-header.js +7 -7
  27. package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -1
  28. package/lib/components/metrics-table-header/metrics-table-header.module.css +11 -4
  29. package/lib/components/metrics-table-options/metrics-table-options.js +2 -2
  30. package/lib/components/metrics-table-options/metrics-table-options.js.map +1 -1
  31. package/lib/components/metrics-table-title/metrics-table-title.js +1 -1
  32. package/lib/components/metrics-table-title/metrics-table-title.js.map +1 -1
  33. package/lib/components/metrics-table-title/metrics-table-title.module.css +1 -0
  34. package/lib/components/metrics-treemap/index.js +4 -0
  35. package/lib/components/metrics-treemap/index.js.map +1 -1
  36. package/lib/components/metrics-treemap/metrics-treemap.constants.js +3 -0
  37. package/lib/components/metrics-treemap/metrics-treemap.constants.js.map +1 -0
  38. package/lib/components/metrics-treemap/metrics-treemap.i18n.js +6 -0
  39. package/lib/components/metrics-treemap/metrics-treemap.i18n.js.map +1 -0
  40. package/lib/components/metrics-treemap/metrics-treemap.js +100 -62
  41. package/lib/components/metrics-treemap/metrics-treemap.js.map +1 -1
  42. package/lib/components/metrics-treemap/metrics-treemap.module.css +139 -51
  43. package/lib/components/metrics-treemap/metrics-treemap.utils.js +109 -0
  44. package/lib/components/metrics-treemap/metrics-treemap.utils.js.map +1 -0
  45. package/lib/components/module-info/module-info.js +1 -2
  46. package/lib/components/module-info/module-info.js.map +1 -1
  47. package/lib/components/run-info/run-info.module.css +7 -7
  48. package/lib/css/variables.css +14 -13
  49. package/lib/hooks/metrics-display-type.js +45 -24
  50. package/lib/hooks/metrics-display-type.js.map +1 -1
  51. package/lib/hooks/search-params.js +1 -0
  52. package/lib/hooks/search-params.js.map +1 -1
  53. package/lib/layout/box/box.module.css +4 -2
  54. package/lib/layout/flex-stack/flex-stack.js +3 -4
  55. package/lib/layout/flex-stack/flex-stack.js.map +1 -1
  56. package/lib/layout/flex-stack/flex-stack.module.css +19 -23
  57. package/lib/ui/button/button.js +5 -4
  58. package/lib/ui/button/button.js.map +1 -1
  59. package/lib/ui/button/button.module.css +55 -53
  60. package/lib/ui/dropdown/dropdown.js +10 -40
  61. package/lib/ui/dropdown/dropdown.js.map +1 -1
  62. package/lib/ui/dropdown/index.js.map +1 -1
  63. package/lib/ui/filters/filters.js +33 -35
  64. package/lib/ui/filters/filters.js.map +1 -1
  65. package/lib/ui/filters/filters.module.css +55 -67
  66. package/lib/ui/hover-card/hover-card.js +1 -1
  67. package/lib/ui/hover-card/hover-card.js.map +1 -1
  68. package/lib/ui/icon/icon.js +2 -1
  69. package/lib/ui/icon/icon.js.map +1 -1
  70. package/lib/ui/input-search/input-search.js +1 -1
  71. package/lib/ui/input-search/input-search.js.map +1 -1
  72. package/lib/ui/loader/loader.js +1 -1
  73. package/lib/ui/loader/loader.js.map +1 -1
  74. package/lib/ui/table/table.module.css +30 -0
  75. package/lib/ui/tag/tag.module.css +3 -3
  76. package/lib/ui/toolbar/toolbar.module.css +1 -3
  77. package/lib-esm/app/app.js +4 -8
  78. package/lib-esm/app/app.js.map +1 -1
  79. package/lib-esm/app/app.module.css +2 -2
  80. package/lib-esm/assets/icons.svg +70 -67
  81. package/lib-esm/assets/icons.svg.js +14 -12
  82. package/lib-esm/assets/icons.svg.js.map +1 -1
  83. package/lib-esm/components/bundle-assets/bundle-assets.js +45 -11
  84. package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
  85. package/lib-esm/components/bundle-assets/bundle-assets.module.css +0 -5
  86. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js +15 -13
  87. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  88. package/lib-esm/components/bundle-modules/bundle-modules.i18n.js +1 -1
  89. package/lib-esm/components/bundle-modules/bundle-modules.js +40 -16
  90. package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
  91. package/lib-esm/components/bundle-modules/bundle-modules.module.css +0 -5
  92. package/lib-esm/components/bundle-packages/bundle-packages.js +44 -10
  93. package/lib-esm/components/bundle-packages/bundle-packages.js.map +1 -1
  94. package/lib-esm/components/bundle-packages/bundle-packages.module.css +0 -5
  95. package/lib-esm/components/delta/delta.js +1 -1
  96. package/lib-esm/components/delta/delta.js.map +1 -1
  97. package/lib-esm/components/delta/delta.module.css +10 -1
  98. package/lib-esm/components/jobs-header/jobs-header.module.css +0 -4
  99. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js +42 -5
  100. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
  101. package/lib-esm/components/metrics-display-selector/metrics-display-selector.module.css +15 -7
  102. package/lib-esm/components/metrics-table-header/metrics-table-header.js +7 -7
  103. package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -1
  104. package/lib-esm/components/metrics-table-header/metrics-table-header.module.css +11 -4
  105. package/lib-esm/components/metrics-table-options/metrics-table-options.js +3 -3
  106. package/lib-esm/components/metrics-table-options/metrics-table-options.js.map +1 -1
  107. package/lib-esm/components/metrics-table-title/metrics-table-title.js +1 -1
  108. package/lib-esm/components/metrics-table-title/metrics-table-title.js.map +1 -1
  109. package/lib-esm/components/metrics-table-title/metrics-table-title.module.css +1 -0
  110. package/lib-esm/components/metrics-treemap/index.js +1 -0
  111. package/lib-esm/components/metrics-treemap/index.js.map +1 -1
  112. package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js +2 -0
  113. package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js.map +1 -0
  114. package/lib-esm/components/metrics-treemap/metrics-treemap.i18n.js +3 -0
  115. package/lib-esm/components/metrics-treemap/metrics-treemap.i18n.js.map +1 -0
  116. package/lib-esm/components/metrics-treemap/metrics-treemap.js +102 -63
  117. package/lib-esm/components/metrics-treemap/metrics-treemap.js.map +1 -1
  118. package/lib-esm/components/metrics-treemap/metrics-treemap.module.css +139 -51
  119. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js +105 -0
  120. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js.map +1 -0
  121. package/lib-esm/components/module-info/module-info.js +1 -2
  122. package/lib-esm/components/module-info/module-info.js.map +1 -1
  123. package/lib-esm/components/run-info/run-info.module.css +7 -7
  124. package/lib-esm/css/variables.css +14 -13
  125. package/lib-esm/hooks/metrics-display-type.js +46 -24
  126. package/lib-esm/hooks/metrics-display-type.js.map +1 -1
  127. package/lib-esm/hooks/search-params.js +1 -0
  128. package/lib-esm/hooks/search-params.js.map +1 -1
  129. package/lib-esm/layout/box/box.module.css +4 -2
  130. package/lib-esm/layout/flex-stack/flex-stack.js +3 -4
  131. package/lib-esm/layout/flex-stack/flex-stack.js.map +1 -1
  132. package/lib-esm/layout/flex-stack/flex-stack.module.css +19 -23
  133. package/lib-esm/ui/button/button.js +5 -4
  134. package/lib-esm/ui/button/button.js.map +1 -1
  135. package/lib-esm/ui/button/button.module.css +55 -53
  136. package/lib-esm/ui/dropdown/dropdown.js +8 -39
  137. package/lib-esm/ui/dropdown/dropdown.js.map +1 -1
  138. package/lib-esm/ui/dropdown/index.js.map +1 -1
  139. package/lib-esm/ui/filters/filters.js +34 -36
  140. package/lib-esm/ui/filters/filters.js.map +1 -1
  141. package/lib-esm/ui/filters/filters.module.css +55 -67
  142. package/lib-esm/ui/hover-card/hover-card.js +1 -1
  143. package/lib-esm/ui/hover-card/hover-card.js.map +1 -1
  144. package/lib-esm/ui/icon/icon.js +2 -1
  145. package/lib-esm/ui/icon/icon.js.map +1 -1
  146. package/lib-esm/ui/input-search/input-search.js +1 -1
  147. package/lib-esm/ui/input-search/input-search.js.map +1 -1
  148. package/lib-esm/ui/loader/loader.js +1 -1
  149. package/lib-esm/ui/loader/loader.js.map +1 -1
  150. package/lib-esm/ui/table/table.module.css +30 -0
  151. package/lib-esm/ui/tag/tag.module.css +3 -3
  152. package/lib-esm/ui/toolbar/toolbar.module.css +1 -3
  153. package/package.json +9 -9
  154. package/src/app/app.jsx +4 -12
  155. package/src/app/app.module.css +2 -2
  156. package/src/assets/icons/check.svg +4 -0
  157. package/src/assets/icons.svg +70 -67
  158. package/src/assets/icons.svg.jsx +12 -12
  159. package/src/components/bundle-assets/bundle-assets.jsx +82 -25
  160. package/src/components/bundle-assets/bundle-assets.module.css +0 -5
  161. package/src/components/bundle-assets-totals/bundle-assets-totals.jsx +53 -46
  162. package/src/components/bundle-modules/bundle-modules.i18n.ts +1 -1
  163. package/src/components/bundle-modules/bundle-modules.module.css +0 -5
  164. package/src/components/bundle-modules/bundle-modules.tsx +117 -53
  165. package/src/components/bundle-packages/bundle-packages.jsx +77 -20
  166. package/src/components/bundle-packages/bundle-packages.module.css +0 -5
  167. package/src/components/delta/delta.jsx +1 -1
  168. package/src/components/delta/delta.module.css +10 -1
  169. package/src/components/jobs-header/jobs-header.module.css +0 -4
  170. package/src/components/metrics-display-selector/metrics-display-selector.module.css +15 -7
  171. package/src/components/metrics-display-selector/metrics-display-selector.stories.tsx +33 -0
  172. package/src/components/metrics-display-selector/metrics-display-selector.tsx +86 -28
  173. package/src/components/metrics-table-header/metrics-table-header.module.css +11 -4
  174. package/src/components/metrics-table-header/metrics-table-header.tsx +7 -7
  175. package/src/components/metrics-table-options/metrics-table-options.jsx +4 -10
  176. package/src/components/metrics-table-title/metrics-table-title.jsx +1 -1
  177. package/src/components/metrics-table-title/metrics-table-title.module.css +1 -0
  178. package/src/components/metrics-treemap/__tests__/metrics-treemap.utils.ts +188 -0
  179. package/src/components/metrics-treemap/index.ts +1 -0
  180. package/src/components/metrics-treemap/metrics-treemap.constants.ts +52 -0
  181. package/src/components/metrics-treemap/metrics-treemap.i18n.ts +2 -0
  182. package/src/components/metrics-treemap/metrics-treemap.module.css +139 -51
  183. package/src/components/metrics-treemap/metrics-treemap.stories.tsx +44 -10
  184. package/src/components/metrics-treemap/metrics-treemap.tsx +329 -120
  185. package/src/components/metrics-treemap/metrics-treemap.utils.ts +162 -0
  186. package/src/components/module-info/module-info.tsx +1 -1
  187. package/src/components/run-info/run-info.module.css +7 -7
  188. package/src/css/variables.css +14 -13
  189. package/src/hooks/metrics-display-type.ts +79 -29
  190. package/src/hooks/search-params.js +1 -0
  191. package/src/layout/box/box.module.css +4 -2
  192. package/src/layout/flex-stack/flex-stack.module.css +19 -23
  193. package/src/layout/flex-stack/flex-stack.tsx +2 -8
  194. package/src/ui/button/button.module.css +55 -53
  195. package/src/ui/button/button.stories.tsx +16 -9
  196. package/src/ui/button/button.tsx +8 -7
  197. package/src/ui/dropdown/dropdown.stories.tsx +25 -0
  198. package/src/ui/dropdown/dropdown.tsx +66 -0
  199. package/src/ui/filters/filters.module.css +55 -67
  200. package/src/ui/filters/filters.stories.tsx +109 -0
  201. package/src/ui/filters/filters.tsx +128 -167
  202. package/src/ui/hover-card/hover-card.tsx +1 -1
  203. package/src/ui/icon/icon.tsx +2 -1
  204. package/src/ui/input-search/input-search.tsx +1 -0
  205. package/src/ui/loader/loader.jsx +1 -1
  206. package/src/ui/table/table.module.css +30 -0
  207. package/src/ui/tag/tag.module.css +3 -3
  208. package/src/ui/toolbar/toolbar.module.css +1 -3
  209. package/types/components/bundle-modules/bundle-modules.i18n.d.ts +1 -1
  210. package/types/components/delta/delta.d.ts +2 -2
  211. package/types/components/metrics-display-selector/metrics-display-selector.d.ts +5 -3
  212. package/types/components/metrics-treemap/index.d.ts +1 -0
  213. package/types/components/metrics-treemap/metrics-treemap.constants.d.ts +20 -0
  214. package/types/components/metrics-treemap/metrics-treemap.d.ts +7 -5
  215. package/types/components/metrics-treemap/metrics-treemap.i18n.d.ts +2 -0
  216. package/types/components/metrics-treemap/metrics-treemap.utils.d.ts +5 -0
  217. package/types/hooks/metrics-display-type.d.ts +8 -2
  218. package/types/ui/dropdown/dropdown.d.ts +12 -47
  219. package/types/ui/dropdown/index.d.ts +1 -1
  220. package/types/ui/filters/filters.d.ts +2 -7
  221. package/types/ui/icon/icon.d.ts +4 -2
  222. package/types/ui/loader/loader.d.ts +2 -2
  223. package/lib/components/bundle-assets-totals/bundle-assets-totals.module.css +0 -7
  224. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.module.css +0 -7
  225. package/src/components/bundle-assets-totals/bundle-assets-totals.module.css +0 -7
  226. package/src/ui/dropdown/dropdown.jsx +0 -88
  227. /package/src/ui/dropdown/{index.js → index.ts} +0 -0
@@ -9,7 +9,6 @@ export const SvgIcons = (props) => (
9
9
  strokeWidth="2"
10
10
  strokeLinecap="round"
11
11
  strokeLinejoin="round"
12
- className="feather feather-arrow-down"
13
12
  id="arrow"
14
13
  xmlns="http://www.w3.org/2000/svg"
15
14
  >
@@ -21,7 +20,6 @@ export const SvgIcons = (props) => (
21
20
  strokeWidth="2"
22
21
  strokeLinecap="round"
23
22
  strokeLinejoin="round"
24
- className="feather feather-arrow-right-circle"
25
23
  viewBox="0 0 24 24"
26
24
  id="arrow-right-circle"
27
25
  xmlns="http://www.w3.org/2000/svg"
@@ -29,13 +27,24 @@ export const SvgIcons = (props) => (
29
27
  <circle cx="12" cy="12" r="10" />
30
28
  <path d="m12 16 4-4-4-4M8 12h8" />
31
29
  </symbol>
30
+ <symbol
31
+ viewBox="0 0 24 24"
32
+ fill="none"
33
+ stroke="currentColor"
34
+ strokeWidth="2"
35
+ strokeLinecap="round"
36
+ strokeLinejoin="round"
37
+ id="check"
38
+ xmlns="http://www.w3.org/2000/svg"
39
+ >
40
+ <path d="M20 6 9 17l-5-5" />
41
+ </symbol>
32
42
  <symbol
33
43
  fill="none"
34
44
  stroke="currentColor"
35
45
  strokeWidth="2"
36
46
  strokeLinecap="round"
37
47
  strokeLinejoin="round"
38
- className="lucide lucide-chevron-down"
39
48
  viewBox="0 0 24 24"
40
49
  id="chevron-down"
41
50
  xmlns="http://www.w3.org/2000/svg"
@@ -48,7 +57,6 @@ export const SvgIcons = (props) => (
48
57
  strokeWidth="2"
49
58
  strokeLinecap="round"
50
59
  strokeLinejoin="round"
51
- className="lucide lucide-chevron-up"
52
60
  viewBox="0 0 24 24"
53
61
  id="chevron-up"
54
62
  xmlns="http://www.w3.org/2000/svg"
@@ -62,7 +70,6 @@ export const SvgIcons = (props) => (
62
70
  strokeWidth="2"
63
71
  strokeLinecap="round"
64
72
  strokeLinejoin="round"
65
- className="feather feather-clock"
66
73
  id="clock"
67
74
  xmlns="http://www.w3.org/2000/svg"
68
75
  >
@@ -75,7 +82,6 @@ export const SvgIcons = (props) => (
75
82
  strokeWidth="2"
76
83
  strokeLinecap="round"
77
84
  strokeLinejoin="round"
78
- className="feather feather-x-circle"
79
85
  viewBox="0 0 24 24"
80
86
  id="close"
81
87
  xmlns="http://www.w3.org/2000/svg"
@@ -90,7 +96,6 @@ export const SvgIcons = (props) => (
90
96
  strokeWidth="2"
91
97
  strokeLinecap="round"
92
98
  strokeLinejoin="round"
93
- className="feather feather-git-commit"
94
99
  id="commit"
95
100
  xmlns="http://www.w3.org/2000/svg"
96
101
  >
@@ -116,7 +121,6 @@ export const SvgIcons = (props) => (
116
121
  strokeWidth="2"
117
122
  strokeLinecap="round"
118
123
  strokeLinejoin="round"
119
- className="feather feather-external-link"
120
124
  viewBox="0 0 24 24"
121
125
  id="external-link"
122
126
  xmlns="http://www.w3.org/2000/svg"
@@ -130,7 +134,6 @@ export const SvgIcons = (props) => (
130
134
  strokeWidth="2"
131
135
  strokeLinecap="round"
132
136
  strokeLinejoin="round"
133
- className="feather feather-bar-chart"
134
137
  id="filter"
135
138
  xmlns="http://www.w3.org/2000/svg"
136
139
  >
@@ -151,7 +154,6 @@ export const SvgIcons = (props) => (
151
154
  strokeWidth="2"
152
155
  strokeLinecap="round"
153
156
  strokeLinejoin="round"
154
- className="feather feather-help-circle"
155
157
  id="help"
156
158
  xmlns="http://www.w3.org/2000/svg"
157
159
  >
@@ -178,7 +180,6 @@ export const SvgIcons = (props) => (
178
180
  strokeWidth="2"
179
181
  strokeLinecap="round"
180
182
  strokeLinejoin="round"
181
- className="feather feather-menu"
182
183
  id="menu"
183
184
  xmlns="http://www.w3.org/2000/svg"
184
185
  >
@@ -233,7 +234,6 @@ export const SvgIcons = (props) => (
233
234
  strokeWidth="2"
234
235
  strokeLinecap="round"
235
236
  strokeLinejoin="round"
236
- className="feather feather-alert-triangle"
237
237
  id="warning"
238
238
  xmlns="http://www.w3.org/2000/svg"
239
239
  >
@@ -15,7 +15,9 @@ import config from '../../config.json';
15
15
  import I18N from '../../i18n';
16
16
  import { MetricsDisplayType } from '../../constants';
17
17
  import { useMetricsDisplayType } from '../../hooks/metrics-display-type';
18
+ import { Box } from '../../layout/box';
18
19
  import { FlexStack } from '../../layout/flex-stack';
20
+ import { Stack } from '../../layout/stack';
19
21
  import { Icon } from '../../ui/icon';
20
22
  import { InputSearch } from '../../ui/input-search';
21
23
  import { FileName } from '../../ui/file-name';
@@ -33,7 +35,7 @@ import { MetricsTableOptions } from '../metrics-table-options';
33
35
  import { MetricsTableTitle } from '../metrics-table-title';
34
36
  import { MetricsDisplaySelector } from '../metrics-display-selector';
35
37
  import { MetricsTableHeader } from '../metrics-table-header';
36
- import { MetricsTreemap } from '../metrics-treemap';
38
+ import { MetricsTreemap, getTreemapNodes, getTreemapNodesGroupedByPath } from '../metrics-treemap';
37
39
  import { SEARCH_PLACEHOLDER } from './bundle-assets.i18n';
38
40
  import css from './bundle-assets.module.css';
39
41
 
@@ -41,6 +43,10 @@ const RUN_TITLE_CURRENT = 'Current';
41
43
  const RUN_TITLE_BASELINE = 'Baseline';
42
44
  const RUNS_LABELS = [RUN_TITLE_CURRENT, RUN_TITLE_BASELINE];
43
45
 
46
+ const DISPLAY_TYPE_GROUPS = {
47
+ [MetricsDisplayType.TREEMAP]: ['folder'],
48
+ };
49
+
44
50
  const getFileTypeFilters = (filters) =>
45
51
  Object.entries(FILE_TYPE_LABELS)
46
52
  .map(([key, label]) => ({
@@ -161,6 +167,60 @@ RowHeader.defaultProps = {
161
167
  chunks: [],
162
168
  };
163
169
 
170
+ const ViewMetricsTreemap = (props) => {
171
+ const { metricsTableTitle, jobs, items, displayType, emptyMessage, showEntryInfo, updateSearch } = props;
172
+
173
+ const treeNodes = useMemo(() => {
174
+ if (displayType.groupBy === 'folder') {
175
+ return getTreemapNodesGroupedByPath(items);
176
+ }
177
+
178
+ return getTreemapNodes(items);
179
+ }, [items, displayType.groupBy]);
180
+
181
+ const onGroupClick = useCallback(
182
+ (groupPath) => {
183
+ // Search by group path
184
+ // 1. use `^` to match only the string beggining
185
+ // 2. add `/` suffix to match only exact directories
186
+ // 3. if the group path is empty(root), clear search
187
+ if (groupPath) {
188
+ updateSearch(`^${groupPath}/`);
189
+ } else {
190
+ updateSearch('');
191
+ }
192
+ },
193
+ [updateSearch],
194
+ );
195
+
196
+ return (
197
+ <>
198
+ <Table compact>
199
+ <MetricsTableHeader metricTitle={metricsTableTitle} showSum jobs={jobs} rows={items} />
200
+ </Table>
201
+ <MetricsTreemap
202
+ treeNodes={treeNodes}
203
+ nested={Boolean(displayType.groupBy)}
204
+ emptyMessage={emptyMessage}
205
+ onItemClick={showEntryInfo}
206
+ onGroupClick={onGroupClick}
207
+ />
208
+ </>
209
+ );
210
+ };
211
+
212
+ ViewMetricsTreemap.propTypes = {
213
+ jobs: PropTypes.arrayOf(PropTypes.object).isRequired, // eslint-disable-line react/forbid-prop-types
214
+ items: PropTypes.arrayOf(PropTypes.object).isRequired, // eslint-disable-line react/forbid-prop-types
215
+ metricsTableTitle: PropTypes.node.isRequired,
216
+ displayType: PropTypes.shape({
217
+ groupBy: PropTypes.string,
218
+ }).isRequired,
219
+ emptyMessage: PropTypes.node.isRequired,
220
+ showEntryInfo: PropTypes.func.isRequired,
221
+ updateSearch: PropTypes.func.isRequired,
222
+ };
223
+
164
224
  export const BundleAssets = (props) => {
165
225
  const {
166
226
  className,
@@ -185,7 +245,7 @@ export const BundleAssets = (props) => {
185
245
 
186
246
  const jobLabels = jobs?.map((job) => job?.label);
187
247
 
188
- const [displayType, setDisplayType] = useMetricsDisplayType();
248
+ const [displayType, setDisplayType] = useMetricsDisplayType(DISPLAY_TYPE_GROUPS);
189
249
 
190
250
  const dropdownFilters = useMemo(
191
251
  () => getFilters({ compareMode: jobs?.length > 1, filters }),
@@ -232,12 +292,16 @@ export const BundleAssets = (props) => {
232
292
 
233
293
  return (
234
294
  <>
235
- <section className={cx(css.root, className)}>
295
+ <Stack space="xsmall" as="section" className={cx(css.root, className)}>
236
296
  <Toolbar
237
- className={css.toolbar}
238
297
  renderActions={({ actionClassName }) => (
239
298
  <FlexStack space="xxsmall" className={cx(css.dropdown, actionClassName)}>
240
- <MetricsDisplaySelector onSelect={setDisplayType} value={displayType} />
299
+ <MetricsDisplaySelector
300
+ value={displayType.value}
301
+ groupBy={displayType.groupBy}
302
+ groups={DISPLAY_TYPE_GROUPS}
303
+ onSelect={setDisplayType}
304
+ />
241
305
  <MetricsTableOptions
242
306
  handleViewAll={resetAllFilters}
243
307
  handleResetFilters={resetFilters}
@@ -260,8 +324,8 @@ export const BundleAssets = (props) => {
260
324
  />
261
325
  </FlexStack>
262
326
  </Toolbar>
263
- <main>
264
- {displayType === MetricsDisplayType.TABLE && (
327
+ <Box outline as="main">
328
+ {displayType.value === MetricsDisplayType.TABLE && (
265
329
  <MetricsTable
266
330
  runs={jobs}
267
331
  items={items}
@@ -273,25 +337,18 @@ export const BundleAssets = (props) => {
273
337
  updateSort={updateSort}
274
338
  />
275
339
  )}
276
- {displayType === MetricsDisplayType.TREEMAP && (
277
- <>
278
- <Table compact>
279
- <MetricsTableHeader
280
- metricTitle={metricsTableTitle}
281
- showSum
282
- jobs={jobs}
283
- rows={items}
284
- />
285
- </Table>
286
- <MetricsTreemap
287
- emptyMessage={emptyMessage}
288
- items={items}
289
- onItemClick={showEntryInfo}
290
- />
291
- </>
340
+ {displayType.value === MetricsDisplayType.TREEMAP && (
341
+ <ViewMetricsTreemap
342
+ jobs={jobs}
343
+ items={items}
344
+ displayType={displayType}
345
+ emptyMessage={emptyMessage}
346
+ showEntryInfo={showEntryInfo}
347
+ updateSearch={updateSearch}
348
+ />
292
349
  )}
293
- </main>
294
- </section>
350
+ </Box>
351
+ </Stack>
295
352
 
296
353
  {entryItem && (
297
354
  <AssetInfo
@@ -1,11 +1,6 @@
1
- .toolbar {
2
- border-bottom: 1px solid var(--color-outline);
3
- }
4
-
5
1
  .toolbarSearch {
6
2
  width: 100%;
7
3
  max-width: 240px;
8
- margin-right: -1px; /** collapse border */
9
4
  }
10
5
 
11
6
  .assetNameWrapper {
@@ -13,13 +13,22 @@ import { useMetricsDisplayType } from '../../hooks/metrics-display-type';
13
13
  import I18N from '../../i18n';
14
14
  import { Toolbar } from '../../ui/toolbar';
15
15
  import { Table } from '../../ui/table';
16
+ import { Box } from '../../layout/box';
17
+ import { Stack } from '../../layout/stack';
16
18
  import { MetricsDisplaySelector } from '../metrics-display-selector';
17
19
  import { MetricsTable } from '../metrics-table';
18
20
  import { MetricsTableTitle } from '../metrics-table-title';
19
21
  import { MetricsTableHeader } from '../metrics-table-header';
20
- import { MetricsTreemap } from '../metrics-treemap';
22
+ import { MetricsTreemap, getTreemapNodes } from '../metrics-treemap';
21
23
  import { ComponentLink } from '../component-link';
22
- import css from './bundle-assets-totals.module.css';
24
+
25
+ const metricsTableTitle = (
26
+ <MetricsTableTitle
27
+ title={I18N.ASSET_TOTALS}
28
+ popoverInfo={I18N.ASSET_TOTALS_INFO}
29
+ popoverHref={config.documentation.assets}
30
+ />
31
+ );
23
32
 
24
33
  export const BundleAssetsTotals = ({
25
34
  className,
@@ -31,18 +40,21 @@ export const BundleAssetsTotals = ({
31
40
  const [displayType, setDisplayType] = useMetricsDisplayType();
32
41
  const history = useHistory();
33
42
 
34
- const items = webpack.compareBySection.sizes(jobs);
43
+ const items = useMemo(() => webpack.compareBySection.sizes(jobs), [jobs]);
35
44
 
36
- const renderRowHeader = (item) => {
37
- const fileType = ASSETS_SIZES_FILE_TYPE_MAP[item.key];
38
- const { section, title, params } = getBundleAssetsFileTypeComponentLink(fileType, item.label);
45
+ const renderRowHeader = useCallback(
46
+ (item) => {
47
+ const fileType = ASSETS_SIZES_FILE_TYPE_MAP[item.key];
48
+ const { section, title, params } = getBundleAssetsFileTypeComponentLink(fileType, item.label);
39
49
 
40
- return (
41
- <CustomComponentLink section={section} title={title} params={params}>
42
- {item.label}
43
- </CustomComponentLink>
44
- );
45
- };
50
+ return (
51
+ <CustomComponentLink section={section} title={title} params={params}>
52
+ {item.label}
53
+ </CustomComponentLink>
54
+ );
55
+ },
56
+ [CustomComponentLink],
57
+ );
46
58
 
47
59
  const handleMetricsTreemapItemClick = useCallback(
48
60
  (entryId) => {
@@ -56,47 +68,42 @@ export const BundleAssetsTotals = ({
56
68
  [history],
57
69
  );
58
70
 
59
- const metricsTableTitle = useMemo(
60
- () => (
61
- <MetricsTableTitle
62
- title={I18N.ASSET_TOTALS}
63
- popoverInfo={I18N.ASSET_TOTALS_INFO}
64
- popoverHref={config.documentation.assets}
65
- />
66
- ),
67
- [],
68
- );
69
-
70
71
  return (
71
- <div className={className}>
72
+ <Stack space="xsmall" as="section" className={className}>
72
73
  <Toolbar
73
- className={css.toolbar}
74
74
  renderActions={() => (
75
- <MetricsDisplaySelector onSelect={setDisplayType} value={displayType} />
75
+ <MetricsDisplaySelector onSelect={setDisplayType} value={displayType.value} />
76
76
  )}
77
77
  />
78
- {displayType === MetricsDisplayType.TABLE && (
79
- <MetricsTable
80
- title={metricsTableTitle}
81
- runs={jobs}
82
- items={items}
83
- renderRowHeader={renderRowHeader}
84
- showHeaderSum
85
- {...restProps}
86
- />
87
- )}
88
- {displayType === MetricsDisplayType.TREEMAP && (
89
- <>
90
- <Table compact>
91
- <MetricsTableHeader metricTitle={metricsTableTitle} showSum jobs={jobs} rows={items} />
92
- </Table>
93
- <MetricsTreemap
78
+ <Box outline as="main">
79
+ {displayType.value === MetricsDisplayType.TABLE && (
80
+ <MetricsTable
81
+ title={metricsTableTitle}
82
+ runs={jobs}
94
83
  items={items}
95
- onItemClick={onTreemapItemClick || handleMetricsTreemapItemClick}
84
+ renderRowHeader={renderRowHeader}
85
+ showHeaderSum
86
+ {...restProps}
96
87
  />
97
- </>
98
- )}
99
- </div>
88
+ )}
89
+ {displayType.value === MetricsDisplayType.TREEMAP && (
90
+ <>
91
+ <Table compact>
92
+ <MetricsTableHeader
93
+ metricTitle={metricsTableTitle}
94
+ showSum
95
+ jobs={jobs}
96
+ rows={items}
97
+ />
98
+ </Table>
99
+ <MetricsTreemap
100
+ treeNodes={getTreemapNodes(items)}
101
+ onItemClick={onTreemapItemClick || handleMetricsTreemapItemClick}
102
+ />
103
+ </>
104
+ )}
105
+ </Box>
106
+ </Stack>
100
107
  );
101
108
  };
102
109
 
@@ -1,4 +1,4 @@
1
- export const SEARCH = 'Search by module name';
1
+ export const SEARCH = 'Search by module path';
2
2
  export const CHANGED = 'Changed';
3
3
  export const DUPLICATE = 'Duplicate';
4
4
  export const CHUNK = 'Chunk';
@@ -2,14 +2,9 @@
2
2
  color: var(--color-text-light);
3
3
  }
4
4
 
5
- .toolbar {
6
- border-bottom: 1px solid var(--color-outline);
7
- }
8
-
9
5
  .toolbarSearch {
10
6
  width: 100%;
11
7
  max-width: 240px;
12
- margin-right: -1px; /** collapse border */
13
8
  }
14
9
 
15
10
  .metricSelector {
@@ -5,10 +5,12 @@ import { SECTIONS, COMPONENT } from '@bundle-stats/utils';
5
5
  import { SortAction } from '../../types';
6
6
  import config from '../../config.json';
7
7
  import I18N from '../../i18n';
8
- import { Box } from '../../layout/box';
9
8
  import { MetricsDisplayType } from '../../constants';
9
+ import { Box } from '../../layout/box';
10
10
  import { FlexStack } from '../../layout/flex-stack';
11
+ import { Stack } from '../../layout/stack';
11
12
  import { Button } from '../../ui/button';
13
+ import { ControlGroup } from '../../ui/control-group';
12
14
  import { EmptySet } from '../../ui/empty-set';
13
15
  import { FileName } from '../../ui/file-name';
14
16
  import { Filters } from '../../ui/filters';
@@ -20,7 +22,7 @@ import { Tooltip } from '../../ui/tooltip';
20
22
  import { ComponentLink } from '../component-link';
21
23
  import { MetricsTable } from '../metrics-table';
22
24
  import { MetricsTableHeader } from '../metrics-table-header';
23
- import { MetricsTreemap } from '../metrics-treemap';
25
+ import { MetricsTreemap, getTreemapNodes, getTreemapNodesGroupedByPath } from '../metrics-treemap';
24
26
  import { MetricsTableOptions } from '../metrics-table-options';
25
27
  import { MetricsDisplaySelector } from '../metrics-display-selector';
26
28
  import { MetricsTableTitle } from '../metrics-table-title';
@@ -32,6 +34,10 @@ import * as I18N_MODULES from './bundle-modules.i18n';
32
34
  import css from './bundle-modules.module.css';
33
35
  import { useMetricsDisplayType } from '../../hooks/metrics-display-type';
34
36
 
37
+ const DISPLAY_TYPE_GROUPS = {
38
+ [MetricsDisplayType.TREEMAP]: ['folder'],
39
+ };
40
+
35
41
  interface RowHeaderProps {
36
42
  row: ReportMetricModuleRow;
37
43
  filters?: any;
@@ -59,6 +65,59 @@ const RowHeader = (props: RowHeaderProps) => {
59
65
  );
60
66
  };
61
67
 
68
+ interface ViewMetricsTreemapProps {
69
+ metricsTableTitle: React.ReactNode;
70
+ jobs: Array<any>;
71
+ items: Array<any>;
72
+ displayType: { value: MetricsDisplayType; groupBy?: string };
73
+ emptyMessage: React.ReactNode;
74
+ showEntryInfo: React.ComponentProps<typeof MetricsTreemap>['onItemClick'];
75
+ updateSearch: (newSerarch: string) => void;
76
+ }
77
+
78
+ const ViewMetricsTreemap = (props: ViewMetricsTreemapProps) => {
79
+ const { metricsTableTitle, jobs, items, displayType, emptyMessage, showEntryInfo, updateSearch } =
80
+ props;
81
+
82
+ const treeNodes = useMemo(() => {
83
+ if (displayType.groupBy === 'folder') {
84
+ return getTreemapNodesGroupedByPath(items);
85
+ }
86
+
87
+ return getTreemapNodes(items);
88
+ }, [items, displayType]);
89
+
90
+ const onGroupClick = useCallback(
91
+ (groupPath: string) => {
92
+ // Search by group path
93
+ // 1. use `^` to match only the string beggining
94
+ // 2. add `/` suffix to match only exact directories
95
+ // 3. if the group path is empty(root), clear search
96
+ if (groupPath) {
97
+ updateSearch(`^${groupPath}/`);
98
+ } else {
99
+ updateSearch('');
100
+ }
101
+ },
102
+ [updateSearch],
103
+ );
104
+
105
+ return (
106
+ <>
107
+ <Table compact>
108
+ <MetricsTableHeader metricTitle={metricsTableTitle} showSum jobs={jobs} rows={items} />
109
+ </Table>
110
+ <MetricsTreemap
111
+ treeNodes={treeNodes}
112
+ nested={Boolean(displayType.groupBy)}
113
+ emptyMessage={emptyMessage}
114
+ onItemClick={showEntryInfo}
115
+ onGroupClick={onGroupClick}
116
+ />
117
+ </>
118
+ );
119
+ };
120
+
62
121
  interface BundleModulesProps extends React.ComponentProps<'div'> {
63
122
  jobs?: Array<Job>;
64
123
  items?: Array<ReportMetricModuleRow>;
@@ -115,7 +174,7 @@ export const BundleModules = (props: BundleModulesProps) => {
115
174
  const rootClassName = cx(css.root, className);
116
175
  const jobLabels = jobs?.map((job) => job?.label);
117
176
 
118
- const [displayType, setDisplayType] = useMetricsDisplayType();
177
+ const [displayType, setDisplayType] = useMetricsDisplayType(DISPLAY_TYPE_GROUPS);
119
178
 
120
179
  const filterFieldsData = useMemo(
121
180
  () => generateFilterFieldsData({ filters, chunks, compareMode: jobs.length > 1 }),
@@ -169,12 +228,17 @@ export const BundleModules = (props: BundleModulesProps) => {
169
228
 
170
229
  return (
171
230
  <>
172
- <div className={rootClassName}>
231
+ <Stack space="xsmall" as="section" className={rootClassName}>
173
232
  <Toolbar
174
233
  className={css.toolbar}
175
234
  renderActions={({ actionClassName }) => (
176
235
  <FlexStack space="xxsmall" className={cx(css.dropdown, actionClassName)}>
177
- <MetricsDisplaySelector onSelect={setDisplayType} value={displayType} />
236
+ <MetricsDisplaySelector
237
+ onSelect={setDisplayType}
238
+ value={displayType.value}
239
+ groupBy={displayType.groupBy}
240
+ groups={DISPLAY_TYPE_GROUPS}
241
+ />
178
242
  <MetricsTableOptions
179
243
  handleViewAll={resetAllFilters}
180
244
  handleResetFilters={resetFilters}
@@ -196,55 +260,55 @@ export const BundleModules = (props: BundleModulesProps) => {
196
260
  />
197
261
  </FlexStack>
198
262
  </Toolbar>
199
- <Box padding={['xsmall', 'small']} className={css.metricSelector}>
200
- <FlexStack space="xxsmall" as="nav">
201
- <Button
202
- outline
203
- active={moduleMetric === ModuleMetric.SIZE}
204
- size="small"
205
- type="button"
206
- onClick={() => setModuleMetric(ModuleMetric.SIZE)}
207
- >
208
- <Tooltip title="Size (excluding duplicate modules)">Module size</Tooltip>
209
- </Button>
210
- <Button
211
- outline
212
- active={moduleMetric === ModuleMetric.TOTAL_SIZE}
213
- size="small"
214
- type="button"
215
- onClick={() => setModuleMetric(ModuleMetric.TOTAL_SIZE)}
216
- >
217
- <Tooltip title="Size (including duplicate modules)">Module total size</Tooltip>
218
- </Button>
219
- </FlexStack>
263
+ <Box outline as="main">
264
+ <Box padding={['xsmall', 'small']} className={css.metricSelector}>
265
+ <ControlGroup as="nav">
266
+ <Button
267
+ outline
268
+ active={moduleMetric === ModuleMetric.SIZE}
269
+ size="small"
270
+ type="button"
271
+ onClick={() => setModuleMetric(ModuleMetric.SIZE)}
272
+ >
273
+ <Tooltip title="Size (excluding duplicate modules)">Module size</Tooltip>
274
+ </Button>
275
+ <Button
276
+ outline
277
+ active={moduleMetric === ModuleMetric.TOTAL_SIZE}
278
+ size="small"
279
+ type="button"
280
+ onClick={() => setModuleMetric(ModuleMetric.TOTAL_SIZE)}
281
+ >
282
+ <Tooltip title="Size (including duplicate modules)">Module total size</Tooltip>
283
+ </Button>
284
+ </ControlGroup>
285
+ </Box>
286
+ {displayType.value === MetricsDisplayType.TABLE && (
287
+ <MetricsTable
288
+ className={css.table}
289
+ items={items}
290
+ runs={jobs}
291
+ renderRowHeader={renderRowHeader}
292
+ emptyMessage={emptyMessage}
293
+ showHeaderSum
294
+ title={metricsTableTitle}
295
+ sort={sort}
296
+ updateSort={updateSort}
297
+ />
298
+ )}
299
+ {displayType.value === MetricsDisplayType.TREEMAP && (
300
+ <ViewMetricsTreemap
301
+ metricsTableTitle={metricsTableTitle}
302
+ jobs={jobs}
303
+ items={items}
304
+ displayType={displayType}
305
+ emptyMessage={emptyMessage}
306
+ showEntryInfo={showEntryInfo}
307
+ updateSearch={updateSearch}
308
+ />
309
+ )}
220
310
  </Box>
221
- {displayType === MetricsDisplayType.TABLE && (
222
- <MetricsTable
223
- className={css.table}
224
- items={items}
225
- runs={jobs}
226
- renderRowHeader={renderRowHeader}
227
- emptyMessage={emptyMessage}
228
- showHeaderSum
229
- title={metricsTableTitle}
230
- sort={sort}
231
- updateSort={updateSort}
232
- />
233
- )}
234
- {displayType === MetricsDisplayType.TREEMAP && (
235
- <>
236
- <Table compact>
237
- <MetricsTableHeader
238
- metricTitle={metricsTableTitle}
239
- showSum
240
- jobs={jobs}
241
- rows={items}
242
- />
243
- </Table>
244
- <MetricsTreemap emptyMessage={emptyMessage} items={items} onItemClick={showEntryInfo} />
245
- </>
246
- )}
247
- </div>
311
+ </Stack>
248
312
  {entryItem && (
249
313
  <ModuleInfo
250
314
  className={css.moduleInfo}