shadcn-rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +40 -0
  3. data/CHANGELOG.md +54 -0
  4. data/CLAUDE.md +463 -0
  5. data/PROGRESS.md +485 -0
  6. data/README.md +1483 -0
  7. data/Rakefile +29 -0
  8. data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +13 -0
  9. data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +46 -0
  10. data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +111 -0
  11. data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +27 -0
  12. data/__tests__/controllers/accordion_controller.test.js +904 -0
  13. data/__tests__/controllers/calendar_controller.test.js +1370 -0
  14. data/__tests__/controllers/carousel_controller.test.js +912 -0
  15. data/__tests__/controllers/checkbox_controller.test.js +454 -0
  16. data/__tests__/controllers/collapsible_controller.test.js +407 -0
  17. data/__tests__/controllers/combobox_controller.test.js +966 -0
  18. data/__tests__/controllers/context_menu_controller.test.js +627 -0
  19. data/__tests__/controllers/date_picker_controller.test.js +636 -0
  20. data/__tests__/controllers/dialog_controller.test.js +878 -0
  21. data/__tests__/controllers/drawer_controller.test.js +995 -0
  22. data/__tests__/controllers/menubar_controller.test.js +736 -0
  23. data/__tests__/controllers/navigation_menu_controller.test.js +598 -0
  24. data/__tests__/controllers/popover_controller.test.js +1007 -0
  25. data/__tests__/controllers/radio_group_controller.test.js +640 -0
  26. data/__tests__/controllers/resizable_controller.test.js +680 -0
  27. data/__tests__/controllers/select_controller.test.js +674 -0
  28. data/__tests__/controllers/sheet_controller.test.js +986 -0
  29. data/__tests__/controllers/slider_controller.test.js +1036 -0
  30. data/__tests__/controllers/switch_controller.test.js +424 -0
  31. data/__tests__/controllers/tabs_controller.test.js +907 -0
  32. data/__tests__/controllers/toggle_group_controller.test.js +839 -0
  33. data/__tests__/controllers/tooltip_controller.test.js +808 -0
  34. data/__tests__/helpers/stimulus-test-helper.js +203 -0
  35. data/app/assets/config/manifest.js +1 -0
  36. data/app/assets/javascripts/shadcn/controllers/accordion_controller.d.ts +53 -0
  37. data/app/assets/javascripts/shadcn/controllers/accordion_controller.js +140 -0
  38. data/app/assets/javascripts/shadcn/controllers/avatar_controller.d.ts +22 -0
  39. data/app/assets/javascripts/shadcn/controllers/avatar_controller.js +26 -0
  40. data/app/assets/javascripts/shadcn/controllers/calendar_controller.js +592 -0
  41. data/app/assets/javascripts/shadcn/controllers/carousel_controller.js +263 -0
  42. data/app/assets/javascripts/shadcn/controllers/checkbox_controller.d.ts +31 -0
  43. data/app/assets/javascripts/shadcn/controllers/checkbox_controller.js +48 -0
  44. data/app/assets/javascripts/shadcn/controllers/collapsible_controller.d.ts +43 -0
  45. data/app/assets/javascripts/shadcn/controllers/collapsible_controller.js +73 -0
  46. data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +234 -0
  47. data/app/assets/javascripts/shadcn/controllers/command_controller.js +141 -0
  48. data/app/assets/javascripts/shadcn/controllers/command_dialog_controller.js +162 -0
  49. data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +202 -0
  50. data/app/assets/javascripts/shadcn/controllers/date_picker_controller.js +282 -0
  51. data/app/assets/javascripts/shadcn/controllers/dialog_controller.d.ts +67 -0
  52. data/app/assets/javascripts/shadcn/controllers/dialog_controller.js +187 -0
  53. data/app/assets/javascripts/shadcn/controllers/drawer_controller.d.ts +58 -0
  54. data/app/assets/javascripts/shadcn/controllers/drawer_controller.js +112 -0
  55. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.d.ts +83 -0
  56. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +225 -0
  57. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.d.ts +59 -0
  58. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +143 -0
  59. data/app/assets/javascripts/shadcn/controllers/input_otp_controller.d.ts +44 -0
  60. data/app/assets/javascripts/shadcn/controllers/input_otp_controller.js +206 -0
  61. data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +323 -0
  62. data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +251 -0
  63. data/app/assets/javascripts/shadcn/controllers/popover_controller.d.ts +56 -0
  64. data/app/assets/javascripts/shadcn/controllers/popover_controller.js +141 -0
  65. data/app/assets/javascripts/shadcn/controllers/radio_group_controller.d.ts +47 -0
  66. data/app/assets/javascripts/shadcn/controllers/radio_group_controller.js +108 -0
  67. data/app/assets/javascripts/shadcn/controllers/resizable_controller.js +272 -0
  68. data/app/assets/javascripts/shadcn/controllers/scroll_area_controller.d.ts +44 -0
  69. data/app/assets/javascripts/shadcn/controllers/scroll_area_controller.js +74 -0
  70. data/app/assets/javascripts/shadcn/controllers/select_controller.d.ts +84 -0
  71. data/app/assets/javascripts/shadcn/controllers/select_controller.js +222 -0
  72. data/app/assets/javascripts/shadcn/controllers/sheet_controller.d.ts +60 -0
  73. data/app/assets/javascripts/shadcn/controllers/sheet_controller.js +151 -0
  74. data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +148 -0
  75. data/app/assets/javascripts/shadcn/controllers/slider_controller.d.ts +102 -0
  76. data/app/assets/javascripts/shadcn/controllers/slider_controller.js +364 -0
  77. data/app/assets/javascripts/shadcn/controllers/switch_controller.d.ts +46 -0
  78. data/app/assets/javascripts/shadcn/controllers/switch_controller.js +78 -0
  79. data/app/assets/javascripts/shadcn/controllers/tabs_controller.d.ts +51 -0
  80. data/app/assets/javascripts/shadcn/controllers/tabs_controller.js +126 -0
  81. data/app/assets/javascripts/shadcn/controllers/toast_controller.d.ts +37 -0
  82. data/app/assets/javascripts/shadcn/controllers/toast_controller.js +58 -0
  83. data/app/assets/javascripts/shadcn/controllers/toggle_controller.d.ts +27 -0
  84. data/app/assets/javascripts/shadcn/controllers/toggle_controller.js +42 -0
  85. data/app/assets/javascripts/shadcn/controllers/toggle_group_controller.d.ts +44 -0
  86. data/app/assets/javascripts/shadcn/controllers/toggle_group_controller.js +68 -0
  87. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.d.ts +56 -0
  88. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +117 -0
  89. data/app/assets/javascripts/shadcn/index.d.ts +74 -0
  90. data/app/assets/javascripts/shadcn/index.js +133 -0
  91. data/app/assets/stylesheets/.keep +0 -0
  92. data/app/assets/stylesheets/shadcn/base.css +445 -0
  93. data/app/assets/stylesheets/shadcn/components.css +513 -0
  94. data/app/assets/stylesheets/shadcn/index.css +18 -0
  95. data/app/assets/stylesheets/shadcn/themes/gray.css +68 -0
  96. data/app/assets/stylesheets/shadcn/themes/slate.css +68 -0
  97. data/app/assets/stylesheets/shadcn/themes/stone.css +68 -0
  98. data/app/assets/stylesheets/shadcn/themes/zinc.css +68 -0
  99. data/app/components/shadcn/accordion_component.rb +63 -0
  100. data/app/components/shadcn/accordion_content_component.rb +29 -0
  101. data/app/components/shadcn/accordion_item_component.rb +40 -0
  102. data/app/components/shadcn/accordion_trigger_component.rb +49 -0
  103. data/app/components/shadcn/alert_component.rb +75 -0
  104. data/app/components/shadcn/alert_description_component.rb +12 -0
  105. data/app/components/shadcn/alert_dialog_action_component.rb +24 -0
  106. data/app/components/shadcn/alert_dialog_cancel_component.rb +24 -0
  107. data/app/components/shadcn/alert_dialog_component.rb +71 -0
  108. data/app/components/shadcn/alert_dialog_content_component.rb +57 -0
  109. data/app/components/shadcn/alert_dialog_description_component.rb +12 -0
  110. data/app/components/shadcn/alert_dialog_footer_component.rb +19 -0
  111. data/app/components/shadcn/alert_dialog_header_component.rb +19 -0
  112. data/app/components/shadcn/alert_dialog_title_component.rb +12 -0
  113. data/app/components/shadcn/alert_title_component.rb +12 -0
  114. data/app/components/shadcn/aspect_ratio_component.rb +49 -0
  115. data/app/components/shadcn/avatar_component.rb +107 -0
  116. data/app/components/shadcn/avatar_fallback_component.rb +17 -0
  117. data/app/components/shadcn/badge_component.rb +49 -0
  118. data/app/components/shadcn/base_component.rb +100 -0
  119. data/app/components/shadcn/breadcrumb_component.rb +70 -0
  120. data/app/components/shadcn/breadcrumb_item_component.rb +50 -0
  121. data/app/components/shadcn/button_component.rb +141 -0
  122. data/app/components/shadcn/button_group_component.rb +69 -0
  123. data/app/components/shadcn/calendar_component.rb +337 -0
  124. data/app/components/shadcn/card_action_component.rb +10 -0
  125. data/app/components/shadcn/card_component.rb +63 -0
  126. data/app/components/shadcn/card_content_component.rb +19 -0
  127. data/app/components/shadcn/card_description_component.rb +12 -0
  128. data/app/components/shadcn/card_footer_component.rb +12 -0
  129. data/app/components/shadcn/card_header_component.rb +24 -0
  130. data/app/components/shadcn/card_title_component.rb +18 -0
  131. data/app/components/shadcn/carousel_component.rb +275 -0
  132. data/app/components/shadcn/checkbox_component.rb +103 -0
  133. data/app/components/shadcn/collapsible_component.rb +66 -0
  134. data/app/components/shadcn/collapsible_content_component.rb +28 -0
  135. data/app/components/shadcn/combobox_component.rb +322 -0
  136. data/app/components/shadcn/command_component.rb +52 -0
  137. data/app/components/shadcn/command_dialog_component.rb +76 -0
  138. data/app/components/shadcn/command_empty_component.rb +12 -0
  139. data/app/components/shadcn/command_group_component.rb +34 -0
  140. data/app/components/shadcn/command_input_component.rb +59 -0
  141. data/app/components/shadcn/command_item_component.rb +48 -0
  142. data/app/components/shadcn/command_list_component.rb +38 -0
  143. data/app/components/shadcn/command_separator_component.rb +12 -0
  144. data/app/components/shadcn/command_shortcut_component.rb +12 -0
  145. data/app/components/shadcn/context_menu_component.rb +64 -0
  146. data/app/components/shadcn/context_menu_content_component.rb +44 -0
  147. data/app/components/shadcn/context_menu_item_component.rb +63 -0
  148. data/app/components/shadcn/context_menu_label_component.rb +18 -0
  149. data/app/components/shadcn/context_menu_separator_component.rb +12 -0
  150. data/app/components/shadcn/context_menu_shortcut_component.rb +12 -0
  151. data/app/components/shadcn/date_picker_component.rb +368 -0
  152. data/app/components/shadcn/dialog_component.rb +77 -0
  153. data/app/components/shadcn/dialog_content_component.rb +91 -0
  154. data/app/components/shadcn/dialog_description_component.rb +12 -0
  155. data/app/components/shadcn/dialog_footer_component.rb +12 -0
  156. data/app/components/shadcn/dialog_header_component.rb +19 -0
  157. data/app/components/shadcn/dialog_title_component.rb +12 -0
  158. data/app/components/shadcn/drawer_component.rb +72 -0
  159. data/app/components/shadcn/drawer_content_component.rb +76 -0
  160. data/app/components/shadcn/drawer_description_component.rb +12 -0
  161. data/app/components/shadcn/drawer_footer_component.rb +12 -0
  162. data/app/components/shadcn/drawer_header_component.rb +19 -0
  163. data/app/components/shadcn/drawer_title_component.rb +12 -0
  164. data/app/components/shadcn/dropdown_menu_component.rb +75 -0
  165. data/app/components/shadcn/dropdown_menu_content_component.rb +49 -0
  166. data/app/components/shadcn/dropdown_menu_group_component.rb +10 -0
  167. data/app/components/shadcn/dropdown_menu_item_component.rb +63 -0
  168. data/app/components/shadcn/dropdown_menu_label_component.rb +18 -0
  169. data/app/components/shadcn/dropdown_menu_separator_component.rb +12 -0
  170. data/app/components/shadcn/dropdown_menu_shortcut_component.rb +12 -0
  171. data/app/components/shadcn/empty_component.rb +48 -0
  172. data/app/components/shadcn/empty_content_component.rb +12 -0
  173. data/app/components/shadcn/empty_description_component.rb +12 -0
  174. data/app/components/shadcn/empty_header_component.rb +29 -0
  175. data/app/components/shadcn/empty_media_component.rb +21 -0
  176. data/app/components/shadcn/empty_title_component.rb +12 -0
  177. data/app/components/shadcn/field_component.rb +113 -0
  178. data/app/components/shadcn/hover_card_component.rb +64 -0
  179. data/app/components/shadcn/hover_card_content_component.rb +36 -0
  180. data/app/components/shadcn/input_component.rb +108 -0
  181. data/app/components/shadcn/input_group_component.rb +70 -0
  182. data/app/components/shadcn/input_otp_component.rb +183 -0
  183. data/app/components/shadcn/item_actions_component.rb +12 -0
  184. data/app/components/shadcn/item_component.rb +98 -0
  185. data/app/components/shadcn/item_content_component.rb +24 -0
  186. data/app/components/shadcn/item_description_component.rb +12 -0
  187. data/app/components/shadcn/item_footer_component.rb +12 -0
  188. data/app/components/shadcn/item_group_component.rb +24 -0
  189. data/app/components/shadcn/item_header_component.rb +12 -0
  190. data/app/components/shadcn/item_media_component.rb +22 -0
  191. data/app/components/shadcn/item_separator_component.rb +12 -0
  192. data/app/components/shadcn/item_title_component.rb +12 -0
  193. data/app/components/shadcn/kbd_component.rb +36 -0
  194. data/app/components/shadcn/label_component.rb +49 -0
  195. data/app/components/shadcn/menubar_checkbox_item_component.rb +76 -0
  196. data/app/components/shadcn/menubar_component.rb +56 -0
  197. data/app/components/shadcn/menubar_content_component.rb +64 -0
  198. data/app/components/shadcn/menubar_item_component.rb +65 -0
  199. data/app/components/shadcn/menubar_label_component.rb +27 -0
  200. data/app/components/shadcn/menubar_menu_component.rb +34 -0
  201. data/app/components/shadcn/menubar_radio_group_component.rb +42 -0
  202. data/app/components/shadcn/menubar_radio_item_component.rb +76 -0
  203. data/app/components/shadcn/menubar_separator_component.rb +22 -0
  204. data/app/components/shadcn/menubar_shortcut_component.rb +21 -0
  205. data/app/components/shadcn/menubar_sub_component.rb +38 -0
  206. data/app/components/shadcn/menubar_sub_content_component.rb +45 -0
  207. data/app/components/shadcn/menubar_sub_trigger_component.rb +59 -0
  208. data/app/components/shadcn/menubar_trigger_component.rb +31 -0
  209. data/app/components/shadcn/native_select_component.rb +150 -0
  210. data/app/components/shadcn/navigation_menu_component.rb +76 -0
  211. data/app/components/shadcn/navigation_menu_content_component.rb +30 -0
  212. data/app/components/shadcn/navigation_menu_item_component.rb +39 -0
  213. data/app/components/shadcn/navigation_menu_link_component.rb +38 -0
  214. data/app/components/shadcn/navigation_menu_list_component.rb +29 -0
  215. data/app/components/shadcn/navigation_menu_trigger_component.rb +59 -0
  216. data/app/components/shadcn/pagination_component.rb +195 -0
  217. data/app/components/shadcn/pagination_content_component.rb +47 -0
  218. data/app/components/shadcn/pagination_ellipsis_component.rb +30 -0
  219. data/app/components/shadcn/pagination_item_component.rb +53 -0
  220. data/app/components/shadcn/pagination_next_component.rb +48 -0
  221. data/app/components/shadcn/pagination_previous_component.rb +48 -0
  222. data/app/components/shadcn/popover_component.rb +76 -0
  223. data/app/components/shadcn/popover_content_component.rb +25 -0
  224. data/app/components/shadcn/progress_component.rb +77 -0
  225. data/app/components/shadcn/radio_group_component.rb +129 -0
  226. data/app/components/shadcn/radio_group_item_component.rb +109 -0
  227. data/app/components/shadcn/resizable_handle_component.rb +98 -0
  228. data/app/components/shadcn/resizable_panel_component.rb +56 -0
  229. data/app/components/shadcn/resizable_panel_group_component.rb +94 -0
  230. data/app/components/shadcn/scroll_area_component.rb +110 -0
  231. data/app/components/shadcn/select_component.rb +151 -0
  232. data/app/components/shadcn/select_group_component.rb +32 -0
  233. data/app/components/shadcn/select_item_component.rb +59 -0
  234. data/app/components/shadcn/select_separator_component.rb +12 -0
  235. data/app/components/shadcn/separator_component.rb +54 -0
  236. data/app/components/shadcn/sheet_component.rb +82 -0
  237. data/app/components/shadcn/sheet_content_component.rb +95 -0
  238. data/app/components/shadcn/sheet_description_component.rb +12 -0
  239. data/app/components/shadcn/sheet_footer_component.rb +12 -0
  240. data/app/components/shadcn/sheet_header_component.rb +19 -0
  241. data/app/components/shadcn/sheet_title_component.rb +12 -0
  242. data/app/components/shadcn/sidebar_component.rb +180 -0
  243. data/app/components/shadcn/sidebar_content_component.rb +32 -0
  244. data/app/components/shadcn/sidebar_footer_component.rb +24 -0
  245. data/app/components/shadcn/sidebar_group_action_component.rb +26 -0
  246. data/app/components/shadcn/sidebar_group_component.rb +38 -0
  247. data/app/components/shadcn/sidebar_group_content_component.rb +32 -0
  248. data/app/components/shadcn/sidebar_group_label_component.rb +25 -0
  249. data/app/components/shadcn/sidebar_header_component.rb +24 -0
  250. data/app/components/shadcn/sidebar_inset_component.rb +25 -0
  251. data/app/components/shadcn/sidebar_menu_action_component.rb +37 -0
  252. data/app/components/shadcn/sidebar_menu_badge_component.rb +25 -0
  253. data/app/components/shadcn/sidebar_menu_button_component.rb +52 -0
  254. data/app/components/shadcn/sidebar_menu_component.rb +32 -0
  255. data/app/components/shadcn/sidebar_menu_item_component.rb +41 -0
  256. data/app/components/shadcn/sidebar_menu_skeleton_component.rb +46 -0
  257. data/app/components/shadcn/sidebar_menu_sub_button_component.rb +43 -0
  258. data/app/components/shadcn/sidebar_menu_sub_component.rb +33 -0
  259. data/app/components/shadcn/sidebar_menu_sub_item_component.rb +30 -0
  260. data/app/components/shadcn/sidebar_provider_component.rb +57 -0
  261. data/app/components/shadcn/sidebar_rail_component.rb +30 -0
  262. data/app/components/shadcn/sidebar_separator_component.rb +24 -0
  263. data/app/components/shadcn/sidebar_trigger_component.rb +51 -0
  264. data/app/components/shadcn/skeleton_component.rb +29 -0
  265. data/app/components/shadcn/slider_component.rb +76 -0
  266. data/app/components/shadcn/spinner_component.rb +67 -0
  267. data/app/components/shadcn/switch_component.rb +147 -0
  268. data/app/components/shadcn/table_body_component.rb +16 -0
  269. data/app/components/shadcn/table_caption_component.rb +12 -0
  270. data/app/components/shadcn/table_cell_component.rb +12 -0
  271. data/app/components/shadcn/table_component.rb +57 -0
  272. data/app/components/shadcn/table_footer_component.rb +16 -0
  273. data/app/components/shadcn/table_head_component.rb +12 -0
  274. data/app/components/shadcn/table_header_component.rb +16 -0
  275. data/app/components/shadcn/table_row_component.rb +40 -0
  276. data/app/components/shadcn/tabs_component.rb +78 -0
  277. data/app/components/shadcn/tabs_content_component.rb +32 -0
  278. data/app/components/shadcn/tabs_list_component.rb +30 -0
  279. data/app/components/shadcn/tabs_trigger_component.rb +37 -0
  280. data/app/components/shadcn/textarea_component.rb +84 -0
  281. data/app/components/shadcn/toast_action_component.rb +18 -0
  282. data/app/components/shadcn/toast_component.rb +114 -0
  283. data/app/components/shadcn/toast_description_component.rb +12 -0
  284. data/app/components/shadcn/toast_title_component.rb +12 -0
  285. data/app/components/shadcn/toast_viewport_component.rb +12 -0
  286. data/app/components/shadcn/toggle_component.rb +77 -0
  287. data/app/components/shadcn/toggle_group_component.rb +96 -0
  288. data/app/components/shadcn/toggle_group_item_component.rb +62 -0
  289. data/app/components/shadcn/tooltip_component.rb +89 -0
  290. data/app/components/shadcn/typography_component.rb +112 -0
  291. data/babel.config.cjs +5 -0
  292. data/bin/console +11 -0
  293. data/bin/setup +8 -0
  294. data/config/importmap.rb +5 -0
  295. data/fly.toml +26 -0
  296. data/jest.config.js +19 -0
  297. data/jest.setup.js +8 -0
  298. data/lib/generators/shadcn/component/component_generator.rb +188 -0
  299. data/lib/generators/shadcn/install/install_generator.rb +140 -0
  300. data/lib/generators/shadcn/install/templates/initializer.rb.tt +35 -0
  301. data/lib/generators/shadcn/install/templates/shadcn.yml.tt +35 -0
  302. data/lib/generators/shadcn/theme/theme_generator.rb +128 -0
  303. data/lib/shadcn/rails/class_merger.rb +228 -0
  304. data/lib/shadcn/rails/configuration.rb +341 -0
  305. data/lib/shadcn/rails/engine.rb +59 -0
  306. data/lib/shadcn/rails/helpers/class_name_helper.rb +35 -0
  307. data/lib/shadcn/rails/helpers/component_helper.rb +60 -0
  308. data/lib/shadcn/rails/helpers/pagination_helper.rb +187 -0
  309. data/lib/shadcn/rails/version.rb +7 -0
  310. data/lib/shadcn/rails.rb +179 -0
  311. data/package-lock.json +7415 -0
  312. data/package.json +68 -0
  313. data/rollup.config.js +29 -0
  314. data/sig/shadcn/rails.rbs +6 -0
  315. metadata +526 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 91e663eb5a019fc790f77760827732cadc390370b571b56b67d86615a94d7b4e
4
+ data.tar.gz: 6ebd1786b43b3ff9c67f53741455d259f295bde129ec5c71af020c9e9946d4a1
5
+ SHA512:
6
+ metadata.gz: 91bc71ef5c64f298fd17fadfdec2674fb2478e6942a3e6466d7ad226b06f46bbdcb348738613d6c8d7fa28b936c141701148a0492bcde44e18af4a1ecbb1058a
7
+ data.tar.gz: a65da33bedb5affa1c8ecae55bbae1e149910f06fdaa4ee1df45822e95ab2179ce799fbc1630e3ade61ccab6af815b9c533aa7d4110f5fcc08bdf75a84dfd4a9
data/.dockerignore ADDED
@@ -0,0 +1,40 @@
1
+ # .dockerignore for shadcn-rails
2
+ # Keep the build context small while including necessary files
3
+
4
+ # Git
5
+ .git
6
+ .gitignore
7
+
8
+ # IDE
9
+ .idea
10
+ .vscode
11
+ *.swp
12
+ *.swo
13
+
14
+ # OS
15
+ .DS_Store
16
+ Thumbs.db
17
+
18
+ # Ruby
19
+ *.gem
20
+ .bundle
21
+ vendor/bundle
22
+
23
+ # Logs
24
+ log/*
25
+ tmp/*
26
+ *.log
27
+
28
+ # Test artifacts
29
+ coverage/
30
+ test/dummy/tmp/
31
+ test/dummy/log/
32
+ test/dummy/storage/
33
+
34
+ # Node (if any)
35
+ node_modules/
36
+
37
+ # Keep these (don't ignore)
38
+ # !app/
39
+ # !lib/
40
+ # !test/dummy/
data/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2024-11-27
11
+
12
+ ### Added
13
+
14
+ - Initial release of shadcn-rails
15
+ - **40+ ViewComponents** ported from shadcn/ui:
16
+ - Accordion, Alert, AlertDialog, AspectRatio, Avatar, Badge
17
+ - Breadcrumb, Button, Calendar, Card, Carousel, Checkbox
18
+ - Collapsible, Combobox, Command, ContextMenu, DatePicker
19
+ - Dialog, Drawer, DropdownMenu, HoverCard, Input, Label
20
+ - Menubar, Pagination, Popover, Progress, RadioGroup
21
+ - ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton
22
+ - Slider, Switch, Tabs, Textarea, Toast, Toggle, ToggleGroup, Tooltip
23
+ - **Stimulus Controllers** for interactive components:
24
+ - Accordion, AlertDialog, Calendar, Carousel, Checkbox, Collapsible
25
+ - Combobox, Command, ContextMenu, Dialog, Drawer, DropdownMenu
26
+ - HoverCard, Menubar, Popover, RadioGroup, ScrollArea, Select
27
+ - Sheet, Sidebar, Slider, Switch, Tabs, Toast, Toggle, ToggleGroup, Tooltip
28
+ - **CSS Theming** with HSL color variables and dark mode support
29
+ - **Theme presets**: neutral, slate, stone, zinc, gray
30
+ - **Rails generators**:
31
+ - `rails g shadcn:install` - Initial setup
32
+ - `rails g shadcn:component [name]` - Add individual components
33
+ - `rails g shadcn:theme [name]` - Switch color themes
34
+ - **Tailwind CSS integration** with class merging utility
35
+ - **Accessibility features** following WAI-ARIA patterns
36
+ - **npm package** (`shadcn-rails-stimulus`) for Stimulus controllers
37
+ - **Comprehensive test suite** with 500+ Ruby tests and 1100+ JavaScript tests
38
+
39
+ ### Slider Controller Features
40
+
41
+ - One-way output sync via `data-output-target` and `data-output-format`
42
+ - Two-way input binding via `data-input-target` for slider/input synchronization
43
+ - CSS custom property `--slider-fill` for visual fill styling
44
+ - Support for controller attached directly to `<input type="range">` elements
45
+
46
+ ### Documentation
47
+
48
+ - Full documentation site with live examples
49
+ - API reference for all components
50
+ - Accessibility guidelines
51
+ - Installation instructions for various JavaScript bundlers
52
+
53
+ [Unreleased]: https://github.com/iheanyi/shadcn-rails/compare/v0.1.0...HEAD
54
+ [0.1.0]: https://github.com/iheanyi/shadcn-rails/releases/tag/v0.1.0
data/CLAUDE.md ADDED
@@ -0,0 +1,463 @@
1
+ # CLAUDE.md - Development Guide for shadcn-rails
2
+
3
+ This document contains learnings, patterns, and guidelines for future development sessions on this project.
4
+
5
+ ## Project Overview
6
+
7
+ shadcn-rails is a Ruby port of [shadcn/ui](https://ui.shadcn.com) for Rails applications. It uses:
8
+ - **ViewComponent** for Ruby-based component architecture
9
+ - **Stimulus** for JavaScript interactivity
10
+ - **Tailwind CSS** for styling
11
+ - **CSS Custom Properties** for theming
12
+
13
+ ## Architecture Patterns
14
+
15
+ ### Component Structure
16
+
17
+ All components inherit from `Shadcn::BaseComponent` which provides:
18
+ - `cn(*classes)` - Class name merging utility (like clsx + tailwind-merge)
19
+ - `stimulus_data(controller, values, actions)` - Stimulus data attribute builder
20
+ - `build_html_attributes(**attrs)` - HTML attribute builder with class merging
21
+
22
+ ```ruby
23
+ # app/components/shadcn/base_component.rb
24
+ class Shadcn::BaseComponent < ViewComponent::Base
25
+ include Shadcn::Rails::Helpers::ClassNameHelper
26
+
27
+ def cn(*classes)
28
+ Shadcn::Rails.cn(*classes)
29
+ end
30
+ end
31
+ ```
32
+
33
+ ### Component Location
34
+
35
+ Components are located in `app/components/shadcn/`:
36
+ - Each component is a single Ruby file (e.g., `button_component.rb`)
37
+ - Complex components use ViewComponent slots for composition
38
+ - ERB templates are inline using `erb_template` when simple, or separate `.html.erb` files when complex
39
+
40
+ ### Stimulus Controllers
41
+
42
+ Controllers are in `app/assets/javascripts/shadcn/controllers/`:
43
+ - Named `{component}_controller.js`
44
+ - Use Stimulus naming convention: `shadcn--{component}`
45
+ - Handle interactivity: open/close states, keyboard navigation, focus management
46
+
47
+ ```javascript
48
+ // Example controller pattern
49
+ import { Controller } from "@hotwired/stimulus"
50
+
51
+ export default class extends Controller {
52
+ static targets = ["trigger", "content"]
53
+ static values = { open: Boolean }
54
+
55
+ toggle() {
56
+ this.openValue = !this.openValue
57
+ }
58
+
59
+ openValueChanged() {
60
+ // React to state changes
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### CSS Theming
66
+
67
+ CSS variables are defined in `app/assets/stylesheets/shadcn/base.css`:
68
+ - All colors use HSL format without `hsl()` wrapper: `--primary: 0 0% 9%;`
69
+ - Components use: `hsl(var(--primary))`
70
+ - Dark mode uses `.dark` class on `<html>` element
71
+
72
+ Theme presets are in `lib/shadcn/rails/configuration.rb` with full HSL values for:
73
+ - neutral, slate, stone, zinc, gray
74
+
75
+ ## Key Files
76
+
77
+ ### Core Library
78
+ - `lib/shadcn/rails.rb` - Main module, configuration, `cn()` helper
79
+ - `lib/shadcn/rails/engine.rb` - Rails engine setup
80
+ - `lib/shadcn/rails/configuration.rb` - Theme configuration with CSS variables
81
+ - `lib/shadcn/rails/class_merger.rb` - Tailwind class conflict resolution
82
+
83
+ ### Components (app/components/shadcn/)
84
+
85
+ The library includes 47 components organized by category:
86
+
87
+ **Buttons & Actions**
88
+ | File | Description |
89
+ |------|-------------|
90
+ | `button_component.rb` | 6 variants (default, secondary, destructive, outline, ghost, link), 6 sizes |
91
+ | `toggle_component.rb` | Two-state button with pressed/unpressed states |
92
+ | `toggle_group_component.rb` | Group of toggle buttons (single/multiple selection) |
93
+ | `button_group_component.rb` | Group of related buttons |
94
+
95
+ **Form Inputs**
96
+ | File | Description |
97
+ |------|-------------|
98
+ | `input_component.rb` | Text input with various types |
99
+ | `textarea_component.rb` | Multi-line text input |
100
+ | `label_component.rb` | Form label element |
101
+ | `checkbox_component.rb` | Checkbox with indeterminate state support |
102
+ | `switch_component.rb` | Toggle switch control |
103
+ | `slider_component.rb` | Range slider input |
104
+ | `select_component.rb` | Custom styled select dropdown |
105
+ | `native_select_component.rb` | Native HTML select with styling |
106
+ | `radio_group_component.rb` | Radio button group |
107
+ | `field_component.rb` | Form field wrapper with label/error slots |
108
+ | `input_group_component.rb` | Input with prefix/suffix addons |
109
+ | `input_otp_component.rb` | One-time password input |
110
+
111
+ **Data Display**
112
+ | File | Description |
113
+ |------|-------------|
114
+ | `badge_component.rb` | Labels with variants (default, secondary, destructive, outline) |
115
+ | `avatar_component.rb` | User avatar with image/fallback |
116
+ | `card_component.rb` | Header, content, footer slots |
117
+ | `table_component.rb` | Styled table with header/body/footer |
118
+ | `progress_component.rb` | Progress bar indicator |
119
+ | `skeleton_component.rb` | Loading placeholder |
120
+ | `spinner_component.rb` | Loading spinner animation |
121
+ | `kbd_component.rb` | Keyboard key display |
122
+ | `typography_component.rb` | Text styling utilities |
123
+ | `aspect_ratio_component.rb` | Maintains aspect ratio for media content |
124
+ | `scroll_area_component.rb` | Custom scrollbar container |
125
+
126
+ **Feedback**
127
+ | File | Description |
128
+ |------|-------------|
129
+ | `alert_component.rb` | Callout/notification with variants (default, destructive) |
130
+ | `tooltip_component.rb` | Hover tooltip popup |
131
+ | `toast_component.rb` | Temporary notification messages |
132
+
133
+ **Overlays**
134
+ | File | Description |
135
+ |------|-------------|
136
+ | `dialog_component.rb` | Modal with portal, focus trap |
137
+ | `alert_dialog_component.rb` | Confirmation dialog with cancel/confirm actions |
138
+ | `sheet_component.rb` | Slide-out panel from any edge |
139
+ | `drawer_component.rb` | Bottom sheet drawer |
140
+ | `popover_component.rb` | Floating content panel |
141
+ | `hover_card_component.rb` | Card that appears on hover |
142
+ | `dropdown_menu_component.rb` | Dropdown menu with items, separators, keyboard shortcuts |
143
+
144
+ **Navigation**
145
+ | File | Description |
146
+ |------|-------------|
147
+ | `tabs_component.rb` | Tabbed interface with URL sync support |
148
+ | `accordion_component.rb` | Collapsible sections (single/multiple mode) |
149
+ | `breadcrumb_component.rb` | Navigation breadcrumb trail |
150
+ | `pagination_component.rb` | Page navigation with Kaminari/Pagy/WillPaginate support |
151
+ | `collapsible_component.rb` | Show/hide content section |
152
+ | `separator_component.rb` | Visual divider line |
153
+ | `context_menu_component.rb` | Right-click context menu |
154
+ | `menubar_component.rb` | Horizontal menu bar with dropdowns |
155
+ | `navigation_menu_component.rb` | Navigation with dropdown content |
156
+ | `resizable_component.rb` | Resizable panel groups |
157
+
158
+ ### Generators (lib/generators/shadcn/)
159
+ - `install/` - Initial setup generator
160
+ - `component/` - Add individual components
161
+ - `theme/` - Switch color themes
162
+
163
+ ### Tests
164
+ - `test/components/` - Component unit tests
165
+ - `test/components/previews/` - Lookbook previews
166
+ - `test/dummy/` - Rails dummy app for integration testing
167
+
168
+ ## Development Commands
169
+
170
+ ```bash
171
+ # Install dependencies
172
+ bundle install
173
+
174
+ # Run tests
175
+ bundle exec rake test
176
+
177
+ # Run component tests only
178
+ bundle exec rake test_components
179
+
180
+ # Start dummy app
181
+ cd test/dummy && rails server
182
+
183
+ # Start Lookbook previews
184
+ cd test/dummy && rails lookbook:preview
185
+ ```
186
+
187
+ ## Patterns to Follow
188
+
189
+ ### 1. Component Variants
190
+
191
+ Use symbols for variant options and define them as constants:
192
+
193
+ ```ruby
194
+ VARIANTS = {
195
+ default: "bg-primary text-primary-foreground",
196
+ destructive: "bg-destructive text-destructive-foreground",
197
+ outline: "border border-input bg-background",
198
+ secondary: "bg-secondary text-secondary-foreground",
199
+ ghost: "hover:bg-accent hover:text-accent-foreground",
200
+ link: "text-primary underline-offset-4 hover:underline"
201
+ }
202
+
203
+ def initialize(variant: :default, **attrs)
204
+ @variant = variant.to_sym
205
+ end
206
+ ```
207
+
208
+ ### 2. Compound Components with Slots
209
+
210
+ Use ViewComponent's `renders_one` and `renders_many` for composition:
211
+
212
+ ```ruby
213
+ renders_one :header, "HeaderComponent"
214
+ renders_many :items, "ItemComponent"
215
+
216
+ class HeaderComponent < ViewComponent::Base
217
+ renders_one :title
218
+ renders_one :description
219
+ end
220
+ ```
221
+
222
+ ### 3. Stimulus Integration
223
+
224
+ Components that need JavaScript should:
225
+ 1. Define a Stimulus controller
226
+ 2. Use `stimulus_data()` helper in the component
227
+ 3. Follow the `shadcn--{name}` naming convention
228
+
229
+ ```ruby
230
+ def stimulus_attributes
231
+ stimulus_data(
232
+ "shadcn--dialog",
233
+ { open: @open },
234
+ { "trigger->click": "toggle" }
235
+ )
236
+ end
237
+ ```
238
+
239
+ ### 4. Accessibility (ARIA)
240
+
241
+ All interactive components must include proper ARIA attributes:
242
+ - `role` attributes where needed
243
+ - `aria-expanded`, `aria-hidden`, `aria-controls`
244
+ - `aria-labelledby`, `aria-describedby` for relationships
245
+ - Keyboard navigation support
246
+
247
+ ### 5. CSS Class Merging
248
+
249
+ Always use `cn()` for class composition to handle Tailwind conflicts:
250
+
251
+ ```ruby
252
+ def classes
253
+ cn(
254
+ "base-classes here",
255
+ VARIANTS[@variant],
256
+ SIZES[@size],
257
+ @class_name
258
+ )
259
+ end
260
+ ```
261
+
262
+ ### 6. Test Coverage
263
+
264
+ For each component, create tests in `test/components/`:
265
+ - Test default rendering
266
+ - Test all variants
267
+ - Test all sizes (if applicable)
268
+ - Test slot rendering
269
+ - Test accessibility attributes
270
+
271
+ ```ruby
272
+ class ButtonComponentTest < ViewComponent::TestCase
273
+ def test_renders_button
274
+ render_inline(Shadcn::ButtonComponent.new) { "Click" }
275
+ assert_selector "button", text: "Click"
276
+ end
277
+
278
+ def test_renders_variants
279
+ Shadcn::ButtonComponent::VARIANTS.keys.each do |variant|
280
+ render_inline(Shadcn::ButtonComponent.new(variant: variant)) { "Test" }
281
+ assert_selector "button"
282
+ end
283
+ end
284
+ end
285
+ ```
286
+
287
+ ## Adding New Components
288
+
289
+ 1. Create component file in `app/components/shadcn/{name}_component.rb`
290
+ 2. Inherit from `Shadcn::BaseComponent`
291
+ 3. If interactive, create Stimulus controller in `app/assets/javascripts/shadcn/controllers/{name}_controller.js`
292
+ 4. Add controller export to `app/assets/javascripts/shadcn/index.js`
293
+ 5. Create test in `test/components/{name}_component_test.rb`
294
+ 6. Create Lookbook preview in `test/components/previews/{name}_component_preview.rb`
295
+ 7. Add example to dummy app views
296
+
297
+ ## Common Issues & Solutions
298
+
299
+ ### ViewComponent Preview Nested Render Issue
300
+
301
+ **Problem**: When using nested `render()` calls inside ViewComponent preview slots, the output is a hash like `{args: {}, block: #<Proc:...>, component: #<...>}` instead of rendered HTML.
302
+
303
+ **Solution**: Use raw HTML strings instead of nested render calls in previews:
304
+
305
+ ```ruby
306
+ # BAD - nested render returns hash, not HTML
307
+ def default
308
+ render(Shadcn::DialogComponent.new) do |dialog|
309
+ dialog.with_trigger do
310
+ render(Shadcn::ButtonComponent.new(variant: :outline)) { "Open" } # Returns hash!
311
+ end
312
+ end
313
+ end
314
+
315
+ # GOOD - use raw HTML strings or helper methods
316
+ def default
317
+ render(Shadcn::DialogComponent.new) do |dialog|
318
+ dialog.with_trigger do
319
+ button_html(:outline, "Open") # Returns HTML string
320
+ end
321
+ end
322
+ end
323
+
324
+ private
325
+
326
+ def button_html(variant, text, extra_class = nil)
327
+ # Generate HTML string directly
328
+ %(<button class="#{classes}">#{text}</button>).html_safe
329
+ end
330
+ ```
331
+
332
+ ### Superclass Mismatch Error
333
+
334
+ **Problem**: Rails throws "superclass mismatch for class X" error for nested component classes (e.g., `DialogContentComponent`).
335
+
336
+ **Cause**: Rails Zeitwerk autoloading gets confused when nested classes are reloaded and the parent class definition has changed.
337
+
338
+ **Solution**: Restart the Rails server to clear cached class definitions. This commonly happens when modifying component files with nested classes.
339
+
340
+ ### Tailwind Class Conflicts
341
+
342
+ The `ClassMerger` utility handles conflicts like `p-2 p-4` (p-4 wins). If you encounter unresolved conflicts, add the pattern to `CLASS_GROUPS` or `CONFLICT_PATTERNS` in `lib/shadcn/rails/class_merger.rb`.
343
+
344
+ **Pattern Ordering Issue**: When adding regex patterns to `CONFLICT_PATTERNS`, be careful of pattern matching order. The `find_conflict_group` method returns on the first match, so patterns must use negative lookaheads to exclude overlapping cases.
345
+
346
+ Example fix for border classes:
347
+ ```ruby
348
+ # PROBLEM: border-0 was matching border_color before border_width
349
+ /^border-(?!solid|dashed|dotted|double|none)/ => :border_color,
350
+
351
+ # SOLUTION: Add [0-9] to the negative lookahead to exclude border widths
352
+ /^border-(?!solid|dashed|dotted|double|none|[0-9])/ => :border_color,
353
+ ```
354
+
355
+ This ensures `border-0`, `border-2`, etc. are categorized as `:border_width` (not `:border_color`) so they properly conflict with and override `border`.
356
+
357
+ ### Stimulus Controller Not Loading
358
+
359
+ Ensure:
360
+ 1. Controller is exported in `index.js`
361
+ 2. Controller name matches: `shadcn--{name}`
362
+ 3. User has called `registerShadcnControllers(application)` or manually registered
363
+
364
+ ### Preview Layout Requirements
365
+
366
+ The `component_preview.html.erb` layout must include:
367
+ 1. **Tailwind CSS** via CDN with custom shadcn color tokens
368
+ 2. **Stimulus application** initialized and connected
369
+ 3. **Inline Stimulus controllers** for all interactive components (Dialog, Sheet, Tabs, Accordion, Checkbox, Switch, Popover, Tooltip)
370
+ 4. **CSS animations** for transitions (dialog fade-in, sheet slide-in, etc.)
371
+
372
+ For previews, Stimulus controllers are inlined directly in the layout since the JavaScript bundling isn't available. This is different from production where controllers come from the npm package.
373
+
374
+ ### Tabs Controller Method Names
375
+
376
+ The Tabs Stimulus controller uses `selectTab` for the click action, not `select`:
377
+
378
+ ```javascript
379
+ // In tabs_controller.js
380
+ selectTab(event) {
381
+ const trigger = event.currentTarget
382
+ const value = trigger.dataset.value
383
+ this.valueValue = value
384
+ }
385
+ ```
386
+
387
+ Ensure your triggers use: `data-action="click->shadcn--tabs#selectTab"`
388
+
389
+ ### Dark Mode Not Working
390
+
391
+ Check:
392
+ 1. CSS variables are loaded
393
+ 2. `.dark` class is on `<html>` element (not `<body>`)
394
+ 3. Tailwind dark mode is configured as `class` strategy
395
+
396
+ ## Documentation Site
397
+
398
+ The `test/dummy` app serves as both a testing environment and documentation site. It includes:
399
+ - Full documentation for all 47 components at `/docs`
400
+ - Live interactive examples that demonstrate each component
401
+ - Code examples stored in `app/code_examples/{component}/` as `.txt` files
402
+ - `erb_example` helper to display code examples with syntax highlighting
403
+ - Showcase page at `/showcase`
404
+
405
+ ### Documentation Structure
406
+
407
+ ```
408
+ test/dummy/
409
+ ├── app/
410
+ │ ├── views/docs/ # Component documentation pages
411
+ │ │ ├── button.html.erb
412
+ │ │ ├── dialog.html.erb
413
+ │ │ └── ...
414
+ │ ├── code_examples/ # Code examples displayed in docs
415
+ │ │ ├── button/
416
+ │ │ │ └── default.txt
417
+ │ │ └── pagination/
418
+ │ │ ├── kaminari_view.txt
419
+ │ │ └── pagy_view.txt
420
+ │ └── helpers/
421
+ │ └── docs_helper.rb # erb_example helper method
422
+ ```
423
+
424
+ ## Future Improvements
425
+
426
+ **Missing Components** (from shadcn/ui):
427
+ - [ ] Command palette
428
+ - [ ] Combobox
429
+ - [ ] Date Picker
430
+ - [ ] Calendar
431
+ - [ ] Sonner (toast alternative)
432
+ - [ ] Carousel
433
+ - [ ] Chart
434
+ - [ ] Data Table
435
+ - [ ] Sidebar
436
+
437
+ **Enhancements**:
438
+ - [ ] Form builder integration (Rails form helpers)
439
+ - [ ] Hotwire/Turbo Stream integration helpers
440
+ - [ ] RTL support
441
+ - [ ] Visual regression tests with Percy or similar
442
+ - [ ] Dropdown Menu submenus and checkbox/radio items
443
+ - [ ] Drawer gesture support (touch drag to dismiss)
444
+
445
+ **Completed**:
446
+ - [x] 47 core components implemented
447
+ - [x] Full documentation site with live examples
448
+ - [x] Stimulus controllers for all interactive components
449
+ - [x] Pagination with Kaminari/Pagy/WillPaginate adapters
450
+ - [x] CSS animations for dialogs, sheets, toasts, accordions
451
+ - [x] Context Menu component
452
+ - [x] Menubar component
453
+ - [x] Navigation Menu component
454
+ - [x] Resizable panels component
455
+ - [x] Input OTP with group separators
456
+
457
+ ## Resources
458
+
459
+ - [shadcn/ui Documentation](https://ui.shadcn.com)
460
+ - [ViewComponent Guide](https://viewcomponent.org)
461
+ - [Stimulus Handbook](https://stimulus.hotwired.dev/handbook/introduction)
462
+ - [Tailwind CSS Documentation](https://tailwindcss.com/docs)
463
+ - [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)