@nadicodeai/ui 12.1.102 → 12.1.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. package/dist/components/accordion.d.ts +38 -12
  2. package/dist/components/accordion.d.ts.map +1 -1
  3. package/dist/components/accordion.js +36 -15
  4. package/dist/components/account-menu.js +2 -2
  5. package/dist/components/action-menu.d.ts +20 -19
  6. package/dist/components/action-menu.d.ts.map +1 -1
  7. package/dist/components/action-menu.js +22 -15
  8. package/dist/components/action-status.d.ts +14 -10
  9. package/dist/components/action-status.d.ts.map +1 -1
  10. package/dist/components/action-status.js +14 -10
  11. package/dist/components/activity-calendar.d.ts +3 -1
  12. package/dist/components/activity-calendar.d.ts.map +1 -1
  13. package/dist/components/activity-calendar.js +16 -2
  14. package/dist/components/activity-feed.d.ts +2 -2
  15. package/dist/components/activity-feed.d.ts.map +1 -1
  16. package/dist/components/activity-feed.js +14 -5
  17. package/dist/components/agent-card.d.ts +11 -5
  18. package/dist/components/agent-card.d.ts.map +1 -1
  19. package/dist/components/agent-card.js +13 -7
  20. package/dist/components/agent-list-row.js +1 -1
  21. package/dist/components/agent-orb-appearance.d.ts +7 -1
  22. package/dist/components/agent-orb-appearance.d.ts.map +1 -1
  23. package/dist/components/agent-orb-appearance.js +26 -0
  24. package/dist/components/agent-profile.d.ts +8 -7
  25. package/dist/components/agent-profile.d.ts.map +1 -1
  26. package/dist/components/agent-profile.js +6 -6
  27. package/dist/components/alert-dialog.d.ts +25 -16
  28. package/dist/components/alert-dialog.d.ts.map +1 -1
  29. package/dist/components/alert-dialog.js +30 -18
  30. package/dist/components/alert.d.ts +1 -1
  31. package/dist/components/avatar.d.ts +83 -17
  32. package/dist/components/avatar.d.ts.map +1 -1
  33. package/dist/components/avatar.js +89 -23
  34. package/dist/components/badge.d.ts +59 -8
  35. package/dist/components/badge.d.ts.map +1 -1
  36. package/dist/components/badge.js +57 -14
  37. package/dist/components/breadcrumb.d.ts +18 -7
  38. package/dist/components/breadcrumb.d.ts.map +1 -1
  39. package/dist/components/breadcrumb.js +37 -13
  40. package/dist/components/button-group.d.ts +12 -15
  41. package/dist/components/button-group.d.ts.map +1 -1
  42. package/dist/components/button-group.js +13 -17
  43. package/dist/components/button.d.ts +126 -23
  44. package/dist/components/button.d.ts.map +1 -1
  45. package/dist/components/button.js +164 -39
  46. package/dist/components/calendar.d.ts +26 -15
  47. package/dist/components/calendar.d.ts.map +1 -1
  48. package/dist/components/calendar.js +60 -46
  49. package/dist/components/card-row.d.ts +13 -5
  50. package/dist/components/card-row.d.ts.map +1 -1
  51. package/dist/components/card-row.js +24 -10
  52. package/dist/components/card.d.ts +6 -12
  53. package/dist/components/card.d.ts.map +1 -1
  54. package/dist/components/card.js +11 -16
  55. package/dist/components/carousel.d.ts +3 -3
  56. package/dist/components/carousel.d.ts.map +1 -1
  57. package/dist/components/carousel.js +7 -7
  58. package/dist/components/catalog-drawer.d.ts +7 -7
  59. package/dist/components/catalog-drawer.d.ts.map +1 -1
  60. package/dist/components/catalog-drawer.js +6 -6
  61. package/dist/components/chart-area-stacked.d.ts +1 -1
  62. package/dist/components/chart-area-stacked.d.ts.map +1 -1
  63. package/dist/components/chart-area-stacked.js +4 -4
  64. package/dist/components/chart-axis.d.ts +14 -1
  65. package/dist/components/chart-axis.d.ts.map +1 -1
  66. package/dist/components/chart-axis.js +11 -1
  67. package/dist/components/chart-bar-horizontal.d.ts +2 -2
  68. package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
  69. package/dist/components/chart-bar-horizontal.js +14 -5
  70. package/dist/components/chart-bar-multiple.d.ts +1 -1
  71. package/dist/components/chart-bar-multiple.d.ts.map +1 -1
  72. package/dist/components/chart-bar-multiple.js +3 -3
  73. package/dist/components/chart-bar-stacked.d.ts +1 -1
  74. package/dist/components/chart-bar-stacked.d.ts.map +1 -1
  75. package/dist/components/chart-bar-stacked.js +3 -3
  76. package/dist/components/chart-card.d.ts +17 -6
  77. package/dist/components/chart-card.d.ts.map +1 -1
  78. package/dist/components/chart-card.js +11 -4
  79. package/dist/components/chart-date-range-control.d.ts +18 -9
  80. package/dist/components/chart-date-range-control.d.ts.map +1 -1
  81. package/dist/components/chart-date-range-control.js +43 -47
  82. package/dist/components/chart-sparkline.d.ts +4 -3
  83. package/dist/components/chart-sparkline.d.ts.map +1 -1
  84. package/dist/components/chart-sparkline.js +6 -5
  85. package/dist/components/check-counts.d.ts +44 -0
  86. package/dist/components/check-counts.d.ts.map +1 -0
  87. package/dist/components/check-counts.js +51 -0
  88. package/dist/components/checkbox.d.ts +39 -11
  89. package/dist/components/checkbox.d.ts.map +1 -1
  90. package/dist/components/checkbox.js +38 -11
  91. package/dist/components/choicebox.d.ts +96 -0
  92. package/dist/components/choicebox.d.ts.map +1 -0
  93. package/dist/components/choicebox.js +113 -0
  94. package/dist/components/clearable-input.d.ts +57 -0
  95. package/dist/components/clearable-input.d.ts.map +1 -0
  96. package/dist/components/clearable-input.js +58 -0
  97. package/dist/components/code-block.d.ts +77 -17
  98. package/dist/components/code-block.d.ts.map +1 -1
  99. package/dist/components/code-block.js +85 -15
  100. package/dist/components/collapsible.d.ts +27 -10
  101. package/dist/components/collapsible.d.ts.map +1 -1
  102. package/dist/components/collapsible.js +24 -9
  103. package/dist/components/collection-filters.d.ts +3 -1
  104. package/dist/components/collection-filters.d.ts.map +1 -1
  105. package/dist/components/collection-filters.js +7 -9
  106. package/dist/components/collection-page.d.ts +31 -10
  107. package/dist/components/collection-page.d.ts.map +1 -1
  108. package/dist/components/collection-page.js +14 -13
  109. package/dist/components/collection-search.d.ts +32 -10
  110. package/dist/components/collection-search.d.ts.map +1 -1
  111. package/dist/components/collection-search.js +24 -13
  112. package/dist/components/collection-sort.d.ts.map +1 -1
  113. package/dist/components/collection-sort.js +2 -2
  114. package/dist/components/collection-toolbar.d.ts +5 -2
  115. package/dist/components/collection-toolbar.d.ts.map +1 -1
  116. package/dist/components/collection-toolbar.js +7 -4
  117. package/dist/components/combobox.d.ts +97 -22
  118. package/dist/components/combobox.d.ts.map +1 -1
  119. package/dist/components/combobox.js +80 -28
  120. package/dist/components/command.d.ts +34 -21
  121. package/dist/components/command.d.ts.map +1 -1
  122. package/dist/components/command.js +33 -25
  123. package/dist/components/confirm-dialog.d.ts +23 -6
  124. package/dist/components/confirm-dialog.d.ts.map +1 -1
  125. package/dist/components/confirm-dialog.js +32 -13
  126. package/dist/components/context-menu.d.ts +14 -10
  127. package/dist/components/context-menu.d.ts.map +1 -1
  128. package/dist/components/context-menu.js +17 -12
  129. package/dist/components/copy-button.d.ts +5 -2
  130. package/dist/components/copy-button.d.ts.map +1 -1
  131. package/dist/components/copy-button.js +16 -8
  132. package/dist/components/data-table.d.ts +120 -54
  133. package/dist/components/data-table.d.ts.map +1 -1
  134. package/dist/components/data-table.js +163 -92
  135. package/dist/components/desktop-shell.d.ts +4 -2
  136. package/dist/components/desktop-shell.d.ts.map +1 -1
  137. package/dist/components/desktop-shell.js +3 -3
  138. package/dist/components/dialog.d.ts +63 -24
  139. package/dist/components/dialog.d.ts.map +1 -1
  140. package/dist/components/dialog.js +52 -31
  141. package/dist/components/disclosure-row.d.ts +1 -2
  142. package/dist/components/disclosure-row.d.ts.map +1 -1
  143. package/dist/components/disclosure-row.js +1 -2
  144. package/dist/components/disclosure.d.ts +1 -1
  145. package/dist/components/disclosure.js +1 -1
  146. package/dist/components/drawer.d.ts +33 -12
  147. package/dist/components/drawer.d.ts.map +1 -1
  148. package/dist/components/drawer.js +47 -35
  149. package/dist/components/dropdown-menu.d.ts +59 -14
  150. package/dist/components/dropdown-menu.d.ts.map +1 -1
  151. package/dist/components/dropdown-menu.js +58 -26
  152. package/dist/components/empty-state.d.ts +35 -12
  153. package/dist/components/empty-state.d.ts.map +1 -1
  154. package/dist/components/empty-state.js +35 -17
  155. package/dist/components/entry-scene.d.ts +4 -4
  156. package/dist/components/entry-scene.d.ts.map +1 -1
  157. package/dist/components/entry-scene.js +2 -2
  158. package/dist/components/field.d.ts +44 -14
  159. package/dist/components/field.d.ts.map +1 -1
  160. package/dist/components/field.js +49 -20
  161. package/dist/components/file-diff.d.ts.map +1 -1
  162. package/dist/components/file-diff.js +3 -4
  163. package/dist/components/form-dialog.d.ts +7 -7
  164. package/dist/components/form-dialog.d.ts.map +1 -1
  165. package/dist/components/form-dialog.js +13 -11
  166. package/dist/components/form-drawer.d.ts +10 -7
  167. package/dist/components/form-drawer.d.ts.map +1 -1
  168. package/dist/components/form-drawer.js +11 -10
  169. package/dist/components/gauge.d.ts +64 -0
  170. package/dist/components/gauge.d.ts.map +1 -0
  171. package/dist/components/gauge.js +73 -0
  172. package/dist/components/hover-card.d.ts +72 -14
  173. package/dist/components/hover-card.d.ts.map +1 -1
  174. package/dist/components/hover-card.js +51 -17
  175. package/dist/components/identity-mark.d.ts +8 -1
  176. package/dist/components/identity-mark.d.ts.map +1 -1
  177. package/dist/components/identity-mark.js +31 -5
  178. package/dist/components/input-group.d.ts +44 -21
  179. package/dist/components/input-group.d.ts.map +1 -1
  180. package/dist/components/input-group.js +74 -27
  181. package/dist/components/input.d.ts +64 -12
  182. package/dist/components/input.d.ts.map +1 -1
  183. package/dist/components/input.js +51 -15
  184. package/dist/components/item.d.ts +37 -15
  185. package/dist/components/item.d.ts.map +1 -1
  186. package/dist/components/item.js +41 -22
  187. package/dist/components/kbd.d.ts +49 -13
  188. package/dist/components/kbd.d.ts.map +1 -1
  189. package/dist/components/kbd.js +115 -16
  190. package/dist/components/kpi-card.d.ts +12 -4
  191. package/dist/components/kpi-card.d.ts.map +1 -1
  192. package/dist/components/kpi-card.js +13 -4
  193. package/dist/components/label.d.ts +17 -10
  194. package/dist/components/label.d.ts.map +1 -1
  195. package/dist/components/label.js +18 -11
  196. package/dist/components/library-shelf.d.ts +6 -6
  197. package/dist/components/library-shelf.d.ts.map +1 -1
  198. package/dist/components/library-shelf.js +5 -5
  199. package/dist/components/load-more-button.d.ts +35 -0
  200. package/dist/components/load-more-button.d.ts.map +1 -0
  201. package/dist/components/load-more-button.js +26 -0
  202. package/dist/components/message-notice.d.ts +8 -13
  203. package/dist/components/message-notice.d.ts.map +1 -1
  204. package/dist/components/message-notice.js +25 -22
  205. package/dist/components/middle-truncate.d.ts +33 -0
  206. package/dist/components/middle-truncate.d.ts.map +1 -0
  207. package/dist/components/middle-truncate.js +72 -0
  208. package/dist/components/multi-select.d.ts +94 -0
  209. package/dist/components/multi-select.d.ts.map +1 -0
  210. package/dist/components/multi-select.js +132 -0
  211. package/dist/components/native-select.d.ts +37 -13
  212. package/dist/components/native-select.d.ts.map +1 -1
  213. package/dist/components/native-select.js +27 -11
  214. package/dist/components/notice-banner.d.ts +17 -10
  215. package/dist/components/notice-banner.d.ts.map +1 -1
  216. package/dist/components/notice-banner.js +12 -11
  217. package/dist/components/numbered-steps.d.ts +10 -4
  218. package/dist/components/numbered-steps.d.ts.map +1 -1
  219. package/dist/components/numbered-steps.js +9 -7
  220. package/dist/components/object-page.d.ts +40 -14
  221. package/dist/components/object-page.d.ts.map +1 -1
  222. package/dist/components/object-page.js +12 -10
  223. package/dist/components/object-workspace.d.ts +29 -10
  224. package/dist/components/object-workspace.d.ts.map +1 -1
  225. package/dist/components/object-workspace.js +18 -8
  226. package/dist/components/overview-page.d.ts +2 -2
  227. package/dist/components/overview-page.d.ts.map +1 -1
  228. package/dist/components/overview-page.js +8 -7
  229. package/dist/components/page-actions.d.ts +28 -8
  230. package/dist/components/page-actions.d.ts.map +1 -1
  231. package/dist/components/page-actions.js +22 -25
  232. package/dist/components/page-header.d.ts +11 -4
  233. package/dist/components/page-header.d.ts.map +1 -1
  234. package/dist/components/page-header.js +10 -5
  235. package/dist/components/pending-label.d.ts +6 -5
  236. package/dist/components/pending-label.d.ts.map +1 -1
  237. package/dist/components/pending-label.js +14 -6
  238. package/dist/components/picture-label.d.ts +2 -2
  239. package/dist/components/picture-label.d.ts.map +1 -1
  240. package/dist/components/picture-label.js +3 -3
  241. package/dist/components/portal-sidebar-frame.d.ts +9 -21
  242. package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
  243. package/dist/components/portal-sidebar-frame.js +13 -27
  244. package/dist/components/progress-checklist.d.ts +46 -0
  245. package/dist/components/progress-checklist.d.ts.map +1 -0
  246. package/dist/components/progress-checklist.js +46 -0
  247. package/dist/components/progress.d.ts +48 -8
  248. package/dist/components/progress.d.ts.map +1 -1
  249. package/dist/components/progress.js +92 -16
  250. package/dist/components/prose.d.ts +19 -0
  251. package/dist/components/prose.d.ts.map +1 -0
  252. package/dist/components/prose.js +29 -0
  253. package/dist/components/radio-group.d.ts +51 -12
  254. package/dist/components/radio-group.d.ts.map +1 -1
  255. package/dist/components/radio-group.js +42 -12
  256. package/dist/components/reading-column.js +1 -1
  257. package/dist/components/record-identity.d.ts +6 -5
  258. package/dist/components/record-identity.d.ts.map +1 -1
  259. package/dist/components/record-identity.js +12 -3
  260. package/dist/components/record-list.d.ts +117 -27
  261. package/dist/components/record-list.d.ts.map +1 -1
  262. package/dist/components/record-list.js +185 -55
  263. package/dist/components/record-time.d.ts +20 -7
  264. package/dist/components/record-time.d.ts.map +1 -1
  265. package/dist/components/record-time.js +38 -19
  266. package/dist/components/resizable.d.ts +7 -5
  267. package/dist/components/resizable.d.ts.map +1 -1
  268. package/dist/components/resizable.js +6 -6
  269. package/dist/components/scope-switcher.d.ts +2 -0
  270. package/dist/components/scope-switcher.d.ts.map +1 -1
  271. package/dist/components/scope-switcher.js +2 -2
  272. package/dist/components/scroll-area.d.ts +47 -11
  273. package/dist/components/scroll-area.d.ts.map +1 -1
  274. package/dist/components/scroll-area.js +72 -14
  275. package/dist/components/segmented-control.d.ts +82 -0
  276. package/dist/components/segmented-control.d.ts.map +1 -0
  277. package/dist/components/segmented-control.js +90 -0
  278. package/dist/components/select.d.ts +55 -15
  279. package/dist/components/select.d.ts.map +1 -1
  280. package/dist/components/select.js +62 -19
  281. package/dist/components/separator.d.ts +12 -5
  282. package/dist/components/separator.d.ts.map +1 -1
  283. package/dist/components/separator.js +11 -6
  284. package/dist/components/settings-facts.d.ts +34 -14
  285. package/dist/components/settings-facts.d.ts.map +1 -1
  286. package/dist/components/settings-facts.js +21 -12
  287. package/dist/components/settings-page.d.ts +4 -4
  288. package/dist/components/settings-page.js +5 -5
  289. package/dist/components/settings-section.d.ts +160 -34
  290. package/dist/components/settings-section.d.ts.map +1 -1
  291. package/dist/components/settings-section.js +92 -39
  292. package/dist/components/sheet.d.ts +47 -16
  293. package/dist/components/sheet.d.ts.map +1 -1
  294. package/dist/components/sheet.js +40 -19
  295. package/dist/components/sidebar-sections.d.ts +16 -12
  296. package/dist/components/sidebar-sections.d.ts.map +1 -1
  297. package/dist/components/sidebar-sections.js +30 -15
  298. package/dist/components/sidebar.d.ts +117 -21
  299. package/dist/components/sidebar.d.ts.map +1 -1
  300. package/dist/components/sidebar.js +180 -55
  301. package/dist/components/skeleton.d.ts +54 -8
  302. package/dist/components/skeleton.d.ts.map +1 -1
  303. package/dist/components/skeleton.js +44 -9
  304. package/dist/components/slider.d.ts +53 -11
  305. package/dist/components/slider.d.ts.map +1 -1
  306. package/dist/components/slider.js +71 -17
  307. package/dist/components/snippet.d.ts +57 -0
  308. package/dist/components/snippet.d.ts.map +1 -0
  309. package/dist/components/snippet.js +60 -0
  310. package/dist/components/sonner.d.ts +13 -14
  311. package/dist/components/sonner.d.ts.map +1 -1
  312. package/dist/components/sonner.js +25 -22
  313. package/dist/components/status-badge.d.ts +37 -11
  314. package/dist/components/status-badge.d.ts.map +1 -1
  315. package/dist/components/status-badge.js +63 -15
  316. package/dist/components/status-dot.d.ts +42 -11
  317. package/dist/components/status-dot.d.ts.map +1 -1
  318. package/dist/components/status-dot.js +40 -11
  319. package/dist/components/switch.d.ts +43 -12
  320. package/dist/components/switch.d.ts.map +1 -1
  321. package/dist/components/switch.js +42 -12
  322. package/dist/components/table-card.d.ts +21 -12
  323. package/dist/components/table-card.d.ts.map +1 -1
  324. package/dist/components/table-card.js +17 -9
  325. package/dist/components/table-layouts.d.ts +40 -8
  326. package/dist/components/table-layouts.d.ts.map +1 -1
  327. package/dist/components/table-layouts.js +52 -8
  328. package/dist/components/table-value.d.ts +4 -3
  329. package/dist/components/table-value.d.ts.map +1 -1
  330. package/dist/components/table-value.js +6 -5
  331. package/dist/components/table.d.ts +62 -25
  332. package/dist/components/table.d.ts.map +1 -1
  333. package/dist/components/table.js +62 -26
  334. package/dist/components/tabs.d.ts +86 -17
  335. package/dist/components/tabs.d.ts.map +1 -1
  336. package/dist/components/tabs.js +93 -22
  337. package/dist/components/text-link.d.ts +4 -1
  338. package/dist/components/text-link.d.ts.map +1 -1
  339. package/dist/components/text-link.js +4 -1
  340. package/dist/components/text-with-copy-button.d.ts +30 -0
  341. package/dist/components/text-with-copy-button.d.ts.map +1 -0
  342. package/dist/components/text-with-copy-button.js +32 -0
  343. package/dist/components/textarea.d.ts +40 -10
  344. package/dist/components/textarea.d.ts.map +1 -1
  345. package/dist/components/textarea.js +50 -11
  346. package/dist/components/theme-mode-switcher.d.ts +18 -1
  347. package/dist/components/theme-mode-switcher.d.ts.map +1 -1
  348. package/dist/components/theme-mode-switcher.js +20 -2
  349. package/dist/components/toggle-group.d.ts +28 -8
  350. package/dist/components/toggle-group.d.ts.map +1 -1
  351. package/dist/components/toggle-group.js +12 -6
  352. package/dist/components/toggle.d.ts +6 -3
  353. package/dist/components/toggle.d.ts.map +1 -1
  354. package/dist/components/toggle.js +10 -7
  355. package/dist/components/tooltip.d.ts +43 -12
  356. package/dist/components/tooltip.d.ts.map +1 -1
  357. package/dist/components/tooltip.js +45 -16
  358. package/dist/components/trend-badge.js +1 -1
  359. package/dist/components/update-card.js +1 -1
  360. package/dist/eslint/index.js +82 -0
  361. package/dist/eslint/rules/badge-is-static-label.js +93 -0
  362. package/dist/eslint/rules/button-icon-slot.js +102 -0
  363. package/dist/eslint/rules/button-link-for-navigation.js +146 -0
  364. package/dist/eslint/rules/button-no-aria-label-with-text.js +75 -0
  365. package/dist/eslint/rules/button-type-roles-only-in-buttons.js +83 -0
  366. package/dist/eslint/rules/choice-control-has-a-name.js +98 -0
  367. package/dist/eslint/rules/choice-group-in-fieldset.js +86 -0
  368. package/dist/eslint/rules/command-shortcut-single-owner.js +118 -0
  369. package/dist/eslint/rules/confirm-dialog-words.js +63 -0
  370. package/dist/eslint/rules/data-table-one-unsized-column.js +96 -0
  371. package/dist/eslint/rules/destructive-action-placement.js +69 -0
  372. package/dist/eslint/rules/disabled-choice-says-why.js +71 -0
  373. package/dist/eslint/rules/ellipsis-opens-a-dialog.js +110 -0
  374. package/dist/eslint/rules/input-group-owners.js +155 -0
  375. package/dist/eslint/rules/kbd-children-no-modifier-text.js +128 -0
  376. package/dist/eslint/rules/literal-text.js +41 -0
  377. package/dist/eslint/rules/middle-truncate-placement.js +69 -0
  378. package/dist/eslint/rules/no-bare-button-label.js +55 -0
  379. package/dist/eslint/rules/no-control-in-read-only-surface.js +106 -0
  380. package/dist/eslint/rules/no-hand-built-busy.js +104 -0
  381. package/dist/eslint/rules/no-hand-built-theme-picker.js +144 -0
  382. package/dist/eslint/rules/no-hand-built-tile.js +41 -0
  383. package/dist/eslint/rules/no-hand-formatted-date.js +87 -0
  384. package/dist/eslint/rules/no-hand-stacked-avatars.js +67 -0
  385. package/dist/eslint/rules/no-nested-collapse.js +60 -0
  386. package/dist/eslint/rules/no-search-in-form.js +47 -0
  387. package/dist/eslint/rules/no-shadcn-appearance-override.js +2 -16
  388. package/dist/eslint/rules/no-shell-prompt-in-snippet.js +74 -0
  389. package/dist/eslint/rules/no-stock-error-words.js +56 -0
  390. package/dist/eslint/rules/no-tooltip-around-labelled-field.js +72 -0
  391. package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +57 -0
  392. package/dist/eslint/rules/one-submenu-level.js +43 -0
  393. package/dist/eslint/rules/one-toast-per-flow.js +91 -0
  394. package/dist/eslint/rules/option-count.js +167 -0
  395. package/dist/eslint/rules/page-command-link-not-render.js +43 -0
  396. package/dist/eslint/rules/progress-needs-name.js +57 -0
  397. package/dist/eslint/rules/settings-limit-in-footer.js +94 -0
  398. package/dist/eslint/rules/skeleton-in-region.js +80 -0
  399. package/dist/eslint/rules/sortable-heading-uses-sort.js +79 -0
  400. package/dist/eslint/rules/table-cell-inset-owner.js +107 -0
  401. package/dist/eslint/rules/tabs-selection-is-controlled.js +47 -0
  402. package/dist/eslint/rules/tooltip-only-arrow.js +38 -0
  403. package/dist/eslint/rules/tooltip-trigger-accessible-name.js +114 -0
  404. package/dist/eslint/strict-design-system.js +21 -7
  405. package/dist/index.d.ts +13 -13
  406. package/dist/index.d.ts.map +1 -1
  407. package/dist/index.js +12 -13
  408. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
  409. package/dist/internal/assistant-ui/attachment.js +2 -2
  410. package/dist/internal/assistant-ui/reasoning.d.ts +1 -1
  411. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
  412. package/dist/internal/assistant-ui/tool-fallback.js +1 -1
  413. package/dist/internal/assistant-ui/tool-group.d.ts +1 -1
  414. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
  415. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +2 -3
  416. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -1
  417. package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
  418. package/dist/internal/catalog-list.js +2 -2
  419. package/dist/internal/collection-note.d.ts +23 -0
  420. package/dist/internal/collection-note.d.ts.map +1 -0
  421. package/dist/internal/collection-note.js +17 -0
  422. package/dist/internal/collection-rail.d.ts +57 -0
  423. package/dist/internal/collection-rail.d.ts.map +1 -0
  424. package/dist/internal/collection-rail.js +33 -0
  425. package/dist/internal/company-logo.d.ts +18 -0
  426. package/dist/internal/company-logo.d.ts.map +1 -0
  427. package/dist/internal/company-logo.js +14 -0
  428. package/dist/internal/control-name.d.ts +12 -0
  429. package/dist/internal/control-name.d.ts.map +1 -0
  430. package/dist/internal/control-name.js +1 -0
  431. package/dist/internal/diff-line.d.ts +9 -0
  432. package/dist/internal/diff-line.d.ts.map +1 -0
  433. package/dist/internal/diff-line.js +8 -0
  434. package/dist/internal/empty.d.ts +8 -4
  435. package/dist/internal/empty.d.ts.map +1 -1
  436. package/dist/internal/empty.js +14 -8
  437. package/dist/internal/field-frame.d.ts +33 -0
  438. package/dist/internal/field-frame.d.ts.map +1 -0
  439. package/dist/internal/field-frame.js +20 -0
  440. package/dist/internal/final-focus.d.ts +8 -0
  441. package/dist/internal/final-focus.d.ts.map +1 -0
  442. package/dist/internal/final-focus.js +10 -0
  443. package/dist/internal/footer-strip.d.ts.map +1 -1
  444. package/dist/internal/footer-strip.js +3 -1
  445. package/dist/internal/form-submit.d.ts +9 -5
  446. package/dist/internal/form-submit.d.ts.map +1 -1
  447. package/dist/internal/form-submit.js +31 -2
  448. package/dist/internal/input-box.d.ts +26 -0
  449. package/dist/internal/input-box.d.ts.map +1 -0
  450. package/dist/internal/input-box.js +59 -0
  451. package/dist/internal/menu-surface.d.ts +10 -3
  452. package/dist/internal/menu-surface.d.ts.map +1 -1
  453. package/dist/internal/menu-surface.js +10 -3
  454. package/dist/internal/notice.d.ts +25 -0
  455. package/dist/internal/notice.d.ts.map +1 -0
  456. package/dist/internal/notice.js +33 -0
  457. package/dist/internal/overlay-stem.d.ts +5 -0
  458. package/dist/internal/overlay-stem.d.ts.map +1 -0
  459. package/dist/internal/overlay-stem.js +7 -0
  460. package/dist/internal/phone-sheet.d.ts +4 -0
  461. package/dist/internal/phone-sheet.d.ts.map +1 -0
  462. package/dist/internal/phone-sheet.js +2 -0
  463. package/dist/internal/present-content.d.ts +3 -0
  464. package/dist/internal/present-content.d.ts.map +1 -0
  465. package/dist/internal/present-content.js +1 -0
  466. package/dist/internal/record-menu-items.d.ts +4 -3
  467. package/dist/internal/record-menu-items.d.ts.map +1 -1
  468. package/dist/internal/record-menu-items.js +21 -6
  469. package/dist/internal/settings-save.d.ts +9 -2
  470. package/dist/internal/settings-save.d.ts.map +1 -1
  471. package/dist/internal/settings-save.js +19 -6
  472. package/dist/internal/table-compact-line.d.ts +38 -0
  473. package/dist/internal/table-compact-line.d.ts.map +1 -0
  474. package/dist/internal/table-compact-line.js +35 -0
  475. package/dist/internal/title-when-cut.d.ts +8 -0
  476. package/dist/internal/title-when-cut.d.ts.map +1 -0
  477. package/dist/internal/title-when-cut.js +22 -0
  478. package/dist/internal/unsaved-guard.d.ts +18 -0
  479. package/dist/internal/unsaved-guard.d.ts.map +1 -0
  480. package/dist/internal/unsaved-guard.js +31 -0
  481. package/dist/lib/merge-tokens.generated.js +2 -2
  482. package/dist/showcase/foundations.d.ts.map +1 -1
  483. package/dist/showcase/foundations.js +10 -2
  484. package/dist/showcase/specimens/actions.d.ts +2 -0
  485. package/dist/showcase/specimens/actions.d.ts.map +1 -1
  486. package/dist/showcase/specimens/actions.js +30 -5
  487. package/dist/showcase/specimens/charts.d.ts.map +1 -1
  488. package/dist/showcase/specimens/charts.js +22 -13
  489. package/dist/showcase/specimens/choices.d.ts +14 -3
  490. package/dist/showcase/specimens/choices.d.ts.map +1 -1
  491. package/dist/showcase/specimens/choices.js +93 -13
  492. package/dist/showcase/specimens/compositions.d.ts.map +1 -1
  493. package/dist/showcase/specimens/compositions.js +136 -23
  494. package/dist/showcase/specimens/data.d.ts +12 -7
  495. package/dist/showcase/specimens/data.d.ts.map +1 -1
  496. package/dist/showcase/specimens/data.js +139 -35
  497. package/dist/showcase/specimens/feedback.d.ts +2 -0
  498. package/dist/showcase/specimens/feedback.d.ts.map +1 -1
  499. package/dist/showcase/specimens/feedback.js +39 -15
  500. package/dist/showcase/specimens/index.d.ts +20 -12
  501. package/dist/showcase/specimens/index.d.ts.map +1 -1
  502. package/dist/showcase/specimens/inputs.d.ts +4 -2
  503. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  504. package/dist/showcase/specimens/inputs.js +62 -19
  505. package/dist/showcase/specimens/menus.d.ts +0 -1
  506. package/dist/showcase/specimens/menus.d.ts.map +1 -1
  507. package/dist/showcase/specimens/menus.js +47 -17
  508. package/dist/showcase/specimens/navigation.d.ts +6 -4
  509. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  510. package/dist/showcase/specimens/navigation.js +61 -32
  511. package/dist/showcase/specimens/other.d.ts +1 -3
  512. package/dist/showcase/specimens/other.d.ts.map +1 -1
  513. package/dist/showcase/specimens/other.js +17 -13
  514. package/dist/showcase/specimens/status.d.ts +4 -1
  515. package/dist/showcase/specimens/status.d.ts.map +1 -1
  516. package/dist/showcase/specimens/status.js +64 -11
  517. package/dist/showcase/usage.generated.d.ts +1 -1
  518. package/dist/showcase/usage.generated.d.ts.map +1 -1
  519. package/dist/showcase/usage.generated.js +632 -544
  520. package/dist/standalone/index.js +1 -1
  521. package/dist/styles/components.css +13 -13
  522. package/dist/styles/globals.css +25 -0
  523. package/package.json +2 -3
  524. package/dist/components/approval-row.d.ts +0 -34
  525. package/dist/components/approval-row.d.ts.map +0 -1
  526. package/dist/components/approval-row.js +0 -27
  527. package/dist/components/channel-view.d.ts +0 -112
  528. package/dist/components/channel-view.d.ts.map +0 -1
  529. package/dist/components/channel-view.js +0 -84
  530. package/dist/components/dashboard-shell.d.ts +0 -51
  531. package/dist/components/dashboard-shell.d.ts.map +0 -1
  532. package/dist/components/dashboard-shell.js +0 -89
  533. package/dist/components/direction.d.ts +0 -2
  534. package/dist/components/direction.d.ts.map +0 -1
  535. package/dist/components/direction.js +0 -1
  536. package/dist/components/expandable-block.d.ts +0 -20
  537. package/dist/components/expandable-block.d.ts.map +0 -1
  538. package/dist/components/expandable-block.js +0 -32
  539. package/dist/components/form.d.ts +0 -42
  540. package/dist/components/form.d.ts.map +0 -1
  541. package/dist/components/form.js +0 -91
  542. package/dist/components/label-system.d.ts +0 -17
  543. package/dist/components/label-system.d.ts.map +0 -1
  544. package/dist/components/label-system.js +0 -21
  545. package/dist/components/memory-item.d.ts +0 -21
  546. package/dist/components/memory-item.d.ts.map +0 -1
  547. package/dist/components/memory-item.js +0 -18
  548. package/dist/components/menubar.d.ts +0 -43
  549. package/dist/components/menubar.d.ts.map +0 -1
  550. package/dist/components/menubar.js +0 -69
  551. package/dist/components/navigation-menu.d.ts +0 -26
  552. package/dist/components/navigation-menu.d.ts.map +0 -1
  553. package/dist/components/navigation-menu.js +0 -45
  554. package/dist/components/pagination.d.ts +0 -33
  555. package/dist/components/pagination.d.ts.map +0 -1
  556. package/dist/components/pagination.js +0 -41
  557. package/dist/components/plugin-slot-boundary.d.ts +0 -42
  558. package/dist/components/plugin-slot-boundary.d.ts.map +0 -1
  559. package/dist/components/plugin-slot-boundary.js +0 -41
  560. package/dist/components/status-row.d.ts +0 -32
  561. package/dist/components/status-row.d.ts.map +0 -1
  562. package/dist/components/status-row.js +0 -35
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useMemo } from "react";
4
4
  import { cva } from "class-variance-authority";
5
+ import { OctagonAlertIcon } from "lucide-react";
5
6
  import { cn } from "../lib/utils.js";
6
7
  import { Label } from "./label.js";
7
8
  import { Separator } from "./separator.js";
@@ -9,12 +10,12 @@ function FieldSet({ className, ...props }) {
9
10
  return (_jsx("fieldset", { "data-slot": "field-set", className: cn("flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", className), ...props }));
10
11
  }
11
12
  function FieldLegend({ className, variant = "legend", ...props }) {
12
- return (_jsx("legend", { "data-slot": "field-legend", "data-variant": variant, className: cn("mb-1.5 data-[variant=label]:text-label data-[variant=label]:font-medium data-[variant=legend]:text-heading-xs", className), ...props }));
13
+ return (_jsx("legend", { "data-slot": "field-legend", "data-variant": variant, className: cn("mb-1.5 data-[variant=label]:text-label-sm data-[variant=label]:leading-normal data-[variant=label]:text-muted-foreground data-[variant=legend]:text-heading-xs", className), ...props }));
13
14
  }
14
15
  function FieldGroup({ className, ...props }) {
15
- return (_jsx("div", { "data-slot": "field-group", className: cn("group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4", className), ...props }));
16
+ return (_jsx("div", { "data-slot": "field-group", className: cn("group/field-group @container/field-group flex w-full flex-col gap-4 data-[slot=checkbox-group]:gap-3", className), ...props }));
16
17
  }
17
- const fieldVariants = cva("group/field flex w-full gap-2 data-[invalid=true]:text-destructive", {
18
+ const fieldVariants = cva("group/field flex w-full gap-2", {
18
19
  variants: {
19
20
  orientation: {
20
21
  vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
@@ -27,21 +28,49 @@ const fieldVariants = cva("group/field flex w-full gap-2 data-[invalid=true]:tex
27
28
  },
28
29
  });
29
30
  /**
30
- * A control with its label, its help and its error, tied together.
31
+ * A control with its label and its error, tied together; a checkbox, a radio or a switch with the
32
+ * sentence beside it.
31
33
  *
32
34
  * @family Inputs
33
- * @when Every control with a name: it ties the label, the help and the error to the control. Inside
34
- * a settings section `SettingsField` does it and hands the control its `controlProps`. A rich
35
- * choice tile is a `FieldLabel` holding a `Field` with its radio or checkbox.
36
- * @instead A group of radios or checkboxes is a `FieldSet` with a `FieldLegend`. A whole save group
37
- * is `SettingsSection`.
38
- * @behaviour Label, then help, then the error, then the control, 8 px apart. Invalid turns the
39
- * label and message red and puts the red edge and outline on the control. Validate on submit or on
40
- * leaving a field, then update the message as the value is corrected.
41
- * @words The help says what the setting changes, in one sentence. The error says how to fix it, not
42
- * what went wrong: *Enter a full address, like name@company.it.* A disabled field says why.
35
+ * @when A checkbox, a radio or a switch with its sentence, or a group of such rows. Inside a
36
+ * settings section `SettingsField` does it and hands the control its `controlProps`.
37
+ * @instead A text box, a textarea, a select, a combobox or a multi-select takes `label` and `error`
38
+ * as props and draws these same parts: wrapping one in `Field` with a `FieldLabel` is the same job
39
+ * done twice. A bordered tile that holds a radio or checkbox and a sentence is `ChoiceboxGroup`. A
40
+ * whole save group is `SettingsSection`. A group of radios or checkboxes is a `FieldSet` with a
41
+ * `FieldLegend`:
42
+ * "Wrap related radios in `<fieldset>` + `<legend>` so screen readers announce the group name before each option." (https://vercel.com/geist/radio)
43
+ * "Wrap related checkboxes in `<fieldset>` with a `<legend>` so screen readers announce the group name before each option." (https://vercel.com/geist/checkbox)
44
+ * @behaviour "Accessible text label for form controls." (https://vercel.com/geist/label) Label,
45
+ * then the control, then the error under it, 8 px apart, at regular weight; the fields of a
46
+ * `FieldGroup` stand 16 px apart. The label stays neutral when the control is invalid: red sits on
47
+ * the control's edge and on the message, the message with an alert mark before it at 13 px (16 px
48
+ * beside a large control). A control fills its field.
49
+ * "Helper text is sentence case, one sentence with a trailing period, on a sibling element wired through `aria-describedby`." (https://vercel.com/geist/input)
50
+ * Ours: help is the one-line description of the card or the form that holds the field, not a line
51
+ * under each field; a `FieldDescription` is for the sentence beside a checkbox, a radio or a
52
+ * switch.
53
+ * "Validate on blur, not on every keystroke; surface the message by passing a string to `error`." (https://vercel.com/geist/input)
54
+ * "Validate on blur and pass a string to `error` to render the inline message; the validation replaces helper text on failure." (https://vercel.com/geist/textarea)
55
+ * Ours: the message updates as the value is corrected.
56
+ * "Keep the field focusable while saving; pair `disabled` with a spinner only when input is impossible." (https://vercel.com/geist/input)
57
+ * Ours: no spinner, the loading state stays still.
58
+ * "Trim leading and trailing whitespace before submit so ` example.com` and `example.com` resolve to one value." (https://vercel.com/geist/input)
59
+ * Ours: the save of `FormDialog`, `FormDrawer`, `RowEditForm` and `SettingsSection` trims the ends
60
+ * of every text value; a bare `<form>` does not.
61
+ * "The click target already extends to the label. Don’t override the `<label>`/`htmlFor` association with a custom wrapper that breaks the click region." (https://vercel.com/geist/checkbox)
62
+ * "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox)
63
+ * Ours: a disabled field says why in the card's footer, never in a tooltip around the control.
64
+ * @words
65
+ * "Labels are short Title Case nouns: `Project Name`, `Domain`, `Environment Variable Name`." (https://vercel.com/geist/input)
66
+ * Ours: sentence case, a short noun (*Display name*); a field that may stay empty says so in its
67
+ * label (*Address line 2 (optional)*), never in its placeholder.
68
+ * "Placeholders show an example value (`my-awesome-project`, `example.com`), never instructions like `Enter your project name`." (https://vercel.com/geist/input)
69
+ * "Validation names the field and the constraint, ends in a period, and skips `please` (`Project name is required.`, `Code must be 6 digits.`)." (https://vercel.com/geist/input)
70
+ * Ours: *Enter a full address, like name@company.it.*
43
71
  * @access `FieldError` is `role="alert"`. The control carries `id`, `aria-invalid`,
44
- * `aria-describedby` (help, then error), `disabled` and `required`.
72
+ * `aria-describedby` (the error), `disabled` and `required`.
73
+ * "Don’t wrap a labelled `<Input>` in a `Tooltip`; put the explainer on a sibling icon button so the label stays announced." (https://vercel.com/geist/input)
45
74
  */
46
75
  function Field({ className, orientation = "vertical", ...props }) {
47
76
  return (_jsx("div", { role: "group", "data-slot": "field", "data-orientation": orientation, className: cn(fieldVariants({ orientation }), className), ...props }));
@@ -52,11 +81,11 @@ function Field({ className, orientation = "vertical", ...props }) {
52
81
  function FieldContent({ className, ...props }) {
53
82
  return (_jsx("div", { "data-slot": "field-content", className: cn("group/field-content flex flex-1 flex-col gap-1 *:data-[slot=field-label]:block *:data-[slot=field-label]:leading-snug", className), ...props }));
54
83
  }
55
- function FieldLabel({ className, ...props }) {
56
- return (_jsx(Label, { "data-slot": "field-label", className: cn("group/field-label peer/field-label flex w-fit gap-2 group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary has-data-checked:bg-muted has-[>[data-slot=field]]:rounded-sm has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5", "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col", className), ...props }));
84
+ function FieldLabel({ className, htmlFor, ...props }) {
85
+ return (_jsx(Label, { "data-slot": "field-label", htmlFor: htmlFor, className: cn("group/field-label peer/field-label flex w-fit gap-2 group-data-[disabled=true]/field:text-placeholder", "group-has-[[role=checkbox]]/field:leading-5 group-has-[[role=checkbox]]/field:text-foreground group-has-[[role=radio]]/field:leading-5 group-has-[[role=radio]]/field:text-foreground", "group-has-[[role=switch]]/field:text-xs group-has-[[role=switch]]/field:font-medium group-has-[[role=switch]]/field:text-foreground", className), ...props }));
57
86
  }
58
87
  function FieldTitle({ className, ...props }) {
59
- return (_jsx("div", { "data-slot": "field-label", className: cn("flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50", className), ...props }));
88
+ return (_jsx("div", { "data-slot": "field-label", className: cn("flex w-fit items-center gap-2 text-label group-data-[disabled=true]/field:text-placeholder", className), ...props }));
60
89
  }
61
90
  function FieldDescription({ className, ...props }) {
62
91
  return (_jsx("p", { "data-slot": "field-description", className: cn("text-left text-sm font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5", "last:mt-0 nth-last-2:-mt-1", "[&>a]:text-(--nc-link) [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:decoration-2", className), ...props }));
@@ -64,7 +93,7 @@ function FieldDescription({ className, ...props }) {
64
93
  function FieldSeparator({ children, className, ...props }) {
65
94
  return (_jsxs("div", { "data-slot": "field-separator", "data-content": !!children, className: cn("relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", className), ...props, children: [_jsx(Separator, { className: "absolute inset-0 top-1/2" }), children && (_jsx("span", { className: "relative mx-auto block w-fit bg-background px-2 text-muted-foreground", "data-slot": "field-separator-content", children: children }))] }));
66
95
  }
67
- function FieldError({ className, children, errors, ...props }) {
96
+ function FieldError({ className, children, errors, size = "default", ...props }) {
68
97
  const content = useMemo(() => {
69
98
  if (children) {
70
99
  return children;
@@ -83,6 +112,6 @@ function FieldError({ className, children, errors, ...props }) {
83
112
  if (!content) {
84
113
  return null;
85
114
  }
86
- return (_jsx("div", { role: "alert", "data-slot": "field-error", className: cn("text-sm font-normal text-destructive", className), ...props, children: content }));
115
+ return (_jsxs("div", { role: "alert", "aria-atomic": "true", "data-slot": "field-error", "data-size": size, className: cn("flex items-start gap-2 text-label-sm leading-5 font-normal text-destructive data-[size=lg]:text-base data-[size=lg]:leading-6", className), ...props, children: [_jsx(OctagonAlertIcon, { "aria-hidden": "true", className: "mt-0.5 size-4 shrink-0 in-data-[size=lg]:mt-1" }), _jsx("div", { className: "min-w-0", children: content })] }));
87
116
  }
88
117
  export { Field, FieldLabel, FieldDescription, FieldError, FieldGroup, FieldLegend, FieldSeparator, FieldSet, FieldContent, FieldTitle, };
@@ -1 +1 @@
1
- {"version":3,"file":"file-diff.d.ts","sourceRoot":"","sources":["../../src/components/file-diff.tsx"],"names":[],"mappings":"AAKA,UAAU,aAAc,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1C;AAcD;;;;;;;;;;;GAWG;AACH,iBAAS,QAAQ,CAAC,EAChB,UAAoB,EACpB,KAAK,EACL,MAAM,EACN,SAAS,EACT,OAAW,EACX,YAAwB,EACxB,YAAoD,EACpD,GAAG,KAAK,EACT,EAAE,aAAa,+BAkCf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"file-diff.d.ts","sourceRoot":"","sources":["../../src/components/file-diff.tsx"],"names":[],"mappings":"AAMA,UAAU,aAAc,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1C;AAYD;;;;;;;;;;;GAWG;AACH,iBAAS,QAAQ,CAAC,EAChB,UAAoB,EACpB,KAAK,EACL,MAAM,EACN,SAAS,EACT,OAAW,EACX,YAAwB,EACxB,YAAoD,EACpD,GAAG,KAAK,EACT,EAAE,aAAa,+BAkCf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1,16 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
+ import { DIFF_MARK, DIFF_ROW } from "../internal/diff-line.js";
3
4
  import { lineDiff } from "../lib/line-diff.js";
4
5
  import { cn } from "../lib/utils.js";
5
6
  const ROW = {
6
- added: "bg-success-soft text-success-soft-foreground",
7
+ ...DIFF_ROW,
7
8
  context: "text-muted-foreground",
8
- removed: "bg-destructive-soft text-destructive-soft-foreground",
9
9
  };
10
10
  const MARK = {
11
- added: "+",
11
+ ...DIFF_MARK,
12
12
  context: "",
13
- removed: "−",
14
13
  };
15
14
  /**
16
15
  * A file's before and after, line by line.
@@ -5,15 +5,15 @@ export type FormDialogProps = FormSurfaceProps & {
5
5
  pending?: boolean;
6
6
  };
7
7
  /**
8
- * A new record, or one or two values from a command, in a centred dialog.
8
+ * A new record, or one or two values from a command, in a modal dialog.
9
9
  *
10
10
  * @family Compositions
11
- * @when A person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
12
- * @instead A record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
13
- * @behaviour Centred over a scrim without blur: the title and its help, the fields in a body that scrolls, then the footer with Cancel and the primary at its trailing edge. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them.
14
- * @words The title names the job and its object: "New customer", "Add a mailbox". The primary repeats it: "Create customer", "Add mailbox", never "OK" or "Submit".
15
- * @access A modal dialog named by its title; focus starts in its first field or `initialFocus`, Escape and Close close it unless the save runs, and focus returns to the opener or `finalFocus`.
11
+ * @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal) Ours: a person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
12
+ * @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
13
+ * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close.
14
+ * @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox".
15
+ * @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal) "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal) Ours: a modal dialog with a Close named by `closeLabel`; focus starts in its first field or `initialFocus` and returns to the opener or `finalFocus`. Escape and Close close it unless the save runs.
16
16
  */
17
- export declare function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus, pending, }: FormDialogProps): import("react").JSX.Element;
17
+ export declare function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus, unsaved, pending, }: FormDialogProps): import("react").JSX.Element;
18
18
  export declare function FormDialogForm({ cancelLabel, submit, notice, children, ...form }: FormProps): import("react").JSX.Element;
19
19
  //# sourceMappingURL=form-dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-dialog.d.ts","sourceRoot":"","sources":["../../src/components/form-dialog.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,wBAAwB,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG;IAC/C,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,YAAY,EACZ,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,OAAe,GAChB,EAAE,eAAe,+BAuBjB;AAED,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAsB3F"}
1
+ {"version":3,"file":"form-dialog.d.ts","sourceRoot":"","sources":["../../src/components/form-dialog.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,wBAAwB,CAAC;AAG1E,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG;IAC/C,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,YAAY,EACZ,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,UAAiB,EACjB,OAAO,EACP,OAAe,GAChB,EAAE,eAAe,+BAmBjB;AAED,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAsB3F"}
@@ -4,23 +4,25 @@ import { Button } from "./button.js";
4
4
  import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "./dialog.js";
5
5
  import { WaitingLine } from "./waiting-line.js";
6
6
  import { FormSubmitButton } from "../internal/form-submit.js";
7
+ import { guardUnsaved } from "../internal/unsaved-guard.js";
7
8
  /**
8
- * A new record, or one or two values from a command, in a centred dialog.
9
+ * A new record, or one or two values from a command, in a modal dialog.
9
10
  *
10
11
  * @family Compositions
11
- * @when A person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
12
- * @instead A record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
13
- * @behaviour Centred over a scrim without blur: the title and its help, the fields in a body that scrolls, then the footer with Cancel and the primary at its trailing edge. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them.
14
- * @words The title names the job and its object: "New customer", "Add a mailbox". The primary repeats it: "Create customer", "Add mailbox", never "OK" or "Submit".
15
- * @access A modal dialog named by its title; focus starts in its first field or `initialFocus`, Escape and Close close it unless the save runs, and focus returns to the opener or `finalFocus`.
12
+ * @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal) Ours: a person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
13
+ * @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
14
+ * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close.
15
+ * @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox".
16
+ * @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal) "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal) Ours: a modal dialog with a Close named by `closeLabel`; focus starts in its first field or `initialFocus` and returns to the opener or `finalFocus`. Escape and Close close it unless the save runs.
16
17
  */
17
- export function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus, pending = false, }) {
18
- return (_jsx(Dialog, { open: open, onOpenChange: (next) => {
18
+ export function FormDialog({ open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus = true, unsaved, pending = false, }) {
19
+ const requestOpenChange = guardUnsaved(onOpenChange, unsaved);
20
+ return (_jsx(Dialog, { open: open, onOpenChange: (next, details) => {
19
21
  if (next || !pending)
20
- onOpenChange(next);
21
- }, onOpenChangeComplete: onOpenChangeComplete, children: _jsxs(DialogContent, { className: "sm:max-w-lg", closeLabel: closeLabel, initialFocus: initialFocus, finalFocus: finalFocus, children: [_jsxs(DialogHeader, { className: "pr-8", children: [_jsx(DialogTitle, { children: title }), description ? _jsx(DialogDescription, { children: description }) : null] }), children] }) }));
22
+ requestOpenChange(next, details);
23
+ }, onOpenChangeComplete: onOpenChangeComplete, children: _jsxs(DialogContent, { closeLabel: closeLabel, initialFocus: initialFocus, finalFocus: finalFocus, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title }), description ? _jsx(DialogDescription, { children: description }) : null] }), children] }) }));
22
24
  }
23
25
  export function FormDialogForm({ cancelLabel, submit, notice, children, ...form }) {
24
26
  const pending = submit.pending === true;
25
- return (_jsxs("form", { className: "flex min-h-0 flex-col gap-6", "aria-busy": pending || undefined, "data-slot": "form-dialog-form", ...form, children: [_jsx(DialogBody, { children: children }), notice, _jsxs(DialogFooter, { className: "relative", children: [_jsx(DialogClose, { disabled: pending, render: _jsx(Button, { type: "button", variant: "outline" }), children: cancelLabel }), _jsx(FormSubmitButton, { submit: submit }), pending ? (_jsx(WaitingLine, { className: "absolute inset-x-nadicode-lg bottom-1 w-auto", decorative: true })) : null] })] }));
27
+ return (_jsxs("form", { className: "flex min-h-0 flex-col gap-(--dialog-gap)", "aria-busy": pending || undefined, "data-slot": "form-dialog-form", ...form, children: [_jsx(DialogBody, { children: children }), notice, _jsxs(DialogFooter, { className: "relative", children: [_jsx(DialogClose, { disabled: pending, render: _jsx(Button, { type: "button", variant: "outline" }), children: cancelLabel }), _jsx(FormSubmitButton, { submit: submit }), pending ? (_jsx(WaitingLine, { className: "absolute inset-x-nadicode-sm bottom-1 w-auto", decorative: true })) : null] })] }));
26
28
  }
@@ -1,6 +1,7 @@
1
1
  import type { ComponentProps, ReactNode } from "react";
2
2
  import { SheetContent } from "./sheet.js";
3
3
  import { type FormProps } from "../internal/form-submit.js";
4
+ import { type UnsavedGuard } from "../internal/unsaved-guard.js";
4
5
  export type { FormProps, FormSubmit } from "../internal/form-submit.js";
5
6
  /** What a form surface is told by its caller, whether it draws a drawer or a dialog. */
6
7
  export type FormSurfaceProps = {
@@ -19,6 +20,8 @@ export type FormSurfaceProps = {
19
20
  initialFocus?: ComponentProps<typeof SheetContent>["initialFocus"];
20
21
  /** Where focus returns when the drawer closes, when its opener is gone. */
21
22
  finalFocus?: ComponentProps<typeof SheetContent>["finalFocus"];
23
+ /** Typed input that Escape would lose: while `dirty` it is held back and `onDismissBlocked` runs. */
24
+ unsaved?: UnsavedGuard;
22
25
  };
23
26
  /**
24
27
  * Why this is a drawer and not a dialog: "catalog" chooses from a list too long
@@ -34,14 +37,14 @@ export type FormDrawerProps = FormSurfaceProps & ({
34
37
  progress: string;
35
38
  });
36
39
  /**
37
- * The right-side drawer for a catalogue or a setup in steps, at one width.
40
+ * The right-side sheet for a catalogue or a setup in steps, at one width.
38
41
  *
39
42
  * @family Compositions
40
- * @when Choosing from a catalogue too long for a dialog (through `CatalogDrawer`), or setting something up in several steps with a wait: connect a messaging channel, Telegram's code.
41
- * @instead A new record from a few fields is a `FormDialog`; a record already in a list edits in its row with `RowEditForm`; a fact on the record's own page changes in place in its section; a consequence is confirmed in a `ConfirmDialog`.
42
- * @behaviour Opens from the right edge at one width, 560 px (the full width on a compact screen), with the page still behind it; 12 px corners on the edges not flush with the window. The header holds the step ("Step 2 of 3") over the title, the description and Close; the body scrolls between the header and a recessed footer that stays, Cancel then the primary at its trailing edge. Cancel holds while a save runs.
43
- * @words The title names the job and its object: "Connect Telegram", "Add a skill". The step reads "Step N of M". The primary says what it does: "Connect", "Continue", never "OK".
44
- * @access A modal dialog named by its title; focus moves inside on open and returns to the opener on close, or to `finalFocus` when the opener is gone. Escape and Close close it; the step is read before the title.
43
+ * @when Ours: choosing from a catalogue too long for a dialog (through `CatalogDrawer`), or setting something up in several steps with a wait: connect a messaging channel, Telegram's code.
44
+ * @instead "Don’t use Sheet to confirm destructive actions. The default `modal=false` keeps the page interactive, which weakens severity for a delete or revoke." (https://vercel.com/geist/sheet) Ours: a new record from a few fields is a `FormDialog`; a record already in a list edits in its row with `RowEditForm`; a fact on the record's own page changes in place in its section; a consequence is confirmed in a `ConfirmDialog`; a phone's short job is a `Drawer`.
45
+ * @behaviour "Sheet defaults to `modal=false` so toasts and other high-z elements stay reachable. Keep that default unless the sheet owns the screen." (https://vercel.com/geist/sheet) "Pick `side` from the trigger location: a row inspector slides from `right`, a global filter from `left`. Don’t change sides mid-session." (https://vercel.com/geist/sheet) "Outside-click does not auto-close, so always render an explicit close affordance and honor Escape." (https://vercel.com/geist/sheet) Ours: a modal `Sheet` from the right edge over the scrim, because the drawer owns the screen, at the Sheet's one width that no caller sets. The header holds the step ("Step 2 of 3") over the title, the description and Close; the body scrolls between the header and a footer that stays, with no fill or rule of its own, Cancel then the primary at its trailing edge. A press outside does not close it; Escape does, unless `unsaved.dirty` holds it back. Cancel holds while a save runs.
46
+ * @words "Title is Title Case and names the entity (`Deployment Details`, `Member Profile`), not the page action." (https://vercel.com/geist/sheet) "Body is read-mostly: sentence case prose with Title Case sub-headings. Action buttons are optional; when present, follow `Verb + Noun`." (https://vercel.com/geist/sheet) Ours: the title is sentence case and names the job and its object: "Connect Telegram", "Add a skill". The step reads "Step N of M". The primary says what it does: "Connect", "Continue", never "OK".
47
+ * @access "Trap focus inside the sheet while it’s open and return focus to the trigger row on close so keyboard users keep their place in the list." (https://vercel.com/geist/sheet) "Provide a visible close button labeled `Close` (or an icon button with `aria-label="Close"`) since clicking outside doesn’t dismiss." (https://vercel.com/geist/sheet) "Announce the sheet with `aria-labelledby` pointing at the title; pair it with `aria-describedby` only when the body is short and load-bearing." (https://vercel.com/geist/sheet) Ours: a modal dialog named by its title; focus returns to the opener on close, or to `finalFocus` when the opener is gone. The step is read before the title.
45
48
  */
46
49
  export declare function FormDrawer(props: FormDrawerProps): import("react").JSX.Element;
47
50
  /** The part of the drawer that scrolls between its title and its footer. */
@@ -55,7 +58,7 @@ export type FormDrawerFooterProps = {
55
58
  /** The step's own actions, the primary last so it sits rightmost. */
56
59
  children?: ReactNode;
57
60
  };
58
- /** The footer that stays in place under the body: Cancel, then the actions, right-aligned. */
61
+ /** The footer that stays in place under the body, on the sheet's own surface: Cancel, then the actions, at the trailing edge. */
59
62
  export declare function FormDrawerFooter({ cancel, children }: FormDrawerFooterProps): import("react").JSX.Element;
60
63
  /**
61
64
  * The drawer's form: the fields in the body, a notice where the save button
@@ -1 +1 @@
1
- {"version":3,"file":"form-drawer.d.ts","sourceRoot":"","sources":["../../src/components/form-drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,OAAO,EAGL,YAAY,EAKb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,wBAAwB,CAAC;AAG1E,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpE,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,6FAA6F;IAC7F,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,wGAAwG;IACxG,QAAQ,EAAE,SAAS,CAAC;IACpB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,cAAc,CAAC,CAAC;IACnE,2EAA2E;IAC3E,UAAU,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC;CAChE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAC5C,CACI;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IACE,GAAG,EAAE,OAAO,CAAC;IACb,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AAEJ;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BAqChD;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,KAAK,CAAC,+BAW5E;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,+DAA+D;IAC/D,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,qEAAqE;IACrE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,qBAAqB,+BAc3E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAqB3F"}
1
+ {"version":3,"file":"form-drawer.d.ts","sourceRoot":"","sources":["../../src/components/form-drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,OAAO,EAGL,YAAY,EAKb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG3E,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpE,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,6FAA6F;IAC7F,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,wGAAwG;IACxG,QAAQ,EAAE,SAAS,CAAC;IACpB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,cAAc,CAAC,CAAC;IACnE,2EAA2E;IAC3E,UAAU,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC;IAC/D,qGAAqG;IACrG,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAC5C,CACI;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IACE,GAAG,EAAE,OAAO,CAAC;IACb,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AAEJ;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BA0ChD;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,KAAK,CAAC,+BAW5E;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,+DAA+D;IAC/D,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,qEAAqE;IACrE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,iIAAiI;AACjI,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,qBAAqB,+BAW3E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAqB3F"}
@@ -4,28 +4,29 @@ import { Button } from "./button.js";
4
4
  import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "./sheet.js";
5
5
  import { WaitingLine } from "./waiting-line.js";
6
6
  import { FormSubmitButton } from "../internal/form-submit.js";
7
+ import { guardUnsaved } from "../internal/unsaved-guard.js";
7
8
  import { cn } from "../lib/utils.js";
8
9
  /**
9
- * The right-side drawer for a catalogue or a setup in steps, at one width.
10
+ * The right-side sheet for a catalogue or a setup in steps, at one width.
10
11
  *
11
12
  * @family Compositions
12
- * @when Choosing from a catalogue too long for a dialog (through `CatalogDrawer`), or setting something up in several steps with a wait: connect a messaging channel, Telegram's code.
13
- * @instead A new record from a few fields is a `FormDialog`; a record already in a list edits in its row with `RowEditForm`; a fact on the record's own page changes in place in its section; a consequence is confirmed in a `ConfirmDialog`.
14
- * @behaviour Opens from the right edge at one width, 560 px (the full width on a compact screen), with the page still behind it; 12 px corners on the edges not flush with the window. The header holds the step ("Step 2 of 3") over the title, the description and Close; the body scrolls between the header and a recessed footer that stays, Cancel then the primary at its trailing edge. Cancel holds while a save runs.
15
- * @words The title names the job and its object: "Connect Telegram", "Add a skill". The step reads "Step N of M". The primary says what it does: "Connect", "Continue", never "OK".
16
- * @access A modal dialog named by its title; focus moves inside on open and returns to the opener on close, or to `finalFocus` when the opener is gone. Escape and Close close it; the step is read before the title.
13
+ * @when Ours: choosing from a catalogue too long for a dialog (through `CatalogDrawer`), or setting something up in several steps with a wait: connect a messaging channel, Telegram's code.
14
+ * @instead "Don’t use Sheet to confirm destructive actions. The default `modal=false` keeps the page interactive, which weakens severity for a delete or revoke." (https://vercel.com/geist/sheet) Ours: a new record from a few fields is a `FormDialog`; a record already in a list edits in its row with `RowEditForm`; a fact on the record's own page changes in place in its section; a consequence is confirmed in a `ConfirmDialog`; a phone's short job is a `Drawer`.
15
+ * @behaviour "Sheet defaults to `modal=false` so toasts and other high-z elements stay reachable. Keep that default unless the sheet owns the screen." (https://vercel.com/geist/sheet) "Pick `side` from the trigger location: a row inspector slides from `right`, a global filter from `left`. Don’t change sides mid-session." (https://vercel.com/geist/sheet) "Outside-click does not auto-close, so always render an explicit close affordance and honor Escape." (https://vercel.com/geist/sheet) Ours: a modal `Sheet` from the right edge over the scrim, because the drawer owns the screen, at the Sheet's one width that no caller sets. The header holds the step ("Step 2 of 3") over the title, the description and Close; the body scrolls between the header and a footer that stays, with no fill or rule of its own, Cancel then the primary at its trailing edge. A press outside does not close it; Escape does, unless `unsaved.dirty` holds it back. Cancel holds while a save runs.
16
+ * @words "Title is Title Case and names the entity (`Deployment Details`, `Member Profile`), not the page action." (https://vercel.com/geist/sheet) "Body is read-mostly: sentence case prose with Title Case sub-headings. Action buttons are optional; when present, follow `Verb + Noun`." (https://vercel.com/geist/sheet) Ours: the title is sentence case and names the job and its object: "Connect Telegram", "Add a skill". The step reads "Step N of M". The primary says what it does: "Connect", "Continue", never "OK".
17
+ * @access "Trap focus inside the sheet while it’s open and return focus to the trigger row on close so keyboard users keep their place in the list." (https://vercel.com/geist/sheet) "Provide a visible close button labeled `Close` (or an icon button with `aria-label="Close"`) since clicking outside doesn’t dismiss." (https://vercel.com/geist/sheet) "Announce the sheet with `aria-labelledby` pointing at the title; pair it with `aria-describedby` only when the body is short and load-bearing." (https://vercel.com/geist/sheet) Ours: a modal dialog named by its title; focus returns to the opener on close, or to `finalFocus` when the opener is gone. The step is read before the title.
17
18
  */
18
19
  export function FormDrawer(props) {
19
- const { open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus, } = props;
20
- return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, onOpenChangeComplete: onOpenChangeComplete, children: _jsxs(SheetContent, { className: "max-sm:data-[side=right]:left-nadicode-sm max-sm:data-[side=right]:w-auto data-[side=right]:sm:w-[560px] data-[side=right]:sm:max-w-[calc(100%-var(--nc-lg))]", closeLabel: closeLabel, finalFocus: finalFocus, initialFocus: initialFocus, side: "right", children: [_jsxs(SheetHeader, { className: "pr-12", children: [props.job === "steps" ? (_jsx("p", { className: "font-label-mono text-label-mono text-muted-foreground", "data-slot": "form-drawer-progress", children: props.progress })) : null, _jsx(SheetTitle, { className: "break-words", children: title }), description ? _jsx(SheetDescription, { children: description }) : null] }), children] }) }));
20
+ const { open, onOpenChange, onOpenChangeComplete, title, description, closeLabel, children, initialFocus, finalFocus = true, unsaved, } = props;
21
+ return (_jsx(Sheet, { modal: true, open: open, onOpenChange: guardUnsaved(onOpenChange, unsaved), onOpenChangeComplete: onOpenChangeComplete, children: _jsxs(SheetContent, { closeLabel: closeLabel, finalFocus: finalFocus, initialFocus: initialFocus, side: "right", children: [_jsxs(SheetHeader, { className: "pr-12", children: [props.job === "steps" ? (_jsx("p", { className: "font-label-mono text-label-mono text-muted-foreground", "data-slot": "form-drawer-progress", children: props.progress })) : null, _jsx(SheetTitle, { className: "break-words", children: title }), description ? _jsx(SheetDescription, { children: description }) : null] }), children] }) }));
21
22
  }
22
23
  /** The part of the drawer that scrolls between its title and its footer. */
23
24
  export function FormDrawerBody({ className, ...props }) {
24
25
  return (_jsx("div", { "data-slot": "form-drawer-body", className: cn("grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)] content-start gap-4 overflow-y-auto px-nadicode-lg", className), ...props }));
25
26
  }
26
- /** The footer that stays in place under the body: Cancel, then the actions, right-aligned. */
27
+ /** The footer that stays in place under the body, on the sheet's own surface: Cancel, then the actions, at the trailing edge. */
27
28
  export function FormDrawerFooter({ cancel, children }) {
28
- return (_jsxs(SheetFooter, { className: "flex-row flex-wrap items-center justify-end", "data-slot": "form-drawer-footer", children: [cancel ? (_jsx(SheetClose, { disabled: cancel.disabled, render: _jsx(Button, { type: "button", variant: "outline" }), children: cancel.label })) : null, children] }));
29
+ return (_jsxs(SheetFooter, { className: "flex-wrap items-center", "data-slot": "form-drawer-footer", children: [cancel ? (_jsx(SheetClose, { disabled: cancel.disabled, render: _jsx(Button, { type: "button", variant: "outline" }), children: cancel.label })) : null, children] }));
29
30
  }
30
31
  /**
31
32
  * The drawer's form: the fields in the body, a notice where the save button
@@ -0,0 +1,64 @@
1
+ import type { ReactElement } from "react";
2
+ import { Meter } from "@base-ui/react/meter";
3
+ import type { ProgressTone } from "./progress.js";
4
+ type GaugeSize = "xs" | "sm" | "md" | "lg";
5
+ type GaugeValueSize = Exclude<GaugeSize, "xs">;
6
+ type GaugeName = {
7
+ "aria-label": string;
8
+ "aria-labelledby"?: never;
9
+ } | {
10
+ "aria-labelledby": string;
11
+ "aria-label"?: never;
12
+ };
13
+ type GaugeFace = {
14
+ size?: GaugeValueSize;
15
+ showValue: true;
16
+ children?: never;
17
+ } | {
18
+ size?: GaugeSize;
19
+ showValue?: false;
20
+ children?: ReactElement;
21
+ };
22
+ type GaugeProps = Omit<Meter.Root.Props, "value" | "min" | "max" | "children" | "aria-label" | "aria-labelledby"> & {
23
+ /** The ratio, 0 to 100; a value outside it is drawn at the nearest end. */
24
+ value: number;
25
+ tone?: ProgressTone;
26
+ } & GaugeName & GaugeFace;
27
+ /**
28
+ * A ring that shows one ratio out of 100.
29
+ *
30
+ * @family Data
31
+ * @when "A 0–100 ratio against a fixed maximum where the comparison is the point, like quota usage, build cache hit rate, uptime, or billing-period consumption." (https://vercel.com/geist/gauge)
32
+ * Ours: `size` follows the weight of the figure beside it.
33
+ * @instead "For determinate task progress with a known total (uploads, multi-step setup), use `Progress`." (https://vercel.com/geist/gauge)
34
+ * "For binary or enumerated state, use `Status Dot` for deployments or `Badge` for everything else." (https://vercel.com/geist/gauge)
35
+ * Ours: those are `StatusDot` and `StatusBadge`. A single figure on its own is a `KpiCard`. A wait
36
+ * of unknown length is the waiting line; the gauge has no indeterminate form. Two shares of one
37
+ * whole are a chart.
38
+ * @behaviour "Use `arc="equal"` for true ratios so 50% reads as exactly half." (https://vercel.com/geist/gauge)
39
+ * "Use the default `primary` arc for single-percentage usage where the filled portion is the story." (https://vercel.com/geist/gauge)
40
+ * "When using the gauge to display a ratio, use the `equal` arc priority to make both arcs are equally sized." (https://vercel.com/geist/gauge)
41
+ * Ours: there is no `arc` prop; the gauge always draws the primary arc, from the top, clockwise,
42
+ * with round ends and a small gap before the neutral track; at 0 or 100 there is no gap. Colour
43
+ * sits on the arc alone: the track stays the neutral line colour, and the number and icon stay
44
+ * neutral.
45
+ * "Threshold colors should match the same numeric breakpoints used elsewhere in the product (`>=80%` warning, `>=95%` error). Don’t invent gauge-only thresholds." (https://vercel.com/geist/gauge)
46
+ * Ours: `tone` is that threshold, never derived from the value.
47
+ * "Pair `indeterminate` with explanatory copy nearby (`Calculating usage…`) so the user knows the value is loading, not zero." (https://vercel.com/geist/gauge)
48
+ * Ours: there is no `indeterminate`; a value still loading is the waiting line. The smallest size
49
+ * has room only for an icon. The arc moves on `open`, still under reduced motion.
50
+ * @words "Always pair the gauge with an adjacent label or `Tooltip` naming what the number represents (`Build Cache Hit Rate`). The gauge alone is not self-describing." (https://vercel.com/geist/gauge)
51
+ * "Don’t put units inside `children`; the label carries the unit (`Uptime · 99.97%`). `children` is reserved for an icon overlay." (https://vercel.com/geist/gauge)
52
+ * "When `showValue` is on, the rendered number is the value only. Never inject a `%` or unit string into the prop." (https://vercel.com/geist/gauge)
53
+ * Ours: sentence case, *Cache hit rate · 99.97%*. `showValue` prints the number; `children` is only
54
+ * an icon.
55
+ * @access "The component sets `role="progressbar"` with `aria-valuemin`, `aria-valuemax`, and `aria-valuenow`. Don’t override those." (https://vercel.com/geist/gauge)
56
+ * Ours: the role is `meter`, with the same three values.
57
+ * "The adjacent label is the gauge’s accessible name. Tie it with `aria-labelledby` on the gauge wrapper so screen readers read “Uptime, 99 percent.”" (https://vercel.com/geist/gauge)
58
+ * Ours: it always has a name, `aria-label` or `aria-labelledby` pointing at the adjacent label, and
59
+ * the type asks for one.
60
+ * "Don’t use color to encode the threshold without redundant text; pair the warning tint with copy below or in the Tooltip." (https://vercel.com/geist/gauge)
61
+ */
62
+ declare function Gauge({ className, value, tone, size, showValue, children, ...props }: GaugeProps): import("react").JSX.Element;
63
+ export { Gauge };
64
+ //# sourceMappingURL=gauge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gauge.d.ts","sourceRoot":"","sources":["../../src/components/gauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,KAAK,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3C,KAAK,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAkC/C,KAAK,SAAS,GACV;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,KAAK,CAAA;CAAE,GACnD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAExD,KAAK,SAAS,GACV;IAAE,IAAI,CAAC,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5D;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC;AAErE,KAAK,UAAU,GAAG,IAAI,CACpB,KAAK,CAAC,IAAI,CAAC,KAAK,EAChB,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,iBAAiB,CACxE,GAAG;IACF,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,GAAG,SAAS,GACX,SAAS,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,KAAK,EACL,IAAgB,EAChB,IAAW,EACX,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,UAAU,+BAuEZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,73 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Meter } from "@base-ui/react/meter";
4
+ import { cn } from "../lib/utils.js";
5
+ const GAUGE_BOX_CLASS = {
6
+ xs: "size-5",
7
+ sm: "size-8",
8
+ md: "size-16",
9
+ lg: "size-32",
10
+ };
11
+ const GAUGE_VALUE_CLASS = {
12
+ sm: "text-[11px] leading-5 font-medium",
13
+ md: "nc-type-label-lg font-medium",
14
+ lg: "text-[32px] leading-5 font-semibold",
15
+ };
16
+ const GAUGE_ARC_CLASS = {
17
+ default: "stroke-primary",
18
+ secondary: "stroke-muted-foreground",
19
+ success: "stroke-(--nc-state-complete)",
20
+ warning: "stroke-(--nc-state-review)",
21
+ critical: "stroke-(--nc-state-blocked)",
22
+ info: "stroke-info",
23
+ };
24
+ const GAUGE_RING = {
25
+ xs: { radius: 42.5, strokeWidth: 15, gap: 9 },
26
+ sm: { radius: 45, strokeWidth: 10, gap: 6 },
27
+ md: { radius: 45, strokeWidth: 10, gap: 5 },
28
+ lg: { radius: 45, strokeWidth: 10, gap: 5 },
29
+ };
30
+ const GAUGE_ARC_MOTION = "transition-[stroke-dasharray,stroke-dashoffset,stroke] duration-[var(--nc-duration-open)] ease-[var(--nc-ease-out-strong)] motion-reduce:transition-none";
31
+ /**
32
+ * A ring that shows one ratio out of 100.
33
+ *
34
+ * @family Data
35
+ * @when "A 0–100 ratio against a fixed maximum where the comparison is the point, like quota usage, build cache hit rate, uptime, or billing-period consumption." (https://vercel.com/geist/gauge)
36
+ * Ours: `size` follows the weight of the figure beside it.
37
+ * @instead "For determinate task progress with a known total (uploads, multi-step setup), use `Progress`." (https://vercel.com/geist/gauge)
38
+ * "For binary or enumerated state, use `Status Dot` for deployments or `Badge` for everything else." (https://vercel.com/geist/gauge)
39
+ * Ours: those are `StatusDot` and `StatusBadge`. A single figure on its own is a `KpiCard`. A wait
40
+ * of unknown length is the waiting line; the gauge has no indeterminate form. Two shares of one
41
+ * whole are a chart.
42
+ * @behaviour "Use `arc="equal"` for true ratios so 50% reads as exactly half." (https://vercel.com/geist/gauge)
43
+ * "Use the default `primary` arc for single-percentage usage where the filled portion is the story." (https://vercel.com/geist/gauge)
44
+ * "When using the gauge to display a ratio, use the `equal` arc priority to make both arcs are equally sized." (https://vercel.com/geist/gauge)
45
+ * Ours: there is no `arc` prop; the gauge always draws the primary arc, from the top, clockwise,
46
+ * with round ends and a small gap before the neutral track; at 0 or 100 there is no gap. Colour
47
+ * sits on the arc alone: the track stays the neutral line colour, and the number and icon stay
48
+ * neutral.
49
+ * "Threshold colors should match the same numeric breakpoints used elsewhere in the product (`>=80%` warning, `>=95%` error). Don’t invent gauge-only thresholds." (https://vercel.com/geist/gauge)
50
+ * Ours: `tone` is that threshold, never derived from the value.
51
+ * "Pair `indeterminate` with explanatory copy nearby (`Calculating usage…`) so the user knows the value is loading, not zero." (https://vercel.com/geist/gauge)
52
+ * Ours: there is no `indeterminate`; a value still loading is the waiting line. The smallest size
53
+ * has room only for an icon. The arc moves on `open`, still under reduced motion.
54
+ * @words "Always pair the gauge with an adjacent label or `Tooltip` naming what the number represents (`Build Cache Hit Rate`). The gauge alone is not self-describing." (https://vercel.com/geist/gauge)
55
+ * "Don’t put units inside `children`; the label carries the unit (`Uptime · 99.97%`). `children` is reserved for an icon overlay." (https://vercel.com/geist/gauge)
56
+ * "When `showValue` is on, the rendered number is the value only. Never inject a `%` or unit string into the prop." (https://vercel.com/geist/gauge)
57
+ * Ours: sentence case, *Cache hit rate · 99.97%*. `showValue` prints the number; `children` is only
58
+ * an icon.
59
+ * @access "The component sets `role="progressbar"` with `aria-valuemin`, `aria-valuemax`, and `aria-valuenow`. Don’t override those." (https://vercel.com/geist/gauge)
60
+ * Ours: the role is `meter`, with the same three values.
61
+ * "The adjacent label is the gauge’s accessible name. Tie it with `aria-labelledby` on the gauge wrapper so screen readers read “Uptime, 99 percent.”" (https://vercel.com/geist/gauge)
62
+ * Ours: it always has a name, `aria-label` or `aria-labelledby` pointing at the adjacent label, and
63
+ * the type asks for one.
64
+ * "Don’t use color to encode the threshold without redundant text; pair the warning tint with copy below or in the Tooltip." (https://vercel.com/geist/gauge)
65
+ */
66
+ function Gauge({ className, value, tone = "default", size = "md", showValue, children, ...props }) {
67
+ const ratio = Math.min(100, Math.max(0, value));
68
+ const { radius, strokeWidth, gap } = GAUGE_RING[size];
69
+ const gapLength = ratio === 0 || ratio === 100 ? 0 : gap;
70
+ const trackLength = Math.max(0, 100 - ratio - 2 * gapLength);
71
+ return (_jsxs(Meter.Root, { className: cn("relative inline-flex shrink-0 items-center justify-center", GAUGE_BOX_CLASS[size], className), "data-size": size, "data-slot": "gauge", "data-tone": tone, max: 100, min: 0, value: ratio, ...props, children: [_jsxs("svg", { "aria-hidden": "true", className: "absolute inset-0 size-full -rotate-90", fill: "none", viewBox: "0 0 100 100", children: [_jsx("circle", { className: cn("stroke-border", GAUGE_ARC_MOTION), cx: "50", cy: "50", "data-slot": "gauge-track", opacity: trackLength === 0 ? 0 : 1, pathLength: 100, r: radius, strokeDasharray: `${trackLength} 100`, strokeDashoffset: -(ratio + gapLength), strokeLinecap: "round", strokeWidth: strokeWidth }), _jsx("circle", { className: cn(GAUGE_ARC_CLASS[tone], GAUGE_ARC_MOTION), cx: "50", cy: "50", "data-slot": "gauge-arc", opacity: ratio === 0 ? 0 : 1, pathLength: 100, r: radius, strokeDasharray: `${ratio} 100`, strokeLinecap: "round", strokeWidth: strokeWidth })] }), showValue && size !== "xs" ? (_jsx("span", { className: cn("relative tabular-nums", GAUGE_VALUE_CLASS[size]), "data-slot": "gauge-value", children: Math.round(ratio) })) : null, children ? (_jsx("span", { className: "absolute inset-0 flex items-center justify-center text-muted-foreground [&>svg]:size-1/2", "data-slot": "gauge-icon", children: children })) : null] }));
72
+ }
73
+ export { Gauge };