bulma-phlex 0.13.0 → 0.15.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 +33 -4
- data/lib/bulma_phlex/button.rb +24 -3
- data/lib/bulma_phlex/card.rb +23 -9
- data/lib/bulma_phlex/form_field.rb +5 -2
- data/lib/bulma_phlex/hero.rb +16 -9
- data/lib/bulma_phlex/message.rb +69 -0
- data/lib/bulma_phlex/notification.rb +9 -4
- data/lib/bulma_phlex/table.rb +73 -44
- data/lib/bulma_phlex/tag.rb +3 -3
- data/lib/bulma_phlex/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a1d3209d836363da07529fa00c9374618623280e70f3167c409e320b77dd4c4
|
|
4
|
+
data.tar.gz: e078ae57978d967610194b989078d484ad2297d4cdd71b0ae2d65b07d80dc105
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c7c0d1e8bbfb69e58e78af757f14b4dde6ab532f085e7ea970cb1addd511f2c5c33ba964df7b80dcfdac878f4475108858ceace18f3e5b52356d3b9b3d7df521
|
|
7
|
+
data.tar.gz: c41d7a84d0a5e5c2c03aafd7ff74764af2e94221c051aa67766815d46805cd153829deb87173b7d73285fcfaf9752433412070effb7755fced7d3e45df388912
|
data/README.md
CHANGED
|
@@ -20,6 +20,7 @@ This gem provides a set of ready-to-use [Phlex](https://github.com/phlex-ruby/ph
|
|
|
20
20
|
- [Hero](#hero)
|
|
21
21
|
- [Icon](#icon)
|
|
22
22
|
- [Level](#level)
|
|
23
|
+
- [Message](#message)
|
|
23
24
|
- [Modal](#modal)
|
|
24
25
|
- [NavigationBar](#navigationbar)
|
|
25
26
|
- [Notification](#notification)
|
|
@@ -58,7 +59,7 @@ gem install bulma-phlex
|
|
|
58
59
|
|
|
59
60
|
This gem requires:
|
|
60
61
|
|
|
61
|
-
- Ruby 3.
|
|
62
|
+
- Ruby 3.3 or higher
|
|
62
63
|
- Phlex 2.4.1 or higher
|
|
63
64
|
- Bulma CSS (which you'll need to include in your application)
|
|
64
65
|
|
|
@@ -84,11 +85,12 @@ Renders a [Bulma button](https://bulma.io/documentation/elements/button/) elemen
|
|
|
84
85
|
The component generates a `<button>` by default. Pass an `href:` attribute to generate an `<a>` element instead. Pass `input: "submit"` (or `"button"` or `"reset"`) to generate an `<input>` element.
|
|
85
86
|
|
|
86
87
|
```ruby
|
|
87
|
-
BulmaPhlex::Button(color: "primary", size: "large", icon: "fas fa-thumbs-up")
|
|
88
|
+
BulmaPhlex::Button("Like", color: "primary", size: "large", icon: "fas fa-thumbs-up")
|
|
88
89
|
BulmaPhlex::Button(href: "/profile") { "View Profile" }
|
|
89
90
|
BulmaPhlex::Button(input: "submit", color: "success")
|
|
90
91
|
```
|
|
91
92
|
|
|
93
|
+
The button label can be passed in as a string or in a block.
|
|
92
94
|
|
|
93
95
|
### Card
|
|
94
96
|
|
|
@@ -105,6 +107,9 @@ render BulmaPhlex::Card.new do |card|
|
|
|
105
107
|
end
|
|
106
108
|
```
|
|
107
109
|
|
|
110
|
+
Use method `footer_item` for full control of the footer items. Class `footer-item` must be on the outer element
|
|
111
|
+
of the block.
|
|
112
|
+
|
|
108
113
|
|
|
109
114
|
### Columns
|
|
110
115
|
|
|
@@ -157,7 +162,7 @@ Renders a [Bulma form field](https://bulma.io/documentation/form/general/#form-f
|
|
|
157
162
|
|
|
158
163
|
```ruby
|
|
159
164
|
render BulmaPhlex::FormField.new(help: "We'll never share your email.") do |field|
|
|
160
|
-
field.label("Email Address")
|
|
165
|
+
field.label("Email Address", for: "user_email_address")
|
|
161
166
|
field.control { input(name: "user[email_address]", type: "email") }
|
|
162
167
|
end
|
|
163
168
|
```
|
|
@@ -217,6 +222,17 @@ end
|
|
|
217
222
|
```
|
|
218
223
|
|
|
219
224
|
|
|
225
|
+
### Message
|
|
226
|
+
|
|
227
|
+
Renders a [Bulma message](https://bulma.io/documentation/components/message/) component with a header, optional delete button, and body.
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
render BulmaPhlex::Message.new("Hello World", color: "info", delete: true) do
|
|
231
|
+
"Look, it's a deletable message box!"
|
|
232
|
+
end
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
|
|
220
236
|
### Modal
|
|
221
237
|
|
|
222
238
|
Renders a [Bulma modal](https://bulma.io/documentation/components/modal/) dialog overlay with a background, content area, and close button. Content is provided via a block.
|
|
@@ -322,6 +338,19 @@ To add pagination to the table, call `paginate` with a block that returns a path
|
|
|
322
338
|
table.paginate { |page| products_path(page: page) }
|
|
323
339
|
```
|
|
324
340
|
|
|
341
|
+
Pass HTML attributes to the `tr` elements via the `row` method, using either keyword arguments or a block
|
|
342
|
+
that receives the record for the row:
|
|
343
|
+
|
|
344
|
+
```ruby
|
|
345
|
+
table.row(class: "custom-row-class") { |row| { id: "row-id-#{row.id}" } }
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Hide columns on smaller screens with the column `hidden` option:
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
table.column("Email", hidden: { mobile: true }) { |user| user.email }
|
|
352
|
+
```
|
|
353
|
+
|
|
325
354
|
|
|
326
355
|
### Tabs
|
|
327
356
|
|
|
@@ -402,4 +431,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
402
431
|
|
|
403
432
|
## Credits
|
|
404
433
|
|
|
405
|
-
This leverages the [Bulma CSS library](https://bulma.io/documentation/) and [Phlex](https://www.phlex.fun/) but is not endorsed or certified by either. We are fans of both and this makes using them together easier.
|
|
434
|
+
This leverages the [Bulma CSS library](https://bulma.io/documentation/) and [Phlex](https://www.phlex.fun/) but is not endorsed or certified by either. We are fans of both and this makes using them together easier.
|
data/lib/bulma_phlex/button.rb
CHANGED
|
@@ -7,6 +7,8 @@ module BulmaPhlex
|
|
|
7
7
|
# arguments provided. Supports Bulma options for **color**, **size**, **style mode**,
|
|
8
8
|
# and **layout** (responsive, fullwidth, outlined, inverted, rounded), as well as
|
|
9
9
|
# optional **icons** on the left and/or right side of the label.
|
|
10
|
+
#
|
|
11
|
+
# The label can be passed into the component as a string or from a block.
|
|
10
12
|
class Button < Base
|
|
11
13
|
# Returns an array of CSS classes for the button based on the provided options.
|
|
12
14
|
def self.classes_for(color: nil, # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
@@ -31,6 +33,7 @@ module BulmaPhlex
|
|
|
31
33
|
|
|
32
34
|
# **Parameters**
|
|
33
35
|
#
|
|
36
|
+
# - `label` (positional) — Optionally pass in button label as a string
|
|
34
37
|
# - `color` — Button color: `"primary"`, `"link"`, `"info"`, `"success"`, `"warning"`, `"danger"`
|
|
35
38
|
# - `mode` — Button style mode: `"light"` or `"dark"`
|
|
36
39
|
# - `size` — Button size: `"small"`, `"normal"`, `"medium"`, `"large"`
|
|
@@ -44,7 +47,8 @@ module BulmaPhlex
|
|
|
44
47
|
# - `icon_right` — Icon class added to the right of the button text
|
|
45
48
|
# - `input` — If set, renders an `<input>` element of this type (`"button"`, `"reset"`, `"submit"`)
|
|
46
49
|
# - `**html_attributes` — Additional HTML attributes for the button element
|
|
47
|
-
def self.new(
|
|
50
|
+
def self.new(label = nil,
|
|
51
|
+
color: nil,
|
|
48
52
|
mode: nil,
|
|
49
53
|
size: nil,
|
|
50
54
|
responsive: false,
|
|
@@ -60,7 +64,8 @@ module BulmaPhlex
|
|
|
60
64
|
super
|
|
61
65
|
end
|
|
62
66
|
|
|
63
|
-
def initialize(
|
|
67
|
+
def initialize(label = nil,
|
|
68
|
+
color: nil,
|
|
64
69
|
mode: nil,
|
|
65
70
|
size: nil,
|
|
66
71
|
responsive: false,
|
|
@@ -73,6 +78,7 @@ module BulmaPhlex
|
|
|
73
78
|
icon_right: nil,
|
|
74
79
|
input: nil,
|
|
75
80
|
**html_attributes)
|
|
81
|
+
@label = label
|
|
76
82
|
@classes = self.class.classes_for(color:, mode:, size:, responsive:, fullwidth:, outlined:, inverted:, rounded:)
|
|
77
83
|
@input = input
|
|
78
84
|
@icon_left = icon || icon_left
|
|
@@ -81,6 +87,8 @@ module BulmaPhlex
|
|
|
81
87
|
end
|
|
82
88
|
|
|
83
89
|
def view_template(&)
|
|
90
|
+
block_content = capture(&)
|
|
91
|
+
|
|
84
92
|
options = mix({ class: @classes }, @html_attributes)
|
|
85
93
|
|
|
86
94
|
if @input
|
|
@@ -89,10 +97,23 @@ module BulmaPhlex
|
|
|
89
97
|
element_type = @html_attributes.key?(:href) ? :a : :button
|
|
90
98
|
tag(element_type, **options) do
|
|
91
99
|
Icon(@icon_left) if @icon_left
|
|
92
|
-
|
|
100
|
+
button_label(block_content)
|
|
93
101
|
Icon(@icon_right) if @icon_right
|
|
94
102
|
end
|
|
95
103
|
end
|
|
96
104
|
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def button_label(block_content)
|
|
109
|
+
value = @label || block_content
|
|
110
|
+
return if value.nil? || value.empty?
|
|
111
|
+
|
|
112
|
+
if @icon_left || @icon_right
|
|
113
|
+
span { value }
|
|
114
|
+
else
|
|
115
|
+
plain value
|
|
116
|
+
end
|
|
117
|
+
end
|
|
97
118
|
end
|
|
98
119
|
end
|
data/lib/bulma_phlex/card.rb
CHANGED
|
@@ -65,6 +65,12 @@ module BulmaPhlex
|
|
|
65
65
|
(@footer_items ||= []) << [text, href, html_attributes]
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
# Delegates full control of the footer item to the block. The top element in the block must include
|
|
69
|
+
# the `card-footer-item` class.
|
|
70
|
+
def footer_item(&block)
|
|
71
|
+
(@footer_items ||= []) << block
|
|
72
|
+
end
|
|
73
|
+
|
|
68
74
|
private
|
|
69
75
|
|
|
70
76
|
def card_header
|
|
@@ -87,20 +93,28 @@ module BulmaPhlex
|
|
|
87
93
|
return if @footer_items.nil? || @footer_items.empty?
|
|
88
94
|
|
|
89
95
|
footer(class: "card-footer") do
|
|
90
|
-
@footer_items.each do |
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
icon_text(icon, text)
|
|
96
|
-
else
|
|
97
|
-
plain text
|
|
98
|
-
end
|
|
96
|
+
@footer_items.each do |block_or_text, href, html_attributes|
|
|
97
|
+
if block_or_text.is_a?(Proc)
|
|
98
|
+
block_or_text.call
|
|
99
|
+
else
|
|
100
|
+
render_footer_link(block_or_text, href, html_attributes)
|
|
99
101
|
end
|
|
100
102
|
end
|
|
101
103
|
end
|
|
102
104
|
end
|
|
103
105
|
|
|
106
|
+
def render_footer_link(text, href, html_attributes)
|
|
107
|
+
icon = html_attributes.delete(:icon)
|
|
108
|
+
html_attributes[:class] = [html_attributes[:class], "card-footer-item"].compact.join(" ")
|
|
109
|
+
a(href:, **html_attributes) do
|
|
110
|
+
if icon.nil?
|
|
111
|
+
plain text
|
|
112
|
+
else
|
|
113
|
+
icon_text(icon, text)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
104
118
|
def icon_text(icon, text)
|
|
105
119
|
span(class: "icon-text") do
|
|
106
120
|
span(class: "icon") { i(class: icon) }
|
|
@@ -9,6 +9,8 @@ module BulmaPhlex
|
|
|
9
9
|
# integrating with Bulma's column and grid systems. The form control content is set via the
|
|
10
10
|
# `control` method (or a block passed directly to the component).
|
|
11
11
|
#
|
|
12
|
+
# If the label is passes as a string argument, the any additional html attributes can also be included as arguments.
|
|
13
|
+
#
|
|
12
14
|
# ## References
|
|
13
15
|
#
|
|
14
16
|
# - [Bulma Form Field](https://bulma.io/documentation/form/general/#form-field)
|
|
@@ -46,8 +48,9 @@ module BulmaPhlex
|
|
|
46
48
|
#
|
|
47
49
|
# Optionally expects a block that renders a custom label (e.g. with a link or icon inside).
|
|
48
50
|
# Only one of `label_string` or a block should be provided.
|
|
49
|
-
def label(label_string = nil, &block)
|
|
51
|
+
def label(label_string = nil, **html_attributes, &block)
|
|
50
52
|
@label_string = label_string
|
|
53
|
+
@label_attributes = html_attributes
|
|
51
54
|
@label_builder = block
|
|
52
55
|
end
|
|
53
56
|
|
|
@@ -103,7 +106,7 @@ module BulmaPhlex
|
|
|
103
106
|
|
|
104
107
|
def render_label
|
|
105
108
|
if @label_string
|
|
106
|
-
html_label(class: "label") { @label_string }
|
|
109
|
+
html_label(**mix({ class: "label" }, **@label_attributes)) { @label_string }
|
|
107
110
|
elsif @label_builder
|
|
108
111
|
raw @label_builder&.call
|
|
109
112
|
end
|
data/lib/bulma_phlex/hero.rb
CHANGED
|
@@ -3,9 +3,16 @@
|
|
|
3
3
|
module BulmaPhlex
|
|
4
4
|
# Renders a [Bulma Hero](https://bulma.io/documentation/layout/hero/) component.
|
|
5
5
|
#
|
|
6
|
-
# Supports **color** and **size** options.
|
|
7
|
-
#
|
|
8
|
-
#
|
|
6
|
+
# Supports **color** and **size** options. There are three ways to provide content:
|
|
7
|
+
#
|
|
8
|
+
# 1. **Title/subtitle params** — pass `title:` and/or `subtitle:` to the constructor; no block needed.
|
|
9
|
+
# 2. **Direct body block** — pass a block to `render`; call Phlex HTML methods on the yielded
|
|
10
|
+
# component and they are rendered inside the `hero-body` div.
|
|
11
|
+
# 3. **Building blocks** — call `head`, `body`, and `foot` on the yielded component to
|
|
12
|
+
# populate each of Bulma's three hero regions independently:
|
|
13
|
+
# - `hero-head` — typically a navbar or branding bar
|
|
14
|
+
# - `hero-body` — main content area
|
|
15
|
+
# - `hero-foot` — bottom tabs or action bar
|
|
9
16
|
class Hero < BulmaPhlex::Base
|
|
10
17
|
# **Parameters**
|
|
11
18
|
#
|
|
@@ -42,16 +49,16 @@ module BulmaPhlex
|
|
|
42
49
|
output = capture(&)
|
|
43
50
|
|
|
44
51
|
section(**mix({ class: hero_classes }, @html_attributes)) do
|
|
45
|
-
if @body.
|
|
46
|
-
building_blocks(&)
|
|
47
|
-
else
|
|
52
|
+
if @body.nil?
|
|
48
53
|
div(class: "hero-body") do
|
|
49
|
-
if output.
|
|
50
|
-
output
|
|
51
|
-
else
|
|
54
|
+
if output.empty?
|
|
52
55
|
title_and_subtitle
|
|
56
|
+
else
|
|
57
|
+
raw safe(output)
|
|
53
58
|
end
|
|
54
59
|
end
|
|
60
|
+
else
|
|
61
|
+
building_blocks(&)
|
|
55
62
|
end
|
|
56
63
|
end
|
|
57
64
|
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Renders a [Bulma message](https://bulma.io/documentation/components/message/) component with a
|
|
5
|
+
# header, optional delete button, and body.
|
|
6
|
+
#
|
|
7
|
+
# The component generates an `article` element and supports color and size options, as well as any
|
|
8
|
+
# additional html attributes.
|
|
9
|
+
class Message < BulmaPhlex::Base
|
|
10
|
+
# **Parameters**
|
|
11
|
+
#
|
|
12
|
+
# - `header_text` (positional, optional) — If not provided, the header will be skipped
|
|
13
|
+
# - `delete` — If `true`, includes a delete button to dismiss the message. Can also be a hash of HTML
|
|
14
|
+
# attributes for the button
|
|
15
|
+
# - `color` — Color of the notification (e.g. `"primary"`, `"info"`, `"danger"`)
|
|
16
|
+
# - `size` — `"small"`, `"normal"` (the default), `"medium"` or `"large"`
|
|
17
|
+
# - `**html_attributes` — Additional HTML attributes for the notification element
|
|
18
|
+
def self.new(header_text = nil, delete: nil, color: nil, size: nil, **html_attributes)
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(header_text = nil, delete: nil, color: nil, size: nil, **html_attributes)
|
|
23
|
+
@header_text = header_text
|
|
24
|
+
@delete = delete
|
|
25
|
+
@color = color
|
|
26
|
+
@size = size
|
|
27
|
+
@html_attributes = html_attributes
|
|
28
|
+
after_initialize
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def view_template(&)
|
|
32
|
+
vanish(&)
|
|
33
|
+
|
|
34
|
+
article(**mix({ class: message_classes }, **@html_attributes)) do
|
|
35
|
+
message_header unless @header_text.nil?
|
|
36
|
+
message_body(&)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# allows for easy customization
|
|
43
|
+
def after_initialize; end
|
|
44
|
+
|
|
45
|
+
def message_classes
|
|
46
|
+
classes = ["message"]
|
|
47
|
+
classes << "is-#{@color}" unless @color.nil?
|
|
48
|
+
classes << "is-#{@size}" if !@size.nil? && @size.to_s != "normal"
|
|
49
|
+
classes.join(" ")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def message_header
|
|
53
|
+
div(class: "message-header") do
|
|
54
|
+
p { @header_text }
|
|
55
|
+
delete_button if @delete
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def delete_button
|
|
60
|
+
button_attributes = { class: "delete", aria_label: "delete" }
|
|
61
|
+
button_attributes = mix(button_attributes, @delete) if @delete.is_a?(Hash)
|
|
62
|
+
button(**button_attributes)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def message_body(&)
|
|
66
|
+
div(class: "message-body", &)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -14,15 +14,17 @@ module BulmaPhlex
|
|
|
14
14
|
# - `color` — Color of the notification (e.g. `"primary"`, `"info"`, `"danger"`)
|
|
15
15
|
# - `mode` — Style mode: `"light"` or `"dark"`
|
|
16
16
|
# - `**html_attributes` — Additional HTML attributes for the notification element
|
|
17
|
-
def self.new(delete:
|
|
17
|
+
def self.new(delete: nil, color: nil, mode: nil, **html_attributes)
|
|
18
18
|
super
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def initialize(delete:
|
|
21
|
+
def initialize(delete: nil, color: nil, mode: nil, **html_attributes)
|
|
22
22
|
@delete = delete
|
|
23
23
|
@color = color
|
|
24
24
|
@mode = mode
|
|
25
25
|
@html_attributes = html_attributes
|
|
26
|
+
|
|
27
|
+
after_initialize
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def view_template(&)
|
|
@@ -36,10 +38,13 @@ module BulmaPhlex
|
|
|
36
38
|
|
|
37
39
|
private
|
|
38
40
|
|
|
41
|
+
# allows for easy customization
|
|
42
|
+
def after_initialize; end
|
|
43
|
+
|
|
39
44
|
def notification_classes
|
|
40
45
|
classes = ["notification"]
|
|
41
|
-
classes << "is-#{@color}"
|
|
42
|
-
classes << "is-#{@mode}"
|
|
46
|
+
classes << "is-#{@color}" unless @color.nil?
|
|
47
|
+
classes << "is-#{@mode}" unless @mode.nil?
|
|
43
48
|
classes.join(" ")
|
|
44
49
|
end
|
|
45
50
|
|
data/lib/bulma_phlex/table.rb
CHANGED
|
@@ -8,24 +8,42 @@ module BulmaPhlex
|
|
|
8
8
|
# (bordered, striped, hoverable) and **layout** options (narrow, fullwidth). An optional
|
|
9
9
|
# **pagination** control can be added to the table footer via the `paginate` method.
|
|
10
10
|
#
|
|
11
|
+
# The `tr` elements can be customized with the `row` method, which accepts static HTML attributes
|
|
12
|
+
# and/or a block that generates dynamic attributes based on the row data.
|
|
13
|
+
#
|
|
14
|
+
# To make the table responsive, use the `hidden` argument to hide certain columns on smaller
|
|
15
|
+
# screens. See the [Bulma documentation](https://bulma.io/documentation/helpers/visibility-helpers/#hide)
|
|
16
|
+
# for the full list, but the most common options are `hidden: "mobile"` and `hidden: "touch"`.
|
|
17
|
+
#
|
|
18
|
+
# The table supports any additional HTML attributes on the `<table>` element, such as `id` or `data-*`
|
|
19
|
+
# attributes, via the `**html_attributes` argument in the constructor.
|
|
20
|
+
#
|
|
11
21
|
# ## Example
|
|
12
22
|
#
|
|
13
23
|
# users = User.all
|
|
14
24
|
#
|
|
15
25
|
# render BulmaPhlex::Table.new(users) do |table|
|
|
16
|
-
# table.
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# table.
|
|
21
|
-
# user.email
|
|
22
|
-
# end
|
|
23
|
-
#
|
|
26
|
+
# table.row(class: "has-background-light") { |user| { id: "user-row-#{user.id}" } }
|
|
27
|
+
# table.column("Name", &:full_name)
|
|
28
|
+
# table.column("Email", hidden: "touch", &:email)
|
|
29
|
+
# table.date_column("Joined", hidden: "mobile", &:created_at, format: "%B %d, %Y")
|
|
30
|
+
# table.conditional_icon("Admin?", &:admin?)
|
|
24
31
|
# table.column "Actions" do |user|
|
|
25
32
|
# link_to "Edit", edit_user_path(user), class: "button is-small"
|
|
26
33
|
# end
|
|
27
34
|
# end
|
|
28
|
-
class Table < BulmaPhlex::Base
|
|
35
|
+
class Table < BulmaPhlex::Base # rubocop:disable Metrics/ClassLength
|
|
36
|
+
# Returns an array of CSS classes for the table based on the provided options.
|
|
37
|
+
def self.classes_for(bordered: false, striped: false, narrow: false, hoverable: false, fullwidth: false)
|
|
38
|
+
classes = ["table"]
|
|
39
|
+
classes << "is-bordered" if bordered
|
|
40
|
+
classes << "is-striped" if striped
|
|
41
|
+
classes << "is-narrow" if narrow
|
|
42
|
+
classes << "is-hoverable" if hoverable
|
|
43
|
+
classes << "is-fullwidth" if fullwidth
|
|
44
|
+
classes
|
|
45
|
+
end
|
|
46
|
+
|
|
29
47
|
# **Parameters**
|
|
30
48
|
#
|
|
31
49
|
# - `rows` — The collection of records to display in the table
|
|
@@ -53,11 +71,7 @@ module BulmaPhlex
|
|
|
53
71
|
fullwidth: false,
|
|
54
72
|
**html_attributes)
|
|
55
73
|
@rows = rows
|
|
56
|
-
@
|
|
57
|
-
@striped = striped
|
|
58
|
-
@narrow = narrow
|
|
59
|
-
@hoverable = hoverable
|
|
60
|
-
@fullwidth = fullwidth
|
|
74
|
+
@table_classes = self.class.classes_for(bordered:, striped:, narrow:, hoverable:, fullwidth:)
|
|
61
75
|
@html_attributes = html_attributes
|
|
62
76
|
@columns = []
|
|
63
77
|
end
|
|
@@ -65,19 +79,15 @@ module BulmaPhlex
|
|
|
65
79
|
def view_template(&)
|
|
66
80
|
vanish(&)
|
|
67
81
|
|
|
68
|
-
table(**mix({ class: table_classes }, @html_attributes)) do
|
|
82
|
+
table(**mix({ class: @table_classes }, @html_attributes)) do
|
|
69
83
|
thead do
|
|
70
|
-
@columns.each
|
|
71
|
-
table_header(column)
|
|
72
|
-
end
|
|
84
|
+
@columns.each { |column| table_header(column) }
|
|
73
85
|
end
|
|
74
86
|
|
|
75
87
|
tbody do
|
|
76
88
|
@rows.each do |row|
|
|
77
|
-
tr do
|
|
78
|
-
@columns.each
|
|
79
|
-
td(**column[:html_attributes]) { column[:content].call(row) }
|
|
80
|
-
end
|
|
89
|
+
tr(**table_row_html_attributes(row)) do
|
|
90
|
+
@columns.each { |column| table_data_cell(column, row) }
|
|
81
91
|
end
|
|
82
92
|
end
|
|
83
93
|
end
|
|
@@ -86,14 +96,19 @@ module BulmaPhlex
|
|
|
86
96
|
end
|
|
87
97
|
end
|
|
88
98
|
|
|
99
|
+
def row(**html_attributes, &attribute_builder)
|
|
100
|
+
@row_attributes = html_attributes
|
|
101
|
+
@row_attribute_builder = attribute_builder
|
|
102
|
+
end
|
|
103
|
+
|
|
89
104
|
# Adds a column to the table. Can be called multiple times to define all columns.
|
|
90
105
|
#
|
|
91
106
|
# - `header` — The column header text
|
|
92
107
|
# - `**html_attributes` — Additional HTML attributes for each `<td>` cell in this column
|
|
93
108
|
#
|
|
94
109
|
# Expects a block that receives each `row` object and returns the cell content.
|
|
95
|
-
def column(header, **html_attributes, &content)
|
|
96
|
-
@columns << { header:, html_attributes:, content: }
|
|
110
|
+
def column(header, hidden: false, **html_attributes, &content)
|
|
111
|
+
@columns << { header:, hidden:, html_attributes:, content: }
|
|
97
112
|
end
|
|
98
113
|
|
|
99
114
|
# Adds a date-formatted column to the table. Can be called multiple times.
|
|
@@ -103,8 +118,8 @@ module BulmaPhlex
|
|
|
103
118
|
# - `**html_attributes` — Additional HTML attributes for each `<td>` cell in this column
|
|
104
119
|
#
|
|
105
120
|
# Expects a block that receives each `row` object and returns a `Date` or `Time` value.
|
|
106
|
-
def date_column(header, format: "%Y-%m-%d", **html_attributes, &content)
|
|
107
|
-
column(header, **html_attributes) do |row|
|
|
121
|
+
def date_column(header, hidden: false, format: "%Y-%m-%d", **html_attributes, &content)
|
|
122
|
+
column(header, hidden:, **html_attributes) do |row|
|
|
108
123
|
content.call(row)&.strftime(format)
|
|
109
124
|
end
|
|
110
125
|
end
|
|
@@ -116,10 +131,10 @@ module BulmaPhlex
|
|
|
116
131
|
# - `**html_attributes` — Additional HTML attributes for each `<td>` cell in this column
|
|
117
132
|
#
|
|
118
133
|
# Expects a block that receives each `row` object and returns a truthy or falsy value.
|
|
119
|
-
def conditional_icon(header, icon_class: "fas fa-check", **html_attributes, &content)
|
|
134
|
+
def conditional_icon(header, hidden: false, icon_class: "fas fa-check", **html_attributes, &content)
|
|
120
135
|
html_attributes[:class] = [html_attributes[:class], "has-text-centered"].compact.join(" ")
|
|
121
136
|
|
|
122
|
-
column(header, **html_attributes) do |row|
|
|
137
|
+
column(header, hidden:, **html_attributes) do |row|
|
|
123
138
|
Icon(icon_class) if content.call(row)
|
|
124
139
|
end
|
|
125
140
|
end
|
|
@@ -134,35 +149,49 @@ module BulmaPhlex
|
|
|
134
149
|
|
|
135
150
|
private
|
|
136
151
|
|
|
137
|
-
def
|
|
138
|
-
|
|
139
|
-
classes << "is-bordered" if @bordered
|
|
140
|
-
classes << "is-striped" if @striped
|
|
141
|
-
classes << "is-narrow" if @narrow
|
|
142
|
-
classes << "is-hoverable" if @hoverable
|
|
143
|
-
classes << "is-fullwidth" if @fullwidth
|
|
144
|
-
classes
|
|
152
|
+
def table_header(column)
|
|
153
|
+
th(class: header_classes(column)) { column[:header] }
|
|
145
154
|
end
|
|
146
155
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
th(**attributes) { column[:header] }
|
|
156
|
+
def header_classes(column)
|
|
157
|
+
classes = []
|
|
158
|
+
classes << "is-hidden-#{column[:hidden]}" if column[:hidden]
|
|
159
|
+
classes << header_alignment(column[:html_attributes])
|
|
160
|
+
classes.compact
|
|
153
161
|
end
|
|
154
162
|
|
|
155
163
|
def header_alignment(html_attributes)
|
|
156
164
|
classes = html_attributes[:class]
|
|
157
165
|
return if classes.nil?
|
|
158
166
|
|
|
159
|
-
if classes
|
|
167
|
+
if classes.include?("has-text-right") || classes.include?("amount-display")
|
|
160
168
|
"has-text-right"
|
|
161
|
-
elsif classes
|
|
169
|
+
elsif classes.include?("has-text-centered")
|
|
162
170
|
"has-text-centered"
|
|
163
171
|
end
|
|
164
172
|
end
|
|
165
173
|
|
|
174
|
+
def table_row_html_attributes(row)
|
|
175
|
+
attributes = @row_attributes || {}
|
|
176
|
+
if @row_attribute_builder
|
|
177
|
+
dynamic_attributes = @row_attribute_builder.call(row) || {}
|
|
178
|
+
attributes = attributes.merge(dynamic_attributes)
|
|
179
|
+
end
|
|
180
|
+
attributes
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def table_data_cell(column, row)
|
|
184
|
+
td(**mix({ class: cell_classes(column) }, column[:html_attributes])) do
|
|
185
|
+
column[:content].call(row)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def cell_classes(column)
|
|
190
|
+
return unless column[:hidden]
|
|
191
|
+
|
|
192
|
+
"is-hidden-#{column[:hidden]}"
|
|
193
|
+
end
|
|
194
|
+
|
|
166
195
|
def pagination
|
|
167
196
|
return unless @path_builder
|
|
168
197
|
|
data/lib/bulma_phlex/tag.rb
CHANGED
|
@@ -32,7 +32,7 @@ module BulmaPhlex
|
|
|
32
32
|
def view_template
|
|
33
33
|
if @html_attributes.key?(:href)
|
|
34
34
|
a(class: tag_classes, **@html_attributes) { text_and_optional_delete_button }
|
|
35
|
-
elsif @options[:delete] ||
|
|
35
|
+
elsif @options[:delete] || !@html_attributes.dig(:data, :action).nil?
|
|
36
36
|
button(class: tag_classes, **@html_attributes) { text_and_optional_delete_button }
|
|
37
37
|
else
|
|
38
38
|
span(class: tag_classes, **@html_attributes) { plain @text }
|
|
@@ -51,9 +51,9 @@ module BulmaPhlex
|
|
|
51
51
|
|
|
52
52
|
def tag_classes
|
|
53
53
|
classes = ["tag"]
|
|
54
|
-
classes << "is-#{@options[:color]}"
|
|
54
|
+
classes << "is-#{@options[:color]}" unless @options[:color].nil?
|
|
55
55
|
classes << "is-#{@options[:light]} is-light" if @options[:light]
|
|
56
|
-
classes << "is-#{@options[:size]}"
|
|
56
|
+
classes << "is-#{@options[:size]}" unless @options[:size].nil?
|
|
57
57
|
classes << "is-rounded" if @options[:rounded]
|
|
58
58
|
classes.join(" ")
|
|
59
59
|
end
|
data/lib/bulma_phlex/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bulma-phlex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Todd Kummer
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-04-16 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: phlex
|
|
@@ -76,6 +76,7 @@ files:
|
|
|
76
76
|
- lib/bulma_phlex/hero.rb
|
|
77
77
|
- lib/bulma_phlex/icon.rb
|
|
78
78
|
- lib/bulma_phlex/level.rb
|
|
79
|
+
- lib/bulma_phlex/message.rb
|
|
79
80
|
- lib/bulma_phlex/modal.rb
|
|
80
81
|
- lib/bulma_phlex/navigation_bar.rb
|
|
81
82
|
- lib/bulma_phlex/navigation_bar_dropdown.rb
|
|
@@ -102,7 +103,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
102
103
|
requirements:
|
|
103
104
|
- - ">="
|
|
104
105
|
- !ruby/object:Gem::Version
|
|
105
|
-
version: 3.
|
|
106
|
+
version: '3.3'
|
|
106
107
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
108
|
requirements:
|
|
108
109
|
- - ">="
|