tembro 2.0.5 → 2.1.0

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 (381) hide show
  1. package/dist/components/calendar/calendar.cjs +1 -1
  2. package/dist/components/calendar/calendar.d.ts +2 -1
  3. package/dist/components/calendar/calendar.js +126 -122
  4. package/dist/components/calendar/date-range-picker.cjs +1 -1
  5. package/dist/components/calendar/date-range-picker.d.ts +2 -1
  6. package/dist/components/calendar/date-range-picker.js +39 -39
  7. package/dist/components/charts/charts.cjs +1 -1
  8. package/dist/components/charts/charts.d.ts +13 -4
  9. package/dist/components/charts/charts.js +76 -46
  10. package/dist/components/charts/progress-ring.cjs +1 -1
  11. package/dist/components/charts/progress-ring.d.ts +3 -1
  12. package/dist/components/charts/progress-ring.js +11 -10
  13. package/dist/components/data-table/data-table-column-visibility-menu.cjs +1 -1
  14. package/dist/components/data-table/data-table-column-visibility-menu.d.ts +4 -1
  15. package/dist/components/data-table/data-table-column-visibility-menu.js +36 -8
  16. package/dist/components/data-table/data-table-pagination.cjs +1 -1
  17. package/dist/components/data-table/data-table-pagination.js +4 -4
  18. package/dist/components/data-table/data-table-toolbar.cjs +1 -1
  19. package/dist/components/data-table/data-table-toolbar.js +12 -13
  20. package/dist/components/data-table/data-table.cjs +1 -1
  21. package/dist/components/data-table/data-table.d.ts +2 -2
  22. package/dist/components/data-table/data-table.js +2 -1
  23. package/dist/components/display/carousel.cjs +1 -1
  24. package/dist/components/display/carousel.d.ts +15 -1
  25. package/dist/components/display/carousel.js +128 -86
  26. package/dist/components/display/code-block.cjs +2 -2
  27. package/dist/components/display/code-block.d.ts +2 -1
  28. package/dist/components/display/code-block.js +17 -12
  29. package/dist/components/display/delta-badge.cjs +1 -1
  30. package/dist/components/display/delta-badge.d.ts +2 -1
  31. package/dist/components/display/delta-badge.js +11 -7
  32. package/dist/components/display/kanban.cjs +1 -1
  33. package/dist/components/display/kanban.d.ts +4 -1
  34. package/dist/components/display/kanban.js +60 -33
  35. package/dist/components/display/metric-grid.cjs +1 -1
  36. package/dist/components/display/metric-grid.d.ts +1 -0
  37. package/dist/components/display/metric-grid.js +1 -1
  38. package/dist/components/display/qr-code.cjs +1 -1
  39. package/dist/components/display/qr-code.d.ts +2 -1
  40. package/dist/components/display/qr-code.js +19 -16
  41. package/dist/components/display/smart-card.d.ts +1 -1
  42. package/dist/components/display/status-legend.d.ts +1 -1
  43. package/dist/components/display/tag.cjs +1 -1
  44. package/dist/components/display/tag.d.ts +2 -1
  45. package/dist/components/display/tag.js +28 -22
  46. package/dist/components/display/tree-view.cjs +1 -1
  47. package/dist/components/display/tree-view.d.ts +9 -1
  48. package/dist/components/display/tree-view.js +104 -40
  49. package/dist/components/display/trend-card.cjs +1 -1
  50. package/dist/components/display/trend-card.js +27 -41
  51. package/dist/components/feedback/alert.cjs +1 -1
  52. package/dist/components/feedback/alert.d.ts +2 -1
  53. package/dist/components/feedback/alert.js +6 -6
  54. package/dist/components/feedback/loading-state.cjs +1 -1
  55. package/dist/components/feedback/loading-state.d.ts +3 -1
  56. package/dist/components/feedback/loading-state.js +23 -10
  57. package/dist/components/feedback/page-state.cjs +1 -1
  58. package/dist/components/feedback/page-state.d.ts +2 -1
  59. package/dist/components/feedback/page-state.js +7 -4
  60. package/dist/components/form/form-field-shell.cjs +1 -1
  61. package/dist/components/form/form-field-shell.d.ts +4 -2
  62. package/dist/components/form/form-field-shell.js +57 -41
  63. package/dist/components/form/form-input.cjs +1 -1
  64. package/dist/components/form/form-input.d.ts +3 -4
  65. package/dist/components/form/form-input.js +259 -257
  66. package/dist/components/form/form-select.cjs +1 -1
  67. package/dist/components/form/form-select.d.ts +2 -2
  68. package/dist/components/form/form-select.js +8 -6
  69. package/dist/components/form/form-switch.cjs +1 -1
  70. package/dist/components/form/form-switch.d.ts +1 -1
  71. package/dist/components/form/form-switch.js +58 -54
  72. package/dist/components/form/form-textarea.cjs +1 -1
  73. package/dist/components/form/form-textarea.d.ts +1 -1
  74. package/dist/components/form/form-textarea.js +29 -27
  75. package/dist/components/inputs/async-select.d.ts +3 -0
  76. package/dist/components/inputs/search-input.d.ts +3 -0
  77. package/dist/components/inputs/simple-select.cjs +1 -1
  78. package/dist/components/inputs/simple-select.d.ts +10 -32
  79. package/dist/components/inputs/simple-select.js +5 -101
  80. package/dist/components/layout/app-sidebar.cjs +1 -1
  81. package/dist/components/layout/app-sidebar.d.ts +1 -0
  82. package/dist/components/layout/app-sidebar.js +36 -36
  83. package/dist/components/layout/breadcrumbs.cjs +1 -1
  84. package/dist/components/layout/breadcrumbs.d.ts +2 -1
  85. package/dist/components/layout/breadcrumbs.js +7 -7
  86. package/dist/components/modern/calendar-scheduler.cjs +1 -1
  87. package/dist/components/modern/calendar-scheduler.d.ts +5 -1
  88. package/dist/components/modern/calendar-scheduler.js +47 -28
  89. package/dist/components/modern/dual-list-picker.cjs +1 -1
  90. package/dist/components/modern/dual-list-picker.d.ts +5 -1
  91. package/dist/components/modern/dual-list-picker.js +81 -23
  92. package/dist/components/modern/rich-text-editor.cjs +1 -1
  93. package/dist/components/modern/rich-text-editor.d.ts +3 -1
  94. package/dist/components/modern/rich-text-editor.js +12 -9
  95. package/dist/components/modern/tour.cjs +1 -1
  96. package/dist/components/modern/tour.d.ts +5 -1
  97. package/dist/components/modern/tour.js +57 -35
  98. package/dist/components/navigation/command-bar.cjs +1 -1
  99. package/dist/components/navigation/command-bar.d.ts +3 -1
  100. package/dist/components/navigation/command-bar.js +10 -7
  101. package/dist/components/navigation/demo.cjs +1 -1
  102. package/dist/components/navigation/demo.js +0 -1
  103. package/dist/components/navigation/nav-tabs.cjs +1 -1
  104. package/dist/components/navigation/nav-tabs.js +39 -27
  105. package/dist/components/navigation/page-tabs.cjs +1 -1
  106. package/dist/components/navigation/page-tabs.js +41 -30
  107. package/dist/components/navigation/pagination.cjs +1 -1
  108. package/dist/components/navigation/pagination.d.ts +7 -1
  109. package/dist/components/navigation/pagination.js +48 -25
  110. package/dist/components/notifications/notification-center.cjs +1 -1
  111. package/dist/components/notifications/notification-center.d.ts +3 -1
  112. package/dist/components/notifications/notification-center.js +56 -38
  113. package/dist/components/notifications/toast.cjs +1 -1
  114. package/dist/components/notifications/toast.d.ts +1 -0
  115. package/dist/components/notifications/toast.js +4 -0
  116. package/dist/components/overlay/alert-dialog.cjs +1 -1
  117. package/dist/components/overlay/alert-dialog.js +1 -1
  118. package/dist/components/overlay/confirm-dialog.cjs +1 -1
  119. package/dist/components/overlay/confirm-dialog.d.ts +4 -2
  120. package/dist/components/overlay/confirm-dialog.js +31 -22
  121. package/dist/components/overlay/drawer.cjs +1 -1
  122. package/dist/components/overlay/drawer.d.ts +3 -1
  123. package/dist/components/overlay/drawer.js +24 -16
  124. package/dist/components/ui/accordion/index.d.ts +4 -0
  125. package/dist/components/ui/badge/index.cjs +1 -1
  126. package/dist/components/ui/badge/index.d.ts +1 -1
  127. package/dist/components/ui/badge/index.js +2 -1
  128. package/dist/components/ui/button/index.cjs +1 -1
  129. package/dist/components/ui/button/index.d.ts +2 -1
  130. package/dist/components/ui/button/index.js +13 -10
  131. package/dist/components/ui/card/index.cjs +1 -1
  132. package/dist/components/ui/card/index.d.ts +13 -2
  133. package/dist/components/ui/card/index.js +74 -49
  134. package/dist/components/ui/dialog/index.cjs +1 -1
  135. package/dist/components/ui/dialog/index.js +2 -1
  136. package/dist/components/ui/hover-card.cjs +1 -1
  137. package/dist/components/ui/hover-card.d.ts +11 -3
  138. package/dist/components/ui/hover-card.js +29 -24
  139. package/dist/components/ui/input/index.cjs +1 -1
  140. package/dist/components/ui/input/index.d.ts +9 -1
  141. package/dist/components/ui/input/index.js +63 -30
  142. package/dist/components/ui/popover/index.cjs +1 -1
  143. package/dist/components/ui/popover/index.d.ts +2 -2
  144. package/dist/components/ui/popover/index.js +6 -5
  145. package/dist/components/ui/radio-group/index.cjs +1 -1
  146. package/dist/components/ui/radio-group/index.d.ts +5 -1
  147. package/dist/components/ui/radio-group/index.js +50 -16
  148. package/dist/components/ui/right-click-menu/index.cjs +1 -1
  149. package/dist/components/ui/right-click-menu/index.d.ts +5 -1
  150. package/dist/components/ui/right-click-menu/index.js +77 -23
  151. package/dist/components/ui/segmented-control/index.cjs +1 -1
  152. package/dist/components/ui/segmented-control/index.d.ts +2 -1
  153. package/dist/components/ui/segmented-control/index.js +23 -11
  154. package/dist/components/ui/select/index.cjs +1 -1
  155. package/dist/components/ui/select/index.d.ts +40 -1
  156. package/dist/components/ui/select/index.js +159 -48
  157. package/dist/components/ui/switch/index.cjs +1 -1
  158. package/dist/components/ui/switch/index.d.ts +18 -0
  159. package/dist/components/ui/switch/index.js +47 -17
  160. package/dist/components/ui/tabs/index.cjs +1 -1
  161. package/dist/components/ui/tabs/index.d.ts +14 -4
  162. package/dist/components/ui/tabs/index.js +11 -8
  163. package/dist/components/ui/textarea/index.cjs +1 -1
  164. package/dist/components/ui/textarea/index.d.ts +10 -2
  165. package/dist/components/ui/textarea/index.js +37 -8
  166. package/dist/components/ui/textarea.cjs +1 -0
  167. package/dist/components/ui/textarea.d.ts +1 -0
  168. package/dist/components/ui/textarea.js +2 -0
  169. package/dist/components/ui/tooltip/index.cjs +1 -1
  170. package/dist/components/ui/tooltip/index.d.ts +11 -3
  171. package/dist/components/ui/tooltip/index.js +41 -20
  172. package/dist/components/upload/file-upload.cjs +1 -1
  173. package/dist/components/upload/file-upload.d.ts +8 -1
  174. package/dist/components/upload/file-upload.js +132 -100
  175. package/dist/components/upload/image-upload.cjs +1 -1
  176. package/dist/components/upload/image-upload.d.ts +5 -1
  177. package/dist/components/upload/image-upload.js +34 -9
  178. package/dist/index.cjs +1 -1
  179. package/dist/index.js +31 -31
  180. package/dist/public-component-surface.cjs +1 -1
  181. package/dist/public-component-surface.js +15 -0
  182. package/dist/showcase/component-api-schema.cjs +1 -1
  183. package/dist/showcase/component-api-schema.js +187 -10
  184. package/dist/showcase/create-demo.cjs +5 -4
  185. package/dist/showcase/create-demo.js +2 -2
  186. package/dist/showcase/fallback.cjs +3 -3
  187. package/dist/showcase/fallback.js +221 -243
  188. package/dist/showcase/premium/alert/showcase.cjs +1 -1
  189. package/dist/showcase/premium/alert/showcase.js +1 -0
  190. package/dist/showcase/premium/app-sidebar/showcase.cjs +1 -1
  191. package/dist/showcase/premium/app-sidebar/showcase.js +1 -0
  192. package/dist/showcase/premium/badge/showcase.cjs +1 -1
  193. package/dist/showcase/premium/badge/showcase.js +7 -0
  194. package/dist/showcase/premium/badge/types.d.ts +1 -1
  195. package/dist/showcase/premium/breadcrumbs/showcase.cjs +1 -1
  196. package/dist/showcase/premium/breadcrumbs/showcase.js +12 -1
  197. package/dist/showcase/premium/button/mock.cjs +1 -4
  198. package/dist/showcase/premium/button/mock.js +1 -1
  199. package/dist/showcase/premium/button/showcase.cjs +1 -1
  200. package/dist/showcase/premium/button/showcase.js +2 -2
  201. package/dist/showcase/premium/card/showcase.cjs +1 -1
  202. package/dist/showcase/premium/card/showcase.js +96 -47
  203. package/dist/showcase/premium/carousel/showcase.cjs +1 -1
  204. package/dist/showcase/premium/carousel/showcase.js +76 -49
  205. package/dist/showcase/premium/command-bar/showcase.cjs +1 -1
  206. package/dist/showcase/premium/command-bar/showcase.js +2 -0
  207. package/dist/showcase/premium/data-table/mock.cjs +12 -11
  208. package/dist/showcase/premium/data-table/mock.js +1 -1
  209. package/dist/showcase/premium/data-table/showcase.cjs +1 -1
  210. package/dist/showcase/premium/data-table/showcase.js +1 -1
  211. package/dist/showcase/premium/data-table-parts/showcase.cjs +1 -1
  212. package/dist/showcase/premium/data-table-parts/showcase.js +3 -1
  213. package/dist/showcase/premium/file-upload/showcase.cjs +1 -1
  214. package/dist/showcase/premium/file-upload/showcase.js +25 -4
  215. package/dist/showcase/premium/image-upload/showcase.cjs +1 -1
  216. package/dist/showcase/premium/image-upload/showcase.js +4 -1
  217. package/dist/showcase/premium/index.cjs +1 -1
  218. package/dist/showcase/premium/index.js +396 -402
  219. package/dist/showcase/premium/loading-state/showcase.cjs +1 -1
  220. package/dist/showcase/premium/loading-state/showcase.js +3 -1
  221. package/dist/showcase/premium/metric-grid/showcase.cjs +1 -1
  222. package/dist/showcase/premium/metric-grid/showcase.js +96 -28
  223. package/dist/showcase/premium/notification-center/showcase.cjs +1 -1
  224. package/dist/showcase/premium/notification-center/showcase.js +7 -3
  225. package/dist/showcase/premium/page-state/showcase.cjs +1 -1
  226. package/dist/showcase/premium/page-state/showcase.js +5 -1
  227. package/dist/showcase/premium/pagination/showcase.cjs +1 -1
  228. package/dist/showcase/premium/pagination/showcase.js +15 -2
  229. package/dist/showcase/premium/popover/showcase.cjs +1 -1
  230. package/dist/showcase/premium/popover/showcase.js +85 -50
  231. package/dist/showcase/premium/radio-group/showcase.cjs +1 -1
  232. package/dist/showcase/premium/radio-group/showcase.js +27 -4
  233. package/dist/showcase/premium/right-click-menu/showcase.cjs +1 -1
  234. package/dist/showcase/premium/right-click-menu/showcase.js +56 -43
  235. package/dist/showcase/premium/segmented-control/showcase.cjs +1 -1
  236. package/dist/showcase/premium/segmented-control/showcase.js +1 -0
  237. package/dist/showcase/premium/select/data.cjs +1 -1
  238. package/dist/showcase/premium/select/data.js +69 -34
  239. package/dist/showcase/premium/select/mock.cjs +20 -8
  240. package/dist/showcase/premium/select/mock.js +3 -2
  241. package/dist/showcase/premium/select/showcase.cjs +1 -1
  242. package/dist/showcase/premium/select/showcase.js +101 -86
  243. package/dist/showcase/premium/select/types.d.ts +3 -0
  244. package/dist/showcase/premium/statistic/showcase.cjs +1 -1
  245. package/dist/showcase/premium/statistic/showcase.js +57 -25
  246. package/dist/showcase/premium/switch/showcase.cjs +1 -1
  247. package/dist/showcase/premium/switch/showcase.js +25 -14
  248. package/dist/showcase/premium/tabs/showcase.cjs +1 -1
  249. package/dist/showcase/premium/tabs/showcase.js +171 -48
  250. package/dist/showcase/premium/textarea/mock.cjs +12 -4
  251. package/dist/showcase/premium/textarea/mock.js +1 -1
  252. package/dist/showcase/premium/textarea/showcase.cjs +1 -1
  253. package/dist/showcase/premium/textarea/showcase.js +8 -3
  254. package/dist/showcase/premium/toast/showcase.cjs +1 -1
  255. package/dist/showcase/premium/toast/showcase.js +32 -6
  256. package/dist/showcase/premium/types.d.ts +1 -1
  257. package/dist/showcase/registry-quality.cjs +1 -1
  258. package/dist/showcase/registry-quality.js +1 -0
  259. package/dist/showcase/registry-specific.cjs +1 -1
  260. package/dist/showcase/registry-specific.js +78 -74
  261. package/dist/showcase/render-registry-preview.cjs +1 -1
  262. package/dist/showcase/render-registry-preview.js +90 -108
  263. package/dist/showcase/site-data.cjs +1 -1
  264. package/dist/showcase/site-data.js +60 -21
  265. package/dist/showcase/tembro-registry.json.cjs +1 -1
  266. package/dist/showcase/tembro-registry.json.js +34 -20
  267. package/dist/showcase/types.d.ts +1 -1
  268. package/package.json +1 -1
  269. package/packages/cli/dist/index.cjs +31 -31
  270. package/packages/cli/vendor/src/components/calendar/calendar.tsx +59 -50
  271. package/packages/cli/vendor/src/components/calendar/date-range-picker.tsx +7 -4
  272. package/packages/cli/vendor/src/components/charts/charts.tsx +109 -66
  273. package/packages/cli/vendor/src/components/charts/progress-ring.tsx +37 -26
  274. package/packages/cli/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +41 -22
  275. package/packages/cli/vendor/src/components/data-table/data-table-pagination.tsx +7 -7
  276. package/packages/cli/vendor/src/components/data-table/data-table-toolbar.tsx +8 -6
  277. package/packages/cli/vendor/src/components/data-table/data-table.tsx +21 -20
  278. package/packages/cli/vendor/src/components/display/carousel.tsx +102 -9
  279. package/packages/cli/vendor/src/components/display/code-block.tsx +22 -2
  280. package/packages/cli/vendor/src/components/display/delta-badge.tsx +11 -11
  281. package/packages/cli/vendor/src/components/display/kanban.tsx +103 -57
  282. package/packages/cli/vendor/src/components/display/metric-grid.tsx +16 -13
  283. package/packages/cli/vendor/src/components/display/qr-code.tsx +17 -15
  284. package/packages/cli/vendor/src/components/display/smart-card.tsx +1 -1
  285. package/packages/cli/vendor/src/components/display/status-legend.tsx +1 -1
  286. package/packages/cli/vendor/src/components/display/tag.tsx +39 -21
  287. package/packages/cli/vendor/src/components/display/tree-view.tsx +221 -84
  288. package/packages/cli/vendor/src/components/display/trend-card.tsx +6 -40
  289. package/packages/cli/vendor/src/components/feedback/alert.tsx +3 -1
  290. package/packages/cli/vendor/src/components/feedback/loading-state.tsx +33 -17
  291. package/packages/cli/vendor/src/components/feedback/page-state.tsx +8 -7
  292. package/packages/cli/vendor/src/components/form/form-field-shell.tsx +37 -8
  293. package/packages/cli/vendor/src/components/form/form-input.tsx +11 -12
  294. package/packages/cli/vendor/src/components/form/form-select.tsx +6 -4
  295. package/packages/cli/vendor/src/components/form/form-switch.tsx +9 -3
  296. package/packages/cli/vendor/src/components/form/form-textarea.tsx +6 -2
  297. package/packages/cli/vendor/src/components/inputs/async-select.tsx +11 -8
  298. package/packages/cli/vendor/src/components/inputs/search-input.tsx +5 -2
  299. package/packages/cli/vendor/src/components/inputs/simple-select.tsx +20 -190
  300. package/packages/cli/vendor/src/components/layout/app-sidebar.tsx +3 -1
  301. package/packages/cli/vendor/src/components/layout/breadcrumbs.tsx +3 -1
  302. package/packages/cli/vendor/src/components/modern/calendar-scheduler.tsx +28 -13
  303. package/packages/cli/vendor/src/components/modern/dual-list-picker.tsx +103 -35
  304. package/packages/cli/vendor/src/components/modern/rich-text-editor.tsx +25 -22
  305. package/packages/cli/vendor/src/components/modern/tour.tsx +47 -29
  306. package/packages/cli/vendor/src/components/navigation/command-bar.tsx +6 -0
  307. package/packages/cli/vendor/src/components/navigation/demo.tsx +0 -1
  308. package/packages/cli/vendor/src/components/navigation/nav-tabs.tsx +38 -29
  309. package/packages/cli/vendor/src/components/navigation/page-tabs.tsx +35 -23
  310. package/packages/cli/vendor/src/components/navigation/pagination.tsx +65 -31
  311. package/packages/cli/vendor/src/components/notifications/notification-center.tsx +64 -39
  312. package/packages/cli/vendor/src/components/notifications/toast.tsx +23 -21
  313. package/packages/cli/vendor/src/components/overlay/alert-dialog.tsx +1 -1
  314. package/packages/cli/vendor/src/components/overlay/confirm-dialog.tsx +45 -22
  315. package/packages/cli/vendor/src/components/overlay/drawer.tsx +18 -5
  316. package/packages/cli/vendor/src/components/ui/accordion/index.tsx +4 -0
  317. package/packages/cli/vendor/src/components/ui/badge/index.tsx +2 -1
  318. package/packages/cli/vendor/src/components/ui/button/index.tsx +11 -5
  319. package/packages/cli/vendor/src/components/ui/card/index.tsx +95 -25
  320. package/packages/cli/vendor/src/components/ui/dialog/index.tsx +2 -1
  321. package/packages/cli/vendor/src/components/ui/hover-card.tsx +54 -28
  322. package/packages/cli/vendor/src/components/ui/input/index.tsx +98 -0
  323. package/packages/cli/vendor/src/components/ui/popover/index.tsx +10 -8
  324. package/packages/cli/vendor/src/components/ui/radio-group/index.tsx +55 -6
  325. package/packages/cli/vendor/src/components/ui/right-click-menu/index.tsx +120 -9
  326. package/packages/cli/vendor/src/components/ui/segmented-control/index.tsx +29 -3
  327. package/packages/cli/vendor/src/components/ui/select/index.tsx +260 -34
  328. package/packages/cli/vendor/src/components/ui/switch/index.tsx +71 -6
  329. package/packages/cli/vendor/src/components/ui/tabs/index.tsx +22 -6
  330. package/packages/cli/vendor/src/components/ui/textarea/index.tsx +105 -15
  331. package/packages/cli/vendor/src/components/ui/textarea.tsx +2 -0
  332. package/packages/cli/vendor/src/components/ui/tooltip/index.tsx +67 -22
  333. package/packages/cli/vendor/src/components/upload/file-upload.tsx +120 -57
  334. package/packages/cli/vendor/src/components/upload/image-upload.tsx +71 -24
  335. package/packages/cli/vendor/src/public-component-surface.ts +3 -0
  336. package/packages/cli/vendor/src/showcase/component-api-schema.ts +79 -41
  337. package/packages/cli/vendor/src/showcase/create-demo.tsx +16 -15
  338. package/packages/cli/vendor/src/showcase/fallback.tsx +4 -19
  339. package/packages/cli/vendor/src/showcase/premium/alert/showcase.tsx +1 -0
  340. package/packages/cli/vendor/src/showcase/premium/app-sidebar/showcase.tsx +1 -0
  341. package/packages/cli/vendor/src/showcase/premium/badge/showcase.tsx +4 -2
  342. package/packages/cli/vendor/src/showcase/premium/badge/types.ts +1 -1
  343. package/packages/cli/vendor/src/showcase/premium/breadcrumbs/showcase.tsx +3 -1
  344. package/packages/cli/vendor/src/showcase/premium/button/mock.ts +2 -5
  345. package/packages/cli/vendor/src/showcase/premium/button/showcase.tsx +2 -2
  346. package/packages/cli/vendor/src/showcase/premium/card/showcase.tsx +26 -1
  347. package/packages/cli/vendor/src/showcase/premium/carousel/showcase.tsx +19 -3
  348. package/packages/cli/vendor/src/showcase/premium/command-bar/showcase.tsx +1 -1
  349. package/packages/cli/vendor/src/showcase/premium/data-table/mock.ts +26 -25
  350. package/packages/cli/vendor/src/showcase/premium/data-table/showcase.tsx +3 -3
  351. package/packages/cli/vendor/src/showcase/premium/data-table-parts/showcase.tsx +3 -3
  352. package/packages/cli/vendor/src/showcase/premium/file-upload/showcase.tsx +21 -1
  353. package/packages/cli/vendor/src/showcase/premium/image-upload/showcase.tsx +4 -1
  354. package/packages/cli/vendor/src/showcase/premium/index.ts +0 -2
  355. package/packages/cli/vendor/src/showcase/premium/loading-state/showcase.tsx +1 -1
  356. package/packages/cli/vendor/src/showcase/premium/metric-grid/showcase.tsx +36 -4
  357. package/packages/cli/vendor/src/showcase/premium/notification-center/showcase.tsx +4 -3
  358. package/packages/cli/vendor/src/showcase/premium/page-state/showcase.tsx +1 -0
  359. package/packages/cli/vendor/src/showcase/premium/pagination/showcase.tsx +13 -1
  360. package/packages/cli/vendor/src/showcase/premium/popover/showcase.tsx +27 -11
  361. package/packages/cli/vendor/src/showcase/premium/radio-group/showcase.tsx +13 -1
  362. package/packages/cli/vendor/src/showcase/premium/right-click-menu/showcase.tsx +8 -5
  363. package/packages/cli/vendor/src/showcase/premium/segmented-control/showcase.tsx +1 -0
  364. package/packages/cli/vendor/src/showcase/premium/select/data.ts +12 -3
  365. package/packages/cli/vendor/src/showcase/premium/select/mock.ts +4 -4
  366. package/packages/cli/vendor/src/showcase/premium/select/showcase.tsx +35 -22
  367. package/packages/cli/vendor/src/showcase/premium/select/types.ts +3 -0
  368. package/packages/cli/vendor/src/showcase/premium/statistic/showcase.tsx +10 -1
  369. package/packages/cli/vendor/src/showcase/premium/switch/showcase.tsx +15 -6
  370. package/packages/cli/vendor/src/showcase/premium/tabs/showcase.tsx +48 -1
  371. package/packages/cli/vendor/src/showcase/premium/textarea/mock.ts +12 -4
  372. package/packages/cli/vendor/src/showcase/premium/textarea/showcase.tsx +5 -0
  373. package/packages/cli/vendor/src/showcase/premium/toast/showcase.tsx +17 -1
  374. package/packages/cli/vendor/src/showcase/premium/types.ts +1 -1
  375. package/packages/cli/vendor/src/showcase/registry-quality.ts +3 -2
  376. package/packages/cli/vendor/src/showcase/registry-specific.tsx +7 -8
  377. package/packages/cli/vendor/src/showcase/render-registry-preview.tsx +5 -21
  378. package/packages/cli/vendor/src/showcase/site-data.tsx +21 -15
  379. package/packages/cli/vendor/src/showcase/tembro-registry.json +42 -20
  380. package/packages/cli/vendor/src/showcase/types.ts +1 -1
  381. package/registry.json +18 -6
@@ -87,7 +87,7 @@ function DataTableToolbar({
87
87
  </div>
88
88
  )}
89
89
 
90
- {actions && <div className={cn("flex min-w-0 shrink-0 flex-wrap items-center gap-2 xl:justify-end", actionsClassName)}>{actions}</div>}
90
+ {actions && <div className={cn("flex w-full min-w-0 flex-wrap items-center gap-2 sm:w-auto xl:shrink-0 xl:justify-end", actionsClassName)}>{actions}</div>}
91
91
  </div>
92
92
  )}
93
93
 
@@ -95,10 +95,12 @@ function DataTableToolbar({
95
95
  <div className="flex flex-col gap-3 xl:flex-row xl:items-start xl:justify-between">
96
96
  <div className="flex min-w-0 flex-1 flex-col gap-3">
97
97
  {hasMainControls && (
98
- <div className="flex min-w-0 flex-1 flex-col gap-2 lg:flex-row lg:flex-wrap lg:items-center">
99
- {search ? <div className={cn("min-w-[16rem] max-w-xl flex-1", searchClassName)}>{search}</div> : null}
100
- {filters ? <div className={cn("flex min-w-0 flex-1 flex-wrap items-center gap-2", filtersClassName)}>{filters}</div> : null}
101
- {children}
98
+ <div className="grid min-w-0 flex-1 gap-2 lg:grid-cols-[minmax(14rem,24rem)_minmax(0,1fr)] lg:items-start">
99
+ {search ? <div className={cn("min-w-0 max-w-full", searchClassName)}>{search}</div> : null}
100
+ <div className="flex min-w-0 flex-wrap items-center gap-2">
101
+ {filters ? <div className={cn("flex min-w-0 flex-1 flex-wrap items-center gap-2 [&>*]:min-w-0", filtersClassName)}>{filters}</div> : null}
102
+ {children}
103
+ </div>
102
104
  </div>
103
105
  )}
104
106
  {summary ? (
@@ -112,7 +114,7 @@ function DataTableToolbar({
112
114
  </div>
113
115
 
114
116
  {hasSelection && (
115
- <div data-slot="data-table-selection-bar" className="flex shrink-0 flex-wrap items-center gap-2 rounded-[var(--radius-md)] border border-[color:var(--aui-control-border-strong,var(--border))] bg-[color:var(--aui-control-surface,var(--background))] px-2.5 py-1.5 text-sm shadow-[var(--aui-control-shadow,none)] backdrop-blur">
117
+ <div data-slot="data-table-selection-bar" className="flex w-full shrink-0 flex-wrap items-center gap-2 rounded-[var(--radius-md)] border border-[color:var(--aui-control-border-strong,var(--border))] bg-[color:var(--aui-control-surface,var(--background))] px-2.5 py-1.5 text-sm shadow-[var(--aui-control-shadow,none)] backdrop-blur sm:w-auto">
116
118
  <span className="text-muted-foreground">{selectedLabel(selectedCount, totalCount)}</span>
117
119
  {selectionActions}
118
120
  </div>
@@ -20,17 +20,17 @@ import {
20
20
 
21
21
  import { createDataTableActionsColumn } from "@/components/data-table/data-table-actions-column"
22
22
  import { DataTableBulkActions, type DataTableBulkAction } from "@/components/data-table/data-table-bulk-actions"
23
- import { DataTableColumnVisibilityMenu } from "@/components/data-table/data-table-column-visibility-menu"
24
- import { DataTablePagination, type DataTablePaginationProps } from "@/components/data-table/data-table-pagination"
25
- import { type DataTableRowAction } from "@/components/data-table/data-table-row-actions"
26
- import { DataTableToolbar, type DataTableToolbarProps } from "@/components/data-table/data-table-toolbar"
23
+ import { DataTableColumnVisibilityMenu } from "@/components/data-table/data-table-column-visibility-menu"
24
+ import { DataTablePagination, type DataTablePaginationProps } from "@/components/data-table/data-table-pagination"
25
+ import { type DataTableRowAction } from "@/components/data-table/data-table-row-actions"
26
+ import { DataTableToolbar, type DataTableToolbarProps } from "@/components/data-table/data-table-toolbar"
27
27
  import { DataState, type DataStateProps } from "@/components/display/data-state"
28
- import { LoadingState, type LoadingStateProps } from "@/components/feedback/loading-state"
29
- import { SearchInput, type SearchInputProps } from "@/components/inputs/search-input"
30
- import { Button } from "@/components/ui/button"
31
- import {
32
- Table,
33
- TableBody,
28
+ import { LoadingState, type LoadingStateProps } from "@/components/feedback/loading-state"
29
+ import { Button } from "@/components/ui/button"
30
+ import { Input, type InputSearchProps } from "@/components/ui/input"
31
+ import {
32
+ Table,
33
+ TableBody,
34
34
  TableCell,
35
35
  TableHead,
36
36
  TableHeader,
@@ -50,12 +50,12 @@ export type DataTableFeatureConfig = {
50
50
  export?: boolean
51
51
  }
52
52
 
53
- export type DataTableSearchConfig = Pick<
54
- SearchInputProps,
55
- | "value"
56
- | "onValueChange"
57
- | "placeholder"
58
- | "inputClassName"
53
+ export type DataTableSearchConfig = Pick<
54
+ InputSearchProps,
55
+ | "value"
56
+ | "onValueChange"
57
+ | "placeholder"
58
+ | "inputClassName"
59
59
  | "disabled"
60
60
  | "clearable"
61
61
  | "clearLabel"
@@ -324,10 +324,11 @@ function DataTable<TData, TValue = unknown>({
324
324
  )
325
325
  const shouldShowColumnVisibilityInToolbar = shouldShowColumnVisibility && hasPrimaryToolbarContent
326
326
  const defaultSearch = shouldShowSearch && search ? (
327
- <SearchInput
328
- value={search.value}
329
- onValueChange={search.onValueChange}
330
- placeholder={search.placeholder ?? "Search..."}
327
+ <Input
328
+ type="search"
329
+ value={search.value}
330
+ onValueChange={search.onValueChange}
331
+ placeholder={search.placeholder ?? "Search..."}
331
332
  wrapperClassName={search.wrapperClassName ?? search.className}
332
333
  inputClassName={search.inputClassName}
333
334
  disabled={search.disabled}
@@ -22,9 +22,23 @@ export type CarouselProps = React.ComponentProps<"div"> & {
22
22
  pauseOnHover?: boolean
23
23
  stopAutoplayOnInteraction?: boolean
24
24
  showPlaybackControl?: boolean
25
+ showStatus?: boolean
26
+ showThumbnails?: boolean
25
27
  playLabel?: string
26
28
  pauseLabel?: string
29
+ statusLabel?: (index: number, total: number) => string
30
+ renderThumbnail?: (item: React.ReactNode, index: number, active: boolean) => React.ReactNode
31
+ renderActiveDetail?: (item: React.ReactNode, index: number) => React.ReactNode
32
+ aspectRatio?: string
33
+ mouseDrag?: boolean
27
34
  onAutoplayChange?: (playing: boolean) => void
35
+ viewportClassName?: string
36
+ controlsClassName?: string
37
+ dotsClassName?: string
38
+ arrowClassName?: string
39
+ dotClassName?: string
40
+ activeDotClassName?: string
41
+ thumbnailsClassName?: string
28
42
  }
29
43
 
30
44
  export type CarouselItemProps = React.ComponentProps<"div">
@@ -53,9 +67,23 @@ function Carousel({
53
67
  pauseOnHover = true,
54
68
  stopAutoplayOnInteraction = true,
55
69
  showPlaybackControl = false,
70
+ showStatus = false,
71
+ showThumbnails = false,
56
72
  playLabel = "Start autoplay",
57
73
  pauseLabel = "Pause autoplay",
74
+ statusLabel,
75
+ renderThumbnail,
76
+ renderActiveDetail,
77
+ aspectRatio,
78
+ mouseDrag = true,
58
79
  onAutoplayChange,
80
+ viewportClassName,
81
+ controlsClassName,
82
+ dotsClassName,
83
+ arrowClassName,
84
+ dotClassName,
85
+ activeDotClassName,
86
+ thumbnailsClassName,
59
87
  className,
60
88
  children,
61
89
  ...props
@@ -63,11 +91,13 @@ function Carousel({
63
91
  const items = React.Children.toArray(children)
64
92
  const [internalIndex, setInternalIndex] = React.useState(defaultIndex)
65
93
  const touchStartXRef = React.useRef<number | null>(null)
94
+ const pointerStartXRef = React.useRef<number | null>(null)
66
95
  const [isHovered, setIsHovered] = React.useState(false)
67
96
  const [autoplayStopped, setAutoplayStopped] = React.useState(false)
68
97
  const [autoplayEnabled, setAutoplayEnabled] = React.useState(autoplay)
69
98
  const controlled = index !== undefined
70
99
  const activeIndex = clampIndex(controlled ? index : internalIndex, items.length, loop)
100
+ const activeItem = items[activeIndex]
71
101
 
72
102
  React.useEffect(() => {
73
103
  setAutoplayEnabled(autoplay)
@@ -104,6 +134,21 @@ function Carousel({
104
134
  if (deltaX < 0 && canGoNext) setActiveIndex(activeIndex + 1)
105
135
  }
106
136
 
137
+ const handlePointerDown: React.PointerEventHandler<HTMLDivElement> = (event) => {
138
+ if (!mouseDrag || event.pointerType === "touch") return
139
+ pointerStartXRef.current = event.clientX
140
+ }
141
+
142
+ const handlePointerUp: React.PointerEventHandler<HTMLDivElement> = (event) => {
143
+ if (!mouseDrag || pointerStartXRef.current == null || items.length <= 1) return
144
+ const deltaX = event.clientX - pointerStartXRef.current
145
+ pointerStartXRef.current = null
146
+
147
+ if (Math.abs(deltaX) < swipeThreshold) return
148
+ if (deltaX > 0 && canGoPrevious) setActiveIndex(activeIndex - 1)
149
+ if (deltaX < 0 && canGoNext) setActiveIndex(activeIndex + 1)
150
+ }
151
+
107
152
  React.useEffect(() => {
108
153
  if (!autoplayEnabled || items.length <= 1 || autoplayStopped) return
109
154
  if (pauseOnHover && isHovered) return
@@ -140,9 +185,19 @@ function Carousel({
140
185
  event.preventDefault()
141
186
  setActiveIndex(activeIndex + 1)
142
187
  }
188
+ if (event.key === "Home") {
189
+ event.preventDefault()
190
+ setActiveIndex(0)
191
+ }
192
+ if (event.key === "End") {
193
+ event.preventDefault()
194
+ setActiveIndex(items.length - 1)
195
+ }
143
196
  }}
144
197
  onTouchStart={handleTouchStart}
145
198
  onTouchEnd={handleTouchEnd}
199
+ onPointerDown={handlePointerDown}
200
+ onPointerUp={handlePointerUp}
146
201
  onMouseEnter={() => setIsHovered(true)}
147
202
  onMouseLeave={() => setIsHovered(false)}
148
203
  {...props}
@@ -151,8 +206,17 @@ function Carousel({
151
206
  "relative overflow-hidden rounded-[var(--aui-card-radius,var(--radius-lg))] border border-[color:var(--aui-card-border,var(--border))] bg-card shadow-[var(--aui-card-shadow,0_12px_32px_rgba(15,23,42,0.08))]",
152
207
  variant === "hero" && "min-h-72",
153
208
  variant === "minimal" && "rounded-[var(--radius-md)] shadow-none"
154
- )}>
155
- <div className="transition-transform duration-300 ease-out" aria-live="polite">
209
+ , viewportClassName)}>
210
+ {showStatus ? (
211
+ <div className="pointer-events-none absolute right-3 top-3 z-10 rounded-full border border-border/70 bg-background/92 px-2.5 py-1 text-[11px] font-medium text-muted-foreground shadow-sm">
212
+ {statusLabel?.(activeIndex, items.length) ?? `Slide ${activeIndex + 1} / ${items.length}`}
213
+ </div>
214
+ ) : null}
215
+ <div
216
+ className="transition-transform duration-300 ease-out"
217
+ aria-live="polite"
218
+ style={aspectRatio ? { aspectRatio } : undefined}
219
+ >
156
220
  {items[activeIndex]}
157
221
  </div>
158
222
  {showArrows && items.length > 1 ? (
@@ -161,7 +225,7 @@ function Carousel({
161
225
  type="button"
162
226
  variant={variant === "hero" ? "default" : "secondary"}
163
227
  size="icon-sm"
164
- className="absolute left-3 top-1/2 -translate-y-1/2 rounded-full shadow-lg"
228
+ className={cn("absolute left-3 top-1/2 -translate-y-1/2 rounded-full shadow-lg", arrowClassName)}
165
229
  disabled={!canGoPrevious}
166
230
  aria-label={previousLabel}
167
231
  onClick={() => setActiveIndex(activeIndex - 1)}
@@ -172,7 +236,7 @@ function Carousel({
172
236
  type="button"
173
237
  variant={variant === "hero" ? "default" : "secondary"}
174
238
  size="icon-sm"
175
- className="absolute right-3 top-1/2 -translate-y-1/2 rounded-full shadow-lg"
239
+ className={cn("absolute right-3 top-1/2 -translate-y-1/2 rounded-full shadow-lg", arrowClassName)}
176
240
  disabled={!canGoNext}
177
241
  aria-label={nextLabel}
178
242
  onClick={() => setActiveIndex(activeIndex + 1)}
@@ -183,7 +247,7 @@ function Carousel({
183
247
  ) : null}
184
248
  </div>
185
249
  {showDots && items.length > 1 && (
186
- <div className="flex flex-wrap items-center justify-center gap-2" role="tablist" aria-label={`${ariaLabel} slides`}>
250
+ <div className={cn("flex flex-wrap items-center justify-center gap-2", dotsClassName)} role="tablist" aria-label={`${ariaLabel} slides`}>
187
251
  {items.map((_, itemIndex) => (
188
252
  <button
189
253
  key={itemIndex}
@@ -193,7 +257,7 @@ function Carousel({
193
257
  aria-selected={itemIndex === activeIndex}
194
258
  className={cn(
195
259
  "h-2.5 rounded-full bg-muted-foreground/30 transition-[width,background-color,opacity] hover:bg-muted-foreground/55",
196
- itemIndex === activeIndex ? "w-7 bg-primary" : "w-2.5"
260
+ itemIndex === activeIndex ? cn("w-7 bg-primary", activeDotClassName) : cn("w-2.5", dotClassName)
197
261
  )}
198
262
  onClick={() => setActiveIndex(itemIndex)}
199
263
  />
@@ -203,7 +267,7 @@ function Carousel({
203
267
  type="button"
204
268
  variant="ghost"
205
269
  size="sm"
206
- className="ml-2 rounded-full"
270
+ className={cn("ml-2 rounded-full", controlsClassName)}
207
271
  onClick={() => {
208
272
  const nextPlaying = !autoplayEnabled
209
273
  setAutoplayStopped(false)
@@ -216,9 +280,38 @@ function Carousel({
216
280
  ) : null}
217
281
  </div>
218
282
  )}
283
+ {showThumbnails && items.length > 1 ? (
284
+ <div className={cn("grid grid-cols-2 gap-2 sm:grid-cols-4", thumbnailsClassName)}>
285
+ {items.map((item, itemIndex) => {
286
+ const active = itemIndex === activeIndex
287
+
288
+ return (
289
+ <button
290
+ key={itemIndex}
291
+ type="button"
292
+ aria-current={active ? "true" : undefined}
293
+ aria-label={`Open slide ${itemIndex + 1}`}
294
+ className={cn(
295
+ "overflow-hidden rounded-[min(var(--radius-xl),16px)] border bg-card text-left transition hover:border-primary/35 hover:shadow-sm",
296
+ active ? "border-primary/35 ring-2 ring-primary/15" : "border-border/70"
297
+ )}
298
+ onClick={() => setActiveIndex(itemIndex)}
299
+ >
300
+ {renderThumbnail
301
+ ? renderThumbnail(item, itemIndex, active)
302
+ : <div className="line-clamp-2 min-h-16 p-3 text-xs text-muted-foreground">Slide {itemIndex + 1}</div>}
303
+ </button>
304
+ )
305
+ })}
306
+ </div>
307
+ ) : null}
308
+ {renderActiveDetail ? renderActiveDetail(activeItem, activeIndex) : null}
309
+ <span className="sr-only" aria-live="polite">
310
+ {statusLabel?.(activeIndex, items.length) ?? `${ariaLabel}: slide ${activeIndex + 1} of ${items.length}`}
311
+ </span>
219
312
  </div>
220
- )
221
- }
313
+ )
314
+ }
222
315
 
223
316
  function CarouselItem({ className, ...props }: CarouselItemProps) {
224
317
  return <div data-slot="carousel-item" className={cn("min-h-40 p-5 sm:p-6", className)} {...props} />
@@ -10,6 +10,7 @@ export type CodeBlockProps = React.ComponentProps<"div"> & {
10
10
  showCopy?: boolean
11
11
  wrap?: boolean
12
12
  lineNumbers?: boolean
13
+ highlightLines?: number[] | readonly number[]
13
14
  maxHeight?: number | string
14
15
  }
15
16
 
@@ -20,11 +21,13 @@ function CodeBlock({
20
21
  showCopy = true,
21
22
  wrap = false,
22
23
  lineNumbers = false,
24
+ highlightLines = [],
23
25
  maxHeight,
24
26
  className,
25
27
  ...props
26
28
  }: CodeBlockProps) {
27
29
  const lines = React.useMemo(() => code.split("\n"), [code])
30
+ const highlightedLineSet = React.useMemo(() => new Set(highlightLines), [highlightLines])
28
31
 
29
32
  return (
30
33
  <div
@@ -48,14 +51,31 @@ function CodeBlock({
48
51
  {lineNumbers ? (
49
52
  <code className="grid">
50
53
  {lines.map((line, index) => (
51
- <span key={`${index}-${line}`} className="grid grid-cols-[auto_1fr] gap-4">
54
+ <span
55
+ key={`${index}-${line}`}
56
+ data-highlighted={highlightedLineSet.has(index + 1) || undefined}
57
+ className={cn(
58
+ "grid grid-cols-[auto_1fr] gap-4 rounded px-1",
59
+ highlightedLineSet.has(index + 1) && "bg-primary/10 text-foreground"
60
+ )}
61
+ >
52
62
  <span className="select-none text-right text-xs text-muted-foreground/75">{index + 1}</span>
53
63
  <span>{line || " "}</span>
54
64
  </span>
55
65
  ))}
56
66
  </code>
57
67
  ) : (
58
- <code>{code}</code>
68
+ <code>
69
+ {lines.map((line, index) => (
70
+ <span
71
+ key={`${index}-${line}`}
72
+ data-highlighted={highlightedLineSet.has(index + 1) || undefined}
73
+ className={cn("block rounded px-1", highlightedLineSet.has(index + 1) && "bg-primary/10 text-foreground")}
74
+ >
75
+ {line || " "}
76
+ </span>
77
+ ))}
78
+ </code>
59
79
  )}
60
80
  </pre>
61
81
  </div>
@@ -1,9 +1,10 @@
1
1
  import * as React from "react"
2
2
  import { ArrowDownIcon, ArrowUpIcon, MinusIcon } from "lucide-react"
3
3
 
4
+ import { Badge, type BadgeProps } from "@/components/ui/badge"
4
5
  import { cn } from "@/lib/utils"
5
6
 
6
- export type DeltaBadgeProps = React.ComponentProps<"span"> & {
7
+ export type DeltaBadgeProps = Omit<BadgeProps, "children" | "label" | "tone" | "status" | "leftIcon" | "variant" | "size"> & {
7
8
  value: React.ReactNode
8
9
  trend?: "up" | "down" | "neutral"
9
10
  size?: "sm" | "default"
@@ -19,23 +20,22 @@ function DeltaBadge({
19
20
  ...props
20
21
  }: DeltaBadgeProps) {
21
22
  const TrendIcon = trend === "up" ? ArrowUpIcon : trend === "down" ? ArrowDownIcon : MinusIcon
23
+ const tone = trend === "up" ? "success" : trend === "down" ? "danger" : "muted"
22
24
 
23
25
  return (
24
- <span
26
+ <Badge
25
27
  data-slot="delta-badge"
28
+ variant="soft"
29
+ tone={tone}
30
+ size={size}
31
+ leftIcon={icon ? <TrendIcon className={cn("shrink-0", size === "sm" ? "size-2.5" : "size-3")} /> : undefined}
32
+ label={value}
26
33
  className={cn(
27
- "inline-flex items-center justify-center font-medium",
28
- size === "sm" ? "gap-0.5 rounded px-1 py-0.5 text-[10px]" : "gap-1 rounded-full px-1.5 py-0.5 text-xs",
29
- trend === "up" && "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
30
- trend === "down" && "bg-destructive/10 text-destructive",
31
- trend === "neutral" && "bg-muted text-muted-foreground",
34
+ size === "sm" && "min-h-5 px-1.5 text-[10px]",
32
35
  className
33
36
  )}
34
37
  {...props}
35
- >
36
- {icon && <TrendIcon className={cn("shrink-0", size === "sm" ? "size-2.5" : "size-3")} />}
37
- {value}
38
- </span>
38
+ />
39
39
  )
40
40
  }
41
41
 
@@ -3,14 +3,15 @@ import * as React from "react"
3
3
  import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
4
4
  import { cn } from "@/lib/utils"
5
5
 
6
- export type KanbanCard = {
7
- key: string
8
- title: React.ReactNode
9
- description?: React.ReactNode
10
- meta?: React.ReactNode
11
- extra?: React.ReactNode
12
- disabled?: boolean
13
- }
6
+ export type KanbanCard = {
7
+ key: string
8
+ title: React.ReactNode
9
+ description?: React.ReactNode
10
+ meta?: React.ReactNode
11
+ extra?: React.ReactNode
12
+ actions?: React.ReactNode
13
+ disabled?: boolean
14
+ }
14
15
 
15
16
  export type KanbanColumn = {
16
17
  key: string
@@ -22,24 +23,31 @@ export type KanbanColumn = {
22
23
 
23
24
  export type KanbanBoardProps = React.ComponentProps<"div"> & {
24
25
  columns: KanbanColumn[]
25
- renderCard?: (card: KanbanCard, column: KanbanColumn) => React.ReactNode
26
- onCardClick?: (card: KanbanCard, column: KanbanColumn) => void
27
- columnClassName?: string
28
- cardClassName?: string
29
- }
30
-
31
- function KanbanBoard({ columns, renderCard, onCardClick, columnClassName, cardClassName, className, ...props }: KanbanBoardProps) {
32
- return (
33
- <div data-slot="kanban-board" className={cn("grid auto-cols-[minmax(280px,1fr)] grid-flow-col gap-4 overflow-x-auto pb-2", className)} {...props}>
34
- {columns.map((column) => (
26
+ renderCard?: (card: KanbanCard, column: KanbanColumn) => React.ReactNode
27
+ onCardClick?: (card: KanbanCard, column: KanbanColumn) => void
28
+ onCardMove?: (card: KanbanCard, fromColumn: KanbanColumn, toColumn: KanbanColumn) => void
29
+ emptyColumn?: React.ReactNode | ((column: KanbanColumn) => React.ReactNode)
30
+ columnClassName?: string
31
+ cardClassName?: string
32
+ }
33
+
34
+ function KanbanBoard({ columns, renderCard, onCardClick, onCardMove, emptyColumn = "No cards yet.", columnClassName, cardClassName, className, ...props }: KanbanBoardProps) {
35
+ const columnByKey = React.useMemo(() => new Map(columns.map((column) => [column.key, column])), [columns])
36
+
37
+ return (
38
+ <div data-slot="kanban-board" className={cn("grid auto-cols-[minmax(280px,1fr)] grid-flow-col gap-4 overflow-x-auto pb-2", className)} {...props}>
39
+ {columns.map((column) => (
35
40
  <KanbanColumnView
36
41
  key={column.key}
37
42
  column={column}
38
- renderCard={renderCard}
39
- onCardClick={onCardClick}
40
- columnClassName={columnClassName}
41
- cardClassName={cardClassName}
42
- />
43
+ renderCard={renderCard}
44
+ onCardClick={onCardClick}
45
+ onCardMove={onCardMove}
46
+ columnByKey={columnByKey}
47
+ emptyColumn={emptyColumn}
48
+ columnClassName={columnClassName}
49
+ cardClassName={cardClassName}
50
+ />
43
51
  ))}
44
52
  </div>
45
53
  )
@@ -47,46 +55,84 @@ function KanbanBoard({ columns, renderCard, onCardClick, columnClassName, cardCl
47
55
 
48
56
  function KanbanColumnView({
49
57
  column,
50
- renderCard,
51
- onCardClick,
52
- columnClassName,
53
- cardClassName,
54
- }: {
55
- column: KanbanColumn
56
- renderCard?: (card: KanbanCard, column: KanbanColumn) => React.ReactNode
57
- onCardClick?: (card: KanbanCard, column: KanbanColumn) => void
58
- columnClassName?: string
59
- cardClassName?: string
60
- }) {
61
- return (
62
- <section data-slot="kanban-column" className={cn("grid min-h-40 content-start gap-3 rounded-lg border bg-muted/35 p-3", columnClassName)}>
58
+ renderCard,
59
+ onCardClick,
60
+ onCardMove,
61
+ columnByKey,
62
+ emptyColumn,
63
+ columnClassName,
64
+ cardClassName,
65
+ }: {
66
+ column: KanbanColumn
67
+ renderCard?: (card: KanbanCard, column: KanbanColumn) => React.ReactNode
68
+ onCardClick?: (card: KanbanCard, column: KanbanColumn) => void
69
+ onCardMove?: (card: KanbanCard, fromColumn: KanbanColumn, toColumn: KanbanColumn) => void
70
+ columnByKey: Map<string, KanbanColumn>
71
+ emptyColumn: React.ReactNode | ((column: KanbanColumn) => React.ReactNode)
72
+ columnClassName?: string
73
+ cardClassName?: string
74
+ }) {
75
+ return (
76
+ <section
77
+ data-slot="kanban-column"
78
+ className={cn("grid min-h-40 content-start gap-3 rounded-lg border bg-muted/35 p-3", columnClassName)}
79
+ onDragOver={(event) => {
80
+ if (onCardMove) event.preventDefault()
81
+ }}
82
+ onDrop={(event) => {
83
+ const cardKey = event.dataTransfer.getData("application/x-tembro-kanban-card")
84
+ const fromColumnKey = event.dataTransfer.getData("application/x-tembro-kanban-column")
85
+ const fromColumn = columnByKey.get(fromColumnKey)
86
+ const card = fromColumn?.cards.find((item) => item.key === cardKey)
87
+ if (card && fromColumn && fromColumn.key !== column.key) onCardMove?.(card, fromColumn, column)
88
+ }}
89
+ >
63
90
  <div className="flex items-start justify-between gap-3">
64
91
  <div className="grid gap-0.5">
65
92
  <h3 className="text-sm font-semibold text-foreground">{column.title}</h3>
66
93
  {column.description && <p className="text-xs text-muted-foreground">{column.description}</p>}
67
94
  </div>
68
95
  <div className="rounded-full bg-background px-2 py-0.5 text-xs text-muted-foreground">{column.count ?? column.cards.length}</div>
69
- </div>
70
- <div className="grid gap-2">
71
- {column.cards.map((card) => (
72
- renderCard?.(card, column) ?? (
73
- <Card
74
- key={card.key}
75
- data-slot="kanban-card"
76
- className={cn(
77
- "transition-colors hover:bg-muted/40",
78
- onCardClick && !card.disabled && "cursor-pointer",
79
- card.disabled && "pointer-events-none opacity-55",
80
- cardClassName
81
- )}
82
- onClick={() => onCardClick?.(card, column)}
83
- >
84
- <CardHeader className="p-3 pb-1">
85
- <div className="flex items-start justify-between gap-2">
86
- <CardTitle className="text-sm">{card.title}</CardTitle>
87
- {card.extra}
88
- </div>
89
- </CardHeader>
96
+ </div>
97
+ <div className="grid gap-2">
98
+ {column.cards.length === 0 ? (
99
+ <div data-slot="kanban-column-empty" className="rounded-md border border-dashed bg-background/60 px-3 py-6 text-center text-sm text-muted-foreground">
100
+ {typeof emptyColumn === "function" ? emptyColumn(column) : emptyColumn}
101
+ </div>
102
+ ) : column.cards.map((card) => (
103
+ renderCard?.(card, column) ?? (
104
+ <Card
105
+ key={card.key}
106
+ data-slot="kanban-card"
107
+ role={onCardClick ? "button" : undefined}
108
+ tabIndex={onCardClick && !card.disabled ? 0 : undefined}
109
+ draggable={Boolean(onCardMove && !card.disabled)}
110
+ className={cn(
111
+ "transition-colors hover:bg-muted/40",
112
+ onCardClick && !card.disabled && "cursor-pointer",
113
+ onCardMove && !card.disabled && "cursor-grab active:cursor-grabbing",
114
+ card.disabled && "pointer-events-none opacity-55",
115
+ cardClassName
116
+ )}
117
+ onDragStart={(event) => {
118
+ event.dataTransfer.setData("application/x-tembro-kanban-card", card.key)
119
+ event.dataTransfer.setData("application/x-tembro-kanban-column", column.key)
120
+ event.dataTransfer.effectAllowed = "move"
121
+ }}
122
+ onClick={() => onCardClick?.(card, column)}
123
+ onKeyDown={(event) => {
124
+ if ((event.key === "Enter" || event.key === " ") && onCardClick && !card.disabled) {
125
+ event.preventDefault()
126
+ onCardClick(card, column)
127
+ }
128
+ }}
129
+ >
130
+ <CardHeader className="p-3 pb-1">
131
+ <div className="flex items-start justify-between gap-2">
132
+ <CardTitle className="text-sm">{card.title}</CardTitle>
133
+ {(card.extra || card.actions) && <div className="flex shrink-0 items-center gap-1">{card.extra}{card.actions}</div>}
134
+ </div>
135
+ </CardHeader>
90
136
  {(card.description || card.meta) && (
91
137
  <CardContent className="grid gap-2 p-3 pt-0 text-xs text-muted-foreground">
92
138
  {card.description}
@@ -6,17 +6,18 @@ import { cn } from "@/lib/utils"
6
6
  export type MetricTone = "default" | "success" | "warning" | "danger" | "info" | "muted"
7
7
  export type MetricGridColumn = 1 | 2 | 3 | 4
8
8
 
9
- export type MetricItem = {
9
+ export type MetricItem = {
10
10
  key: string
11
11
  label: React.ReactNode
12
12
  value: React.ReactNode
13
13
  description?: React.ReactNode
14
14
  icon?: React.ReactNode
15
15
  trend?: React.ReactNode
16
- tone?: MetricTone
17
- hidden?: boolean
18
- className?: string
19
- }
16
+ tone?: MetricTone
17
+ hidden?: boolean
18
+ className?: string
19
+ loading?: boolean
20
+ }
20
21
 
21
22
  export type MetricGridProps = React.ComponentProps<"div"> & {
22
23
  items: MetricItem[]
@@ -63,14 +64,16 @@ function MetricGrid({
63
64
  data-slot="stat-card"
64
65
  data-tone={item.tone ?? "default"}
65
66
  className={cn("min-w-0 overflow-hidden", toneClassName[item.tone ?? "default"], itemClassName, item.className)}
66
- >
67
- <CardHeader className={cn("flex flex-row items-start justify-between gap-3 space-y-0", compact ? "p-3 pb-1" : "pb-2")}>
68
- <div className="min-w-0 space-y-1">
69
- <CardDescription className="truncate">{item.label}</CardDescription>
70
- <CardTitle className={cn("truncate", compact ? "text-xl" : "text-2xl")}>{item.value}</CardTitle>
71
- </div>
72
- {item.icon && <div className="shrink-0 rounded-lg bg-muted p-2 text-muted-foreground [&_svg]:size-4">{item.icon}</div>}
73
- </CardHeader>
67
+ >
68
+ <CardHeader className={cn("flex flex-row items-start justify-between gap-3 space-y-0", compact ? "p-3 pb-1" : "pb-2")}>
69
+ <div className="min-w-0 space-y-1">
70
+ <CardDescription className="truncate">{item.label}</CardDescription>
71
+ <CardTitle className={cn("truncate", compact ? "text-xl" : "text-2xl")}>
72
+ {item.loading ? <span className="block h-8 w-24 animate-pulse rounded bg-muted" /> : item.value}
73
+ </CardTitle>
74
+ </div>
75
+ {item.icon && <div className="shrink-0 rounded-lg bg-muted p-2 text-muted-foreground [&_svg]:size-4">{item.icon}</div>}
76
+ </CardHeader>
74
77
  {(item.description || item.trend) && (
75
78
  <CardContent className={cn("flex min-w-0 items-center justify-between gap-2", compact ? "p-3 pt-1" : "pt-0")}>
76
79
  {item.description && <div className="min-w-0 truncate text-xs text-muted-foreground">{item.description}</div>}