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,351 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class Command < Base
5
+ class_variants(base: "inline-block max-w-fit")
6
+
7
+ MODIFIER_KEYS = [
8
+ :ctrl,
9
+ :alt,
10
+ :shift,
11
+ ]
12
+
13
+ def initialize(modifier_key: nil, shortcut_key: nil, search_path: nil, open: false, **attributes)
14
+ if modifier_key && !MODIFIER_KEYS.include?(modifier_key)
15
+ raise ArgumentError, "Expected one of #{MODIFIER_KEYS} for \"modifier_key\", got #{modifier_key}"
16
+ end
17
+
18
+ @open = open
19
+ @modifier_key = modifier_key
20
+ @shortcut_key = shortcut_key
21
+ @search_path = search_path
22
+ @aria_id = "command-#{SecureRandom.hex(5)}"
23
+ super(**attributes)
24
+ end
25
+
26
+ def trigger(**attributes, &)
27
+ CommandTrigger(modifier_key: @modifier_key, shortcut_key: @shortcut_key, aria_id: @aria_id, **attributes, &)
28
+ end
29
+
30
+ def content(**attributes, &)
31
+ CommandContent(aria_id: @aria_id, **attributes, &)
32
+ end
33
+
34
+ def item(**attributes, &)
35
+ CommandItem(aria_id: @aria_id, **attributes, &)
36
+ end
37
+
38
+ def label(**attributes, &)
39
+ CommandLabel(**attributes, &)
40
+ end
41
+
42
+ def group(**attributes, &)
43
+ CommandGroup(aria_id: @aria_id, **attributes, &)
44
+ end
45
+
46
+ def empty(**attributes, &)
47
+ CommandEmpty(**attributes, &)
48
+ end
49
+
50
+ def default_attributes
51
+ {
52
+ data: {
53
+ controller: "command",
54
+ modifier_key: @modifier_key,
55
+ shortcut_key: @shortcut_key,
56
+ search_path: @search_path,
57
+ command_is_open_value: @open.to_s,
58
+ },
59
+ }
60
+ end
61
+
62
+ def view_template(&)
63
+ div(**@attributes, &)
64
+ end
65
+ end
66
+
67
+ class CommandTrigger < Base
68
+ def initialize(modifier_key: nil, shortcut_key: nil, aria_id: nil, **attributes)
69
+ @modifier_key = modifier_key
70
+ @shortcut_key = shortcut_key
71
+ @aria_id = aria_id
72
+ super(**attributes)
73
+ end
74
+
75
+ def class_variants(**args)
76
+ Button.new.class_variants(
77
+ variant: :secondary,
78
+ class: <<~HEREDOC,
79
+ bg-surface text-surface-foreground/60 dark:bg-card relative h-8 w-full justify-start pl-2.5 font-normal
80
+ shadow-none sm:pr-12 md:w-40 lg:w-56 xl:w-64 #{args[:class]}
81
+ HEREDOC
82
+ )
83
+ end
84
+
85
+ def default_attributes
86
+ {
87
+ role: "button",
88
+ aria: {
89
+ haspopup: "dialog",
90
+ expanded: "false",
91
+ controls: "#{@aria_id}-content",
92
+ },
93
+ data: {
94
+ action: "click->command#open",
95
+ command_target: "trigger",
96
+ as_child: @as_child.to_s,
97
+ },
98
+ }
99
+ end
100
+
101
+ def view_template(&)
102
+ button(**@attributes) do
103
+ yield
104
+
105
+ if @modifier_key || @shortcut_key
106
+ span(class: "absolute top-1.5 right-1.5 hidden gap-1 sm:flex") do
107
+ if @modifier_key
108
+ CommandKbd(class: "capitalize", data: { command_target: "modifierKey" }) { @modifier_key }
109
+ end
110
+
111
+ if @shortcut_key
112
+ CommandKbd(class: "capitalize") { @shortcut_key }
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ class CommandContent < Base
121
+ class_variants(
122
+ base: <<~HEREDOC,
123
+ bg-background bg-clip-padding dark:bg-neutral-900 dark:ring-neutral-800 data-[state=closed]:animate-out#{" "}
124
+ data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0
125
+ data-[state=open]:zoom-in-95 duration-200 fixed gap-4 grid left-[50%] max-w-[calc(100%-2rem)] p-2 pb-11 ring-4 ring-neutral-200/80
126
+ rounded-xl shadow-2xl sm:max-w-lg top-[50%] translate-x-[-50%] translate-y-[-50%] w-full z-50 pointer-events-auto
127
+ HEREDOC
128
+ )
129
+
130
+ def initialize(search_placeholder: "Search...", aria_id: nil, **attributes)
131
+ @search_placeholder = search_placeholder
132
+ @aria_id = aria_id
133
+ super(**attributes)
134
+ end
135
+
136
+ def default_attributes
137
+ {
138
+ id: "#{@aria_id}-content",
139
+ tabindex: -1,
140
+ role: "dialog",
141
+ aria: {
142
+ describedby: "#{@aria_id}-description",
143
+ labelledby: "#{@aria_id}-title",
144
+ },
145
+ data: {
146
+ command_target: "content",
147
+ state: "closed",
148
+ action: <<~HEREDOC,
149
+ command:click:outside->command#close
150
+ keydown.up->command#highlightItem:prevent
151
+ keydown.down->command#highlightItem:prevent
152
+ keydown.enter->command#select
153
+ HEREDOC
154
+
155
+ },
156
+ }
157
+ end
158
+
159
+ def view_template(&)
160
+ @class = @attributes.delete(:class)
161
+
162
+ div(class: "#{@class} hidden", **@attributes) do
163
+ div(class: "text-popover-foreground flex h-full w-full flex-col overflow-hidden bg-transparent") do
164
+ div(class: "sr-only") do
165
+ h2(id: "#{@aria_id}-title") { @search_placeholder }
166
+ p(id: "#{@aria_id}-description") { "Search for a command to run..." }
167
+ end
168
+
169
+ label(
170
+ class: "sr-only",
171
+ id: "#{@aria_id}-search-label",
172
+ for: "#{@aria_id}-search",
173
+ ) { @search_placeholder }
174
+
175
+ div(class: "flex h-9 items-center gap-2 border px-3 bg-input/50 border-input rounded-md") do
176
+ icon("search", class: "size-4 shrink-0 opacity-50")
177
+
178
+ input(
179
+ class: "placeholder:text-muted-foreground flex w-full rounded-md bg-transparent py-3 text-sm
180
+ outline-hidden disabled:cursor-not-allowed disabled:opacity-50 h-9",
181
+ id: "#{@aria_id}-search",
182
+ placeholder: @search_placeholder,
183
+ type: :text,
184
+ autocomplete: "off",
185
+ autocorrect: "off",
186
+ role: "combobox",
187
+ spellcheck: "false",
188
+ aria: {
189
+ autocomplete: "list",
190
+ expanded: "false",
191
+ controls: "#{@aria_id}-list",
192
+ labelledby: "#{@aria_id}-search-label",
193
+ },
194
+ data: {
195
+ command_target: "searchInput",
196
+ action: "input->command#search",
197
+ },
198
+ )
199
+ end
200
+
201
+ div(class: "p-1 max-h-80 min-h-80 overflow-y-auto", id: "#{@aria_id}-list", data: { command_target: "list" }) do
202
+ div(data: { command_target: "results" }, &)
203
+ end
204
+
205
+ CommandFooter()
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ class CommandItem < Base
212
+ class_variants(
213
+ base: <<~HEREDOC,
214
+ data-[highlighted=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex
215
+ cursor-default items-center gap-2 px-3 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none
216
+ data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
217
+ data-[highlighted=true]:border-input data-[highlighted=true]:bg-input/50 h-9 rounded-md border border-transparent
218
+ font-medium
219
+ HEREDOC
220
+ )
221
+
222
+ def initialize(value: nil, aria_id: nil, **attributes)
223
+ @value = value
224
+ @aria_id = aria_id
225
+ super(**attributes)
226
+ end
227
+
228
+ def view_template(&)
229
+ div(**@attributes, &)
230
+ end
231
+
232
+ def default_attributes
233
+ {
234
+ role: "option",
235
+ tabindex: -1,
236
+ aria: {
237
+ labelledby: @aria_labelledby,
238
+ },
239
+ data: {
240
+ highlighted: "false",
241
+ disabled: @disabled,
242
+ value: @value,
243
+ action: <<~HEREDOC,
244
+ click->command#select
245
+ mouseover->command#highlightItem
246
+ HEREDOC
247
+ command_target: "item",
248
+ },
249
+ }
250
+ end
251
+ end
252
+
253
+ class CommandLabel < Base
254
+ class_variants(base: "text-muted-foreground text-xs p-3 pb-1 text-xs font-medium")
255
+
256
+ def initialize(aria_id: nil, **attributes)
257
+ @aria_id = aria_id
258
+ super(**attributes)
259
+ end
260
+
261
+ def view_template(&)
262
+ div(**@attributes, &)
263
+ end
264
+
265
+ def default_attributes
266
+ {
267
+ data: {
268
+ command_target: "label",
269
+ },
270
+ }
271
+ end
272
+ end
273
+
274
+ class CommandGroup < Base
275
+ class_variants(base: "scroll-mt-16")
276
+
277
+ def initialize(aria_id:, **attributes)
278
+ @aria_id = aria_id
279
+ super(**attributes)
280
+ end
281
+
282
+ def view_template(&)
283
+ div(**@attributes, &)
284
+ end
285
+
286
+ def default_attributes
287
+ {
288
+ role: "group",
289
+ aria: {
290
+ labelledby: "#{@aria_id}-group-#{SecureRandom.hex(5)}",
291
+ },
292
+ data: {
293
+ command_target: "group",
294
+ },
295
+ }
296
+ end
297
+ end
298
+
299
+ class CommandEmpty < Base
300
+ class_variants(base: "py-6 text-center text-sm hidden")
301
+
302
+ def default_attributes
303
+ {
304
+ role: "presentation",
305
+ data: { command_target: "empty" },
306
+ }
307
+ end
308
+
309
+ def view_template(&)
310
+ if block_given?
311
+ div(**@attributes, &)
312
+ else
313
+ div(**@attributes) { "No results found" }
314
+ end
315
+ end
316
+ end
317
+
318
+ class CommandKbd < Base
319
+ class_variants(
320
+ base: <<~HEREDOC,
321
+ bg-background text-muted-foreground pointer-events-none flex h-5 items-center justify-center gap-1 rounded
322
+ border px-1 font-sans text-[0.7rem] font-medium select-none [&_svg:not([class*='size-'])]:size-3
323
+ HEREDOC
324
+ )
325
+
326
+ def view_template(&)
327
+ kbd(**@attributes, &)
328
+ end
329
+ end
330
+
331
+ class CommandFooter < Base
332
+ class_variants(
333
+ base: <<~HEREDOC,
334
+ text-muted-foreground absolute inset-x-0 bottom-0 z-20 flex h-10 items-center gap-2 rounded-b-xl border-t#{" "}
335
+ border-t-neutral-100 bg-neutral-50 px-4 text-xs font-medium dark:border-t-neutral-700 dark:bg-neutral-800
336
+ HEREDOC
337
+ )
338
+
339
+ def view_template
340
+ div(**@attributes) do
341
+ div(class: "flex items-center gap-2") do
342
+ CommandKbd do
343
+ icon("corner-down-left")
344
+ end
345
+
346
+ plain("Go to Page")
347
+ end
348
+ end
349
+ end
350
+ end
351
+ end
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DatePicker < Base
5
+ class_variants(base: "w-full")
6
+
7
+ class << self
8
+ button = Button.new
9
+
10
+ {
11
+ input_container: <<~HEREDOC,
12
+ focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]
13
+ data-[focus=true]:border-ring data-[focus=true]:ring-ring/50 data-[focus=true]:ring-[3px]
14
+ data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 flex shadow-xs transition-[color,box-shadow]
15
+ rounded-md border bg-transparent dark:bg-input/30 border-input outline-none h-9 flex items-center
16
+ aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive
17
+ HEREDOC
18
+ input: <<~HEREDOC,
19
+ md:text-sm placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground
20
+ flex h-9 w-full min-w-0 text-base outline-none px-3 py-1#{" "}
21
+ HEREDOC
22
+ calendar: {
23
+ calendar: "relative flex flex-col outline-none",
24
+ controls: "absolute z-20 -left-1 -right-1 -top-1.5 flex justify-between items-center pt-1.5 px-1 pointer-events-none box-content",
25
+ grid: "grid gap-4 grid-cols-1 md:grid-cols-2",
26
+ column: "flex flex-col",
27
+ header: "relative flex items-center mb-4",
28
+ headerContent: "grid grid-flow-col gap-x-1 auto-cols-max items-center justify-center px-4 whitespace-pre-wrap grow",
29
+ month: button.class_variants(variant: :outline, size: :sm, class: "text-xs h-7 bg-transparent"),
30
+ year: button.class_variants(variant: :outline, size: :sm, class: "text-xs h-7 bg-transparent"),
31
+ arrowPrev: button.class_variants(variant: :outline, size: :icon, class: "pointer-events-auto size-7 bg-transparent p-0 opacity-50 hover:opacity-100"),
32
+ arrowNext: button.class_variants(variant: :outline, size: :icon, class: "pointer-events-auto size-7 bg-transparent p-0 opacity-50 hover:opacity-100"),
33
+ wrapper: "flex items-center content-center h-full",
34
+ content: "flex flex-col grow h-full",
35
+ months: "grid gap-2 grid-cols-4 items-center grow",
36
+ monthsMonth: button.class_variants(variant: :ghost, class: "aria-[selected=true]:text-primary-foreground aria-[selected=true]:bg-primary aria-[selected=true]:hover:text-primary-foreground aria-[selected=true]:hover:bg-primary"),
37
+ years: "grid gap-2 grid-cols-5 items-center grow",
38
+ yearsYear: button.class_variants(variant: :ghost, class: "aria-[selected=true]:text-primary-foreground aria-[selected=true]:bg-primary aria-[selected=true]:hover:text-primary-foreground aria-[selected=true]:hover:bg-primary"),
39
+ week: "grid mb-2 grid-cols-[repeat(7,_1fr)] justify-items-center items-center text-center",
40
+ weekDay: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
41
+ weekNumbers: "vc-week-numbers",
42
+ weekNumbersTitle: "vc-week-numbers__title",
43
+ weekNumbersContent: "vc-week-numbers__content",
44
+ weekNumber: "vc-week-number",
45
+ dates: "grid gap-y-2 grid-cols-[repeat(7,_1fr)] justify-items-center items-center",
46
+ date: <<~HEREDOC,
47
+ vc-date data-[vc-date-selected]:[&_button]:bg-primary#{" "}
48
+ data-[vc-date-selected]:[&_button]:text-primary-foreground#{" "}
49
+ data-[vc-date-selected]:[&_button]:hover:bg-primary#{" "}
50
+ data-[vc-date-selected]:[&_button]:hover:text-primary-foreground#{" "}
51
+ data-[vc-date-selected]:[&_button]:focus:bg-primary#{" "}
52
+ data-[vc-date-selected]:[&_button]:focus:text-primary-foreground
53
+ data-[vc-date-today]:[&_button]:bg-accent
54
+ data-[vc-date-today]:[&_button]:text-accent-foreground
55
+ data-[vc-date-month=prev]:[&_button]:text-muted-foreground
56
+ data-[vc-date-month=next]:[&_button]:text-muted-foreground
57
+ data-[vc-date-selected='middle']:data-[vc-date-selected]:[&_button]:bg-accent
58
+ data-[vc-date-selected='middle']:data-[vc-date-selected]:[&_button]:text-accent-foreground
59
+ data-[vc-date-hover]:[&_button]:bg-accent data-[vc-date-hover]:[&_button]:text-accent-foreground
60
+ HEREDOC
61
+ dateBtn: button.class_variants(variant: :ghost, class: "size-8 p-0 font-normal aria-[disabled]:text-muted-foreground aria-[disabled]:opacity-50 aria-[disabled]:pointer-events-none"),
62
+ datePopup: "vc-date__popup",
63
+ dateRangeTooltip: "vc-date-range-tooltip",
64
+ time: "vc-time",
65
+ timeContent: "vc-time__content",
66
+ timeHour: "vc-time__hour",
67
+ timeMinute: "vc-time__minute",
68
+ timeKeeping: "vc-time__keeping",
69
+ timeRanges: "vc-time__ranges",
70
+ timeRange: "vc-time__range",
71
+ },
72
+ }
73
+ end
74
+
75
+ def initialize(
76
+ name: nil,
77
+ id: nil,
78
+ value: nil,
79
+ format: "DD/MM/YYYY",
80
+ select_only: false,
81
+ placeholder: nil,
82
+ disabled: false,
83
+ options: {},
84
+ mask: true,
85
+ **attributes
86
+ )
87
+ @name = name
88
+ @id = id
89
+ @value = value&.utc&.iso8601
90
+ @format = format
91
+ @select_only = select_only
92
+ @placeholder = placeholder
93
+ @disabled = disabled
94
+ @mask = mask
95
+ @aria_id = "date-picker-#{SecureRandom.hex(5)}"
96
+ @date_picker_styles = self.class.date_picker_styles
97
+ @options = options.merge(styles: @date_picker_styles[:calendar])
98
+ super(**attributes)
99
+ end
100
+
101
+ def default_attributes
102
+ {
103
+ data: {
104
+ controller: "date-picker",
105
+ value: @value,
106
+ format: @format,
107
+ options: @options.to_json,
108
+ mask: @mask.to_s,
109
+ },
110
+ }
111
+ end
112
+
113
+ def view_template(&)
114
+ div(**@attributes) do
115
+ input(
116
+ type: :hidden,
117
+ name: @name,
118
+ value: @value,
119
+ data: { date_picker_target: "hiddenInput" },
120
+ )
121
+
122
+ if @select_only
123
+ # For select_only date picker, id is passed to button so that clicking on its
124
+ # label will trigger the popover to appear
125
+ DatePickerTrigger(
126
+ disabled: @disabled,
127
+ aria_id: @aria_id,
128
+ select_only: @select_only,
129
+ id: @id,
130
+ placeholder: @placeholder,
131
+ )
132
+ else
133
+ div(class: @date_picker_styles[:input_container], data: { date_picker_target: "inputContainer", disabled: @disabled }) do
134
+ input(
135
+ id: @id,
136
+ placeholder: @placeholder || @format,
137
+ type: :text,
138
+ class: @date_picker_styles[:input],
139
+ disabled: @disabled,
140
+ data: {
141
+ date_picker_target: "input",
142
+ action: "input->date-picker#inputDate
143
+ blur->date-picker#inputBlur
144
+ focus->date-picker#setContainerFocus",
145
+ },
146
+ )
147
+
148
+ DatePickerTrigger(
149
+ disabled: @disabled,
150
+ aria_id: @aria_id,
151
+ select_only: @select_only,
152
+ placeholder: @placeholder,
153
+ )
154
+ end
155
+ end
156
+
157
+ DatePickerContent(aria_id: @aria_id)
158
+ end
159
+ end
160
+ end
161
+
162
+ class DatePickerTrigger < Base
163
+ def initialize(
164
+ select_only: true,
165
+ placeholder: nil,
166
+ aria_id: nil,
167
+ **attributes
168
+ )
169
+ @select_only = select_only
170
+ @placeholder = placeholder
171
+ @aria_id = aria_id
172
+ super(**attributes)
173
+ end
174
+
175
+ def class_variants(**args)
176
+ if @select_only
177
+ Button.new.class_variants(variant: :outline, class: "justify-between w-full data-[placeholder]:data-[has-value=false]:text-muted-foreground #{args[:class]}")
178
+ else
179
+ Button.new.class_variants(variant: :ghost, size: :icon, class: "size-7 mr-1.5 disabled:!opacity-100 #{args[:class]}")
180
+ end
181
+ end
182
+
183
+ def view_template
184
+ if @select_only
185
+ button(type: :button, disabled: @disabled, **@attributes) do
186
+ span(class: "pointer-events-none", data: { "#{stimulus_controller_name}-target" => "triggerText" })
187
+
188
+ icon("calendar", class: "size-5")
189
+ end
190
+ else
191
+ button(type: :button, disabled: @disabled, **@attributes) do
192
+ icon("calendar", class: "size-5")
193
+ end
194
+ end
195
+ end
196
+
197
+ def default_attributes
198
+ {
199
+ aria: {
200
+ haspopup: "dialog",
201
+ expanded: false,
202
+ controls: "#{@aria_id}-content",
203
+ },
204
+ data: {
205
+ placeholder: @placeholder,
206
+ action: "click->#{stimulus_controller_name}#toggle",
207
+ "#{stimulus_controller_name}-target" => "trigger",
208
+ },
209
+ }
210
+ end
211
+
212
+ def stimulus_controller_name
213
+ "date-picker"
214
+ end
215
+ end
216
+
217
+ class DatePickerContent < Base
218
+ def initialize(side: :bottom, align: :start, aria_id: nil, **attributes)
219
+ @side = side
220
+ @align = align
221
+ @aria_id = aria_id
222
+ super(**attributes)
223
+ end
224
+
225
+ def class_variants(**args)
226
+ PopoverContent.new.class_variants(
227
+ class: <<~HEREDOC,
228
+ fixed left-1/2 top-1/2 shadow-lg -translate-x-1/2 -translate-y-1/2 pointer-events-auto w-max
229
+ md:relative md:left-[unset] md:top-[unset] md:shadow-md md:translate-x-[unset] md:translate-y-[unset] md:pointer-events-[unset]
230
+ #{args[:class]}
231
+ HEREDOC
232
+ )
233
+ end
234
+
235
+ def default_attributes
236
+ {
237
+ id: "#{@aria_id}-content",
238
+ tabindex: -1,
239
+ role: "dialog",
240
+ data: {
241
+ side: @side,
242
+ align: @align,
243
+ "#{stimulus_controller_name}-target" => "content",
244
+ action: "#{stimulus_controller_name}:click:outside->#{stimulus_controller_name}#clickOutside",
245
+ },
246
+ }
247
+ end
248
+
249
+ def stimulus_controller_name
250
+ "date-picker"
251
+ end
252
+
253
+ def view_template(&)
254
+ div(
255
+ class: "hidden fixed top-0 left-0 w-max z-50",
256
+ data: { "#{stimulus_controller_name}-target" => "contentContainer" },
257
+ ) do
258
+ div(**@attributes) do
259
+ div(data: { "#{stimulus_controller_name}-target" => "calendar" })
260
+ end
261
+ end
262
+ end
263
+ end
264
+ end