relay_ui 0.1.1 → 0.3.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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +100 -0
  4. data/lib/relay_ui/engine.rb +11 -14
  5. data/lib/relay_ui/version.rb +2 -2
  6. data/lib/relay_ui.rb +1 -1
  7. data/lib/rui/badges/base.rb +9 -0
  8. data/lib/rui/badges/blue.rb +7 -0
  9. data/lib/rui/badges/gray.rb +7 -0
  10. data/lib/rui/badges/green.rb +7 -0
  11. data/lib/rui/badges/purple.rb +7 -0
  12. data/lib/rui/badges/red.rb +7 -0
  13. data/lib/rui/badges/yellow.rb +7 -0
  14. data/lib/rui/badges.rb +3 -0
  15. data/lib/rui/base.rb +8 -0
  16. data/lib/rui/buttons/base.rb +29 -0
  17. data/lib/rui/buttons/destructive.rb +7 -0
  18. data/lib/rui/buttons/ghost.rb +7 -0
  19. data/lib/rui/buttons/outline.rb +7 -0
  20. data/lib/rui/buttons/primary.rb +7 -0
  21. data/lib/rui/buttons/secondary.rb +7 -0
  22. data/lib/rui/buttons.rb +3 -0
  23. data/lib/rui/card.rb +92 -0
  24. data/lib/rui/flash.rb +51 -0
  25. data/lib/rui/forms/checkbox.rb +25 -0
  26. data/lib/rui/forms/email.rb +19 -0
  27. data/lib/rui/forms/field_group.rb +5 -0
  28. data/lib/rui/forms/label.rb +7 -0
  29. data/lib/rui/forms/password.rb +18 -0
  30. data/lib/rui/forms/phone.rb +18 -0
  31. data/lib/rui/forms/radio.rb +22 -0
  32. data/lib/rui/forms/select.rb +24 -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 +13 -0
  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 +30 -0
  43. data/lib/rui/links/destructive.rb +7 -0
  44. data/lib/rui/links/ghost.rb +7 -0
  45. data/lib/rui/links/outline.rb +7 -0
  46. data/lib/rui/links/primary.rb +7 -0
  47. data/lib/rui/links/secondary.rb +7 -0
  48. data/lib/rui/links.rb +3 -0
  49. data/lib/rui/markdown/generator.rb +36 -0
  50. data/lib/rui/markdown/safe.rb +9 -0
  51. data/lib/rui/markdown/safe_renderer.rb +15 -0
  52. data/lib/rui/markdown/unsafe.rb +9 -0
  53. data/lib/rui/markdown/unsafe_renderer.rb +42 -0
  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 +3 -0
  59. data/{app/components → lib/rui}/slideout.rb +9 -9
  60. data/lib/rui/table.rb +54 -0
  61. data/lib/rui/text.rb +21 -0
  62. metadata +147 -37
  63. data/Rakefile +0 -64
  64. data/app/assets/javascripts/relay_ui/index.js +0 -5
  65. data/app/assets/stylesheets/relay_ui/application.css +0 -1
  66. data/app/components/badges/base.rb +0 -5
  67. data/app/components/badges/blue.rb +0 -5
  68. data/app/components/badges/gray.rb +0 -5
  69. data/app/components/badges/green.rb +0 -5
  70. data/app/components/badges/purple.rb +0 -5
  71. data/app/components/badges/red.rb +0 -5
  72. data/app/components/badges/yellow.rb +0 -5
  73. data/app/components/base.rb +0 -15
  74. data/app/components/buttons/base.rb +0 -30
  75. data/app/components/buttons/destructive.rb +0 -5
  76. data/app/components/buttons/ghost.rb +0 -5
  77. data/app/components/buttons/link.rb +0 -9
  78. data/app/components/buttons/outline.rb +0 -5
  79. data/app/components/buttons/primary.rb +0 -5
  80. data/app/components/buttons/secondary.rb +0 -5
  81. data/app/components/code_block.rb +0 -13
  82. data/app/components/headings.rb +0 -37
  83. data/app/components/icon.rb +0 -9
  84. data/app/components/lists/base.rb +0 -13
  85. data/app/components/lists/ordered.rb +0 -5
  86. data/app/components/lists/unordered.rb +0 -5
  87. data/app/components/navigation.rb +0 -49
  88. data/app/components/text.rb +0 -19
  89. data/package.json +0 -16
  90. data/tailwind.config.js +0 -10
  91. data/vendor/assets/javascripts/relay_ui/dist/relay_ui.js +0 -2471
  92. data/vendor/assets/stylesheets/relay_ui/relay_ui.css +0 -2528
@@ -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 ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tabler_icons_ruby"
4
+
5
+ class RUI::Icon < RUI::Base
6
+ def initialize(icon)
7
+ @icon = icon
8
+ end
9
+
10
+ def view_template
11
+ div { TablerIconsRuby.render(@icon) }
12
+ end
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 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
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Links::Base < RUI::Base
4
+ def initialize(href: "#", icon: nil, data: {})
5
+ @href = href
6
+ @icon = icon
7
+ @data = data
8
+ end
9
+
10
+ def view_template
11
+ a(href: @href, class: classes, data: @data) do
12
+ div(class: "flex flex-row items-center gap-2") do
13
+ if @icon
14
+ div(class: "size-4 my-1") do
15
+ render RUI::Icon.new(@icon)
16
+ end
17
+ end
18
+ span { yield } if block_given?
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def classes
26
+ "#{base_classes} #{variant_classes}"
27
+ end
28
+
29
+ def base_classes = "inline-block px-2 py-1 hover:cursor-pointer rounded transition duration-200 ease-in-out"
30
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Links::Destructive < RUI::Links::Base
4
+ private
5
+
6
+ def variant_classes = "bg-red-700 hover:bg-red-900 text-white border border-red-700 hover:border-red-900"
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Links::Ghost < RUI::Links::Base
4
+ private
5
+
6
+ def variant_classes = "text-blue-700 hover:text-blue-900 hover:bg-zinc-100"
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Links::Outline < RUI::Links::Base
4
+ private
5
+
6
+ def variant_classes = "border rounded border-zinc-300 hover:border-zinc-700 text-zinc-700"
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Links::Primary < RUI::Links::Base
4
+ private
5
+
6
+ def variant_classes = "bg-blue-700 hover:bg-blue-900 text-white border border-blue-700 hover:border-blue-900"
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Links::Secondary < RUI::Links::Base
4
+ private
5
+
6
+ def variant_classes = "bg-zinc-700 hover:bg-zinc-900 text-white border border-zinc-700 hover:border-zinc-900"
7
+ end
data/lib/rui/links.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Links; end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "redcarpet"
4
+
5
+ class RUI::Markdown::Generator
6
+ include Singleton
7
+
8
+ def initialize
9
+ options = {
10
+ filter_html: true,
11
+ hard_wrap: true,
12
+ escape_html: true
13
+ }
14
+
15
+ unsafe_renderer = RUI::Markdown::UnsafeRenderer.new options
16
+ safe_renderer = RUI::Markdown::SafeRenderer.new options
17
+
18
+ extensions = {
19
+ autolink: true,
20
+ tables: true,
21
+ fenced_code_blocks: true,
22
+ lax_spacing: true,
23
+ no_intra_emphasis: true,
24
+ strikethrough: true,
25
+ superscript: true,
26
+ disable_indented_code_blocks: true
27
+ }
28
+
29
+ @unsafe_generator = Redcarpet::Markdown.new unsafe_renderer, extensions
30
+ @safe_generator = Redcarpet::Markdown.new safe_renderer, extensions
31
+ end
32
+
33
+ def get_unsafe(markdown) = @unsafe_generator.render(markdown).html_safe
34
+
35
+ def get_safe(markdown) = @safe_generator.render(markdown).html_safe
36
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Markdown::Safe < RUI::Base
4
+ def view_template(&block)
5
+ article(class: "prose") do
6
+ RUI::Markdown::Generator.instance.get_safe(capture(&block))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rouge"
4
+ require "rouge/plugins/redcarpet"
5
+ require "redcarpet"
6
+
7
+ class RUI::Markdown::SafeRenderer < Redcarpet::Render::HTML
8
+ include Rouge::Plugins::Redcarpet
9
+
10
+ private
11
+
12
+ def rouge_formatter(lexer)
13
+ Rouge::Formatters::HTMLLegacy.new(inline_theme: "github.dark")
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Markdown::Unsafe < RUI::Base
4
+ def view_template(&block)
5
+ article(class: "prose") do
6
+ RUI::Markdown::Generator.instance.get_unsafe(capture(&block))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rouge"
4
+ require "rouge/plugins/redcarpet"
5
+ require "redcarpet"
6
+
7
+ class RUI::Markdown::UnsafeRenderer < Redcarpet::Render::HTML
8
+ include Rouge::Plugins::Redcarpet
9
+
10
+ def block_code(code, lang)
11
+ lexer =
12
+ begin
13
+ Rouge::Lexer.find_fancy(lang, code)
14
+ rescue Rouge::Guesser::Ambiguous => e
15
+ e.alternatives.first
16
+ end
17
+ lexer ||= Rouge::Lexers::PlainText
18
+
19
+ if lexer.tag == "make"
20
+ code.gsub! %r{^ }, "\t"
21
+ end
22
+
23
+ formatter = rouge_formatter(lexer)
24
+
25
+ # This is a hack to unescape HTML entities in code blocks
26
+ unescaped = CGI.unescapeHTML(code)
27
+
28
+ formatter.format(lexer.lex(unescaped))
29
+ end
30
+
31
+ def codespan(code)
32
+ unescaped = CGI.unescapeHTML(code)
33
+
34
+ "<code>#{unescaped}</code>"
35
+ end
36
+
37
+ private
38
+
39
+ def rouge_formatter(lexer)
40
+ Rouge::Formatters::HTMLLegacy.new(inline_theme: "github.dark")
41
+ end
42
+ end
@@ -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: "p-10 pb-36 hidden lg:flex flex-col bg-white z-50 lg:z-auto fixed lg:relative w-screen md:w-auto h-screen lg:h-auto overflow-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
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Navigation; end
@@ -1,20 +1,20 @@
1
- class RelayUi::Slideout < RelayUi::Base
1
+ # frozen_string_literal: true
2
+
3
+ class RUI::Slideout < RUI::Base
2
4
  include Phlex::Rails::Helpers::TurboFrameTag
3
-
4
- def view_template
5
+
6
+ def view_template(&)
5
7
  turbo_frame_tag "slideout" do
6
- div(class: "absolute inset-0 z-50", data: {controller: "slideout"}) do
8
+ div(class: "absolute inset-0 z-50", data: { controller: "slideout" }) do
7
9
  a(href: "#", class: "cursor-default", data: { action: "slideout#hide" }) do
8
- div(id: "modal-curtain", class: "w-screen h-screen bg-black transition-opacity opacity-75")
10
+ div(id: "modal-curtain", class: "w-screen h-screen bg-black transition-opacity opacity-75", data: { slideout_target: "curtain" })
9
11
  end
10
12
  div(class: "right-0 fixed inset-y-0 flex max-w-1/2 pointer-events-none") do
11
13
  div(class: "w-screen pointer-events-auto", data: { slideout_target: "slideout" }) do
12
- div(class: "w-full h-full bg-white shadow") do
13
- yield
14
- end
14
+ div(class: "w-full h-full bg-white shadow", &)
15
15
  end
16
16
  end
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
data/lib/rui/table.rb ADDED
@@ -0,0 +1,54 @@
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") do
11
+ thead(class: "bg-blue-50") do
12
+ @columns.each do |column|
13
+ th(class: "border border-zinc-300 py-2 px-2 #{align(column[:align])}") do
14
+ column[:header]
15
+ end
16
+ end
17
+ th(class: "border border-zinc-300 px-2 text-center") { "" }
18
+ end
19
+
20
+ tbody do
21
+ @rows.each do |row|
22
+ tr(class: "hover:bg-zinc-50") do
23
+ @columns.each do |column|
24
+ td(class: "border border-zinc-300 py-1 px-2 #{align(column[:align])}") do
25
+ column[:content].call(row)
26
+ end
27
+ end
28
+ td(class: "border border-zinc-300 py-1 px-2 text-center") do
29
+ div(class: "flex flex-row justify-center gap-3") do
30
+ render RUI::Buttons::Ghost.new(icon: "edit")
31
+ render RUI::Buttons::Ghost.new(icon: "archive")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def column(header, align = :left, &content)
41
+ @columns << { header:, align:, content: }
42
+ end
43
+
44
+ def align(align)
45
+ case align
46
+ when :right
47
+ "text-right"
48
+ when :center
49
+ "text-center"
50
+ else
51
+ "text-left"
52
+ end
53
+ end
54
+ end
data/lib/rui/text.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RUI::Text
4
+ class Large < RUI::Base
5
+ def view_template
6
+ p(class: "text-lg text-zinc-700 mb-4", **@attrs) { yield }
7
+ end
8
+ end
9
+
10
+ class Medium < RUI::Base
11
+ def view_template
12
+ p(class: "text-base text-zinc-700 mb-4", **@attrs) { yield }
13
+ end
14
+ end
15
+
16
+ class Small < RUI::Base
17
+ def view_template
18
+ p(class: "text-sm text-zinc-700 mb-4", **@attrs) { yield }
19
+ end
20
+ end
21
+ end