@nadicodeai/ui 12.1.102 → 12.1.103

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 +9 -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
@@ -1,6 +1,15 @@
1
+ import type { ComponentProps, ReactNode } from "react";
2
+ import { HoverCardContent } from "./hover-card.js";
1
3
  export type RecordTimeProps = {
2
- /** When it happened. */
3
- at: Date | number | string;
4
+ /** When it happened; null or a time that names no moment draws `children`, or nothing. */
5
+ at: Date | number | string | null | undefined;
6
+ /**
7
+ * A state the time cannot describe, such as "Just now", "Pending" or "Queued". It replaces the
8
+ * sentence while `at` names a moment, and stands alone, without a card, while it does not.
9
+ */
10
+ children?: ReactNode;
11
+ /** Which side of the time the card opens on; above by default. */
12
+ side?: ComponentProps<typeof HoverCardContent>["side"];
4
13
  /** The person's language; the runtime's when left out. */
5
14
  locale?: string;
6
15
  /**
@@ -31,11 +40,15 @@ export declare function recordDate(at: Date | number | string | null | undefined
31
40
  * says what, or the time of day in a feed's time column.
32
41
  *
33
42
  * @family Data
34
- * @when The moment a record was made, changed or last ran, in its row or its facts ("Updated 3 hours ago"), and the time of each event in an ActivityFeed or a RunTimeline step (`mode="clock"`).
35
- * @instead A date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product ("Took 4 min").
36
- * @behaviour Relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows the exact moment in UTC and in the viewer's zone. A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws nothing.
37
- * @words The product writes the sentence through `phrase` ("Updated {when}", "Ran {when}"); the clock needs no words. The package formats every date with the person's `locale`.
38
- * @access A `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
43
+ * @when "Use `<RelativeTimeCard>` anywhere a recent timestamp appears in scannable surfaces: `Table` cells, `Entity` rows, deploy lists, activity feeds." (https://vercel.com/geist/relative-time-card)
44
+ * Ours: `RelativeTimeCard` is `RecordTime`: the moment a record was made, changed or last ran, in its row or its facts, and the time of each event in an ActivityFeed or a RunTimeline step (`mode="clock"`).
45
+ * @instead "For a static date in body prose past 7 days, render `Mar 14, 2026` directly." (https://vercel.com/geist/relative-time-card)
46
+ * Ours: a date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product (*Took 4 min*).
47
+ * @behaviour "The hover card already shows absolute UTC and local time, so don’t duplicate that copy elsewhere on the row." (https://vercel.com/geist/relative-time-card)
48
+ * Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing.
49
+ * @words "Pass `date` as a number (Unix ms or epoch)." "Don’t pre-format the value, and don’t replace `children` with a formatted string." "The component’s short formatter is the canonical form (`2m`, `5h`, `Yesterday`)." "Don’t append `ago` after the component." "The formatter already produces `2m ago` / `5h ago`, so `<RelativeTimeCard /> ago` reads as `2m ago ago`." "Use `children` only for non-time labels (`Just now`, `Pending`, `Queued`) where the formatter can’t describe the state." "Pair with a leading label when the row is ambiguous on its own: `Last deploy <RelativeTimeCard date={ts} />`." (https://vercel.com/geist/relative-time-card)
50
+ * Ours: `at` takes a Date, epoch milliseconds or an ISO string, never a display string such as *3 hours ago*. The reading is the locale's long form (*3 hours ago*, *12 Sep*), not `2m`. The product writes the sentence through `phrase` (*Updated {when}*, *Ran {when}*), so *ago* is never added after it; the clock needs no words. The package formats every date with the person's `locale`.
51
+ * @access Ours: a `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
39
52
  */
40
53
  export declare function RecordTime(props: RecordTimeProps): import("react").JSX.Element | null;
41
54
  //# sourceMappingURL=record-time.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-time.d.ts","sourceRoot":"","sources":["../../src/components/record-time.tsx"],"names":[],"mappings":"AAcA,MAAM,MAAM,eAAe,GAAG;IAC5B,wBAAwB;IACxB,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,CACA;IACE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AACH,gEAAgE;GAC9D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CACpB,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,EACf,GAAG,SAAa,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAcR;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAIrF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAoDhD"}
1
+ {"version":3,"file":"record-time.d.ts","sourceRoot":"","sources":["../../src/components/record-time.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAa,gBAAgB,EAAoB,MAAM,yBAAyB,CAAC;AAYxF,MAAM,MAAM,eAAe,GAAG;IAC5B,0FAA0F;IAC1F,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,kEAAkE;IAClE,IAAI,CAAC,EAAE,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;IACvD,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,CACA;IACE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AACH,gEAAgE;GAC9D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CACpB,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,EACf,GAAG,SAAa,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAcR;AAeD,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAIrF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAyEhD"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { HoverCard, HoverCardContent, HoverCardTrigger } from "./hover-card.js";
4
4
  import { useHydrated } from "../hooks/use-hydrated.js";
5
5
  const DAY = 86_400_000;
@@ -27,6 +27,17 @@ export function formatRecordTime(at, locale, now = Date.now(), timeZone) {
27
27
  shown.year = "numeric";
28
28
  return new Intl.DateTimeFormat(locale, shown).format(at);
29
29
  }
30
+ function offsetLabel(at, locale, timeZone) {
31
+ return new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: "shortOffset" })
32
+ .formatToParts(at)
33
+ .find((part) => part.type === "timeZoneName")?.value;
34
+ }
35
+ function exactMoment(at, locale, timeZone) {
36
+ return {
37
+ date: new Intl.DateTimeFormat(locale, { dateStyle: "long", timeZone }).format(at),
38
+ time: new Intl.DateTimeFormat(locale, { timeStyle: "medium", timeZone }).format(at),
39
+ };
40
+ }
30
41
  /** The moment `at` names, or null when it names none, such as an empty or malformed time. */
31
42
  export function recordDate(at) {
32
43
  if (at == null)
@@ -39,35 +50,43 @@ export function recordDate(at) {
39
50
  * says what, or the time of day in a feed's time column.
40
51
  *
41
52
  * @family Data
42
- * @when The moment a record was made, changed or last ran, in its row or its facts ("Updated 3 hours ago"), and the time of each event in an ActivityFeed or a RunTimeline step (`mode="clock"`).
43
- * @instead A date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product ("Took 4 min").
44
- * @behaviour Relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows the exact moment in UTC and in the viewer's zone. A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws nothing.
45
- * @words The product writes the sentence through `phrase` ("Updated {when}", "Ran {when}"); the clock needs no words. The package formats every date with the person's `locale`.
46
- * @access A `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
53
+ * @when "Use `<RelativeTimeCard>` anywhere a recent timestamp appears in scannable surfaces: `Table` cells, `Entity` rows, deploy lists, activity feeds." (https://vercel.com/geist/relative-time-card)
54
+ * Ours: `RelativeTimeCard` is `RecordTime`: the moment a record was made, changed or last ran, in its row or its facts, and the time of each event in an ActivityFeed or a RunTimeline step (`mode="clock"`).
55
+ * @instead "For a static date in body prose past 7 days, render `Mar 14, 2026` directly." (https://vercel.com/geist/relative-time-card)
56
+ * Ours: a date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product (*Took 4 min*).
57
+ * @behaviour "The hover card already shows absolute UTC and local time, so don’t duplicate that copy elsewhere on the row." (https://vercel.com/geist/relative-time-card)
58
+ * Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing.
59
+ * @words "Pass `date` as a number (Unix ms or epoch)." "Don’t pre-format the value, and don’t replace `children` with a formatted string." "The component’s short formatter is the canonical form (`2m`, `5h`, `Yesterday`)." "Don’t append `ago` after the component." "The formatter already produces `2m ago` / `5h ago`, so `<RelativeTimeCard /> ago` reads as `2m ago ago`." "Use `children` only for non-time labels (`Just now`, `Pending`, `Queued`) where the formatter can’t describe the state." "Pair with a leading label when the row is ambiguous on its own: `Last deploy <RelativeTimeCard date={ts} />`." (https://vercel.com/geist/relative-time-card)
60
+ * Ours: `at` takes a Date, epoch milliseconds or an ISO string, never a display string such as *3 hours ago*. The reading is the locale's long form (*3 hours ago*, *12 Sep*), not `2m`. The product writes the sentence through `phrase` (*Updated {when}*, *Ran {when}*), so *ago* is never added after it; the clock needs no words. The package formats every date with the person's `locale`.
61
+ * @access Ours: a `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
47
62
  */
48
63
  export function RecordTime(props) {
49
64
  const { at, locale, now } = props;
50
65
  const hydrated = useHydrated();
51
66
  const timeZone = props.timeZone ?? (hydrated ? undefined : "UTC");
52
67
  const date = recordDate(at);
53
- if (!date)
54
- return null;
55
- const inZone = new Intl.DateTimeFormat(locale, {
68
+ if (!date) {
69
+ return props.children ? (_jsx("span", { className: "whitespace-nowrap text-muted-foreground", "data-slot": "record-time", children: props.children })) : null;
70
+ }
71
+ const local = new Intl.DateTimeFormat(locale, {
56
72
  dateStyle: "long",
57
73
  timeStyle: "medium",
58
74
  timeZone,
59
- });
60
- const local = inZone.format(date);
61
- const utc = new Intl.DateTimeFormat(locale, {
62
- dateStyle: "long",
63
- timeStyle: "medium",
64
- timeZone: "UTC",
65
75
  }).format(date);
76
+ const exactRows = [
77
+ { id: "utc", zone: "UTC", ...exactMoment(date, locale, "UTC") },
78
+ {
79
+ id: "viewer",
80
+ zone: offsetLabel(date, locale, timeZone) ?? "UTC",
81
+ ...exactMoment(date, locale, timeZone),
82
+ },
83
+ ];
66
84
  const clock = props.mode === "clock";
67
- const shown = clock
68
- ? new Intl.DateTimeFormat(locale, { timeStyle: "short", timeZone }).format(date)
69
- : props.phrase(formatRecordTime(date, locale, now, timeZone));
85
+ const shown = props.children ??
86
+ (clock
87
+ ? new Intl.DateTimeFormat(locale, { timeStyle: "short", timeZone }).format(date)
88
+ : props.phrase(formatRecordTime(date, locale, now, timeZone)));
70
89
  return (_jsxs(HoverCard, { children: [_jsxs(HoverCardTrigger, { render: _jsx("time", { className: clock
71
90
  ? "whitespace-nowrap tabular-nums text-muted-foreground"
72
- : "whitespace-nowrap text-muted-foreground", "data-slot": "record-time", dateTime: date.toISOString() }), children: [shown, _jsxs("span", { className: "sr-only", children: [", ", local] })] }), _jsx(HoverCardContent, { className: "w-auto", children: _jsxs("dl", { className: "grid grid-cols-[auto_auto] gap-x-4 gap-y-1 text-xs", "data-slot": "record-time-exact", children: [_jsx("dt", { className: "text-muted-foreground", children: "UTC" }), _jsx("dd", { className: "tabular-nums", children: utc }), _jsx("dt", { className: "text-muted-foreground", children: inZone.resolvedOptions().timeZone }), _jsx("dd", { className: "tabular-nums", children: local })] }) })] }));
91
+ : "whitespace-nowrap text-muted-foreground", "data-slot": "record-time", dateTime: date.toISOString() }), children: [shown, _jsxs("span", { className: "sr-only", children: [", ", local] })] }), _jsx(HoverCardContent, { side: props.side, sideOffset: 13, children: _jsxs("div", { className: "grid min-w-75 gap-3 text-body-compact", "data-slot": "record-time-exact", children: [_jsx("p", { className: "text-muted-foreground tabular-nums", children: formatRecordTime(date, locale, now, timeZone) }), _jsx("dl", { className: "grid gap-2", children: exactRows.map((row) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("dt", { className: "inline-flex h-4 items-center rounded-xs bg-recessed px-1.5 font-label-mono text-label-mono text-muted-foreground", children: row.zone }), _jsxs("dd", { className: "flex min-w-0 flex-1 items-center justify-between gap-3", children: [_jsx("span", { children: row.date }), _jsx("span", { className: "font-label-mono text-label-mono text-muted-foreground tabular-nums", children: row.time })] })] }, row.id))) })] }) })] }));
73
92
  }
@@ -3,15 +3,17 @@ import * as ResizablePrimitive from "react-resizable-panels";
3
3
  * Panels a person resizes by dragging the handle between them.
4
4
  *
5
5
  * @family Other
6
- * @when Side-by-side panes whose balance a person sets: a conversation and its side panel.
7
- * @instead The product frame's sidebar resizes through `DashboardShell` or `DesktopAppShell`.
8
- * @behaviour The handle moves on drag and on arrow keys; each panel keeps its minimum and maximum.
9
- * @words None of its own.
10
- * @access The handle is the resizable library's focusable separator.
6
+ * @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
7
+ * @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column.
8
+ * @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum and maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px reach on each side; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else.
9
+ * @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
10
+ * @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
11
11
  */
12
12
  declare function ResizablePanelGroup({ className, ...props }: ResizablePrimitive.GroupProps): import("react").JSX.Element;
13
13
  declare function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps): import("react").JSX.Element;
14
14
  declare function ResizableHandle({ withHandle, className, ...props }: ResizablePrimitive.SeparatorProps & {
15
+ /** Names the handle for assistive technology: "Resize the side panel". */
16
+ "aria-label": string;
15
17
  withHandle?: boolean;
16
18
  }): import("react").JSX.Element;
17
19
  export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -1 +1 @@
1
- {"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../src/components/resizable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,kBAAkB,MAAM,wBAAwB,CAAC;AAI7D;;;;;;;;;GASG;AACH,iBAAS,mBAAmB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BASlF;AAED,iBAAS,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BAElE;AAED,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,cAAc,GAAG;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,+BAaA;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../src/components/resizable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,kBAAkB,MAAM,wBAAwB,CAAC;AAI7D;;;;;;;;;GASG;AACH,iBAAS,mBAAmB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BASlF;AAED,iBAAS,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BAElE;AAED,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,cAAc,GAAG;IACrC,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,+BAaA;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC"}
@@ -6,11 +6,11 @@ import { cn } from "../lib/utils.js";
6
6
  * Panels a person resizes by dragging the handle between them.
7
7
  *
8
8
  * @family Other
9
- * @when Side-by-side panes whose balance a person sets: a conversation and its side panel.
10
- * @instead The product frame's sidebar resizes through `DashboardShell` or `DesktopAppShell`.
11
- * @behaviour The handle moves on drag and on arrow keys; each panel keeps its minimum and maximum.
12
- * @words None of its own.
13
- * @access The handle is the resizable library's focusable separator.
9
+ * @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
10
+ * @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column.
11
+ * @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum and maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px reach on each side; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else.
12
+ * @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
13
+ * @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
14
14
  */
15
15
  function ResizablePanelGroup({ className, ...props }) {
16
16
  return (_jsx(ResizablePrimitive.Group, { "data-slot": "resizable-panel-group", className: cn("flex h-full w-full aria-[orientation=vertical]:flex-col", className), ...props }));
@@ -19,6 +19,6 @@ function ResizablePanel({ ...props }) {
19
19
  return _jsx(ResizablePrimitive.Panel, { "data-slot": "resizable-panel", ...props });
20
20
  }
21
21
  function ResizableHandle({ withHandle, className, ...props }) {
22
- return (_jsx(ResizablePrimitive.Separator, { "data-slot": "resizable-handle", className: cn("relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90", className), ...props, children: withHandle && _jsx("div", { className: "z-10 flex h-6 w-1 shrink-0 rounded-full bg-border" }) }));
22
+ return (_jsx(ResizablePrimitive.Separator, { "data-slot": "resizable-handle", className: cn("relative flex w-px items-center justify-center bg-border nc-transition-paint data-[separator=active]:bg-ring data-[separator=focus]:bg-ring data-[separator=hover]:bg-ring after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90", className), ...props, children: withHandle && _jsx("div", { className: "z-10 flex h-6 w-1 shrink-0 rounded-full bg-border" }) }));
23
23
  }
24
24
  export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -9,6 +9,8 @@ export type ScopeSwitcherCopy = {
9
9
  label: string;
10
10
  search: string;
11
11
  empty: string;
12
+ /** The sentence a screen reader hears as the list narrows, from the catalogue: "3 results". */
13
+ results: (count: number) => string;
12
14
  };
13
15
  export type ScopeSwitcherProps = {
14
16
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"scope-switcher.d.ts","sourceRoot":"","sources":["../../src/components/scope-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,8DAA8D;IAC9D,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAClD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,kBAAkB,qBA6FhG"}
1
+ {"version":3,"file":"scope-switcher.d.ts","sourceRoot":"","sources":["../../src/components/scope-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,+FAA+F;IAC/F,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,8DAA8D;IAC9D,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAClD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,kBAAkB,qBA6FhG"}
@@ -34,11 +34,11 @@ export function ScopeSwitcher({ value, options, onValueChange, copy, create }) {
34
34
  onValueChange(next);
35
35
  };
36
36
  const switchable = options.length > 1 || create !== undefined;
37
- return (_jsxs("span", { "data-slot": "scope-switcher", className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { "aria-hidden": switchable ? "true" : undefined, className: "text-xs font-medium text-muted-foreground", children: copy.label }), switchable ? (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(Button, { variant: "ghost", "aria-label": `${copy.label}: ${currentLabel}`, className: "max-w-64" }), children: [_jsx("span", { className: "truncate", children: currentLabel }), _jsx(ChevronsUpDown, { "data-icon": "inline-end", "aria-hidden": "true" })] }), _jsxs(PopoverContent, { align: "start", className: "w-72 p-0", initialFocus: search, children: [_jsx(PopoverTitle, { className: "sr-only", children: copy.label }), _jsxs(Command, { label: copy.search, children: [_jsx(CommandInput, { ref: search, "aria-label": copy.search, placeholder: copy.search }), _jsxs(CommandList, { label: copy.label, children: [_jsx(CommandEmpty, { children: copy.empty }), groups.map(([group, items]) => (_jsx(CommandGroup, { heading: group, children: items.map((option) => (_jsx(CommandItem, { value: option.value, keywords: [
37
+ return (_jsxs("span", { "data-slot": "scope-switcher", className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { "aria-hidden": switchable ? "true" : undefined, className: "text-xs font-medium text-muted-foreground", children: copy.label }), switchable ? (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(Button, { variant: "ghost", className: "max-w-64", suffix: _jsx(ChevronsUpDown, { "aria-hidden": "true" }) }), children: [_jsxs("span", { className: "sr-only", children: [copy.label, ":"] }), " ", _jsx("span", { className: "truncate", children: currentLabel })] }), _jsxs(PopoverContent, { align: "start", className: "w-72 p-0", initialFocus: search, children: [_jsx(PopoverTitle, { className: "sr-only", children: copy.label }), _jsxs(Command, { label: copy.search, resultCount: copy.results, children: [_jsx(CommandInput, { ref: search, "aria-label": copy.search, placeholder: copy.search }), _jsxs(CommandList, { label: copy.label, children: [_jsx(CommandEmpty, { children: copy.empty }), groups.map(([group, items]) => (_jsx(CommandGroup, { heading: group, children: items.map((option) => (_jsx(CommandItem, { value: option.value, keywords: [
38
38
  option.label,
39
39
  ...(option.group ? [option.group] : []),
40
40
  ...(option.keywords ?? []),
41
- ], "data-checked": option.value === value, onSelect: () => choose(option.value), children: _jsx("span", { className: "truncate", children: option.label }) }, option.value))) }, group ?? ""))), create ? (_jsxs(_Fragment, { children: [_jsx(CommandSeparator, { alwaysRender: true }), _jsx(CommandGroup, { forceMount: true, children: _jsxs(CommandItem, { value: `create ${create.label}`, forceMount: true, onSelect: () => {
41
+ ], "data-checked": option.value === value, onSelect: () => choose(option.value), children: _jsx("span", { className: "truncate", children: option.label }) }, option.value))) }, group ?? ""))), create ? (_jsxs(_Fragment, { children: [_jsx(CommandSeparator, { alwaysRender: true }), _jsx(CommandGroup, { forceMount: true, heading: undefined, children: _jsxs(CommandItem, { value: `create ${create.label}`, forceMount: true, onSelect: () => {
42
42
  setOpen(false);
43
43
  create.onSelect();
44
44
  }, children: [_jsx(Plus, { "aria-hidden": "true" }), create.label] }) })] })) : null] })] })] })] })) : (_jsx("span", { className: "truncate px-3 text-sm", children: currentLabel }))] }));
@@ -1,18 +1,54 @@
1
1
  import * as React from "react";
2
2
  import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
3
+ type ButtonLabels = {
4
+ /** Names the move back and what moves, such as "Scroll installations left". */
5
+ previous: string;
6
+ /** Names the move forward and what moves, such as "Scroll installations right". */
7
+ next: string;
8
+ };
9
+ type ScrollAxes = {
10
+ overflow: "y" | "x" | "both";
11
+ buttonLabels?: undefined;
12
+ } | {
13
+ overflow: "y" | "x";
14
+ buttonLabels: ButtonLabels;
15
+ };
16
+ type ScrollAreaProps = Omit<ScrollAreaPrimitive.Root.Props, "children" | "render"> & ScrollAxes & {
17
+ children: React.ReactNode;
18
+ /** Classes of the element that holds the children; its children are what the buttons scroll to. */
19
+ contentClassName?: string | undefined;
20
+ /** Classes of the scrolling box alone, such as a border and radius; the buttons stay outside it. */
21
+ frameClassName?: string | undefined;
22
+ };
3
23
  /**
4
- * An area that scrolls with the product's own thin scrollbar.
24
+ * An area that scrolls along one axis, with a fade where more is waiting.
5
25
  *
6
26
  * @family Other
7
- * @when A bounded area whose content overflows on one axis: a side panel's list, a menu's long
8
- * body.
9
- * @instead A page scrolls as the document. A rail of slides is `Carousel`.
10
- * @behaviour The viewport scrolls natively, so wheel, touch and keyboard all reach it; the thin
11
- * scrollbar is drawn over the content.
12
- * @words None of its own.
13
- * @access The content keeps its own semantics; the scrollbar is paint.
27
+ * @when “Use Scroller for an overflowing list of peer items along a single axis: chip rows, log streams, code snippets, command palettes.” (https://vercel.com/geist/scroller)
28
+ * “Pick `vertical` for stacked feeds, `horizontal` for chip and tile rails, `free` only when content genuinely scrolls in both directions (logs with very long lines).” (https://vercel.com/geist/scroller)
29
+ * “For paginated or virtualized data sets larger than a few hundred items, render with a virtualization library inside the Scroller rather than dumping every node into the DOM.” (https://vercel.com/geist/scroller)
30
+ * Ours: Geist's `Scroller` is `ScrollArea`, and `vertical`, `horizontal` and `free` are `overflow="y"`,
31
+ * `"x"` and `"both"`. A bounded area whose content overflows: a side panel's list, a menu's long
32
+ * body, a rail of chips or logos.
33
+ * @instead Ours: a page scrolls as the document. A sequence of slides on the website is `Carousel`.
34
+ * @behaviour “Buttons will automatically scroll to a given **direct** child.” (https://vercel.com/geist/scroller)
35
+ * “Auto-scroll buttons target direct children only. If items are wrapped in extra layout nodes the buttons won’t find their target.” (https://vercel.com/geist/scroller)
36
+ * “Show edge fade or shadow affordances on the clipped axis so users see there’s more content past the viewport.” (https://vercel.com/geist/scroller)
37
+ * “Keep item widths and gaps consistent in horizontal scrollers; ragged edges break the snap rhythm and make the rail feel broken.” (https://vercel.com/geist/scroller)
38
+ * Ours: `overflow` is required. Give the area its height or width with `className`, and a border or
39
+ * radius with `frameClassName`, which draws only the scrolling box and leaves the buttons outside
40
+ * it. The scrollbar is hidden; a 40 px fade of the surface at each clipped edge is the only sign
41
+ * there is more, and it is gone at an edge with nothing beyond it. The viewport scrolls natively, so
42
+ * wheel, touch and keyboard all reach it. `buttonLabels` adds two round 32 px outline buttons, 16 px
43
+ * from the area: above it and centred for `y`, below it and at the start for `x`. They sit disabled
44
+ * at the ends. Smooth scrolling gives way to an instant jump under reduced motion. Colour is neutral
45
+ * only.
46
+ * @words “Scroller buttons need `aria-label`s that name the direction and content (`Scroll customer logos left`), not bare `Previous`/`Next`.” (https://vercel.com/geist/scroller)
47
+ * Ours: *Scroll installations left*; both labels are required with the buttons.
48
+ * @access “Tab order follows DOM order, so place items in reading order regardless of visual scroll direction.” (https://vercel.com/geist/scroller)
49
+ * “Make sure focusing an off-screen item scrolls it into view; the default browser behavior covers this, but custom focus traps can break it.” (https://vercel.com/geist/scroller)
50
+ * Ours: the content keeps its own semantics. The viewport is a tab stop when it scrolls.
14
51
  */
15
- declare function ScrollArea({ className, children, ...props }: ScrollAreaPrimitive.Root.Props): React.JSX.Element;
16
- declare function ScrollBar({ className, orientation, ...props }: ScrollAreaPrimitive.Scrollbar.Props): React.JSX.Element;
17
- export { ScrollArea, ScrollBar };
52
+ declare function ScrollArea({ className, children, contentClassName, frameClassName, overflow, buttonLabels, ...props }: ScrollAreaProps): React.JSX.Element;
53
+ export { ScrollArea };
18
54
  //# sourceMappingURL=scroll-area.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAI/E;;;;;;;;;;;GAWG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,qBAiBpF;AAED,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,WAAwB,EACxB,GAAG,KAAK,EACT,EAAE,mBAAmB,CAAC,SAAS,CAAC,KAAK,qBAkBrC;AAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAM/E,KAAK,YAAY,GAAG;IAClB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,UAAU,GACX;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GAC1D;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,CAAC;AAExD,KAAK,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC,GAChF,UAAU,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,CAAC;AAmCJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,eAAe,qBAyEjB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -1,22 +1,80 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
2
4
  import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
5
+ import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from "lucide-react";
6
+ import { Button } from "./button.js";
3
7
  import { cn } from "../lib/utils.js";
8
+ const viewportAxis = {
9
+ y: "overflow-x-hidden! [mask-image:linear-gradient(to_bottom,transparent,black_min(2.5rem,var(--scroll-area-overflow-y-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-y-end,0px))),transparent)]",
10
+ x: "overflow-y-hidden! [mask-image:linear-gradient(to_right,transparent,black_min(2.5rem,var(--scroll-area-overflow-x-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-x-end,0px))),transparent)]",
11
+ both: "[mask-composite:intersect] [mask-image:linear-gradient(to_bottom,transparent,black_min(2.5rem,var(--scroll-area-overflow-y-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-y-end,0px))),transparent),linear-gradient(to_right,transparent,black_min(2.5rem,var(--scroll-area-overflow-x-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-x-end,0px))),transparent)]",
12
+ };
13
+ function scrollToNeighbour(viewport, content, axis, direction) {
14
+ const edges = (box) => axis === "y" ? { start: box.top, end: box.bottom } : { start: box.left, end: box.right };
15
+ const view = edges(viewport.getBoundingClientRect());
16
+ const items = Array.from(content.children, (child) => edges(child.getBoundingClientRect()));
17
+ const target = direction === "next"
18
+ ? items.find((item) => item.end > view.end + 1)
19
+ : items.reverse().find((item) => item.start < view.start - 1);
20
+ if (!target)
21
+ return;
22
+ const distance = direction === "next"
23
+ ? Math.min(target.end - view.end, target.start - view.start)
24
+ : target.start - view.start;
25
+ viewport.scrollBy(axis === "y" ? { top: distance } : { left: distance });
26
+ }
27
+ const buttonIcons = {
28
+ x: { previous: ChevronLeftIcon, next: ChevronRightIcon },
29
+ y: { previous: ChevronUpIcon, next: ChevronDownIcon },
30
+ };
4
31
  /**
5
- * An area that scrolls with the product's own thin scrollbar.
32
+ * An area that scrolls along one axis, with a fade where more is waiting.
6
33
  *
7
34
  * @family Other
8
- * @when A bounded area whose content overflows on one axis: a side panel's list, a menu's long
9
- * body.
10
- * @instead A page scrolls as the document. A rail of slides is `Carousel`.
11
- * @behaviour The viewport scrolls natively, so wheel, touch and keyboard all reach it; the thin
12
- * scrollbar is drawn over the content.
13
- * @words None of its own.
14
- * @access The content keeps its own semantics; the scrollbar is paint.
35
+ * @when “Use Scroller for an overflowing list of peer items along a single axis: chip rows, log streams, code snippets, command palettes.” (https://vercel.com/geist/scroller)
36
+ * “Pick `vertical` for stacked feeds, `horizontal` for chip and tile rails, `free` only when content genuinely scrolls in both directions (logs with very long lines).” (https://vercel.com/geist/scroller)
37
+ * “For paginated or virtualized data sets larger than a few hundred items, render with a virtualization library inside the Scroller rather than dumping every node into the DOM.” (https://vercel.com/geist/scroller)
38
+ * Ours: Geist's `Scroller` is `ScrollArea`, and `vertical`, `horizontal` and `free` are `overflow="y"`,
39
+ * `"x"` and `"both"`. A bounded area whose content overflows: a side panel's list, a menu's long
40
+ * body, a rail of chips or logos.
41
+ * @instead Ours: a page scrolls as the document. A sequence of slides on the website is `Carousel`.
42
+ * @behaviour “Buttons will automatically scroll to a given **direct** child.” (https://vercel.com/geist/scroller)
43
+ * “Auto-scroll buttons target direct children only. If items are wrapped in extra layout nodes the buttons won’t find their target.” (https://vercel.com/geist/scroller)
44
+ * “Show edge fade or shadow affordances on the clipped axis so users see there’s more content past the viewport.” (https://vercel.com/geist/scroller)
45
+ * “Keep item widths and gaps consistent in horizontal scrollers; ragged edges break the snap rhythm and make the rail feel broken.” (https://vercel.com/geist/scroller)
46
+ * Ours: `overflow` is required. Give the area its height or width with `className`, and a border or
47
+ * radius with `frameClassName`, which draws only the scrolling box and leaves the buttons outside
48
+ * it. The scrollbar is hidden; a 40 px fade of the surface at each clipped edge is the only sign
49
+ * there is more, and it is gone at an edge with nothing beyond it. The viewport scrolls natively, so
50
+ * wheel, touch and keyboard all reach it. `buttonLabels` adds two round 32 px outline buttons, 16 px
51
+ * from the area: above it and centred for `y`, below it and at the start for `x`. They sit disabled
52
+ * at the ends. Smooth scrolling gives way to an instant jump under reduced motion. Colour is neutral
53
+ * only.
54
+ * @words “Scroller buttons need `aria-label`s that name the direction and content (`Scroll customer logos left`), not bare `Previous`/`Next`.” (https://vercel.com/geist/scroller)
55
+ * Ours: *Scroll installations left*; both labels are required with the buttons.
56
+ * @access “Tab order follows DOM order, so place items in reading order regardless of visual scroll direction.” (https://vercel.com/geist/scroller)
57
+ * “Make sure focusing an off-screen item scrolls it into view; the default browser behavior covers this, but custom focus traps can break it.” (https://vercel.com/geist/scroller)
58
+ * Ours: the content keeps its own semantics. The viewport is a tab stop when it scrolls.
15
59
  */
16
- function ScrollArea({ className, children, ...props }) {
17
- return (_jsxs(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", className: cn("relative", className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { "data-slot": "scroll-area-viewport", className: "size-full rounded-[inherit] transition-colors", children: children }), _jsx(ScrollBar, {}), _jsx(ScrollAreaPrimitive.Corner, {})] }));
18
- }
19
- function ScrollBar({ className, orientation = "vertical", ...props }) {
20
- return (_jsx(ScrollAreaPrimitive.Scrollbar, { "data-slot": "scroll-area-scrollbar", "data-orientation": orientation, orientation: orientation, className: cn("flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent", className), ...props, children: _jsx(ScrollAreaPrimitive.Thumb, { "data-slot": "scroll-area-thumb", className: "relative flex-1 rounded-full bg-border" }) }));
60
+ function ScrollArea({ className, children, contentClassName, frameClassName, overflow, buttonLabels, ...props }) {
61
+ const viewport = React.useRef(null);
62
+ const content = React.useRef(null);
63
+ const axis = overflow === "y" ? "y" : "x";
64
+ const buttons = (disabled) => buttonLabels ? (_jsx("div", { className: cn("m-px flex gap-2", axis === "y" ? "justify-center" : "justify-start"), "data-slot": "scroll-area-buttons", children: ["previous", "next"].map((direction) => {
65
+ const Icon = buttonIcons[axis][direction];
66
+ return (_jsx(Button, { "aria-label": buttonLabels[direction], disabled: disabled[direction], onClick: () => {
67
+ if (viewport.current && content.current) {
68
+ scrollToNeighbour(viewport.current, content.current, axis, direction);
69
+ }
70
+ }, shape: "circle", size: "icon-sm", variant: "outline", children: _jsx(Icon, { "aria-hidden": "true" }) }, direction));
71
+ }) })) : null;
72
+ return (_jsx(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", className: cn("relative flex flex-col gap-4", className), render: (rootProps, state) => {
73
+ const row = buttons({
74
+ previous: axis === "y" ? !state.overflowYStart : !state.overflowXStart,
75
+ next: axis === "y" ? !state.overflowYEnd : !state.overflowXEnd,
76
+ });
77
+ return (_jsxs("div", { ...rootProps, children: [axis === "y" ? row : null, _jsx("div", { className: cn("relative min-h-0 flex-1 rounded-[inherit]", frameClassName), children: rootProps.children }), axis === "x" ? row : null] }));
78
+ }, ...props, children: _jsx(ScrollAreaPrimitive.Viewport, { ref: viewport, "data-slot": "scroll-area-viewport", className: cn("size-full scroll-smooth rounded-[inherit] transition-colors motion-reduce:scroll-auto", viewportAxis[overflow]), children: _jsx(ScrollAreaPrimitive.Content, { ref: content, "data-slot": "scroll-area-content", className: contentClassName, children: children }) }) }));
21
79
  }
22
- export { ScrollArea, ScrollBar };
80
+ export { ScrollArea };
@@ -0,0 +1,82 @@
1
+ import * as React from "react";
2
+ import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
3
+ export type SegmentedControlSize = "sm" | "default" | "lg";
4
+ export type SegmentedOption<Value extends string = string> = {
5
+ value: Value;
6
+ /** The option's name. An icon-only option shows it as a tooltip and keeps it as its accessible name. */
7
+ label: string;
8
+ disabled?: boolean;
9
+ } & ({
10
+ icon?: undefined;
11
+ iconOnly?: undefined;
12
+ } | {
13
+ icon: React.ReactElement;
14
+ iconOnly?: boolean;
15
+ });
16
+ export type SegmentedOptions<Value extends string = string> = readonly [SegmentedOption<Value>, SegmentedOption<Value>] | readonly [SegmentedOption<Value>, SegmentedOption<Value>, SegmentedOption<Value>];
17
+ export type SegmentedControlProps<Value extends string = string> = Omit<RadioGroupPrimitive.Props<Value>, "aria-label" | "aria-labelledby" | "children" | "defaultValue" | "onValueChange" | "readOnly" | "render" | "required" | "value"> & {
18
+ options: SegmentedOptions<Value>;
19
+ size?: SegmentedControlSize;
20
+ /** Stretches the control to its container, with the options sharing the width equally. */
21
+ fullWidth?: boolean;
22
+ } & ({
23
+ "aria-label": string;
24
+ "aria-labelledby"?: undefined;
25
+ } | {
26
+ "aria-labelledby": string;
27
+ "aria-label"?: undefined;
28
+ }) & ({
29
+ value: Value;
30
+ defaultValue?: undefined;
31
+ onValueChange: (value: Value) => void;
32
+ } | {
33
+ defaultValue: Value;
34
+ value?: undefined;
35
+ onValueChange?: (value: Value) => void;
36
+ });
37
+ /**
38
+ * Two or three options that show different views of one surface, the chosen one filled.
39
+ *
40
+ * @family Choices
41
+ * @when "Use Switch as a segmented selector for 2–3 mutually exclusive options that show different
42
+ * views of the same surface, like `Source` vs `Output`." (https://vercel.com/geist/switch) Ours:
43
+ * Geist's `Switch` is our `SegmentedControl`.
44
+ * @instead "For a boolean on/off setting, use `Toggle`." (https://vercel.com/geist/switch) "Switch
45
+ * implements radio semantics, so two options stay mutually exclusive rather than reading as a
46
+ * checkbox." (https://vercel.com/geist/switch) "Past 3 options or when labels grow beyond a couple
47
+ * of words, switch to `Tabs` or a `Select`." (https://vercel.com/geist/switch) Ours: Geist's
48
+ * `Toggle` is our `Switch`. The theme is `ThemeModeSwitcher`, never a second picker. Four to six
49
+ * that must be compared are a `RadioGroup`. Pressed buttons that can be several or none are a
50
+ * `ToggleGroup`. Panels of one object are `Tabs`.
51
+ * @behaviour "Pass a `name` so the underlying radios are grouped; without it, more than one option
52
+ * can appear selected at once." (https://vercel.com/geist/switch) "Set `defaultChecked` (or
53
+ * controlled `checked`) on exactly one `Switch.Control` so the group has a defined initial state."
54
+ * (https://vercel.com/geist/switch) "Pad each `Switch.Control` so the widest label fits without the
55
+ * active pill resizing on selection." (https://vercel.com/geist/switch) "Test with the longest copy
56
+ * in the set." (https://vercel.com/geist/switch) Ours: the group's name (`aria-label` or
57
+ * `aria-labelledby`), a label on every option and a starting choice (`defaultValue` or `value`) are
58
+ * required; without them it does not compile. The options are one radio group, so they stay
59
+ * exclusive without a form `name`. The
60
+ * options share the width of the widest, so the fill never resizes as the choice moves; where the
61
+ * row is narrower than that, each option keeps its own word's width rather than cutting it. The track
62
+ * is white with a hairline and a 4 px inset, so it is 32, 36 or 40 px high around options of 24, 28
63
+ * or 32 px. Colour: neutral throughout, the chosen option filled grey with ink words and the others
64
+ * grey words that turn ink on hover; nothing takes a hue. Icons are 16 px, 20 px at `lg`. A
65
+ * disabled option keeps the chosen fill, lightens only its words and has no hover change. The
66
+ * options are radios in one group: arrows move and choose, and pressing the chosen one changes
67
+ * nothing. It applies at once; it is not a field that waits for a Save. `fullWidth` when it heads a
68
+ * form or a dialog, as the two-factor form's method switch does.
69
+ * @words "Title Case each `Switch.Control` label." (https://vercel.com/geist/switch) "Keep labels
70
+ * to one or two words and parallel: `Source` / `Output`, not `Source` / `Show output`."
71
+ * (https://vercel.com/geist/switch) Ours: sentence case: *Source*, *Output*.
72
+ * @access "Always provide a `label` on every `Switch.Control`, even when an `icon` carries the
73
+ * meaning, so screen readers announce the option." (https://vercel.com/geist/switch) "The component
74
+ * renders it as `geist-sr-only` for icon-only controls." (https://vercel.com/geist/switch) "Pair an
75
+ * icon-only Switch with a `Tooltip` on each control so sighted users get the same label assistive
76
+ * tech receives." (https://vercel.com/geist/switch) Ours: `role="radiogroup"` named by `aria-label`
77
+ * or `aria-labelledby`; each option a radio named by its label, shown as a tooltip on an icon-only
78
+ * option.
79
+ */
80
+ declare function SegmentedControl<Value extends string = string>({ options, size, fullWidth, className, ...props }: SegmentedControlProps<Value>): React.JSX.Element;
81
+ export { SegmentedControl };
82
+ //# sourceMappingURL=segmented-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../src/components/segmented-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AA6C/E,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;AAE3D,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI;IAC3D,KAAK,EAAE,KAAK,CAAC;IACb,wGAAwG;IACxG,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,CAAC;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEpG,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IACtD,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,GACzD,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;AAEtF,MAAM,MAAM,qBAAqB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CACrE,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,EAC9B,YAAY,GACZ,iBAAiB,GACjB,UAAU,GACV,cAAc,GACd,eAAe,GACf,UAAU,GACV,QAAQ,GACR,UAAU,GACV,OAAO,CACV,GAAG;IACF,OAAO,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,0FAA0F;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,CACE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,CAC1D,GACD,CACI;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GACjF;IAAE,YAAY,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,CACrF,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,iBAAS,gBAAgB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,EACvD,OAAO,EACP,IAAgB,EAChB,SAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,qBAAqB,CAAC,KAAK,CAAC,qBAkC9B;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}