tembro 2.0.6 → 2.1.1

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 (344) 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-toolbar.cjs +1 -1
  17. package/dist/components/data-table/data-table-toolbar.js +12 -13
  18. package/dist/components/display/carousel.cjs +1 -1
  19. package/dist/components/display/carousel.d.ts +9 -1
  20. package/dist/components/display/carousel.js +123 -81
  21. package/dist/components/display/code-block.cjs +2 -2
  22. package/dist/components/display/code-block.d.ts +2 -1
  23. package/dist/components/display/code-block.js +17 -12
  24. package/dist/components/display/delta-badge.cjs +1 -1
  25. package/dist/components/display/delta-badge.d.ts +2 -1
  26. package/dist/components/display/delta-badge.js +11 -7
  27. package/dist/components/display/kanban.cjs +1 -1
  28. package/dist/components/display/kanban.d.ts +4 -1
  29. package/dist/components/display/kanban.js +60 -33
  30. package/dist/components/display/metric-grid.cjs +1 -1
  31. package/dist/components/display/metric-grid.d.ts +1 -0
  32. package/dist/components/display/metric-grid.js +1 -1
  33. package/dist/components/display/qr-code.cjs +1 -1
  34. package/dist/components/display/qr-code.d.ts +2 -1
  35. package/dist/components/display/qr-code.js +19 -16
  36. package/dist/components/display/status-legend.cjs +1 -1
  37. package/dist/components/display/status-legend.js +6 -2
  38. package/dist/components/display/tag.cjs +1 -1
  39. package/dist/components/display/tag.d.ts +2 -1
  40. package/dist/components/display/tag.js +28 -22
  41. package/dist/components/display/tree-view.cjs +1 -1
  42. package/dist/components/display/tree-view.d.ts +9 -1
  43. package/dist/components/display/tree-view.js +104 -40
  44. package/dist/components/display/trend-card.cjs +1 -1
  45. package/dist/components/display/trend-card.js +27 -41
  46. package/dist/components/feedback/alert.cjs +1 -1
  47. package/dist/components/feedback/alert.d.ts +2 -1
  48. package/dist/components/feedback/alert.js +6 -6
  49. package/dist/components/feedback/loading-state.cjs +1 -1
  50. package/dist/components/feedback/loading-state.d.ts +3 -1
  51. package/dist/components/feedback/loading-state.js +23 -10
  52. package/dist/components/feedback/page-state.cjs +1 -1
  53. package/dist/components/feedback/page-state.d.ts +2 -1
  54. package/dist/components/feedback/page-state.js +7 -4
  55. package/dist/components/form/form-field-shell.cjs +1 -1
  56. package/dist/components/form/form-field-shell.d.ts +4 -2
  57. package/dist/components/form/form-field-shell.js +57 -41
  58. package/dist/components/form/form-input.cjs +1 -1
  59. package/dist/components/form/form-input.js +2 -0
  60. package/dist/components/form/form-select.cjs +1 -1
  61. package/dist/components/form/form-select.js +2 -0
  62. package/dist/components/form/form-switch.cjs +1 -1
  63. package/dist/components/form/form-switch.d.ts +1 -1
  64. package/dist/components/form/form-switch.js +58 -54
  65. package/dist/components/form/form-textarea.cjs +1 -1
  66. package/dist/components/form/form-textarea.d.ts +1 -1
  67. package/dist/components/form/form-textarea.js +29 -27
  68. package/dist/components/layout/app-sidebar.cjs +1 -1
  69. package/dist/components/layout/app-sidebar.d.ts +1 -0
  70. package/dist/components/layout/app-sidebar.js +36 -36
  71. package/dist/components/layout/breadcrumbs.cjs +1 -1
  72. package/dist/components/layout/breadcrumbs.d.ts +2 -1
  73. package/dist/components/layout/breadcrumbs.js +7 -7
  74. package/dist/components/modern/calendar-scheduler.cjs +1 -1
  75. package/dist/components/modern/calendar-scheduler.d.ts +5 -1
  76. package/dist/components/modern/calendar-scheduler.js +47 -28
  77. package/dist/components/modern/dual-list-picker.cjs +1 -1
  78. package/dist/components/modern/dual-list-picker.d.ts +5 -1
  79. package/dist/components/modern/dual-list-picker.js +81 -23
  80. package/dist/components/modern/rich-text-editor.cjs +1 -1
  81. package/dist/components/modern/rich-text-editor.d.ts +3 -1
  82. package/dist/components/modern/rich-text-editor.js +12 -9
  83. package/dist/components/modern/tour.cjs +1 -1
  84. package/dist/components/modern/tour.d.ts +5 -1
  85. package/dist/components/modern/tour.js +57 -35
  86. package/dist/components/navigation/command-bar.cjs +1 -1
  87. package/dist/components/navigation/command-bar.d.ts +3 -1
  88. package/dist/components/navigation/command-bar.js +10 -7
  89. package/dist/components/navigation/demo.cjs +1 -1
  90. package/dist/components/navigation/demo.js +0 -1
  91. package/dist/components/navigation/nav-tabs.cjs +1 -1
  92. package/dist/components/navigation/nav-tabs.js +39 -27
  93. package/dist/components/navigation/page-tabs.cjs +1 -1
  94. package/dist/components/navigation/page-tabs.js +41 -30
  95. package/dist/components/navigation/pagination.cjs +1 -1
  96. package/dist/components/navigation/pagination.d.ts +7 -1
  97. package/dist/components/navigation/pagination.js +48 -25
  98. package/dist/components/notifications/notification-center.cjs +1 -1
  99. package/dist/components/notifications/notification-center.d.ts +3 -1
  100. package/dist/components/notifications/notification-center.js +56 -38
  101. package/dist/components/notifications/toast.cjs +1 -1
  102. package/dist/components/notifications/toast.d.ts +1 -0
  103. package/dist/components/notifications/toast.js +4 -0
  104. package/dist/components/overlay/alert-dialog.cjs +1 -1
  105. package/dist/components/overlay/alert-dialog.js +1 -1
  106. package/dist/components/overlay/confirm-dialog.cjs +1 -1
  107. package/dist/components/overlay/confirm-dialog.d.ts +4 -2
  108. package/dist/components/overlay/confirm-dialog.js +31 -22
  109. package/dist/components/overlay/drawer.cjs +1 -1
  110. package/dist/components/overlay/drawer.d.ts +3 -1
  111. package/dist/components/overlay/drawer.js +24 -16
  112. package/dist/components/ui/accordion/index.d.ts +4 -0
  113. package/dist/components/ui/badge/index.cjs +1 -1
  114. package/dist/components/ui/badge/index.d.ts +1 -1
  115. package/dist/components/ui/badge/index.js +2 -1
  116. package/dist/components/ui/button/index.cjs +1 -1
  117. package/dist/components/ui/button/index.d.ts +2 -1
  118. package/dist/components/ui/button/index.js +13 -10
  119. package/dist/components/ui/dialog/index.cjs +1 -1
  120. package/dist/components/ui/dialog/index.js +2 -1
  121. package/dist/components/ui/hover-card.cjs +1 -1
  122. package/dist/components/ui/hover-card.d.ts +11 -3
  123. package/dist/components/ui/hover-card.js +29 -24
  124. package/dist/components/ui/input/index.d.ts +1 -1
  125. package/dist/components/ui/popover/index.cjs +1 -1
  126. package/dist/components/ui/popover/index.d.ts +2 -2
  127. package/dist/components/ui/popover/index.js +6 -5
  128. package/dist/components/ui/radio-group/index.cjs +1 -1
  129. package/dist/components/ui/radio-group/index.d.ts +5 -1
  130. package/dist/components/ui/radio-group/index.js +50 -16
  131. package/dist/components/ui/right-click-menu/index.cjs +1 -1
  132. package/dist/components/ui/right-click-menu/index.d.ts +5 -1
  133. package/dist/components/ui/right-click-menu/index.js +77 -23
  134. package/dist/components/ui/segmented-control/index.cjs +1 -1
  135. package/dist/components/ui/segmented-control/index.d.ts +2 -1
  136. package/dist/components/ui/segmented-control/index.js +23 -11
  137. package/dist/components/ui/select/index.cjs +1 -1
  138. package/dist/components/ui/select/index.d.ts +8 -1
  139. package/dist/components/ui/select/index.js +40 -35
  140. package/dist/components/ui/switch/index.cjs +1 -1
  141. package/dist/components/ui/switch/index.d.ts +18 -0
  142. package/dist/components/ui/switch/index.js +47 -17
  143. package/dist/components/ui/tabs/index.cjs +1 -1
  144. package/dist/components/ui/tabs/index.d.ts +14 -4
  145. package/dist/components/ui/tabs/index.js +11 -8
  146. package/dist/components/ui/textarea/index.cjs +1 -1
  147. package/dist/components/ui/textarea/index.d.ts +10 -2
  148. package/dist/components/ui/textarea/index.js +37 -8
  149. package/dist/components/ui/textarea.cjs +1 -0
  150. package/dist/components/ui/textarea.d.ts +1 -0
  151. package/dist/components/ui/textarea.js +2 -0
  152. package/dist/components/ui/tooltip/index.cjs +1 -1
  153. package/dist/components/ui/tooltip/index.d.ts +11 -3
  154. package/dist/components/ui/tooltip/index.js +41 -20
  155. package/dist/components/upload/file-upload.cjs +1 -1
  156. package/dist/components/upload/file-upload.d.ts +8 -1
  157. package/dist/components/upload/file-upload.js +132 -100
  158. package/dist/components/upload/image-upload.cjs +1 -1
  159. package/dist/components/upload/image-upload.d.ts +5 -1
  160. package/dist/components/upload/image-upload.js +34 -9
  161. package/dist/index.cjs +1 -1
  162. package/dist/index.js +31 -31
  163. package/dist/public-component-surface.cjs +1 -1
  164. package/dist/public-component-surface.js +15 -0
  165. package/dist/showcase/component-api-schema.cjs +1 -1
  166. package/dist/showcase/component-api-schema.js +187 -10
  167. package/dist/showcase/fallback.cjs +3 -3
  168. package/dist/showcase/fallback.js +221 -243
  169. package/dist/showcase/premium/alert/showcase.cjs +1 -1
  170. package/dist/showcase/premium/alert/showcase.js +1 -0
  171. package/dist/showcase/premium/app-sidebar/showcase.cjs +1 -1
  172. package/dist/showcase/premium/app-sidebar/showcase.js +1 -0
  173. package/dist/showcase/premium/badge/showcase.cjs +1 -1
  174. package/dist/showcase/premium/badge/showcase.js +7 -0
  175. package/dist/showcase/premium/badge/types.d.ts +1 -1
  176. package/dist/showcase/premium/breadcrumbs/showcase.cjs +1 -1
  177. package/dist/showcase/premium/breadcrumbs/showcase.js +12 -1
  178. package/dist/showcase/premium/button/mock.cjs +1 -4
  179. package/dist/showcase/premium/button/mock.js +1 -1
  180. package/dist/showcase/premium/button/showcase.cjs +1 -1
  181. package/dist/showcase/premium/button/showcase.js +2 -2
  182. package/dist/showcase/premium/card/showcase.cjs +1 -1
  183. package/dist/showcase/premium/card/showcase.js +96 -47
  184. package/dist/showcase/premium/carousel/showcase.cjs +1 -1
  185. package/dist/showcase/premium/carousel/showcase.js +76 -49
  186. package/dist/showcase/premium/command-bar/showcase.cjs +1 -1
  187. package/dist/showcase/premium/command-bar/showcase.js +2 -0
  188. package/dist/showcase/premium/data-table/mock.cjs +12 -11
  189. package/dist/showcase/premium/data-table/mock.js +1 -1
  190. package/dist/showcase/premium/file-upload/showcase.cjs +1 -1
  191. package/dist/showcase/premium/file-upload/showcase.js +25 -4
  192. package/dist/showcase/premium/image-upload/showcase.cjs +1 -1
  193. package/dist/showcase/premium/image-upload/showcase.js +4 -1
  194. package/dist/showcase/premium/index.cjs +1 -1
  195. package/dist/showcase/premium/index.js +396 -402
  196. package/dist/showcase/premium/loading-state/showcase.cjs +1 -1
  197. package/dist/showcase/premium/loading-state/showcase.js +3 -1
  198. package/dist/showcase/premium/metric-grid/showcase.cjs +1 -1
  199. package/dist/showcase/premium/metric-grid/showcase.js +96 -28
  200. package/dist/showcase/premium/notification-center/showcase.cjs +1 -1
  201. package/dist/showcase/premium/notification-center/showcase.js +7 -3
  202. package/dist/showcase/premium/page-state/showcase.cjs +1 -1
  203. package/dist/showcase/premium/page-state/showcase.js +5 -1
  204. package/dist/showcase/premium/pagination/showcase.cjs +1 -1
  205. package/dist/showcase/premium/pagination/showcase.js +15 -2
  206. package/dist/showcase/premium/popover/showcase.cjs +1 -1
  207. package/dist/showcase/premium/popover/showcase.js +85 -50
  208. package/dist/showcase/premium/radio-group/showcase.cjs +1 -1
  209. package/dist/showcase/premium/radio-group/showcase.js +27 -4
  210. package/dist/showcase/premium/right-click-menu/showcase.cjs +1 -1
  211. package/dist/showcase/premium/right-click-menu/showcase.js +56 -43
  212. package/dist/showcase/premium/segmented-control/showcase.cjs +1 -1
  213. package/dist/showcase/premium/segmented-control/showcase.js +1 -0
  214. package/dist/showcase/premium/select/data.cjs +1 -1
  215. package/dist/showcase/premium/select/data.js +69 -34
  216. package/dist/showcase/premium/select/mock.cjs +19 -6
  217. package/dist/showcase/premium/select/mock.js +3 -2
  218. package/dist/showcase/premium/select/showcase.cjs +1 -1
  219. package/dist/showcase/premium/select/showcase.js +43 -18
  220. package/dist/showcase/premium/select/types.d.ts +3 -0
  221. package/dist/showcase/premium/statistic/showcase.cjs +1 -1
  222. package/dist/showcase/premium/statistic/showcase.js +57 -25
  223. package/dist/showcase/premium/switch/showcase.cjs +1 -1
  224. package/dist/showcase/premium/switch/showcase.js +25 -14
  225. package/dist/showcase/premium/tabs/showcase.cjs +1 -1
  226. package/dist/showcase/premium/tabs/showcase.js +171 -48
  227. package/dist/showcase/premium/textarea/mock.cjs +12 -4
  228. package/dist/showcase/premium/textarea/mock.js +1 -1
  229. package/dist/showcase/premium/textarea/showcase.cjs +1 -1
  230. package/dist/showcase/premium/textarea/showcase.js +8 -3
  231. package/dist/showcase/premium/toast/showcase.cjs +1 -1
  232. package/dist/showcase/premium/toast/showcase.js +32 -6
  233. package/dist/showcase/premium/types.d.ts +1 -1
  234. package/dist/showcase/registry-quality.cjs +1 -1
  235. package/dist/showcase/registry-quality.js +1 -0
  236. package/dist/showcase/render-registry-preview.cjs +1 -1
  237. package/dist/showcase/render-registry-preview.js +57 -79
  238. package/dist/showcase/site-data.cjs +1 -1
  239. package/dist/showcase/site-data.js +60 -21
  240. package/dist/showcase/tembro-registry.json.cjs +1 -1
  241. package/dist/showcase/tembro-registry.json.js +34 -20
  242. package/dist/showcase/types.d.ts +1 -1
  243. package/package.json +1 -1
  244. package/packages/cli/dist/index.cjs +31 -31
  245. package/packages/cli/vendor/src/components/calendar/calendar.tsx +59 -50
  246. package/packages/cli/vendor/src/components/calendar/date-range-picker.tsx +7 -4
  247. package/packages/cli/vendor/src/components/charts/charts.tsx +109 -66
  248. package/packages/cli/vendor/src/components/charts/progress-ring.tsx +37 -26
  249. package/packages/cli/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +41 -22
  250. package/packages/cli/vendor/src/components/data-table/data-table-toolbar.tsx +8 -6
  251. package/packages/cli/vendor/src/components/display/carousel.tsx +84 -3
  252. package/packages/cli/vendor/src/components/display/code-block.tsx +22 -2
  253. package/packages/cli/vendor/src/components/display/delta-badge.tsx +11 -11
  254. package/packages/cli/vendor/src/components/display/kanban.tsx +103 -57
  255. package/packages/cli/vendor/src/components/display/metric-grid.tsx +16 -13
  256. package/packages/cli/vendor/src/components/display/qr-code.tsx +17 -15
  257. package/packages/cli/vendor/src/components/display/status-legend.tsx +11 -8
  258. package/packages/cli/vendor/src/components/display/tag.tsx +39 -21
  259. package/packages/cli/vendor/src/components/display/tree-view.tsx +221 -84
  260. package/packages/cli/vendor/src/components/display/trend-card.tsx +6 -40
  261. package/packages/cli/vendor/src/components/feedback/alert.tsx +3 -1
  262. package/packages/cli/vendor/src/components/feedback/loading-state.tsx +33 -17
  263. package/packages/cli/vendor/src/components/feedback/page-state.tsx +8 -7
  264. package/packages/cli/vendor/src/components/form/form-field-shell.tsx +37 -8
  265. package/packages/cli/vendor/src/components/form/form-input.tsx +2 -0
  266. package/packages/cli/vendor/src/components/form/form-select.tsx +2 -0
  267. package/packages/cli/vendor/src/components/form/form-switch.tsx +9 -3
  268. package/packages/cli/vendor/src/components/form/form-textarea.tsx +6 -2
  269. package/packages/cli/vendor/src/components/layout/app-sidebar.tsx +3 -1
  270. package/packages/cli/vendor/src/components/layout/breadcrumbs.tsx +3 -1
  271. package/packages/cli/vendor/src/components/modern/calendar-scheduler.tsx +28 -13
  272. package/packages/cli/vendor/src/components/modern/dual-list-picker.tsx +103 -35
  273. package/packages/cli/vendor/src/components/modern/rich-text-editor.tsx +25 -22
  274. package/packages/cli/vendor/src/components/modern/tour.tsx +47 -29
  275. package/packages/cli/vendor/src/components/navigation/command-bar.tsx +6 -0
  276. package/packages/cli/vendor/src/components/navigation/demo.tsx +0 -1
  277. package/packages/cli/vendor/src/components/navigation/nav-tabs.tsx +38 -29
  278. package/packages/cli/vendor/src/components/navigation/page-tabs.tsx +35 -23
  279. package/packages/cli/vendor/src/components/navigation/pagination.tsx +65 -31
  280. package/packages/cli/vendor/src/components/notifications/notification-center.tsx +64 -39
  281. package/packages/cli/vendor/src/components/notifications/toast.tsx +23 -21
  282. package/packages/cli/vendor/src/components/overlay/alert-dialog.tsx +1 -1
  283. package/packages/cli/vendor/src/components/overlay/confirm-dialog.tsx +45 -22
  284. package/packages/cli/vendor/src/components/overlay/drawer.tsx +18 -5
  285. package/packages/cli/vendor/src/components/ui/accordion/index.tsx +4 -0
  286. package/packages/cli/vendor/src/components/ui/badge/index.tsx +2 -1
  287. package/packages/cli/vendor/src/components/ui/button/index.tsx +11 -5
  288. package/packages/cli/vendor/src/components/ui/dialog/index.tsx +2 -1
  289. package/packages/cli/vendor/src/components/ui/hover-card.tsx +54 -28
  290. package/packages/cli/vendor/src/components/ui/popover/index.tsx +10 -8
  291. package/packages/cli/vendor/src/components/ui/radio-group/index.tsx +55 -6
  292. package/packages/cli/vendor/src/components/ui/right-click-menu/index.tsx +120 -9
  293. package/packages/cli/vendor/src/components/ui/segmented-control/index.tsx +29 -3
  294. package/packages/cli/vendor/src/components/ui/select/index.tsx +64 -31
  295. package/packages/cli/vendor/src/components/ui/switch/index.tsx +71 -6
  296. package/packages/cli/vendor/src/components/ui/tabs/index.tsx +22 -6
  297. package/packages/cli/vendor/src/components/ui/textarea/index.tsx +105 -15
  298. package/packages/cli/vendor/src/components/ui/textarea.tsx +2 -0
  299. package/packages/cli/vendor/src/components/ui/tooltip/index.tsx +67 -22
  300. package/packages/cli/vendor/src/components/upload/file-upload.tsx +120 -57
  301. package/packages/cli/vendor/src/components/upload/image-upload.tsx +71 -24
  302. package/packages/cli/vendor/src/public-component-surface.ts +3 -0
  303. package/packages/cli/vendor/src/showcase/component-api-schema.ts +79 -41
  304. package/packages/cli/vendor/src/showcase/fallback.tsx +4 -19
  305. package/packages/cli/vendor/src/showcase/premium/alert/showcase.tsx +1 -0
  306. package/packages/cli/vendor/src/showcase/premium/app-sidebar/showcase.tsx +1 -0
  307. package/packages/cli/vendor/src/showcase/premium/badge/showcase.tsx +4 -2
  308. package/packages/cli/vendor/src/showcase/premium/badge/types.ts +1 -1
  309. package/packages/cli/vendor/src/showcase/premium/breadcrumbs/showcase.tsx +3 -1
  310. package/packages/cli/vendor/src/showcase/premium/button/mock.ts +2 -5
  311. package/packages/cli/vendor/src/showcase/premium/button/showcase.tsx +2 -2
  312. package/packages/cli/vendor/src/showcase/premium/card/showcase.tsx +26 -1
  313. package/packages/cli/vendor/src/showcase/premium/carousel/showcase.tsx +19 -3
  314. package/packages/cli/vendor/src/showcase/premium/command-bar/showcase.tsx +1 -1
  315. package/packages/cli/vendor/src/showcase/premium/data-table/mock.ts +26 -25
  316. package/packages/cli/vendor/src/showcase/premium/file-upload/showcase.tsx +21 -1
  317. package/packages/cli/vendor/src/showcase/premium/image-upload/showcase.tsx +4 -1
  318. package/packages/cli/vendor/src/showcase/premium/index.ts +0 -2
  319. package/packages/cli/vendor/src/showcase/premium/loading-state/showcase.tsx +1 -1
  320. package/packages/cli/vendor/src/showcase/premium/metric-grid/showcase.tsx +36 -4
  321. package/packages/cli/vendor/src/showcase/premium/notification-center/showcase.tsx +4 -3
  322. package/packages/cli/vendor/src/showcase/premium/page-state/showcase.tsx +1 -0
  323. package/packages/cli/vendor/src/showcase/premium/pagination/showcase.tsx +13 -1
  324. package/packages/cli/vendor/src/showcase/premium/popover/showcase.tsx +27 -11
  325. package/packages/cli/vendor/src/showcase/premium/radio-group/showcase.tsx +13 -1
  326. package/packages/cli/vendor/src/showcase/premium/right-click-menu/showcase.tsx +8 -5
  327. package/packages/cli/vendor/src/showcase/premium/segmented-control/showcase.tsx +1 -0
  328. package/packages/cli/vendor/src/showcase/premium/select/data.ts +12 -3
  329. package/packages/cli/vendor/src/showcase/premium/select/mock.ts +4 -4
  330. package/packages/cli/vendor/src/showcase/premium/select/showcase.tsx +22 -1
  331. package/packages/cli/vendor/src/showcase/premium/select/types.ts +3 -0
  332. package/packages/cli/vendor/src/showcase/premium/statistic/showcase.tsx +10 -1
  333. package/packages/cli/vendor/src/showcase/premium/switch/showcase.tsx +15 -6
  334. package/packages/cli/vendor/src/showcase/premium/tabs/showcase.tsx +48 -1
  335. package/packages/cli/vendor/src/showcase/premium/textarea/mock.ts +12 -4
  336. package/packages/cli/vendor/src/showcase/premium/textarea/showcase.tsx +5 -0
  337. package/packages/cli/vendor/src/showcase/premium/toast/showcase.tsx +17 -1
  338. package/packages/cli/vendor/src/showcase/premium/types.ts +1 -1
  339. package/packages/cli/vendor/src/showcase/registry-quality.ts +3 -2
  340. package/packages/cli/vendor/src/showcase/render-registry-preview.tsx +0 -15
  341. package/packages/cli/vendor/src/showcase/site-data.tsx +21 -15
  342. package/packages/cli/vendor/src/showcase/tembro-registry.json +42 -20
  343. package/packages/cli/vendor/src/showcase/types.ts +1 -1
  344. package/registry.json +18 -6
@@ -10,6 +10,8 @@ export type FormFieldShellProps = React.ComponentProps<"div"> & {
10
10
  label?: React.ReactNode
11
11
  description?: React.ReactNode
12
12
  error?: React.ReactNode
13
+ success?: React.ReactNode
14
+ loading?: boolean
13
15
  required?: boolean
14
16
  htmlFor?: string
15
17
  labelId?: string
@@ -34,6 +36,8 @@ export type FormFieldShellControlProps = Pick<
34
36
  FormFieldShellProps,
35
37
  | "label"
36
38
  | "description"
39
+ | "success"
40
+ | "loading"
37
41
  | "required"
38
42
  | "className"
39
43
  | "htmlFor"
@@ -89,6 +93,8 @@ function FormFieldShell({
89
93
  label,
90
94
  description,
91
95
  error,
96
+ success,
97
+ loading = false,
92
98
  required = false,
93
99
  htmlFor,
94
100
  labelId,
@@ -181,13 +187,30 @@ function FormFieldShell({
181
187
  {showErrorIcon && <span className="mt-1 shrink-0">{resolvedErrorIcon}</span>}
182
188
  <span className="min-w-0">{error}</span>
183
189
  </p>
184
- ) : null
185
-
186
- return (
190
+ ) : null
191
+
192
+ const successNode = success && !error ? (
193
+ <p
194
+ data-slot="form-field-success"
195
+ className="rounded-[min(var(--radius-xl),16px)] border border-emerald-500/18 bg-emerald-500/8 px-3 py-2 text-sm font-medium leading-6 text-emerald-700 dark:text-emerald-300"
196
+ >
197
+ {success}
198
+ </p>
199
+ ) : null
200
+
201
+ const loadingNode = loading ? (
202
+ <p data-slot="form-field-loading" className="text-sm leading-6 text-muted-foreground">
203
+ Loading...
204
+ </p>
205
+ ) : null
206
+
207
+ return (
187
208
  <div
188
209
  data-slot="form-field-shell"
189
210
  data-layout={layout}
190
211
  data-invalid={Boolean(error) || undefined}
212
+ data-success={Boolean(success && !error) || undefined}
213
+ data-loading={loading || undefined}
191
214
  data-disabled={disabled || undefined}
192
215
  data-readonly={readOnly || undefined}
193
216
  aria-disabled={disabled || undefined}
@@ -202,7 +225,9 @@ function FormFieldShell({
202
225
  </div>
203
226
  <div className="grid min-w-0 gap-2">
204
227
  {content}
228
+ {loadingNode}
205
229
  {hasDescriptionBottom && descriptionNode}
230
+ {successNode}
206
231
  {errorNode}
207
232
  </div>
208
233
  </>
@@ -212,17 +237,21 @@ function FormFieldShell({
212
237
  <div className="grid min-w-0 flex-1 gap-2">
213
238
  {hasDescriptionTop && descriptionNode}
214
239
  {content}
240
+ {loadingNode}
215
241
  {hasDescriptionBottom && descriptionNode}
216
- {errorNode}
242
+ {successNode}
243
+ {errorNode}
217
244
  </div>
218
245
  </>
219
246
  ) : (
220
247
  <>
221
248
  {header}
222
- {hasDescriptionTop && descriptionNode}
223
- {content}
224
- {hasDescriptionBottom && descriptionNode}
225
- {errorNode}
249
+ {hasDescriptionTop && descriptionNode}
250
+ {content}
251
+ {loadingNode}
252
+ {hasDescriptionBottom && descriptionNode}
253
+ {successNode}
254
+ {errorNode}
226
255
  </>
227
256
  )}
228
257
  </div>
@@ -192,6 +192,8 @@ function buildShellProps<
192
192
  return {
193
193
  label: props.label,
194
194
  description: props.description,
195
+ success: props.success,
196
+ loading: props.loading,
195
197
  required: props.required,
196
198
  className: props.className,
197
199
  htmlFor: props.id ?? props.name,
@@ -67,6 +67,8 @@ function buildShellProps<
67
67
  return {
68
68
  label: props.label,
69
69
  description: props.description,
70
+ success: props.success,
71
+ loading: props.loading,
70
72
  required: props.required,
71
73
  className: props.className,
72
74
  htmlFor: props.name,
@@ -29,9 +29,11 @@ function FormSwitch<
29
29
  >({
30
30
  control,
31
31
  name,
32
- label,
33
- description,
34
- required,
32
+ label,
33
+ description,
34
+ success,
35
+ loading,
36
+ required,
35
37
  className,
36
38
  layout,
37
39
  descriptionPosition,
@@ -96,6 +98,8 @@ function FormSwitch<
96
98
  <FormFieldShell
97
99
  label={label}
98
100
  description={description}
101
+ success={success}
102
+ loading={loading}
99
103
  required={required}
100
104
  error={error}
101
105
  htmlFor={switchId}
@@ -122,6 +126,8 @@ function FormSwitch<
122
126
  ) : (
123
127
  <FormFieldShell
124
128
  error={error}
129
+ success={success}
130
+ loading={loading}
125
131
  className={className}
126
132
  descriptionId={resolvedIds.descriptionId}
127
133
  errorId={resolvedIds.errorId}
@@ -29,8 +29,10 @@ function FormTextarea<
29
29
  name,
30
30
  rules,
31
31
  label,
32
- description,
33
- required,
32
+ description,
33
+ success,
34
+ loading,
35
+ required,
34
36
  className,
35
37
  layout,
36
38
  descriptionPosition,
@@ -68,6 +70,8 @@ function FormTextarea<
68
70
  <FormFieldShell
69
71
  label={label}
70
72
  description={description}
73
+ success={success}
74
+ loading={loading}
71
75
  required={required}
72
76
  error={error}
73
77
  htmlFor={textareaId}
@@ -59,6 +59,7 @@ export type AppSidebarProps = React.ComponentProps<"aside"> & {
59
59
  mobileToggleClassName?: string
60
60
  mobilePanelClassName?: string
61
61
  mobileOverlayClassName?: string
62
+ footerClassName?: string
62
63
  renderMobileToggle?: (state: { open: boolean; setOpen: (open: boolean) => void }) => React.ReactNode
63
64
  onItemSelect?: (item: AppSidebarNavItem) => void
64
65
  renderItem?: (item: AppSidebarNavItem, state: { collapsed: boolean }) => React.ReactNode
@@ -433,6 +434,7 @@ function SidebarSurface({
433
434
  footerAccount,
434
435
  secondaryActions = [],
435
436
  footerSecondary,
437
+ footerClassName,
436
438
  tooltipOnCollapsed,
437
439
  onItemSelect,
438
440
  renderItem,
@@ -531,7 +533,7 @@ function SidebarSurface({
531
533
  </nav>
532
534
 
533
535
  {(footerAccount || footerSecondary || footer || visibleSecondaryActions.length > 0 || (collapsed && (collapsedRail || visibleRailItems.length > 0))) && (
534
- <div data-slot="app-sidebar-footer" className="shrink-0 border-t p-3">
536
+ <div data-slot="app-sidebar-footer" className={cn("shrink-0 border-t p-3", footerClassName)}>
535
537
  {collapsed ? (
536
538
  <>
537
539
  {visibleRailItems.length > 0 ? (
@@ -19,6 +19,7 @@ export type BreadcrumbsProps = React.ComponentProps<"nav"> & {
19
19
  collapseLabel?: React.ReactNode
20
20
  separator?: React.ReactNode
21
21
  wrap?: boolean
22
+ currentItemLabel?: React.AriaAttributes["aria-current"]
22
23
  renderLink?: (props: React.ComponentProps<"a"> & { item: BreadcrumbItem; [key: `data-${string}`]: string | boolean | undefined }) => React.ReactNode
23
24
  }
24
25
 
@@ -46,6 +47,7 @@ function Breadcrumbs({
46
47
  collapseLabel = "…",
47
48
  separator = <ChevronRightIcon className="size-3.5" />,
48
49
  wrap = false,
50
+ currentItemLabel,
49
51
  renderLink,
50
52
  ...props
51
53
  }: BreadcrumbsProps) {
@@ -106,7 +108,7 @@ function Breadcrumbs({
106
108
  ) : (
107
109
  <span
108
110
  data-slot="breadcrumbs-current"
109
- aria-current={isCurrent ? (item.currentLabel ?? "page") : undefined}
111
+ aria-current={isCurrent ? ((item.currentLabel ?? currentItemLabel ?? "page") as React.AriaAttributes["aria-current"]) : undefined}
110
112
  className={cn(
111
113
  "inline-flex min-w-0 items-center gap-1.5 truncate rounded-[var(--radius-sm)] px-1 py-0.5",
112
114
  isCurrent && "bg-accent/45 font-medium text-foreground"
@@ -2,18 +2,22 @@ import * as React from "react"
2
2
 
3
3
  import { cn } from "@/lib/utils"
4
4
 
5
- export type CalendarSchedulerEvent = {
6
- id: string
7
- title: React.ReactNode
8
- date: string
9
- time?: string
10
- tone?: "default" | "success" | "warning" | "danger"
11
- }
12
-
5
+ export type CalendarSchedulerEvent = {
6
+ id: string
7
+ title: React.ReactNode
8
+ date: string
9
+ time?: string
10
+ tone?: "default" | "success" | "warning" | "danger"
11
+ durationMinutes?: number
12
+ }
13
+
13
14
  export type CalendarSchedulerProps = React.ComponentProps<"div"> & {
14
15
  events: CalendarSchedulerEvent[]
15
16
  days?: string[]
17
+ view?: "day" | "week" | "month"
16
18
  empty?: React.ReactNode
19
+ onCreateEvent?: (date: string) => void
20
+ onEventClick?: (event: CalendarSchedulerEvent) => void
17
21
  }
18
22
 
19
23
  const toneClassName = {
@@ -23,11 +27,11 @@ const toneClassName = {
23
27
  danger: "border-red-200 bg-red-50 text-red-700 dark:border-red-900 dark:bg-red-950 dark:text-red-300",
24
28
  }
25
29
 
26
- function CalendarScheduler({ events, days, empty = "No events scheduled.", className, ...props }: CalendarSchedulerProps) {
30
+ function CalendarScheduler({ events, days, view = "week", empty = "No events scheduled.", onCreateEvent, onEventClick, className, ...props }: CalendarSchedulerProps) {
27
31
  const visibleDays = days ?? Array.from(new Set(events.map((event) => event.date)))
28
32
 
29
33
  return (
30
- <div data-slot="calendar-scheduler" className={cn("grid gap-3", className)} {...props}>
34
+ <div data-slot="calendar-scheduler" data-view={view} className={cn("grid gap-3", view === "month" && "md:grid-cols-2 xl:grid-cols-3", className)} {...props}>
31
35
  {visibleDays.map((day) => (
32
36
  <section key={day} className="rounded-[var(--aui-card-radius,var(--radius-xl))] border border-[color:var(--aui-card-border,var(--border))] bg-card p-4 shadow-[var(--aui-card-shadow,var(--aui-control-shadow,none))]">
33
37
  <div className="mb-3 flex items-center justify-between gap-3">
@@ -41,16 +45,27 @@ function CalendarScheduler({ events, days, empty = "No events scheduled.", class
41
45
  </div>
42
46
  ) : (
43
47
  events.filter((event) => event.date === day).map((event) => (
44
- <div key={event.id} className={cn("rounded-[var(--radius-md)] border px-3 py-2.5 text-sm shadow-sm", toneClassName[event.tone ?? "default"])}>
48
+ <button
49
+ key={event.id}
50
+ type="button"
51
+ className={cn("rounded-[var(--radius-md)] border px-3 py-2.5 text-left text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40", toneClassName[event.tone ?? "default"])}
52
+ onClick={() => onEventClick?.(event)}
53
+ >
45
54
  <div className="font-medium">{event.title}</div>
46
55
  {event.time && <div className="mt-1 text-xs opacity-70">{event.time}</div>}
47
- </div>
56
+ {event.durationMinutes && <div className="mt-1 text-xs opacity-70">{event.durationMinutes} min</div>}
57
+ </button>
48
58
  ))
49
59
  )}
50
60
  </div>
61
+ {onCreateEvent && (
62
+ <button type="button" className="mt-3 w-full rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground hover:bg-muted/50" onClick={() => onCreateEvent(day)}>
63
+ Create event
64
+ </button>
65
+ )}
51
66
  </section>
52
67
  ))}
53
- </div>
68
+ </div>
54
69
  )
55
70
  }
56
71
 
@@ -8,44 +8,112 @@ export type DualListItem = {
8
8
  disabled?: boolean
9
9
  }
10
10
 
11
- export type DualListPickerProps = React.ComponentProps<"div"> & {
12
- items: DualListItem[]
13
- picked?: string[]
14
- onPickedChange?: (value: string[]) => void
15
- availableTitle?: React.ReactNode
16
- pickedTitle?: React.ReactNode
17
- }
18
-
19
- function DualListPicker({ items, picked = [], onPickedChange, availableTitle = "Available", pickedTitle = "Selected", className, ...props }: DualListPickerProps) {
20
- const pickedSet = new Set(picked)
21
- const availableItems = items.filter((item) => !pickedSet.has(item.value))
22
- const pickedItems = items.filter((item) => pickedSet.has(item.value))
23
-
24
- function toggle(value: string) {
25
- const next = pickedSet.has(value) ? picked.filter((item) => item !== value) : [...picked, value]
26
- onPickedChange?.(next)
27
- }
28
-
29
- const renderColumn = (title: React.ReactNode, columnItems: DualListItem[]) => (
30
- <div className="min-h-48 rounded-lg border bg-card">
31
- <div className="border-b px-3 py-2 text-sm font-medium">{title}</div>
32
- <div className="grid gap-1 p-2">
33
- {columnItems.map((item) => (
34
- <button key={item.value} type="button" disabled={item.disabled} className="flex items-center justify-between rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted disabled:opacity-50" onClick={() => toggle(item.value)}>
35
- <span>{item.label}</span>
36
- <span className="text-muted-foreground">{pickedSet.has(item.value) ? "" : "+"}</span>
37
- </button>
11
+ export type DualListPickerProps = React.ComponentProps<"div"> & {
12
+ items: DualListItem[]
13
+ picked?: string[]
14
+ onPickedChange?: (value: string[]) => void
15
+ availableTitle?: React.ReactNode
16
+ pickedTitle?: React.ReactNode
17
+ searchPlaceholder?: string
18
+ emptyMessage?: React.ReactNode
19
+ maxPicked?: number
20
+ transferAll?: boolean
21
+ }
22
+
23
+ function DualListPicker({
24
+ items,
25
+ picked = [],
26
+ onPickedChange,
27
+ availableTitle = "Available",
28
+ pickedTitle = "Selected",
29
+ searchPlaceholder = "Search items...",
30
+ emptyMessage = "No items.",
31
+ maxPicked,
32
+ transferAll = true,
33
+ className,
34
+ ...props
35
+ }: DualListPickerProps) {
36
+ const [query, setQuery] = React.useState("")
37
+ const pickedSet = new Set(picked)
38
+ const normalizedQuery = query.trim().toLowerCase()
39
+ const matchesQuery = (item: DualListItem) => {
40
+ if (!normalizedQuery) return true
41
+ return String(item.label).toLowerCase().includes(normalizedQuery) || item.value.toLowerCase().includes(normalizedQuery)
42
+ }
43
+ const availableItems = items.filter((item) => !pickedSet.has(item.value) && matchesQuery(item))
44
+ const pickedItems = items.filter((item) => pickedSet.has(item.value) && matchesQuery(item))
45
+ const maxReached = maxPicked !== undefined && picked.length >= maxPicked
46
+
47
+ function toggle(value: string) {
48
+ const isPicked = pickedSet.has(value)
49
+ if (!isPicked && maxReached) return
50
+ const next = isPicked ? picked.filter((item) => item !== value) : [...picked, value]
51
+ onPickedChange?.(next)
52
+ }
53
+
54
+ function addAll() {
55
+ const next = [...picked]
56
+ for (const item of items) {
57
+ if (item.disabled || pickedSet.has(item.value)) continue
58
+ if (maxPicked !== undefined && next.length >= maxPicked) break
59
+ next.push(item.value)
60
+ }
61
+ onPickedChange?.(next)
62
+ }
63
+
64
+ function removeAll() {
65
+ onPickedChange?.([])
66
+ }
67
+
68
+ const renderColumn = (title: React.ReactNode, columnItems: DualListItem[], mode: "available" | "picked") => (
69
+ <div className="min-h-48 rounded-lg border bg-card">
70
+ <div className="flex items-center justify-between gap-2 border-b px-3 py-2 text-sm font-medium">
71
+ <span>{title}</span>
72
+ <span className="text-xs font-normal text-muted-foreground">{columnItems.length}</span>
73
+ </div>
74
+ <div className="grid gap-1 p-2">
75
+ {columnItems.length === 0 ? (
76
+ <div className="rounded-md border border-dashed px-3 py-6 text-center text-sm text-muted-foreground">{emptyMessage}</div>
77
+ ) : columnItems.map((item) => (
78
+ <button
79
+ key={item.value}
80
+ type="button"
81
+ disabled={item.disabled || (mode === "available" && maxReached)}
82
+ className="flex items-center justify-between rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:opacity-50"
83
+ aria-pressed={pickedSet.has(item.value)}
84
+ onClick={() => toggle(item.value)}
85
+ >
86
+ <span>{item.label}</span>
87
+ <span className="text-muted-foreground">{pickedSet.has(item.value) ? "−" : "+"}</span>
88
+ </button>
38
89
  ))}
39
90
  </div>
40
91
  </div>
41
92
  )
42
-
43
- return (
44
- <div data-slot="dual-list-picker" className={cn("grid gap-3 md:grid-cols-2", className)} {...props}>
45
- {renderColumn(availableTitle, availableItems)}
46
- {renderColumn(pickedTitle, pickedItems)}
47
- </div>
48
- )
49
- }
93
+
94
+ return (
95
+ <div data-slot="dual-list-picker" className={cn("grid gap-3", className)} {...props}>
96
+ <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
97
+ <input
98
+ value={query}
99
+ placeholder={searchPlaceholder}
100
+ className="h-9 min-w-0 rounded-md border bg-background px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/40 sm:max-w-xs"
101
+ onChange={(event) => setQuery(event.currentTarget.value)}
102
+ />
103
+ {transferAll && (
104
+ <div className="flex gap-2">
105
+ <button type="button" className="rounded-md border px-3 py-1.5 text-sm disabled:opacity-50" disabled={maxReached} onClick={addAll}>Add all</button>
106
+ <button type="button" className="rounded-md border px-3 py-1.5 text-sm disabled:opacity-50" disabled={picked.length === 0} onClick={removeAll}>Remove all</button>
107
+ </div>
108
+ )}
109
+ </div>
110
+ <div className="grid gap-3 md:grid-cols-2">
111
+ {renderColumn(availableTitle, availableItems, "available")}
112
+ {renderColumn(pickedTitle, pickedItems, "picked")}
113
+ </div>
114
+ {maxPicked !== undefined && <div className="text-xs text-muted-foreground">{picked.length} / {maxPicked} selected</div>}
115
+ </div>
116
+ )
117
+ }
50
118
 
51
119
  export { DualListPicker }
@@ -2,14 +2,16 @@ import * as React from "react"
2
2
 
3
3
  import { cn } from "@/lib/utils"
4
4
 
5
- export type RichTextEditorProps = Omit<React.ComponentProps<"div">, "onChange"> & {
6
- value?: string
7
- onValueChange?: (value: string) => void
8
- placeholder?: string
9
- }
10
-
11
- function RichTextEditor({ value, onValueChange, placeholder = "Write something...", className, ...props }: RichTextEditorProps) {
12
- const ref = React.useRef<HTMLDivElement | null>(null)
5
+ export type RichTextEditorProps = Omit<React.ComponentProps<"div">, "onChange"> & {
6
+ value?: string
7
+ onValueChange?: (value: string) => void
8
+ placeholder?: string
9
+ output?: "html" | "text"
10
+ disabled?: boolean
11
+ }
12
+
13
+ function RichTextEditor({ value, onValueChange, placeholder = "Write something...", output = "html", disabled = false, className, ...props }: RichTextEditorProps) {
14
+ const ref = React.useRef<HTMLDivElement | null>(null)
13
15
 
14
16
  React.useEffect(() => {
15
17
  if (ref.current && value !== undefined && ref.current.innerHTML !== value) {
@@ -18,27 +20,28 @@ function RichTextEditor({ value, onValueChange, placeholder = "Write something..
18
20
  }, [value])
19
21
 
20
22
  return (
21
- <div data-slot="rich-text-editor" className={cn("grid gap-2 rounded-lg border bg-background p-2", className)} {...props}>
22
- <div className="flex flex-wrap gap-1 border-b pb-2">
23
+ <div data-slot="rich-text-editor" data-disabled={disabled || undefined} className={cn("grid gap-2 rounded-lg border bg-background p-2", disabled && "opacity-60", className)} {...props}>
24
+ <div className="flex flex-wrap gap-1 border-b pb-2">
23
25
  {[
24
26
  ["bold", "B"],
25
27
  ["italic", "I"],
26
28
  ["underline", "U"],
27
29
  ].map(([command, label]) => (
28
- <button key={command} type="button" className="rounded border px-2 py-1 text-xs font-medium" onClick={() => document.execCommand(command)}>
29
- {label}
30
- </button>
30
+ <button key={command} type="button" disabled={disabled} className="rounded border px-2 py-1 text-xs font-medium disabled:opacity-50" onClick={() => document.execCommand(command)}>
31
+ {label}
32
+ </button>
31
33
  ))}
32
34
  </div>
33
35
  <div
34
- ref={ref}
35
- contentEditable
36
- data-placeholder={placeholder}
37
- className="min-h-32 rounded-md p-2 text-sm outline-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]"
38
- onInput={(event) => onValueChange?.(event.currentTarget.innerHTML)}
39
- />
40
- </div>
41
- )
42
- }
36
+ ref={ref}
37
+ contentEditable={!disabled}
38
+ aria-disabled={disabled || undefined}
39
+ data-placeholder={placeholder}
40
+ className="min-h-32 rounded-md p-2 text-sm outline-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]"
41
+ onInput={(event) => onValueChange?.(output === "text" ? event.currentTarget.textContent ?? "" : event.currentTarget.innerHTML)}
42
+ />
43
+ </div>
44
+ )
45
+ }
43
46
 
44
47
  export { RichTextEditor }
@@ -2,38 +2,56 @@ import * as React from "react"
2
2
 
3
3
  import { cn } from "@/lib/utils"
4
4
 
5
- export type TourStep = {
6
- title: React.ReactNode
7
- description?: React.ReactNode
8
- }
5
+ export type TourStep = {
6
+ title: React.ReactNode
7
+ description?: React.ReactNode
8
+ target?: string
9
+ }
9
10
 
10
11
  export type TourProps = React.ComponentProps<"div"> & {
11
12
  steps: TourStep[]
12
- index?: number
13
- onIndexChange?: (index: number) => void
14
- onClose?: () => void
15
- }
16
-
17
- function Tour({ steps, index = 0, onIndexChange, onClose, className, ...props }: TourProps) {
18
- const step = steps[index]
19
- if (!step) return null
20
-
21
- return (
22
- <div data-slot="tour" className={cn("rounded-xl border bg-popover p-4 text-popover-foreground shadow-lg", className)} {...props}>
23
- <div className="grid gap-2">
24
- <div className="font-semibold">{step.title}</div>
25
- {step.description && <div className="text-sm text-muted-foreground">{step.description}</div>}
26
- <div className="flex items-center justify-between gap-3 pt-2">
27
- <span className="text-xs text-muted-foreground">{index + 1} / {steps.length}</span>
28
- <div className="flex gap-2">
29
- <button type="button" className="rounded-md border px-2.5 py-1 text-sm" disabled={index === 0} onClick={() => onIndexChange?.(index - 1)}>Back</button>
30
- {index < steps.length - 1 ? (
31
- <button type="button" className="rounded-md bg-primary px-2.5 py-1 text-sm text-primary-foreground" onClick={() => onIndexChange?.(index + 1)}>Next</button>
32
- ) : (
33
- <button type="button" className="rounded-md bg-primary px-2.5 py-1 text-sm text-primary-foreground" onClick={onClose}>Done</button>
34
- )}
35
- </div>
36
- </div>
13
+ index?: number
14
+ onIndexChange?: (index: number) => void
15
+ onClose?: () => void
16
+ onSkip?: () => void
17
+ onFinish?: () => void
18
+ placement?: "top" | "right" | "bottom" | "left"
19
+ }
20
+
21
+ function Tour({ steps, index = 0, onIndexChange, onClose, onSkip, onFinish, placement = "bottom", className, ...props }: TourProps) {
22
+ const step = steps[index]
23
+ const containerRef = React.useRef<HTMLDivElement | null>(null)
24
+ React.useEffect(() => {
25
+ containerRef.current?.focus()
26
+ }, [index])
27
+
28
+ if (!step) return null
29
+
30
+ return (
31
+ <div
32
+ ref={containerRef}
33
+ data-slot="tour"
34
+ data-placement={placement}
35
+ tabIndex={-1}
36
+ className={cn("rounded-xl border bg-popover p-4 text-popover-foreground shadow-lg outline-none focus-visible:ring-2 focus-visible:ring-ring/40", className)}
37
+ {...props}
38
+ >
39
+ <div className="grid gap-2">
40
+ <div className="font-semibold">{step.title}</div>
41
+ {step.description && <div className="text-sm text-muted-foreground">{step.description}</div>}
42
+ {step.target && <div className="text-xs text-muted-foreground">{step.target}</div>}
43
+ <div className="flex items-center justify-between gap-3 pt-2">
44
+ <span className="text-xs text-muted-foreground">{index + 1} / {steps.length}</span>
45
+ <div className="flex gap-2">
46
+ <button type="button" className="rounded-md border px-2.5 py-1 text-sm" onClick={() => { onSkip?.(); onClose?.() }}>Skip</button>
47
+ <button type="button" className="rounded-md border px-2.5 py-1 text-sm" disabled={index === 0} onClick={() => onIndexChange?.(index - 1)}>Back</button>
48
+ {index < steps.length - 1 ? (
49
+ <button type="button" className="rounded-md bg-primary px-2.5 py-1 text-sm text-primary-foreground" onClick={() => onIndexChange?.(index + 1)}>Next</button>
50
+ ) : (
51
+ <button type="button" className="rounded-md bg-primary px-2.5 py-1 text-sm text-primary-foreground" onClick={() => { onFinish?.(); onClose?.() }}>Done</button>
52
+ )}
53
+ </div>
54
+ </div>
37
55
  </div>
38
56
  </div>
39
57
  )
@@ -5,11 +5,15 @@ export type CommandBarProps = React.ComponentProps<"div"> & {
5
5
  open?: boolean
6
6
  onOpenChange?: (open: boolean) => void
7
7
  position?: "bottom" | "top"
8
+ grouped?: boolean
9
+ label?: React.ReactNode
8
10
  }
9
11
 
10
12
  function CommandBar({
11
13
  open = true,
12
14
  position = "bottom",
15
+ grouped = false,
16
+ label,
13
17
  children,
14
18
  className,
15
19
  ...props
@@ -22,10 +26,12 @@ function CommandBar({
22
26
  className={cn(
23
27
  "fixed left-1/2 z-50 flex -translate-x-1/2 items-center gap-2 rounded-full border bg-background/95 px-4 py-2 shadow-lg backdrop-blur supports-[backdrop-filter]:bg-background/60",
24
28
  position === "bottom" ? "bottom-6" : "top-6",
29
+ grouped && "gap-3 rounded-[28px] px-3 py-2.5",
25
30
  className
26
31
  )}
27
32
  {...props}
28
33
  >
34
+ {label ? <span className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">{label}</span> : null}
29
35
  {children}
30
36
  </div>
31
37
  )
@@ -3,7 +3,6 @@ import { component, createShowcaseDemoRegistry } from "@/showcase/create-demo"
3
3
  export const navigationShowcaseDemoRegistry = createShowcaseDemoRegistry([
4
4
  component("pagination", "Pagination", "navigation", "Controlled page navigation with edge buttons and active state."),
5
5
  component("nav-tabs", "NavTabs", "navigation", "Navigation tabs for switching related document sections."),
6
- component("anchor-nav", "AnchorNav", "navigation", "Section jump navigation for long detail pages."),
7
6
  component("page-tabs", "PageTabs", "navigation", "Top-level page tab strip for route-sized sections."),
8
7
  component("stepper-tabs", "StepperTabs", "navigation", "Step-like tabs for setup and onboarding progress."),
9
8
  ])