relay_ui 0.2.3 → 0.4.0
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/README.md +0 -13
- data/lib/relay_ui/engine.rb +14 -10
- data/lib/relay_ui/version.rb +1 -1
- data/lib/rui/badges/base.rb +5 -1
- data/lib/rui/badges/blue.rb +3 -1
- data/lib/rui/badges/gray.rb +3 -1
- data/lib/rui/badges/green.rb +3 -1
- data/lib/rui/badges/purple.rb +3 -1
- data/lib/rui/badges/red.rb +3 -1
- data/lib/rui/badges/yellow.rb +3 -1
- data/lib/rui/badges.rb +3 -0
- data/lib/rui/base.rb +3 -8
- data/lib/rui/buttons/base.rb +12 -9
- data/lib/rui/buttons/destructive.rb +3 -1
- data/lib/rui/buttons/ghost.rb +3 -1
- data/lib/rui/buttons/outline.rb +3 -1
- data/lib/rui/buttons/primary.rb +6 -1
- data/lib/rui/buttons/secondary.rb +3 -1
- data/lib/rui/buttons.rb +3 -0
- data/lib/rui/card.rb +92 -0
- data/lib/rui/flash.rb +51 -0
- data/lib/rui/forms/checkbox.rb +25 -0
- data/lib/rui/forms/email.rb +19 -0
- data/lib/rui/forms/field_group.rb +5 -0
- data/lib/rui/forms/helpers.rb +19 -0
- data/lib/rui/forms/label.rb +7 -0
- data/lib/rui/forms/password.rb +18 -0
- data/lib/rui/forms/phone.rb +18 -0
- data/lib/rui/forms/radio.rb +22 -0
- data/lib/rui/forms/select.rb +24 -0
- data/lib/rui/forms/tailwind_form_builder.rb +142 -0
- data/lib/rui/forms/text.rb +17 -0
- data/lib/rui/forms/textarea.rb +18 -0
- data/lib/rui/forms.rb +3 -0
- data/lib/rui/helpers.rb +3 -0
- data/lib/rui/icon.rb +3 -1
- data/lib/rui/layout/body.rb +7 -0
- data/lib/rui/layout/main.rb +5 -0
- data/lib/rui/layout/page.rb +5 -0
- data/lib/rui/layout.rb +3 -0
- data/lib/rui/links/base.rb +5 -3
- data/lib/rui/links/destructive.rb +3 -1
- data/lib/rui/links/ghost.rb +3 -1
- data/lib/rui/links/outline.rb +3 -1
- data/lib/rui/links/primary.rb +3 -1
- data/lib/rui/links/secondary.rb +3 -1
- data/lib/rui/links.rb +3 -0
- data/lib/rui/markdown/generator.rb +2 -1
- data/lib/rui/markdown/safe.rb +3 -1
- data/lib/rui/markdown/safe_renderer.rb +3 -1
- data/lib/rui/markdown/unsafe.rb +3 -1
- data/lib/rui/markdown/unsafe_renderer.rb +9 -1
- data/lib/rui/markdown.rb +3 -0
- data/lib/rui/navigation/menu_button.rb +7 -0
- data/lib/rui/navigation/sidebar.rb +43 -0
- data/lib/rui/navigation/top.rb +19 -0
- data/lib/rui/navigation.rb +2 -50
- data/lib/rui/slideout.rb +9 -9
- data/lib/rui/table.rb +44 -0
- data/lib/rui/tailwind_merger.rb +17 -0
- data/lib/rui/text.rb +5 -3
- metadata +87 -3
- data/dist/relay_ui/relay_ui.css +0 -595
@@ -0,0 +1,142 @@
|
|
1
|
+
module RUI::Forms
|
2
|
+
class TailwindFormBuilder < ActionView::Helpers::FormBuilder
|
3
|
+
include ActionView::Helpers::TagHelper
|
4
|
+
|
5
|
+
class_attribute :text_field_helpers, default: field_helpers - [ :label, :check_box, :radio_button, :fields_for, :fields, :hidden_field, :file_field ]
|
6
|
+
|
7
|
+
TEXT_FIELD_STYLE = "bg-white ring ring-zinc-100 hover:ring-zinc-400 rounded px-2 py-1".freeze
|
8
|
+
SELECT_FIELD_STYLE = "block bg-white ring ring-zinc-100 hover:ring-zinc-400 rounded px-2 py-1".freeze
|
9
|
+
|
10
|
+
text_field_helpers.each do |field_method|
|
11
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
12
|
+
def #{field_method}(method, options = {})
|
13
|
+
if options.delete(:tailwindified)
|
14
|
+
super
|
15
|
+
else
|
16
|
+
text_like_field(#{field_method.inspect}, method, options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
RUBY_EVAL
|
20
|
+
end
|
21
|
+
|
22
|
+
def submit(value = nil, options = {})
|
23
|
+
custom_opts, opts = partition_custom_opts(options)
|
24
|
+
style_classes = RUI::TailwindMerger.instance.merge(
|
25
|
+
RUI::Buttons::Base::STYLE,
|
26
|
+
RUI::Buttons::Primary::STYLE
|
27
|
+
)
|
28
|
+
classes = apply_style_classes(style_classes, custom_opts)
|
29
|
+
|
30
|
+
@template.content_tag("div", super(value, { class: classes }.merge(opts)))
|
31
|
+
end
|
32
|
+
|
33
|
+
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
34
|
+
custom_opts, opts = partition_custom_opts(options)
|
35
|
+
classes = apply_style_classes(SELECT_FIELD_STYLE, custom_opts, method)
|
36
|
+
|
37
|
+
labels = labels(method, custom_opts[:label], options)
|
38
|
+
field = super(method, choices, opts, html_options.merge({ class: classes }), &block)
|
39
|
+
|
40
|
+
labels + field
|
41
|
+
end
|
42
|
+
|
43
|
+
def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
44
|
+
custom_opts = partition_custom_opts(options)
|
45
|
+
|
46
|
+
check_boxes = @template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
|
47
|
+
|
48
|
+
labels = labels(method, custom_opts, options)
|
49
|
+
|
50
|
+
@template.content_tag("div", labels + check_boxes, { class: "flex flex-col gap-3 items-start justify-middle" })
|
51
|
+
end
|
52
|
+
|
53
|
+
# def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
54
|
+
# custom_opts = partition_custom_opts(options)
|
55
|
+
|
56
|
+
# buttons = @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
|
57
|
+
|
58
|
+
# labels = labels(method, custom_opts, options)
|
59
|
+
|
60
|
+
# @template.content_tag("div", labels + buttons, { class: "flex flex-col gap-3 items-start justify-middle" })
|
61
|
+
# end
|
62
|
+
|
63
|
+
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
|
64
|
+
@template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def text_like_field(field_method, object_method, options = {})
|
70
|
+
custom_opts, opts = partition_custom_opts(options)
|
71
|
+
|
72
|
+
classes = apply_style_classes(TEXT_FIELD_STYLE, custom_opts, object_method)
|
73
|
+
|
74
|
+
field = send(field_method, object_method, {
|
75
|
+
class: classes,
|
76
|
+
title: errors_for(object_method)&.join(" ")
|
77
|
+
}.compact.merge(opts).merge({ tailwindified: true }))
|
78
|
+
|
79
|
+
labels = labels(object_method, custom_opts[:label], options)
|
80
|
+
|
81
|
+
@template.content_tag("div", labels + field, { class: "flex flex-col gap-1" })
|
82
|
+
end
|
83
|
+
|
84
|
+
def labels(object_method, label_options, field_options)
|
85
|
+
label = tailwind_label(object_method, label_options, field_options)
|
86
|
+
error_label = error_label(object_method, field_options)
|
87
|
+
|
88
|
+
@template.content_tag("div", label + error_label, { class: "flex flex-col items-start" })
|
89
|
+
end
|
90
|
+
|
91
|
+
def tailwind_label(object_method, label_options, field_options)
|
92
|
+
text, label_opts = if label_options.present?
|
93
|
+
[ label_options[:text], label_options.except(:text) ]
|
94
|
+
else
|
95
|
+
[ nil, {} ]
|
96
|
+
end
|
97
|
+
|
98
|
+
label_classes = label_opts[:class] || "text-sm font-semibold"
|
99
|
+
label_classes += " font-zinc-500" if field_options[:disabled]
|
100
|
+
label(object_method, text, {
|
101
|
+
class: label_classes
|
102
|
+
}.merge(label_opts.except(:class)))
|
103
|
+
end
|
104
|
+
|
105
|
+
def error_label(object_method, options)
|
106
|
+
if errors_for(object_method).present?
|
107
|
+
error_message = @object.errors[object_method].collect(&:titleize).join(", ")
|
108
|
+
tailwind_label(object_method, { text: error_message, class: " font-bold text-red-500" }, options)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def border_color_classes(object_method)
|
113
|
+
if errors_for(object_method).present?
|
114
|
+
" border-2 border-red-400 focus:border-rose-200"
|
115
|
+
else
|
116
|
+
" border border-gray-300 focus:border-yellow-700"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def apply_style_classes(classes, custom_opts, object_method = nil)
|
121
|
+
classes + border_color_classes(object_method) + " #{custom_opts[:class]}"
|
122
|
+
end
|
123
|
+
|
124
|
+
CUSTOM_OPTS = [ :label, :class ].freeze
|
125
|
+
def partition_custom_opts(opts)
|
126
|
+
opts.partition { |k, v| CUSTOM_OPTS.include?(k) }.map(&:to_h)
|
127
|
+
end
|
128
|
+
|
129
|
+
def errors_for(object_method)
|
130
|
+
return unless @object.present? && object_method.present?
|
131
|
+
|
132
|
+
@object.errors[object_method]
|
133
|
+
end
|
134
|
+
|
135
|
+
def check_box_classes(method, field_classes = nil)
|
136
|
+
classes = <<~CLASSES.strip
|
137
|
+
block rounded size-3.5 focus:ring focus:ring-success checked:bg-success checked:hover:bg-success/90 cursor-pointer focus:ring-opacity-50
|
138
|
+
CLASSES
|
139
|
+
"#{classes} #{field_classes} #{border_color_classes(method)}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RUI::Forms::Text < RUI::Base
|
4
|
+
def initialize(**kwargs)
|
5
|
+
@kwargs = kwargs
|
6
|
+
end
|
7
|
+
|
8
|
+
def view_template(&)
|
9
|
+
render RUI::Forms::FieldGroup.new do
|
10
|
+
render RUI::Forms::Label.new(&) if block_given?
|
11
|
+
input(
|
12
|
+
class: "border border-zinc-300 hover:border-zinc-400 rounded px-2 py-1",
|
13
|
+
**@kwargs
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RUI::Forms::Textarea < RUI::Base
|
4
|
+
def initialize(**kwargs)
|
5
|
+
@kwargs = kwargs
|
6
|
+
end
|
7
|
+
|
8
|
+
def view_template(&)
|
9
|
+
render RUI::Forms::FieldGroup.new do
|
10
|
+
render RUI::Forms::Label.new(&) if block_given?
|
11
|
+
textarea(
|
12
|
+
rows: 5,
|
13
|
+
class: "border border-zinc-300 hover:border-zinc-400 rounded px-2 py-1",
|
14
|
+
**@kwargs
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/rui/forms.rb
ADDED
data/lib/rui/helpers.rb
ADDED
data/lib/rui/icon.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "tabler_icons_ruby"
|
2
4
|
|
3
5
|
class RUI::Icon < RUI::Base
|
@@ -6,6 +8,6 @@ class RUI::Icon < RUI::Base
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def view_template
|
9
|
-
|
11
|
+
div { TablerIconsRuby.render(@icon) }
|
10
12
|
end
|
11
13
|
end
|
data/lib/rui/layout.rb
ADDED
data/lib/rui/links/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RUI::Links::Base < RUI::Base
|
2
4
|
def initialize(href: "#", icon: nil, data: {})
|
3
5
|
@href = href
|
@@ -7,9 +9,9 @@ class RUI::Links::Base < RUI::Base
|
|
7
9
|
|
8
10
|
def view_template
|
9
11
|
a(href: @href, class: classes, data: @data) do
|
10
|
-
div(class: "
|
12
|
+
div(class: "flex flex-row items-center gap-2") do
|
11
13
|
if @icon
|
12
|
-
div(class: "
|
14
|
+
div(class: "size-4 my-1") do
|
13
15
|
render RUI::Icon.new(@icon)
|
14
16
|
end
|
15
17
|
end
|
@@ -24,5 +26,5 @@ class RUI::Links::Base < RUI::Base
|
|
24
26
|
"#{base_classes} #{variant_classes}"
|
25
27
|
end
|
26
28
|
|
27
|
-
def base_classes = "
|
29
|
+
def base_classes = "inline-block px-2 py-1 hover:cursor-pointer rounded transition duration-200 ease-in-out"
|
28
30
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RUI::Links::Destructive < RUI::Links::Base
|
2
4
|
private
|
3
5
|
|
4
|
-
def variant_classes = "
|
6
|
+
def variant_classes = "bg-red-700 hover:bg-red-900 text-white border border-red-700 hover:border-red-900"
|
5
7
|
end
|
data/lib/rui/links/ghost.rb
CHANGED
data/lib/rui/links/outline.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RUI::Links::Outline < RUI::Links::Base
|
2
4
|
private
|
3
5
|
|
4
|
-
def variant_classes = "
|
6
|
+
def variant_classes = "border rounded border-zinc-300 hover:border-zinc-700 text-zinc-700"
|
5
7
|
end
|
data/lib/rui/links/primary.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RUI::Links::Primary < RUI::Links::Base
|
2
4
|
private
|
3
5
|
|
4
|
-
def variant_classes = "
|
6
|
+
def variant_classes = "bg-blue-700 hover:bg-blue-900 text-white border border-blue-700 hover:border-blue-900"
|
5
7
|
end
|
data/lib/rui/links/secondary.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RUI::Links::Secondary < RUI::Links::Base
|
2
4
|
private
|
3
5
|
|
4
|
-
def variant_classes = "
|
6
|
+
def variant_classes = "bg-zinc-700 hover:bg-zinc-900 text-white border border-zinc-700 hover:border-zinc-900"
|
5
7
|
end
|
data/lib/rui/links.rb
ADDED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "redcarpet"
|
2
4
|
|
3
5
|
class RUI::Markdown::Generator
|
@@ -7,7 +9,6 @@ class RUI::Markdown::Generator
|
|
7
9
|
options = {
|
8
10
|
filter_html: true,
|
9
11
|
hard_wrap: true,
|
10
|
-
link_attributes: { rel: "nofollow", target: "_blank" },
|
11
12
|
escape_html: true
|
12
13
|
}
|
13
14
|
|
data/lib/rui/markdown/safe.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rouge"
|
2
4
|
require "rouge/plugins/redcarpet"
|
3
5
|
require "redcarpet"
|
4
6
|
|
5
|
-
class RUI::Markdown::SafeRenderer < Redcarpet::Render::
|
7
|
+
class RUI::Markdown::SafeRenderer < Redcarpet::Render::HTML
|
6
8
|
include Rouge::Plugins::Redcarpet
|
7
9
|
|
8
10
|
private
|
data/lib/rui/markdown/unsafe.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rouge"
|
2
4
|
require "rouge/plugins/redcarpet"
|
3
5
|
require "redcarpet"
|
4
6
|
|
5
|
-
class RUI::Markdown::UnsafeRenderer < Redcarpet::Render::
|
7
|
+
class RUI::Markdown::UnsafeRenderer < Redcarpet::Render::HTML
|
6
8
|
include Rouge::Plugins::Redcarpet
|
7
9
|
|
8
10
|
def block_code(code, lang)
|
@@ -26,6 +28,12 @@ class RUI::Markdown::UnsafeRenderer < Redcarpet::Render::XHTML
|
|
26
28
|
formatter.format(lexer.lex(unescaped))
|
27
29
|
end
|
28
30
|
|
31
|
+
def codespan(code)
|
32
|
+
unescaped = CGI.unescapeHTML(code)
|
33
|
+
|
34
|
+
"<code>#{unescaped}</code>"
|
35
|
+
end
|
36
|
+
|
29
37
|
private
|
30
38
|
|
31
39
|
def rouge_formatter(lexer)
|
data/lib/rui/markdown.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RUI::Navigation::Sidebar < RUI::Base
|
4
|
+
def view_template
|
5
|
+
div(class: "lg:w-72 p-10 pb-36 hidden lg:flex flex-col bg-white z-50 lg:z-auto fixed w-screen md:w-auto h-screen lg:max-h-full overflow-y-auto", data: { "navigation-target": "sidebar" }) do
|
6
|
+
yield
|
7
|
+
end
|
8
|
+
button(class: "lg:hidden hidden bg-black/75 fixed w-screen h-screen", data: { navigation_target: "curtain", action: "navigation#toggle" })
|
9
|
+
end
|
10
|
+
|
11
|
+
def section_heading
|
12
|
+
p(class: "pt-8 pb-4 mt-6 text-base md:text-sm font-semibold uppercase text-zinc-400") do
|
13
|
+
yield
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def icon_link(icon:, href:, selected: false)
|
18
|
+
if selected
|
19
|
+
state_classes = "border-blue-700 text-zinc-700 **:[svg]:stroke-blue-700 font-semibold"
|
20
|
+
else
|
21
|
+
state_classes = "border-transparent text-zinc-500 hover:border-zinc-200 hover:text-zinc-700 **:[svg]:stroke-zinc-400 hover:**:[svg]:stroke-zinc-700"
|
22
|
+
end
|
23
|
+
|
24
|
+
a(href:, class: "inline-flex items-center gap-2 py-1 #{state_classes}") do
|
25
|
+
div(class: "size-5 md:size-4") do
|
26
|
+
render RUI::Icon.new(icon)
|
27
|
+
end
|
28
|
+
span(class: "text-lg md:text-base") { yield }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def text_link(href:, selected: false)
|
33
|
+
if selected
|
34
|
+
state_classes = "border-blue-700 text-zinc-700 font-semibold"
|
35
|
+
else
|
36
|
+
state_classes = "border-transparent text-zinc-400 hover:border-zinc-200 hover:text-zinc-700"
|
37
|
+
end
|
38
|
+
|
39
|
+
a(href:, class: "text-zinc-400 px-5 py-1 border-l-3 #{state_classes}") do
|
40
|
+
span(class: "text-lg md:text-base") { yield }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RUI::Navigation::Top < RUI::Base
|
4
|
+
def view_template(&)
|
5
|
+
div(class: "fixed top-0 left-0 right-0 bg-white flex flex-col z-50") do
|
6
|
+
section(class: "flex flex-row items-center justify-between gap-3 border-b border-zinc-300 p-3 lg:px-10", &)
|
7
|
+
section(class: "lg:hidden p-3 border-b border-zinc-300") do
|
8
|
+
render RUI::Buttons::Ghost.new(
|
9
|
+
icon: "menu",
|
10
|
+
data: { action: "navigation#toggle" }
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def group(&)
|
17
|
+
section(class: "flex flex-row items-center gap-3", &)
|
18
|
+
end
|
19
|
+
end
|
data/lib/rui/navigation.rb
CHANGED
@@ -1,51 +1,3 @@
|
|
1
|
-
|
2
|
-
register_value_helper :request
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
div(class: "rui:flex rui:flex-col rui:sticky rui:top-0 rui:max-h-screen rui:overflow-y-auto rui:mx-10 rui:py-10") do
|
6
|
-
yield
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def section_heading
|
11
|
-
p(class: "rui:pt-8 rui:pb-4 rui:mt-6 rui:text-sm rui:font-semibold rui:uppercase rui:text-zinc-400 rui:border-t rui:border-zinc-200") do
|
12
|
-
yield
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def icon_link(href:, icon:)
|
17
|
-
if request.path == href
|
18
|
-
state_classes = "rui:border-blue-700 rui:text-zinc-700 rui:**:[svg]:stroke-blue-700"
|
19
|
-
else
|
20
|
-
state_classes = "rui:border-transparent rui:text-zinc-400 rui:hover:border-zinc-200 rui:hover:text-zinc-700 rui:**:[svg]:stroke-zinc-300 rui:hover:**:[svg]:stroke-zinc-700"
|
21
|
-
end
|
22
|
-
|
23
|
-
a(href:, class: "rui:inline-flex rui:items-center rui:gap-2 rui:py-1 #{state_classes}") do
|
24
|
-
div(class: "rui:size-4") do
|
25
|
-
render RUI::Icon.new(icon)
|
26
|
-
end
|
27
|
-
span { yield }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def text_link(href)
|
32
|
-
if request.path == href
|
33
|
-
state_classes = "rui:border-blue-700 rui:text-zinc-700"
|
34
|
-
else
|
35
|
-
state_classes = "rui:border-transparent rui:text-zinc-400 rui:hover:border-zinc-200 rui:hover:text-zinc-700"
|
36
|
-
end
|
37
|
-
|
38
|
-
a(href:, class: "rui:text-zinc-400 rui:px-5 rui:py-1 rui:border-l-3 #{state_classes}") do
|
39
|
-
span { yield }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def coming_soon
|
44
|
-
div(class: "rui:flex rui:flex-row rui:items-center") do
|
45
|
-
span(class: "rui:text-zinc-400 rui:px-5 rui:py-1 rui:border-l-3 rui:border-transparent") do
|
46
|
-
yield
|
47
|
-
end
|
48
|
-
render RUI::Badges::Gray.new { "Coming Soon" }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
3
|
+
module RUI::Navigation; end
|
data/lib/rui/slideout.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RUI::Slideout < RUI::Base
|
2
4
|
include Phlex::Rails::Helpers::TurboFrameTag
|
3
5
|
|
4
|
-
def view_template
|
6
|
+
def view_template(&)
|
5
7
|
turbo_frame_tag "slideout" do
|
6
|
-
div(class: "
|
7
|
-
a(href: "#", class: "
|
8
|
-
div(id: "modal-curtain", class: "
|
8
|
+
div(class: "absolute inset-0 z-50", data: { controller: "slideout" }) do
|
9
|
+
a(href: "#", class: "cursor-default", data: { action: "slideout#hide" }) do
|
10
|
+
div(id: "modal-curtain", class: "w-screen h-screen bg-black transition-opacity opacity-75", data: { slideout_target: "curtain" })
|
9
11
|
end
|
10
|
-
div(class: "
|
11
|
-
div(class: "
|
12
|
-
div(class: "
|
13
|
-
yield
|
14
|
-
end
|
12
|
+
div(class: "right-0 fixed inset-y-0 flex max-w-1/2 pointer-events-none") do
|
13
|
+
div(class: "w-screen pointer-events-auto", data: { slideout_target: "slideout" }) do
|
14
|
+
div(class: "w-full h-full bg-white shadow", &)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/rui/table.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
class RUI::Table < RUI::Base
|
2
|
+
def initialize(rows)
|
3
|
+
@rows = rows
|
4
|
+
@columns = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def view_template(&)
|
8
|
+
vanish(&)
|
9
|
+
|
10
|
+
table(class: "bg-white w-full table-auto border-collapse rounded") do
|
11
|
+
thead(class: "bg-blue-50") do
|
12
|
+
@columns.each do |column|
|
13
|
+
th(class: classes(column[:attrs][:class])) do
|
14
|
+
column[:header]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
tbody do
|
20
|
+
@rows.each do |row|
|
21
|
+
tr(class: "odd:bg-white even:bg-zinc-100 hover:bg-zinc-200") do
|
22
|
+
@columns.each do |column|
|
23
|
+
td(class: classes(column[:attrs][:class])) do
|
24
|
+
column[:content].call(row)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def column(header = "", **attrs, &content)
|
34
|
+
@columns << { header:, attrs:, content: }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def base_classes = "border border-zinc-300 py-1 px-2 text-left"
|
40
|
+
|
41
|
+
def classes(custom_classes)
|
42
|
+
RUI::TailwindMerger.instance.merge(base_classes, custom_classes)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal
|
2
|
+
|
3
|
+
require "tailwind_merge"
|
4
|
+
|
5
|
+
class RUI::TailwindMerger
|
6
|
+
include Singleton
|
7
|
+
include TailwindMerge
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@merger = TailwindMerge::Merger.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def merge(base_classes, given_classes)
|
14
|
+
return base_classes if given_classes.nil?
|
15
|
+
@merger.merge([ base_classes, given_classes ])
|
16
|
+
end
|
17
|
+
end
|
data/lib/rui/text.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RUI::Text
|
2
4
|
class Large < RUI::Base
|
3
5
|
def view_template
|
4
|
-
p(class: "
|
6
|
+
p(class: "text-lg text-zinc-700 mb-4", **@attrs) { yield }
|
5
7
|
end
|
6
8
|
end
|
7
9
|
|
8
10
|
class Medium < RUI::Base
|
9
11
|
def view_template
|
10
|
-
p(class: "
|
12
|
+
p(class: "text-base text-zinc-700 mb-4", **@attrs) { yield }
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
16
|
class Small < RUI::Base
|
15
17
|
def view_template
|
16
|
-
p(class: "
|
18
|
+
p(class: "text-sm text-zinc-700 mb-4", **@attrs) { yield }
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|