shadcn-ui 0.0.10 → 0.0.13
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/app/assets/stylesheets/shadcn.css +67 -83
- data/app/{form_builders/shadcn_form_builder.rb → components/shadcn/form_builder.rb} +23 -4
- data/app/components/shadcn/select_component.rb +23 -0
- data/app/helpers/components/alert_helper.rb +3 -2
- data/app/helpers/components/badge_helper.rb +2 -2
- data/app/helpers/components/button_helper.rb +3 -2
- data/app/helpers/components/dropzone_helper.rb +5 -0
- data/app/helpers/components/filter_helper.rb +4 -0
- data/app/helpers/components/forms_helper.rb +2 -2
- data/app/helpers/components/input_helper.rb +3 -2
- data/app/helpers/components/select_helper.rb +6 -0
- data/app/helpers/components/sheet_helper.rb +3 -2
- data/app/helpers/components/table_helper.rb +61 -0
- data/app/helpers/components_helper.rb +2 -2
- data/app/javascript/controllers/ui/dialog_controller.js +3 -0
- data/app/javascript/controllers/ui/dropzone_controller.js +48 -0
- data/app/views/components/ui/_alert.html.erb +3 -3
- data/app/views/components/ui/_card.html.erb +1 -1
- data/app/views/components/ui/_dropzone.html.erb +12 -0
- data/app/views/components/ui/_sheet.html.erb +10 -5
- data/app/views/components/ui/_textarea.html.erb +2 -2
- data/app/views/documentation/index.html.md +1 -1
- data/app/views/documentation/installation.html.md +1 -1
- data/app/views/examples/components/accordion/code/_usage.erb +1 -1
- data/app/views/examples/components/accordion.html.erb +1 -1
- data/app/views/examples/components/card/code/_usage.erb +1 -1
- data/app/views/examples/components/dialog.html.erb +1 -1
- data/app/views/examples/components/dropdown-menu.html.erb +1 -1
- data/app/views/examples/components/dropzone/_usage.html.erb +20 -0
- data/app/views/examples/components/dropzone/code/_preview.erb +1 -0
- data/app/views/examples/components/dropzone/code/_usage.erb +1 -0
- data/app/views/examples/components/dropzone.html.erb +27 -0
- data/app/views/examples/components/forms/_usage.html.erb +2 -2
- data/app/views/examples/components/select/_usage.html.erb +22 -0
- data/app/views/examples/components/select/code/_preview.erb +7 -0
- data/app/views/examples/components/select/code/_usage.erb +5 -0
- data/app/views/examples/components/select.html.erb +27 -0
- data/app/views/examples/components/table/_usage.html.erb +23 -0
- data/app/views/examples/components/table/code/_preview.erb +35 -0
- data/app/views/examples/components/table/code/_usage.erb +12 -0
- data/app/views/examples/components/table.html.erb +27 -0
- data/app/views/layouts/shared/_components.html.erb +4 -3
- data/lib/components.json +25 -8
- data/lib/generators/shadcn-ui_generator.rb +1 -1
- data/lib/shadcn-ui/version.rb +1 -1
- data/shadcn-ui.gemspec +39 -0
- metadata +23 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 403f7186d9ebbcca03f5f3bc13901e29db5d84bcdefa1d8648be46387822defc
|
4
|
+
data.tar.gz: eb7e79a3a62954cdbb21777e46aea6bee225a1fbde655e2e85616f2a7d357648
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05b4c95efea37e11f8251081572564b057ab11a77e10e97af756f5e3c9f880b0dbc68d15105dfb91af2c5c2b59723a8b0ced098b7f68f2e57e15603a8386c29f
|
7
|
+
data.tar.gz: 8e03c73187dca4d4408962a83e676c5fe0ff8a344dd27bc60fe0575a5c1014386bc7d1de29ddc31414c14264b75c6626456ce3eb715ad0200f28f90b9156d7a2
|
@@ -1,84 +1,64 @@
|
|
1
|
+
:root {
|
2
|
+
--font-sans: "Inter var";
|
3
|
+
|
4
|
+
--background: 0 0% 100%;
|
5
|
+
--foreground: 240 10% 3.9%;
|
6
|
+
--card: 0 0% 100%;
|
7
|
+
--card-foreground: 240 10% 3.9%;
|
8
|
+
--popover: 0 0% 100%;
|
9
|
+
--popover-foreground: 240 10% 3.9%;
|
10
|
+
--primary: 240 5.9% 10%;
|
11
|
+
--primary-foreground: 0 0% 98%;
|
12
|
+
--secondary: 240 4.8% 95.9%;
|
13
|
+
--secondary-foreground: 240 5.9% 10%;
|
14
|
+
--muted: 240 4.8% 95.9%;
|
15
|
+
--muted-foreground: 240 3.8% 46.1%;
|
16
|
+
--accent: 240 4.8% 95.9%;
|
17
|
+
--accent-foreground: 240 5.9% 10%;
|
18
|
+
--destructive: 0 84.2% 60.2%;
|
19
|
+
--destructive-foreground: 0 0% 98%;
|
20
|
+
--border: 240 5.9% 90%;
|
21
|
+
--input: 240 5.9% 90%;
|
22
|
+
--ring: 240 5% 64.9%;
|
23
|
+
--radius: 0.5rem;
|
24
|
+
|
25
|
+
--success: 132, 95.3%, 33.3%, 0.74;
|
26
|
+
--success-foreground: 109 55% 28%;
|
27
|
+
|
28
|
+
--info: 223 78% 42%;
|
29
|
+
--info-foreground: 225 100% 50%;
|
30
|
+
|
31
|
+
--attention: 45 90% 45%;
|
32
|
+
--attention-foreground: 60 98.4% 48.8% 0.82;
|
33
|
+
}
|
1
34
|
@layer base {
|
2
|
-
:root {
|
3
|
-
--font-sans: "Inter var";
|
4
|
-
--background: 0 0% 100%;
|
5
|
-
--foreground: 222.2 47.4% 11.2%;
|
6
|
-
|
7
|
-
--muted: 210 40% 96.1%;
|
8
|
-
--muted-foreground: 215.4 16.3% 46.9%;
|
9
|
-
|
10
|
-
--popover: 0 0% 100%;
|
11
|
-
--popover-foreground: 222.2 47.4% 11.2%;
|
12
|
-
|
13
|
-
--border: 214.3 31.8% 91.4%;
|
14
|
-
--input: 214.3 31.8% 91.4%;
|
15
|
-
|
16
|
-
--card: 0 0% 100%;
|
17
|
-
--card-foreground: 222.2 47.4% 11.2%;
|
18
|
-
|
19
|
-
--primary: 222.2 47.4% 11.2%;
|
20
|
-
--primary-foreground: 210 40% 98%;
|
21
|
-
|
22
|
-
--secondary: 210 40% 96.1%;
|
23
|
-
--secondary-foreground: 222.2 47.4% 11.2%;
|
24
|
-
|
25
|
-
--accent: 210 40% 96.1%;
|
26
|
-
--accent-foreground: 222.2 47.4% 11.2%;
|
27
|
-
|
28
|
-
--destructive: 0 100% 50%;
|
29
|
-
--destructive-foreground: 210 40% 98%;
|
30
|
-
|
31
|
-
--success: 132, 95.3%, 33.3%, 0.74;
|
32
|
-
--success-foreground: 109 55% 28%;
|
33
|
-
|
34
|
-
--info: 223 78% 42%;
|
35
|
-
--info-foreground: 225 100% 50%;
|
36
|
-
|
37
|
-
--attention: 45 90% 45%;
|
38
|
-
--attention-foreground: 60 98.4% 48.8% 0.82;
|
39
|
-
|
40
|
-
--ring: 215 20.2% 65.1%;
|
41
|
-
|
42
|
-
--radius: 0.5rem;
|
43
|
-
}
|
44
|
-
|
45
35
|
.dark {
|
46
|
-
--background:
|
47
|
-
--foreground:
|
48
|
-
|
49
|
-
--
|
50
|
-
--
|
51
|
-
|
52
|
-
--
|
53
|
-
--
|
54
|
-
|
55
|
-
--
|
56
|
-
--
|
57
|
-
|
58
|
-
--
|
59
|
-
--
|
60
|
-
|
61
|
-
--
|
62
|
-
--
|
63
|
-
|
64
|
-
--
|
65
|
-
--
|
66
|
-
|
67
|
-
--secondary: 222.2 47.4% 11.2%;
|
68
|
-
--secondary-foreground: 210 40% 98%;
|
69
|
-
|
70
|
-
--destructive: 0 63% 31%;
|
71
|
-
--destructive-foreground: 210 40% 98%;
|
72
|
-
|
73
|
-
--attention: 45, 90%, 45%, 0.8;
|
74
|
-
--attention-foreground: 60 98.4% 48.8% 0.82;
|
36
|
+
--background: 240 10% 3.9%;
|
37
|
+
--foreground: 0 0% 98%;
|
38
|
+
--card: 240 10% 3.9%;
|
39
|
+
--card-foreground: 0 0% 98%;
|
40
|
+
--popover: 240 10% 3.9%;
|
41
|
+
--popover-foreground: 0 0% 98%;
|
42
|
+
--primary: 0 0% 98%;
|
43
|
+
--primary-foreground: 240 5.9% 10%;
|
44
|
+
--secondary: 240 3.7% 15.9%;
|
45
|
+
--secondary-foreground: 0 0% 98%;
|
46
|
+
--muted: 240 3.7% 15.9%;
|
47
|
+
--muted-foreground: 240 5% 64.9%;
|
48
|
+
--accent: 240 3.7% 15.9%;
|
49
|
+
--accent-foreground: 0 0% 98%;
|
50
|
+
--destructive: 0 62.8% 30.6%;
|
51
|
+
--destructive-foreground: 0 85.7% 97.3%;
|
52
|
+
--border: 240 3.7% 15.9%;
|
53
|
+
--input: 240 3.7% 15.9%;
|
54
|
+
--ring: 240 4.9% 83.9%;
|
55
|
+
--radius: 0.5rem;
|
75
56
|
|
76
57
|
--success: 109 55% 28%;
|
77
58
|
--success-foreground: 109 55% 28%;
|
78
59
|
|
79
|
-
--
|
80
|
-
|
81
|
-
--radius: 0.5rem;
|
60
|
+
--attention: 45, 90%, 45%, 0.8;
|
61
|
+
--attention-foreground: 60 98.4% 48.8% 0.82;
|
82
62
|
}
|
83
63
|
}
|
84
64
|
|
@@ -104,7 +84,19 @@
|
|
104
84
|
.code-sample span {
|
105
85
|
@apply bg-zinc-950;
|
106
86
|
}
|
87
|
+
input.error {
|
88
|
+
@apply border-red-400;
|
89
|
+
}
|
90
|
+
|
91
|
+
label.error {
|
92
|
+
@apply text-destructive;
|
93
|
+
}
|
94
|
+
|
95
|
+
input.error:focus-visible {
|
96
|
+
@apply ring-destructive;
|
97
|
+
}
|
107
98
|
}
|
99
|
+
|
108
100
|
input[type="range"] {
|
109
101
|
display: inline-block;
|
110
102
|
vertical-align: middle;
|
@@ -214,11 +206,3 @@ input[type="range"]::-ms-track {
|
|
214
206
|
overflow: hidden;
|
215
207
|
transition: all 0.2s;
|
216
208
|
}
|
217
|
-
|
218
|
-
input.error {
|
219
|
-
@apply border-red-400;
|
220
|
-
}
|
221
|
-
|
222
|
-
label.error {
|
223
|
-
@apply text-destructive;
|
224
|
-
}
|
@@ -1,12 +1,13 @@
|
|
1
|
-
class
|
1
|
+
class Shadcn::FormBuilder < ActionView::Helpers::FormBuilder
|
2
2
|
def label(method, options = {})
|
3
3
|
error_class = @object.errors[method].any? ? "error" : ""
|
4
4
|
options[:class] = @template.tw("#{options[:class]} #{error_class}")
|
5
|
-
@template.render_label(name: "#{object_name}[#{method}]", label: method
|
5
|
+
@template.render_label(name: "#{object_name}[#{method}]", label: label_for(@object, method), **options)
|
6
6
|
end
|
7
7
|
|
8
8
|
def text_field(method, options = {})
|
9
|
-
|
9
|
+
error_class = @object.errors[method].any? ? "error" : ""
|
10
|
+
options[:class] = @template.tw("#{options[:class]} #{error_class}")
|
10
11
|
@template.render_input(
|
11
12
|
name: "#{object_name}[#{method}]",
|
12
13
|
id: "#{object_name}_#{method}",
|
@@ -36,8 +37,26 @@ class ShadcnFormBuilder < ActionView::Helpers::FormBuilder
|
|
36
37
|
type: "email", **options
|
37
38
|
)
|
38
39
|
end
|
39
|
-
|
40
|
+
|
41
|
+
def text_area(method, options = {})
|
42
|
+
error_class = @object.errors[method].any? ? "error" : ""
|
43
|
+
options[:class] = @template.tw("#{options[:class]} #{error_class}")
|
44
|
+
@template.render_textarea(
|
45
|
+
name: "#{object_name}[#{method}]",
|
46
|
+
id: "#{object_name}_#{method}",
|
47
|
+
value: @object.send(method),
|
48
|
+
type: "text", **options
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
40
52
|
def submit(value = nil, options = {})
|
41
53
|
@template.render_button(value, **options)
|
42
54
|
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def label_for(object, method)
|
59
|
+
return method.capitalize if object.nil?
|
60
|
+
object.class.human_attribute_name(method)
|
61
|
+
end
|
43
62
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Shadcn::SelectComponent
|
2
|
+
include ComponentsHelper
|
3
|
+
attr_reader :name, :selected, :view_context
|
4
|
+
|
5
|
+
def initialize(name:, view_context:, selected: nil, **options, &block)
|
6
|
+
@name = name
|
7
|
+
@view_context = view_context
|
8
|
+
@selected = selected
|
9
|
+
@options = options
|
10
|
+
@content = view_context.capture(self, &block) if block
|
11
|
+
end
|
12
|
+
|
13
|
+
def option(value:, label: nil, &block)
|
14
|
+
content = label || view_context.capture(&block)
|
15
|
+
option_options = {value: value}
|
16
|
+
option_options[:selected] = "selected" if value == selected
|
17
|
+
view_context.content_tag :option, content, option_options
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
view_context.content_tag :select, @content, name: name, class: tw("rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", @options[:class])
|
22
|
+
end
|
23
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Components::AlertHelper
|
2
|
-
def render_alert(title:, description: nil, variant: :default, icon: true)
|
2
|
+
def render_alert(title:, description: nil, variant: :default, icon: true, &block)
|
3
3
|
alert_classes = case variant.to_sym
|
4
4
|
when :default
|
5
5
|
"[&>svg]:text-foreground bg-background text-foreground"
|
@@ -12,6 +12,7 @@ module Components::AlertHelper
|
|
12
12
|
when :attention
|
13
13
|
"border-attention/50 text-attention dark:border-attention [&>svg]:text-attention"
|
14
14
|
end
|
15
|
-
|
15
|
+
content = (capture(&block) if block) || description
|
16
|
+
render "components/ui/alert", title:, content:, alert_classes:, variant:, icon:
|
16
17
|
end
|
17
18
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Components::BadgeHelper
|
2
2
|
def render_badge(label = "", data: "", text: "", variant: :default, **options)
|
3
3
|
badge_classes = " inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 "
|
4
|
-
|
4
|
+
variant_classes = case variant.to_sym
|
5
5
|
when :default
|
6
6
|
ComponentsHelper::PRIMARY_CLASSES
|
7
7
|
when :secondary
|
@@ -13,7 +13,7 @@ module Components::BadgeHelper
|
|
13
13
|
when :ghost
|
14
14
|
ComponentsHelper::GHOST_CLASSES
|
15
15
|
end
|
16
|
-
badge_classes << " #{
|
16
|
+
badge_classes << " #{variant_classes}"
|
17
17
|
text = label if label.present?
|
18
18
|
|
19
19
|
content_tag :div, class: badge_classes do
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Components::ButtonHelper
|
2
2
|
def render_button(label = "", text: nil, variant: :default, as: :button, href: nil, data: {}, **options, &block)
|
3
3
|
button_classes = " inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2 "
|
4
|
-
|
4
|
+
variant_classes = case variant.to_sym
|
5
5
|
when :default
|
6
6
|
" bg-primary text-primary-foreground hover:bg-primary/90 "
|
7
7
|
when :secondary
|
@@ -13,7 +13,8 @@ module Components::ButtonHelper
|
|
13
13
|
when :ghost
|
14
14
|
" hover:bg-accent hover:text-accent-foreground "
|
15
15
|
end
|
16
|
-
button_classes
|
16
|
+
button_classes = tw(button_classes, variant_classes, options[:class])
|
17
|
+
|
17
18
|
text = label if label.present?
|
18
19
|
text = capture(&block) if block
|
19
20
|
render "components/ui/button", text:, button_classes:, as:, href:, data:, **options
|
@@ -9,4 +9,8 @@ module Components::FilterHelper
|
|
9
9
|
input_class = content_for?(:filter_icon) ? "pl-1" : ""
|
10
10
|
render "components/ui/filter", items: items, options: options, input_class: input_class, content: content
|
11
11
|
end
|
12
|
+
|
13
|
+
def list_item(:value, :name, :selected)
|
14
|
+
"#{name}"
|
15
|
+
end
|
12
16
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Components::FormsHelper
|
2
2
|
def render_form_with(**opts)
|
3
|
-
form_with(**opts.merge(builder:
|
3
|
+
form_with(**opts.merge(builder: Shadcn::FormBuilder)) do |form|
|
4
4
|
yield form
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
8
|
def render_form_for(obj, **opts)
|
9
|
-
form_for(obj, **opts.merge(builder:
|
9
|
+
form_for(obj, **opts.merge(builder: Shadcn::FormBuilder), html: opts) do |form|
|
10
10
|
yield form
|
11
11
|
end
|
12
12
|
end
|
@@ -10,14 +10,15 @@ module Components::InputHelper
|
|
10
10
|
options[:class] = tw(options[:class])
|
11
11
|
|
12
12
|
options.reverse_merge!(
|
13
|
-
label: (options[:
|
13
|
+
label: (options[:label] || false),
|
14
14
|
required: (options[:required] || false),
|
15
15
|
disabled: (options[:disabled] || false),
|
16
16
|
readonly: (options[:readonly] || false),
|
17
17
|
placeholder: (options[:placeholder] || ""),
|
18
18
|
autocomplete: (options[:autocomplete] || ""),
|
19
19
|
autocapitalize: (options[:autocapitalize] || nil),
|
20
|
-
autocorrect: (options[:autocorrect] || nil)
|
20
|
+
autocorrect: (options[:autocorrect] || nil),
|
21
|
+
autofocus: (options[:autofocus] || nil)
|
21
22
|
)
|
22
23
|
render partial: "components/ui/input", locals: {
|
23
24
|
type:,
|
@@ -2,6 +2,7 @@ module Components::SheetHelper
|
|
2
2
|
def render_sheet(**options, &block)
|
3
3
|
options[:direction] ||= "left"
|
4
4
|
options[:width] ||= "w-3/4"
|
5
|
+
options[:state] ||= "closed"
|
5
6
|
|
6
7
|
content_for :sheet_trigger, "", flush: true
|
7
8
|
content_for :sheet_content, "", flush: true
|
@@ -20,8 +21,8 @@ module Components::SheetHelper
|
|
20
21
|
|
21
22
|
def direction_class(direction)
|
22
23
|
mappings = {
|
23
|
-
|
24
|
-
|
24
|
+
left: "left-0",
|
25
|
+
right: "right-0"
|
25
26
|
}
|
26
27
|
|
27
28
|
mappings[direction.to_sym]
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Components::TableHelper
|
2
|
+
def render_table(caption = nil, **options, &block)
|
3
|
+
content_tag :table, options.reverse_merge(
|
4
|
+
class: tw("w-full text-sm border-b", options[:class])
|
5
|
+
) do
|
6
|
+
if caption.present?
|
7
|
+
content_tag :caption, caption, class: "mt-4 text-sm text-muted-foreground " do
|
8
|
+
capture(&block)
|
9
|
+
end
|
10
|
+
else
|
11
|
+
capture(&block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def table_head(**options, &block)
|
17
|
+
content_tag :thead, options.reverse_merge(
|
18
|
+
class: tw("[&_tr]:border-b", options[:class])
|
19
|
+
) do
|
20
|
+
content_tag :tr, class: "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted" do
|
21
|
+
capture(&block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def table_header(content = nil, **options, &block)
|
27
|
+
content_tag :th, options.reverse_merge(
|
28
|
+
class: tw("h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", options[:class])
|
29
|
+
) do
|
30
|
+
if block
|
31
|
+
capture(&block)
|
32
|
+
else
|
33
|
+
content
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def table_body(**options, &block)
|
39
|
+
content_tag :tbody, class: options.reverse_merge(
|
40
|
+
class: tw("[&_tr:last-child]:border-0", options[:class])
|
41
|
+
), &block
|
42
|
+
end
|
43
|
+
|
44
|
+
def table_row(**options, &block)
|
45
|
+
content_tag :tr, options.reverse_merge(
|
46
|
+
class: tw("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", options[:class])
|
47
|
+
), &block
|
48
|
+
end
|
49
|
+
|
50
|
+
def table_column(content = nil, **options, &block)
|
51
|
+
content_tag :td, options.reverse_merge(
|
52
|
+
class: tw("p-4 align-middle [&:has([role=checkbox])]:pr-0 font-medium", options[:class])
|
53
|
+
) do
|
54
|
+
if block
|
55
|
+
capture(&block)
|
56
|
+
else
|
57
|
+
content
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require "tailwind_merge"
|
2
2
|
|
3
3
|
module ComponentsHelper
|
4
|
-
def tw(classes)
|
5
|
-
TailwindMerge::Merger.new.merge(classes)
|
4
|
+
def tw(*classes)
|
5
|
+
TailwindMerge::Merger.new.merge(classes.join(" "))
|
6
6
|
end
|
7
7
|
|
8
8
|
PRIMARY_CLASSES = " bg-primary text-primary-foreground hover:bg-primary/80 "
|
@@ -61,6 +61,9 @@ export default class UIDialog extends Controller {
|
|
61
61
|
closeBy(target) {
|
62
62
|
this.toggleClass(false);
|
63
63
|
|
64
|
+
if (target.getAttribute('data-ui--dialog-target') === 'modal') {
|
65
|
+
document.body.classList.remove("overflow-hidden");
|
66
|
+
}
|
64
67
|
this.dispatch("closed", { detail: { target: target } });
|
65
68
|
}
|
66
69
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["fileInput"];
|
5
|
+
connect() {
|
6
|
+
this.element.addEventListener("dragover", this.preventDragDefaults);
|
7
|
+
this.element.addEventListener("dragenter", this.preventDragDefaults);
|
8
|
+
}
|
9
|
+
|
10
|
+
disconnect() {
|
11
|
+
this.element.removeEventListener("dragover", this.preventDragDefaults);
|
12
|
+
this.element.removeEventListener("dragenter", this.preventDragDefaults);
|
13
|
+
}
|
14
|
+
|
15
|
+
preventDragDefaults(e) {
|
16
|
+
e.preventDefault();
|
17
|
+
e.stopPropagation();
|
18
|
+
}
|
19
|
+
|
20
|
+
trigger() {
|
21
|
+
this.fileInputTarget.click();
|
22
|
+
}
|
23
|
+
|
24
|
+
acceptFiles(event) {
|
25
|
+
event.preventDefault();
|
26
|
+
const files = event.dataTransfer ? event.dataTransfer.files : event.target.files;
|
27
|
+
[...files].forEach((file) => {
|
28
|
+
this.uploadFile(file);
|
29
|
+
});
|
30
|
+
}
|
31
|
+
|
32
|
+
// Implement your own file upload strategy here...
|
33
|
+
uploadFile(file) {
|
34
|
+
console.log("Received file for upload: ", file);
|
35
|
+
console.log("Implement your own file upload strategy here...");
|
36
|
+
// const formData = new FormData();
|
37
|
+
// formData.append("file", file);
|
38
|
+
|
39
|
+
// fetch("/upload", {
|
40
|
+
// method: "POST",
|
41
|
+
// body: formData,
|
42
|
+
// })
|
43
|
+
// .then((response) => response.json())
|
44
|
+
// .then((data) => {
|
45
|
+
// console.log(data);
|
46
|
+
// });
|
47
|
+
}
|
48
|
+
}
|
@@ -61,7 +61,7 @@
|
|
61
61
|
y1="16"
|
62
62
|
y2="16"></line>
|
63
63
|
</svg>
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
<% end if icon %>
|
65
|
+
<h5 class="mb-1 font-medium leading-none tracking-tight"><%= title %></h5>
|
66
|
+
<div class="text-sm [&_p]:leading-relaxed"><%= content %></div>
|
67
67
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="rounded-lg border bg-card text-card-foreground shadow-sm w-[350px]
|
1
|
+
<div class="<%= tw("rounded-lg border bg-card text-card-foreground shadow-sm w-[350px]", options[:class]) %">
|
2
2
|
<% if title || subtitle %>
|
3
3
|
<div class="flex flex-col space-y-1.5 p-6">
|
4
4
|
<% if title %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div class="w-full">
|
2
|
+
<div class="p-6">
|
3
|
+
<div id="dropzone" data-controller="ui--dropzone" data-action="click->ui--dropzone#trigger drop->ui--dropzone#acceptFiles">
|
4
|
+
<button
|
5
|
+
class="w-full rounded-lg bg-muted border-2 border-dashed border-gray-300 p-8 text-center hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
|
6
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mx-auto h-12 w-12 text-gray-400"><path d="M15.5 2H8.6c-.4 0-.8.2-1.1.5-.3.3-.5.7-.5 1.1v12.8c0 .4.2.8.5 1.1.3.3.7.5 1.1.5h9.8c.4 0 .8-.2 1.1-.5.3-.3.5-.7.5-1.1V6.5L15.5 2z" /><path d="M3 7.6v12.8c0 .4.2.8.5 1.1.3.3.7.5 1.1.5h9.8" /><path d="M15 2v5h5" /></svg>
|
7
|
+
<span class="mt-2 block text-sm font-semibold text-muted-foreground dark:text-white">Drag Files to Upload or Click Here</span>
|
8
|
+
</button>
|
9
|
+
<input type="file" class="hidden" multiple data-ui--dropzone-target="fileInput" data-action="change->ui--dropzone#acceptFiles">
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
@@ -5,12 +5,17 @@
|
|
5
5
|
|
6
6
|
<div
|
7
7
|
role="dialog"
|
8
|
-
data-state="
|
8
|
+
data-state="<%= options[:state]%>"
|
9
9
|
data-ui--sheet-target="dialog"
|
10
|
-
class="data-[state=closed]:hidden data-[state=open]:block fixed z-50 gap-4 bg-background p-6 shadow-lg
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
class="<%= tw("data-[state=closed]:hidden data-[state=open]:block fixed z-50 gap-4 bg-background p-6 shadow-lg
|
11
|
+
transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300
|
12
|
+
data-[state=open]:duration-500 inset-y-0 h-full border-l sm:max-w-sm",
|
13
|
+
"data-[state=closed]:slide-out-to-#{options[:direction]}
|
14
|
+
data-[state=open]:slide-in-from-#{options[:direction]}",
|
15
|
+
direction_class(options[:direction]), options[:width],
|
16
|
+
options[:class]) %>"
|
17
|
+
tabindex="-1"
|
18
|
+
style="pointer-events: auto">
|
14
19
|
<div data-ui--sheet-target="content"><%= content_for(:sheet_content) %></div>
|
15
20
|
<button
|
16
21
|
data-ui--sheet-target="closeButton"
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<textarea
|
2
|
-
class="flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50
|
2
|
+
class="<%= tw("flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", options[:class]) %>"
|
3
3
|
placeholder="<%= options[:placeholder] %>"
|
4
4
|
name="<%= name %>"
|
5
5
|
id="<% id %>"
|
6
6
|
<%= options[:disabled] ? "disabled" : "" %>
|
7
7
|
<%= options[:required] ? "required" : "" %>
|
8
8
|
<%= options[:readonly] ? "readonly" : "" %>
|
9
|
-
<%= options[:rows] ? "rows" : ""
|
9
|
+
<%= options[:rows] ? "rows" : "" %>><%= value %></textarea>
|
@@ -34,4 +34,4 @@ needs without any unnecessary abstraction.
|
|
34
34
|
|
35
35
|
The gem provides a generator for you to use in your application to facilitate copying the code from
|
36
36
|
this application to yours. It also enforces some setup for you as the component files alone in
|
37
|
-
isolation won't always work. [Learn more about the generator](/
|
37
|
+
isolation won't always work. [Learn more about the generator](/docs/generators).
|
@@ -117,7 +117,7 @@ by being at the end. And obviously feel free to inspect shadcnConfig and keep on
|
|
117
117
|
## End
|
118
118
|
|
119
119
|
That's it! You are now set to start
|
120
|
-
[installing components via the generator](
|
120
|
+
[installing components via the generator](/docs/generators) and rendering them into your
|
121
121
|
views.
|
122
122
|
|
123
123
|
# Manual Installation
|
@@ -17,7 +17,7 @@
|
|
17
17
|
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
18
18
|
|
19
19
|
<%= code_sample(language: "sh") do %>
|
20
|
-
rails generate shadcn-ui
|
20
|
+
rails generate shadcn-ui accordion
|
21
21
|
<% end %>
|
22
22
|
|
23
23
|
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage"><a href="/docs/components/dialog#usage">Usage</a></h2>
|
@@ -16,7 +16,7 @@
|
|
16
16
|
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
17
17
|
|
18
18
|
<%= code_sample(language: "sh") do %>
|
19
|
-
rails generate
|
19
|
+
rails generate shadcn-ui dialog
|
20
20
|
<% end %>
|
21
21
|
|
22
22
|
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage"><a href="/docs/components/dialog#usage">Usage</a></h2>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
description: "Displays a menu to the user — such as a set of actions or functions — triggered by a button." %>
|
3
3
|
|
4
4
|
<%= content_for :preview, flush: true do %>
|
5
|
-
|
5
|
+
<%= render_dropdown_menu do %>
|
6
6
|
<%= dropdown_menu_trigger do %>
|
7
7
|
<%= render_button "Open Dropdown", variant: :outline %>
|
8
8
|
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">The Dropzone component introduces:</p>
|
2
|
+
|
3
|
+
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-sm">
|
4
|
+
<li><%= code("app/helpers/components/dropzone_helper.rb") %></li>
|
5
|
+
<li><%= code("app/views/components/ui/_dropzone.html.erb") %></li>
|
6
|
+
<li><%= code("app/javascript/controllers/ui/dropzone_controller.js") %></li>
|
7
|
+
</ul>
|
8
|
+
|
9
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
10
|
+
The method <%= code("render_dropzone") %> defined in <%= code("app/helpers/components/dropzone_helper.rb") %> will render the dropzone widget that is bound to the Stimulus controller.
|
11
|
+
Upon triggering the file dialog or dragging and dropping files, the controller will delegate the files individually to a function, <%= code("uploadFile") %>. It is up to you to define what to do when a a file is to be uploaded.
|
12
|
+
<p>
|
13
|
+
|
14
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
15
|
+
To implement fully, edit the <%= code("uploadFile") %> function in <%= code("app/javascript/controllers/ui/dropzone_controller.js") %>. This function is called for each file that is to be uploaded. The function is passed the file object.
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
19
|
+
If you try the example component, you will see that it is logging the file object to the console.
|
20
|
+
</p>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render_dropzone %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render_dropzone %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= render "layouts/documentation/component_header",
|
2
|
+
title: "Dropzone",
|
3
|
+
description: "A dropzone component that accepts multiple files via drag and drop." %>
|
4
|
+
|
5
|
+
<% content_for :preview, flush: true do %>
|
6
|
+
<div class="w-full flex justify-center">
|
7
|
+
<%= render_code_preview('dropzone') %>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% content_for :code, flush: true do %>
|
12
|
+
<div class="w-full flex justify-center">
|
13
|
+
<%= code_partial("dropzone/preview", :erb) %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<%= render_preview %>
|
18
|
+
|
19
|
+
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
20
|
+
<%= code_sample(language: "sh") do %>
|
21
|
+
rails generate shadcn-ui dropzone
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage">Usage</h2>
|
25
|
+
<%= code_partial("dropzone/usage", :erb) %>
|
26
|
+
|
27
|
+
<%= render_usage("dropzone") %>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<p class="leading-7 [&:not(:first-child)]:mt-6">The Forms component introduces:</p>
|
2
2
|
|
3
3
|
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-sm">
|
4
|
-
<li><%= code("app/
|
4
|
+
<li><%= code("app/components/shadcn/form_builder.rb") %></li>
|
5
5
|
<li><%= code("app/helpers/components/forms_helper.rb") %></li>
|
6
6
|
</ul>
|
7
7
|
|
8
8
|
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
9
|
-
The <code>
|
9
|
+
The <code>Shadcn::FormBuilder</code> is a custom form builder that extends the
|
10
10
|
<code>FormBuilder</code> class. It adds the following methods that provide the form with inputs and controls:
|
11
11
|
<p>
|
12
12
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">The Select component introduces:</p>
|
2
|
+
|
3
|
+
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-sm">
|
4
|
+
<li><%= code("app/helpers/components/select_helper.rb") %></li>
|
5
|
+
<li><%= code("app/components/shadcn/select_component.rb") %></li>
|
6
|
+
</ul>
|
7
|
+
|
8
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
9
|
+
The select component is implemented as a component object defined in <%= code("app/components/shadcn/select_component.rb") %>.
|
10
|
+
This ruby class is initialized from the helper defined in <%= code("app/helpers/components/select_helper.rb") %>, <%= code "render_select" %>.
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
14
|
+
The <%= code("render_select") %> method accepts a <%= code("name") %> keyword argument for the name of the form field.
|
15
|
+
An optional argument of <%= code "selected" %> can contain the value of the option to be selected by default.
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
19
|
+
<%= code("render_select") %> yields an instance of the <%= code "Shadcn::SelectComponent" %> that can be used to build <%= code "option" %>s for the select.
|
20
|
+
<%= code "option" %> on the component instance accepts a <%= code "label" %> argument for the label text to be displayed for the option whose value will be the <%= code "value" %> on the component instance yields a new option object that accepts a <%= code "label" %> and <%= code "value" %> argument.
|
21
|
+
<%= code "option" %> also accepts a block that can be used to create the label.
|
22
|
+
</p>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= render "layouts/documentation/component_header",
|
2
|
+
title: "Select",
|
3
|
+
description: "A standard but styled select component." %>
|
4
|
+
|
5
|
+
<% content_for :preview, flush: true do %>
|
6
|
+
<div class="w-full flex justify-center">
|
7
|
+
<%= render_code_preview('select') %>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% content_for :code, flush: true do %>
|
12
|
+
<div class="w-full flex justify-center">
|
13
|
+
<%= code_partial("select/preview", :erb) %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<%= render_preview %>
|
18
|
+
|
19
|
+
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
20
|
+
<%= code_sample(language: "sh") do %>
|
21
|
+
rails generate shadcn-ui select
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage">Usage</h2>
|
25
|
+
<%= code_partial("select/usage", :erb) %>
|
26
|
+
|
27
|
+
<%= render_usage("select") %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">The Table component introduces:</p>
|
2
|
+
|
3
|
+
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-sm">
|
4
|
+
<li><%= code("app/helpers/components/table_helper.rb") %></li>
|
5
|
+
</ul>
|
6
|
+
|
7
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
8
|
+
The table component is so far unique in that it is entirely provided by <%= code("app/helpers/components/table_helper.rb") %>. This helper introduces methods that rely on <%= code("content_tag") %> to create the markup for the table. To edit anything about the rendered table, look there.
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
12
|
+
<%= code("app/helpers/components/table_helper.rb") %> introduces the following methods that can be used to create a table.
|
13
|
+
|
14
|
+
<ul class="my-6 ml-6 list-disc [&>li]:mt-2 text-md">
|
15
|
+
<li><%= code("render_table") %> accepts an optional caption as the first argument along with the block for the rest of the table components.</li>
|
16
|
+
<li><%= code("table_head") %> accepts a block for the content of the <%= code("thead") %> row.</li>
|
17
|
+
<li><%= code("table_header") %> accepts the header content inline or in a block. This will be rendered within the <%= code("thead") %> for that column.</li>
|
18
|
+
<li><%= code("table_body") %> accepts a block for the content of the <%= code("tbody") %>.</li>
|
19
|
+
<li><%= code("table_row") %> accepts a block for the content of the <%= code("tr") %>.</li>
|
20
|
+
<li><%= code("table_column") %> accepts the column content inline or in a block. This will be rendered within the <%= code("td") %> for the column.</li>
|
21
|
+
</ul>
|
22
|
+
|
23
|
+
</p>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<% @tracks = [
|
2
|
+
{title: "Total Eclipse of the Heart", artist: "Bonnie Tyler"},
|
3
|
+
{title: "I Will Always Love You", artist: "Whitney Houston"},
|
4
|
+
{title: "I Wanna Dance with Somebody", artist: "Whitney Houston"},
|
5
|
+
{title: "I Will Survive", artist: "Gloria Gaynor"},
|
6
|
+
{title: "My Heart Will Go On", artist: "Celine Dion"},
|
7
|
+
] %>
|
8
|
+
|
9
|
+
<%= render_table do %>
|
10
|
+
<%= table_head do %>
|
11
|
+
<%= table_header "", class: "w-1" %>
|
12
|
+
<%= table_header class: "" do %>
|
13
|
+
Title
|
14
|
+
<% end %>
|
15
|
+
<%= table_header "Artist" %>
|
16
|
+
<% end %>
|
17
|
+
<%= table_body do %>
|
18
|
+
<% @tracks.each.with_index do |track, i| %>
|
19
|
+
<%= table_row do %>
|
20
|
+
<%= table_column do %>
|
21
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
22
|
+
stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
23
|
+
stroke-linejoin="round">
|
24
|
+
<circle cx="12" cy="12" r="10"></circle>
|
25
|
+
<polygon points="10 8 16 12 10 16 10 8"></polygon>
|
26
|
+
</svg>
|
27
|
+
<% end %>
|
28
|
+
<%= table_column do %>
|
29
|
+
<%= track[:title] %>
|
30
|
+
<% end %>
|
31
|
+
<%= table_column track[:artist] %>
|
32
|
+
<% end %>
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= render "layouts/documentation/component_header",
|
2
|
+
title: "Table",
|
3
|
+
description: "A simple table component for displaying data in rows and columns." %>
|
4
|
+
|
5
|
+
<% content_for :preview, flush: true do %>
|
6
|
+
<div class="w-full flex justify-center">
|
7
|
+
<%= render_code_preview('table') %>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% content_for :code, flush: true do %>
|
12
|
+
<div class="w-full flex justify-center">
|
13
|
+
<%= code_partial("table/preview", :erb) %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<%= render_preview %>
|
18
|
+
|
19
|
+
<h2 class="font-heading scroll-m-20 border-b pb-2 text-2xl font-semibold tracking-tight first:mt-0" id="installation">Installation</h2>
|
20
|
+
<%= code_sample(language: "sh") do %>
|
21
|
+
rails generate shadcn-ui table
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<h2 class="font-heading mt-12 scroll-m-20 border-b pb-2 mb-2 text-2xl font-semibold tracking-tight first:mt-0" id="usage">Usage</h2>
|
25
|
+
<%= code_partial("table/usage", :erb) %>
|
26
|
+
|
27
|
+
<%= render_usage("table") %>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<%= sidebar_link "Installation", documentation_path("installation") %>
|
10
10
|
<%= sidebar_link "Generators", documentation_path("generators") %>
|
11
11
|
<%= sidebar_link "Helpers", documentation_path("helpers") %>
|
12
|
-
<%= sidebar_link "Stimulus", documentation_path("
|
12
|
+
<%= sidebar_link "Stimulus", documentation_path("javascript") %>
|
13
13
|
<%= sidebar_link "About", documentation_path("about") %>
|
14
14
|
</div>
|
15
15
|
</div>
|
@@ -34,6 +34,7 @@
|
|
34
34
|
<%#= sidebar_link "Date Picker", "/docs/components/date-picker" %>
|
35
35
|
<%= sidebar_link "✅ 📖 Dialog", "/docs/components/dialog" %>
|
36
36
|
<%= sidebar_link "✅ 📖 Dropdown Menu", "/docs/components/dropdown-menu" %>
|
37
|
+
<%= sidebar_link "✅ 📖 Dropzone", "/docs/components/dropzone" %>
|
37
38
|
<%= sidebar_link "✅ 📖 Filter", "/docs/components/filter" %>
|
38
39
|
<%= sidebar_link "✅ 📖 Forms", "/docs/components/forms" %>
|
39
40
|
<%= sidebar_link "✅ 📖 Hover Card", "/docs/components/hover-card" %>
|
@@ -45,13 +46,13 @@
|
|
45
46
|
<%= sidebar_link "✅ 📖 Progress", "/docs/components/progress" %>
|
46
47
|
<%#= sidebar_link "Radio Group", "/docs/components/radio-group" %>
|
47
48
|
<%#= sidebar_link "Scroll Area", "/docs/components/scroll-area" %>
|
48
|
-
|
49
|
+
<%= sidebar_link "✅ 📖 Select", "/docs/components/select" %>
|
49
50
|
<%= sidebar_link "✅ 📖 Separator", "/docs/components/separator" %>
|
50
51
|
<%= sidebar_link "✅ 📖 Sheet", "/docs/components/sheet" %>
|
51
52
|
<%= sidebar_link "✅ 📖 Skeleton", "/docs/components/skeleton" %>
|
52
53
|
<%= sidebar_link "✅ 📖 Slider", "/docs/components/slider" %>
|
53
54
|
<%= sidebar_link "✅ 📖 Switch", "/docs/components/switch" %>
|
54
|
-
|
55
|
+
<%= sidebar_link "✅ 📖 Table", "/docs/components/table" %>
|
55
56
|
<%= sidebar_link "✅ 📖 Tabs", "/docs/components/tabs" %>
|
56
57
|
<%= sidebar_link "✅ 📖 Textarea", "/docs/components/textarea" %>
|
57
58
|
<%= sidebar_link "✅ 📖 Toast", "/docs/components/toast" %>
|
data/lib/components.json
CHANGED
@@ -21,11 +21,10 @@
|
|
21
21
|
"name": "alert-dialog",
|
22
22
|
"type": "components:ui",
|
23
23
|
"files": [
|
24
|
-
"app/helpers/components/
|
25
|
-
"app/views/components/ui/
|
26
|
-
"app/javascript/controllers/ui/alert-dialog_controller.js"
|
24
|
+
"app/helpers/components/alert_dialog_helper.rb",
|
25
|
+
"app/views/components/ui/_alert_dialog.html.erb"
|
27
26
|
],
|
28
|
-
"dependencies": [{ "component": "dialog" }]
|
27
|
+
"dependencies": [{ "component": "dialog" }, "app/views/components/ui/shared/_backdrop.html.erb"]
|
29
28
|
},
|
30
29
|
"badge": {
|
31
30
|
"name": "badge",
|
@@ -102,7 +101,8 @@
|
|
102
101
|
"app/helpers/components/dialog_helper.rb",
|
103
102
|
"app/views/components/ui/_dialog.html.erb",
|
104
103
|
"app/javascript/controllers/ui/dialog_controller.js"
|
105
|
-
]
|
104
|
+
],
|
105
|
+
"dependencies": ["app/views/components/ui/shared/_backdrop.html.erb"]
|
106
106
|
},
|
107
107
|
"dropdown-menu": {
|
108
108
|
"name": "dropdown-menu",
|
@@ -117,10 +117,28 @@
|
|
117
117
|
"app/views/components/ui/shared/_menu_item.html.erb"
|
118
118
|
]
|
119
119
|
},
|
120
|
+
"dropzone": {
|
121
|
+
"name": "dropzone",
|
122
|
+
"type": "components:ui",
|
123
|
+
"files": [
|
124
|
+
"app/helpers/components/dropzone_helper.rb",
|
125
|
+
"app/views/components/ui/_dropzone.html.erb",
|
126
|
+
"app/javascript/controllers/ui/dropzone_controller.js"
|
127
|
+
]
|
128
|
+
},
|
129
|
+
"filter": {
|
130
|
+
"name": "filter",
|
131
|
+
"type": "components:ui",
|
132
|
+
"files": [
|
133
|
+
"app/helpers/components/filter_helper.rb",
|
134
|
+
"app/views/components/ui/_filter.html.erb",
|
135
|
+
"app/javascript/controllers/ui/filter_controller.js"
|
136
|
+
]
|
137
|
+
},
|
120
138
|
"forms": {
|
121
139
|
"name": "forms",
|
122
140
|
"type": "components:ui",
|
123
|
-
"files": ["app/helpers/components/forms_helper.rb", "app/
|
141
|
+
"files": ["app/helpers/components/forms_helper.rb", "app/components/shadcn/form_builder.rb"],
|
124
142
|
"dependencies": [
|
125
143
|
{ "component": "input" },
|
126
144
|
{ "component": "label" },
|
@@ -214,8 +232,7 @@
|
|
214
232
|
"type": "components:ui",
|
215
233
|
"files": [
|
216
234
|
"app/helpers/components/select_helper.rb",
|
217
|
-
"app/
|
218
|
-
"app/javascript/controllers/ui/select_controller.js"
|
235
|
+
"app/components/shadcn/select_component.rb"
|
219
236
|
]
|
220
237
|
},
|
221
238
|
"separator": {
|
@@ -120,7 +120,7 @@ class ShadcnUiGenerator < Rails::Generators::Base
|
|
120
120
|
if File.exist?(tailwind_file_path)
|
121
121
|
true
|
122
122
|
else
|
123
|
-
abort "shadcn-ui requires Tailwind CSS. Please include tailwindcss-rails in your Gemfile and run `rails g
|
123
|
+
abort "shadcn-ui requires Tailwind CSS. Please include tailwindcss-rails in your Gemfile and run `rails g tailwindcss:install` to install Tailwind CSS."
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
data/lib/shadcn-ui/version.rb
CHANGED
data/shadcn-ui.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/shadcn-ui/shadcn-ui"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "shadcn-ui"
|
7
|
+
spec.version = ShadcnUi::VERSION
|
8
|
+
spec.authors = ["Avi Flombaum"]
|
9
|
+
spec.email = ["git@avi.nyc"]
|
10
|
+
|
11
|
+
spec.homepage = "https://shadcn.rails-components.com"
|
12
|
+
spec.summary = "Provides the shadcn-ui component library to a Ruby on Rails application."
|
13
|
+
spec.description = "This gem is a documentation site and gem that will copy components from the shadcn-ui library into a Ruby on Rails application."
|
14
|
+
spec.homepage = "https://github.com/aviflombaum/shadcn-rails"
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.required_ruby_version = ">= 2.6.0"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/aviflombaum/shadcn-rails"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/aviflombaum/shadcn-rails/tree/main/CHANGELOG.md"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(__dir__) do
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
(File.expand_path(f) == __FILE__) ||
|
27
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
spec.bindir = "bin"
|
31
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
# Uncomment to register a new dependency of your gem
|
35
|
+
spec.add_dependency "tailwind_merge", "~> 0.7"
|
36
|
+
|
37
|
+
# For more information and examples about making a new gem, check out our
|
38
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
39
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shadcn-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Avi Flombaum
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tailwind_merge
|
@@ -53,12 +53,13 @@ files:
|
|
53
53
|
- app/assets/stylesheets/shadcn.css
|
54
54
|
- app/channels/application_cable/channel.rb
|
55
55
|
- app/channels/application_cable/connection.rb
|
56
|
+
- app/components/shadcn/form_builder.rb
|
57
|
+
- app/components/shadcn/select_component.rb
|
56
58
|
- app/controllers/application_controller.rb
|
57
59
|
- app/controllers/components_controller.rb
|
58
60
|
- app/controllers/concerns/.keep
|
59
61
|
- app/controllers/documentation_controller.rb
|
60
62
|
- app/controllers/users_controller.rb
|
61
|
-
- app/form_builders/shadcn_form_builder.rb
|
62
63
|
- app/helpers/application_helper.rb
|
63
64
|
- app/helpers/components/accordion_helper.rb
|
64
65
|
- app/helpers/components/alert_dialog_helper.rb
|
@@ -71,6 +72,7 @@ files:
|
|
71
72
|
- app/helpers/components/combobox_helper.rb
|
72
73
|
- app/helpers/components/dialog_helper.rb
|
73
74
|
- app/helpers/components/dropdown_menu_helper.rb
|
75
|
+
- app/helpers/components/dropzone_helper.rb
|
74
76
|
- app/helpers/components/filter_helper.rb
|
75
77
|
- app/helpers/components/forms_helper.rb
|
76
78
|
- app/helpers/components/hover_card_helper.rb
|
@@ -79,11 +81,13 @@ files:
|
|
79
81
|
- app/helpers/components/list_helper.rb
|
80
82
|
- app/helpers/components/popover_helper.rb
|
81
83
|
- app/helpers/components/progress_helper.rb
|
84
|
+
- app/helpers/components/select_helper.rb
|
82
85
|
- app/helpers/components/separator_helper.rb
|
83
86
|
- app/helpers/components/sheet_helper.rb
|
84
87
|
- app/helpers/components/skeleton_helper.rb
|
85
88
|
- app/helpers/components/slider_helper.rb
|
86
89
|
- app/helpers/components/switch_helper.rb
|
90
|
+
- app/helpers/components/table_helper.rb
|
87
91
|
- app/helpers/components/tabs_helper.rb
|
88
92
|
- app/helpers/components/textarea_helper.rb
|
89
93
|
- app/helpers/components/toast_helper.rb
|
@@ -103,6 +107,7 @@ files:
|
|
103
107
|
- app/javascript/controllers/ui/collapsible_controller.js
|
104
108
|
- app/javascript/controllers/ui/dialog_controller.js
|
105
109
|
- app/javascript/controllers/ui/dropdown_controller.js
|
110
|
+
- app/javascript/controllers/ui/dropzone_controller.js
|
106
111
|
- app/javascript/controllers/ui/filter_controller.js
|
107
112
|
- app/javascript/controllers/ui/hover-card_controller.js
|
108
113
|
- app/javascript/controllers/ui/popover_controller.js
|
@@ -131,6 +136,7 @@ files:
|
|
131
136
|
- app/views/components/ui/_command.html.erb
|
132
137
|
- app/views/components/ui/_dialog.html.erb
|
133
138
|
- app/views/components/ui/_dropdown_menu.html.erb
|
139
|
+
- app/views/components/ui/_dropzone.html.erb
|
134
140
|
- app/views/components/ui/_filter.html.erb
|
135
141
|
- app/views/components/ui/_hover_card.html.erb
|
136
142
|
- app/views/components/ui/_input.html.erb
|
@@ -215,6 +221,10 @@ files:
|
|
215
221
|
- app/views/examples/components/dropdown-menu/_usage.html.erb
|
216
222
|
- app/views/examples/components/dropdown-menu/code/_preview.erb
|
217
223
|
- app/views/examples/components/dropdown-menu/code/_usage.erb
|
224
|
+
- app/views/examples/components/dropzone.html.erb
|
225
|
+
- app/views/examples/components/dropzone/_usage.html.erb
|
226
|
+
- app/views/examples/components/dropzone/code/_preview.erb
|
227
|
+
- app/views/examples/components/dropzone/code/_usage.erb
|
218
228
|
- app/views/examples/components/filter.html.erb
|
219
229
|
- app/views/examples/components/filter/_usage.html.erb
|
220
230
|
- app/views/examples/components/filter/code/_icon.html.erb
|
@@ -246,6 +256,10 @@ files:
|
|
246
256
|
- app/views/examples/components/progress/_usage.erb
|
247
257
|
- app/views/examples/components/progress/code/_preview.erb
|
248
258
|
- app/views/examples/components/progress/code/_usage.erb
|
259
|
+
- app/views/examples/components/select.html.erb
|
260
|
+
- app/views/examples/components/select/_usage.html.erb
|
261
|
+
- app/views/examples/components/select/code/_preview.erb
|
262
|
+
- app/views/examples/components/select/code/_usage.erb
|
249
263
|
- app/views/examples/components/separator.html.erb
|
250
264
|
- app/views/examples/components/separator/_usage.html.erb
|
251
265
|
- app/views/examples/components/separator/code/_fancy.erb
|
@@ -268,6 +282,10 @@ files:
|
|
268
282
|
- app/views/examples/components/switch/_usage.html.erb
|
269
283
|
- app/views/examples/components/switch/code/_preview.erb
|
270
284
|
- app/views/examples/components/switch/code/_usage.erb
|
285
|
+
- app/views/examples/components/table.html.erb
|
286
|
+
- app/views/examples/components/table/_usage.html.erb
|
287
|
+
- app/views/examples/components/table/code/_preview.erb
|
288
|
+
- app/views/examples/components/table/code/_usage.erb
|
271
289
|
- app/views/examples/components/tabs.html.erb
|
272
290
|
- app/views/examples/components/tabs/_usage.html.erb
|
273
291
|
- app/views/examples/components/tabs/code/_account.html.erb
|
@@ -350,6 +368,7 @@ files:
|
|
350
368
|
- public/favicon.ico
|
351
369
|
- public/og.jpg
|
352
370
|
- public/robots.txt
|
371
|
+
- shadcn-ui.gemspec
|
353
372
|
- sig/shadcn-ui.rbs
|
354
373
|
- storage/.keep
|
355
374
|
- tmp/.keep
|
@@ -379,7 +398,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
379
398
|
- !ruby/object:Gem::Version
|
380
399
|
version: '0'
|
381
400
|
requirements: []
|
382
|
-
rubygems_version: 3.4
|
401
|
+
rubygems_version: 3.5.4
|
383
402
|
signing_key:
|
384
403
|
specification_version: 4
|
385
404
|
summary: Provides the shadcn-ui component library to a Ruby on Rails application.
|