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
@@ -43,10 +43,15 @@ module Shadcn
43
43
  }
44
44
 
45
45
  # Input slot - renders an Input component
46
- renders_one :input, lambda { |**options|
46
+ # @param error [Boolean] Whether to show error styles on the input
47
+ # Note: If using with_error slot, call it BEFORE with_input for automatic error detection,
48
+ # or pass error: true explicitly
49
+ renders_one :input, lambda { |error: nil, **options|
47
50
  options[:id] ||= @input_id
48
51
  options[:name] ||= @name
49
- if @has_error
52
+ # Use explicit error param if provided, otherwise check error slot
53
+ has_error = error.nil? ? error? : error
54
+ if has_error
50
55
  options[:class_name] = cn("border-destructive focus-visible:ring-destructive", options[:class_name])
51
56
  end
52
57
  Shadcn::InputComponent.new(**options)
@@ -67,12 +72,6 @@ module Shadcn
67
72
  super(**options)
68
73
  @name = name
69
74
  @input_id = id || generate_id
70
- @has_error = false
71
- end
72
-
73
- def before_render
74
- # Track if error is present for styling
75
- @has_error = error.present?
76
75
  end
77
76
 
78
77
  def call
@@ -0,0 +1,12 @@
1
+ <div class="<%= hover_card_classes %>"
2
+ data-controller="<%= hover_card_data_attrs[:controller] %>"
3
+ data-shadcn--hover-card-open-delay-value="<%= hover_card_data_attrs[:"shadcn--hover-card-open-delay-value"] %>"
4
+ data-shadcn--hover-card-close-delay-value="<%= hover_card_data_attrs[:"shadcn--hover-card-close-delay-value"] %>"
5
+ <%= tag_attributes %>>
6
+ <% if trigger? %>
7
+ <div data-shadcn--hover-card-target="trigger">
8
+ <%= trigger %>
9
+ </div>
10
+ <% end %>
11
+ <%= card_content if card_content? %>
12
+ </div>
@@ -28,37 +28,18 @@ module Shadcn
28
28
  @close_delay = close_delay
29
29
  end
30
30
 
31
- def call
32
- content_tag(:div, build_card_content, card_attributes)
33
- end
34
-
35
31
  private
36
32
 
37
- def build_card_content
38
- safe_join([
39
- trigger_wrapper,
40
- card_content
41
- ].compact)
42
- end
43
-
44
- def trigger_wrapper
45
- return unless trigger
46
-
47
- content_tag(:div, trigger, {
48
- "data-shadcn--hover-card-target": "trigger"
49
- })
33
+ def hover_card_classes
34
+ cn("relative inline-block", class_name)
50
35
  end
51
36
 
52
- def card_attributes
53
- attrs = {
54
- class: cn("relative inline-block", class_name),
55
- "data-controller": "shadcn--hover-card",
56
- "data-shadcn--hover-card-open-delay-value": @open_delay,
57
- "data-shadcn--hover-card-close-delay-value": @close_delay
37
+ def hover_card_data_attrs
38
+ {
39
+ controller: "shadcn--hover-card",
40
+ "shadcn--hover-card-open-delay-value": @open_delay,
41
+ "shadcn--hover-card-close-delay-value": @close_delay
58
42
  }
59
- attrs.merge!(html_options)
60
- attrs.merge!(build_data)
61
- attrs.compact
62
43
  end
63
44
  end
64
45
  end
@@ -0,0 +1,18 @@
1
+ <input type="<%= @type %>"
2
+ class="<%= input_classes %>"<% if @name %>
3
+ name="<%= ERB::Util.html_escape_once(@name) %>"<% end %><% if @id %>
4
+ id="<%= ERB::Util.html_escape_once(@id) %>"<% end %><% if @value %>
5
+ value="<%= ERB::Util.html_escape_once(@value) %>"<% end %><% if @placeholder %>
6
+ placeholder="<%= ERB::Util.html_escape_once(@placeholder) %>"<% end %><% if @disabled %>
7
+ disabled<% end %><% if @required %>
8
+ required<% end %><% if @readonly %>
9
+ readonly<% end %><% if @autofocus %>
10
+ autofocus<% end %><% if @autocomplete %>
11
+ autocomplete="<%= ERB::Util.html_escape_once(@autocomplete) %>"<% end %><% if @pattern %>
12
+ pattern="<%= ERB::Util.html_escape_once(@pattern) %>"<% end %><% if @min %>
13
+ min="<%= ERB::Util.html_escape_once(@min) %>"<% end %><% if @max %>
14
+ max="<%= ERB::Util.html_escape_once(@max) %>"<% end %><% if @step %>
15
+ step="<%= ERB::Util.html_escape_once(@step) %>"<% end %><% if @minlength %>
16
+ minlength="<%= @minlength %>"<% end %><% if @maxlength %>
17
+ maxlength="<%= @maxlength %>"<% end %>
18
+ <%= tag_attributes %>>
@@ -74,35 +74,10 @@ module Shadcn
74
74
  @maxlength = maxlength
75
75
  end
76
76
 
77
- def call
78
- tag(:input, input_attributes)
79
- end
80
-
81
77
  private
82
78
 
83
- def input_attributes
84
- attrs = {
85
- type: @type,
86
- name: @name,
87
- id: @id,
88
- value: @value,
89
- placeholder: @placeholder,
90
- disabled: @disabled || nil,
91
- required: @required || nil,
92
- readonly: @readonly || nil,
93
- autofocus: @autofocus || nil,
94
- autocomplete: @autocomplete,
95
- pattern: @pattern,
96
- min: @min,
97
- max: @max,
98
- step: @step,
99
- minlength: @minlength,
100
- maxlength: @maxlength,
101
- class: merge_classes(BASE_CLASSES)
102
- }
103
- attrs.merge!(html_options)
104
- attrs.merge!(build_data)
105
- attrs.compact
79
+ def input_classes
80
+ merge_classes(BASE_CLASSES)
106
81
  end
107
82
  end
108
83
  end
@@ -31,7 +31,7 @@ module Shadcn
31
31
  renders_many :groups, "GroupComponent"
32
32
 
33
33
  # Separators between groups
34
- renders_many :separators, "SeparatorComponent"
34
+ renders_many :separators, "OtpSeparatorComponent"
35
35
 
36
36
  # @param length [Integer] Number of OTP digits
37
37
  # @param name [String] Input name for form submission
@@ -169,8 +169,8 @@ module Shadcn
169
169
  end
170
170
  end
171
171
 
172
- # Separator subcomponent
173
- class SeparatorComponent < BaseComponent
172
+ # Separator subcomponent (named OtpSeparatorComponent to avoid conflict with standalone SeparatorComponent)
173
+ class OtpSeparatorComponent < BaseComponent
174
174
  BASE_CLASSES = "flex items-center justify-center px-2"
175
175
 
176
176
  def call
@@ -0,0 +1 @@
1
+ <kbd class="<%= kbd_classes %>" <%= tag_attributes %>><%= content %></kbd>
@@ -18,19 +18,12 @@ module Shadcn
18
18
  # </span>
19
19
  #
20
20
  class KbdComponent < BaseComponent
21
- BASE_CLASSES = "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"
22
-
23
- def call
24
- tag.kbd(content, **kbd_attributes)
25
- end
21
+ BASE_CLASSES = 'pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100'
26
22
 
27
23
  private
28
24
 
29
- def kbd_attributes
30
- attrs = { class: merge_classes(BASE_CLASSES) }
31
- attrs.merge!(html_options)
32
- attrs.merge!(build_data)
33
- attrs.compact
25
+ def kbd_classes
26
+ merge_classes(BASE_CLASSES)
34
27
  end
35
28
  end
36
29
  end
@@ -0,0 +1,3 @@
1
+ <label <% if @for %>for="<%= @for %>"<% end %> class="<%= label_classes %>" <%= tag_attributes %>>
2
+ <%= content %><% if @required %><span class="text-destructive" aria-hidden="true"> *</span><% end %>
3
+ </label>
@@ -24,26 +24,10 @@ module Shadcn
24
24
  @required = required
25
25
  end
26
26
 
27
- def call
28
- label_text = content
29
- label_text = safe_join([label_text, required_indicator]) if @required
30
- tag.label(label_text, **label_attributes)
31
- end
32
-
33
27
  private
34
28
 
35
- def required_indicator
36
- content_tag(:span, " *", class: "text-destructive", "aria-hidden": "true")
37
- end
38
-
39
- def label_attributes
40
- attrs = {
41
- for: @for,
42
- class: merge_classes(BASE_CLASSES)
43
- }
44
- attrs.merge!(html_options)
45
- attrs.merge!(build_data)
46
- attrs.compact
29
+ def label_classes
30
+ cn(BASE_CLASSES, class_name)
47
31
  end
48
32
  end
49
33
  end
@@ -0,0 +1,6 @@
1
+ <div class="<%= menubar_classes %>"
2
+ role="menubar"
3
+ data-controller="shadcn--menubar"
4
+ <%= tag_attributes %>>
5
+ <%= menubar_content %>
6
+ </div>
@@ -32,25 +32,14 @@ module Shadcn
32
32
  MenubarMenuComponent.new(**options)
33
33
  }
34
34
 
35
- def call
36
- content_tag(:div, menubar_content, menubar_attributes)
37
- end
38
-
39
35
  private
40
36
 
41
- def menubar_content
42
- safe_join(menus)
37
+ def menubar_classes
38
+ cn(BASE_CLASSES, class_name)
43
39
  end
44
40
 
45
- def menubar_attributes
46
- attrs = {
47
- class: cn(BASE_CLASSES, class_name),
48
- role: "menubar",
49
- "data-controller": "shadcn--menubar"
50
- }
51
- attrs.merge!(html_options)
52
- attrs.merge!(build_data)
53
- attrs.compact
41
+ def menubar_content
42
+ safe_join(menus)
54
43
  end
55
44
  end
56
45
  end
@@ -0,0 +1,22 @@
1
+ <div class="<%= WRAPPER_CLASSES %>">
2
+ <select <%= "name=\"#{ERB::Util.html_escape_once(@name)}\"".html_safe if @name %>
3
+ <%= "id=\"#{ERB::Util.html_escape_once(@id)}\"".html_safe if @id %>
4
+ <%= "disabled" if @disabled %>
5
+ <%= "required" if @required %>
6
+ class="<%= select_classes %>"
7
+ <%= tag_attributes %>>
8
+ <%= select_content %>
9
+ </select>
10
+ <svg xmlns="http://www.w3.org/2000/svg"
11
+ width="16"
12
+ height="16"
13
+ viewBox="0 0 24 24"
14
+ fill="none"
15
+ stroke="currentColor"
16
+ stroke-width="2"
17
+ stroke-linecap="round"
18
+ stroke-linejoin="round"
19
+ class="<%= CHEVRON_CLASSES %>">
20
+ <path d="m6 9 6 6 6-6" />
21
+ </svg>
22
+ </div>
@@ -57,48 +57,18 @@ module Shadcn
57
57
  @required = required
58
58
  end
59
59
 
60
- def call
61
- tag.div(class: WRAPPER_CLASSES) do
62
- safe_join([
63
- tag.select(**select_attributes) do
64
- if optgroups.any?
65
- safe_join(optgroups)
66
- else
67
- safe_join(options)
68
- end
69
- end,
70
- chevron_icon
71
- ])
72
- end
73
- end
60
+ private
74
61
 
75
- def chevron_icon
76
- tag.svg(
77
- xmlns: "http://www.w3.org/2000/svg",
78
- width: "16",
79
- height: "16",
80
- viewBox: "0 0 24 24",
81
- fill: "none",
82
- stroke: "currentColor",
83
- stroke_width: "2",
84
- stroke_linecap: "round",
85
- stroke_linejoin: "round",
86
- class: CHEVRON_CLASSES
87
- ) do
88
- tag.path(d: "m6 9 6 6 6-6")
89
- end
62
+ def select_classes
63
+ merge_classes(SELECT_CLASSES)
90
64
  end
91
65
 
92
- private
93
-
94
- def select_attributes
95
- {
96
- name: @name,
97
- id: @id,
98
- disabled: @disabled || nil,
99
- required: @required || nil,
100
- class: merge_classes(SELECT_CLASSES)
101
- }.merge(html_options).merge(build_data).compact
66
+ def select_content
67
+ if optgroups.any?
68
+ safe_join(optgroups)
69
+ else
70
+ safe_join(options)
71
+ end
102
72
  end
103
73
 
104
74
  # Option subcomponent
@@ -0,0 +1,6 @@
1
+ <nav class="<%= navigation_classes %>"
2
+ data-controller="shadcn--navigation-menu"
3
+ aria-label="Main"
4
+ <%= tag_attributes %>>
5
+ <%= navigation_content %>
6
+ </nav>
@@ -31,12 +31,12 @@ module Shadcn
31
31
  NavigationMenuListComponent.new(**options)
32
32
  }
33
33
 
34
- def call
35
- content_tag(:nav, navigation_content, navigation_attributes)
36
- end
37
-
38
34
  private
39
35
 
36
+ def navigation_classes
37
+ cn(BASE_CLASSES, class_name)
38
+ end
39
+
40
40
  def navigation_content
41
41
  safe_join([list, viewport].compact)
42
42
  end
@@ -61,16 +61,5 @@ module Shadcn
61
61
  hidden: true
62
62
  }
63
63
  end
64
-
65
- def navigation_attributes
66
- attrs = {
67
- class: cn(BASE_CLASSES, class_name),
68
- "data-controller": "shadcn--navigation-menu",
69
- "aria-label": "Main"
70
- }
71
- attrs.merge!(html_options)
72
- attrs.merge!(build_data)
73
- attrs.compact
74
- end
75
64
  end
76
65
  end
@@ -0,0 +1,5 @@
1
+ <% if @should_render %>
2
+ <nav role="navigation" aria-label="pagination" class="<%= pagination_classes %>" <%= tag_attributes %>>
3
+ <%= build_pagination_content %>
4
+ </nav>
5
+ <% end %>
@@ -43,13 +43,12 @@ module Shadcn
43
43
  @window = window
44
44
  end
45
45
 
46
- def call
46
+ def before_render
47
+ # Pre-compute auto-generated content if needed
47
48
  if auto_generate?
48
- return "" if total_pages <= 1
49
-
50
- content_tag(:nav, auto_generated_content, pagination_attributes)
49
+ @should_render = total_pages > 1
51
50
  else
52
- content_tag(:nav, build_pagination_content, pagination_attributes)
51
+ @should_render = true
53
52
  end
54
53
  end
55
54
 
@@ -178,18 +177,15 @@ module Shadcn
178
177
  end
179
178
 
180
179
  def build_pagination_content
181
- pagination_content || ""
180
+ if auto_generate?
181
+ auto_generated_content
182
+ else
183
+ pagination_content || ""
184
+ end
182
185
  end
183
186
 
184
- def pagination_attributes
185
- attrs = {
186
- role: "navigation",
187
- "aria-label": "pagination",
188
- class: merge_classes(BASE_CLASSES)
189
- }
190
- attrs.merge!(html_options)
191
- attrs.merge!(build_data)
192
- attrs.compact
187
+ def pagination_classes
188
+ merge_classes(BASE_CLASSES)
193
189
  end
194
190
  end
195
191
  end
@@ -0,0 +1,15 @@
1
+ <div class="<%= popover_classes %>"
2
+ data-controller="<%= popover_data_attrs[:controller] %>"
3
+ data-shadcn--popover-open-value="<%= popover_data_attrs[:"shadcn--popover-open-value"] %>"
4
+ data-shadcn--popover-side-value="<%= popover_data_attrs[:"shadcn--popover-side-value"] %>"
5
+ data-shadcn--popover-align-value="<%= popover_data_attrs[:"shadcn--popover-align-value"] %>"
6
+ data-shadcn--popover-modal-value="<%= popover_data_attrs[:"shadcn--popover-modal-value"] %>"
7
+ data-action="<%= popover_data_attrs[:action] %>"
8
+ <%= tag_attributes %>>
9
+ <% if trigger? %>
10
+ <div data-shadcn--popover-target="trigger" data-action="click->shadcn--popover#toggle">
11
+ <%= trigger %>
12
+ </div>
13
+ <% end %>
14
+ <%= body if body? %>
15
+ </div>
@@ -36,41 +36,21 @@ module Shadcn
36
36
  @modal = modal
37
37
  end
38
38
 
39
- def call
40
- content_tag(:div, popover_structure, popover_attributes)
41
- end
42
-
43
39
  private
44
40
 
45
- def popover_structure
46
- safe_join([
47
- trigger_wrapper,
48
- body
49
- ].compact)
50
- end
51
-
52
- def trigger_wrapper
53
- return unless trigger
54
-
55
- content_tag(:div, trigger, {
56
- "data-shadcn--popover-target": "trigger",
57
- "data-action": "click->shadcn--popover#toggle"
58
- })
41
+ def popover_classes
42
+ cn("relative inline-block", class_name)
59
43
  end
60
44
 
61
- def popover_attributes
62
- attrs = {
63
- class: cn("relative inline-block", class_name),
64
- "data-controller": "shadcn--popover",
65
- "data-shadcn--popover-open-value": @open.to_s,
66
- "data-shadcn--popover-side-value": @side.to_s,
67
- "data-shadcn--popover-align-value": @align.to_s,
68
- "data-shadcn--popover-modal-value": @modal.to_s,
69
- "data-action": "keydown.escape->shadcn--popover#close"
45
+ def popover_data_attrs
46
+ {
47
+ controller: "shadcn--popover",
48
+ "shadcn--popover-open-value": @open.to_s,
49
+ "shadcn--popover-side-value": @side.to_s,
50
+ "shadcn--popover-align-value": @align.to_s,
51
+ "shadcn--popover-modal-value": @modal.to_s,
52
+ action: "keydown.escape->shadcn--popover#close"
70
53
  }
71
- attrs.merge!(html_options)
72
- attrs.merge!(build_data)
73
- attrs.compact
74
54
  end
75
55
  end
76
56
  end
@@ -0,0 +1,13 @@
1
+ <div class="<%= progress_classes %>"
2
+ role="progressbar"
3
+ aria-valuemin="0"
4
+ aria-valuemax="<%= @max %>"<% unless @indeterminate %>
5
+ aria-valuenow="<%= @value %>"<% end %>
6
+ data-state="<%= data_state %>"<% if @value %>
7
+ data-value="<%= @value %>"<% end %>
8
+ data-max="<%= @max %>"
9
+ <%= tag_attributes %>>
10
+ <div class="<%= indicator_classes %>"<% if indicator_style %>
11
+ style="<%= indicator_style %>"<% end %>
12
+ data-state="<%= data_state %>"></div>
13
+ </div>
@@ -27,14 +27,10 @@ module Shadcn
27
27
  @indeterminate = indeterminate
28
28
  end
29
29
 
30
- def call
31
- content_tag(:div, progress_indicator, progress_attributes)
32
- end
33
-
34
30
  private
35
31
 
36
- def progress_indicator
37
- content_tag(:div, "", indicator_attributes)
32
+ def progress_classes
33
+ merge_classes(BASE_CLASSES)
38
34
  end
39
35
 
40
36
  def progress_percentage
@@ -50,28 +46,12 @@ module Shadcn
50
46
  end
51
47
  end
52
48
 
53
- def progress_attributes
54
- attrs = {
55
- class: merge_classes(BASE_CLASSES),
56
- role: "progressbar",
57
- "aria-valuemin": 0,
58
- "aria-valuemax": @max,
59
- "aria-valuenow": @indeterminate ? nil : @value,
60
- "data-state": @indeterminate ? "indeterminate" : "determinate",
61
- "data-value": @value,
62
- "data-max": @max
63
- }
64
- attrs.merge!(html_options)
65
- attrs.merge!(build_data)
66
- attrs.compact
49
+ def indicator_classes
50
+ cn(INDICATOR_CLASSES, @indeterminate ? "animate-progress-indeterminate" : "")
67
51
  end
68
52
 
69
- def indicator_attributes
70
- {
71
- class: cn(INDICATOR_CLASSES, @indeterminate ? "animate-progress-indeterminate" : ""),
72
- style: indicator_style,
73
- "data-state": @indeterminate ? "indeterminate" : "determinate"
74
- }
53
+ def data_state
54
+ @indeterminate ? "indeterminate" : "determinate"
75
55
  end
76
56
  end
77
57
  end
@@ -0,0 +1,8 @@
1
+ <div role="radiogroup"
2
+ class="<%= group_classes %>"
3
+ <%= "aria-required=true" if @required %>
4
+ <%= "aria-disabled=true" if @disabled %>
5
+ <%= tag_attributes %>>
6
+ <%= render_data_items %>
7
+ <%= render_slot_items %>
8
+ </div>
@@ -70,13 +70,20 @@ module Shadcn
70
70
  @orientation = orientation
71
71
  end
72
72
 
73
- def call
74
- content_tag(:div, group_attributes) do
75
- safe_join([render_data_items, render_slot_items].compact)
76
- end
73
+ private
74
+
75
+ def group_classes
76
+ cn(BASE_CLASSES, orientation_classes, class_name)
77
77
  end
78
78
 
79
- private
79
+ def orientation_classes
80
+ case @orientation
81
+ when :horizontal
82
+ "flex flex-row gap-4"
83
+ else
84
+ "grid gap-3"
85
+ end
86
+ end
80
87
 
81
88
  # Render items from the items: data array
82
89
  def render_data_items
@@ -104,26 +111,5 @@ module Shadcn
104
111
  def generate_item_id(value)
105
112
  "#{@name}-#{value}".parameterize
106
113
  end
107
-
108
- def group_attributes
109
- attrs = {
110
- role: "radiogroup",
111
- class: cn(BASE_CLASSES, orientation_classes, class_name),
112
- "aria-required": @required ? "true" : nil,
113
- "aria-disabled": @disabled ? "true" : nil
114
- }
115
- attrs.merge!(html_options)
116
- attrs.merge!(build_data)
117
- attrs.compact
118
- end
119
-
120
- def orientation_classes
121
- case @orientation
122
- when :horizontal
123
- "flex flex-row gap-4"
124
- else
125
- "grid gap-3"
126
- end
127
- end
128
114
  end
129
115
  end
@@ -0,0 +1,7 @@
1
+ <div class="<%= scroll_classes %>"
2
+ data-controller="shadcn--scroll-area"
3
+ data-shadcn--scroll-area-orientation-value="<%= @orientation %>"
4
+ data-shadcn--scroll-area-type-value="<%= @type %>"
5
+ <%= tag_attributes %>>
6
+ <%= scroll_structure %>
7
+ </div>