@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
@@ -0,0 +1,96 @@
1
+ import * as React from "react";
2
+ type ChoiceboxGroupBase = {
3
+ /** Names the group for assistive technology; drawn above the tiles only with `showLabel`. */
4
+ label: string;
5
+ showLabel?: boolean;
6
+ /** Makes every tile unavailable and writes why under the legend. */
7
+ disabledReason?: string;
8
+ name?: string;
9
+ orientation?: "vertical" | "horizontal";
10
+ className?: string;
11
+ children: React.ReactNode;
12
+ };
13
+ export type ChoiceboxGroupProps = ChoiceboxGroupBase & ({
14
+ type: "radio";
15
+ required?: boolean;
16
+ value?: string | null;
17
+ defaultValue?: string;
18
+ onValueChange?: (value: string) => void;
19
+ } | {
20
+ type: "checkbox";
21
+ required?: undefined;
22
+ value?: string[];
23
+ defaultValue?: string[];
24
+ onValueChange?: (value: string[]) => void;
25
+ });
26
+ /**
27
+ * A group of larger tiles, each a radio or a checkbox with a title and a description.
28
+ *
29
+ * @family Choices
30
+ * @when "A choice that benefits from a larger tap target plus a description or icon, like a
31
+ * framework picker, plan comparison, or deployment region with latency."
32
+ * (https://vercel.com/geist/choicebox) "Single-select for mutually exclusive choices, multi-select
33
+ * for additive ones." (https://vercel.com/geist/choicebox) "Don’t mix the two within one group."
34
+ * (https://vercel.com/geist/choicebox) "Cap at 4–6 tiles." (https://vercel.com/geist/choicebox)
35
+ * Ours: where a Library entry applies, an API key's access level.
36
+ * @instead "Past that, switch to `Select` or `Combobox` so the page doesn’t scroll for a single
37
+ * field." (https://vercel.com/geist/choicebox) "For plain text labels with no description, use
38
+ * `Radio`." (https://vercel.com/geist/choicebox) Ours: Geist's `Radio` is our `RadioGroup`, or a
39
+ * `Checkbox` for several. Two or three views of one surface are a `SegmentedControl`.
40
+ * @behaviour "The whole tile is the click and focus target; tapping anywhere inside selects it."
41
+ * (https://vercel.com/geist/choicebox) "Don’t place nested buttons or links inside a tile that
42
+ * would steal the click." (https://vercel.com/geist/choicebox) "Selected state shows a check or
43
+ * filled dot in the corner." (https://vercel.com/geist/choicebox) "The border highlight alone isn’t
44
+ * enough on low-contrast screens." (https://vercel.com/geist/choicebox) "Disabled tiles need a
45
+ * Tooltip naming why (`Available on Pro`)." (https://vercel.com/geist/choicebox) "A faded tile with
46
+ * no reason reads as broken." (https://vercel.com/geist/choicebox) Ours: the group has a `label`
47
+ * and a `type`, and every tile a `title` and a `description`; a group or a tile without them does
48
+ * not compile. Tiles share one row and wrap to a column on a narrow screen;
49
+ * `orientation="vertical"` stacks them. They are 12 px apart, each with 12 px inside and 24 px
50
+ * between its words and its corner mark, the mark centred against the words. Colour: a selected,
51
+ * available tile is the one place blue sits on a choice, as a blue border, a blue tint behind the
52
+ * title and description, blue words, and a blue corner mark; a selected tile that is unavailable
53
+ * stays grey, never a faded blue. An unselected tile stays neutral and takes a grey fill on hover.
54
+ * `children` of a tile appear below its tinted row while it is selected. A tile, or the whole
55
+ * group, is unavailable only with a `disabledReason`, written under the tile's description or the
56
+ * legend, and only its title greys. A tile may carry `specs`, grey chips under its title, and one
57
+ * `badge` beside it for the option to prefer (*Recommended*); both are grey `secondary` badges,
58
+ * because blue marks only the selected tile.
59
+ * @words "Titles are parallel: one Title Case title plus one sentence-case description per tile,
60
+ * ending in a period." (https://vercel.com/geist/choicebox) "Don’t restate the title in the
61
+ * description." (https://vercel.com/geist/choicebox) "The description adds the differentiator
62
+ * (`$20/mo · 100 GB bandwidth`), not a synonym." (https://vercel.com/geist/choicebox) "Icons are
63
+ * decorative when paired with a title; if the icon is the only label, give the tile an `aria-label`
64
+ * naming the choice." (https://vercel.com/geist/choicebox) Ours: the title is a short noun phrase
65
+ * in sentence case: *Pro trial*; the description is *Free for two weeks.* The label names the
66
+ * choice: *Plan*.
67
+ * @access "Tiles render as radios or checkboxes under the hood, so keep them inside a `<fieldset>`
68
+ * with a `<legend>` so screen readers announce the group." (https://vercel.com/geist/choicebox)
69
+ * "Arrow keys move within a single-select group, Space toggles in multi-select."
70
+ * (https://vercel.com/geist/choicebox) "Don’t override those keys with custom handlers."
71
+ * (https://vercel.com/geist/choicebox) "Color is not the selection signal."
72
+ * (https://vercel.com/geist/choicebox) "Pair the highlight border with the corner check so
73
+ * colorblind users still see what’s active." (https://vercel.com/geist/choicebox) Ours: a
74
+ * `FieldSet` with the label as its legend, which names a group of checkboxes; a `role="radiogroup"`
75
+ * is labelled by the same legend. Each tile is named by its title and described by its description
76
+ * and reason. Keyboard focus outlines the whole tile, and the box in its corner draws no outline of
77
+ * its own.
78
+ */
79
+ declare function ChoiceboxGroup(props: ChoiceboxGroupProps): React.JSX.Element;
80
+ export type ChoiceboxGroupItemProps = {
81
+ value: string;
82
+ title: string;
83
+ description: string;
84
+ /** Grey facts under the title that set the options apart: *4 vCPU*, *8 GB*. */
85
+ specs?: readonly string[];
86
+ /** One chip beside the title that singles the tile out: *Recommended*. */
87
+ badge?: string;
88
+ /** Makes the tile unavailable and writes why under its description. */
89
+ disabledReason?: string;
90
+ className?: string;
91
+ /** Read-only content shown while the tile is selected. */
92
+ children?: React.ReactNode;
93
+ };
94
+ declare function ChoiceboxGroupItem({ value, title, description, specs, badge, disabledReason, className, children, }: ChoiceboxGroupItemProps): React.JSX.Element;
95
+ export { ChoiceboxGroup, ChoiceboxGroupItem };
96
+ //# sourceMappingURL=choicebox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choicebox.d.ts","sourceRoot":"","sources":["../../src/components/choicebox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkB/B,KAAK,kBAAkB,GAAG;IACxB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAClD,CACI;IACE,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC3C,CACJ,CAAC;AAQJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,iBAAS,cAAc,CAAC,KAAK,EAAE,mBAAmB,qBAwDjD;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,iBAAS,kBAAkB,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,WAAW,EACX,KAAK,EACL,KAAK,EACL,cAAc,EACd,SAAS,EACT,QAAQ,GACT,EAAE,uBAAuB,qBA0FzB;AAED,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,113 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { CheckboxGroup as CheckboxGroupPrimitive } from "@base-ui/react/checkbox-group";
5
+ import { Badge } from "./badge.js";
6
+ import { Checkbox } from "./checkbox.js";
7
+ import { FieldDescription, FieldLegend, FieldSet } from "./field.js";
8
+ import { RadioGroup, RadioGroupItem } from "./radio-group.js";
9
+ import { cn } from "../lib/utils.js";
10
+ const ChoiceboxSelectionContext = React.createContext(null);
11
+ function asList(value) {
12
+ if (value === undefined)
13
+ return undefined;
14
+ if (value === null)
15
+ return [];
16
+ return Array.isArray(value) ? value : [value];
17
+ }
18
+ /**
19
+ * A group of larger tiles, each a radio or a checkbox with a title and a description.
20
+ *
21
+ * @family Choices
22
+ * @when "A choice that benefits from a larger tap target plus a description or icon, like a
23
+ * framework picker, plan comparison, or deployment region with latency."
24
+ * (https://vercel.com/geist/choicebox) "Single-select for mutually exclusive choices, multi-select
25
+ * for additive ones." (https://vercel.com/geist/choicebox) "Don’t mix the two within one group."
26
+ * (https://vercel.com/geist/choicebox) "Cap at 4–6 tiles." (https://vercel.com/geist/choicebox)
27
+ * Ours: where a Library entry applies, an API key's access level.
28
+ * @instead "Past that, switch to `Select` or `Combobox` so the page doesn’t scroll for a single
29
+ * field." (https://vercel.com/geist/choicebox) "For plain text labels with no description, use
30
+ * `Radio`." (https://vercel.com/geist/choicebox) Ours: Geist's `Radio` is our `RadioGroup`, or a
31
+ * `Checkbox` for several. Two or three views of one surface are a `SegmentedControl`.
32
+ * @behaviour "The whole tile is the click and focus target; tapping anywhere inside selects it."
33
+ * (https://vercel.com/geist/choicebox) "Don’t place nested buttons or links inside a tile that
34
+ * would steal the click." (https://vercel.com/geist/choicebox) "Selected state shows a check or
35
+ * filled dot in the corner." (https://vercel.com/geist/choicebox) "The border highlight alone isn’t
36
+ * enough on low-contrast screens." (https://vercel.com/geist/choicebox) "Disabled tiles need a
37
+ * Tooltip naming why (`Available on Pro`)." (https://vercel.com/geist/choicebox) "A faded tile with
38
+ * no reason reads as broken." (https://vercel.com/geist/choicebox) Ours: the group has a `label`
39
+ * and a `type`, and every tile a `title` and a `description`; a group or a tile without them does
40
+ * not compile. Tiles share one row and wrap to a column on a narrow screen;
41
+ * `orientation="vertical"` stacks them. They are 12 px apart, each with 12 px inside and 24 px
42
+ * between its words and its corner mark, the mark centred against the words. Colour: a selected,
43
+ * available tile is the one place blue sits on a choice, as a blue border, a blue tint behind the
44
+ * title and description, blue words, and a blue corner mark; a selected tile that is unavailable
45
+ * stays grey, never a faded blue. An unselected tile stays neutral and takes a grey fill on hover.
46
+ * `children` of a tile appear below its tinted row while it is selected. A tile, or the whole
47
+ * group, is unavailable only with a `disabledReason`, written under the tile's description or the
48
+ * legend, and only its title greys. A tile may carry `specs`, grey chips under its title, and one
49
+ * `badge` beside it for the option to prefer (*Recommended*); both are grey `secondary` badges,
50
+ * because blue marks only the selected tile.
51
+ * @words "Titles are parallel: one Title Case title plus one sentence-case description per tile,
52
+ * ending in a period." (https://vercel.com/geist/choicebox) "Don’t restate the title in the
53
+ * description." (https://vercel.com/geist/choicebox) "The description adds the differentiator
54
+ * (`$20/mo · 100 GB bandwidth`), not a synonym." (https://vercel.com/geist/choicebox) "Icons are
55
+ * decorative when paired with a title; if the icon is the only label, give the tile an `aria-label`
56
+ * naming the choice." (https://vercel.com/geist/choicebox) Ours: the title is a short noun phrase
57
+ * in sentence case: *Pro trial*; the description is *Free for two weeks.* The label names the
58
+ * choice: *Plan*.
59
+ * @access "Tiles render as radios or checkboxes under the hood, so keep them inside a `<fieldset>`
60
+ * with a `<legend>` so screen readers announce the group." (https://vercel.com/geist/choicebox)
61
+ * "Arrow keys move within a single-select group, Space toggles in multi-select."
62
+ * (https://vercel.com/geist/choicebox) "Don’t override those keys with custom handlers."
63
+ * (https://vercel.com/geist/choicebox) "Color is not the selection signal."
64
+ * (https://vercel.com/geist/choicebox) "Pair the highlight border with the corner check so
65
+ * colorblind users still see what’s active." (https://vercel.com/geist/choicebox) Ours: a
66
+ * `FieldSet` with the label as its legend, which names a group of checkboxes; a `role="radiogroup"`
67
+ * is labelled by the same legend. Each tile is named by its title and described by its description
68
+ * and reason. Keyboard focus outlines the whole tile, and the box in its corner draws no outline of
69
+ * its own.
70
+ */
71
+ function ChoiceboxGroup(props) {
72
+ const legendId = React.useId();
73
+ const reasonId = React.useId();
74
+ const { label, showLabel = false, disabledReason, name, orientation = "horizontal", className, } = props;
75
+ const groupReasonId = disabledReason ? reasonId : undefined;
76
+ const [internal, setInternal] = React.useState(asList(props.defaultValue) ?? []);
77
+ const selected = asList(props.value) ?? internal;
78
+ const list = cn("grid gap-3", orientation === "horizontal" && "sm:auto-cols-fr sm:grid-flow-col");
79
+ return (_jsx(ChoiceboxSelectionContext.Provider, { value: { type: props.type, name, selected, groupReasonId }, children: _jsxs(FieldSet, { className: className, "data-slot": "choicebox-group", children: [_jsx(FieldLegend, { className: showLabel ? "mb-2" : "sr-only", id: legendId, variant: "label", children: label }), disabledReason ? (_jsx(FieldDescription, { id: reasonId, children: disabledReason })) : null, props.type === "radio" ? (_jsx(RadioGroup, { "aria-labelledby": legendId, className: list, disabled: groupReasonId !== undefined, name: name, onValueChange: (next) => {
80
+ setInternal([next]);
81
+ props.onValueChange?.(next);
82
+ }, required: props.required, value: selected[0] ?? null, children: props.children })) : (_jsx(CheckboxGroupPrimitive, { className: list, disabled: groupReasonId !== undefined, onValueChange: (next) => {
83
+ setInternal(next);
84
+ props.onValueChange?.(next);
85
+ }, value: selected, children: props.children }))] }) }));
86
+ }
87
+ function ChoiceboxGroupItem({ value, title, description, specs, badge, disabledReason, className, children, }) {
88
+ const group = React.useContext(ChoiceboxSelectionContext);
89
+ const titleId = React.useId();
90
+ const descriptionId = React.useId();
91
+ const specsId = React.useId();
92
+ const badgeId = React.useId();
93
+ const reasonId = React.useId();
94
+ if (group === null) {
95
+ throw new Error("ChoiceboxGroupItem belongs inside a ChoiceboxGroup");
96
+ }
97
+ const control = {
98
+ "aria-describedby": [
99
+ descriptionId,
100
+ specs?.length ? specsId : undefined,
101
+ badge ? badgeId : undefined,
102
+ disabledReason ? reasonId : undefined,
103
+ group.groupReasonId,
104
+ ]
105
+ .filter((id) => id !== undefined)
106
+ .join(" "),
107
+ "aria-labelledby": titleId,
108
+ disabled: Boolean(disabledReason) || group.groupReasonId !== undefined,
109
+ value,
110
+ };
111
+ return (_jsxs("div", { className: cn("group/choicebox flex flex-col overflow-hidden rounded-sm border bg-background nc-transition-paint not-has-data-disabled:hover:bg-accent has-focus-visible:nc-focus-outline has-focus-visible:outline-ring has-data-checked:not-has-data-disabled:border-info", className), "data-slot": "choicebox-item", children: [_jsxs("label", { className: "flex cursor-pointer items-center justify-between gap-6 p-3 nc-transition-paint has-data-checked:not-has-data-disabled:bg-info-soft has-data-disabled:cursor-not-allowed", children: [_jsxs("span", { className: "flex min-w-0 flex-col gap-1", children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-medium group-has-data-checked/choicebox:not-group-has-data-disabled/choicebox:text-info-soft-foreground group-has-data-disabled/choicebox:text-muted-foreground", id: titleId, children: title }), badge ? (_jsx(Badge, { id: badgeId, size: "sm", variant: "secondary", children: badge })) : null] }), specs?.length ? (_jsx("span", { className: "flex flex-wrap gap-1", id: specsId, children: specs.map((spec) => (_jsx(Badge, { size: "sm", variant: "secondary", children: spec }, spec))) })) : null, _jsx("span", { className: "text-sm text-muted-foreground group-has-data-checked/choicebox:not-group-has-data-disabled/choicebox:text-info-soft-foreground", id: descriptionId, children: description }), disabledReason ? (_jsx("span", { className: "text-sm text-muted-foreground", id: reasonId, children: disabledReason })) : null] }), group.type === "radio" ? (_jsx(RadioGroupItem, { ...control, className: "outline-none data-checked:not-data-disabled:border-info-soft-foreground data-checked:not-data-disabled:text-info-soft-foreground" })) : (_jsx(Checkbox, { ...control, className: "outline-none data-checked:not-data-disabled:border-info-soft-foreground data-checked:not-data-disabled:bg-info-soft-foreground data-checked:not-data-disabled:text-info-soft", name: group.name }))] }), children && group.selected.includes(value) ? (_jsx("div", { className: "p-2", "data-slot": "choicebox-content", children: children })) : null] }));
112
+ }
113
+ export { ChoiceboxGroup, ChoiceboxGroupItem };
@@ -0,0 +1,57 @@
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 { type KbdProps } from "./kbd.js";
5
+ /** The keys of a shortcut as `Kbd` takes them; `ClearableInput` draws them at the size of a field. */
6
+ export type ClearableInputShortcut = KbdProps extends infer Keys ? Keys extends unknown ? Omit<Keys, "size"> : never : never;
7
+ export type ClearableInputProps = Omit<React.ComponentProps<"input">, "defaultValue" | "onChange" | "prefix" | "ref" | "size" | "value"> & {
8
+ value: string;
9
+ onValueChange: (value: string) => void;
10
+ /** Runs after the value is emptied, so the caller can reset what depends on it. */
11
+ onClear?: () => void;
12
+ /** The clear button's name, in the product's words: "Clear search". */
13
+ clearLabel: string;
14
+ size?: FieldSize;
15
+ /** A mark before the text. Decorative; the input keeps its own name. */
16
+ prefix?: React.ReactNode;
17
+ /** The keys that open the command palette, shown while the box is empty. Esc replaces them once it has text. */
18
+ shortcut?: ClearableInputShortcut;
19
+ /** A query is running; the results stay on screen. */
20
+ loading?: boolean;
21
+ /** The message under the box, in the product's words; it also marks the box invalid. */
22
+ error?: string;
23
+ } & FieldName;
24
+ /**
25
+ * A text box that empties itself: a clear button once it has text, and Escape.
26
+ *
27
+ * @family Inputs
28
+ * @when "Text input with a clear button that resets the value on Escape."
29
+ * (https://vercel.com/geist/clearable-input) Ours: a single-line value a person may want to empty
30
+ * in one move: a filter, a search, a reference they paste and replace.
31
+ * @instead A collection's search is `CollectionSearch`. A value that is never emptied is `Input`. A
32
+ * box with a fixed prefix or suffix is `Input`; one with a copy button is `InputGroup`.
33
+ * @behaviour Same ring, halo, hover, disabled and error as `Input`; colour sits where it does there
34
+ * and nowhere else. The clear button shows only while the box has text and is enabled, as an Esc
35
+ * key cap flush against the end of the box that darkens on hover and keeps a transparent fill (a
36
+ * close mark on a touch screen, which has no Escape). Pressing it, or Escape inside the box,
37
+ * empties the value, calls `onClear` and puts focus back in the box. Escape on an empty box does
38
+ * nothing here, so it closes the dialog or drawer around it. "Automatically clears the input if
39
+ * escape is pressed." (https://vercel.com/geist/input) "Displays the <kbd>⌘</kbd> <kbd>K</kbd>
40
+ * shortcut to indicate that the input supports a command palette." (https://vercel.com/geist/input)
41
+ * "Transitions to showing <kbd>Esc</kbd> when the field is dirty." (https://vercel.com/geist/input)
42
+ * Ours: the `shortcut` keys are one cap per key (*⌘* then *K*, 4 px apart, 10 px from the edge),
43
+ * hidden on a touch screen. `loading` marks the box busy and, after a second, draws the waiting
44
+ * line along its bottom edge; nothing spins and the results stay. `label` and `error` draw the
45
+ * `Field` parts around the box as on `Input`, and a string `label` requires `id`; a box with no
46
+ * name does not compile. `className` lands on the box.
47
+ * @words The clear button is named for what it empties (*Clear search*, *Clear filter*).
48
+ * "Placeholders show an example value (`my-awesome-project`, `example.com`), never instructions
49
+ * like `Enter your project name`." (https://vercel.com/geist/input) Ours: the placeholder may also
50
+ * be the scope.
51
+ * @access A visible `label` or `aria-label` names the box. The clear button is a named button,
52
+ * `aria-keyshortcuts` Escape; the prefix and the keys are hidden from assistive technology.
53
+ * `aria-busy` while `loading`.
54
+ */
55
+ declare function ClearableInput({ className, value, onValueChange, onClear, clearLabel, size, prefix, shortcut, loading, label, error, disabled, onKeyDown, ...props }: ClearableInputProps): React.JSX.Element;
56
+ export { ClearableInput };
57
+ //# sourceMappingURL=clearable-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearable-input.d.ts","sourceRoot":"","sources":["../../src/components/clearable-input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGtD,sGAAsG;AACtG,MAAM,MAAM,sBAAsB,GAAG,QAAQ,SAAS,MAAM,IAAI,GAC5D,IAAI,SAAS,OAAO,GAClB,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,GAClB,KAAK,GACP,KAAK,CAAC;AAEV,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAC7B,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAClE,GAAG;IACF,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,gHAAgH;IAChH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,KAAK,EACL,aAAa,EACb,OAAO,EACP,UAAU,EACV,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,OAAe,EACf,KAAK,EACL,KAAK,EACL,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,mBAAmB,qBAyErB;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { XIcon } from "lucide-react";
5
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupControl, } from "./input-group.js";
6
+ import { FieldFrame } from "../internal/field-frame.js";
7
+ import { Kbd } from "./kbd.js";
8
+ import { WaitingLine } from "./waiting-line.js";
9
+ /**
10
+ * A text box that empties itself: a clear button once it has text, and Escape.
11
+ *
12
+ * @family Inputs
13
+ * @when "Text input with a clear button that resets the value on Escape."
14
+ * (https://vercel.com/geist/clearable-input) Ours: a single-line value a person may want to empty
15
+ * in one move: a filter, a search, a reference they paste and replace.
16
+ * @instead A collection's search is `CollectionSearch`. A value that is never emptied is `Input`. A
17
+ * box with a fixed prefix or suffix is `Input`; one with a copy button is `InputGroup`.
18
+ * @behaviour Same ring, halo, hover, disabled and error as `Input`; colour sits where it does there
19
+ * and nowhere else. The clear button shows only while the box has text and is enabled, as an Esc
20
+ * key cap flush against the end of the box that darkens on hover and keeps a transparent fill (a
21
+ * close mark on a touch screen, which has no Escape). Pressing it, or Escape inside the box,
22
+ * empties the value, calls `onClear` and puts focus back in the box. Escape on an empty box does
23
+ * nothing here, so it closes the dialog or drawer around it. "Automatically clears the input if
24
+ * escape is pressed." (https://vercel.com/geist/input) "Displays the <kbd>⌘</kbd> <kbd>K</kbd>
25
+ * shortcut to indicate that the input supports a command palette." (https://vercel.com/geist/input)
26
+ * "Transitions to showing <kbd>Esc</kbd> when the field is dirty." (https://vercel.com/geist/input)
27
+ * Ours: the `shortcut` keys are one cap per key (*⌘* then *K*, 4 px apart, 10 px from the edge),
28
+ * hidden on a touch screen. `loading` marks the box busy and, after a second, draws the waiting
29
+ * line along its bottom edge; nothing spins and the results stay. `label` and `error` draw the
30
+ * `Field` parts around the box as on `Input`, and a string `label` requires `id`; a box with no
31
+ * name does not compile. `className` lands on the box.
32
+ * @words The clear button is named for what it empties (*Clear search*, *Clear filter*).
33
+ * "Placeholders show an example value (`my-awesome-project`, `example.com`), never instructions
34
+ * like `Enter your project name`." (https://vercel.com/geist/input) Ours: the placeholder may also
35
+ * be the scope.
36
+ * @access A visible `label` or `aria-label` names the box. The clear button is a named button,
37
+ * `aria-keyshortcuts` Escape; the prefix and the keys are hidden from assistive technology.
38
+ * `aria-busy` while `loading`.
39
+ */
40
+ function ClearableInput({ className, value, onValueChange, onClear, clearLabel, size, prefix, shortcut, loading = false, label, error, disabled, onKeyDown, ...props }) {
41
+ const input = React.useRef(null);
42
+ const clearable = value !== "" && !disabled;
43
+ const shortcutHint = shortcut ? (_jsxs(InputGroupAddon, { align: "inline-end", "aria-hidden": "true", className: "gap-1 pr-2.5 pl-3 pointer-coarse:hidden", children: [shortcut.meta ? _jsx(Kbd, { size: "sm", meta: true }) : null, shortcut.shift ? _jsx(Kbd, { size: "sm", shift: true }) : null, shortcut.alt ? _jsx(Kbd, { size: "sm", alt: true }) : null, shortcut.ctrl ? _jsx(Kbd, { size: "sm", ctrl: true }) : null, shortcut.children ? _jsx(Kbd, { size: "sm", children: shortcut.children }) : null] })) : null;
44
+ function clear() {
45
+ input.current?.focus();
46
+ onValueChange("");
47
+ onClear?.();
48
+ }
49
+ return (_jsx(FieldFrame, { label: label, error: error, size: size, control: props, children: (aria) => (_jsxs(InputGroup, { size: size, className: className, children: [prefix ? _jsx(InputGroupAddon, { "aria-hidden": "true", children: prefix }) : null, _jsx(InputGroupControl, { ref: input, "aria-busy": loading || undefined, className: "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none", disabled: disabled, onChange: (event) => onValueChange(event.target.value), onKeyDown: (event) => {
50
+ onKeyDown?.(event);
51
+ if (event.key !== "Escape" || event.defaultPrevented || !clearable)
52
+ return;
53
+ event.preventDefault();
54
+ event.stopPropagation();
55
+ clear();
56
+ }, value: value, ...props, ...aria }), clearable ? (_jsx(InputGroupAddon, { align: "inline-end", className: "has-[>button]:pl-3", children: _jsxs(InputGroupButton, { "aria-keyshortcuts": "Escape", "aria-label": clearLabel, onClick: clear, size: "icon", children: [_jsx(Kbd, { "aria-hidden": "true", className: "pointer-coarse:hidden group-hover/button:text-foreground", size: "sm", children: "Esc" }), _jsx(XIcon, { "aria-hidden": "true", className: "hidden pointer-coarse:block" })] }) })) : (shortcutHint), loading ? (_jsx(WaitingLine, { className: "absolute inset-x-1.5 bottom-px w-auto", decorative: true })) : null] })) }));
57
+ }
58
+ export { ClearableInput };
@@ -1,23 +1,83 @@
1
1
  import { type CopyButtonProps } from "./copy-button.js";
2
+ type MarkedState = "highlighted" | "added" | "removed";
3
+ type LanguageSwitch = {
4
+ label: string;
5
+ options: readonly {
6
+ label: string;
7
+ value: string;
8
+ }[];
9
+ value: string;
10
+ onChange: (value: string) => void;
11
+ };
12
+ type LanguageControl = {
13
+ switcher?: LanguageSwitch | undefined;
14
+ tabs?: undefined;
15
+ } | {
16
+ tabs?: LanguageSwitch | undefined;
17
+ switcher?: undefined;
18
+ };
19
+ /** A block that marks lines says each mark in words; a block that marks none has nothing to say. */
20
+ type MarkedLines = {
21
+ highlightedLinesNumbers?: readonly number[] | undefined;
22
+ addedLinesNumbers?: readonly number[] | undefined;
23
+ removedLinesNumbers?: readonly number[] | undefined;
24
+ lineLabel: (line: number, state: MarkedState) => string;
25
+ } | {
26
+ highlightedLinesNumbers?: undefined;
27
+ addedLinesNumbers?: undefined;
28
+ removedLinesNumbers?: undefined;
29
+ lineLabel?: undefined;
30
+ };
31
+ type CodeBlockProps = {
32
+ code: string;
33
+ label: string;
34
+ filename?: string | undefined;
35
+ className?: string | undefined;
36
+ hideLineNumbers?: boolean | undefined;
37
+ } & MarkedLines & LanguageControl & Pick<CopyButtonProps, "copyLabel" | "copiedLabel" | "copyFailedLabel">;
2
38
  /**
3
- * Several lines of exact text to read or copy.
39
+ * Several lines of exact text to read, copy or point at line by line.
4
40
  *
5
41
  * @family Data
6
- * @when Several lines a person reads or copies exactly: a configuration, static JSON, a command
7
- * sequence.
8
- * @instead One short value to copy is a read-only input with a `CopyButton`. A before and after is
9
- * `FileDiff`. Code in a conversation is her `MarkdownText`.
10
- * @behaviour Read-only, no wrapping, scrolls in both directions up to 384 px. Copy takes the exact
11
- * text, says Copied only on success and says when it failed. No syntax colour, no line numbers.
12
- * @words The real filename, or an honest label. The language as its common name: *JSON*. Copy,
13
- * Copied, Couldn't copy.
14
- * @access The text area is named by its `label`; the copy button names its target (*Copy mcp.json*)
15
- * and announces the result.
42
+ * @when “Use `<CodeBlock>` for multi-line, syntax-highlighted source the reader will scan or paste.” (https://vercel.com/geist/code-block)
43
+ * Ours: several lines a person reads or copies exactly: a configuration, static JSON, a command
44
+ * sequence, a file with the lines under discussion marked. There is no syntax colour yet.
45
+ * @instead “For a single inline token (env var, function name, file path), use `Inline Code`.” (https://vercel.com/geist/code-block)
46
+ * “Pick `Snippet` for a copy-to-clipboard shell command or one-line key reveal; it ships with the prompt glyph and copy affordance built in.” (https://vercel.com/geist/code-block)
47
+ * Ours: a token inside a sentence is inline code. One short value to copy is `TextWithCopyButton`. A
48
+ * before and after to compute is `FileDiff`. Code in a conversation is Nadia's `MarkdownText`.
49
+ * @behaviour “Highlight only the lines under discussion. A block where every line is highlighted reads the same as no highlight at all.” (https://vercel.com/geist/code-block)
50
+ * “Mark added or removed lines with the `diff` syntax or the dedicated added/removed props. Faking them with `// added` comments breaks copy-paste.” (https://vercel.com/geist/code-block)
51
+ * “Show the filename header when the snippet has a paste destination (`app/page.tsx`, `vercel.json`). Omit it for ephemeral examples.” (https://vercel.com/geist/code-block)
52
+ * “You can link to lines. Just press on any line number.” (https://vercel.com/geist/code-block)
53
+ * “Use the `tabs` prop for a tabbed language switcher instead of the default select.” (https://vercel.com/geist/code-block)
54
+ * “Always pass a `language`/`syntax` (`tsx`, `bash`, `json`, `diff`). Highlighting is the primary reason to choose `<CodeBlock>` over a plain `<pre>`.” (https://vercel.com/geist/code-block)
55
+ * Ours: read-only, no wrapping, 20 px rows, each line numbered with a number that links to it. Colour
56
+ * sits on the row and its 2 px bar at the start, never on the text or the numbers:
57
+ * `highlightedLinesNumbers` (info), `addedLinesNumbers` (success) and `removedLinesNumbers`
58
+ * (destructive); a line carries one mark, and the line a link points at takes the warning fill. A
59
+ * mark is fill and bar with no glyph, announced by the line's name. `hideLineNumbers` is for a few
60
+ * lines where numbers add nothing. The header (40 px, muted fill, the file's icon and name) exists
61
+ * only with a `filename`, a `switcher` or `tabs`. `tabs` draw as a row above the header, a
62
+ * `switcher` (a select) sits in the header before the copy button; never both. In the header the
63
+ * filename and the copy mark are muted; without a header the copy button floats 15 px from the top
64
+ * right corner in the full text colour and shows while the block is hovered or something in it has
65
+ * focus (always on a touch screen). A line number links to its line for a pointer and is out of the
66
+ * tab order. The file icon follows the filename's extension. There is no syntax colour and no
67
+ * `language` until a highlighter is adopted, and no Open in v0 action.
68
+ * @words “Snippets stay runnable. Don’t paraphrase real code into pseudo-syntax, and don’t prepend `$` to shell commands. `<Snippet>` already renders the prompt, so `text="$ vercel deploy"` doubles to `$ $ vercel deploy`.” (https://vercel.com/geist/code-block)
69
+ * “Keep prose around the block in sentence case and put backticks around CLI flags inline (`` `--prebuilt` ``).” (https://vercel.com/geist/code-block)
70
+ * Ours: the real filename, or none. A switcher's `label` names what it switches (*Language*), and
71
+ * its options are the languages by their common names (*JSON*). `label` names the code (*MCP
72
+ * configuration*). `lineLabel` says a marked line and its mark in the catalogue's words (*Line 3,
73
+ * added*, *Riga 3, aggiunta*); it is only called for a highlighted, added or removed line.
74
+ * `copyLabel` names what is copied (*Copy mcp.json*); `copiedLabel` (*Copied*); `copyFailedLabel`
75
+ * (*Couldn't copy*). `label` and the three copy words are required, and `lineLabel` with any marked line.
76
+ * @access Ours: the code is a focusable, scrollable region named by `label`. Line numbers are hidden from
77
+ * assistive technology and are not tab stops; a highlighted, added or removed line carries
78
+ * `lineLabel`'s words as hidden text, with the numbers shown or not. The copy button names its
79
+ * target and announces the result.
16
80
  */
17
- export declare function CodeBlock({ code, label, filename, language, copyLabel, copiedLabel, copyFailedLabel, }: {
18
- code: string;
19
- label: string;
20
- filename?: string;
21
- language?: string;
22
- } & Pick<CopyButtonProps, "copyLabel" | "copiedLabel" | "copyFailedLabel">): import("react").JSX.Element;
81
+ declare function CodeBlock({ addedLinesNumbers, className, code, copiedLabel, copyFailedLabel, copyLabel, filename, hideLineNumbers, highlightedLinesNumbers, label, lineLabel, removedLinesNumbers, switcher, tabs, }: CodeBlockProps): import("react").JSX.Element;
82
+ export { CodeBlock, type CodeBlockProps };
23
83
  //# sourceMappingURL=code-block.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../../src/components/code-block.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAQ5E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAW,EACX,eAAe,GAChB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,aAAa,GAAG,iBAAiB,CAAC,+BAiCzE"}
1
+ {"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../../src/components/code-block.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAc5E,KAAK,WAAW,GAAG,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;AAGvD,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,KAAK,eAAe,GAChB;IAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,GAC3D;IAAE,IAAI,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAEhE,oGAAoG;AACpG,KAAK,WAAW,GACZ;IACE,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACxD,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAClD,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACpD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC;CACzD,GACD;IACE,uBAAuB,CAAC,EAAE,SAAS,CAAC;IACpC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC9B,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEN,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvC,GAAG,WAAW,GACb,eAAe,GACf,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,aAAa,GAAG,iBAAiB,CAAC,CAAC;AAyDzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,iBAAS,SAAS,CAAC,EACjB,iBAAiB,EACjB,SAAS,EACT,IAAI,EACJ,WAAW,EACX,eAAe,EACf,SAAS,EACT,QAAQ,EACR,eAAuB,EACvB,uBAAuB,EACvB,KAAK,EACL,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,IAAI,GACL,EAAE,cAAc,+BA4FhB;AAED,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,CAAC"}
@@ -1,22 +1,92 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useId } from "react";
3
4
  import { CopyButton } from "./copy-button.js";
4
- import { InputGroup, InputGroupAddon, InputGroupText, InputGroupTextarea, } from "./input-group.js";
5
+ import { FileTypeIcon } from "./file-type-icon.js";
6
+ import { MiddleTruncate } from "./middle-truncate.js";
7
+ import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from "./select.js";
8
+ import { Tabs, TabsList, TabsTrigger } from "./tabs.js";
9
+ import { cn } from "../lib/utils.js";
10
+ const ROW = {
11
+ plain: "",
12
+ highlighted: "bg-info-soft shadow-[inset_2px_0_0_0_var(--info)]",
13
+ added: "bg-success-soft shadow-[inset_2px_0_0_0_var(--success)]",
14
+ removed: "bg-destructive-soft shadow-[inset_2px_0_0_0_var(--destructive)]",
15
+ };
16
+ const LINKED_ROW = "target:bg-warning-soft target:shadow-[inset_2px_0_0_0_var(--warning-soft-foreground)]";
17
+ const SHOWN_ON_HOVER = "nc-transition-opacity [@media(hover:hover)_and_(pointer:fine)]:opacity-0 group-hover/code-block:opacity-100 group-focus-within/code-block:opacity-100";
18
+ function LanguageSwitcher({ label, onChange, options, value }) {
19
+ return (_jsxs(Select, { value: value, onValueChange: (next) => {
20
+ if (next !== null)
21
+ onChange(next);
22
+ }, children: [_jsx(SelectTrigger, { "aria-label": label, size: "sm", className: "w-auto bg-transparent pr-2 pl-2 text-label-sm text-muted-foreground shadow-none hover:bg-accent focus-visible:shadow-[0_0_0_2px_var(--ring)] data-popup-open:bg-accent [&_svg]:size-4", children: _jsx(SelectValue, { children: options.find((option) => option.value === value)?.label }) }), _jsx(SelectContent, { children: _jsx(SelectGroup, { children: options.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value))) }) })] }));
23
+ }
24
+ function LanguageTabs({ label, onChange, options, value }) {
25
+ return (_jsx(Tabs, { value: value, onValueChange: (next) => onChange(String(next)), className: "min-w-0", children: _jsx(TabsList, { "aria-label": label, children: options.map((option) => (_jsx(TabsTrigger, { value: option.value, children: option.label }, option.value))) }) }));
26
+ }
5
27
  /**
6
- * Several lines of exact text to read or copy.
28
+ * Several lines of exact text to read, copy or point at line by line.
7
29
  *
8
30
  * @family Data
9
- * @when Several lines a person reads or copies exactly: a configuration, static JSON, a command
10
- * sequence.
11
- * @instead One short value to copy is a read-only input with a `CopyButton`. A before and after is
12
- * `FileDiff`. Code in a conversation is her `MarkdownText`.
13
- * @behaviour Read-only, no wrapping, scrolls in both directions up to 384 px. Copy takes the exact
14
- * text, says Copied only on success and says when it failed. No syntax colour, no line numbers.
15
- * @words The real filename, or an honest label. The language as its common name: *JSON*. Copy,
16
- * Copied, Couldn't copy.
17
- * @access The text area is named by its `label`; the copy button names its target (*Copy mcp.json*)
18
- * and announces the result.
31
+ * @when “Use `<CodeBlock>` for multi-line, syntax-highlighted source the reader will scan or paste.” (https://vercel.com/geist/code-block)
32
+ * Ours: several lines a person reads or copies exactly: a configuration, static JSON, a command
33
+ * sequence, a file with the lines under discussion marked. There is no syntax colour yet.
34
+ * @instead “For a single inline token (env var, function name, file path), use `Inline Code`.” (https://vercel.com/geist/code-block)
35
+ * “Pick `Snippet` for a copy-to-clipboard shell command or one-line key reveal; it ships with the prompt glyph and copy affordance built in.” (https://vercel.com/geist/code-block)
36
+ * Ours: a token inside a sentence is inline code. One short value to copy is `TextWithCopyButton`. A
37
+ * before and after to compute is `FileDiff`. Code in a conversation is Nadia's `MarkdownText`.
38
+ * @behaviour “Highlight only the lines under discussion. A block where every line is highlighted reads the same as no highlight at all.” (https://vercel.com/geist/code-block)
39
+ * “Mark added or removed lines with the `diff` syntax or the dedicated added/removed props. Faking them with `// added` comments breaks copy-paste.” (https://vercel.com/geist/code-block)
40
+ * “Show the filename header when the snippet has a paste destination (`app/page.tsx`, `vercel.json`). Omit it for ephemeral examples.” (https://vercel.com/geist/code-block)
41
+ * “You can link to lines. Just press on any line number.” (https://vercel.com/geist/code-block)
42
+ * “Use the `tabs` prop for a tabbed language switcher instead of the default select.” (https://vercel.com/geist/code-block)
43
+ * “Always pass a `language`/`syntax` (`tsx`, `bash`, `json`, `diff`). Highlighting is the primary reason to choose `<CodeBlock>` over a plain `<pre>`.” (https://vercel.com/geist/code-block)
44
+ * Ours: read-only, no wrapping, 20 px rows, each line numbered with a number that links to it. Colour
45
+ * sits on the row and its 2 px bar at the start, never on the text or the numbers:
46
+ * `highlightedLinesNumbers` (info), `addedLinesNumbers` (success) and `removedLinesNumbers`
47
+ * (destructive); a line carries one mark, and the line a link points at takes the warning fill. A
48
+ * mark is fill and bar with no glyph, announced by the line's name. `hideLineNumbers` is for a few
49
+ * lines where numbers add nothing. The header (40 px, muted fill, the file's icon and name) exists
50
+ * only with a `filename`, a `switcher` or `tabs`. `tabs` draw as a row above the header, a
51
+ * `switcher` (a select) sits in the header before the copy button; never both. In the header the
52
+ * filename and the copy mark are muted; without a header the copy button floats 15 px from the top
53
+ * right corner in the full text colour and shows while the block is hovered or something in it has
54
+ * focus (always on a touch screen). A line number links to its line for a pointer and is out of the
55
+ * tab order. The file icon follows the filename's extension. There is no syntax colour and no
56
+ * `language` until a highlighter is adopted, and no Open in v0 action.
57
+ * @words “Snippets stay runnable. Don’t paraphrase real code into pseudo-syntax, and don’t prepend `$` to shell commands. `<Snippet>` already renders the prompt, so `text="$ vercel deploy"` doubles to `$ $ vercel deploy`.” (https://vercel.com/geist/code-block)
58
+ * “Keep prose around the block in sentence case and put backticks around CLI flags inline (`` `--prebuilt` ``).” (https://vercel.com/geist/code-block)
59
+ * Ours: the real filename, or none. A switcher's `label` names what it switches (*Language*), and
60
+ * its options are the languages by their common names (*JSON*). `label` names the code (*MCP
61
+ * configuration*). `lineLabel` says a marked line and its mark in the catalogue's words (*Line 3,
62
+ * added*, *Riga 3, aggiunta*); it is only called for a highlighted, added or removed line.
63
+ * `copyLabel` names what is copied (*Copy mcp.json*); `copiedLabel` (*Copied*); `copyFailedLabel`
64
+ * (*Couldn't copy*). `label` and the three copy words are required, and `lineLabel` with any marked line.
65
+ * @access Ours: the code is a focusable, scrollable region named by `label`. Line numbers are hidden from
66
+ * assistive technology and are not tab stops; a highlighted, added or removed line carries
67
+ * `lineLabel`'s words as hidden text, with the numbers shown or not. The copy button names its
68
+ * target and announces the result.
19
69
  */
20
- export function CodeBlock({ code, label, filename, language, copyLabel, copiedLabel, copyFailedLabel, }) {
21
- return (_jsxs(InputGroup, { children: [_jsx(InputGroupTextarea, { "aria-label": label, value: code, readOnly: true, wrap: "off", spellCheck: false, className: "max-h-96 min-h-0 overflow-auto font-code text-code md:text-code" }), _jsxs(InputGroupAddon, { align: "block-start", className: "justify-between border-b border-border", children: [_jsx(InputGroupText, { title: filename ?? label, className: "min-w-0 truncate font-label-mono text-label-mono", children: filename ?? label }), _jsx(CopyButton, { value: code, copyLabel: copyLabel, copiedLabel: copiedLabel, copyFailedLabel: copyFailedLabel, size: "icon-xs" })] }), language ? (_jsx(InputGroupAddon, { align: "block-end", className: "border-t border-border", children: _jsx(InputGroupText, { children: language }) })) : null] }));
70
+ function CodeBlock({ addedLinesNumbers, className, code, copiedLabel, copyFailedLabel, copyLabel, filename, hideLineNumbers = false, highlightedLinesNumbers, label, lineLabel, removedLinesNumbers, switcher, tabs, }) {
71
+ const id = useId();
72
+ const lines = (code.endsWith("\n") ? code.slice(0, -1) : code).split("\n");
73
+ const added = new Set(addedLinesNumbers);
74
+ const removed = new Set(removedLinesNumbers);
75
+ const highlighted = new Set(highlightedLinesNumbers);
76
+ const gutterWidth = `calc(${Math.max(String(lines.length).length, 2)}ch + 1rem)`;
77
+ const hasHeader = filename !== undefined || switcher !== undefined || tabs !== undefined;
78
+ const copyButton = (_jsx(CopyButton, { value: code, copyLabel: copyLabel, copiedLabel: copiedLabel, copyFailedLabel: copyFailedLabel, size: "icon-sm" }));
79
+ return (_jsxs("div", { "data-slot": "code-block", className: cn("flex min-w-0 flex-col gap-3", className), children: [tabs ? _jsx(LanguageTabs, { ...tabs }) : null, _jsxs("div", { className: "group/code-block relative min-w-0 overflow-hidden rounded-md border border-border bg-background", children: [hasHeader ? (_jsxs("div", { className: "flex h-10 items-center gap-1 border-b border-border bg-muted pr-0.75 pl-4 text-label-sm text-muted-foreground", children: [_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: filename === undefined ? null : (_jsxs(_Fragment, { children: [_jsx(FileTypeIcon, { path: filename }), _jsx(MiddleTruncate, { value: filename })] })) }), switcher ? _jsx(LanguageSwitcher, { ...switcher }) : null, copyButton] })) : (_jsx("div", { className: cn("absolute top-3.75 right-3.75 z-10 rounded-sm bg-muted ring-1 ring-border", SHOWN_ON_HOVER), children: copyButton })), _jsx("pre", { "aria-label": label, className: "max-h-96 overflow-auto py-4 font-label-mono-md text-label-mono-md", role: "region", tabIndex: 0, children: _jsx("code", { className: "block min-w-max", children: lines.map((text, index) => {
80
+ const line = index + 1;
81
+ const state = removed.has(line)
82
+ ? "removed"
83
+ : added.has(line)
84
+ ? "added"
85
+ : highlighted.has(line)
86
+ ? "highlighted"
87
+ : "plain";
88
+ const anchor = `${id}-L${line}`;
89
+ return (_jsxs("span", { className: cn("flex px-4", ROW[state], LINKED_ROW), "data-state": state, id: anchor, children: [state === "plain" ? null : (_jsx("span", { className: "sr-only", children: lineLabel?.(line, state) })), hideLineNumbers ? null : (_jsx("a", { "aria-hidden": "true", className: "nc-transition-paint shrink-0 pr-4 text-right text-muted-foreground tabular-nums select-none hover:text-foreground", href: `#${anchor}`, style: { minWidth: gutterWidth }, tabIndex: -1, children: line })), _jsx("span", { className: "whitespace-pre", children: text || " " })] }, anchor));
90
+ }) }) })] })] }));
22
91
  }
92
+ export { CodeBlock };