shadcn-rails 0.2.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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -2
  3. data/README.md +21 -8
  4. data/__mocks__/@floating-ui/dom.js +67 -0
  5. data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +23 -2
  6. data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +4 -31
  7. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +32 -41
  8. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
  9. data/app/assets/javascripts/shadcn/controllers/popover_controller.js +29 -54
  10. data/app/assets/javascripts/shadcn/controllers/select_controller.js +26 -8
  11. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
  12. data/app/assets/javascripts/shadcn/index.js +7 -1
  13. data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
  14. data/app/assets/stylesheets/shadcn/base.css +32 -0
  15. data/app/components/shadcn/accordion_component.html.erb +8 -0
  16. data/app/components/shadcn/accordion_component.rb +6 -15
  17. data/app/components/shadcn/alert_component.html.erb +6 -0
  18. data/app/components/shadcn/alert_component.rb +0 -18
  19. data/app/components/shadcn/alert_dialog_component.html.erb +12 -0
  20. data/app/components/shadcn/alert_dialog_component.rb +7 -27
  21. data/app/components/shadcn/aspect_ratio_component.html.erb +7 -0
  22. data/app/components/shadcn/aspect_ratio_component.rb +4 -19
  23. data/app/components/shadcn/avatar_component.html.erb +20 -0
  24. data/app/components/shadcn/avatar_component.rb +8 -36
  25. data/app/components/shadcn/badge_component.html.erb +1 -0
  26. data/app/components/shadcn/badge_component.rb +0 -11
  27. data/app/components/shadcn/base_component.rb +15 -2
  28. data/app/components/shadcn/breadcrumb_component.html.erb +5 -0
  29. data/app/components/shadcn/breadcrumb_component.rb +6 -16
  30. data/app/components/shadcn/button_component.html.erb +18 -0
  31. data/app/components/shadcn/button_component.rb +1 -41
  32. data/app/components/shadcn/card_component.html.erb +8 -0
  33. data/app/components/shadcn/card_component.rb +2 -6
  34. data/app/components/shadcn/checkbox_component.html.erb +32 -0
  35. data/app/components/shadcn/checkbox_component.rb +4 -43
  36. data/app/components/shadcn/collapsible_component.html.erb +8 -0
  37. data/app/components/shadcn/collapsible_component.rb +6 -15
  38. data/app/components/shadcn/context_menu_component.html.erb +11 -0
  39. data/app/components/shadcn/context_menu_component.rb +6 -26
  40. data/app/components/shadcn/dialog_component.html.erb +14 -0
  41. data/app/components/shadcn/dialog_component.rb +8 -29
  42. data/app/components/shadcn/drawer_component.html.erb +12 -0
  43. data/app/components/shadcn/drawer_component.rb +7 -27
  44. data/app/components/shadcn/dropdown_menu_component.html.erb +14 -0
  45. data/app/components/shadcn/dropdown_menu_component.rb +9 -29
  46. data/app/components/shadcn/field_component.rb +7 -8
  47. data/app/components/shadcn/hover_card_component.html.erb +12 -0
  48. data/app/components/shadcn/hover_card_component.rb +7 -26
  49. data/app/components/shadcn/input_component.html.erb +18 -0
  50. data/app/components/shadcn/input_component.rb +2 -27
  51. data/app/components/shadcn/input_otp_component.rb +3 -3
  52. data/app/components/shadcn/kbd_component.html.erb +1 -0
  53. data/app/components/shadcn/kbd_component.rb +3 -10
  54. data/app/components/shadcn/label_component.html.erb +3 -0
  55. data/app/components/shadcn/label_component.rb +2 -18
  56. data/app/components/shadcn/menubar_component.html.erb +6 -0
  57. data/app/components/shadcn/menubar_component.rb +4 -15
  58. data/app/components/shadcn/native_select_component.html.erb +22 -0
  59. data/app/components/shadcn/native_select_component.rb +9 -39
  60. data/app/components/shadcn/navigation_menu_component.html.erb +6 -0
  61. data/app/components/shadcn/navigation_menu_component.rb +4 -15
  62. data/app/components/shadcn/pagination_component.html.erb +5 -0
  63. data/app/components/shadcn/pagination_component.rb +11 -15
  64. data/app/components/shadcn/popover_component.html.erb +15 -0
  65. data/app/components/shadcn/popover_component.rb +10 -30
  66. data/app/components/shadcn/progress_component.html.erb +13 -0
  67. data/app/components/shadcn/progress_component.rb +6 -26
  68. data/app/components/shadcn/radio_group_component.html.erb +8 -0
  69. data/app/components/shadcn/radio_group_component.rb +12 -26
  70. data/app/components/shadcn/scroll_area_component.html.erb +7 -0
  71. data/app/components/shadcn/scroll_area_component.rb +4 -16
  72. data/app/components/shadcn/select_component.html.erb +46 -0
  73. data/app/components/shadcn/select_component.rb +6 -80
  74. data/app/components/shadcn/separator_component.html.erb +5 -0
  75. data/app/components/shadcn/separator_component.rb +6 -14
  76. data/app/components/shadcn/sheet_component.html.erb +12 -0
  77. data/app/components/shadcn/sheet_component.rb +7 -27
  78. data/app/components/shadcn/sidebar_component.rb +2 -2
  79. data/app/components/shadcn/skeleton_component.html.erb +1 -0
  80. data/app/components/shadcn/skeleton_component.rb +4 -2
  81. data/app/components/shadcn/slider_component.html.erb +12 -0
  82. data/app/components/shadcn/slider_component.rb +2 -21
  83. data/app/components/shadcn/spinner_component.html.erb +18 -0
  84. data/app/components/shadcn/spinner_component.rb +2 -30
  85. data/app/components/shadcn/switch_component.html.erb +72 -0
  86. data/app/components/shadcn/switch_component.rb +4 -82
  87. data/app/components/shadcn/table_component.html.erb +9 -0
  88. data/app/components/shadcn/table_component.rb +2 -10
  89. data/app/components/shadcn/tabs_component.html.erb +8 -0
  90. data/app/components/shadcn/tabs_component.rb +4 -17
  91. data/app/components/shadcn/textarea_component.html.erb +13 -0
  92. data/app/components/shadcn/textarea_component.rb +6 -22
  93. data/app/components/shadcn/toast_component.html.erb +36 -0
  94. data/app/components/shadcn/toast_component.rb +6 -54
  95. data/app/components/shadcn/toggle_component.html.erb +12 -0
  96. data/app/components/shadcn/toggle_component.rb +6 -21
  97. data/app/components/shadcn/toggle_group_component.html.erb +14 -0
  98. data/app/components/shadcn/toggle_group_component.rb +6 -29
  99. data/app/components/shadcn/tooltip_component.html.erb +20 -0
  100. data/app/components/shadcn/tooltip_component.rb +13 -38
  101. data/lib/generators/shadcn/add/USAGE +24 -0
  102. data/lib/generators/shadcn/add/add_generator.rb +279 -0
  103. data/lib/generators/shadcn/install/USAGE +22 -0
  104. data/lib/generators/shadcn/install/install_generator.rb +8 -3
  105. data/lib/generators/shadcn/install/templates/initializer.rb.tt +7 -27
  106. data/lib/generators/shadcn/install/templates/shadcn.yml.tt +15 -31
  107. data/lib/shadcn/rails/version.rb +1 -1
  108. metadata +47 -45
  109. data/.dockerignore +0 -40
  110. data/CLAUDE.md +0 -612
  111. data/PROGRESS.md +0 -495
  112. data/Rakefile +0 -95
  113. data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +0 -13
  114. data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +0 -46
  115. data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +0 -111
  116. data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +0 -27
  117. data/__tests__/controllers/accordion_controller.test.js +0 -904
  118. data/__tests__/controllers/calendar_controller.test.js +0 -1370
  119. data/__tests__/controllers/carousel_controller.test.js +0 -912
  120. data/__tests__/controllers/checkbox_controller.test.js +0 -454
  121. data/__tests__/controllers/collapsible_controller.test.js +0 -407
  122. data/__tests__/controllers/combobox_controller.test.js +0 -971
  123. data/__tests__/controllers/context_menu_controller.test.js +0 -905
  124. data/__tests__/controllers/date_picker_controller.test.js +0 -636
  125. data/__tests__/controllers/dialog_controller.test.js +0 -878
  126. data/__tests__/controllers/drawer_controller.test.js +0 -995
  127. data/__tests__/controllers/menubar_controller.test.js +0 -737
  128. data/__tests__/controllers/navigation_menu_controller.test.js +0 -599
  129. data/__tests__/controllers/popover_controller.test.js +0 -982
  130. data/__tests__/controllers/radio_group_controller.test.js +0 -640
  131. data/__tests__/controllers/resizable_controller.test.js +0 -680
  132. data/__tests__/controllers/select_controller.test.js +0 -678
  133. data/__tests__/controllers/sheet_controller.test.js +0 -986
  134. data/__tests__/controllers/slider_controller.test.js +0 -1036
  135. data/__tests__/controllers/switch_controller.test.js +0 -424
  136. data/__tests__/controllers/tabs_controller.test.js +0 -907
  137. data/__tests__/controllers/toggle_group_controller.test.js +0 -839
  138. data/__tests__/controllers/tooltip_controller.test.js +0 -808
  139. data/__tests__/helpers/stimulus-test-helper.js +0 -203
  140. data/babel.config.cjs +0 -5
  141. data/bin/bump +0 -321
  142. data/bin/console +0 -11
  143. data/bin/release +0 -205
  144. data/bin/setup +0 -8
  145. data/bin/test +0 -75
  146. data/jest.config.js +0 -19
  147. data/jest.setup.js +0 -8
  148. data/lib/generators/shadcn/component/component_generator.rb +0 -188
  149. data/lib/generators/shadcn/theme/theme_generator.rb +0 -128
  150. data/package-lock.json +0 -7438
  151. data/package.json +0 -71
  152. data/rollup.config.js +0 -29
@@ -33,12 +33,12 @@ module Shadcn
33
33
  @type = type.to_sym
34
34
  end
35
35
 
36
- def call
37
- content_tag(:div, scroll_structure, scroll_attributes)
38
- end
39
-
40
36
  private
41
37
 
38
+ def scroll_classes
39
+ merge_classes(BASE_CLASSES)
40
+ end
41
+
42
42
  def scroll_structure
43
43
  safe_join([
44
44
  viewport,
@@ -94,17 +94,5 @@ module Shadcn
94
94
 
95
95
  content_tag(:div, "", class: "absolute right-0 bottom-0 h-2.5 w-2.5 bg-transparent")
96
96
  end
97
-
98
- def scroll_attributes
99
- attrs = {
100
- class: merge_classes(BASE_CLASSES),
101
- "data-controller": "shadcn--scroll-area",
102
- "data-shadcn--scroll-area-orientation-value": @orientation.to_s,
103
- "data-shadcn--scroll-area-type-value": @type.to_s
104
- }
105
- attrs.merge!(html_options)
106
- attrs.merge!(build_data)
107
- attrs.compact
108
- end
109
97
  end
110
98
  end
@@ -0,0 +1,46 @@
1
+ <div class="<%= wrapper_classes %>"
2
+ data-controller="shadcn--select"
3
+ data-shadcn--select-value-value="<%= @value %>"
4
+ data-action="keydown.escape->shadcn--select#close"
5
+ <%= tag_attributes %>>
6
+ <input type="hidden"
7
+ <%= "name=\"#{ERB::Util.html_escape_once(@name)}\"".html_safe if @name %>
8
+ <%= "id=\"#{ERB::Util.html_escape_once(@id)}\"".html_safe if @id %>
9
+ <%= "value=\"#{ERB::Util.html_escape_once(@value)}\"".html_safe if @value %>
10
+ <%= "required" if @required %>
11
+ data-shadcn--select-target="input" />
12
+
13
+ <button type="button"
14
+ class="<%= trigger_classes %>"
15
+ role="combobox"
16
+ <%= "disabled" if @disabled %>
17
+ aria-expanded="false"
18
+ aria-haspopup="listbox"
19
+ data-shadcn--select-target="trigger"
20
+ data-action="click->shadcn--select#toggle keydown->shadcn--select#handleKeydown"
21
+ data-placeholder="<%= @placeholder %>">
22
+ <span data-shadcn--select-target="display"><%= display_text %></span>
23
+ <svg xmlns="http://www.w3.org/2000/svg"
24
+ width="16"
25
+ height="16"
26
+ viewBox="0 0 24 24"
27
+ fill="none"
28
+ class="h-4 w-4 opacity-50">
29
+ <path d="m6 9 6 6 6-6"
30
+ stroke="currentColor"
31
+ stroke-width="2"
32
+ stroke-linecap="round"
33
+ stroke-linejoin="round" />
34
+ </svg>
35
+ </button>
36
+
37
+ <div class="<%= CONTENT_CLASSES %>"
38
+ role="listbox"
39
+ data-shadcn--select-target="content"
40
+ data-state="closed"
41
+ hidden>
42
+ <div class="<%= VIEWPORT_CLASSES %>">
43
+ <%= items_content %>
44
+ </div>
45
+ </div>
46
+ </div>
@@ -65,80 +65,18 @@ module Shadcn
65
65
  @required = required
66
66
  end
67
67
 
68
- def call
69
- content_tag(:div, select_structure, select_attributes)
70
- end
71
-
72
68
  private
73
69
 
74
- def select_structure
75
- safe_join([
76
- hidden_input,
77
- trigger,
78
- content_wrapper
79
- ])
80
- end
81
-
82
- def hidden_input
83
- tag(:input,
84
- type: "hidden",
85
- name: @name,
86
- id: @id,
87
- value: @value,
88
- required: @required || nil,
89
- "data-shadcn--select-target": "input"
90
- )
91
- end
92
-
93
- def trigger
94
- content_tag(:button, trigger_content, trigger_attributes)
95
- end
96
-
97
- def trigger_content
98
- safe_join([
99
- content_tag(:span, @value.presence || @placeholder, "data-shadcn--select-target": "display"),
100
- chevron_icon
101
- ])
70
+ def wrapper_classes
71
+ cn("relative inline-block", class_name)
102
72
  end
103
73
 
104
- def chevron_icon
105
- content_tag(:svg,
106
- content_tag(:path, nil, d: "m6 9 6 6 6-6", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round"),
107
- xmlns: "http://www.w3.org/2000/svg",
108
- width: "16",
109
- height: "16",
110
- viewBox: "0 0 24 24",
111
- fill: "none",
112
- class: "h-4 w-4 opacity-50"
113
- )
74
+ def trigger_classes
75
+ cn(TRIGGER_CLASSES, class_name)
114
76
  end
115
77
 
116
- def trigger_attributes
117
- {
118
- type: "button",
119
- class: cn(TRIGGER_CLASSES, class_name),
120
- role: "combobox",
121
- disabled: @disabled || nil,
122
- "aria-expanded": "false",
123
- "aria-haspopup": "listbox",
124
- "data-shadcn--select-target": "trigger",
125
- "data-action": "click->shadcn--select#toggle keydown->shadcn--select#handleKeydown",
126
- "data-placeholder": @placeholder
127
- }
128
- end
129
-
130
- def content_wrapper
131
- content_tag(:div, viewport, {
132
- class: CONTENT_CLASSES,
133
- role: "listbox",
134
- "data-shadcn--select-target": "content",
135
- "data-state": "closed",
136
- hidden: true
137
- })
138
- end
139
-
140
- def viewport
141
- content_tag(:div, items_content, class: VIEWPORT_CLASSES)
78
+ def display_text
79
+ @value.presence || @placeholder
142
80
  end
143
81
 
144
82
  def items_content
@@ -152,17 +90,5 @@ module Shadcn
152
90
  raw_content
153
91
  end
154
92
  end
155
-
156
- def select_attributes
157
- attrs = {
158
- class: cn("relative inline-block", class_name),
159
- "data-controller": "shadcn--select",
160
- "data-shadcn--select-value-value": @value,
161
- "data-action": "keydown.escape->shadcn--select#close"
162
- }
163
- attrs.merge!(html_options.except(:class))
164
- attrs.merge!(build_data)
165
- attrs.compact
166
- end
167
93
  end
168
94
  end
@@ -0,0 +1,5 @@
1
+ <div class="<%= separator_classes %>"
2
+ role="<%= separator_role %>"<% if aria_orientation %>
3
+ aria-orientation="<%= aria_orientation %>"<% end %>
4
+ data-orientation="<%= @orientation %>"
5
+ <%= tag_attributes %>></div>
@@ -29,26 +29,18 @@ module Shadcn
29
29
  @decorative = decorative
30
30
  end
31
31
 
32
- def call
33
- tag.div(**separator_attributes)
34
- end
35
-
36
32
  private
37
33
 
38
34
  def separator_classes
39
35
  cn(BASE_CLASSES, ORIENTATIONS[@orientation], class_name)
40
36
  end
41
37
 
42
- def separator_attributes
43
- attrs = {
44
- class: separator_classes,
45
- role: @decorative ? "none" : "separator",
46
- "aria-orientation": @decorative ? nil : @orientation.to_s,
47
- "data-orientation": @orientation.to_s
48
- }
49
- attrs.merge!(html_options)
50
- attrs.merge!(build_data)
51
- attrs.compact
38
+ def separator_role
39
+ @decorative ? "none" : "separator"
40
+ end
41
+
42
+ def aria_orientation
43
+ @decorative ? nil : @orientation.to_s
52
44
  end
53
45
  end
54
46
  end
@@ -0,0 +1,12 @@
1
+ <div class="<%= sheet_classes %>"
2
+ data-controller="<%= sheet_data_attrs[:controller] %>"
3
+ data-shadcn--sheet-open-value="<%= sheet_data_attrs[:"shadcn--sheet-open-value"] %>"
4
+ data-shadcn--sheet-side-value="<%= sheet_data_attrs[:"shadcn--sheet-side-value"] %>"
5
+ <%= tag_attributes %>>
6
+ <% if trigger? %>
7
+ <div data-shadcn--sheet-target="trigger" data-action="click->shadcn--sheet#open">
8
+ <%= trigger %>
9
+ </div>
10
+ <% end %>
11
+ <%= body if body? %>
12
+ </div>
@@ -45,38 +45,18 @@ module Shadcn
45
45
  @open = open
46
46
  end
47
47
 
48
- def call
49
- content_tag(:div, sheet_structure, sheet_attributes)
50
- end
51
-
52
48
  private
53
49
 
54
- def sheet_structure
55
- safe_join([
56
- trigger_wrapper,
57
- body
58
- ].compact)
59
- end
60
-
61
- def trigger_wrapper
62
- return unless trigger
63
-
64
- content_tag(:div, trigger, {
65
- "data-shadcn--sheet-target": "trigger",
66
- "data-action": "click->shadcn--sheet#open"
67
- })
50
+ def sheet_classes
51
+ class_name
68
52
  end
69
53
 
70
- def sheet_attributes
71
- attrs = {
72
- class: class_name,
73
- "data-controller": "shadcn--sheet",
74
- "data-shadcn--sheet-open-value": @open.to_s,
75
- "data-shadcn--sheet-side-value": @side.to_s
54
+ def sheet_data_attrs
55
+ {
56
+ controller: "shadcn--sheet",
57
+ "shadcn--sheet-open-value": @open.to_s,
58
+ "shadcn--sheet-side-value": @side.to_s
76
59
  }
77
- attrs.merge!(html_options)
78
- attrs.merge!(build_data)
79
- attrs.compact
80
60
  end
81
61
  end
82
62
  end
@@ -86,12 +86,12 @@ module Shadcn
86
86
  end
87
87
 
88
88
  def call
89
- content_tag(:aside, sidebar_content, sidebar_attributes)
89
+ content_tag(:aside, sidebar_wrapper, sidebar_attributes)
90
90
  end
91
91
 
92
92
  private
93
93
 
94
- def sidebar_content
94
+ def sidebar_wrapper
95
95
  safe_join([
96
96
  sidebar_inner
97
97
  ].compact)
@@ -0,0 +1 @@
1
+ <div class="<%= skeleton_classes %>" <%= tag_attributes %>><%= content %></div>
@@ -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