@bundle-stats/ui 4.13.0-beta.9 → 4.13.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) 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 +61 -26
  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/index.js +3 -1
  11. package/lib/components/bundle-assets/index.js.map +1 -1
  12. package/lib/components/bundle-assets-totals/bundle-assets-totals.js +14 -12
  13. package/lib/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  14. package/lib/components/bundle-modules/bundle-modules.i18n.js +1 -1
  15. package/lib/components/bundle-modules/bundle-modules.js +42 -15
  16. package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
  17. package/lib/components/bundle-modules/bundle-modules.module.css +0 -5
  18. package/lib/components/bundle-modules/bundle-modules.utils.js +2 -13
  19. package/lib/components/bundle-modules/bundle-modules.utils.js.map +1 -1
  20. package/lib/components/bundle-modules/index.js +2 -1
  21. package/lib/components/bundle-modules/index.js.map +1 -1
  22. package/lib/components/bundle-packages/bundle-packages.js +48 -9
  23. package/lib/components/bundle-packages/bundle-packages.js.map +1 -1
  24. package/lib/components/bundle-packages/bundle-packages.module.css +0 -5
  25. package/lib/components/delta/delta.js +1 -1
  26. package/lib/components/delta/delta.js.map +1 -1
  27. package/lib/components/delta/delta.module.css +10 -1
  28. package/lib/components/jobs-header/jobs-header.module.css +0 -4
  29. package/lib/components/metrics-display-selector/metrics-display-selector.js +41 -4
  30. package/lib/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
  31. package/lib/components/metrics-display-selector/metrics-display-selector.module.css +15 -7
  32. package/lib/components/metrics-treemap/index.js +4 -0
  33. package/lib/components/metrics-treemap/index.js.map +1 -1
  34. package/lib/components/metrics-treemap/metrics-treemap.constants.js +10 -0
  35. package/lib/components/metrics-treemap/metrics-treemap.constants.js.map +1 -0
  36. package/lib/components/metrics-treemap/metrics-treemap.i18n.js +6 -0
  37. package/lib/components/metrics-treemap/metrics-treemap.i18n.js.map +1 -0
  38. package/lib/components/metrics-treemap/metrics-treemap.js +131 -95
  39. package/lib/components/metrics-treemap/metrics-treemap.js.map +1 -1
  40. package/lib/components/metrics-treemap/metrics-treemap.module.css +179 -54
  41. package/lib/components/metrics-treemap/metrics-treemap.utils.js +168 -0
  42. package/lib/components/metrics-treemap/metrics-treemap.utils.js.map +1 -0
  43. package/lib/components/module-info/module-info.js +1 -2
  44. package/lib/components/module-info/module-info.js.map +1 -1
  45. package/lib/components/run-info/run-info.module.css +7 -7
  46. package/lib/css/variables.css +14 -13
  47. package/lib/hooks/metrics-display-type.js +45 -24
  48. package/lib/hooks/metrics-display-type.js.map +1 -1
  49. package/lib/hooks/search-params.js +1 -0
  50. package/lib/hooks/search-params.js.map +1 -1
  51. package/lib/layout/box/box.module.css +4 -2
  52. package/lib/layout/flex-stack/flex-stack.js +3 -4
  53. package/lib/layout/flex-stack/flex-stack.js.map +1 -1
  54. package/lib/layout/flex-stack/flex-stack.module.css +19 -23
  55. package/lib/ui/button/button.js +5 -4
  56. package/lib/ui/button/button.js.map +1 -1
  57. package/lib/ui/button/button.module.css +55 -53
  58. package/lib/ui/dropdown/dropdown.js +2 -2
  59. package/lib/ui/dropdown/dropdown.js.map +1 -1
  60. package/lib/ui/filters/filters.js +2 -2
  61. package/lib/ui/filters/filters.js.map +1 -1
  62. package/lib/ui/filters/filters.module.css +8 -1
  63. package/lib/ui/hover-card/hover-card.js +1 -1
  64. package/lib/ui/hover-card/hover-card.js.map +1 -1
  65. package/lib/ui/icon/icon.js +2 -1
  66. package/lib/ui/icon/icon.js.map +1 -1
  67. package/lib/ui/input-search/input-search.js +1 -1
  68. package/lib/ui/input-search/input-search.js.map +1 -1
  69. package/lib/ui/loader/loader.js +1 -1
  70. package/lib/ui/loader/loader.js.map +1 -1
  71. package/lib/ui/table/table.module.css +30 -0
  72. package/lib/ui/tag/tag.module.css +3 -3
  73. package/lib/ui/toolbar/toolbar.module.css +1 -3
  74. package/lib/utils/colors.js +22 -0
  75. package/lib/utils/colors.js.map +1 -0
  76. package/lib/{utils.js → utils/components.js} +2 -17
  77. package/lib/utils/components.js.map +1 -0
  78. package/lib/utils/index.js +20 -0
  79. package/lib/utils/index.js.map +1 -0
  80. package/lib/utils/jobs.js +18 -0
  81. package/lib/utils/jobs.js.map +1 -0
  82. package/lib-esm/app/app.js +4 -8
  83. package/lib-esm/app/app.js.map +1 -1
  84. package/lib-esm/app/app.module.css +2 -2
  85. package/lib-esm/assets/icons.svg +70 -67
  86. package/lib-esm/assets/icons.svg.js +14 -12
  87. package/lib-esm/assets/icons.svg.js.map +1 -1
  88. package/lib-esm/components/bundle-assets/bundle-assets.js +62 -28
  89. package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
  90. package/lib-esm/components/bundle-assets/bundle-assets.module.css +0 -5
  91. package/lib-esm/components/bundle-assets/index.js +3 -1
  92. package/lib-esm/components/bundle-assets/index.js.map +1 -1
  93. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js +15 -13
  94. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  95. package/lib-esm/components/bundle-modules/bundle-modules.i18n.js +1 -1
  96. package/lib-esm/components/bundle-modules/bundle-modules.js +43 -16
  97. package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
  98. package/lib-esm/components/bundle-modules/bundle-modules.module.css +0 -5
  99. package/lib-esm/components/bundle-modules/bundle-modules.utils.js +1 -11
  100. package/lib-esm/components/bundle-modules/bundle-modules.utils.js.map +1 -1
  101. package/lib-esm/components/bundle-modules/index.js +3 -2
  102. package/lib-esm/components/bundle-modules/index.js.map +1 -1
  103. package/lib-esm/components/bundle-packages/bundle-packages.js +49 -10
  104. package/lib-esm/components/bundle-packages/bundle-packages.js.map +1 -1
  105. package/lib-esm/components/bundle-packages/bundle-packages.module.css +0 -5
  106. package/lib-esm/components/delta/delta.js +1 -1
  107. package/lib-esm/components/delta/delta.js.map +1 -1
  108. package/lib-esm/components/delta/delta.module.css +10 -1
  109. package/lib-esm/components/jobs-header/jobs-header.module.css +0 -4
  110. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js +41 -4
  111. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
  112. package/lib-esm/components/metrics-display-selector/metrics-display-selector.module.css +15 -7
  113. package/lib-esm/components/metrics-treemap/index.js +1 -0
  114. package/lib-esm/components/metrics-treemap/index.js.map +1 -1
  115. package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js +7 -0
  116. package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js.map +1 -0
  117. package/lib-esm/components/metrics-treemap/metrics-treemap.i18n.js +3 -0
  118. package/lib-esm/components/metrics-treemap/metrics-treemap.i18n.js.map +1 -0
  119. package/lib-esm/components/metrics-treemap/metrics-treemap.js +134 -98
  120. package/lib-esm/components/metrics-treemap/metrics-treemap.js.map +1 -1
  121. package/lib-esm/components/metrics-treemap/metrics-treemap.module.css +179 -54
  122. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js +162 -0
  123. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js.map +1 -0
  124. package/lib-esm/components/module-info/module-info.js +1 -2
  125. package/lib-esm/components/module-info/module-info.js.map +1 -1
  126. package/lib-esm/components/run-info/run-info.module.css +7 -7
  127. package/lib-esm/css/variables.css +14 -13
  128. package/lib-esm/hooks/metrics-display-type.js +46 -24
  129. package/lib-esm/hooks/metrics-display-type.js.map +1 -1
  130. package/lib-esm/hooks/search-params.js +1 -0
  131. package/lib-esm/hooks/search-params.js.map +1 -1
  132. package/lib-esm/layout/box/box.module.css +4 -2
  133. package/lib-esm/layout/flex-stack/flex-stack.js +3 -4
  134. package/lib-esm/layout/flex-stack/flex-stack.js.map +1 -1
  135. package/lib-esm/layout/flex-stack/flex-stack.module.css +19 -23
  136. package/lib-esm/ui/button/button.js +5 -4
  137. package/lib-esm/ui/button/button.js.map +1 -1
  138. package/lib-esm/ui/button/button.module.css +55 -53
  139. package/lib-esm/ui/dropdown/dropdown.js +2 -2
  140. package/lib-esm/ui/dropdown/dropdown.js.map +1 -1
  141. package/lib-esm/ui/filters/filters.js +2 -2
  142. package/lib-esm/ui/filters/filters.js.map +1 -1
  143. package/lib-esm/ui/filters/filters.module.css +8 -1
  144. package/lib-esm/ui/hover-card/hover-card.js +1 -1
  145. package/lib-esm/ui/hover-card/hover-card.js.map +1 -1
  146. package/lib-esm/ui/icon/icon.js +2 -1
  147. package/lib-esm/ui/icon/icon.js.map +1 -1
  148. package/lib-esm/ui/input-search/input-search.js +1 -1
  149. package/lib-esm/ui/input-search/input-search.js.map +1 -1
  150. package/lib-esm/ui/loader/loader.js +1 -1
  151. package/lib-esm/ui/loader/loader.js.map +1 -1
  152. package/lib-esm/ui/table/table.module.css +30 -0
  153. package/lib-esm/ui/tag/tag.module.css +3 -3
  154. package/lib-esm/ui/toolbar/toolbar.module.css +1 -3
  155. package/lib-esm/utils/colors.js +15 -0
  156. package/lib-esm/utils/colors.js.map +1 -0
  157. package/lib-esm/utils/components.js +16 -0
  158. package/lib-esm/utils/components.js.map +1 -0
  159. package/lib-esm/utils/index.js +4 -0
  160. package/lib-esm/utils/index.js.map +1 -0
  161. package/lib-esm/utils/jobs.js +11 -0
  162. package/lib-esm/utils/jobs.js.map +1 -0
  163. package/package.json +9 -9
  164. package/src/app/app.jsx +4 -12
  165. package/src/app/app.module.css +2 -2
  166. package/src/assets/icons/check.svg +4 -0
  167. package/src/assets/icons.svg +70 -67
  168. package/src/assets/icons.svg.jsx +12 -12
  169. package/src/components/bundle-assets/bundle-assets.jsx +147 -66
  170. package/src/components/bundle-assets/bundle-assets.module.css +0 -5
  171. package/src/components/bundle-assets/index.jsx +4 -0
  172. package/src/components/bundle-assets-totals/bundle-assets-totals.jsx +53 -46
  173. package/src/components/bundle-modules/bundle-modules.i18n.ts +1 -1
  174. package/src/components/bundle-modules/bundle-modules.module.css +0 -5
  175. package/src/components/bundle-modules/bundle-modules.tsx +140 -56
  176. package/src/components/bundle-modules/bundle-modules.types.d.ts +2 -17
  177. package/src/components/bundle-modules/bundle-modules.utils.ts +7 -18
  178. package/src/components/bundle-modules/index.tsx +4 -3
  179. package/src/components/bundle-packages/bundle-packages.jsx +89 -20
  180. package/src/components/bundle-packages/bundle-packages.module.css +0 -5
  181. package/src/components/delta/delta.jsx +1 -1
  182. package/src/components/delta/delta.module.css +10 -1
  183. package/src/components/jobs-header/jobs-header.module.css +0 -4
  184. package/src/components/metrics-display-selector/metrics-display-selector.module.css +15 -7
  185. package/src/components/metrics-display-selector/metrics-display-selector.stories.tsx +33 -0
  186. package/src/components/metrics-display-selector/metrics-display-selector.tsx +83 -25
  187. package/src/components/metrics-treemap/__tests__/metrics-treemap.utils.ts +188 -0
  188. package/src/components/metrics-treemap/index.ts +1 -0
  189. package/src/components/metrics-treemap/metrics-treemap.constants.ts +63 -0
  190. package/src/components/metrics-treemap/metrics-treemap.i18n.ts +2 -0
  191. package/src/components/metrics-treemap/metrics-treemap.module.css +179 -54
  192. package/src/components/metrics-treemap/metrics-treemap.stories.tsx +44 -10
  193. package/src/components/metrics-treemap/metrics-treemap.tsx +453 -184
  194. package/src/components/metrics-treemap/metrics-treemap.utils.ts +268 -0
  195. package/src/components/module-info/module-info.tsx +1 -1
  196. package/src/components/run-info/run-info.module.css +7 -7
  197. package/src/css/variables.css +14 -13
  198. package/src/hooks/metrics-display-type.ts +79 -29
  199. package/src/hooks/search-params.js +1 -0
  200. package/src/layout/box/box.module.css +4 -2
  201. package/src/layout/flex-stack/flex-stack.module.css +19 -23
  202. package/src/layout/flex-stack/flex-stack.tsx +2 -8
  203. package/src/ui/button/button.module.css +55 -53
  204. package/src/ui/button/button.stories.tsx +16 -9
  205. package/src/ui/button/button.tsx +8 -7
  206. package/src/ui/dropdown/dropdown.tsx +2 -3
  207. package/src/ui/filters/filters.module.css +8 -1
  208. package/src/ui/filters/filters.tsx +2 -3
  209. package/src/ui/hover-card/hover-card.tsx +1 -1
  210. package/src/ui/icon/icon.tsx +2 -1
  211. package/src/ui/input-search/input-search.tsx +1 -0
  212. package/src/ui/loader/loader.jsx +1 -1
  213. package/src/ui/table/table.module.css +30 -0
  214. package/src/ui/tag/tag.module.css +3 -3
  215. package/src/ui/toolbar/toolbar.module.css +1 -3
  216. package/src/utils/colors.ts +19 -0
  217. package/src/utils/components.tsx +19 -0
  218. package/src/utils/index.ts +3 -0
  219. package/src/utils/jobs.ts +22 -0
  220. package/types/components/bundle-assets/bundle-assets.d.ts +1 -5
  221. package/types/components/bundle-modules/bundle-modules.d.ts +4 -2
  222. package/types/components/bundle-modules/bundle-modules.i18n.d.ts +1 -1
  223. package/types/components/bundle-modules/bundle-modules.utils.d.ts +3 -7
  224. package/types/components/bundle-modules/index.d.ts +2 -2
  225. package/types/components/delta/delta.d.ts +2 -2
  226. package/types/components/metrics-display-selector/metrics-display-selector.d.ts +3 -1
  227. package/types/components/metrics-treemap/index.d.ts +1 -0
  228. package/types/components/metrics-treemap/metrics-treemap.constants.d.ts +28 -0
  229. package/types/components/metrics-treemap/metrics-treemap.d.ts +7 -5
  230. package/types/components/metrics-treemap/metrics-treemap.i18n.d.ts +2 -0
  231. package/types/components/metrics-treemap/metrics-treemap.utils.d.ts +15 -0
  232. package/types/hooks/metrics-display-type.d.ts +8 -2
  233. package/types/ui/dropdown/dropdown.d.ts +0 -1
  234. package/types/ui/icon/icon.d.ts +4 -2
  235. package/types/ui/loader/loader.d.ts +2 -2
  236. package/types/utils/colors.d.ts +1 -0
  237. package/types/utils/components.d.ts +2 -0
  238. package/types/utils/index.d.ts +3 -0
  239. package/types/utils/jobs.d.ts +7 -0
  240. package/lib/components/bundle-assets-totals/bundle-assets-totals.module.css +0 -7
  241. package/lib/utils.js.map +0 -1
  242. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.module.css +0 -7
  243. package/lib-esm/utils.js +0 -30
  244. package/lib-esm/utils.js.map +0 -1
  245. package/src/components/bundle-assets-totals/bundle-assets-totals.module.css +0 -7
  246. package/src/utils.jsx +0 -38
  247. package/types/utils.d.ts +0 -3
@@ -0,0 +1,268 @@
1
+ import { type RefObject, useCallback } from 'react';
2
+ import { useDebounce, useMouseHovered } from 'react-use';
3
+ import { useTooltipState } from 'ariakit/tooltip';
4
+ import {
5
+ DeltaType,
6
+ type MetricRunInfoBaseline,
7
+ type MetricRunInfo,
8
+ type ReportMetricRow,
9
+ } from '@bundle-stats/utils';
10
+
11
+ import {
12
+ type TreeLeaf,
13
+ type TreeNodeChildren,
14
+ type Tree,
15
+ type TreeTotal,
16
+ type TileSizeDisplay,
17
+ type TileGroupSizeDisplay,
18
+ NESTED_PADDING_TOP,
19
+ } from './metrics-treemap.constants';
20
+
21
+ const ROOT_LABEL = '(root)';
22
+
23
+ /**
24
+ * Set node value to the largest run value to allow to
25
+ * display the impact of deleted/new entries
26
+ */
27
+ function getReportMetricRowMaxValue(item: ReportMetricRow): number {
28
+ const values = item.runs.map((run) => run?.value || 0);
29
+ return Math.max(...values);
30
+ }
31
+
32
+ /**
33
+ * Generate treemap node list(flat)
34
+ */
35
+ export function getTreemapNodes(items: Array<ReportMetricRow>): Tree {
36
+ const rootChildren: Array<TreeLeaf> = items.map((item) => ({
37
+ id: item.key,
38
+ label: item.label,
39
+ value: getReportMetricRowMaxValue(item),
40
+ item,
41
+ }));
42
+
43
+ return {
44
+ id: '',
45
+ label: ROOT_LABEL,
46
+ value: 0,
47
+ children: rootChildren,
48
+ };
49
+ }
50
+
51
+ function getItemValues(runs: ReportMetricRow['runs']): TreeTotal {
52
+ const runCount = runs?.length;
53
+ const current = runs[0]?.value || 0;
54
+
55
+ if (runCount < 2) {
56
+ return { current, baseline: 0 };
57
+ }
58
+
59
+ return {
60
+ current,
61
+ baseline: runs[runCount - 1]?.value || 0,
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Recursively set treemap nodes
67
+ */
68
+ function setTreeNode(
69
+ nodes: TreeNodeChildren,
70
+ slugs: Array<string>,
71
+ currentSlugId: number,
72
+ newNode: TreeLeaf,
73
+ ): TreeTotal {
74
+ const baseSlugs = slugs.slice(0, currentSlugId);
75
+ const [currentSlug, ...restSlug] = slugs.slice(currentSlugId);
76
+
77
+ // Add to current nodes if there are no child nodes
78
+ if (!currentSlug) {
79
+ nodes.push(newNode);
80
+ return getItemValues(newNode.item.runs);
81
+ }
82
+
83
+ const currentNodePath = [...baseSlugs, currentSlug].join('/');
84
+
85
+ // Check for existing parent in current nodes
86
+ let parentNode = nodes.find((treeNode) => treeNode.id === currentNodePath) as Tree;
87
+
88
+ // Create the new parentNode if missing
89
+ if (!parentNode) {
90
+ parentNode = {
91
+ id: currentNodePath,
92
+ label: currentSlug,
93
+ value: 0,
94
+ children: [],
95
+ total: {
96
+ current: 0,
97
+ baseline: 0,
98
+ },
99
+ };
100
+
101
+ nodes.push(parentNode);
102
+ }
103
+
104
+ // accumulate children values
105
+ const nodeValues = getItemValues(newNode?.item?.runs);
106
+
107
+ parentNode.total = {
108
+ current: (parentNode.total?.current || 0) + nodeValues.current,
109
+ baseline: (parentNode.total?.baseline || 0) + (nodeValues.baseline || 0),
110
+ };
111
+
112
+ // If there are no other slugs, the new node is as leaf and we add it to the parent
113
+ if (restSlug.length === 0) {
114
+ parentNode.children.push(newNode);
115
+ return getItemValues(newNode.item.runs);
116
+ }
117
+
118
+ return setTreeNode(parentNode.children, slugs, currentSlugId + 1, newNode);
119
+ }
120
+
121
+ /**
122
+ * Generate treemap nodes tree by directory
123
+ */
124
+ export function getTreemapNodesGroupedByPath(items: Array<ReportMetricRow>): Tree {
125
+ const treeNodes: TreeNodeChildren = [];
126
+ const total = { current: 0, baseline: 0 };
127
+
128
+ items.forEach((item) => {
129
+ const slugs = item.key.split('/');
130
+ const baseSlugs = slugs.slice(0, -1);
131
+ const baseName = slugs.slice(-1)[0];
132
+
133
+ const treeNode = {
134
+ id: item.key,
135
+ label: baseName,
136
+ value: getReportMetricRowMaxValue(item),
137
+ item,
138
+ };
139
+
140
+ const childrenTotal = setTreeNode(treeNodes, baseSlugs, 0, treeNode);
141
+
142
+ total.current += childrenTotal.current || 0;
143
+ total.baseline += childrenTotal.baseline || 0;
144
+ });
145
+
146
+ return {
147
+ id: '',
148
+ label: ROOT_LABEL,
149
+ value: 0,
150
+ children: treeNodes,
151
+ total,
152
+ };
153
+ }
154
+
155
+ export function resolveGroupDeltaType(
156
+ metricRunInfo?: MetricRunInfo | MetricRunInfoBaseline,
157
+ ): DeltaType.NO_CHANGE | DeltaType.NEGATIVE | DeltaType.POSITIVE {
158
+ if (!metricRunInfo) {
159
+ return DeltaType.NO_CHANGE;
160
+ }
161
+
162
+ const deltaType = 'displayDelta' in metricRunInfo ? metricRunInfo.deltaType : undefined;
163
+
164
+ if (deltaType?.match(/NEGATIVE/)) {
165
+ return DeltaType.NEGATIVE;
166
+ }
167
+
168
+ if (deltaType?.match(/POSITIVE/)) {
169
+ return DeltaType.POSITIVE;
170
+ }
171
+
172
+ return DeltaType.NO_CHANGE;
173
+ }
174
+
175
+ /**
176
+ * Resolve the tile's size using predefined values to avoid
177
+ * computing the size of the content for every tile
178
+ */
179
+ const PADDING_TOP = 8;
180
+ const PADDING_BOTTOM = 8;
181
+ const PADDING_LEFT = 8;
182
+ const PADDING_RIGHT = 8;
183
+ const LINE_HEIGHT = 16;
184
+ const LINE_HEIGHT_SMALL = 13.3;
185
+
186
+ export function resolveTileGroupSizeDisplay(width: number, height: number): TileGroupSizeDisplay {
187
+ if (height < NESTED_PADDING_TOP) {
188
+ return 'minimal';
189
+ }
190
+
191
+ if (width < 24) {
192
+ return 'minimal';
193
+ }
194
+
195
+ if (height < NESTED_PADDING_TOP + 8) {
196
+ return 'small';
197
+ }
198
+
199
+ return 'default';
200
+ }
201
+
202
+ export function resolveTileSizeDisplay(width: number, height: number): TileSizeDisplay {
203
+ if (height < PADDING_TOP + PADDING_BOTTOM + LINE_HEIGHT_SMALL) {
204
+ return 'minimal';
205
+ }
206
+
207
+ if (width < PADDING_LEFT + PADDING_RIGHT + 42) {
208
+ return 'minimal';
209
+ }
210
+
211
+ if (height < PADDING_TOP + PADDING_TOP + LINE_HEIGHT * 2) {
212
+ return 'small';
213
+ }
214
+
215
+ if (width < PADDING_LEFT + PADDING_RIGHT + 96) {
216
+ return 'small';
217
+ }
218
+
219
+ return 'default';
220
+ }
221
+
222
+ interface UseTooltipStateWithMouseFollowOptions {
223
+ /**
224
+ * React ref to parent div
225
+ */
226
+ parentRef: RefObject<Element>;
227
+ /**
228
+ * Tooltip gutter
229
+ */
230
+ gutter?: number;
231
+ /**
232
+ * Tooltip timeout
233
+ */
234
+ timeout?: number;
235
+ }
236
+
237
+ /**
238
+ * Ariakit tooltip state hook with mouse follow functionality
239
+ */
240
+ export function useTooltipStateWithMouseFollow(options: UseTooltipStateWithMouseFollowOptions) {
241
+ const { parentRef, gutter = 16, timeout = 180 } = options;
242
+
243
+ const pointer = useMouseHovered(parentRef, { whenHovered: true });
244
+
245
+ // Return custom rect based on the mouse position
246
+ const getAnchorRect = useCallback(() => {
247
+ // Skip custom component rect area if the pointer position is empty
248
+ if (pointer.docX === 0 && pointer.docY === 0 && pointer.elW === 0 && pointer.elH === 0) {
249
+ return null;
250
+ }
251
+
252
+ const newRect = {
253
+ x: pointer.docX - (document?.defaultView?.scrollX ?? 0),
254
+ y: pointer.docY - (document?.defaultView?.scrollY ?? 0),
255
+ w: 1,
256
+ h: 1,
257
+ };
258
+
259
+ return newRect;
260
+ }, [pointer.docX, pointer.docY]);
261
+
262
+ const tooltipState = useTooltipState({ gutter, getAnchorRect, timeout });
263
+
264
+ // Update tooltip position when pointer values change
265
+ useDebounce(tooltipState.render, 10, [pointer.docX, pointer.docY]);
266
+
267
+ return tooltipState;
268
+ }
@@ -76,7 +76,7 @@ export const ModuleInfo = (props: ModuleInfoProps & React.ComponentProps<'div'>)
76
76
  (currentRun, index) =>
77
77
  !isEmpty(currentRun?.chunkIds) && (
78
78
  <EntryInfo.Meta label="Chunks" className={css.chunks}>
79
- Job #{index + 1}:
79
+ {labels[index]}:
80
80
  {currentRun.chunkIds.map((chunkId) => {
81
81
  const chunk = chunks?.find(({ id }) => id === chunkId);
82
82
 
@@ -31,6 +31,10 @@
31
31
  font-weight: bold;
32
32
  }
33
33
 
34
+ .delta {
35
+ font-weight: normal;
36
+ }
37
+
34
38
  .deltaValue + .deltaValue::before {
35
39
  margin-left: calc(var(--space-xxxsmall) / 2);
36
40
  margin-right: calc(var(--space-xxxsmall) / 2);
@@ -72,17 +76,13 @@
72
76
 
73
77
  /* Size variation */
74
78
  .small .currentMetric {
75
- font-size: var(--size-large);
79
+ font-size: var(--size-medium);
76
80
  }
77
81
 
78
82
  .large .currentMetric {
79
- font-size: var(--size-xxxlarge);
83
+ font-size: var(--size-xxlarge);
80
84
  }
81
85
 
82
86
  .large .baselineMetric {
83
- font-size: var(--size-medium);
84
- }
85
-
86
- .large .delta {
87
- margin-left: var(--space-xxxsmall);
87
+ font-size: var(--size-small);
88
88
  }
@@ -29,20 +29,20 @@
29
29
  /*
30
30
  * Color scheme:
31
31
  * https://coolors.co/287acc-da444e-55b950-efcc1a-192339
32
- * http://mcg.mbitson.com/#!?mcgpalette0=%23da444e&mcgpalette1=%2355b950&mcgpalette2=%23efcc1a&mcgpalette3=%23353138&mcgpalette4=%23287acc&themename=mcgtheme
32
+ * http://mcg.mbitson.com/#!?mcgpalette0=%23da444e&mcgpalette1=%2355b950&mcgpalette2=%23efcc1a&mcgpalette3=%233e3c49&mcgpalette4=%23287acc&themename=bundle-stats
33
33
  * https://hihayk.github.io/scale/#4/5/50/90/-51/0/0/14/353138/53/49/56/white
34
34
  */
35
35
  --color-gray-25: #f9f9fa;
36
36
  --color-gray-50: #e8e8e9;
37
- --color-gray-100: #c6c5c7;
38
- --color-gray-200: #a2a0a4;
39
- --color-gray-300: #7e7b80;
40
- --color-gray-400: #59565c;
41
- --color-gray-500: #353138;
42
- --color-gray-600: #302b31;
43
- --color-gray-700: #2a252a;
44
- --color-gray-800: #231e22;
45
- --color-gray-900: #1c181b;
37
+ --color-gray-100: #c5c5c8;
38
+ --color-gray-200: #9f9ea4;
39
+ --color-gray-300: #787780;
40
+ --color-gray-400: #5b5964;
41
+ --color-gray-500: #3e3c49;
42
+ --color-gray-600: #383642;
43
+ --color-gray-700: #302e39;
44
+ --color-gray-800: #282731;
45
+ --color-gray-900: #1b1a21;
46
46
 
47
47
  --color-gray-ultra-light: var(--color-gray-200);
48
48
  --color-gray-light: var(--color-gray-300);
@@ -192,9 +192,10 @@
192
192
  --shadow-layer: 0 0 var(--space-xxxsmall) var(--color-shadow);
193
193
  --shadow-layer-high: 0 0 var(--space-xxsmall) var(--color-shadow);
194
194
 
195
- --radius-small: 4px;
196
- --radius-medium: 5px;
197
- --radius-large: 6px;
195
+ --radius-xsmall: 3px;
196
+ --radius-small: 5px;
197
+ --radius-medium: 7px;
198
+ --radius-large: 9px;
198
199
 
199
200
  --outline-hover: 0 0 0 3px var(--color-highlight);
200
201
 
@@ -4,53 +4,103 @@ import { StringParam, useQueryParams } from 'use-query-params';
4
4
 
5
5
  import { MetricsDisplayType } from '../constants';
6
6
 
7
- const DEFAULT_DISPLAY_TYPE = MetricsDisplayType.TABLE;
8
- const PARAM_NAME = 'dt';
7
+ const DEFAULT_VALUE = MetricsDisplayType.TABLE;
8
+ const DEFAULT_GROUP_BY = '';
9
9
 
10
- type UseMetricsDisplayType = [MetricsDisplayType, (value: MetricsDisplayType) => void];
10
+ // Display type query param name
11
+ const QUERY_PARAM_VALUE = 'dt';
12
+ // Display type group by param name
13
+ const QUERY_PARAM_GROUP_BY = 'dtg';
11
14
 
12
- export const useMetricsDisplayType = (): UseMetricsDisplayType => {
13
- const [{ [PARAM_NAME]: queryDisplayType }, setQueryParams] = useQueryParams({
14
- [PARAM_NAME]: StringParam,
15
+ type MetricsDisplayTypeData = {
16
+ value: MetricsDisplayType;
17
+ groupBy: string;
18
+ };
19
+
20
+ type UseMetricsDisplayType = [
21
+ { value: MetricsDisplayType; groupBy?: string },
22
+ (newDisplayType: MetricsDisplayType, newGroupBy?: string) => void,
23
+ ];
24
+
25
+ export const useMetricsDisplayType = (
26
+ groups?: Partial<Record<MetricsDisplayType, Array<string>>>,
27
+ ): UseMetricsDisplayType => {
28
+ const [queryParams, setQueryParams] = useQueryParams({
29
+ [QUERY_PARAM_VALUE]: StringParam,
30
+ [QUERY_PARAM_GROUP_BY]: StringParam,
15
31
  });
16
- const [storageDisplayType, setStoreageDisplayType] = useLocalStorage(
17
- PARAM_NAME,
18
- MetricsDisplayType.TABLE,
32
+
33
+ const { [QUERY_PARAM_VALUE]: queryParamValue, [QUERY_PARAM_GROUP_BY]: queryParamGroupBy } =
34
+ queryParams;
35
+ const [localStorage, setLocalStorage] = useLocalStorage<Partial<MetricsDisplayTypeData>>(
36
+ 'storage',
37
+ {
38
+ value: DEFAULT_VALUE,
39
+ groupBy: DEFAULT_GROUP_BY,
40
+ },
19
41
  );
20
42
 
21
- const displayType = useMemo(() => {
22
- const value = queryDisplayType || storageDisplayType;
43
+ /**
44
+ * Normalize display type value
45
+ */
46
+ const value = useMemo(() => {
47
+ const resolvedValue = queryParamValue ?? localStorage?.value;
48
+
49
+ if (!resolvedValue) {
50
+ return DEFAULT_VALUE;
51
+ }
52
+
53
+ if (!Object.values(MetricsDisplayType).includes(resolvedValue as MetricsDisplayType)) {
54
+ return DEFAULT_VALUE;
55
+ }
23
56
 
24
- if (!value) {
25
- return DEFAULT_DISPLAY_TYPE;
57
+ return resolvedValue as MetricsDisplayType;
58
+ }, [queryParamValue, localStorage?.value]);
59
+
60
+ /**
61
+ * Normalize display type group by
62
+ */
63
+ const groupBy = useMemo(() => {
64
+ const resolvedValue = queryParamGroupBy ?? localStorage?.groupBy;
65
+
66
+ if (!resolvedValue) {
67
+ return DEFAULT_GROUP_BY;
26
68
  }
27
69
 
28
- if (!Object.values(MetricsDisplayType).includes(value as MetricsDisplayType)) {
29
- return DEFAULT_DISPLAY_TYPE;
70
+ if (!groups?.[value]?.includes(resolvedValue as MetricsDisplayType)) {
71
+ return DEFAULT_GROUP_BY;
30
72
  }
31
73
 
32
- return value as MetricsDisplayType;
33
- }, [queryDisplayType, storageDisplayType]);
74
+ return resolvedValue;
75
+ }, [queryParamGroupBy, localStorage?.groupBy]);
34
76
 
77
+ /**
78
+ * Synchronize query params when values are different
79
+ */
35
80
  useEffect(() => {
36
- // Update query string display type when missing
37
- if (queryDisplayType !== displayType) {
38
- setQueryParams({ [PARAM_NAME]: displayType });
81
+ if (value !== queryParamValue || groupBy !== queryParamGroupBy) {
82
+ setQueryParams({ [QUERY_PARAM_VALUE]: value, [QUERY_PARAM_GROUP_BY]: groupBy });
39
83
  }
84
+ }, [value, queryParamValue, groupBy, queryParamGroupBy, setQueryParams]);
40
85
 
41
- // Update storage state when query string is set and different
42
- if (storageDisplayType !== displayType) {
43
- setStoreageDisplayType(queryDisplayType as MetricsDisplayType);
86
+ /**
87
+ * Synchronize storage when values are different
88
+ */
89
+ useEffect(() => {
90
+ if (value !== localStorage?.value || groupBy !== localStorage.groupBy) {
91
+ setLocalStorage({ value, groupBy });
44
92
  }
45
- }, [displayType, queryDisplayType, storageDisplayType, setQueryParams, setStoreageDisplayType]);
93
+ }, [value, groupBy, setLocalStorage, localStorage]);
46
94
 
47
95
  const setDisplayType = useCallback(
48
- (value: MetricsDisplayType) => {
49
- setStoreageDisplayType(value);
50
- setQueryParams({ [PARAM_NAME]: value });
96
+ (newValue: MetricsDisplayType, newGroupBy: string = DEFAULT_GROUP_BY) => {
97
+ setQueryParams({
98
+ [QUERY_PARAM_VALUE]: newValue,
99
+ [QUERY_PARAM_GROUP_BY]: newGroupBy,
100
+ });
51
101
  },
52
- [setStoreageDisplayType, setQueryParams],
102
+ [setQueryParams],
53
103
  );
54
104
 
55
- return [displayType, setDisplayType];
105
+ return useMemo(() => [{ value, groupBy }, setDisplayType], [value, groupBy, setDisplayType]);
56
106
  };
@@ -38,6 +38,7 @@ const getSearchReducer =
38
38
  const newState = {
39
39
  filters: payload,
40
40
  search: state.search,
41
+ searchPattern: getSearchPattern(state.search),
41
42
  };
42
43
  setParentState(newState);
43
44
  return newState;
@@ -8,11 +8,13 @@
8
8
  }
9
9
 
10
10
  .outline > :first-child {
11
- border-radius: var(--radius-medium) var(--radius-medium) 0 0;
11
+ border-top-left-radius: var(--radius-medium);
12
+ border-top-right-radius: var(--radius-medium);
12
13
  }
13
14
 
14
15
  .outline > :last-child {
15
- border-radius: 0 0 var(--radius-medium) var(--radius-medium);
16
+ border-bottom-left-radius: var(--radius-medium);
17
+ border-bottom-right-radius: var(--radius-medium);
16
18
  }
17
19
 
18
20
  .outlineHover {
@@ -1,48 +1,44 @@
1
1
  .root {
2
2
  display: flex;
3
- align-items: stretch;
4
3
  justify-content: flex-start;
5
- }
6
-
7
- .root > .item:last-child {
8
- margin-right: 0;
4
+ gap: 0;
9
5
  }
10
6
 
11
7
  /** Space variation */
12
- .space--xxxsmall > .item {
13
- margin: 0 var(--space-xxxsmall) 0 0;
8
+ .space--xxxsmall {
9
+ gap: var(--space-xxxsmall);
14
10
  }
15
11
 
16
- .space--xxsmall > .item {
17
- margin: 0 var(--space-xxsmall) 0 0;
12
+ .space--xxsmall {
13
+ gap: var(--space-xxsmall);
18
14
  }
19
15
 
20
- .space--xsmall > .item {
21
- margin: 0 var(--space-xsmall) 0 0;
16
+ .space--xsmall {
17
+ gap: var(--space-xsmall);
22
18
  }
23
19
 
24
- .space--small > .item {
25
- margin: 0 var(--space-small) 0 0;
20
+ .space--small {
21
+ gap: var(--space-small);
26
22
  }
27
23
 
28
- .space--medium > .item {
29
- margin: 0 var(--space-medium) 0 0;
24
+ .space--medium {
25
+ gap: var(--space-medium);
30
26
  }
31
27
 
32
- .space--large > .item {
33
- margin: 0 var(--space-large) 0 0;
28
+ .space--large {
29
+ gap: var(--space-large);
34
30
  }
35
31
 
36
- .space--xlarge > .item {
37
- margin: 0 var(--space-xlarge) 0 0;
32
+ .space--xlarge {
33
+ gap: var(--space-xlarge);
38
34
  }
39
35
 
40
- .space--xxlarge > .item {
41
- margin: 0 var(--space-xxlarge) 0 0;
36
+ .space--xxlarge {
37
+ gap: var(--space-xxlarge);
42
38
  }
43
39
 
44
- .space--xxxlarge > .item {
45
- margin: 0 var(--space-xxxlarge) 0 0;
40
+ .space--xxxlarge {
41
+ gap: var(--space-xxxlarge);
46
42
  }
47
43
 
48
44
  /** Align items variation */
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import cx from 'classnames';
3
3
 
4
4
  import { NO_SPACE, SPACES } from '../../tokens';
5
- import { getRenderChildWithClassName } from '../../utils';
6
5
  import css from './flex-stack.module.css';
7
6
 
8
7
  type SpaceValue = (typeof SPACES)[number];
@@ -22,22 +21,17 @@ export const FlexStack = <T extends React.ElementType = 'div'>(
22
21
  className = '',
23
22
  space = NO_SPACE,
24
23
  inline = false,
25
- children = null,
26
24
  alignItems = '',
27
25
  ...restProps
28
26
  } = props;
29
27
 
30
28
  const rootClassName = cx(
31
- className,
32
29
  css.root,
33
30
  css[`space--${space}`],
34
31
  css[`align-items--${alignItems}`],
35
32
  inline && css.inline,
33
+ className,
36
34
  );
37
35
 
38
- return (
39
- <Component {...restProps} className={rootClassName}>
40
- {React.Children.map(children, getRenderChildWithClassName(css.item))}
41
- </Component>
42
- );
36
+ return <Component {...restProps} className={rootClassName} />;
43
37
  };