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