shadcn_phlexcomponents 0.1.9 → 0.1.14

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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/app/javascript/controllers/accordion_controller.ts +136 -0
  3. data/app/javascript/controllers/alert_dialog_controller.ts +12 -0
  4. data/app/javascript/controllers/avatar_controller.ts +24 -0
  5. data/app/javascript/controllers/checkbox_controller.ts +41 -0
  6. data/app/javascript/controllers/collapsible_controller.ts +52 -0
  7. data/app/javascript/controllers/combobox_controller.ts +376 -0
  8. data/app/javascript/controllers/command_controller.ts +301 -0
  9. data/app/javascript/controllers/date_picker_controller.ts +334 -0
  10. data/app/javascript/controllers/date_range_picker_controller.ts +253 -0
  11. data/app/javascript/controllers/dialog_controller.ts +115 -0
  12. data/app/javascript/controllers/dropdown_menu_controller.ts +309 -0
  13. data/app/javascript/controllers/dropdown_menu_sub_controller.ts +152 -0
  14. data/app/javascript/controllers/form_field_controller.ts +27 -0
  15. data/app/javascript/controllers/hover_card_controller.ts +103 -0
  16. data/app/javascript/controllers/{loading_button_controller.js → loading_button_controller.ts} +7 -2
  17. data/app/javascript/controllers/popover_controller.ts +118 -0
  18. data/app/javascript/controllers/progress_controller.ts +23 -0
  19. data/app/javascript/controllers/radio_group_controller.ts +113 -0
  20. data/app/javascript/controllers/select_controller.ts +341 -0
  21. data/app/javascript/controllers/{sidebar_controller.js → sidebar_controller.ts} +6 -2
  22. data/app/javascript/controllers/sidebar_trigger_controller.ts +21 -0
  23. data/app/javascript/controllers/slider_controller.ts +114 -0
  24. data/app/javascript/controllers/switch_controller.ts +37 -0
  25. data/app/javascript/controllers/tabs_controller.ts +87 -0
  26. data/app/javascript/controllers/theme_switcher_controller.ts +40 -0
  27. data/app/javascript/controllers/toast_container_controller.ts +67 -0
  28. data/app/javascript/controllers/toast_controller.ts +34 -0
  29. data/app/javascript/controllers/toggle_controller.ts +28 -0
  30. data/app/javascript/controllers/toggle_group_controller.ts +28 -0
  31. data/app/javascript/controllers/tooltip_controller.ts +110 -0
  32. data/app/javascript/shadcn_phlexcomponents.ts +61 -0
  33. data/app/javascript/utils/command.ts +544 -0
  34. data/app/javascript/utils/floating_ui.ts +196 -0
  35. data/app/javascript/utils/index.ts +417 -0
  36. data/app/stylesheets/date_picker.css +81 -101
  37. data/app/stylesheets/nouislider.css +173 -0
  38. data/app/stylesheets/tw-animate.css +486 -0
  39. data/lib/install/install_shadcn_phlexcomponents.rb +16 -3
  40. data/lib/shadcn_phlexcomponents/alias.rb +6 -1
  41. data/lib/shadcn_phlexcomponents/components/accordion.rb +130 -0
  42. data/lib/shadcn_phlexcomponents/components/alert.rb +59 -0
  43. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +279 -0
  44. data/lib/shadcn_phlexcomponents/components/{aspect_ratio/aspect_ratio.rb → aspect_ratio.rb} +2 -2
  45. data/lib/shadcn_phlexcomponents/components/avatar.rb +63 -0
  46. data/lib/shadcn_phlexcomponents/components/badge.rb +35 -0
  47. data/lib/shadcn_phlexcomponents/components/base.rb +48 -7
  48. data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +150 -0
  49. data/lib/shadcn_phlexcomponents/components/button.rb +49 -0
  50. data/lib/shadcn_phlexcomponents/components/card.rb +88 -0
  51. data/lib/shadcn_phlexcomponents/components/{checkbox/checkbox.rb → checkbox.rb} +18 -14
  52. data/lib/shadcn_phlexcomponents/components/{checkbox_group/checkbox_group.rb → checkbox_group.rb} +7 -8
  53. data/lib/shadcn_phlexcomponents/components/collapsible.rb +90 -0
  54. data/lib/shadcn_phlexcomponents/components/combobox.rb +428 -0
  55. data/lib/shadcn_phlexcomponents/components/command.rb +381 -0
  56. data/lib/shadcn_phlexcomponents/components/date_picker.rb +208 -0
  57. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +143 -0
  58. data/lib/shadcn_phlexcomponents/components/dialog.rb +236 -0
  59. data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +283 -0
  60. data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +136 -0
  61. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +6 -7
  62. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +2 -2
  63. data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +64 -0
  64. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +3 -4
  65. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +27 -41
  66. data/lib/shadcn_phlexcomponents/components/form/form_error.rb +1 -1
  67. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +43 -8
  68. data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +1 -1
  69. data/lib/shadcn_phlexcomponents/components/form/form_input.rb +3 -4
  70. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +4 -5
  71. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +3 -4
  72. data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +91 -0
  73. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +7 -6
  74. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +3 -4
  75. data/lib/shadcn_phlexcomponents/components/{form/form.rb → form.rb} +36 -4
  76. data/lib/shadcn_phlexcomponents/components/hover_card.rb +111 -0
  77. data/lib/shadcn_phlexcomponents/components/input.rb +31 -0
  78. data/lib/shadcn_phlexcomponents/components/label.rb +16 -0
  79. data/lib/shadcn_phlexcomponents/components/{link/link.rb → link.rb} +10 -3
  80. data/lib/shadcn_phlexcomponents/components/{loading_button/loading_button.rb → loading_button.rb} +9 -2
  81. data/lib/shadcn_phlexcomponents/components/pagination.rb +166 -0
  82. data/lib/shadcn_phlexcomponents/components/popover.rb +116 -0
  83. data/lib/shadcn_phlexcomponents/components/{progress/progress.rb → progress.rb} +4 -4
  84. data/lib/shadcn_phlexcomponents/components/radio_group.rb +155 -0
  85. data/lib/shadcn_phlexcomponents/components/select.rb +406 -0
  86. data/lib/shadcn_phlexcomponents/components/{separator/separator.rb → separator.rb} +9 -8
  87. data/lib/shadcn_phlexcomponents/components/sheet.rb +243 -0
  88. data/lib/shadcn_phlexcomponents/components/{skeleton/skeleton.rb → skeleton.rb} +1 -1
  89. data/lib/shadcn_phlexcomponents/components/slider.rb +72 -0
  90. data/lib/shadcn_phlexcomponents/components/switch.rb +75 -0
  91. data/lib/shadcn_phlexcomponents/components/table.rb +140 -0
  92. data/lib/shadcn_phlexcomponents/components/tabs.rb +135 -0
  93. data/lib/shadcn_phlexcomponents/components/textarea.rb +24 -0
  94. data/lib/shadcn_phlexcomponents/components/toast.rb +153 -0
  95. data/lib/shadcn_phlexcomponents/components/{toast/toast_container.rb → toast_container.rb} +23 -4
  96. data/lib/shadcn_phlexcomponents/components/toggle.rb +54 -0
  97. data/lib/shadcn_phlexcomponents/components/tooltip.rb +132 -0
  98. data/lib/shadcn_phlexcomponents/engine.rb +1 -5
  99. data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +25 -0
  100. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  101. data/lib/tasks/install.rake +1 -1
  102. metadata +83 -167
  103. data/app/javascript/controllers/accordion_controller.js +0 -124
  104. data/app/javascript/controllers/alert_dialog_controller.js +0 -21
  105. data/app/javascript/controllers/avatar_controller.js +0 -15
  106. data/app/javascript/controllers/checkbox_controller.js +0 -28
  107. data/app/javascript/controllers/collapsible_controller.js +0 -35
  108. data/app/javascript/controllers/combobox_controller.js +0 -54
  109. data/app/javascript/controllers/date_picker_controller.js +0 -253
  110. data/app/javascript/controllers/date_range_picker_controller.js +0 -344
  111. data/app/javascript/controllers/dialog_controller.js +0 -114
  112. data/app/javascript/controllers/dropdown_menu_controller.js +0 -171
  113. data/app/javascript/controllers/form_field_controller.js +0 -24
  114. data/app/javascript/controllers/hover_card_controller.js +0 -21
  115. data/app/javascript/controllers/popover_controller.js +0 -113
  116. data/app/javascript/controllers/progress_controller.js +0 -14
  117. data/app/javascript/controllers/radio_group_controller.js +0 -90
  118. data/app/javascript/controllers/select_controller.js +0 -274
  119. data/app/javascript/controllers/sidebar_trigger_controller.js +0 -15
  120. data/app/javascript/controllers/switch_controller.js +0 -24
  121. data/app/javascript/controllers/tabs_controller.js +0 -73
  122. data/app/javascript/controllers/theme_switcher_controller.js +0 -32
  123. data/app/javascript/controllers/toast_container_controller.js +0 -22
  124. data/app/javascript/controllers/toast_controller.js +0 -45
  125. data/app/javascript/controllers/tooltip_controller.js +0 -40
  126. data/app/javascript/shadcn_phlexcomponents.js +0 -53
  127. data/app/javascript/utils.js +0 -184
  128. data/app/stylesheets/choices.css +0 -324
  129. data/app/stylesheets/tailwindcss-animate.css +0 -318
  130. data/lib/shadcn_phlexcomponents/components/accordion/accordion.rb +0 -38
  131. data/lib/shadcn_phlexcomponents/components/accordion/accordion_content.rb +0 -30
  132. data/lib/shadcn_phlexcomponents/components/accordion/accordion_item.rb +0 -26
  133. data/lib/shadcn_phlexcomponents/components/accordion/accordion_trigger.rb +0 -46
  134. data/lib/shadcn_phlexcomponents/components/alert/alert.rb +0 -40
  135. data/lib/shadcn_phlexcomponents/components/alert/alert_description.rb +0 -11
  136. data/lib/shadcn_phlexcomponents/components/alert/alert_title.rb +0 -11
  137. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog.rb +0 -60
  138. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_action.rb +0 -22
  139. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_action_to.rb +0 -40
  140. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_cancel.rb +0 -22
  141. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_content.rb +0 -40
  142. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_description.rb +0 -22
  143. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_footer.rb +0 -11
  144. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_header.rb +0 -11
  145. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_title.rb +0 -22
  146. data/lib/shadcn_phlexcomponents/components/alert_dialog/alert_dialog_trigger.rb +0 -50
  147. data/lib/shadcn_phlexcomponents/components/avatar/avatar.rb +0 -31
  148. data/lib/shadcn_phlexcomponents/components/avatar/avatar_fallback.rb +0 -21
  149. data/lib/shadcn_phlexcomponents/components/avatar/avatar_image.rb +0 -19
  150. data/lib/shadcn_phlexcomponents/components/badge/badge.rb +0 -30
  151. data/lib/shadcn_phlexcomponents/components/breadcrumb/breadcrumb.rb +0 -53
  152. data/lib/shadcn_phlexcomponents/components/breadcrumb/breadcrumb_ellipsis.rb +0 -23
  153. data/lib/shadcn_phlexcomponents/components/breadcrumb/breadcrumb_item.rb +0 -11
  154. data/lib/shadcn_phlexcomponents/components/breadcrumb/breadcrumb_link.rb +0 -7
  155. data/lib/shadcn_phlexcomponents/components/breadcrumb/breadcrumb_page.rb +0 -21
  156. data/lib/shadcn_phlexcomponents/components/breadcrumb/breadcrumb_separator.rb +0 -26
  157. data/lib/shadcn_phlexcomponents/components/button/button.rb +0 -53
  158. data/lib/shadcn_phlexcomponents/components/card/card.rb +0 -31
  159. data/lib/shadcn_phlexcomponents/components/card/card_content.rb +0 -11
  160. data/lib/shadcn_phlexcomponents/components/card/card_description.rb +0 -11
  161. data/lib/shadcn_phlexcomponents/components/card/card_footer.rb +0 -11
  162. data/lib/shadcn_phlexcomponents/components/card/card_header.rb +0 -11
  163. data/lib/shadcn_phlexcomponents/components/card/card_title.rb +0 -11
  164. data/lib/shadcn_phlexcomponents/components/collapsible/collapsible.rb +0 -31
  165. data/lib/shadcn_phlexcomponents/components/collapsible/collapsible_content.rb +0 -24
  166. data/lib/shadcn_phlexcomponents/components/collapsible/collapsible_trigger.rb +0 -50
  167. data/lib/shadcn_phlexcomponents/components/date_picker/date_picker.rb +0 -87
  168. data/lib/shadcn_phlexcomponents/components/date_picker/date_picker_content.rb +0 -45
  169. data/lib/shadcn_phlexcomponents/components/date_picker/date_picker_trigger.rb +0 -64
  170. data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker.rb +0 -105
  171. data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker_content.rb +0 -9
  172. data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker_trigger.rb +0 -9
  173. data/lib/shadcn_phlexcomponents/components/dialog/dialog.rb +0 -52
  174. data/lib/shadcn_phlexcomponents/components/dialog/dialog_close.rb +0 -42
  175. data/lib/shadcn_phlexcomponents/components/dialog/dialog_content.rb +0 -54
  176. data/lib/shadcn_phlexcomponents/components/dialog/dialog_description.rb +0 -22
  177. data/lib/shadcn_phlexcomponents/components/dialog/dialog_footer.rb +0 -11
  178. data/lib/shadcn_phlexcomponents/components/dialog/dialog_header.rb +0 -11
  179. data/lib/shadcn_phlexcomponents/components/dialog/dialog_title.rb +0 -22
  180. data/lib/shadcn_phlexcomponents/components/dialog/dialog_trigger.rb +0 -50
  181. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu.rb +0 -50
  182. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu_content.rb +0 -52
  183. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu_item.rb +0 -56
  184. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu_item_to.rb +0 -28
  185. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu_label.rb +0 -11
  186. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu_separator.rb +0 -20
  187. data/lib/shadcn_phlexcomponents/components/dropdown_menu/dropdown_menu_trigger.rb +0 -57
  188. data/lib/shadcn_phlexcomponents/components/hover_card/hover_card.rb +0 -33
  189. data/lib/shadcn_phlexcomponents/components/hover_card/hover_card_content.rb +0 -32
  190. data/lib/shadcn_phlexcomponents/components/hover_card/hover_card_trigger.rb +0 -44
  191. data/lib/shadcn_phlexcomponents/components/input/input.rb +0 -32
  192. data/lib/shadcn_phlexcomponents/components/label/label.rb +0 -14
  193. data/lib/shadcn_phlexcomponents/components/pagination/pagination.rb +0 -38
  194. data/lib/shadcn_phlexcomponents/components/pagination/pagination_ellipsis.rb +0 -24
  195. data/lib/shadcn_phlexcomponents/components/pagination/pagination_link.rb +0 -34
  196. data/lib/shadcn_phlexcomponents/components/pagination/pagination_next.rb +0 -32
  197. data/lib/shadcn_phlexcomponents/components/pagination/pagination_previous.rb +0 -32
  198. data/lib/shadcn_phlexcomponents/components/popover/popover.rb +0 -34
  199. data/lib/shadcn_phlexcomponents/components/popover/popover_content.rb +0 -40
  200. data/lib/shadcn_phlexcomponents/components/popover/popover_trigger.rb +0 -50
  201. data/lib/shadcn_phlexcomponents/components/radio_group/radio_group.rb +0 -88
  202. data/lib/shadcn_phlexcomponents/components/radio_group/radio_group_item.rb +0 -66
  203. data/lib/shadcn_phlexcomponents/components/select/select.rb +0 -194
  204. data/lib/shadcn_phlexcomponents/components/select/select_content.rb +0 -64
  205. data/lib/shadcn_phlexcomponents/components/select/select_group.rb +0 -23
  206. data/lib/shadcn_phlexcomponents/components/select/select_item.rb +0 -59
  207. data/lib/shadcn_phlexcomponents/components/select/select_label.rb +0 -24
  208. data/lib/shadcn_phlexcomponents/components/select/select_trigger.rb +0 -56
  209. data/lib/shadcn_phlexcomponents/components/sheet/sheet.rb +0 -53
  210. data/lib/shadcn_phlexcomponents/components/sheet/sheet_close.rb +0 -42
  211. data/lib/shadcn_phlexcomponents/components/sheet/sheet_content.rb +0 -65
  212. data/lib/shadcn_phlexcomponents/components/sheet/sheet_description.rb +0 -22
  213. data/lib/shadcn_phlexcomponents/components/sheet/sheet_footer.rb +0 -11
  214. data/lib/shadcn_phlexcomponents/components/sheet/sheet_header.rb +0 -11
  215. data/lib/shadcn_phlexcomponents/components/sheet/sheet_title.rb +0 -22
  216. data/lib/shadcn_phlexcomponents/components/sheet/sheet_trigger.rb +0 -50
  217. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar.rb +0 -108
  218. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_container.rb +0 -11
  219. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_content.rb +0 -11
  220. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_footer.rb +0 -11
  221. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_group.rb +0 -11
  222. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_group_content.rb +0 -11
  223. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_group_label.rb +0 -16
  224. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_header.rb +0 -11
  225. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_inset.rb +0 -15
  226. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_menu.rb +0 -11
  227. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_menu_button.rb +0 -61
  228. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_menu_item.rb +0 -9
  229. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_menu_sub.rb +0 -14
  230. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_menu_sub_button.rb +0 -48
  231. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_menu_sub_item.rb +0 -9
  232. data/lib/shadcn_phlexcomponents/components/sidebar/sidebar_trigger.rb +0 -40
  233. data/lib/shadcn_phlexcomponents/components/switch/switch.rb +0 -66
  234. data/lib/shadcn_phlexcomponents/components/table/table.rb +0 -75
  235. data/lib/shadcn_phlexcomponents/components/table/table_body.rb +0 -11
  236. data/lib/shadcn_phlexcomponents/components/table/table_caption.rb +0 -11
  237. data/lib/shadcn_phlexcomponents/components/table/table_cell.rb +0 -11
  238. data/lib/shadcn_phlexcomponents/components/table/table_footer.rb +0 -11
  239. data/lib/shadcn_phlexcomponents/components/table/table_head.rb +0 -14
  240. data/lib/shadcn_phlexcomponents/components/table/table_header.rb +0 -11
  241. data/lib/shadcn_phlexcomponents/components/table/table_row.rb +0 -11
  242. data/lib/shadcn_phlexcomponents/components/tabs/tabs.rb +0 -38
  243. data/lib/shadcn_phlexcomponents/components/tabs/tabs_content.rb +0 -35
  244. data/lib/shadcn_phlexcomponents/components/tabs/tabs_list.rb +0 -23
  245. data/lib/shadcn_phlexcomponents/components/tabs/tabs_trigger.rb +0 -45
  246. data/lib/shadcn_phlexcomponents/components/textarea/textarea.rb +0 -29
  247. data/lib/shadcn_phlexcomponents/components/toast/toast.rb +0 -101
  248. data/lib/shadcn_phlexcomponents/components/toast/toast_action.rb +0 -39
  249. data/lib/shadcn_phlexcomponents/components/toast/toast_action_to.rb +0 -28
  250. data/lib/shadcn_phlexcomponents/components/toast/toast_content.rb +0 -11
  251. data/lib/shadcn_phlexcomponents/components/toast/toast_description.rb +0 -11
  252. data/lib/shadcn_phlexcomponents/components/toast/toast_title.rb +0 -11
  253. data/lib/shadcn_phlexcomponents/components/tooltip/tooltip.rb +0 -34
  254. data/lib/shadcn_phlexcomponents/components/tooltip/tooltip_content.rb +0 -39
  255. data/lib/shadcn_phlexcomponents/components/tooltip/tooltip_trigger.rb +0 -48
  256. /data/lib/shadcn_phlexcomponents/components/{theme_switcher/theme_switcher.rb → theme_switcher.rb} +0 -0
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class RadioGroup < Base
5
+ class_variants(base: "grid gap-3 outline-none")
6
+
7
+ def initialize(name: nil, value: nil, dir: "ltr", include_hidden: true, **attributes)
8
+ @name = name
9
+ @value = value
10
+ @dir = dir
11
+ @include_hidden = include_hidden
12
+ super(**attributes)
13
+ end
14
+
15
+ def label(**attributes)
16
+ @label_attributes = attributes
17
+ nil
18
+ end
19
+
20
+ def radio(**attributes)
21
+ @radio_attributes = attributes
22
+ nil
23
+ end
24
+
25
+ def item(name: nil, value: nil, checked: false, **attributes)
26
+ RadioGroupItem(name: name || @name, value: value, checked: checked || @value == value, **attributes)
27
+ end
28
+
29
+ def items(collection, value_method:, text_method:, container_class: nil, disabled_items: nil, id_prefix: nil, &)
30
+ vanish(&)
31
+
32
+ container_class = TAILWIND_MERGER.merge("flex items-center gap-3 #{container_class}")
33
+
34
+ if collection.first&.is_a?(Hash)
35
+ collection = convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
36
+ end
37
+
38
+ collection.each do |item|
39
+ value = item.public_send(value_method)
40
+ text = item.public_send(text_method)
41
+ id = if id_prefix
42
+ "#{id_prefix.parameterize.underscore}_#{value}"
43
+ else
44
+ "#{@name.parameterize.underscore}_#{value}"
45
+ end
46
+
47
+ div(class: container_class) do
48
+ RadioGroupItem(
49
+ name: @name,
50
+ value: value,
51
+ checked: @value == value,
52
+ id: id,
53
+ disabled: item_disabled?(disabled_items, value),
54
+ **@radio_attributes,
55
+ )
56
+ Label(for: id, **@label_attributes) { text }
57
+ end
58
+ end
59
+
60
+ nil
61
+ end
62
+
63
+ def default_attributes
64
+ {
65
+ role: "radiogroup",
66
+ dir: @dir,
67
+ aria: {
68
+ required: false,
69
+ },
70
+ data: {
71
+ controller: "radio-group",
72
+ radio_group_selected_value: @value,
73
+ },
74
+ }
75
+ end
76
+
77
+ def view_template(&)
78
+ div(**@attributes) do
79
+ if @include_hidden
80
+ input(type: "hidden", name: @name, autocomplete: "off")
81
+ end
82
+
83
+ yield
84
+ end
85
+ end
86
+ end
87
+
88
+ class RadioGroupItem < Base
89
+ class_variants(
90
+ base: <<~HEREDOC,
91
+ border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20
92
+ dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4
93
+ shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px]
94
+ disabled:cursor-not-allowed disabled:opacity-50 relative
95
+ HEREDOC
96
+ )
97
+
98
+ def initialize(name: nil, value: nil, checked: false, **attributes)
99
+ @value = value
100
+ @name = name
101
+ @checked = checked
102
+ super(**attributes)
103
+ end
104
+
105
+ def view_template(&)
106
+ button(**@attributes) do
107
+ span(
108
+ class: "relative flex items-center justify-center",
109
+ data: {
110
+ radio_group_target: "indicator",
111
+ },
112
+ ) do
113
+ icon("circle", class: "fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2")
114
+ end
115
+
116
+ input(
117
+ type: "radio",
118
+ value: @value,
119
+ class: "-translate-x-full pointer-events-none absolute top-0 left-0 size-4 opacity-0",
120
+ name: @name,
121
+ tabindex: -1,
122
+ checked: @checked,
123
+ aria: { hidden: "true" },
124
+ data: {
125
+ radio_group_target: "input",
126
+ },
127
+ )
128
+ end
129
+ end
130
+
131
+ def default_attributes
132
+ {
133
+ type: "button",
134
+ tabindex: -1,
135
+ role: "radio",
136
+ aria: {
137
+ checked: @checked.to_s,
138
+ },
139
+ data: {
140
+ checked: @checked.to_s,
141
+ value: @value,
142
+ radio_group_target: "item",
143
+ action: <<~HEREDOC,
144
+ click->radio-group#select
145
+ keydown.right->radio-group#selectItem:prevent
146
+ keydown.down->radio-group#selectItem:prevent
147
+ keydown.up->radio-group#selectItem:prevent
148
+ keydown.left->radio-group#selectItem:prevent
149
+ keydown.enter->radio-group#preventDefault
150
+ HEREDOC
151
+ },
152
+ }
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,406 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ NATIVE_OPTION_STYLES = "bg-popover text-popover-foreground"
5
+
6
+ class Select < Base
7
+ def initialize(
8
+ id: nil,
9
+ name: nil,
10
+ value: nil,
11
+ placeholder: nil,
12
+ native: false,
13
+ include_blank: false,
14
+ disabled: false,
15
+ **attributes
16
+ )
17
+ @id = id
18
+ @name = name
19
+ @value = value
20
+ @placeholder = placeholder
21
+ @native = native
22
+ @include_blank = include_blank
23
+ @disabled = disabled
24
+ @aria_id = "select-#{SecureRandom.hex(5)}"
25
+ super(**attributes)
26
+ end
27
+
28
+ def class_variants(**args)
29
+ if @native
30
+ Input.new.class_variants(class: "appearance-none #{args[:class]}")
31
+ else
32
+ TAILWIND_MERGER.merge("w-full #{args[:class]}")
33
+ end
34
+ end
35
+
36
+ def trigger(**attributes)
37
+ SelectTrigger(
38
+ id: @id,
39
+ aria_id: @aria_id,
40
+ value: @value,
41
+ placeholder: @placeholder,
42
+ disabled: @disabled,
43
+ **attributes,
44
+ )
45
+ end
46
+
47
+ def content(**attributes, &)
48
+ SelectContent(
49
+ aria_id: @aria_id, include_blank: @include_blank, native: @native, **attributes, &
50
+ )
51
+ end
52
+
53
+ def item(**attributes, &)
54
+ SelectItem(aria_id: @aria_id, **attributes, &)
55
+ end
56
+
57
+ def label(**attributes, &)
58
+ SelectLabel(**attributes, &)
59
+ end
60
+
61
+ def group(**attributes, &)
62
+ SelectGroup(aria_id: @aria_id, **attributes, &)
63
+ end
64
+
65
+ def items(collection, value_method:, text_method:, disabled_items: nil, &)
66
+ vanish(&)
67
+
68
+ if collection.first&.is_a?(Hash)
69
+ collection = convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
70
+ end
71
+
72
+ SelectTrigger(
73
+ id: @id,
74
+ aria_id: @aria_id,
75
+ value: @value,
76
+ placeholder: @placeholder,
77
+ disabled: @disabled,
78
+ )
79
+
80
+ SelectContent(aria_id: @aria_id, include_blank: @include_blank, native: @native) do
81
+ collection.each do |item|
82
+ value = item.public_send(value_method)
83
+ text = item.public_send(text_method)
84
+
85
+ SelectItem(value: value, aria_id: @aria_id, disabled: item_disabled?(disabled_items, value)) { text }
86
+ end
87
+ end
88
+ end
89
+
90
+ def view_template(&)
91
+ content = capture(&)
92
+ element = Nokogiri::HTML.fragment(content.to_s)
93
+ content_element = element.css('[data-select-target="content"]')
94
+
95
+ if @native
96
+ div(class: "relative") do
97
+ select(**@attributes) do
98
+ if @placeholder || @include_blank
99
+ option(value: "", class: NATIVE_OPTION_STYLES) { @placeholder }
100
+ end
101
+
102
+ build_native_options(content_element)
103
+ end
104
+
105
+ icon("chevron-down", class: "size-4 absolute opacity-50 top-1/2 -translate-y-1/2 right-3 pointer-events-none")
106
+ end
107
+ else
108
+ div(**@attributes) do
109
+ yield
110
+
111
+ select(
112
+ name: @name,
113
+ disabled: @disabled,
114
+ class: "sr-only",
115
+ tabindex: -1,
116
+ data: {
117
+ select_target: "select",
118
+ },
119
+ ) do
120
+ option(value: "")
121
+ build_native_options(content_element)
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ def default_attributes
128
+ if @native
129
+ {
130
+ id: @id,
131
+ name: @name,
132
+ disabled: @disabled,
133
+ }
134
+ else
135
+ {
136
+ data: {
137
+ aria_id: @aria_id,
138
+ controller: "select",
139
+ select_selected_value: @value,
140
+ },
141
+ }
142
+ end
143
+ end
144
+
145
+ def build_native_options(content_element)
146
+ content_element.children.each do |content_child|
147
+ next if content_child.is_a?(Nokogiri::XML::Text) || content_child.is_a?(Nokogiri::XML::Comment)
148
+
149
+ if content_child.attributes["data-select-target"]&.value == "group"
150
+ group_label = content_child.at_css('[data-shadcn-phlexcomponents="select-label"]')&.text
151
+
152
+ optgroup(label: group_label, class: NATIVE_OPTION_STYLES) do
153
+ content_child.css('[data-select-target="item"]').each do |i|
154
+ option(
155
+ value: i.attributes["data-value"].value,
156
+ class: NATIVE_OPTION_STYLES,
157
+ selected: i.attributes["data-value"].value == @value,
158
+ disabled: i.attributes["data-disabled"]&.value == "",
159
+ ) do
160
+ i.text
161
+ end
162
+ end
163
+ end
164
+ elsif content_child.attributes["data-select-target"]&.value == "item"
165
+
166
+ option(
167
+ value: content_child.attributes["data-value"].value,
168
+ class: NATIVE_OPTION_STYLES,
169
+ selected: content_child.attributes["data-value"].value == @value,
170
+ disabled: content_child.attributes["data-disabled"]&.value == "",
171
+ ) do
172
+ content_child.text
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ class SelectTrigger < Base
180
+ class_variants(
181
+ base: <<~HEREDOC,
182
+ border-input [&_svg:not([class*='text-'])]:text-muted-foreground
183
+ focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
184
+ aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex items-center
185
+ justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs
186
+ transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50
187
+ data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[select-target=triggerText]:line-clamp-1#{" "}
188
+ *:data-[select-target=triggerText]:flex *:data-[select-target=triggerText]:items-center *:data-[select-target=triggerText]:gap-2
189
+ [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
190
+ data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full
191
+ HEREDOC
192
+ )
193
+
194
+ def initialize(id: nil, value: nil, placeholder: nil, aria_id: nil, **attributes)
195
+ @id = id
196
+ @value = value
197
+ @placeholder = placeholder
198
+ @aria_id = aria_id
199
+ super(**attributes)
200
+ end
201
+
202
+ def view_template
203
+ button(**@attributes) do
204
+ span(class: "pointer-events-none", data: { select_target: "triggerText" }) do
205
+ @value || @placeholder
206
+ end
207
+
208
+ icon("chevron-down", class: "size-4 opacity-50 text-foreground")
209
+ end
210
+ end
211
+
212
+ def default_attributes
213
+ {
214
+ type: "button",
215
+ id: @id,
216
+ role: "combobox",
217
+ aria: {
218
+ autocomplete: "none",
219
+ expanded: false,
220
+ controls: "#{@aria_id}-content",
221
+ },
222
+ data: {
223
+ placeholder: @placeholder,
224
+ has_value: @value.present?.to_s,
225
+ action: <<~HEREDOC,
226
+ click->select#toggle
227
+ keydown.down->select#open:prevent
228
+ keydown.space->select#open:prevent
229
+ keydown.enter->select#open:prevent
230
+ HEREDOC
231
+ select_target: "trigger",
232
+ },
233
+ }
234
+ end
235
+ end
236
+
237
+ class SelectContent < Base
238
+ class_variants(
239
+ base: <<~HEREDOC,
240
+ bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out
241
+ data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
242
+ data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
243
+ data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50
244
+ max-h-(--radix-popper-available-height) min-w-[8rem] origin-(--radix-popper-transform-origin)
245
+ overflow-x-hidden overflow-y-auto rounded-md border shadow-md p-1 pointer-events-auto outline-none
246
+ HEREDOC
247
+ )
248
+
249
+ def initialize(include_blank: false, native: false, side: :bottom, align: :center, aria_id: nil, **attributes)
250
+ @include_blank = include_blank
251
+ @native = native
252
+ @side = side
253
+ @align = align
254
+ @aria_id = aria_id
255
+ super(**attributes)
256
+ end
257
+
258
+ def view_template(&)
259
+ div(
260
+ style: { display: "none" },
261
+ class: "fixed top-0 left-0 w-max z-50",
262
+ data: { select_target: "contentContainer" },
263
+ ) do
264
+ div(**@attributes) do
265
+ if @include_blank && !@native
266
+ SelectItem(aria_id: @aria_id, value: "", class: "h-8") do
267
+ @include_blank.is_a?(String) ? @include_blank : ""
268
+ end
269
+ end
270
+
271
+ yield
272
+ end
273
+ end
274
+ end
275
+
276
+ def default_attributes
277
+ {
278
+ id: "#{@aria_id}-content",
279
+ tabindex: -1,
280
+ role: "listbox",
281
+ aria: {
282
+ labelledby: "#{@aria_id}-trigger",
283
+ orientation: "vertical",
284
+ },
285
+ data: {
286
+ side: @side,
287
+ align: @align,
288
+ state: "closed",
289
+ select_target: "content",
290
+ action: <<~HEREDOC,
291
+ select:click:outside->select#clickOutside
292
+ keydown.up->select#focusItemByIndex:prevent:self
293
+ keydown.down->select#focusItemByIndex:prevent:self
294
+ HEREDOC
295
+ },
296
+ }
297
+ end
298
+ end
299
+
300
+ class SelectLabel < Base
301
+ class_variants(
302
+ base: "text-muted-foreground px-2 py-1.5 text-xs",
303
+ )
304
+
305
+ def initialize(**attributes)
306
+ super(**attributes)
307
+ end
308
+
309
+ def view_template(&)
310
+ div(**@attributes, &)
311
+ end
312
+ end
313
+
314
+ class SelectItem < Base
315
+ class_variants(
316
+ base: <<~HEREDOC,
317
+ focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground
318
+ relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm
319
+ outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50
320
+ [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
321
+ *:[span]:last:items-center *:[span]:last:gap-2 group/item
322
+ HEREDOC
323
+ )
324
+
325
+ def initialize(value: nil, disabled: false, aria_id: nil, **attributes)
326
+ @value = value
327
+ @disabled = disabled
328
+ @aria_id = aria_id
329
+ @aria_labelledby = "#{@aria_id}-#{@value.dasherize.parameterize}"
330
+ super(**attributes)
331
+ end
332
+
333
+ def view_template(&)
334
+ div(**@attributes) do
335
+ span(id: @aria_labelledby, &)
336
+
337
+ span(class: "absolute right-2 h-3.5 w-3.5 items-center hidden justify-center
338
+ group-aria-[selected=true]/item:flex group-data-[value='']/item:hidden") do
339
+ icon("check", class: "size-4")
340
+ end
341
+ end
342
+ end
343
+
344
+ def default_attributes
345
+ {
346
+ role: "option",
347
+ tabindex: -1,
348
+ aria: {
349
+ selected: false,
350
+ labelledby: @aria_labelledby,
351
+ },
352
+ data: {
353
+ disabled: @disabled,
354
+ value: @value,
355
+ action: <<~HEREDOC,
356
+ click->select#select
357
+ mouseover->select#focusItem
358
+ keydown.up->select#focusItem:prevent
359
+ keydown.down->select#focusItem:prevent
360
+ focus->select#onItemFocus
361
+ blur->select#onItemBlur
362
+ keydown.enter->select#select:prevent
363
+ keydown.space->select#select:prevent
364
+ mouseout->select#focusContent
365
+ HEREDOC
366
+ select_target: "item",
367
+ },
368
+ }
369
+ end
370
+ end
371
+
372
+ class SelectGroup < Base
373
+ def initialize(aria_id: nil, **attributes)
374
+ @aria_id = aria_id
375
+ super(**attributes)
376
+ end
377
+
378
+ def view_template(&)
379
+ div(**@attributes, &)
380
+ end
381
+
382
+ def default_attributes
383
+ {
384
+ role: "group",
385
+ aria: {
386
+ labelledby: "#{@aria_id}-group-#{SecureRandom.hex(5)}",
387
+ },
388
+ data: {
389
+ select_target: "group",
390
+ },
391
+ }
392
+ end
393
+ end
394
+
395
+ class SelectSeparator < Base
396
+ class_variants(base: "bg-border pointer-events-none -mx-1 my-1 h-px")
397
+
398
+ def view_template(&)
399
+ div(**@attributes, &)
400
+ end
401
+
402
+ def default_attributes
403
+ { aria: { hidden: "true" } }
404
+ end
405
+ end
406
+ end
@@ -2,23 +2,24 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class Separator < Base
5
- ORIENTATIONS = {
6
- horizontal: "shrink-0 bg-border h-[1px] w-full",
7
- vertical: "shrink-0 bg-border h-full w-[1px]",
8
- }.freeze
5
+ class_variants(
6
+ base: <<~HEREDOC,
7
+ bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full
8
+ data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px
9
+ HEREDOC
10
+ )
9
11
 
10
12
  def initialize(orientation: :horizontal, **attributes)
11
13
  @orientation = orientation
12
14
  super(**attributes)
13
15
  end
14
16
 
15
- def default_styles
16
- ORIENTATIONS[@orientation].to_s
17
- end
18
-
19
17
  def default_attributes
20
18
  {
21
19
  role: "none",
20
+ data: {
21
+ orientation: @orientation,
22
+ },
22
23
  }
23
24
  end
24
25