bs5 0.0.12 → 0.0.17

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/components/bs5/accordion_component.html.erb +4 -11
  4. data/app/components/bs5/accordion_component.rb +1 -0
  5. data/app/components/bs5/alert_component.html.erb +1 -1
  6. data/app/components/bs5/list_group_component.html.erb +17 -0
  7. data/app/components/bs5/list_group_component.rb +143 -0
  8. data/app/controllers/bs5/pages_controller.rb +11 -0
  9. data/app/helpers/bs5/components_helper.rb +11 -8
  10. data/app/service/bs5/collapse_service.rb +49 -0
  11. data/app/service/bs5/popover_service.rb +31 -0
  12. data/app/service/bs5/tooltip_service.rb +31 -0
  13. data/app/views/bs5/examples/accordion/default/_example.html.erb +1 -1
  14. data/app/views/bs5/examples/accordion/flush/_example.html.erb +1 -1
  15. data/app/views/bs5/examples/alert/additional_content/_example.html.erb +1 -1
  16. data/app/views/bs5/examples/alert/default/_example.html.erb +1 -1
  17. data/app/views/bs5/examples/alert/dismissable/_example.html.erb +1 -1
  18. data/app/views/bs5/examples/alert/style/_example.html.erb +1 -1
  19. data/app/views/bs5/examples/badge/default/_example.html.erb +1 -1
  20. data/app/views/bs5/examples/badge/pill/_example.html.erb +1 -1
  21. data/app/views/bs5/examples/badge/style/_example.html.erb +1 -1
  22. data/app/views/bs5/examples/breadcrumb/default/_example.html.erb +1 -1
  23. data/app/views/bs5/examples/buttons/button_tag/default/snippet.html.erb +6 -6
  24. data/app/views/bs5/examples/buttons/button_tag/outline/snippet.html.erb +9 -9
  25. data/app/views/bs5/examples/buttons/button_tag/size/large.html.erb +2 -2
  26. data/app/views/bs5/examples/buttons/button_tag/size/small.html.erb +2 -2
  27. data/app/views/bs5/examples/buttons/button_tag/style/snippet.html.erb +9 -9
  28. data/app/views/bs5/examples/close_button/default/_example.html.erb +1 -1
  29. data/app/views/bs5/examples/close_button/disabled/_example.html.erb +1 -1
  30. data/app/views/bs5/examples/close_button/white/_example.html.erb +1 -1
  31. data/app/views/bs5/examples/collapse/default/_example.html.erb +4 -0
  32. data/app/views/bs5/examples/collapse/default/multiple_targets.html.erb +21 -0
  33. data/app/views/bs5/examples/collapse/default/snippet.html.erb +9 -0
  34. data/app/views/bs5/examples/list_group/actionable/_example.html.erb +3 -0
  35. data/app/views/bs5/examples/list_group/actionable/button.html.erb +7 -0
  36. data/app/views/bs5/examples/list_group/actionable/snippet.html.erb +7 -0
  37. data/app/views/bs5/examples/list_group/active/_example.html.erb +2 -0
  38. data/app/views/bs5/examples/list_group/active/snippet.html.erb +7 -0
  39. data/app/views/bs5/examples/list_group/checkboxes_and_radios/_example.html.erb +3 -0
  40. data/app/views/bs5/examples/list_group/checkboxes_and_radios/default.html.erb +22 -0
  41. data/app/views/bs5/examples/list_group/checkboxes_and_radios/with_labels.html.erb +32 -0
  42. data/app/views/bs5/examples/list_group/custom_content/_example.html.erb +2 -0
  43. data/app/views/bs5/examples/list_group/custom_content/default.html.erb +32 -0
  44. data/app/views/bs5/examples/list_group/default/_example.html.erb +2 -0
  45. data/app/views/bs5/examples/list_group/default/snippet.html.erb +7 -0
  46. data/app/views/bs5/examples/list_group/disabled/_example.html.erb +2 -0
  47. data/app/views/bs5/examples/list_group/disabled/snippet.html.erb +7 -0
  48. data/app/views/bs5/examples/list_group/flush/_example.html.erb +2 -0
  49. data/app/views/bs5/examples/list_group/flush/snippet.html.erb +7 -0
  50. data/app/views/bs5/examples/list_group/horizontal/_example.html.erb +2 -0
  51. data/app/views/bs5/examples/list_group/horizontal/snippet.html.erb +30 -0
  52. data/app/views/bs5/examples/list_group/style/_example.html.erb +3 -0
  53. data/app/views/bs5/examples/list_group/style/actionable.html.erb +11 -0
  54. data/app/views/bs5/examples/list_group/style/default.html.erb +11 -0
  55. data/app/views/bs5/examples/list_group/with_badges/_example.html.erb +2 -0
  56. data/app/views/bs5/examples/list_group/with_badges/default.html.erb +14 -0
  57. data/app/views/bs5/examples/popovers/default/_example.html.erb +2 -0
  58. data/app/views/bs5/examples/popovers/default/snippet.html.erb +1 -0
  59. data/app/views/bs5/examples/popovers/disabled_elements/_example.html.erb +2 -0
  60. data/app/views/bs5/examples/popovers/disabled_elements/snippet.html.erb +3 -0
  61. data/app/views/bs5/examples/popovers/dismissable_on_next_click/_example.html.erb +2 -0
  62. data/app/views/bs5/examples/popovers/dismissable_on_next_click/snippet.html.erb +1 -0
  63. data/app/views/bs5/examples/popovers/four_directions/_example.html.erb +2 -0
  64. data/app/views/bs5/examples/popovers/four_directions/snippet.html.erb +7 -0
  65. data/app/views/bs5/examples/tooltips/default/_example.html.erb +1 -1
  66. data/app/views/bs5/pages/accordion.html.erb +3 -0
  67. data/app/views/bs5/{examples/_alert.html.erb → pages/alert.html.erb} +1 -1
  68. data/app/views/bs5/{examples/_badge.html.erb → pages/badge.html.erb} +1 -1
  69. data/app/views/bs5/pages/breadcrumb.html.erb +2 -0
  70. data/app/views/bs5/{examples/_buttons.html.erb → pages/buttons.html.erb} +3 -3
  71. data/app/views/bs5/{examples/_close_button.html.erb → pages/close_button.html.erb} +1 -1
  72. data/app/views/bs5/pages/collapse.html.erb +2 -0
  73. data/app/views/bs5/pages/list_group.html.erb +11 -0
  74. data/app/views/bs5/pages/popovers.html.erb +5 -0
  75. data/app/views/bs5/{examples/_tooltips.html.erb → pages/tooltips.html.erb} +1 -1
  76. data/app/views/layouts/bs5/application.html.erb +1 -0
  77. data/app/views/layouts/bs5/pages.html.erb +35 -0
  78. data/config/initializers/hash_refinement.rb +9 -0
  79. data/config/routes.rb +2 -2
  80. data/lib/bs5/version.rb +1 -1
  81. data/lib/generators/bs5/install/install_generator.rb +2 -1
  82. data/lib/generators/bs5/install/templates/bs5.js +11 -1
  83. metadata +68 -11
  84. data/app/controllers/bs5/examples_controller.rb +0 -9
  85. data/app/views/bs5/examples/_accordion.html.erb +0 -3
  86. data/app/views/bs5/examples/_breadcrumb.html.erb +0 -2
  87. data/app/views/bs5/examples/index.html.erb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74aab58d89e345e58ed93c1960217477600d6c0bb9c3e9af1dcb3b3542ec55f0
4
- data.tar.gz: 79c1ddc04689b15bb773de0b99751045f30ffb101acd8ed62e8d816263723f8d
3
+ metadata.gz: 22c6a9e55865f643c0c955fa134144831a0e1aa3d68f9487757a2406429707fd
4
+ data.tar.gz: 94f28cbdc41c9f5cc4a223779247521659d66b0ac82aa9756bc37cbb1f73c45c
5
5
  SHA512:
6
- metadata.gz: 623342435dddb84001b2d70dfd1abc6cf6088b278d2f7c8deb0b11793778fcfcb7e531f5e6c32dcb18865ce918d5bb7a209496577ae486e85304e0d98fc590f3
7
- data.tar.gz: ba822b14f63cce1ea2be57273aef6014618d1cdab09050a6e842ac8719bf68f7d40b5f04d8a27991f7905700fe35a30b75640d805460599242449b9b7d36cbf6
6
+ metadata.gz: 7b08a72d089dba1ac047006893c765deac278eb925c5ace940882708af292e306a5f69ee71062493d120a1bc3be347a729113d0cb4c486cf8bd899918b4c5247
7
+ data.tar.gz: bc39e72b8af466e92f006ce3833aa1610c294959bba9a4201d581fa4aa4839f2ec6fa841db203a6adee60c7dcffe5872697a87d9be3ee2f27014d21741de1354
data/README.md CHANGED
@@ -32,7 +32,7 @@ $ gem install bs5
32
32
 
33
33
  Run the following command to setup your project to use Bootstrap 5.
34
34
 
35
- $ rails generate bs5:install
35
+ $ bin/rails generate bs5:install
36
36
 
37
37
  ## Contributing
38
38
 
@@ -6,22 +6,15 @@
6
6
  id="<%= item.header_id %>"
7
7
  class="accordion-header"
8
8
  >
9
- <button
10
- class="<%= item.button_class %>"
11
- type="button"
12
- data-toggle="collapse"
13
- data-target="#<%= item.collapse_id %>"
14
- aria-expanded="true"
15
- aria-controls="<%= item.collapse_id %>"
16
- >
17
- <%= item.title %>
18
- </button>
9
+ <%= button_tag item.title,
10
+ bs5_collapse(target: "##{item.collapse_id}", expanded: !item.collapsed?)
11
+ .merge(type: :button, class: item.button_class) %>
19
12
  </h2>
20
13
  <div
21
14
  id="<%= item.collapse_id %>"
22
15
  class="<%= item.collapse_class %>"
23
16
  aria-labelledby="<%= item.header_id %>"
24
- data-parent="#<%= id %>"
17
+ data-bs-parent="#<%= id %>"
25
18
  >
26
19
  <div class="accordion-body">
27
20
  <%= item.content %>
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Bs5
4
4
  class AccordionComponent < ViewComponent::Base
5
+ include ComponentsHelper
5
6
  include ViewComponent::Slotable
6
7
 
7
8
  with_slot :item, collection: true, class_name: 'Item'
@@ -1,6 +1,6 @@
1
1
  <div class="<%= component_class %>" role="alert">
2
2
  <%= content %>
3
3
  <%- if is_dismissable %>
4
- <%= render Bs5::CloseButtonComponent.new(data: { dismiss: :alert }) %>
4
+ <%= render Bs5::CloseButtonComponent.new(data: { 'bs-dismiss': :alert }) %>
5
5
  <%- end %>
6
6
  </div>
@@ -0,0 +1,17 @@
1
+ <% if items.any? %>
2
+ <% if actionables? %>
3
+ <div class="<%= component_class %>">
4
+ <% items.each do |item| %>
5
+ <%= item.decorated_content %>
6
+ <% end %>
7
+ </div>
8
+ <% else %>
9
+ <ul class="<%= component_class %>">
10
+ <% items.each do |item| %>
11
+ <%= tag.li(**item.options) do %>
12
+ <%= item.content %>
13
+ <% end %>
14
+ <% end %>
15
+ </ul>
16
+ <% end %>
17
+ <% end %>
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class ListGroupComponent < ViewComponent::Base
5
+ CLASS_NAME_BASE = 'list-group'
6
+ CLASS_NAME_FLUSH = "#{CLASS_NAME_BASE}-flush"
7
+ CLASS_NAME_HORIZONTAL = "#{CLASS_NAME_BASE}-horizontal"
8
+
9
+ include ViewComponent::Slotable
10
+
11
+ with_slot :item, collection: true, class_name: 'Item'
12
+
13
+ def initialize(flush: false, horizontal: false)
14
+ @flush = flush
15
+ @horizontal = horizontal
16
+ end
17
+
18
+ private
19
+
20
+ def flush?
21
+ !!@flush
22
+ end
23
+
24
+ def actionables?
25
+ items.any?(&:actionable?)
26
+ end
27
+
28
+ def horizontal?
29
+ !!@horizontal
30
+ end
31
+
32
+ def component_class
33
+ class_names = [CLASS_NAME_BASE]
34
+ class_names << flush_class
35
+ class_names << horizontal_class
36
+ class_names.join(' ')
37
+ end
38
+
39
+ def flush_class
40
+ CLASS_NAME_FLUSH if flush?
41
+ end
42
+
43
+ def horizontal_class
44
+ return unless horizontal?
45
+
46
+ class_names = [CLASS_NAME_HORIZONTAL]
47
+ class_names << @horizontal if @horizontal.in?(%i[sm md lg xl xxl])
48
+ class_names.join('-')
49
+ end
50
+
51
+ class Item < ViewComponent::Slot
52
+ CLASS_NAME_BASE = 'list-group-item'
53
+ CLASS_NAME_ACTION = "#{CLASS_NAME_BASE}-action"
54
+
55
+ attr_reader :options
56
+
57
+ def initialize(options = {})
58
+ @options = options.symbolize_keys
59
+
60
+ @active = @options.delete(:active) || false
61
+ @disabled = @options.delete(:disabled) || false
62
+ @style = @options.delete(:style)
63
+
64
+ set_attributes
65
+ end
66
+
67
+ def actionable?
68
+ !!actionable_element
69
+ end
70
+
71
+ def actionable_element
72
+ @actionable_element ||= begin
73
+ if (elements = Nokogiri::HTML::DocumentFragment.parse(content).elements).one? &&
74
+ (element = elements.first).name.in?(%w[a button label])
75
+ element
76
+ end
77
+ end
78
+ end
79
+
80
+ def decorated_content
81
+ set_actionable_element_attributes
82
+ actionable_element.to_html.html_safe # rubocop:disable Rails/OutputSafety
83
+ end
84
+
85
+ private
86
+
87
+ def set_actionable_element_class_names
88
+ class_names = Array(actionable_element[:class])
89
+ class_names << item_classes
90
+ class_names << CLASS_NAME_ACTION if actionable_element.name.in?(%w[a button])
91
+ actionable_element[:class] = class_names.join(' ')
92
+ end
93
+
94
+ def set_actionable_element_attributes
95
+ set_actionable_element_class_names
96
+ actionable_element['aria-current'] = true if active?
97
+
98
+ return unless disabled?
99
+
100
+ case actionable_element.name
101
+ when 'a'
102
+ actionable_element['aria-disabled'] = true
103
+ actionable_element['tabindex'] = -1
104
+ when 'button'
105
+ actionable_element['disabled'] = ''
106
+ end
107
+ end
108
+
109
+ def set_attributes
110
+ @options[:class] = Array(@options[:class])
111
+ @options[:class] << item_classes
112
+ @options[:aria] ||= {}
113
+ @options[:aria][:current] = true if active?
114
+ @options[:aria][:disabled] = true if disabled?
115
+ end
116
+
117
+ def item_classes
118
+ class_names = [CLASS_NAME_BASE]
119
+ class_names << 'active' if active?
120
+ class_names << 'disabled' if disabled?
121
+ class_names << contextual_class if style?
122
+
123
+ class_names
124
+ end
125
+
126
+ def active?
127
+ !!@active
128
+ end
129
+
130
+ def disabled?
131
+ !!@disabled
132
+ end
133
+
134
+ def style?
135
+ !!@style
136
+ end
137
+
138
+ def contextual_class
139
+ [CLASS_NAME_BASE, @style].join('-')
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'bs5/application_controller'
4
+
5
+ module Bs5
6
+ class PagesController < ApplicationController
7
+ def show
8
+ render template: "bs5/pages/#{params[:page]}"
9
+ end
10
+ end
11
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bs5
4
4
  module ComponentsHelper
5
- COMPONENTS = %w[accordion alert badge close_button breadcrumb button_tag button_to].freeze
5
+ COMPONENTS = %w[accordion alert badge close_button breadcrumb button_tag button_to list_group].freeze
6
6
 
7
7
  COMPONENTS.each do |name|
8
8
  define_method("bs5_#{name}") do |*args, &block|
@@ -11,13 +11,16 @@ module Bs5
11
11
  end
12
12
  end
13
13
 
14
- def bs5_tooltip(title, options = nil)
15
- default_options = { toggle: :tooltip }
16
- options = Hash(options).symbolize_keys.merge(default_options)
17
- {
18
- title: title,
19
- data: options
20
- }
14
+ def bs5_tooltip(*args)
15
+ TooltipService.new(*args).to_hash
16
+ end
17
+
18
+ def bs5_popover(*args)
19
+ PopoverService.new(*args).to_hash
20
+ end
21
+
22
+ def bs5_collapse(*args)
23
+ CollapseService.new(*args).to_hash
21
24
  end
22
25
 
23
26
  private
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class CollapseService
5
+ using HashRefinement
6
+
7
+ CONTROLS_ERR_MSG = 'Please provide either a `controls` option' \
8
+ ' containing the id of the collapsible element' \
9
+ ' or an ID selector as `target` options.'
10
+
11
+ attr_reader :expanded, :target, :controls
12
+
13
+ def initialize(expanded: false, target: nil, controls: nil)
14
+ @expanded = expanded
15
+ @target = target
16
+ @controls = controls
17
+ end
18
+
19
+ def to_hash
20
+ {
21
+ data: data_options,
22
+ aria: aria_options
23
+ }
24
+ end
25
+
26
+ private
27
+
28
+ def data_options
29
+ options = { toggle: :collapse }
30
+ options[:target] = target if target
31
+
32
+ options.prefix_keys_with_bs
33
+ end
34
+
35
+ def aria_options
36
+ options = { expanded: expanded }
37
+
38
+ if controls
39
+ options[:controls] = controls
40
+ elsif target&.start_with?('#')
41
+ options[:controls] = target.delete_prefix('#')
42
+ else
43
+ raise CONTROLS_ERR_MSG
44
+ end
45
+
46
+ options
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class PopoverService
5
+ using HashRefinement
6
+
7
+ attr_reader :title
8
+
9
+ def initialize(options = {})
10
+ @title = options.delete(:title)
11
+ @options = options
12
+ end
13
+
14
+ def to_hash
15
+ {
16
+ title: title,
17
+ data: options
18
+ }.compact
19
+ end
20
+
21
+ private
22
+
23
+ def options
24
+ @options.symbolize_keys.merge(default_options).prefix_keys_with_bs
25
+ end
26
+
27
+ def default_options
28
+ { toggle: :popover }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class TooltipService
5
+ using HashRefinement
6
+
7
+ attr_reader :title
8
+
9
+ def initialize(title, options = {})
10
+ @title = title
11
+ @options = options
12
+ end
13
+
14
+ def to_hash
15
+ {
16
+ title: title,
17
+ data: options
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ def options
24
+ @options.symbolize_keys.merge(default_options).prefix_keys_with_bs
25
+ end
26
+
27
+ def default_options
28
+ { toggle: :tooltip }
29
+ end
30
+ end
31
+ end
@@ -1,2 +1,2 @@
1
- <h3>Default</h3>
1
+ <h2>Example</h2>
2
2
  <%= bs5_example(snippet: 'accordion/default/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Flush</h3>
1
+ <h2>Flush</h2>
2
2
  <%= bs5_example(snippet: 'accordion/flush/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Additional content</h3>
1
+ <h2>Additional content</h2>
2
2
  <%= bs5_example(snippet: 'alert/additional_content/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Default</h3>
1
+ <h2>Examples</h2>
2
2
  <%= bs5_example(snippet: 'alert/default/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Dismissing</h3>
1
+ <h2>Dismissing</h2>
2
2
  <%= bs5_example(snippet: 'alert/dismissable/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Style</h3>
1
+ <h2>Style</h2>
2
2
  <%= bs5_example(snippet: 'alert/style/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Example</h3>
1
+ <h2>Example</h2>
2
2
  <%= bs5_example(snippet: 'badge/default/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Pill badges</h3>
1
+ <h2>Pill badges</h2>
2
2
  <%= bs5_example(snippet: 'badge/pill/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Background colors</h3>
1
+ <h2>Background colors</h2>
2
2
  <%= bs5_example(snippet: 'badge/style/snippet') %>
@@ -1,2 +1,2 @@
1
- <h3>Example</h3>
1
+ <h2>Example</h2>
2
2
  <%= bs5_example(snippet: 'breadcrumb/default/snippet') %>
@@ -1,15 +1,15 @@
1
1
  <%= bs5_button_tag %>
2
2
 
3
- <%= bs5_button_tag 'Reset', type: 'reset' %>
3
+ <%= bs5_button_tag('Reset', type: 'reset') %>
4
4
 
5
- <%= bs5_button_tag 'Button', type: 'button' %>
5
+ <%= bs5_button_tag('Button', type: 'button') %>
6
6
 
7
- <%= bs5_button_tag 'Reset', type: 'reset', disabled: true %>
7
+ <%= bs5_button_tag('Reset', type: 'reset', disabled: true) %>
8
8
 
9
9
  <%= bs5_button_tag(type: 'button') do %>
10
- <%= content_tag(:strong, 'Ask me!') %>
10
+ <%= tag.strong('Ask me!') %>
11
11
  <% end %>
12
12
 
13
- <%= bs5_button_tag 'Save', data: { confirm: 'Are you sure?' } %>
13
+ <%= bs5_button_tag('Save', data: { confirm: 'Are you sure?' }) %>
14
14
 
15
- <%= bs5_button_tag 'Checkout', data: { disable_with: 'Please wait...' } %>
15
+ <%= bs5_button_tag('Checkout', data: { disable_with: 'Please wait...' }) %>