@nadicodeai/ui 12.1.102 → 12.1.104

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 (562) hide show
  1. package/dist/components/accordion.d.ts +38 -12
  2. package/dist/components/accordion.d.ts.map +1 -1
  3. package/dist/components/accordion.js +36 -15
  4. package/dist/components/account-menu.js +2 -2
  5. package/dist/components/action-menu.d.ts +20 -19
  6. package/dist/components/action-menu.d.ts.map +1 -1
  7. package/dist/components/action-menu.js +22 -15
  8. package/dist/components/action-status.d.ts +14 -10
  9. package/dist/components/action-status.d.ts.map +1 -1
  10. package/dist/components/action-status.js +14 -10
  11. package/dist/components/activity-calendar.d.ts +3 -1
  12. package/dist/components/activity-calendar.d.ts.map +1 -1
  13. package/dist/components/activity-calendar.js +16 -2
  14. package/dist/components/activity-feed.d.ts +2 -2
  15. package/dist/components/activity-feed.d.ts.map +1 -1
  16. package/dist/components/activity-feed.js +14 -5
  17. package/dist/components/agent-card.d.ts +11 -5
  18. package/dist/components/agent-card.d.ts.map +1 -1
  19. package/dist/components/agent-card.js +13 -7
  20. package/dist/components/agent-list-row.js +1 -1
  21. package/dist/components/agent-orb-appearance.d.ts +7 -1
  22. package/dist/components/agent-orb-appearance.d.ts.map +1 -1
  23. package/dist/components/agent-orb-appearance.js +26 -0
  24. package/dist/components/agent-profile.d.ts +8 -7
  25. package/dist/components/agent-profile.d.ts.map +1 -1
  26. package/dist/components/agent-profile.js +6 -6
  27. package/dist/components/alert-dialog.d.ts +25 -16
  28. package/dist/components/alert-dialog.d.ts.map +1 -1
  29. package/dist/components/alert-dialog.js +30 -18
  30. package/dist/components/alert.d.ts +1 -1
  31. package/dist/components/avatar.d.ts +83 -17
  32. package/dist/components/avatar.d.ts.map +1 -1
  33. package/dist/components/avatar.js +89 -23
  34. package/dist/components/badge.d.ts +59 -8
  35. package/dist/components/badge.d.ts.map +1 -1
  36. package/dist/components/badge.js +57 -14
  37. package/dist/components/breadcrumb.d.ts +18 -7
  38. package/dist/components/breadcrumb.d.ts.map +1 -1
  39. package/dist/components/breadcrumb.js +37 -13
  40. package/dist/components/button-group.d.ts +12 -15
  41. package/dist/components/button-group.d.ts.map +1 -1
  42. package/dist/components/button-group.js +13 -17
  43. package/dist/components/button.d.ts +126 -23
  44. package/dist/components/button.d.ts.map +1 -1
  45. package/dist/components/button.js +164 -39
  46. package/dist/components/calendar.d.ts +26 -15
  47. package/dist/components/calendar.d.ts.map +1 -1
  48. package/dist/components/calendar.js +60 -46
  49. package/dist/components/card-row.d.ts +13 -5
  50. package/dist/components/card-row.d.ts.map +1 -1
  51. package/dist/components/card-row.js +24 -10
  52. package/dist/components/card.d.ts +6 -12
  53. package/dist/components/card.d.ts.map +1 -1
  54. package/dist/components/card.js +11 -16
  55. package/dist/components/carousel.d.ts +3 -3
  56. package/dist/components/carousel.d.ts.map +1 -1
  57. package/dist/components/carousel.js +7 -7
  58. package/dist/components/catalog-drawer.d.ts +7 -7
  59. package/dist/components/catalog-drawer.d.ts.map +1 -1
  60. package/dist/components/catalog-drawer.js +6 -6
  61. package/dist/components/chart-area-stacked.d.ts +1 -1
  62. package/dist/components/chart-area-stacked.d.ts.map +1 -1
  63. package/dist/components/chart-area-stacked.js +4 -4
  64. package/dist/components/chart-axis.d.ts +14 -1
  65. package/dist/components/chart-axis.d.ts.map +1 -1
  66. package/dist/components/chart-axis.js +11 -1
  67. package/dist/components/chart-bar-horizontal.d.ts +2 -2
  68. package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
  69. package/dist/components/chart-bar-horizontal.js +14 -5
  70. package/dist/components/chart-bar-multiple.d.ts +1 -1
  71. package/dist/components/chart-bar-multiple.d.ts.map +1 -1
  72. package/dist/components/chart-bar-multiple.js +3 -3
  73. package/dist/components/chart-bar-stacked.d.ts +1 -1
  74. package/dist/components/chart-bar-stacked.d.ts.map +1 -1
  75. package/dist/components/chart-bar-stacked.js +3 -3
  76. package/dist/components/chart-card.d.ts +17 -6
  77. package/dist/components/chart-card.d.ts.map +1 -1
  78. package/dist/components/chart-card.js +11 -4
  79. package/dist/components/chart-date-range-control.d.ts +18 -9
  80. package/dist/components/chart-date-range-control.d.ts.map +1 -1
  81. package/dist/components/chart-date-range-control.js +43 -47
  82. package/dist/components/chart-sparkline.d.ts +4 -3
  83. package/dist/components/chart-sparkline.d.ts.map +1 -1
  84. package/dist/components/chart-sparkline.js +6 -5
  85. package/dist/components/check-counts.d.ts +44 -0
  86. package/dist/components/check-counts.d.ts.map +1 -0
  87. package/dist/components/check-counts.js +51 -0
  88. package/dist/components/checkbox.d.ts +39 -11
  89. package/dist/components/checkbox.d.ts.map +1 -1
  90. package/dist/components/checkbox.js +38 -11
  91. package/dist/components/choicebox.d.ts +96 -0
  92. package/dist/components/choicebox.d.ts.map +1 -0
  93. package/dist/components/choicebox.js +113 -0
  94. package/dist/components/clearable-input.d.ts +57 -0
  95. package/dist/components/clearable-input.d.ts.map +1 -0
  96. package/dist/components/clearable-input.js +58 -0
  97. package/dist/components/code-block.d.ts +77 -17
  98. package/dist/components/code-block.d.ts.map +1 -1
  99. package/dist/components/code-block.js +85 -15
  100. package/dist/components/collapsible.d.ts +27 -10
  101. package/dist/components/collapsible.d.ts.map +1 -1
  102. package/dist/components/collapsible.js +24 -9
  103. package/dist/components/collection-filters.d.ts +3 -1
  104. package/dist/components/collection-filters.d.ts.map +1 -1
  105. package/dist/components/collection-filters.js +7 -9
  106. package/dist/components/collection-page.d.ts +31 -10
  107. package/dist/components/collection-page.d.ts.map +1 -1
  108. package/dist/components/collection-page.js +14 -13
  109. package/dist/components/collection-search.d.ts +32 -10
  110. package/dist/components/collection-search.d.ts.map +1 -1
  111. package/dist/components/collection-search.js +24 -13
  112. package/dist/components/collection-sort.d.ts.map +1 -1
  113. package/dist/components/collection-sort.js +2 -2
  114. package/dist/components/collection-toolbar.d.ts +5 -2
  115. package/dist/components/collection-toolbar.d.ts.map +1 -1
  116. package/dist/components/collection-toolbar.js +7 -4
  117. package/dist/components/combobox.d.ts +97 -22
  118. package/dist/components/combobox.d.ts.map +1 -1
  119. package/dist/components/combobox.js +80 -28
  120. package/dist/components/command.d.ts +34 -21
  121. package/dist/components/command.d.ts.map +1 -1
  122. package/dist/components/command.js +33 -25
  123. package/dist/components/confirm-dialog.d.ts +23 -6
  124. package/dist/components/confirm-dialog.d.ts.map +1 -1
  125. package/dist/components/confirm-dialog.js +32 -13
  126. package/dist/components/context-menu.d.ts +14 -10
  127. package/dist/components/context-menu.d.ts.map +1 -1
  128. package/dist/components/context-menu.js +17 -12
  129. package/dist/components/copy-button.d.ts +5 -2
  130. package/dist/components/copy-button.d.ts.map +1 -1
  131. package/dist/components/copy-button.js +16 -8
  132. package/dist/components/data-table.d.ts +120 -54
  133. package/dist/components/data-table.d.ts.map +1 -1
  134. package/dist/components/data-table.js +163 -92
  135. package/dist/components/desktop-shell.d.ts +4 -2
  136. package/dist/components/desktop-shell.d.ts.map +1 -1
  137. package/dist/components/desktop-shell.js +3 -3
  138. package/dist/components/dialog.d.ts +63 -24
  139. package/dist/components/dialog.d.ts.map +1 -1
  140. package/dist/components/dialog.js +52 -31
  141. package/dist/components/disclosure-row.d.ts +1 -2
  142. package/dist/components/disclosure-row.d.ts.map +1 -1
  143. package/dist/components/disclosure-row.js +1 -2
  144. package/dist/components/disclosure.d.ts +1 -1
  145. package/dist/components/disclosure.js +1 -1
  146. package/dist/components/drawer.d.ts +33 -12
  147. package/dist/components/drawer.d.ts.map +1 -1
  148. package/dist/components/drawer.js +47 -35
  149. package/dist/components/dropdown-menu.d.ts +59 -14
  150. package/dist/components/dropdown-menu.d.ts.map +1 -1
  151. package/dist/components/dropdown-menu.js +58 -26
  152. package/dist/components/empty-state.d.ts +35 -12
  153. package/dist/components/empty-state.d.ts.map +1 -1
  154. package/dist/components/empty-state.js +35 -17
  155. package/dist/components/entry-scene.d.ts +4 -4
  156. package/dist/components/entry-scene.d.ts.map +1 -1
  157. package/dist/components/entry-scene.js +2 -2
  158. package/dist/components/field.d.ts +44 -14
  159. package/dist/components/field.d.ts.map +1 -1
  160. package/dist/components/field.js +49 -20
  161. package/dist/components/file-diff.d.ts.map +1 -1
  162. package/dist/components/file-diff.js +3 -4
  163. package/dist/components/form-dialog.d.ts +7 -7
  164. package/dist/components/form-dialog.d.ts.map +1 -1
  165. package/dist/components/form-dialog.js +13 -11
  166. package/dist/components/form-drawer.d.ts +10 -7
  167. package/dist/components/form-drawer.d.ts.map +1 -1
  168. package/dist/components/form-drawer.js +11 -10
  169. package/dist/components/gauge.d.ts +64 -0
  170. package/dist/components/gauge.d.ts.map +1 -0
  171. package/dist/components/gauge.js +73 -0
  172. package/dist/components/hover-card.d.ts +72 -14
  173. package/dist/components/hover-card.d.ts.map +1 -1
  174. package/dist/components/hover-card.js +51 -17
  175. package/dist/components/identity-mark.d.ts +8 -1
  176. package/dist/components/identity-mark.d.ts.map +1 -1
  177. package/dist/components/identity-mark.js +31 -5
  178. package/dist/components/input-group.d.ts +44 -21
  179. package/dist/components/input-group.d.ts.map +1 -1
  180. package/dist/components/input-group.js +74 -27
  181. package/dist/components/input.d.ts +64 -12
  182. package/dist/components/input.d.ts.map +1 -1
  183. package/dist/components/input.js +51 -15
  184. package/dist/components/item.d.ts +37 -15
  185. package/dist/components/item.d.ts.map +1 -1
  186. package/dist/components/item.js +41 -22
  187. package/dist/components/kbd.d.ts +49 -13
  188. package/dist/components/kbd.d.ts.map +1 -1
  189. package/dist/components/kbd.js +115 -16
  190. package/dist/components/kpi-card.d.ts +12 -4
  191. package/dist/components/kpi-card.d.ts.map +1 -1
  192. package/dist/components/kpi-card.js +13 -4
  193. package/dist/components/label.d.ts +17 -10
  194. package/dist/components/label.d.ts.map +1 -1
  195. package/dist/components/label.js +18 -11
  196. package/dist/components/library-shelf.d.ts +6 -6
  197. package/dist/components/library-shelf.d.ts.map +1 -1
  198. package/dist/components/library-shelf.js +5 -5
  199. package/dist/components/load-more-button.d.ts +35 -0
  200. package/dist/components/load-more-button.d.ts.map +1 -0
  201. package/dist/components/load-more-button.js +26 -0
  202. package/dist/components/message-notice.d.ts +8 -13
  203. package/dist/components/message-notice.d.ts.map +1 -1
  204. package/dist/components/message-notice.js +25 -22
  205. package/dist/components/middle-truncate.d.ts +33 -0
  206. package/dist/components/middle-truncate.d.ts.map +1 -0
  207. package/dist/components/middle-truncate.js +72 -0
  208. package/dist/components/multi-select.d.ts +94 -0
  209. package/dist/components/multi-select.d.ts.map +1 -0
  210. package/dist/components/multi-select.js +132 -0
  211. package/dist/components/native-select.d.ts +37 -13
  212. package/dist/components/native-select.d.ts.map +1 -1
  213. package/dist/components/native-select.js +27 -11
  214. package/dist/components/notice-banner.d.ts +17 -10
  215. package/dist/components/notice-banner.d.ts.map +1 -1
  216. package/dist/components/notice-banner.js +12 -11
  217. package/dist/components/numbered-steps.d.ts +10 -4
  218. package/dist/components/numbered-steps.d.ts.map +1 -1
  219. package/dist/components/numbered-steps.js +9 -7
  220. package/dist/components/object-page.d.ts +40 -14
  221. package/dist/components/object-page.d.ts.map +1 -1
  222. package/dist/components/object-page.js +12 -10
  223. package/dist/components/object-workspace.d.ts +29 -10
  224. package/dist/components/object-workspace.d.ts.map +1 -1
  225. package/dist/components/object-workspace.js +18 -8
  226. package/dist/components/overview-page.d.ts +2 -2
  227. package/dist/components/overview-page.d.ts.map +1 -1
  228. package/dist/components/overview-page.js +8 -7
  229. package/dist/components/page-actions.d.ts +28 -8
  230. package/dist/components/page-actions.d.ts.map +1 -1
  231. package/dist/components/page-actions.js +22 -25
  232. package/dist/components/page-header.d.ts +11 -4
  233. package/dist/components/page-header.d.ts.map +1 -1
  234. package/dist/components/page-header.js +10 -5
  235. package/dist/components/pending-label.d.ts +6 -5
  236. package/dist/components/pending-label.d.ts.map +1 -1
  237. package/dist/components/pending-label.js +14 -6
  238. package/dist/components/picture-label.d.ts +2 -2
  239. package/dist/components/picture-label.d.ts.map +1 -1
  240. package/dist/components/picture-label.js +3 -3
  241. package/dist/components/portal-sidebar-frame.d.ts +9 -21
  242. package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
  243. package/dist/components/portal-sidebar-frame.js +13 -27
  244. package/dist/components/progress-checklist.d.ts +46 -0
  245. package/dist/components/progress-checklist.d.ts.map +1 -0
  246. package/dist/components/progress-checklist.js +46 -0
  247. package/dist/components/progress.d.ts +48 -8
  248. package/dist/components/progress.d.ts.map +1 -1
  249. package/dist/components/progress.js +92 -16
  250. package/dist/components/prose.d.ts +19 -0
  251. package/dist/components/prose.d.ts.map +1 -0
  252. package/dist/components/prose.js +29 -0
  253. package/dist/components/radio-group.d.ts +51 -12
  254. package/dist/components/radio-group.d.ts.map +1 -1
  255. package/dist/components/radio-group.js +42 -12
  256. package/dist/components/reading-column.js +1 -1
  257. package/dist/components/record-identity.d.ts +6 -5
  258. package/dist/components/record-identity.d.ts.map +1 -1
  259. package/dist/components/record-identity.js +12 -3
  260. package/dist/components/record-list.d.ts +117 -27
  261. package/dist/components/record-list.d.ts.map +1 -1
  262. package/dist/components/record-list.js +185 -55
  263. package/dist/components/record-time.d.ts +20 -7
  264. package/dist/components/record-time.d.ts.map +1 -1
  265. package/dist/components/record-time.js +38 -19
  266. package/dist/components/resizable.d.ts +7 -5
  267. package/dist/components/resizable.d.ts.map +1 -1
  268. package/dist/components/resizable.js +6 -6
  269. package/dist/components/scope-switcher.d.ts +2 -0
  270. package/dist/components/scope-switcher.d.ts.map +1 -1
  271. package/dist/components/scope-switcher.js +2 -2
  272. package/dist/components/scroll-area.d.ts +47 -11
  273. package/dist/components/scroll-area.d.ts.map +1 -1
  274. package/dist/components/scroll-area.js +72 -14
  275. package/dist/components/segmented-control.d.ts +82 -0
  276. package/dist/components/segmented-control.d.ts.map +1 -0
  277. package/dist/components/segmented-control.js +90 -0
  278. package/dist/components/select.d.ts +55 -15
  279. package/dist/components/select.d.ts.map +1 -1
  280. package/dist/components/select.js +62 -19
  281. package/dist/components/separator.d.ts +12 -5
  282. package/dist/components/separator.d.ts.map +1 -1
  283. package/dist/components/separator.js +11 -6
  284. package/dist/components/settings-facts.d.ts +34 -14
  285. package/dist/components/settings-facts.d.ts.map +1 -1
  286. package/dist/components/settings-facts.js +21 -12
  287. package/dist/components/settings-page.d.ts +4 -4
  288. package/dist/components/settings-page.js +5 -5
  289. package/dist/components/settings-section.d.ts +160 -34
  290. package/dist/components/settings-section.d.ts.map +1 -1
  291. package/dist/components/settings-section.js +92 -39
  292. package/dist/components/sheet.d.ts +47 -16
  293. package/dist/components/sheet.d.ts.map +1 -1
  294. package/dist/components/sheet.js +40 -19
  295. package/dist/components/sidebar-sections.d.ts +16 -12
  296. package/dist/components/sidebar-sections.d.ts.map +1 -1
  297. package/dist/components/sidebar-sections.js +30 -15
  298. package/dist/components/sidebar.d.ts +117 -21
  299. package/dist/components/sidebar.d.ts.map +1 -1
  300. package/dist/components/sidebar.js +180 -55
  301. package/dist/components/skeleton.d.ts +54 -8
  302. package/dist/components/skeleton.d.ts.map +1 -1
  303. package/dist/components/skeleton.js +44 -9
  304. package/dist/components/slider.d.ts +53 -11
  305. package/dist/components/slider.d.ts.map +1 -1
  306. package/dist/components/slider.js +71 -17
  307. package/dist/components/snippet.d.ts +57 -0
  308. package/dist/components/snippet.d.ts.map +1 -0
  309. package/dist/components/snippet.js +60 -0
  310. package/dist/components/sonner.d.ts +13 -14
  311. package/dist/components/sonner.d.ts.map +1 -1
  312. package/dist/components/sonner.js +25 -22
  313. package/dist/components/status-badge.d.ts +37 -11
  314. package/dist/components/status-badge.d.ts.map +1 -1
  315. package/dist/components/status-badge.js +63 -15
  316. package/dist/components/status-dot.d.ts +42 -11
  317. package/dist/components/status-dot.d.ts.map +1 -1
  318. package/dist/components/status-dot.js +40 -11
  319. package/dist/components/switch.d.ts +43 -12
  320. package/dist/components/switch.d.ts.map +1 -1
  321. package/dist/components/switch.js +42 -12
  322. package/dist/components/table-card.d.ts +21 -12
  323. package/dist/components/table-card.d.ts.map +1 -1
  324. package/dist/components/table-card.js +17 -9
  325. package/dist/components/table-layouts.d.ts +40 -8
  326. package/dist/components/table-layouts.d.ts.map +1 -1
  327. package/dist/components/table-layouts.js +52 -8
  328. package/dist/components/table-value.d.ts +4 -3
  329. package/dist/components/table-value.d.ts.map +1 -1
  330. package/dist/components/table-value.js +6 -5
  331. package/dist/components/table.d.ts +62 -25
  332. package/dist/components/table.d.ts.map +1 -1
  333. package/dist/components/table.js +62 -26
  334. package/dist/components/tabs.d.ts +86 -17
  335. package/dist/components/tabs.d.ts.map +1 -1
  336. package/dist/components/tabs.js +93 -22
  337. package/dist/components/text-link.d.ts +4 -1
  338. package/dist/components/text-link.d.ts.map +1 -1
  339. package/dist/components/text-link.js +4 -1
  340. package/dist/components/text-with-copy-button.d.ts +30 -0
  341. package/dist/components/text-with-copy-button.d.ts.map +1 -0
  342. package/dist/components/text-with-copy-button.js +32 -0
  343. package/dist/components/textarea.d.ts +40 -10
  344. package/dist/components/textarea.d.ts.map +1 -1
  345. package/dist/components/textarea.js +50 -11
  346. package/dist/components/theme-mode-switcher.d.ts +18 -1
  347. package/dist/components/theme-mode-switcher.d.ts.map +1 -1
  348. package/dist/components/theme-mode-switcher.js +20 -2
  349. package/dist/components/toggle-group.d.ts +28 -8
  350. package/dist/components/toggle-group.d.ts.map +1 -1
  351. package/dist/components/toggle-group.js +12 -6
  352. package/dist/components/toggle.d.ts +6 -3
  353. package/dist/components/toggle.d.ts.map +1 -1
  354. package/dist/components/toggle.js +10 -7
  355. package/dist/components/tooltip.d.ts +43 -12
  356. package/dist/components/tooltip.d.ts.map +1 -1
  357. package/dist/components/tooltip.js +45 -16
  358. package/dist/components/trend-badge.js +1 -1
  359. package/dist/components/update-card.js +1 -1
  360. package/dist/eslint/index.js +82 -0
  361. package/dist/eslint/rules/badge-is-static-label.js +93 -0
  362. package/dist/eslint/rules/button-icon-slot.js +102 -0
  363. package/dist/eslint/rules/button-link-for-navigation.js +146 -0
  364. package/dist/eslint/rules/button-no-aria-label-with-text.js +75 -0
  365. package/dist/eslint/rules/button-type-roles-only-in-buttons.js +83 -0
  366. package/dist/eslint/rules/choice-control-has-a-name.js +98 -0
  367. package/dist/eslint/rules/choice-group-in-fieldset.js +86 -0
  368. package/dist/eslint/rules/command-shortcut-single-owner.js +118 -0
  369. package/dist/eslint/rules/confirm-dialog-words.js +63 -0
  370. package/dist/eslint/rules/data-table-one-unsized-column.js +96 -0
  371. package/dist/eslint/rules/destructive-action-placement.js +69 -0
  372. package/dist/eslint/rules/disabled-choice-says-why.js +71 -0
  373. package/dist/eslint/rules/ellipsis-opens-a-dialog.js +110 -0
  374. package/dist/eslint/rules/input-group-owners.js +155 -0
  375. package/dist/eslint/rules/kbd-children-no-modifier-text.js +128 -0
  376. package/dist/eslint/rules/literal-text.js +41 -0
  377. package/dist/eslint/rules/middle-truncate-placement.js +69 -0
  378. package/dist/eslint/rules/no-bare-button-label.js +55 -0
  379. package/dist/eslint/rules/no-control-in-read-only-surface.js +106 -0
  380. package/dist/eslint/rules/no-hand-built-busy.js +104 -0
  381. package/dist/eslint/rules/no-hand-built-theme-picker.js +144 -0
  382. package/dist/eslint/rules/no-hand-built-tile.js +41 -0
  383. package/dist/eslint/rules/no-hand-formatted-date.js +87 -0
  384. package/dist/eslint/rules/no-hand-stacked-avatars.js +67 -0
  385. package/dist/eslint/rules/no-nested-collapse.js +60 -0
  386. package/dist/eslint/rules/no-search-in-form.js +47 -0
  387. package/dist/eslint/rules/no-shadcn-appearance-override.js +2 -16
  388. package/dist/eslint/rules/no-shell-prompt-in-snippet.js +74 -0
  389. package/dist/eslint/rules/no-stock-error-words.js +56 -0
  390. package/dist/eslint/rules/no-tooltip-around-labelled-field.js +72 -0
  391. package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +57 -0
  392. package/dist/eslint/rules/one-submenu-level.js +43 -0
  393. package/dist/eslint/rules/one-toast-per-flow.js +91 -0
  394. package/dist/eslint/rules/option-count.js +167 -0
  395. package/dist/eslint/rules/page-command-link-not-render.js +43 -0
  396. package/dist/eslint/rules/progress-needs-name.js +57 -0
  397. package/dist/eslint/rules/settings-limit-in-footer.js +94 -0
  398. package/dist/eslint/rules/skeleton-in-region.js +80 -0
  399. package/dist/eslint/rules/sortable-heading-uses-sort.js +79 -0
  400. package/dist/eslint/rules/table-cell-inset-owner.js +107 -0
  401. package/dist/eslint/rules/tabs-selection-is-controlled.js +47 -0
  402. package/dist/eslint/rules/tooltip-only-arrow.js +38 -0
  403. package/dist/eslint/rules/tooltip-trigger-accessible-name.js +114 -0
  404. package/dist/eslint/strict-design-system.js +21 -7
  405. package/dist/index.d.ts +13 -13
  406. package/dist/index.d.ts.map +1 -1
  407. package/dist/index.js +12 -13
  408. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
  409. package/dist/internal/assistant-ui/attachment.js +2 -2
  410. package/dist/internal/assistant-ui/reasoning.d.ts +1 -1
  411. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
  412. package/dist/internal/assistant-ui/tool-fallback.js +1 -1
  413. package/dist/internal/assistant-ui/tool-group.d.ts +1 -1
  414. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
  415. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +2 -3
  416. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -1
  417. package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
  418. package/dist/internal/catalog-list.js +2 -2
  419. package/dist/internal/collection-note.d.ts +23 -0
  420. package/dist/internal/collection-note.d.ts.map +1 -0
  421. package/dist/internal/collection-note.js +17 -0
  422. package/dist/internal/collection-rail.d.ts +57 -0
  423. package/dist/internal/collection-rail.d.ts.map +1 -0
  424. package/dist/internal/collection-rail.js +33 -0
  425. package/dist/internal/company-logo.d.ts +18 -0
  426. package/dist/internal/company-logo.d.ts.map +1 -0
  427. package/dist/internal/company-logo.js +14 -0
  428. package/dist/internal/control-name.d.ts +12 -0
  429. package/dist/internal/control-name.d.ts.map +1 -0
  430. package/dist/internal/control-name.js +1 -0
  431. package/dist/internal/diff-line.d.ts +9 -0
  432. package/dist/internal/diff-line.d.ts.map +1 -0
  433. package/dist/internal/diff-line.js +8 -0
  434. package/dist/internal/empty.d.ts +8 -4
  435. package/dist/internal/empty.d.ts.map +1 -1
  436. package/dist/internal/empty.js +14 -8
  437. package/dist/internal/field-frame.d.ts +33 -0
  438. package/dist/internal/field-frame.d.ts.map +1 -0
  439. package/dist/internal/field-frame.js +20 -0
  440. package/dist/internal/final-focus.d.ts +8 -0
  441. package/dist/internal/final-focus.d.ts.map +1 -0
  442. package/dist/internal/final-focus.js +10 -0
  443. package/dist/internal/footer-strip.d.ts.map +1 -1
  444. package/dist/internal/footer-strip.js +3 -1
  445. package/dist/internal/form-submit.d.ts +9 -5
  446. package/dist/internal/form-submit.d.ts.map +1 -1
  447. package/dist/internal/form-submit.js +31 -2
  448. package/dist/internal/input-box.d.ts +26 -0
  449. package/dist/internal/input-box.d.ts.map +1 -0
  450. package/dist/internal/input-box.js +59 -0
  451. package/dist/internal/menu-surface.d.ts +10 -3
  452. package/dist/internal/menu-surface.d.ts.map +1 -1
  453. package/dist/internal/menu-surface.js +10 -3
  454. package/dist/internal/notice.d.ts +25 -0
  455. package/dist/internal/notice.d.ts.map +1 -0
  456. package/dist/internal/notice.js +33 -0
  457. package/dist/internal/overlay-stem.d.ts +5 -0
  458. package/dist/internal/overlay-stem.d.ts.map +1 -0
  459. package/dist/internal/overlay-stem.js +7 -0
  460. package/dist/internal/phone-sheet.d.ts +4 -0
  461. package/dist/internal/phone-sheet.d.ts.map +1 -0
  462. package/dist/internal/phone-sheet.js +2 -0
  463. package/dist/internal/present-content.d.ts +3 -0
  464. package/dist/internal/present-content.d.ts.map +1 -0
  465. package/dist/internal/present-content.js +1 -0
  466. package/dist/internal/record-menu-items.d.ts +4 -3
  467. package/dist/internal/record-menu-items.d.ts.map +1 -1
  468. package/dist/internal/record-menu-items.js +21 -6
  469. package/dist/internal/settings-save.d.ts +9 -2
  470. package/dist/internal/settings-save.d.ts.map +1 -1
  471. package/dist/internal/settings-save.js +19 -6
  472. package/dist/internal/table-compact-line.d.ts +38 -0
  473. package/dist/internal/table-compact-line.d.ts.map +1 -0
  474. package/dist/internal/table-compact-line.js +35 -0
  475. package/dist/internal/title-when-cut.d.ts +8 -0
  476. package/dist/internal/title-when-cut.d.ts.map +1 -0
  477. package/dist/internal/title-when-cut.js +22 -0
  478. package/dist/internal/unsaved-guard.d.ts +18 -0
  479. package/dist/internal/unsaved-guard.d.ts.map +1 -0
  480. package/dist/internal/unsaved-guard.js +31 -0
  481. package/dist/lib/merge-tokens.generated.js +2 -2
  482. package/dist/showcase/foundations.d.ts.map +1 -1
  483. package/dist/showcase/foundations.js +10 -2
  484. package/dist/showcase/specimens/actions.d.ts +2 -0
  485. package/dist/showcase/specimens/actions.d.ts.map +1 -1
  486. package/dist/showcase/specimens/actions.js +30 -5
  487. package/dist/showcase/specimens/charts.d.ts.map +1 -1
  488. package/dist/showcase/specimens/charts.js +22 -13
  489. package/dist/showcase/specimens/choices.d.ts +14 -3
  490. package/dist/showcase/specimens/choices.d.ts.map +1 -1
  491. package/dist/showcase/specimens/choices.js +93 -13
  492. package/dist/showcase/specimens/compositions.d.ts.map +1 -1
  493. package/dist/showcase/specimens/compositions.js +136 -23
  494. package/dist/showcase/specimens/data.d.ts +12 -7
  495. package/dist/showcase/specimens/data.d.ts.map +1 -1
  496. package/dist/showcase/specimens/data.js +139 -35
  497. package/dist/showcase/specimens/feedback.d.ts +2 -0
  498. package/dist/showcase/specimens/feedback.d.ts.map +1 -1
  499. package/dist/showcase/specimens/feedback.js +39 -15
  500. package/dist/showcase/specimens/index.d.ts +20 -12
  501. package/dist/showcase/specimens/index.d.ts.map +1 -1
  502. package/dist/showcase/specimens/inputs.d.ts +4 -2
  503. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  504. package/dist/showcase/specimens/inputs.js +62 -19
  505. package/dist/showcase/specimens/menus.d.ts +0 -1
  506. package/dist/showcase/specimens/menus.d.ts.map +1 -1
  507. package/dist/showcase/specimens/menus.js +47 -17
  508. package/dist/showcase/specimens/navigation.d.ts +6 -4
  509. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  510. package/dist/showcase/specimens/navigation.js +61 -32
  511. package/dist/showcase/specimens/other.d.ts +1 -3
  512. package/dist/showcase/specimens/other.d.ts.map +1 -1
  513. package/dist/showcase/specimens/other.js +17 -13
  514. package/dist/showcase/specimens/status.d.ts +4 -1
  515. package/dist/showcase/specimens/status.d.ts.map +1 -1
  516. package/dist/showcase/specimens/status.js +64 -11
  517. package/dist/showcase/usage.generated.d.ts +1 -1
  518. package/dist/showcase/usage.generated.d.ts.map +1 -1
  519. package/dist/showcase/usage.generated.js +632 -544
  520. package/dist/standalone/index.js +1 -1
  521. package/dist/styles/components.css +13 -13
  522. package/dist/styles/globals.css +25 -0
  523. package/package.json +2 -3
  524. package/dist/components/approval-row.d.ts +0 -34
  525. package/dist/components/approval-row.d.ts.map +0 -1
  526. package/dist/components/approval-row.js +0 -27
  527. package/dist/components/channel-view.d.ts +0 -112
  528. package/dist/components/channel-view.d.ts.map +0 -1
  529. package/dist/components/channel-view.js +0 -84
  530. package/dist/components/dashboard-shell.d.ts +0 -51
  531. package/dist/components/dashboard-shell.d.ts.map +0 -1
  532. package/dist/components/dashboard-shell.js +0 -89
  533. package/dist/components/direction.d.ts +0 -2
  534. package/dist/components/direction.d.ts.map +0 -1
  535. package/dist/components/direction.js +0 -1
  536. package/dist/components/expandable-block.d.ts +0 -20
  537. package/dist/components/expandable-block.d.ts.map +0 -1
  538. package/dist/components/expandable-block.js +0 -32
  539. package/dist/components/form.d.ts +0 -42
  540. package/dist/components/form.d.ts.map +0 -1
  541. package/dist/components/form.js +0 -91
  542. package/dist/components/label-system.d.ts +0 -17
  543. package/dist/components/label-system.d.ts.map +0 -1
  544. package/dist/components/label-system.js +0 -21
  545. package/dist/components/memory-item.d.ts +0 -21
  546. package/dist/components/memory-item.d.ts.map +0 -1
  547. package/dist/components/memory-item.js +0 -18
  548. package/dist/components/menubar.d.ts +0 -43
  549. package/dist/components/menubar.d.ts.map +0 -1
  550. package/dist/components/menubar.js +0 -69
  551. package/dist/components/navigation-menu.d.ts +0 -26
  552. package/dist/components/navigation-menu.d.ts.map +0 -1
  553. package/dist/components/navigation-menu.js +0 -45
  554. package/dist/components/pagination.d.ts +0 -33
  555. package/dist/components/pagination.d.ts.map +0 -1
  556. package/dist/components/pagination.js +0 -41
  557. package/dist/components/plugin-slot-boundary.d.ts +0 -42
  558. package/dist/components/plugin-slot-boundary.d.ts.map +0 -1
  559. package/dist/components/plugin-slot-boundary.js +0 -41
  560. package/dist/components/status-row.d.ts +0 -32
  561. package/dist/components/status-row.d.ts.map +0 -1
  562. package/dist/components/status-row.js +0 -35
@@ -2,18 +2,23 @@
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { flushSync } from "react-dom";
5
- import { columnFilteringFeature, columnVisibilityFeature, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_arrIncludes, filterFn_equals, filterFn_inDateRange, filterFn_includesString, filterFn_inNumberRange, filterFn_weakEquals, flexRender, metaHelper, rowPaginationFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_datetime, sortFn_text, tableFeatures, useTable, } from "@tanstack/react-table";
5
+ import { columnFilteringFeature, columnSizingFeature, columnVisibilityFeature, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_arrIncludes, filterFn_equals, filterFn_inDateRange, filterFn_includesString, filterFn_inNumberRange, filterFn_weakEquals, flexRender, metaHelper, rowPaginationFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_datetime, sortFn_text, tableFeatures, useTable, } from "@tanstack/react-table";
6
6
  import { ChevronDown } from "lucide-react";
7
7
  import { cn } from "../lib/utils.js";
8
- import { Button } from "./button.js";
8
+ import { ActionContextMenu } from "./action-menu.js";
9
+ import { Button, ButtonLink } from "./button.js";
9
10
  import { CollectionToolbar } from "./collection-toolbar.js";
10
11
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuTrigger, } from "./dropdown-menu.js";
11
12
  import { EmptyState } from "./empty-state.js";
12
- import { Table, TableCell, TableDetailRow, TableHead, TableHeader, TableRecordGroup, TableRow, } from "./table.js";
13
+ import { MiddleTruncate } from "./middle-truncate.js";
14
+ import { Table, TableCell, TableCol, TableColgroup, TableDetailRow, TableHead, TableHeader, TableRecordGroup, TableRow, } from "./table.js";
13
15
  import { TableCard } from "./table-card.js";
14
- import { tableCompactLayouts } from "./table-layouts.js";
16
+ import { TableCompactLine, TableLaidOutCompact } from "../internal/table-compact-line.js";
17
+ import { compactLayoutFor, tableCompactLayouts, } from "./table-layouts.js";
18
+ import { titleWhenCut } from "../internal/title-when-cut.js";
15
19
  const dataTableFeatures = tableFeatures({
16
20
  columnFilteringFeature,
21
+ columnSizingFeature,
17
22
  columnVisibilityFeature,
18
23
  rowPaginationFeature,
19
24
  rowSortingFeature,
@@ -41,53 +46,41 @@ function isEmptyValue(value) {
41
46
  function isNumericColumn(column) {
42
47
  return column.columnDef.meta?.numeric === true;
43
48
  }
44
- const NARROW_COLUMN_CLASS = "w-px whitespace-nowrap";
45
- const IDENTITY_COLUMN_CLASS = "max-w-0 min-w-24";
46
- const IDENTITY_CONTENT_CLASS = "truncate";
47
- const PROSE_COLUMN_CLASS = "min-w-32";
48
- const WRAPPING_COLUMN_CLASS = "min-w-32 whitespace-normal align-top";
49
- const PROSE_FRAME_CLASS = "grid grid-cols-[minmax(0,max-content)]";
50
- const PROSE_CONTENT_CLASS = "max-w-64 truncate";
51
- const CELL_INSET_CLASS = "px-4";
52
- function primaryRowLinkProps({ href, label, identity, content, }) {
49
+ function renderCell(cell) {
50
+ const value = cell.getValue();
51
+ if (cell.column.columnDef.meta?.identifier === true && !isEmptyValue(value) && value !== "") {
52
+ return _jsx(MiddleTruncate, { value: String(value) });
53
+ }
54
+ return flexRender(cell.column.columnDef.cell, cell.getContext());
55
+ }
56
+ function primaryRowLinkProps({ href, label, wraps, content, }) {
53
57
  const props = {
54
58
  href,
55
59
  "aria-label": label,
56
60
  "data-row-link": "",
57
- className: cn("-mx-2 -my-1.5 block rounded-md px-2 py-1.5", identity && IDENTITY_CONTENT_CLASS),
61
+ className: cn("-my-1.5 block rounded-sm py-1.5", !wraps && "truncate"),
58
62
  children: content,
59
63
  };
60
- if (identity) {
64
+ if (!wraps) {
61
65
  props.onFocus = titleWhenCut;
62
66
  props.onPointerEnter = titleWhenCut;
63
67
  }
64
68
  return props;
65
69
  }
66
- function titleWhenCut(event) {
67
- const element = event.currentTarget;
68
- const cut = [element, ...element.querySelectorAll("*")].some((node) => node.scrollWidth > node.clientWidth);
69
- const text = element.textContent?.replace(/\s+/g, " ").trim();
70
- if (cut && text)
71
- element.title = text;
72
- else
73
- element.removeAttribute("title");
74
- }
70
+ // Below its layout's width the table lays out by content, so the identity takes the room the
71
+ // other columns leave and a long name ends in an ellipsis instead of widening the table.
75
72
  const COMPACT_IDENTITY_CLASS = {
76
- tight: "@max-xl/table:w-full",
77
- standard: "@max-3xl/table:w-full",
78
- wide: "@max-5xl/table:w-full",
79
- spacious: "@max-6xl/table:w-full",
73
+ narrow: "@max-md/table:w-full @max-md/table:max-w-0",
74
+ tight: "@max-xl/table:w-full @max-xl/table:max-w-0",
75
+ standard: "@max-3xl/table:w-full @max-3xl/table:max-w-0",
76
+ wide: "@max-5xl/table:w-full @max-5xl/table:max-w-0",
77
+ roomy: "@max-[68rem]/table:w-full @max-[68rem]/table:max-w-0",
78
+ spacious: "@max-6xl/table:w-full @max-6xl/table:max-w-0",
80
79
  };
81
- function widthClass(column, identityColumnId, compactLayout, identityAlone, balancedIdentity) {
82
- if (column.columnDef.meta?.narrow === true)
83
- return NARROW_COLUMN_CLASS;
84
- if (column.columnDef.meta?.prose === true)
85
- return PROSE_COLUMN_CLASS;
86
- if (column.columnDef.meta?.wraps === true)
87
- return WRAPPING_COLUMN_CLASS;
88
- if (column.id !== identityColumnId)
89
- return false;
90
- return cn(IDENTITY_COLUMN_CLASS, balancedIdentity ? "w-1/4" : "w-1/3 sm:min-w-44", identityAlone && "w-full", compactLayout && COMPACT_IDENTITY_CLASS[compactLayout]);
80
+ function identityWidthClass(column, identityColumnId, compactLayout) {
81
+ return column.id === identityColumnId && compactLayout
82
+ ? COMPACT_IDENTITY_CLASS[compactLayout]
83
+ : false;
91
84
  }
92
85
  function definitionId(column) {
93
86
  if (!column)
@@ -101,11 +94,27 @@ export function columnMenuLabel(column) {
101
94
  // oxlint-disable-next-line anti-slop/no-runtime-typeof -- TanStack types a column header as a string or a render function; only typeof tells them apart.
102
95
  return typeof header === "string" ? header : column.id;
103
96
  }
104
- function collapseClass(columnId, primaryColumns, compactLayout) {
105
- if (primaryColumns.includes(columnId))
97
+ function sortOrder(sorted) {
98
+ if (sorted === "asc")
99
+ return "ascending";
100
+ if (sorted === "desc")
101
+ return "descending";
102
+ return undefined;
103
+ }
104
+ function collapseLayout(column, primaryColumns, compactLayout) {
105
+ if (primaryColumns.includes(column.id))
106
106
  return undefined;
107
- return compactLayout ? tableCompactLayouts[compactLayout].column : undefined;
107
+ return compactLayout;
108
108
  }
109
+ function collapseClass(column, primaryColumns, compactLayout) {
110
+ const layout = collapseLayout(column, primaryColumns, compactLayout);
111
+ return layout ? tableCompactLayouts[layout].column : undefined;
112
+ }
113
+ function collapseTrackClass(column, primaryColumns, compactLayout) {
114
+ const layout = collapseLayout(column, primaryColumns, compactLayout);
115
+ return layout ? tableCompactLayouts[layout].track : undefined;
116
+ }
117
+ const NO_ROW_MENU = { label: "", record: "", commands: [] };
109
118
  function useShownLayout() {
110
119
  const [shownLayout, setShownLayout] = React.useState("both");
111
120
  const probeRef = React.useCallback((probe) => {
@@ -152,33 +161,62 @@ function LayoutProbeLeadingRecords({ layout, probeRef, children, }) {
152
161
  return (_jsxs(_Fragment, { children: [layout ? (_jsx("tbody", { ref: probeRef, "aria-hidden": "true", "data-slot": "table-layout-probe", className: tableCompactLayouts[layout].details }, layout)) : null, children] }));
153
162
  }
154
163
  const defaultRowLink = (props) => _jsx("a", { ...props });
164
+ function PagerButton({ enabled, label, link, onClick, }) {
165
+ if (link && enabled) {
166
+ return (_jsx(ButtonLink, { render: link, variant: "outline", children: label }));
167
+ }
168
+ return (_jsx(Button, { disabled: !enabled, onClick: onClick, variant: "outline", children: label }));
169
+ }
170
+ function GroupHeading({ children, span }) {
171
+ return (_jsx("tbody", { "data-slot": "table-group-heading", children: _jsx(TableRow, { children: _jsx(TableHead, { className: "text-foreground last:text-left", colSpan: span, scope: "colgroup", children: children }) }) }));
172
+ }
155
173
  function DefaultToolbar({ actions }) {
156
174
  return actions ? _jsx(CollectionToolbar, { label: "", actions: actions }) : null;
157
175
  }
158
176
  /**
159
- * Records that share comparable facts, read across in rows inside their `TableCard`.
177
+ * Records compared across columns: the same facts for every record, read down a column and
178
+ * across a row, inside their `TableCard`.
160
179
  *
161
180
  * @family Data
162
- * @when Records that share comparable facts: usage per Agent, statements, invoices, customers with
163
- * their partner and count. 40 px rows for figures; `density="comfortable"`, the default, gives 48 px
164
- * for entity rows.
165
- * @instead An entity collection that is the page's whole job is `CollectionPage`, which draws its own
166
- * 56 px rows. A descriptive list is `ItemGroup`. One object's facts are `ObjectFacts`.
167
- * @behaviour Headings visible by default; numbers trail in tabular figures. Row hover, focus within
168
- * and an open menu take `accent`; a selected row takes `muted`; headers and footers never highlight.
169
- * Narrow cards move facts into a detail row, never scroll sideways; an `optional` column's empty
170
- * value is left out of it. Empty sits outside the body.
171
- * @words Headings are nouns with their unit: "Cost (€)", "Tokens". The footer is a count or the
172
- * paging; the summary row is a labelled total. Italian headings run a third longer and never wrap.
173
- * @access A native table with `aria-label`; `th scope="col"`; the record's name is the row's one
174
- * link. A missing value is a hidden "—" with screen-reader text, never blank.
181
+ * @when “Use `<Table>` for tabular data where rows share the same shape and at least one column is sortable or comparable across rows.” (https://vercel.com/geist/table)
182
+ * Ours: the person compares: usage per Agent, statements, invoices, customers with their partner and count. The columns are fixed, each has a heading, and at least one is a figure or can be sorted. There are three kinds of list. Objects a person opens (a project, a deployment, a member, an integration) are entity rows: a `RecordList`. Values edited in place (a domain, an environment variable) are entity rows that expand into their form: a `RecordList`'s `editor`. Records compared across columns are this table.
183
+ * @instead “For a row of descriptive content paired with a single action (membership row, integration row), use `Entity` instead.” (https://vercel.com/geist/table)
184
+ * “For a key/value metadata block on a detail page, use `Description`, not a two-column table.” (https://vercel.com/geist/table)
185
+ * Ours: Geist's `Entity` is a `RecordList` row. A registry of entities whose columns `RecordList` cannot hold, more than three facts beside a filter bar the product owns, as Vercel's Deployments list, is this table with `rows="entities"`, which draws the same rows: headings for assistive technology only, 72 px rows, a `RecordIdentity` in the identity column. Its `Description` is `ObjectFacts`. A list on a page of its own is a `CollectionPage`. A descriptive list is `ItemGroup`.
186
+ * @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 36 px high above 12 px of room and the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
187
+ * “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table)
188
+ * “After an async filter change, wrap the region in `aria-live="polite"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state)
189
+ * Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced.
190
+ * “Sortable column headers are buttons. The visible label stays Title Case; the sort-direction arrow is decorative and the button announces the next sort state to assistive tech.” (https://vercel.com/geist/table)
191
+ * Ours: the order has one owner, the app's `sorting`, which the URL holds, so no heading is a button and every page of a paged list follows one order.
192
+ * “Apply `tabular-nums` (or Geist Mono) to numeric columns so digits align across rows for comparison.” (https://vercel.com/geist/table)
193
+ * Ours: a numeric column trails in tabular figures.
194
+ * @words “Column headers (`<Table.Head>`) are Title Case nouns or noun phrases: `Last Used`, `Requests (7d)`, `Created`, `Status`. Never sentences.” (https://vercel.com/geist/table)
195
+ * “Render `—` in cells where a value is unknown or not applicable. Don’t substitute `N/A`, `null`, or an empty string.” (https://vercel.com/geist/table)
196
+ * “Use the canonical short relative-time form in cells (`2m ago`, `5h ago`); switch to `Mar 14, 2026` past 7 days. See `Relative Time Card`.” (https://vercel.com/geist/table)
197
+ * “Pagination labels are `Previous` and `Next`. Page-count copy reads `Page 2 of 7` or `21–40 of 142` with an en-dash inside the range.” (https://vercel.com/geist/table)
198
+ * Ours: headings are sentence case nouns with their unit, "Cost (€)", "Tokens", where Geist writes Title Case. The words of a time and of Previous and Next are the product's catalogue, in both languages. The footer is a count or the paging; the summary row is a labelled total. Italian headings run a third longer and never wrap.
199
+ * @access A native table named by `tableLabel`, which is required; `th scope="col"`; the record's name is the row's one link. A sorted column's heading carries `aria-sort`. Ours: a missing value is a hidden "—" with screen-reader text, never blank.
200
+ */
201
+ export function DataTable(props) {
202
+ return _jsx(RecordsTable, { ...props, kind: props.rows ?? "figures" });
203
+ }
204
+ /**
205
+ * The entity rows `RecordList` draws: a table whose headings only a screen reader reads, 72 px
206
+ * rows, and a form that opens inside the record's row. A screen draws these rows with
207
+ * `RecordList`, never with this.
175
208
  */
176
- export function DataTable({ columns, data, getRowId, filterColumnId, filterPlaceholder, primaryColumns, compactLayout: requestedCompactLayout, tableLabel, heading, footer, showColumnHeaders = true, density = "comfortable", interactive = true, embedded = false, summary, rowHref, rowLabel, primaryColumnId, empty, noMatchMessage, columnsLabel, clearSearchLabel, pageLabels, toolbarActions, externalFilter, sorting: externalSorting, pagination, renderRowLink = defaultRowLink, renderToolbar = DefaultToolbar, wrapCard, rowEditor, }) {
209
+ export function EntityTable(props) {
210
+ return _jsx(RecordsTable, { ...props, kind: "entities" });
211
+ }
212
+ function RecordsTable({ kind, columns, data, getRowId, filterColumnId, filterPlaceholder, primaryColumns, compactLayout: requestedCompactLayout, tableLabel, heading, footer, footerNote, group, embedded = false, summary, rowHref, rowLabel, primaryColumnId, empty, noMatchMessage, columnsLabel, clearSearchLabel, pageLabels, toolbarActions, externalFilter, sorting: externalSorting, pagination, renderRowLink = defaultRowLink, renderToolbar = DefaultToolbar, wrapCard, rowEditor, rowMenu, }) {
213
+ const entities = kind === "entities";
177
214
  const [sorting, setSorting] = React.useState([]);
178
215
  const [columnFilters, setColumnFilters] = React.useState([]);
179
216
  const [columnVisibility, setColumnVisibility] = React.useState({});
180
- const identityColumnId = definitionId(columns.find((column) => column.meta?.narrow !== true && column.meta?.prose !== true && column.meta?.wraps !== true));
181
- const identityAlone = columns.every((column) => column.meta?.narrow === true || definitionId(column) === identityColumnId);
217
+ const identityColumnId = primaryColumnId ?? definitionId(columns[0]);
218
+ // TanStack gives a column without a size its default one; only the caller's definition says whether it has one.
219
+ const sizeOf = new Map(columns.map((column) => [definitionId(column), column.size]));
182
220
  // An external pager means `data` is already one bounded server page:
183
221
  // `manualPagination` makes the paginated row model a passthrough so every
184
222
  // row of the current page renders.
@@ -201,28 +239,40 @@ export function DataTable({ columns, data, getRowId, filterColumnId, filterPlace
201
239
  if (getRowId)
202
240
  tableOptions.getRowId = getRowId;
203
241
  const table = useTable(tableOptions);
204
- const balancedIdentity = showColumnHeaders && table.getVisibleLeafColumns().length > 5;
205
242
  const hasDetailColumns = table
206
243
  .getAllLeafColumns()
207
244
  .some((column) => !primaryColumns.includes(column.id));
208
- const compactLayout = hasDetailColumns
209
- ? (requestedCompactLayout ?? (table.getVisibleLeafColumns().length > 7 ? "wide" : "standard"))
210
- : undefined;
245
+ const neededLayout = requestedCompactLayout ??
246
+ compactLayoutFor(table.getVisibleLeafColumns().map((column) => sizeOf.get(column.id)));
247
+ const compactLayout = hasDetailColumns ? neededLayout : undefined;
248
+ // A table whose every column stays lays out by its content on a narrow card, so the name wraps
249
+ // beside the columns instead of collapsing between them.
250
+ const tableLayout = compactLayout ?? neededLayout;
211
251
  const [shownLayout, layoutProbeRef] = useShownLayout();
212
252
  const canPreviousPage = pagination ? pagination.hasPrevious : table.getCanPreviousPage();
213
253
  const canNextPage = pagination ? pagination.hasNext : table.getCanNextPage();
214
254
  const goPreviousPage = pagination ? pagination.onPrevious : () => table.previousPage();
215
255
  const goNextPage = pagination ? pagination.onNext : () => table.nextPage();
256
+ const waitingForPage = pagination ? pagination.isPending === true : false;
216
257
  const filterColumn = filterColumnId ? table.getColumn(filterColumnId) : undefined;
217
258
  const rawFilterValue = filterColumn?.getFilterValue();
218
259
  // oxlint-disable-next-line anti-slop/no-runtime-typeof -- TanStack types a column filter value as unknown; this is where it is read.
219
260
  const filterValue = typeof rawFilterValue === "string" ? rawFilterValue : "";
220
261
  const canHideColumns = Boolean(columnsLabel) && table.getAllColumns().some((column) => column.getCanHide());
221
- const columnsControl = canHideColumns ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { render: _jsxs(Button, { variant: "outline", children: [columnsLabel, _jsx(ChevronDown, { "aria-hidden": "true", "data-icon": "inline-end" })] }) }), _jsx(DropdownMenuContent, { align: "end", children: _jsx(DropdownMenuGroup, { children: table
262
+ const columnsControl = canHideColumns ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { render: _jsx(Button, { variant: "outline", suffix: _jsx(ChevronDown, { "aria-hidden": "true" }), children: columnsLabel }) }), _jsx(DropdownMenuContent, { align: "end", children: _jsx(DropdownMenuGroup, { children: table
222
263
  .getAllColumns()
223
264
  .filter((column) => column.getCanHide())
224
265
  .map((column) => (_jsx(DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange: (value) => column.toggleVisibility(!!value), children: columnMenuLabel(column) }, column.id))) }) })] })) : null;
225
266
  const rows = table.getRowModel().rows;
267
+ const sections = [];
268
+ for (const row of rows) {
269
+ const heading = group?.(row.original);
270
+ const section = sections.find((each) => each.heading === heading);
271
+ if (section)
272
+ section.rows.push(row);
273
+ else
274
+ sections.push({ heading, rows: [row] });
275
+ }
226
276
  const renderRow = (row) => {
227
277
  const href = rowHref?.(row.original);
228
278
  const label = rowLabel?.(row.original);
@@ -230,12 +280,28 @@ export function DataTable({ columns, data, getRowId, filterColumnId, filterPlace
230
280
  const configuredPrimaryVisible = primaryColumnId !== undefined && table.getColumn(primaryColumnId)?.getIsVisible();
231
281
  const primaryId = configuredPrimaryVisible ? primaryColumnId : visibleCells[0]?.column.id;
232
282
  const detailCells = visibleCells.filter((cell) => !primaryColumns.includes(cell.column.id) &&
283
+ cell.column.columnDef.meta?.compact !== "dropped" &&
233
284
  !(cell.column.columnDef.meta?.optional === true && isEmptyValue(cell.getValue())));
234
- return (_jsxs(TableRecordGroup, { children: [_jsx(TableRow, { "data-href": href, className: cn(href && "cursor-pointer"), detailLayout: detailCells.length > 0 ? compactLayout : undefined, onClick: href
285
+ const detailFacts = () => detailCells.map((cell) => ({
286
+ id: cell.id,
287
+ label: columnMenuLabel(cell.column),
288
+ value: entities && cell.column.columnDef.meta?.compact === "text"
289
+ ? String(cell.getValue() ?? "")
290
+ : renderCell(cell),
291
+ wraps: cell.column.columnDef.meta?.wraps === true,
292
+ }));
293
+ // An entity row keeps its record on one 72 px row on a narrow card: the facts that leave the
294
+ // row join the line under the name, which `RecordIdentity` draws, instead of a row of their own.
295
+ const compactLine = entities && compactLayout && detailCells.length > 0 && shownLayout !== "columns"
296
+ ? { layout: compactLayout, facts: detailFacts() }
297
+ : undefined;
298
+ const detailRowShown = !entities && detailCells.length > 0 && shownLayout !== "columns";
299
+ const menu = rowMenu?.(row.original);
300
+ const record = (_jsxs(TableRecordGroup, { interactive: Boolean(href), children: [_jsx(TableRow, { "data-href": href, className: cn(href && "cursor-pointer"), detailLayout: !entities && detailCells.length > 0 ? compactLayout : undefined, onClick: href
235
301
  ? (event) => {
236
302
  const target = event.target;
237
303
  if (!(target instanceof Element) ||
238
- target.closest("a, button, input, select, textarea, label, [role='button'], [role='menuitem'], [role='checkbox']")) {
304
+ target.closest("a, button, input, select, textarea, label, [role='button'], [role='menuitem'], [role='checkbox'], [role='dialog']")) {
239
305
  return;
240
306
  }
241
307
  event.currentTarget.querySelector("a[data-row-link]")?.click();
@@ -243,24 +309,25 @@ export function DataTable({ columns, data, getRowId, filterColumnId, filterPlace
243
309
  : undefined, children: visibleCells.map((cell) => {
244
310
  const numeric = isNumericColumn(cell.column);
245
311
  const isPrimaryLink = href && cell.column.id === primaryId;
246
- const collapsed = collapseClass(cell.column.id, primaryColumns, compactLayout);
247
- const className = cn(CELL_INSET_CLASS, numeric && "text-right tabular-nums wrap-normal", cell.column.columnDef.meta?.wraps && "whitespace-normal", widthClass(cell.column, identityColumnId, compactLayout, identityAlone, balancedIdentity), collapsed);
312
+ const collapsed = collapseClass(cell.column, primaryColumns, compactLayout);
313
+ const wraps = cell.column.columnDef.meta?.wraps === true;
314
+ const centered = cell.column.columnDef.meta?.centered === true;
315
+ const cutByEllipsis = !wraps && !isPrimaryLink;
316
+ const holdsCompactLine = compactLine !== undefined && cell.column.id === identityColumnId;
317
+ const className = cn(numeric && "text-right tabular-nums wrap-normal", wraps && "whitespace-normal last:text-left", centered && "text-center last:text-center", cutByEllipsis && "overflow-hidden text-ellipsis", identityWidthClass(cell.column, identityColumnId, tableLayout), collapsed);
248
318
  const drawnOnlyInDetailRow = Boolean(collapsed) && shownLayout === "details" && !isPrimaryLink;
249
319
  if (drawnOnlyInDetailRow) {
250
320
  return _jsx(TableCell, { className: className }, cell.id);
251
321
  }
252
- const content = flexRender(cell.column.columnDef.cell, cell.getContext());
253
- const identity = cell.column.id === identityColumnId;
254
- const prose = cell.column.columnDef.meta?.prose === true;
255
- return (_jsx(TableCell, { className: className, children: isPrimaryLink ? (renderRowLink(primaryRowLinkProps({ href, label, identity, content }))) : identity ? (_jsx("div", { className: IDENTITY_CONTENT_CLASS, onFocus: titleWhenCut, onPointerEnter: titleWhenCut, children: content })) : prose ? (_jsx("div", { className: PROSE_FRAME_CLASS, children: _jsx("div", { className: PROSE_CONTENT_CLASS, onFocus: titleWhenCut, onPointerEnter: titleWhenCut, children: content }) })) : (content) }, cell.id));
256
- }) }), rowEditor?.rowId === row.id ? (_jsx(TableRow, { "data-slot": "table-row-editor", className: "in-[tbody]:hover:bg-transparent", children: _jsx(TableCell, { colSpan: visibleCells.length, className: "p-0 whitespace-normal", children: rowEditor.render(row.original) }) })) : null, detailCells.length > 0 && shownLayout !== "columns" ? (_jsx(TableDetailRow, { layout: compactLayout, colSpan: visibleCells.filter((cell) => !collapseClass(cell.column.id, primaryColumns, compactLayout)).length, facts: detailCells.map((cell) => ({
257
- id: cell.id,
258
- label: columnMenuLabel(cell.column),
259
- numeric: isNumericColumn(cell.column),
260
- value: flexRender(cell.column.columnDef.cell, cell.getContext()),
261
- })) })) : null] }, row.id));
322
+ const content = holdsCompactLine ? (_jsx(TableCompactLine, { ...compactLine, children: renderCell(cell) })) : (renderCell(cell));
323
+ const titledWhenCut = cutByEllipsis || holdsCompactLine;
324
+ return (_jsx(TableCell, { className: className, onFocus: titledWhenCut ? titleWhenCut : undefined, onPointerEnter: titledWhenCut ? titleWhenCut : undefined, children: isPrimaryLink
325
+ ? renderRowLink(primaryRowLinkProps({ href, label, wraps, content }))
326
+ : content }, cell.id));
327
+ }) }), rowEditor?.rowId === row.id ? (_jsx(TableRow, { "data-slot": "table-row-editor", className: "h-auto! [&>td]:bg-transparent!", children: _jsx(TableCell, { colSpan: visibleCells.length, className: "p-0 whitespace-normal", children: rowEditor.render(row.original) }) })) : null, detailRowShown ? (_jsx(TableDetailRow, { layout: compactLayout, colSpan: visibleCells.filter((cell) => !collapseClass(cell.column, primaryColumns, compactLayout)).length, facts: detailFacts() })) : null] }));
328
+ return (_jsx(React.Fragment, { children: _jsx(ActionContextMenu, { ...(menu ?? NO_ROW_MENU), children: record }) }, row.id));
262
329
  };
263
- const tableNode = rows.length === 0 ? (_jsx(EmptyState, { scope: "card", ...(filterValue && noMatchMessage && clearSearchLabel && filterColumn
330
+ const absence = rows.length === 0 && (_jsx(EmptyState, { scope: "card", ...(filterValue && noMatchMessage && clearSearchLabel && filterColumn
264
331
  ? {
265
332
  kind: "noResults",
266
333
  message: noMatchMessage,
@@ -269,26 +336,30 @@ export function DataTable({ columns, data, getRowId, filterColumnId, filterPlace
269
336
  onClick: () => filterColumn.setFilterValue(""),
270
337
  },
271
338
  }
272
- : empty) })) : (_jsxs(Table, { "aria-label": tableLabel, className: "text-body-sm", compactDetails: compactLayout, density: density, interactive: interactive, children: [_jsx(TableHeader, { className: showColumnHeaders ? undefined : "sr-only", children: table.getHeaderGroups().map((headerGroup) => (_jsx(TableRow, { children: headerGroup.headers.map((header) => (_jsx(TableHead, { className: cn(CELL_INSET_CLASS, isNumericColumn(header.column) && "text-right tabular-nums", widthClass(header.column, identityColumnId, compactLayout, identityAlone, balancedIdentity), collapseClass(header.column.id, primaryColumns, compactLayout)), children: header.isPlaceholder
273
- ? null
274
- : flexRender(header.column.columnDef.header, header.getContext()) }, header.id))) }, headerGroup.id))) }), _jsx(LayoutProbeLeadingRecords, { layout: compactLayout, probeRef: layoutProbeRef, children: rows.map(renderRow) })] }));
339
+ : empty) }));
340
+ const tableNode = (_jsxs(_Fragment, { children: [_jsx("div", { "aria-live": "polite", "data-slot": "data-table-absence", children: absence }), rows.length === 0 ? null : (_jsx(TableLaidOutCompact, { compact: entities && compactLayout !== undefined && shownLayout === "details", children: _jsxs(Table, { "aria-label": tableLabel, className: "table-fixed text-body-sm", compactDetails: tableLayout, density: entities ? "comfortable" : "default", children: [_jsx(TableColgroup, { children: table.getVisibleLeafColumns().map((column) => {
341
+ const size = sizeOf.get(column.id);
342
+ return (_jsx(TableCol, { className: cn(collapseTrackClass(column, primaryColumns, compactLayout)), style: size === undefined ? undefined : { width: size } }, column.id));
343
+ }) }), _jsx(TableHeader, { className: entities ? "sr-only" : undefined, children: table.getHeaderGroups().map((headerGroup) => (_jsx(TableRow, { children: headerGroup.headers.map((header) => (_jsx(TableHead, { "aria-sort": sortOrder(header.column.getIsSorted()), "data-identity": header.column.id === identityColumnId ? "" : undefined, className: cn(isNumericColumn(header.column) && "text-right tabular-nums", header.column.columnDef.meta?.wraps === true && "last:text-left", header.column.columnDef.meta?.centered === true &&
344
+ "text-center last:text-center", identityWidthClass(header.column, identityColumnId, tableLayout), collapseClass(header.column, primaryColumns, compactLayout)), children: header.isPlaceholder
345
+ ? null
346
+ : flexRender(header.column.columnDef.header, header.getContext()) }, header.id))) }, headerGroup.id))) }), _jsx(LayoutProbeLeadingRecords, { layout: compactLayout, probeRef: layoutProbeRef, children: sections.map((section) => (_jsxs(React.Fragment, { children: [section.heading === undefined ? null : (_jsx(GroupHeading, { span: table.getVisibleLeafColumns().length, children: section.heading })), section.rows.map(renderRow)] }, section.heading ?? ""))) })] }) }))] }));
275
347
  const actions = columnsControl || toolbarActions ? (_jsxs(_Fragment, { children: [columnsControl, toolbarActions] })) : null;
276
348
  const toolbarSlots = { actions };
277
- if (filterColumn) {
349
+ if (filterColumn && filterPlaceholder !== undefined && clearSearchLabel !== undefined) {
278
350
  toolbarSlots.search = {
279
- label: filterPlaceholder ?? "",
280
- placeholder: filterPlaceholder ?? "",
351
+ label: filterPlaceholder,
352
+ placeholder: filterPlaceholder,
281
353
  value: filterValue,
282
354
  onChange: (value) => filterColumn.setFilterValue(value),
283
355
  };
284
- if (clearSearchLabel) {
285
- toolbarSlots.clear = {
286
- label: clearSearchLabel,
287
- onClear: () => filterColumn.setFilterValue(""),
288
- };
289
- }
356
+ toolbarSlots.clear = {
357
+ label: clearSearchLabel,
358
+ onClear: () => filterColumn.setFilterValue(""),
359
+ };
290
360
  }
291
361
  const toolbarRow = renderToolbar(toolbarSlots);
292
- const card = (_jsx(TableCard, { surface: embedded ? "plain" : "resting", ...(heading ? { title: heading.title } : {}), ...(heading?.description ? { description: heading.description } : {}), ...(heading && toolbarRow ? { toolbar: toolbarRow } : {}), ...(summary ? { summary } : {}), ...(footer ? { footer } : {}), children: tableNode }));
293
- return (_jsxs("div", { className: "min-w-0 w-full text-body-sm", "data-slot": "data-table", children: [heading ? null : toolbarRow, wrapCard ? wrapCard(card) : card, !pageLabels || pagination === false || (!canPreviousPage && !canNextPage) ? null : (_jsxs("div", { className: "flex items-center justify-end gap-2 py-4", children: [_jsx(Button, { variant: "outline", onClick: goPreviousPage, disabled: !canPreviousPage || (pagination && pagination.isPending), children: pageLabels.previous }), _jsx(Button, { variant: "outline", onClick: goNextPage, disabled: !canNextPage || (pagination && pagination.isPending), children: pageLabels.next })] }))] }));
362
+ const pager = pageLabels && pagination !== false && (canPreviousPage || canNextPage) ? (_jsxs("div", { "aria-busy": waitingForPage || undefined, className: "flex items-center gap-3", children: [pagination && pagination.status ? (_jsx("span", { className: "tabular-nums", children: pagination.status })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(PagerButton, { enabled: canPreviousPage && !waitingForPage, label: pageLabels.previous, link: pagination ? pagination.previousLink : undefined, onClick: goPreviousPage }), _jsx(PagerButton, { enabled: canNextPage && !waitingForPage, label: pageLabels.next, link: pagination ? pagination.nextLink : undefined, onClick: goNextPage })] })] })) : null;
363
+ const card = (_jsx(TableCard, { surface: embedded ? "plain" : "resting", title: heading?.title, description: heading?.description, toolbar: heading ? toolbarRow : undefined, summary: summary, footerHint: footer, footer: pager, note: footerNote, children: tableNode }));
364
+ return (_jsxs("div", { className: "min-w-0 w-full text-body-sm", "data-slot": "data-table", children: [heading ? null : toolbarRow, wrapCard ? wrapCard(card) : card] }));
294
365
  }
@@ -12,6 +12,8 @@ type DesktopAppShellProps = Omit<React.ComponentProps<"section">, "title"> & {
12
12
  primaryPaneLabel?: string;
13
13
  secondaryPaneLabel?: string;
14
14
  inspectorRailLabel?: string;
15
+ secondaryResizeLabel?: string;
16
+ inspectorResizeLabel?: string;
15
17
  primaryPaneSize?: number;
16
18
  secondaryPaneSize?: number;
17
19
  inspectorPaneSize?: number;
@@ -28,7 +30,7 @@ type DesktopAppShellProps = Omit<React.ComponentProps<"section">, "title"> & {
28
30
  * @family Navigation
29
31
  * @when A desktop product's whole window: Nadia's left column (the Agents list, then an Agent's
30
32
  * sections behind *‹ Agents*), its workspace and its side panes.
31
- * @instead The Portal's column is `PortalSidebarFrame` inside `DashboardShell`. Both draw their
33
+ * @instead The Portal's column is `PortalSidebarFrame` inside its `Sidebar`. Both draw their
32
34
  * rows with the same `SidebarMenuButton` and end with the same `AccountMenu`.
33
35
  * @behaviour One 44 px band shares the window buttons and the window's commands. The workspace
34
36
  * splits into resizable panes; the secondary pane and the inspector rail appear only when given.
@@ -37,7 +39,7 @@ type DesktopAppShellProps = Omit<React.ComponentProps<"section">, "title"> & {
37
39
  * under six words: *Writes quotes from the price list*.
38
40
  * @access Each pane and rail is a labelled region; the orb beside a name is decorative.
39
41
  */
40
- declare function DesktopAppShell({ title, titlebar, titlebarActions, activityRail, inspectorRail, secondaryPane, statusbar, children, activityRailLabel, primaryPaneLabel, secondaryPaneLabel, inspectorRailLabel, primaryPaneSize, secondaryPaneSize, inspectorPaneSize, className, titlebarClassName, bodyClassName, primaryPaneClassName, secondaryPaneClassName, inspectorRailClassName, statusbarClassName, ...props }: DesktopAppShellProps): React.JSX.Element;
42
+ declare function DesktopAppShell({ title, titlebar, titlebarActions, activityRail, inspectorRail, secondaryPane, statusbar, children, activityRailLabel, primaryPaneLabel, secondaryPaneLabel, inspectorRailLabel, secondaryResizeLabel, inspectorResizeLabel, primaryPaneSize, secondaryPaneSize, inspectorPaneSize, className, titlebarClassName, bodyClassName, primaryPaneClassName, secondaryPaneClassName, inspectorRailClassName, statusbarClassName, ...props }: DesktopAppShellProps): React.JSX.Element;
41
43
  export { DesktopAppShell };
42
44
  export type { DesktopAppShellProps };
43
45
  //# sourceMappingURL=desktop-shell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"desktop-shell.d.ts","sourceRoot":"","sources":["../../src/components/desktop-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,KAAK,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,GAAG;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,iBAAS,eAAe,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,EACb,SAAS,EACT,QAAQ,EACR,iBAA8B,EAC9B,gBAAsC,EACtC,kBAA0C,EAC1C,kBAAgC,EAChC,eAA2D,EAC3D,iBAA2C,EAC3C,iBAAsB,EACtB,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAyGtB;AAED,OAAO,EAAE,eAAe,EAAE,CAAC;AAC3B,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"desktop-shell.d.ts","sourceRoot":"","sources":["../../src/components/desktop-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,KAAK,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,GAAG;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,iBAAS,eAAe,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,EACb,SAAS,EACT,QAAQ,EACR,iBAA8B,EAC9B,gBAAsC,EACtC,kBAA0C,EAC1C,kBAAgC,EAChC,oBAAuD,EACvD,oBAA6C,EAC7C,eAA2D,EAC3D,iBAA2C,EAC3C,iBAAsB,EACtB,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAyGtB;AAED,OAAO,EAAE,eAAe,EAAE,CAAC;AAC3B,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
@@ -8,7 +8,7 @@ import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./resizabl
8
8
  * @family Navigation
9
9
  * @when A desktop product's whole window: Nadia's left column (the Agents list, then an Agent's
10
10
  * sections behind *‹ Agents*), its workspace and its side panes.
11
- * @instead The Portal's column is `PortalSidebarFrame` inside `DashboardShell`. Both draw their
11
+ * @instead The Portal's column is `PortalSidebarFrame` inside its `Sidebar`. Both draw their
12
12
  * rows with the same `SidebarMenuButton` and end with the same `AccountMenu`.
13
13
  * @behaviour One 44 px band shares the window buttons and the window's commands. The workspace
14
14
  * splits into resizable panes; the secondary pane and the inspector rail appear only when given.
@@ -17,7 +17,7 @@ import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./resizabl
17
17
  * under six words: *Writes quotes from the price list*.
18
18
  * @access Each pane and rail is a labelled region; the orb beside a name is decorative.
19
19
  */
20
- function DesktopAppShell({ title, titlebar, titlebarActions, activityRail, inspectorRail, secondaryPane, statusbar, children, activityRailLabel = "Activity", primaryPaneLabel = "Primary workspace", secondaryPaneLabel = "Secondary workspace", inspectorRailLabel = "Inspector", primaryPaneSize = secondaryPane || inspectorRail ? 58 : 100, secondaryPaneSize = inspectorRail ? 24 : 36, inspectorPaneSize = 18, className, titlebarClassName, bodyClassName, primaryPaneClassName, secondaryPaneClassName, inspectorRailClassName, statusbarClassName, ...props }) {
21
- return (_jsxs("section", { "data-slot": "desktop-app-shell", className: cn("flex h-svh min-h-0 flex-col overflow-hidden border bg-background text-foreground", className), ...props, children: [_jsxs("header", { "data-slot": "desktop-app-titlebar", className: cn("flex h-11 shrink-0 items-center justify-between gap-3 border-b bg-background px-3", titlebarClassName), children: [titlebar ?? (_jsx("div", { "data-slot": "desktop-app-titlebar-content", className: "flex min-w-0 flex-1 items-center gap-2", children: title && _jsx("p", { className: "m-0 truncate text-sm font-medium", children: title }) })), titlebarActions && (_jsx("div", { "data-slot": "desktop-app-titlebar-actions", className: "flex shrink-0 items-center gap-2", children: titlebarActions }))] }), _jsxs("div", { "data-slot": "desktop-app-body", className: cn("flex min-h-0 flex-1", bodyClassName), children: [activityRail && (_jsx("nav", { "data-slot": "desktop-app-activity-rail", "aria-label": activityRailLabel, className: "flex w-14 shrink-0 flex-col items-center gap-2 border-r bg-sidebar p-2 text-sidebar-foreground", children: activityRail })), _jsx("div", { "data-slot": "desktop-app-panes", className: "min-w-0 flex-1", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", className: "min-w-0 flex-1", children: [_jsx(ResizablePanel, { defaultSize: primaryPaneSize, minSize: 30, children: _jsx("section", { "data-slot": "desktop-app-primary-pane", "aria-label": primaryPaneLabel, className: cn("h-full min-w-0 overflow-auto bg-background", primaryPaneClassName), children: children }) }), secondaryPane && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { defaultSize: secondaryPaneSize, minSize: 18, children: _jsx("section", { "data-slot": "desktop-app-secondary-pane", "aria-label": secondaryPaneLabel, className: cn("h-full min-w-0 overflow-auto bg-background", secondaryPaneClassName), children: secondaryPane }) })] })), inspectorRail && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { defaultSize: inspectorPaneSize, minSize: 16, maxSize: 36, children: _jsx("aside", { "data-slot": "desktop-app-inspector-rail", "aria-label": inspectorRailLabel, className: cn("h-full min-w-0 overflow-auto bg-background", inspectorRailClassName), children: inspectorRail }) })] }))] }) })] }), statusbar && (_jsx("footer", { "data-slot": "desktop-app-statusbar", className: cn("flex min-h-8 shrink-0 items-center justify-between gap-3 border-t bg-background px-3 text-xs text-muted-foreground", statusbarClassName), children: statusbar }))] }));
20
+ function DesktopAppShell({ title, titlebar, titlebarActions, activityRail, inspectorRail, secondaryPane, statusbar, children, activityRailLabel = "Activity", primaryPaneLabel = "Primary workspace", secondaryPaneLabel = "Secondary workspace", inspectorRailLabel = "Inspector", secondaryResizeLabel = "Resize the secondary workspace", inspectorResizeLabel = "Resize the inspector", primaryPaneSize = secondaryPane || inspectorRail ? 58 : 100, secondaryPaneSize = inspectorRail ? 24 : 36, inspectorPaneSize = 18, className, titlebarClassName, bodyClassName, primaryPaneClassName, secondaryPaneClassName, inspectorRailClassName, statusbarClassName, ...props }) {
21
+ return (_jsxs("section", { "data-slot": "desktop-app-shell", className: cn("flex h-svh min-h-0 flex-col overflow-hidden border bg-background text-foreground", className), ...props, children: [_jsxs("header", { "data-slot": "desktop-app-titlebar", className: cn("flex h-11 shrink-0 items-center justify-between gap-3 border-b bg-background px-3", titlebarClassName), children: [titlebar ?? (_jsx("div", { "data-slot": "desktop-app-titlebar-content", className: "flex min-w-0 flex-1 items-center gap-2", children: title && _jsx("p", { className: "m-0 truncate text-sm font-medium", children: title }) })), titlebarActions && (_jsx("div", { "data-slot": "desktop-app-titlebar-actions", className: "flex shrink-0 items-center gap-2", children: titlebarActions }))] }), _jsxs("div", { "data-slot": "desktop-app-body", className: cn("flex min-h-0 flex-1", bodyClassName), children: [activityRail && (_jsx("nav", { "data-slot": "desktop-app-activity-rail", "aria-label": activityRailLabel, className: "flex w-14 shrink-0 flex-col items-center gap-2 border-r bg-sidebar p-2 text-sidebar-foreground", children: activityRail })), _jsx("div", { "data-slot": "desktop-app-panes", className: "min-w-0 flex-1", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", className: "min-w-0 flex-1", children: [_jsx(ResizablePanel, { defaultSize: `${primaryPaneSize}%`, minSize: "30%", children: _jsx("section", { "data-slot": "desktop-app-primary-pane", "aria-label": primaryPaneLabel, className: cn("h-full min-w-0 overflow-auto bg-background", primaryPaneClassName), children: children }) }), secondaryPane && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { "aria-label": secondaryResizeLabel, withHandle: true }), _jsx(ResizablePanel, { defaultSize: `${secondaryPaneSize}%`, minSize: "18%", children: _jsx("section", { "data-slot": "desktop-app-secondary-pane", "aria-label": secondaryPaneLabel, className: cn("h-full min-w-0 overflow-auto bg-background", secondaryPaneClassName), children: secondaryPane }) })] })), inspectorRail && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { "aria-label": inspectorResizeLabel, withHandle: true }), _jsx(ResizablePanel, { defaultSize: `${inspectorPaneSize}%`, minSize: "16%", maxSize: "36%", children: _jsx("aside", { "data-slot": "desktop-app-inspector-rail", "aria-label": inspectorRailLabel, className: cn("h-full min-w-0 overflow-auto bg-background", inspectorRailClassName), children: inspectorRail }) })] }))] }) })] }), statusbar && (_jsx("footer", { "data-slot": "desktop-app-statusbar", className: cn("flex min-h-8 shrink-0 items-center justify-between gap-3 border-t bg-background px-3 text-xs text-muted-foreground", statusbarClassName), children: statusbar }))] }));
22
22
  }
23
23
  export { DesktopAppShell };
@@ -1,20 +1,41 @@
1
1
  import * as React from "react";
2
2
  import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
3
+ import { type PhoneLayout } from "../internal/phone-sheet.js";
3
4
  /**
4
- * A centred modal for a bounded job the person finishes or cancels.
5
+ * A modal for a bounded job the person finishes or cancels.
5
6
  *
6
7
  * @family Menus
7
- * @when A new record through a few fields, or one or two values changed from a command: a bounded
8
- * job the person finishes or cancels. Usually reached through `FormDialog`.
9
- * @instead A record already in a list edits inside its row. A catalogue or a setup in steps is
10
- * `FormDrawer`. A consequence is `ConfirmDialog`. A linkable workflow is its own page.
11
- * @behaviour Centred, 384 px, 24 px padding, 16 px gaps, 12 px corners, modal height over the 50%
12
- * scrim. `DialogBody` scrolls between a header and footer that stay. Footer recessed behind a
13
- * hairline, Cancel then the primary at the trailing edge.
14
- * @words Title is verb and noun (*Add MCP server*); the primary repeats it (*Add server*); the
15
- * pending word is its -ing form. The failure comes from the catalogue, above the footer.
16
- * @access `role="dialog"` named by its title. Focus starts on the first field, is held inside,
17
- * returns to the opener. Escape and the named close button dismiss when nothing is running.
8
+ * @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal)
9
+ * "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal)
10
+ * Ours: `Dialog` is Geist's Modal, usually reached through `FormDialog`: a new record through a few
11
+ * fields, or one or two values changed from a command.
12
+ * @instead "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal)
13
+ * Ours: a consequence is `ConfirmDialog`. A catalogue or a setup in steps is `FormDrawer`. A record
14
+ * that already has a page, or a linkable workflow, is that page.
15
+ * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal)
16
+ * Ours: centred over a scrim, 540 px wide with 20 px of padding; on a phone it is a bottom sheet
17
+ * (`phoneLayout="centred"` keeps it centred). The title, its optional description and the fields
18
+ * scroll and the footer stays at the bottom; with `sticky` the header stays too, as a recessed bar.
19
+ * The footer is recessed and holds 32 px buttons in one row, also on a phone: Cancel at the leading
20
+ * edge, the primary at the trailing edge, a lone button across the full width. A step back
21
+ * (*Previous*) is wrapped with Cancel in one group at the leading edge, so the footer keeps two
22
+ * ends. A footer always holds an action: `children`, or `showCloseButton` with its `closeLabel`.
23
+ * All neutral: the footer and a `sticky` header are recessed behind a hairline, and no hue appears
24
+ * but the focus ring.
25
+ * @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal)
26
+ * "`Modal.P` body is sentence case, 1–3 sentences. State the consequence first, then any cascade." (https://vercel.com/geist/modal)
27
+ * "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal)
28
+ * "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal)
29
+ * "Pair the success toast verb 1:1 with the primary button: `Delete Project` button, `Project deleted` toast." (https://vercel.com/geist/modal)
30
+ * Ours: titles and buttons are sentence case where Geist writes Title Case: the title *Add MCP
31
+ * server*, the primary *Add server*, and its pending word is its -ing form. The failure comes from
32
+ * the catalogue, above the footer. The description is optional and runs to two lines.
33
+ * @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal)
34
+ * "Keep the Cancel button literally `Cancel` so screen-reader users hear a stable dismissal label across destructive flows." (https://vercel.com/geist/modal)
35
+ * "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal)
36
+ * "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal)
37
+ * Ours: `role="dialog"` named by its title. The corner Close is named by `closeLabel`. Focus starts
38
+ * on the first field or `initialFocus`.
18
39
  */
19
40
  declare function Dialog({ ...props }: DialogPrimitive.Root.Props): React.JSX.Element;
20
41
  declare function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props): React.JSX.Element;
@@ -26,23 +47,41 @@ type DialogOverlayProps = DialogPrimitive.Backdrop.Props & {
26
47
  };
27
48
  declare function DialogOverlay({ className, motion, ...props }: DialogOverlayProps): React.JSX.Element;
28
49
  type DialogContentProps = DialogPrimitive.Popup.Props & {
29
- showCloseButton?: boolean;
30
- closeLabel?: React.ReactNode;
31
50
  motion?: DialogMotion;
32
- };
33
- declare function DialogContent({ className, children, showCloseButton, closeLabel, motion, ...props }: DialogContentProps): React.JSX.Element;
51
+ phoneLayout?: PhoneLayout;
52
+ /**
53
+ * The header stays in place as a recessed bar while the body scrolls under it. Without it the
54
+ * header scrolls away with the content; the footer stays either way.
55
+ */
56
+ sticky?: boolean;
57
+ } & ({
58
+ showCloseButton?: true;
59
+ closeLabel: string;
60
+ } | {
61
+ showCloseButton: false;
62
+ closeLabel?: undefined;
63
+ });
64
+ declare function DialogContent({ className, children, showCloseButton, closeLabel, motion, phoneLayout, sticky, finalFocus, ...props }: DialogContentProps): React.JSX.Element;
34
65
  declare function DialogHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
35
66
  /**
36
- * The part of a dialog that scrolls, between a header and a footer that stay
37
- * in place, so the actions remain reachable on a short viewport. The inline
38
- * padding is cancelled by the negative margin so a field's focus outline at the
39
- * edge is not clipped by the scroll container.
67
+ * The part of a `sticky` dialog that scrolls between its header and its footer, so the actions
68
+ * remain reachable on a short viewport; content runs right up to the header bar and down to the
69
+ * footer. Without `sticky` it is the plain column of content, 12 px between fields. It reaches the
70
+ * dialog's edges and pads its own content, so a field's focus outline at the edge is not clipped by
71
+ * the scroll container.
40
72
  */
41
73
  declare function DialogBody({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
42
- type DialogFooterProps = React.ComponentProps<"div"> & {
43
- showCloseButton?: boolean;
44
- closeLabel?: React.ReactNode;
45
- };
74
+ type DialogFooterProps = Omit<React.ComponentProps<"div">, "children"> & ({
75
+ showCloseButton?: false;
76
+ closeLabel?: undefined;
77
+ children: React.ReactNode;
78
+ }
79
+ /** The footer's own leading button, worded from the product's catalogue. */
80
+ | {
81
+ showCloseButton: true;
82
+ closeLabel: string;
83
+ children?: React.ReactNode;
84
+ });
46
85
  declare function DialogFooter({ className, showCloseButton, closeLabel, children, ...props }: DialogFooterProps): React.JSX.Element;
47
86
  declare function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props): React.JSX.Element;
48
87
  declare function DialogDescription({ className, ...props }: DialogPrimitive.Description.Props): React.JSX.Element;