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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -13
  3. data/lib/relay_ui/engine.rb +14 -10
  4. data/lib/relay_ui/version.rb +1 -1
  5. data/lib/rui/badges/base.rb +5 -1
  6. data/lib/rui/badges/blue.rb +3 -1
  7. data/lib/rui/badges/gray.rb +3 -1
  8. data/lib/rui/badges/green.rb +3 -1
  9. data/lib/rui/badges/purple.rb +3 -1
  10. data/lib/rui/badges/red.rb +3 -1
  11. data/lib/rui/badges/yellow.rb +3 -1
  12. data/lib/rui/badges.rb +3 -0
  13. data/lib/rui/base.rb +3 -8
  14. data/lib/rui/buttons/base.rb +12 -9
  15. data/lib/rui/buttons/destructive.rb +3 -1
  16. data/lib/rui/buttons/ghost.rb +3 -1
  17. data/lib/rui/buttons/outline.rb +3 -1
  18. data/lib/rui/buttons/primary.rb +6 -1
  19. data/lib/rui/buttons/secondary.rb +3 -1
  20. data/lib/rui/buttons.rb +3 -0
  21. data/lib/rui/card.rb +92 -0
  22. data/lib/rui/flash.rb +51 -0
  23. data/lib/rui/forms/checkbox.rb +25 -0
  24. data/lib/rui/forms/email.rb +19 -0
  25. data/lib/rui/forms/field_group.rb +5 -0
  26. data/lib/rui/forms/helpers.rb +19 -0
  27. data/lib/rui/forms/label.rb +7 -0
  28. data/lib/rui/forms/password.rb +18 -0
  29. data/lib/rui/forms/phone.rb +18 -0
  30. data/lib/rui/forms/radio.rb +22 -0
  31. data/lib/rui/forms/select.rb +24 -0
  32. data/lib/rui/forms/tailwind_form_builder.rb +142 -0
  33. data/lib/rui/forms/text.rb +17 -0
  34. data/lib/rui/forms/textarea.rb +18 -0
  35. data/lib/rui/forms.rb +3 -0
  36. data/lib/rui/helpers.rb +3 -0
  37. data/lib/rui/icon.rb +3 -1
  38. data/lib/rui/layout/body.rb +7 -0
  39. data/lib/rui/layout/main.rb +5 -0
  40. data/lib/rui/layout/page.rb +5 -0
  41. data/lib/rui/layout.rb +3 -0
  42. data/lib/rui/links/base.rb +5 -3
  43. data/lib/rui/links/destructive.rb +3 -1
  44. data/lib/rui/links/ghost.rb +3 -1
  45. data/lib/rui/links/outline.rb +3 -1
  46. data/lib/rui/links/primary.rb +3 -1
  47. data/lib/rui/links/secondary.rb +3 -1
  48. data/lib/rui/links.rb +3 -0
  49. data/lib/rui/markdown/generator.rb +2 -1
  50. data/lib/rui/markdown/safe.rb +3 -1
  51. data/lib/rui/markdown/safe_renderer.rb +3 -1
  52. data/lib/rui/markdown/unsafe.rb +3 -1
  53. data/lib/rui/markdown/unsafe_renderer.rb +9 -1
  54. data/lib/rui/markdown.rb +3 -0
  55. data/lib/rui/navigation/menu_button.rb +7 -0
  56. data/lib/rui/navigation/sidebar.rb +43 -0
  57. data/lib/rui/navigation/top.rb +19 -0
  58. data/lib/rui/navigation.rb +2 -50
  59. data/lib/rui/slideout.rb +9 -9
  60. data/lib/rui/table.rb +44 -0
  61. data/lib/rui/tailwind_merger.rb +17 -0
  62. data/lib/rui/text.rb +5 -3
  63. metadata +87 -3
  64. 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
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Forms; end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Helpers; end
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
- raw TablerIconsRuby.render(@icon)
11
+ div { TablerIconsRuby.render(@icon) }
10
12
  end
11
13
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Layout::Body < RUI::Base
4
+ def view_template(&)
5
+ body(class: "flex flex-col", data: { controller: "navigation" }, &)
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class RUI::Layout::Main < RUI::Base
2
+ def view_template(&)
3
+ main(class: "p-5 lg:p-10 lg:ml-72 w-full max-w-[800px]", &)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RUI::Layout::Page < RUI::Base
2
+ def view_template(&)
3
+ div(class: "flex flex-row mt-25.5 lg:mt-14", &)
4
+ end
5
+ end
data/lib/rui/layout.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Layout; end
@@ -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: "rui:flex rui:flex-row rui:items-center rui:gap-2") do
12
+ div(class: "flex flex-row items-center gap-2") do
11
13
  if @icon
12
- div(class: "rui:size-4 rui:my-1") do
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 = "rui:inline-block rui:px-3 rui:py-1 rui:hover:cursor-pointer rui:rounded rui:transition rui:duration-200 rui:ease-in-out"
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 = "rui:bg-red-700 rui:hover:bg-red-900 rui:text-white"
6
+ def variant_classes = "bg-red-700 hover:bg-red-900 text-white border border-red-700 hover:border-red-900"
5
7
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Links::Ghost < RUI::Links::Base
2
4
  private
3
5
 
4
- def variant_classes = "rui:hover:bg-zinc-100"
6
+ def variant_classes = "text-blue-700 hover:text-blue-900 hover:bg-zinc-100"
5
7
  end
@@ -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 = "rui:border rui:rounded rui:border-zinc-700 rui:hover:border-zinc-900 rui:text-zinc-700 rui:hover:text-zinc-900 rui:hover:bg-zinc-100"
6
+ def variant_classes = "border rounded border-zinc-300 hover:border-zinc-700 text-zinc-700"
5
7
  end
@@ -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 = "rui:bg-blue-700 rui:hover:bg-blue-900 rui:text-white"
6
+ def variant_classes = "bg-blue-700 hover:bg-blue-900 text-white border border-blue-700 hover:border-blue-900"
5
7
  end
@@ -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 = "rui:bg-zinc-700 rui:hover:bg-zinc-900 rui:text-white"
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
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Links; end
@@ -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
 
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Markdown::Safe < RUI::Base
2
4
  def view_template(&block)
3
- article(class: "rui:markdown") do
5
+ article(class: "prose") do
4
6
  RUI::Markdown::Generator.instance.get_safe(capture(&block))
5
7
  end
6
8
  end
@@ -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::XHTML
7
+ class RUI::Markdown::SafeRenderer < Redcarpet::Render::HTML
6
8
  include Rouge::Plugins::Redcarpet
7
9
 
8
10
  private
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class RUI::Markdown::Unsafe < RUI::Base
2
4
  def view_template(&block)
3
- article(class: "rui:markdown") do
5
+ article(class: "prose") do
4
6
  RUI::Markdown::Generator.instance.get_unsafe(capture(&block))
5
7
  end
6
8
  end
@@ -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::XHTML
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)
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Markdown; end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Navigation::MenuButton < RUI::Base
4
+ def view_template
5
+ render RUI::Buttons::Outline.new(icon: "menu", data: { action: "navigation#toggle", class: "lg:hidden" })
6
+ end
7
+ end
@@ -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
@@ -1,51 +1,3 @@
1
- class RUI::Navigation < RUI::Base
2
- register_value_helper :request
1
+ # frozen_string_literal: true
3
2
 
4
- def view_template
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: "rui:absolute rui:inset-0 rui:z-50", data: { controller: "slideout" }) do
7
- a(href: "#", class: "rui:cursor-default", data: { action: "slideout#hide" }) do
8
- div(id: "modal-curtain", class: "rui:w-screen rui:h-screen rui:bg-black rui:transition-opacity rui:opacity-75", data: { slideout_target: "curtain" })
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: "rui:right-0 rui:fixed rui:inset-y-0 rui:flex rui:max-w-1/2 rui:pointer-events-none") do
11
- div(class: "rui:w-screen rui:pointer-events-auto", data: { slideout_target: "slideout" }) do
12
- div(class: "rui:w-full rui:h-full rui:bg-white rui:shadow") do
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: "rui:text-lg rui:text-zinc-700 rui:mb-4") { yield }
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: "rui:text-base rui:text-zinc-700 rui:mb-4") { yield }
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: "rui:text-sm rui:text-zinc-700 rui:mb-4") { yield }
18
+ p(class: "text-sm text-zinc-700 mb-4", **@attrs) { yield }
17
19
  end
18
20
  end
19
21
  end