cursedbelt 5.40.0 → 5.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/dist/react/Toast.d.ts +12 -2
  2. package/dist/react/Toast.d.ts.map +1 -1
  3. package/dist/react/Toast.js +32 -3
  4. package/dist/react/Toast.js.map +1 -1
  5. package/dist/react/analytics/MetricDrilldown.js +1 -1
  6. package/dist/react/charts/AreaChart.d.ts.map +1 -1
  7. package/dist/react/charts/AreaChart.js +5 -5
  8. package/dist/react/charts/AreaChart.js.map +1 -1
  9. package/dist/react/charts/BarChart.d.ts.map +1 -1
  10. package/dist/react/charts/BarChart.js +3 -3
  11. package/dist/react/charts/BarChart.js.map +1 -1
  12. package/dist/react/charts/ChartCard.d.ts +53 -0
  13. package/dist/react/charts/ChartCard.d.ts.map +1 -0
  14. package/dist/react/charts/ChartCard.js +46 -0
  15. package/dist/react/charts/ChartCard.js.map +1 -0
  16. package/dist/react/charts/ChartFrame.d.ts +12 -5
  17. package/dist/react/charts/ChartFrame.d.ts.map +1 -1
  18. package/dist/react/charts/ChartFrame.js +12 -5
  19. package/dist/react/charts/ChartFrame.js.map +1 -1
  20. package/dist/react/charts/ChartLegend.js +1 -1
  21. package/dist/react/charts/ChartLegend.js.map +1 -1
  22. package/dist/react/charts/HeatmapChart.js +3 -3
  23. package/dist/react/charts/HeatmapChart.js.map +1 -1
  24. package/dist/react/charts/IntervalTimeline.js +1 -1
  25. package/dist/react/charts/IntervalTimeline.js.map +1 -1
  26. package/dist/react/charts/LineChart.d.ts.map +1 -1
  27. package/dist/react/charts/LineChart.js +3 -3
  28. package/dist/react/charts/LineChart.js.map +1 -1
  29. package/dist/react/charts/TimeSeriesChart.d.ts.map +1 -1
  30. package/dist/react/charts/TimeSeriesChart.js +6 -6
  31. package/dist/react/charts/TimeSeriesChart.js.map +1 -1
  32. package/dist/react/charts/chartBox.d.ts +46 -0
  33. package/dist/react/charts/chartBox.d.ts.map +1 -0
  34. package/dist/react/charts/chartBox.js +45 -0
  35. package/dist/react/charts/chartBox.js.map +1 -0
  36. package/dist/react/charts/index.d.ts +2 -0
  37. package/dist/react/charts/index.d.ts.map +1 -1
  38. package/dist/react/charts/index.js +2 -0
  39. package/dist/react/charts/index.js.map +1 -1
  40. package/dist/react/charts/shared.d.ts +13 -2
  41. package/dist/react/charts/shared.d.ts.map +1 -1
  42. package/dist/react/charts/shared.js +14 -3
  43. package/dist/react/charts/shared.js.map +1 -1
  44. package/dist/react/chat/Bubble.js +4 -4
  45. package/dist/react/chat/Bubble.js.map +1 -1
  46. package/dist/react/chat/MessageScroller.js +1 -1
  47. package/dist/react/chat/MessageScroller.js.map +1 -1
  48. package/dist/react/components/ActionBar.d.ts.map +1 -1
  49. package/dist/react/components/ActionBar.js +63 -1
  50. package/dist/react/components/ActionBar.js.map +1 -1
  51. package/dist/react/components/AddItemsMenu.js +1 -1
  52. package/dist/react/components/AddItemsMenu.js.map +1 -1
  53. package/dist/react/components/Alert.d.ts +16 -2
  54. package/dist/react/components/Alert.d.ts.map +1 -1
  55. package/dist/react/components/Alert.js +35 -2
  56. package/dist/react/components/Alert.js.map +1 -1
  57. package/dist/react/components/AppShell.d.ts +55 -33
  58. package/dist/react/components/AppShell.d.ts.map +1 -1
  59. package/dist/react/components/AppShell.js +121 -31
  60. package/dist/react/components/AppShell.js.map +1 -1
  61. package/dist/react/components/AsyncPanel.d.ts +21 -3
  62. package/dist/react/components/AsyncPanel.d.ts.map +1 -1
  63. package/dist/react/components/AsyncPanel.js +49 -5
  64. package/dist/react/components/AsyncPanel.js.map +1 -1
  65. package/dist/react/components/BannerLane.d.ts +32 -0
  66. package/dist/react/components/BannerLane.d.ts.map +1 -0
  67. package/dist/react/components/BannerLane.js +41 -0
  68. package/dist/react/components/BannerLane.js.map +1 -0
  69. package/dist/react/components/Button.d.ts.map +1 -1
  70. package/dist/react/components/Button.js +2 -1
  71. package/dist/react/components/Button.js.map +1 -1
  72. package/dist/react/components/ChipFilterStrip.js +1 -1
  73. package/dist/react/components/ChipFilterStrip.js.map +1 -1
  74. package/dist/react/components/ComboboxField.d.ts.map +1 -1
  75. package/dist/react/components/ComboboxField.js +14 -4
  76. package/dist/react/components/ComboboxField.js.map +1 -1
  77. package/dist/react/components/CommentThread.js +2 -2
  78. package/dist/react/components/CommentThread.js.map +1 -1
  79. package/dist/react/components/ConfirmDialog.js +1 -1
  80. package/dist/react/components/ConfirmDialog.js.map +1 -1
  81. package/dist/react/components/DataTable/DataTable.d.ts +18 -2
  82. package/dist/react/components/DataTable/DataTable.d.ts.map +1 -1
  83. package/dist/react/components/DataTable/DataTable.js +51 -12
  84. package/dist/react/components/DataTable/DataTable.js.map +1 -1
  85. package/dist/react/components/DataTable/Pagination.js +1 -1
  86. package/dist/react/components/DataTable/Pagination.js.map +1 -1
  87. package/dist/react/components/DataTable/RowActions.d.ts +7 -1
  88. package/dist/react/components/DataTable/RowActions.d.ts.map +1 -1
  89. package/dist/react/components/DataTable/RowActions.js +10 -3
  90. package/dist/react/components/DataTable/RowActions.js.map +1 -1
  91. package/dist/react/components/DataTable/TableFilterBuilder.js +1 -1
  92. package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -1
  93. package/dist/react/components/DataTable/cells/CodeCell.js +1 -1
  94. package/dist/react/components/DataTable/cells/CodeCell.js.map +1 -1
  95. package/dist/react/components/DataTable/cells/LinkCell.js +1 -1
  96. package/dist/react/components/DataTable/cells/LinkCell.js.map +1 -1
  97. package/dist/react/components/DataTable/index.d.ts +1 -1
  98. package/dist/react/components/DataTable/index.d.ts.map +1 -1
  99. package/dist/react/components/DataTable/index.js.map +1 -1
  100. package/dist/react/components/DataTable/types.d.ts +20 -0
  101. package/dist/react/components/DataTable/types.d.ts.map +1 -1
  102. package/dist/react/components/DataTable/types.js +22 -0
  103. package/dist/react/components/DataTable/types.js.map +1 -1
  104. package/dist/react/components/DateTimeField.d.ts.map +1 -1
  105. package/dist/react/components/DateTimeField.js +4 -1
  106. package/dist/react/components/DateTimeField.js.map +1 -1
  107. package/dist/react/components/DeleteButton.js +2 -0
  108. package/dist/react/components/DeleteButton.js.map +1 -1
  109. package/dist/react/components/Drawer.js +3 -3
  110. package/dist/react/components/Drawer.js.map +1 -1
  111. package/dist/react/components/DropdownMenu.d.ts +16 -0
  112. package/dist/react/components/DropdownMenu.d.ts.map +1 -1
  113. package/dist/react/components/DropdownMenu.js +22 -6
  114. package/dist/react/components/DropdownMenu.js.map +1 -1
  115. package/dist/react/components/EmptyState.d.ts +10 -2
  116. package/dist/react/components/EmptyState.d.ts.map +1 -1
  117. package/dist/react/components/EmptyState.js +10 -5
  118. package/dist/react/components/EmptyState.js.map +1 -1
  119. package/dist/react/components/EventTimeline.js +1 -1
  120. package/dist/react/components/EventTimeline.js.map +1 -1
  121. package/dist/react/components/FileDropZone.js +1 -1
  122. package/dist/react/components/FileDropZone.js.map +1 -1
  123. package/dist/react/components/Grid.d.ts +9 -1
  124. package/dist/react/components/Grid.d.ts.map +1 -1
  125. package/dist/react/components/Grid.js +20 -2
  126. package/dist/react/components/Grid.js.map +1 -1
  127. package/dist/react/components/Guide.d.ts +31 -0
  128. package/dist/react/components/Guide.d.ts.map +1 -0
  129. package/dist/react/components/Guide.js +18 -0
  130. package/dist/react/components/Guide.js.map +1 -0
  131. package/dist/react/components/InfoHintImpl.d.ts +0 -13
  132. package/dist/react/components/InfoHintImpl.d.ts.map +1 -1
  133. package/dist/react/components/InfoHintImpl.js +17 -1
  134. package/dist/react/components/InfoHintImpl.js.map +1 -1
  135. package/dist/react/components/InlineEditableText.js +1 -1
  136. package/dist/react/components/InlineEditableText.js.map +1 -1
  137. package/dist/react/components/IsolatedFrame.js +1 -1
  138. package/dist/react/components/IsolatedFrame.js.map +1 -1
  139. package/dist/react/components/ListToolbar.d.ts.map +1 -1
  140. package/dist/react/components/ListToolbar.js +2 -2
  141. package/dist/react/components/ListToolbar.js.map +1 -1
  142. package/dist/react/components/LogViewer.d.ts +26 -2
  143. package/dist/react/components/LogViewer.d.ts.map +1 -1
  144. package/dist/react/components/LogViewer.js +41 -26
  145. package/dist/react/components/LogViewer.js.map +1 -1
  146. package/dist/react/components/Modal.d.ts +5 -1
  147. package/dist/react/components/Modal.d.ts.map +1 -1
  148. package/dist/react/components/Modal.js +18 -8
  149. package/dist/react/components/Modal.js.map +1 -1
  150. package/dist/react/components/Page.d.ts +51 -7
  151. package/dist/react/components/Page.d.ts.map +1 -1
  152. package/dist/react/components/Page.js +53 -8
  153. package/dist/react/components/Page.js.map +1 -1
  154. package/dist/react/components/PageGuideButton.d.ts +11 -0
  155. package/dist/react/components/PageGuideButton.d.ts.map +1 -0
  156. package/dist/react/components/PageGuideButton.js +13 -0
  157. package/dist/react/components/PageGuideButton.js.map +1 -0
  158. package/dist/react/components/PanelSeparator.js +1 -1
  159. package/dist/react/components/PanelSeparator.js.map +1 -1
  160. package/dist/react/components/Popover.d.ts.map +1 -1
  161. package/dist/react/components/Popover.js +2 -1
  162. package/dist/react/components/Popover.js.map +1 -1
  163. package/dist/react/components/PromptDialog.js +1 -1
  164. package/dist/react/components/PromptDialog.js.map +1 -1
  165. package/dist/react/components/ScrollArea.d.ts +9 -1
  166. package/dist/react/components/ScrollArea.d.ts.map +1 -1
  167. package/dist/react/components/ScrollArea.js +9 -3
  168. package/dist/react/components/ScrollArea.js.map +1 -1
  169. package/dist/react/components/Section.d.ts +5 -2
  170. package/dist/react/components/Section.d.ts.map +1 -1
  171. package/dist/react/components/Section.js +5 -2
  172. package/dist/react/components/Section.js.map +1 -1
  173. package/dist/react/components/Skeleton.d.ts +19 -1
  174. package/dist/react/components/Skeleton.d.ts.map +1 -1
  175. package/dist/react/components/Skeleton.js +24 -2
  176. package/dist/react/components/Skeleton.js.map +1 -1
  177. package/dist/react/components/StatStrip.js +1 -1
  178. package/dist/react/components/StatStrip.js.map +1 -1
  179. package/dist/react/components/StatTile.d.ts +30 -3
  180. package/dist/react/components/StatTile.d.ts.map +1 -1
  181. package/dist/react/components/StatTile.js +35 -9
  182. package/dist/react/components/StatTile.js.map +1 -1
  183. package/dist/react/components/StatTileGrid.d.ts +10 -1
  184. package/dist/react/components/StatTileGrid.d.ts.map +1 -1
  185. package/dist/react/components/StatTileGrid.js +50 -33
  186. package/dist/react/components/StatTileGrid.js.map +1 -1
  187. package/dist/react/components/StatusPill.d.ts.map +1 -1
  188. package/dist/react/components/StatusPill.js +26 -1
  189. package/dist/react/components/StatusPill.js.map +1 -1
  190. package/dist/react/components/Surface.d.ts +1 -1
  191. package/dist/react/components/Surface.d.ts.map +1 -1
  192. package/dist/react/components/Surface.js +20 -11
  193. package/dist/react/components/Surface.js.map +1 -1
  194. package/dist/react/components/SwatchPicker.d.ts.map +1 -1
  195. package/dist/react/components/SwatchPicker.js +5 -1
  196. package/dist/react/components/SwatchPicker.js.map +1 -1
  197. package/dist/react/components/Switch.js +1 -1
  198. package/dist/react/components/Switch.js.map +1 -1
  199. package/dist/react/components/WidgetHeader.js +1 -1
  200. package/dist/react/components/WidgetHeader.js.map +1 -1
  201. package/dist/react/components/calendar/CalendarLegend.js +1 -1
  202. package/dist/react/components/calendar/CalendarLegend.js.map +1 -1
  203. package/dist/react/components/calendar/DayAgenda.js +1 -1
  204. package/dist/react/components/calendar/DayAgenda.js.map +1 -1
  205. package/dist/react/components/calendar/EventChip.js +1 -1
  206. package/dist/react/components/calendar/EventChip.js.map +1 -1
  207. package/dist/react/components/calendar/MonthGrid.js +1 -1
  208. package/dist/react/components/calendar/MonthGrid.js.map +1 -1
  209. package/dist/react/components/calendar/WeekView.js +2 -2
  210. package/dist/react/components/calendar/WeekView.js.map +1 -1
  211. package/dist/react/components/cardFrame.d.ts +16 -0
  212. package/dist/react/components/cardFrame.d.ts.map +1 -0
  213. package/dist/react/components/cardFrame.js +24 -0
  214. package/dist/react/components/cardFrame.js.map +1 -0
  215. package/dist/react/components/dialog.d.ts.map +1 -1
  216. package/dist/react/components/dialog.js +2 -1
  217. package/dist/react/components/dialog.js.map +1 -1
  218. package/dist/react/dashboard-grid/WidgetFrame.js +2 -2
  219. package/dist/react/dashboard-grid/WidgetFrame.js.map +1 -1
  220. package/dist/react/emoji/EmojiPicker.js +1 -1
  221. package/dist/react/emoji/EmojiPicker.js.map +1 -1
  222. package/dist/react/file-tree/FileTree.d.ts +8 -1
  223. package/dist/react/file-tree/FileTree.d.ts.map +1 -1
  224. package/dist/react/file-tree/FileTree.js +29 -4
  225. package/dist/react/file-tree/FileTree.js.map +1 -1
  226. package/dist/react/filter-rail/FilterRail.js +1 -1
  227. package/dist/react/filter-rail/FilterRail.js.map +1 -1
  228. package/dist/react/icons.js +1 -1
  229. package/dist/react/icons.js.map +1 -1
  230. package/dist/react/index.d.ts +8 -5
  231. package/dist/react/index.d.ts.map +1 -1
  232. package/dist/react/index.js +5 -2
  233. package/dist/react/index.js.map +1 -1
  234. package/dist/react/lib/menuSections.d.ts +8 -0
  235. package/dist/react/lib/menuSections.d.ts.map +1 -0
  236. package/dist/react/lib/menuSections.js +37 -0
  237. package/dist/react/lib/menuSections.js.map +1 -0
  238. package/dist/react/markdown/Markdown.js +2 -2
  239. package/dist/react/markdown/Markdown.js.map +1 -1
  240. package/dist/react/media/HoverScrubVideoThumb.js +1 -1
  241. package/dist/react/media/HoverScrubVideoThumb.js.map +1 -1
  242. package/dist/react/media/MaskPainter.js +1 -1
  243. package/dist/react/media/MediaUploadControl.js +1 -1
  244. package/dist/react/media/MediaUploadControl.js.map +1 -1
  245. package/dist/react/media/VideoTrimmer.js +1 -1
  246. package/dist/react/media/VideoTrimmer.js.map +1 -1
  247. package/dist/react/media/denseGallery.css +5 -1
  248. package/dist/react/namespace/NamespaceTargetCapsule.js +1 -1
  249. package/dist/react/namespace/NamespaceTargetCapsule.js.map +1 -1
  250. package/dist/react/nav/BreadcrumbTrail.js +1 -1
  251. package/dist/react/nav/BreadcrumbTrail.js.map +1 -1
  252. package/dist/react/nav/CommandBar.d.ts +7 -1
  253. package/dist/react/nav/CommandBar.d.ts.map +1 -1
  254. package/dist/react/nav/CommandBar.js +5 -3
  255. package/dist/react/nav/CommandBar.js.map +1 -1
  256. package/dist/react/nav/PlaceBar.d.ts.map +1 -1
  257. package/dist/react/nav/PlaceBar.js +7 -9
  258. package/dist/react/nav/PlaceBar.js.map +1 -1
  259. package/dist/react/nav/SideNav.d.ts +12 -2
  260. package/dist/react/nav/SideNav.d.ts.map +1 -1
  261. package/dist/react/nav/SideNav.js +42 -22
  262. package/dist/react/nav/SideNav.js.map +1 -1
  263. package/dist/react/nav/TopBar.d.ts +65 -31
  264. package/dist/react/nav/TopBar.d.ts.map +1 -1
  265. package/dist/react/nav/TopBar.js +59 -24
  266. package/dist/react/nav/TopBar.js.map +1 -1
  267. package/dist/react/nav/index.d.ts +1 -1
  268. package/dist/react/nav/index.d.ts.map +1 -1
  269. package/dist/react/nav/index.js +1 -1
  270. package/dist/react/nav/index.js.map +1 -1
  271. package/dist/react/nav/navShared.d.ts +10 -1
  272. package/dist/react/nav/navShared.d.ts.map +1 -1
  273. package/dist/react/nav/navShared.js +23 -0
  274. package/dist/react/nav/navShared.js.map +1 -1
  275. package/dist/react/notifications/NotificationFeed.js +2 -2
  276. package/dist/react/notifications/NotificationFeed.js.map +1 -1
  277. package/dist/react/palette/Command.d.ts.map +1 -1
  278. package/dist/react/palette/Command.js +1 -1
  279. package/dist/react/palette/Command.js.map +1 -1
  280. package/dist/react/palette/CommandPalette.d.ts +13 -1
  281. package/dist/react/palette/CommandPalette.d.ts.map +1 -1
  282. package/dist/react/palette/CommandPalette.js +44 -8
  283. package/dist/react/palette/CommandPalette.js.map +1 -1
  284. package/dist/react/palette/commandSources.d.ts +57 -0
  285. package/dist/react/palette/commandSources.d.ts.map +1 -0
  286. package/dist/react/palette/commandSources.js +129 -0
  287. package/dist/react/palette/commandSources.js.map +1 -0
  288. package/dist/react/palette/index.d.ts +1 -0
  289. package/dist/react/palette/index.d.ts.map +1 -1
  290. package/dist/react/palette/index.js +1 -0
  291. package/dist/react/palette/index.js.map +1 -1
  292. package/dist/react/rich-text/RichTextEditor.js +1 -1
  293. package/dist/react/rich-text/RichTextEditor.js.map +1 -1
  294. package/dist/react/rich-text/RichTextToolbar.js +1 -1
  295. package/dist/react/rich-text/RichTextToolbar.js.map +1 -1
  296. package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
  297. package/dist/styles-areas/analytics.css +16 -16
  298. package/dist/styles-areas/auth.css +3 -3
  299. package/dist/styles-areas/calendar.css +6 -6
  300. package/dist/styles-areas/chart-table.css +1 -1
  301. package/dist/styles-areas/charts.css +3 -3
  302. package/dist/styles-areas/chat.css +7 -6
  303. package/dist/styles-areas/companion-link.css +2 -2
  304. package/dist/styles-areas/core.css +98 -89
  305. package/dist/styles-areas/dashboard-grid.css +4 -4
  306. package/dist/styles-areas/data-table.css +16 -16
  307. package/dist/styles-areas/disk-usage.css +5 -5
  308. package/dist/styles-areas/emoji.css +2 -2
  309. package/dist/styles-areas/fields.css +13 -14
  310. package/dist/styles-areas/filter-rail.css +4 -4
  311. package/dist/styles-areas/folder-tree.css +3 -3
  312. package/dist/styles-areas/markdown.css +2 -1
  313. package/dist/styles-areas/master-detail.css +3 -3
  314. package/dist/styles-areas/media-gallery.css +8 -8
  315. package/dist/styles-areas/media.css +12 -13
  316. package/dist/styles-areas/nav.css +28 -14
  317. package/dist/styles-areas/notifications.css +4 -4
  318. package/dist/styles-areas/overlays.css +4 -4
  319. package/dist/styles-areas/palette.css +4 -3
  320. package/dist/styles-areas/rich-text.css +3 -3
  321. package/dist/styles-areas/sharing.css +4 -3
  322. package/dist/styles-areas/stats.css +9 -8
  323. package/dist/styles-areas/test-report.css +3 -3
  324. package/dist/styles-areas/wizard.css +6 -5
  325. package/dist/styles-areas/workbench.css +10 -9
  326. package/dist/styles-areas/workbook-viewer.css +2 -2
  327. package/dist/styles-utilities.css +272 -187
  328. package/dist/testing/designAudit.d.ts.map +1 -1
  329. package/dist/testing/designAudit.js +4 -0
  330. package/dist/testing/designAudit.js.map +1 -1
  331. package/dist/testing/designBaseline.d.ts.map +1 -1
  332. package/dist/testing/designBaseline.js +4 -0
  333. package/dist/testing/designBaseline.js.map +1 -1
  334. package/dist/theme.css +103 -2
  335. package/package.json +3 -2
  336. package/scripts/guardrails-baseline.json +2 -1
  337. package/scripts/guardrailsEnforce.spec.ts +64 -0
  338. package/scripts/guardrailsEnforce.ts +65 -8
  339. package/scripts/styleAreas.ts +1 -0
  340. package/src/nodeTypesDeclared.spec.ts +47 -0
  341. package/src/react/Toast.spec.tsx +43 -0
  342. package/src/react/Toast.tsx +45 -2
  343. package/src/react/analytics/MetricDrilldown.tsx +1 -1
  344. package/src/react/charts/AreaChart.tsx +9 -8
  345. package/src/react/charts/BarChart.tsx +11 -10
  346. package/src/react/charts/ChartCard.tsx +146 -0
  347. package/src/react/charts/ChartFrame.tsx +28 -10
  348. package/src/react/charts/ChartLegend.tsx +1 -1
  349. package/src/react/charts/HeatmapChart.tsx +5 -5
  350. package/src/react/charts/IntervalTimeline.tsx +2 -2
  351. package/src/react/charts/LineChart.tsx +9 -8
  352. package/src/react/charts/TimeSeriesChart.tsx +11 -10
  353. package/src/react/charts/chartBox.spec.ts +40 -0
  354. package/src/react/charts/chartBox.ts +75 -0
  355. package/src/react/charts/index.ts +2 -0
  356. package/src/react/charts/shared.ts +16 -3
  357. package/src/react/chat/Bubble.tsx +5 -5
  358. package/src/react/chat/MessageScroller.tsx +1 -1
  359. package/src/react/components/ActionBar.spec.tsx +90 -0
  360. package/src/react/components/ActionBar.tsx +82 -2
  361. package/src/react/components/AddItemsMenu.tsx +1 -1
  362. package/src/react/components/Alert.spec.tsx +32 -2
  363. package/src/react/components/Alert.tsx +47 -3
  364. package/src/react/components/AppShell.spec.tsx +199 -13
  365. package/src/react/components/AppShell.tsx +235 -92
  366. package/src/react/components/AsyncPanel.spec.tsx +7 -1
  367. package/src/react/components/AsyncPanel.tsx +85 -5
  368. package/src/react/components/BannerLane.tsx +128 -0
  369. package/src/react/components/Button.tsx +2 -0
  370. package/src/react/components/ChipFilterStrip.tsx +1 -1
  371. package/src/react/components/ComboboxField.tsx +20 -3
  372. package/src/react/components/CommentThread.tsx +2 -2
  373. package/src/react/components/ConfirmDialog.tsx +1 -1
  374. package/src/react/components/DataTable/DataTable.tsx +80 -8
  375. package/src/react/components/DataTable/Pagination.tsx +1 -1
  376. package/src/react/components/DataTable/RowActions.tsx +55 -2
  377. package/src/react/components/DataTable/TableFilterBuilder.tsx +1 -1
  378. package/src/react/components/DataTable/cells/CodeCell.tsx +1 -1
  379. package/src/react/components/DataTable/cells/LinkCell.tsx +1 -1
  380. package/src/react/components/DataTable/index.ts +1 -0
  381. package/src/react/components/DataTable/numericColumn.spec.ts +19 -0
  382. package/src/react/components/DataTable/types.ts +36 -0
  383. package/src/react/components/DateTimeField.tsx +3 -1
  384. package/src/react/components/DeleteButton.tsx +3 -0
  385. package/src/react/components/Drawer.tsx +3 -3
  386. package/src/react/components/DropdownMenu.spec.tsx +55 -0
  387. package/src/react/components/DropdownMenu.tsx +73 -20
  388. package/src/react/components/EmptyState.tsx +26 -7
  389. package/src/react/components/EventTimeline.tsx +1 -1
  390. package/src/react/components/Field.width.spec.tsx +11 -0
  391. package/src/react/components/FileDropZone.tsx +1 -1
  392. package/src/react/components/Grid.spec.tsx +44 -0
  393. package/src/react/components/Grid.tsx +41 -11
  394. package/src/react/components/Guide.tsx +77 -0
  395. package/src/react/components/InfoHint.spec.tsx +21 -0
  396. package/src/react/components/InfoHintImpl.tsx +22 -1
  397. package/src/react/components/InlineEditableText.tsx +1 -1
  398. package/src/react/components/IsolatedFrame.tsx +1 -1
  399. package/src/react/components/ListToolbar.spec.tsx +12 -0
  400. package/src/react/components/ListToolbar.tsx +8 -5
  401. package/src/react/components/LogViewer.tsx +118 -18
  402. package/src/react/components/Modal.spec.tsx +17 -2
  403. package/src/react/components/Modal.tsx +25 -10
  404. package/src/react/components/MultiSelectField.spec.tsx +6 -0
  405. package/src/react/components/Page.spec.tsx +89 -5
  406. package/src/react/components/Page.tsx +100 -16
  407. package/src/react/components/PageGuideButton.tsx +42 -0
  408. package/src/react/components/PanelSeparator.tsx +1 -1
  409. package/src/react/components/Popover.tsx +3 -1
  410. package/src/react/components/PromptDialog.tsx +1 -1
  411. package/src/react/components/ScrollArea.spec.tsx +20 -0
  412. package/src/react/components/ScrollArea.tsx +19 -0
  413. package/src/react/components/Section.spec.tsx +82 -1
  414. package/src/react/components/Section.tsx +10 -4
  415. package/src/react/components/Skeleton.tsx +50 -2
  416. package/src/react/components/StatStrip.tsx +1 -1
  417. package/src/react/components/StatTile.tsx +84 -11
  418. package/src/react/components/StatTileGrid.spec.tsx +6 -1
  419. package/src/react/components/StatTileGrid.tsx +25 -0
  420. package/src/react/components/StatusPill.tsx +26 -1
  421. package/src/react/components/Surface.tsx +22 -14
  422. package/src/react/components/SwatchPicker.tsx +4 -0
  423. package/src/react/components/Switch.tsx +1 -1
  424. package/src/react/components/WidgetHeader.tsx +1 -1
  425. package/src/react/components/calendar/CalendarLegend.tsx +1 -1
  426. package/src/react/components/calendar/DayAgenda.tsx +1 -1
  427. package/src/react/components/calendar/EventChip.tsx +1 -1
  428. package/src/react/components/calendar/MonthGrid.tsx +1 -1
  429. package/src/react/components/calendar/WeekView.tsx +2 -2
  430. package/src/react/components/cardFrame.ts +28 -0
  431. package/src/react/components/dataDisplay.spec.tsx +176 -0
  432. package/src/react/components/dialog.tsx +4 -1
  433. package/src/react/dashboard-grid/WidgetFrame.tsx +2 -2
  434. package/src/react/emoji/EmojiPicker.tsx +1 -1
  435. package/src/react/file-tree/FileTree.spec.tsx +49 -0
  436. package/src/react/file-tree/FileTree.tsx +37 -4
  437. package/src/react/filter-rail/FilterRail.tsx +1 -1
  438. package/src/react/icons.tsx +1 -1
  439. package/src/react/index.ts +28 -3
  440. package/src/react/lib/menuSections.ts +33 -0
  441. package/src/react/markdown/Markdown.tsx +2 -2
  442. package/src/react/media/HoverScrubVideoThumb.tsx +2 -2
  443. package/src/react/media/MaskPainter.tsx +1 -1
  444. package/src/react/media/MediaUploadControl.tsx +1 -1
  445. package/src/react/media/VideoTrimmer.tsx +1 -1
  446. package/src/react/media/denseGallery.css +5 -1
  447. package/src/react/namespace/NamespaceTargetCapsule.tsx +1 -1
  448. package/src/react/nav/BreadcrumbTrail.tsx +2 -2
  449. package/src/react/nav/CommandBar.tsx +14 -3
  450. package/src/react/nav/PlaceBar.tsx +18 -8
  451. package/src/react/nav/SideNav.tsx +99 -17
  452. package/src/react/nav/TopBar.spec.tsx +78 -21
  453. package/src/react/nav/TopBar.tsx +270 -98
  454. package/src/react/nav/index.ts +8 -1
  455. package/src/react/nav/nav.spec.tsx +46 -2
  456. package/src/react/nav/navShared.tsx +23 -2
  457. package/src/react/notifications/NotificationFeed.tsx +2 -2
  458. package/src/react/palette/Command.tsx +1 -1
  459. package/src/react/palette/CommandPalette.spec.tsx +31 -0
  460. package/src/react/palette/CommandPalette.tsx +108 -11
  461. package/src/react/palette/commandSources.tsx +186 -0
  462. package/src/react/palette/index.ts +7 -0
  463. package/src/react/rich-text/RichTextEditor.tsx +1 -1
  464. package/src/react/rich-text/RichTextToolbar.tsx +1 -1
  465. package/src/styles-areas/analytics.css +16 -16
  466. package/src/styles-areas/auth.css +3 -3
  467. package/src/styles-areas/calendar.css +6 -6
  468. package/src/styles-areas/chart-table.css +1 -1
  469. package/src/styles-areas/charts.css +3 -3
  470. package/src/styles-areas/chat.css +7 -6
  471. package/src/styles-areas/companion-link.css +2 -2
  472. package/src/styles-areas/core.css +98 -89
  473. package/src/styles-areas/dashboard-grid.css +4 -4
  474. package/src/styles-areas/data-table.css +16 -16
  475. package/src/styles-areas/disk-usage.css +5 -5
  476. package/src/styles-areas/emoji.css +2 -2
  477. package/src/styles-areas/fields.css +13 -14
  478. package/src/styles-areas/filter-rail.css +4 -4
  479. package/src/styles-areas/folder-tree.css +3 -3
  480. package/src/styles-areas/markdown.css +2 -1
  481. package/src/styles-areas/master-detail.css +3 -3
  482. package/src/styles-areas/media-gallery.css +8 -8
  483. package/src/styles-areas/media.css +12 -13
  484. package/src/styles-areas/nav.css +28 -14
  485. package/src/styles-areas/notifications.css +4 -4
  486. package/src/styles-areas/overlays.css +4 -4
  487. package/src/styles-areas/palette.css +4 -3
  488. package/src/styles-areas/rich-text.css +3 -3
  489. package/src/styles-areas/sharing.css +4 -3
  490. package/src/styles-areas/stats.css +9 -8
  491. package/src/styles-areas/test-report.css +3 -3
  492. package/src/styles-areas/wizard.css +6 -5
  493. package/src/styles-areas/workbench.css +10 -9
  494. package/src/styles-areas/workbook-viewer.css +2 -2
  495. package/src/styles-utilities.css +272 -187
  496. package/src/testing/designAudit.ts +3 -0
  497. package/src/testing/designBaseline.ts +4 -0
  498. package/src/theme.css +103 -2
  499. package/src/themeDarkScopeAliases.spec.ts +65 -0
@@ -0,0 +1,176 @@
1
+ import { afterEach, beforeAll, describe, expect, spyOn, test } from 'bun:test';
2
+ import { act, cleanup, fireEvent, render, waitFor } from '@testing-library/react';
3
+ import { AsyncPanel } from './AsyncPanel.js';
4
+ import { DataTable, preloadDataTableParts } from './DataTable/DataTable.js';
5
+ import type { ColDef } from './DataTable/types.js';
6
+ import { EmptyState } from './EmptyState.js';
7
+ import { LogViewer } from './LogViewer.js';
8
+ import { STATUS_ATTENTION_TONE } from './StatusPill.js';
9
+ import { StatTile } from './StatTile.js';
10
+ import { StatTileGrid } from './StatTileGrid.js';
11
+
12
+ // Task 2464's unit half — what happy-dom can decide, through the components alone (the pure
13
+ // helpers are specced beside them: `DataTable/numericColumn.spec.ts`, `charts/chartBox.spec.ts`,
14
+ // `StatTileGrid.spec.tsx`, `AsyncPanel.spec.tsx`). Layout (fit at 2560, chart resize, the log's
15
+ // follow pause) is measured in `e2e/data-display.spec.ts`.
16
+
17
+ beforeAll(preloadDataTableParts);
18
+ afterEach(cleanup);
19
+
20
+ interface Row extends Record<string, unknown> {
21
+ step: string;
22
+ runs: number;
23
+ code: string;
24
+ }
25
+ const ROWS: Row[] = [
26
+ { step: 'gate', runs: 2472, code: '41' },
27
+ { step: 'prove-red', runs: 531, code: '7' },
28
+ ];
29
+ const COLUMNS: ColDef<Row>[] = [
30
+ { key: 'step', label: 'Step', type: 'text' },
31
+ { key: 'runs', label: 'Runs', type: 'number' },
32
+ ];
33
+
34
+ describe('DAT-1 · numeric columns', () => {
35
+ test('numeric header and cells stack digits; the warning fires once in dev', () => {
36
+ const warn = spyOn(console, 'warn').mockImplementation(() => undefined);
37
+ const { container } = render(
38
+ <DataTable<Row> columns={[...COLUMNS, { key: 'code', label: 'Code', type: 'text' }]} data={ROWS} hidePagination />,
39
+ );
40
+ const th = [...container.querySelectorAll('thead th')].find((n) => n.textContent?.includes('Runs'));
41
+ expect(th?.className).toContain('tabular-nums');
42
+ const cells = container.querySelectorAll('tbody tr:first-child td');
43
+ expect(cells[1]?.className).toContain('tabular-nums');
44
+ expect(cells[0]?.className).not.toContain('tabular-nums');
45
+ expect(warn.mock.calls.some(([m]) => String(m).includes('"code"'))).toBe(true);
46
+ warn.mockRestore();
47
+ });
48
+ });
49
+
50
+ describe('DAT-3 / DAT-5 · fit and the row action', () => {
51
+ test('`fit` marks the table and drops the full-width rule', () => {
52
+ const { container } = render(<DataTable<Row> columns={COLUMNS} data={ROWS} fit hidePagination />);
53
+ const table = container.querySelector('table');
54
+ expect(table?.getAttribute('data-cb-table-fit')).toBe('true');
55
+ expect(table?.className.split(' ')).not.toContain('w-full');
56
+ expect(table?.className).toContain('w-auto');
57
+ });
58
+
59
+ test('one inline action where the row returns one, none where it returns null', () => {
60
+ const { container } = render(
61
+ <DataTable<Row>
62
+ columns={COLUMNS}
63
+ data={ROWS}
64
+ hidePagination
65
+ rowAction={(r) => (r.runs > 1000 ? { label: 'Retry', onClick: () => undefined } : null)}
66
+ />,
67
+ );
68
+ const rows = container.querySelectorAll('tbody tr');
69
+ expect(rows[0]?.textContent).toContain('Retry');
70
+ expect(rows[1]?.textContent).not.toContain('Retry');
71
+ });
72
+
73
+ test('a right-click opens the row menu only where the row has one', () => {
74
+ const { container } = render(
75
+ <DataTable<Row> columns={COLUMNS} data={ROWS} hidePagination rowMenu={() => [{ key: 'o', label: 'Open', onClick: () => undefined }]} />,
76
+ );
77
+ const row = container.querySelector('tbody tr') as HTMLElement;
78
+ const event = new MouseEvent('contextmenu', { bubbles: true, cancelable: true });
79
+ act(() => {
80
+ row.dispatchEvent(event);
81
+ });
82
+ expect(event.defaultPrevented).toBe(true);
83
+ });
84
+ });
85
+
86
+ describe('STA-3 · filtered to nothing', () => {
87
+ test('EmptyState `onClearFilters` is the filtered variant with its own verb', () => {
88
+ let cleared = 0;
89
+ const { getByText, container } = render(<EmptyState onClearFilters={() => cleared++} />);
90
+ expect(getByText('No matches')).toBeDefined();
91
+ expect(container.querySelector('[data-cb-empty-state]')?.getAttribute('data-cb-empty-state')).toBe('filtered');
92
+ fireEvent.click(getByText('Clear filters'));
93
+ expect(cleared).toBe(1);
94
+ });
95
+
96
+ test('a DataTable searched to nothing offers Clear filters, which brings the rows back', async () => {
97
+ const { container, getByText } = render(<DataTable<Row> columns={COLUMNS} data={ROWS} hidePagination />);
98
+ const input = container.querySelector('input') as HTMLInputElement;
99
+ fireEvent.change(input, { target: { value: 'zzz-nothing' } });
100
+ await waitFor(() => expect(getByText('Clear filters')).toBeDefined());
101
+ fireEvent.click(getByText('Clear filters'));
102
+ await waitFor(() => expect(container.querySelectorAll('tbody tr').length).toBe(2));
103
+ });
104
+
105
+ test('an empty dataset is NOT the filtered variant', () => {
106
+ const { container } = render(<DataTable<Row> columns={COLUMNS} data={[]} hidePagination />);
107
+ expect(container.textContent).toContain('No results');
108
+ expect(container.textContent).not.toContain('Clear filters');
109
+ });
110
+ });
111
+
112
+ describe('DAT-8 / DAT-9 · StatTile', () => {
113
+ test('one value size per grid — the longest value sets it for every tile', () => {
114
+ const { container } = render(
115
+ <StatTileGrid>
116
+ <StatTile label='a' value='21' />
117
+ <StatTile label='b' value='61h 20m' />
118
+ <StatTile label='c' value='Executing now' />
119
+ </StatTileGrid>,
120
+ );
121
+ const sizes = [...container.querySelectorAll('[data-cb-stat-size]')].map((n) => n.getAttribute('data-cb-stat-size'));
122
+ expect(sizes).toEqual(['sm', 'sm', 'sm']);
123
+ });
124
+
125
+ test('a budget past its max reads as the real percentage, in the critical tone', () => {
126
+ const { container, getByText } = render(
127
+ <StatTile label='DO' value='1.11M' budget={{ used: 1.11, max: 1, verb: 'of the allowance', window: 'Oct' }} />,
128
+ );
129
+ expect(getByText('111% of the allowance')).toBeDefined();
130
+ expect(container.querySelector('[data-cb-stat-budget]')?.getAttribute('data-cb-stat-budget')).toBe('critical');
131
+ });
132
+ });
133
+
134
+ describe('STA-1 / STA-2 · AsyncPanel', () => {
135
+ test('first load is a skeleton of the content\'s shape', () => {
136
+ const { container } = render(
137
+ <AsyncPanel loading skeleton='tiles'>
138
+ <p>never</p>
139
+ </AsyncPanel>,
140
+ );
141
+ expect(container.querySelector('[data-cb-skeleton="tiles"]')).not.toBeNull();
142
+ });
143
+
144
+ test('a refetch keeps the data on screen and says it is updating', () => {
145
+ const { getByText, rerender, container } = render(
146
+ <AsyncPanel updatedAt={Date.now() - 12_000}>
147
+ <p>the goods</p>
148
+ </AsyncPanel>,
149
+ );
150
+ expect(container.querySelector('[data-cb-freshness]')?.getAttribute('data-cb-freshness')).toBe('fresh');
151
+ rerender(
152
+ <AsyncPanel loading updatedAt={Date.now() - 12_000}>
153
+ <p>the goods</p>
154
+ </AsyncPanel>,
155
+ );
156
+ expect(getByText('the goods')).toBeDefined();
157
+ expect(getByText('Updating…')).toBeDefined();
158
+ });
159
+ });
160
+
161
+ describe('DAT-4 / DAT-13 · status and the log', () => {
162
+ test('the operator vocabulary of station and roms is rationed, not neutral', () => {
163
+ expect(STATUS_ATTENTION_TONE.interrupted).toBe('error');
164
+ expect(STATUS_ATTENTION_TONE['not-answering']).toBe('error');
165
+ expect(STATUS_ATTENTION_TONE.stale).toBe('warning');
166
+ expect(STATUS_ATTENTION_TONE.transcoding).toBe('success');
167
+ });
168
+
169
+ test('a log with a stream draws the header strip and no empty toolbar row', () => {
170
+ const { container, getByText } = render(
171
+ <LogViewer text={'a\nb'} stream='Batch B1' age='3m' openFullLog={{ href: '#x' }} filterable={false} />,
172
+ );
173
+ expect(container.querySelector('[data-cb-log-header]')?.textContent).toContain('Batch B1');
174
+ expect(getByText(/Open full log/)).toBeDefined();
175
+ });
176
+ });
@@ -1,6 +1,7 @@
1
1
  import * as DialogPrimitive from '@radix-ui/react-dialog';
2
2
  import { type ComponentPropsWithoutRef, forwardRef, useEffect } from 'react';
3
3
  import { cn } from '../lib/cn.js';
4
+ import { CardFrameContext } from './cardFrame.js';
4
5
  import { useFloatingContainer } from '../lib/floatingContainer.js';
5
6
  import { noteDialogOpen } from '../lib/openDialogs.js';
6
7
 
@@ -115,7 +116,9 @@ export const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(
115
116
  {...props}
116
117
  >
117
118
  <CountsAsOpen />
118
- {children}
119
+ {/* A dialog floats: what it holds starts a fresh stack of container levels, even
120
+ when it was opened from inside a card (React context crosses the portal). */}
121
+ <CardFrameContext.Provider value={false}>{children}</CardFrameContext.Provider>
119
122
  </DialogPrimitive.Content>
120
123
  </DialogPortal>
121
124
  );
@@ -84,9 +84,9 @@ export function WidgetFrame({
84
84
  </>
85
85
  }
86
86
  className={cn(
87
- 'dashboard-drag-handle h-auto min-h-[2.75rem] cursor-grab select-none active:cursor-grabbing',
87
+ 'dashboard-drag-handle h-auto min-h-11 cursor-grab select-none active:cursor-grabbing',
88
88
  onKeyDown !== undefined &&
89
- 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring',
89
+ 'focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring',
90
90
  )}
91
91
  {...(onKeyDown !== undefined && {
92
92
  tabIndex: 0,
@@ -57,7 +57,7 @@ function EmojiMartPanel(props: Record<string, unknown>) {
57
57
  if (failed) throw failed;
58
58
  return (
59
59
  <>
60
- {!ready && <Skeleton className='h-[420px] w-[352px]' />}
60
+ {!ready && <Skeleton className='h-105 w-88' />}
61
61
  <div ref={host} />
62
62
  </>
63
63
  );
@@ -673,6 +673,55 @@ describe('where you are', () => {
673
673
  view.rerender(<FileTree nodes={TREE} selectedId='dinos' onSelect={() => undefined} />);
674
674
  expect(scrolled).toEqual([]);
675
675
  });
676
+
677
+ test('a changed revealKey reveals the SAME selection again; an unchanged one does not', () => {
678
+ const scrolled: string[] = [];
679
+ const props = { nodes: TREE, onSelect: () => undefined, selectedId: 'dinos' };
680
+ const view = render(<FileTree {...props} revealKey={0} />);
681
+ for (const row of screen.getAllByRole('treeitem') as HTMLElement[]) {
682
+ row.scrollIntoView = () => scrolled.push((row.textContent ?? '').trim());
683
+ row.getBoundingClientRect = () => ({ top: 900, bottom: 920 }) as DOMRect;
684
+ }
685
+ (view.container.querySelector('.cbft-scroll') as HTMLElement).getBoundingClientRect = () =>
686
+ ({ top: 0, bottom: 400 }) as DOMRect;
687
+ view.rerender(<FileTree {...props} revealKey={0} />);
688
+ expect(scrolled).toEqual([]);
689
+ view.rerender(<FileTree {...props} revealKey={1} />);
690
+ expect(scrolled).toEqual(['Dinos']);
691
+ });
692
+
693
+ test('🔴 under scroll="host" the HOST scroller is the frame, not the tree drawn at full height', () => {
694
+ // music's rail: the tree is laid out at its natural height inside the rail's scroller, so
695
+ // its own frame holds every row and measuring against it never scrolled a revealed row
696
+ // into view (owner, 2026-10-01: "the file tree does not open to it").
697
+ const scrolled: string[] = [];
698
+ const host = document.createElement('div');
699
+ host.style.overflowY = 'auto';
700
+ document.body.append(host);
701
+ host.getBoundingClientRect = () => ({ top: 0, bottom: 400 }) as DOMRect;
702
+ const props = { nodes: TREE, onSelect: () => undefined, scroll: 'host' as const };
703
+ const view = render(<FileTree {...props} selectedId={null} />, { container: host });
704
+ try {
705
+ // The tree's own box spans every row — exactly what made the old check a no-op.
706
+ (host.querySelector('.cbft-scroll') as HTMLElement).getBoundingClientRect = () =>
707
+ ({ top: 0, bottom: 2000 }) as DOMRect;
708
+ for (const row of screen.getAllByRole('treeitem') as HTMLElement[]) {
709
+ row.scrollIntoView = () => scrolled.push((row.textContent ?? '').trim());
710
+ row.getBoundingClientRect = () => ({ top: 900, bottom: 920 }) as DOMRect;
711
+ }
712
+ view.rerender(<FileTree {...props} selectedId='dinos' />);
713
+ expect(scrolled).toEqual(['Dinos']);
714
+
715
+ // …and a row the host already shows still does not jump.
716
+ for (const row of screen.getAllByRole('treeitem') as HTMLElement[])
717
+ row.getBoundingClientRect = () => ({ top: 10, bottom: 32 }) as DOMRect;
718
+ view.rerender(<FileTree {...props} selectedId='simpsons' />);
719
+ expect(scrolled).toEqual(['Dinos']);
720
+ } finally {
721
+ view.unmount();
722
+ host.remove();
723
+ }
724
+ });
676
725
  });
677
726
 
678
727
  /**
@@ -365,6 +365,13 @@ export interface FileTreeProps {
365
365
  * Wire it to whatever decides the fetch plan, never to the stored collapse.
366
366
  */
367
367
  onRevealExpand?: (ids: readonly string[]) => void;
368
+ /**
369
+ * Change it to reveal the selection AGAIN — VS Code's *Reveal in Explorer* on the file that
370
+ * is already selected. The reveal otherwise fires once per {@link selectedId}, so a "show me
371
+ * where it is" button pressed after the reader scrolled away or shut its folder did nothing.
372
+ * Any value; only a change counts. Omit it and nothing differs.
373
+ */
374
+ revealKey?: unknown;
368
375
 
369
376
  /**
370
377
  * The rows kept in a section of their own ABOVE the folders — *"pin open files where they
@@ -809,6 +816,7 @@ export function FileTree({
809
816
  onCollapsedChange,
810
817
  expandOnReveal = false,
811
818
  onRevealExpand,
819
+ revealKey,
812
820
  pinnedIds,
813
821
  onPinnedChange,
814
822
  pinnedLabel = 'Pinned',
@@ -1327,7 +1335,9 @@ export function FileTree({
1327
1335
  announceReveal.current = onRevealExpand;
1328
1336
  }, [revealShut, onRevealExpand]);
1329
1337
  /** The selection an expanding reveal has already fired for — see limit 1 below. */
1330
- const revealedFor = useRef<string | null>(null);
1338
+ const revealedFor = useRef<string | null | undefined>(null);
1339
+ /** The {@link FileTreeProps.revealKey} last honoured — a change re-arms `revealedFor`. */
1340
+ const revealedKey = useRef(revealKey);
1331
1341
 
1332
1342
  /**
1333
1343
  * Bring the selected row into view — the explorer's *reveal*.
@@ -1384,10 +1394,14 @@ export function FileTree({
1384
1394
  * expansion returns without scrolling and the re-render it causes is what lands the scroll.
1385
1395
  * What it must NOT be is the trigger for expanding again — that is `revealedFor`, below.
1386
1396
  */
1387
- // biome-ignore lint/correctness/useExhaustiveDependencies: `selectedId` is the trigger and not a read; `drag` is a guard and not a trigger; `revealOpened` is the second pass — see just above.
1397
+ // biome-ignore lint/correctness/useExhaustiveDependencies: `selectedId` and `revealKey` are the triggers; `drag` is a guard and not a trigger; `revealOpened` is the second pass — see just above.
1388
1398
  useEffect(() => {
1389
1399
  const scroller = scrollRef.current;
1390
1400
  if (!scroller || drag?.active) return;
1401
+ if (revealedKey.current !== revealKey) {
1402
+ revealedKey.current = revealKey;
1403
+ revealedFor.current = undefined;
1404
+ }
1391
1405
  /*
1392
1406
  * Once per selection, whatever it finds — the ref moves even when there is nothing shut to
1393
1407
  * open, so a later hand-shut of one of these folders cannot be undone by this effect.
@@ -1408,12 +1422,19 @@ export function FileTree({
1408
1422
  scroller.querySelector<HTMLElement>('.cbft-row[data-holds-open]');
1409
1423
  if (!row?.scrollIntoView) return;
1410
1424
  const box = row.getBoundingClientRect();
1411
- const frame = scroller.getBoundingClientRect();
1425
+ /*
1426
+ * 🔴 Under `scroll='host'` the tree's own frame is NOT what clips it: it is drawn at full
1427
+ * height, so every row is always "inside" it and this check returned before scrolling —
1428
+ * a reveal in music's rail opened the folders and lit the row eight hundred pixels below
1429
+ * the fold (owner, 2026-10-01: *"the file tree does not open to it"*). The frame that
1430
+ * decides "already visible" is the host's scroller.
1431
+ */
1432
+ const frame = (scroll === 'host' ? hostScroller(scroller) : scroller).getBoundingClientRect();
1412
1433
  if (box.top >= frame.top && box.bottom <= frame.bottom) return;
1413
1434
  // `nearest` on both axes: the least movement that makes the row visible, and no sideways
1414
1435
  // travel in a list that does not scroll sideways.
1415
1436
  row.scrollIntoView({ block: 'nearest', inline: 'nearest' });
1416
- }, [selectedId, revealOpened]);
1437
+ }, [selectedId, revealOpened, revealKey]);
1417
1438
 
1418
1439
  // ── The drag ──────────────────────────────────────────────────────────────────────────
1419
1440
 
@@ -3249,3 +3270,15 @@ function nameOf(nodes: readonly FileTreeNode[], id: string): string {
3249
3270
  }
3250
3271
  return '';
3251
3272
  }
3273
+
3274
+ /**
3275
+ * The element that actually clips a `scroll='host'` tree: its nearest ancestor that scrolls
3276
+ * vertically, or the document's scroller when nothing between here and the root does.
3277
+ */
3278
+ function hostScroller(from: HTMLElement): Element {
3279
+ for (let node = from.parentElement; node; node = node.parentElement) {
3280
+ const overflow = getComputedStyle(node).overflowY;
3281
+ if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') return node;
3282
+ }
3283
+ return document.scrollingElement ?? document.documentElement;
3284
+ }
@@ -443,7 +443,7 @@ function FilterRailRow({
443
443
  // Outlined rather than filled, so the row's own SELECTED paint stays readable
444
444
  // underneath it — a row can be both the current one and the drop target.
445
445
  item.dropActive &&
446
- 'outline outline-2 outline-dashed outline-offset-[-2px] outline-accent bg-accent/10',
446
+ 'outline outline-2 outline-dashed -outline-offset-2 outline-accent bg-accent/10',
447
447
  )}
448
448
  // A collapsed rail has no room to indent, and a 14rem-wide column has no room to
449
449
  // indent far — the step is deliberately small and it stops growing at depth 6, so a
@@ -331,7 +331,7 @@ export function DynamicIcon({ token, iconMap, className }: DynamicIconProps) {
331
331
  className={cn(
332
332
  // guardrails-ignore micro-typography-floor: 0.6em is RELATIVE to the avatar box —
333
333
  // it scales with the circle rather than sitting at a fixed sub-floor size.
334
- 'inline-flex shrink-0 items-center justify-center overflow-hidden text-[0.6em] font-semibold uppercase leading-none',
334
+ 'inline-flex shrink-0 items-center justify-center overflow-hidden text-[length:var(--text-glyph-relative)] font-semibold uppercase leading-none',
335
335
  className,
336
336
  )}
337
337
  data-icon={token}
@@ -116,6 +116,7 @@ export {
116
116
  type AmbientIntensity,
117
117
  } from './components/AmbientBackdrop.js';
118
118
  export { AppShell, type AppShellProps } from './components/AppShell.js';
119
+ export { BannerLane, type BannerLaneProps, type ShellBanner } from './components/BannerLane.js';
119
120
  export { AuthGate, type AuthGateProps, notifyUnauthorized } from './AuthGate.js';
120
121
  export { AutocompleteField, type AutocompleteProps } from './components/Autocomplete.js';
121
122
  export { AutoGrowTextarea, type AutoGrowTextareaProps } from './components/AutoGrowTextarea.js';
@@ -289,6 +290,7 @@ export {
289
290
  type TableViewMode,
290
291
  TableViewToggle,
291
292
  type DataTableHandle,
293
+ type DataTableRowAction,
292
294
  type DataTableRowProps,
293
295
  type DataTableSelectAll,
294
296
  type DataTableServerWindow,
@@ -463,10 +465,19 @@ export { OtpInput, type OtpInputProps } from './components/OtpInput.js';
463
465
  export {
464
466
  Page,
465
467
  PageContainer,
468
+ type PageContainerProps,
466
469
  PageHeader,
467
470
  type PageHeaderProps,
471
+ type PageWidth,
468
472
  ReadableColumn,
469
473
  } from './components/Page.js';
474
+ export {
475
+ GuideRoute,
476
+ type GuideRouteProps,
477
+ GuideSection,
478
+ type GuideSectionProps,
479
+ } from './components/Guide.js';
480
+ export { PageGuideButton, type PageGuideButtonProps } from './components/PageGuideButton.js';
470
481
  export { PathText, type PathTextProps } from './components/PathText.js';
471
482
  export { TruncatedText, type TruncatedTextProps } from './components/TruncatedText.js';
472
483
  export { UnstyledButton, type UnstyledButtonProps } from './components/UnstyledButton.js';
@@ -500,7 +511,7 @@ export {
500
511
  } from './components/ResponsiveWorkbench.js';
501
512
  export { RevealAction, type RevealActionProps } from './components/RevealAction.js';
502
513
  export { REVEAL_ON_HOVER } from './components/revealOnHover.js';
503
- export { ScrollArea, type ScrollAreaProps, type ScrollAreaSpace } from './components/ScrollArea.js';
514
+ export { ScrollArea, type ScrollAreaHeight, type ScrollAreaProps, type ScrollAreaSpace } from './components/ScrollArea.js';
504
515
  export { ScrollToTopButton } from './components/ScrollToTopButton.js';
505
516
  export {
506
517
  SaveIndicator,
@@ -530,7 +541,15 @@ export {
530
541
  type SelectGroup,
531
542
  type SelectOption,
532
543
  } from './components/SelectField.js';
533
- export { Skeleton, SkeletonList, type SkeletonListProps } from './components/Skeleton.js';
544
+ export {
545
+ ContentSkeleton,
546
+ Skeleton,
547
+ SkeletonChart,
548
+ SkeletonList,
549
+ type SkeletonListProps,
550
+ SkeletonTiles,
551
+ type SkeletonVariant,
552
+ } from './components/Skeleton.js';
534
553
  export {
535
554
  RangeSlider,
536
555
  type RangeSliderProps,
@@ -578,7 +597,13 @@ export {
578
597
  } from './components/SplitPane.js';
579
598
  export { Sparkline, type SparklineProps } from './components/Sparkline.js';
580
599
  export { StatStrip, type StatStripItem, type StatStripProps } from './components/StatStrip.js';
581
- export { StatTile, type StatTileProps, type StatTileTone } from './components/StatTile.js';
600
+ export {
601
+ StatTile,
602
+ type StatTileBudget,
603
+ type StatTileProps,
604
+ type StatTileTone,
605
+ type StatValueSize,
606
+ } from './components/StatTile.js';
582
607
  export {
583
608
  ThresholdMeter,
584
609
  type ThresholdMeterProps,
@@ -0,0 +1,33 @@
1
+ import type { DropdownMenuAction, DropdownMenuItem } from '../components/DropdownMenu.js';
2
+
3
+ // Kept out of `DropdownMenu.tsx` so the `./react/dropdown-menu` subpath does not export it.
4
+
5
+ /**
6
+ * OVL-7's order: the caller's sections (split at its dividers, then by `group`), and every
7
+ * destructive action pulled out into one last section, so "Delete" is never between "Rename"
8
+ * and "Duplicate" and never sits by accident under the pointer's resting place.
9
+ */
10
+ export function arrangeMenuItems(items: readonly DropdownMenuItem[]): DropdownMenuAction[][] {
11
+ const sections: DropdownMenuAction[][] = [];
12
+ const destructive: DropdownMenuAction[] = [];
13
+ let run: DropdownMenuAction[] = [];
14
+ const flush = () => {
15
+ const byGroup = new Map<string, DropdownMenuAction[]>();
16
+ for (const item of run) {
17
+ const key = item.group ?? '';
18
+ const list = byGroup.get(key);
19
+ if (list) list.push(item);
20
+ else byGroup.set(key, [item]);
21
+ }
22
+ sections.push(...byGroup.values());
23
+ run = [];
24
+ };
25
+ for (const item of items) {
26
+ if (item.divider) flush();
27
+ else if (item.destructive) destructive.push(item);
28
+ else run.push(item);
29
+ }
30
+ flush();
31
+ if (destructive.length) sections.push(destructive);
32
+ return sections.filter((section) => section.length > 0);
33
+ }
@@ -23,7 +23,7 @@ function renderInline(nodes: InlineNode[], keyPrefix: string): ReactNode[] {
23
23
  return <em key={key}>{renderInline(node.children, key)}</em>;
24
24
  case 'code':
25
25
  return (
26
- <code key={key} className='rounded bg-black/10 px-1 py-0.5 font-mono text-[0.9em] dark:bg-white/10'>
26
+ <code key={key} className='rounded bg-black/10 px-1 py-0.5 font-mono text-[length:var(--text-code-inline)] dark:bg-white/10'>
27
27
  {node.value}
28
28
  </code>
29
29
  );
@@ -67,7 +67,7 @@ function renderBlock(block: BlockNode, key: string): ReactNode {
67
67
  <pre
68
68
  // guardrails-ignore no-raw-overflow: horizontal-only scroll sized to the code
69
69
  // block's own content, not a keyboard-aware vertical page region.
70
- className='overflow-x-auto rounded-md bg-black/10 p-2 pr-9 font-mono text-[0.85em] leading-snug dark:bg-white/10'
70
+ className='overflow-x-auto rounded-md bg-black/10 p-2 pr-9 font-mono text-[length:var(--text-code-block)] leading-snug dark:bg-white/10'
71
71
  >
72
72
  <code>{block.code}</code>
73
73
  </pre>
@@ -265,8 +265,8 @@ export function HoverScrubVideoThumb({
265
265
  */}
266
266
  {!previewing && !posterFailed && video.posterUrl ? (
267
267
  <span className='pointer-events-none absolute inset-0 flex items-center justify-center'>
268
- <span className='flex size-9 items-center justify-center rounded-full bg-black/55 text-white shadow-sm backdrop-blur-[2px]'>
269
- <Play aria-hidden className='size-4 translate-x-[1px]' />
268
+ <span className='flex size-9 items-center justify-center rounded-full bg-black/55 text-white shadow-sm backdrop-blur-xs'>
269
+ <Play aria-hidden className='size-4 translate-x-px' />
270
270
  </span>
271
271
  </span>
272
272
  ) : null}
@@ -687,7 +687,7 @@ export function MaskPainter({
687
687
  <Modal
688
688
  open={open}
689
689
  onClose={onClose}
690
- size='xl'
690
+ size='lg'
691
691
  title='Paint mask'
692
692
  scrollBody={false}
693
693
  // guardrails-ignore no-raw-modal-footer: wraps a toolbar row above the actual ActionBar
@@ -97,7 +97,7 @@ export function MediaUploadControl({
97
97
  placeholder='tags, comma,separated'
98
98
  spellCheck={false}
99
99
  disabled={busy}
100
- className='max-w-[200px]'
100
+ className='max-w-50'
101
101
  aria-label='Upload tags'
102
102
  />
103
103
  <Button
@@ -173,7 +173,7 @@ export function VideoTrimmer({
173
173
  <video
174
174
  ref={videoRef}
175
175
  src={src}
176
- className='mx-auto max-h-[48vh] w-full bg-black'
176
+ className='mx-auto max-h-[var(--media-max-h)] w-full bg-black'
177
177
  playsInline
178
178
  preload='metadata'
179
179
  crossOrigin='anonymous'
@@ -32,7 +32,11 @@
32
32
  .cbgd-search {
33
33
  margin-left: auto;
34
34
  width: min(360px, 50%);
35
- padding: 7px 12px;
35
+ /* The order pills' 28px, so the header row is one control height (FND-4); the phone rule
36
+ * below raises both to 44px together. */
37
+ box-sizing: border-box;
38
+ height: 28px;
39
+ padding: 0 12px;
36
40
  border-radius: 18px;
37
41
  border: 1px solid var(--border);
38
42
  background: var(--muted);
@@ -116,7 +116,7 @@ export function NamespaceTargetCapsule({
116
116
  data-testid="namespace-target-capsule"
117
117
  >
118
118
  <span aria-hidden className={cn('inline-block size-2.5 shrink-0 rounded-full', dot.className)} style={dot.style} />
119
- <span className="max-w-[10rem] truncate">{selected?.label ?? 'General'}</span>
119
+ <span className="max-w-40 truncate">{selected?.label ?? 'General'}</span>
120
120
  <ChevronDown className="size-3 shrink-0 opacity-60" />
121
121
  </Button>
122
122
  }
@@ -500,7 +500,7 @@ const Crumb = memo(function Crumb({
500
500
  typeof node.label === 'string' ? (
501
501
  <TruncatedText
502
502
  as='span'
503
- className={cn(isLeaf ? 'max-w-[20rem]' : 'max-w-[12rem]', hideLabel && 'hidden')}
503
+ className={cn(isLeaf ? 'max-w-80' : 'max-w-48', hideLabel && 'hidden')}
504
504
  {...(isRoot ? { 'data-cb-crumb-rootlabel': '' } : {})}
505
505
  >
506
506
  {node.label}
@@ -520,7 +520,7 @@ const Crumb = memo(function Crumb({
520
520
  <span
521
521
  className={cn(
522
522
  'inline-flex min-w-0 items-center [&>*]:min-w-0',
523
- isLeaf ? 'max-w-[20rem]' : 'max-w-[12rem]',
523
+ isLeaf ? 'max-w-80' : 'max-w-48',
524
524
  hideLabel && 'hidden',
525
525
  )}
526
526
  >
@@ -30,6 +30,12 @@ export interface CommandBarProps {
30
30
  * `PlaceBar` owns capture via its raised center FAB, so capture isn't duplicated.
31
31
  */
32
32
  captureDesktopOnly?: boolean;
33
+ /**
34
+ * The command trigger as a square ⌘K button instead of a field — for a header whose
35
+ * center zone holds the places (a 2–5-place `AppShell`), where the trigger sits in the
36
+ * locked right zone and must not compete with them for width.
37
+ */
38
+ compact?: boolean;
33
39
  className?: string;
34
40
  }
35
41
 
@@ -52,6 +58,7 @@ export function CommandBar({
52
58
  commandHint = '⌘K',
53
59
  extra,
54
60
  captureDesktopOnly = false,
61
+ compact = false,
55
62
  className,
56
63
  }: CommandBarProps) {
57
64
  return (
@@ -63,6 +70,8 @@ export function CommandBar({
63
70
  data-cb-command-trigger=''
64
71
  onClick={onOpenCommand}
65
72
  aria-keyshortcuts='Meta+K Control+K'
73
+ // The square trigger paints no words, so it is named by them.
74
+ aria-label={compact ? commandPlaceholder : undefined}
66
75
  leftIcon={<Search className='size-4 shrink-0' aria-hidden='true' />}
67
76
  className={cn(
68
77
  'group h-10 min-w-0 flex-1 justify-start gap-2 rounded-lg border border-border bg-surface px-3 font-normal text-muted-foreground hover:border-foreground/20',
@@ -72,16 +81,18 @@ export function CommandBar({
72
81
  // `pointer-coarse:min-w-11` alongside it: the collapsed `w-10` square is
73
82
  // a mouse-fine 40px, short of the 44px touch floor on a coarse pointer
74
83
  // (owner orch-host 390px teardown — measured 40×44).
75
- 'max-sm:w-10 max-sm:flex-none max-sm:justify-center max-sm:px-0 pointer-coarse:min-w-11',
84
+ compact
85
+ ? 'w-10 flex-none justify-center px-0 pointer-coarse:min-w-11'
86
+ : 'max-sm:w-10 max-sm:flex-none max-sm:justify-center max-sm:px-0 pointer-coarse:min-w-11',
76
87
  )}
77
88
  >
78
89
  {/* Below sm the field can be squeezed by spine meta (badges/pills) — a
79
90
  truncated placeholder fragment ("S..") reads broken, so the text
80
91
  yields entirely and the trigger collapses to the icon button above. */}
81
- <span className='hidden min-w-0 flex-1 truncate text-left text-sm sm:inline'>
92
+ <span className={cn('hidden min-w-0 flex-1 truncate text-left text-sm', !compact && 'sm:inline')}>
82
93
  {commandPlaceholder}
83
94
  </span>
84
- {commandHint != null && (
95
+ {commandHint != null && !compact && (
85
96
  <kbd className='hidden shrink-0 items-center rounded border border-border bg-background px-1.5 py-0.5 font-sans text-xs text-muted-foreground sm:inline-flex'>
86
97
  {commandHint}
87
98
  </kbd>