@bundle-stats/ui 4.12.2 → 4.13.0-beta.10

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 (301) hide show
  1. package/lib/app/app.js +5 -13
  2. package/lib/app/app.js.map +1 -1
  3. package/lib/app/app.module.css +2 -2
  4. package/lib/assets/icons.svg +26 -20
  5. package/lib/assets/icons.svg.js +27 -23
  6. package/lib/assets/icons.svg.js.map +1 -1
  7. package/lib/components/bundle-assets/bundle-assets.js +21 -6
  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 -4
  11. package/lib/components/bundle-assets/index.js.map +1 -1
  12. package/lib/components/bundle-assets-totals/bundle-assets-totals.js +88 -0
  13. package/lib/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -0
  14. package/lib/{ui/horizontal-bar-chart → components/bundle-assets-totals}/index.js +1 -1
  15. package/lib/components/bundle-assets-totals/index.js.map +1 -0
  16. package/lib/components/bundle-modules/bundle-modules.js +24 -9
  17. package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
  18. package/lib/components/bundle-modules/bundle-modules.module.css +0 -5
  19. package/lib/components/bundle-modules/index.js +3 -4
  20. package/lib/components/bundle-modules/index.js.map +1 -1
  21. package/lib/components/bundle-packages/bundle-packages.js +19 -4
  22. package/lib/components/bundle-packages/bundle-packages.js.map +1 -1
  23. package/lib/components/bundle-packages/bundle-packages.module.css +0 -5
  24. package/lib/components/bundle-packages/index.js +3 -4
  25. package/lib/components/bundle-packages/index.js.map +1 -1
  26. package/lib/components/index.js +3 -7
  27. package/lib/components/index.js.map +1 -1
  28. package/lib/components/jobs-header/jobs-header.module.css +0 -4
  29. package/lib/components/{bundle-assets-totals-table → metrics-display-selector}/index.js +1 -1
  30. package/lib/components/metrics-display-selector/index.js.map +1 -0
  31. package/lib/components/metrics-display-selector/metrics-display-selector.js +21 -0
  32. package/lib/components/metrics-display-selector/metrics-display-selector.js.map +1 -0
  33. package/lib/components/metrics-display-selector/metrics-display-selector.module.css +10 -0
  34. package/lib/components/metrics-table/metrics-table.i18n.js +1 -6
  35. package/lib/components/metrics-table/metrics-table.i18n.js.map +1 -1
  36. package/lib/components/metrics-table/metrics-table.js +4 -37
  37. package/lib/components/metrics-table/metrics-table.js.map +1 -1
  38. package/lib/components/metrics-table/metrics-table.module.css +1 -44
  39. package/lib/components/{total-size-type-title → metrics-table-header}/index.js +1 -1
  40. package/lib/components/metrics-table-header/index.js.map +1 -0
  41. package/lib/components/metrics-table-header/metrics-table-header.i18n.js +9 -0
  42. package/lib/components/metrics-table-header/metrics-table-header.i18n.js.map +1 -0
  43. package/lib/components/metrics-table-header/metrics-table-header.js +79 -0
  44. package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -0
  45. package/lib/components/metrics-table-header/metrics-table-header.module.css +51 -0
  46. package/lib/components/metrics-table-options/metrics-table-options.js +2 -2
  47. package/lib/components/metrics-table-options/metrics-table-options.js.map +1 -1
  48. package/lib/components/metrics-table-title/metrics-table-title.js +1 -1
  49. package/lib/components/metrics-table-title/metrics-table-title.js.map +1 -1
  50. package/lib/components/metrics-table-title/metrics-table-title.module.css +4 -4
  51. package/lib/components/{bundle-assets-totals-chart-bars → metrics-treemap}/index.js +1 -1
  52. package/lib/components/metrics-treemap/index.js.map +1 -0
  53. package/lib/components/metrics-treemap/metrics-treemap.js +163 -0
  54. package/lib/components/metrics-treemap/metrics-treemap.js.map +1 -0
  55. package/lib/components/metrics-treemap/metrics-treemap.module.css +201 -0
  56. package/lib/components/sort-button/sort-button.module.css +1 -0
  57. package/lib/constants.js +6 -1
  58. package/lib/constants.js.map +1 -1
  59. package/lib/css/variables.css +11 -11
  60. package/lib/hooks/entry-info.js +12 -0
  61. package/lib/hooks/entry-info.js.map +1 -0
  62. package/lib/hooks/metrics-display-type.js +40 -0
  63. package/lib/hooks/metrics-display-type.js.map +1 -0
  64. package/lib/layout/flex-stack/flex-stack.js +3 -4
  65. package/lib/layout/flex-stack/flex-stack.js.map +1 -1
  66. package/lib/layout/flex-stack/flex-stack.module.css +19 -23
  67. package/lib/query-state.js +1 -1
  68. package/lib/query-state.js.map +1 -1
  69. package/lib/ui/button/button.module.css +1 -0
  70. package/lib/ui/dropdown/dropdown.js +10 -40
  71. package/lib/ui/dropdown/dropdown.js.map +1 -1
  72. package/lib/ui/dropdown/index.js.map +1 -1
  73. package/lib/ui/filters/filters.js +33 -35
  74. package/lib/ui/filters/filters.js.map +1 -1
  75. package/lib/ui/filters/filters.module.css +55 -67
  76. package/lib/ui/hover-card/hover-card.js +1 -1
  77. package/lib/ui/hover-card/hover-card.js.map +1 -1
  78. package/lib/ui/icon/icon.js +2 -0
  79. package/lib/ui/icon/icon.js.map +1 -1
  80. package/lib/ui/index.js +1 -3
  81. package/lib/ui/index.js.map +1 -1
  82. package/lib/ui/toolbar/toolbar.module.css +1 -3
  83. package/lib-esm/app/app.js +5 -13
  84. package/lib-esm/app/app.js.map +1 -1
  85. package/lib-esm/app/app.module.css +2 -2
  86. package/lib-esm/assets/icons.svg +26 -20
  87. package/lib-esm/assets/icons.svg.js +27 -23
  88. package/lib-esm/assets/icons.svg.js.map +1 -1
  89. package/lib-esm/components/bundle-assets/bundle-assets.js +21 -6
  90. package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
  91. package/lib-esm/components/bundle-assets/bundle-assets.module.css +0 -5
  92. package/lib-esm/components/bundle-assets/index.js +5 -6
  93. package/lib-esm/components/bundle-assets/index.js.map +1 -1
  94. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js +58 -0
  95. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -0
  96. package/lib-esm/components/bundle-assets-totals/index.js +2 -0
  97. package/lib-esm/components/bundle-assets-totals/index.js.map +1 -0
  98. package/lib-esm/components/bundle-modules/bundle-modules.js +24 -9
  99. package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
  100. package/lib-esm/components/bundle-modules/bundle-modules.module.css +0 -5
  101. package/lib-esm/components/bundle-modules/index.js +3 -4
  102. package/lib-esm/components/bundle-modules/index.js.map +1 -1
  103. package/lib-esm/components/bundle-packages/bundle-packages.js +19 -4
  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/bundle-packages/index.js +5 -6
  107. package/lib-esm/components/bundle-packages/index.js.map +1 -1
  108. package/lib-esm/components/index.js +1 -3
  109. package/lib-esm/components/index.js.map +1 -1
  110. package/lib-esm/components/jobs-header/jobs-header.module.css +0 -4
  111. package/lib-esm/components/metrics-display-selector/index.js +2 -0
  112. package/lib-esm/components/metrics-display-selector/index.js.map +1 -0
  113. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js +14 -0
  114. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js.map +1 -0
  115. package/lib-esm/components/metrics-display-selector/metrics-display-selector.module.css +10 -0
  116. package/lib-esm/components/metrics-table/metrics-table.i18n.js +0 -5
  117. package/lib-esm/components/metrics-table/metrics-table.i18n.js.map +1 -1
  118. package/lib-esm/components/metrics-table/metrics-table.js +4 -37
  119. package/lib-esm/components/metrics-table/metrics-table.js.map +1 -1
  120. package/lib-esm/components/metrics-table/metrics-table.module.css +1 -44
  121. package/lib-esm/components/metrics-table-header/index.js +2 -0
  122. package/lib-esm/components/metrics-table-header/index.js.map +1 -0
  123. package/lib-esm/components/metrics-table-header/metrics-table-header.i18n.js +6 -0
  124. package/lib-esm/components/metrics-table-header/metrics-table-header.i18n.js.map +1 -0
  125. package/lib-esm/components/metrics-table-header/metrics-table-header.js +49 -0
  126. package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -0
  127. package/lib-esm/components/metrics-table-header/metrics-table-header.module.css +51 -0
  128. package/lib-esm/components/metrics-table-options/metrics-table-options.js +3 -3
  129. package/lib-esm/components/metrics-table-options/metrics-table-options.js.map +1 -1
  130. package/lib-esm/components/metrics-table-title/metrics-table-title.js +1 -1
  131. package/lib-esm/components/metrics-table-title/metrics-table-title.js.map +1 -1
  132. package/lib-esm/components/metrics-table-title/metrics-table-title.module.css +4 -4
  133. package/lib-esm/components/metrics-treemap/index.js +2 -0
  134. package/lib-esm/components/metrics-treemap/index.js.map +1 -0
  135. package/lib-esm/components/metrics-treemap/metrics-treemap.js +135 -0
  136. package/lib-esm/components/metrics-treemap/metrics-treemap.js.map +1 -0
  137. package/lib-esm/components/metrics-treemap/metrics-treemap.module.css +201 -0
  138. package/lib-esm/components/sort-button/sort-button.module.css +1 -0
  139. package/lib-esm/constants.js +5 -0
  140. package/lib-esm/constants.js.map +1 -1
  141. package/lib-esm/css/variables.css +11 -11
  142. package/lib-esm/hooks/entry-info.js +8 -0
  143. package/lib-esm/hooks/entry-info.js.map +1 -0
  144. package/lib-esm/hooks/metrics-display-type.js +36 -0
  145. package/lib-esm/hooks/metrics-display-type.js.map +1 -0
  146. package/lib-esm/layout/flex-stack/flex-stack.js +3 -4
  147. package/lib-esm/layout/flex-stack/flex-stack.js.map +1 -1
  148. package/lib-esm/layout/flex-stack/flex-stack.module.css +19 -23
  149. package/lib-esm/query-state.js +1 -1
  150. package/lib-esm/query-state.js.map +1 -1
  151. package/lib-esm/ui/button/button.module.css +1 -0
  152. package/lib-esm/ui/dropdown/dropdown.js +8 -39
  153. package/lib-esm/ui/dropdown/dropdown.js.map +1 -1
  154. package/lib-esm/ui/dropdown/index.js.map +1 -1
  155. package/lib-esm/ui/filters/filters.js +34 -36
  156. package/lib-esm/ui/filters/filters.js.map +1 -1
  157. package/lib-esm/ui/filters/filters.module.css +55 -67
  158. package/lib-esm/ui/hover-card/hover-card.js +1 -1
  159. package/lib-esm/ui/hover-card/hover-card.js.map +1 -1
  160. package/lib-esm/ui/icon/icon.js +2 -0
  161. package/lib-esm/ui/icon/icon.js.map +1 -1
  162. package/lib-esm/ui/index.js +0 -1
  163. package/lib-esm/ui/index.js.map +1 -1
  164. package/lib-esm/ui/toolbar/toolbar.module.css +1 -3
  165. package/package.json +10 -7
  166. package/src/app/app.jsx +5 -17
  167. package/src/app/app.module.css +2 -2
  168. package/src/assets/icons/table.svg +3 -0
  169. package/src/assets/icons/treemap.svg +4 -0
  170. package/src/assets/icons.svg +26 -20
  171. package/src/assets/icons.svg.jsx +91 -55
  172. package/src/components/bundle-assets/bundle-assets.jsx +47 -16
  173. package/src/components/bundle-assets/bundle-assets.module.css +0 -5
  174. package/src/components/bundle-assets/index.jsx +10 -5
  175. package/src/components/bundle-assets-totals/bundle-assets-totals.jsx +125 -0
  176. package/src/components/bundle-assets-totals/index.js +1 -0
  177. package/src/components/bundle-modules/bundle-modules.module.css +0 -5
  178. package/src/components/bundle-modules/bundle-modules.tsx +65 -35
  179. package/src/components/bundle-modules/index.tsx +4 -3
  180. package/src/components/bundle-packages/bundle-packages.jsx +42 -14
  181. package/src/components/bundle-packages/bundle-packages.module.css +0 -5
  182. package/src/components/bundle-packages/index.jsx +10 -5
  183. package/src/components/index.js +1 -3
  184. package/src/components/jobs-header/jobs-header.module.css +0 -4
  185. package/src/components/metrics-display-selector/index.tsx +1 -0
  186. package/src/components/metrics-display-selector/metrics-display-selector.module.css +10 -0
  187. package/src/components/metrics-display-selector/metrics-display-selector.tsx +47 -0
  188. package/src/components/metrics-table/metrics-table.i18n.ts +0 -7
  189. package/src/components/metrics-table/metrics-table.module.css +1 -44
  190. package/src/components/metrics-table/metrics-table.tsx +17 -153
  191. package/src/components/metrics-table-header/index.ts +1 -0
  192. package/src/components/metrics-table-header/metrics-table-header.i18n.ts +6 -0
  193. package/src/components/metrics-table-header/metrics-table-header.module.css +51 -0
  194. package/src/components/metrics-table-header/metrics-table-header.tsx +172 -0
  195. package/src/components/metrics-table-options/metrics-table-options.jsx +4 -10
  196. package/src/components/metrics-table-title/metrics-table-title.jsx +1 -1
  197. package/src/components/metrics-table-title/metrics-table-title.module.css +4 -4
  198. package/src/components/metrics-treemap/index.ts +1 -0
  199. package/src/components/metrics-treemap/metrics-treemap.module.css +201 -0
  200. package/src/components/metrics-treemap/metrics-treemap.stories.tsx +23 -0
  201. package/src/components/metrics-treemap/metrics-treemap.tsx +304 -0
  202. package/src/components/sort-button/sort-button.module.css +1 -0
  203. package/src/{constants.js → constants.ts} +5 -0
  204. package/src/css/variables.css +11 -11
  205. package/src/hooks/entry-info.ts +19 -0
  206. package/src/hooks/metrics-display-type.ts +56 -0
  207. package/src/layout/flex-stack/flex-stack.module.css +19 -23
  208. package/src/layout/flex-stack/flex-stack.tsx +2 -8
  209. package/src/query-state.tsx +1 -1
  210. package/src/types.d.ts +2 -0
  211. package/src/ui/button/button.module.css +1 -0
  212. package/src/ui/dropdown/dropdown.stories.tsx +25 -0
  213. package/src/ui/dropdown/dropdown.tsx +66 -0
  214. package/src/ui/filters/filters.module.css +55 -67
  215. package/src/ui/filters/filters.stories.tsx +109 -0
  216. package/src/ui/filters/filters.tsx +128 -167
  217. package/src/ui/hover-card/hover-card.tsx +1 -1
  218. package/src/ui/icon/icon.tsx +2 -0
  219. package/src/ui/index.js +0 -1
  220. package/src/ui/toolbar/toolbar.module.css +1 -3
  221. package/types/components/bundle-assets/bundle-assets.d.ts +2 -1
  222. package/types/components/{bundle-assets-totals-table/bundle-assets-totals-table.d.ts → bundle-assets-totals/bundle-assets-totals.d.ts} +6 -2
  223. package/types/components/bundle-assets-totals/index.d.ts +1 -0
  224. package/types/components/bundle-modules/bundle-modules.d.ts +2 -1
  225. package/types/components/bundle-modules/index.d.ts +1 -1
  226. package/types/components/bundle-packages/bundle-packages.d.ts +1 -0
  227. package/types/components/index.d.ts +1 -3
  228. package/types/components/metrics-display-selector/index.d.ts +1 -0
  229. package/types/components/metrics-display-selector/metrics-display-selector.d.ts +9 -0
  230. package/types/components/metrics-table/metrics-table.d.ts +4 -10
  231. package/types/components/metrics-table/metrics-table.i18n.d.ts +0 -5
  232. package/types/components/metrics-table-header/index.d.ts +1 -0
  233. package/types/components/metrics-table-header/metrics-table-header.d.ts +15 -0
  234. package/types/components/metrics-table-header/metrics-table-header.i18n.d.ts +5 -0
  235. package/types/components/metrics-treemap/index.d.ts +1 -0
  236. package/types/components/metrics-treemap/metrics-treemap.d.ts +9 -0
  237. package/types/constants.d.ts +19 -15
  238. package/types/hooks/entry-info.d.ts +8 -0
  239. package/types/hooks/metrics-display-type.d.ts +4 -0
  240. package/types/ui/dropdown/dropdown.d.ts +12 -47
  241. package/types/ui/dropdown/index.d.ts +1 -1
  242. package/types/ui/filters/filters.d.ts +2 -7
  243. package/types/ui/icon/icon.d.ts +4 -0
  244. package/types/ui/index.d.ts +0 -1
  245. package/lib/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.js +0 -95
  246. package/lib/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.js.map +0 -1
  247. package/lib/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.module.css +0 -42
  248. package/lib/components/bundle-assets-totals-chart-bars/index.js.map +0 -1
  249. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.js +0 -57
  250. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.js.map +0 -1
  251. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +0 -3
  252. package/lib/components/bundle-assets-totals-table/index.js.map +0 -1
  253. package/lib/components/total-size-type-title/index.js.map +0 -1
  254. package/lib/components/total-size-type-title/total-size-type-title.js +0 -32
  255. package/lib/components/total-size-type-title/total-size-type-title.js.map +0 -1
  256. package/lib/components/total-size-type-title/total-size-type-title.module.css +0 -14
  257. package/lib/ui/horizontal-bar-chart/horizontal-bar-chart.js +0 -102
  258. package/lib/ui/horizontal-bar-chart/horizontal-bar-chart.js.map +0 -1
  259. package/lib/ui/horizontal-bar-chart/horizontal-bar-chart.module.css +0 -42
  260. package/lib/ui/horizontal-bar-chart/index.js.map +0 -1
  261. package/lib-esm/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.js +0 -66
  262. package/lib-esm/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.js.map +0 -1
  263. package/lib-esm/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.module.css +0 -42
  264. package/lib-esm/components/bundle-assets-totals-chart-bars/index.js +0 -2
  265. package/lib-esm/components/bundle-assets-totals-chart-bars/index.js.map +0 -1
  266. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.js +0 -27
  267. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.js.map +0 -1
  268. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +0 -3
  269. package/lib-esm/components/bundle-assets-totals-table/index.js +0 -2
  270. package/lib-esm/components/bundle-assets-totals-table/index.js.map +0 -1
  271. package/lib-esm/components/total-size-type-title/index.js +0 -2
  272. package/lib-esm/components/total-size-type-title/index.js.map +0 -1
  273. package/lib-esm/components/total-size-type-title/total-size-type-title.js +0 -25
  274. package/lib-esm/components/total-size-type-title/total-size-type-title.js.map +0 -1
  275. package/lib-esm/components/total-size-type-title/total-size-type-title.module.css +0 -14
  276. package/lib-esm/ui/horizontal-bar-chart/horizontal-bar-chart.js +0 -96
  277. package/lib-esm/ui/horizontal-bar-chart/horizontal-bar-chart.js.map +0 -1
  278. package/lib-esm/ui/horizontal-bar-chart/horizontal-bar-chart.module.css +0 -42
  279. package/lib-esm/ui/horizontal-bar-chart/index.js +0 -2
  280. package/lib-esm/ui/horizontal-bar-chart/index.js.map +0 -1
  281. package/src/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.jsx +0 -106
  282. package/src/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.module.css +0 -42
  283. package/src/components/bundle-assets-totals-chart-bars/index.js +0 -1
  284. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.jsx +0 -55
  285. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +0 -3
  286. package/src/components/bundle-assets-totals-table/index.js +0 -1
  287. package/src/components/total-size-type-title/index.js +0 -1
  288. package/src/components/total-size-type-title/total-size-type-title.jsx +0 -41
  289. package/src/components/total-size-type-title/total-size-type-title.module.css +0 -14
  290. package/src/ui/dropdown/dropdown.jsx +0 -88
  291. package/src/ui/horizontal-bar-chart/horizontal-bar-chart.jsx +0 -156
  292. package/src/ui/horizontal-bar-chart/horizontal-bar-chart.module.css +0 -42
  293. package/src/ui/horizontal-bar-chart/index.js +0 -1
  294. package/types/components/bundle-assets-totals-chart-bars/bundle-assets-totals-chart-bars.d.ts +0 -22
  295. package/types/components/bundle-assets-totals-chart-bars/index.d.ts +0 -1
  296. package/types/components/bundle-assets-totals-table/index.d.ts +0 -1
  297. package/types/components/total-size-type-title/index.d.ts +0 -1
  298. package/types/components/total-size-type-title/total-size-type-title.d.ts +0 -14
  299. package/types/ui/horizontal-bar-chart/horizontal-bar-chart.d.ts +0 -23
  300. package/types/ui/horizontal-bar-chart/index.d.ts +0 -1
  301. /package/src/ui/dropdown/{index.js → index.ts} +0 -0
@@ -0,0 +1,201 @@
1
+ .root {
2
+ position: relative;
3
+ aspect-ratio: 16/9;
4
+ background: var(--color-background);
5
+ }
6
+
7
+ .canvas {
8
+ position: absolute;
9
+ left: 0;
10
+ top: 0;
11
+ width: 100%;
12
+ height: 100%;
13
+ fill: var(--color-text);
14
+ font-family: var(--font-family);
15
+ background: var(--color-background);
16
+ }
17
+
18
+ /** Tile overlay fill background transition */
19
+ .root {
20
+ transition: var(--ui-transition-out);
21
+ transition-property: opacity;
22
+ }
23
+
24
+ /** Leaf wrapper button */
25
+ .leaf {
26
+ position: absolute;
27
+ appearance: none;
28
+ border: 0;
29
+ border-radius: 0;
30
+ padding: 0;
31
+ background: none;
32
+ display: flex;
33
+ align-items: center;
34
+ font-family: var(--font-family-fixed);
35
+ font-size: var(--size-small);
36
+ line-height: var(--line-height-heading);
37
+ text-align: left;
38
+ }
39
+
40
+ .leaf::before {
41
+ content: "";
42
+ display: block;
43
+ position: absolute;
44
+ z-index: 1;
45
+ left: 0;
46
+ top: 0;
47
+ width: 100%;
48
+ height: 100%;
49
+ background-color: currentColor;
50
+ color: var(--color-background);
51
+ transition: var(--ui-transition-out);
52
+ transition-property: opacity;
53
+ opacity: 0.6;
54
+ }
55
+
56
+ .leaf:hover::before {
57
+ transition: var(--ui-transition-in);
58
+ opacity: 0.4;
59
+ }
60
+
61
+ .leafContent {
62
+ position: relative;
63
+ z-index: 1;
64
+ width: 100%;
65
+ height: 100%;
66
+ display: flex;
67
+ flex-flow: column;
68
+ justify-content: center;
69
+ padding: var(--space-xxsmall) var(--space-xxsmall);
70
+ gap: var(--space-xxxsmall);
71
+ line-height: var(--line-height-heading);
72
+ }
73
+
74
+ /** Align label to other elements on the first column leafs */
75
+ .leafFirstCol .leafContent {
76
+ padding-left: var(--space-small);
77
+ }
78
+
79
+ .leadContentLabel {
80
+ flex: 0 1 auto;
81
+ width: 100%;
82
+ min-width: 0;
83
+ max-height: calc(2em * var(--line-height-heading));
84
+ overflow: hidden;
85
+ }
86
+
87
+ .leadContentValue {
88
+ flex: 0 0 auto;
89
+ max-width: calc(100% + var(--space-xxsmall));
90
+ white-space: nowrap;
91
+ overflow: hidden;
92
+ }
93
+
94
+ .leadContentMetric {
95
+ font-weight: bold;
96
+ }
97
+
98
+ .leadContentDelta {
99
+ margin-left: var(--space-xxxsmall);
100
+ }
101
+
102
+ /** Tile size variation */
103
+ .leafSmall .leafContent {
104
+ padding: var(--space-xxxsmall) var(--space-xxsmall);
105
+ gap: 0;
106
+ font-size: var(--size-xsmall);
107
+ }
108
+
109
+ .leafSmall .leadContentLabel {
110
+ margin-top: 0;
111
+ }
112
+
113
+ /** Tile diff variation */
114
+ .leaf-NO_CHANGE {
115
+ color: var(--color-text-light);
116
+ }
117
+
118
+ .leaf-NO_CHANGE::before {
119
+ color: var(--color-gray-50);
120
+ opacity: 0.4;
121
+ }
122
+
123
+ .leaf-NO_CHANGE:hover::before {
124
+ opacity: 0.2;
125
+ }
126
+
127
+ .leaf-HIGH_NEGATIVE::before {
128
+ color: var(--color-red-100);
129
+ }
130
+
131
+ .leaf-NEGATIVE::before {
132
+ color: var(--color-red-50);
133
+ }
134
+
135
+ .leaf-LOW_NEGATIVE::before {
136
+ color: var(--color-red-25);
137
+ }
138
+
139
+ .leaf-LOW_POSITIVE::before {
140
+ color: var(--color-green-25);
141
+ }
142
+
143
+ .leaf-POSITIVE::before {
144
+ color: var(--color-green-50);
145
+ }
146
+
147
+ .leaf-HIGH_POSITIVE::before {
148
+ color: var(--color-green-100);
149
+ }
150
+
151
+ /** empty message */
152
+ .emptyMessage {
153
+ position: absolute;
154
+ left: 0;
155
+ top: 0;
156
+ width: 100%;
157
+ height: 100%;
158
+ display: flex;
159
+ align-items: center;
160
+ justify-content: center;
161
+ }
162
+
163
+ .emptyMessageWrapper {
164
+ max-width: 100%;
165
+ text-align: center;
166
+ }
167
+
168
+ /** tooltip */
169
+ .leafContentTooltipAnchor {
170
+ width: 100%;
171
+ height: 100%;
172
+ }
173
+
174
+ .tooltip {
175
+ z-index: var(--layer-xxhigh);
176
+ padding: var(--space-xsmall) var(--space-small);
177
+ border-radius: var(--radius-medium);
178
+ width: calc(100vw - 2 * var(--space-small));
179
+ max-width: 340px;
180
+ outline: none;
181
+ filter: drop-shadow(var(--shadow-layer-high));
182
+ will-change: filter;
183
+ background: var(--color-light);
184
+ font-size: var(--size-small);
185
+ pointer-events: none;
186
+ }
187
+
188
+ /* prevent tooltip portal wrapper from capturing events */
189
+ div[role="presentation"]:has(.tooltip) {
190
+ pointer-events: none;
191
+ }
192
+
193
+
194
+ .leafTooltipArrow svg {
195
+ display: block;
196
+ fill: var(--color-background) !important;
197
+ }
198
+
199
+ .leafTooltipContentTitle {
200
+ font-size: var(--size-medium);
201
+ }
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { Meta, StoryObj } from '@storybook/react';
3
+ // eslint-disable-next-line import/no-extraneous-dependencies
4
+ import { action } from '@storybook/addon-actions';
5
+
6
+ // eslint-disable-next-line import/no-relative-packages
7
+ import moduleItemsFixture from '../../../../../fixtures/module-items.json';
8
+ import { MetricsTreemap } from '.';
9
+
10
+ export default {
11
+ title: 'Components/MetricsTreemap',
12
+ component: MetricsTreemap,
13
+ } as Meta;
14
+
15
+ export const Default: StoryObj = {
16
+ render: (props: React.ComponentProps<typeof MetricsTreemap>) => (
17
+ <MetricsTreemap style={{ maxWidth: 'var(--max-width)' }} {...props} />
18
+ ),
19
+ args: {
20
+ items: moduleItemsFixture,
21
+ onItemClick: action('CLICK'),
22
+ },
23
+ };
@@ -0,0 +1,304 @@
1
+ import React, { RefObject, forwardRef, useCallback, useMemo, useRef } from 'react';
2
+ import { useDebounce, useHoverDirty, useMeasure, useMouseHovered } from 'react-use';
3
+ import cx from 'classnames';
4
+ import type { ReportMetricRow, MetricRunInfo, MetricRunInfoBaseline } from '@bundle-stats/utils';
5
+ import { hierarchy, treemap, treemapSquarify } from 'd3';
6
+ import { Tooltip, TooltipArrow, TooltipAnchor, useTooltipState } from 'ariakit/tooltip';
7
+
8
+ import { Stack } from '../../layout/stack';
9
+ import { FileName } from '../../ui/file-name';
10
+ import { Delta } from '../delta';
11
+ import { RunInfo } from '../run-info';
12
+ import css from './metrics-treemap.module.css';
13
+
14
+ const SQUARIFY_RATIO = 1.33;
15
+ const PADDING_OUTER = 0;
16
+ const PADDING_INNER = 2;
17
+
18
+ type TileSizeDisplay = 'minimal' | 'small' | 'default';
19
+
20
+ /**
21
+ * Resolve the tile size using predefined values to avoid
22
+ * computing the size of the content for every tile
23
+ */
24
+ const PADDING_TOP = 4;
25
+ const PADDING_BOTTOM = 2; // substracted to allow longer texts to appear
26
+ const PADDING_LEFT = 16;
27
+ const PADDING_RIGHT = 4; // substracted to allow longer texts to not break
28
+ const VERTICAL_SPACING = 4;
29
+ const LINE_HEIGHT = 16;
30
+ const LINE_HEIGHT_SMALL = 13.3;
31
+
32
+ function resolveLeafSizeDisplay(width: number, height: number): TileSizeDisplay {
33
+ if (
34
+ height > PADDING_TOP + PADDING_BOTTOM + VERTICAL_SPACING + LINE_HEIGHT * 2 &&
35
+ width > PADDING_LEFT + PADDING_RIGHT + 128
36
+ ) {
37
+ return 'default';
38
+ }
39
+
40
+ if (
41
+ height > PADDING_TOP + PADDING_BOTTOM + LINE_HEIGHT_SMALL * 2 &&
42
+ width > PADDING_LEFT + PADDING_BOTTOM + 48
43
+ ) {
44
+ return 'small';
45
+ }
46
+
47
+ return 'minimal';
48
+ }
49
+
50
+ interface LeafTooltipContentProps {
51
+ item: ReportMetricRow;
52
+ }
53
+
54
+ const LeafTooltipContent = (props: LeafTooltipContentProps) => {
55
+ const { item } = props;
56
+
57
+ const currentRun = item.runs[0] as MetricRunInfo;
58
+ const baselineRun = item.runs[item.runs.length - 1] as MetricRunInfoBaseline;
59
+
60
+ return (
61
+ <Stack space="small" className={css.leafTooltipContent}>
62
+ <h3 className={css.leafTooltipContentTitle}>
63
+ <FileName as="code" name={item.label} />
64
+ </h3>
65
+ <RunInfo
66
+ current={currentRun.displayValue}
67
+ delta={currentRun.displayDeltaPercentage}
68
+ deltaType={currentRun.deltaType}
69
+ baseline={baselineRun?.displayValue || '0B'}
70
+ />
71
+ </Stack>
72
+ );
73
+ };
74
+
75
+ interface LeafContentProps {
76
+ sizeDisplay: 'minimal' | 'small' | 'default';
77
+ item: ReportMetricRow;
78
+ runInfo: MetricRunInfo;
79
+ }
80
+
81
+ const LeafContent = forwardRef((props: LeafContentProps, ref: React.Ref<HTMLDivElement>) => {
82
+ const { sizeDisplay, item, runInfo } = props;
83
+
84
+ if (sizeDisplay === 'minimal') {
85
+ return <div className={css.leafContent} ref={ref} />;
86
+ }
87
+
88
+ return (
89
+ <div className={css.leafContent} ref={ref}>
90
+ <FileName as="p" className={css.leadContentLabel} name={item.label} />
91
+ {sizeDisplay !== 'small' && (
92
+ <p className={css.leadContentValue}>
93
+ <span className={css.leadContentMetric}>{runInfo.displayValue}</span>
94
+ <Delta
95
+ className={css.leadContentDelta}
96
+ displayValue={runInfo.displayDeltaPercentage}
97
+ deltaType={runInfo.deltaType}
98
+ />
99
+ </p>
100
+ )}
101
+ </div>
102
+ );
103
+ });
104
+
105
+ const LeafContentWithTooltip = (props: LeafContentProps & { parentRef: RefObject<Element> }) => {
106
+ const { sizeDisplay, item, runInfo, parentRef } = props;
107
+
108
+ const pointer = useMouseHovered(parentRef, { whenHovered: true });
109
+
110
+ // Return custom rect based on the mouse position
111
+ const getAnchorRect = useCallback(() => {
112
+ // Skip custom component rect area if the pointer position is empty
113
+ if (pointer.docX === 0 && pointer.docY === 0 && pointer.elW === 0 && pointer.elH === 0) {
114
+ return null;
115
+ }
116
+
117
+ const newRect = {
118
+ x: pointer.docX - (document?.defaultView?.scrollX ?? 0),
119
+ y: pointer.docY - (document?.defaultView?.scrollY ?? 0),
120
+ w: 1,
121
+ h: 1,
122
+ };
123
+
124
+ return newRect;
125
+ }, [pointer.docX, pointer.docY]);
126
+
127
+ const tooltipState = useTooltipState({ gutter: 12, getAnchorRect, timeout: 120 });
128
+
129
+ // Update tooltip position when poiner values are changing
130
+ useDebounce(tooltipState.render, 5, [pointer.docX, pointer.docY]);
131
+
132
+ return (
133
+ <>
134
+ <TooltipAnchor state={tooltipState} className={css.leafContentTooltipAnchor}>
135
+ <LeafContent sizeDisplay={sizeDisplay} item={item} runInfo={runInfo} />
136
+ </TooltipAnchor>
137
+ <Tooltip state={tooltipState} className={css.tooltip}>
138
+ <TooltipArrow state={tooltipState} size={16} className={css.leafTooltipArrow} />
139
+ <LeafTooltipContent item={item} />
140
+ </Tooltip>
141
+ </>
142
+ );
143
+ };
144
+
145
+ interface TreeNode {
146
+ id: string;
147
+ value: number;
148
+ item: ReportMetricRow;
149
+ children?: Array<TreeNode>;
150
+ }
151
+
152
+ interface RootTree {
153
+ id: string;
154
+ value: number;
155
+ children: Array<TreeNode>;
156
+ }
157
+
158
+ interface LeafProps {
159
+ left: number;
160
+ top: number;
161
+ width: number;
162
+ height: number;
163
+ data: TreeNode;
164
+ onClick?: (id: string) => void;
165
+ }
166
+
167
+ const Leaf = (props: LeafProps) => {
168
+ const { left, top, width, height, data, onClick } = props;
169
+
170
+ const { item } = data;
171
+ const runInfo = item.runs?.[0] as MetricRunInfo;
172
+
173
+ const sizeDisplay = useMemo(() => resolveLeafSizeDisplay(width, height), [width, height]);
174
+ const handleOnClick = useCallback(() => onClick?.(item.key), [item.key, onClick]);
175
+
176
+ const leafContentRef = useRef<HTMLButtonElement>(null);
177
+ const hover = useHoverDirty(leafContentRef);
178
+
179
+ const leafClassName = cx(
180
+ css.leaf,
181
+ css[`leaf-${runInfo.deltaType}`],
182
+ sizeDisplay === 'small' && css.leafSmall,
183
+ left === 0 && css.leafFirstCol,
184
+ );
185
+
186
+ return (
187
+ <button
188
+ type="button"
189
+ onClick={handleOnClick}
190
+ ref={leafContentRef}
191
+ style={{ left, top, width, height }}
192
+ className={leafClassName}
193
+ >
194
+ {hover ? (
195
+ <LeafContentWithTooltip
196
+ sizeDisplay={sizeDisplay}
197
+ item={item}
198
+ runInfo={runInfo}
199
+ parentRef={leafContentRef}
200
+ />
201
+ ) : (
202
+ <LeafContent sizeDisplay={sizeDisplay} item={item} runInfo={runInfo} />
203
+ )}
204
+ </button>
205
+ );
206
+ };
207
+
208
+ interface UseMetricsTreemapHierarchyParams {
209
+ items: Array<ReportMetricRow>;
210
+ width: number;
211
+ height: number;
212
+ }
213
+
214
+ function useMetricsTreemapHierarchy(params: UseMetricsTreemapHierarchyParams) {
215
+ const { items, width, height } = params;
216
+
217
+ const treemapHierarchy = useMemo(() => {
218
+ const children = items.map((item) => {
219
+ /**
220
+ * Set leaf value to the largest run value to allow to
221
+ * display the impact of deleted / items
222
+ */
223
+ const values = item.runs.map((run) => run?.value || 0);
224
+ const value = Math.max(...values);
225
+
226
+ return {
227
+ id: item.key,
228
+ value,
229
+ item,
230
+ };
231
+ });
232
+
233
+ const treemapData = {
234
+ id: 'root',
235
+ name: 'root',
236
+ value: 0,
237
+ children,
238
+ };
239
+
240
+ const customHierarchy = hierarchy<RootTree>(treemapData);
241
+ customHierarchy.sum((node) => node.value);
242
+ // @ts-expect-error
243
+ customHierarchy.sort((a, b) => b.value - a.value);
244
+
245
+ return customHierarchy;
246
+ }, [items]);
247
+
248
+ const cells = useMemo(() => {
249
+ const createTremapLayout = treemap()
250
+ .size([width, height])
251
+ .tile(treemapSquarify.ratio(SQUARIFY_RATIO))
252
+ .paddingOuter(PADDING_OUTER)
253
+ .paddingInner(PADDING_INNER);
254
+ // @ts-expect-error
255
+ const tremapLayout = createTremapLayout(treemapHierarchy);
256
+
257
+ return tremapLayout.leaves().filter((leaf) => Boolean(leaf.parent));
258
+ }, [height, width, treemapHierarchy]);
259
+
260
+ return cells;
261
+ }
262
+
263
+ interface MetricsTreemapProps {
264
+ items: Array<ReportMetricRow>;
265
+ emptyMessage?: React.ReactNode;
266
+ onItemClick?: (entryId: string) => void;
267
+ }
268
+
269
+ export const MetricsTreemap = (props: MetricsTreemapProps & React.ComponentProps<'div'>) => {
270
+ const { className = '', items, onItemClick, emptyMessage = 'No data', ...restProps } = props;
271
+
272
+ const [containerRef, { width, height }] = useMeasure<HTMLDivElement>();
273
+ const cells = useMetricsTreemapHierarchy({ items, width, height });
274
+
275
+ return (
276
+ <div className={cx(css.root, className)} {...restProps} ref={containerRef}>
277
+ {cells.length > 0 ? (
278
+ <div className={css.canvas}>
279
+ {cells.map((leaf) => {
280
+ if (!leaf.parent) {
281
+ return null;
282
+ }
283
+
284
+ return (
285
+ <Leaf
286
+ data={leaf.data as TreeNode}
287
+ left={leaf.x0}
288
+ top={leaf.y0}
289
+ width={leaf.x1 - leaf.x0}
290
+ height={leaf.y1 - leaf.y0}
291
+ onClick={onItemClick}
292
+ key={leaf.id}
293
+ />
294
+ );
295
+ })}
296
+ </div>
297
+ ) : (
298
+ <div className={css.emptyMessage}>
299
+ <div className={css.emptyMessageWrapper}>{emptyMessage}</div>
300
+ </div>
301
+ )}
302
+ </div>
303
+ );
304
+ };
@@ -3,6 +3,7 @@
3
3
  display: inline-block;
4
4
  border-radius: var(--radius-small);
5
5
  position: relative;
6
+ color: var(--color-text-ultra-light);
6
7
  }
7
8
 
8
9
  .toggle {
@@ -40,3 +40,8 @@ export const SORT = {
40
40
  ASC: 'asc',
41
41
  DESC: 'desc',
42
42
  };
43
+
44
+ export enum MetricsDisplayType {
45
+ TABLE = 'table',
46
+ TREEMAP = 'treemap',
47
+ }
@@ -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);
@@ -199,7 +199,7 @@
199
199
  --outline-hover: 0 0 0 3px var(--color-highlight);
200
200
 
201
201
  /** Layout */
202
- --max-width: 88rem;
202
+ --max-width: 82rem;
203
203
  --entry-info-width: 64rem;
204
204
  --entry-info-top: var(--header-height);
205
205
  }
@@ -0,0 +1,19 @@
1
+ import { useCallback } from 'react';
2
+
3
+ interface UseEntryInfoParams {
4
+ setState: (data: { entryId: string }) => void;
5
+ }
6
+
7
+ type UseEntryInfo = [() => void, (entryId: string) => void];
8
+
9
+ /**
10
+ * Show/hide side panel entry
11
+ */
12
+ export function useEntryInfo(params: UseEntryInfoParams): UseEntryInfo {
13
+ const { setState } = params;
14
+
15
+ const hideEntryInfo = useCallback(() => setState({ entryId: '' }), [setState]);
16
+ const showEntryInfo = useCallback((entryId: string) => setState({ entryId }), [setState]);
17
+
18
+ return [hideEntryInfo, showEntryInfo];
19
+ }
@@ -0,0 +1,56 @@
1
+ import { useCallback, useEffect, useMemo } from 'react';
2
+ import { useLocalStorage } from 'react-use';
3
+ import { StringParam, useQueryParams } from 'use-query-params';
4
+
5
+ import { MetricsDisplayType } from '../constants';
6
+
7
+ const DEFAULT_DISPLAY_TYPE = MetricsDisplayType.TABLE;
8
+ const PARAM_NAME = 'dt';
9
+
10
+ type UseMetricsDisplayType = [MetricsDisplayType, (value: MetricsDisplayType) => void];
11
+
12
+ export const useMetricsDisplayType = (): UseMetricsDisplayType => {
13
+ const [{ [PARAM_NAME]: queryDisplayType }, setQueryParams] = useQueryParams({
14
+ [PARAM_NAME]: StringParam,
15
+ });
16
+ const [storageDisplayType, setStoreageDisplayType] = useLocalStorage(
17
+ PARAM_NAME,
18
+ MetricsDisplayType.TABLE,
19
+ );
20
+
21
+ const displayType = useMemo(() => {
22
+ const value = queryDisplayType || storageDisplayType;
23
+
24
+ if (!value) {
25
+ return DEFAULT_DISPLAY_TYPE;
26
+ }
27
+
28
+ if (!Object.values(MetricsDisplayType).includes(value as MetricsDisplayType)) {
29
+ return DEFAULT_DISPLAY_TYPE;
30
+ }
31
+
32
+ return value as MetricsDisplayType;
33
+ }, [queryDisplayType, storageDisplayType]);
34
+
35
+ useEffect(() => {
36
+ // Update query string display type when missing
37
+ if (queryDisplayType !== displayType) {
38
+ setQueryParams({ [PARAM_NAME]: displayType });
39
+ }
40
+
41
+ // Update storage state when query string is set and different
42
+ if (storageDisplayType !== displayType) {
43
+ setStoreageDisplayType(queryDisplayType as MetricsDisplayType);
44
+ }
45
+ }, [displayType, queryDisplayType, storageDisplayType, setQueryParams, setStoreageDisplayType]);
46
+
47
+ const setDisplayType = useCallback(
48
+ (value: MetricsDisplayType) => {
49
+ setStoreageDisplayType(value);
50
+ setQueryParams({ [PARAM_NAME]: value });
51
+ },
52
+ [setStoreageDisplayType, setQueryParams],
53
+ );
54
+
55
+ return [displayType, setDisplayType];
56
+ };