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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -2
- data/README.md +102 -1398
- data/__mocks__/@floating-ui/dom.js +67 -0
- data/app/assets/javascripts/shadcn/controllers/base_menu_controller.js +266 -0
- data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +34 -8
- data/app/assets/javascripts/shadcn/controllers/command_controller.js +5 -1
- data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +64 -135
- data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +56 -186
- data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
- data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +10 -7
- data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +10 -6
- data/app/assets/javascripts/shadcn/controllers/popover_controller.js +35 -60
- data/app/assets/javascripts/shadcn/controllers/select_controller.js +37 -17
- data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +24 -14
- data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
- data/app/assets/javascripts/shadcn/index.js +9 -1
- data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
- data/app/assets/stylesheets/shadcn/base.css +32 -0
- data/app/assets/stylesheets/shadcn/components.css +12 -0
- data/app/components/shadcn/accordion_component.html.erb +8 -0
- data/app/components/shadcn/accordion_component.rb +6 -15
- data/app/components/shadcn/alert_component.html.erb +6 -0
- data/app/components/shadcn/alert_component.rb +0 -18
- data/app/components/shadcn/alert_dialog_component.html.erb +12 -0
- data/app/components/shadcn/alert_dialog_component.rb +7 -27
- data/app/components/shadcn/aspect_ratio_component.html.erb +7 -0
- data/app/components/shadcn/aspect_ratio_component.rb +4 -19
- data/app/components/shadcn/avatar_component.html.erb +20 -0
- data/app/components/shadcn/avatar_component.rb +8 -36
- data/app/components/shadcn/badge_component.html.erb +1 -0
- data/app/components/shadcn/badge_component.rb +0 -11
- data/app/components/shadcn/base_component.rb +15 -2
- data/app/components/shadcn/breadcrumb_component.html.erb +5 -0
- data/app/components/shadcn/breadcrumb_component.rb +6 -16
- data/app/components/shadcn/button_component.html.erb +18 -0
- data/app/components/shadcn/button_component.rb +1 -41
- data/app/components/shadcn/card_component.html.erb +8 -0
- data/app/components/shadcn/card_component.rb +2 -6
- data/app/components/shadcn/checkbox_component.html.erb +32 -0
- data/app/components/shadcn/checkbox_component.rb +4 -43
- data/app/components/shadcn/collapsible_component.html.erb +8 -0
- data/app/components/shadcn/collapsible_component.rb +6 -15
- data/app/components/shadcn/command_list_component.rb +29 -14
- data/app/components/shadcn/context_menu_checkbox_item_component.rb +76 -0
- data/app/components/shadcn/context_menu_component.html.erb +11 -0
- data/app/components/shadcn/context_menu_component.rb +6 -26
- data/app/components/shadcn/context_menu_content_component.rb +37 -14
- data/app/components/shadcn/context_menu_item_component.rb +3 -2
- data/app/components/shadcn/context_menu_radio_group_component.rb +42 -0
- data/app/components/shadcn/context_menu_radio_item_component.rb +76 -0
- data/app/components/shadcn/dialog_component.html.erb +14 -0
- data/app/components/shadcn/dialog_component.rb +8 -29
- data/app/components/shadcn/drawer_component.html.erb +12 -0
- data/app/components/shadcn/drawer_component.rb +7 -27
- data/app/components/shadcn/dropdown_menu_checkbox_item_component.rb +76 -0
- data/app/components/shadcn/dropdown_menu_component.html.erb +14 -0
- data/app/components/shadcn/dropdown_menu_component.rb +9 -29
- data/app/components/shadcn/dropdown_menu_content_component.rb +45 -16
- data/app/components/shadcn/dropdown_menu_radio_group_component.rb +42 -0
- data/app/components/shadcn/dropdown_menu_radio_item_component.rb +76 -0
- data/app/components/shadcn/field_component.rb +7 -8
- data/app/components/shadcn/hover_card_component.html.erb +12 -0
- data/app/components/shadcn/hover_card_component.rb +7 -26
- data/app/components/shadcn/input_component.html.erb +18 -0
- data/app/components/shadcn/input_component.rb +2 -27
- data/app/components/shadcn/input_otp_component.rb +3 -3
- data/app/components/shadcn/kbd_component.html.erb +1 -0
- data/app/components/shadcn/kbd_component.rb +3 -10
- data/app/components/shadcn/label_component.html.erb +3 -0
- data/app/components/shadcn/label_component.rb +2 -18
- data/app/components/shadcn/menubar_component.html.erb +6 -0
- data/app/components/shadcn/menubar_component.rb +4 -15
- data/app/components/shadcn/menubar_content_component.rb +45 -20
- data/app/components/shadcn/menubar_sub_content_component.rb +21 -8
- data/app/components/shadcn/native_select_component.html.erb +22 -0
- data/app/components/shadcn/native_select_component.rb +9 -39
- data/app/components/shadcn/navigation_menu_component.html.erb +6 -0
- data/app/components/shadcn/navigation_menu_component.rb +4 -15
- data/app/components/shadcn/pagination_component.html.erb +5 -0
- data/app/components/shadcn/pagination_component.rb +11 -15
- data/app/components/shadcn/popover_component.html.erb +15 -0
- data/app/components/shadcn/popover_component.rb +10 -30
- data/app/components/shadcn/progress_component.html.erb +13 -0
- data/app/components/shadcn/progress_component.rb +6 -26
- data/app/components/shadcn/radio_group_component.html.erb +8 -0
- data/app/components/shadcn/radio_group_component.rb +12 -26
- data/app/components/shadcn/radio_group_item_component.rb +32 -6
- data/app/components/shadcn/resizable_panel_group_component.rb +27 -16
- data/app/components/shadcn/scroll_area_component.html.erb +7 -0
- data/app/components/shadcn/scroll_area_component.rb +4 -16
- data/app/components/shadcn/select_component.html.erb +46 -0
- data/app/components/shadcn/select_component.rb +29 -86
- data/app/components/shadcn/separator_component.html.erb +5 -0
- data/app/components/shadcn/separator_component.rb +6 -14
- data/app/components/shadcn/sheet_component.html.erb +12 -0
- data/app/components/shadcn/sheet_component.rb +7 -27
- data/app/components/shadcn/sidebar_component.rb +2 -2
- data/app/components/shadcn/skeleton_component.html.erb +1 -0
- data/app/components/shadcn/skeleton_component.rb +4 -2
- data/app/components/shadcn/slider_component.html.erb +12 -0
- data/app/components/shadcn/slider_component.rb +2 -21
- data/app/components/shadcn/spinner_component.html.erb +18 -0
- data/app/components/shadcn/spinner_component.rb +2 -30
- data/app/components/shadcn/switch_component.html.erb +72 -0
- data/app/components/shadcn/switch_component.rb +4 -82
- data/app/components/shadcn/table_component.html.erb +9 -0
- data/app/components/shadcn/table_component.rb +2 -10
- data/app/components/shadcn/tabs_component.html.erb +8 -0
- data/app/components/shadcn/tabs_component.rb +4 -17
- data/app/components/shadcn/textarea_component.html.erb +13 -0
- data/app/components/shadcn/textarea_component.rb +6 -22
- data/app/components/shadcn/toast_component.html.erb +36 -0
- data/app/components/shadcn/toast_component.rb +6 -54
- data/app/components/shadcn/toggle_component.html.erb +12 -0
- data/app/components/shadcn/toggle_component.rb +6 -21
- data/app/components/shadcn/toggle_group_component.html.erb +14 -0
- data/app/components/shadcn/toggle_group_component.rb +6 -29
- data/app/components/shadcn/tooltip_component.html.erb +20 -0
- data/app/components/shadcn/tooltip_component.rb +13 -38
- data/lib/generators/shadcn/add/USAGE +24 -0
- data/lib/generators/shadcn/add/add_generator.rb +279 -0
- data/lib/generators/shadcn/install/USAGE +22 -0
- data/lib/generators/shadcn/install/install_generator.rb +8 -3
- data/lib/generators/shadcn/install/templates/initializer.rb.tt +7 -27
- data/lib/generators/shadcn/install/templates/shadcn.yml.tt +15 -31
- data/lib/shadcn/rails/version.rb +1 -1
- metadata +54 -42
- data/.dockerignore +0 -40
- data/CLAUDE.md +0 -463
- data/PROGRESS.md +0 -485
- data/Rakefile +0 -29
- data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +0 -13
- data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +0 -46
- data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +0 -111
- data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +0 -27
- data/__tests__/controllers/accordion_controller.test.js +0 -904
- data/__tests__/controllers/calendar_controller.test.js +0 -1370
- data/__tests__/controllers/carousel_controller.test.js +0 -912
- data/__tests__/controllers/checkbox_controller.test.js +0 -454
- data/__tests__/controllers/collapsible_controller.test.js +0 -407
- data/__tests__/controllers/combobox_controller.test.js +0 -966
- data/__tests__/controllers/context_menu_controller.test.js +0 -627
- data/__tests__/controllers/date_picker_controller.test.js +0 -636
- data/__tests__/controllers/dialog_controller.test.js +0 -878
- data/__tests__/controllers/drawer_controller.test.js +0 -995
- data/__tests__/controllers/menubar_controller.test.js +0 -736
- data/__tests__/controllers/navigation_menu_controller.test.js +0 -598
- data/__tests__/controllers/popover_controller.test.js +0 -1007
- data/__tests__/controllers/radio_group_controller.test.js +0 -640
- data/__tests__/controllers/resizable_controller.test.js +0 -680
- data/__tests__/controllers/select_controller.test.js +0 -674
- data/__tests__/controllers/sheet_controller.test.js +0 -986
- data/__tests__/controllers/slider_controller.test.js +0 -1036
- data/__tests__/controllers/switch_controller.test.js +0 -424
- data/__tests__/controllers/tabs_controller.test.js +0 -907
- data/__tests__/controllers/toggle_group_controller.test.js +0 -839
- data/__tests__/controllers/tooltip_controller.test.js +0 -808
- data/__tests__/helpers/stimulus-test-helper.js +0 -203
- data/babel.config.cjs +0 -5
- data/bin/console +0 -11
- data/bin/setup +0 -8
- data/jest.config.js +0 -19
- data/jest.setup.js +0 -8
- data/lib/generators/shadcn/component/component_generator.rb +0 -188
- data/lib/generators/shadcn/theme/theme_generator.rb +0 -128
- data/package-lock.json +0 -7415
- data/package.json +0 -68
- data/rollup.config.js +0 -29
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
# Dropdown Menu Radio Item component
|
|
5
|
+
# A radio button within a radio group
|
|
6
|
+
class DropdownMenuRadioItemComponent < BaseComponent
|
|
7
|
+
BASE_CLASSES = "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
|
|
8
|
+
|
|
9
|
+
renders_one :shortcut, lambda { |**options|
|
|
10
|
+
DropdownMenuShortcutComponent.new(**options)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# @param value [String] Value of this radio item
|
|
14
|
+
# @param checked [Boolean] Whether item is selected
|
|
15
|
+
# @param disabled [Boolean] Whether item is disabled
|
|
16
|
+
def initialize(value: nil, checked: false, disabled: false, **options, &block)
|
|
17
|
+
super(**options, &block)
|
|
18
|
+
@value = value
|
|
19
|
+
@checked = checked
|
|
20
|
+
@disabled = disabled
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def call
|
|
24
|
+
content_tag(:div, item_content, item_attributes)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def item_content
|
|
30
|
+
safe_join([
|
|
31
|
+
radio_indicator,
|
|
32
|
+
content,
|
|
33
|
+
shortcut
|
|
34
|
+
].compact)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def radio_indicator
|
|
38
|
+
content_tag(:span, radio_icon, class: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def radio_icon
|
|
42
|
+
return "" unless @checked
|
|
43
|
+
|
|
44
|
+
content_tag(:svg, circle_svg, {
|
|
45
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
46
|
+
width: "16",
|
|
47
|
+
height: "16",
|
|
48
|
+
viewBox: "0 0 24 24",
|
|
49
|
+
fill: "currentColor",
|
|
50
|
+
stroke: "none",
|
|
51
|
+
class: "h-4 w-4"
|
|
52
|
+
})
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def circle_svg
|
|
56
|
+
content_tag(:circle, "", cx: "12", cy: "12", r: "6")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def item_attributes
|
|
60
|
+
attrs = {
|
|
61
|
+
class: cn(BASE_CLASSES, class_name),
|
|
62
|
+
role: "menuitemradio",
|
|
63
|
+
"aria-checked": @checked.to_s,
|
|
64
|
+
tabindex: @disabled ? nil : "-1",
|
|
65
|
+
"data-disabled": @disabled ? "" : nil,
|
|
66
|
+
"data-state": @checked ? "checked" : "unchecked",
|
|
67
|
+
"data-value": @value,
|
|
68
|
+
"data-shadcn--dropdown-target": "item",
|
|
69
|
+
"data-action": "click->shadcn--dropdown#selectRadio"
|
|
70
|
+
}
|
|
71
|
+
attrs.merge!(html_options)
|
|
72
|
+
attrs.merge!(build_data)
|
|
73
|
+
attrs.compact
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -43,10 +43,15 @@ module Shadcn
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
# Input slot - renders an Input component
|
|
46
|
-
|
|
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
|
|
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
|
|
38
|
-
|
|
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
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"
|
|
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
|
|
84
|
-
|
|
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, "
|
|
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
|
|
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 =
|
|
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
|
|
30
|
-
|
|
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
|
|
@@ -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
|
|
36
|
-
|
|
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
|
|
@@ -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
|
|
42
|
-
|
|
37
|
+
def menubar_classes
|
|
38
|
+
cn(BASE_CLASSES, class_name)
|
|
43
39
|
end
|
|
44
40
|
|
|
45
|
-
def
|
|
46
|
-
|
|
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
|
|
@@ -6,23 +6,44 @@ module Shadcn
|
|
|
6
6
|
class MenubarContentComponent < BaseComponent
|
|
7
7
|
BASE_CLASSES = "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
# Use polymorphic slots to preserve the order of items, labels, separators, etc.
|
|
10
|
+
renders_many :menu_items, types: {
|
|
11
|
+
item: {
|
|
12
|
+
renders: lambda { |**options, &block|
|
|
13
|
+
MenubarItemComponent.new(**options, &block)
|
|
14
|
+
},
|
|
15
|
+
as: :item
|
|
16
|
+
},
|
|
17
|
+
label: {
|
|
18
|
+
renders: lambda { |**options, &block|
|
|
19
|
+
MenubarLabelComponent.new(**options, &block)
|
|
20
|
+
},
|
|
21
|
+
as: :label
|
|
22
|
+
},
|
|
23
|
+
separator: {
|
|
24
|
+
renders: lambda { |**options|
|
|
25
|
+
MenubarSeparatorComponent.new(**options)
|
|
26
|
+
},
|
|
27
|
+
as: :separator
|
|
28
|
+
},
|
|
29
|
+
checkbox_item: {
|
|
30
|
+
renders: lambda { |**options, &block|
|
|
31
|
+
MenubarCheckboxItemComponent.new(**options, &block)
|
|
32
|
+
},
|
|
33
|
+
as: :checkbox_item
|
|
34
|
+
},
|
|
35
|
+
radio_group: {
|
|
36
|
+
renders: lambda { |**options, &block|
|
|
37
|
+
MenubarRadioGroupComponent.new(**options, &block)
|
|
38
|
+
},
|
|
39
|
+
as: :radio_group
|
|
40
|
+
},
|
|
41
|
+
sub_menu: {
|
|
42
|
+
renders: lambda { |**options, &block|
|
|
43
|
+
MenubarSubComponent.new(**options, &block)
|
|
44
|
+
},
|
|
45
|
+
as: :sub_menu
|
|
46
|
+
}
|
|
26
47
|
}
|
|
27
48
|
|
|
28
49
|
# @param align [Symbol] Content alignment (:start, :center, :end)
|
|
@@ -40,10 +61,14 @@ module Shadcn
|
|
|
40
61
|
private
|
|
41
62
|
|
|
42
63
|
def menu_content
|
|
43
|
-
|
|
44
|
-
|
|
64
|
+
# Trigger slot evaluation first by accessing content
|
|
65
|
+
raw_content = content
|
|
66
|
+
# If polymorphic slots were used, render them in order
|
|
67
|
+
if menu_items.any?
|
|
68
|
+
safe_join(menu_items)
|
|
45
69
|
else
|
|
46
|
-
content
|
|
70
|
+
# Otherwise render the raw block content (for backwards compatibility)
|
|
71
|
+
raw_content
|
|
47
72
|
end
|
|
48
73
|
end
|
|
49
74
|
|
|
@@ -6,11 +6,20 @@ module Shadcn
|
|
|
6
6
|
class MenubarSubContentComponent < BaseComponent
|
|
7
7
|
BASE_CLASSES = "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
# Use polymorphic slots to preserve the order of items and separators
|
|
10
|
+
renders_many :menu_items, types: {
|
|
11
|
+
item: {
|
|
12
|
+
renders: lambda { |**options, &block|
|
|
13
|
+
MenubarItemComponent.new(**options, &block)
|
|
14
|
+
},
|
|
15
|
+
as: :item
|
|
16
|
+
},
|
|
17
|
+
separator: {
|
|
18
|
+
renders: lambda { |**options|
|
|
19
|
+
MenubarSeparatorComponent.new(**options)
|
|
20
|
+
},
|
|
21
|
+
as: :separator
|
|
22
|
+
}
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
def call
|
|
@@ -20,10 +29,14 @@ module Shadcn
|
|
|
20
29
|
private
|
|
21
30
|
|
|
22
31
|
def sub_content
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
# Trigger slot evaluation first by accessing content
|
|
33
|
+
raw_content = content
|
|
34
|
+
# If polymorphic slots were used, render them in order
|
|
35
|
+
if menu_items.any?
|
|
36
|
+
safe_join(menu_items)
|
|
25
37
|
else
|
|
26
|
-
content
|
|
38
|
+
# Otherwise render the raw block content (for backwards compatibility)
|
|
39
|
+
raw_content
|
|
27
40
|
end
|
|
28
41
|
end
|
|
29
42
|
|
|
@@ -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
|
-
|
|
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
|
|
76
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
|
@@ -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
|
|
@@ -43,13 +43,12 @@ module Shadcn
|
|
|
43
43
|
@window = window
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
def
|
|
46
|
+
def before_render
|
|
47
|
+
# Pre-compute auto-generated content if needed
|
|
47
48
|
if auto_generate?
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
content_tag(:nav, auto_generated_content, pagination_attributes)
|
|
49
|
+
@should_render = total_pages > 1
|
|
51
50
|
else
|
|
52
|
-
|
|
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
|
-
|
|
180
|
+
if auto_generate?
|
|
181
|
+
auto_generated_content
|
|
182
|
+
else
|
|
183
|
+
pagination_content || ""
|
|
184
|
+
end
|
|
182
185
|
end
|
|
183
186
|
|
|
184
|
-
def
|
|
185
|
-
|
|
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>
|