uchi 0.1.5 → 0.1.6
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/javascripts/uchi/application.js +2655 -24
- data/app/assets/javascripts/uchi.js +11 -0
- data/app/assets/stylesheets/uchi/application.css +982 -1311
- data/app/assets/tailwind/uchi.css +4 -4
- data/app/components/uchi/field/belongs_to/edit.html.erb +1 -1
- data/app/components/uchi/field/belongs_to/index.html.erb +1 -1
- data/app/components/uchi/field/belongs_to/show.html.erb +3 -5
- data/app/components/uchi/field/belongs_to.rb +30 -7
- data/app/components/uchi/field/boolean/edit.html.erb +1 -1
- data/app/components/uchi/field/date/edit.html.erb +1 -1
- data/app/components/uchi/field/date_time/edit.html.erb +1 -1
- data/app/components/uchi/field/file/edit.html.erb +1 -1
- data/app/components/uchi/field/file/index.html.erb +2 -1
- data/app/components/uchi/field/file/show.html.erb +3 -2
- data/app/components/uchi/field/has_and_belongs_to_many/show.html.erb +5 -3
- data/app/components/uchi/field/has_many/show.html.erb +5 -3
- data/app/components/uchi/field/id/index.html.erb +1 -1
- data/app/components/uchi/field/id/show.html.erb +1 -1
- data/app/components/uchi/field/image/edit.html.erb +1 -1
- data/app/components/uchi/field/image/index.html.erb +2 -1
- data/app/components/uchi/field/image/show.html.erb +2 -1
- data/app/components/uchi/field/number/edit.html.erb +1 -1
- data/app/components/uchi/field/string/edit.html.erb +1 -1
- data/app/components/uchi/field/text/edit.html.erb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb.rb +5 -5
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_home.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_item/current.rb +3 -3
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_item/first.rb +4 -4
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_item.rb +4 -4
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_separator.rb +7 -5
- data/app/components/uchi/flowbite/button/outline.rb +37 -0
- data/app/components/uchi/flowbite/button/pill.rb +40 -0
- data/app/components/uchi/flowbite/button.rb +93 -0
- data/app/components/uchi/flowbite/card/card.html.erb +7 -0
- data/app/components/uchi/flowbite/card/title.rb +37 -0
- data/app/components/uchi/flowbite/card.rb +84 -0
- data/app/components/{flowbite → uchi/flowbite}/input/checkbox.rb +7 -7
- data/app/components/{flowbite → uchi/flowbite}/input/date.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/date_time.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/email.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/field.rb +11 -10
- data/app/components/uchi/flowbite/input/file.rb +30 -0
- data/app/components/{flowbite → uchi/flowbite}/input/hint.rb +6 -5
- data/app/components/{flowbite → uchi/flowbite}/input/label.rb +8 -7
- data/app/components/{flowbite → uchi/flowbite}/input/number.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/password.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/phone.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/radio_button.rb +7 -7
- data/app/components/{flowbite → uchi/flowbite}/input/select.rb +16 -7
- data/app/components/uchi/flowbite/input/textarea.rb +42 -0
- data/app/components/{flowbite → uchi/flowbite}/input/url.rb +1 -1
- data/app/components/uchi/flowbite/input/validation_error.rb +39 -0
- data/app/components/uchi/flowbite/input_field/checkbox.html.erb +9 -0
- data/app/components/{flowbite → uchi/flowbite}/input_field/checkbox.rb +10 -6
- data/app/components/{flowbite → uchi/flowbite}/input_field/date.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/date_time.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/email.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/file.rb +2 -2
- data/app/components/uchi/flowbite/input_field/input_field.html.erb +9 -0
- data/app/components/{flowbite → uchi/flowbite}/input_field/number.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/password.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/phone.rb +2 -2
- data/app/components/uchi/flowbite/input_field/radio_button.html.erb +9 -0
- data/app/components/{flowbite → uchi/flowbite}/input_field/radio_button.rb +13 -9
- data/app/components/{flowbite → uchi/flowbite}/input_field/select.rb +7 -3
- data/app/components/{flowbite → uchi/flowbite}/input_field/text.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input_field/textarea.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/url.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field.rb +19 -5
- data/app/components/uchi/flowbite/link.rb +41 -0
- data/app/components/{flowbite → uchi/flowbite}/style.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/toast/icon.rb +1 -1
- data/app/components/uchi/flowbite/toast/toast.html.erb +40 -0
- data/app/components/{flowbite → uchi/flowbite}/toast.rb +2 -2
- data/app/components/uchi/ui/actions/dropdown/dropdown.html.erb +59 -0
- data/app/components/uchi/ui/actions/dropdown.rb +32 -0
- data/app/components/uchi/ui/breadcrumb/breadcrumb.html.erb +4 -4
- data/app/components/uchi/ui/form/input/collection_checkboxes.html.erb +2 -1
- data/app/components/uchi/ui/form/input/collection_checkboxes.rb +12 -17
- data/app/components/uchi/ui/frame/frame.html.erb +6 -1
- data/app/components/uchi/ui/index/records_table/records_table.html.erb +109 -18
- data/app/components/uchi/ui/index/records_table/search_form/search_form.html.erb +21 -5
- data/app/components/uchi/ui/navigation/navigation.html.erb +9 -0
- data/app/components/uchi/ui/navigation.rb +37 -0
- data/app/components/uchi/ui/no_value/no_value.html.erb +1 -0
- data/app/components/uchi/ui/no_value.rb +8 -0
- data/app/components/uchi/ui/page_header/page_header.html.erb +7 -2
- data/app/components/uchi/ui/pagination/current_link.html.erb +1 -1
- data/app/components/uchi/ui/pagination/gap.html.erb +7 -1
- data/app/components/uchi/ui/pagination/link.html.erb +1 -1
- data/app/components/uchi/ui/pagination/next_link.html.erb +18 -3
- data/app/components/uchi/ui/pagination/pagination.html.erb +3 -1
- data/app/components/uchi/ui/pagination/previous_link.html.erb +18 -3
- data/app/components/uchi/ui/pagination.rb +1 -1
- data/app/components/uchi/ui/show/attribute_fields/attribute_fields.html.erb +4 -3
- data/app/components/uchi/ui/spinner/spinner.html.erb +17 -3
- data/app/controllers/uchi/actions/executions_controller.rb +107 -0
- data/app/controllers/uchi/repository_controller.rb +21 -1
- data/app/views/layouts/uchi/_flash_messages.html.erb +1 -1
- data/app/views/layouts/uchi/application.html.erb +10 -16
- data/app/views/uchi/navigation/_main.html.erb +9 -0
- data/app/views/uchi/repository/edit.html.erb +2 -2
- data/app/views/uchi/repository/index.html.erb +12 -3
- data/app/views/uchi/repository/new.html.erb +2 -2
- data/app/views/uchi/repository/show.html.erb +13 -2
- data/lib/generators/uchi/controller/templates/controller.rb.tt +0 -5
- data/lib/generators/uchi/scaffold/scaffold_generator.rb +15 -0
- data/lib/uchi/action.rb +84 -0
- data/lib/uchi/action_response.rb +108 -0
- data/lib/uchi/repository/translate.rb +14 -0
- data/lib/uchi/repository.rb +25 -0
- data/lib/uchi/version.rb +1 -1
- data/lib/uchi.rb +2 -0
- metadata +63 -50
- data/app/components/flowbite/button/outline.rb +0 -22
- data/app/components/flowbite/button/pill.rb +0 -40
- data/app/components/flowbite/button.rb +0 -92
- data/app/components/flowbite/card.rb +0 -45
- data/app/components/flowbite/input/file.rb +0 -30
- data/app/components/flowbite/input/textarea.rb +0 -42
- data/app/components/flowbite/input/validation_error.rb +0 -11
- data/app/components/flowbite/input_field/checkbox.html.erb +0 -14
- data/app/components/flowbite/input_field/input_field.html.erb +0 -8
- data/app/components/flowbite/input_field/radio_button.html.erb +0 -14
- data/app/components/flowbite/link.rb +0 -21
- data/app/components/flowbite/toast/toast.html.erb +0 -11
- /data/app/components/{flowbite → uchi/flowbite}/toast/icon.html.erb +0 -0
|
@@ -10,12 +10,12 @@ running the following command:
|
|
|
10
10
|
/* We need tailwindcss, duh */
|
|
11
11
|
@import "tailwindcss";
|
|
12
12
|
|
|
13
|
-
/* Import the default theme variables from Flowbite
|
|
14
|
-
This imports them from node_modules/flowbite/src/themes/default.css */
|
|
15
|
-
@import "flowbite/src/themes/default";
|
|
16
|
-
|
|
17
13
|
/* Import the Flowbite plugin */
|
|
18
14
|
@plugin "flowbite/plugin";
|
|
19
15
|
|
|
16
|
+
/* Import the default theme variables from Flowbite */
|
|
17
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
|
|
18
|
+
@import "flowbite/src/themes/default"; /* This imports them from node_modules/flowbite/src/themes/default.css */
|
|
19
|
+
|
|
20
20
|
/* Configure the source files of Flowbite */
|
|
21
21
|
@source "../../../node_modules/flowbite";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::Select.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::Select.new(**options)) %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%=
|
|
1
|
+
<%= label_for_associated_record %>
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
).with_content(associated_record.to_s)) %>
|
|
5
|
-
<% end %>
|
|
1
|
+
<%= render(Uchi::Flowbite::Link.new(
|
|
2
|
+
href: path_to_show_associated_record,
|
|
3
|
+
).with_content(label_for_associated_record)) %>
|
|
@@ -5,6 +5,23 @@ module Uchi
|
|
|
5
5
|
class BelongsTo < Field
|
|
6
6
|
DEFAULT_COLLECTION_QUERY = ->(query) { query }.freeze
|
|
7
7
|
|
|
8
|
+
module Helpers
|
|
9
|
+
def associated_record
|
|
10
|
+
field.value(record)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def associated_repository
|
|
14
|
+
reflection = record.class.reflect_on_association(field.name)
|
|
15
|
+
model = reflection.klass
|
|
16
|
+
repository_class = Uchi::Repository.for_model(model)
|
|
17
|
+
repository_class.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def label_for_associated_record
|
|
21
|
+
associated_repository.title(associated_record)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
8
25
|
class Edit < Uchi::Field::Base::Edit
|
|
9
26
|
def associated_repository
|
|
10
27
|
model = reflection.klass
|
|
@@ -54,18 +71,24 @@ module Uchi
|
|
|
54
71
|
end
|
|
55
72
|
|
|
56
73
|
class Index < Uchi::Field::Base::Index
|
|
74
|
+
include Helpers
|
|
75
|
+
|
|
76
|
+
def render?
|
|
77
|
+
associated_record.present?
|
|
78
|
+
end
|
|
57
79
|
end
|
|
58
80
|
|
|
59
81
|
class Show < Uchi::Field::Base::Show
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
include Helpers
|
|
83
|
+
|
|
84
|
+
def path_to_show_associated_record
|
|
85
|
+
associated_repository
|
|
86
|
+
.routes
|
|
87
|
+
.path_for(:show, id: associated_record.id)
|
|
62
88
|
end
|
|
63
89
|
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
model = reflection.klass
|
|
67
|
-
repository_class = Uchi::Repository.for_model(model)
|
|
68
|
-
repository_class.new
|
|
90
|
+
def render?
|
|
91
|
+
associated_record.present?
|
|
69
92
|
end
|
|
70
93
|
end
|
|
71
94
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::Checkbox.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::Checkbox.new(**options)) %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::Date.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::Date.new(**options)) %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::DateTime.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::DateTime.new(**options)) %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::File.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::File.new(**options)) %>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<% attachment = field.value(record) %>
|
|
2
|
+
|
|
2
3
|
<% if attachment.attached? %>
|
|
3
|
-
<%= render Flowbite::Link.new(href: Rails.application.routes.url_helpers.rails_blob_path(attachment, only_path: true)) do %>
|
|
4
|
+
<%= render Uchi::Flowbite::Link.new(href: Rails.application.routes.url_helpers.rails_blob_path(attachment, only_path: true)) do %>
|
|
4
5
|
<%= attachment.filename %>
|
|
5
6
|
<% end %>
|
|
6
7
|
<% else %>
|
|
7
|
-
|
|
8
|
+
<%= render(Uchi::Ui::NoValue.new) %>
|
|
8
9
|
<% end %>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<div class="my-10">
|
|
2
|
-
<h2 class="px-4 my-6 text-2xl font-
|
|
2
|
+
<h2 class="px-4 my-6 text-2xl font-semibold tracking-tight text-heading md:px-0">
|
|
3
|
+
<%= repository.translate.field_label(field) %>
|
|
4
|
+
</h2>
|
|
3
5
|
|
|
4
6
|
<%= render(Uchi::Ui::Index::TurboFrame.new(
|
|
5
7
|
repository: associated_repository,
|
|
@@ -19,10 +21,10 @@
|
|
|
19
21
|
},
|
|
20
22
|
)
|
|
21
23
|
)) do %>
|
|
22
|
-
|
|
24
|
+
<%= render(Uchi::Ui::Frame.new) do %>
|
|
23
25
|
<div class="grid grid place-items-center p-8">
|
|
24
26
|
<%= render(Uchi::Ui::Spinner.new(message: repository.translate.loading_message)) %>
|
|
25
27
|
</div>
|
|
26
|
-
|
|
28
|
+
<% end %>
|
|
27
29
|
<% end %>
|
|
28
30
|
</div>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<div class="my-10">
|
|
2
|
-
<h2 class="px-4 my-6 text-2xl font-
|
|
2
|
+
<h2 class="px-4 my-6 text-2xl font-semibold tracking-tight text-heading md:px-0">
|
|
3
|
+
<%= repository.translate.field_label(field) %>
|
|
4
|
+
</h2>
|
|
3
5
|
|
|
4
6
|
<%= render(Uchi::Ui::Index::TurboFrame.new(
|
|
5
7
|
repository: associated_repository,
|
|
@@ -19,10 +21,10 @@
|
|
|
19
21
|
},
|
|
20
22
|
)
|
|
21
23
|
)) do %>
|
|
22
|
-
|
|
24
|
+
<%= render(Uchi::Ui::Frame.new) do %>
|
|
23
25
|
<div class="grid grid place-items-center p-8">
|
|
24
26
|
<%= render(Uchi::Ui::Spinner.new(message: repository.translate.loading_message)) %>
|
|
25
27
|
</div>
|
|
26
|
-
|
|
28
|
+
<% end %>
|
|
27
29
|
<% end %>
|
|
28
30
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::File.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::File.new(**options)) %>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<% attachment = field.value(record) %>
|
|
2
|
+
|
|
2
3
|
<% if attachment.attached? %>
|
|
3
4
|
<%= image_tag attachment.variant(resize_to_limit: [100, 100]), class: "h-12 w-12 object-cover rounded" %>
|
|
4
5
|
<% else %>
|
|
5
|
-
|
|
6
|
+
<%= render(Uchi::Ui::NoValue.new) %>
|
|
6
7
|
<% end %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::Number.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::Number.new(**options)) %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::Text.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::Text.new(**options)) %>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%= render(Flowbite::InputField::Textarea.new(**options)) %>
|
|
1
|
+
<%= render(Uchi::Flowbite::InputField::Textarea.new(**options)) %>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
# Renders a breadcrumb navigation component.
|
|
5
5
|
#
|
|
6
6
|
# See https://flowbite.com/docs/components/breadcrumb/
|
|
7
7
|
#
|
|
8
8
|
# @example Basic usage with BreadcrumbItem components
|
|
9
|
-
# <%= render Flowbite::Breadcrumb.new do |breadcrumb| %>
|
|
9
|
+
# <%= render Uchi::Flowbite::Breadcrumb.new do |breadcrumb| %>
|
|
10
10
|
# <% breadcrumb.with_item do %>
|
|
11
|
-
# <%= render Flowbite::BreadcrumbItem::First.new(href: "/") { "Home" } %>
|
|
11
|
+
# <%= render Uchi::Flowbite::BreadcrumbItem::First.new(href: "/") { "Home" } %>
|
|
12
12
|
# <% end %>
|
|
13
13
|
# <% breadcrumb.with_item do %>
|
|
14
|
-
# <%= render Flowbite::BreadcrumbItem.new(href: "/projects") { "Projects" } %>
|
|
14
|
+
# <%= render Uchi::Flowbite::BreadcrumbItem.new(href: "/projects") { "Projects" } %>
|
|
15
15
|
# <% end %>
|
|
16
16
|
# <% breadcrumb.with_item do %>
|
|
17
|
-
# <%= render Flowbite::BreadcrumbItem::Current.new { "Current Page" } %>
|
|
17
|
+
# <%= render Uchi::Flowbite::BreadcrumbItem::Current.new { "Current Page" } %>
|
|
18
18
|
# <% end %>
|
|
19
19
|
# <% end %>
|
|
20
20
|
class Breadcrumb < ViewComponent::Base
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
# Renders a breadcrumb home icon.
|
|
5
5
|
#
|
|
6
6
|
# This is typically used as a prefix icon in the first breadcrumb item,
|
|
7
7
|
# but can be used standalone if needed.
|
|
8
8
|
#
|
|
9
9
|
# @example Standalone usage
|
|
10
|
-
# <%= render Flowbite::BreadcrumbHome.new %>
|
|
10
|
+
# <%= render Uchi::Flowbite::BreadcrumbHome.new %>
|
|
11
11
|
class BreadcrumbHome < ViewComponent::Base
|
|
12
12
|
def call
|
|
13
13
|
tag.svg(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
class BreadcrumbItem
|
|
5
5
|
# Renders the current page breadcrumb item.
|
|
6
6
|
# Current items are rendered as non-interactive spans with different styling.
|
|
@@ -8,7 +8,7 @@ module Flowbite
|
|
|
8
8
|
# @param options [Hash] Additional HTML attributes to pass to the span element.
|
|
9
9
|
#
|
|
10
10
|
# @example Current page item
|
|
11
|
-
# <%= render Flowbite::BreadcrumbItem::Current.new { "Current Page" } %>
|
|
11
|
+
# <%= render Uchi::Flowbite::BreadcrumbItem::Current.new { "Current Page" } %>
|
|
12
12
|
class Current < BreadcrumbItem
|
|
13
13
|
def initialize(**options)
|
|
14
14
|
super(href: nil, **options)
|
|
@@ -26,7 +26,7 @@ module Flowbite
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def link_classes
|
|
29
|
-
["ms-1", "text-sm", "font-medium", "text-
|
|
29
|
+
["ms-1", "text-sm", "font-medium", "text-body-subtle"]
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
class BreadcrumbItem
|
|
5
5
|
# Renders the first breadcrumb item (typically home).
|
|
6
6
|
# First items don't show a separator icon.
|
|
@@ -9,7 +9,7 @@ module Flowbite
|
|
|
9
9
|
# @param options [Hash] Additional HTML attributes to pass to the link element.
|
|
10
10
|
#
|
|
11
11
|
# @example First item
|
|
12
|
-
# <%= render Flowbite::BreadcrumbItem::First.new(href: "/") { "Home" } %>
|
|
12
|
+
# <%= render Uchi::Flowbite::BreadcrumbItem::First.new(href: "/") { "Home" } %>
|
|
13
13
|
class First < BreadcrumbItem
|
|
14
14
|
protected
|
|
15
15
|
|
|
@@ -18,7 +18,7 @@ module Flowbite
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def link_classes
|
|
21
|
-
["text-sm", "font-medium", "inline-flex", "items-center", "text-
|
|
21
|
+
["text-sm", "font-medium", "inline-flex", "items-center", "text-body", "hover:text-fg-brand"]
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def prefix_icon
|
|
@@ -26,7 +26,7 @@ module Flowbite
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def render_link
|
|
29
|
-
icon = render(Flowbite::BreadcrumbHome.new)
|
|
29
|
+
icon = render(Uchi::Flowbite::BreadcrumbHome.new)
|
|
30
30
|
link_options = {class: link_classes}.merge(options)
|
|
31
31
|
content_tag(:a, safe_join([icon, content]), href: href, **link_options)
|
|
32
32
|
end
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
# Base class for rendering a breadcrumb item (middle items in the breadcrumb trail).
|
|
5
5
|
#
|
|
6
6
|
# @param href [String] The URL for the breadcrumb link.
|
|
7
7
|
# @param options [Hash] Additional HTML attributes to pass to the link element.
|
|
8
8
|
#
|
|
9
9
|
# @example Middle item
|
|
10
|
-
# <%= render Flowbite::BreadcrumbItem.new(href: "/projects") { "Projects" } %>
|
|
10
|
+
# <%= render Uchi::Flowbite::BreadcrumbItem.new(href: "/projects") { "Projects" } %>
|
|
11
11
|
class BreadcrumbItem < ViewComponent::Base
|
|
12
12
|
attr_reader :href, :options
|
|
13
13
|
|
|
@@ -33,7 +33,7 @@ module Flowbite
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def prefix_icon
|
|
36
|
-
Flowbite::BreadcrumbSeparator.new
|
|
36
|
+
Uchi::Flowbite::BreadcrumbSeparator.new
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def render_link
|
|
@@ -42,7 +42,7 @@ module Flowbite
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def link_classes
|
|
45
|
-
["ms-1", "text-sm", "font-medium", "text-
|
|
45
|
+
["ms-1", "text-sm", "font-medium", "text-body", "hover:text-fg-brand"]
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
# Renders a breadcrumb separator icon.
|
|
5
5
|
#
|
|
6
6
|
# This is automatically used by BreadcrumbItem components, but can be
|
|
7
7
|
# used standalone if needed.
|
|
8
8
|
#
|
|
9
9
|
# @example Standalone usage
|
|
10
|
-
# <%= render Flowbite::BreadcrumbSeparator.new %>
|
|
10
|
+
# <%= render Uchi::Flowbite::BreadcrumbSeparator.new %>
|
|
11
11
|
class BreadcrumbSeparator < ViewComponent::Base
|
|
12
12
|
def call
|
|
13
13
|
tag.svg(
|
|
14
|
-
class: "
|
|
14
|
+
class: "w-3.5 h-3.5 rtl:rotate-180 text-body",
|
|
15
15
|
"aria-hidden": "true",
|
|
16
16
|
xmlns: "http://www.w3.org/2000/svg",
|
|
17
17
|
fill: "none",
|
|
18
|
-
|
|
18
|
+
height: 24,
|
|
19
|
+
viewBox: "0 0 24 24",
|
|
20
|
+
width: 24
|
|
19
21
|
) do
|
|
20
22
|
tag.path(
|
|
21
23
|
stroke: "currentColor",
|
|
22
24
|
"stroke-linecap": "round",
|
|
23
25
|
"stroke-linejoin": "round",
|
|
24
26
|
"stroke-width": "2",
|
|
25
|
-
d: "
|
|
27
|
+
d: "m9 5 7 7-7 7"
|
|
26
28
|
)
|
|
27
29
|
end
|
|
28
30
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uchi::Flowbite
|
|
4
|
+
class Button
|
|
5
|
+
class Outline < Uchi::Flowbite::Button
|
|
6
|
+
class << self
|
|
7
|
+
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
|
8
|
+
def styles
|
|
9
|
+
{
|
|
10
|
+
danger: Uchi::Flowbite::Style.new(
|
|
11
|
+
default: ["focus:outline-none", "text-danger", "bg-transparent", "box-border", "border", "border-danger", "hover:text-white", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
12
|
+
),
|
|
13
|
+
dark: Uchi::Flowbite::Style.new(
|
|
14
|
+
default: ["focus:outline-none", "text-dark", "bg-transparent", "box-border", "border", "border-dark", "hover:text-white", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
15
|
+
),
|
|
16
|
+
default: Uchi::Flowbite::Style.new(
|
|
17
|
+
default: ["focus:outline-none", "text-brand", "bg-transparent", "box-border", "border", "border-brand", "hover:text-white", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
18
|
+
),
|
|
19
|
+
secondary: Uchi::Flowbite::Style.new(
|
|
20
|
+
default: ["focus:outline-none", "text-body", "bg-transparent", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
21
|
+
),
|
|
22
|
+
success: Uchi::Flowbite::Style.new(
|
|
23
|
+
default: ["focus:outline-none", "text-success", "bg-transparent", "box-border", "border", "border-success", "hover:text-white", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
24
|
+
),
|
|
25
|
+
tertiary: Uchi::Flowbite::Style.new(
|
|
26
|
+
default: ["focus:outline-none", "text-body", "bg-transparent", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
27
|
+
),
|
|
28
|
+
warning: Uchi::Flowbite::Style.new(
|
|
29
|
+
default: ["focus:outline-none", "text-warning", "bg-transparent", "box-border", "border", "border-warning", "hover:text-white", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uchi::Flowbite
|
|
4
|
+
class Button
|
|
5
|
+
class Pill < Uchi::Flowbite::Button
|
|
6
|
+
class << self
|
|
7
|
+
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
|
8
|
+
def styles
|
|
9
|
+
{
|
|
10
|
+
danger: Uchi::Flowbite::Style.new(
|
|
11
|
+
default: ["focus:outline-none", "text-white", "bg-danger", "box-border", "border", "border-transparent", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
12
|
+
),
|
|
13
|
+
dark: Uchi::Flowbite::Style.new(
|
|
14
|
+
default: ["focus:outline-none", "text-white", "bg-dark", "box-border", "border", "border-transparent", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
15
|
+
),
|
|
16
|
+
default: Uchi::Flowbite::Style.new(
|
|
17
|
+
default: ["focus:outline-none", "text-white", "bg-brand", "box-border", "border", "border-transparent", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
18
|
+
),
|
|
19
|
+
ghost: Uchi::Flowbite::Style.new(
|
|
20
|
+
default: ["focus:outline-none", "text-heading", "bg-transparent", "box-border", "border", "border-transparent", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
21
|
+
),
|
|
22
|
+
secondary: Uchi::Flowbite::Style.new(
|
|
23
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
24
|
+
),
|
|
25
|
+
success: Uchi::Flowbite::Style.new(
|
|
26
|
+
default: ["focus:outline-none", "text-white", "bg-success", "box-border", "border", "border-transparent", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
27
|
+
),
|
|
28
|
+
tertiary: Uchi::Flowbite::Style.new(
|
|
29
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-primary-soft", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
30
|
+
),
|
|
31
|
+
warning: Uchi::Flowbite::Style.new(
|
|
32
|
+
default: ["focus:outline-none", "text-white", "bg-warning", "box-border", "border", "border-transparent", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uchi::Flowbite
|
|
4
|
+
# Renders a HTML button element.
|
|
5
|
+
#
|
|
6
|
+
# See https://flowbite.com/docs/components/buttons/
|
|
7
|
+
#
|
|
8
|
+
# @param label [String] The text to display on the button.
|
|
9
|
+
#
|
|
10
|
+
# All other parameters are optional and are passed directly to the button tag
|
|
11
|
+
# as HTML attributes.
|
|
12
|
+
class Button < ViewComponent::Base
|
|
13
|
+
SIZES = {
|
|
14
|
+
xs: ["text-xs", "px-3", "py-1.5"],
|
|
15
|
+
sm: ["text-sm", "px-3", "py-2"],
|
|
16
|
+
default: ["text-sm", "px-4", "py-2.5"],
|
|
17
|
+
lg: ["text-base", "px-5", "py-3"],
|
|
18
|
+
xl: ["text-base", "px-6", "py-3.5"]
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def classes(size: :default, state: :default, style: :default)
|
|
23
|
+
style = styles.fetch(style) or raise "wut"
|
|
24
|
+
classes = style.fetch(state)
|
|
25
|
+
classes + sizes.fetch(size)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def sizes
|
|
29
|
+
SIZES
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# rubocop:disable Layout/LineLength
|
|
33
|
+
def styles
|
|
34
|
+
{
|
|
35
|
+
danger: Uchi::Flowbite::Style.new(
|
|
36
|
+
default: ["focus:outline-none", "text-white", "bg-danger", "box-border", "border", "border-transparent", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
37
|
+
),
|
|
38
|
+
dark: Uchi::Flowbite::Style.new(
|
|
39
|
+
default: ["focus:outline-none", "text-white", "bg-dark", "box-border", "border", "border-transparent", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
40
|
+
),
|
|
41
|
+
default: Uchi::Flowbite::Style.new(
|
|
42
|
+
default: ["focus:outline-none", "text-white", "bg-brand", "box-border", "border", "border-transparent", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
43
|
+
),
|
|
44
|
+
ghost: Uchi::Flowbite::Style.new(
|
|
45
|
+
default: ["focus:outline-none", "text-heading", "bg-transparent", "box-border", "border", "border-transparent", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "font-medium", "leading-5", "rounded-base"]
|
|
46
|
+
),
|
|
47
|
+
secondary: Uchi::Flowbite::Style.new(
|
|
48
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
49
|
+
),
|
|
50
|
+
success: Uchi::Flowbite::Style.new(
|
|
51
|
+
default: ["focus:outline-none", "text-white", "bg-success", "box-border", "border", "border-transparent", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
52
|
+
),
|
|
53
|
+
tertiary: Uchi::Flowbite::Style.new(
|
|
54
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-primary-soft", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
55
|
+
),
|
|
56
|
+
warning: Uchi::Flowbite::Style.new(
|
|
57
|
+
default: ["focus:outline-none", "text-white", "bg-warning", "box-border", "border", "border-transparent", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
58
|
+
)
|
|
59
|
+
}.freeze
|
|
60
|
+
end
|
|
61
|
+
# rubocop:enable Layout/LineLength
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
attr_reader :button_attributes, :size, :style
|
|
65
|
+
|
|
66
|
+
def initialize(class: nil, size: :default, style: :default, **button_attributes)
|
|
67
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
68
|
+
@size = size
|
|
69
|
+
@style = style
|
|
70
|
+
@button_attributes = button_attributes
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def call
|
|
74
|
+
content_tag(
|
|
75
|
+
:button,
|
|
76
|
+
content,
|
|
77
|
+
**options
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def classes
|
|
84
|
+
self.class.classes(size: size, state: :default, style: style) + @class
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def options
|
|
88
|
+
{
|
|
89
|
+
class: classes
|
|
90
|
+
}.merge(button_attributes)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uchi::Flowbite
|
|
4
|
+
class Card
|
|
5
|
+
# Renders the title of a card element.
|
|
6
|
+
class Title < ViewComponent::Base
|
|
7
|
+
class << self
|
|
8
|
+
def classes(state: :default, style: :default)
|
|
9
|
+
style = styles.fetch(style)
|
|
10
|
+
style.fetch(state)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# rubocop:disable Layout/LineLength
|
|
14
|
+
def styles
|
|
15
|
+
{
|
|
16
|
+
default: Uchi::Flowbite::Style.new(
|
|
17
|
+
default: ["mb-2", "text-2xl", "font-semibold", "tracking-tight", "text-heading"]
|
|
18
|
+
)
|
|
19
|
+
}.freeze
|
|
20
|
+
end
|
|
21
|
+
# rubocop:enable Layout/LineLength
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def call
|
|
25
|
+
title_options = {
|
|
26
|
+
class: self.class.classes
|
|
27
|
+
}.merge(@options)
|
|
28
|
+
|
|
29
|
+
content_tag(:h5, content, **title_options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def initialize(**options)
|
|
33
|
+
@options = options || {}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|