@neynar/ui 0.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 (364) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/components/ui/accordion.d.ts +229 -0
  4. package/dist/components/ui/accordion.d.ts.map +1 -0
  5. package/dist/components/ui/alert-dialog.d.ts +247 -0
  6. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  7. package/dist/components/ui/alert.d.ts +187 -0
  8. package/dist/components/ui/alert.d.ts.map +1 -0
  9. package/dist/components/ui/aspect-ratio.d.ts +94 -0
  10. package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
  11. package/dist/components/ui/avatar.d.ts +244 -0
  12. package/dist/components/ui/avatar.d.ts.map +1 -0
  13. package/dist/components/ui/badge.d.ts +163 -0
  14. package/dist/components/ui/badge.d.ts.map +1 -0
  15. package/dist/components/ui/breadcrumb.d.ts +281 -0
  16. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  17. package/dist/components/ui/button.d.ts +129 -0
  18. package/dist/components/ui/button.d.ts.map +1 -0
  19. package/dist/components/ui/calendar.d.ts +169 -0
  20. package/dist/components/ui/calendar.d.ts.map +1 -0
  21. package/dist/components/ui/card.d.ts +365 -0
  22. package/dist/components/ui/card.d.ts.map +1 -0
  23. package/dist/components/ui/carousel.d.ts +369 -0
  24. package/dist/components/ui/carousel.d.ts.map +1 -0
  25. package/dist/components/ui/chart.d.ts +442 -0
  26. package/dist/components/ui/chart.d.ts.map +1 -0
  27. package/dist/components/ui/checkbox.d.ts +88 -0
  28. package/dist/components/ui/checkbox.d.ts.map +1 -0
  29. package/dist/components/ui/collapsible.d.ts +182 -0
  30. package/dist/components/ui/collapsible.d.ts.map +1 -0
  31. package/dist/components/ui/combobox.d.ts +270 -0
  32. package/dist/components/ui/combobox.d.ts.map +1 -0
  33. package/dist/components/ui/command.d.ts +355 -0
  34. package/dist/components/ui/command.d.ts.map +1 -0
  35. package/dist/components/ui/container.d.ts +102 -0
  36. package/dist/components/ui/container.d.ts.map +1 -0
  37. package/dist/components/ui/context-menu.d.ts +339 -0
  38. package/dist/components/ui/context-menu.d.ts.map +1 -0
  39. package/dist/components/ui/date-picker.d.ts +145 -0
  40. package/dist/components/ui/date-picker.d.ts.map +1 -0
  41. package/dist/components/ui/dialog.d.ts +322 -0
  42. package/dist/components/ui/dialog.d.ts.map +1 -0
  43. package/dist/components/ui/drawer.d.ts +154 -0
  44. package/dist/components/ui/drawer.d.ts.map +1 -0
  45. package/dist/components/ui/dropdown-menu.d.ts +349 -0
  46. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  47. package/dist/components/ui/empty-state.d.ts +133 -0
  48. package/dist/components/ui/empty-state.d.ts.map +1 -0
  49. package/dist/components/ui/hover-card.d.ts +109 -0
  50. package/dist/components/ui/hover-card.d.ts.map +1 -0
  51. package/dist/components/ui/input.d.ts +89 -0
  52. package/dist/components/ui/input.d.ts.map +1 -0
  53. package/dist/components/ui/label.d.ts +93 -0
  54. package/dist/components/ui/label.d.ts.map +1 -0
  55. package/dist/components/ui/menubar.d.ts +306 -0
  56. package/dist/components/ui/menubar.d.ts.map +1 -0
  57. package/dist/components/ui/navigation-menu.d.ts +318 -0
  58. package/dist/components/ui/navigation-menu.d.ts.map +1 -0
  59. package/dist/components/ui/pagination.d.ts +343 -0
  60. package/dist/components/ui/pagination.d.ts.map +1 -0
  61. package/dist/components/ui/popover.d.ts +178 -0
  62. package/dist/components/ui/popover.d.ts.map +1 -0
  63. package/dist/components/ui/progress.d.ts +64 -0
  64. package/dist/components/ui/progress.d.ts.map +1 -0
  65. package/dist/components/ui/radio-group.d.ts +144 -0
  66. package/dist/components/ui/radio-group.d.ts.map +1 -0
  67. package/dist/components/ui/resizable.d.ts +164 -0
  68. package/dist/components/ui/resizable.d.ts.map +1 -0
  69. package/dist/components/ui/scroll-area.d.ts +82 -0
  70. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  71. package/dist/components/ui/select.d.ts +316 -0
  72. package/dist/components/ui/select.d.ts.map +1 -0
  73. package/dist/components/ui/separator.d.ts +80 -0
  74. package/dist/components/ui/separator.d.ts.map +1 -0
  75. package/dist/components/ui/sheet.d.ts +346 -0
  76. package/dist/components/ui/sheet.d.ts.map +1 -0
  77. package/dist/components/ui/sidebar.d.ts +1561 -0
  78. package/dist/components/ui/sidebar.d.ts.map +1 -0
  79. package/dist/components/ui/skeleton.d.ts +66 -0
  80. package/dist/components/ui/skeleton.d.ts.map +1 -0
  81. package/dist/components/ui/slider.d.ts +95 -0
  82. package/dist/components/ui/slider.d.ts.map +1 -0
  83. package/dist/components/ui/sonner.d.ts +101 -0
  84. package/dist/components/ui/sonner.d.ts.map +1 -0
  85. package/dist/components/ui/stack.d.ts +192 -0
  86. package/dist/components/ui/stack.d.ts.map +1 -0
  87. package/dist/components/ui/stories/accordion.stories.d.ts +71 -0
  88. package/dist/components/ui/stories/accordion.stories.d.ts.map +1 -0
  89. package/dist/components/ui/stories/alert-dialog.stories.d.ts +39 -0
  90. package/dist/components/ui/stories/alert-dialog.stories.d.ts.map +1 -0
  91. package/dist/components/ui/stories/alert.stories.d.ts +48 -0
  92. package/dist/components/ui/stories/alert.stories.d.ts.map +1 -0
  93. package/dist/components/ui/stories/aspect-ratio.stories.d.ts +53 -0
  94. package/dist/components/ui/stories/aspect-ratio.stories.d.ts.map +1 -0
  95. package/dist/components/ui/stories/avatar.stories.d.ts +49 -0
  96. package/dist/components/ui/stories/avatar.stories.d.ts.map +1 -0
  97. package/dist/components/ui/stories/badge.stories.d.ts +64 -0
  98. package/dist/components/ui/stories/badge.stories.d.ts.map +1 -0
  99. package/dist/components/ui/stories/breadcrumb.stories.d.ts +27 -0
  100. package/dist/components/ui/stories/breadcrumb.stories.d.ts.map +1 -0
  101. package/dist/components/ui/stories/button.stories.d.ts +92 -0
  102. package/dist/components/ui/stories/button.stories.d.ts.map +1 -0
  103. package/dist/components/ui/stories/calendar.stories.d.ts +94 -0
  104. package/dist/components/ui/stories/calendar.stories.d.ts.map +1 -0
  105. package/dist/components/ui/stories/card.stories.d.ts +29 -0
  106. package/dist/components/ui/stories/card.stories.d.ts.map +1 -0
  107. package/dist/components/ui/stories/carousel.stories.d.ts +42 -0
  108. package/dist/components/ui/stories/carousel.stories.d.ts.map +1 -0
  109. package/dist/components/ui/stories/chart.stories.d.ts +51 -0
  110. package/dist/components/ui/stories/chart.stories.d.ts.map +1 -0
  111. package/dist/components/ui/stories/checkbox.stories.d.ts +72 -0
  112. package/dist/components/ui/stories/checkbox.stories.d.ts.map +1 -0
  113. package/dist/components/ui/stories/cn.stories.d.ts +19 -0
  114. package/dist/components/ui/stories/cn.stories.d.ts.map +1 -0
  115. package/dist/components/ui/stories/collapsible.stories.d.ts +51 -0
  116. package/dist/components/ui/stories/collapsible.stories.d.ts.map +1 -0
  117. package/dist/components/ui/stories/colors.stories.d.ts +31 -0
  118. package/dist/components/ui/stories/colors.stories.d.ts.map +1 -0
  119. package/dist/components/ui/stories/combobox.stories.d.ts +89 -0
  120. package/dist/components/ui/stories/combobox.stories.d.ts.map +1 -0
  121. package/dist/components/ui/stories/command.stories.d.ts +69 -0
  122. package/dist/components/ui/stories/command.stories.d.ts.map +1 -0
  123. package/dist/components/ui/stories/container.stories.d.ts +42 -0
  124. package/dist/components/ui/stories/container.stories.d.ts.map +1 -0
  125. package/dist/components/ui/stories/context-menu.stories.d.ts +32 -0
  126. package/dist/components/ui/stories/context-menu.stories.d.ts.map +1 -0
  127. package/dist/components/ui/stories/date-picker.stories.d.ts +67 -0
  128. package/dist/components/ui/stories/date-picker.stories.d.ts.map +1 -0
  129. package/dist/components/ui/stories/dialog.stories.d.ts +48 -0
  130. package/dist/components/ui/stories/dialog.stories.d.ts.map +1 -0
  131. package/dist/components/ui/stories/drawer.stories.d.ts +33 -0
  132. package/dist/components/ui/stories/drawer.stories.d.ts.map +1 -0
  133. package/dist/components/ui/stories/dropdown-menu.stories.d.ts +31 -0
  134. package/dist/components/ui/stories/dropdown-menu.stories.d.ts.map +1 -0
  135. package/dist/components/ui/stories/empty-state.stories.d.ts +74 -0
  136. package/dist/components/ui/stories/empty-state.stories.d.ts.map +1 -0
  137. package/dist/components/ui/stories/hover-card.stories.d.ts +35 -0
  138. package/dist/components/ui/stories/hover-card.stories.d.ts.map +1 -0
  139. package/dist/components/ui/stories/input.stories.d.ts +69 -0
  140. package/dist/components/ui/stories/input.stories.d.ts.map +1 -0
  141. package/dist/components/ui/stories/label.stories.d.ts +47 -0
  142. package/dist/components/ui/stories/label.stories.d.ts.map +1 -0
  143. package/dist/components/ui/stories/menubar.stories.d.ts +39 -0
  144. package/dist/components/ui/stories/menubar.stories.d.ts.map +1 -0
  145. package/dist/components/ui/stories/navigation-menu.stories.d.ts +44 -0
  146. package/dist/components/ui/stories/navigation-menu.stories.d.ts.map +1 -0
  147. package/dist/components/ui/stories/pagination.stories.d.ts +33 -0
  148. package/dist/components/ui/stories/pagination.stories.d.ts.map +1 -0
  149. package/dist/components/ui/stories/popover.stories.d.ts +36 -0
  150. package/dist/components/ui/stories/popover.stories.d.ts.map +1 -0
  151. package/dist/components/ui/stories/progress.stories.d.ts +38 -0
  152. package/dist/components/ui/stories/progress.stories.d.ts.map +1 -0
  153. package/dist/components/ui/stories/radio-group.stories.d.ts +76 -0
  154. package/dist/components/ui/stories/radio-group.stories.d.ts.map +1 -0
  155. package/dist/components/ui/stories/resizable.stories.d.ts +49 -0
  156. package/dist/components/ui/stories/resizable.stories.d.ts.map +1 -0
  157. package/dist/components/ui/stories/scroll-area.stories.d.ts +35 -0
  158. package/dist/components/ui/stories/scroll-area.stories.d.ts.map +1 -0
  159. package/dist/components/ui/stories/select.stories.d.ts +51 -0
  160. package/dist/components/ui/stories/select.stories.d.ts.map +1 -0
  161. package/dist/components/ui/stories/separator.stories.d.ts +58 -0
  162. package/dist/components/ui/stories/separator.stories.d.ts.map +1 -0
  163. package/dist/components/ui/stories/sheet.stories.d.ts +43 -0
  164. package/dist/components/ui/stories/sheet.stories.d.ts.map +1 -0
  165. package/dist/components/ui/stories/sidebar.stories.d.ts +60 -0
  166. package/dist/components/ui/stories/sidebar.stories.d.ts.map +1 -0
  167. package/dist/components/ui/stories/skeleton.stories.d.ts +42 -0
  168. package/dist/components/ui/stories/skeleton.stories.d.ts.map +1 -0
  169. package/dist/components/ui/stories/slider.stories.d.ts +99 -0
  170. package/dist/components/ui/stories/slider.stories.d.ts.map +1 -0
  171. package/dist/components/ui/stories/sonner.stories.d.ts +9 -0
  172. package/dist/components/ui/stories/sonner.stories.d.ts.map +1 -0
  173. package/dist/components/ui/stories/stack.stories.d.ts +39 -0
  174. package/dist/components/ui/stories/stack.stories.d.ts.map +1 -0
  175. package/dist/components/ui/stories/switch.stories.d.ts +71 -0
  176. package/dist/components/ui/stories/switch.stories.d.ts.map +1 -0
  177. package/dist/components/ui/stories/table.stories.d.ts +40 -0
  178. package/dist/components/ui/stories/table.stories.d.ts.map +1 -0
  179. package/dist/components/ui/stories/tabs.stories.d.ts +62 -0
  180. package/dist/components/ui/stories/tabs.stories.d.ts.map +1 -0
  181. package/dist/components/ui/stories/text-field.stories.d.ts +78 -0
  182. package/dist/components/ui/stories/text-field.stories.d.ts.map +1 -0
  183. package/dist/components/ui/stories/textarea.stories.d.ts +57 -0
  184. package/dist/components/ui/stories/textarea.stories.d.ts.map +1 -0
  185. package/dist/components/ui/stories/theme-toggle.stories.d.ts +71 -0
  186. package/dist/components/ui/stories/theme-toggle.stories.d.ts.map +1 -0
  187. package/dist/components/ui/stories/theme.stories.d.ts +51 -0
  188. package/dist/components/ui/stories/theme.stories.d.ts.map +1 -0
  189. package/dist/components/ui/stories/toggle-group.stories.d.ts +71 -0
  190. package/dist/components/ui/stories/toggle-group.stories.d.ts.map +1 -0
  191. package/dist/components/ui/stories/toggle.stories.d.ts +78 -0
  192. package/dist/components/ui/stories/toggle.stories.d.ts.map +1 -0
  193. package/dist/components/ui/stories/tooltip.stories.d.ts +37 -0
  194. package/dist/components/ui/stories/tooltip.stories.d.ts.map +1 -0
  195. package/dist/components/ui/stories/typography.stories.d.ts +137 -0
  196. package/dist/components/ui/stories/typography.stories.d.ts.map +1 -0
  197. package/dist/components/ui/stories/use-mobile.stories.d.ts +20 -0
  198. package/dist/components/ui/stories/use-mobile.stories.d.ts.map +1 -0
  199. package/dist/components/ui/stories/use-theme.stories.d.ts +23 -0
  200. package/dist/components/ui/stories/use-theme.stories.d.ts.map +1 -0
  201. package/dist/components/ui/switch.d.ts +84 -0
  202. package/dist/components/ui/switch.d.ts.map +1 -0
  203. package/dist/components/ui/table.d.ts +321 -0
  204. package/dist/components/ui/table.d.ts.map +1 -0
  205. package/dist/components/ui/tabs.d.ts +260 -0
  206. package/dist/components/ui/tabs.d.ts.map +1 -0
  207. package/dist/components/ui/text-field.d.ts +157 -0
  208. package/dist/components/ui/text-field.d.ts.map +1 -0
  209. package/dist/components/ui/textarea.d.ts +84 -0
  210. package/dist/components/ui/textarea.d.ts.map +1 -0
  211. package/dist/components/ui/theme-toggle.d.ts +105 -0
  212. package/dist/components/ui/theme-toggle.d.ts.map +1 -0
  213. package/dist/components/ui/theme.d.ts +110 -0
  214. package/dist/components/ui/theme.d.ts.map +1 -0
  215. package/dist/components/ui/toggle-group.d.ts +133 -0
  216. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  217. package/dist/components/ui/toggle.d.ts +84 -0
  218. package/dist/components/ui/toggle.d.ts.map +1 -0
  219. package/dist/components/ui/tooltip.d.ts +202 -0
  220. package/dist/components/ui/tooltip.d.ts.map +1 -0
  221. package/dist/components/ui/typography.d.ts +287 -0
  222. package/dist/components/ui/typography.d.ts.map +1 -0
  223. package/dist/hooks/use-mobile.d.ts +74 -0
  224. package/dist/hooks/use-mobile.d.ts.map +1 -0
  225. package/dist/hooks/use-theme.d.ts +142 -0
  226. package/dist/hooks/use-theme.d.ts.map +1 -0
  227. package/dist/index.d.ts +57 -0
  228. package/dist/index.d.ts.map +1 -0
  229. package/dist/index.js +27498 -0
  230. package/dist/index.js.map +1 -0
  231. package/dist/lib/utils.d.ts +43 -0
  232. package/dist/lib/utils.d.ts.map +1 -0
  233. package/dist/tsconfig.tsbuildinfo +1 -0
  234. package/docs/llm/colors.md +273 -0
  235. package/docs/llm/components/buttons.md +68 -0
  236. package/docs/llm/components/cards.md +53 -0
  237. package/docs/llm/components/display.md +134 -0
  238. package/docs/llm/components/feedback.md +96 -0
  239. package/docs/llm/components/forms.md +90 -0
  240. package/docs/llm/components/layout.md +59 -0
  241. package/docs/llm/components/menus.md +70 -0
  242. package/docs/llm/components/navigation.md +80 -0
  243. package/docs/llm/components/overlays.md +83 -0
  244. package/docs/llm/components/tables.md +73 -0
  245. package/docs/llm/components/typography.md +199 -0
  246. package/docs/llm/components/utilities.md +114 -0
  247. package/docs/llm/guide.md +165 -0
  248. package/llms.txt +122 -0
  249. package/package.json +104 -0
  250. package/src/components/ui/accordion.tsx +285 -0
  251. package/src/components/ui/alert-dialog.tsx +387 -0
  252. package/src/components/ui/alert.tsx +243 -0
  253. package/src/components/ui/aspect-ratio.tsx +99 -0
  254. package/src/components/ui/avatar.tsx +288 -0
  255. package/src/components/ui/badge.tsx +205 -0
  256. package/src/components/ui/breadcrumb.tsx +378 -0
  257. package/src/components/ui/button.tsx +195 -0
  258. package/src/components/ui/calendar.tsx +371 -0
  259. package/src/components/ui/card.tsx +447 -0
  260. package/src/components/ui/carousel.tsx +624 -0
  261. package/src/components/ui/chart.tsx +802 -0
  262. package/src/components/ui/checkbox.tsx +113 -0
  263. package/src/components/ui/collapsible.tsx +207 -0
  264. package/src/components/ui/combobox.tsx +373 -0
  265. package/src/components/ui/command.tsx +518 -0
  266. package/src/components/ui/container.tsx +114 -0
  267. package/src/components/ui/context-menu.tsx +563 -0
  268. package/src/components/ui/date-picker.tsx +213 -0
  269. package/src/components/ui/dialog.tsx +447 -0
  270. package/src/components/ui/drawer.tsx +273 -0
  271. package/src/components/ui/dropdown-menu.tsx +578 -0
  272. package/src/components/ui/empty-state.tsx +145 -0
  273. package/src/components/ui/hover-card.tsx +144 -0
  274. package/src/components/ui/input.tsx +106 -0
  275. package/src/components/ui/label.tsx +110 -0
  276. package/src/components/ui/menubar.tsx +553 -0
  277. package/src/components/ui/navigation-menu.tsx +471 -0
  278. package/src/components/ui/pagination.tsx +456 -0
  279. package/src/components/ui/popover.tsx +216 -0
  280. package/src/components/ui/progress.tsx +88 -0
  281. package/src/components/ui/radio-group.tsx +183 -0
  282. package/src/components/ui/resizable.tsx +209 -0
  283. package/src/components/ui/scroll-area.tsx +132 -0
  284. package/src/components/ui/select.tsx +485 -0
  285. package/src/components/ui/separator.tsx +101 -0
  286. package/src/components/ui/sheet.tsx +495 -0
  287. package/src/components/ui/sidebar.tsx +2211 -0
  288. package/src/components/ui/skeleton.tsx +76 -0
  289. package/src/components/ui/slider.tsx +147 -0
  290. package/src/components/ui/sonner.tsx +120 -0
  291. package/src/components/ui/stack.tsx +180 -0
  292. package/src/components/ui/stories/accordion.stories.tsx +429 -0
  293. package/src/components/ui/stories/alert-dialog.stories.tsx +519 -0
  294. package/src/components/ui/stories/alert.stories.tsx +228 -0
  295. package/src/components/ui/stories/aspect-ratio.stories.tsx +200 -0
  296. package/src/components/ui/stories/avatar.stories.tsx +317 -0
  297. package/src/components/ui/stories/badge.stories.tsx +260 -0
  298. package/src/components/ui/stories/breadcrumb.stories.tsx +482 -0
  299. package/src/components/ui/stories/button.stories.tsx +266 -0
  300. package/src/components/ui/stories/calendar.stories.tsx +375 -0
  301. package/src/components/ui/stories/card.stories.tsx +308 -0
  302. package/src/components/ui/stories/carousel.stories.tsx +328 -0
  303. package/src/components/ui/stories/chart.stories.tsx +430 -0
  304. package/src/components/ui/stories/checkbox.stories.tsx +297 -0
  305. package/src/components/ui/stories/cn.stories.tsx +433 -0
  306. package/src/components/ui/stories/collapsible.stories.tsx +256 -0
  307. package/src/components/ui/stories/colors.stories.tsx +502 -0
  308. package/src/components/ui/stories/combobox.stories.tsx +301 -0
  309. package/src/components/ui/stories/command.stories.tsx +632 -0
  310. package/src/components/ui/stories/container.stories.tsx +250 -0
  311. package/src/components/ui/stories/context-menu.stories.tsx +446 -0
  312. package/src/components/ui/stories/date-picker.stories.tsx +378 -0
  313. package/src/components/ui/stories/dialog.stories.tsx +535 -0
  314. package/src/components/ui/stories/drawer.stories.tsx +364 -0
  315. package/src/components/ui/stories/dropdown-menu.stories.tsx +374 -0
  316. package/src/components/ui/stories/empty-state.stories.tsx +244 -0
  317. package/src/components/ui/stories/hover-card.stories.tsx +355 -0
  318. package/src/components/ui/stories/input.stories.tsx +289 -0
  319. package/src/components/ui/stories/label.stories.tsx +294 -0
  320. package/src/components/ui/stories/menubar.stories.tsx +764 -0
  321. package/src/components/ui/stories/navigation-menu.stories.tsx +539 -0
  322. package/src/components/ui/stories/pagination.stories.tsx +604 -0
  323. package/src/components/ui/stories/popover.stories.tsx +392 -0
  324. package/src/components/ui/stories/progress.stories.tsx +218 -0
  325. package/src/components/ui/stories/radio-group.stories.tsx +400 -0
  326. package/src/components/ui/stories/resizable.stories.tsx +417 -0
  327. package/src/components/ui/stories/scroll-area.stories.tsx +180 -0
  328. package/src/components/ui/stories/select.stories.tsx +389 -0
  329. package/src/components/ui/stories/separator.stories.tsx +192 -0
  330. package/src/components/ui/stories/sheet.stories.tsx +468 -0
  331. package/src/components/ui/stories/sidebar.stories.tsx +731 -0
  332. package/src/components/ui/stories/skeleton.stories.tsx +216 -0
  333. package/src/components/ui/stories/slider.stories.tsx +321 -0
  334. package/src/components/ui/stories/sonner.stories.tsx +373 -0
  335. package/src/components/ui/stories/stack.stories.tsx +222 -0
  336. package/src/components/ui/stories/switch.stories.tsx +202 -0
  337. package/src/components/ui/stories/table.stories.tsx +541 -0
  338. package/src/components/ui/stories/tabs.stories.tsx +544 -0
  339. package/src/components/ui/stories/text-field.stories.tsx +280 -0
  340. package/src/components/ui/stories/textarea.stories.tsx +245 -0
  341. package/src/components/ui/stories/theme-toggle.stories.tsx +275 -0
  342. package/src/components/ui/stories/theme.stories.tsx +412 -0
  343. package/src/components/ui/stories/toggle-group.stories.tsx +337 -0
  344. package/src/components/ui/stories/toggle.stories.tsx +325 -0
  345. package/src/components/ui/stories/tooltip.stories.tsx +444 -0
  346. package/src/components/ui/stories/typography.stories.tsx +1586 -0
  347. package/src/components/ui/stories/use-mobile.stories.tsx +420 -0
  348. package/src/components/ui/stories/use-theme.stories.tsx +531 -0
  349. package/src/components/ui/switch.tsx +106 -0
  350. package/src/components/ui/table.tsx +424 -0
  351. package/src/components/ui/tabs.tsx +316 -0
  352. package/src/components/ui/text-field.tsx +206 -0
  353. package/src/components/ui/textarea.tsx +98 -0
  354. package/src/components/ui/theme-toggle.tsx +185 -0
  355. package/src/components/ui/theme.tsx +148 -0
  356. package/src/components/ui/toggle-group.tsx +196 -0
  357. package/src/components/ui/toggle.tsx +115 -0
  358. package/src/components/ui/tooltip.tsx +253 -0
  359. package/src/components/ui/typography.tsx +468 -0
  360. package/src/hooks/use-mobile.ts +91 -0
  361. package/src/hooks/use-theme.ts +319 -0
  362. package/src/index.ts +77 -0
  363. package/src/lib/utils.ts +57 -0
  364. package/src/styles/globals.css +160 -0
@@ -0,0 +1,802 @@
1
+ import * as React from "react";
2
+ import * as RechartsPrimitive from "recharts";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ // Format: { THEME_NAME: CSS_SELECTOR }
7
+ const THEMES = { light: "", dark: ".dark" } as const;
8
+
9
+ /**
10
+ * Configuration object for chart data series
11
+ *
12
+ * Defines labels, colors, and icons for chart data series with support for
13
+ * both static colors and theme-aware color definitions. Each series can have
14
+ * either a static color or theme-specific colors for light/dark modes.
15
+ * This configuration drives both visual styling and accessibility features
16
+ * throughout the chart ecosystem.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // Static color configuration with icon
21
+ * const chartConfig = {
22
+ * revenue: {
23
+ * label: "Revenue",
24
+ * color: "hsl(var(--chart-1))",
25
+ * icon: DollarSignIcon,
26
+ * },
27
+ * } satisfies ChartConfig
28
+ * ```
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * // Theme-aware color configuration for dark/light modes
33
+ * const chartConfig = {
34
+ * users: {
35
+ * label: "Active Users",
36
+ * theme: {
37
+ * light: "#0ea5e9",
38
+ * dark: "#0284c7",
39
+ * },
40
+ * },
41
+ * } satisfies ChartConfig
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * // Complex configuration with multiple series
47
+ * const chartConfig = {
48
+ * desktop: {
49
+ * label: "Desktop Users",
50
+ * color: "var(--chart-1)",
51
+ * icon: MonitorIcon,
52
+ * },
53
+ * mobile: {
54
+ * label: "Mobile Users",
55
+ * color: "var(--chart-2)",
56
+ * icon: SmartphoneIcon,
57
+ * },
58
+ * revenue: {
59
+ * label: "Revenue ($)",
60
+ * theme: {
61
+ * light: "#059669",
62
+ * dark: "#10b981",
63
+ * },
64
+ * },
65
+ * } satisfies ChartConfig
66
+ * ```
67
+ *
68
+ * @since 1.0.0
69
+ */
70
+ export type ChartConfig = {
71
+ [k in string]: {
72
+ label?: React.ReactNode;
73
+ icon?: React.ComponentType;
74
+ } & (
75
+ | { color?: string; theme?: never }
76
+ | { color?: never; theme: Record<keyof typeof THEMES, string> }
77
+ );
78
+ };
79
+
80
+ type ChartContextProps = {
81
+ config: ChartConfig;
82
+ };
83
+
84
+ const ChartContext = React.createContext<ChartContextProps | null>(null);
85
+
86
+ /**
87
+ * Hook to access chart configuration context
88
+ *
89
+ * Provides access to the chart configuration within chart components.
90
+ * Must be used within a ChartContainer component to access the chart config.
91
+ *
92
+ * @returns Chart configuration context containing config object
93
+ * @throws Error when used outside of ChartContainer
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * function CustomTooltip() {
98
+ * const { config } = useChart()
99
+ *
100
+ * return (
101
+ * <div>
102
+ * {Object.entries(config).map(([key, series]) => (
103
+ * <div key={key} style={{ color: series.color }}>
104
+ * {series.label}
105
+ * </div>
106
+ * ))}
107
+ * </div>
108
+ * )
109
+ * }
110
+ * ```
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * function CustomChartComponent() {
115
+ * const { config } = useChart()
116
+ * const seriesConfig = config.revenue
117
+ *
118
+ * return (
119
+ * <div>
120
+ * <seriesConfig.icon />
121
+ * <span>{seriesConfig.label}</span>
122
+ * </div>
123
+ * )
124
+ * }
125
+ * ```
126
+ *
127
+ * @since 1.0.0
128
+ */
129
+ function useChart() {
130
+ const context = React.useContext(ChartContext);
131
+
132
+ if (!context) {
133
+ throw new Error("useChart must be used within a <ChartContainer />");
134
+ }
135
+
136
+ return context;
137
+ }
138
+
139
+ /**
140
+ * Container component for Recharts charts with theming and configuration
141
+ *
142
+ * The ChartContainer provides a responsive wrapper for Recharts components with
143
+ * automatic theming, color management, and configuration. It generates CSS custom
144
+ * properties for chart colors, handles dark mode support, and applies consistent
145
+ * styling across all chart types. Built on the shadcn/ui design system with
146
+ * Recharts as the underlying charting library.
147
+ *
148
+ * @component
149
+ * @example
150
+ * ```tsx
151
+ * // Basic line chart with accessibility and tooltips
152
+ * const chartData = [
153
+ * { month: "Jan", revenue: 2000, profit: 400 },
154
+ * { month: "Feb", revenue: 2400, profit: 600 },
155
+ * { month: "Mar", revenue: 3200, profit: 900 },
156
+ * ]
157
+ *
158
+ * const chartConfig = {
159
+ * revenue: {
160
+ * label: "Revenue",
161
+ * color: "hsl(var(--chart-1))",
162
+ * },
163
+ * profit: {
164
+ * label: "Profit",
165
+ * color: "hsl(var(--chart-2))",
166
+ * },
167
+ * } satisfies ChartConfig
168
+ *
169
+ * <ChartContainer config={chartConfig} className="min-h-[300px]">
170
+ * <LineChart data={chartData} accessibilityLayer>
171
+ * <CartesianGrid strokeDasharray="3 3" />
172
+ * <XAxis dataKey="month" />
173
+ * <YAxis />
174
+ * <ChartTooltip content={<ChartTooltipContent />} />
175
+ * <Line
176
+ * type="monotone"
177
+ * dataKey="revenue"
178
+ * stroke="var(--color-revenue)"
179
+ * strokeWidth={2}
180
+ * />
181
+ * <Line
182
+ * type="monotone"
183
+ * dataKey="profit"
184
+ * stroke="var(--color-profit)"
185
+ * strokeWidth={2}
186
+ * />
187
+ * </LineChart>
188
+ * </ChartContainer>
189
+ * ```
190
+ *
191
+ * @example
192
+ * ```tsx
193
+ * // Bar chart with theme-aware colors and custom formatting
194
+ * <ChartContainer
195
+ * config={{
196
+ * sales: {
197
+ * label: "Sales",
198
+ * theme: {
199
+ * light: "#0ea5e9",
200
+ * dark: "#0284c7",
201
+ * },
202
+ * },
203
+ * }}
204
+ * className="h-[400px]"
205
+ * >
206
+ * <BarChart data={data} accessibilityLayer>
207
+ * <XAxis dataKey="month" />
208
+ * <YAxis tickFormatter={(value) => `$${value.toLocaleString()}`} />
209
+ * <ChartTooltip content={<ChartTooltipContent />} />
210
+ * <Bar dataKey="sales" fill="var(--color-sales)" radius={4} />
211
+ * </BarChart>
212
+ * </ChartContainer>
213
+ * ```
214
+ *
215
+ * @example
216
+ * ```tsx
217
+ * // Pie chart with legend and icons for device breakdown
218
+ * <ChartContainer config={{
219
+ * desktop: {
220
+ * label: "Desktop",
221
+ * color: "var(--chart-1)",
222
+ * icon: MonitorIcon,
223
+ * },
224
+ * mobile: {
225
+ * label: "Mobile",
226
+ * color: "var(--chart-2)",
227
+ * icon: SmartphoneIcon,
228
+ * },
229
+ * }}>
230
+ * <PieChart>
231
+ * <Pie data={data} dataKey="value" nameKey="device" />
232
+ * <ChartTooltip content={<ChartTooltipContent />} />
233
+ * <ChartLegend content={<ChartLegendContent />} />
234
+ * </PieChart>
235
+ * </ChartContainer>
236
+ * ```
237
+ *
238
+ * @accessibility
239
+ * **Core Accessibility Features:**
240
+ * - Responsive container adapts to screen size automatically
241
+ * - Theme-aware color system designed for WCAG contrast compliance
242
+ * - Supports Recharts' `accessibilityLayer` prop for keyboard navigation
243
+ * - High contrast colors available in both light and dark themes
244
+ * - Semantic HTML structure for screen reader compatibility
245
+ *
246
+ * **Important Accessibility Notes:**
247
+ * - Always include `accessibilityLayer` prop on Recharts components for keyboard access
248
+ * - Consider adding `aria-label` or `title` attributes for chart context
249
+ * - Ensure color is not the only way to distinguish data (use patterns, labels, or icons)
250
+ * - Test with screen readers as automatic data announcement may be limited
251
+ * - Provide alternative data representations (tables, text summaries) for complex charts
252
+ *
253
+ * **Keyboard Navigation:**
254
+ * - Arrow keys navigate between data points when `accessibilityLayer` is enabled
255
+ * - Tab key moves focus to interactive chart elements
256
+ * - Screen reader users should be provided with data summaries or alternative formats
257
+ *
258
+ * @performance
259
+ * - Use appropriate chart types for data size (avoid complex charts with large datasets)
260
+ * - Consider virtualization for charts with many data points
261
+ * - CSS variables are generated only for configured colors to minimize style overhead
262
+ *
263
+ * @see {@link https://ui.shadcn.com/docs/components/chart} shadcn/ui Chart documentation
264
+ * @see {@link https://recharts.org/en-US/api} Recharts API documentation
265
+ * @see {@link ChartTooltip} Tooltip component for interactive data display
266
+ * @see {@link ChartLegend} Legend component for series identification
267
+ * @see {@link useChart} Hook to access chart configuration
268
+ * @since 1.0.0
269
+ */
270
+ function ChartContainer({
271
+ id,
272
+ className,
273
+ children,
274
+ config,
275
+ ...props
276
+ }: React.ComponentProps<"div"> & {
277
+ /**
278
+ * Chart configuration defining series labels and colors
279
+ */
280
+ config: ChartConfig;
281
+ /**
282
+ * Recharts component(s) to render
283
+ */
284
+ children: React.ComponentProps<
285
+ typeof RechartsPrimitive.ResponsiveContainer
286
+ >["children"];
287
+ }) {
288
+ const uniqueId = React.useId();
289
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
290
+
291
+ return (
292
+ <ChartContext.Provider value={{ config }}>
293
+ <div
294
+ data-slot="chart"
295
+ data-chart={chartId}
296
+ className={cn(
297
+ "[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
298
+ className,
299
+ )}
300
+ {...props}
301
+ >
302
+ <ChartStyle id={chartId} config={config} />
303
+ <RechartsPrimitive.ResponsiveContainer>
304
+ {children}
305
+ </RechartsPrimitive.ResponsiveContainer>
306
+ </div>
307
+ </ChartContext.Provider>
308
+ );
309
+ }
310
+
311
+ /**
312
+ * Internal component that generates CSS custom properties for chart colors
313
+ *
314
+ * Creates CSS variables based on the chart configuration to enable theme-aware
315
+ * coloring. Generates variables for both light and dark themes when theme
316
+ * configurations are provided, or uses static colors when available.
317
+ *
318
+ * @component
319
+ * @internal
320
+ * @param id - Unique identifier for the chart instance
321
+ * @param config - Chart configuration with color definitions
322
+ * @since 1.0.0
323
+ */
324
+ function ChartStyle({ id, config }: { id: string; config: ChartConfig }) {
325
+ const colorConfig = Object.entries(config).filter(
326
+ ([, config]) => config.theme || config.color,
327
+ );
328
+
329
+ if (!colorConfig.length) {
330
+ return null;
331
+ }
332
+
333
+ return (
334
+ <style
335
+ dangerouslySetInnerHTML={{
336
+ __html: Object.entries(THEMES)
337
+ .map(
338
+ ([theme, prefix]) => `
339
+ ${prefix} [data-chart=${id}] {
340
+ ${colorConfig
341
+ .map(([key, itemConfig]) => {
342
+ const color =
343
+ itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
344
+ itemConfig.color;
345
+ return color ? ` --color-${key}: ${color};` : null;
346
+ })
347
+ .join("\n")}
348
+ }
349
+ `,
350
+ )
351
+ .join("\n"),
352
+ }}
353
+ />
354
+ );
355
+ }
356
+
357
+ /**
358
+ * Tooltip component for charts
359
+ *
360
+ * Re-export of Recharts Tooltip component with support for custom content.
361
+ * Use with ChartTooltipContent for consistent styling and theming integration.
362
+ *
363
+ * @component
364
+ * @example
365
+ * ```tsx
366
+ * // Basic tooltip
367
+ * <ChartTooltip content={<ChartTooltipContent />} />
368
+ * ```
369
+ *
370
+ * @example
371
+ * ```tsx
372
+ * // Tooltip with custom positioning
373
+ * <ChartTooltip
374
+ * content={<ChartTooltipContent />}
375
+ * cursor={false}
376
+ * position={{ x: 10, y: 10 }}
377
+ * />
378
+ * ```
379
+ *
380
+ * @see {@link ChartTooltipContent} Custom tooltip content component
381
+ * @since 1.0.0
382
+ */
383
+ const ChartTooltip = RechartsPrimitive.Tooltip;
384
+
385
+ /**
386
+ * Custom tooltip content component for charts
387
+ *
388
+ * Provides a styled tooltip that displays chart data with proper formatting,
389
+ * colors, and labels from the chart configuration. Supports multiple indicator
390
+ * styles, custom formatters, and automatic theming integration.
391
+ *
392
+ * @component
393
+ * @example
394
+ * ```tsx
395
+ * // Basic tooltip with default styling
396
+ * <ChartTooltip content={<ChartTooltipContent />} />
397
+ * ```
398
+ *
399
+ * @example
400
+ * ```tsx
401
+ * // Tooltip with custom value formatter
402
+ * <ChartTooltip
403
+ * content={
404
+ * <ChartTooltipContent
405
+ * formatter={(value, name) => [
406
+ * `$${value.toLocaleString()}`,
407
+ * name.toUpperCase()
408
+ * ]}
409
+ * />
410
+ * }
411
+ * />
412
+ * ```
413
+ *
414
+ * @example
415
+ * ```tsx
416
+ * // Tooltip with line indicator and custom label
417
+ * <ChartTooltip
418
+ * content={
419
+ * <ChartTooltipContent
420
+ * indicator="line"
421
+ * labelFormatter={(label) => `Week of ${label}`}
422
+ * hideLabel={false}
423
+ * />
424
+ * }
425
+ * />
426
+ * ```
427
+ *
428
+ * @example
429
+ * ```tsx
430
+ * // Tooltip with dashed indicator and no icons
431
+ * <ChartTooltip
432
+ * content={
433
+ * <ChartTooltipContent
434
+ * indicator="dashed"
435
+ * hideIndicator={false}
436
+ * nameKey="category"
437
+ * />
438
+ * }
439
+ * />
440
+ * ```
441
+ *
442
+ * @accessibility
443
+ * - High contrast colors for visibility in both themes
444
+ * - Proper semantic markup for screen readers
445
+ * - Formatted numbers with locale-aware display
446
+ * - Clear visual indicators for data series
447
+ *
448
+ * @since 1.0.0
449
+ */
450
+ function ChartTooltipContent({
451
+ active,
452
+ payload,
453
+ className,
454
+ indicator = "dot",
455
+ hideLabel = false,
456
+ hideIndicator = false,
457
+ label,
458
+ labelFormatter,
459
+ labelClassName,
460
+ formatter,
461
+ color,
462
+ nameKey,
463
+ labelKey,
464
+ }: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
465
+ React.ComponentProps<"div"> & {
466
+ /**
467
+ * Whether to hide the label
468
+ * @default false
469
+ */
470
+ hideLabel?: boolean;
471
+ /**
472
+ * Whether to hide the color indicator
473
+ * @default false
474
+ */
475
+ hideIndicator?: boolean;
476
+ /**
477
+ * Style of the color indicator
478
+ * @default "dot"
479
+ */
480
+ indicator?: "line" | "dot" | "dashed";
481
+ /**
482
+ * Key to use for the name in payload
483
+ */
484
+ nameKey?: string;
485
+ /**
486
+ * Key to use for the label in payload
487
+ */
488
+ labelKey?: string;
489
+ }) {
490
+ const { config } = useChart();
491
+
492
+ const getTooltipLabel = () => {
493
+ if (hideLabel || !payload?.length) {
494
+ return null;
495
+ }
496
+
497
+ const [item] = payload;
498
+ const key = `${labelKey || item?.dataKey || item?.name || "value"}`;
499
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
500
+ const value =
501
+ !labelKey && typeof label === "string"
502
+ ? config[label as keyof typeof config]?.label || label
503
+ : itemConfig?.label;
504
+
505
+ if (labelFormatter) {
506
+ return (
507
+ <div className={cn("font-medium", labelClassName)}>
508
+ {labelFormatter(value, payload)}
509
+ </div>
510
+ );
511
+ }
512
+
513
+ if (!value) {
514
+ return null;
515
+ }
516
+
517
+ return <div className={cn("font-medium", labelClassName)}>{value}</div>;
518
+ };
519
+
520
+ const tooltipLabel = getTooltipLabel();
521
+
522
+ if (!active || !payload?.length) {
523
+ return null;
524
+ }
525
+
526
+ const nestLabel = payload.length === 1 && indicator !== "dot";
527
+
528
+ return (
529
+ <div
530
+ className={cn(
531
+ "border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
532
+ className,
533
+ )}
534
+ >
535
+ {!nestLabel ? tooltipLabel : null}
536
+ <div className="grid gap-1.5">
537
+ {payload.map((item, index) => {
538
+ const key = `${nameKey || item.name || item.dataKey || "value"}`;
539
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
540
+ const indicatorColor = color || item.payload.fill || item.color;
541
+
542
+ return (
543
+ <div
544
+ key={item.dataKey}
545
+ className={cn(
546
+ "[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
547
+ indicator === "dot" && "items-center",
548
+ )}
549
+ >
550
+ {formatter && item?.value !== undefined && item.name ? (
551
+ formatter(item.value, item.name, item, index, item.payload)
552
+ ) : (
553
+ <>
554
+ {itemConfig?.icon ? (
555
+ <itemConfig.icon />
556
+ ) : (
557
+ !hideIndicator && (
558
+ <div
559
+ className={cn(
560
+ "shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
561
+ {
562
+ "h-2.5 w-2.5": indicator === "dot",
563
+ "w-1": indicator === "line",
564
+ "w-0 border-[1.5px] border-dashed bg-transparent":
565
+ indicator === "dashed",
566
+ "my-0.5": nestLabel && indicator === "dashed",
567
+ },
568
+ )}
569
+ style={
570
+ {
571
+ "--color-bg": indicatorColor,
572
+ "--color-border": indicatorColor,
573
+ } as React.CSSProperties
574
+ }
575
+ />
576
+ )
577
+ )}
578
+ <div
579
+ className={cn(
580
+ "flex flex-1 justify-between leading-none",
581
+ nestLabel ? "items-end" : "items-center",
582
+ )}
583
+ >
584
+ <div className="grid gap-1.5">
585
+ {nestLabel ? tooltipLabel : null}
586
+ <span className="text-muted-foreground">
587
+ {itemConfig?.label || item.name}
588
+ </span>
589
+ </div>
590
+ {item.value && (
591
+ <span className="text-foreground font-mono font-medium tabular-nums">
592
+ {item.value.toLocaleString()}
593
+ </span>
594
+ )}
595
+ </div>
596
+ </>
597
+ )}
598
+ </div>
599
+ );
600
+ })}
601
+ </div>
602
+ </div>
603
+ );
604
+ }
605
+
606
+ /**
607
+ * Legend component for charts
608
+ *
609
+ * Re-export of Recharts Legend component with support for custom content.
610
+ * Use with ChartLegendContent for consistent styling and theming integration.
611
+ *
612
+ * @component
613
+ * @example
614
+ * ```tsx
615
+ * // Basic legend
616
+ * <ChartLegend content={<ChartLegendContent />} />
617
+ * ```
618
+ *
619
+ * @example
620
+ * ```tsx
621
+ * // Legend positioned at top
622
+ * <ChartLegend
623
+ * content={<ChartLegendContent />}
624
+ * verticalAlign="top"
625
+ * height={36}
626
+ * />
627
+ * ```
628
+ *
629
+ * @see {@link ChartLegendContent} Custom legend content component
630
+ * @since 1.0.0
631
+ */
632
+ const ChartLegend = RechartsPrimitive.Legend;
633
+
634
+ /**
635
+ * Custom legend content component for charts
636
+ *
637
+ * Provides a styled legend that displays chart series with colors and labels
638
+ * from the chart configuration. Supports icon display, custom positioning,
639
+ * and automatic theming integration.
640
+ *
641
+ * @component
642
+ * @example
643
+ * ```tsx
644
+ * // Basic legend with default settings
645
+ * <ChartLegend content={<ChartLegendContent />} />
646
+ * ```
647
+ *
648
+ * @example
649
+ * ```tsx
650
+ * // Legend positioned at top without icons
651
+ * <ChartLegend
652
+ * content={
653
+ * <ChartLegendContent
654
+ * verticalAlign="top"
655
+ * hideIcon={true}
656
+ * />
657
+ * }
658
+ * />
659
+ * ```
660
+ *
661
+ * @example
662
+ * ```tsx
663
+ * // Legend with custom name key
664
+ * <ChartLegend
665
+ * content={
666
+ * <ChartLegendContent
667
+ * nameKey="category"
668
+ * className="justify-start"
669
+ * />
670
+ * }
671
+ * />
672
+ * ```
673
+ *
674
+ * @accessibility
675
+ * - Semantic markup for screen readers
676
+ * - Color indicators with clear labels
677
+ * - Proper contrast ratios for visibility
678
+ * - Logical tab order for keyboard navigation
679
+ *
680
+ * @since 1.0.0
681
+ */
682
+ function ChartLegendContent({
683
+ className,
684
+ hideIcon = false,
685
+ payload,
686
+ verticalAlign = "bottom",
687
+ nameKey,
688
+ }: React.ComponentProps<"div"> &
689
+ Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
690
+ /**
691
+ * Whether to hide series icons
692
+ * @default false
693
+ */
694
+ hideIcon?: boolean;
695
+ /**
696
+ * Key to use for the name in payload
697
+ */
698
+ nameKey?: string;
699
+ }) {
700
+ const { config } = useChart();
701
+
702
+ if (!payload?.length) {
703
+ return null;
704
+ }
705
+
706
+ return (
707
+ <div
708
+ className={cn(
709
+ "flex items-center justify-center gap-4",
710
+ verticalAlign === "top" ? "pb-3" : "pt-3",
711
+ className,
712
+ )}
713
+ >
714
+ {payload.map((item) => {
715
+ const key = `${nameKey || item.dataKey || "value"}`;
716
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
717
+
718
+ return (
719
+ <div
720
+ key={item.value}
721
+ className={cn(
722
+ "[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3",
723
+ )}
724
+ >
725
+ {itemConfig?.icon && !hideIcon ? (
726
+ <itemConfig.icon />
727
+ ) : (
728
+ <div
729
+ className="h-2 w-2 shrink-0 rounded-[2px]"
730
+ style={{
731
+ backgroundColor: item.color,
732
+ }}
733
+ />
734
+ )}
735
+ {itemConfig?.label}
736
+ </div>
737
+ );
738
+ })}
739
+ </div>
740
+ );
741
+ }
742
+
743
+ /**
744
+ * Internal helper to extract chart configuration from payload data
745
+ *
746
+ * Retrieves the appropriate configuration for a data series from the chart
747
+ * config based on the payload data structure. Handles nested payload objects
748
+ * and fallback key resolution.
749
+ *
750
+ * @internal
751
+ * @param config - The chart configuration object
752
+ * @param payload - The data payload from Recharts
753
+ * @param key - The key to look up in the configuration
754
+ * @returns The configuration for the data series, or undefined if not found
755
+ * @since 1.0.0
756
+ */
757
+ function getPayloadConfigFromPayload(
758
+ config: ChartConfig,
759
+ payload: unknown,
760
+ key: string,
761
+ ) {
762
+ if (typeof payload !== "object" || payload === null) {
763
+ return undefined;
764
+ }
765
+
766
+ const payloadPayload =
767
+ "payload" in payload &&
768
+ typeof payload.payload === "object" &&
769
+ payload.payload !== null
770
+ ? payload.payload
771
+ : undefined;
772
+
773
+ let configLabelKey: string = key;
774
+
775
+ if (
776
+ key in payload &&
777
+ typeof payload[key as keyof typeof payload] === "string"
778
+ ) {
779
+ configLabelKey = payload[key as keyof typeof payload] as string;
780
+ } else if (
781
+ payloadPayload &&
782
+ key in payloadPayload &&
783
+ typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
784
+ ) {
785
+ configLabelKey = payloadPayload[
786
+ key as keyof typeof payloadPayload
787
+ ] as string;
788
+ }
789
+
790
+ return configLabelKey in config
791
+ ? config[configLabelKey]
792
+ : config[key as keyof typeof config];
793
+ }
794
+
795
+ export {
796
+ ChartContainer,
797
+ ChartTooltip,
798
+ ChartTooltipContent,
799
+ ChartLegend,
800
+ ChartLegendContent,
801
+ ChartStyle,
802
+ };