bulma-phlex 0.7.0 → 0.8.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 +65 -32
- data/lib/bulma-phlex.rb +1 -17
- data/lib/bulma_phlex/base.rb +18 -0
- data/lib/bulma_phlex/card.rb +89 -0
- data/lib/bulma_phlex/dropdown.rb +107 -0
- data/lib/bulma_phlex/level.rb +67 -0
- data/lib/bulma_phlex/navigation_bar.rb +106 -0
- data/lib/bulma_phlex/navigation_bar_dropdown.rb +44 -0
- data/lib/bulma_phlex/pagination.rb +121 -0
- data/lib/bulma_phlex/tab_components/content.rb +28 -0
- data/lib/bulma_phlex/tab_components/tab.rb +42 -0
- data/lib/bulma_phlex/table.rb +148 -0
- data/lib/bulma_phlex/tabs.rb +117 -0
- data/lib/bulma_phlex/tag.rb +60 -0
- data/lib/bulma_phlex/title.rb +57 -0
- data/lib/bulma_phlex/version.rb +1 -1
- data/lib/{components/bulma.rb → bulma_phlex.rb} +10 -6
- metadata +15 -44
- data/lib/bulma_phlex/rails/card_helper.rb +0 -34
- data/lib/bulma_phlex/rails/table_helper.rb +0 -24
- data/lib/bulma_phlex/railtie.rb +0 -20
- data/lib/components/bulma/base.rb +0 -20
- data/lib/components/bulma/card.rb +0 -83
- data/lib/components/bulma/dropdown.rb +0 -109
- data/lib/components/bulma/level.rb +0 -69
- data/lib/components/bulma/navigation_bar.rb +0 -108
- data/lib/components/bulma/navigation_bar_dropdown.rb +0 -46
- data/lib/components/bulma/pagination.rb +0 -123
- data/lib/components/bulma/tab_components/content.rb +0 -30
- data/lib/components/bulma/tab_components/tab.rb +0 -44
- data/lib/components/bulma/table.rb +0 -150
- data/lib/components/bulma/tabs.rb +0 -119
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Pagination component for navigating through multi-page content
|
|
5
|
+
#
|
|
6
|
+
# This component implements the [Bulma pagination](https://bulma.io/documentation/components/pagination/)
|
|
7
|
+
# interface, providing navigation controls for paginated content. It shows:
|
|
8
|
+
# - Previous/next page links
|
|
9
|
+
# - First/last page links when appropriate
|
|
10
|
+
# - Current page indicator
|
|
11
|
+
# - Ellipses for skipped page ranges
|
|
12
|
+
# - Summary of items being displayed
|
|
13
|
+
#
|
|
14
|
+
# ## Example
|
|
15
|
+
#
|
|
16
|
+
# ```ruby
|
|
17
|
+
# # In a controller action:
|
|
18
|
+
# @products = Product.page(params[:page]).per(20)
|
|
19
|
+
#
|
|
20
|
+
# # In the view:
|
|
21
|
+
# BulmaPhlex::Pagination(@products, ->(page) { products_path(page: page) })
|
|
22
|
+
# ```
|
|
23
|
+
#
|
|
24
|
+
class Pagination < BulmaPhlex::Base
|
|
25
|
+
attr_reader :pager, :path_builder
|
|
26
|
+
|
|
27
|
+
# Initializes the pagination component
|
|
28
|
+
#
|
|
29
|
+
# @param pager [Object] An object that responds to:
|
|
30
|
+
# - `current_page` - Integer representing the current page number
|
|
31
|
+
# - `total_pages` - Integer representing the total number of pages
|
|
32
|
+
# - `per_page` - Integer representing the number of items per page
|
|
33
|
+
# - `total_count` - Integer representing the total number of items
|
|
34
|
+
# - `previous_page` - Integer or nil representing the previous page number
|
|
35
|
+
# - `next_page` - Integer or nil representing the next page number
|
|
36
|
+
# @param path_builder [Proc] A callable that takes a page number and returns a URL string
|
|
37
|
+
def initialize(pager, path_builder)
|
|
38
|
+
@pager = pager
|
|
39
|
+
@path_builder = path_builder
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def view_template
|
|
43
|
+
return unless pager.total_pages > 1
|
|
44
|
+
|
|
45
|
+
div(class: "pagination-container mt-5") do
|
|
46
|
+
nav(class: "pagination", role: "navigation", aria_label: "pagination") do
|
|
47
|
+
# Previous page link
|
|
48
|
+
if pager.previous_page
|
|
49
|
+
a(class: "pagination-previous", href: page_url(pager.previous_page)) { "Previous" }
|
|
50
|
+
else
|
|
51
|
+
a(class: "pagination-previous", disabled: true) { "Previous" }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Next page link
|
|
55
|
+
if pager.next_page
|
|
56
|
+
a(class: "pagination-next", href: page_url(pager.next_page)) { "Next" }
|
|
57
|
+
else
|
|
58
|
+
a(class: "pagination-next", disabled: true) { "Next" }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Page number links
|
|
62
|
+
ul(class: "pagination-list") do
|
|
63
|
+
# First page and ellipsis if needed
|
|
64
|
+
if pager.current_page > 3
|
|
65
|
+
render_page_item(1)
|
|
66
|
+
render_ellipsis if pager.current_page > 4
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Pages around current page
|
|
70
|
+
page_window.each do |page_number|
|
|
71
|
+
render_page_item(page_number)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Ellipsis and last page if needed
|
|
75
|
+
if pager.current_page < pager.total_pages - 2
|
|
76
|
+
render_ellipsis if pager.current_page < pager.total_pages - 3
|
|
77
|
+
render_page_item(pager.total_pages)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
div(class: "has-text-centered mt-2 is-size-7") do
|
|
83
|
+
start_item = ((pager.current_page - 1) * pager.per_page) + 1
|
|
84
|
+
end_item = [start_item + pager.per_page - 1, pager.total_count].min
|
|
85
|
+
|
|
86
|
+
plain "Showing #{start_item}-#{end_item} of #{pager.total_count} items"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def render_page_item(page_number)
|
|
94
|
+
li do
|
|
95
|
+
if page_number == pager.current_page
|
|
96
|
+
a(class: "pagination-link is-current",
|
|
97
|
+
aria_label: "Page #{page_number}",
|
|
98
|
+
aria_current: "page") { page_number.to_s }
|
|
99
|
+
else
|
|
100
|
+
a(class: "pagination-link",
|
|
101
|
+
href: page_url(page_number),
|
|
102
|
+
aria_label: "Go to page #{page_number}") { page_number.to_s }
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def render_ellipsis
|
|
108
|
+
li { span(class: "pagination-ellipsis") { "…" } }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def page_window
|
|
112
|
+
start_page = [pager.current_page - 2, 1].max
|
|
113
|
+
end_page = [pager.current_page + 2, pager.total_pages].min
|
|
114
|
+
(start_page..end_page).to_a
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def page_url(page_number)
|
|
118
|
+
@path_builder.call(page_number)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
module TabComponents
|
|
5
|
+
# # Content
|
|
6
|
+
#
|
|
7
|
+
# This component represents a single content section within the Bulma Tabs component.
|
|
8
|
+
#
|
|
9
|
+
# ## Arguments:
|
|
10
|
+
# - `id`: Unique identifier for the content.
|
|
11
|
+
# - `active`: Boolean indicating if the content is currently active.
|
|
12
|
+
# - `data_attributes_proc`: A proc that generates data attributes for the content.
|
|
13
|
+
class Content < BulmaPhlex::Base
|
|
14
|
+
def initialize(id:, active:, data_attributes_proc: nil)
|
|
15
|
+
@id = id
|
|
16
|
+
@active = active
|
|
17
|
+
@data_attributes = data_attributes_proc ||
|
|
18
|
+
BulmaPhlex::Tabs::StimulusDataAttributes.new("bulma-phlex--tabs").method(:for_content)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def view_template(&)
|
|
22
|
+
div(id: @id,
|
|
23
|
+
class: @active ? "" : "is-hidden",
|
|
24
|
+
data: @data_attributes.call(@id), &)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
module TabComponents
|
|
5
|
+
# # Tab
|
|
6
|
+
#
|
|
7
|
+
# This component represents a single tab within the Bulma Tabs component.
|
|
8
|
+
#
|
|
9
|
+
# The component can be used if you need to create or update a tab dynamically.
|
|
10
|
+
#
|
|
11
|
+
# ## Arguments
|
|
12
|
+
#
|
|
13
|
+
# - `id`: Unique identifier for the tab.
|
|
14
|
+
# - `title`: The text displayed on the tab.
|
|
15
|
+
# - `icon`: Optional icon to display on the tab.
|
|
16
|
+
# - `active`: Boolean indicating if the tab is currently active.
|
|
17
|
+
# - `data_attributes_proc`: A proc that generates data attributes for the tab.
|
|
18
|
+
class Tab < BulmaPhlex::Base
|
|
19
|
+
def initialize(id:, title:, icon:, active:,
|
|
20
|
+
data_attributes_proc: BulmaPhlex::Tabs::StimulusDataAttributes.new("bulma-phlex--tabs").method(:for_tab))
|
|
21
|
+
@id = id
|
|
22
|
+
@title = title
|
|
23
|
+
@icon = icon
|
|
24
|
+
@active = active
|
|
25
|
+
@data_attributes_proc = data_attributes_proc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def view_template(&)
|
|
29
|
+
li(
|
|
30
|
+
id: "#{@id}-tab",
|
|
31
|
+
data: @data_attributes_proc.call(@id),
|
|
32
|
+
class: @active ? "is-active" : ""
|
|
33
|
+
) do
|
|
34
|
+
a do
|
|
35
|
+
icon_span(@icon, "mr-1") if @icon
|
|
36
|
+
span { @title }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Table component for data display
|
|
5
|
+
#
|
|
6
|
+
# This component implements the [Bulma table](https://bulma.io/documentation/elements/table/)
|
|
7
|
+
# interface, providing a way to display data in rows and columns with customizable
|
|
8
|
+
# headers and formatting options.
|
|
9
|
+
#
|
|
10
|
+
# ## Example
|
|
11
|
+
#
|
|
12
|
+
# ```ruby
|
|
13
|
+
# users = User.all
|
|
14
|
+
#
|
|
15
|
+
# BulmaPhlex::Table(users) do |table|
|
|
16
|
+
# table.column "Name" do |user|
|
|
17
|
+
# user.full_name
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# table.column "Email" do |user|
|
|
21
|
+
# user.email
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# table.column "Actions" do |user|
|
|
25
|
+
# link_to "Edit", edit_user_path(user), class: "button is-small"
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
# ```
|
|
29
|
+
#
|
|
30
|
+
class Table < BulmaPhlex::Base
|
|
31
|
+
def initialize(rows, id_or_options = nil, **options)
|
|
32
|
+
@rows = rows
|
|
33
|
+
@id, @table_class = parse_id_and_options(id_or_options, options, rows)
|
|
34
|
+
@columns = []
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def view_template(&)
|
|
38
|
+
vanish(&)
|
|
39
|
+
|
|
40
|
+
table(id: @id, class: @table_class) do
|
|
41
|
+
thead do
|
|
42
|
+
@columns.each do |column|
|
|
43
|
+
table_header(column)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
tbody do
|
|
48
|
+
@rows.each do |row|
|
|
49
|
+
tr do
|
|
50
|
+
@columns.each do |column|
|
|
51
|
+
td(**column[:html_attributes]) { column[:content].call(row) }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
pagination
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def column(header, **html_attributes, &content)
|
|
62
|
+
@columns << { header:, html_attributes:, content: }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def date_column(header, format: "%Y-%m-%d", **html_attributes, &content)
|
|
66
|
+
column(header, **html_attributes) do |row|
|
|
67
|
+
content.call(row)&.strftime(format)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def conditional_icon(header, icon_class: "fas fa-check", **html_attributes, &content)
|
|
72
|
+
html_attributes[:class] = [html_attributes[:class], "has-text-centered"].compact.join(" ")
|
|
73
|
+
|
|
74
|
+
column(header, **html_attributes) do |row|
|
|
75
|
+
icon_span(icon_class) if content.call(row)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def paginate(&path_builder)
|
|
80
|
+
@path_builder = path_builder
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def parse_id_and_options(id_or_options, options, rows)
|
|
86
|
+
if id_or_options.is_a?(String)
|
|
87
|
+
id = id_or_options
|
|
88
|
+
opts = options
|
|
89
|
+
else
|
|
90
|
+
opts = (id_or_options || {}).merge(options)
|
|
91
|
+
id = opts.delete(:id) || id_from_array_or_arel(rows)
|
|
92
|
+
end
|
|
93
|
+
table_class = "table #{parse_table_classes(opts)}"
|
|
94
|
+
[id, table_class]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def id_from_array_or_arel(rows)
|
|
98
|
+
if rows.respond_to? :model
|
|
99
|
+
rows.model.model_name.plural
|
|
100
|
+
elsif rows.empty?
|
|
101
|
+
"table"
|
|
102
|
+
else
|
|
103
|
+
rows.first.model_name.plural
|
|
104
|
+
end
|
|
105
|
+
rescue StandardError
|
|
106
|
+
"table"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def parse_table_classes(options)
|
|
110
|
+
options.slice(*%i[bordered striped narrow hoverable fullwidth])
|
|
111
|
+
.transform_keys { |key| "is-#{key}" }
|
|
112
|
+
.select { |_, value| value }
|
|
113
|
+
.keys
|
|
114
|
+
.join(" ")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# this derives a th class from the column html attributes
|
|
118
|
+
# perhaps a better way would be pre-defined pairs?
|
|
119
|
+
def table_header(column)
|
|
120
|
+
attributes = {}
|
|
121
|
+
attributes[:class] = header_alignment(column[:html_attributes])
|
|
122
|
+
th(**attributes) { column[:header] }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def header_alignment(html_attributes)
|
|
126
|
+
classes = html_attributes[:class]
|
|
127
|
+
return if classes.nil?
|
|
128
|
+
|
|
129
|
+
if classes&.include?("has-text-right") || classes&.include?("amount-display")
|
|
130
|
+
"has-text-right"
|
|
131
|
+
elsif classes&.include?("has-text-centered")
|
|
132
|
+
"has-text-centered"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def pagination
|
|
137
|
+
return unless @path_builder
|
|
138
|
+
|
|
139
|
+
tfoot do
|
|
140
|
+
tr do
|
|
141
|
+
td(class: "py-0", colspan: @columns.size) do
|
|
142
|
+
Pagination(@rows, @path_builder)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Tabs component for toggling between different content sections
|
|
5
|
+
#
|
|
6
|
+
# This component implements the [Bulma tabs](https://bulma.io/documentation/components/tabs/)
|
|
7
|
+
# interface, providing a way to toggle between different content sections using
|
|
8
|
+
# tabbed navigation. Includes support for icons and active state management.
|
|
9
|
+
#
|
|
10
|
+
# Classes can be assigned to either the tabs or contents wrappers. The tabs div is where Bulma
|
|
11
|
+
# options such as `is-boxed`, `is-centered`, or `is-small` can be added.
|
|
12
|
+
#
|
|
13
|
+
# Use method `right_content` to add content to the right of the tabs, such as a button.
|
|
14
|
+
#
|
|
15
|
+
# The tabs behavior can be managed by the data attributes provided by the `data_attributes_builder` argument. By
|
|
16
|
+
# default, this will use the `StimulusDataAttributes` class with the controller name `bulma-phlex--tabs`. That
|
|
17
|
+
# controlleris not provided by this library, but you can create your own Stimulus controller to handle the tab
|
|
18
|
+
# switching logic. Here is [an implementation of a Stimulus controller for Bulma tabs](https://github.com/RockSolt/bulma-rails-helpers/blob/main/app/javascript/controllers/bulma/tabs_controller.js).
|
|
19
|
+
#
|
|
20
|
+
# ## Example
|
|
21
|
+
#
|
|
22
|
+
# ```ruby
|
|
23
|
+
# BulmaPhlex::Tabs() do |tabs|
|
|
24
|
+
# tabs.tab(id: "profile", title: "Profile", active: true) do
|
|
25
|
+
# "Profile content goes here"
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# tabs.tab(id: "settings", title: "Settings", icon: "fas fa-cog") do
|
|
29
|
+
# "Settings content goes here"
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# tabs.tab(id: "notifications", title: "Notifications", icon: "fas fa-bell") do
|
|
33
|
+
# "Notifications content goes here"
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
# ```
|
|
37
|
+
#
|
|
38
|
+
class Tabs < BulmaPhlex::Base
|
|
39
|
+
StimulusDataAttributes = Data.define(:stimulus_controller) do
|
|
40
|
+
def for_container
|
|
41
|
+
{ controller: stimulus_controller }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def for_tab(id)
|
|
45
|
+
{
|
|
46
|
+
target_key => "tab",
|
|
47
|
+
tab_content: id,
|
|
48
|
+
action: "click->#{stimulus_controller}#showTabContent"
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def for_content(_id)
|
|
53
|
+
{ target_key => "content" }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def target_key
|
|
59
|
+
"#{stimulus_controller}-target"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def initialize(id: nil, tabs_class: nil, contents_class: nil,
|
|
64
|
+
data_attributes_builder: StimulusDataAttributes.new("bulma-phlex--tabs"))
|
|
65
|
+
@id = id || "tabs"
|
|
66
|
+
@tabs_class = tabs_class
|
|
67
|
+
@contents_class = contents_class
|
|
68
|
+
@data_attributes_builder = data_attributes_builder
|
|
69
|
+
@tabs = []
|
|
70
|
+
@contents = []
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def tab(id:, title:, icon: nil, active: false, &)
|
|
74
|
+
@tabs << TabComponents::Tab.new(id:, title:, icon:, active:,
|
|
75
|
+
data_attributes_proc: @data_attributes_builder.method(:for_tab))
|
|
76
|
+
@contents << TabComponents::Content.new(id:, active:,
|
|
77
|
+
data_attributes_proc: @data_attributes_builder.method(:for_content),
|
|
78
|
+
&)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def right_content(&content)
|
|
82
|
+
@right_content = content
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def view_template(&)
|
|
86
|
+
vanish(&)
|
|
87
|
+
|
|
88
|
+
div(id: @id, data: @data_attributes_builder.for_container) do
|
|
89
|
+
build_tabs_with_optional_right_content
|
|
90
|
+
div(id: "#{@id}-content", class: @contents_class) { build_content }
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def build_tabs_with_optional_right_content
|
|
97
|
+
return build_tabs if @right_content.nil?
|
|
98
|
+
|
|
99
|
+
div(class: "columns") do
|
|
100
|
+
div(class: "column") { build_tabs }
|
|
101
|
+
div(class: "column is-narrow") { @right_content.call }
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def build_tabs
|
|
106
|
+
div(class: "tabs #{@tabs_class}".strip) do
|
|
107
|
+
ul(id: "#{@id}-tabs") do
|
|
108
|
+
@tabs.each { render it }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def build_content
|
|
114
|
+
@contents.each { render it }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# # Tag
|
|
5
|
+
#
|
|
6
|
+
# The Tag component is a bit of a chameleon. It can generate a `span`, `a`, or `button` element
|
|
7
|
+
# based on the provided attributes. If an `href` attribute is provided, the tag will render as an `a` element. If
|
|
8
|
+
# the `delete` option is true or a `data-action` attribute is present, it will render as a `button` element.
|
|
9
|
+
# Otherwise, it defaults to a `span` element.
|
|
10
|
+
#
|
|
11
|
+
# ## Options
|
|
12
|
+
#
|
|
13
|
+
# - `delete`: If true, adds a delete button inside the tag.
|
|
14
|
+
# - `color`: Sets the [color of the tag](https://bulma.io/documentation/elements/tag/#colors)
|
|
15
|
+
# - `light`: To use a light version of the color, use the key `light` instead of `color`.
|
|
16
|
+
# - `size`: Sets the [size of the tag](https://bulma.io/documentation/elements/tag/#sizes): normal, medium, or large.
|
|
17
|
+
# - `rounded`: If true, adds the `is-rounded` class to the tag.
|
|
18
|
+
#
|
|
19
|
+
# ## HTML Attributes
|
|
20
|
+
#
|
|
21
|
+
# Any additional HTML attributes provided will be applied to the rendered element.
|
|
22
|
+
class Tag < BulmaPhlex::Base
|
|
23
|
+
TAG_OPTIONS = %i[delete color light size rounded].freeze
|
|
24
|
+
|
|
25
|
+
def initialize(text, **options_and_html_attributes)
|
|
26
|
+
@text = text
|
|
27
|
+
@html_attributes = options_and_html_attributes.except(*TAG_OPTIONS)
|
|
28
|
+
@options = options_and_html_attributes.slice(*TAG_OPTIONS)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def view_template
|
|
32
|
+
if @html_attributes.key?(:href)
|
|
33
|
+
a(class: tag_classes, **@html_attributes) { text_and_optional_delete_button }
|
|
34
|
+
elsif @options[:delete] || @html_attributes.dig(:data, :action).present?
|
|
35
|
+
button(class: tag_classes, **@html_attributes) { text_and_optional_delete_button }
|
|
36
|
+
else
|
|
37
|
+
span(class: tag_classes, **@html_attributes) { plain @text }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def text_and_optional_delete_button
|
|
44
|
+
plain @text
|
|
45
|
+
return unless @options[:delete]
|
|
46
|
+
|
|
47
|
+
size = "is-small" unless @options[:size] == "large"
|
|
48
|
+
span(class: "delete #{size}".rstrip)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def tag_classes
|
|
52
|
+
classes = ["tag"]
|
|
53
|
+
classes << "is-#{@options[:color]}" if @options[:color].present?
|
|
54
|
+
classes << "is-#{@options[:light]} is-light" if @options[:light]
|
|
55
|
+
classes << "is-#{@options[:size]}" if @options[:size].present?
|
|
56
|
+
classes << "is-rounded" if @options[:rounded]
|
|
57
|
+
classes.join(" ")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# # Title
|
|
5
|
+
#
|
|
6
|
+
# This component implements the
|
|
7
|
+
# [Bulma title element](https://bulma.io/documentation/elements/title/). It can optionally
|
|
8
|
+
# include a subtitle as well.
|
|
9
|
+
#
|
|
10
|
+
# ## Parameters
|
|
11
|
+
#
|
|
12
|
+
# - `text`: (positional, required) The main title text to display.
|
|
13
|
+
# - `size`: (optional) An integer from 1 to 6 indicating the size of the title. Corresponds to
|
|
14
|
+
# Bulma's `is-<size>` classes.
|
|
15
|
+
# - `subtitle`: (optional) The subtitle text to display below the main title.
|
|
16
|
+
# - `subtitle_size`: (optional) An integer from 1 to 6 indicating the size of the subtitle. If
|
|
17
|
+
# not provided and a title size is given, it defaults to `size + 2`.
|
|
18
|
+
# - `spaced`: (optional) A boolean indicating whether to add the `is-spaced` class to the title.
|
|
19
|
+
#
|
|
20
|
+
# ## Example
|
|
21
|
+
#
|
|
22
|
+
# ```ruby
|
|
23
|
+
# BulmaPhlex::Title("Hello World")
|
|
24
|
+
# BulmaPhlex::Title("Dr. Strangelove", size: 2, subtitle: "Or: How I Learned to Stop Worrying and
|
|
25
|
+
# Love the Bomb")
|
|
26
|
+
# ```
|
|
27
|
+
class Title < BulmaPhlex::Base
|
|
28
|
+
def initialize(text, size: nil, subtitle: nil, subtitle_size: nil, spaced: false)
|
|
29
|
+
@text = text
|
|
30
|
+
@size = size
|
|
31
|
+
@subtitle = subtitle
|
|
32
|
+
@subtitle_size = subtitle_size
|
|
33
|
+
@spaced = spaced
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def view_template
|
|
37
|
+
h1(class: title_classes) { @text }
|
|
38
|
+
h2(class: subtitle_classes) { @subtitle } if @subtitle
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def title_classes
|
|
44
|
+
classes = ["title"]
|
|
45
|
+
classes << "is-#{@size}" if @size
|
|
46
|
+
classes << "is-spaced" if @spaced
|
|
47
|
+
classes.join(" ")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def subtitle_classes
|
|
51
|
+
@subtitle_size = @size + 2 if @size && !@subtitle_size
|
|
52
|
+
classes = ["subtitle"]
|
|
53
|
+
classes << "is-#{@subtitle_size}" if @subtitle_size
|
|
54
|
+
classes.join(" ")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/bulma_phlex/version.rb
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "phlex"
|
|
4
|
+
require "zeitwerk"
|
|
5
|
+
|
|
6
|
+
loader = Zeitwerk::Loader.for_gem
|
|
7
|
+
loader.ignore("#{__dir__}/bulma-phlex.rb")
|
|
8
|
+
loader.setup # ready!
|
|
9
|
+
|
|
3
10
|
# A collection of Bulma components built with Phlex
|
|
4
11
|
#
|
|
5
12
|
# This module provides a set of components that implement the [Bulma CSS framework](https://bulma.io/)
|
|
6
13
|
# using the Phlex view component library. These components make it easy to build
|
|
7
|
-
# Bulma-styled applications with a Ruby-focused
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
module Bulma
|
|
11
|
-
extend Phlex::Kit
|
|
12
|
-
end
|
|
14
|
+
# Bulma-styled applications with a Ruby-focused components.
|
|
15
|
+
module BulmaPhlex
|
|
16
|
+
extend Phlex::Kit
|
|
13
17
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bulma-phlex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Todd Kummer
|
|
@@ -37,34 +37,6 @@ dependencies:
|
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '0'
|
|
40
|
-
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: actionview
|
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - ">="
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0'
|
|
47
|
-
type: :development
|
|
48
|
-
prerelease: false
|
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - ">="
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0'
|
|
54
|
-
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: activesupport
|
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - ">="
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: '0'
|
|
61
|
-
type: :development
|
|
62
|
-
prerelease: false
|
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - ">="
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: '0'
|
|
68
40
|
- !ruby/object:Gem::Dependency
|
|
69
41
|
name: minitest-difftastic
|
|
70
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -90,22 +62,21 @@ files:
|
|
|
90
62
|
- README.md
|
|
91
63
|
- Rakefile
|
|
92
64
|
- lib/bulma-phlex.rb
|
|
93
|
-
- lib/bulma_phlex
|
|
94
|
-
- lib/bulma_phlex/
|
|
95
|
-
- lib/bulma_phlex/
|
|
65
|
+
- lib/bulma_phlex.rb
|
|
66
|
+
- lib/bulma_phlex/base.rb
|
|
67
|
+
- lib/bulma_phlex/card.rb
|
|
68
|
+
- lib/bulma_phlex/dropdown.rb
|
|
69
|
+
- lib/bulma_phlex/level.rb
|
|
70
|
+
- lib/bulma_phlex/navigation_bar.rb
|
|
71
|
+
- lib/bulma_phlex/navigation_bar_dropdown.rb
|
|
72
|
+
- lib/bulma_phlex/pagination.rb
|
|
73
|
+
- lib/bulma_phlex/tab_components/content.rb
|
|
74
|
+
- lib/bulma_phlex/tab_components/tab.rb
|
|
75
|
+
- lib/bulma_phlex/table.rb
|
|
76
|
+
- lib/bulma_phlex/tabs.rb
|
|
77
|
+
- lib/bulma_phlex/tag.rb
|
|
78
|
+
- lib/bulma_phlex/title.rb
|
|
96
79
|
- lib/bulma_phlex/version.rb
|
|
97
|
-
- lib/components/bulma.rb
|
|
98
|
-
- lib/components/bulma/base.rb
|
|
99
|
-
- lib/components/bulma/card.rb
|
|
100
|
-
- lib/components/bulma/dropdown.rb
|
|
101
|
-
- lib/components/bulma/level.rb
|
|
102
|
-
- lib/components/bulma/navigation_bar.rb
|
|
103
|
-
- lib/components/bulma/navigation_bar_dropdown.rb
|
|
104
|
-
- lib/components/bulma/pagination.rb
|
|
105
|
-
- lib/components/bulma/tab_components/content.rb
|
|
106
|
-
- lib/components/bulma/tab_components/tab.rb
|
|
107
|
-
- lib/components/bulma/table.rb
|
|
108
|
-
- lib/components/bulma/tabs.rb
|
|
109
80
|
homepage: https://github.com/RockSolt/bulma-phlex
|
|
110
81
|
licenses:
|
|
111
82
|
- MIT
|