bs5_expandable_list_group 0.4.0 → 0.5.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.
Files changed (21) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +69 -10
  3. data/app/components/bs5/expandable_list/group_component.html.erb +9 -0
  4. data/app/components/bs5/expandable_list/group_component.rb +43 -0
  5. data/app/components/bs5/expandable_list/group_item_component.html.erb +15 -0
  6. data/app/components/bs5/expandable_list/group_item_component.rb +100 -0
  7. data/app/components/bs5/{expandable_list_item_header_actions_component.html.erb → expandable_list/group_item_header/actions_component.html.erb} +1 -1
  8. data/app/components/bs5/expandable_list/group_item_header/actions_component.rb +18 -0
  9. data/app/components/bs5/{expandable_list_item_header_title_component.html.erb → expandable_list/group_item_header/title_component.html.erb} +2 -2
  10. data/app/components/bs5/expandable_list/group_item_header/title_component.rb +27 -0
  11. data/app/helpers/bs5_expandable_list_group/view_components_helper.rb +7 -1
  12. data/lib/bs5_expandable_list_group/version.rb +1 -1
  13. data/lib/generators/bs5_expandable_list_group/install/templates/controllers/stretchable_item_controller.js +1 -2
  14. data/lib/generators/bs5_expandable_list_group/install/templates/stylesheets/_expandable-items.scss +15 -7
  15. metadata +10 -10
  16. data/app/components/bs5/expandable_list_group_component.html.erb +0 -5
  17. data/app/components/bs5/expandable_list_group_component.rb +0 -41
  18. data/app/components/bs5/expandable_list_item_component.html.erb +0 -15
  19. data/app/components/bs5/expandable_list_item_component.rb +0 -74
  20. data/app/components/bs5/expandable_list_item_header_actions_component.rb +0 -14
  21. data/app/components/bs5/expandable_list_item_header_title_component.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb85128dd2e5cbcfadab803722f3641dc1f899d48f7648967790c4c07167e53e
4
- data.tar.gz: 7e35116c8fd0739e75387b65d99b071d68b4b99de79df9aeb2b538e37a94e9e9
3
+ metadata.gz: d0fe287158fb9bd8dc214ab834588e700e6a1c87c13410afa2761f6200a34dc8
4
+ data.tar.gz: 20e7875417d6b574f86c92e6c70595cad7cfd555ebbbde4f68e9c7bdf082d661
5
5
  SHA512:
6
- metadata.gz: 2020c90cf7b667d478018ed5d508b58167f28303f82bb79e9fb36010499e1e54e5e1bed16c13ce9408b7813363baad4a46322b250d232be895166e0c26eb41e8
7
- data.tar.gz: 0b380cdc5f32d767177cb16e2bd72b7df0088f41b23eb706591654d37dfd96bd8c035b11a4ea2f6175bc0c04238d4140521d6dd8f42815027a9b37fdd3856351
6
+ metadata.gz: 9ae2e083544567258691eb1a6d0b60b4c43de0bc7c9bbe4dbabb98d46e9df9c7d06c67b9febbd2daa156bee4a863a63f1a1e05fa31649ab11f960867ebd22fe7
7
+ data.tar.gz: 80aee9b9c941a123cde3190788c6d1e528ea65aff3eea285197edddb3627818ae8f86ab3daeb8cf0d1da5f5ba833caa779dad6a7a9eca090cfcef48c7f51bbbf
data/README.md CHANGED
@@ -66,7 +66,7 @@ Stylesheets are copied to `app/javascript/stylesheets`. If needed, you can add t
66
66
 
67
67
  ## Usage
68
68
 
69
- To render a **Bootstrap 5 expandable list group** you use `render(Bs5::ExpandableListGroupComponent.new)` and pass it a block for rendering every list item.
69
+ To render a **Bootstrap 5 expandable list group** you use `bs5_expandable_list_group` and pass it a block for rendering every list item.
70
70
 
71
71
  Given that you have assigned a list of `Post` instances to `@posts`, to render these `@posts` in a **Bootstrap 5 expandable list group**, you put the following code in your template:
72
72
 
@@ -160,7 +160,25 @@ To show a different set on hovering:
160
160
  <% end %>
161
161
  ```
162
162
 
163
- ### Omitting the `item` methods
163
+ #### Bypassing the hover behaviour
164
+
165
+ By default, when an item is collapsed, actions only show when you hover your mouse over the item. Since we use the `visibility` CSS property for this, you can bypass this behaviour one or more actions by setting its `visibility` property to `visible`. The following example uses the [`visible` utility](https://getbootstrap.com/docs/5.0/utilities/visibility/) from Bootstrap 5, but of course you can also use CSS:
166
+
167
+ ```erb
168
+ ...
169
+ <% c.item do |i| %>
170
+ <%= i.title do |t| %>
171
+ ...
172
+ <% end %>
173
+ <% i.actions do |a| %>
174
+ <%= link_to 'Not so important link', ... %>
175
+ <%= link_to 'Very important link', ..., class: 'visible` %>
176
+ <% end %>
177
+ <%= i.body { ... } %>
178
+ <% end %>
179
+ ```
180
+
181
+ ### Omitting the `item`'s methods
164
182
 
165
183
  Instead of using the `item`'s methods `title`, `body` and/or `actions` you can just use (HTML-) text as a block.
166
184
  This will render just a [list group item](https://getbootstrap.com/docs/5.0/components/list-group/#basic-example), but will come in handy when you, i.e. show the first 25 items of a longer list and want to present a "Load more" link as last item of the list (for simplicity sake the sample uses a non-working `link_to_next_page` although this is [part of Kaminari](https://github.com/kaminari/kaminari#the-link_to_next_page-and-link_to_previous_page-aliased-to-link_to_prev_page-helper-methods)):
@@ -181,9 +199,49 @@ This will render just a [list group item](https://getbootstrap.com/docs/5.0/comp
181
199
  <% end %>
182
200
  ```
183
201
 
202
+ ### Omitting the `item`
203
+
204
+ Instead of calling the `item` method on the yielded component, when you pass a block, it's rendered wrapped in the container element:
205
+
206
+ ```erb
207
+ <%= bs5_expandable_list_group do %>
208
+ <%= render @posts %>
209
+ <% end %>
210
+ ```
211
+
212
+ This will give you the same results as wrapping the posts in a `div` with the class **list-group**, but you can still pass other options to the `bs5_expandable_list_group` (although not all of them will be effective).
213
+
214
+ ### Rendering a single item
215
+
216
+ By calling the `item` method on the passed component you can render an item. But this can also be achieved outside the block by using the `bs5_expandable_list_group_item` helper method. The following snippet has the same result as other examples, but it does not use the `bs5_expandable_list_group` method:
217
+
218
+ ```erb
219
+ <div id="posts" class="list-group">
220
+ <% @posts.each do |post| %>
221
+ <% bs5_expandable_list_group_item(parent_id: 'posts') do |i| %>
222
+ <%= i.title { post.title } %>
223
+ <%= i.body { post.text } %>
224
+ <% end %>
225
+ <% end %>
226
+ </div>
227
+ ```
228
+
229
+ An application for rendering a single item is when you want to update an item without doing a full page reload by sending a response that contains only the list item and use JavaScript or (preferably) [Turbo](https://turbo.hotwire.dev/) to update the page.
230
+
231
+ #### Passing options
232
+
233
+ The following options can be passed to `bs5_expandable_list_group_item`:
234
+
235
+ | name | default | description |
236
+ |---|---|---|
237
+ | `tag` | `:div` | A symbol or string of a valid HTML tag that is used for the tag of the list item. |
238
+ | `parent_id` | | ID of a parent element to add accordion-like behaviour. |
239
+ | `stretchable` | `false` | Expanded items are shown a little bit bigger as if they come out a bit. |
240
+
241
+
184
242
  ### Wrap an item in an extra element
185
243
 
186
- Every list item is a `div` with one or more CSS classes and, dependent on block passed, some `data` attributes and is not customizable (yet).
244
+ Every list item is a `div` (or the element specified with `tag`) with one or more CSS classes and, dependent on block passed, some `data` attributes.
187
245
  However, you can wrap a list item in a extra element by passing a `wrapper_html` option to the `item` method:
188
246
 
189
247
  ```erb
@@ -205,20 +263,21 @@ All options passed to the item method are used as HTML attributes of the wrapper
205
263
 
206
264
  ### Passing options
207
265
 
208
- The following options can be passed to `Bs5::ExpandableListGroupComponent.new`:
266
+ The following options can be passed to `bs5_expandable_list_group`:
209
267
 
210
268
  | name | default | description |
211
269
  |---|---|---|
212
- | `tag` | `:div` | A symbol or string of a valid HTML tag that is used for the tag of the list group |
213
- | `id` | | is used to assign an id HTML attribute to the rendered container |
214
- | `class` | | is added to the class attribute of the rendered container |
215
- | `accordion` | `false` | Behaves as an Bootstrap [accordion](https://getbootstrap.com/docs/5.0/components/accordion/) by having only 1 item expanded |
216
- | `expandable` | `false` | Expanded items are shown a little bit bigger as if they come out a bit|
270
+ | `tag` | `:div` | A symbol or string of a valid HTML tag that is used for the tag of the list group. |
271
+ | `id` | | is used to assign an id HTML attribute to the rendered container. |
272
+ | `class` | | is added to the class attribute of the rendered container. |
273
+ | `accordion` | `false` | Behaves as an Bootstrap [accordion](https://getbootstrap.com/docs/5.0/components/accordion/) by having only 1 item expanded (only effective when used with `item` in the passed block). |
274
+ | `stretchable` | `false` | Expanded items are shown a little bit bigger as if they come out a bit. |
275
+ | `expanded` | `false` | Show the item expanded. |
217
276
 
218
277
  Example:
219
278
 
220
279
  ```erb
221
- <%= bs5_expandable_list_group(accordion: true, expandable: true) do |c| %>
280
+ <%= bs5_expandable_list_group(accordion: true, stretchable: true) do |c| %>
222
281
  ...
223
282
  <% end %>
224
283
  ```
@@ -0,0 +1,9 @@
1
+ <%= tag.send(tag_name, **component_attributes) do %>
2
+ <% if items.any? %>
3
+ <% items.each do |item| %>
4
+ <%= item %>
5
+ <% end %>
6
+ <% else %>
7
+ <%= content %>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ class GroupComponent < ViewComponent::Base
6
+ renders_many :items, lambda { |options = {}|
7
+ options.merge!(parent_id: id, stretchable: stretchable?)
8
+ GroupItemComponent.new(**options)
9
+ }
10
+
11
+ attr_reader :options, :is_accordion, :is_stretchable, :tag_name
12
+
13
+ DEFAULT_TAG_NAME = :div
14
+
15
+ def initialize(options = {})
16
+ @is_accordion = options.delete(:accordion)
17
+ @is_stretchable = options.delete(:stretchable)
18
+ @id = options.delete(:id)
19
+ @tag_name = options.delete(:tag) || DEFAULT_TAG_NAME
20
+ @options = options
21
+ end
22
+
23
+ private
24
+
25
+ def id
26
+ @id || (accordion? && "list-group-#{object_id}")
27
+ end
28
+
29
+ def component_class
30
+ ['list-group'].tap do |arr|
31
+ arr << @options[:class]
32
+ end
33
+ end
34
+
35
+ def component_attributes
36
+ options.merge(id: id, class: component_class)
37
+ end
38
+
39
+ alias accordion? is_accordion
40
+ alias stretchable? is_stretchable
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ <%= wrapper do %>
2
+ <% if simple_content? %>
3
+ <%= tag.send(tag_name, content, **component_attributes) %>
4
+ <% else %>
5
+ <%= tag.send(tag_name, **component_attributes) do %>
6
+ <div class="expandable-item-header">
7
+ <%= title %>
8
+ <%= actions %>
9
+ </div>
10
+ <%= tag.div(id: target_id, class: body_class, data: body_data_options) do %>
11
+ <%= body %>
12
+ <% end %>
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ class GroupItemComponent < ViewComponent::Base
6
+ DEFAULT_WRAPPER_TAG = :div
7
+ DEFAULT_TAG_NAME = :div
8
+ renders_one :title, lambda {
9
+ GroupItemHeader::TitleComponent.new(target_id: target_id, expanded: expanded?)
10
+ }
11
+ renders_one :actions, GroupItemHeader::ActionsComponent
12
+ renders_one :body
13
+
14
+ attr_reader :parent_id, :is_stretchable, :is_expanded, :tag_name, :wrapper_html, :options
15
+
16
+ def initialize(options = {})
17
+ @parent_id = options.delete(:parent_id)
18
+ @is_stretchable = options.delete(:stretchable)
19
+ @is_expanded = options.delete(:expanded)
20
+ @tag_name = options.delete(:tag) || DEFAULT_TAG_NAME
21
+ @wrapper_html = options.delete(:wrapper_html)
22
+ @options = options
23
+ end
24
+
25
+ private
26
+
27
+ def wrapper_html?
28
+ @wrapper_html.present?
29
+ end
30
+
31
+ def wrapper_tag
32
+ @wrapper_html.delete(:tag) || DEFAULT_WRAPPER_TAG
33
+ end
34
+
35
+ def wrapper(&block)
36
+ if wrapper_html?
37
+ tag.send(wrapper_tag, **wrapper_html, &block)
38
+ else
39
+ capture { block.call }
40
+ end
41
+ end
42
+
43
+ def simple_content?
44
+ title.blank? && body.blank? && actions.blank?
45
+ end
46
+
47
+ def target_id
48
+ "expandable-list-item-#{object_id}"
49
+ end
50
+
51
+ def body_data_options
52
+ {}.tap do |h|
53
+ h['bs-parent'] = "##{parent_id}" if parent_id
54
+ end
55
+ end
56
+
57
+ def component_data_options
58
+ {}.tap do |h|
59
+ h.merge!(stimulus_attributes) if stretchable?
60
+ end
61
+ end
62
+
63
+ def component_class
64
+ ['list-group-item'].tap do |arr|
65
+ arr << 'expandable-item' unless simple_content?
66
+ arr << 'stretchable-item'
67
+ arr << 'stretched' if !simple_content? && expanded?
68
+ end
69
+ end
70
+
71
+ def body_class
72
+ %w[expandable-item-body collapse].tap do |arr|
73
+ arr << 'show' if expanded?
74
+ end
75
+ end
76
+
77
+ def component_attributes
78
+ options.tap do |h|
79
+ h[:class] = component_class
80
+ h[:data] = component_data_options unless simple_content?
81
+ end
82
+ end
83
+
84
+ def stimulus_attributes
85
+ {
86
+ controller: stimulus_controller,
87
+ "#{stimulus_controller}-target": 'container',
88
+ "#{stimulus_controller}-stretched-class": 'stretched'
89
+ }
90
+ end
91
+
92
+ def stimulus_controller
93
+ 'stretchable-item'
94
+ end
95
+
96
+ alias stretchable? is_stretchable
97
+ alias expanded? is_expanded
98
+ end
99
+ end
100
+ end
@@ -1,6 +1,6 @@
1
1
  <div class="expandable-item-header-actions">
2
2
  <% if variable_actions? %>
3
- <%= tag.div(class: "expandable-item-header-actions-collaped") do %>
3
+ <%= tag.div(class: "expandable-item-header-actions-collapsed") do %>
4
4
  <%= collapsed %>
5
5
  <% end %>
6
6
  <%= tag.div(class: "expandable-item-header-actions-expanded") do %>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ module GroupItemHeader
6
+ class ActionsComponent < ViewComponent::Base
7
+ renders_one :collapsed
8
+ renders_one :expanded
9
+
10
+ private
11
+
12
+ def variable_actions?
13
+ collapsed || expanded
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
- <%= tag.div(class: "expandable-item-header-title", data: { "bs-toggle": :collapse, "bs-target": "##{target_id}" } ) do %>
1
+ <%= tag.div(class: "expandable-item-header-title", data: { "bs-toggle": :collapse, "bs-target": "##{target_id}" }, aria: { expanded: expanded? } ) do %>
2
2
  <% if variable_title? %>
3
- <%= tag.div(class: "expandable-item-header-title-collaped") do %>
3
+ <%= tag.div(class: "expandable-item-header-title-collapsed") do %>
4
4
  <%= collapsed %>
5
5
  <% end %>
6
6
  <%= tag.div(class: "expandable-item-header-title-expanded") do %>
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ module GroupItemHeader
6
+ class TitleComponent < ViewComponent::Base
7
+ renders_one :collapsed
8
+ renders_one :expanded
9
+
10
+ attr_reader :target_id, :is_expanded
11
+
12
+ def initialize(target_id:, expanded: false)
13
+ @target_id = target_id
14
+ @is_expanded = expanded
15
+ end
16
+
17
+ private
18
+
19
+ def variable_title?
20
+ collapsed || expanded
21
+ end
22
+
23
+ alias expanded? is_expanded
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,7 +1,13 @@
1
1
  module Bs5ExpandableListGroup
2
2
  module ViewComponentsHelper
3
3
  def bs5_expandable_list_group(*args)
4
- render ::Bs5::ExpandableListGroupComponent.new(*args) do |c|
4
+ render ::Bs5::ExpandableList::GroupComponent.new(*args) do |c|
5
+ yield c if block_given?
6
+ end
7
+ end
8
+
9
+ def bs5_expandable_list_group_item(*args)
10
+ render ::Bs5::ExpandableList::GroupItemComponent.new(*args) do |c|
5
11
  yield c if block_given?
6
12
  end
7
13
  end
@@ -1,3 +1,3 @@
1
1
  module Bs5ExpandableListGroup
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -5,7 +5,7 @@ const HIDE_EVENT = "hide.bs.collapse";
5
5
 
6
6
  export default class extends Controller {
7
7
  static targets = ["container"];
8
- static classes = ["item", "stretched"];
8
+ static classes = ["stretched"];
9
9
 
10
10
  initialize() {
11
11
  this.onShow = this._onShow.bind(this);
@@ -14,7 +14,6 @@ export default class extends Controller {
14
14
  }
15
15
 
16
16
  connect() {
17
- this.containerTarget.classList.add(this.itemClass);
18
17
  this.contentNode.addEventListener(SHOW_EVENT, this.onShow);
19
18
  this.contentNode.addEventListener(HIDE_EVENT, this.onHide);
20
19
  }
@@ -3,7 +3,14 @@
3
3
  position: relative;
4
4
  cursor: pointer;
5
5
 
6
- &-actions {
6
+ &-title-expanded {
7
+ position: absolute;
8
+ top: 0;
9
+ right: 0;
10
+ left: 0;
11
+ }
12
+
13
+ &-actions-collapsed, &-actions-expanded {
7
14
  position: absolute;
8
15
  top: 0;
9
16
  right: 0;
@@ -12,17 +19,18 @@
12
19
 
13
20
  &:hover &-header-actions,
14
21
  &-header-title[aria-expanded="true"] &-header-title-expanded,
15
- &-header-title:not([aria-expanded="true"]) &-header-title-collaped,
22
+ &-header-title:not([aria-expanded="true"]) &-header-title-collapsed,
16
23
  &-header-title[aria-expanded="true"] + &-header-actions,
17
- &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-expanded {
18
- display: revert;
24
+ &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-expanded,
25
+ &-header-actions :focus-within {
26
+ visibility: visible;
19
27
  }
20
28
 
21
29
  &-header &-header-actions,
22
- &-header-title[aria-expanded="true"] &-header-title-collaped,
30
+ &-header-title[aria-expanded="true"] &-header-title-collapsed,
23
31
  &-header-title:not([aria-expanded="true"]) &-header-title-expanded,
24
32
  &-header-actions-expanded,
25
- &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-collaped {
26
- display: none;
33
+ &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-collapsed {
34
+ visibility: hidden;
27
35
  }
28
36
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bs5_expandable_list_group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Baselier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-03 00:00:00.000000000 Z
11
+ date: 2021-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -100,14 +100,14 @@ files:
100
100
  - Rakefile
101
101
  - app/assets/config/bs5_expandable_list_group_manifest.js
102
102
  - app/assets/stylesheets/bs5_expandable_list_group/application.css
103
- - app/components/bs5/expandable_list_group_component.html.erb
104
- - app/components/bs5/expandable_list_group_component.rb
105
- - app/components/bs5/expandable_list_item_component.html.erb
106
- - app/components/bs5/expandable_list_item_component.rb
107
- - app/components/bs5/expandable_list_item_header_actions_component.html.erb
108
- - app/components/bs5/expandable_list_item_header_actions_component.rb
109
- - app/components/bs5/expandable_list_item_header_title_component.html.erb
110
- - app/components/bs5/expandable_list_item_header_title_component.rb
103
+ - app/components/bs5/expandable_list/group_component.html.erb
104
+ - app/components/bs5/expandable_list/group_component.rb
105
+ - app/components/bs5/expandable_list/group_item_component.html.erb
106
+ - app/components/bs5/expandable_list/group_item_component.rb
107
+ - app/components/bs5/expandable_list/group_item_header/actions_component.html.erb
108
+ - app/components/bs5/expandable_list/group_item_header/actions_component.rb
109
+ - app/components/bs5/expandable_list/group_item_header/title_component.html.erb
110
+ - app/components/bs5/expandable_list/group_item_header/title_component.rb
111
111
  - app/controllers/bs5_expandable_list_group/application_controller.rb
112
112
  - app/helpers/bs5_expandable_list_group/application_helper.rb
113
113
  - app/helpers/bs5_expandable_list_group/view_components_helper.rb
@@ -1,5 +0,0 @@
1
- <%= tag.send(tag_name, **component_attributes) do %>
2
- <% items.each do |item| %>
3
- <%= item %>
4
- <% end %>
5
- <% end %>
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListGroupComponent < ViewComponent::Base
5
- renders_many :items, lambda { |options = {}|
6
- options.merge!(parent_id: id, stretchable: stretchable?)
7
- ExpandableListItemComponent.new(**options)
8
- }
9
-
10
- attr_reader :options, :accordion, :stretchable, :tag_name
11
-
12
- DEFAULT_TAG_NAME = :div
13
-
14
- def initialize(options = {})
15
- @accordion = options.delete(:accordion)
16
- @stretchable = options.delete(:stretchable)
17
- @id = options.delete(:id)
18
- @tag_name = options.delete(:tag) || DEFAULT_TAG_NAME
19
- @options = options
20
- end
21
-
22
- private
23
-
24
- def id
25
- @id || (accordion? && "list-group-#{object_id}")
26
- end
27
-
28
- def component_class
29
- class_names = ['list-group']
30
- class_names << @options[:class]
31
- class_names
32
- end
33
-
34
- def component_attributes
35
- options.merge(id: id, class: component_class)
36
- end
37
-
38
- alias accordion? accordion
39
- alias stretchable? stretchable
40
- end
41
- end
@@ -1,15 +0,0 @@
1
- <%= wrapper do %>
2
- <% if simple_content? %>
3
- <%= tag.div(content, class: "list-group-item") %>
4
- <% else %>
5
- <%= tag.div(class: "list-group-item expandable-item", data: component_data_options) do %>
6
- <div class="expandable-item-header">
7
- <%= title %>
8
- <%= actions %>
9
- </div>
10
- <%= tag.div(id: target_id, class: "expandable-item-body collapse", data: body_data_options) do %>
11
- <%= body %>
12
- <% end %>
13
- <% end %>
14
- <% end %>
15
- <% end %>
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListItemComponent < ViewComponent::Base
5
- DEFAULT_WRAPPER_TAG = :div
6
- renders_one :title, lambda {
7
- ExpandableListItemHeaderTitleComponent.new(target_id: target_id)
8
- }
9
- renders_one :actions, ExpandableListItemHeaderActionsComponent
10
- renders_one :body
11
-
12
- attr_reader :parent_id, :stretchable, :wrapper_html
13
-
14
- def initialize(options = {})
15
- @parent_id = options.delete(:parent_id)
16
- @stretchable = options.delete(:stretchable)
17
- @wrapper_html = options.delete(:wrapper_html)
18
- @options = options
19
- end
20
-
21
- private
22
-
23
- def wrapper_html?
24
- @wrapper_html.present?
25
- end
26
-
27
- def wrapper_tag
28
- @wrapper_html.delete(:tag) || DEFAULT_WRAPPER_TAG
29
- end
30
-
31
- def wrapper(&block)
32
- if wrapper_html?
33
- tag.send(wrapper_tag, **wrapper_html, &block)
34
- else
35
- capture { block.call }
36
- end
37
- end
38
-
39
- def simple_content?
40
- title.blank? && body.blank? && actions.blank?
41
- end
42
-
43
- def target_id
44
- "expandable-list-item-#{object_id}"
45
- end
46
-
47
- def body_data_options
48
- {}.tap do |h|
49
- h['bs-parent'] = "##{parent_id}" if parent_id
50
- end
51
- end
52
-
53
- def component_data_options
54
- {}.tap do |h|
55
- h.merge!(stimulus_attributes) if stretchable?
56
- end
57
- end
58
-
59
- def stimulus_attributes
60
- {
61
- controller: stimulus_controller,
62
- "#{stimulus_controller}-target": 'container',
63
- "#{stimulus_controller}-item-class": 'stretchable-item',
64
- "#{stimulus_controller}-stretched-class": 'stretched'
65
- }
66
- end
67
-
68
- def stimulus_controller
69
- 'stretchable-item'
70
- end
71
-
72
- alias stretchable? stretchable
73
- end
74
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListItemHeaderActionsComponent < ViewComponent::Base
5
- renders_one :collapsed
6
- renders_one :expanded
7
-
8
- private
9
-
10
- def variable_actions?
11
- collapsed || expanded
12
- end
13
- end
14
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListItemHeaderTitleComponent < ViewComponent::Base
5
- renders_one :collapsed
6
- renders_one :expanded
7
-
8
- attr_reader :target_id
9
-
10
- def initialize(target_id:)
11
- @target_id = target_id
12
- end
13
-
14
- private
15
-
16
- def variable_title?
17
- collapsed || expanded
18
- end
19
- end
20
- end