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,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