shadcn_view_component 0.3.3

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 (507) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +255 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +604 -0
  5. data/app/assets/stylesheets/shadcn-themes.css +1075 -0
  6. data/app/assets/stylesheets/shadcn.css +853 -0
  7. data/app/components/shadcn/accordion/component.rb +44 -0
  8. data/app/components/shadcn/accordion/content/component.rb +44 -0
  9. data/app/components/shadcn/accordion/item/component.rb +41 -0
  10. data/app/components/shadcn/accordion/preview.rb +16 -0
  11. data/app/components/shadcn/accordion/previews/default.html.erb +10 -0
  12. data/app/components/shadcn/accordion/previews/multiple.html.erb +13 -0
  13. data/app/components/shadcn/accordion/trigger/component.rb +52 -0
  14. data/app/components/shadcn/alert/component.rb +52 -0
  15. data/app/components/shadcn/alert/preview.rb +11 -0
  16. data/app/components/shadcn/alert/previews/default.html.erb +8 -0
  17. data/app/components/shadcn/alert.rb +17 -0
  18. data/app/components/shadcn/alert_dialog/action/component.rb +35 -0
  19. data/app/components/shadcn/alert_dialog/cancel/component.rb +16 -0
  20. data/app/components/shadcn/alert_dialog/component.rb +20 -0
  21. data/app/components/shadcn/alert_dialog/content/component.rb +55 -0
  22. data/app/components/shadcn/alert_dialog/header/component.rb +33 -0
  23. data/app/components/shadcn/alert_dialog/preview.rb +16 -0
  24. data/app/components/shadcn/alert_dialog/previews/default.html.erb +13 -0
  25. data/app/components/shadcn/alert_dialog/previews/small_with_media.html.erb +38 -0
  26. data/app/components/shadcn/alert_dialog.rb +32 -0
  27. data/app/components/shadcn/application_view_component.rb +225 -0
  28. data/app/components/shadcn/application_view_component_preview.rb +8 -0
  29. data/app/components/shadcn/aspect_ratio/component.rb +34 -0
  30. data/app/components/shadcn/aspect_ratio/preview.rb +16 -0
  31. data/app/components/shadcn/aspect_ratio/previews/default.html.erb +5 -0
  32. data/app/components/shadcn/aspect_ratio/previews/ratios.html.erb +12 -0
  33. data/app/components/shadcn/attachment/action/component.rb +19 -0
  34. data/app/components/shadcn/attachment/component.rb +76 -0
  35. data/app/components/shadcn/attachment/media/component.rb +56 -0
  36. data/app/components/shadcn/attachment/preview.rb +11 -0
  37. data/app/components/shadcn/attachment/previews/default.html.erb +80 -0
  38. data/app/components/shadcn/attachment/trigger/component.rb +31 -0
  39. data/app/components/shadcn/attachment.rb +42 -0
  40. data/app/components/shadcn/avatar/component.rb +43 -0
  41. data/app/components/shadcn/avatar/fallback/component.rb +23 -0
  42. data/app/components/shadcn/avatar/image/component.rb +20 -0
  43. data/app/components/shadcn/avatar/preview.rb +11 -0
  44. data/app/components/shadcn/avatar/previews/default.html.erb +13 -0
  45. data/app/components/shadcn/avatar.rb +32 -0
  46. data/app/components/shadcn/badge/component.rb +57 -0
  47. data/app/components/shadcn/badge/preview.rb +11 -0
  48. data/app/components/shadcn/badge/previews/default.html.erb +5 -0
  49. data/app/components/shadcn/breadcrumb/component.rb +15 -0
  50. data/app/components/shadcn/breadcrumb/ellipsis/component.rb +28 -0
  51. data/app/components/shadcn/breadcrumb/page/component.rb +25 -0
  52. data/app/components/shadcn/breadcrumb/preview.rb +16 -0
  53. data/app/components/shadcn/breadcrumb/previews/custom_separator.html.erb +17 -0
  54. data/app/components/shadcn/breadcrumb/previews/default.html.erb +15 -0
  55. data/app/components/shadcn/breadcrumb/separator/component.rb +31 -0
  56. data/app/components/shadcn/breadcrumb.rb +18 -0
  57. data/app/components/shadcn/bubble/component.rb +90 -0
  58. data/app/components/shadcn/bubble/preview.rb +16 -0
  59. data/app/components/shadcn/bubble/previews/alignment.html.erb +33 -0
  60. data/app/components/shadcn/bubble/previews/default.html.erb +22 -0
  61. data/app/components/shadcn/bubble/reactions/component.rb +54 -0
  62. data/app/components/shadcn/bubble.rb +24 -0
  63. data/app/components/shadcn/button/component.rb +85 -0
  64. data/app/components/shadcn/button/preview.rb +31 -0
  65. data/app/components/shadcn/button/previews/default.html.erb +8 -0
  66. data/app/components/shadcn/button/previews/sizes.html.erb +5 -0
  67. data/app/components/shadcn/button/previews/variants.html.erb +5 -0
  68. data/app/components/shadcn/button_group/component.rb +53 -0
  69. data/app/components/shadcn/button_group/preview.rb +15 -0
  70. data/app/components/shadcn/button_group/previews/default.html.erb +18 -0
  71. data/app/components/shadcn/button_group/previews/vertical.html.erb +5 -0
  72. data/app/components/shadcn/button_group/separator/component.rb +30 -0
  73. data/app/components/shadcn/button_group/text/component.rb +20 -0
  74. data/app/components/shadcn/calendar/component.rb +558 -0
  75. data/app/components/shadcn/calendar/month.rb +74 -0
  76. data/app/components/shadcn/calendar/preview.rb +64 -0
  77. data/app/components/shadcn/calendar/previews/booked.html.erb +18 -0
  78. data/app/components/shadcn/calendar/previews/custom_cell_size.html.erb +11 -0
  79. data/app/components/shadcn/calendar/previews/date_and_time.html.erb +31 -0
  80. data/app/components/shadcn/calendar/previews/default.html.erb +8 -0
  81. data/app/components/shadcn/calendar/previews/dropdown_caption.html.erb +11 -0
  82. data/app/components/shadcn/calendar/previews/in_a_form.html.erb +8 -0
  83. data/app/components/shadcn/calendar/previews/presets.html.erb +20 -0
  84. data/app/components/shadcn/calendar/previews/range.html.erb +10 -0
  85. data/app/components/shadcn/calendar/previews/week_numbers.html.erb +8 -0
  86. data/app/components/shadcn/card/component.rb +24 -0
  87. data/app/components/shadcn/card/header/component.rb +26 -0
  88. data/app/components/shadcn/card/preview.rb +16 -0
  89. data/app/components/shadcn/card/previews/default.html.erb +18 -0
  90. data/app/components/shadcn/card/previews/image.html.erb +37 -0
  91. data/app/components/shadcn/card.rb +21 -0
  92. data/app/components/shadcn/carousel/component.rb +61 -0
  93. data/app/components/shadcn/carousel/content/component.rb +86 -0
  94. data/app/components/shadcn/carousel/item/component.rb +42 -0
  95. data/app/components/shadcn/carousel/next/component.rb +59 -0
  96. data/app/components/shadcn/carousel/preview.rb +22 -0
  97. data/app/components/shadcn/carousel/previews/default.html.erb +22 -0
  98. data/app/components/shadcn/carousel/previews/sizes.html.erb +42 -0
  99. data/app/components/shadcn/carousel/previews/vertical.html.erb +27 -0
  100. data/app/components/shadcn/carousel/previous/component.rb +59 -0
  101. data/app/components/shadcn/chart/area/component.rb +43 -0
  102. data/app/components/shadcn/chart/bar/component.rb +75 -0
  103. data/app/components/shadcn/chart/cartesian/component.rb +152 -0
  104. data/app/components/shadcn/chart/component.rb +124 -0
  105. data/app/components/shadcn/chart/focusable.rb +38 -0
  106. data/app/components/shadcn/chart/legend/component.rb +55 -0
  107. data/app/components/shadcn/chart/line/component.rb +50 -0
  108. data/app/components/shadcn/chart/pie/component.rb +169 -0
  109. data/app/components/shadcn/chart/plot.rb +147 -0
  110. data/app/components/shadcn/chart/preview.rb +45 -0
  111. data/app/components/shadcn/chart/previews/area.html.erb +31 -0
  112. data/app/components/shadcn/chart/previews/bar.html.erb +32 -0
  113. data/app/components/shadcn/chart/previews/bar_stacked.html.erb +30 -0
  114. data/app/components/shadcn/chart/previews/default.html.erb +30 -0
  115. data/app/components/shadcn/chart/previews/donut.html.erb +16 -0
  116. data/app/components/shadcn/chart/previews/line.html.erb +30 -0
  117. data/app/components/shadcn/chart/previews/percentages.html.erb +17 -0
  118. data/app/components/shadcn/chart/table/component.rb +75 -0
  119. data/app/components/shadcn/chart/tooltip/component.rb +111 -0
  120. data/app/components/shadcn/checkbox/component.rb +109 -0
  121. data/app/components/shadcn/checkbox/preview.rb +16 -0
  122. data/app/components/shadcn/checkbox/previews/default.html.erb +14 -0
  123. data/app/components/shadcn/checkbox/previews/states.html.erb +23 -0
  124. data/app/components/shadcn/collapsible/component.rb +35 -0
  125. data/app/components/shadcn/collapsible/content/component.rb +20 -0
  126. data/app/components/shadcn/collapsible/preview.rb +11 -0
  127. data/app/components/shadcn/collapsible/previews/default.html.erb +9 -0
  128. data/app/components/shadcn/collapsible/trigger/component.rb +23 -0
  129. data/app/components/shadcn/combobox/chip/component.rb +60 -0
  130. data/app/components/shadcn/combobox/chip_input/component.rb +43 -0
  131. data/app/components/shadcn/combobox/chips/component.rb +54 -0
  132. data/app/components/shadcn/combobox/clear/component.rb +32 -0
  133. data/app/components/shadcn/combobox/component.rb +113 -0
  134. data/app/components/shadcn/combobox/content/component.rb +59 -0
  135. data/app/components/shadcn/combobox/empty/component.rb +23 -0
  136. data/app/components/shadcn/combobox/input/component.rb +85 -0
  137. data/app/components/shadcn/combobox/item/component.rb +69 -0
  138. data/app/components/shadcn/combobox/list/component.rb +27 -0
  139. data/app/components/shadcn/combobox/preview.rb +31 -0
  140. data/app/components/shadcn/combobox/previews/default.html.erb +20 -0
  141. data/app/components/shadcn/combobox/previews/grouped.html.erb +25 -0
  142. data/app/components/shadcn/combobox/previews/multiple.html.erb +28 -0
  143. data/app/components/shadcn/combobox/previews/with_clear.html.erb +16 -0
  144. data/app/components/shadcn/combobox/trigger/component.rb +54 -0
  145. data/app/components/shadcn/combobox.rb +16 -0
  146. data/app/components/shadcn/command/component.rb +67 -0
  147. data/app/components/shadcn/command/dialog/component.rb +72 -0
  148. data/app/components/shadcn/command/empty/component.rb +29 -0
  149. data/app/components/shadcn/command/group/component.rb +63 -0
  150. data/app/components/shadcn/command/input/component.rb +66 -0
  151. data/app/components/shadcn/command/item/component.rb +62 -0
  152. data/app/components/shadcn/command/list/component.rb +36 -0
  153. data/app/components/shadcn/command/preview.rb +26 -0
  154. data/app/components/shadcn/command/previews/default.html.erb +41 -0
  155. data/app/components/shadcn/command/previews/dialog.html.erb +33 -0
  156. data/app/components/shadcn/command/previews/ranking.html.erb +16 -0
  157. data/app/components/shadcn/command/separator/component.rb +33 -0
  158. data/app/components/shadcn/command.rb +14 -0
  159. data/app/components/shadcn/concerns/modal_root.rb +43 -0
  160. data/app/components/shadcn/concerns/submits_value.rb +81 -0
  161. data/app/components/shadcn/context_menu/component.rb +45 -0
  162. data/app/components/shadcn/context_menu/content/component.rb +40 -0
  163. data/app/components/shadcn/context_menu/preview.rb +16 -0
  164. data/app/components/shadcn/context_menu/previews/default.html.erb +34 -0
  165. data/app/components/shadcn/context_menu/previews/items.html.erb +35 -0
  166. data/app/components/shadcn/context_menu/sub/component.rb +47 -0
  167. data/app/components/shadcn/context_menu/sub_content/component.rb +31 -0
  168. data/app/components/shadcn/context_menu/trigger/component.rb +50 -0
  169. data/app/components/shadcn/context_menu.rb +43 -0
  170. data/app/components/shadcn/dialog/close/component.rb +20 -0
  171. data/app/components/shadcn/dialog/component.rb +20 -0
  172. data/app/components/shadcn/dialog/content/component.rb +78 -0
  173. data/app/components/shadcn/dialog/header/component.rb +23 -0
  174. data/app/components/shadcn/dialog/overlay/component.rb +28 -0
  175. data/app/components/shadcn/dialog/preview.rb +28 -0
  176. data/app/components/shadcn/dialog/previews/default.html.erb +17 -0
  177. data/app/components/shadcn/dialog/previews/inside_stacking_context.html.erb +25 -0
  178. data/app/components/shadcn/dialog/previews/no_close_button.html.erb +15 -0
  179. data/app/components/shadcn/dialog/previews/scrollable_content.html.erb +29 -0
  180. data/app/components/shadcn/dialog/trigger/component.rb +24 -0
  181. data/app/components/shadcn/dialog.rb +17 -0
  182. data/app/components/shadcn/drawer/component.rb +33 -0
  183. data/app/components/shadcn/drawer/content/component.rb +95 -0
  184. data/app/components/shadcn/drawer/header/component.rb +34 -0
  185. data/app/components/shadcn/drawer/preview.rb +29 -0
  186. data/app/components/shadcn/drawer/previews/default.html.erb +21 -0
  187. data/app/components/shadcn/drawer/previews/scrollable.html.erb +20 -0
  188. data/app/components/shadcn/drawer/previews/scrollable_side.html.erb +21 -0
  189. data/app/components/shadcn/drawer/previews/sides.html.erb +17 -0
  190. data/app/components/shadcn/drawer.rb +27 -0
  191. data/app/components/shadcn/dropdown_menu/checkbox_item/component.rb +61 -0
  192. data/app/components/shadcn/dropdown_menu/component.rb +48 -0
  193. data/app/components/shadcn/dropdown_menu/content/component.rb +49 -0
  194. data/app/components/shadcn/dropdown_menu/group/component.rb +16 -0
  195. data/app/components/shadcn/dropdown_menu/item/component.rb +50 -0
  196. data/app/components/shadcn/dropdown_menu/preview.rb +16 -0
  197. data/app/components/shadcn/dropdown_menu/previews/checkboxes_and_radio.html.erb +34 -0
  198. data/app/components/shadcn/dropdown_menu/previews/default.html.erb +23 -0
  199. data/app/components/shadcn/dropdown_menu/radio_group/component.rb +16 -0
  200. data/app/components/shadcn/dropdown_menu/radio_item/component.rb +63 -0
  201. data/app/components/shadcn/dropdown_menu/sub/component.rb +44 -0
  202. data/app/components/shadcn/dropdown_menu/sub_content/component.rb +45 -0
  203. data/app/components/shadcn/dropdown_menu/sub_trigger/component.rb +58 -0
  204. data/app/components/shadcn/dropdown_menu/trigger/component.rb +25 -0
  205. data/app/components/shadcn/dropdown_menu.rb +18 -0
  206. data/app/components/shadcn/empty/component.rb +17 -0
  207. data/app/components/shadcn/empty/media/component.rb +48 -0
  208. data/app/components/shadcn/empty/preview.rb +16 -0
  209. data/app/components/shadcn/empty/previews/default.html.erb +15 -0
  210. data/app/components/shadcn/empty/previews/media.html.erb +32 -0
  211. data/app/components/shadcn/empty.rb +26 -0
  212. data/app/components/shadcn/field/component.rb +61 -0
  213. data/app/components/shadcn/field/error/component.rb +49 -0
  214. data/app/components/shadcn/field/legend/component.rb +30 -0
  215. data/app/components/shadcn/field/preview.rb +17 -0
  216. data/app/components/shadcn/field/previews/default.html.erb +29 -0
  217. data/app/components/shadcn/field/previews/form_builder.html.erb +38 -0
  218. data/app/components/shadcn/field/separator/component.rb +35 -0
  219. data/app/components/shadcn/field.rb +44 -0
  220. data/app/components/shadcn/hover_card/component.rb +51 -0
  221. data/app/components/shadcn/hover_card/content/component.rb +45 -0
  222. data/app/components/shadcn/hover_card/preview.rb +16 -0
  223. data/app/components/shadcn/hover_card/previews/default.html.erb +36 -0
  224. data/app/components/shadcn/hover_card/previews/sides.html.erb +15 -0
  225. data/app/components/shadcn/hover_card/trigger/component.rb +33 -0
  226. data/app/components/shadcn/icon/component.rb +76 -0
  227. data/app/components/shadcn/icon.rb +43 -0
  228. data/app/components/shadcn/input/component.rb +26 -0
  229. data/app/components/shadcn/input/preview.rb +16 -0
  230. data/app/components/shadcn/input/previews/default.html.erb +5 -0
  231. data/app/components/shadcn/input/previews/states.html.erb +20 -0
  232. data/app/components/shadcn/input_group/addon/component.rb +65 -0
  233. data/app/components/shadcn/input_group/button/component.rb +40 -0
  234. data/app/components/shadcn/input_group/component.rb +43 -0
  235. data/app/components/shadcn/input_group/input/component.rb +25 -0
  236. data/app/components/shadcn/input_group/preview.rb +17 -0
  237. data/app/components/shadcn/input_group/previews/addons.html.erb +53 -0
  238. data/app/components/shadcn/input_group/previews/default.html.erb +25 -0
  239. data/app/components/shadcn/input_group/text/component.rb +20 -0
  240. data/app/components/shadcn/input_group/textarea/component.rb +21 -0
  241. data/app/components/shadcn/input_otp/component.rb +95 -0
  242. data/app/components/shadcn/input_otp/preview.rb +17 -0
  243. data/app/components/shadcn/input_otp/previews/default.html.erb +19 -0
  244. data/app/components/shadcn/input_otp/previews/variations.html.erb +33 -0
  245. data/app/components/shadcn/input_otp/separator/component.rb +21 -0
  246. data/app/components/shadcn/input_otp/slot/component.rb +60 -0
  247. data/app/components/shadcn/input_otp.rb +11 -0
  248. data/app/components/shadcn/item/component.rb +56 -0
  249. data/app/components/shadcn/item/group/component.rb +53 -0
  250. data/app/components/shadcn/item/media/component.rb +53 -0
  251. data/app/components/shadcn/item/preview.rb +20 -0
  252. data/app/components/shadcn/item/previews/default.html.erb +32 -0
  253. data/app/components/shadcn/item/previews/link.html.erb +39 -0
  254. data/app/components/shadcn/item/previews/outline.html.erb +8 -0
  255. data/app/components/shadcn/item/separator/component.rb +24 -0
  256. data/app/components/shadcn/item.rb +34 -0
  257. data/app/components/shadcn/kbd/component.rb +23 -0
  258. data/app/components/shadcn/kbd/group/component.rb +17 -0
  259. data/app/components/shadcn/kbd/preview.rb +11 -0
  260. data/app/components/shadcn/kbd/previews/default.html.erb +4 -0
  261. data/app/components/shadcn/label/component.rb +20 -0
  262. data/app/components/shadcn/label/preview.rb +11 -0
  263. data/app/components/shadcn/label/previews/default.html.erb +4 -0
  264. data/app/components/shadcn/marker/component.rb +46 -0
  265. data/app/components/shadcn/marker/icon/component.rb +23 -0
  266. data/app/components/shadcn/marker/preview.rb +17 -0
  267. data/app/components/shadcn/marker/previews/default.html.erb +18 -0
  268. data/app/components/shadcn/marker/previews/status.html.erb +32 -0
  269. data/app/components/shadcn/marker.rb +17 -0
  270. data/app/components/shadcn/menubar/component.rb +36 -0
  271. data/app/components/shadcn/menubar/content/component.rb +49 -0
  272. data/app/components/shadcn/menubar/menu/component.rb +39 -0
  273. data/app/components/shadcn/menubar/preview.rb +16 -0
  274. data/app/components/shadcn/menubar/previews/default.html.erb +52 -0
  275. data/app/components/shadcn/menubar/previews/items.html.erb +38 -0
  276. data/app/components/shadcn/menubar/sub/component.rb +43 -0
  277. data/app/components/shadcn/menubar/sub_content/component.rb +31 -0
  278. data/app/components/shadcn/menubar/sub_trigger/component.rb +31 -0
  279. data/app/components/shadcn/menubar/trigger/component.rb +41 -0
  280. data/app/components/shadcn/menubar.rb +47 -0
  281. data/app/components/shadcn/message/component.rb +33 -0
  282. data/app/components/shadcn/message/preview.rb +16 -0
  283. data/app/components/shadcn/message/previews/actions.html.erb +51 -0
  284. data/app/components/shadcn/message/previews/default.html.erb +35 -0
  285. data/app/components/shadcn/message.rb +35 -0
  286. data/app/components/shadcn/message_scroller/button/component.rb +78 -0
  287. data/app/components/shadcn/message_scroller/component.rb +59 -0
  288. data/app/components/shadcn/message_scroller/content/component.rb +50 -0
  289. data/app/components/shadcn/message_scroller/item/component.rb +45 -0
  290. data/app/components/shadcn/message_scroller/preview.rb +11 -0
  291. data/app/components/shadcn/message_scroller/previews/default.html.erb +72 -0
  292. data/app/components/shadcn/message_scroller/viewport/component.rb +41 -0
  293. data/app/components/shadcn/mode_switcher/component.rb +67 -0
  294. data/app/components/shadcn/mode_switcher/preview.rb +11 -0
  295. data/app/components/shadcn/mode_switcher/previews/default.html.erb +5 -0
  296. data/app/components/shadcn/mode_toggle/component.rb +75 -0
  297. data/app/components/shadcn/mode_toggle/preview.rb +11 -0
  298. data/app/components/shadcn/mode_toggle/previews/default.html.erb +20 -0
  299. data/app/components/shadcn/native_select/component.rb +59 -0
  300. data/app/components/shadcn/native_select/preview.rb +16 -0
  301. data/app/components/shadcn/native_select/previews/default.html.erb +9 -0
  302. data/app/components/shadcn/native_select/previews/groups.html.erb +26 -0
  303. data/app/components/shadcn/native_select.rb +16 -0
  304. data/app/components/shadcn/navigation_menu/component.rb +51 -0
  305. data/app/components/shadcn/navigation_menu/content/component.rb +58 -0
  306. data/app/components/shadcn/navigation_menu/preview.rb +11 -0
  307. data/app/components/shadcn/navigation_menu/previews/default.html.erb +49 -0
  308. data/app/components/shadcn/navigation_menu/trigger/component.rb +59 -0
  309. data/app/components/shadcn/navigation_menu.rb +28 -0
  310. data/app/components/shadcn/pagination/component.rb +19 -0
  311. data/app/components/shadcn/pagination/ellipsis/component.rb +28 -0
  312. data/app/components/shadcn/pagination/link/component.rb +37 -0
  313. data/app/components/shadcn/pagination/next/component.rb +31 -0
  314. data/app/components/shadcn/pagination/preview.rb +16 -0
  315. data/app/components/shadcn/pagination/previews/default.html.erb +18 -0
  316. data/app/components/shadcn/pagination/previews/simple.html.erb +39 -0
  317. data/app/components/shadcn/pagination/previous/component.rb +31 -0
  318. data/app/components/shadcn/pagination.rb +14 -0
  319. data/app/components/shadcn/parts.rb +38 -0
  320. data/app/components/shadcn/popover/anchor/component.rb +17 -0
  321. data/app/components/shadcn/popover/component.rb +42 -0
  322. data/app/components/shadcn/popover/content/component.rb +40 -0
  323. data/app/components/shadcn/popover/preview.rb +28 -0
  324. data/app/components/shadcn/popover/previews/align.html.erb +13 -0
  325. data/app/components/shadcn/popover/previews/default.html.erb +9 -0
  326. data/app/components/shadcn/popover/previews/inside_containing_block.html.erb +41 -0
  327. data/app/components/shadcn/popover/previews/inside_stacking_context.html.erb +30 -0
  328. data/app/components/shadcn/popover/trigger/component.rb +24 -0
  329. data/app/components/shadcn/popover.rb +16 -0
  330. data/app/components/shadcn/progress/component.rb +62 -0
  331. data/app/components/shadcn/progress/preview.rb +11 -0
  332. data/app/components/shadcn/progress/previews/default.html.erb +5 -0
  333. data/app/components/shadcn/radio_group/component.rb +51 -0
  334. data/app/components/shadcn/radio_group/item/component.rb +74 -0
  335. data/app/components/shadcn/radio_group/preview.rb +16 -0
  336. data/app/components/shadcn/radio_group/previews/default.html.erb +15 -0
  337. data/app/components/shadcn/radio_group/previews/states.html.erb +41 -0
  338. data/app/components/shadcn/resizable/component.rb +59 -0
  339. data/app/components/shadcn/resizable/handle/component.rb +70 -0
  340. data/app/components/shadcn/resizable/panel/component.rb +53 -0
  341. data/app/components/shadcn/resizable/preview.rb +23 -0
  342. data/app/components/shadcn/resizable/previews/default.html.erb +25 -0
  343. data/app/components/shadcn/resizable/previews/vertical.html.erb +19 -0
  344. data/app/components/shadcn/resizable/previews/with_handle.html.erb +17 -0
  345. data/app/components/shadcn/scroll_area/component.rb +84 -0
  346. data/app/components/shadcn/scroll_area/preview.rb +11 -0
  347. data/app/components/shadcn/scroll_area/previews/default.html.erb +36 -0
  348. data/app/components/shadcn/scroll_area/scrollbar/component.rb +72 -0
  349. data/app/components/shadcn/scroll_area/viewport/component.rb +70 -0
  350. data/app/components/shadcn/scroll_area.rb +14 -0
  351. data/app/components/shadcn/select/component.rb +67 -0
  352. data/app/components/shadcn/select/content/component.rb +157 -0
  353. data/app/components/shadcn/select/empty/component.rb +38 -0
  354. data/app/components/shadcn/select/group/component.rb +16 -0
  355. data/app/components/shadcn/select/item/component.rb +71 -0
  356. data/app/components/shadcn/select/list/component.rb +41 -0
  357. data/app/components/shadcn/select/preview.rb +24 -0
  358. data/app/components/shadcn/select/previews/default.html.erb +17 -0
  359. data/app/components/shadcn/select/previews/scrollable.html.erb +19 -0
  360. data/app/components/shadcn/select/previews/searchable.html.erb +18 -0
  361. data/app/components/shadcn/select/previews/states.html.erb +25 -0
  362. data/app/components/shadcn/select/search/component.rb +54 -0
  363. data/app/components/shadcn/select/trigger/component.rb +78 -0
  364. data/app/components/shadcn/select/value/component.rb +28 -0
  365. data/app/components/shadcn/select.rb +15 -0
  366. data/app/components/shadcn/separator/component.rb +41 -0
  367. data/app/components/shadcn/separator/preview.rb +11 -0
  368. data/app/components/shadcn/separator/previews/default.html.erb +9 -0
  369. data/app/components/shadcn/sheet/component.rb +16 -0
  370. data/app/components/shadcn/sheet/content/component.rb +98 -0
  371. data/app/components/shadcn/sheet/header/component.rb +23 -0
  372. data/app/components/shadcn/sheet/preview.rb +16 -0
  373. data/app/components/shadcn/sheet/previews/default.html.erb +16 -0
  374. data/app/components/shadcn/sheet/previews/no_close_button.html.erb +14 -0
  375. data/app/components/shadcn/sheet.rb +22 -0
  376. data/app/components/shadcn/sidebar/component.rb +232 -0
  377. data/app/components/shadcn/sidebar/input/component.rb +25 -0
  378. data/app/components/shadcn/sidebar/menu_action/component.rb +58 -0
  379. data/app/components/shadcn/sidebar/menu_button/component.rb +100 -0
  380. data/app/components/shadcn/sidebar/menu_skeleton/component.rb +51 -0
  381. data/app/components/shadcn/sidebar/menu_sub_button/component.rb +60 -0
  382. data/app/components/shadcn/sidebar/preview.rb +22 -0
  383. data/app/components/shadcn/sidebar/previews/default.html.erb +189 -0
  384. data/app/components/shadcn/sidebar/previews/floating.html.erb +39 -0
  385. data/app/components/shadcn/sidebar/previews/inset.html.erb +48 -0
  386. data/app/components/shadcn/sidebar/provider/component.rb +53 -0
  387. data/app/components/shadcn/sidebar/rail/component.rb +43 -0
  388. data/app/components/shadcn/sidebar/separator/component.rb +23 -0
  389. data/app/components/shadcn/sidebar/trigger/component.rb +39 -0
  390. data/app/components/shadcn/sidebar.rb +98 -0
  391. data/app/components/shadcn/skeleton/component.rb +14 -0
  392. data/app/components/shadcn/skeleton/preview.rb +11 -0
  393. data/app/components/shadcn/skeleton/previews/default.html.erb +7 -0
  394. data/app/components/shadcn/slider/component.rb +145 -0
  395. data/app/components/shadcn/slider/preview.rb +16 -0
  396. data/app/components/shadcn/slider/previews/default.html.erb +17 -0
  397. data/app/components/shadcn/slider/previews/vertical.html.erb +7 -0
  398. data/app/components/shadcn/slider/range/component.rb +51 -0
  399. data/app/components/shadcn/slider/thumb/component.rb +58 -0
  400. data/app/components/shadcn/slider/track/component.rb +32 -0
  401. data/app/components/shadcn/spinner/component.rb +21 -0
  402. data/app/components/shadcn/spinner/preview.rb +11 -0
  403. data/app/components/shadcn/spinner/previews/default.html.erb +7 -0
  404. data/app/components/shadcn/switch/component.rb +104 -0
  405. data/app/components/shadcn/switch/preview.rb +11 -0
  406. data/app/components/shadcn/switch/previews/default.html.erb +24 -0
  407. data/app/components/shadcn/table/component.rb +26 -0
  408. data/app/components/shadcn/table/preview.rb +16 -0
  409. data/app/components/shadcn/table/previews/default.html.erb +19 -0
  410. data/app/components/shadcn/table/previews/footer.html.erb +25 -0
  411. data/app/components/shadcn/table.rb +33 -0
  412. data/app/components/shadcn/tabs/component.rb +40 -0
  413. data/app/components/shadcn/tabs/content/component.rb +34 -0
  414. data/app/components/shadcn/tabs/list/component.rb +51 -0
  415. data/app/components/shadcn/tabs/preview.rb +16 -0
  416. data/app/components/shadcn/tabs/previews/default.html.erb +21 -0
  417. data/app/components/shadcn/tabs/previews/line.html.erb +23 -0
  418. data/app/components/shadcn/tabs/trigger/component.rb +66 -0
  419. data/app/components/shadcn/textarea/component.rb +24 -0
  420. data/app/components/shadcn/textarea/preview.rb +16 -0
  421. data/app/components/shadcn/textarea/previews/default.html.erb +3 -0
  422. data/app/components/shadcn/textarea/previews/states.html.erb +18 -0
  423. data/app/components/shadcn/theme_selector/component.rb +88 -0
  424. data/app/components/shadcn/theme_selector/preview.rb +17 -0
  425. data/app/components/shadcn/theme_selector/previews/all_themes.html.erb +20 -0
  426. data/app/components/shadcn/theme_selector/previews/default.html.erb +18 -0
  427. data/app/components/shadcn/toaster/component.rb +139 -0
  428. data/app/components/shadcn/toaster/preview.rb +16 -0
  429. data/app/components/shadcn/toaster/previews/default.html.erb +19 -0
  430. data/app/components/shadcn/toaster/previews/from_the_server.html.erb +15 -0
  431. data/app/components/shadcn/toaster/toast/component.rb +134 -0
  432. data/app/components/shadcn/toggle/component.rb +81 -0
  433. data/app/components/shadcn/toggle/preview.rb +11 -0
  434. data/app/components/shadcn/toggle/previews/default.html.erb +6 -0
  435. data/app/components/shadcn/toggle_group/component.rb +62 -0
  436. data/app/components/shadcn/toggle_group/item/component.rb +59 -0
  437. data/app/components/shadcn/toggle_group/preview.rb +16 -0
  438. data/app/components/shadcn/toggle_group/previews/default.html.erb +12 -0
  439. data/app/components/shadcn/toggle_group/previews/sizes.html.erb +37 -0
  440. data/app/components/shadcn/tooltip/component.rb +38 -0
  441. data/app/components/shadcn/tooltip/content/component.rb +62 -0
  442. data/app/components/shadcn/tooltip/preview.rb +21 -0
  443. data/app/components/shadcn/tooltip/previews/default.html.erb +4 -0
  444. data/app/components/shadcn/tooltip/previews/sides.html.erb +19 -0
  445. data/app/components/shadcn/tooltip/previews/with_keyboard_shortcut.html.erb +11 -0
  446. data/app/components/shadcn/tooltip/provider/component.rb +28 -0
  447. data/app/components/shadcn/tooltip/trigger/component.rb +25 -0
  448. data/app/helpers/shadcn_view_component/form_helper.rb +25 -0
  449. data/app/helpers/shadcn_view_component/theme_helper.rb +61 -0
  450. data/app/javascript/shadcn/animation.js +180 -0
  451. data/app/javascript/shadcn/command_score.js +110 -0
  452. data/app/javascript/shadcn/controllers/accordion_controller.js +127 -0
  453. data/app/javascript/shadcn/controllers/avatar_controller.js +32 -0
  454. data/app/javascript/shadcn/controllers/calendar_controller.js +633 -0
  455. data/app/javascript/shadcn/controllers/carousel_controller.js +139 -0
  456. data/app/javascript/shadcn/controllers/chart_controller.js +110 -0
  457. data/app/javascript/shadcn/controllers/checkbox_controller.js +61 -0
  458. data/app/javascript/shadcn/controllers/collapsible_controller.js +55 -0
  459. data/app/javascript/shadcn/controllers/combobox_controller.js +360 -0
  460. data/app/javascript/shadcn/controllers/command_controller.js +199 -0
  461. data/app/javascript/shadcn/controllers/dialog_controller.js +154 -0
  462. data/app/javascript/shadcn/controllers/drawer_controller.js +265 -0
  463. data/app/javascript/shadcn/controllers/dropdown_menu_controller.js +259 -0
  464. data/app/javascript/shadcn/controllers/hover_card_controller.js +85 -0
  465. data/app/javascript/shadcn/controllers/input_group_controller.js +17 -0
  466. data/app/javascript/shadcn/controllers/input_otp_controller.js +80 -0
  467. data/app/javascript/shadcn/controllers/menubar_controller.js +151 -0
  468. data/app/javascript/shadcn/controllers/message_scroller_controller.js +456 -0
  469. data/app/javascript/shadcn/controllers/navigation_menu_controller.js +211 -0
  470. data/app/javascript/shadcn/controllers/popover_controller.js +66 -0
  471. data/app/javascript/shadcn/controllers/radio_group_controller.js +69 -0
  472. data/app/javascript/shadcn/controllers/resizable_controller.js +167 -0
  473. data/app/javascript/shadcn/controllers/scroll_area_controller.js +253 -0
  474. data/app/javascript/shadcn/controllers/select_controller.js +320 -0
  475. data/app/javascript/shadcn/controllers/sidebar_controller.js +273 -0
  476. data/app/javascript/shadcn/controllers/slider_controller.js +230 -0
  477. data/app/javascript/shadcn/controllers/switch_controller.js +39 -0
  478. data/app/javascript/shadcn/controllers/tabs_controller.js +81 -0
  479. data/app/javascript/shadcn/controllers/theme_controller.js +67 -0
  480. data/app/javascript/shadcn/controllers/toaster_controller.js +281 -0
  481. data/app/javascript/shadcn/controllers/toggle_controller.js +24 -0
  482. data/app/javascript/shadcn/controllers/toggle_group_controller.js +73 -0
  483. data/app/javascript/shadcn/controllers/tooltip_controller.js +58 -0
  484. data/app/javascript/shadcn/direction.js +41 -0
  485. data/app/javascript/shadcn/dismiss.js +73 -0
  486. data/app/javascript/shadcn/floating.js +207 -0
  487. data/app/javascript/shadcn/focus.js +86 -0
  488. data/app/javascript/shadcn/id.js +14 -0
  489. data/app/javascript/shadcn/index.js +110 -0
  490. data/app/javascript/shadcn/popper.js +262 -0
  491. data/app/javascript/shadcn/scroll_geometry.js +267 -0
  492. data/app/javascript/shadcn/theme.js +161 -0
  493. data/app/javascript/shadcn/top_layer.js +59 -0
  494. data/app/javascript/shadcn/typeahead.js +99 -0
  495. data/config/importmap.rb +6 -0
  496. data/config/locales/en.yml +62 -0
  497. data/lib/generators/shadcn_view_component/install/install_generator.rb +149 -0
  498. data/lib/shadcn_view_component/engine.rb +73 -0
  499. data/lib/shadcn_view_component/form_builder.rb +264 -0
  500. data/lib/shadcn_view_component/icon_registry.rb +66 -0
  501. data/lib/shadcn_view_component/icons.rb +32 -0
  502. data/lib/shadcn_view_component/themes.rb +1065 -0
  503. data/lib/shadcn_view_component/version.rb +3 -0
  504. data/lib/shadcn_view_component.rb +82 -0
  505. data/lib/tasks/icons.rake +53 -0
  506. data/lib/tasks/themes.rake +171 -0
  507. metadata +608 -0
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Pagination
5
+ module Link
6
+ # PaginationLink — styled with the button's own variants, like the TSX
7
+ # does via `buttonVariants({ variant: isActive ? "outline" : "ghost", size })`.
8
+ class Component < ApplicationViewComponent
9
+ default_tag :a
10
+ slot_name :"pagination-link"
11
+
12
+ attr_reader :active, :size
13
+
14
+ def initialize(active: false, size: :icon, **attributes)
15
+ @active = active
16
+ @size = size&.to_sym || :icon
17
+ super(**attributes)
18
+ end
19
+
20
+ def element_attributes(**defaults)
21
+ super(**{
22
+ "aria-current" => ("page" if active),
23
+ "data-active" => active
24
+ }.merge(defaults))
25
+ end
26
+
27
+ def css_classes(extra = nil)
28
+ Button::Component.variant_classes(
29
+ variant: active ? :outline : :ghost,
30
+ size:,
31
+ class: extra
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Pagination
5
+ module Next
6
+ # PaginationNext
7
+ class Component < Link::Component
8
+ EXTRA_CLASSES = "gap-1 px-2.5 sm:pr-2.5"
9
+
10
+ def initialize(**attributes)
11
+ super(size: :default, **attributes)
12
+ end
13
+
14
+ def element_attributes(**defaults)
15
+ super(**{ "aria-label" => shadcn_t("pagination.go_to_next") }.merge(defaults))
16
+ end
17
+
18
+ def css_classes(extra = nil)
19
+ super(ShadcnViewComponent.cn(EXTRA_CLASSES, extra))
20
+ end
21
+
22
+ def call
23
+ render_element(body: safe_join([
24
+ tag.span(shadcn_t("pagination.next"), class: "hidden sm:block"),
25
+ render(Icon::Component.new("chevron-right"))
26
+ ]))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Pagination
5
+ class Preview < ApplicationViewComponentPreview
6
+ def default
7
+ render_with_template
8
+ end
9
+
10
+ # Upstream's "Simple" and "Icons Only".
11
+ def simple
12
+ render_with_template
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ <%= render(Shadcn::Pagination::Component.new) do %>
2
+ <%= render(Shadcn::Pagination::Content::Component.new) do %>
3
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
4
+ <%= render(Shadcn::Pagination::Previous::Component.new(href: "#")) %>
5
+ <% end %>
6
+ <% [["1", false], ["2", true], ["3", false]].each do |label, active| %>
7
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
8
+ <%= render(Shadcn::Pagination::Link::Component.new(href: "#", active:)) { label } %>
9
+ <% end %>
10
+ <% end %>
11
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
12
+ <%= render(Shadcn::Pagination::Ellipsis::Component.new) %>
13
+ <% end %>
14
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
15
+ <%= render(Shadcn::Pagination::Next::Component.new(href: "#")) %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
@@ -0,0 +1,39 @@
1
+ <%# Upstream's "Simple", and what its "Icons Only" actually is.
2
+
3
+ `Previous` and `Next` render a chevron and a word, and the word carries
4
+ `hidden sm:block` (pagination.tsx) — so the icons-only example is the same
5
+ component below the `sm` breakpoint rather than a variant to ask for.
6
+ Narrow the window and the second row here becomes it. Neither component
7
+ takes content: the label is theirs, translated, which is also where the
8
+ accessible name comes from. %>
9
+ <div class="flex flex-col items-center gap-8">
10
+ <%= render(Shadcn::Pagination::Component.new) do %>
11
+ <%= render(Shadcn::Pagination::Content::Component.new) do %>
12
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
13
+ <%= render(Shadcn::Pagination::Previous::Component.new(href: "#")) %>
14
+ <% end %>
15
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
16
+ <span class="px-4 text-sm text-muted-foreground">Page 2 of 10</span>
17
+ <% end %>
18
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
19
+ <%= render(Shadcn::Pagination::Next::Component.new(href: "#")) %>
20
+ <% end %>
21
+ <% end %>
22
+ <% end %>
23
+
24
+ <%= render(Shadcn::Pagination::Component.new) do %>
25
+ <%= render(Shadcn::Pagination::Content::Component.new) do %>
26
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
27
+ <%= render(Shadcn::Pagination::Previous::Component.new(href: "#")) %>
28
+ <% end %>
29
+ <% [1, 2, 3].each do |page| %>
30
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
31
+ <%= render(Shadcn::Pagination::Link::Component.new(href: "#", active: page == 2)) { page.to_s } %>
32
+ <% end %>
33
+ <% end %>
34
+ <%= render(Shadcn::Pagination::Item::Component.new) do %>
35
+ <%= render(Shadcn::Pagination::Next::Component.new(href: "#")) %>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
39
+ </div>
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Pagination
5
+ module Previous
6
+ # PaginationPrevious
7
+ class Component < Link::Component
8
+ EXTRA_CLASSES = "gap-1 px-2.5 sm:pl-2.5"
9
+
10
+ def initialize(**attributes)
11
+ super(size: :default, **attributes)
12
+ end
13
+
14
+ def element_attributes(**defaults)
15
+ super(**{ "aria-label" => shadcn_t("pagination.go_to_previous") }.merge(defaults))
16
+ end
17
+
18
+ def css_classes(extra = nil)
19
+ super(ShadcnViewComponent.cn(EXTRA_CLASSES, extra))
20
+ end
21
+
22
+ def call
23
+ render_element(body: safe_join([
24
+ render(Icon::Component.new("chevron-left")),
25
+ tag.span(shadcn_t("pagination.previous"), class: "hidden sm:block")
26
+ ]))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # The parts of the Pagination family that are just an element with a
5
+ # `data-slot` and a fixed set of classes. Anything with variants, slots or
6
+ # markup of its own keeps its own `component.rb`.
7
+ module Pagination
8
+ extend Parts
9
+
10
+ part :content, tag: :ul, slot: "pagination-content", classes: "flex flex-row items-center gap-1"
11
+
12
+ part :item, tag: :li, slot: "pagination-item"
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Declares the parts of a family that are nothing but an element carrying a
5
+ # `data-slot` and a fixed set of classes.
6
+ #
7
+ # Most of shadcn's sub-components are exactly that — `CardTitle` is a `<div>`
8
+ # with two classes — and writing each as its own file meant thirteen lines of
9
+ # module nesting around one string. Declared on the family module instead, a
10
+ # whole family reads at a glance, and the class strings stay literal, which is
11
+ # what both the parity spec and Tailwind's scanner need.
12
+ #
13
+ # See `card.rb` for a worked example.
14
+ #
15
+ # Parts with behaviour — variants, slots, extra markup, computed attributes —
16
+ # stay as their own `component.rb`. This is only for the ones that have none.
17
+ module Parts
18
+ # @param name [Symbol] the part, snake_case; `:group_count` becomes
19
+ # `GroupCount::Component`
20
+ # @param slot [String] the `data-slot` shadcn stamps on it
21
+ # @param classes [String] its base classes
22
+ # @param tag [Symbol] the element, when it is not a `<div>`
23
+ # @param from [Class] a part to specialise instead of building a new one,
24
+ # for the families shadcn layers on another (Sheet on Dialog)
25
+ def part(name, slot:, classes: nil, tag: nil, from: ApplicationViewComponent)
26
+ namespace = const_set(name.to_s.camelize, Module.new)
27
+ component = namespace.const_set(:Component, Class.new(from))
28
+
29
+ # Configured only after `const_set` has named it: StyleVariants derives the
30
+ # style set's name from the class name, and an anonymous class has none.
31
+ component.default_tag(tag) if tag
32
+ component.slot_name(slot)
33
+ component.style { base { classes } } if classes
34
+
35
+ component
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Popover
5
+ module Anchor
6
+ # PopoverAnchor — positions the content against something other than the
7
+ # trigger.
8
+ class Component < ApplicationViewComponent
9
+ slot_name :"popover-anchor"
10
+
11
+ def element_attributes(**defaults)
12
+ super(**{ "data-shadcn--popover-target" => "anchor" }.merge(defaults))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Popover
5
+ # Port of registry/new-york-v4/ui/popover.tsx
6
+ class Component < ApplicationViewComponent
7
+ renders_one :trigger, "Shadcn::Popover::Trigger::Component"
8
+ renders_one :anchor, "Shadcn::Popover::Anchor::Component"
9
+ renders_one :popover_content, "Shadcn::Popover::Content::Component"
10
+
11
+ slot_name :popover
12
+
13
+ attr_reader :open, :side, :align, :side_offset, :align_offset
14
+
15
+ def initialize(open: false, side: :bottom, align: :center, side_offset: 4,
16
+ align_offset: 0, **attributes)
17
+ @open = open
18
+ @side = side&.to_sym || :bottom
19
+ @align = align&.to_sym || :center
20
+ @side_offset = side_offset
21
+ @align_offset = align_offset
22
+ super(**attributes)
23
+ end
24
+
25
+ def element_attributes(**defaults)
26
+ super(**{
27
+ style: merged_style(CONTENTS_STYLE),
28
+ "data-controller" => "shadcn--popover",
29
+ "data-shadcn--popover-open-value" => open,
30
+ "data-shadcn--popover-side-value" => side,
31
+ "data-shadcn--popover-align-value" => align,
32
+ "data-shadcn--popover-side-offset-value" => side_offset,
33
+ "data-shadcn--popover-align-offset-value" => align_offset
34
+ }.merge(defaults))
35
+ end
36
+
37
+ def call
38
+ render_element(body: safe_join([ anchor, trigger, popover_content, content ].compact))
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Popover
5
+ module Content
6
+ # PopoverContent
7
+ class Component < ApplicationViewComponent
8
+ renders_one :header, "Shadcn::Popover::Header::Component"
9
+
10
+ slot_name :"popover-content"
11
+
12
+ style do
13
+ base {
14
+ "z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border " \
15
+ "bg-popover p-4 text-popover-foreground shadow-md outline-hidden " \
16
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 " \
17
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 " \
18
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 " \
19
+ "data-[state=closed]:zoom-out-95 data-[state=open]:animate-in " \
20
+ "data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"
21
+ }
22
+ end
23
+
24
+ def element_attributes(**defaults)
25
+ super(**{
26
+ role: "dialog",
27
+ tabindex: "-1",
28
+ "data-state" => "closed",
29
+ hidden: true,
30
+ "data-shadcn--popover-target" => "content"
31
+ }.merge(defaults))
32
+ end
33
+
34
+ def call
35
+ render_element(body: safe_join([ header, content ].compact))
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Popover
5
+ class Preview < ApplicationViewComponentPreview
6
+ def default
7
+ render_with_template
8
+ end
9
+
10
+ # The case the layering has to survive: an ancestor that creates a
11
+ # stacking context.
12
+ def inside_stacking_context
13
+ render_with_template
14
+ end
15
+
16
+ # The other ancestor hazard: `transform`, `filter` and `contain` each
17
+ # become the containing block for a fixed descendant.
18
+ def inside_containing_block
19
+ render_with_template
20
+ end
21
+
22
+ # Upstream's "Align".
23
+ def align
24
+ render_with_template
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ <%# Upstream's "Align": the panel is placed against the trigger's start, centre
2
+ or end, which is the argument that decides where a menu-like popover lines
3
+ up under a narrow button. %>
4
+ <div class="flex items-center gap-2">
5
+ <% %i[start center end].each do |align| %>
6
+ <%= render(Shadcn::Popover::Component.new) do |p| %>
7
+ <% p.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { align.to_s.capitalize } %>
8
+ <% p.with_popover_content(align:, class: "w-56") do %>
9
+ <p class="text-sm text-muted-foreground">Aligned to the <%= align %>.</p>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
13
+ </div>
@@ -0,0 +1,9 @@
1
+ <%= render(Shadcn::Popover::Component.new) do |p| %>
2
+ <% p.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Open popover" } %>
3
+ <% p.with_popover_content do |c| %>
4
+ <% c.with_header do |h| %>
5
+ <%= render(Shadcn::Popover::Title::Component.new) { "Dimensions" } %>
6
+ <%= render(Shadcn::Popover::Description::Component.new) { "Set the dimensions for the layer." } %>
7
+ <% end %>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,41 @@
1
+ <%# The other ancestor hazard, and a different one from
2
+ `inside_stacking_context`: that preview is about what *paints over* the
3
+ layer, this is about *where the layer lands*.
4
+
5
+ `transform`, `filter` and `contain: paint` each make an element the
6
+ containing block for `position: fixed` descendants, so a fixed layer inside
7
+ one is positioned against that box rather than the viewport. The Popover API
8
+ is supposed to lift the content into the top layer and out of reach of all
9
+ three; whether it does is what the spec measures rather than assumes.
10
+
11
+ Three ancestors rather than one because the three properties reach the same
12
+ result by different routes in the spec, and browsers have shipped them at
13
+ different times. %>
14
+
15
+ <div class="flex flex-col gap-6">
16
+ <% {
17
+ "transform" => "[transform:translateZ(0)]",
18
+ "filter" => "[filter:blur(0px)]",
19
+ "contain" => "[contain:paint]"
20
+ }.each do |name, ancestor| %>
21
+ <div class="<%= ancestor %> rounded-lg border p-4" data-testid="ancestor-<%= name %>">
22
+ <span class="mr-3 text-sm text-muted-foreground">Inside <%= name %></span>
23
+
24
+ <%= render(Shadcn::Popover::Component.new) do |popover| %>
25
+ <% popover.with_trigger(
26
+ class: Shadcn::Button::Component.variant_classes(variant: :outline),
27
+ "data-testid": "trigger-#{name}"
28
+ ) { "Open popover" } %>
29
+ <% popover.with_popover_content("data-testid": "content-#{name}") do |content| %>
30
+ <% content.with_header do %>
31
+ <%= render(Shadcn::Popover::Title::Component.new) { "Where am I?" } %>
32
+ <%= render(Shadcn::Popover::Description::Component.new) do %>
33
+ If this is not under its trigger, the ancestor became the
34
+ containing block.
35
+ <% end %>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
39
+ </div>
40
+ <% end %>
41
+ </div>
@@ -0,0 +1,30 @@
1
+ <%# A floating layer inside an ancestor that creates a stacking context.
2
+
3
+ `position: fixed` escapes overflow clipping but never escapes a stacking
4
+ context, so the content's `z-50` is scoped to the header's `z-10` and the
5
+ section below — `z-20` — paints over it. This is ordinary Rails markup: a
6
+ sticky header, a card with `isolate`, anything with `opacity < 1`. %>
7
+
8
+ <div class="relative z-10 flex items-center gap-3 rounded-lg border bg-card p-4"
9
+ data-testid="stacking-header">
10
+ <span class="text-sm text-muted-foreground">A header at z-10</span>
11
+
12
+ <%= render(Shadcn::Popover::Component.new) do |popover| %>
13
+ <% popover.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) do %>
14
+ Open popover
15
+ <% end %>
16
+ <% popover.with_popover_content do |content| %>
17
+ <% content.with_header do %>
18
+ <%= render(Shadcn::Popover::Title::Component.new) { "Am I on top?" } %>
19
+ <%= render(Shadcn::Popover::Description::Component.new) do %>
20
+ If the striped panel covers this, the layer lost to a stacking context.
21
+ <% end %>
22
+ <% end %>
23
+ <% end %>
24
+ <% end %>
25
+ </div>
26
+
27
+ <div class="relative z-20 mt-2 h-40 rounded-lg border bg-muted p-4"
28
+ data-testid="stacking-sibling">
29
+ <span class="text-sm font-medium">A sibling at z-20</span>
30
+ </div>
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Popover
5
+ module Trigger
6
+ # PopoverTrigger
7
+ class Component < ApplicationViewComponent
8
+ default_tag :button
9
+ slot_name :"popover-trigger"
10
+
11
+ def element_attributes(**defaults)
12
+ super(**{
13
+ type: "button",
14
+ "aria-haspopup" => "dialog",
15
+ "aria-expanded" => "false",
16
+ "data-state" => "closed",
17
+ "data-shadcn--popover-target" => "trigger",
18
+ "data-action" => "shadcn--popover#toggle"
19
+ }.merge(defaults))
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # The parts of the Popover family that are just an element with a
5
+ # `data-slot` and a fixed set of classes. Anything with variants, slots or
6
+ # markup of its own keeps its own `component.rb`.
7
+ module Popover
8
+ extend Parts
9
+
10
+ part :description, tag: :p, slot: "popover-description", classes: "text-muted-foreground"
11
+
12
+ part :header, slot: "popover-header", classes: "flex flex-col gap-1 text-sm"
13
+
14
+ part :title, slot: "popover-title", classes: "font-medium"
15
+ end
16
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Progress
5
+ # Port of registry/new-york-v4/ui/progress.tsx
6
+ #
7
+ # Reproduces the ARIA surface and the `data-state` / `data-value` / `data-max`
8
+ # attributes Radix puts on both the root and the indicator.
9
+ class Component < ApplicationViewComponent
10
+ slot_name :progress
11
+
12
+ style do
13
+ base { "relative h-2 w-full overflow-hidden rounded-full bg-primary/20" }
14
+ end
15
+
16
+ INDICATOR_CLASSES = "h-full w-full flex-1 bg-primary transition-all"
17
+
18
+ attr_reader :value, :max
19
+
20
+ def initialize(value: nil, max: 100, **attributes)
21
+ @value = value
22
+ @max = max
23
+ super(**attributes)
24
+ end
25
+
26
+ def state
27
+ return "indeterminate" if value.nil?
28
+
29
+ value >= max ? "complete" : "loading"
30
+ end
31
+
32
+ def element_attributes(**defaults)
33
+ super(**{
34
+ role: "progressbar",
35
+ "aria-valuemax" => max,
36
+ "aria-valuemin" => 0,
37
+ "aria-valuenow" => value,
38
+ "data-state" => state,
39
+ "data-value" => value,
40
+ "data-max" => max
41
+ }.merge(defaults))
42
+ end
43
+
44
+ def call
45
+ render_element(body: indicator)
46
+ end
47
+
48
+ private
49
+
50
+ def indicator
51
+ tag.div(
52
+ "data-slot": "progress-indicator",
53
+ "data-state": state,
54
+ "data-value": value,
55
+ "data-max": max,
56
+ class: INDICATOR_CLASSES,
57
+ style: "transform: translateX(-#{100 - (value || 0)}%)"
58
+ )
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Progress
5
+ class Preview < ApplicationViewComponentPreview
6
+ def default
7
+ render_with_template
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ <div class="flex w-[420px] flex-col gap-4">
2
+ <% [0, 33, 66, 100].each do |value| %>
3
+ <%= render(Shadcn::Progress::Component.new(value:, "aria-label": "Upload progress")) %>
4
+ <% end %>
5
+ </div>
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module RadioGroup
5
+ # Port of registry/new-york-v4/ui/radio-group.tsx
6
+ class Component < ApplicationViewComponent
7
+ include Concerns::SubmitsValue
8
+ renders_many :items, "Shadcn::RadioGroup::Item::Component"
9
+
10
+ slot_name :"radio-group"
11
+
12
+ style do
13
+ base { "grid gap-3" }
14
+ end
15
+
16
+ attr_reader :name, :value, :disabled
17
+
18
+ def initialize(name: nil, value: nil, disabled: false, **attributes)
19
+ @name = name
20
+ @value = value.to_s
21
+ @disabled = disabled
22
+ super(**attributes)
23
+ end
24
+
25
+ def element_attributes(**defaults)
26
+ super(**{
27
+ role: "radiogroup",
28
+ "aria-required" => nil,
29
+ "data-disabled" => (true if disabled),
30
+ "data-controller" => "shadcn--radio-group",
31
+ "data-shadcn--radio-group-value-value" => value,
32
+ "data-shadcn--radio-group-disabled-value" => disabled
33
+ }.merge(defaults))
34
+ end
35
+
36
+ def call
37
+ render_element(body: safe_join([ items, content, hidden_input ].flatten.compact))
38
+ end
39
+
40
+ private
41
+
42
+ # Radix mirrors the selection into a hidden input so the group submits
43
+ # with the form.
44
+ def hidden_input
45
+ return unless name
46
+
47
+ tag.input(**hidden_input_attributes("data-shadcn--radio-group-target" => "input"))
48
+ end
49
+ end
50
+ end
51
+ end