shadcn_phlexcomponents 0.1.5 → 0.1.11

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -0
  3. data/app/javascript/controllers/accordion_controller.ts +133 -0
  4. data/app/javascript/controllers/{avatar_controller.js → avatar_controller.ts} +4 -0
  5. data/app/javascript/controllers/checkbox_controller.ts +34 -0
  6. data/app/javascript/controllers/collapsible_controller.ts +45 -0
  7. data/app/javascript/controllers/combobox_controller.ts +145 -0
  8. data/app/javascript/controllers/command_controller.ts +129 -0
  9. data/app/javascript/controllers/command_root_controller.ts +355 -0
  10. data/app/javascript/controllers/date_picker_controller.ts +274 -0
  11. data/app/javascript/controllers/date_range_picker_controller.ts +243 -0
  12. data/app/javascript/controllers/dialog_controller.ts +113 -0
  13. data/app/javascript/controllers/dropdown_menu_controller.ts +133 -0
  14. data/app/javascript/controllers/dropdown_menu_root_controller.ts +234 -0
  15. data/app/javascript/controllers/dropdown_menu_sub_controller.ts +150 -0
  16. data/app/javascript/controllers/form_field_controller.ts +22 -0
  17. data/app/javascript/controllers/hover_card_controller.ts +93 -0
  18. data/app/javascript/controllers/{loading_button_controller.js → loading_button_controller.ts} +2 -2
  19. data/app/javascript/controllers/popover_controller.ts +141 -0
  20. data/app/javascript/controllers/progress_controller.ts +17 -0
  21. data/app/javascript/controllers/radio_group_controller.ts +106 -0
  22. data/app/javascript/controllers/select_controller.ts +200 -0
  23. data/app/javascript/controllers/{sidebar_controller.js → sidebar_controller.ts} +6 -2
  24. data/app/javascript/controllers/sidebar_trigger_controller.ts +21 -0
  25. data/app/javascript/controllers/slider_controller.ts +107 -0
  26. data/app/javascript/controllers/switch_controller.ts +30 -0
  27. data/app/javascript/controllers/tabs_controller.ts +79 -0
  28. data/app/javascript/controllers/{theme_switcher_controller.js → theme_switcher_controller.ts} +12 -9
  29. data/app/javascript/controllers/toast_container_controller.ts +62 -0
  30. data/app/javascript/controllers/toast_controller.ts +28 -0
  31. data/app/javascript/controllers/tooltip_controller.ts +98 -0
  32. data/app/javascript/shadcn_phlexcomponents.ts +57 -0
  33. data/app/javascript/utils.ts +437 -0
  34. data/app/stylesheets/date_picker.css +74 -0
  35. data/app/stylesheets/nouislider.css +173 -0
  36. data/app/stylesheets/tw-animate.css +486 -0
  37. data/lib/install/install_shadcn_phlexcomponents.rb +22 -9
  38. data/lib/shadcn_phlexcomponents/alias.rb +3 -1
  39. data/lib/shadcn_phlexcomponents/components/accordion.rb +129 -0
  40. data/lib/shadcn_phlexcomponents/components/alert.rb +59 -0
  41. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +276 -0
  42. data/lib/{components → shadcn_phlexcomponents/components}/aspect_ratio.rb +2 -2
  43. data/lib/shadcn_phlexcomponents/components/avatar.rb +63 -0
  44. data/lib/shadcn_phlexcomponents/components/badge.rb +35 -0
  45. data/lib/{components → shadcn_phlexcomponents/components}/base.rb +44 -7
  46. data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +150 -0
  47. data/lib/shadcn_phlexcomponents/components/button.rb +49 -0
  48. data/lib/shadcn_phlexcomponents/components/card.rb +88 -0
  49. data/lib/{components → shadcn_phlexcomponents/components}/checkbox.rb +21 -17
  50. data/lib/{components → shadcn_phlexcomponents/components}/checkbox_group.rb +27 -16
  51. data/lib/shadcn_phlexcomponents/components/collapsible.rb +91 -0
  52. data/lib/shadcn_phlexcomponents/components/combobox.rb +398 -0
  53. data/lib/shadcn_phlexcomponents/components/command.rb +351 -0
  54. data/lib/shadcn_phlexcomponents/components/date_picker.rb +264 -0
  55. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +126 -0
  56. data/lib/shadcn_phlexcomponents/components/dialog.rb +234 -0
  57. data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +282 -0
  58. data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +135 -0
  59. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +82 -0
  60. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +116 -0
  61. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +46 -0
  62. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +82 -0
  63. data/lib/{components → shadcn_phlexcomponents/components/form}/form_error.rb +7 -3
  64. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +143 -0
  65. data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +21 -0
  66. data/lib/{components → shadcn_phlexcomponents/components/form}/form_input.rb +3 -4
  67. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +106 -0
  68. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +64 -0
  69. data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +91 -0
  70. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +67 -0
  71. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +59 -0
  72. data/lib/shadcn_phlexcomponents/components/form.rb +157 -0
  73. data/lib/shadcn_phlexcomponents/components/hover_card.rb +110 -0
  74. data/lib/shadcn_phlexcomponents/components/input.rb +31 -0
  75. data/lib/shadcn_phlexcomponents/components/label.rb +16 -0
  76. data/lib/{components → shadcn_phlexcomponents/components}/link.rb +10 -3
  77. data/lib/shadcn_phlexcomponents/components/loading_button.rb +28 -0
  78. data/lib/shadcn_phlexcomponents/components/pagination.rb +166 -0
  79. data/lib/shadcn_phlexcomponents/components/popover.rb +116 -0
  80. data/lib/{components → shadcn_phlexcomponents/components}/progress.rb +5 -5
  81. data/lib/shadcn_phlexcomponents/components/radio_group.rb +155 -0
  82. data/lib/shadcn_phlexcomponents/components/select.rb +421 -0
  83. data/lib/{components → shadcn_phlexcomponents/components}/separator.rb +9 -8
  84. data/lib/shadcn_phlexcomponents/components/sheet.rb +239 -0
  85. data/lib/{components → shadcn_phlexcomponents/components}/skeleton.rb +1 -1
  86. data/lib/shadcn_phlexcomponents/components/slider.rb +72 -0
  87. data/lib/shadcn_phlexcomponents/components/switch.rb +75 -0
  88. data/lib/shadcn_phlexcomponents/components/table.rb +140 -0
  89. data/lib/shadcn_phlexcomponents/components/tabs.rb +135 -0
  90. data/lib/shadcn_phlexcomponents/components/textarea.rb +24 -0
  91. data/lib/{components → shadcn_phlexcomponents/components}/theme_switcher.rb +2 -2
  92. data/lib/shadcn_phlexcomponents/components/toast.rb +153 -0
  93. data/lib/{components → shadcn_phlexcomponents/components}/toast_container.rb +24 -5
  94. data/lib/shadcn_phlexcomponents/components/tooltip.rb +131 -0
  95. data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +25 -0
  96. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  97. data/lib/tasks/install.rake +1 -1
  98. metadata +92 -168
  99. data/app/assets/tailwind/choices.css +0 -324
  100. data/app/assets/tailwind/tailwindcss-animate.css +0 -318
  101. data/app/assets/tailwind/vanilla-calendar-pro.css +0 -466
  102. data/app/javascript/controllers/accordion_controller.js +0 -133
  103. data/app/javascript/controllers/alert_dialog_controller.js +0 -157
  104. data/app/javascript/controllers/checkbox_controller.js +0 -28
  105. data/app/javascript/controllers/collapsible_controller.js +0 -35
  106. data/app/javascript/controllers/combobox_controller.js +0 -34
  107. data/app/javascript/controllers/date_picker_controller.js +0 -118
  108. data/app/javascript/controllers/date_range_picker_controller.js +0 -231
  109. data/app/javascript/controllers/dialog_controller.js +0 -159
  110. data/app/javascript/controllers/dropdown_menu_controller.js +0 -193
  111. data/app/javascript/controllers/hover_card_controller.js +0 -42
  112. data/app/javascript/controllers/popover_controller.js +0 -124
  113. data/app/javascript/controllers/progress_controller.js +0 -14
  114. data/app/javascript/controllers/radio_group_controller.js +0 -90
  115. data/app/javascript/controllers/select_controller.js +0 -294
  116. data/app/javascript/controllers/sheet_controller.js +0 -159
  117. data/app/javascript/controllers/sidebar_trigger_controller.js +0 -15
  118. data/app/javascript/controllers/switch_controller.js +0 -24
  119. data/app/javascript/controllers/tabs_controller.js +0 -73
  120. data/app/javascript/controllers/toast_container_controller.js +0 -22
  121. data/app/javascript/controllers/toast_controller.js +0 -45
  122. data/app/javascript/controllers/tooltip_controller.js +0 -41
  123. data/lib/components/accordion.rb +0 -38
  124. data/lib/components/accordion_content.rb +0 -30
  125. data/lib/components/accordion_item.rb +0 -26
  126. data/lib/components/accordion_trigger.rb +0 -45
  127. data/lib/components/alert.rb +0 -40
  128. data/lib/components/alert_description.rb +0 -11
  129. data/lib/components/alert_dialog.rb +0 -60
  130. data/lib/components/alert_dialog_action.rb +0 -22
  131. data/lib/components/alert_dialog_action_to.rb +0 -40
  132. data/lib/components/alert_dialog_cancel.rb +0 -22
  133. data/lib/components/alert_dialog_content.rb +0 -40
  134. data/lib/components/alert_dialog_description.rb +0 -22
  135. data/lib/components/alert_dialog_footer.rb +0 -11
  136. data/lib/components/alert_dialog_header.rb +0 -11
  137. data/lib/components/alert_dialog_title.rb +0 -22
  138. data/lib/components/alert_dialog_trigger.rb +0 -50
  139. data/lib/components/alert_title.rb +0 -11
  140. data/lib/components/avatar.rb +0 -31
  141. data/lib/components/avatar_fallback.rb +0 -21
  142. data/lib/components/avatar_image.rb +0 -19
  143. data/lib/components/badge.rb +0 -30
  144. data/lib/components/breadcrumb.rb +0 -51
  145. data/lib/components/breadcrumb_ellipsis.rb +0 -23
  146. data/lib/components/breadcrumb_item.rb +0 -11
  147. data/lib/components/breadcrumb_link.rb +0 -7
  148. data/lib/components/breadcrumb_page.rb +0 -21
  149. data/lib/components/breadcrumb_separator.rb +0 -26
  150. data/lib/components/button.rb +0 -53
  151. data/lib/components/card.rb +0 -31
  152. data/lib/components/card_content.rb +0 -11
  153. data/lib/components/card_description.rb +0 -11
  154. data/lib/components/card_footer.rb +0 -11
  155. data/lib/components/card_header.rb +0 -11
  156. data/lib/components/card_title.rb +0 -11
  157. data/lib/components/collapsible.rb +0 -31
  158. data/lib/components/collapsible_content.rb +0 -24
  159. data/lib/components/collapsible_trigger.rb +0 -50
  160. data/lib/components/combobox.rb +0 -57
  161. data/lib/components/combobox_item.rb +0 -9
  162. data/lib/components/date_picker.rb +0 -94
  163. data/lib/components/date_range_picker.rb +0 -113
  164. data/lib/components/dialog.rb +0 -52
  165. data/lib/components/dialog_close.rb +0 -42
  166. data/lib/components/dialog_content.rb +0 -54
  167. data/lib/components/dialog_description.rb +0 -22
  168. data/lib/components/dialog_footer.rb +0 -11
  169. data/lib/components/dialog_header.rb +0 -11
  170. data/lib/components/dialog_title.rb +0 -22
  171. data/lib/components/dialog_trigger.rb +0 -50
  172. data/lib/components/dropdown_menu.rb +0 -50
  173. data/lib/components/dropdown_menu_content.rb +0 -52
  174. data/lib/components/dropdown_menu_item.rb +0 -56
  175. data/lib/components/dropdown_menu_item_to.rb +0 -28
  176. data/lib/components/dropdown_menu_label.rb +0 -11
  177. data/lib/components/dropdown_menu_separator.rb +0 -20
  178. data/lib/components/dropdown_menu_trigger.rb +0 -57
  179. data/lib/components/form.rb +0 -59
  180. data/lib/components/form_hint.rb +0 -17
  181. data/lib/components/hover_card.rb +0 -33
  182. data/lib/components/hover_card_content.rb +0 -32
  183. data/lib/components/hover_card_trigger.rb +0 -44
  184. data/lib/components/input.rb +0 -32
  185. data/lib/components/label.rb +0 -14
  186. data/lib/components/loading_button.rb +0 -21
  187. data/lib/components/pagination.rb +0 -38
  188. data/lib/components/pagination_ellipsis.rb +0 -24
  189. data/lib/components/pagination_link.rb +0 -34
  190. data/lib/components/pagination_next.rb +0 -32
  191. data/lib/components/pagination_previous.rb +0 -32
  192. data/lib/components/popover.rb +0 -34
  193. data/lib/components/popover_content.rb +0 -40
  194. data/lib/components/popover_trigger.rb +0 -51
  195. data/lib/components/radio_group.rb +0 -62
  196. data/lib/components/radio_group_item.rb +0 -66
  197. data/lib/components/select.rb +0 -184
  198. data/lib/components/select_content.rb +0 -64
  199. data/lib/components/select_group.rb +0 -23
  200. data/lib/components/select_item.rb +0 -59
  201. data/lib/components/select_label.rb +0 -24
  202. data/lib/components/select_trigger.rb +0 -56
  203. data/lib/components/sheet.rb +0 -53
  204. data/lib/components/sheet_close.rb +0 -42
  205. data/lib/components/sheet_content.rb +0 -65
  206. data/lib/components/sheet_description.rb +0 -22
  207. data/lib/components/sheet_footer.rb +0 -11
  208. data/lib/components/sheet_header.rb +0 -11
  209. data/lib/components/sheet_title.rb +0 -22
  210. data/lib/components/sheet_trigger.rb +0 -50
  211. data/lib/components/sidebar.rb +0 -108
  212. data/lib/components/sidebar_container.rb +0 -11
  213. data/lib/components/sidebar_content.rb +0 -11
  214. data/lib/components/sidebar_footer.rb +0 -11
  215. data/lib/components/sidebar_group.rb +0 -11
  216. data/lib/components/sidebar_group_content.rb +0 -11
  217. data/lib/components/sidebar_group_label.rb +0 -16
  218. data/lib/components/sidebar_header.rb +0 -11
  219. data/lib/components/sidebar_inset.rb +0 -15
  220. data/lib/components/sidebar_menu.rb +0 -11
  221. data/lib/components/sidebar_menu_button.rb +0 -61
  222. data/lib/components/sidebar_menu_item.rb +0 -9
  223. data/lib/components/sidebar_menu_sub.rb +0 -14
  224. data/lib/components/sidebar_menu_sub_button.rb +0 -48
  225. data/lib/components/sidebar_menu_sub_item.rb +0 -9
  226. data/lib/components/sidebar_trigger.rb +0 -40
  227. data/lib/components/switch.rb +0 -66
  228. data/lib/components/table.rb +0 -75
  229. data/lib/components/table_body.rb +0 -11
  230. data/lib/components/table_caption.rb +0 -11
  231. data/lib/components/table_cell.rb +0 -11
  232. data/lib/components/table_footer.rb +0 -11
  233. data/lib/components/table_head.rb +0 -14
  234. data/lib/components/table_header.rb +0 -11
  235. data/lib/components/table_row.rb +0 -11
  236. data/lib/components/tabs.rb +0 -38
  237. data/lib/components/tabs_content.rb +0 -35
  238. data/lib/components/tabs_list.rb +0 -23
  239. data/lib/components/tabs_trigger.rb +0 -45
  240. data/lib/components/textarea.rb +0 -28
  241. data/lib/components/toast.rb +0 -101
  242. data/lib/components/toast_action.rb +0 -39
  243. data/lib/components/toast_action_to.rb +0 -28
  244. data/lib/components/toast_content.rb +0 -11
  245. data/lib/components/toast_description.rb +0 -11
  246. data/lib/components/toast_title.rb +0 -11
  247. data/lib/components/tooltip.rb +0 -34
  248. data/lib/components/tooltip_content.rb +0 -39
  249. data/lib/components/tooltip_trigger.rb +0 -48
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormRadioGroup < Base
5
+ include FormHelpers
6
+
7
+ def initialize(
8
+ method = nil,
9
+ model: false,
10
+ object_name: nil,
11
+ collection: [],
12
+ value_method: nil,
13
+ text_method: nil,
14
+ value: nil,
15
+ name: nil,
16
+ id: nil,
17
+ label: nil,
18
+ error: nil,
19
+ hint: nil,
20
+ disabled_items: nil,
21
+ **attributes
22
+ )
23
+ @method = method
24
+ @model = model
25
+ @object_name = object_name
26
+
27
+ @collection = if collection.first&.is_a?(Hash)
28
+ convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
29
+ else
30
+ collection
31
+ end
32
+
33
+ @value_method = value_method
34
+ @text_method = text_method
35
+ @value = default_value(value, method)
36
+ @name = name
37
+ @id = id
38
+ @label = label
39
+ @error = default_error(error, method)
40
+ @hint = hint
41
+ @disabled_items = disabled_items
42
+ @aria_id = "form-field-#{SecureRandom.hex(5)}"
43
+ super(**attributes)
44
+ end
45
+
46
+ def aria_attributes
47
+ attrs = super
48
+ attrs[:labelledby] = "#{@aria_id}-label"
49
+ attrs
50
+ end
51
+
52
+ def label_attributes(use_label_styles: false, **attributes)
53
+ attrs = super(use_label_styles: use_label_styles, **attributes)
54
+ attrs[:id] = "#{@aria_id}-label"
55
+ attrs
56
+ end
57
+
58
+ def radio(**attributes)
59
+ @radio_attributes = attributes
60
+ nil
61
+ end
62
+
63
+ def radio_label(**attributes)
64
+ @radio_label_attributes = attributes
65
+ nil
66
+ end
67
+
68
+ def view_template(&)
69
+ vanish(&)
70
+
71
+ @id ||= field_id(@object_name, @method)
72
+ @name ||= field_name(@object_name, @method)
73
+
74
+ div(class: "space-y-2", data: label_and_hint_container_attributes) do
75
+ render_label(&)
76
+
77
+ RadioGroup(
78
+ name: @name,
79
+ id: @id,
80
+ value: @value,
81
+ aria: aria_attributes,
82
+ **@attributes,
83
+ ) do |c|
84
+ c.items(
85
+ @collection,
86
+ value_method: @value_method,
87
+ text_method: @text_method,
88
+ disabled_items: @disabled_items,
89
+ id_prefix: @id,
90
+ ) do
91
+ if @radio_attributes
92
+ c.radio(**@radio_attributes)
93
+ end
94
+
95
+ if @radio_label_attributes
96
+ c.label(**@radio_label_attributes)
97
+ end
98
+ end
99
+ end
100
+
101
+ render_hint(&)
102
+ render_error
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormSelect < Base
5
+ include FormHelpers
6
+
7
+ def initialize(
8
+ method = nil,
9
+ model: false,
10
+ object_name: nil,
11
+ collection: [],
12
+ value_method: nil,
13
+ text_method: nil,
14
+ value: nil,
15
+ name: nil,
16
+ id: nil,
17
+ label: nil,
18
+ error: nil,
19
+ hint: nil,
20
+ disabled_items: nil,
21
+ **attributes
22
+ )
23
+ @method = method
24
+ @model = model
25
+ @object_name = object_name
26
+
27
+ @collection = if collection.first&.is_a?(Hash)
28
+ convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
29
+ else
30
+ collection
31
+ end
32
+
33
+ @value_method = value_method
34
+ @text_method = text_method
35
+ @value = default_value(value, method)
36
+ @name = name
37
+ @id = id
38
+ @label = label
39
+ @error = default_error(error, method)
40
+ @hint = hint
41
+ @disabled_items = disabled_items
42
+ @aria_id = "form-field-#{SecureRandom.hex(5)}"
43
+ super(**attributes)
44
+ end
45
+
46
+ def view_template(&)
47
+ vanish(&)
48
+
49
+ @id ||= field_id(@object_name, @method)
50
+ @name ||= field_name(@object_name, @method)
51
+
52
+ div(class: "space-y-2", data: label_and_hint_container_attributes) do
53
+ render_label(&)
54
+
55
+ Select(id: @id, name: @name, value: @value, aria: aria_attributes, **@attributes) do |s|
56
+ s.items(@collection, value_method: @value_method, text_method: @text_method, disabled_items: @disabled_items)
57
+ end
58
+
59
+ render_hint(&)
60
+ render_error
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormSlider < Base
5
+ include FormHelpers
6
+
7
+ def initialize(
8
+ method,
9
+ end_method = nil,
10
+ model: false,
11
+ object_name: nil,
12
+ range: false,
13
+ value: nil,
14
+ name: nil,
15
+ id: nil,
16
+ label: nil,
17
+ error: nil,
18
+ hint: nil,
19
+ **attributes
20
+ )
21
+ @method = method
22
+ @end_method = end_method
23
+ @model = model
24
+ @object_name = object_name
25
+ @range = range
26
+
27
+ if @range
28
+ @value = [
29
+ default_value(value ? value[0] : nil, method),
30
+ default_value(value ? value[1] : nil, end_method),
31
+ ]
32
+ @error = [
33
+ default_error(error ? error[0] : nil, method),
34
+ default_error(error ? error[1] : nil, end_method),
35
+ ].compact
36
+ else
37
+ @value = default_value(value, method)
38
+ @error = default_error(error, method)
39
+ end
40
+
41
+ @name = name
42
+ @id = id
43
+ @label = label
44
+ @hint = hint
45
+ @aria_id = "form-field-#{SecureRandom.hex(5)}"
46
+ super(**attributes)
47
+ end
48
+
49
+ def render_label(&)
50
+ # It's currently not possible to separate the content of the yield in Phlex.
51
+ # So we use Javascript to remove the duplicated hint or label.
52
+ if @yield_label && @yield_hint
53
+ div(data: { remove_hint: true }, &)
54
+ elsif @yield_label
55
+ yield
56
+ elsif @label
57
+ attrs = label_attributes(use_label_styles: false)
58
+ Label(**attrs) { @label }
59
+ elsif @label != false
60
+ attrs = label_attributes(use_label_styles: true)
61
+ label_text = @range ? [@method, @end_method].to_sentence : @method
62
+ rails_label(@object_name, label_text, nil, **attrs)
63
+ end
64
+ end
65
+
66
+ def view_template(&)
67
+ vanish(&)
68
+
69
+ @id ||= field_id(@object_name, @method)
70
+
71
+ if @name.blank?
72
+ @name =
73
+ if @range
74
+ [
75
+ field_name(@object_name, @method),
76
+ field_name(@object_name, @end_method),
77
+ ]
78
+ else
79
+ field_name(@object_name, @method)
80
+ end
81
+ end
82
+
83
+ div(class: "space-y-2", data: label_and_hint_container_attributes) do
84
+ render_label(&)
85
+ Slider(id: @id, name: @name, value: @value, aria: aria_attributes, range: @range, **@attributes)
86
+ render_hint(&)
87
+ render_error
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormSwitch < Base
5
+ include FormHelpers
6
+
7
+ def initialize(
8
+ method = nil,
9
+ model: false,
10
+ object_name: nil,
11
+ value: nil,
12
+ name: nil,
13
+ id: nil,
14
+ label: nil,
15
+ error: nil,
16
+ hint: nil,
17
+ checked: nil,
18
+ **attributes
19
+ )
20
+ @method = method
21
+ @model = model
22
+ @object_name = object_name
23
+ @value = value || "1"
24
+ @name = name
25
+ @id = id
26
+ @label = label
27
+ @error = default_error(error, method)
28
+ @hint = hint
29
+ @aria_id = "form-field-#{SecureRandom.hex(5)}"
30
+ @checked = default_checked(checked, method)
31
+ super(**attributes)
32
+ end
33
+
34
+ def label_attributes(use_label_styles: false, **attributes)
35
+ attributes[:class] = [
36
+ use_label_styles ? Label.new.class_variants : nil,
37
+ attributes[:class],
38
+ ].compact.join(" ")
39
+ attributes[:for] ||= @id
40
+ attributes
41
+ end
42
+
43
+ def view_template(&)
44
+ vanish(&)
45
+
46
+ @id ||= field_id(@object_name, @method)
47
+ @name ||= field_name(@object_name, @method)
48
+
49
+ div(class: "space-y-2", data: label_and_hint_container_attributes) do
50
+ div(class: "flex items-center gap-2") do
51
+ Switch(
52
+ id: @id,
53
+ name: @name,
54
+ value: @value,
55
+ checked: @checked,
56
+ aria: aria_attributes,
57
+ disabled: @disabled,
58
+ **@attributes,
59
+ )
60
+ render_label(&)
61
+ end
62
+ render_hint(&)
63
+ render_error
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormTextarea < Base
5
+ include FormHelpers
6
+
7
+ def initialize(
8
+ method = nil,
9
+ model: false,
10
+ object_name: nil,
11
+ value: nil,
12
+ name: nil,
13
+ id: nil,
14
+ label: nil,
15
+ error: nil,
16
+ hint: nil,
17
+ **attributes
18
+ )
19
+ @method = method
20
+ @model = model
21
+ @object_name = object_name
22
+ @value = default_value(value, method)
23
+ @name = name
24
+ @id = id
25
+ @label = label
26
+ @error = default_error(error, method)
27
+ @hint = hint
28
+ @aria_id = "form-field-#{SecureRandom.hex(5)}"
29
+ super(**attributes)
30
+ end
31
+
32
+ def view_template(&)
33
+ vanish(&)
34
+
35
+ @id ||= field_id(@object_name, @method)
36
+ @name ||= field_name(@object_name, @method)
37
+
38
+ div(class: "space-y-2", data: label_and_hint_container_attributes) do
39
+ render_label(&)
40
+
41
+ # Wrap textarea in div to ensure spacing is correct as there were instances where certain browser extensions
42
+ # injecting html before/after the textarea causing the spacing to go weird.
43
+ div do
44
+ Textarea(
45
+ type: @type,
46
+ id: @id,
47
+ name: @name,
48
+ value: @value,
49
+ aria: aria_attributes,
50
+ **@attributes,
51
+ )
52
+ end
53
+
54
+ render_hint(&)
55
+ render_error
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "form/form_helpers"
4
+ require_relative "form/form_input"
5
+ require_relative "form/form_hint"
6
+ require_relative "form/form_error"
7
+ require_relative "form/form_textarea"
8
+ require_relative "form/form_checkbox"
9
+ require_relative "form/form_switch"
10
+ require_relative "form/form_checkbox_group"
11
+ require_relative "form/form_date_picker"
12
+ require_relative "form/form_date_range_picker"
13
+ require_relative "form/form_select"
14
+ require_relative "form/form_radio_group"
15
+ require_relative "form/form_slider"
16
+
17
+ module ShadcnPhlexcomponents
18
+ class Form < Base
19
+ include Phlex::Rails::Helpers::FormWith
20
+
21
+ def initialize(model: false, scope: nil, url: nil, format: nil, loading: false, **options)
22
+ @model = model
23
+ @scope = scope
24
+ @url = url
25
+ @format = format
26
+ @options = options
27
+ @loading = loading
28
+ @object_name = model ? model.to_model.model_name.param_key : nil
29
+ end
30
+
31
+ def input(method = nil, **attributes, &)
32
+ FormInput(method, model: @model, object_name: @object_name, **attributes, &)
33
+ end
34
+
35
+ def textarea(method = nil, **attributes, &)
36
+ FormTextarea(method, model: @model, object_name: @object_name, **attributes, &)
37
+ end
38
+
39
+ def checkbox(method = nil, **attributes, &)
40
+ FormCheckbox(method, model: @model, object_name: @object_name, **attributes, &)
41
+ end
42
+
43
+ def switch(method = nil, **attributes, &)
44
+ FormSwitch(method, model: @model, object_name: @object_name, **attributes, &)
45
+ end
46
+
47
+ def checkbox_group(method = nil, collection = [], value_method:, text_method:, **attributes, &)
48
+ FormCheckboxGroup(
49
+ method,
50
+ model: @model,
51
+ object_name: @object_name,
52
+ collection: collection,
53
+ value_method: value_method,
54
+ text_method: text_method,
55
+ **attributes,
56
+ &
57
+ )
58
+ end
59
+
60
+ def radio_group(method = nil, collection = [], value_method:, text_method:, **attributes, &)
61
+ FormRadioGroup(
62
+ method,
63
+ model: @model,
64
+ object_name: @object_name,
65
+ collection: collection,
66
+ value_method: value_method,
67
+ text_method: text_method,
68
+ **attributes,
69
+ &
70
+ )
71
+ end
72
+
73
+ def select(method = nil, collection = [], value_method:, text_method:, **attributes, &)
74
+ FormSelect(
75
+ method,
76
+ model: @model,
77
+ object_name: @object_name,
78
+ collection: collection,
79
+ value_method: value_method,
80
+ text_method: text_method,
81
+ **attributes,
82
+ &
83
+ )
84
+ end
85
+
86
+ def date_picker(method = nil, **attributes, &)
87
+ FormDatePicker(method, model: @model, object_name: @object_name, **attributes, &)
88
+ end
89
+
90
+ def date_range_picker(method = nil, end_method = nil, **attributes, &)
91
+ FormDateRangePicker(method, end_method, model: @model, object_name: @object_name, **attributes, &)
92
+ end
93
+
94
+ def slider(method = nil, end_method = nil, **attributes, &)
95
+ FormSlider(method, end_method, model: @model, object_name: @object_name, **attributes, &)
96
+ end
97
+
98
+ def submit(value = nil, variant: :default, **attributes, &)
99
+ if @loading
100
+ LoadingButton(variant: variant, type: :submit, **attributes) do
101
+ if block_given?
102
+ yield
103
+ else
104
+ value || submit_default_value
105
+ end
106
+ end
107
+ else
108
+ Button(variant: variant, type: :submit, **attributes) do
109
+ if block_given?
110
+ yield
111
+ else
112
+ value || submit_default_value
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ def view_template(&)
119
+ @form_class = @options[:class]
120
+ @options[:class] = "#{@options[:class]} #{"group" if @loading}"
121
+ # rubocop:disable Style/ExplicitBlockArgument
122
+ form_with(model: @model, scope: @scope, url: @url, format: @format, **@options) do
123
+ yield
124
+ end
125
+ # rubocop:enable Style/ExplicitBlockArgument
126
+ end
127
+
128
+ # Follows rails f.submit
129
+ # https://github.com/rails/rails/blob/3235827585d87661942c91bc81f64f56d710f0b2/actionview/lib/action_view/helpers/form_helper.rb#L2681-L2706
130
+ def submit_default_value
131
+ object = @model.respond_to?(:to_model) ? @model.to_model : nil
132
+ key = if object
133
+ object.persisted? ? :update : :create
134
+ else
135
+ :submit
136
+ end
137
+
138
+ model = if object.respond_to?(:model_name)
139
+ object.model_name.human
140
+ else
141
+ @object_name.to_s.humanize
142
+ end
143
+
144
+ defaults = []
145
+ # Object is a model and it is not overwritten by as and scope option.
146
+ defaults << if object.respond_to?(:model_name) && @object_name.to_s == model.downcase
147
+ :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
148
+ else
149
+ :"helpers.submit.#{@object_name}.#{key}"
150
+ end
151
+ defaults << :"helpers.submit.#{key}"
152
+ defaults << "#{key.to_s.humanize} #{model}"
153
+
154
+ I18n.t(defaults.shift, model: model, default: defaults)
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class HoverCard < Base
5
+ class_variants(base: "inline-block max-w-fit")
6
+
7
+ def initialize(open: false, **attributes)
8
+ @open = open
9
+ super(**attributes)
10
+ end
11
+
12
+ def content(**attributes, &)
13
+ HoverCardContent(**attributes, &)
14
+ end
15
+
16
+ def trigger(**attributes, &)
17
+ HoverCardTrigger(**attributes, &)
18
+ end
19
+
20
+ def default_attributes
21
+ {
22
+ data: {
23
+ controller: "hover-card",
24
+ hover_card_is_open_value: @open.to_s,
25
+ },
26
+ }
27
+ end
28
+
29
+ def view_template(&)
30
+ div(**@attributes, &)
31
+ end
32
+ end
33
+
34
+ class HoverCardTrigger < Base
35
+ def initialize(as_child: false, **attributes)
36
+ @as_child = as_child
37
+ super(**attributes)
38
+ end
39
+
40
+ def view_template(&)
41
+ if @as_child
42
+ content = capture(&)
43
+ element = find_as_child(content.to_s)
44
+ vanish(&)
45
+ merged_attributes = merged_as_child_attributes(element, @attributes)
46
+
47
+ send(element.name, **merged_attributes) do
48
+ sanitize_as_child(element.children.to_s)
49
+ end
50
+ else
51
+ div(**@attributes, &)
52
+ end
53
+ end
54
+
55
+ def default_attributes
56
+ {
57
+ id: @id,
58
+ role: "button",
59
+ data: {
60
+ as_child: @as_child.to_s,
61
+ hover_card_target: "trigger",
62
+ action: <<~HEREDOC,
63
+ focus->hover-card#open
64
+ blur->hover-card#close
65
+ click->hover-card#open
66
+ HEREDOC
67
+ },
68
+ }
69
+ end
70
+ end
71
+
72
+ class HoverCardContent < Base
73
+ class_variants(
74
+ base: <<~HEREDOC,
75
+ bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out
76
+ data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
77
+ data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
78
+ data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64
79
+ origin-(--radix-popper-transform-origin) rounded-md border p-4 shadow-md outline-hidden
80
+ HEREDOC
81
+ )
82
+
83
+ def initialize(side: :bottom, align: :center, **attributes)
84
+ @side = side
85
+ @align = align
86
+ super(**attributes)
87
+ end
88
+
89
+ def view_template(&)
90
+ div(
91
+ class: "hidden fixed top-0 left-0 w-max z-50",
92
+ data: { hover_card_target: "contentContainer" },
93
+ ) do
94
+ div(**@attributes, &)
95
+ end
96
+ end
97
+
98
+ def default_attributes
99
+ {
100
+ tabindex: -1,
101
+ data: {
102
+ side: @side,
103
+ align: @align,
104
+ hover_card_target: "content",
105
+ action: "mouseover->hover-card#open mouseout->hover-card#close",
106
+ },
107
+ }
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class Input < Base
5
+ class_variants(
6
+ base: <<~HEREDOC,
7
+ file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground
8
+ dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base
9
+ shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent
10
+ file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm
11
+ focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]
12
+ aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive
13
+ HEREDOC
14
+ )
15
+
16
+ def initialize(type: :text, **attributes)
17
+ @type = type
18
+ super(**attributes)
19
+ end
20
+
21
+ def default_attributes
22
+ {
23
+ type: @type,
24
+ }
25
+ end
26
+
27
+ def view_template(&)
28
+ input(**@attributes, &)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class Label < Base
5
+ class_variants(
6
+ base: <<~HEREDOC,
7
+ flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none
8
+ group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50
9
+ HEREDOC
10
+ )
11
+
12
+ def view_template(&)
13
+ label(**@attributes, &)
14
+ end
15
+ end
16
+ end