@nadicodeai/ui 12.1.101 → 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 (567) 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.d.ts +18 -18
  5. package/dist/components/account-menu.d.ts.map +1 -1
  6. package/dist/components/account-menu.js +17 -13
  7. package/dist/components/action-menu.d.ts +20 -19
  8. package/dist/components/action-menu.d.ts.map +1 -1
  9. package/dist/components/action-menu.js +22 -15
  10. package/dist/components/action-status.d.ts +14 -10
  11. package/dist/components/action-status.d.ts.map +1 -1
  12. package/dist/components/action-status.js +14 -10
  13. package/dist/components/activity-calendar.d.ts +3 -1
  14. package/dist/components/activity-calendar.d.ts.map +1 -1
  15. package/dist/components/activity-calendar.js +16 -2
  16. package/dist/components/activity-feed.d.ts +2 -2
  17. package/dist/components/activity-feed.d.ts.map +1 -1
  18. package/dist/components/activity-feed.js +14 -5
  19. package/dist/components/agent-card.d.ts +11 -5
  20. package/dist/components/agent-card.d.ts.map +1 -1
  21. package/dist/components/agent-card.js +13 -7
  22. package/dist/components/agent-list-row.js +1 -1
  23. package/dist/components/agent-orb-appearance.d.ts +7 -1
  24. package/dist/components/agent-orb-appearance.d.ts.map +1 -1
  25. package/dist/components/agent-orb-appearance.js +26 -0
  26. package/dist/components/agent-profile.d.ts +8 -7
  27. package/dist/components/agent-profile.d.ts.map +1 -1
  28. package/dist/components/agent-profile.js +6 -6
  29. package/dist/components/alert-dialog.d.ts +25 -16
  30. package/dist/components/alert-dialog.d.ts.map +1 -1
  31. package/dist/components/alert-dialog.js +30 -18
  32. package/dist/components/alert.d.ts +1 -1
  33. package/dist/components/avatar.d.ts +83 -17
  34. package/dist/components/avatar.d.ts.map +1 -1
  35. package/dist/components/avatar.js +89 -23
  36. package/dist/components/badge.d.ts +59 -8
  37. package/dist/components/badge.d.ts.map +1 -1
  38. package/dist/components/badge.js +57 -14
  39. package/dist/components/breadcrumb.d.ts +18 -7
  40. package/dist/components/breadcrumb.d.ts.map +1 -1
  41. package/dist/components/breadcrumb.js +37 -13
  42. package/dist/components/button-group.d.ts +12 -15
  43. package/dist/components/button-group.d.ts.map +1 -1
  44. package/dist/components/button-group.js +13 -17
  45. package/dist/components/button.d.ts +126 -23
  46. package/dist/components/button.d.ts.map +1 -1
  47. package/dist/components/button.js +164 -39
  48. package/dist/components/calendar.d.ts +26 -15
  49. package/dist/components/calendar.d.ts.map +1 -1
  50. package/dist/components/calendar.js +60 -46
  51. package/dist/components/card-row.d.ts +13 -5
  52. package/dist/components/card-row.d.ts.map +1 -1
  53. package/dist/components/card-row.js +24 -10
  54. package/dist/components/card.d.ts +6 -12
  55. package/dist/components/card.d.ts.map +1 -1
  56. package/dist/components/card.js +11 -16
  57. package/dist/components/carousel.d.ts +3 -3
  58. package/dist/components/carousel.d.ts.map +1 -1
  59. package/dist/components/carousel.js +7 -7
  60. package/dist/components/catalog-drawer.d.ts +7 -7
  61. package/dist/components/catalog-drawer.d.ts.map +1 -1
  62. package/dist/components/catalog-drawer.js +6 -6
  63. package/dist/components/chart-area-stacked.d.ts +1 -1
  64. package/dist/components/chart-area-stacked.d.ts.map +1 -1
  65. package/dist/components/chart-area-stacked.js +4 -4
  66. package/dist/components/chart-axis.d.ts +14 -1
  67. package/dist/components/chart-axis.d.ts.map +1 -1
  68. package/dist/components/chart-axis.js +11 -1
  69. package/dist/components/chart-bar-horizontal.d.ts +2 -2
  70. package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
  71. package/dist/components/chart-bar-horizontal.js +14 -5
  72. package/dist/components/chart-bar-multiple.d.ts +1 -1
  73. package/dist/components/chart-bar-multiple.d.ts.map +1 -1
  74. package/dist/components/chart-bar-multiple.js +3 -3
  75. package/dist/components/chart-bar-stacked.d.ts +1 -1
  76. package/dist/components/chart-bar-stacked.d.ts.map +1 -1
  77. package/dist/components/chart-bar-stacked.js +3 -3
  78. package/dist/components/chart-card.d.ts +17 -6
  79. package/dist/components/chart-card.d.ts.map +1 -1
  80. package/dist/components/chart-card.js +11 -4
  81. package/dist/components/chart-date-range-control.d.ts +18 -9
  82. package/dist/components/chart-date-range-control.d.ts.map +1 -1
  83. package/dist/components/chart-date-range-control.js +43 -47
  84. package/dist/components/chart-sparkline.d.ts +4 -3
  85. package/dist/components/chart-sparkline.d.ts.map +1 -1
  86. package/dist/components/chart-sparkline.js +6 -5
  87. package/dist/components/check-counts.d.ts +44 -0
  88. package/dist/components/check-counts.d.ts.map +1 -0
  89. package/dist/components/check-counts.js +51 -0
  90. package/dist/components/checkbox.d.ts +39 -11
  91. package/dist/components/checkbox.d.ts.map +1 -1
  92. package/dist/components/checkbox.js +38 -11
  93. package/dist/components/choicebox.d.ts +96 -0
  94. package/dist/components/choicebox.d.ts.map +1 -0
  95. package/dist/components/choicebox.js +113 -0
  96. package/dist/components/clearable-input.d.ts +57 -0
  97. package/dist/components/clearable-input.d.ts.map +1 -0
  98. package/dist/components/clearable-input.js +58 -0
  99. package/dist/components/code-block.d.ts +77 -17
  100. package/dist/components/code-block.d.ts.map +1 -1
  101. package/dist/components/code-block.js +85 -15
  102. package/dist/components/collapsible.d.ts +27 -10
  103. package/dist/components/collapsible.d.ts.map +1 -1
  104. package/dist/components/collapsible.js +24 -9
  105. package/dist/components/collection-filters.d.ts +3 -1
  106. package/dist/components/collection-filters.d.ts.map +1 -1
  107. package/dist/components/collection-filters.js +7 -9
  108. package/dist/components/collection-page.d.ts +31 -10
  109. package/dist/components/collection-page.d.ts.map +1 -1
  110. package/dist/components/collection-page.js +14 -13
  111. package/dist/components/collection-search.d.ts +32 -10
  112. package/dist/components/collection-search.d.ts.map +1 -1
  113. package/dist/components/collection-search.js +24 -13
  114. package/dist/components/collection-sort.d.ts.map +1 -1
  115. package/dist/components/collection-sort.js +2 -2
  116. package/dist/components/collection-toolbar.d.ts +5 -2
  117. package/dist/components/collection-toolbar.d.ts.map +1 -1
  118. package/dist/components/collection-toolbar.js +7 -4
  119. package/dist/components/combobox.d.ts +97 -22
  120. package/dist/components/combobox.d.ts.map +1 -1
  121. package/dist/components/combobox.js +80 -28
  122. package/dist/components/command.d.ts +34 -21
  123. package/dist/components/command.d.ts.map +1 -1
  124. package/dist/components/command.js +33 -25
  125. package/dist/components/confirm-dialog.d.ts +23 -6
  126. package/dist/components/confirm-dialog.d.ts.map +1 -1
  127. package/dist/components/confirm-dialog.js +32 -13
  128. package/dist/components/context-menu.d.ts +14 -10
  129. package/dist/components/context-menu.d.ts.map +1 -1
  130. package/dist/components/context-menu.js +17 -12
  131. package/dist/components/copy-button.d.ts +5 -2
  132. package/dist/components/copy-button.d.ts.map +1 -1
  133. package/dist/components/copy-button.js +16 -8
  134. package/dist/components/data-table.d.ts +120 -54
  135. package/dist/components/data-table.d.ts.map +1 -1
  136. package/dist/components/data-table.js +163 -92
  137. package/dist/components/desktop-shell.d.ts +4 -2
  138. package/dist/components/desktop-shell.d.ts.map +1 -1
  139. package/dist/components/desktop-shell.js +3 -3
  140. package/dist/components/dialog.d.ts +63 -24
  141. package/dist/components/dialog.d.ts.map +1 -1
  142. package/dist/components/dialog.js +52 -31
  143. package/dist/components/disclosure-row.d.ts +1 -2
  144. package/dist/components/disclosure-row.d.ts.map +1 -1
  145. package/dist/components/disclosure-row.js +1 -2
  146. package/dist/components/disclosure.d.ts +1 -1
  147. package/dist/components/disclosure.js +1 -1
  148. package/dist/components/drawer.d.ts +33 -12
  149. package/dist/components/drawer.d.ts.map +1 -1
  150. package/dist/components/drawer.js +47 -35
  151. package/dist/components/dropdown-menu.d.ts +59 -14
  152. package/dist/components/dropdown-menu.d.ts.map +1 -1
  153. package/dist/components/dropdown-menu.js +58 -26
  154. package/dist/components/empty-state.d.ts +35 -12
  155. package/dist/components/empty-state.d.ts.map +1 -1
  156. package/dist/components/empty-state.js +35 -17
  157. package/dist/components/entry-scene.d.ts +4 -4
  158. package/dist/components/entry-scene.d.ts.map +1 -1
  159. package/dist/components/entry-scene.js +2 -2
  160. package/dist/components/field.d.ts +44 -14
  161. package/dist/components/field.d.ts.map +1 -1
  162. package/dist/components/field.js +49 -20
  163. package/dist/components/file-diff.d.ts.map +1 -1
  164. package/dist/components/file-diff.js +3 -4
  165. package/dist/components/form-dialog.d.ts +7 -7
  166. package/dist/components/form-dialog.d.ts.map +1 -1
  167. package/dist/components/form-dialog.js +13 -11
  168. package/dist/components/form-drawer.d.ts +10 -7
  169. package/dist/components/form-drawer.d.ts.map +1 -1
  170. package/dist/components/form-drawer.js +11 -10
  171. package/dist/components/gauge.d.ts +64 -0
  172. package/dist/components/gauge.d.ts.map +1 -0
  173. package/dist/components/gauge.js +73 -0
  174. package/dist/components/hover-card.d.ts +72 -14
  175. package/dist/components/hover-card.d.ts.map +1 -1
  176. package/dist/components/hover-card.js +51 -17
  177. package/dist/components/identity-mark.d.ts +8 -1
  178. package/dist/components/identity-mark.d.ts.map +1 -1
  179. package/dist/components/identity-mark.js +31 -5
  180. package/dist/components/input-group.d.ts +44 -21
  181. package/dist/components/input-group.d.ts.map +1 -1
  182. package/dist/components/input-group.js +74 -27
  183. package/dist/components/input.d.ts +64 -12
  184. package/dist/components/input.d.ts.map +1 -1
  185. package/dist/components/input.js +51 -15
  186. package/dist/components/item.d.ts +37 -15
  187. package/dist/components/item.d.ts.map +1 -1
  188. package/dist/components/item.js +41 -22
  189. package/dist/components/kbd.d.ts +49 -13
  190. package/dist/components/kbd.d.ts.map +1 -1
  191. package/dist/components/kbd.js +115 -16
  192. package/dist/components/kpi-card.d.ts +12 -4
  193. package/dist/components/kpi-card.d.ts.map +1 -1
  194. package/dist/components/kpi-card.js +13 -4
  195. package/dist/components/label.d.ts +17 -10
  196. package/dist/components/label.d.ts.map +1 -1
  197. package/dist/components/label.js +18 -11
  198. package/dist/components/library-shelf.d.ts +6 -6
  199. package/dist/components/library-shelf.d.ts.map +1 -1
  200. package/dist/components/library-shelf.js +5 -5
  201. package/dist/components/load-more-button.d.ts +35 -0
  202. package/dist/components/load-more-button.d.ts.map +1 -0
  203. package/dist/components/load-more-button.js +26 -0
  204. package/dist/components/menu-choice-row.d.ts +6 -8
  205. package/dist/components/menu-choice-row.d.ts.map +1 -1
  206. package/dist/components/menu-choice-row.js +8 -8
  207. package/dist/components/message-notice.d.ts +8 -13
  208. package/dist/components/message-notice.d.ts.map +1 -1
  209. package/dist/components/message-notice.js +25 -22
  210. package/dist/components/middle-truncate.d.ts +33 -0
  211. package/dist/components/middle-truncate.d.ts.map +1 -0
  212. package/dist/components/middle-truncate.js +72 -0
  213. package/dist/components/multi-select.d.ts +94 -0
  214. package/dist/components/multi-select.d.ts.map +1 -0
  215. package/dist/components/multi-select.js +132 -0
  216. package/dist/components/native-select.d.ts +37 -13
  217. package/dist/components/native-select.d.ts.map +1 -1
  218. package/dist/components/native-select.js +27 -11
  219. package/dist/components/notice-banner.d.ts +17 -10
  220. package/dist/components/notice-banner.d.ts.map +1 -1
  221. package/dist/components/notice-banner.js +12 -11
  222. package/dist/components/numbered-steps.d.ts +10 -4
  223. package/dist/components/numbered-steps.d.ts.map +1 -1
  224. package/dist/components/numbered-steps.js +9 -7
  225. package/dist/components/object-page.d.ts +40 -14
  226. package/dist/components/object-page.d.ts.map +1 -1
  227. package/dist/components/object-page.js +12 -10
  228. package/dist/components/object-workspace.d.ts +29 -10
  229. package/dist/components/object-workspace.d.ts.map +1 -1
  230. package/dist/components/object-workspace.js +18 -8
  231. package/dist/components/overview-page.d.ts +2 -2
  232. package/dist/components/overview-page.d.ts.map +1 -1
  233. package/dist/components/overview-page.js +8 -7
  234. package/dist/components/page-actions.d.ts +28 -8
  235. package/dist/components/page-actions.d.ts.map +1 -1
  236. package/dist/components/page-actions.js +22 -25
  237. package/dist/components/page-header.d.ts +11 -4
  238. package/dist/components/page-header.d.ts.map +1 -1
  239. package/dist/components/page-header.js +10 -5
  240. package/dist/components/pending-label.d.ts +6 -5
  241. package/dist/components/pending-label.d.ts.map +1 -1
  242. package/dist/components/pending-label.js +14 -6
  243. package/dist/components/picture-label.d.ts +2 -2
  244. package/dist/components/picture-label.d.ts.map +1 -1
  245. package/dist/components/picture-label.js +3 -3
  246. package/dist/components/portal-sidebar-frame.d.ts +9 -21
  247. package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
  248. package/dist/components/portal-sidebar-frame.js +13 -27
  249. package/dist/components/progress-checklist.d.ts +46 -0
  250. package/dist/components/progress-checklist.d.ts.map +1 -0
  251. package/dist/components/progress-checklist.js +46 -0
  252. package/dist/components/progress.d.ts +48 -8
  253. package/dist/components/progress.d.ts.map +1 -1
  254. package/dist/components/progress.js +92 -16
  255. package/dist/components/prose.d.ts +19 -0
  256. package/dist/components/prose.d.ts.map +1 -0
  257. package/dist/components/prose.js +29 -0
  258. package/dist/components/radio-group.d.ts +51 -12
  259. package/dist/components/radio-group.d.ts.map +1 -1
  260. package/dist/components/radio-group.js +42 -12
  261. package/dist/components/reading-column.js +1 -1
  262. package/dist/components/record-identity.d.ts +6 -5
  263. package/dist/components/record-identity.d.ts.map +1 -1
  264. package/dist/components/record-identity.js +12 -3
  265. package/dist/components/record-list.d.ts +117 -27
  266. package/dist/components/record-list.d.ts.map +1 -1
  267. package/dist/components/record-list.js +185 -55
  268. package/dist/components/record-time.d.ts +20 -7
  269. package/dist/components/record-time.d.ts.map +1 -1
  270. package/dist/components/record-time.js +38 -19
  271. package/dist/components/resizable.d.ts +7 -5
  272. package/dist/components/resizable.d.ts.map +1 -1
  273. package/dist/components/resizable.js +6 -6
  274. package/dist/components/scope-switcher.d.ts +2 -0
  275. package/dist/components/scope-switcher.d.ts.map +1 -1
  276. package/dist/components/scope-switcher.js +2 -2
  277. package/dist/components/scroll-area.d.ts +47 -11
  278. package/dist/components/scroll-area.d.ts.map +1 -1
  279. package/dist/components/scroll-area.js +72 -14
  280. package/dist/components/segmented-control.d.ts +82 -0
  281. package/dist/components/segmented-control.d.ts.map +1 -0
  282. package/dist/components/segmented-control.js +90 -0
  283. package/dist/components/select.d.ts +55 -15
  284. package/dist/components/select.d.ts.map +1 -1
  285. package/dist/components/select.js +62 -19
  286. package/dist/components/separator.d.ts +12 -5
  287. package/dist/components/separator.d.ts.map +1 -1
  288. package/dist/components/separator.js +11 -6
  289. package/dist/components/settings-facts.d.ts +34 -14
  290. package/dist/components/settings-facts.d.ts.map +1 -1
  291. package/dist/components/settings-facts.js +21 -12
  292. package/dist/components/settings-page.d.ts +4 -4
  293. package/dist/components/settings-page.js +5 -5
  294. package/dist/components/settings-section.d.ts +160 -34
  295. package/dist/components/settings-section.d.ts.map +1 -1
  296. package/dist/components/settings-section.js +92 -39
  297. package/dist/components/sheet.d.ts +47 -16
  298. package/dist/components/sheet.d.ts.map +1 -1
  299. package/dist/components/sheet.js +40 -19
  300. package/dist/components/sidebar-sections.d.ts +16 -12
  301. package/dist/components/sidebar-sections.d.ts.map +1 -1
  302. package/dist/components/sidebar-sections.js +30 -15
  303. package/dist/components/sidebar.d.ts +117 -21
  304. package/dist/components/sidebar.d.ts.map +1 -1
  305. package/dist/components/sidebar.js +180 -55
  306. package/dist/components/skeleton.d.ts +54 -8
  307. package/dist/components/skeleton.d.ts.map +1 -1
  308. package/dist/components/skeleton.js +44 -9
  309. package/dist/components/slider.d.ts +53 -11
  310. package/dist/components/slider.d.ts.map +1 -1
  311. package/dist/components/slider.js +71 -17
  312. package/dist/components/snippet.d.ts +57 -0
  313. package/dist/components/snippet.d.ts.map +1 -0
  314. package/dist/components/snippet.js +60 -0
  315. package/dist/components/sonner.d.ts +13 -14
  316. package/dist/components/sonner.d.ts.map +1 -1
  317. package/dist/components/sonner.js +25 -22
  318. package/dist/components/status-badge.d.ts +37 -11
  319. package/dist/components/status-badge.d.ts.map +1 -1
  320. package/dist/components/status-badge.js +63 -15
  321. package/dist/components/status-dot.d.ts +42 -11
  322. package/dist/components/status-dot.d.ts.map +1 -1
  323. package/dist/components/status-dot.js +40 -11
  324. package/dist/components/switch.d.ts +43 -12
  325. package/dist/components/switch.d.ts.map +1 -1
  326. package/dist/components/switch.js +42 -12
  327. package/dist/components/table-card.d.ts +21 -12
  328. package/dist/components/table-card.d.ts.map +1 -1
  329. package/dist/components/table-card.js +17 -9
  330. package/dist/components/table-layouts.d.ts +40 -8
  331. package/dist/components/table-layouts.d.ts.map +1 -1
  332. package/dist/components/table-layouts.js +52 -8
  333. package/dist/components/table-value.d.ts +4 -3
  334. package/dist/components/table-value.d.ts.map +1 -1
  335. package/dist/components/table-value.js +6 -5
  336. package/dist/components/table.d.ts +62 -25
  337. package/dist/components/table.d.ts.map +1 -1
  338. package/dist/components/table.js +62 -26
  339. package/dist/components/tabs.d.ts +86 -17
  340. package/dist/components/tabs.d.ts.map +1 -1
  341. package/dist/components/tabs.js +93 -22
  342. package/dist/components/text-link.d.ts +4 -1
  343. package/dist/components/text-link.d.ts.map +1 -1
  344. package/dist/components/text-link.js +4 -1
  345. package/dist/components/text-with-copy-button.d.ts +30 -0
  346. package/dist/components/text-with-copy-button.d.ts.map +1 -0
  347. package/dist/components/text-with-copy-button.js +32 -0
  348. package/dist/components/textarea.d.ts +40 -10
  349. package/dist/components/textarea.d.ts.map +1 -1
  350. package/dist/components/textarea.js +50 -11
  351. package/dist/components/theme-mode-switcher.d.ts +20 -3
  352. package/dist/components/theme-mode-switcher.d.ts.map +1 -1
  353. package/dist/components/theme-mode-switcher.js +23 -6
  354. package/dist/components/toggle-group.d.ts +28 -8
  355. package/dist/components/toggle-group.d.ts.map +1 -1
  356. package/dist/components/toggle-group.js +12 -6
  357. package/dist/components/toggle.d.ts +6 -3
  358. package/dist/components/toggle.d.ts.map +1 -1
  359. package/dist/components/toggle.js +10 -7
  360. package/dist/components/tooltip.d.ts +43 -12
  361. package/dist/components/tooltip.d.ts.map +1 -1
  362. package/dist/components/tooltip.js +45 -16
  363. package/dist/components/trend-badge.js +1 -1
  364. package/dist/components/update-card.js +1 -1
  365. package/dist/eslint/index.js +82 -0
  366. package/dist/eslint/rules/badge-is-static-label.js +93 -0
  367. package/dist/eslint/rules/button-icon-slot.js +102 -0
  368. package/dist/eslint/rules/button-link-for-navigation.js +146 -0
  369. package/dist/eslint/rules/button-no-aria-label-with-text.js +75 -0
  370. package/dist/eslint/rules/button-type-roles-only-in-buttons.js +83 -0
  371. package/dist/eslint/rules/choice-control-has-a-name.js +98 -0
  372. package/dist/eslint/rules/choice-group-in-fieldset.js +86 -0
  373. package/dist/eslint/rules/command-shortcut-single-owner.js +118 -0
  374. package/dist/eslint/rules/confirm-dialog-words.js +63 -0
  375. package/dist/eslint/rules/data-table-one-unsized-column.js +96 -0
  376. package/dist/eslint/rules/destructive-action-placement.js +69 -0
  377. package/dist/eslint/rules/disabled-choice-says-why.js +71 -0
  378. package/dist/eslint/rules/ellipsis-opens-a-dialog.js +110 -0
  379. package/dist/eslint/rules/input-group-owners.js +155 -0
  380. package/dist/eslint/rules/kbd-children-no-modifier-text.js +128 -0
  381. package/dist/eslint/rules/literal-text.js +41 -0
  382. package/dist/eslint/rules/middle-truncate-placement.js +69 -0
  383. package/dist/eslint/rules/no-bare-button-label.js +55 -0
  384. package/dist/eslint/rules/no-control-in-read-only-surface.js +106 -0
  385. package/dist/eslint/rules/no-hand-built-busy.js +104 -0
  386. package/dist/eslint/rules/no-hand-built-theme-picker.js +144 -0
  387. package/dist/eslint/rules/no-hand-built-tile.js +41 -0
  388. package/dist/eslint/rules/no-hand-formatted-date.js +87 -0
  389. package/dist/eslint/rules/no-hand-stacked-avatars.js +67 -0
  390. package/dist/eslint/rules/no-nested-collapse.js +60 -0
  391. package/dist/eslint/rules/no-search-in-form.js +47 -0
  392. package/dist/eslint/rules/no-shadcn-appearance-override.js +2 -16
  393. package/dist/eslint/rules/no-shell-prompt-in-snippet.js +74 -0
  394. package/dist/eslint/rules/no-stock-error-words.js +56 -0
  395. package/dist/eslint/rules/no-tooltip-around-labelled-field.js +72 -0
  396. package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +57 -0
  397. package/dist/eslint/rules/one-submenu-level.js +43 -0
  398. package/dist/eslint/rules/one-toast-per-flow.js +91 -0
  399. package/dist/eslint/rules/option-count.js +167 -0
  400. package/dist/eslint/rules/page-command-link-not-render.js +43 -0
  401. package/dist/eslint/rules/progress-needs-name.js +57 -0
  402. package/dist/eslint/rules/settings-limit-in-footer.js +94 -0
  403. package/dist/eslint/rules/skeleton-in-region.js +80 -0
  404. package/dist/eslint/rules/sortable-heading-uses-sort.js +79 -0
  405. package/dist/eslint/rules/table-cell-inset-owner.js +107 -0
  406. package/dist/eslint/rules/tabs-selection-is-controlled.js +47 -0
  407. package/dist/eslint/rules/tooltip-only-arrow.js +38 -0
  408. package/dist/eslint/rules/tooltip-trigger-accessible-name.js +114 -0
  409. package/dist/eslint/strict-design-system.js +21 -7
  410. package/dist/index.d.ts +13 -13
  411. package/dist/index.d.ts.map +1 -1
  412. package/dist/index.js +12 -13
  413. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
  414. package/dist/internal/assistant-ui/attachment.js +2 -2
  415. package/dist/internal/assistant-ui/reasoning.d.ts +1 -1
  416. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
  417. package/dist/internal/assistant-ui/tool-fallback.js +1 -1
  418. package/dist/internal/assistant-ui/tool-group.d.ts +1 -1
  419. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
  420. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +2 -3
  421. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -1
  422. package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
  423. package/dist/internal/catalog-list.js +2 -2
  424. package/dist/internal/collection-note.d.ts +23 -0
  425. package/dist/internal/collection-note.d.ts.map +1 -0
  426. package/dist/internal/collection-note.js +17 -0
  427. package/dist/internal/collection-rail.d.ts +57 -0
  428. package/dist/internal/collection-rail.d.ts.map +1 -0
  429. package/dist/internal/collection-rail.js +33 -0
  430. package/dist/internal/company-logo.d.ts +18 -0
  431. package/dist/internal/company-logo.d.ts.map +1 -0
  432. package/dist/internal/company-logo.js +14 -0
  433. package/dist/internal/control-name.d.ts +12 -0
  434. package/dist/internal/control-name.d.ts.map +1 -0
  435. package/dist/internal/control-name.js +1 -0
  436. package/dist/internal/diff-line.d.ts +9 -0
  437. package/dist/internal/diff-line.d.ts.map +1 -0
  438. package/dist/internal/diff-line.js +8 -0
  439. package/dist/internal/empty.d.ts +8 -4
  440. package/dist/internal/empty.d.ts.map +1 -1
  441. package/dist/internal/empty.js +14 -8
  442. package/dist/internal/field-frame.d.ts +33 -0
  443. package/dist/internal/field-frame.d.ts.map +1 -0
  444. package/dist/internal/field-frame.js +20 -0
  445. package/dist/internal/final-focus.d.ts +8 -0
  446. package/dist/internal/final-focus.d.ts.map +1 -0
  447. package/dist/internal/final-focus.js +10 -0
  448. package/dist/internal/footer-strip.d.ts.map +1 -1
  449. package/dist/internal/footer-strip.js +3 -1
  450. package/dist/internal/form-submit.d.ts +9 -5
  451. package/dist/internal/form-submit.d.ts.map +1 -1
  452. package/dist/internal/form-submit.js +31 -2
  453. package/dist/internal/input-box.d.ts +26 -0
  454. package/dist/internal/input-box.d.ts.map +1 -0
  455. package/dist/internal/input-box.js +59 -0
  456. package/dist/internal/menu-surface.d.ts +10 -3
  457. package/dist/internal/menu-surface.d.ts.map +1 -1
  458. package/dist/internal/menu-surface.js +10 -3
  459. package/dist/internal/notice.d.ts +25 -0
  460. package/dist/internal/notice.d.ts.map +1 -0
  461. package/dist/internal/notice.js +33 -0
  462. package/dist/internal/overlay-stem.d.ts +5 -0
  463. package/dist/internal/overlay-stem.d.ts.map +1 -0
  464. package/dist/internal/overlay-stem.js +7 -0
  465. package/dist/internal/phone-sheet.d.ts +4 -0
  466. package/dist/internal/phone-sheet.d.ts.map +1 -0
  467. package/dist/internal/phone-sheet.js +2 -0
  468. package/dist/internal/present-content.d.ts +3 -0
  469. package/dist/internal/present-content.d.ts.map +1 -0
  470. package/dist/internal/present-content.js +1 -0
  471. package/dist/internal/record-menu-items.d.ts +4 -3
  472. package/dist/internal/record-menu-items.d.ts.map +1 -1
  473. package/dist/internal/record-menu-items.js +21 -6
  474. package/dist/internal/settings-save.d.ts +9 -2
  475. package/dist/internal/settings-save.d.ts.map +1 -1
  476. package/dist/internal/settings-save.js +9 -6
  477. package/dist/internal/table-compact-line.d.ts +38 -0
  478. package/dist/internal/table-compact-line.d.ts.map +1 -0
  479. package/dist/internal/table-compact-line.js +35 -0
  480. package/dist/internal/title-when-cut.d.ts +8 -0
  481. package/dist/internal/title-when-cut.d.ts.map +1 -0
  482. package/dist/internal/title-when-cut.js +22 -0
  483. package/dist/internal/unsaved-guard.d.ts +18 -0
  484. package/dist/internal/unsaved-guard.d.ts.map +1 -0
  485. package/dist/internal/unsaved-guard.js +31 -0
  486. package/dist/lib/merge-tokens.generated.js +2 -2
  487. package/dist/showcase/foundations.d.ts.map +1 -1
  488. package/dist/showcase/foundations.js +10 -2
  489. package/dist/showcase/specimens/actions.d.ts +2 -0
  490. package/dist/showcase/specimens/actions.d.ts.map +1 -1
  491. package/dist/showcase/specimens/actions.js +30 -5
  492. package/dist/showcase/specimens/charts.d.ts.map +1 -1
  493. package/dist/showcase/specimens/charts.js +22 -13
  494. package/dist/showcase/specimens/choices.d.ts +14 -3
  495. package/dist/showcase/specimens/choices.d.ts.map +1 -1
  496. package/dist/showcase/specimens/choices.js +93 -13
  497. package/dist/showcase/specimens/compositions.d.ts.map +1 -1
  498. package/dist/showcase/specimens/compositions.js +136 -23
  499. package/dist/showcase/specimens/data.d.ts +12 -7
  500. package/dist/showcase/specimens/data.d.ts.map +1 -1
  501. package/dist/showcase/specimens/data.js +139 -35
  502. package/dist/showcase/specimens/feedback.d.ts +2 -0
  503. package/dist/showcase/specimens/feedback.d.ts.map +1 -1
  504. package/dist/showcase/specimens/feedback.js +39 -15
  505. package/dist/showcase/specimens/index.d.ts +20 -12
  506. package/dist/showcase/specimens/index.d.ts.map +1 -1
  507. package/dist/showcase/specimens/inputs.d.ts +4 -2
  508. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  509. package/dist/showcase/specimens/inputs.js +62 -19
  510. package/dist/showcase/specimens/menus.d.ts +0 -1
  511. package/dist/showcase/specimens/menus.d.ts.map +1 -1
  512. package/dist/showcase/specimens/menus.js +47 -18
  513. package/dist/showcase/specimens/navigation.d.ts +6 -4
  514. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  515. package/dist/showcase/specimens/navigation.js +61 -32
  516. package/dist/showcase/specimens/other.d.ts +1 -3
  517. package/dist/showcase/specimens/other.d.ts.map +1 -1
  518. package/dist/showcase/specimens/other.js +17 -13
  519. package/dist/showcase/specimens/status.d.ts +4 -1
  520. package/dist/showcase/specimens/status.d.ts.map +1 -1
  521. package/dist/showcase/specimens/status.js +64 -11
  522. package/dist/showcase/usage.generated.d.ts +1 -1
  523. package/dist/showcase/usage.generated.d.ts.map +1 -1
  524. package/dist/showcase/usage.generated.js +637 -549
  525. package/dist/standalone/index.js +1 -1
  526. package/dist/styles/components.css +13 -13
  527. package/dist/styles/globals.css +25 -0
  528. package/package.json +2 -3
  529. package/dist/components/approval-row.d.ts +0 -34
  530. package/dist/components/approval-row.d.ts.map +0 -1
  531. package/dist/components/approval-row.js +0 -27
  532. package/dist/components/channel-view.d.ts +0 -112
  533. package/dist/components/channel-view.d.ts.map +0 -1
  534. package/dist/components/channel-view.js +0 -84
  535. package/dist/components/dashboard-shell.d.ts +0 -51
  536. package/dist/components/dashboard-shell.d.ts.map +0 -1
  537. package/dist/components/dashboard-shell.js +0 -89
  538. package/dist/components/direction.d.ts +0 -2
  539. package/dist/components/direction.d.ts.map +0 -1
  540. package/dist/components/direction.js +0 -1
  541. package/dist/components/expandable-block.d.ts +0 -20
  542. package/dist/components/expandable-block.d.ts.map +0 -1
  543. package/dist/components/expandable-block.js +0 -32
  544. package/dist/components/form.d.ts +0 -42
  545. package/dist/components/form.d.ts.map +0 -1
  546. package/dist/components/form.js +0 -91
  547. package/dist/components/label-system.d.ts +0 -17
  548. package/dist/components/label-system.d.ts.map +0 -1
  549. package/dist/components/label-system.js +0 -21
  550. package/dist/components/memory-item.d.ts +0 -21
  551. package/dist/components/memory-item.d.ts.map +0 -1
  552. package/dist/components/memory-item.js +0 -18
  553. package/dist/components/menubar.d.ts +0 -43
  554. package/dist/components/menubar.d.ts.map +0 -1
  555. package/dist/components/menubar.js +0 -69
  556. package/dist/components/navigation-menu.d.ts +0 -26
  557. package/dist/components/navigation-menu.d.ts.map +0 -1
  558. package/dist/components/navigation-menu.js +0 -45
  559. package/dist/components/pagination.d.ts +0 -33
  560. package/dist/components/pagination.d.ts.map +0 -1
  561. package/dist/components/pagination.js +0 -41
  562. package/dist/components/plugin-slot-boundary.d.ts +0 -42
  563. package/dist/components/plugin-slot-boundary.d.ts.map +0 -1
  564. package/dist/components/plugin-slot-boundary.js +0 -41
  565. package/dist/components/status-row.d.ts +0 -32
  566. package/dist/components/status-row.d.ts.map +0 -1
  567. package/dist/components/status-row.js +0 -35
@@ -4,19 +4,31 @@ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog
4
4
  import { cn } from "../lib/utils.js";
5
5
  import { modalOverlayMotion, overlayBackdropMotion } from "../lib/motion.js";
6
6
  import { Button } from "./button.js";
7
+ import { phoneSheetLayout } from "../internal/phone-sheet.js";
7
8
  /**
8
9
  * The blocking dialog primitive under `ConfirmDialog`.
9
10
  *
10
11
  * @family Menus
11
- * @when Before an action that stops or loses something, through `ConfirmDialog`, which owns the
12
+ * @when "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: before an action that stops or loses something, through `ConfirmDialog`, which owns the
12
14
  * words and the pending state.
13
- * @instead A product confirms with `ConfirmDialog`, never a hand-built alert dialog. A reversible
14
- * local change needs no confirmation; give it Undo in a toast.
15
- * @behaviour No backdrop dismissal; Escape cancels. `AlertDialogAction` closes on press; a confirm
16
- * that can fail is a plain button so the dialog stays open with the error.
17
- * @words Title a statement naming the record, never a question. Body the consequence, once.
18
- * @access `role="alertdialog"`, named by the title and described by the consequence. Focus starts
19
- * on Cancel, the safe choice.
15
+ * @instead Ours: a product confirms with `ConfirmDialog`, never a hand-built alert dialog. A
16
+ * reversible local change needs no confirmation; give it Undo in a toast.
17
+ * @behaviour "Default focus to `Cancel` on any destructive Modal. Enter must never trigger the destructive action without a typed confirmation." (https://vercel.com/geist/modal)
18
+ * "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal)
19
+ * Ours: a bottom sheet on a phone, centred from 640 px, 480 px wide with 20 px of padding and a
20
+ * 20 px column of title, description and body. The footer is a recessed bar that stays at the bottom
21
+ * while a tall confirmation scrolls, and holds 32 px buttons in one row, also on a phone: Cancel at
22
+ * the leading edge, the confirm at the trailing edge, a lone button filling the width. All neutral;
23
+ * red belongs to what `ConfirmDialog` puts inside. A press outside does not close it, because Base UI
24
+ * fixes that for an alert dialog and a stray click must not discard a typed phrase or an action in
25
+ * flight; Escape and Cancel close it. `AlertDialogAction` closes on press; a confirm that can fail
26
+ * is a plain button so the dialog stays open with the error.
27
+ * @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal)
28
+ * "`Modal.P` body is sentence case, 1–3 sentences. State the consequence first, then any cascade." (https://vercel.com/geist/modal)
29
+ * @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal)
30
+ * "Keep the Cancel button literally `Cancel` so screen-reader users hear a stable dismissal label across destructive flows." (https://vercel.com/geist/modal)
31
+ * Ours: `role="alertdialog"`, named by the title and described by the consequence.
20
32
  */
21
33
  function AlertDialog({ ...props }) {
22
34
  return _jsx(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", ...props });
@@ -30,23 +42,23 @@ function AlertDialogPortal({ ...props }) {
30
42
  function AlertDialogOverlay({ className, ...props }) {
31
43
  return (_jsx(AlertDialogPrimitive.Backdrop, { "data-slot": "alert-dialog-overlay", className: cn("pointer-events-auto", "fixed inset-0 isolate z-50 bg-scrim/scrim", overlayBackdropMotion, className), ...props }));
32
44
  }
33
- function AlertDialogContent({ className, size = "default", ...props }) {
34
- return (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Popup, { "data-slot": "alert-dialog-content", "data-size": size, className: cn("pointer-events-auto", "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-nadicode-md rounded-lg border-0 bg-popover p-nadicode-lg text-popover-foreground nc-elevation-modal outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm", modalOverlayMotion, className), ...props })] }));
45
+ function AlertDialogContent({ className, ...props }) {
46
+ return (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Popup, { "data-slot": "alert-dialog-content", "data-phone-layout": "sheet", className: cn("pointer-events-auto", "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 flex max-h-[min(50rem,80svh)] w-full -translate-x-1/2 -translate-y-1/2 flex-col gap-(--dialog-gap) overflow-y-auto rounded-lg border-0 bg-popover p-(--dialog-padding) [--dialog-gap:var(--dialog-padding)] [--dialog-padding:var(--spacing-nadicode-card-padding)] text-popover-foreground nc-elevation-modal outline-none sm:max-w-120", phoneSheetLayout, modalOverlayMotion, className), ...props })] }));
35
47
  }
36
48
  function AlertDialogHeader({ className, ...props }) {
37
- return (_jsx("div", { "data-slot": "alert-dialog-header", className: cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className), ...props }));
49
+ return (_jsx("div", { "data-slot": "alert-dialog-header", className: cn("flex flex-col gap-2", className), ...props }));
38
50
  }
39
- function AlertDialogFooter({ className, ...props }) {
40
- return (_jsx("div", { "data-slot": "alert-dialog-footer", className: cn("-mx-nadicode-lg -mb-nadicode-lg flex flex-col-reverse gap-2 rounded-b-lg border-t border-border bg-recessed px-nadicode-lg py-control-padding-inline group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", className), ...props }));
51
+ function AlertDialogBody({ className, ...props }) {
52
+ return (_jsx("div", { "data-slot": "alert-dialog-body", className: cn("flex flex-col gap-nadicode-lg", className), ...props }));
41
53
  }
42
- function AlertDialogMedia({ className, ...props }) {
43
- return (_jsx("div", { "data-slot": "alert-dialog-media", className: cn("mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className), ...props }));
54
+ function AlertDialogFooter({ className, ...props }) {
55
+ return (_jsx("div", { "data-slot": "alert-dialog-footer", className: cn("sticky -bottom-(--dialog-padding) z-10 -mx-(--dialog-padding) -mb-(--dialog-padding) flex shrink-0 flex-row justify-between gap-nadicode-md rounded-b-lg border-t border-border bg-recessed p-nadicode-sm group-data-[phone-layout=sheet]/alert-dialog-content:max-sm:rounded-b-none *:only:w-full [&_[data-slot=button]]:h-nadicode-control-height-sm [&_[data-slot=button]]:min-h-nadicode-control-height-sm [&_[data-slot=button]]:px-button-padding-inline-sm", className), ...props }));
44
56
  }
45
57
  function AlertDialogTitle({ className, ...props }) {
46
- return (_jsx(AlertDialogPrimitive.Title, { "data-slot": "alert-dialog-title", className: cn("min-w-0 text-heading-sm break-words sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", className), ...props }));
58
+ return (_jsx(AlertDialogPrimitive.Title, { "data-slot": "alert-dialog-title", className: cn("min-w-0 text-heading-sm break-words", className), ...props }));
47
59
  }
48
60
  function AlertDialogDescription({ className, ...props }) {
49
- return (_jsx(AlertDialogPrimitive.Description, { "data-slot": "alert-dialog-description", className: cn("text-body-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className), ...props }));
61
+ return (_jsx(AlertDialogPrimitive.Description, { "data-slot": "alert-dialog-description", className: cn("text-body-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className), ...props }));
50
62
  }
51
63
  // An action is also a Base UI Close so the standard alert-dialog contract
52
64
  // dismisses after confirmation while preserving the Button API.
@@ -56,4 +68,4 @@ function AlertDialogAction({ className, variant = "default", size = "default", .
56
68
  function AlertDialogCancel({ className, variant = "outline", size = "default", ...props }) {
57
69
  return (_jsx(AlertDialogPrimitive.Close, { "data-slot": "alert-dialog-cancel", className: cn(className), render: _jsx(Button, { variant: variant, size: size }), ...props }));
58
70
  }
59
- export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, };
71
+ export { AlertDialog, AlertDialogAction, AlertDialogBody, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, };
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const alertVariants: (props?: ({
4
- variant?: "default" | "destructive" | "info" | "warning" | null | undefined;
4
+ variant?: "default" | "destructive" | "warning" | "info" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  /**
7
7
  * The note primitive under every banner and notice: an icon, a title, a description and an action.
@@ -1,28 +1,94 @@
1
1
  import * as React from "react";
2
2
  import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
3
+ type AvatarSize = "xs" | "sm" | "default" | "lg";
4
+ /**
5
+ * The uppercase first letters of a name's first two words; `length` 1 keeps only the first. A name
6
+ * with nothing to read, such as an emoji alone, gives an empty string.
7
+ */
8
+ declare function avatarInitials(name: string, length?: 1 | 2): string;
9
+ type AvatarName = {
10
+ label: string;
11
+ decorative?: never;
12
+ } | {
13
+ decorative: true;
14
+ label?: never;
15
+ };
16
+ type AvatarRootProps = Omit<AvatarPrimitive.Root.Props, "role" | "aria-hidden" | "aria-label" | "aria-labelledby">;
17
+ type AvatarProps = AvatarRootProps & AvatarName & {
18
+ size?: AvatarSize;
19
+ };
3
20
  /**
4
21
  * A person or a team: their picture, else their initials.
5
22
  *
6
23
  * @family Status
7
- * @when A person or a team: the account at the foot of the sidebar, a member list, who changed
8
- * something. The picture stands in for a person's own photo.
9
- * @instead An Agent is always its `AgentOrb`, never an avatar. A company is its initials in a 6 px
10
- * tile inside `RecordIdentity`.
11
- * @behaviour A picture that fails falls back to initials, then to the person glyph while the owner
12
- * is unknown; never blank. A group overlaps 8 px with a 2 px ring of the ground. The profile's 80
13
- * px upload button is `AvatarUploadButton`.
14
- * @words Two uppercase initials from the name, else from the email. The overflow is a count: *+2*.
15
- * @access Beside a visible name it is `aria-hidden`. Alone, its alt is the person's name. A group
16
- * is labelled: *5 members*.
24
+ * @when "Use a single `<Avatar>` for one person, team, or organization." (https://vercel.com/geist/avatar)
25
+ * "For two or more stacked avatars, use `<AvatarGroup>` so the cluster gets correct overlap, sizing, and a single accessible label." (https://vercel.com/geist/avatar)
26
+ * Ours: a person or a team: the account at the foot of the sidebar, a member list, who changed
27
+ * something. It always says who it shows: `label` names the entity (*Jane Doe*), and `decorative`
28
+ * stands for a name beside it that already does. The type asks for one of the two.
29
+ * "Pass `src` first and fall back to `letter` (1–2 uppercase chars) when the image is missing." (https://vercel.com/geist/avatar)
30
+ * Ours: the children are an `AvatarImage` and an `AvatarFallback` with the initials.
31
+ * "Pick a size that matches adjacent type: 20–24px next to `text-label-14`, 32px next to `text-label-16`, 48–64px in headers and onboarding states." (https://vercel.com/geist/avatar)
32
+ * Ours: `size` follows the type beside it: `xs` (16 px) and `sm` (24 px) next to small labels,
33
+ * `default` (32 px) next to body text, `lg` (48 px) in a header or an onboarding step.
34
+ * `AvatarWithIcon` puts a status glyph at the corner of a person's avatar.
35
+ * @instead Ours: an Agent is always its `AgentOrb`, never an avatar. A company is its initials in a
36
+ * 6 px tile inside `RecordIdentity`.
37
+ * @behaviour "By default the first member sits on top of the stack, so the first credited author stays the most prominent." (https://vercel.com/geist/avatar)
38
+ * "Set `reverse` to flip the order so the last member sits on top instead." (https://vercel.com/geist/avatar)
39
+ * "The visual left-to-right order is unchanged." (https://vercel.com/geist/avatar)
40
+ * "By default `overlap="auto"` scales the spacing with `size`, keeping a generous, evenly-spaced cluster at any size." (https://vercel.com/geist/avatar)
41
+ * "Pass a number to set the overlap in pixels instead." (https://vercel.com/geist/avatar)
42
+ * "Lower values give more generous spacing; higher values pack tighter for dense, space-constrained UI." (https://vercel.com/geist/avatar)
43
+ * Ours: `auto` is about 30 % of the size (5, 7, 10 and 14 px), and each member is cut out with a 1
44
+ * px ring in the page colour. When `limit` cuts the group, the last place is a dark `+N` count that
45
+ * covers the member it hides.
46
+ * "Reserve `placeholder` for the loading shell, never as a permanent fallback." (https://vercel.com/geist/avatar)
47
+ * Ours: there is no `placeholder`; a picture that fails falls back to initials from
48
+ * `avatarInitials`, set in the neutral accent fill with the text colour on it, in both themes.
49
+ * For a name with no readable letter the caller passes a glyph, so it is never blank. The picture
50
+ * is held by a 1 px hairline. The corner glyph of `AvatarWithIcon` is the person's state, in the
51
+ * muted foreground colour, so its `label` names the person and the state. The profile's upload
52
+ * button is `AvatarUploadButton`.
53
+ * @words "Keep `letter` uppercase and derived from the entity name. No emoji, no punctuation, no `?`." (https://vercel.com/geist/avatar)
54
+ * Ours: the initials come from the name, else from the email; one initial at `xs`. The overflow is
55
+ * a count: *+2*.
56
+ * @access "`title` is the literal entity name (`Acme Inc.`, `Jane Doe`)." (https://vercel.com/geist/avatar)
57
+ * "Geist already prefixes letter avatars with `Avatar with initials:` for screen readers, so don’t hand-write `Avatar of …`." (https://vercel.com/geist/avatar)
58
+ * Ours: the name is `label`, as it is written (*Jane Doe*, not *Avatar of Jane Doe*), and we add no
59
+ * prefix. Beside a visible name it is `decorative`. A group carries one label: *5 members*. A
60
+ * corner glyph is `aria-hidden`; `label` says the state: *Jane Doe, paused*.
17
61
  */
18
- declare function Avatar({ className, size, ...props }: AvatarPrimitive.Root.Props & {
19
- size?: "default" | "sm" | "lg";
20
- }): React.JSX.Element;
62
+ declare function Avatar({ className, size, label, decorative, ...props }: AvatarProps): React.JSX.Element;
21
63
  declare function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props): React.JSX.Element;
22
64
  declare function AvatarFallback({ className, ...props }: AvatarPrimitive.Fallback.Props): React.JSX.Element;
23
- declare function AvatarBadge({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
24
- declare function AvatarGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
25
- declare function AvatarGroupCount({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
65
+ type AvatarMember = {
66
+ id: string;
67
+ name: string;
68
+ src?: string;
69
+ };
70
+ declare function AvatarGroup({ members, label, limit, size, reverse, overlap, className, ...props }: Omit<React.ComponentProps<"div">, "children" | "aria-label" | "aria-labelledby" | "role"> & {
71
+ members: readonly AvatarMember[];
72
+ /** The label of the whole group, in the reader's language: "5 members". */
73
+ label: string;
74
+ /** The most places drawn, the count included: the last place is `+N` over the member it hides. */
75
+ limit?: number;
76
+ size?: AvatarSize;
77
+ /** The last member on top instead of the first; the left-to-right order stays. */
78
+ reverse?: boolean;
79
+ /** `auto` scales the overlap with `size`; a number sets it in pixels. */
80
+ overlap?: "auto" | number;
81
+ }): React.JSX.Element;
82
+ type AvatarWithIconProps = Omit<AvatarRootProps, "children"> & AvatarName & {
83
+ icon: React.ReactElement;
84
+ /** The person's name: the initials shown while there is no picture. */
85
+ name: string;
86
+ src?: string;
87
+ size?: AvatarSize;
88
+ /** Draws the page-colour disc behind the glyph, so it reads over the picture. */
89
+ iconBackground?: boolean;
90
+ };
91
+ declare function AvatarWithIcon({ icon, name, src, size, iconBackground, ...props }: AvatarWithIconProps): React.JSX.Element;
26
92
  declare function AvatarUploadButton({ label, pendingLabel, src, fallback, busy, onClick, }: {
27
93
  label: string;
28
94
  pendingLabel: string;
@@ -31,5 +97,5 @@ declare function AvatarUploadButton({ label, pendingLabel, src, fallback, busy,
31
97
  busy?: boolean;
32
98
  onClick: () => void;
33
99
  }): React.JSX.Element;
34
- export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarBadge, AvatarUploadButton, };
100
+ export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarUploadButton, AvatarWithIcon, avatarInitials, type AvatarMember, };
35
101
  //# sourceMappingURL=avatar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/components/avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQlE;;;;;;;;;;;;;;GAcG;AACH,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAAG;IAC9B,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;CAChC,qBAYA;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,qBAW9E;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAczE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAYxE;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW7E;AAED,iBAAS,kBAAkB,CAAC,EAC1B,KAAK,EACL,YAAY,EACZ,GAAG,EACH,QAAQ,EACR,IAAY,EACZ,OAAO,GACR,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,qBA0BA;AAED,OAAO,EACL,MAAM,EACN,WAAW,EACX,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,kBAAkB,GACnB,CAAC"}
1
+ {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/components/avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQlE,KAAK,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;AA4BjD;;;GAGG;AACH,iBAAS,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,CAAC,GAAG,CAAK,GAAG,MAAM,CAQ/D;AAED,KAAK,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE9F,KAAK,eAAe,GAAG,IAAI,CACzB,eAAe,CAAC,IAAI,CAAC,KAAK,EAC1B,MAAM,GAAG,aAAa,GAAG,YAAY,GAAG,iBAAiB,CAC1D,CAAC;AAEF,KAAK,WAAW,GAAG,eAAe,GAAG,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,iBAAS,MAAM,CAAC,EAAE,SAAS,EAAE,IAAgB,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW,qBAgBxF;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,qBAW9E;AAED,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAqBF,iBAAS,WAAW,CAAC,EACnB,OAAO,EACP,KAAK,EACL,KAAK,EACL,IAAgB,EAChB,OAAe,EACf,OAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,YAAY,GAAG,iBAAiB,GAAG,MAAM,CAAC,GAAG;IAC7F,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B,qBAsCA;AAED,KAAK,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,GAC1D,UAAU,GAAG;IACX,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IACzB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,iFAAiF;IACjF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEJ,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAgB,EAChB,cAAsB,EACtB,GAAG,KAAK,EACT,EAAE,mBAAmB,qBAmBrB;AAED,iBAAS,kBAAkB,CAAC,EAC1B,KAAK,EACL,YAAY,EACZ,GAAG,EACH,QAAQ,EACR,IAAY,EACZ,OAAO,GACR,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,qBA0BA;AAED,OAAO,EACL,MAAM,EACN,WAAW,EACX,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,KAAK,YAAY,GAClB,CAAC"}
@@ -4,42 +4,108 @@ import { CameraIcon } from "lucide-react";
4
4
  import { Button } from "./button.js";
5
5
  import { WaitingLine } from "./waiting-line.js";
6
6
  import { cn } from "../lib/utils.js";
7
+ const AVATAR_SIZE_CLASS = {
8
+ xs: "size-4",
9
+ sm: "size-6",
10
+ default: "size-8",
11
+ lg: "size-12",
12
+ };
13
+ const AVATAR_COUNT_TEXT_CLASS = {
14
+ xs: "text-[10px] leading-3",
15
+ sm: "text-[10px] leading-3",
16
+ default: "text-[10px] leading-3",
17
+ lg: "text-xs leading-4",
18
+ };
19
+ const AVATAR_CORNER_ICON_CLASS = {
20
+ xs: "-start-0.5 -bottom-0.5 size-2 [&>svg]:size-1.5",
21
+ sm: "-start-0.5 -bottom-1 size-3 [&>svg]:size-2.5",
22
+ default: "-start-0.75 -bottom-1.25 size-4 [&>svg]:size-3.5",
23
+ lg: "-start-1 -bottom-2 size-6 [&>svg]:size-5",
24
+ };
25
+ const AVATAR_AUTO_OVERLAP = { xs: 5, sm: 7, default: 10, lg: 14 };
26
+ /**
27
+ * The uppercase first letters of a name's first two words; `length` 1 keeps only the first. A name
28
+ * with nothing to read, such as an emoji alone, gives an empty string.
29
+ */
30
+ function avatarInitials(name, length = 2) {
31
+ return name
32
+ .split(/\s+/)
33
+ .map((word) => word.match(/^[\p{L}\p{N}]/u)?.[0])
34
+ .filter((initial) => initial !== undefined)
35
+ .slice(0, length)
36
+ .join("")
37
+ .toUpperCase();
38
+ }
7
39
  /**
8
40
  * A person or a team: their picture, else their initials.
9
41
  *
10
42
  * @family Status
11
- * @when A person or a team: the account at the foot of the sidebar, a member list, who changed
12
- * something. The picture stands in for a person's own photo.
13
- * @instead An Agent is always its `AgentOrb`, never an avatar. A company is its initials in a 6 px
14
- * tile inside `RecordIdentity`.
15
- * @behaviour A picture that fails falls back to initials, then to the person glyph while the owner
16
- * is unknown; never blank. A group overlaps 8 px with a 2 px ring of the ground. The profile's 80
17
- * px upload button is `AvatarUploadButton`.
18
- * @words Two uppercase initials from the name, else from the email. The overflow is a count: *+2*.
19
- * @access Beside a visible name it is `aria-hidden`. Alone, its alt is the person's name. A group
20
- * is labelled: *5 members*.
43
+ * @when "Use a single `<Avatar>` for one person, team, or organization." (https://vercel.com/geist/avatar)
44
+ * "For two or more stacked avatars, use `<AvatarGroup>` so the cluster gets correct overlap, sizing, and a single accessible label." (https://vercel.com/geist/avatar)
45
+ * Ours: a person or a team: the account at the foot of the sidebar, a member list, who changed
46
+ * something. It always says who it shows: `label` names the entity (*Jane Doe*), and `decorative`
47
+ * stands for a name beside it that already does. The type asks for one of the two.
48
+ * "Pass `src` first and fall back to `letter` (1–2 uppercase chars) when the image is missing." (https://vercel.com/geist/avatar)
49
+ * Ours: the children are an `AvatarImage` and an `AvatarFallback` with the initials.
50
+ * "Pick a size that matches adjacent type: 20–24px next to `text-label-14`, 32px next to `text-label-16`, 48–64px in headers and onboarding states." (https://vercel.com/geist/avatar)
51
+ * Ours: `size` follows the type beside it: `xs` (16 px) and `sm` (24 px) next to small labels,
52
+ * `default` (32 px) next to body text, `lg` (48 px) in a header or an onboarding step.
53
+ * `AvatarWithIcon` puts a status glyph at the corner of a person's avatar.
54
+ * @instead Ours: an Agent is always its `AgentOrb`, never an avatar. A company is its initials in a
55
+ * 6 px tile inside `RecordIdentity`.
56
+ * @behaviour "By default the first member sits on top of the stack, so the first credited author stays the most prominent." (https://vercel.com/geist/avatar)
57
+ * "Set `reverse` to flip the order so the last member sits on top instead." (https://vercel.com/geist/avatar)
58
+ * "The visual left-to-right order is unchanged." (https://vercel.com/geist/avatar)
59
+ * "By default `overlap="auto"` scales the spacing with `size`, keeping a generous, evenly-spaced cluster at any size." (https://vercel.com/geist/avatar)
60
+ * "Pass a number to set the overlap in pixels instead." (https://vercel.com/geist/avatar)
61
+ * "Lower values give more generous spacing; higher values pack tighter for dense, space-constrained UI." (https://vercel.com/geist/avatar)
62
+ * Ours: `auto` is about 30 % of the size (5, 7, 10 and 14 px), and each member is cut out with a 1
63
+ * px ring in the page colour. When `limit` cuts the group, the last place is a dark `+N` count that
64
+ * covers the member it hides.
65
+ * "Reserve `placeholder` for the loading shell, never as a permanent fallback." (https://vercel.com/geist/avatar)
66
+ * Ours: there is no `placeholder`; a picture that fails falls back to initials from
67
+ * `avatarInitials`, set in the neutral accent fill with the text colour on it, in both themes.
68
+ * For a name with no readable letter the caller passes a glyph, so it is never blank. The picture
69
+ * is held by a 1 px hairline. The corner glyph of `AvatarWithIcon` is the person's state, in the
70
+ * muted foreground colour, so its `label` names the person and the state. The profile's upload
71
+ * button is `AvatarUploadButton`.
72
+ * @words "Keep `letter` uppercase and derived from the entity name. No emoji, no punctuation, no `?`." (https://vercel.com/geist/avatar)
73
+ * Ours: the initials come from the name, else from the email; one initial at `xs`. The overflow is
74
+ * a count: *+2*.
75
+ * @access "`title` is the literal entity name (`Acme Inc.`, `Jane Doe`)." (https://vercel.com/geist/avatar)
76
+ * "Geist already prefixes letter avatars with `Avatar with initials:` for screen readers, so don’t hand-write `Avatar of …`." (https://vercel.com/geist/avatar)
77
+ * Ours: the name is `label`, as it is written (*Jane Doe*, not *Avatar of Jane Doe*), and we add no
78
+ * prefix. Beside a visible name it is `decorative`. A group carries one label: *5 members*. A
79
+ * corner glyph is `aria-hidden`; `label` says the state: *Jane Doe, paused*.
21
80
  */
22
- function Avatar({ className, size = "default", ...props }) {
23
- return (_jsx(AvatarPrimitive.Root, { "data-slot": "avatar", "data-size": size, className: cn("group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6", className), ...props }));
81
+ function Avatar({ className, size = "default", label, decorative, ...props }) {
82
+ return (_jsx(AvatarPrimitive.Root, { "data-slot": "avatar", "data-size": size, "aria-hidden": decorative ? "true" : undefined, "aria-label": label, role: decorative ? undefined : "img", className: cn("group/avatar relative flex shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken", AVATAR_SIZE_CLASS[size], className), ...props }));
24
83
  }
25
84
  function AvatarImage({ className, ...props }) {
26
85
  return (_jsx(AvatarPrimitive.Image, { "data-slot": "avatar-image", className: cn("aspect-square size-full rounded-full object-cover", className), ...props }));
27
86
  }
28
87
  function AvatarFallback({ className, ...props }) {
29
- return (_jsx(AvatarPrimitive.Fallback, { "data-slot": "avatar-fallback", className: cn("flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs", className), ...props }));
88
+ return (_jsx(AvatarPrimitive.Fallback, { "data-slot": "avatar-fallback", className: cn("flex size-full items-center justify-center rounded-full bg-accent text-base font-medium text-foreground group-data-[size=sm]/avatar:text-xs group-data-[size=xs]/avatar:text-xs", className), ...props }));
30
89
  }
31
- function AvatarBadge({ className, ...props }) {
32
- return (_jsx("span", { "data-slot": "avatar-badge", className: cn("absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className), ...props }));
90
+ function AvatarGroupCount({ className, size, ...props }) {
91
+ return (_jsx("span", { "data-slot": "avatar-group-count", className: cn("relative flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-nc-dark-line bg-nc-dark-canvas-soft-2 font-semibold text-nc-dark-ink ring-1 ring-background tabular-nums", AVATAR_SIZE_CLASS[size], AVATAR_COUNT_TEXT_CLASS[size], className), ...props }));
33
92
  }
34
- function AvatarGroup({ className, ...props }) {
35
- return (_jsx("div", { "data-slot": "avatar-group", className: cn(
36
- // eslint-disable-next-line better-tailwindcss/no-restricted-classes -- an avatar group overlaps its members; negative spacing has no gap-* equivalent.
37
- "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background", className), ...props }));
93
+ function AvatarGroup({ members, label, limit, size = "default", reverse = false, overlap = "auto", className, ...props }) {
94
+ const places = limit === undefined ? members.length : Math.max(0, limit);
95
+ const drawn = members.length > places ? members.slice(0, Math.max(0, places - 1)) : members;
96
+ const hidden = members.length - drawn.length;
97
+ const total = drawn.length + (hidden > 0 ? 1 : 0);
98
+ const overlapPx = overlap === "auto" ? AVATAR_AUTO_OVERLAP[size] : overlap;
99
+ const stack = (index) => ({
100
+ marginInlineStart: index === 0 ? 0 : -overlapPx,
101
+ zIndex: reverse ? index + 1 : total - index,
102
+ });
103
+ return (_jsxs("div", { ...props, "aria-label": label, className: cn("isolate flex items-center", className), "data-slot": "avatar-group", role: "group", children: [drawn.map((member, index) => (_jsxs(Avatar, { className: "ring-1 ring-background", decorative: true, size: size, style: stack(index), children: [member.src ? _jsx(AvatarImage, { alt: "", src: member.src }) : null, _jsx(AvatarFallback, { children: avatarInitials(member.name, size === "xs" ? 1 : 2) })] }, member.id))), hidden > 0 ? (_jsxs(AvatarGroupCount, { "aria-hidden": "true", size: size, style: stack(drawn.length), children: ["+", hidden] })) : null] }));
38
104
  }
39
- function AvatarGroupCount({ className, ...props }) {
40
- return (_jsx("div", { "data-slot": "avatar-group-count", className: cn("relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className), ...props }));
105
+ function AvatarWithIcon({ icon, name, src, size = "default", iconBackground = false, ...props }) {
106
+ return (_jsxs(Avatar, { ...props, size: size, children: [src ? _jsx(AvatarImage, { alt: "", src: src }) : null, _jsx(AvatarFallback, { children: avatarInitials(name, size === "xs" ? 1 : 2) }), _jsx("span", { "aria-hidden": "true", className: cn("absolute z-10 inline-flex items-center justify-center rounded-full text-muted-foreground", iconBackground && "border border-background bg-background", AVATAR_CORNER_ICON_CLASS[size]), "data-background": iconBackground || undefined, "data-slot": "avatar-icon", children: icon })] }));
41
107
  }
42
108
  function AvatarUploadButton({ label, pendingLabel, src, fallback, busy = false, onClick, }) {
43
- return (_jsxs("div", { className: "relative inline-flex w-20 shrink-0 flex-col items-center", children: [_jsxs(Button, { "aria-label": busy ? pendingLabel : label, "aria-busy": busy || undefined, disabled: busy, type: "button", variant: "ghost", className: "group/avatar-upload relative size-20 shrink-0 rounded-full p-0", onClick: onClick, children: [_jsxs(Avatar, { "aria-hidden": "true", className: "size-full", children: [_jsx(AvatarImage, { src: src, alt: "" }), _jsx(AvatarFallback, { className: "text-xl", children: fallback })] }), _jsx("span", { "aria-hidden": "true", className: "absolute inset-0 flex items-center justify-center rounded-full bg-background/80 opacity-0 group-hover/avatar-upload:opacity-100 group-focus-visible/avatar-upload:opacity-100 group-aria-busy/avatar-upload:opacity-100", children: _jsx(CameraIcon, { "data-icon": "inline-start", className: "size-5" }) })] }), busy ? _jsx(WaitingLine, { className: "absolute inset-x-0 -bottom-3", decorative: true }) : null] }));
109
+ return (_jsxs("div", { className: "relative inline-flex w-20 shrink-0 flex-col items-center", children: [_jsxs(Button, { "aria-label": busy ? pendingLabel : label, loading: busy, size: "icon", type: "button", variant: "ghost", className: "group/avatar-upload relative size-20 shrink-0 rounded-full p-0", onClick: onClick, children: [_jsxs(Avatar, { className: "size-full", decorative: true, children: [_jsx(AvatarImage, { src: src, alt: "" }), _jsx(AvatarFallback, { className: "text-xl", children: fallback })] }), _jsx("span", { "aria-hidden": "true", className: "absolute inset-0 flex items-center justify-center rounded-full bg-background/80 opacity-0 group-hover/avatar-upload:opacity-100 group-focus-visible/avatar-upload:opacity-100 group-aria-busy/avatar-upload:opacity-100", children: _jsx(CameraIcon, { className: "size-5" }) })] }), busy ? _jsx(WaitingLine, { className: "absolute inset-x-0 -bottom-3", decorative: true }) : null] }));
44
110
  }
45
- export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarBadge, AvatarUploadButton, };
111
+ export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarUploadButton, AvatarWithIcon, avatarInitials, };
@@ -1,18 +1,69 @@
1
+ import type { ReactNode } from "react";
1
2
  import { useRender } from "@base-ui/react/use-render";
2
3
  import { type VariantProps } from "class-variance-authority";
3
4
  declare const badgeVariants: (props?: ({
4
- variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | "pink" | "purple" | "teal" | null | undefined;
5
+ variant?: "default" | "outline" | "secondary" | "pink" | "purple" | "teal" | null | undefined;
6
+ size?: "sm" | "lg" | "md" | null | undefined;
5
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ type BadgeSize = NonNullable<VariantProps<typeof badgeVariants>["size"]>;
9
+ type BadgeProps = Omit<useRender.ComponentProps<"span">, "onClick" | "children" | "title"> & VariantProps<typeof badgeVariants> & ({
10
+ children: ReactNode;
11
+ /** One mark before the word; never a second icon. */
12
+ icon?: ReactNode;
13
+ title?: string;
14
+ } | {
15
+ children?: never;
16
+ icon: ReactNode;
17
+ /** What the mark means: an icon alone has no word to name it. */
18
+ title: string;
19
+ });
6
20
  /**
7
21
  * Short metadata beside its subject: a role, a plan, "Beta".
8
22
  *
9
23
  * @family Status
10
- * @when Short metadata beside its subject: a role ("Owner"), a plan, "Beta". 20 px high, 6 px corners, 12 px label at 500. The category fills (teal, purple, pink) name a kind.
11
- * @instead For a state use `StatusBadge`, which picks the tone and its mark: the gray, green, red, amber and blue fills are its alone. For one categorical fact in a row use `Tag`. For a change in a figure, `TrendBadge`.
12
- * @behaviour A static label. It becomes a link only through `render` with a real anchor, which then takes the hover. Never a click handler, never nested, never a paragraph.
13
- * @words One to three words, sentence case, a noun: "Business plan", not "This is on Business".
14
- * @access Read in place as text. A coloured variant still carries its word.
24
+ * @when "Use Badge for short, scannable metadata that sits next to the thing it describes: status, plan tier, environment, or role." (https://vercel.com/geist/badge)
25
+ * "One badge per row; two side by side is a sign the row needs a second column." (https://vercel.com/geist/badge)
26
+ * Ours: a state is a `StatusBadge`; a `Badge` is a role (*Owner*), a plan, an environment, *Beta*.
27
+ * It always has a word, or one `icon` with a `title`, and the type asks for it. `size` follows the
28
+ * type beside it: `sm` (20 px) next to small labels, `md` (24 px) in a row, `lg` (32 px) in a
29
+ * header. The category fills (teal, purple, pink) name a kind.
30
+ * @instead "For a colored dot without text, use `Status Dot`." (https://vercel.com/geist/badge)
31
+ * Ours: that is `StatusDot`.
32
+ * "For clickable filter chips that toggle a query, use the `pill` variant or a small `Button`." (https://vercel.com/geist/badge)
33
+ * Ours: there is no `pill` variant; a filter that toggles a query is a `Button` or
34
+ * `CollectionFilters`. For a state use `StatusBadge`, which picks the tone and its mark: the gray,
35
+ * green, red, amber and blue fills, soft or solid, are its alone. One categorical fact in a row is
36
+ * a `Tag`. A change in a figure is a `TrendBadge`.
37
+ * @behaviour "Badges are static labels." (https://vercel.com/geist/badge)
38
+ * "Don’t wire `onClick` onto them; promote to a Button or link if the user can act on the value." (https://vercel.com/geist/badge)
39
+ * Ours: it takes no `onClick`, no hover and no focus; it becomes a link only through `render` with
40
+ * a real anchor, and only `outline` takes the hover, a gray fill.
41
+ * "Keep badge content to text or `icon` + text." (https://vercel.com/geist/badge)
42
+ * "Never stack two icons or a child Badge inside a Badge." (https://vercel.com/geist/badge) Ours:
43
+ * never a paragraph either.
44
+ * "Pair lifecycle badges (`Alpha`, `Beta`, `Early Access`) with a `Tooltip` that names the limit, like `Alpha: API may change before GA`." (https://vercel.com/geist/badge)
45
+ * Ours: the badge is the `render` of a `TooltipTrigger` with `tabIndex={0}`, so keyboard and touch
46
+ * users reach the limit it names.
47
+ * "Don’t add a checkmark icon for success states or an X for errors; the variant carries that signal." (https://vercel.com/geist/badge)
48
+ * Ours: only `StatusBadge` carries a state, and it always draws its tone's mark.
49
+ * "Map meaning to color: `green` for healthy, `red` for error, `amber` for warning, `blue` for informational or production, `gray` for neutral." (https://vercel.com/geist/badge)
50
+ * "The `-subtle` suffix tones any of them down on dense surfaces." (https://vercel.com/geist/badge)
51
+ * Ours: those fills are `StatusBadge`'s, as the tones `success`, `danger`, `warning`, `info` and
52
+ * `neutral`, with `emphasis` `subtle` or `solid`. `Badge` is a fixed-height pill (20, 24 or 32 px)
53
+ * with no border: colour sits on the fill and the word. A soft fill takes its hue's strong shade
54
+ * for the word, `default` is the foreground colour inverted, and `outline` is neutral, a
55
+ * page-colour fill held by a 1 px inset ring. With an icon, the left padding is 6, 8 or 12 px, so
56
+ * the mark and the word look evenly spaced. The icon takes the word's colour.
57
+ * @words "Title Case, one word when possible, two max: `Active`, `Pending`, `Pro`, `Enterprise Trial`." (https://vercel.com/geist/badge)
58
+ * Ours: sentence case (*Enterprise trial*).
59
+ * "Match the canonical API or log term: `Production` not `Prod`, `Deployed` not `Live`, `Canceled` not `Cancelled` (the Vercel API uses one L)." (https://vercel.com/geist/badge)
60
+ * Ours: the term is our own API's.
61
+ * "Skip stuffing sentences inside (`Currently Active`, `You are on Pro`); the surrounding row supplies the context." (https://vercel.com/geist/badge)
62
+ * @access "Set `title` for icon-only or ambiguous badges so screen readers announce the meaning." (https://vercel.com/geist/badge)
63
+ * Ours: an icon alone must set `title`, and the type asks for it. Read in place as text.
64
+ * "Don’t rely on color alone; the text has to be readable without it." (https://vercel.com/geist/badge)
65
+ * Ours: a coloured variant still carries its word.
15
66
  */
16
- declare function Badge({ className, variant, render, ...props }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
17
- export { Badge, badgeVariants };
67
+ declare function Badge({ className, variant, size, icon, children, render, ...props }: BadgeProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
68
+ export { Badge, badgeVariants, type BadgeProps, type BadgeSize };
18
69
  //# sourceMappingURL=badge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../src/components/badge.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE,QAAA,MAAM,aAAa;;8EAqBlB,CAAC;AAEF;;;;;;;;;GASG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAmB,EACnB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,8FAevE;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../src/components/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE,QAAA,MAAM,aAAa;;;8EAuBlB,CAAC;AAEF,KAAK,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEzE,KAAK,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC,GACxF,YAAY,CAAC,OAAO,aAAa,CAAC,GAClC,CACI;IACE,QAAQ,EAAE,SAAS,CAAC;IACpB,qDAAqD;IACrD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACD;IACE,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;CACf,CACJ,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAmB,EACnB,IAAW,EACX,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,GAAG,KAAK,EACT,EAAE,UAAU,8FA0BZ;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,CAAC"}
@@ -1,45 +1,88 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
2
  import { mergeProps } from "@base-ui/react/merge-props";
2
3
  import { useRender } from "@base-ui/react/use-render";
3
4
  import { cva } from "class-variance-authority";
4
5
  import { cn } from "../lib/utils.js";
5
- const badgeVariants = cva("group/badge inline-flex min-h-5 w-fit max-w-full shrink-0 items-center justify-center gap-1 overflow-hidden rounded-sm border border-transparent px-2 py-px text-xs font-medium transition-[background-color,border-color,color,opacity] duration-[var(--nc-duration-confirm)] ease-[var(--nc-ease-out-strong)] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive [&>svg]:pointer-events-none [&>svg]:size-3!", {
6
+ const badgeVariants = cva("group/badge inline-flex w-fit max-w-full shrink-0 items-center justify-center overflow-hidden rounded-full font-medium whitespace-nowrap tabular-nums transition-[background-color,box-shadow,color,opacity] duration-[var(--nc-duration-confirm)] ease-[var(--nc-ease-out-strong)]", {
6
7
  variants: {
7
8
  variant: {
8
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary-hover",
9
- secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-accent",
10
- destructive: "bg-destructive-soft text-destructive-soft-foreground [a]:hover:border-destructive-soft-foreground",
11
- outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
12
- ghost: "hover:bg-muted hover:text-muted-foreground",
13
- link: "text-(--nc-link) underline-offset-4 hover:underline",
9
+ default: "bg-primary text-primary-foreground",
10
+ secondary: "bg-secondary text-secondary-foreground",
11
+ outline: "bg-background text-foreground ring-1 ring-inset ring-border [a]:hover:bg-accent",
14
12
  teal: "bg-category-teal text-category-teal-foreground",
15
13
  purple: "bg-category-purple text-category-purple-foreground",
16
14
  pink: "bg-category-pink text-category-pink-foreground",
17
15
  },
16
+ size: {
17
+ sm: "h-5 gap-1 px-2 text-[11px] leading-5 tracking-[0.2px] has-data-[icon=inline-start]:pl-1.5 [&>[data-icon]>svg]:size-3",
18
+ md: "h-6 gap-1.25 px-3 text-xs leading-6 has-data-[icon=inline-start]:pl-2 [&>[data-icon]>svg]:size-3.5",
19
+ lg: "h-8 gap-1.5 px-3 text-sm leading-5 [&>[data-icon]>svg]:size-4",
20
+ },
18
21
  },
19
22
  defaultVariants: {
20
23
  variant: "default",
24
+ size: "md",
21
25
  },
22
26
  });
23
27
  /**
24
28
  * Short metadata beside its subject: a role, a plan, "Beta".
25
29
  *
26
30
  * @family Status
27
- * @when Short metadata beside its subject: a role ("Owner"), a plan, "Beta". 20 px high, 6 px corners, 12 px label at 500. The category fills (teal, purple, pink) name a kind.
28
- * @instead For a state use `StatusBadge`, which picks the tone and its mark: the gray, green, red, amber and blue fills are its alone. For one categorical fact in a row use `Tag`. For a change in a figure, `TrendBadge`.
29
- * @behaviour A static label. It becomes a link only through `render` with a real anchor, which then takes the hover. Never a click handler, never nested, never a paragraph.
30
- * @words One to three words, sentence case, a noun: "Business plan", not "This is on Business".
31
- * @access Read in place as text. A coloured variant still carries its word.
31
+ * @when "Use Badge for short, scannable metadata that sits next to the thing it describes: status, plan tier, environment, or role." (https://vercel.com/geist/badge)
32
+ * "One badge per row; two side by side is a sign the row needs a second column." (https://vercel.com/geist/badge)
33
+ * Ours: a state is a `StatusBadge`; a `Badge` is a role (*Owner*), a plan, an environment, *Beta*.
34
+ * It always has a word, or one `icon` with a `title`, and the type asks for it. `size` follows the
35
+ * type beside it: `sm` (20 px) next to small labels, `md` (24 px) in a row, `lg` (32 px) in a
36
+ * header. The category fills (teal, purple, pink) name a kind.
37
+ * @instead "For a colored dot without text, use `Status Dot`." (https://vercel.com/geist/badge)
38
+ * Ours: that is `StatusDot`.
39
+ * "For clickable filter chips that toggle a query, use the `pill` variant or a small `Button`." (https://vercel.com/geist/badge)
40
+ * Ours: there is no `pill` variant; a filter that toggles a query is a `Button` or
41
+ * `CollectionFilters`. For a state use `StatusBadge`, which picks the tone and its mark: the gray,
42
+ * green, red, amber and blue fills, soft or solid, are its alone. One categorical fact in a row is
43
+ * a `Tag`. A change in a figure is a `TrendBadge`.
44
+ * @behaviour "Badges are static labels." (https://vercel.com/geist/badge)
45
+ * "Don’t wire `onClick` onto them; promote to a Button or link if the user can act on the value." (https://vercel.com/geist/badge)
46
+ * Ours: it takes no `onClick`, no hover and no focus; it becomes a link only through `render` with
47
+ * a real anchor, and only `outline` takes the hover, a gray fill.
48
+ * "Keep badge content to text or `icon` + text." (https://vercel.com/geist/badge)
49
+ * "Never stack two icons or a child Badge inside a Badge." (https://vercel.com/geist/badge) Ours:
50
+ * never a paragraph either.
51
+ * "Pair lifecycle badges (`Alpha`, `Beta`, `Early Access`) with a `Tooltip` that names the limit, like `Alpha: API may change before GA`." (https://vercel.com/geist/badge)
52
+ * Ours: the badge is the `render` of a `TooltipTrigger` with `tabIndex={0}`, so keyboard and touch
53
+ * users reach the limit it names.
54
+ * "Don’t add a checkmark icon for success states or an X for errors; the variant carries that signal." (https://vercel.com/geist/badge)
55
+ * Ours: only `StatusBadge` carries a state, and it always draws its tone's mark.
56
+ * "Map meaning to color: `green` for healthy, `red` for error, `amber` for warning, `blue` for informational or production, `gray` for neutral." (https://vercel.com/geist/badge)
57
+ * "The `-subtle` suffix tones any of them down on dense surfaces." (https://vercel.com/geist/badge)
58
+ * Ours: those fills are `StatusBadge`'s, as the tones `success`, `danger`, `warning`, `info` and
59
+ * `neutral`, with `emphasis` `subtle` or `solid`. `Badge` is a fixed-height pill (20, 24 or 32 px)
60
+ * with no border: colour sits on the fill and the word. A soft fill takes its hue's strong shade
61
+ * for the word, `default` is the foreground colour inverted, and `outline` is neutral, a
62
+ * page-colour fill held by a 1 px inset ring. With an icon, the left padding is 6, 8 or 12 px, so
63
+ * the mark and the word look evenly spaced. The icon takes the word's colour.
64
+ * @words "Title Case, one word when possible, two max: `Active`, `Pending`, `Pro`, `Enterprise Trial`." (https://vercel.com/geist/badge)
65
+ * Ours: sentence case (*Enterprise trial*).
66
+ * "Match the canonical API or log term: `Production` not `Prod`, `Deployed` not `Live`, `Canceled` not `Cancelled` (the Vercel API uses one L)." (https://vercel.com/geist/badge)
67
+ * Ours: the term is our own API's.
68
+ * "Skip stuffing sentences inside (`Currently Active`, `You are on Pro`); the surrounding row supplies the context." (https://vercel.com/geist/badge)
69
+ * @access "Set `title` for icon-only or ambiguous badges so screen readers announce the meaning." (https://vercel.com/geist/badge)
70
+ * Ours: an icon alone must set `title`, and the type asks for it. Read in place as text.
71
+ * "Don’t rely on color alone; the text has to be readable without it." (https://vercel.com/geist/badge)
72
+ * Ours: a coloured variant still carries its word.
32
73
  */
33
- function Badge({ className, variant = "default", render, ...props }) {
74
+ function Badge({ className, variant = "default", size = "md", icon, children, render, ...props }) {
34
75
  return useRender({
35
76
  defaultTagName: "span",
36
77
  props: mergeProps({
37
- className: cn(badgeVariants({ variant }), className),
78
+ className: cn(badgeVariants({ variant, size }), className),
79
+ children: icon ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "pointer-events-none inline-flex shrink-0", "data-icon": "inline-start", children: icon }), children] })) : (children),
38
80
  }, props),
39
81
  render,
40
82
  state: {
41
83
  slot: "badge",
42
84
  variant,
85
+ size,
43
86
  },
44
87
  });
45
88
  }