@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
@@ -0,0 +1,33 @@
1
+ import * as React from "react";
2
+ /**
3
+ * A technical string cut in the middle, so its start and its end both stay readable.
4
+ *
5
+ * @family Data
6
+ * @when “Use Middle Truncate for strings whose head and tail both carry information: file paths (`apps/…/page.tsx`), URLs, deployment IDs (`dpl_…abc123`), commit hashes, branch names with prefixes.” (https://vercel.com/geist/middle-truncate)
7
+ * Ours: an environment variable is one of these too.
8
+ * @instead “For prose, descriptions, and headings, use end-truncation with `…` instead; cutting the middle of a sentence destroys meaning.” (https://vercel.com/geist/middle-truncate)
9
+ * “For any truncated value the user might need verbatim, pair with a `Tooltip` showing the full string or a copy-on-click affordance.” (https://vercel.com/geist/middle-truncate)
10
+ * Ours: a value someone may need exactly is `TextWithCopyButton` or sits beside a `CopyButton`; while
11
+ * the middle is cut, the whole value is also the element's `title`.
12
+ * @behaviour “Middle Truncate renders a single ellipsis glyph (`…`) rather than three periods. This keeps monospace values, including environment variable keys, IDs, hashes, and paths, from reserving three character cells for the truncation marker.” (https://vercel.com/geist/middle-truncate)
13
+ * “The component listens to its container width, so layouts that change width on hover (expanding cards, animated rows) cause the truncation point to jitter. Lock the width during interaction.” (https://vercel.com/geist/middle-truncate)
14
+ * “Copying truncated text yields the full original string from the underlying value, not the visible ellipsis form. Confirm this stays true if wrapping with custom `onCopy`.” (https://vercel.com/geist/middle-truncate)
15
+ * “Don’t wrap Middle Truncate in another `text-overflow: ellipsis` container; the two strategies fight each other and the inner ellipsis wins inconsistently.” (https://vercel.com/geist/middle-truncate)
16
+ * “Keep the visible string long enough on small viewports that the head still identifies the resource (path segment, ID prefix).” (https://vercel.com/geist/middle-truncate)
17
+ * Ours: it fills the width its parent gives and shows the whole value when it fits. Too narrow, the
18
+ * last third of the value, at most 16 characters, stays whole. While the middle is cut, copying a
19
+ * selection made inside it puts the whole value on the clipboard; a value shown in full copies only
20
+ * what is selected. A custom `onCopy` runs first, and `preventDefault` in it keeps the value as
21
+ * selected.
22
+ * @words Ours: the value as the system writes it, unchanged; the ellipsis comes from the layout, never from
23
+ * the text.
24
+ * @access “Expose the full string to assistive tech via the wrapping element’s accessible name (the component already keeps the full value in the DOM for copy).” (https://vercel.com/geist/middle-truncate)
25
+ * “Avoid Middle Truncate inside focusable controls without an explicit `aria-label`; the ellipsis on its own gives screen readers nothing to announce.” (https://vercel.com/geist/middle-truncate)
26
+ * Ours: the whole value is the element's text, read in full; inside a link or a button, the control
27
+ * carries the `aria-label` that names the target.
28
+ */
29
+ declare function MiddleTruncate({ className, onCopy, value, ...props }: Omit<React.ComponentProps<"span">, "children"> & {
30
+ value: string;
31
+ }): React.JSX.Element;
32
+ export { MiddleTruncate };
33
+ //# sourceMappingURL=middle-truncate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middle-truncate.d.ts","sourceRoot":"","sources":["../../src/components/middle-truncate.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAmC/B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,MAAM,EACN,KAAK,EACL,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,qBA0BpE;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/utils.js";
5
+ const TAIL_SHARE = 3;
6
+ const TAIL_MAX = 16;
7
+ function copiesWholeValue(root) {
8
+ const head = root.firstElementChild;
9
+ const selection = window.getSelection();
10
+ return (head !== null &&
11
+ head.scrollWidth > head.clientWidth &&
12
+ selection !== null &&
13
+ !selection.isCollapsed &&
14
+ root.contains(selection.anchorNode) &&
15
+ root.contains(selection.focusNode));
16
+ }
17
+ function useIsCut(root, value) {
18
+ const [cut, setCut] = React.useState(false);
19
+ React.useEffect(() => {
20
+ const element = root.current;
21
+ const head = element?.firstElementChild;
22
+ if (!element || !head || typeof ResizeObserver === "undefined")
23
+ return;
24
+ const measure = () => setCut(head.scrollWidth > head.clientWidth);
25
+ measure();
26
+ const observer = new ResizeObserver(measure);
27
+ observer.observe(element);
28
+ return () => observer.disconnect();
29
+ }, [root, value]);
30
+ return cut;
31
+ }
32
+ /**
33
+ * A technical string cut in the middle, so its start and its end both stay readable.
34
+ *
35
+ * @family Data
36
+ * @when “Use Middle Truncate for strings whose head and tail both carry information: file paths (`apps/…/page.tsx`), URLs, deployment IDs (`dpl_…abc123`), commit hashes, branch names with prefixes.” (https://vercel.com/geist/middle-truncate)
37
+ * Ours: an environment variable is one of these too.
38
+ * @instead “For prose, descriptions, and headings, use end-truncation with `…` instead; cutting the middle of a sentence destroys meaning.” (https://vercel.com/geist/middle-truncate)
39
+ * “For any truncated value the user might need verbatim, pair with a `Tooltip` showing the full string or a copy-on-click affordance.” (https://vercel.com/geist/middle-truncate)
40
+ * Ours: a value someone may need exactly is `TextWithCopyButton` or sits beside a `CopyButton`; while
41
+ * the middle is cut, the whole value is also the element's `title`.
42
+ * @behaviour “Middle Truncate renders a single ellipsis glyph (`…`) rather than three periods. This keeps monospace values, including environment variable keys, IDs, hashes, and paths, from reserving three character cells for the truncation marker.” (https://vercel.com/geist/middle-truncate)
43
+ * “The component listens to its container width, so layouts that change width on hover (expanding cards, animated rows) cause the truncation point to jitter. Lock the width during interaction.” (https://vercel.com/geist/middle-truncate)
44
+ * “Copying truncated text yields the full original string from the underlying value, not the visible ellipsis form. Confirm this stays true if wrapping with custom `onCopy`.” (https://vercel.com/geist/middle-truncate)
45
+ * “Don’t wrap Middle Truncate in another `text-overflow: ellipsis` container; the two strategies fight each other and the inner ellipsis wins inconsistently.” (https://vercel.com/geist/middle-truncate)
46
+ * “Keep the visible string long enough on small viewports that the head still identifies the resource (path segment, ID prefix).” (https://vercel.com/geist/middle-truncate)
47
+ * Ours: it fills the width its parent gives and shows the whole value when it fits. Too narrow, the
48
+ * last third of the value, at most 16 characters, stays whole. While the middle is cut, copying a
49
+ * selection made inside it puts the whole value on the clipboard; a value shown in full copies only
50
+ * what is selected. A custom `onCopy` runs first, and `preventDefault` in it keeps the value as
51
+ * selected.
52
+ * @words Ours: the value as the system writes it, unchanged; the ellipsis comes from the layout, never from
53
+ * the text.
54
+ * @access “Expose the full string to assistive tech via the wrapping element’s accessible name (the component already keeps the full value in the DOM for copy).” (https://vercel.com/geist/middle-truncate)
55
+ * “Avoid Middle Truncate inside focusable controls without an explicit `aria-label`; the ellipsis on its own gives screen readers nothing to announce.” (https://vercel.com/geist/middle-truncate)
56
+ * Ours: the whole value is the element's text, read in full; inside a link or a button, the control
57
+ * carries the `aria-label` that names the target.
58
+ */
59
+ function MiddleTruncate({ className, onCopy, value, ...props }) {
60
+ const root = React.useRef(null);
61
+ const cut = useIsCut(root, value);
62
+ const characters = Array.from(value);
63
+ const tailStart = characters.length - Math.min(Math.ceil(characters.length / TAIL_SHARE), TAIL_MAX);
64
+ return (_jsxs("span", { ref: root, "data-slot": "middle-truncate", title: cut ? value : undefined, className: cn("inline-flex max-w-full min-w-0 overflow-hidden", className), onCopy: (event) => {
65
+ onCopy?.(event);
66
+ if (event.defaultPrevented || !copiesWholeValue(event.currentTarget))
67
+ return;
68
+ event.clipboardData.setData("text/plain", value);
69
+ event.preventDefault();
70
+ }, ...props, children: [_jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-pre", children: characters.slice(0, tailStart).join("") }), _jsx("span", { className: "shrink-0 whitespace-pre", children: characters.slice(tailStart).join("") })] }));
71
+ }
72
+ export { MiddleTruncate };
@@ -0,0 +1,94 @@
1
+ import * as React from "react";
2
+ import { type FieldName } from "../internal/field-frame.js";
3
+ import { type FieldSize } from "../internal/input-box.js";
4
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
5
+ type MultiSelectContextValue = {
6
+ selectedCount: number;
7
+ totalCount: number;
8
+ onSelectAll: () => void;
9
+ selectOnlyLabel: string;
10
+ selectAllLabel: string;
11
+ };
12
+ type MultiSelectProps = React.ComponentProps<typeof Popover> & MultiSelectContextValue;
13
+ /**
14
+ * A menu of checkbox rows that chooses several values from a known list, with the count in its
15
+ * trigger.
16
+ *
17
+ * @family Choices
18
+ * @when "A keyboard-navigable dropdown for selecting multiple items with advanced focus management."
19
+ * (https://vercel.com/geist/multi-select) "Pick `<MultiSelect>` when users pick more than one value
20
+ * from a known list (regions, scopes, tags)." (https://vercel.com/geist/multi-select) Ours: also the facets of a collection.
21
+ * @instead "For a single value from a short list, use `Select`."
22
+ * (https://vercel.com/geist/multi-select) "When typing to filter is more important than seeing
23
+ * every option at once, use `Combobox`." (https://vercel.com/geist/multi-select) "Skip
24
+ * `<MultiSelect>` for boolean settings; `Toggle` handles those."
25
+ * (https://vercel.com/geist/multi-select) Ours: `Combobox` takes several values with `multiple`; a
26
+ * yes-or-no setting is a `Switch`, never a one-row multi-select.
27
+ * @behaviour "Use controlled mode when state lives in the URL or syncs to the server so the trigger
28
+ * label and stored value stay in lockstep." (https://vercel.com/geist/multi-select) "Use controlled
29
+ * state to manage selections programmatically." (https://vercel.com/geist/multi-select) Ours: the
30
+ * caller always owns the selection and passes it back through each row, so the trigger and the
31
+ * stored value (the URL, the server) never disagree; the root takes the same `selectedCount` and
32
+ * `totalCount` the trigger's summary is built from. "Show the selected count in the trigger (`3
33
+ * regions selected`); show the single name when only one is picked."
34
+ * (https://vercel.com/geist/multi-select) The trigger is `Input`'s box at its default size, in
35
+ * regular weight, with the chevron at the end (it turns up while the list is open); it keeps the
36
+ * hover edge while the list is open and takes the page's outline for keyboard focus, as a button
37
+ * does. Everything is neutral: a checked box is ink, never blue, and an error turns only the
38
+ * trigger's ring red. `label` and `error` go on `MultiSelectTrigger`, and a string `label` requires
39
+ * `id`; a trigger with no name does not compile. The list opens 8 px under the trigger at least as
40
+ * wide as it, in an 8 px inset, with rows 28 px tall and no gap, and stops 16 px short of the
41
+ * screen's edge (at most 24rem tall, then it scrolls). A row is the checkbox in a 28 px square that
42
+ * fills on hover, then a button holding the row's name; pressing the name runs the button, pressing
43
+ * the box toggles the row. "**Checkbox focus + Enter/Space**: Toggle individual item"
44
+ * (https://vercel.com/geist/multi-select) "**Button focus + Enter/Space**: Smart selection (Select
45
+ * Only, Select All, or Toggle based on context)" (https://vercel.com/geist/multi-select) "**Hidden
46
+ * action labels**: Appear on hover/focus to show available actions"
47
+ * (https://vercel.com/geist/multi-select) Ours: the button's label reads *Select all* on a chosen
48
+ * row while some rows are unchosen, and *Select only* on every other row; it shows on hover and
49
+ * focus of the row, and always on touch. "Keep checkbox focus and button focus distinct so Up/Down
50
+ * navigates rows and Left/Right toggles between the row’s checkbox and action button."
51
+ * (https://vercel.com/geist/multi-select) "**Up/Down arrows**: Navigate between rows while
52
+ * maintaining checkbox/button focus state" (https://vercel.com/geist/multi-select) "**Left/Right
53
+ * arrows**: Switch between checkbox and button focus within the current row"
54
+ * (https://vercel.com/geist/multi-select) "**Tab**: Focus away from the menu (natural tab
55
+ * behavior)" (https://vercel.com/geist/multi-select) "**Enter/Space**: Execute actions based on
56
+ * current focus (checkbox toggle or button click)" (https://vercel.com/geist/multi-select) "Trap
57
+ * focus inside the menu while it’s open and return focus to the trigger on close."
58
+ * (https://vercel.com/geist/multi-select) Ours: focus moves into the list when it opens; Tab leaves
59
+ * it in order. "For empty filters, render `No {items} match "{query}"` rather than `No results`."
60
+ * (https://vercel.com/geist/multi-select) Ours: there is no filter box, so a list that needs one is
61
+ * a `Combobox` with `multiple`.
62
+ * @words The trigger says how many are chosen in the product's words: the name when exactly one is
63
+ * chosen, *No regions selected* when none. It is never empty. Rows are sentence case names.
64
+ * "Announce bulk actions (`Select All`, `Select Only`) through the visible button label so the
65
+ * action matches what the screen reader speaks." (https://vercel.com/geist/multi-select) Ours: the
66
+ * two button labels come from the caller, in sentence case.
67
+ * @access "Each row checkbox needs an `aria-label` that names the item (`Select us-east-1`); a bare
68
+ * `Select` is unanchored for screen readers." (https://vercel.com/geist/multi-select) Ours: each
69
+ * row's checkbox is named by the row's name; each button is named by its label and the row (*Select
70
+ * only us-east-1*). "The trigger button needs a stable accessible name even when zero items are
71
+ * selected; don’t rely on the placeholder alone." (https://vercel.com/geist/multi-select) Ours: the
72
+ * trigger is a button with `aria-expanded`, named by its visible label tied by `id`, or by
73
+ * `aria-label` or `aria-labelledby`; the summary describes it.
74
+ */
75
+ declare function MultiSelect({ selectedCount, totalCount, onSelectAll, selectOnlyLabel, selectAllLabel, ...props }: MultiSelectProps): React.JSX.Element;
76
+ declare function MultiSelectTrigger({ className, children, size, label, error, ...props }: Omit<React.ComponentProps<typeof PopoverTrigger>, "children"> & {
77
+ /** The summary of the choice: a count, a name, or that nothing is chosen. It describes the trigger. */
78
+ children: string;
79
+ size?: FieldSize;
80
+ /** The message under the box, in the product's words; it also marks the box invalid. */
81
+ error?: string;
82
+ } & FieldName): React.JSX.Element;
83
+ declare function MultiSelectContent({ className, align, sideOffset, onKeyDown, ...props }: React.ComponentProps<typeof PopoverContent>): React.JSX.Element;
84
+ declare function MultiSelectRow({ name, checked, onCheckedChange, onSelectOnly, disabled, className, }: {
85
+ name: string;
86
+ checked: boolean;
87
+ onCheckedChange: (checked: boolean) => void;
88
+ /** Chooses this row and clears the rest. */
89
+ onSelectOnly: () => void;
90
+ disabled?: boolean;
91
+ className?: string;
92
+ }): React.JSX.Element;
93
+ export { MultiSelect, MultiSelectContent, MultiSelectRow, MultiSelectTrigger };
94
+ //# sourceMappingURL=multi-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-select.d.ts","sourceRoot":"","sources":["../../src/components/multi-select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG/E,KAAK,uBAAuB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAUF,KAAK,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,OAAO,CAAC,GAAG,uBAAuB,CAAC;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,iBAAS,WAAW,CAAC,EACnB,aAAa,EACb,UAAU,EACV,WAAW,EACX,eAAe,EACf,cAAc,EACd,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAUlB;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,QAAQ,EACR,IAAgB,EAChB,KAAK,EACL,KAAK,EACL,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACjE,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,qBAmCZ;AAwBD,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,KAAe,EACf,UAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,qBAiB7C;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,OAAO,EACP,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,4CAA4C;IAC5C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,qBAuDA;AAED,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,132 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
5
+ import { cn } from "../lib/utils.js";
6
+ import { Button } from "./button.js";
7
+ import { Checkbox } from "./checkbox.js";
8
+ import { FieldFrame } from "../internal/field-frame.js";
9
+ import { fieldTriggerStates } from "../internal/input-box.js";
10
+ import { Label } from "./label.js";
11
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
12
+ import { selectTriggerVariants } from "./select.js";
13
+ const MultiSelectContext = React.createContext(null);
14
+ function useMultiSelect() {
15
+ const context = React.useContext(MultiSelectContext);
16
+ if (!context)
17
+ throw new Error("MultiSelectRow must be inside <MultiSelect>");
18
+ return context;
19
+ }
20
+ /**
21
+ * A menu of checkbox rows that chooses several values from a known list, with the count in its
22
+ * trigger.
23
+ *
24
+ * @family Choices
25
+ * @when "A keyboard-navigable dropdown for selecting multiple items with advanced focus management."
26
+ * (https://vercel.com/geist/multi-select) "Pick `<MultiSelect>` when users pick more than one value
27
+ * from a known list (regions, scopes, tags)." (https://vercel.com/geist/multi-select) Ours: also the facets of a collection.
28
+ * @instead "For a single value from a short list, use `Select`."
29
+ * (https://vercel.com/geist/multi-select) "When typing to filter is more important than seeing
30
+ * every option at once, use `Combobox`." (https://vercel.com/geist/multi-select) "Skip
31
+ * `<MultiSelect>` for boolean settings; `Toggle` handles those."
32
+ * (https://vercel.com/geist/multi-select) Ours: `Combobox` takes several values with `multiple`; a
33
+ * yes-or-no setting is a `Switch`, never a one-row multi-select.
34
+ * @behaviour "Use controlled mode when state lives in the URL or syncs to the server so the trigger
35
+ * label and stored value stay in lockstep." (https://vercel.com/geist/multi-select) "Use controlled
36
+ * state to manage selections programmatically." (https://vercel.com/geist/multi-select) Ours: the
37
+ * caller always owns the selection and passes it back through each row, so the trigger and the
38
+ * stored value (the URL, the server) never disagree; the root takes the same `selectedCount` and
39
+ * `totalCount` the trigger's summary is built from. "Show the selected count in the trigger (`3
40
+ * regions selected`); show the single name when only one is picked."
41
+ * (https://vercel.com/geist/multi-select) The trigger is `Input`'s box at its default size, in
42
+ * regular weight, with the chevron at the end (it turns up while the list is open); it keeps the
43
+ * hover edge while the list is open and takes the page's outline for keyboard focus, as a button
44
+ * does. Everything is neutral: a checked box is ink, never blue, and an error turns only the
45
+ * trigger's ring red. `label` and `error` go on `MultiSelectTrigger`, and a string `label` requires
46
+ * `id`; a trigger with no name does not compile. The list opens 8 px under the trigger at least as
47
+ * wide as it, in an 8 px inset, with rows 28 px tall and no gap, and stops 16 px short of the
48
+ * screen's edge (at most 24rem tall, then it scrolls). A row is the checkbox in a 28 px square that
49
+ * fills on hover, then a button holding the row's name; pressing the name runs the button, pressing
50
+ * the box toggles the row. "**Checkbox focus + Enter/Space**: Toggle individual item"
51
+ * (https://vercel.com/geist/multi-select) "**Button focus + Enter/Space**: Smart selection (Select
52
+ * Only, Select All, or Toggle based on context)" (https://vercel.com/geist/multi-select) "**Hidden
53
+ * action labels**: Appear on hover/focus to show available actions"
54
+ * (https://vercel.com/geist/multi-select) Ours: the button's label reads *Select all* on a chosen
55
+ * row while some rows are unchosen, and *Select only* on every other row; it shows on hover and
56
+ * focus of the row, and always on touch. "Keep checkbox focus and button focus distinct so Up/Down
57
+ * navigates rows and Left/Right toggles between the row’s checkbox and action button."
58
+ * (https://vercel.com/geist/multi-select) "**Up/Down arrows**: Navigate between rows while
59
+ * maintaining checkbox/button focus state" (https://vercel.com/geist/multi-select) "**Left/Right
60
+ * arrows**: Switch between checkbox and button focus within the current row"
61
+ * (https://vercel.com/geist/multi-select) "**Tab**: Focus away from the menu (natural tab
62
+ * behavior)" (https://vercel.com/geist/multi-select) "**Enter/Space**: Execute actions based on
63
+ * current focus (checkbox toggle or button click)" (https://vercel.com/geist/multi-select) "Trap
64
+ * focus inside the menu while it’s open and return focus to the trigger on close."
65
+ * (https://vercel.com/geist/multi-select) Ours: focus moves into the list when it opens; Tab leaves
66
+ * it in order. "For empty filters, render `No {items} match "{query}"` rather than `No results`."
67
+ * (https://vercel.com/geist/multi-select) Ours: there is no filter box, so a list that needs one is
68
+ * a `Combobox` with `multiple`.
69
+ * @words The trigger says how many are chosen in the product's words: the name when exactly one is
70
+ * chosen, *No regions selected* when none. It is never empty. Rows are sentence case names.
71
+ * "Announce bulk actions (`Select All`, `Select Only`) through the visible button label so the
72
+ * action matches what the screen reader speaks." (https://vercel.com/geist/multi-select) Ours: the
73
+ * two button labels come from the caller, in sentence case.
74
+ * @access "Each row checkbox needs an `aria-label` that names the item (`Select us-east-1`); a bare
75
+ * `Select` is unanchored for screen readers." (https://vercel.com/geist/multi-select) Ours: each
76
+ * row's checkbox is named by the row's name; each button is named by its label and the row (*Select
77
+ * only us-east-1*). "The trigger button needs a stable accessible name even when zero items are
78
+ * selected; don’t rely on the placeholder alone." (https://vercel.com/geist/multi-select) Ours: the
79
+ * trigger is a button with `aria-expanded`, named by its visible label tied by `id`, or by
80
+ * `aria-label` or `aria-labelledby`; the summary describes it.
81
+ */
82
+ function MultiSelect({ selectedCount, totalCount, onSelectAll, selectOnlyLabel, selectAllLabel, ...props }) {
83
+ const value = React.useMemo(() => ({ selectedCount, totalCount, onSelectAll, selectOnlyLabel, selectAllLabel }), [selectedCount, totalCount, onSelectAll, selectOnlyLabel, selectAllLabel]);
84
+ return (_jsx(MultiSelectContext.Provider, { value: value, children: _jsx(Popover, { ...props }) }));
85
+ }
86
+ function MultiSelectTrigger({ className, children, size = "default", label, error, ...props }) {
87
+ const summaryId = React.useId();
88
+ return (_jsx(FieldFrame, { label: label, error: error, size: size, control: props, children: (aria) => (_jsxs(PopoverTrigger, { "data-slot": "multi-select-trigger", "data-size": size, "data-field-frame": "", className: cn(selectTriggerVariants({ size }), fieldTriggerStates, "group/multi-select-trigger pr-3.25 pl-2.5", size !== "lg" && "leading-5.25", className), ...props, ...aria, "aria-describedby": [aria["aria-describedby"], summaryId].filter(Boolean).join(" "), children: [_jsx("span", { id: summaryId, className: "flex-1 truncate px-1.5 text-left", children: children }), _jsx(ChevronDownIcon, { "aria-hidden": "true", className: "size-3.5 text-muted-foreground group-data-popup-open/multi-select-trigger:hidden" }), _jsx(ChevronUpIcon, { "aria-hidden": "true", className: "hidden size-3.5 text-muted-foreground group-data-popup-open/multi-select-trigger:block" })] })) }));
89
+ }
90
+ const ROW = "[data-slot=multi-select-row]";
91
+ function moveFocus(event) {
92
+ const target = event.target;
93
+ if (!(target instanceof HTMLElement))
94
+ return;
95
+ const column = target.closest("[data-multi-select]")?.dataset.multiSelect;
96
+ const row = target.closest(ROW);
97
+ if (!column || !row)
98
+ return;
99
+ const rows = [...event.currentTarget.querySelectorAll(ROW)];
100
+ const index = rows.indexOf(row);
101
+ const focusIn = (next, name) => {
102
+ const control = next?.querySelector(`[data-multi-select=${name}]`);
103
+ if (!control)
104
+ return;
105
+ event.preventDefault();
106
+ control.focus();
107
+ };
108
+ if (event.key === "ArrowDown")
109
+ focusIn(rows[index + 1], column);
110
+ else if (event.key === "ArrowUp")
111
+ focusIn(rows[index - 1], column);
112
+ else if (event.key === "ArrowRight" && column === "check")
113
+ focusIn(row, "action");
114
+ else if (event.key === "ArrowLeft" && column === "action")
115
+ focusIn(row, "check");
116
+ }
117
+ function MultiSelectContent({ className, align = "start", sideOffset = 8, onKeyDown, ...props }) {
118
+ return (_jsx(PopoverContent, { "data-slot": "multi-select-content", align: align, sideOffset: sideOffset, className: cn("max-h-[min(calc(var(--available-height)---spacing(4)),24rem)] w-auto min-w-(--anchor-width) gap-0 overflow-y-auto p-2", className), onKeyDown: (event) => {
119
+ onKeyDown?.(event);
120
+ if (!event.defaultPrevented)
121
+ moveFocus(event);
122
+ }, ...props }));
123
+ }
124
+ function MultiSelectRow({ name, checked, onCheckedChange, onSelectOnly, disabled, className, }) {
125
+ const { selectedCount, totalCount, onSelectAll, selectOnlyLabel, selectAllLabel } = useMultiSelect();
126
+ const id = React.useId();
127
+ const actionId = `${id}-action`;
128
+ const nameId = `${id}-name`;
129
+ const selectsAll = checked && selectedCount < totalCount;
130
+ return (_jsxs("div", { "data-slot": "multi-select-row", className: cn("group/multi-select-row flex min-h-touch-target items-center text-sm [@media(hover:hover)_and_(pointer:fine)]:min-h-7", className), children: [_jsx(Label, { className: "size-7 shrink-0 justify-center gap-0 rounded-xs-plus hover:bg-accent active:bg-border has-data-disabled:pointer-events-none", htmlFor: id, children: _jsx(Checkbox, { id: id, "aria-labelledby": nameId, checked: checked, "data-multi-select": "check", disabled: disabled, onCheckedChange: onCheckedChange }) }), totalCount > 1 ? (_jsxs(Button, { "aria-labelledby": `${actionId} ${nameId}`, className: "h-7 flex-1 justify-between gap-0 rounded-xs-plus p-1 text-sm font-normal hover:bg-accent focus-visible:bg-accent active:bg-border disabled:text-placeholder disabled:opacity-100", "data-multi-select": "action", disabled: disabled, onClick: selectsAll ? onSelectAll : onSelectOnly, size: "xs", variant: "ghost", children: [_jsx("span", { className: "min-w-0 truncate text-left", id: nameId, children: name }), _jsx("span", { className: "min-w-16 rounded-xs-plus px-1 py-0.5 text-right text-xs font-normal text-muted-foreground opacity-0 group-focus-within/multi-select-row:opacity-100 group-hover/multi-select-row:opacity-100 [@media(hover:none)]:opacity-100", id: actionId, children: selectsAll ? selectAllLabel : selectOnlyLabel })] })) : (_jsx(Label, { className: "flex-1 truncate px-1 text-sm leading-5", htmlFor: id, id: nameId, children: name }))] }));
131
+ }
132
+ export { MultiSelect, MultiSelectContent, MultiSelectRow, MultiSelectTrigger };
@@ -1,24 +1,48 @@
1
1
  import * as React from "react";
2
- type NativeSelectProps = Omit<React.ComponentProps<"select">, "size"> & {
3
- size?: "sm" | "default";
4
- };
2
+ import { type FieldName } from "../internal/field-frame.js";
3
+ import { type FieldSize } from "../internal/input-box.js";
4
+ type NativeSelectProps = Omit<React.ComponentProps<"select">, "prefix" | "size"> & {
5
+ size?: FieldSize;
6
+ /** A mark before the value, such as an icon. */
7
+ prefix?: React.ReactNode;
8
+ /** A mark at the end, in place of the chevron. */
9
+ suffix?: React.ReactNode;
10
+ /** One muted sentence under the box that says what to enter, read with the box. */
11
+ description?: string;
12
+ /** The message under the box, in the product's words; it also marks the box invalid. */
13
+ error?: string;
14
+ } & FieldName;
5
15
  /**
6
16
  * The platform's own select, drawn as our input box.
7
17
  *
8
18
  * @family Inputs
9
19
  * @when A long fixed list inside a native form, where the platform's own picker serves best: a time
10
20
  * zone, a country.
11
- * @instead Two or three options are radios or a segmented control. Up to about ten, drawn in our
12
- * style, is `Select`. A list people type into is `Combobox`.
13
- * @behaviour Same box as `Input`, the chevron 10 px from the edge in the muted grey. It opens the
14
- * system's list, with native keyboard and typing. As an uncontrolled field it keeps a saved value
15
- * instead of snapping back to the page's first default.
16
- * @words The label names the thing chosen (*Time zone*). A placeholder option is distinct from a
17
- * real one and never preselected as if chosen.
18
- * @access A real `select` with a visible label; option groups are `optgroup`. The chevron is
19
- * decorative.
21
+ * @instead Two or three options are radios or a segmented control. "Pick `<Select>` for short,
22
+ * fixed lists (under ~10 items) where typing adds nothing; switch to `Combobox` once filtering
23
+ * helps." (https://vercel.com/geist/select) Ours: `Select` draws the short list in our style.
24
+ * @behaviour Same box, sizes, ring, hover, focus halo and disabled as `Input`, filling its
25
+ * container, the chevron in the muted grey with room reserved for it, after an optional `prefix`
26
+ * mark (a `suffix` mark takes the chevron's place). Colour sits in one place: an error turns the
27
+ * ring red and fills the halo, and colours the message; the fill, the value and the label stay
28
+ * neutral. `label` and `error` draw the `Field` parts around the box, and a string `label` requires
29
+ * `id`; a box with no name does not compile. It opens the system's list, with native keyboard and
30
+ * typing. As an uncontrolled field it keeps a saved value instead of snapping back to the page's
31
+ * first default. "Validate on blur and pass a string to `error`; messages name the field and end in
32
+ * a period (`Select a framework.`)." (https://vercel.com/geist/select) Other form rules are
33
+ * `Field`'s.
34
+ * @words "Label is a short Title Case noun (`Framework`, `Region`); accept the prop directly on
35
+ * `<Select>`." (https://vercel.com/geist/select) "Options are Title Case when short and match
36
+ * canonical branding (`Next.js`, not `NextJS`); keep the same register across the list."
37
+ * (https://vercel.com/geist/select) Ours: the label names the thing chosen (*Time zone*) and
38
+ * options are sentence case. A placeholder option is distinct from a real one and never preselected
39
+ * as if chosen.
40
+ * @access A real `select` with a visible label tied by `id`, or `aria-label`. "Group options past
41
+ * ~10 items with native `<optgroup>`; Geist `<Select>` has no `.Group` static."
42
+ * (https://vercel.com/geist/select) Ours: option groups are `optgroup`. The chevron, the prefix and
43
+ * the suffix are decorative.
20
44
  */
21
- declare function NativeSelect({ className, size, ref, ...props }: NativeSelectProps): React.JSX.Element;
45
+ declare function NativeSelect({ className, size, prefix, suffix, label, description, error, ref, ...props }: NativeSelectProps): React.JSX.Element;
22
46
  declare function NativeSelectOption({ className, ...props }: React.ComponentProps<"option">): React.JSX.Element;
23
47
  declare function NativeSelectOptGroup({ className, ...props }: React.ComponentProps<"optgroup">): React.JSX.Element;
24
48
  export { NativeSelect, NativeSelectOptGroup, NativeSelectOption };
@@ -1 +1 @@
1
- {"version":3,"file":"native-select.d.ts","sourceRoot":"","sources":["../../src/components/native-select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,KAAK,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,GAAG;IACtE,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,IAAgB,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,qBAiEtF;AAED,iBAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,qBAQlF;AAED,iBAAS,oBAAoB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,qBAQtF;AAED,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"native-select.d.ts","sourceRoot":"","sources":["../../src/components/native-select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG7F,KAAK,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,GAAG;IACjF,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,kDAAkD;IAClD,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,IAAgB,EAChB,MAAM,EACN,MAAM,EACN,KAAK,EACL,WAAW,EACX,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,iBAAiB,qBA6FnB;AAED,iBAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,qBAQlF;AAED,iBAAS,oBAAoB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,qBAQtF;AAED,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC"}
@@ -2,6 +2,8 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cn } from "../lib/utils.js";
5
+ import { FieldFrame } from "../internal/field-frame.js";
6
+ import { fieldDisabled, fieldRing, fieldStates } from "../internal/input-box.js";
5
7
  import { ChevronDownIcon } from "lucide-react";
6
8
  /**
7
9
  * The platform's own select, drawn as our input box.
@@ -9,17 +11,31 @@ import { ChevronDownIcon } from "lucide-react";
9
11
  * @family Inputs
10
12
  * @when A long fixed list inside a native form, where the platform's own picker serves best: a time
11
13
  * zone, a country.
12
- * @instead Two or three options are radios or a segmented control. Up to about ten, drawn in our
13
- * style, is `Select`. A list people type into is `Combobox`.
14
- * @behaviour Same box as `Input`, the chevron 10 px from the edge in the muted grey. It opens the
15
- * system's list, with native keyboard and typing. As an uncontrolled field it keeps a saved value
16
- * instead of snapping back to the page's first default.
17
- * @words The label names the thing chosen (*Time zone*). A placeholder option is distinct from a
18
- * real one and never preselected as if chosen.
19
- * @access A real `select` with a visible label; option groups are `optgroup`. The chevron is
20
- * decorative.
14
+ * @instead Two or three options are radios or a segmented control. "Pick `<Select>` for short,
15
+ * fixed lists (under ~10 items) where typing adds nothing; switch to `Combobox` once filtering
16
+ * helps." (https://vercel.com/geist/select) Ours: `Select` draws the short list in our style.
17
+ * @behaviour Same box, sizes, ring, hover, focus halo and disabled as `Input`, filling its
18
+ * container, the chevron in the muted grey with room reserved for it, after an optional `prefix`
19
+ * mark (a `suffix` mark takes the chevron's place). Colour sits in one place: an error turns the
20
+ * ring red and fills the halo, and colours the message; the fill, the value and the label stay
21
+ * neutral. `label` and `error` draw the `Field` parts around the box, and a string `label` requires
22
+ * `id`; a box with no name does not compile. It opens the system's list, with native keyboard and
23
+ * typing. As an uncontrolled field it keeps a saved value instead of snapping back to the page's
24
+ * first default. "Validate on blur and pass a string to `error`; messages name the field and end in
25
+ * a period (`Select a framework.`)." (https://vercel.com/geist/select) Other form rules are
26
+ * `Field`'s.
27
+ * @words "Label is a short Title Case noun (`Framework`, `Region`); accept the prop directly on
28
+ * `<Select>`." (https://vercel.com/geist/select) "Options are Title Case when short and match
29
+ * canonical branding (`Next.js`, not `NextJS`); keep the same register across the list."
30
+ * (https://vercel.com/geist/select) Ours: the label names the thing chosen (*Time zone*) and
31
+ * options are sentence case. A placeholder option is distinct from a real one and never preselected
32
+ * as if chosen.
33
+ * @access A real `select` with a visible label tied by `id`, or `aria-label`. "Group options past
34
+ * ~10 items with native `<optgroup>`; Geist `<Select>` has no `.Group` static."
35
+ * (https://vercel.com/geist/select) Ours: option groups are `optgroup`. The chevron, the prefix and
36
+ * the suffix are decorative.
21
37
  */
22
- function NativeSelect({ className, size = "default", ref, ...props }) {
38
+ function NativeSelect({ className, size = "default", prefix, suffix, label, description, error, ref, ...props }) {
23
39
  const select = React.useRef(null);
24
40
  const setRef = React.useCallback((node) => {
25
41
  select.current = node;
@@ -63,7 +79,7 @@ function NativeSelect({ className, size = "default", ref, ...props }) {
63
79
  option.selected = shown.includes(option.value);
64
80
  appliedDefault.current = defaultKey;
65
81
  }, [defaultKey]);
66
- return (_jsxs("div", { className: cn("group/native-select relative w-fit has-[select:disabled]:opacity-50", className), "data-slot": "native-select-wrapper", "data-size": size, children: [_jsx("select", { ref: setRef, "data-slot": "native-select", "data-size": size, className: "h-control-height min-h-touch-target w-full min-w-0 appearance-none rounded-sm border border-input bg-background py-1 pr-8 pl-control-padding-inline text-sm transition-colors select-none selection:bg-primary selection:text-primary-foreground placeholder:text-placeholder disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive data-[size=sm]:h-nadicode-control-height-sm data-[size=sm]:py-0.5 [@media(hover:hover)_and_(pointer:fine)]:min-h-0", ...props }), _jsx(ChevronDownIcon, { className: "pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none", "aria-hidden": "true", "data-slot": "native-select-icon" })] }));
82
+ return (_jsx(FieldFrame, { label: label, description: description, error: error, size: size, control: props, children: (aria) => (_jsxs("div", { className: cn("group/native-select relative w-full", className), "data-slot": "native-select-wrapper", "data-size": size, children: [prefix ? (_jsx("span", { "data-slot": "native-select-prefix", "aria-hidden": "true", className: "pointer-events-none absolute top-1/2 left-control-padding-inline flex -translate-y-1/2 items-center text-muted-foreground [&_svg:not([class*='size-'])]:size-4", children: prefix })) : null, _jsx("select", { ref: setRef, "data-slot": "native-select", "data-size": size, "data-field-frame": "", className: cn("h-control-height min-h-touch-target w-full min-w-0 cursor-pointer appearance-none rounded-sm bg-(--nc-field,var(--background)) py-0 pr-9 pl-control-padding-inline text-sm select-none selection:bg-primary selection:text-primary-foreground data-[size=lg]:h-nadicode-control-height-lg data-[size=lg]:rounded-md data-[size=lg]:text-base data-[size=sm]:h-nadicode-control-height-sm [@media(hover:hover)_and_(pointer:fine)]:min-h-0", fieldRing, fieldStates, fieldDisabled, prefix ? "pl-10" : undefined), ...props, ...aria }), suffix ? (_jsx("span", { "data-slot": "native-select-suffix", "aria-hidden": "true", className: "pointer-events-none absolute top-1/2 right-3 flex -translate-y-1/2 items-center text-muted-foreground select-none [&_svg:not([class*='size-'])]:size-4", children: suffix })) : (_jsx(ChevronDownIcon, { className: "pointer-events-none absolute top-1/2 right-3 size-3.5 -translate-y-1/2 text-muted-foreground select-none", "aria-hidden": "true", "data-slot": "native-select-icon" }))] })) }));
67
83
  }
68
84
  function NativeSelectOption({ className, ...props }) {
69
85
  return (_jsx("option", { "data-slot": "native-select-option", className: cn("bg-[Canvas] text-[CanvasText]", className), ...props }));
@@ -1,12 +1,19 @@
1
- import type { ComponentProps, ReactElement, ReactNode } from "react";
2
- export type NoticeBannerTone = "neutral" | "info" | "warning" | "destructive";
1
+ import type { ComponentProps, ReactNode } from "react";
2
+ import type { LucideIcon } from "lucide-react";
3
+ import { type NoticeTone } from "../internal/notice.js";
4
+ import type { PageCommand } from "./page-actions.js";
5
+ export type NoticeBannerTone = NoticeTone;
3
6
  export type NoticeBannerLiveRegion = "off" | "polite";
4
7
  export type NoticeBannerProps = {
5
- /** The fix the page offers, as a button or a link. Required: a condition is shown with its fix. */
6
- action: ReactElement;
8
+ /** The one fix the page offers, drawn as an underlined link. Required: a condition is shown with its fix. */
9
+ action: PageCommand;
7
10
  className?: string;
8
11
  description?: ReactNode;
9
12
  detail?: ReactNode;
13
+ /** Replaces the tone's mark with another lucide icon. */
14
+ icon?: LucideIcon;
15
+ /** One or two words naming the topic, leading the title: "Billing", "Slack". */
16
+ label?: string;
10
17
  liveRegion: NoticeBannerLiveRegion;
11
18
  title: ReactNode;
12
19
  tone: NoticeBannerTone;
@@ -15,11 +22,11 @@ export type NoticeBannerProps = {
15
22
  * A condition of the whole page, the account or the service, with its fix.
16
23
  *
17
24
  * @family Feedback
18
- * @when A condition of the whole page, the account or the service that the page itself can resolve, with that resolving action on the banner. One at a time, above the page's content, under its title.
19
- * @instead For one section use `MessageNotice placement="section"`. For a measured level use a `KpiCard` with its tone; crossing a threshold is a notification in the inbox, not a banner.
20
- * @behaviour Tone `neutral` (the plain card fill), `info`, `warning`, `destructive`: a soft ground, deep text, the 1 px line edge, 6 px corners; neutral and info take the Info mark, warning and destructive the TriangleAlert. No close button on an unresolved condition. No action, no banner: `action` is required.
21
- * @words Title names the condition, description what it stops, the action the fix as verb and noun: "Open Slack settings", "Sign in". Sentence case, no "Please". The words come from the product's catalogue code.
22
- * @access `liveRegion="polite"` gives `role="status"`, announced once when it appears; `"off"` gives `role="note"` for one already there at load. The mark is hidden.
25
+ * @when "A prominent message that spans the full width of its container to announce important information." (https://vercel.com/geist/banner) "Used for temporary, project-wide notifications that require resolution" (https://vercel.com/geist/project-banner) "Use Project Banner for project-wide states that need resolution: overdue billing, an active rollback, attack mitigation, an expiring trial blocking deploys." (https://vercel.com/geist/project-banner) "Match `variant` to severity: `error` for critical downtime or payment-blocking states, `warning` for an exceptional state with non-immediate action, `success` for a positive temporary mitigation, `gray` for routine project-wide notices." (https://vercel.com/geist/project-banner) Ours: a condition of the whole page, the account or the service that the page itself can resolve, with that resolving action on the banner. The `tone` is the `variant`: `destructive` is `error`, `warning` is `warning`, `info` is `success` and `neutral` is `gray`. One sits above the page's content, under its title.
26
+ * @instead "Pick `Note` for inline contextual messages tied to a single field or card, `Toast` for transient acknowledgments, `Modal` for confirmations." (https://vercel.com/geist/project-banner) Ours: `Note` is `MessageNotice` (`placement="section"`), `Toast` is `showMessageToast` and `Modal` is `ConfirmDialog`. For a measured level use a `KpiCard` with its tone; crossing a threshold is a notification in the inbox, not a banner.
27
+ * @behaviour "Project Banner is non-dismissible by design. If the message can be dismissed without resolving the underlying state, it isn’t banner-worthy; move it to a `Note`." (https://vercel.com/geist/project-banner) "Show one Project Banner at a time. Stacking competing banners drowns the most urgent state." (https://vercel.com/geist/project-banner) "Always pass a `callToAction` that resolves the state. A banner with no route is a dead end." (https://vercel.com/geist/project-banner) Ours: a strip as wide as its container: a filled ground with a line on its top and bottom edge only, no corners, 40 px high and centred, with the mark, the sentence and the fix on one row; under 768 px the fix drops under the sentence, aligned with its text. Colour sits on the whole strip (ground, both lines, mark and text); the fix is an underlined link in the darkest step of the same hue (neutral: `text-foreground`) and returns to the strip's text on hover. Neutral and info take the Info mark, warning and destructive the TriangleAlert. `action` is the `callToAction`: one command, never two, never a ready-made button, and there is no close button. Required: `action`, `title`, `tone` and `liveRegion`; the mark is always drawn.
28
+ * @words "`label` is one sentence in sentence case that names the impact: `Your Pro trial expires in 3 days.` Don’t open with `Heads up` or apologetic preambles." (https://vercel.com/geist/project-banner) "`callToAction.label` is Title Case `Verb + Noun` and points at the resolver: `Update Payment Method`, `Reactivate Project`, `Review Tokens`." (https://vercel.com/geist/project-banner) "Name the affected entity when the project context isn’t obvious from the surrounding chrome (`Production deployments are paused on my-project`)." (https://vercel.com/geist/project-banner) "Don’t encode severity in the copy with emoji or interjections; the variant carries that signal." (https://vercel.com/geist/project-banner) "`NoteLabel` is a 1–2 word Title Case prefix that names the topic: `Region Change`, `Rate Limit`, `Plan Limit`. Cut hedges like `Heads Up`, `FYI`, and `Note`." (https://vercel.com/geist/note) Ours: the `title` is the `label`: the one sentence, naming the condition, its impact and the object. A `description` only adds what the title leaves out, in one more sentence. Our `label` is the `NoteLabel` topic prefix. The action is sentence case, verb and noun, pointing at the resolver: "Open Slack settings", "Update card". No "Please". The words come from the product's catalogue code.
29
+ * @access `liveRegion="polite"` gives `role="status"`, announced once when it appears; `"off"` gives `role="note"` for one already there at load. The mark, given or not, is hidden.
23
30
  */
24
- export declare function NoticeBanner({ action, className, description, detail, liveRegion, title, tone, ...props }: NoticeBannerProps): import("react").JSX.Element;
31
+ export declare function NoticeBanner({ action, className, description, detail, icon, label, liveRegion, title, tone, ...props }: NoticeBannerProps): import("react").JSX.Element;
25
32
  //# sourceMappingURL=notice-banner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notice-banner.d.ts","sourceRoot":"","sources":["../../src/components/notice-banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKrE,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAC9E,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,mGAAmG;IACnG,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,UAAU,EAAE,sBAAsB,CAAC;IACnC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;AAEtD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,SAAS,EACT,WAAW,EACX,MAAM,EACN,UAAU,EACV,KAAK,EACL,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,iBAAiB,+BAyBnB"}
1
+ {"version":3,"file":"notice-banner.d.ts","sourceRoot":"","sources":["../../src/components/notice-banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAC1C,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,6GAA6G;IAC7G,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,yDAAyD;IACzD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,sBAAsB,CAAC;IACnC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;AAGtD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,SAAS,EACT,WAAW,EACX,MAAM,EACN,IAAI,EACJ,KAAK,EACL,UAAU,EACV,KAAK,EACL,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,iBAAiB,+BA4CnB"}