bulma-phlex 0.1.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 +7 -0
- data/README.md +176 -0
- data/Rakefile +12 -0
- data/lib/bulma-phlex.rb +14 -0
- data/lib/bulma_phlex/version.rb +5 -0
- data/lib/components/bulma/base.rb +20 -0
- data/lib/components/bulma/card.rb +58 -0
- data/lib/components/bulma/level.rb +69 -0
- data/lib/components/bulma/navigation_bar.rb +95 -0
- data/lib/components/bulma/navigation_bar_dropdown.rb +46 -0
- data/lib/components/bulma/pagination.rb +123 -0
- data/lib/components/bulma/table.rb +104 -0
- data/lib/components/bulma/tabs.rb +78 -0
- data/lib/components/bulma.rb +13 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 66aad611632ef1e130fd898e589c7a5c6548673f3bad6efcc9c0fd3e3ee35931
|
4
|
+
data.tar.gz: 665413567403f62d159300df558a62f15aad11ef254e963a75904ea72b77ed67
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f1e1684e053b1d1fc0fd3f2b0013f448f317ce764f544be465ab48e3b474f491cfe9080c45164262d0389657511429ec5d6396a0f4cb8b2887dad122a7b83ec0
|
7
|
+
data.tar.gz: 0a5ffbaf9f9a703b70b304f7d66b9b44789326ce270d84fdbca0da4739a3c29acd38c5f40eeb5647061d2d2854895cd9e3f6888a4160d69ac48e0bfafa19c97d
|
data/README.md
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
[](https://badge.fury.io/rb/bulma-phlex)
|
2
|
+
[](https://github.com/RockSolt/bulma-phlex/actions/workflows/test.yml)
|
3
|
+
[](https://github.com/RockSolt/bulma-phlex/actions/workflows/rubocop.yml)
|
4
|
+
|
5
|
+
# Bulma Components Built with Phlex
|
6
|
+
|
7
|
+
This gem provides a set of ready-to-use components [Phlex](https://github.com/phlex-ruby/phlex) for common [Bulma](https://bulma.io/) components and elements, making it easy to build beautiful, responsive interfaces with a clean, Ruby-focused API.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "bulma-phlex"
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
bundle install
|
21
|
+
```
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
gem install bulma-phlex
|
27
|
+
```
|
28
|
+
|
29
|
+
### Dependencies
|
30
|
+
|
31
|
+
This gem requires:
|
32
|
+
|
33
|
+
- Ruby 3.4 or higher
|
34
|
+
- Phlex 2.0.2 or higher
|
35
|
+
- Bulma CSS (which you'll need to include in your application)
|
36
|
+
|
37
|
+
### Required Setup
|
38
|
+
|
39
|
+
1. Include Bulma CSS in your application. You can add it via npm/yarn, CDN, or the [bulma-rails](https://github.com/joshuajansen/bulma-rails) gem.
|
40
|
+
|
41
|
+
2. Require the gem in your code:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require "bulma-phlex"
|
45
|
+
```
|
46
|
+
|
47
|
+
|
48
|
+
## Usage
|
49
|
+
|
50
|
+
Use the Phlex components in your Rails views or any Ruby application that supports Phlex components.
|
51
|
+
|
52
|
+
### Card
|
53
|
+
|
54
|
+
[Cards](https://bulma.io/documentation/components/card/) are flexible containers that can display various types of content including headers and content sections.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
render Components::Bulma::Card.new do |card|
|
58
|
+
card.head("Card Title")
|
59
|
+
card.content do
|
60
|
+
"This is some card content"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
### Level
|
66
|
+
|
67
|
+
The [Level](https://bulma.io/documentation/layout/level/) component provides a flexible horizontal layout system with left and right alignment.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
render Components::Bulma::Level.new do |level|
|
71
|
+
level.left do
|
72
|
+
button(class: "button") { "Left" }
|
73
|
+
end
|
74
|
+
|
75
|
+
level.right do
|
76
|
+
button(class: "button") { "Right" }
|
77
|
+
end
|
78
|
+
level.right do
|
79
|
+
button(class: "button") { "Right 2" }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
### NavigationBar
|
85
|
+
|
86
|
+
The [NavigationBar](https://bulma.io/documentation/components/navbar/) component provides a responsive navigation header with support for branding, navigation links, and dropdown menus.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
render Components::Bulma::NavigationBar.new do |navbar|
|
90
|
+
navbar.brand_item "My App", "/"
|
91
|
+
|
92
|
+
navbar.left do |menu|
|
93
|
+
menu.item "Home", "/"
|
94
|
+
menu.item "Products", "/products"
|
95
|
+
end
|
96
|
+
|
97
|
+
navbar.right do |menu|
|
98
|
+
menu.item "About", "/about"
|
99
|
+
menu.dropdown "Account" do |dropdown|
|
100
|
+
dropdown.header "User"
|
101
|
+
dropdown.item "Profile", "/profile"
|
102
|
+
dropdown.item "Settings", "/settings"
|
103
|
+
dropdown.divider
|
104
|
+
dropdown.item "Sign Out", "/logout"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
### Pagination
|
111
|
+
|
112
|
+
The [Pagination](https://bulma.io/documentation/components/pagination/) component provides navigation controls for paginated content, including previous/next links, page number links, and a summary of items being displayed.
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
# In a controller action:
|
116
|
+
@products = Product.page(params[:page]).per(20)
|
117
|
+
|
118
|
+
# In the view:
|
119
|
+
render Components::Bulma::Pagination.new(@products, ->(page) { products_path(page: page) })
|
120
|
+
```
|
121
|
+
|
122
|
+
### Table
|
123
|
+
|
124
|
+
The [Table](https://bulma.io/documentation/elements/table/) component provides a way to display data in rows and columns with customizable headers and formatting options.
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
users = User.all
|
128
|
+
|
129
|
+
render Components::Bulma::Table.new(users) do |table|
|
130
|
+
table.column "Name" do |user|
|
131
|
+
user.full_name
|
132
|
+
end
|
133
|
+
|
134
|
+
table.column "Email" do |user|
|
135
|
+
user.email
|
136
|
+
end
|
137
|
+
|
138
|
+
table.column "Actions" do |user|
|
139
|
+
link_to "Edit", edit_user_path(user), class: "button is-small"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
### Tabs
|
145
|
+
|
146
|
+
The [Tabs](https://bulma.io/documentation/components/tabs/) component provides a way to toggle between different content sections using tabbed navigation, with support for icons and active state management.
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
render Components::Bulma::Tabs.new do |tabs|
|
150
|
+
tabs.tab(id: "profile", title: "Profile", active: true) do
|
151
|
+
"Profile content goes here"
|
152
|
+
end
|
153
|
+
|
154
|
+
tabs.tab(id: "settings", title: "Settings", icon: "fas fa-cog") do
|
155
|
+
"Settings content goes here"
|
156
|
+
end
|
157
|
+
|
158
|
+
tabs.tab(id: "notifications", title: "Notifications", icon: "fas fa-bell") do
|
159
|
+
"Notifications content goes here"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
## Development
|
165
|
+
|
166
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
167
|
+
|
168
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
169
|
+
|
170
|
+
## Contributing
|
171
|
+
|
172
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/RockSolt/bulma-phlex.
|
173
|
+
|
174
|
+
## License
|
175
|
+
|
176
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/lib/bulma-phlex.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "phlex"
|
4
|
+
require "bulma_phlex/version"
|
5
|
+
|
6
|
+
require "components/bulma"
|
7
|
+
require "components/bulma/base"
|
8
|
+
require "components/bulma/card"
|
9
|
+
require "components/bulma/level"
|
10
|
+
require "components/bulma/navigation_bar_dropdown"
|
11
|
+
require "components/bulma/navigation_bar"
|
12
|
+
require "components/bulma/pagination"
|
13
|
+
require "components/bulma/table"
|
14
|
+
require "components/bulma/tabs"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Base component for all Bulma components
|
6
|
+
#
|
7
|
+
# This is the parent class for all Bulma components in this library.
|
8
|
+
# It provides common utility methods and inherits from `Phlex::HTML`.
|
9
|
+
#
|
10
|
+
class Base < Phlex::HTML
|
11
|
+
private
|
12
|
+
|
13
|
+
def icon_span(icon, additional_classes = nil)
|
14
|
+
span(class: "icon #{additional_classes}".strip) do
|
15
|
+
i(class: icon)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Card component for content display
|
6
|
+
#
|
7
|
+
# This component implements the [Bulma card](https://bulma.io/documentation/components/card/)
|
8
|
+
# interface. Cards are flexible containers that can display various types of content
|
9
|
+
# including headers, content sections, and more.
|
10
|
+
#
|
11
|
+
# ## Example
|
12
|
+
#
|
13
|
+
# ```ruby
|
14
|
+
# render Components::Bulma::Card.new do |card|
|
15
|
+
# card.head("Card Title")
|
16
|
+
# card.content do
|
17
|
+
# "This is some card content"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# ```
|
21
|
+
#
|
22
|
+
class Card < Components::Bulma::Base
|
23
|
+
def view_template(&)
|
24
|
+
div(class: "card", &)
|
25
|
+
end
|
26
|
+
|
27
|
+
def head(title, classes: nil)
|
28
|
+
header(class: "card-header #{classes}") do
|
29
|
+
p(class: "card-header-title") { plain title }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def content(&)
|
34
|
+
div(class: "card-content") do
|
35
|
+
div(class: "content", &)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
if defined?(Phlex::Rails)
|
40
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
41
|
+
|
42
|
+
# this copies the signature of the turbo_frame_tag helper,
|
43
|
+
# with the addition of a pending_message attribute
|
44
|
+
def turbo_frame_content(*ids, src: nil, target: nil, **attributes)
|
45
|
+
pending_message = attributes.delete(:pending_message) || "Loading..."
|
46
|
+
pending_icon = attributes.delete(:pending_icon) || "fas fa-spinner fa-pulse"
|
47
|
+
|
48
|
+
content do
|
49
|
+
turbo_frame_tag ids, src: src, target: target, **attributes do
|
50
|
+
span(class: "icon") { i class: pending_icon }
|
51
|
+
span { plain pending_message }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Level component for responsive horizontal layouts
|
6
|
+
#
|
7
|
+
# This component implements the [Bulma level](https://bulma.io/documentation/layout/level/)
|
8
|
+
# interface, providing a flexible horizontal layout system with left and right alignment.
|
9
|
+
#
|
10
|
+
# ## Example:
|
11
|
+
#
|
12
|
+
# ```ruby
|
13
|
+
# render Components::Bulma::Level.new do |level|
|
14
|
+
# level.left do
|
15
|
+
# button(class: "button") { "Left" }
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# level.right do
|
19
|
+
# button(class: "button") { "Right" }
|
20
|
+
# end
|
21
|
+
# level.right do
|
22
|
+
# button(class: "button") { "Right 2" }
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# ```
|
26
|
+
#
|
27
|
+
class Level < Components::Bulma::Base
|
28
|
+
def initialize
|
29
|
+
@items = []
|
30
|
+
@left = []
|
31
|
+
@right = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def view_template(&)
|
35
|
+
vanish(&)
|
36
|
+
|
37
|
+
div(class: "level") do
|
38
|
+
div(class: "level-left") do
|
39
|
+
@left.each { level_item(it) }
|
40
|
+
end
|
41
|
+
|
42
|
+
@items.each { level_item(it) }
|
43
|
+
|
44
|
+
div(class: "level-right") do
|
45
|
+
@right.each { level_item(it) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def item(&content)
|
51
|
+
@items << content
|
52
|
+
end
|
53
|
+
|
54
|
+
def left(&content)
|
55
|
+
@left << content
|
56
|
+
end
|
57
|
+
|
58
|
+
def right(&content)
|
59
|
+
@right << content
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def level_item(content)
|
65
|
+
div(class: "level-item") { content.call }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Navigation bar component for site navigation
|
6
|
+
#
|
7
|
+
# This component implements the [Bulma navbar](https://bulma.io/documentation/components/navbar/)
|
8
|
+
# interface. It provides a responsive navigation header with support for branding, navigation
|
9
|
+
# links, and dropdown menus, automatically collapsing on mobile devices.
|
10
|
+
#
|
11
|
+
# ## Example
|
12
|
+
#
|
13
|
+
# ```ruby
|
14
|
+
# render Components::Bulma::NavigationBar.new do |navbar|
|
15
|
+
# navbar.brand do
|
16
|
+
# a(href: "/", class: "navbar-item") { "My App" }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# navbar.left do
|
20
|
+
# a(href: "/", class: "navbar-item") { "Home" }
|
21
|
+
# a(href: "/products", class: "navbar-item") { "Products" }
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# navbar.right do
|
25
|
+
# a(href: "/about", class: "navbar-item") { "About" }
|
26
|
+
#
|
27
|
+
# div(class: "navbar-item has-dropdown is-hoverable") do
|
28
|
+
# a(class: "navbar-link") { "Account" }
|
29
|
+
# render Components::Bulma::NavigationBarDropdown do |dropdown|
|
30
|
+
# dropdown.item "Sign In", "/login"
|
31
|
+
# dropdown.item "Register", "/register"
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# ```
|
37
|
+
#
|
38
|
+
class NavigationBar < Components::Bulma::Base
|
39
|
+
def initialize
|
40
|
+
@brand = []
|
41
|
+
@left = []
|
42
|
+
@right = []
|
43
|
+
end
|
44
|
+
|
45
|
+
def view_template(&)
|
46
|
+
vanish(&)
|
47
|
+
|
48
|
+
nav(class: "navbar is-light block",
|
49
|
+
role: "navigation",
|
50
|
+
aria_label: "main navigation",
|
51
|
+
data: { controller: "bulma--navigation-bar" }) do
|
52
|
+
div(class: "container") do
|
53
|
+
div(class: "navbar-brand") do
|
54
|
+
@brand.each(&:call)
|
55
|
+
|
56
|
+
a(class: "navbar-burger",
|
57
|
+
role: "button",
|
58
|
+
aria_label: "menu",
|
59
|
+
aria_expanded: "false",
|
60
|
+
data: {
|
61
|
+
action: "bulma--navigation-bar#toggle",
|
62
|
+
"bulma--navigation-bar-target": "burger"
|
63
|
+
}) do
|
64
|
+
4.times { span(aria_hidden: "true") }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
div(class: "navbar-menu",
|
69
|
+
data: { "bulma--navigation-bar-target": "menu" }) do
|
70
|
+
div(class: "navbar-start") do
|
71
|
+
@left.each(&:call)
|
72
|
+
end
|
73
|
+
|
74
|
+
div(class: "navbar-end") do
|
75
|
+
@right.each(&:call)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def brand(&block)
|
83
|
+
@brand << block
|
84
|
+
end
|
85
|
+
|
86
|
+
def left(&block)
|
87
|
+
@left << block
|
88
|
+
end
|
89
|
+
|
90
|
+
def right(&block)
|
91
|
+
@right << block
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Dropdown component for the Bulma navigation bar
|
6
|
+
#
|
7
|
+
# This component implements the dropdown portion of the [Bulma navbar](https://bulma.io/documentation/components/navbar/#dropdown-menu).
|
8
|
+
# It provides a structured way to add dropdown menus to a navigation bar with headers, items, and dividers.
|
9
|
+
#
|
10
|
+
# ## Example
|
11
|
+
#
|
12
|
+
# ```ruby
|
13
|
+
# render Components::Bulma::NavigationBar.new do |navbar|
|
14
|
+
# navbar.brand_item "My App", "/"
|
15
|
+
#
|
16
|
+
# navbar.right do |menu|
|
17
|
+
# menu.dropdown "Account" do |dropdown|
|
18
|
+
# dropdown.header "User"
|
19
|
+
# dropdown.item "Profile", "/profile"
|
20
|
+
# dropdown.item "Settings", "/settings"
|
21
|
+
# dropdown.divider
|
22
|
+
# dropdown.item "Sign Out", "/logout"
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# ```
|
27
|
+
#
|
28
|
+
class NavigationBarDropdown < Components::Bulma::Base
|
29
|
+
def view_template(&)
|
30
|
+
div(class: "navbar-dropdown is-right", &)
|
31
|
+
end
|
32
|
+
|
33
|
+
def header(label)
|
34
|
+
div(class: "navbar-item header has-text-weight-medium") { label }
|
35
|
+
end
|
36
|
+
|
37
|
+
def item(label, path)
|
38
|
+
a(class: "navbar-item", href: path) { label }
|
39
|
+
end
|
40
|
+
|
41
|
+
def divider
|
42
|
+
hr(class: "navbar-divider")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Pagination component for navigating through multi-page content
|
6
|
+
#
|
7
|
+
# This component implements the [Bulma pagination](https://bulma.io/documentation/components/pagination/)
|
8
|
+
# interface, providing navigation controls for paginated content. It shows:
|
9
|
+
# - Previous/next page links
|
10
|
+
# - First/last page links when appropriate
|
11
|
+
# - Current page indicator
|
12
|
+
# - Ellipses for skipped page ranges
|
13
|
+
# - Summary of items being displayed
|
14
|
+
#
|
15
|
+
# ## Example
|
16
|
+
#
|
17
|
+
# ```ruby
|
18
|
+
# # In a controller action:
|
19
|
+
# @products = Product.page(params[:page]).per(20)
|
20
|
+
#
|
21
|
+
# # In the view:
|
22
|
+
# render Components::Bulma::Pagination.new(@products, ->(page) { products_path(page: page) })
|
23
|
+
# ```
|
24
|
+
#
|
25
|
+
class Pagination < Components::Bulma::Base
|
26
|
+
attr_reader :pager, :path_builder
|
27
|
+
|
28
|
+
# Initializes the pagination component
|
29
|
+
#
|
30
|
+
# @param pager [Object] An object that responds to:
|
31
|
+
# - `current_page` - Integer representing the current page number
|
32
|
+
# - `total_pages` - Integer representing the total number of pages
|
33
|
+
# - `per_page` - Integer representing the number of items per page
|
34
|
+
# - `total_count` - Integer representing the total number of items
|
35
|
+
# - `previous_page` - Integer or nil representing the previous page number
|
36
|
+
# - `next_page` - Integer or nil representing the next page number
|
37
|
+
# @param path_builder [Proc] A callable that takes a page number and returns a URL string
|
38
|
+
def initialize(pager, path_builder)
|
39
|
+
@pager = pager
|
40
|
+
@path_builder = path_builder
|
41
|
+
end
|
42
|
+
|
43
|
+
def view_template
|
44
|
+
return unless pager.total_pages > 1
|
45
|
+
|
46
|
+
div(class: "pagination-container mt-5") do
|
47
|
+
nav(class: "pagination", role: "navigation", aria_label: "pagination") do
|
48
|
+
# Previous page link
|
49
|
+
if pager.previous_page
|
50
|
+
a(class: "pagination-previous", href: page_url(pager.previous_page)) { "Previous" }
|
51
|
+
else
|
52
|
+
a(class: "pagination-previous", disabled: true) { "Previous" }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Next page link
|
56
|
+
if pager.next_page
|
57
|
+
a(class: "pagination-next", href: page_url(pager.next_page)) { "Next" }
|
58
|
+
else
|
59
|
+
a(class: "pagination-next", disabled: true) { "Next" }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Page number links
|
63
|
+
ul(class: "pagination-list") do
|
64
|
+
# First page and ellipsis if needed
|
65
|
+
if pager.current_page > 3
|
66
|
+
render_page_item(1)
|
67
|
+
render_ellipsis if pager.current_page > 4
|
68
|
+
end
|
69
|
+
|
70
|
+
# Pages around current page
|
71
|
+
page_window.each do |page_number|
|
72
|
+
render_page_item(page_number)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Ellipsis and last page if needed
|
76
|
+
if pager.current_page < pager.total_pages - 2
|
77
|
+
render_ellipsis if pager.current_page < pager.total_pages - 3
|
78
|
+
render_page_item(pager.total_pages)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
div(class: "has-text-centered mt-2 is-size-7") do
|
84
|
+
start_item = ((pager.current_page - 1) * pager.per_page) + 1
|
85
|
+
end_item = [start_item + pager.per_page - 1, pager.total_count].min
|
86
|
+
|
87
|
+
plain "Showing #{start_item}-#{end_item} of #{pager.total_count} items"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def render_page_item(page_number)
|
95
|
+
li do
|
96
|
+
if page_number == pager.current_page
|
97
|
+
a(class: "pagination-link is-current",
|
98
|
+
aria_label: "Page #{page_number}",
|
99
|
+
aria_current: "page") { page_number.to_s }
|
100
|
+
else
|
101
|
+
a(class: "pagination-link",
|
102
|
+
href: page_url(page_number),
|
103
|
+
aria_label: "Go to page #{page_number}") { page_number.to_s }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def render_ellipsis
|
109
|
+
li { span(class: "pagination-ellipsis") { "…" } }
|
110
|
+
end
|
111
|
+
|
112
|
+
def page_window
|
113
|
+
start_page = [pager.current_page - 2, 1].max
|
114
|
+
end_page = [pager.current_page + 2, pager.total_pages].min
|
115
|
+
(start_page..end_page).to_a
|
116
|
+
end
|
117
|
+
|
118
|
+
def page_url(page_number)
|
119
|
+
@path_builder.call(page_number)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Table component for data display
|
6
|
+
#
|
7
|
+
# This component implements the [Bulma table](https://bulma.io/documentation/elements/table/)
|
8
|
+
# interface, providing a way to display data in rows and columns with customizable
|
9
|
+
# headers and formatting options.
|
10
|
+
#
|
11
|
+
# ## Example
|
12
|
+
#
|
13
|
+
# ```ruby
|
14
|
+
# users = User.all
|
15
|
+
#
|
16
|
+
# render Components::Bulma::Table.new(users) do |table|
|
17
|
+
# table.column "Name" do |user|
|
18
|
+
# user.full_name
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# table.column "Email" do |user|
|
22
|
+
# user.email
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# table.column "Actions" do |user|
|
26
|
+
# link_to "Edit", edit_user_path(user), class: "button is-small"
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# ```
|
30
|
+
#
|
31
|
+
class Table < Components::Bulma::Base
|
32
|
+
def initialize(rows, id = nil)
|
33
|
+
@id = id || rows.first&.model_name&.plural
|
34
|
+
@rows = rows
|
35
|
+
@columns = []
|
36
|
+
end
|
37
|
+
|
38
|
+
def view_template(&)
|
39
|
+
vanish(&)
|
40
|
+
|
41
|
+
table(id: @id, class: "table is-fullwidth") do
|
42
|
+
thead do
|
43
|
+
@columns.each do |column|
|
44
|
+
table_header(column)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
tbody do
|
49
|
+
@rows.each do |row|
|
50
|
+
tr do
|
51
|
+
@columns.each do |column|
|
52
|
+
td(**column[:html_attributes]) { column[:content].call(row) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
pagination
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def column(header, **html_attributes, &content)
|
63
|
+
@columns << { header:, html_attributes:, content: }
|
64
|
+
end
|
65
|
+
|
66
|
+
def paginate(&path_builder)
|
67
|
+
@path_builder = path_builder
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# this derives a th class from the column html attributes
|
73
|
+
# perhaps a better way would be pre-defined pairs?
|
74
|
+
def table_header(column)
|
75
|
+
attributes = {}
|
76
|
+
attributes[:class] = header_alignment(column[:html_attributes])
|
77
|
+
th(**attributes) { column[:header] }
|
78
|
+
end
|
79
|
+
|
80
|
+
def header_alignment(html_attributes)
|
81
|
+
classes = html_attributes[:class]
|
82
|
+
return if classes.nil?
|
83
|
+
|
84
|
+
if classes&.include?("has-text-right") || classes&.include?("amount-display")
|
85
|
+
"has-text-right"
|
86
|
+
elsif classes&.include?("has-text-centered")
|
87
|
+
"has-text-centered"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def pagination
|
92
|
+
return unless @path_builder
|
93
|
+
|
94
|
+
tfoot do
|
95
|
+
tr do
|
96
|
+
td(class: "py-0", colspan: @columns.size) do
|
97
|
+
Pagination(@rows, @path_builder)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
# Tabs component for toggling between different content sections
|
6
|
+
#
|
7
|
+
# This component implements the [Bulma tabs](https://bulma.io/documentation/components/tabs/)
|
8
|
+
# interface, providing a way to toggle between different content sections using
|
9
|
+
# tabbed navigation. Includes support for icons and active state management.
|
10
|
+
#
|
11
|
+
# ## Example
|
12
|
+
#
|
13
|
+
# ```ruby
|
14
|
+
# render Components::Bulma::Tabs.new do |tabs|
|
15
|
+
# tabs.tab(id: "profile", title: "Profile", active: true) do
|
16
|
+
# "Profile content goes here"
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# tabs.tab(id: "settings", title: "Settings", icon: "fas fa-cog") do
|
20
|
+
# "Settings content goes here"
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# tabs.tab(id: "notifications", title: "Notifications", icon: "fas fa-bell") do
|
24
|
+
# "Notifications content goes here"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# ```
|
28
|
+
#
|
29
|
+
class Tabs < Components::Bulma::Base
|
30
|
+
Tab = Data.define(:id, :title, :icon, :active)
|
31
|
+
Content = Data.define(:id, :block, :active)
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@tabs = []
|
35
|
+
@contents = []
|
36
|
+
end
|
37
|
+
|
38
|
+
def tab(id:, title:, icon: nil, active: false, &block)
|
39
|
+
@tabs << Tab.new(id:, title:, icon:, active:)
|
40
|
+
@contents << Content.new(id:, block:, active:)
|
41
|
+
end
|
42
|
+
|
43
|
+
def view_template(&)
|
44
|
+
vanish(&)
|
45
|
+
|
46
|
+
div(data: { controller: "tabs" }) do
|
47
|
+
div(class: "tabs is-boxed") do
|
48
|
+
ul do
|
49
|
+
@tabs.each do |tab|
|
50
|
+
li(
|
51
|
+
data: {
|
52
|
+
tabs_target: "tab",
|
53
|
+
tab_content: tab.id,
|
54
|
+
action: "click->tabs#showTabContent"
|
55
|
+
},
|
56
|
+
class: tab.active ? "is-active" : ""
|
57
|
+
) do
|
58
|
+
a do
|
59
|
+
icon_span(tab.icon, "mr-1") if tab.icon
|
60
|
+
span { tab.title }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
@contents.each do |content|
|
68
|
+
div(id: content.id,
|
69
|
+
class: content.active ? "" : "hidden",
|
70
|
+
data: { tabs_target: "content" }) do
|
71
|
+
content.block.call
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A collection of Bulma components built with Phlex
|
4
|
+
#
|
5
|
+
# This module provides a set of components that implement the [Bulma CSS framework](https://bulma.io/)
|
6
|
+
# using the Phlex view component library. These components make it easy to build
|
7
|
+
# Bulma-styled applications with a Ruby-focused component API.
|
8
|
+
#
|
9
|
+
module Components
|
10
|
+
module Bulma
|
11
|
+
extend Phlex::Kit
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bulma-phlex
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Todd Kummer
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: phlex
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 2.0.2
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 2.0.2
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: actionpack
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
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
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: minitest-difftastic
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
description: Add Bulma components including Card, Level, NavigationBar, Pagination,
|
83
|
+
Table, and Tabs to your Phlex application.
|
84
|
+
email:
|
85
|
+
- todd@rockridgesolutions.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- lib/bulma-phlex.rb
|
93
|
+
- lib/bulma_phlex/version.rb
|
94
|
+
- lib/components/bulma.rb
|
95
|
+
- lib/components/bulma/base.rb
|
96
|
+
- lib/components/bulma/card.rb
|
97
|
+
- lib/components/bulma/level.rb
|
98
|
+
- lib/components/bulma/navigation_bar.rb
|
99
|
+
- lib/components/bulma/navigation_bar_dropdown.rb
|
100
|
+
- lib/components/bulma/pagination.rb
|
101
|
+
- lib/components/bulma/table.rb
|
102
|
+
- lib/components/bulma/tabs.rb
|
103
|
+
homepage: https://github.com/RockSolt/bulma-phlex
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata:
|
107
|
+
rubygems_mfa_required: 'true'
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 3.4.0
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubygems_version: 3.6.7
|
123
|
+
specification_version: 4
|
124
|
+
summary: Build Bulma components with Phlex.
|
125
|
+
test_files: []
|