shadcn_phlexcomponents 0.1.0 → 0.1.2

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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/tailwind/choices.css +324 -0
  3. data/app/assets/tailwind/vanilla-calendar-pro.css +5 -0
  4. data/app/javascript/controllers/combobox_controller.js +19 -276
  5. data/app/javascript/controllers/date_picker_controller.js +118 -0
  6. data/app/javascript/controllers/date_range_picker_controller.js +231 -0
  7. data/app/javascript/controllers/dropdown_menu_controller.js +1 -1
  8. data/app/javascript/controllers/hover_card_controller.js +33 -126
  9. data/app/javascript/controllers/sidebar_controller.js +0 -1
  10. data/app/javascript/controllers/tooltip_controller.js +32 -126
  11. data/lib/components/accordion.rb +3 -3
  12. data/lib/components/accordion_content.rb +12 -10
  13. data/lib/components/accordion_item.rb +3 -3
  14. data/lib/components/accordion_trigger.rb +3 -3
  15. data/lib/components/alert_description.rb +1 -1
  16. data/lib/components/alert_dialog.rb +2 -2
  17. data/lib/components/alert_dialog_action.rb +2 -2
  18. data/lib/components/alert_dialog_action_to.rb +5 -2
  19. data/lib/components/alert_dialog_cancel.rb +1 -1
  20. data/lib/components/alert_dialog_content.rb +1 -1
  21. data/lib/components/alert_dialog_description.rb +1 -1
  22. data/lib/components/alert_dialog_footer.rb +1 -1
  23. data/lib/components/alert_dialog_header.rb +1 -1
  24. data/lib/components/alert_dialog_title.rb +1 -1
  25. data/lib/components/alert_dialog_trigger.rb +2 -2
  26. data/lib/components/aspect_ratio.rb +1 -1
  27. data/lib/components/avatar.rb +1 -1
  28. data/lib/components/avatar_fallback.rb +1 -1
  29. data/lib/components/avatar_image.rb +1 -2
  30. data/lib/components/badge.rb +2 -8
  31. data/lib/components/base.rb +5 -5
  32. data/lib/components/breadcrumb.rb +1 -1
  33. data/lib/components/breadcrumb_ellipsis.rb +1 -1
  34. data/lib/components/breadcrumb_item.rb +1 -1
  35. data/lib/components/breadcrumb_link.rb +1 -1
  36. data/lib/components/breadcrumb_page.rb +1 -1
  37. data/lib/components/breadcrumb_separator.rb +1 -1
  38. data/lib/components/button.rb +1 -1
  39. data/lib/components/card.rb +1 -1
  40. data/lib/components/card_content.rb +1 -1
  41. data/lib/components/card_description.rb +1 -1
  42. data/lib/components/card_footer.rb +1 -1
  43. data/lib/components/card_header.rb +1 -1
  44. data/lib/components/card_title.rb +1 -1
  45. data/lib/components/checkbox.rb +14 -10
  46. data/lib/components/checkbox_group.rb +26 -9
  47. data/lib/components/collapsible.rb +2 -3
  48. data/lib/components/collapsible_content.rb +2 -3
  49. data/lib/components/collapsible_trigger.rb +5 -5
  50. data/lib/components/combobox.rb +57 -0
  51. data/lib/components/combobox_item.rb +9 -0
  52. data/lib/components/date_picker.rb +94 -0
  53. data/lib/components/date_range_picker.rb +113 -0
  54. data/lib/components/dialog.rb +1 -1
  55. data/lib/components/dialog_close.rb +1 -1
  56. data/lib/components/dialog_content.rb +2 -2
  57. data/lib/components/dialog_description.rb +1 -1
  58. data/lib/components/dialog_footer.rb +1 -1
  59. data/lib/components/dialog_header.rb +1 -1
  60. data/lib/components/dialog_title.rb +1 -1
  61. data/lib/components/dialog_trigger.rb +2 -2
  62. data/lib/components/dropdown_menu.rb +5 -5
  63. data/lib/components/dropdown_menu_content.rb +12 -9
  64. data/lib/components/dropdown_menu_item.rb +5 -6
  65. data/lib/components/dropdown_menu_item_to.rb +6 -3
  66. data/lib/components/dropdown_menu_label.rb +2 -3
  67. data/lib/components/dropdown_menu_separator.rb +5 -5
  68. data/lib/components/dropdown_menu_trigger.rb +9 -10
  69. data/lib/components/form.rb +59 -0
  70. data/lib/components/form_error.rb +17 -0
  71. data/lib/components/form_hint.rb +17 -0
  72. data/lib/components/form_input.rb +49 -0
  73. data/lib/components/hover_card.rb +6 -6
  74. data/lib/components/hover_card_content.rb +8 -12
  75. data/lib/components/hover_card_trigger.rb +5 -11
  76. data/lib/components/input.rb +1 -1
  77. data/lib/components/label.rb +1 -2
  78. data/lib/components/link.rb +5 -2
  79. data/lib/components/loading_button.rb +1 -1
  80. data/lib/components/pagination.rb +4 -4
  81. data/lib/components/pagination_ellipsis.rb +3 -3
  82. data/lib/components/pagination_link.rb +5 -5
  83. data/lib/components/pagination_next.rb +5 -5
  84. data/lib/components/pagination_previous.rb +4 -4
  85. data/lib/components/popover.rb +6 -7
  86. data/lib/components/popover_content.rb +13 -10
  87. data/lib/components/popover_trigger.rb +5 -6
  88. data/lib/components/progress.rb +7 -7
  89. data/lib/components/radio_group.rb +4 -4
  90. data/lib/components/radio_group_item.rb +8 -8
  91. data/lib/components/select.rb +67 -72
  92. data/lib/components/select_content.rb +12 -7
  93. data/lib/components/select_group.rb +3 -3
  94. data/lib/components/select_item.rb +9 -8
  95. data/lib/components/select_label.rb +6 -5
  96. data/lib/components/select_trigger.rb +12 -10
  97. data/lib/components/separator.rb +3 -3
  98. data/lib/components/sheet.rb +9 -9
  99. data/lib/components/sheet_close.rb +4 -4
  100. data/lib/components/sheet_content.rb +13 -15
  101. data/lib/components/sheet_description.rb +3 -3
  102. data/lib/components/sheet_footer.rb +2 -2
  103. data/lib/components/sheet_header.rb +2 -2
  104. data/lib/components/sheet_title.rb +3 -3
  105. data/lib/components/sheet_trigger.rb +6 -6
  106. data/lib/components/sidebar.rb +30 -25
  107. data/lib/components/sidebar_container.rb +1 -1
  108. data/lib/components/sidebar_content.rb +1 -1
  109. data/lib/components/sidebar_footer.rb +2 -2
  110. data/lib/components/sidebar_group.rb +1 -1
  111. data/lib/components/sidebar_group_content.rb +1 -1
  112. data/lib/components/sidebar_group_label.rb +2 -2
  113. data/lib/components/sidebar_header.rb +2 -2
  114. data/lib/components/sidebar_inset.rb +1 -1
  115. data/lib/components/sidebar_menu.rb +2 -2
  116. data/lib/components/sidebar_menu_button.rb +5 -5
  117. data/lib/components/sidebar_menu_item.rb +1 -1
  118. data/lib/components/sidebar_menu_sub.rb +2 -2
  119. data/lib/components/sidebar_menu_sub_button.rb +7 -7
  120. data/lib/components/sidebar_menu_sub_item.rb +1 -1
  121. data/lib/components/sidebar_trigger.rb +5 -5
  122. data/lib/components/skeleton.rb +2 -2
  123. data/lib/components/switch.rb +10 -9
  124. data/lib/components/table.rb +7 -5
  125. data/lib/components/table_body.rb +2 -2
  126. data/lib/components/table_caption.rb +2 -2
  127. data/lib/components/table_cell.rb +2 -2
  128. data/lib/components/table_footer.rb +2 -2
  129. data/lib/components/table_head.rb +3 -3
  130. data/lib/components/table_header.rb +2 -2
  131. data/lib/components/table_row.rb +2 -2
  132. data/lib/components/tabs.rb +3 -3
  133. data/lib/components/tabs_content.rb +5 -5
  134. data/lib/components/tabs_list.rb +4 -4
  135. data/lib/components/tabs_trigger.rb +3 -3
  136. data/lib/components/textarea.rb +1 -1
  137. data/lib/components/theme_switcher.rb +2 -2
  138. data/lib/components/toast.rb +15 -14
  139. data/lib/components/toast_action.rb +5 -4
  140. data/lib/components/toast_action_to.rb +5 -2
  141. data/lib/components/toast_container.rb +5 -5
  142. data/lib/components/toast_content.rb +1 -1
  143. data/lib/components/toast_description.rb +1 -1
  144. data/lib/components/toast_title.rb +1 -1
  145. data/lib/components/tooltip.rb +8 -8
  146. data/lib/components/tooltip_content.rb +8 -11
  147. data/lib/components/tooltip_trigger.rb +9 -11
  148. data/lib/shadcn_phlexcomponents/alias.rb +4 -93
  149. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  150. metadata +14 -5
  151. data/app/javascript/controllers/datepicker_controller.js +0 -47
  152. data/lib/components/datepicker.rb +0 -38
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class ComboboxItem < Base
5
+ def view_template(&)
6
+ option(**@attributes, &)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DatePicker < Base
5
+ STYLES = "relative"
6
+
7
+ INPUT_STYLES = <<~HEREDOC
8
+ flex h-9 w-full rounded-md border border-input bg-transparent px-3 pr-10 py-1
9
+ text-base shadow-sm transition-colors placeholder:text-muted-foreground
10
+ focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring
11
+ disabled:cursor-not-allowed disabled:opacity-50 md:text-sm
12
+ HEREDOC
13
+
14
+ CLEAR_BUTTON_STYLES = TAILWIND_MERGER.merge("#{Button.default_styles(
15
+ variant: :ghost,
16
+ size: :icon,
17
+ )} text-muted-foreground h-6 w-6")
18
+
19
+ def initialize(name: nil, id: nil, value: nil, format: "DD/MM/YYYY", disabled: false, settings: {}, **attributes)
20
+ @name = name
21
+ @id = id || @name
22
+ @value = value&.utc&.iso8601
23
+ @settings = settings
24
+ @format = format
25
+ @disabled = disabled
26
+ super(**attributes)
27
+ end
28
+
29
+ def default_attributes
30
+ {
31
+ data: {
32
+ value: @value,
33
+ format: @format,
34
+ controller: "shadcn-phlexcomponents--date-picker",
35
+ settings: @settings.to_json,
36
+ has_value: @value.present?.to_s,
37
+ disabled: @disabled,
38
+ action: <<~HEREDOC,
39
+ mouseover->shadcn-phlexcomponents--date-picker#showClearButton
40
+ mouseout->shadcn-phlexcomponents--date-picker#hideClearButton
41
+ HEREDOC
42
+ },
43
+ }
44
+ end
45
+
46
+ def view_template
47
+ div(**@attributes) do
48
+ input(type: :text, id: @id, class: INPUT_STYLES, data: {
49
+ "shadcn-phlexcomponents--date-picker-target": "dateInput",
50
+ action: <<~HEREDOC,
51
+ input->shadcn-phlexcomponents--date-picker#changeDate
52
+ blur->shadcn-phlexcomponents--date-picker#inputBlur
53
+ keydown->shadcn-phlexcomponents--date-picker#closeCalendar
54
+ HEREDOC
55
+ })
56
+ input(
57
+ type: :hidden,
58
+ name: @name,
59
+ value: @value,
60
+ data: { "shadcn-phlexcomponents--date-picker-target": "hiddenInput" },
61
+ )
62
+
63
+ div(
64
+ class: "absolute right-3 inset-y-0 flex items-center -z-1",
65
+ data: {
66
+ action: "",
67
+ },
68
+ ) do
69
+ span(class: "pointer-events-none size-6 inline-flex items-center justify-center") do
70
+ icon(
71
+ "calendar",
72
+ class: "size-4 text-muted-foreground",
73
+ data: { "shadcn-phlexcomponents--date-picker-target": "calendarIcon" },
74
+ )
75
+ end
76
+ end
77
+
78
+ div(class: "absolute right-3 inset-y-0 flex items-center") do
79
+ button(
80
+ type: :button,
81
+ class: "#{CLEAR_BUTTON_STYLES} !hidden",
82
+ tabindex: -1,
83
+ data: {
84
+ action: "shadcn-phlexcomponents--date-picker#clear:stop",
85
+ "shadcn-phlexcomponents--date-picker-target": "clearButton",
86
+ },
87
+ ) do
88
+ icon("x")
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class DateRangePicker < Base
5
+ STYLES = <<~HEREDOC
6
+ flex w-full rounded-md border border-input bg-transparent px-3 pr-10 h-9
7
+ text-base shadow-sm transition-colors placeholder:text-muted-foreground
8
+ outline-none data-[focus=true]:ring-1 data-[focus=true]:ring-ring
9
+ data-disabled:cursor-not-allowed data-disabled:opacity-50 md:text-sm relative
10
+ items-center
11
+ HEREDOC
12
+
13
+ INPUT_STYLES = <<~HEREDOC
14
+ h-9 py-1
15
+ text-base md:text-sm outline-none w-[45%]
16
+ HEREDOC
17
+
18
+ CLEAR_BUTTON_STYLES = TAILWIND_MERGER.merge("#{Button.default_styles(
19
+ variant: :ghost,
20
+ size: :icon,
21
+ )} text-muted-foreground h-6 w-6")
22
+
23
+ def initialize(start_date: nil, end_date: nil, start_date_name: nil, end_date_name: nil, format: "DD/MM/YYYY",
24
+ disabled: false, settings: {}, **attributes)
25
+ @start_date = start_date&.utc&.iso8601
26
+ @end_date = end_date&.utc&.iso8601
27
+ @start_date_name = start_date_name
28
+ @end_date_name = end_date_name
29
+ @settings = settings
30
+ @format = format
31
+ @disabled = disabled
32
+ super(**attributes)
33
+ end
34
+
35
+ def default_attributes
36
+ {
37
+ data: {
38
+ start_date: @start_date,
39
+ end_date: @end_date,
40
+ format: @format,
41
+ controller: "shadcn-phlexcomponents--date-range-picker",
42
+ settings: @settings.to_json,
43
+ has_value: (@start_date.present? && @end_date.present?).to_s,
44
+ disabled: @disabled,
45
+ action: <<~HEREDOC,
46
+ mouseover->shadcn-phlexcomponents--date-range-picker#showClearButton
47
+ mouseout->shadcn-phlexcomponents--date-range-picker#hideClearButton
48
+ HEREDOC
49
+ },
50
+ }
51
+ end
52
+
53
+ def view_template
54
+ div(**@attributes) do
55
+ input(type: :text, class: INPUT_STYLES, data: {
56
+ "shadcn-phlexcomponents--date-range-picker-target": "startDateInput",
57
+ action: <<~HEREDOC,
58
+ focus->shadcn-phlexcomponents--date-range-picker#openCalendar
59
+ input->shadcn-phlexcomponents--date-range-picker#changeDate
60
+ keydown->shadcn-phlexcomponents--date-range-picker#closeCalendar
61
+ HEREDOC
62
+ })
63
+ input(
64
+ type: :hidden,
65
+ name: @start_date_name,
66
+ value: @start_date,
67
+ data: { "shadcn-phlexcomponents--date-range-picker-target": "startDateHiddenInput" },
68
+ )
69
+
70
+ icon("minus", class: "size-4 text-muted-foreground px-3 w-[10%]")
71
+
72
+ input(type: :text, class: INPUT_STYLES, data: {
73
+ "shadcn-phlexcomponents--date-range-picker-target": "endDateInput",
74
+ action: <<~HEREDOC,
75
+ focus->shadcn-phlexcomponents--date-range-picker#openCalendar
76
+ input->shadcn-phlexcomponents--date-range-picker#changeDate
77
+ keydown->shadcn-phlexcomponents--date-range-picker#closeCalendar
78
+ HEREDOC
79
+ })
80
+ input(
81
+ type: :hidden,
82
+ name: @end_date_name,
83
+ value: @end_date,
84
+ data: { "shadcn-phlexcomponents--date-range-picker-target": "endDateHiddenInput" },
85
+ )
86
+
87
+ div(class: "absolute right-3 inset-y-0 flex items-center -z-1") do
88
+ span(class: "pointer-events-none size-6 inline-flex items-center justify-center") do
89
+ icon(
90
+ "calendar",
91
+ class: "size-4 text-muted-foreground",
92
+ data: { "shadcn-phlexcomponents--date-range-picker-target": "calendarIcon" },
93
+ )
94
+ end
95
+ end
96
+
97
+ div(class: "absolute right-3 inset-y-0 flex items-center") do
98
+ button(
99
+ type: :button,
100
+ class: "#{CLEAR_BUTTON_STYLES} !hidden",
101
+ tabindex: -1,
102
+ data: {
103
+ action: "shadcn-phlexcomponents--date-range-picker#clear:stop",
104
+ "shadcn-phlexcomponents--date-range-picker-target": "clearButton",
105
+ },
106
+ ) do
107
+ icon("x")
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -49,4 +49,4 @@ module ShadcnPhlexcomponents
49
49
  div(**@attributes, &)
50
50
  end
51
51
  end
52
- end
52
+ end
@@ -39,4 +39,4 @@ module ShadcnPhlexcomponents
39
39
  end
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -34,7 +34,7 @@ module ShadcnPhlexcomponents
34
34
  },
35
35
  data: {
36
36
  "shadcn-phlexcomponents--dialog-target": "content",
37
- state: "closed"
37
+ state: "closed",
38
38
  },
39
39
  }
40
40
  end
@@ -51,4 +51,4 @@ module ShadcnPhlexcomponents
51
51
  end
52
52
  end
53
53
  end
54
- end
54
+ end
@@ -19,4 +19,4 @@ module ShadcnPhlexcomponents
19
19
  p(**@attributes, &)
20
20
  end
21
21
  end
22
- end
22
+ end
@@ -8,4 +8,4 @@ module ShadcnPhlexcomponents
8
8
  div(**@attributes, &)
9
9
  end
10
10
  end
11
- end
11
+ end
@@ -8,4 +8,4 @@ module ShadcnPhlexcomponents
8
8
  div(**@attributes, &)
9
9
  end
10
10
  end
11
- end
11
+ end
@@ -19,4 +19,4 @@ module ShadcnPhlexcomponents
19
19
  h2(**@attributes, &)
20
20
  end
21
21
  end
22
- end
22
+ end
@@ -19,7 +19,7 @@ module ShadcnPhlexcomponents
19
19
  data: {
20
20
  action: "click->shadcn-phlexcomponents--dialog#open",
21
21
  "shadcn-phlexcomponents--dialog-target": "trigger",
22
- as_child: @as_child.to_s
22
+ as_child: @as_child.to_s,
23
23
  },
24
24
  }
25
25
  end
@@ -47,4 +47,4 @@ module ShadcnPhlexcomponents
47
47
  end
48
48
  end
49
49
  end
50
- end
50
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class DropdownMenu < Base
5
- STYLES = "inline-block".freeze
5
+ STYLES = "inline-block"
6
6
 
7
7
  def initialize(side: :bottom, aria_id: "dropdown-menu-#{SecureRandom.hex(5)}", **attributes)
8
8
  @side = side
@@ -16,7 +16,7 @@ module ShadcnPhlexcomponents
16
16
 
17
17
  def content(**attributes, &)
18
18
  DropdownMenuContent(aria_id: @aria_id, side: @side, **attributes, &)
19
- end
19
+ end
20
20
 
21
21
  def label(**attributes, &)
22
22
  DropdownMenuLabel(**attributes, &)
@@ -38,8 +38,8 @@ module ShadcnPhlexcomponents
38
38
  {
39
39
  data: {
40
40
  controller: "shadcn-phlexcomponents--dropdown-menu",
41
- side: @side
42
- }
41
+ side: @side,
42
+ },
43
43
  }
44
44
  end
45
45
 
@@ -47,4 +47,4 @@ module ShadcnPhlexcomponents
47
47
  div(**@attributes, &)
48
48
  end
49
49
  end
50
- end
50
+ end
@@ -2,14 +2,14 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class DropdownMenuContent < Base
5
- STYLES = <<~HEREDOC.freeze
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
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
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
 
@@ -20,7 +20,10 @@ module ShadcnPhlexcomponents
20
20
  end
21
21
 
22
22
  def view_template(&)
23
- div(class: "hidden fixed top-0 left-0 w-max z-50", data: { "shadcn-phlexcomponents--dropdown-menu-target": "contentWrapper" }) do
23
+ div(
24
+ class: "hidden fixed top-0 left-0 w-max z-50",
25
+ data: { "shadcn-phlexcomponents--dropdown-menu-target": "contentWrapper" },
26
+ ) do
24
27
  div(**@attributes, &)
25
28
  end
26
29
  end
@@ -32,7 +35,7 @@ module ShadcnPhlexcomponents
32
35
  role: "menu",
33
36
  aria: {
34
37
  labelledby: "#{@aria_id}-trigger",
35
- orientation: "vertical"
38
+ orientation: "vertical",
36
39
  },
37
40
  data: {
38
41
  state: "closed",
@@ -42,8 +45,8 @@ module ShadcnPhlexcomponents
42
45
  keydown.up->shadcn-phlexcomponents--dropdown-menu#focusLastItem:prevent
43
46
  keydown.down->shadcn-phlexcomponents--dropdown-menu#focusFirstItem:prevent
44
47
  HEREDOC
45
- }
48
+ },
46
49
  }
47
50
  end
48
51
  end
49
- end
52
+ end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShadcnPhlexcomponents
4
-
5
4
  class DropdownMenuItem < Base
6
- STYLES = <<~HEREDOC.freeze
5
+ STYLES = <<~HEREDOC
7
6
  relative flex cursor-default select-none items-center gap-2 rounded-sm px-2
8
7
  py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground
9
8
  data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0
@@ -26,7 +25,7 @@ module ShadcnPhlexcomponents
26
25
  merged_attributes = mix(@attributes, element_attributes)
27
26
  merged_attributes[:class] = styles
28
27
 
29
- send(element.name, **merged_attributes) do
28
+ send(element.name, **merged_attributes) do
30
29
  sanitize_as_child(element.children.to_s)
31
30
  end
32
31
  else
@@ -49,9 +48,9 @@ module ShadcnPhlexcomponents
49
48
  mouseover->shadcn-phlexcomponents--dropdown-menu#focusItem
50
49
  mouseout->shadcn-phlexcomponents--dropdown-menu#focusContent
51
50
  HEREDOC
52
- "shadcn-phlexcomponents--dropdown-menu-target": "item"
53
- }
51
+ "shadcn-phlexcomponents--dropdown-menu-target": "item",
52
+ },
54
53
  }
55
54
  end
56
55
  end
57
- end
56
+ end
@@ -9,12 +9,15 @@ module ShadcnPhlexcomponents
9
9
  end
10
10
 
11
11
  def view_template(&)
12
- @html_options, @options = @options, @name if block_given?
12
+ if block_given?
13
+ @html_options = @options
14
+ @options = @name
15
+ end
13
16
  @html_options ||= {}
14
17
  @disabled = @html_options[:disabled]
15
18
  @html_options = mix(default_attributes, @html_options)
16
19
  @html_options[:class] = TAILWIND_MERGER.merge("w-full #{default_styles} #{@html_options[:class]}")
17
-
20
+
18
21
  if block_given?
19
22
  button_to(@options, @html_options, &)
20
23
  else
@@ -22,4 +25,4 @@ module ShadcnPhlexcomponents
22
25
  end
23
26
  end
24
27
  end
25
- end
28
+ end
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShadcnPhlexcomponents
4
-
5
4
  class DropdownMenuLabel < Base
6
- STYLES = "px-2 py-1.5 text-sm font-semibold".freeze
5
+ STYLES = "px-2 py-1.5 text-sm font-semibold"
7
6
 
8
7
  def view_template(&)
9
8
  div(**@attributes, &)
10
9
  end
11
10
  end
12
- end
11
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
- module ShadcnPhlexcomponents
3
2
 
3
+ module ShadcnPhlexcomponents
4
4
  class DropdownMenuSeparator < Base
5
- STYLES = "-mx-1 my-1 h-px bg-muted".freeze
5
+ STYLES = "-mx-1 my-1 h-px bg-muted"
6
6
 
7
7
  def view_template(&)
8
8
  div(**@attributes, &)
@@ -12,9 +12,9 @@ module ShadcnPhlexcomponents
12
12
  {
13
13
  role: "separator",
14
14
  aria: {
15
- orientation: "horizontal"
16
- }
15
+ orientation: "horizontal",
16
+ },
17
17
  }
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShadcnPhlexcomponents
4
-
5
4
  class DropdownMenuTrigger < Base
6
5
  def initialize(as_child: false, aria_id: nil, **attributes)
7
6
  @as_child = as_child
@@ -24,7 +23,7 @@ module ShadcnPhlexcomponents
24
23
  merged_attributes.delete(:role)
25
24
  end
26
25
 
27
- send(element.name, **merged_attributes) do
26
+ send(element.name, **merged_attributes) do
28
27
  sanitize_as_child(element.children.to_s)
29
28
  end
30
29
  else
@@ -39,20 +38,20 @@ module ShadcnPhlexcomponents
39
38
  aria: {
40
39
  haspopup: "menu",
41
40
  expanded: false,
42
- controls: "#{@aria_id}-content"
41
+ controls: "#{@aria_id}-content",
43
42
  },
44
43
  data: {
45
44
  state: "closed",
46
45
  as_child: @as_child.to_s,
47
46
  action: <<~HEREDOC,
48
- click->shadcn-phlexcomponents--dropdown-menu#toggle
49
- keydown.space->shadcn-phlexcomponents--dropdown-menu#toggle
50
- keydown.enter->shadcn-phlexcomponents--dropdown-menu#toggle
51
- keydown.down->shadcn-phlexcomponents--dropdown-menu#toggle:prevent
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
52
51
  HEREDOC
53
- "shadcn-phlexcomponents--dropdown-menu-target": "trigger"
54
- }
52
+ "shadcn-phlexcomponents--dropdown-menu-target": "trigger",
53
+ },
55
54
  }
56
55
  end
57
56
  end
58
- end
57
+ end
@@ -0,0 +1,59 @@
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, **options)
8
+ @model = model
9
+ @scope = scope
10
+ @url = url
11
+ @format = format
12
+ @options = options
13
+ @object_name = model ? model.to_model.model_name.param_key : nil
14
+ end
15
+
16
+ def field(method = nil, **attributes, &)
17
+ FormField(method, model: @model, object_name: @object_name, **attributes, &)
18
+ end
19
+
20
+ def submit(variant: :primary, **attributes, &)
21
+ Button(variant: variant, type: :submit, **attributes) do
22
+ if block_given?
23
+ yield
24
+ else
25
+ submit_default_value
26
+ end
27
+ end
28
+ end
29
+
30
+ def view_template(&)
31
+ form_with(model: @model, scope: @scope, url: @url, format: @format, **@options) do
32
+ yield
33
+ end
34
+ end
35
+
36
+ def submit_default_value
37
+ object = @model ? @model.to_model : nil
38
+ key = object ? (object.persisted? ? :update : :create) : :submit
39
+
40
+ model = if object.respond_to?(:model_name)
41
+ object.model_name.human
42
+ else
43
+ @object_name.to_s.humanize
44
+ end
45
+
46
+ defaults = []
47
+ # Object is a model and it is not overwritten by as and scope option.
48
+ if object.respond_to?(:model_name) && @object_name.to_s == model.downcase
49
+ defaults << :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
50
+ else
51
+ defaults << :"helpers.submit.#{@object_name}.#{key}"
52
+ end
53
+ defaults << :"helpers.submit.#{key}"
54
+ defaults << "#{key.to_s.humanize} #{model}"
55
+
56
+ I18n.t(defaults.shift, model: model, default: defaults)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormError < Base
5
+ STYLES = "text-[0.8rem] font-medium text-destructive"
6
+
7
+ def initialize(message: nil, aria_id: nil, **attributes)
8
+ @message = message
9
+ @id = aria_id ? "#{aria_id}-message" : nil
10
+ super(**attributes)
11
+ end
12
+
13
+ def view_template(&)
14
+ p(id: @id, **@attributes) { @message }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormHint < Base
5
+ STYLES = "text-[0.8rem] text-muted-foreground"
6
+
7
+ def initialize(message: nil, aria_id: nil, **attributes)
8
+ @message = message
9
+ @id = aria_id ? "#{aria_id}-description" : nil
10
+ super(**attributes)
11
+ end
12
+
13
+ def view_template(&)
14
+ p(id: @id, **@attributes) { @message }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShadcnPhlexcomponents
4
+ class FormInput < Base
5
+ include FormHelpers
6
+
7
+ def initialize(
8
+ method = nil,
9
+ model: false,
10
+ object_name: nil,
11
+ type: :text,
12
+ value: nil,
13
+ name: nil,
14
+ id: nil,
15
+ label: nil,
16
+ error: nil,
17
+ hint: nil,
18
+ **attributes
19
+ )
20
+ @method = method
21
+ @model = model
22
+ @object_name = object_name
23
+ @type = type.to_sym
24
+ @value = value
25
+ @model_value = model&.public_send(method)
26
+ @name = name
27
+ @id = id
28
+ @label = label
29
+ @error = error || (model ? model.errors.full_messages_for(method).first : nil)
30
+ @hint = hint
31
+ @aria_id = "form-field-#{SecureRandom.hex(5)}"
32
+ super(**attributes)
33
+ end
34
+
35
+ def view_template(&)
36
+ vanish(&)
37
+
38
+ @id ||= field_id(@object_name, @method)
39
+ @name ||= field_name(@object_name, @method)
40
+
41
+ div(class: "space-y-2", data: label_and_hint_container_attributes) do
42
+ render_label(&)
43
+ Input(type: @type, id: @id, name: @name, value: @value || @model_value, aria: aria_attributes, **@attributes)
44
+ render_hint(&)
45
+ render_error
46
+ end
47
+ end
48
+ end
49
+ end