shadcn-rails 0.1.0 → 0.2.1

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -2
  3. data/README.md +102 -1398
  4. data/__mocks__/@floating-ui/dom.js +67 -0
  5. data/app/assets/javascripts/shadcn/controllers/base_menu_controller.js +266 -0
  6. data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +34 -8
  7. data/app/assets/javascripts/shadcn/controllers/command_controller.js +5 -1
  8. data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +64 -135
  9. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +56 -186
  10. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
  11. data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +10 -7
  12. data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +10 -6
  13. data/app/assets/javascripts/shadcn/controllers/popover_controller.js +35 -60
  14. data/app/assets/javascripts/shadcn/controllers/select_controller.js +37 -17
  15. data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +24 -14
  16. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
  17. data/app/assets/javascripts/shadcn/index.js +9 -1
  18. data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
  19. data/app/assets/stylesheets/shadcn/base.css +32 -0
  20. data/app/assets/stylesheets/shadcn/components.css +12 -0
  21. data/app/components/shadcn/accordion_component.html.erb +8 -0
  22. data/app/components/shadcn/accordion_component.rb +6 -15
  23. data/app/components/shadcn/alert_component.html.erb +6 -0
  24. data/app/components/shadcn/alert_component.rb +0 -18
  25. data/app/components/shadcn/alert_dialog_component.html.erb +12 -0
  26. data/app/components/shadcn/alert_dialog_component.rb +7 -27
  27. data/app/components/shadcn/aspect_ratio_component.html.erb +7 -0
  28. data/app/components/shadcn/aspect_ratio_component.rb +4 -19
  29. data/app/components/shadcn/avatar_component.html.erb +20 -0
  30. data/app/components/shadcn/avatar_component.rb +8 -36
  31. data/app/components/shadcn/badge_component.html.erb +1 -0
  32. data/app/components/shadcn/badge_component.rb +0 -11
  33. data/app/components/shadcn/base_component.rb +15 -2
  34. data/app/components/shadcn/breadcrumb_component.html.erb +5 -0
  35. data/app/components/shadcn/breadcrumb_component.rb +6 -16
  36. data/app/components/shadcn/button_component.html.erb +18 -0
  37. data/app/components/shadcn/button_component.rb +1 -41
  38. data/app/components/shadcn/card_component.html.erb +8 -0
  39. data/app/components/shadcn/card_component.rb +2 -6
  40. data/app/components/shadcn/checkbox_component.html.erb +32 -0
  41. data/app/components/shadcn/checkbox_component.rb +4 -43
  42. data/app/components/shadcn/collapsible_component.html.erb +8 -0
  43. data/app/components/shadcn/collapsible_component.rb +6 -15
  44. data/app/components/shadcn/command_list_component.rb +29 -14
  45. data/app/components/shadcn/context_menu_checkbox_item_component.rb +76 -0
  46. data/app/components/shadcn/context_menu_component.html.erb +11 -0
  47. data/app/components/shadcn/context_menu_component.rb +6 -26
  48. data/app/components/shadcn/context_menu_content_component.rb +37 -14
  49. data/app/components/shadcn/context_menu_item_component.rb +3 -2
  50. data/app/components/shadcn/context_menu_radio_group_component.rb +42 -0
  51. data/app/components/shadcn/context_menu_radio_item_component.rb +76 -0
  52. data/app/components/shadcn/dialog_component.html.erb +14 -0
  53. data/app/components/shadcn/dialog_component.rb +8 -29
  54. data/app/components/shadcn/drawer_component.html.erb +12 -0
  55. data/app/components/shadcn/drawer_component.rb +7 -27
  56. data/app/components/shadcn/dropdown_menu_checkbox_item_component.rb +76 -0
  57. data/app/components/shadcn/dropdown_menu_component.html.erb +14 -0
  58. data/app/components/shadcn/dropdown_menu_component.rb +9 -29
  59. data/app/components/shadcn/dropdown_menu_content_component.rb +45 -16
  60. data/app/components/shadcn/dropdown_menu_radio_group_component.rb +42 -0
  61. data/app/components/shadcn/dropdown_menu_radio_item_component.rb +76 -0
  62. data/app/components/shadcn/field_component.rb +7 -8
  63. data/app/components/shadcn/hover_card_component.html.erb +12 -0
  64. data/app/components/shadcn/hover_card_component.rb +7 -26
  65. data/app/components/shadcn/input_component.html.erb +18 -0
  66. data/app/components/shadcn/input_component.rb +2 -27
  67. data/app/components/shadcn/input_otp_component.rb +3 -3
  68. data/app/components/shadcn/kbd_component.html.erb +1 -0
  69. data/app/components/shadcn/kbd_component.rb +3 -10
  70. data/app/components/shadcn/label_component.html.erb +3 -0
  71. data/app/components/shadcn/label_component.rb +2 -18
  72. data/app/components/shadcn/menubar_component.html.erb +6 -0
  73. data/app/components/shadcn/menubar_component.rb +4 -15
  74. data/app/components/shadcn/menubar_content_component.rb +45 -20
  75. data/app/components/shadcn/menubar_sub_content_component.rb +21 -8
  76. data/app/components/shadcn/native_select_component.html.erb +22 -0
  77. data/app/components/shadcn/native_select_component.rb +9 -39
  78. data/app/components/shadcn/navigation_menu_component.html.erb +6 -0
  79. data/app/components/shadcn/navigation_menu_component.rb +4 -15
  80. data/app/components/shadcn/pagination_component.html.erb +5 -0
  81. data/app/components/shadcn/pagination_component.rb +11 -15
  82. data/app/components/shadcn/popover_component.html.erb +15 -0
  83. data/app/components/shadcn/popover_component.rb +10 -30
  84. data/app/components/shadcn/progress_component.html.erb +13 -0
  85. data/app/components/shadcn/progress_component.rb +6 -26
  86. data/app/components/shadcn/radio_group_component.html.erb +8 -0
  87. data/app/components/shadcn/radio_group_component.rb +12 -26
  88. data/app/components/shadcn/radio_group_item_component.rb +32 -6
  89. data/app/components/shadcn/resizable_panel_group_component.rb +27 -16
  90. data/app/components/shadcn/scroll_area_component.html.erb +7 -0
  91. data/app/components/shadcn/scroll_area_component.rb +4 -16
  92. data/app/components/shadcn/select_component.html.erb +46 -0
  93. data/app/components/shadcn/select_component.rb +29 -86
  94. data/app/components/shadcn/separator_component.html.erb +5 -0
  95. data/app/components/shadcn/separator_component.rb +6 -14
  96. data/app/components/shadcn/sheet_component.html.erb +12 -0
  97. data/app/components/shadcn/sheet_component.rb +7 -27
  98. data/app/components/shadcn/sidebar_component.rb +2 -2
  99. data/app/components/shadcn/skeleton_component.html.erb +1 -0
  100. data/app/components/shadcn/skeleton_component.rb +4 -2
  101. data/app/components/shadcn/slider_component.html.erb +12 -0
  102. data/app/components/shadcn/slider_component.rb +2 -21
  103. data/app/components/shadcn/spinner_component.html.erb +18 -0
  104. data/app/components/shadcn/spinner_component.rb +2 -30
  105. data/app/components/shadcn/switch_component.html.erb +72 -0
  106. data/app/components/shadcn/switch_component.rb +4 -82
  107. data/app/components/shadcn/table_component.html.erb +9 -0
  108. data/app/components/shadcn/table_component.rb +2 -10
  109. data/app/components/shadcn/tabs_component.html.erb +8 -0
  110. data/app/components/shadcn/tabs_component.rb +4 -17
  111. data/app/components/shadcn/textarea_component.html.erb +13 -0
  112. data/app/components/shadcn/textarea_component.rb +6 -22
  113. data/app/components/shadcn/toast_component.html.erb +36 -0
  114. data/app/components/shadcn/toast_component.rb +6 -54
  115. data/app/components/shadcn/toggle_component.html.erb +12 -0
  116. data/app/components/shadcn/toggle_component.rb +6 -21
  117. data/app/components/shadcn/toggle_group_component.html.erb +14 -0
  118. data/app/components/shadcn/toggle_group_component.rb +6 -29
  119. data/app/components/shadcn/tooltip_component.html.erb +20 -0
  120. data/app/components/shadcn/tooltip_component.rb +13 -38
  121. data/lib/generators/shadcn/add/USAGE +24 -0
  122. data/lib/generators/shadcn/add/add_generator.rb +279 -0
  123. data/lib/generators/shadcn/install/USAGE +22 -0
  124. data/lib/generators/shadcn/install/install_generator.rb +8 -3
  125. data/lib/generators/shadcn/install/templates/initializer.rb.tt +7 -27
  126. data/lib/generators/shadcn/install/templates/shadcn.yml.tt +15 -31
  127. data/lib/shadcn/rails/version.rb +1 -1
  128. metadata +54 -42
  129. data/.dockerignore +0 -40
  130. data/CLAUDE.md +0 -463
  131. data/PROGRESS.md +0 -485
  132. data/Rakefile +0 -29
  133. data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +0 -13
  134. data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +0 -46
  135. data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +0 -111
  136. data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +0 -27
  137. data/__tests__/controllers/accordion_controller.test.js +0 -904
  138. data/__tests__/controllers/calendar_controller.test.js +0 -1370
  139. data/__tests__/controllers/carousel_controller.test.js +0 -912
  140. data/__tests__/controllers/checkbox_controller.test.js +0 -454
  141. data/__tests__/controllers/collapsible_controller.test.js +0 -407
  142. data/__tests__/controllers/combobox_controller.test.js +0 -966
  143. data/__tests__/controllers/context_menu_controller.test.js +0 -627
  144. data/__tests__/controllers/date_picker_controller.test.js +0 -636
  145. data/__tests__/controllers/dialog_controller.test.js +0 -878
  146. data/__tests__/controllers/drawer_controller.test.js +0 -995
  147. data/__tests__/controllers/menubar_controller.test.js +0 -736
  148. data/__tests__/controllers/navigation_menu_controller.test.js +0 -598
  149. data/__tests__/controllers/popover_controller.test.js +0 -1007
  150. data/__tests__/controllers/radio_group_controller.test.js +0 -640
  151. data/__tests__/controllers/resizable_controller.test.js +0 -680
  152. data/__tests__/controllers/select_controller.test.js +0 -674
  153. data/__tests__/controllers/sheet_controller.test.js +0 -986
  154. data/__tests__/controllers/slider_controller.test.js +0 -1036
  155. data/__tests__/controllers/switch_controller.test.js +0 -424
  156. data/__tests__/controllers/tabs_controller.test.js +0 -907
  157. data/__tests__/controllers/toggle_group_controller.test.js +0 -839
  158. data/__tests__/controllers/tooltip_controller.test.js +0 -808
  159. data/__tests__/helpers/stimulus-test-helper.js +0 -203
  160. data/babel.config.cjs +0 -5
  161. data/bin/console +0 -11
  162. data/bin/setup +0 -8
  163. data/jest.config.js +0 -19
  164. data/jest.setup.js +0 -8
  165. data/lib/generators/shadcn/component/component_generator.rb +0 -188
  166. data/lib/generators/shadcn/theme/theme_generator.rb +0 -128
  167. data/package-lock.json +0 -7415
  168. data/package.json +0 -68
  169. data/rollup.config.js +0 -29
@@ -22,8 +22,10 @@ module Shadcn
22
22
  class SkeletonComponent < BaseComponent
23
23
  BASE_CLASSES = "animate-pulse rounded-md bg-primary/10"
24
24
 
25
- def call
26
- content_tag(:div, content, class: merge_classes(BASE_CLASSES), **html_options.merge(build_data))
25
+ private
26
+
27
+ def skeleton_classes
28
+ merge_classes(BASE_CLASSES)
27
29
  end
28
30
  end
29
31
  end
@@ -0,0 +1,12 @@
1
+ <input type="range"
2
+ <%= "name=\"#{ERB::Util.html_escape_once(@name)}\"".html_safe if @name %>
3
+ value="<%= @value %>"
4
+ min="<%= @min %>"
5
+ max="<%= @max %>"
6
+ step="<%= @step %>"
7
+ <%= "disabled" if @disabled %>
8
+ class="<%= slider_classes %>"
9
+ style="<%= slider_style %>"
10
+ data-controller="shadcn--slider"
11
+ data-action="input->shadcn--slider#updateStyle"
12
+ <%= tag_attributes %> />
@@ -38,29 +38,10 @@ module Shadcn
38
38
  @disabled = disabled
39
39
  end
40
40
 
41
- def call
42
- tag(:input, input_attributes)
43
- end
44
-
45
41
  private
46
42
 
47
- def input_attributes
48
- attrs = {
49
- type: "range",
50
- name: @name,
51
- value: @value,
52
- min: @min,
53
- max: @max,
54
- step: @step,
55
- disabled: @disabled ? true : nil,
56
- class: merge_classes(BASE_CLASSES),
57
- style: slider_style,
58
- "data-controller": "shadcn--slider",
59
- "data-action": "input->shadcn--slider#updateStyle"
60
- }
61
- attrs.merge!(html_options)
62
- attrs.merge!(build_data)
63
- attrs.compact
43
+ def slider_classes
44
+ merge_classes(BASE_CLASSES)
64
45
  end
65
46
 
66
47
  def slider_style
@@ -0,0 +1,18 @@
1
+ <svg class="<%= spinner_classes %>"
2
+ xmlns="http://www.w3.org/2000/svg"
3
+ fill="none"
4
+ viewBox="0 0 24 24"
5
+ role="status"
6
+ aria-label="Loading"
7
+ <%= tag_attributes %>>
8
+ <circle class="opacity-25"
9
+ cx="12"
10
+ cy="12"
11
+ r="10"
12
+ stroke="currentColor"
13
+ stroke-width="4"
14
+ fill="none"></circle>
15
+ <path class="opacity-75"
16
+ fill="currentColor"
17
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
18
+ </svg>
@@ -30,38 +30,10 @@ module Shadcn
30
30
  @size = size.to_sym
31
31
  end
32
32
 
33
- def call
34
- tag.svg(**spinner_attributes) do
35
- safe_join([
36
- tag.circle(
37
- class: "opacity-25",
38
- cx: "12",
39
- cy: "12",
40
- r: "10",
41
- stroke: "currentColor",
42
- "stroke-width": "4",
43
- fill: "none"
44
- ),
45
- tag.path(
46
- class: "opacity-75",
47
- fill: "currentColor",
48
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
49
- )
50
- ])
51
- end
52
- end
53
-
54
33
  private
55
34
 
56
- def spinner_attributes
57
- {
58
- class: cn(BASE_CLASSES, SIZES[@size], class_name),
59
- xmlns: "http://www.w3.org/2000/svg",
60
- fill: "none",
61
- viewBox: "0 0 24 24",
62
- role: "status",
63
- "aria-label": "Loading"
64
- }.merge(html_options).merge(build_data).compact
35
+ def spinner_classes
36
+ cn(BASE_CLASSES, SIZES[@size], class_name)
65
37
  end
66
38
  end
67
39
  end
@@ -0,0 +1,72 @@
1
+ <% if has_label? %>
2
+ <label class="flex items-center gap-3 cursor-pointer">
3
+ <span class="inline-flex items-center"
4
+ data-controller="shadcn--switch"
5
+ data-shadcn--switch-checked-value="<%= @checked %>">
6
+ <% if @name %>
7
+ <input type="hidden" name="<%= ERB::Util.html_escape_once(@name) %>" value="0" autocomplete="off">
8
+ <input type="checkbox"
9
+ class="sr-only"
10
+ name="<%= ERB::Util.html_escape_once(@name) %>"<% if @id %>
11
+ id="<%= ERB::Util.html_escape_once(@id) %>"<% end %>
12
+ value="<%= ERB::Util.html_escape_once(@value) %>"<% if @checked %>
13
+ checked<% end %><% if @disabled %>
14
+ disabled<% end %><% if @required %>
15
+ required<% end %>
16
+ data-shadcn--switch-target="input"
17
+ tabindex="-1">
18
+ <% end %>
19
+ <button type="button"
20
+ role="switch"
21
+ class="<%= switch_classes %>"<% if @disabled %>
22
+ disabled<% end %>
23
+ aria-checked="<%= @checked %>"<% if @required %>
24
+ aria-required="true"<% end %>
25
+ data-state="<%= state %>"
26
+ data-shadcn--switch-target="button"
27
+ data-action="click->shadcn--switch#toggle keydown->shadcn--switch#handleKeydown"
28
+ tabindex="0"
29
+ <%= tag_attributes %>>
30
+ <span class="<%= THUMB_CLASSES %>"
31
+ data-state="<%= state %>"
32
+ data-shadcn--switch-target="thumb"></span>
33
+ </button>
34
+ </span>
35
+ <span class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
36
+ <%= content %>
37
+ </span>
38
+ </label>
39
+ <% else %>
40
+ <span class="inline-flex items-center"
41
+ data-controller="shadcn--switch"
42
+ data-shadcn--switch-checked-value="<%= @checked %>">
43
+ <% if @name %>
44
+ <input type="hidden" name="<%= ERB::Util.html_escape_once(@name) %>" value="0" autocomplete="off">
45
+ <input type="checkbox"
46
+ class="sr-only"
47
+ name="<%= ERB::Util.html_escape_once(@name) %>"<% if @id %>
48
+ id="<%= ERB::Util.html_escape_once(@id) %>"<% end %>
49
+ value="<%= ERB::Util.html_escape_once(@value) %>"<% if @checked %>
50
+ checked<% end %><% if @disabled %>
51
+ disabled<% end %><% if @required %>
52
+ required<% end %>
53
+ data-shadcn--switch-target="input"
54
+ tabindex="-1">
55
+ <% end %>
56
+ <button type="button"
57
+ role="switch"
58
+ class="<%= switch_classes %>"<% if @disabled %>
59
+ disabled<% end %>
60
+ aria-checked="<%= @checked %>"<% if @required %>
61
+ aria-required="true"<% end %>
62
+ data-state="<%= state %>"
63
+ data-shadcn--switch-target="button"
64
+ data-action="click->shadcn--switch#toggle keydown->shadcn--switch#handleKeydown"
65
+ tabindex="0"
66
+ <%= tag_attributes %>>
67
+ <span class="<%= THUMB_CLASSES %>"
68
+ data-state="<%= state %>"
69
+ data-shadcn--switch-target="thumb"></span>
70
+ </button>
71
+ </span>
72
+ <% end %>
@@ -52,96 +52,18 @@ module Shadcn
52
52
  @required = required
53
53
  end
54
54
 
55
- def call
56
- if content.present?
57
- # Render with integrated label
58
- content_tag(:label, class: "flex items-center gap-3 cursor-pointer") do
59
- safe_join([
60
- switch_wrapper,
61
- content_tag(:span, content, class: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70")
62
- ])
63
- end
64
- else
65
- switch_wrapper
66
- end
67
- end
68
-
69
55
  private
70
56
 
71
- def switch_wrapper
72
- content_tag(:span, wrapper_attributes) do
73
- safe_join([
74
- hidden_unchecked_input,
75
- hidden_input,
76
- switch_button
77
- ].compact)
78
- end
79
- end
80
-
81
- def wrapper_attributes
82
- {
83
- class: "inline-flex items-center",
84
- "data-controller": "shadcn--switch",
85
- "data-shadcn--switch-checked-value": @checked.to_s
86
- }
87
- end
88
-
89
- def hidden_unchecked_input
90
- # Rails convention: hidden input with "0" for unchecked state
91
- return unless @name
92
-
93
- tag(:input,
94
- type: "hidden",
95
- name: @name,
96
- value: "0",
97
- autocomplete: "off"
98
- )
99
- end
100
-
101
- def hidden_input
102
- return unless @name
103
-
104
- tag(:input,
105
- type: "checkbox",
106
- name: @name,
107
- id: @id,
108
- value: @value,
109
- checked: @checked || nil,
110
- disabled: @disabled || nil,
111
- required: @required || nil,
112
- class: "sr-only",
113
- "data-shadcn--switch-target": "input",
114
- tabindex: "-1"
115
- )
116
- end
117
-
118
- def switch_button
119
- content_tag(:button, switch_thumb, switch_button_attributes)
120
- end
121
-
122
- def switch_thumb
123
- content_tag(:span, "", class: THUMB_CLASSES, "data-state": state, "data-shadcn--switch-target": "thumb")
57
+ def has_label?
58
+ content.present?
124
59
  end
125
60
 
126
61
  def state
127
62
  @checked ? "checked" : "unchecked"
128
63
  end
129
64
 
130
- def switch_button_attributes
131
- attrs = {
132
- type: "button",
133
- role: "switch",
134
- class: cn(BASE_CLASSES, class_name),
135
- disabled: @disabled || nil,
136
- "aria-checked": @checked.to_s,
137
- "aria-required": @required ? "true" : nil,
138
- "data-state": state,
139
- "data-shadcn--switch-target": "button",
140
- "data-action": "click->shadcn--switch#toggle keydown->shadcn--switch#handleKeydown",
141
- tabindex: "0"
142
- }
143
- attrs.merge!(html_options.except(:class))
144
- attrs.compact
65
+ def switch_classes
66
+ cn(BASE_CLASSES, class_name)
145
67
  end
146
68
  end
147
69
  end
@@ -0,0 +1,9 @@
1
+ <div class="relative w-full overflow-auto">
2
+ <table class="<%= table_classes %>">
3
+ <%= caption %>
4
+ <%= header %>
5
+ <%= body %>
6
+ <%= footer %>
7
+ <%= content %>
8
+ </table>
9
+ </div>
@@ -40,18 +40,10 @@ module Shadcn
40
40
  TableFooterComponent.new(**options)
41
41
  }
42
42
 
43
- def call
44
- content_tag(:div, table_element, class: "relative w-full overflow-auto")
45
- end
46
-
47
43
  private
48
44
 
49
- def table_element
50
- content_tag(:table, table_content, class: merge_classes(BASE_CLASSES))
51
- end
52
-
53
- def table_content
54
- safe_join([caption, header, body, footer, content].compact)
45
+ def table_classes
46
+ merge_classes(BASE_CLASSES)
55
47
  end
56
48
  end
57
49
  end
@@ -0,0 +1,8 @@
1
+ <div class="<%= tabs_classes %>"
2
+ data-controller="shadcn--tabs"
3
+ <% if @default_value %>data-shadcn--tabs-default-value="<%= @default_value %>"<% end %>
4
+ <% if @url_param %>data-shadcn--tabs-url-param-value="<%= @url_param %>"<% end %>
5
+ data-orientation="<%= @orientation %>"
6
+ <%= tag_attributes %>>
7
+ <%= tabs_content %>
8
+ </div>
@@ -52,27 +52,14 @@ module Shadcn
52
52
  @url_param = url_param
53
53
  end
54
54
 
55
- def call
56
- content_tag(:div, tabs_content, tabs_attributes)
57
- end
58
-
59
55
  private
60
56
 
61
- def tabs_content
62
- safe_join([list, panels, content].compact.flatten)
57
+ def tabs_classes
58
+ class_name
63
59
  end
64
60
 
65
- def tabs_attributes
66
- attrs = {
67
- class: class_name,
68
- "data-controller": "shadcn--tabs",
69
- "data-shadcn--tabs-default-value": @default_value,
70
- "data-shadcn--tabs-url-param-value": @url_param,
71
- "data-orientation": @orientation.to_s
72
- }
73
- attrs.merge!(html_options)
74
- attrs.merge!(build_data)
75
- attrs.compact
61
+ def tabs_content
62
+ safe_join([list, panels, content].compact.flatten)
76
63
  end
77
64
  end
78
65
  end
@@ -0,0 +1,13 @@
1
+ <textarea class="<%= textarea_classes %>"<% if @name %>
2
+ name="<%= ERB::Util.html_escape_once(@name) %>"<% end %><% if @id %>
3
+ id="<%= ERB::Util.html_escape_once(@id) %>"<% end %><% if @placeholder %>
4
+ placeholder="<%= ERB::Util.html_escape_once(@placeholder) %>"<% end %><% if @rows %>
5
+ rows="<%= @rows %>"<% end %><% if @cols %>
6
+ cols="<%= @cols %>"<% end %><% if @disabled %>
7
+ disabled<% end %><% if @required %>
8
+ required<% end %><% if @readonly %>
9
+ readonly<% end %><% if @autofocus %>
10
+ autofocus<% end %><% if @minlength %>
11
+ minlength="<%= @minlength %>"<% end %><% if @maxlength %>
12
+ maxlength="<%= @maxlength %>"<% end %>
13
+ <%= tag_attributes %>><%= textarea_content %></textarea>
@@ -55,30 +55,14 @@ module Shadcn
55
55
  @maxlength = maxlength
56
56
  end
57
57
 
58
- def call
59
- content_tag(:textarea, @value || content, textarea_attributes)
60
- end
61
-
62
58
  private
63
59
 
64
- def textarea_attributes
65
- attrs = {
66
- name: @name,
67
- id: @id,
68
- placeholder: @placeholder,
69
- rows: @rows,
70
- cols: @cols,
71
- disabled: @disabled || nil,
72
- required: @required || nil,
73
- readonly: @readonly || nil,
74
- autofocus: @autofocus || nil,
75
- minlength: @minlength,
76
- maxlength: @maxlength,
77
- class: merge_classes(BASE_CLASSES)
78
- }
79
- attrs.merge!(html_options)
80
- attrs.merge!(build_data)
81
- attrs.compact
60
+ def textarea_classes
61
+ merge_classes(BASE_CLASSES)
62
+ end
63
+
64
+ def textarea_content
65
+ @value || content
82
66
  end
83
67
  end
84
68
  end
@@ -0,0 +1,36 @@
1
+ <li class="<%= toast_classes %>"
2
+ role="status"
3
+ aria-live="polite"
4
+ data-controller="shadcn--toast"
5
+ data-shadcn--toast-duration-value="<%= @duration %>"
6
+ data-shadcn--toast-open-value="<%= @open %>"
7
+ data-state="<%= data_state %>"
8
+ <%= tag_attributes %>>
9
+ <div class="grid gap-1">
10
+ <%= title %>
11
+ <%= description %>
12
+ <%= content %>
13
+ </div>
14
+ <%= action %>
15
+ <% if has_custom_close? %>
16
+ <%= close %>
17
+ <% else %>
18
+ <button type="button"
19
+ class="absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600"
20
+ data-action="click->shadcn--toast#close"
21
+ aria-label="Close">
22
+ <svg xmlns="http://www.w3.org/2000/svg"
23
+ width="16"
24
+ height="16"
25
+ viewBox="0 0 24 24"
26
+ fill="none"
27
+ class="h-4 w-4">
28
+ <path d="M18 6 6 18M6 6l12 12"
29
+ stroke="currentColor"
30
+ stroke-width="2"
31
+ stroke-linecap="round"
32
+ stroke-linejoin="round" />
33
+ </svg>
34
+ </button>
35
+ <% end %>
36
+ </li>
@@ -49,66 +49,18 @@ module Shadcn
49
49
  @open = open
50
50
  end
51
51
 
52
- def call
53
- content_tag(:li, toast_content, toast_attributes)
54
- end
55
-
56
52
  private
57
53
 
58
- def toast_content
59
- safe_join([
60
- content_wrapper,
61
- action,
62
- close_button
63
- ].compact)
64
- end
65
-
66
- def content_wrapper
67
- content_tag(:div, safe_join([title, description, content].compact), class: "grid gap-1")
68
- end
69
-
70
- def close_button
71
- close || default_close_button
72
- end
73
-
74
- def default_close_button
75
- content_tag(:button, close_icon, {
76
- type: "button",
77
- class: "absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
78
- "data-action": "click->shadcn--toast#close",
79
- "aria-label": "Close"
80
- })
81
- end
82
-
83
- def close_icon
84
- content_tag(:svg,
85
- content_tag(:path, nil, d: "M18 6 6 18M6 6l12 12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round"),
86
- xmlns: "http://www.w3.org/2000/svg",
87
- width: "16",
88
- height: "16",
89
- viewBox: "0 0 24 24",
90
- fill: "none",
91
- class: "h-4 w-4"
92
- )
93
- end
94
-
95
54
  def toast_classes
96
55
  cn(BASE_CLASSES, VARIANTS[@variant], class_name)
97
56
  end
98
57
 
99
- def toast_attributes
100
- attrs = {
101
- class: toast_classes,
102
- role: "status",
103
- "aria-live": "polite",
104
- "data-controller": "shadcn--toast",
105
- "data-shadcn--toast-duration-value": @duration,
106
- "data-shadcn--toast-open-value": @open.to_s,
107
- "data-state": @open ? "open" : "closed"
108
- }
109
- attrs.merge!(html_options)
110
- attrs.merge!(build_data)
111
- attrs.compact
58
+ def has_custom_close?
59
+ close?
60
+ end
61
+
62
+ def data_state
63
+ @open ? "open" : "closed"
112
64
  end
113
65
  end
114
66
  end
@@ -0,0 +1,12 @@
1
+ <button type="button"
2
+ class="<%= toggle_classes %>"
3
+ <%= "disabled" if @disabled %>
4
+ aria-pressed="<%= @pressed %>"
5
+ <%= "aria-label=\"#{ERB::Util.html_escape_once(@aria_label)}\"".html_safe if @aria_label %>
6
+ data-state="<%= data_state %>"
7
+ data-controller="shadcn--toggle"
8
+ data-action="click->shadcn--toggle#toggle"
9
+ data-shadcn--toggle-pressed-value="<%= @pressed %>"
10
+ <%= tag_attributes %>>
11
+ <%= content %>
12
+ </button>
@@ -49,29 +49,14 @@ module Shadcn
49
49
  @aria_label = aria_label
50
50
  end
51
51
 
52
- def call
53
- content_tag(:button, toggle_attributes) do
54
- content
55
- end
56
- end
57
-
58
52
  private
59
53
 
60
- def toggle_attributes
61
- attrs = {
62
- type: "button",
63
- class: cn(BASE_CLASSES, VARIANTS[@variant], SIZES[@size], class_name),
64
- disabled: @disabled || nil,
65
- "aria-pressed": @pressed.to_s,
66
- "aria-label": @aria_label,
67
- "data-state": @pressed ? "on" : "off",
68
- "data-controller": "shadcn--toggle",
69
- "data-action": "click->shadcn--toggle#toggle",
70
- "data-shadcn--toggle-pressed-value": @pressed.to_s
71
- }
72
- attrs.merge!(html_options)
73
- attrs.merge!(build_data)
74
- attrs.compact
54
+ def toggle_classes
55
+ cn(BASE_CLASSES, VARIANTS[@variant], SIZES[@size], class_name)
56
+ end
57
+
58
+ def data_state
59
+ @pressed ? "on" : "off"
75
60
  end
76
61
  end
77
62
  end
@@ -0,0 +1,14 @@
1
+ <div role="group"
2
+ class="<%= group_classes %>"
3
+ data-controller="shadcn--toggle-group"
4
+ data-shadcn--toggle-group-type-value="<%= @type %>"
5
+ data-shadcn--toggle-group-value-value="<%= value_string %>"
6
+ <%= tag_attributes %>>
7
+ <% if has_name? %>
8
+ <input type="hidden"
9
+ name="<%= @name %>"
10
+ value="<%= value_string %>"
11
+ data-shadcn--toggle-group-target="input" />
12
+ <% end %>
13
+ <%= safe_join(items.map(&:to_s)) %>
14
+ </div>
@@ -56,41 +56,18 @@ module Shadcn
56
56
  @name = name
57
57
  end
58
58
 
59
- def call
60
- content_tag(:div, group_content, group_attributes)
61
- end
62
-
63
59
  private
64
60
 
65
- def group_content
66
- safe_join([
67
- hidden_input,
68
- items.map(&:to_s)
69
- ].flatten.compact)
61
+ def group_classes
62
+ merge_classes(BASE_CLASSES)
70
63
  end
71
64
 
72
- def hidden_input
73
- return unless @name
74
-
75
- tag(:input,
76
- type: "hidden",
77
- name: @name,
78
- value: Array(@value).join(","),
79
- "data-shadcn--toggle-group-target": "input"
80
- )
65
+ def has_name?
66
+ @name.present?
81
67
  end
82
68
 
83
- def group_attributes
84
- attrs = {
85
- role: "group",
86
- class: merge_classes(BASE_CLASSES),
87
- "data-controller": "shadcn--toggle-group",
88
- "data-shadcn--toggle-group-type-value": @type.to_s,
89
- "data-shadcn--toggle-group-value-value": Array(@value).join(",")
90
- }
91
- attrs.merge!(html_options)
92
- attrs.merge!(build_data)
93
- attrs.compact
69
+ def value_string
70
+ Array(@value).join(",")
94
71
  end
95
72
  end
96
73
  end
@@ -0,0 +1,20 @@
1
+ <span class="<%= tooltip_classes %>"
2
+ data-controller="<%= tooltip_data_attrs[:controller] %>"
3
+ data-shadcn--tooltip-side-value="<%= tooltip_data_attrs[:"shadcn--tooltip-side-value"] %>"
4
+ data-shadcn--tooltip-align-value="<%= tooltip_data_attrs[:"shadcn--tooltip-align-value"] %>"
5
+ data-shadcn--tooltip-delay-value="<%= tooltip_data_attrs[:"shadcn--tooltip-delay-value"] %>"
6
+ data-shadcn--tooltip-skip-delay-value="<%= tooltip_data_attrs[:"shadcn--tooltip-skip-delay-value"] %>"
7
+ <%= tag_attributes %>>
8
+ <span data-shadcn--tooltip-target="trigger"
9
+ data-action="mouseenter->shadcn--tooltip#show mouseleave->shadcn--tooltip#hide focus->shadcn--tooltip#show blur->shadcn--tooltip#hide">
10
+ <%= content %>
11
+ </span>
12
+ <div class="<%= tooltip_content_classes %>"
13
+ role="tooltip"
14
+ data-shadcn--tooltip-target="content"
15
+ data-side="<%= @side %>"
16
+ data-state="closed"
17
+ hidden>
18
+ <%= ERB::Util.html_escape_once(@tooltip_content) %>
19
+ </div>
20
+ </span>