shadcn_phlexcomponents 0.1.5 → 0.1.9

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -0
  3. data/app/javascript/controllers/accordion_controller.js +7 -16
  4. data/app/javascript/controllers/alert_dialog_controller.js +5 -141
  5. data/app/javascript/controllers/combobox_controller.js +20 -0
  6. data/app/javascript/controllers/date_picker_controller.js +199 -64
  7. data/app/javascript/controllers/date_range_picker_controller.js +289 -176
  8. data/app/javascript/controllers/dialog_controller.js +19 -64
  9. data/app/javascript/controllers/dropdown_menu_controller.js +15 -37
  10. data/app/javascript/controllers/form_field_controller.js +24 -0
  11. data/app/javascript/controllers/hover_card_controller.js +1 -22
  12. data/app/javascript/controllers/popover_controller.js +20 -31
  13. data/app/javascript/controllers/select_controller.js +32 -52
  14. data/app/javascript/controllers/sidebar_trigger_controller.js +1 -1
  15. data/app/javascript/controllers/toast_controller.js +2 -2
  16. data/app/javascript/controllers/tooltip_controller.js +1 -2
  17. data/app/javascript/shadcn_phlexcomponents.js +53 -0
  18. data/app/javascript/utils.js +184 -0
  19. data/app/stylesheets/date_picker.css +212 -0
  20. data/lib/install/install_shadcn_phlexcomponents.rb +7 -7
  21. data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion.rb +1 -1
  22. data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion_content.rb +1 -1
  23. data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion_item.rb +1 -1
  24. data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion_trigger.rb +5 -4
  25. data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog.rb +1 -1
  26. data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_action.rb +1 -1
  27. data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_action_to.rb +1 -1
  28. data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_cancel.rb +1 -1
  29. data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_content.rb +2 -2
  30. data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_trigger.rb +2 -2
  31. data/lib/{components → shadcn_phlexcomponents/components/avatar}/avatar.rb +1 -1
  32. data/lib/{components → shadcn_phlexcomponents/components/avatar}/avatar_fallback.rb +1 -1
  33. data/lib/{components → shadcn_phlexcomponents/components/avatar}/avatar_image.rb +1 -1
  34. data/lib/{components → shadcn_phlexcomponents/components/badge}/badge.rb +1 -1
  35. data/lib/{components → shadcn_phlexcomponents/components}/base.rb +10 -0
  36. data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb.rb +2 -0
  37. data/lib/{components → shadcn_phlexcomponents/components/button}/button.rb +5 -5
  38. data/lib/{components → shadcn_phlexcomponents/components/checkbox}/checkbox.rb +5 -5
  39. data/lib/{components → shadcn_phlexcomponents/components/checkbox_group}/checkbox_group.rb +27 -15
  40. data/lib/{components → shadcn_phlexcomponents/components/collapsible}/collapsible.rb +1 -1
  41. data/lib/{components → shadcn_phlexcomponents/components/collapsible}/collapsible_content.rb +1 -1
  42. data/lib/{components → shadcn_phlexcomponents/components/collapsible}/collapsible_trigger.rb +2 -2
  43. data/lib/shadcn_phlexcomponents/components/date_picker/date_picker.rb +87 -0
  44. data/lib/shadcn_phlexcomponents/components/date_picker/date_picker_content.rb +45 -0
  45. data/lib/shadcn_phlexcomponents/components/date_picker/date_picker_trigger.rb +64 -0
  46. data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker.rb +105 -0
  47. data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker_content.rb +9 -0
  48. data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker_trigger.rb +9 -0
  49. data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog.rb +8 -8
  50. data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_close.rb +1 -1
  51. data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_content.rb +3 -3
  52. data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_trigger.rb +2 -2
  53. data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu.rb +1 -1
  54. data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_content.rb +9 -9
  55. data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_item.rb +8 -8
  56. data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_trigger.rb +5 -5
  57. data/lib/shadcn_phlexcomponents/components/form/form.rb +139 -0
  58. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +83 -0
  59. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +116 -0
  60. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +47 -0
  61. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +96 -0
  62. data/lib/{components → shadcn_phlexcomponents/components/form}/form_error.rb +6 -2
  63. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +108 -0
  64. data/lib/{components → shadcn_phlexcomponents/components/form}/form_hint.rb +6 -2
  65. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +107 -0
  66. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +65 -0
  67. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +66 -0
  68. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +60 -0
  69. data/lib/{components → shadcn_phlexcomponents/components/hover_card}/hover_card.rb +1 -1
  70. data/lib/{components → shadcn_phlexcomponents/components/hover_card}/hover_card_content.rb +1 -1
  71. data/lib/{components → shadcn_phlexcomponents/components/hover_card}/hover_card_trigger.rb +1 -1
  72. data/lib/{components → shadcn_phlexcomponents/components/input}/input.rb +1 -1
  73. data/lib/{components → shadcn_phlexcomponents/components/loading_button}/loading_button.rb +1 -1
  74. data/lib/{components → shadcn_phlexcomponents/components/popover}/popover.rb +1 -1
  75. data/lib/{components → shadcn_phlexcomponents/components/popover}/popover_content.rb +6 -6
  76. data/lib/{components → shadcn_phlexcomponents/components/popover}/popover_trigger.rb +2 -3
  77. data/lib/{components → shadcn_phlexcomponents/components/progress}/progress.rb +3 -3
  78. data/lib/{components → shadcn_phlexcomponents/components/radio_group}/radio_group.rb +33 -7
  79. data/lib/{components → shadcn_phlexcomponents/components/radio_group}/radio_group_item.rb +7 -7
  80. data/lib/{components → shadcn_phlexcomponents/components/select}/select.rb +22 -12
  81. data/lib/{components → shadcn_phlexcomponents/components/select}/select_content.rb +6 -6
  82. data/lib/{components → shadcn_phlexcomponents/components/select}/select_group.rb +1 -1
  83. data/lib/{components → shadcn_phlexcomponents/components/select}/select_item.rb +8 -8
  84. data/lib/{components → shadcn_phlexcomponents/components/select}/select_label.rb +1 -1
  85. data/lib/{components → shadcn_phlexcomponents/components/select}/select_trigger.rb +10 -10
  86. data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet.rb +1 -1
  87. data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_close.rb +1 -1
  88. data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_content.rb +3 -3
  89. data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_trigger.rb +2 -2
  90. data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar.rb +3 -3
  91. data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_trigger.rb +2 -2
  92. data/lib/{components → shadcn_phlexcomponents/components/switch}/switch.rb +4 -4
  93. data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs.rb +2 -2
  94. data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs_content.rb +1 -1
  95. data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs_trigger.rb +4 -4
  96. data/lib/{components → shadcn_phlexcomponents/components/textarea}/textarea.rb +3 -2
  97. data/lib/{components → shadcn_phlexcomponents/components/theme_switcher}/theme_switcher.rb +2 -2
  98. data/lib/{components → shadcn_phlexcomponents/components/toast}/toast.rb +7 -7
  99. data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_container.rb +1 -1
  100. data/lib/{components → shadcn_phlexcomponents/components/tooltip}/tooltip.rb +3 -3
  101. data/lib/{components → shadcn_phlexcomponents/components/tooltip}/tooltip_content.rb +1 -1
  102. data/lib/{components → shadcn_phlexcomponents/components/tooltip}/tooltip_trigger.rb +1 -1
  103. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  104. metadata +157 -144
  105. data/app/assets/tailwind/vanilla-calendar-pro.css +0 -466
  106. data/app/javascript/controllers/sheet_controller.js +0 -159
  107. data/lib/components/combobox.rb +0 -57
  108. data/lib/components/combobox_item.rb +0 -9
  109. data/lib/components/date_picker.rb +0 -94
  110. data/lib/components/date_range_picker.rb +0 -113
  111. data/lib/components/form.rb +0 -59
  112. /data/app/{assets/tailwind → stylesheets}/choices.css +0 -0
  113. /data/app/{assets/tailwind → stylesheets}/tailwindcss-animate.css +0 -0
  114. /data/lib/{components → shadcn_phlexcomponents/components/alert}/alert.rb +0 -0
  115. /data/lib/{components → shadcn_phlexcomponents/components/alert}/alert_description.rb +0 -0
  116. /data/lib/{components → shadcn_phlexcomponents/components/alert}/alert_title.rb +0 -0
  117. /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_description.rb +0 -0
  118. /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_footer.rb +0 -0
  119. /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_header.rb +0 -0
  120. /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_title.rb +0 -0
  121. /data/lib/{components → shadcn_phlexcomponents/components/aspect_ratio}/aspect_ratio.rb +0 -0
  122. /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_ellipsis.rb +0 -0
  123. /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_item.rb +0 -0
  124. /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_link.rb +0 -0
  125. /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_page.rb +0 -0
  126. /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_separator.rb +0 -0
  127. /data/lib/{components → shadcn_phlexcomponents/components/card}/card.rb +0 -0
  128. /data/lib/{components → shadcn_phlexcomponents/components/card}/card_content.rb +0 -0
  129. /data/lib/{components → shadcn_phlexcomponents/components/card}/card_description.rb +0 -0
  130. /data/lib/{components → shadcn_phlexcomponents/components/card}/card_footer.rb +0 -0
  131. /data/lib/{components → shadcn_phlexcomponents/components/card}/card_header.rb +0 -0
  132. /data/lib/{components → shadcn_phlexcomponents/components/card}/card_title.rb +0 -0
  133. /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_description.rb +0 -0
  134. /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_footer.rb +0 -0
  135. /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_header.rb +0 -0
  136. /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_title.rb +0 -0
  137. /data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_item_to.rb +0 -0
  138. /data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_label.rb +0 -0
  139. /data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_separator.rb +0 -0
  140. /data/lib/{components → shadcn_phlexcomponents/components/form}/form_input.rb +0 -0
  141. /data/lib/{components → shadcn_phlexcomponents/components/label}/label.rb +0 -0
  142. /data/lib/{components → shadcn_phlexcomponents/components/link}/link.rb +0 -0
  143. /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination.rb +0 -0
  144. /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_ellipsis.rb +0 -0
  145. /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_link.rb +0 -0
  146. /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_next.rb +0 -0
  147. /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_previous.rb +0 -0
  148. /data/lib/{components → shadcn_phlexcomponents/components/separator}/separator.rb +0 -0
  149. /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_description.rb +0 -0
  150. /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_footer.rb +0 -0
  151. /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_header.rb +0 -0
  152. /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_title.rb +0 -0
  153. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_container.rb +0 -0
  154. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_content.rb +0 -0
  155. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_footer.rb +0 -0
  156. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_group.rb +0 -0
  157. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_group_content.rb +0 -0
  158. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_group_label.rb +0 -0
  159. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_header.rb +0 -0
  160. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_inset.rb +0 -0
  161. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu.rb +0 -0
  162. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_button.rb +0 -0
  163. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_item.rb +0 -0
  164. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_sub.rb +0 -0
  165. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_sub_button.rb +0 -0
  166. /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_sub_item.rb +0 -0
  167. /data/lib/{components → shadcn_phlexcomponents/components/skeleton}/skeleton.rb +0 -0
  168. /data/lib/{components → shadcn_phlexcomponents/components/table}/table.rb +0 -0
  169. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_body.rb +0 -0
  170. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_caption.rb +0 -0
  171. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_cell.rb +0 -0
  172. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_footer.rb +0 -0
  173. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_head.rb +0 -0
  174. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_header.rb +0 -0
  175. /data/lib/{components → shadcn_phlexcomponents/components/table}/table_row.rb +0 -0
  176. /data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs_list.rb +0 -0
  177. /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_action.rb +0 -0
  178. /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_action_to.rb +0 -0
  179. /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_content.rb +0 -0
  180. /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_description.rb +0 -0
  181. /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_title.rb +0 -0
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DatePicker < Base
5
+ STYLES = "w-full"
6
+ CONTAINER_STYLES = <<~HEREDOC
7
+ flex rounded-md border border-input items-center shadow-sm outline-none
8
+ data-[focus=true]:ring-1 data-[focus=true]:ring-ring focus:ring-1 focus:ring-ring
9
+ data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50
10
+ HEREDOC
11
+ INPUT_STYLES = <<~HEREDOC
12
+ flex h-9 w-full bg-transparent px-3 py-1 text-base transition-colors placeholder:text-muted-foreground
13
+ focus-visible:outline-none grow md:text-sm
14
+ HEREDOC
15
+
16
+ def initialize(name: nil, id: nil, value: nil, format: "DD/MM/YYYY", select_only: false, placeholder: nil,
17
+ disabled: false, settings: {}, aria_id: "date-picker-#{SecureRandom.hex(5)}", **attributes)
18
+ @name = name
19
+ @id = id || @name
20
+ @value = value&.utc&.iso8601
21
+ @format = format
22
+ @select_only = select_only
23
+ @placeholder = placeholder
24
+ @disabled = disabled
25
+ @settings = settings
26
+ @aria_id = aria_id
27
+ super(**attributes)
28
+ end
29
+
30
+ def default_attributes
31
+ {
32
+ data: {
33
+ controller: "date-picker",
34
+ value: @value,
35
+ format: @format,
36
+ settings: @settings.to_json,
37
+ },
38
+ }
39
+ end
40
+
41
+ def view_template(&)
42
+ div(**@attributes) do
43
+ input(
44
+ type: :hidden,
45
+ name: @name,
46
+ value: @value,
47
+ data: { "date-picker-target": "hiddenInput" },
48
+ )
49
+
50
+ if @select_only
51
+ DatePickerTrigger(
52
+ disabled: @disabled,
53
+ aria_id: @aria_id,
54
+ select_only: @select_only,
55
+ select_only_id: @id,
56
+ placeholder: @placeholder,
57
+ )
58
+ else
59
+ div(class: CONTAINER_STYLES, data: { "date-picker-target": "inputContainer", disabled: @disabled }) do
60
+ input(
61
+ id: @id,
62
+ placeholder: @placeholder || @format,
63
+ type: :text,
64
+ class: INPUT_STYLES,
65
+ disabled: @disabled,
66
+ data: {
67
+ "date-picker-target": "input",
68
+ action: "input->date-picker#changeDate
69
+ blur->date-picker#inputBlur
70
+ focus->date-picker#setContainerFocus",
71
+ },
72
+ )
73
+
74
+ DatePickerTrigger(
75
+ disabled: @disabled,
76
+ aria_id: @aria_id,
77
+ select_only: @select_only,
78
+ placeholder: @placeholder,
79
+ )
80
+ end
81
+ end
82
+
83
+ DatePickerContent(aria_id: @aria_id)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DatePickerContent < Base
5
+ STYLES = <<~HEREDOC
6
+ z-51 bg-popover text-popover-foreground outline-none rounded-md min-w-[300px]
7
+ fixed left-[50%] top-[50%] shadow-lg grid translate-x-[-50%] translate-y-[-50%]#{" "}
8
+ md:relative md:left-[unset] md:top-[unset] md:shadow-md md:block md:translate-x-[unset] md:translate-y-[unset] md:min-w-auto
9
+ data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0
10
+ data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
11
+ slide-in-from-top-2
12
+ HEREDOC
13
+
14
+ def initialize(aria_id: nil, **attributes)
15
+ @aria_id = aria_id
16
+ super(**attributes)
17
+ end
18
+
19
+ def view_template(&)
20
+ div(
21
+ class: "hidden fixed top-0 left-0 w-max z-51",
22
+ data: { "#{stimulus_controller_name}-target" => "contentWrapper" },
23
+ ) do
24
+ div(**@attributes) do
25
+ div(data: { "#{stimulus_controller_name}-target" => "calendar" })
26
+ end
27
+ end
28
+ end
29
+
30
+ def default_attributes
31
+ {
32
+ id: "#{@aria_id}-content",
33
+ tabindex: -1,
34
+ role: "dialog",
35
+ data: {
36
+ "#{stimulus_controller_name}-target" => "content",
37
+ },
38
+ }
39
+ end
40
+
41
+ def stimulus_controller_name
42
+ "date-picker"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DatePickerTrigger < Base
5
+ SELECT_ONLY_BUTTON_STYLES = <<~HEREDOC
6
+ flex h-9 items-center justify-between whitespace-nowrap rounded-md border
7
+ border-input bg-transparent px-3 py-2 gap-1.5 text-base md:text-sm shadow-sm ring-offset-background
8
+ data-[placeholder]:data-[has-value=false]:text-muted-foreground focus:outline-none focus:ring-1
9
+ focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1
10
+ w-full cursor-pointer hover:bg-accent hover:text-accent-foreground disabled:hover:bg-transparent
11
+ HEREDOC
12
+
13
+ def initialize(disabled: false, select_only: true, placeholder: nil, select_only_id: nil, aria_id: nil,
14
+ **attributes)
15
+ @disabled = disabled
16
+ @select_only = select_only
17
+ @placeholder = placeholder
18
+ @select_only_id = select_only_id
19
+ @aria_id = aria_id
20
+ super(**attributes)
21
+ end
22
+
23
+ def view_template
24
+ if @select_only
25
+ button(type: :button, disabled: @disabled, id: @select_only_id, **@attributes) do
26
+ span(class: "pointer-events-none", data: { "#{stimulus_controller_name}-target" => "triggerText" })
27
+
28
+ icon("calendar", class: "size-4 text-foreground")
29
+ end
30
+ else
31
+ button(type: :button, disabled: @disabled, **@attributes) do
32
+ icon("calendar")
33
+ end
34
+ end
35
+ end
36
+
37
+ def default_styles
38
+ if @select_only
39
+ SELECT_ONLY_BUTTON_STYLES
40
+ else
41
+ "#{Button.default_styles(variant: :ghost, size: :icon)} mr-1.25 h-7 w-8 disabled:!opacity-100"
42
+ end
43
+ end
44
+
45
+ def default_attributes
46
+ {
47
+ aria: {
48
+ haspopup: "dialog",
49
+ expanded: false,
50
+ controls: "#{@aria_id}-content",
51
+ },
52
+ data: {
53
+ placeholder: @placeholder,
54
+ action: "click->#{stimulus_controller_name}#toggle",
55
+ "#{stimulus_controller_name}-target" => "trigger",
56
+ },
57
+ }
58
+ end
59
+
60
+ def stimulus_controller_name
61
+ "date-picker"
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DateRangePicker < Base
5
+ def initialize(
6
+ start_date_name: nil,
7
+ end_date_name: nil,
8
+ id: nil,
9
+ start_date: nil,
10
+ end_date: nil,
11
+ format: "DD/MM/YYYY",
12
+ select_only: false,
13
+ placeholder: nil,
14
+ disabled: false,
15
+ settings: {},
16
+ aria_id: "date-range-picker-#{SecureRandom.hex(5)}",
17
+ **attributes
18
+ )
19
+ @start_date_name = start_date_name
20
+ @end_date_name = end_date_name
21
+ @id = id || start_date_name
22
+ @start_date = start_date&.utc&.iso8601
23
+ @end_date = end_date&.utc&.iso8601
24
+ @format = format
25
+ @select_only = select_only
26
+ @placeholder = placeholder
27
+ @disabled = disabled
28
+ @settings = settings
29
+ @aria_id = aria_id
30
+ super(**attributes)
31
+ end
32
+
33
+ def default_styles
34
+ DatePicker::STYLES
35
+ end
36
+
37
+ def default_attributes
38
+ {
39
+ data: {
40
+ controller: "date-range-picker",
41
+ start_date: @start_date,
42
+ end_date: @end_date,
43
+ format: @format,
44
+ settings: @settings.to_json,
45
+ },
46
+ }
47
+ end
48
+
49
+ def view_template(&)
50
+ div(**@attributes) do
51
+ input(
52
+ type: :hidden,
53
+ name: @start_date_name,
54
+ value: @start_date,
55
+ data: { "date-range-picker-target": "startDateHiddenInput" },
56
+ )
57
+
58
+ input(
59
+ type: :hidden,
60
+ name: @end_date_name,
61
+ value: @end_date,
62
+ data: { "date-range-picker-target": "endDateHiddenInput" },
63
+ )
64
+
65
+ if @select_only
66
+ DateRangePickerTrigger(
67
+ disabled: @disabled,
68
+ aria_id: @aria_id,
69
+ select_only: @select_only,
70
+ select_only_id: @id,
71
+ placeholder: @placeholder,
72
+ )
73
+ else
74
+ div(
75
+ class: DatePicker::CONTAINER_STYLES,
76
+ data: { "date-range-picker-target": "inputContainer", disabled: @disabled },
77
+ ) do
78
+ input(
79
+ id: @id,
80
+ placeholder: @placeholder || "#{@format} - #{@format}",
81
+ type: :text,
82
+ class: DatePicker::INPUT_STYLES,
83
+ disabled: @disabled,
84
+ data: {
85
+ "date-range-picker-target": "input",
86
+ action: "input->date-range-picker#changeDate
87
+ blur->date-range-picker#inputBlur
88
+ focus->date-range-picker#setContainerFocus",
89
+ },
90
+ )
91
+
92
+ DateRangePickerTrigger(
93
+ disabled: @disabled,
94
+ aria_id: @aria_id,
95
+ select_only: @select_only,
96
+ placeholder: @placeholder,
97
+ )
98
+ end
99
+ end
100
+
101
+ DateRangePickerContent(aria_id: @aria_id)
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DateRangePickerContent < DatePickerContent
5
+ def stimulus_controller_name
6
+ "date-range-picker"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DateRangePickerTrigger < DatePickerTrigger
5
+ def stimulus_controller_name
6
+ "date-range-picker"
7
+ end
8
+ end
9
+ end
@@ -10,37 +10,37 @@ module ShadcnPhlexcomponents
10
10
  end
11
11
 
12
12
  def trigger(**attributes, &)
13
- render(DialogTrigger.new(aria_id: @aria_id, **attributes, &))
13
+ DialogTrigger(aria_id: @aria_id, **attributes, &)
14
14
  end
15
15
 
16
16
  def content(**attributes, &)
17
- render(DialogContent.new(aria_id: @aria_id, **attributes, &))
17
+ DialogContent(aria_id: @aria_id, **attributes, &)
18
18
  end
19
19
 
20
20
  def header(**attributes, &)
21
- render(DialogHeader.new(**attributes, &))
21
+ DialogHeader(**attributes, &)
22
22
  end
23
23
 
24
24
  def title(**attributes, &)
25
- render(DialogTitle.new(aria_id: @aria_id, **attributes, &))
25
+ DialogTitle(aria_id: @aria_id, **attributes, &)
26
26
  end
27
27
 
28
28
  def description(**attributes, &)
29
- render(DialogDescription.new(aria_id: @aria_id, **attributes, &))
29
+ DialogDescription(aria_id: @aria_id, **attributes, &)
30
30
  end
31
31
 
32
32
  def footer(**attributes, &)
33
- render(DialogFooter.new(**attributes, &))
33
+ DialogFooter(**attributes, &)
34
34
  end
35
35
 
36
36
  def close(**attributes, &)
37
- render(DialogClose.new(**attributes, &))
37
+ DialogClose(**attributes, &)
38
38
  end
39
39
 
40
40
  def default_attributes
41
41
  {
42
42
  data: {
43
- controller: "shadcn-phlexcomponents--dialog",
43
+ controller: "dialog",
44
44
  },
45
45
  }
46
46
  end
@@ -11,7 +11,7 @@ module ShadcnPhlexcomponents
11
11
  {
12
12
  role: "button",
13
13
  data: {
14
- action: "click->shadcn-phlexcomponents--dialog#close",
14
+ action: "click->dialog#close",
15
15
  },
16
16
  }
17
17
  end
@@ -3,7 +3,7 @@
3
3
  module ShadcnPhlexcomponents
4
4
  class DialogContent < Base
5
5
  STYLES = <<~HEREDOC
6
- fixed left-[50%] top-[50%] z-51 grid w-full max-w-lg translate-x-[-50%]
6
+ fixed left-[50%] top-[50%] z-51 grid w-full max-w-lg translate-x-[-50%] pointer-events-auto
7
7
  translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200
8
8
  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0
9
9
  data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
@@ -33,7 +33,7 @@ module ShadcnPhlexcomponents
33
33
  labelledby: "#{@aria_id}-title",
34
34
  },
35
35
  data: {
36
- "shadcn-phlexcomponents--dialog-target": "content",
36
+ "dialog-target": "content",
37
37
  state: "closed",
38
38
  },
39
39
  }
@@ -44,7 +44,7 @@ module ShadcnPhlexcomponents
44
44
  div(class: "#{@class} hidden", **@attributes) do
45
45
  yield
46
46
 
47
- button(class: CLOSE_BUTTON_STYLES, data: { action: "click->shadcn-phlexcomponents--dialog#close" }) do
47
+ button(class: CLOSE_BUTTON_STYLES, data: { action: "click->dialog#close" }) do
48
48
  icon("x", class: "size-4")
49
49
  span(class: "sr-only") { "close" }
50
50
  end
@@ -17,8 +17,8 @@ module ShadcnPhlexcomponents
17
17
  controls: "#{@aria_id}-content",
18
18
  },
19
19
  data: {
20
- action: "click->shadcn-phlexcomponents--dialog#open",
21
- "shadcn-phlexcomponents--dialog-target": "trigger",
20
+ action: "click->dialog#open",
21
+ "dialog-target": "trigger",
22
22
  as_child: @as_child.to_s,
23
23
  },
24
24
  }
@@ -37,7 +37,7 @@ module ShadcnPhlexcomponents
37
37
  def default_attributes
38
38
  {
39
39
  data: {
40
- controller: "shadcn-phlexcomponents--dropdown-menu",
40
+ controller: "dropdown-menu",
41
41
  side: @side,
42
42
  },
43
43
  }
@@ -5,11 +5,11 @@ module ShadcnPhlexcomponents
5
5
  STYLES = <<~HEREDOC
6
6
  z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1
7
7
  text-popover-foreground shadow-md outline-none
8
- data-[state=open]:animate-in
9
- data-[state=closed]:animate-out data-[state=closed]:fade-out-0#{" "}
10
- data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95#{" "}
11
- data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2#{" "}
12
- data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2#{" "}
8
+ data-[state=open]:animate-in pointer-events-auto
9
+ data-[state=closed]:animate-out data-[state=closed]:fade-out-0
10
+ data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
11
+ data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
12
+ data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
13
13
  data-[side=top]:slide-in-from-bottom-2
14
14
  HEREDOC
15
15
 
@@ -22,7 +22,7 @@ module ShadcnPhlexcomponents
22
22
  def view_template(&)
23
23
  div(
24
24
  class: "hidden fixed top-0 left-0 w-max z-50",
25
- data: { "shadcn-phlexcomponents--dropdown-menu-target": "contentWrapper" },
25
+ data: { "dropdown-menu-target": "contentWrapper" },
26
26
  ) do
27
27
  div(**@attributes, &)
28
28
  end
@@ -40,10 +40,10 @@ module ShadcnPhlexcomponents
40
40
  data: {
41
41
  state: "closed",
42
42
  side: @side,
43
- "shadcn-phlexcomponents--dropdown-menu-target": "content",
43
+ "dropdown-menu-target": "content",
44
44
  action: <<~HEREDOC,
45
- keydown.up->shadcn-phlexcomponents--dropdown-menu#focusLastItem:prevent
46
- keydown.down->shadcn-phlexcomponents--dropdown-menu#focusFirstItem:prevent
45
+ keydown.up->dropdown-menu#focusLastItem:prevent
46
+ keydown.down->dropdown-menu#focusFirstItem:prevent
47
47
  HEREDOC
48
48
  },
49
49
  }
@@ -40,15 +40,15 @@ module ShadcnPhlexcomponents
40
40
  data: {
41
41
  disabled: @disabled,
42
42
  action: <<~HEREDOC,
43
- click->shadcn-phlexcomponents--dropdown-menu#selectItem
44
- keydown.up->shadcn-phlexcomponents--dropdown-menu#focusPrevItem:stop
45
- keydown.down->shadcn-phlexcomponents--dropdown-menu#focusNextItem:stop
46
- keydown.enter->shadcn-phlexcomponents--dropdown-menu#selectItem:prevent
47
- keydown.space->shadcn-phlexcomponents--dropdown-menu#selectItem:prevent
48
- mouseover->shadcn-phlexcomponents--dropdown-menu#focusItem
49
- mouseout->shadcn-phlexcomponents--dropdown-menu#focusContent
43
+ click->dropdown-menu#selectItem
44
+ keydown.up->dropdown-menu#focusPrevItem:stop
45
+ keydown.down->dropdown-menu#focusNextItem:stop
46
+ keydown.enter->dropdown-menu#selectItem:prevent
47
+ keydown.space->dropdown-menu#selectItem:prevent
48
+ mouseover->dropdown-menu#focusItem
49
+ mouseout->dropdown-menu#focusContent
50
50
  HEREDOC
51
- "shadcn-phlexcomponents--dropdown-menu-target": "item",
51
+ "dropdown-menu-target": "item",
52
52
  },
53
53
  }
54
54
  end
@@ -44,12 +44,12 @@ module ShadcnPhlexcomponents
44
44
  state: "closed",
45
45
  as_child: @as_child.to_s,
46
46
  action: <<~HEREDOC,
47
- click->shadcn-phlexcomponents--dropdown-menu#toggle
48
- keydown.space->shadcn-phlexcomponents--dropdown-menu#toggle
49
- keydown.enter->shadcn-phlexcomponents--dropdown-menu#toggle
50
- keydown.down->shadcn-phlexcomponents--dropdown-menu#toggle:prevent
47
+ click->dropdown-menu#toggle
48
+ keydown.space->dropdown-menu#toggle
49
+ keydown.enter->dropdown-menu#toggle
50
+ keydown.down->dropdown-menu#toggle:prevent
51
51
  HEREDOC
52
- "shadcn-phlexcomponents--dropdown-menu-target": "trigger",
52
+ "dropdown-menu-target": "trigger",
53
53
  },
54
54
  }
55
55
  end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class Form < Base
5
+ include Phlex::Rails::Helpers::FormWith
6
+
7
+ def initialize(model: false, scope: nil, url: nil, format: nil, loading: false, **options)
8
+ @model = model
9
+ @scope = scope
10
+ @url = url
11
+ @format = format
12
+ @options = options
13
+ @loading = loading
14
+ @object_name = model ? model.to_model.model_name.param_key : nil
15
+ end
16
+
17
+ def input(method = nil, **attributes, &)
18
+ FormInput(method, model: @model, object_name: @object_name, **attributes, &)
19
+ end
20
+
21
+ def textarea(method = nil, **attributes, &)
22
+ FormTextarea(method, model: @model, object_name: @object_name, **attributes, &)
23
+ end
24
+
25
+ def checkbox(method = nil, **attributes, &)
26
+ FormCheckbox(method, model: @model, object_name: @object_name, **attributes, &)
27
+ end
28
+
29
+ def switch(method = nil, **attributes, &)
30
+ FormSwitch(method, model: @model, object_name: @object_name, **attributes, &)
31
+ end
32
+
33
+ def checkbox_group(method = nil, collection = [], value_method:, text_method:, **attributes, &)
34
+ FormCheckboxGroup(
35
+ method,
36
+ model: @model,
37
+ object_name: @object_name,
38
+ collection: collection,
39
+ value_method: value_method,
40
+ text_method: text_method,
41
+ **attributes,
42
+ &
43
+ )
44
+ end
45
+
46
+ def radio_group(method = nil, collection = [], value_method:, text_method:, **attributes, &)
47
+ FormRadioGroup(
48
+ method,
49
+ model: @model,
50
+ object_name: @object_name,
51
+ collection: collection,
52
+ value_method: value_method,
53
+ text_method: text_method,
54
+ **attributes,
55
+ &
56
+ )
57
+ end
58
+
59
+ def select(method = nil, collection = [], value_method:, text_method:, **attributes, &)
60
+ FormSelect(
61
+ method,
62
+ model: @model,
63
+ object_name: @object_name,
64
+ collection: collection,
65
+ value_method: value_method,
66
+ text_method: text_method,
67
+ **attributes,
68
+ &
69
+ )
70
+ end
71
+
72
+ def date_picker(method = nil, **attributes, &)
73
+ FormDatePicker(method, model: @model, object_name: @object_name, **attributes, &)
74
+ end
75
+
76
+ def date_range_picker(start_date_method = nil, end_date_method = nil, **attributes, &)
77
+ FormDateRangePicker(start_date_method, end_date_method, model: @model, object_name: @object_name, **attributes, &)
78
+ end
79
+
80
+ def submit(value = nil, variant: :primary, **attributes, &)
81
+ if @loading
82
+ LoadingButton(variant: variant, type: :submit, **attributes) do
83
+ if block_given?
84
+ yield
85
+ else
86
+ value || submit_default_value
87
+ end
88
+ end
89
+ else
90
+ Button(variant: variant, type: :submit, **attributes) do
91
+ if block_given?
92
+ yield
93
+ else
94
+ value || submit_default_value
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def view_template(&)
101
+ @form_class = @options[:class]
102
+ @options[:class] = "#{@options[:class]} #{"group" if @loading}"
103
+ # rubocop:disable Style/ExplicitBlockArgument
104
+ form_with(model: @model, scope: @scope, url: @url, format: @format, **@options) do
105
+ yield
106
+ end
107
+ # rubocop:enable Style/ExplicitBlockArgument
108
+ end
109
+
110
+ # Follows rails f.submit
111
+ # https://github.com/rails/rails/blob/3235827585d87661942c91bc81f64f56d710f0b2/actionview/lib/action_view/helpers/form_helper.rb#L2681-L2706
112
+ def submit_default_value
113
+ object = @model&.to_model
114
+ key = if object
115
+ object.persisted? ? :update : :create
116
+ else
117
+ :submit
118
+ end
119
+
120
+ model = if object.respond_to?(:model_name)
121
+ object.model_name.human
122
+ else
123
+ @object_name.to_s.humanize
124
+ end
125
+
126
+ defaults = []
127
+ # Object is a model and it is not overwritten by as and scope option.
128
+ defaults << if object.respond_to?(:model_name) && @object_name.to_s == model.downcase
129
+ :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
130
+ else
131
+ :"helpers.submit.#{@object_name}.#{key}"
132
+ end
133
+ defaults << :"helpers.submit.#{key}"
134
+ defaults << "#{key.to_s.humanize} #{model}"
135
+
136
+ I18n.t(defaults.shift, model: model, default: defaults)
137
+ end
138
+ end
139
+ end