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.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BulmaPhlex
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.0"
5
5
  end
@@ -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 component API.
8
- #
9
- module Components
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.7.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/rails/card_helper.rb
94
- - lib/bulma_phlex/rails/table_helper.rb
95
- - lib/bulma_phlex/railtie.rb
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