@bundle-stats/ui 4.22.3 → 4.23.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 (395) hide show
  1. package/lib/app/app.js +4 -0
  2. package/lib/app/app.js.map +1 -1
  3. package/lib/app/app.module.css +14 -5
  4. package/lib/app/header/header.module.css +1 -3
  5. package/lib/components/asset-name/asset-name.js +8 -7
  6. package/lib/components/asset-name/asset-name.js.map +1 -1
  7. package/lib/components/asset-name/asset-name.module.css +11 -10
  8. package/lib/components/bundle-assets/bundle-assets.js +4 -2
  9. package/lib/components/bundle-assets/bundle-assets.js.map +1 -1
  10. package/lib/components/bundle-assets/bundle-assets.module.css +0 -12
  11. package/lib/components/bundle-assets/index.js +2 -1
  12. package/lib/components/bundle-assets/index.js.map +1 -1
  13. package/lib/components/bundle-assets-totals/bundle-assets-totals.js +4 -2
  14. package/lib/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  15. package/lib/components/bundle-modules/bundle-modules.js +5 -3
  16. package/lib/components/bundle-modules/bundle-modules.js.map +1 -1
  17. package/lib/components/bundle-modules/bundle-modules.module.css +2 -16
  18. package/lib/components/bundle-modules/index.js +2 -1
  19. package/lib/components/bundle-modules/index.js.map +1 -1
  20. package/lib/components/bundle-packages/bundle-packages.js +5 -3
  21. package/lib/components/bundle-packages/bundle-packages.js.map +1 -1
  22. package/lib/components/bundle-packages/bundle-packages.module.css +18 -22
  23. package/lib/components/delta/delta.js +3 -13
  24. package/lib/components/delta/delta.js.map +1 -1
  25. package/lib/components/delta/delta.module.css +13 -12
  26. package/lib/components/delta/index.js.map +1 -1
  27. package/lib/components/entry-info/entry-info.js +4 -2
  28. package/lib/components/entry-info/entry-info.js.map +1 -1
  29. package/lib/components/entry-info/entry-info.module.css +7 -2
  30. package/lib/components/index.js +3 -1
  31. package/lib/components/index.js.map +1 -1
  32. package/lib/components/insight-icon/insight-icon.module.css +6 -6
  33. package/lib/components/job-name/job-name.js +1 -2
  34. package/lib/components/job-name/job-name.js.map +1 -1
  35. package/lib/components/jobs-header/jobs-header.js +1 -1
  36. package/lib/components/jobs-header/jobs-header.js.map +1 -1
  37. package/lib/components/jobs-header/jobs-header.module.css +0 -1
  38. package/lib/components/metric-change-legend/index.js +18 -0
  39. package/lib/components/metric-change-legend/index.js.map +1 -0
  40. package/lib/components/metric-change-legend/metric-change-legend.js +91 -0
  41. package/lib/components/metric-change-legend/metric-change-legend.js.map +1 -0
  42. package/lib/components/metric-change-legend/metric-change-legend.module.css +80 -0
  43. package/lib/components/metric-run-info/metric-run-info.js +24 -8
  44. package/lib/components/metric-run-info/metric-run-info.js.map +1 -1
  45. package/lib/components/metrics-display-selector/metrics-display-selector.js +7 -9
  46. package/lib/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
  47. package/lib/components/metrics-display-selector/metrics-display-selector.module.css +0 -27
  48. package/lib/components/metrics-table/metrics-table.js +31 -20
  49. package/lib/components/metrics-table/metrics-table.js.map +1 -1
  50. package/lib/components/metrics-table/metrics-table.module.css +4 -12
  51. package/lib/components/metrics-table-header/metrics-table-header.js +6 -6
  52. package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -1
  53. package/lib/components/metrics-table-header/metrics-table-header.module.css +8 -12
  54. package/lib/components/metrics-table-options/metrics-table-options.js +4 -5
  55. package/lib/components/metrics-table-options/metrics-table-options.js.map +1 -1
  56. package/lib/components/metrics-table-row-count/index.js +18 -0
  57. package/lib/components/metrics-table-row-count/index.js.map +1 -0
  58. package/lib/components/metrics-table-row-count/metrics-table-row-count.js +17 -0
  59. package/lib/components/metrics-table-row-count/metrics-table-row-count.js.map +1 -0
  60. package/lib/components/metrics-table-row-count/metrics-table-row-count.module.css +5 -0
  61. package/lib/components/metrics-table-title/metrics-table-title.js +1 -1
  62. package/lib/components/metrics-table-title/metrics-table-title.js.map +1 -1
  63. package/lib/components/metrics-treemap/metrics-treemap.constants.js +3 -1
  64. package/lib/components/metrics-treemap/metrics-treemap.constants.js.map +1 -1
  65. package/lib/components/metrics-treemap/metrics-treemap.js +46 -113
  66. package/lib/components/metrics-treemap/metrics-treemap.js.map +1 -1
  67. package/lib/components/metrics-treemap/metrics-treemap.module.css +3 -274
  68. package/lib/components/metrics-treemap/metrics-treemap.utils.js +81 -16
  69. package/lib/components/metrics-treemap/metrics-treemap.utils.js.map +1 -1
  70. package/lib/components/metrics-treemap/tile/index.js +18 -0
  71. package/lib/components/metrics-treemap/tile/index.js.map +1 -0
  72. package/lib/components/metrics-treemap/tile/tile.js +79 -0
  73. package/lib/components/metrics-treemap/tile/tile.js.map +1 -0
  74. package/lib/components/metrics-treemap/tile/tile.module.css +145 -0
  75. package/lib/components/metrics-treemap/tile-group/index.js +18 -0
  76. package/lib/components/metrics-treemap/tile-group/index.js.map +1 -0
  77. package/lib/components/metrics-treemap/tile-group/tile-group.js +75 -0
  78. package/lib/components/metrics-treemap/tile-group/tile-group.js.map +1 -0
  79. package/lib/components/metrics-treemap/tile-group/tile-group.module.css +57 -0
  80. package/lib/components/metrics-treemap/tile-group-title/index.js +18 -0
  81. package/lib/components/metrics-treemap/tile-group-title/index.js.map +1 -0
  82. package/lib/components/metrics-treemap/tile-group-title/tile-group-title.js +24 -0
  83. package/lib/components/metrics-treemap/tile-group-title/tile-group-title.js.map +1 -0
  84. package/lib/components/metrics-treemap/tile-group-title/tile-group-title.module.css +48 -0
  85. package/lib/components/run-info/run-info.js +26 -14
  86. package/lib/components/run-info/run-info.js.map +1 -1
  87. package/lib/components/run-info/run-info.module.css +35 -26
  88. package/lib/components/sort-button/sort-button.module.css +0 -2
  89. package/lib/components/summary/summary.js +10 -10
  90. package/lib/components/summary/summary.js.map +1 -1
  91. package/lib/components/summary/summary.module.css +60 -14
  92. package/lib/constants.js +13 -1
  93. package/lib/constants.js.map +1 -1
  94. package/lib/css/default.css +7 -4
  95. package/lib/css/variables.css +84 -60
  96. package/lib/layout/flex-stack/flex-stack.js +2 -2
  97. package/lib/layout/flex-stack/flex-stack.js.map +1 -1
  98. package/lib/layout/flex-stack/flex-stack.module.css +65 -10
  99. package/lib/query-state.js +6 -3
  100. package/lib/query-state.js.map +1 -1
  101. package/lib/ui/button/button.js +3 -2
  102. package/lib/ui/button/button.js.map +1 -1
  103. package/lib/ui/button/button.module.css +38 -27
  104. package/lib/ui/control-group/control-group.js +1 -1
  105. package/lib/ui/control-group/control-group.js.map +1 -1
  106. package/lib/ui/copy-to-clipboard/copy-to-clipboard.module.css +2 -2
  107. package/lib/ui/dialog/dialog.js +7 -3
  108. package/lib/ui/dialog/dialog.js.map +1 -1
  109. package/lib/ui/dialog/dialog.module.css +27 -0
  110. package/lib/ui/dropdown/dropdown.js +13 -4
  111. package/lib/ui/dropdown/dropdown.js.map +1 -1
  112. package/lib/ui/dropdown/dropdown.module.css +60 -7
  113. package/lib/ui/filters/filters.js +28 -16
  114. package/lib/ui/filters/filters.js.map +1 -1
  115. package/lib/ui/filters/filters.module.css +3 -19
  116. package/lib/ui/hover-card/hover-card.js +7 -1
  117. package/lib/ui/hover-card/hover-card.js.map +1 -1
  118. package/lib/ui/hover-card/hover-card.module.css +18 -5
  119. package/lib/ui/input/input.module.css +2 -2
  120. package/lib/ui/table/table.module.css +12 -6
  121. package/lib/ui/tabs/tabs.module.css +13 -9
  122. package/lib/ui/tag/tag.module.css +0 -2
  123. package/lib/ui/textarea/textarea.module.css +2 -2
  124. package/lib/ui/toolbar/toolbar.js +2 -1
  125. package/lib/ui/toolbar/toolbar.js.map +1 -1
  126. package/lib/ui/toolbar/toolbar.module.css +0 -6
  127. package/lib/ui/tooltip/tooltip.js +6 -1
  128. package/lib/ui/tooltip/tooltip.js.map +1 -1
  129. package/lib/ui/tooltip/tooltip.module.css +12 -1
  130. package/lib/utils/index.js +1 -0
  131. package/lib/utils/index.js.map +1 -1
  132. package/lib/utils/portal.js +10 -0
  133. package/lib/utils/portal.js.map +1 -0
  134. package/lib-esm/app/app.js +5 -1
  135. package/lib-esm/app/app.js.map +1 -1
  136. package/lib-esm/app/app.module.css +14 -5
  137. package/lib-esm/app/header/header.module.css +1 -3
  138. package/lib-esm/components/asset-name/asset-name.js +8 -7
  139. package/lib-esm/components/asset-name/asset-name.js.map +1 -1
  140. package/lib-esm/components/asset-name/asset-name.module.css +11 -10
  141. package/lib-esm/components/bundle-assets/bundle-assets.js +4 -2
  142. package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
  143. package/lib-esm/components/bundle-assets/bundle-assets.module.css +0 -12
  144. package/lib-esm/components/bundle-assets/index.js +2 -1
  145. package/lib-esm/components/bundle-assets/index.js.map +1 -1
  146. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js +4 -2
  147. package/lib-esm/components/bundle-assets-totals/bundle-assets-totals.js.map +1 -1
  148. package/lib-esm/components/bundle-modules/bundle-modules.js +5 -3
  149. package/lib-esm/components/bundle-modules/bundle-modules.js.map +1 -1
  150. package/lib-esm/components/bundle-modules/bundle-modules.module.css +2 -16
  151. package/lib-esm/components/bundle-modules/index.js +2 -1
  152. package/lib-esm/components/bundle-modules/index.js.map +1 -1
  153. package/lib-esm/components/bundle-packages/bundle-packages.js +5 -3
  154. package/lib-esm/components/bundle-packages/bundle-packages.js.map +1 -1
  155. package/lib-esm/components/bundle-packages/bundle-packages.module.css +18 -22
  156. package/lib-esm/components/delta/delta.js +3 -13
  157. package/lib-esm/components/delta/delta.js.map +1 -1
  158. package/lib-esm/components/delta/delta.module.css +13 -12
  159. package/lib-esm/components/delta/index.js.map +1 -1
  160. package/lib-esm/components/entry-info/entry-info.js +4 -2
  161. package/lib-esm/components/entry-info/entry-info.js.map +1 -1
  162. package/lib-esm/components/entry-info/entry-info.module.css +7 -2
  163. package/lib-esm/components/index.js +1 -0
  164. package/lib-esm/components/index.js.map +1 -1
  165. package/lib-esm/components/insight-icon/insight-icon.module.css +6 -6
  166. package/lib-esm/components/job-name/job-name.js +1 -2
  167. package/lib-esm/components/job-name/job-name.js.map +1 -1
  168. package/lib-esm/components/jobs-header/jobs-header.js +1 -1
  169. package/lib-esm/components/jobs-header/jobs-header.js.map +1 -1
  170. package/lib-esm/components/jobs-header/jobs-header.module.css +0 -1
  171. package/lib-esm/components/metric-change-legend/index.js +2 -0
  172. package/lib-esm/components/metric-change-legend/index.js.map +1 -0
  173. package/lib-esm/components/metric-change-legend/metric-change-legend.js +84 -0
  174. package/lib-esm/components/metric-change-legend/metric-change-legend.js.map +1 -0
  175. package/lib-esm/components/metric-change-legend/metric-change-legend.module.css +80 -0
  176. package/lib-esm/components/metric-run-info/metric-run-info.js +24 -8
  177. package/lib-esm/components/metric-run-info/metric-run-info.js.map +1 -1
  178. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js +7 -9
  179. package/lib-esm/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
  180. package/lib-esm/components/metrics-display-selector/metrics-display-selector.module.css +0 -27
  181. package/lib-esm/components/metrics-table/metrics-table.js +32 -20
  182. package/lib-esm/components/metrics-table/metrics-table.js.map +1 -1
  183. package/lib-esm/components/metrics-table/metrics-table.module.css +4 -12
  184. package/lib-esm/components/metrics-table-header/metrics-table-header.js +6 -6
  185. package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -1
  186. package/lib-esm/components/metrics-table-header/metrics-table-header.module.css +8 -12
  187. package/lib-esm/components/metrics-table-options/metrics-table-options.js +5 -6
  188. package/lib-esm/components/metrics-table-options/metrics-table-options.js.map +1 -1
  189. package/lib-esm/components/metrics-table-row-count/index.js +2 -0
  190. package/lib-esm/components/metrics-table-row-count/index.js.map +1 -0
  191. package/lib-esm/components/metrics-table-row-count/metrics-table-row-count.js +10 -0
  192. package/lib-esm/components/metrics-table-row-count/metrics-table-row-count.js.map +1 -0
  193. package/lib-esm/components/metrics-table-row-count/metrics-table-row-count.module.css +5 -0
  194. package/lib-esm/components/metrics-table-title/metrics-table-title.js +1 -1
  195. package/lib-esm/components/metrics-table-title/metrics-table-title.js.map +1 -1
  196. package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js +2 -0
  197. package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js.map +1 -1
  198. package/lib-esm/components/metrics-treemap/metrics-treemap.js +52 -120
  199. package/lib-esm/components/metrics-treemap/metrics-treemap.js.map +1 -1
  200. package/lib-esm/components/metrics-treemap/metrics-treemap.module.css +3 -274
  201. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js +80 -18
  202. package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js.map +1 -1
  203. package/lib-esm/components/metrics-treemap/tile/index.js +2 -0
  204. package/lib-esm/components/metrics-treemap/tile/index.js.map +1 -0
  205. package/lib-esm/components/metrics-treemap/tile/tile.js +40 -0
  206. package/lib-esm/components/metrics-treemap/tile/tile.js.map +1 -0
  207. package/lib-esm/components/metrics-treemap/tile/tile.module.css +145 -0
  208. package/lib-esm/components/metrics-treemap/tile-group/index.js +2 -0
  209. package/lib-esm/components/metrics-treemap/tile-group/index.js.map +1 -0
  210. package/lib-esm/components/metrics-treemap/tile-group/tile-group.js +35 -0
  211. package/lib-esm/components/metrics-treemap/tile-group/tile-group.js.map +1 -0
  212. package/lib-esm/components/metrics-treemap/tile-group/tile-group.module.css +57 -0
  213. package/lib-esm/components/metrics-treemap/tile-group-title/index.js +2 -0
  214. package/lib-esm/components/metrics-treemap/tile-group-title/index.js.map +1 -0
  215. package/lib-esm/components/metrics-treemap/tile-group-title/tile-group-title.js +17 -0
  216. package/lib-esm/components/metrics-treemap/tile-group-title/tile-group-title.js.map +1 -0
  217. package/lib-esm/components/metrics-treemap/tile-group-title/tile-group-title.module.css +48 -0
  218. package/lib-esm/components/run-info/run-info.js +26 -14
  219. package/lib-esm/components/run-info/run-info.js.map +1 -1
  220. package/lib-esm/components/run-info/run-info.module.css +35 -26
  221. package/lib-esm/components/sort-button/sort-button.module.css +0 -2
  222. package/lib-esm/components/summary/summary.js +11 -11
  223. package/lib-esm/components/summary/summary.js.map +1 -1
  224. package/lib-esm/components/summary/summary.module.css +60 -14
  225. package/lib-esm/constants.js +12 -0
  226. package/lib-esm/constants.js.map +1 -1
  227. package/lib-esm/css/default.css +7 -4
  228. package/lib-esm/css/variables.css +84 -60
  229. package/lib-esm/layout/flex-stack/flex-stack.js +3 -2
  230. package/lib-esm/layout/flex-stack/flex-stack.js.map +1 -1
  231. package/lib-esm/layout/flex-stack/flex-stack.module.css +65 -10
  232. package/lib-esm/query-state.js +7 -4
  233. package/lib-esm/query-state.js.map +1 -1
  234. package/lib-esm/ui/button/button.js +3 -2
  235. package/lib-esm/ui/button/button.js.map +1 -1
  236. package/lib-esm/ui/button/button.module.css +38 -27
  237. package/lib-esm/ui/control-group/control-group.js +1 -1
  238. package/lib-esm/ui/control-group/control-group.js.map +1 -1
  239. package/lib-esm/ui/copy-to-clipboard/copy-to-clipboard.module.css +2 -2
  240. package/lib-esm/ui/dialog/dialog.js +7 -3
  241. package/lib-esm/ui/dialog/dialog.js.map +1 -1
  242. package/lib-esm/ui/dialog/dialog.module.css +27 -0
  243. package/lib-esm/ui/dropdown/dropdown.js +11 -3
  244. package/lib-esm/ui/dropdown/dropdown.js.map +1 -1
  245. package/lib-esm/ui/dropdown/dropdown.module.css +60 -7
  246. package/lib-esm/ui/filters/filters.js +29 -17
  247. package/lib-esm/ui/filters/filters.js.map +1 -1
  248. package/lib-esm/ui/filters/filters.module.css +3 -19
  249. package/lib-esm/ui/hover-card/hover-card.js +7 -1
  250. package/lib-esm/ui/hover-card/hover-card.js.map +1 -1
  251. package/lib-esm/ui/hover-card/hover-card.module.css +18 -5
  252. package/lib-esm/ui/input/input.module.css +2 -2
  253. package/lib-esm/ui/table/table.module.css +12 -6
  254. package/lib-esm/ui/tabs/tabs.module.css +13 -9
  255. package/lib-esm/ui/tag/tag.module.css +0 -2
  256. package/lib-esm/ui/textarea/textarea.module.css +2 -2
  257. package/lib-esm/ui/toolbar/toolbar.js +2 -1
  258. package/lib-esm/ui/toolbar/toolbar.js.map +1 -1
  259. package/lib-esm/ui/toolbar/toolbar.module.css +0 -6
  260. package/lib-esm/ui/tooltip/tooltip.js +6 -1
  261. package/lib-esm/ui/tooltip/tooltip.js.map +1 -1
  262. package/lib-esm/ui/tooltip/tooltip.module.css +12 -1
  263. package/lib-esm/utils/index.js +1 -0
  264. package/lib-esm/utils/index.js.map +1 -1
  265. package/lib-esm/utils/portal.js +6 -0
  266. package/lib-esm/utils/portal.js.map +1 -0
  267. package/package.json +18 -18
  268. package/src/app/app.jsx +7 -1
  269. package/src/app/app.module.css +14 -5
  270. package/src/app/header/header.module.css +1 -3
  271. package/src/components/asset-name/asset-name.module.css +11 -10
  272. package/src/components/asset-name/asset-name.tsx +17 -14
  273. package/src/components/bundle-assets/bundle-assets.module.css +0 -12
  274. package/src/components/bundle-assets/bundle-assets.tsx +8 -1
  275. package/src/components/bundle-assets/index.tsx +3 -1
  276. package/src/components/bundle-assets-totals/bundle-assets-totals.jsx +6 -4
  277. package/src/components/bundle-modules/bundle-modules.module.css +2 -16
  278. package/src/components/bundle-modules/bundle-modules.tsx +10 -3
  279. package/src/components/bundle-modules/index.tsx +3 -1
  280. package/src/components/bundle-packages/bundle-packages.jsx +14 -3
  281. package/src/components/bundle-packages/bundle-packages.module.css +18 -22
  282. package/src/components/delta/delta.module.css +13 -12
  283. package/src/components/delta/delta.tsx +32 -0
  284. package/src/components/entry-info/entry-info.module.css +7 -2
  285. package/src/components/entry-info/entry-info.tsx +9 -3
  286. package/src/components/index.ts +3 -0
  287. package/src/components/insight-icon/insight-icon.module.css +6 -6
  288. package/src/components/job-name/job-name.jsx +2 -3
  289. package/src/components/jobs-header/jobs-header.module.css +0 -1
  290. package/src/components/jobs-header/jobs-header.tsx +2 -2
  291. package/src/components/metric-change-legend/index.ts +1 -0
  292. package/src/components/metric-change-legend/metric-change-legend.module.css +80 -0
  293. package/src/components/metric-change-legend/metric-change-legend.stories.tsx +13 -0
  294. package/src/components/metric-change-legend/metric-change-legend.tsx +148 -0
  295. package/src/components/metric-run-info/metric-run-info.stories.tsx +9 -0
  296. package/src/components/metric-run-info/metric-run-info.tsx +39 -17
  297. package/src/components/metrics-display-selector/metrics-display-selector.module.css +0 -27
  298. package/src/components/metrics-display-selector/metrics-display-selector.tsx +25 -37
  299. package/src/components/metrics-table/metrics-table.module.css +4 -12
  300. package/src/components/metrics-table/metrics-table.tsx +70 -39
  301. package/src/components/metrics-table-header/metrics-table-header.module.css +8 -12
  302. package/src/components/metrics-table-header/metrics-table-header.tsx +5 -6
  303. package/src/components/metrics-table-options/metrics-table-options.tsx +13 -14
  304. package/src/components/metrics-table-row-count/index.ts +1 -0
  305. package/src/components/metrics-table-row-count/metrics-table-row-count.module.css +5 -0
  306. package/src/components/metrics-table-row-count/metrics-table-row-count.tsx +21 -0
  307. package/src/components/metrics-table-title/metrics-table-title.jsx +1 -1
  308. package/src/components/metrics-treemap/metrics-treemap.constants.ts +9 -0
  309. package/src/components/metrics-treemap/metrics-treemap.module.css +3 -274
  310. package/src/components/metrics-treemap/metrics-treemap.stories.utils.ts +46 -0
  311. package/src/components/metrics-treemap/metrics-treemap.tsx +123 -428
  312. package/src/components/metrics-treemap/metrics-treemap.utils.ts +161 -27
  313. package/src/components/metrics-treemap/tile/index.ts +1 -0
  314. package/src/components/metrics-treemap/tile/tile.module.css +145 -0
  315. package/src/components/metrics-treemap/tile/tile.stories.tsx +139 -0
  316. package/src/components/metrics-treemap/tile/tile.tsx +121 -0
  317. package/src/components/metrics-treemap/tile-group/index.ts +1 -0
  318. package/src/components/metrics-treemap/tile-group/tile-group.module.css +57 -0
  319. package/src/components/metrics-treemap/tile-group/tile-group.stories.tsx +163 -0
  320. package/src/components/metrics-treemap/tile-group/tile-group.tsx +177 -0
  321. package/src/components/metrics-treemap/tile-group-title/index.ts +1 -0
  322. package/src/components/metrics-treemap/tile-group-title/tile-group-title.module.css +48 -0
  323. package/src/components/metrics-treemap/tile-group-title/tile-group-title.stories.tsx +88 -0
  324. package/src/components/metrics-treemap/tile-group-title/tile-group-title.tsx +51 -0
  325. package/src/components/run-info/run-info.module.css +35 -26
  326. package/src/components/run-info/run-info.stories.tsx +16 -10
  327. package/src/components/run-info/run-info.tsx +132 -73
  328. package/src/components/sort-button/sort-button.module.css +0 -2
  329. package/src/components/summary/summary.module.css +60 -14
  330. package/src/components/summary/summary.tsx +50 -52
  331. package/src/constants.ts +13 -0
  332. package/src/css/default.css +7 -4
  333. package/src/css/variables.css +84 -60
  334. package/src/layout/flex-stack/flex-stack.module.css +65 -10
  335. package/src/layout/flex-stack/flex-stack.stories.tsx +68 -9
  336. package/src/layout/flex-stack/flex-stack.tsx +24 -4
  337. package/src/query-state.tsx +9 -4
  338. package/src/ui/button/button.module.css +38 -27
  339. package/src/ui/button/button.stories.tsx +1 -1
  340. package/src/ui/button/button.tsx +3 -1
  341. package/src/ui/control-group/control-group.tsx +1 -1
  342. package/src/ui/copy-to-clipboard/copy-to-clipboard.module.css +2 -2
  343. package/src/ui/dialog/dialog.module.css +27 -0
  344. package/src/ui/dialog/dialog.stories.tsx +8 -0
  345. package/src/ui/dialog/dialog.tsx +16 -2
  346. package/src/ui/dropdown/dropdown.module.css +60 -7
  347. package/src/ui/dropdown/dropdown.stories.tsx +6 -0
  348. package/src/ui/dropdown/dropdown.tsx +17 -2
  349. package/src/ui/filters/filters.module.css +3 -19
  350. package/src/ui/filters/filters.tsx +131 -67
  351. package/src/ui/hover-card/hover-card.module.css +18 -5
  352. package/src/ui/hover-card/hover-card.tsx +7 -1
  353. package/src/ui/input/input.module.css +2 -2
  354. package/src/ui/table/table.module.css +12 -6
  355. package/src/ui/tabs/tabs.module.css +13 -9
  356. package/src/ui/tag/tag.module.css +0 -2
  357. package/src/ui/textarea/textarea.module.css +2 -2
  358. package/src/ui/toolbar/toolbar.jsx +4 -1
  359. package/src/ui/toolbar/toolbar.module.css +0 -6
  360. package/src/ui/tooltip/tooltip.module.css +12 -1
  361. package/src/ui/tooltip/tooltip.tsx +6 -1
  362. package/src/utils/index.ts +1 -0
  363. package/src/utils/portal.ts +9 -0
  364. package/types/components/delta/delta.d.ts +7 -21
  365. package/types/components/delta/index.d.ts +1 -1
  366. package/types/components/index.d.ts +3 -0
  367. package/types/components/metric-change-legend/index.d.ts +1 -0
  368. package/types/components/metric-change-legend/metric-change-legend.d.ts +4 -0
  369. package/types/components/metric-run-info/metric-run-info.d.ts +3 -6
  370. package/types/components/metrics-table/metrics-table.d.ts +2 -1
  371. package/types/components/metrics-table-row-count/index.d.ts +1 -0
  372. package/types/components/metrics-table-row-count/metrics-table-row-count.d.ts +7 -0
  373. package/types/components/metrics-treemap/metrics-treemap.constants.d.ts +2 -0
  374. package/types/components/metrics-treemap/metrics-treemap.utils.d.ts +16 -5
  375. package/types/components/metrics-treemap/tile/index.d.ts +1 -0
  376. package/types/components/metrics-treemap/tile/tile.d.ts +11 -0
  377. package/types/components/metrics-treemap/tile-group/index.d.ts +1 -0
  378. package/types/components/metrics-treemap/tile-group/tile-group.d.ts +20 -0
  379. package/types/components/metrics-treemap/tile-group-title/index.d.ts +1 -0
  380. package/types/components/metrics-treemap/tile-group-title/tile-group-title.d.ts +12 -0
  381. package/types/components/run-info/run-info.d.ts +16 -7
  382. package/types/constants.d.ts +12 -0
  383. package/types/layout/flex-stack/flex-stack.d.ts +6 -2
  384. package/types/ui/button/button.d.ts +1 -0
  385. package/types/ui/dialog/dialog.d.ts +3 -2
  386. package/types/ui/dropdown/dropdown.d.ts +4 -1
  387. package/types/ui/filters/filters.d.ts +2 -1
  388. package/types/utils/index.d.ts +1 -0
  389. package/types/utils/portal.d.ts +1 -0
  390. package/vitest.config.ts +4 -0
  391. package/lib/components/metrics-table-options/metrics-table-options.module.css +0 -15
  392. package/lib-esm/components/metrics-table-options/metrics-table-options.module.css +0 -15
  393. package/src/components/delta/delta.jsx +0 -22
  394. package/src/components/metrics-table-options/metrics-table-options.module.css +0 -15
  395. /package/src/components/delta/{index.js → index.ts} +0 -0
@@ -0,0 +1,46 @@
1
+ import {
2
+ type MetricRunInfo,
3
+ type ReportMetricRow,
4
+ METRIC_TYPE_CONFIGS,
5
+ getMetricRunInfo,
6
+ } from '@bundle-stats/utils';
7
+
8
+ const METRIC_TYPE = METRIC_TYPE_CONFIGS.METRIC_TYPE_FILE_SIZE;
9
+
10
+ /**
11
+ * Baseline value used by the delta fixtures
12
+ */
13
+ export const BASELINE_VALUE = 10 * 1024;
14
+
15
+ /**
16
+ * Current values resolving to every file size delta type (smaller is better)
17
+ */
18
+ export const CURRENT_VALUE_BY_DELTA_TYPE = {
19
+ NO_CHANGE: BASELINE_VALUE,
20
+ LOW_NEGATIVE: BASELINE_VALUE * 1.02,
21
+ NEGATIVE: BASELINE_VALUE * 1.2,
22
+ HIGH_NEGATIVE: BASELINE_VALUE * 2,
23
+ LOW_POSITIVE: BASELINE_VALUE * 0.98,
24
+ POSITIVE: BASELINE_VALUE * 0.8,
25
+ HIGH_POSITIVE: BASELINE_VALUE * 0.4,
26
+ } as const;
27
+
28
+ /**
29
+ * Create a file size report row with the current and baseline runs
30
+ */
31
+ export function createReportMetricRow(
32
+ key: string,
33
+ current: number,
34
+ baseline = BASELINE_VALUE,
35
+ ): ReportMetricRow {
36
+ return {
37
+ key,
38
+ label: key,
39
+ biggerIsBetter: METRIC_TYPE.biggerIsBetter,
40
+ changed: current !== baseline,
41
+ runs: [
42
+ getMetricRunInfo(METRIC_TYPE, current, baseline) as MetricRunInfo,
43
+ getMetricRunInfo(METRIC_TYPE, baseline),
44
+ ],
45
+ };
46
+ }
@@ -1,33 +1,22 @@
1
1
  import React, {
2
2
  type ComponentProps,
3
- type MouseEventHandler,
4
3
  type ReactNode,
5
- type Ref,
6
- type RefObject,
7
- forwardRef,
8
4
  useCallback,
5
+ useEffect,
9
6
  useMemo,
10
7
  useRef,
11
8
  } from 'react';
12
- import { useHoverDirty, useMeasure } from 'react-use';
9
+ import { useMeasure } from 'react-use';
13
10
  import cx from 'classnames';
14
11
  import { HierarchyRectangularNode, hierarchy, treemap, treemapSquarify } from 'd3';
15
- import { Tooltip, TooltipArrow, TooltipAnchor } from 'ariakit/tooltip';
16
- import {
17
- type ReportMetricRow,
18
- type MetricRunInfo,
19
- type MetricRunInfoBaseline,
20
- METRIC_TYPE_CONFIGS,
21
- formatFileSize,
22
- getMetricRunInfo,
23
- } from '@bundle-stats/utils';
12
+ import { Tooltip, TooltipArrow } from 'ariakit/tooltip';
13
+ import type { ReportMetricRow, MetricRunInfo, MetricRunInfoBaseline } from '@bundle-stats/utils';
24
14
 
15
+ import { FlexStack } from '../../layout/flex-stack';
25
16
  import { Stack } from '../../layout/stack';
26
17
  import { FileName } from '../../ui/file-name';
27
- import { Delta } from '../delta';
28
18
  import { RunInfo } from '../run-info';
29
19
  import {
30
- type TreeLeaf,
31
20
  type TreeNode,
32
21
  type Tree,
33
22
  SQUARIFY_RATIO,
@@ -36,16 +25,15 @@ import {
36
25
  NESTED_PADDING,
37
26
  NESTED_PADDING_TOP,
38
27
  NESTED_PADDING_LEFT,
39
- TileSizeDisplay,
28
+ NODE_ID_SELECTOR,
40
29
  } from './metrics-treemap.constants';
41
- import * as I18N from './metrics-treemap.i18n';
42
30
  import css from './metrics-treemap.module.css';
43
31
  import {
44
- resolveGroupDeltaType,
45
- resolveTileSizeDisplay,
46
- resolveTileGroupSizeDisplay,
47
- useTooltipStateWithMouseFollow,
32
+ getGroupRunInfo,
33
+ getTreemapNodesIndex,
34
+ useTreemapTooltipState,
48
35
  } from './metrics-treemap.utils';
36
+ import { TileGroup } from './tile-group';
49
37
 
50
38
  interface TileTooltipContentProps {
51
39
  item: ReportMetricRow;
@@ -64,7 +52,8 @@ const TileTooltipContent = (props: TileTooltipContentProps) => {
64
52
  </h3>
65
53
  <RunInfo
66
54
  current={currentRun.displayValue}
67
- delta={currentRun.displayDeltaPercentage}
55
+ delta={currentRun.displayDelta}
56
+ deltaPercentage={currentRun.displayDeltaPercentage}
68
57
  deltaType={currentRun.deltaType}
69
58
  baseline={baselineRun?.displayValue || '0B'}
70
59
  />
@@ -72,408 +61,46 @@ const TileTooltipContent = (props: TileTooltipContentProps) => {
72
61
  );
73
62
  };
74
63
 
75
- interface TileContentProps {
76
- /**
77
- * Node label
78
- */
79
- label: string;
80
- /**
81
- * Tile id - metric label or basename for grouped tiles
82
- */
83
- item: ReportMetricRow;
84
- /**
85
- * The estimated size of the tile
86
- */
87
- sizeDisplay: TileSizeDisplay;
88
- /**
89
- * Metric run info
90
- */
91
- runInfo: MetricRunInfo;
64
+ interface TileGroupTooltipContentProps {
65
+ node: Tree;
92
66
  }
93
67
 
94
- const TileContent = forwardRef((props: TileContentProps, ref: Ref<HTMLDivElement>) => {
95
- const { label, sizeDisplay, item, runInfo } = props;
96
-
97
- // Render only the container
98
- if (sizeDisplay === 'minimal') {
99
- return <div className={css.tileContent} ref={ref} />;
100
- }
101
-
102
- const resolvedLabel = label || item.label;
103
-
104
- // Render only the label
105
- if (sizeDisplay === 'small') {
106
- return (
107
- <div className={css.tileContent} ref={ref}>
108
- <p className={css.tileContentLabel}>{resolvedLabel}</p>
109
- </div>
110
- );
111
- }
112
-
113
- return (
114
- <div className={css.tileContent} ref={ref}>
115
- <p className={css.tileContentLabel}>{label || item.label}</p>
116
- <p className={css.tileContentValue}>
117
- <span className={css.tileContentMetric}>{runInfo.displayValue}</span>
118
- <Delta
119
- className={css.tileContentDelta}
120
- displayValue={runInfo.displayDeltaPercentage}
121
- deltaType={runInfo.deltaType}
122
- />
123
- </p>
124
- </div>
125
- );
126
- });
127
-
128
- const TileContentWithTooltip = (props: TileContentProps & { parentRef: RefObject<Element> }) => {
129
- const { label, sizeDisplay, item, runInfo, parentRef } = props;
130
-
131
- const tooltipState = useTooltipStateWithMouseFollow({ parentRef });
132
-
133
- return (
134
- <>
135
- <TooltipAnchor state={tooltipState} className={css.tileContentTooltipAnchor}>
136
- <TileContent label={label} sizeDisplay={sizeDisplay} item={item} runInfo={runInfo} />
137
- </TooltipAnchor>
138
- <Tooltip state={tooltipState} className={css.tooltip}>
139
- <TooltipArrow state={tooltipState} size={16} className={css.tileTooltipArrow} />
140
- <TileTooltipContent item={item} />
141
- </Tooltip>
142
- </>
143
- );
144
- };
145
-
146
- interface TileProps {
147
- left: number;
148
- top: number;
149
- width: number;
150
- height: number;
151
- data: TreeLeaf;
152
- onClick?: (id: string) => void;
153
- }
154
-
155
- const Tile = (props: TileProps) => {
156
- const { left, top, width, height, data, onClick } = props;
157
-
158
- const { item, label } = data;
159
- const runInfo = item.runs?.[0] as MetricRunInfo;
160
-
161
- const sizeDisplay = useMemo(() => resolveTileSizeDisplay(width, height), [width, height]);
162
- const handleOnClick: MouseEventHandler<HTMLDivElement> = useCallback(
163
- (event) => {
164
- event.stopPropagation();
165
- onClick?.(item.key);
166
- },
167
- [item.key, onClick],
168
- );
68
+ const TileGroupTooltipContent = (props: TileGroupTooltipContentProps) => {
69
+ const { node } = props;
169
70
 
170
- const contentRef = useRef<HTMLDivElement>(null);
171
- const hover = useHoverDirty(contentRef);
71
+ // by default show the node id (full path) as title
72
+ const title = node.id || node.label;
73
+ const groupRunInfo = node.total && getGroupRunInfo(node.total);
172
74
 
173
- const className = cx(
174
- css.tile,
175
- css[`tile-${runInfo.deltaType}`],
176
- sizeDisplay === 'small' && css.tileSizeSmall,
177
- sizeDisplay === 'default' && css.tileSizeDefault,
178
- left === PADDING_INNER && css.tileFirstCol,
179
- );
180
-
181
- /* eslint-disable jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus */
182
75
  return (
183
- <div
184
- onClick={handleOnClick}
185
- role="button"
186
- aria-label={I18N.TILE_LABEL}
187
- ref={contentRef}
188
- style={{ left, top, width, height }}
189
- className={className}
190
- >
191
- {hover ? (
192
- <TileContentWithTooltip
193
- label={label}
194
- sizeDisplay={sizeDisplay}
195
- item={item}
196
- runInfo={runInfo}
197
- parentRef={contentRef}
198
- />
199
- ) : (
200
- <TileContent label={label} sizeDisplay={sizeDisplay} item={item} runInfo={runInfo} />
201
- )}
202
- </div>
203
- );
204
- };
205
-
206
- interface TileGroupTitleTooltipContentProps {
207
- title: string;
208
- runInfo?: MetricRunInfo;
209
- baselineDisplayValue?: string;
210
- }
211
-
212
- const TileGroupTitleTooltipContent = (props: TileGroupTitleTooltipContentProps) => {
213
- const { title, runInfo, baselineDisplayValue } = props;
214
-
215
- return (
216
- <Stack space="small" className={css.tileTooltip}>
76
+ <Stack space="small" className={css.tileTooltipContent}>
217
77
  <h3 className={css.tileTooltipContentTitle}>
218
78
  <FileName as="code" name={title} />
219
79
  </h3>
220
- {runInfo && (
80
+ {groupRunInfo && (
221
81
  <RunInfo
222
- current={runInfo.displayValue}
223
- baseline={baselineDisplayValue}
224
- delta={runInfo.displayDeltaPercentage}
225
- deltaType={runInfo.deltaType}
82
+ current={groupRunInfo.runInfo.displayValue}
83
+ baseline={groupRunInfo.baselineDisplayValue}
84
+ delta={groupRunInfo.runInfo.displayDeltaPercentage}
85
+ deltaType={groupRunInfo.runInfo.deltaType}
226
86
  />
227
87
  )}
228
88
  </Stack>
229
89
  );
230
90
  };
231
91
 
232
- interface TileGroupTitleContentProps {
233
- title?: string;
234
- runInfo?: MetricRunInfo;
235
- }
236
-
237
- const TileGroupTitleContent = (props: TileGroupTitleContentProps) => {
238
- const { title, runInfo } = props;
239
-
240
- return (
241
- <div className={css.tileGroupTitleContent}>
242
- {title && <span className={css.tileGroupTitleText}>{title}</span>}
243
- {runInfo && (
244
- <span className={css.tileGroupTitleTotal}>
245
- {runInfo.displayValue}
246
- {'displayDelta' in runInfo && `(${runInfo.displayDeltaPercentage})`}
247
- </span>
248
- )}
249
- </div>
250
- );
251
- };
252
-
253
- type TileGroupTitleContentWithTooltipProps = {
254
- parentRef: RefObject<Element>;
255
- tooltipContent: TileGroupTitleTooltipContentProps;
256
- } & TileGroupTitleContentProps;
257
-
258
- const TileGroupTitleContentWithTooltip = (props: TileGroupTitleContentWithTooltipProps) => {
259
- const { parentRef, tooltipContent, ...restProps } = props;
260
-
261
- const tooltipState = useTooltipStateWithMouseFollow({ parentRef });
262
-
263
- return (
264
- <>
265
- <TooltipAnchor state={tooltipState} className={css.tileContentTooltipAnchor}>
266
- <TileGroupTitleContent {...restProps} />
267
- </TooltipAnchor>
268
- <Tooltip state={tooltipState} className={css.tooltip}>
269
- <TooltipArrow state={tooltipState} size={16} className={css.tileTooltipArrow} />
270
- <TileGroupTitleTooltipContent {...tooltipContent} />
271
- </Tooltip>
272
- </>
273
- );
274
- };
275
-
276
- type TileGroupTitleProps = Omit<TileGroupTitleContentWithTooltipProps, 'parentRef'>;
277
-
278
- const TileGroupTitle = (props: TileGroupTitleProps) => {
279
- const { tooltipContent, ...restProps } = props;
280
- const contentRef = useRef<HTMLDivElement>(null);
281
- const hover = useHoverDirty(contentRef);
282
-
283
- return (
284
- <div className={css.tileGroupTitle} ref={contentRef}>
285
- {hover ? (
286
- <TileGroupTitleContentWithTooltip
287
- parentRef={contentRef}
288
- tooltipContent={tooltipContent}
289
- {...restProps}
290
- />
291
- ) : (
292
- <TileGroupTitleContent {...restProps} />
293
- )}
294
- </div>
295
- );
296
- };
297
-
298
- interface TileGroupProps extends ComponentProps<'div'> {
299
- /**
300
- * Node title
301
- */
302
- title?: string;
303
- /**
304
- * Group sum
305
- */
306
- total?: Tree['total'];
307
- /**
308
- * Node id
309
- */
310
- id: string;
311
- /**
312
- * Node children
313
- */
314
- childNodes: HierarchyRectangularNode<TreeNode>['children'];
315
- /**
316
- * On click tile handler
317
- */
318
- onItemClick: TileProps['onClick'];
319
- /**
320
- * On click group title
321
- */
322
- onGroupClick?: (groupId: string) => void;
323
-
324
- /**
325
- * Node rectangle dimensions
326
- */
327
- width?: number;
328
- height?: number;
329
-
330
- /**
331
- * Node rectangle relative coordinates (relative to parent)
332
- */
333
- left: number;
334
- top: number;
335
-
336
- /**
337
- * Node rectangle absolute coordinates (relative to canvas)
338
- */
339
- absoluteLeft: number;
340
- absoluteTop: number;
92
+ interface TreemapTooltipContentProps {
93
+ node: TreeNode;
341
94
  }
342
95
 
343
- const TileGroup = (props: TileGroupProps) => {
344
- const {
345
- title = '',
346
- total,
347
- id,
348
- childNodes,
349
- onItemClick,
350
- onGroupClick,
351
- left,
352
- top,
353
- width,
354
- height,
355
- absoluteLeft,
356
- absoluteTop,
357
- } = props;
358
-
359
- const onClick: MouseEventHandler<HTMLDivElement> = useCallback(
360
- (event) => {
361
- onGroupClick?.(id);
362
- event.stopPropagation();
363
- },
364
- [onGroupClick, id],
365
- );
96
+ const TreemapTooltipContent = (props: TreemapTooltipContentProps) => {
97
+ const { node } = props;
366
98
 
367
- const displaySize = useMemo(
368
- () => resolveTileGroupSizeDisplay(width || 0, height || 0),
369
- [width, height],
370
- );
371
-
372
- // Prepare data
373
- const [runInfo, baselineDisplayValue, deltaType] = useMemo(() => {
374
- if (!total) {
375
- return [];
376
- }
377
-
378
- const resolvedRunInfo = getMetricRunInfo(
379
- METRIC_TYPE_CONFIGS.METRIC_TYPE_FILE_SIZE,
380
- total.current,
381
- total.baseline,
382
- ) as MetricRunInfo;
383
- const resolvedBaselineDisplayValue = formatFileSize(total.baseline);
384
- const resolvedDeltaType = resolveGroupDeltaType(resolvedRunInfo);
385
-
386
- return [resolvedRunInfo, resolvedBaselineDisplayValue, resolvedDeltaType];
387
- }, [total]);
388
-
389
- const rootClassName = cx(
390
- css.tileGroup,
391
- css[`tileGroup--${deltaType}`],
392
- css[`tileGroup--${displaySize}`],
393
- );
394
-
395
- // Tooltip data
396
- // - by default show the node id (full path) as title
397
- const tooltipContent = {
398
- title: id || title,
399
- runInfo,
400
- baselineDisplayValue,
401
- } as TileGroupTitleTooltipContentProps;
402
-
403
- if (title && displaySize === 'minimal') {
404
- return (
405
- <div
406
- onClick={onClick}
407
- role="button"
408
- aria-label={I18N.TILE_GROUP_LABEL}
409
- className={rootClassName}
410
- style={{ left, top, width, height }}
411
- >
412
- <TileGroupTitle tooltipContent={tooltipContent} />
413
- </div>
414
- );
415
- }
416
-
417
- if (title && displaySize === 'small') {
418
- return (
419
- <div
420
- onClick={onClick}
421
- role="button"
422
- aria-label={I18N.TILE_GROUP_LABEL}
423
- style={{ left, top, width, height }}
424
- className={rootClassName}
425
- >
426
- <TileGroupTitle title={title} tooltipContent={tooltipContent} />
427
- </div>
428
- );
99
+ if ('item' in node) {
100
+ return <TileTooltipContent item={node.item} />;
429
101
  }
430
102
 
431
- return (
432
- <div
433
- onClick={onClick}
434
- role="button"
435
- aria-label={I18N.TILE_GROUP_LABEL}
436
- className={cx(rootClassName, css.tileGroupSizeDefault)}
437
- style={{ left, top, width, height }}
438
- >
439
- <TileGroupTitle title={title} runInfo={runInfo} tooltipContent={tooltipContent} />
440
- {childNodes?.map((childNode) => {
441
- if ('children' in childNode) {
442
- const groupData = childNode.data as Tree;
443
-
444
- return (
445
- <TileGroup
446
- title={groupData.label}
447
- total={groupData.total}
448
- id={groupData.id}
449
- childNodes={childNode.children}
450
- left={childNode.x0 - absoluteLeft}
451
- top={childNode.y0 - absoluteTop}
452
- absoluteLeft={childNode.x0}
453
- absoluteTop={childNode.y0}
454
- width={childNode.x1 - childNode.x0}
455
- height={childNode.y1 - childNode.y0}
456
- onItemClick={onItemClick}
457
- onGroupClick={onGroupClick}
458
- key={groupData.id}
459
- />
460
- );
461
- }
462
-
463
- return (
464
- <Tile
465
- data={childNode.data as TreeLeaf}
466
- left={childNode.x0 - absoluteLeft}
467
- top={childNode.y0 - absoluteTop}
468
- width={childNode.x1 - childNode.x0}
469
- height={childNode.y1 - childNode.y0}
470
- onClick={onItemClick}
471
- key={childNode.data.id}
472
- />
473
- );
474
- })}
475
- </div>
476
- );
103
+ return <TileGroupTooltipContent node={node} />;
477
104
  };
478
105
 
479
106
  interface UseMetricsTreemapHierarchyParams {
@@ -542,33 +169,101 @@ export const MetricsTreemap = (props: MetricsTreemapProps & ComponentProps<'div'
542
169
  const [containerRef, { width, height }] = useMeasure<HTMLDivElement>();
543
170
  const rootNode = useMetricsTreemapHierarchy({ treeNodes, width, height, nested });
544
171
 
172
+ /**
173
+ * A single tooltip is shared by every tile and tile group title:
174
+ * - tiles are tagged with `data-treemap-id`
175
+ * - the pointer is tracked by one delegated handler on the canvas
176
+ * - hiding is deferred so that the tooltip stays up while the pointer
177
+ * crosses the gutter between two tiles
178
+ */
179
+ const nodesIndex = useMemo(() => getTreemapNodesIndex(treeNodes), [treeNodes]);
180
+ const { tooltipState, setPointer, hoveredNodeId, setHoveredNode, clearHoveredNode } =
181
+ useTreemapTooltipState();
182
+ const canvasRef = useRef<HTMLDivElement>(null);
183
+
184
+ // Resolved on render so that the content cannot go stale when the data changes
185
+ const tooltipNode = hoveredNodeId === null ? null : nodesIndex.get(hoveredNodeId);
186
+
187
+ const handlePointerEvent = useCallback(
188
+ (event: MouseEvent) => {
189
+ // Anchor to the canvas to let ariakit track scrolling/resizing
190
+ tooltipState.anchorRef.current = canvasRef.current;
191
+
192
+ setPointer(event.clientX, event.clientY);
193
+
194
+ const target = (event.target as HTMLElement | null)?.closest<HTMLElement>(NODE_ID_SELECTOR);
195
+ setHoveredNode(target?.dataset.treemapId ?? null);
196
+ },
197
+ [tooltipState, setPointer, setHoveredNode],
198
+ );
199
+
200
+ const hasNodes = Boolean(rootNode.children && rootNode.children.length > 0);
201
+
202
+ useEffect(() => {
203
+ const canvas = canvasRef.current;
204
+
205
+ if (!canvas) {
206
+ return undefined;
207
+ }
208
+
209
+ /**
210
+ * `mouseover` is needed on top of `mousemove`: the hovered element can
211
+ * change without the pointer moving (scrolling, resizing, layout shifts),
212
+ * and the browser only emits boundary events in that case.
213
+ *
214
+ * Native listeners are used instead of the React props because React skips
215
+ * `mouseover` dispatch when `relatedTarget` is inside the same tree.
216
+ */
217
+ canvas.addEventListener('mousemove', handlePointerEvent);
218
+ canvas.addEventListener('mouseover', handlePointerEvent);
219
+ canvas.addEventListener('mouseleave', clearHoveredNode);
220
+
221
+ return () => {
222
+ canvas.removeEventListener('mousemove', handlePointerEvent);
223
+ canvas.removeEventListener('mouseover', handlePointerEvent);
224
+ canvas.removeEventListener('mouseleave', clearHoveredNode);
225
+ };
226
+ }, [hasNodes, handlePointerEvent, clearHoveredNode]);
227
+
228
+ // Keep the cells out of the tooltip render path
229
+ // (`rootNode` is mutated in place by d3, so the layout size drives the memo)
230
+ const canvasContent = useMemo(
231
+ () => (
232
+ <TileGroup
233
+ title={nested ? rootNode.data.label : undefined}
234
+ total={(rootNode.data as Tree).total}
235
+ id={rootNode.data.id}
236
+ childNodes={rootNode.children}
237
+ nested={nested}
238
+ onItemClick={onItemClick}
239
+ onGroupClick={onGroupClick}
240
+ left={rootNode.x0}
241
+ top={rootNode.y0}
242
+ absoluteLeft={rootNode.x0}
243
+ absoluteTop={rootNode.y0}
244
+ width={rootNode.x1 - rootNode.x0}
245
+ height={rootNode.y1 - rootNode.y0}
246
+ />
247
+ ),
248
+ [rootNode, width, height, nested, onItemClick, onGroupClick],
249
+ );
250
+
545
251
  return (
546
- <div
547
- className={cx(css.root, nested && css.nested, className)}
548
- {...restProps}
549
- ref={containerRef}
550
- >
551
- {rootNode.children && rootNode.children?.length > 0 ? (
552
- <div className={css.canvas}>
553
- <TileGroup
554
- title={nested ? rootNode.data.label : undefined}
555
- total={(rootNode.data as Tree).total}
556
- id={rootNode.data.id}
557
- childNodes={rootNode.children}
558
- onItemClick={onItemClick}
559
- onGroupClick={onGroupClick}
560
- left={rootNode.x0}
561
- top={rootNode.y0}
562
- absoluteLeft={rootNode.x0}
563
- absoluteTop={rootNode.y0}
564
- width={rootNode.x1 - rootNode.x0}
565
- height={rootNode.y1 - rootNode.y0}
566
- />
252
+ <div className={cx(css.root, className)} {...restProps} ref={containerRef}>
253
+ {hasNodes ? (
254
+ <div className={css.canvas} ref={canvasRef}>
255
+ {canvasContent}
567
256
  </div>
568
257
  ) : (
569
- <div className={css.emptyMessage}>
258
+ <FlexStack alignItems="center" justifyContent="center" className={css.emptyMessage}>
570
259
  <div className={css.emptyMessageWrapper}>{emptyMessage}</div>
571
- </div>
260
+ </FlexStack>
261
+ )}
262
+ {tooltipNode && (
263
+ <Tooltip state={tooltipState} className={css.tooltip}>
264
+ <TooltipArrow state={tooltipState} size={16} className={css.tileTooltipArrow} />
265
+ <TreemapTooltipContent node={tooltipNode} />
266
+ </Tooltip>
572
267
  )}
573
268
  </div>
574
269
  );