bs5 0.0.17 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/bs5/accordion_component.html.erb +1 -1
  3. data/app/components/bs5/accordion_component.rb +7 -3
  4. data/app/components/bs5/alert_component.rb +5 -5
  5. data/app/components/bs5/badge_component.rb +6 -6
  6. data/app/components/bs5/breadcrumb_component.html.erb +1 -1
  7. data/app/components/bs5/breadcrumb_component.rb +6 -3
  8. data/app/components/bs5/button_group_component.html.erb +3 -0
  9. data/app/components/bs5/button_group_component.rb +49 -0
  10. data/app/components/bs5/button_tag_component.rb +8 -8
  11. data/app/components/bs5/button_to_component.rb +8 -8
  12. data/app/components/bs5/button_toolbar_component.html.erb +3 -0
  13. data/app/components/bs5/button_toolbar_component.rb +21 -0
  14. data/app/components/bs5/list_group_component.html.erb +2 -2
  15. data/app/components/bs5/list_group_component.rb +16 -9
  16. data/app/components/bs5/spinner_component.html.erb +5 -0
  17. data/app/components/bs5/spinner_component.rb +65 -0
  18. data/app/helpers/bs5/components_helper.rb +2 -1
  19. data/app/views/bs5/examples/accordion/default/snippet.html.erb +4 -4
  20. data/app/views/bs5/examples/accordion/flush/snippet.html.erb +4 -4
  21. data/app/views/bs5/examples/alert/additional_content/snippet.html.erb +1 -1
  22. data/app/views/bs5/examples/alert/color/_example.html.erb +1 -0
  23. data/app/views/bs5/examples/alert/{style → color}/snippet.html.erb +8 -8
  24. data/app/views/bs5/examples/alert/dismissable/snippet.html.erb +1 -1
  25. data/app/views/bs5/examples/badge/color/_example.html.erb +2 -0
  26. data/app/views/bs5/examples/badge/color/snippet.html.erb +8 -0
  27. data/app/views/bs5/examples/badge/default/_example.html.erb +2 -1
  28. data/app/views/bs5/examples/badge/default/button.html.erb +3 -0
  29. data/app/views/bs5/examples/badge/pill/snippet.html.erb +8 -8
  30. data/app/views/bs5/examples/breadcrumb/default/snippet.html.erb +9 -9
  31. data/app/views/bs5/examples/button_group/button_toolbar/_example.html.erb +3 -0
  32. data/app/views/bs5/examples/button_group/button_toolbar/snippet.html.erb +18 -0
  33. data/app/views/bs5/examples/button_group/button_toolbar/snippet2.html.erb +27 -0
  34. data/app/views/bs5/examples/button_group/default/_example.html.erb +2 -0
  35. data/app/views/bs5/examples/button_group/default/snippet.html.erb +5 -0
  36. data/app/views/bs5/examples/button_group/sizing/_example.html.erb +2 -0
  37. data/app/views/bs5/examples/button_group/sizing/snippet.html.erb +17 -0
  38. data/app/views/bs5/examples/button_group/vertical/_example.html.erb +2 -0
  39. data/app/views/bs5/examples/button_group/vertical/snippet.html.erb +8 -0
  40. data/app/views/bs5/examples/buttons/button_tag/outline/snippet.html.erb +9 -9
  41. data/app/views/bs5/examples/buttons/button_tag/size/large.html.erb +2 -2
  42. data/app/views/bs5/examples/buttons/button_tag/size/small.html.erb +2 -2
  43. data/app/views/bs5/examples/buttons/button_tag/style/snippet.html.erb +9 -9
  44. data/app/views/bs5/examples/buttons/button_to/default/snippet.html.erb +3 -3
  45. data/app/views/bs5/examples/list_group/actionable/button.html.erb +5 -5
  46. data/app/views/bs5/examples/list_group/actionable/snippet.html.erb +5 -5
  47. data/app/views/bs5/examples/list_group/active/snippet.html.erb +5 -5
  48. data/app/views/bs5/examples/list_group/checkboxes_and_radios/default.html.erb +5 -5
  49. data/app/views/bs5/examples/list_group/checkboxes_and_radios/with_labels.html.erb +5 -5
  50. data/app/views/bs5/examples/list_group/custom_content/default.html.erb +3 -3
  51. data/app/views/bs5/examples/list_group/default/snippet.html.erb +5 -5
  52. data/app/views/bs5/examples/list_group/disabled/snippet.html.erb +5 -5
  53. data/app/views/bs5/examples/list_group/flush/snippet.html.erb +5 -5
  54. data/app/views/bs5/examples/list_group/horizontal/snippet.html.erb +18 -18
  55. data/app/views/bs5/examples/list_group/style/actionable.html.erb +9 -9
  56. data/app/views/bs5/examples/list_group/style/default.html.erb +9 -9
  57. data/app/views/bs5/examples/list_group/with_badges/default.html.erb +6 -6
  58. data/app/views/bs5/examples/popovers/default/snippet.html.erb +1 -1
  59. data/app/views/bs5/examples/popovers/four_directions/snippet.html.erb +4 -4
  60. data/app/views/bs5/examples/spinners/border/_example.html.erb +2 -0
  61. data/app/views/bs5/examples/spinners/border/snippet.html.erb +1 -0
  62. data/app/views/bs5/examples/spinners/buttons/_example.html.erb +2 -0
  63. data/app/views/bs5/examples/spinners/buttons/snippet.html.erb +15 -0
  64. data/app/views/bs5/examples/spinners/colors/_example.html.erb +2 -0
  65. data/app/views/bs5/examples/spinners/colors/snippet.html.erb +16 -0
  66. data/app/views/bs5/examples/spinners/growing/_example.html.erb +3 -0
  67. data/app/views/bs5/examples/spinners/growing/colors.html.erb +16 -0
  68. data/app/views/bs5/examples/spinners/growing/snippet.html.erb +1 -0
  69. data/app/views/bs5/examples/spinners/options/_example.html.erb +10 -0
  70. data/app/views/bs5/examples/spinners/options/floats.html.erb +3 -0
  71. data/app/views/bs5/examples/spinners/options/margin.html.erb +1 -0
  72. data/app/views/bs5/examples/spinners/options/placement_flex1.html.erb +3 -0
  73. data/app/views/bs5/examples/spinners/options/placement_flex2.html.erb +4 -0
  74. data/app/views/bs5/examples/spinners/options/text_align.html.erb +3 -0
  75. data/app/views/bs5/examples/spinners/size/_example.html.erb +3 -0
  76. data/app/views/bs5/examples/spinners/size/size1.html.erb +7 -0
  77. data/app/views/bs5/examples/spinners/size/size2.html.erb +3 -0
  78. data/app/views/bs5/examples/tooltips/default/buttons.html.erb +5 -5
  79. data/app/views/bs5/pages/alert.html.erb +1 -1
  80. data/app/views/bs5/pages/badge.html.erb +1 -1
  81. data/app/views/bs5/pages/button_group.html.erb +5 -0
  82. data/app/views/bs5/pages/spinners.html.erb +7 -0
  83. data/app/views/layouts/bs5/pages.html.erb +12 -10
  84. data/lib/bs5/version.rb +1 -1
  85. data/lib/tasks/rubocop.rake +2 -0
  86. metadata +55 -19
  87. data/app/views/bs5/examples/alert/style/_example.html.erb +0 -2
  88. data/app/views/bs5/examples/badge/style/_example.html.erb +0 -2
  89. data/app/views/bs5/examples/badge/style/snippet.html.erb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22c6a9e55865f643c0c955fa134144831a0e1aa3d68f9487757a2406429707fd
4
- data.tar.gz: 94f28cbdc41c9f5cc4a223779247521659d66b0ac82aa9756bc37cbb1f73c45c
3
+ metadata.gz: feb6bdfa563dc0c4a846de69be606f33deacb0eca228319bb670b2f668103ce2
4
+ data.tar.gz: 51fd44d6cf62d4fcb10aa237f9eb0b1b4e5451bd77235d209c735f991b3eb830
5
5
  SHA512:
6
- metadata.gz: 7b08a72d089dba1ac047006893c765deac278eb925c5ace940882708af292e306a5f69ee71062493d120a1bc3be347a729113d0cb4c486cf8bd899918b4c5247
7
- data.tar.gz: bc39e72b8af466e92f006ce3833aa1610c294959bba9a4201d581fa4aa4839f2ec6fa841db203a6adee60c7dcffe5872697a87d9be3ee2f27014d21741de1354
6
+ metadata.gz: 0cd5058a2b39382182e3f3de2138f0b9c19f0c700c61ff64e7b92e889bc765cb8c292ea69e6c4fba87d3f649756c22b6901c8c8a2f989191672758e66ccc6994
7
+ data.tar.gz: 63705942d873ecd5ddee1cfe12cc0144b24d8c842319d389fb0eeef545b0d45eaab6f3b8133863a8885af811fc1b5c0d896e96c797470f8c5a7b128e86567d09
@@ -17,7 +17,7 @@
17
17
  data-bs-parent="#<%= id %>"
18
18
  >
19
19
  <div class="accordion-body">
20
- <%= item.content %>
20
+ <%= item %>
21
21
  </div>
22
22
  </div>
23
23
  </div>
@@ -3,9 +3,9 @@
3
3
  module Bs5
4
4
  class AccordionComponent < ViewComponent::Base
5
5
  include ComponentsHelper
6
- include ViewComponent::Slotable
6
+ include ViewComponent::SlotableV2
7
7
 
8
- with_slot :item, collection: true, class_name: 'Item'
8
+ renders_many :items, 'ItemComponent'
9
9
 
10
10
  def initialize(flush: false)
11
11
  @flush = flush
@@ -25,7 +25,7 @@ module Bs5
25
25
  class_names.join(' ')
26
26
  end
27
27
 
28
- class Item < ViewComponent::Slot
28
+ class ItemComponent < ViewComponent::Base
29
29
  attr_reader :title
30
30
 
31
31
  def initialize(title:, collapsed: true)
@@ -33,6 +33,10 @@ module Bs5
33
33
  @collapsed = collapsed
34
34
  end
35
35
 
36
+ def call
37
+ content
38
+ end
39
+
36
40
  def id
37
41
  object_id
38
42
  end
@@ -4,13 +4,13 @@ module Bs5
4
4
  class AlertComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark].freeze
6
6
 
7
- attr_reader :style, :is_dismissable
7
+ attr_reader :color, :is_dismissable
8
8
 
9
9
  include ActiveModel::Validations
10
- validates :style, style: true
10
+ validates :color, style: true
11
11
 
12
- def initialize(style: :primary, is_dismissable: false)
13
- @style = style.to_sym
12
+ def initialize(color: :primary, is_dismissable: false)
13
+ @color = color.to_sym
14
14
  @is_dismissable = is_dismissable
15
15
  end
16
16
 
@@ -31,7 +31,7 @@ module Bs5
31
31
  end
32
32
 
33
33
  def contextual_class
34
- "alert-#{@style}"
34
+ "alert-#{@color}"
35
35
  end
36
36
  end
37
37
  end
@@ -4,14 +4,14 @@ module Bs5
4
4
  class BadgeComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark].freeze
6
6
 
7
- attr_reader :text, :style
7
+ attr_reader :text, :color
8
8
 
9
9
  include ActiveModel::Validations
10
- validates :style, style: true
10
+ validates :color, style: true
11
11
 
12
- def initialize(text:, style: :secondary, pill: false)
12
+ def initialize(text:, color: :secondary, pill: false)
13
13
  @text = text
14
- @style = style.to_sym
14
+ @color = color.to_sym
15
15
  @pill = pill
16
16
  end
17
17
 
@@ -32,8 +32,8 @@ module Bs5
32
32
  end
33
33
 
34
34
  def contextual_class
35
- class_names = ["bg-#{@style}"]
36
- class_names << %w[text-dark] if style.in?(%i[warning info light])
35
+ class_names = ["bg-#{@color}"]
36
+ class_names << %w[text-dark] if color.in?(%i[warning info light])
37
37
  class_names.join(' ')
38
38
  end
39
39
  end
@@ -2,7 +2,7 @@
2
2
  <nav aria-label="breadcrumb">
3
3
  <ol class="breadcrumb">
4
4
  <% items.each do |item| %>
5
- <li class="breadcrumb-item <%= item == items.last ? 'active' : '' %>" <%= item == items.last ? 'aria-current=page' : '' %>><%= item.content %></li>
5
+ <li class="breadcrumb-item <%= item == items.last ? 'active' : '' %>" <%= item == items.last ? 'aria-current=page' : '' %>><%= item %></li>
6
6
  <% end %>
7
7
  </ol>
8
8
  </nav>
@@ -2,11 +2,14 @@
2
2
 
3
3
  module Bs5
4
4
  class BreadcrumbComponent < ViewComponent::Base
5
- include ViewComponent::Slotable
5
+ include ViewComponent::SlotableV2
6
6
 
7
- with_slot :item, collection: true, class_name: 'Item'
7
+ renders_many :items, 'ItemComponent'
8
8
 
9
- class Item < ViewComponent::Slot
9
+ class ItemComponent < ViewComponent::Base
10
+ def call
11
+ content
12
+ end
10
13
  end
11
14
  end
12
15
  end
@@ -0,0 +1,3 @@
1
+ <%= tag.div(component_attributes) do %>
2
+ <%= content %>
3
+ <% end %>
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class ButtonGroupComponent < ViewComponent::Base
5
+ SIZES = { small: :sm, large: :lg }.with_indifferent_access.freeze
6
+ CLASS_PREFIX = 'btn-group'
7
+
8
+ attr_reader :vertical, :size
9
+
10
+ def initialize(options = {})
11
+ @options = options.symbolize_keys
12
+ @vertical = @options.delete(:vertical)
13
+ @size = @options.delete(:size)
14
+ end
15
+
16
+ def render?
17
+ content.present?
18
+ end
19
+
20
+ def component_attributes
21
+ default_options = { role: 'group' }
22
+ @options[:class] = component_class
23
+ @options.merge(default_options)
24
+ end
25
+
26
+ private
27
+
28
+ def component_class
29
+ class_names = Array(@options[:class])
30
+ class_names << vertical_class
31
+ class_names << size_class
32
+ class_names
33
+ end
34
+
35
+ def vertical_class
36
+ @vertical ? "#{CLASS_PREFIX}-vertical" : CLASS_PREFIX
37
+ end
38
+
39
+ def size_class
40
+ return unless size?
41
+
42
+ [CLASS_PREFIX, SIZES[size]].join('-')
43
+ end
44
+
45
+ def size?
46
+ !!size
47
+ end
48
+ end
49
+ end
@@ -3,14 +3,14 @@
3
3
  module Bs5
4
4
  class ButtonTagComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark link].freeze
6
- DEFAULT_STYLE = :primary
6
+ DEFAULT_COLOR = :primary
7
7
  SIZES = { small: :sm, large: :lg }.freeze
8
8
  CLASS_PREFIX = 'btn'
9
9
 
10
10
  attr_reader :content_or_options, :size
11
11
 
12
12
  include ActiveModel::Validations
13
- validates :style, style: true
13
+ validates :color, style: true
14
14
  validates :size, inclusion: { in: SIZES.keys, valid_sizes: SIZES.keys.to_sentence, allow_nil: true }
15
15
 
16
16
  def initialize(content_or_options = nil, options = nil)
@@ -44,13 +44,13 @@ module Bs5
44
44
  end
45
45
 
46
46
  def extract_custom_options
47
- extract_style
47
+ extract_color
48
48
  extract_outline
49
49
  extract_size
50
50
  end
51
51
 
52
- def extract_style
53
- @style = @options.delete(:style)
52
+ def extract_color
53
+ @color = @options.delete(:color)
54
54
  end
55
55
 
56
56
  def extract_outline
@@ -76,7 +76,7 @@ module Bs5
76
76
  end
77
77
 
78
78
  def contextual_class
79
- [CLASS_PREFIX, outline? ? 'outline' : nil, style].compact.join('-')
79
+ [CLASS_PREFIX, outline? ? 'outline' : nil, color].compact.join('-')
80
80
  end
81
81
 
82
82
  def size_class
@@ -85,8 +85,8 @@ module Bs5
85
85
  [CLASS_PREFIX, SIZES[size]].join('-')
86
86
  end
87
87
 
88
- def style
89
- (@style || DEFAULT_STYLE).to_sym
88
+ def color
89
+ (@color || DEFAULT_COLOR).to_sym
90
90
  end
91
91
 
92
92
  def outline?
@@ -3,14 +3,14 @@
3
3
  module Bs5
4
4
  class ButtonToComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark link].freeze
6
- DEFAULT_STYLE = :primary
6
+ DEFAULT_COLOR = :primary
7
7
  SIZES = { small: :sm, large: :lg }.freeze
8
8
  CLASS_PREFIX = 'btn'
9
9
 
10
10
  attr_reader :size
11
11
 
12
12
  include ActiveModel::Validations
13
- validates :style, style: true
13
+ validates :color, style: true
14
14
  validates :size, inclusion: { in: SIZES.keys, valid_sizes: SIZES.keys.to_sentence, allow_nil: true }
15
15
 
16
16
  def initialize(name = nil, options = nil, html_options = nil)
@@ -53,13 +53,13 @@ module Bs5
53
53
  end
54
54
 
55
55
  def extract_custom_options
56
- extract_style
56
+ extract_color
57
57
  extract_outline
58
58
  extract_size
59
59
  end
60
60
 
61
- def extract_style
62
- @style = @button_to_options.delete(:style)
61
+ def extract_color
62
+ @color = @button_to_options.delete(:color)
63
63
  end
64
64
 
65
65
  def extract_outline
@@ -85,7 +85,7 @@ module Bs5
85
85
  end
86
86
 
87
87
  def contextual_class
88
- [CLASS_PREFIX, outline? ? 'outline' : nil, style].compact.join('-')
88
+ [CLASS_PREFIX, outline? ? 'outline' : nil, color].compact.join('-')
89
89
  end
90
90
 
91
91
  def size_class
@@ -94,8 +94,8 @@ module Bs5
94
94
  [CLASS_PREFIX, SIZES[size]].join('-')
95
95
  end
96
96
 
97
- def style
98
- (@style || DEFAULT_STYLE).to_sym
97
+ def color
98
+ (@color || DEFAULT_COLOR).to_sym
99
99
  end
100
100
 
101
101
  def outline?
@@ -0,0 +1,3 @@
1
+ <%= tag.div(component_attributes) do %>
2
+ <%= content %>
3
+ <% end %>
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class ButtonToolbarComponent < ViewComponent::Base
5
+ def initialize(options = {})
6
+ @options = options
7
+ end
8
+
9
+ def render?
10
+ content.present?
11
+ end
12
+
13
+ def component_attributes
14
+ default_options = { role: 'toolbar' }
15
+ @options[:class] = Array(@options[:class])
16
+ @options[:class] << 'btn-toolbar'
17
+
18
+ @options.merge(default_options)
19
+ end
20
+ end
21
+ end
@@ -2,14 +2,14 @@
2
2
  <% if actionables? %>
3
3
  <div class="<%= component_class %>">
4
4
  <% items.each do |item| %>
5
- <%= item.decorated_content %>
5
+ <%= item %>
6
6
  <% end %>
7
7
  </div>
8
8
  <% else %>
9
9
  <ul class="<%= component_class %>">
10
10
  <% items.each do |item| %>
11
11
  <%= tag.li(**item.options) do %>
12
- <%= item.content %>
12
+ <%= item %>
13
13
  <% end %>
14
14
  <% end %>
15
15
  </ul>
@@ -6,9 +6,9 @@ module Bs5
6
6
  CLASS_NAME_FLUSH = "#{CLASS_NAME_BASE}-flush"
7
7
  CLASS_NAME_HORIZONTAL = "#{CLASS_NAME_BASE}-horizontal"
8
8
 
9
- include ViewComponent::Slotable
9
+ include ViewComponent::SlotableV2
10
10
 
11
- with_slot :item, collection: true, class_name: 'Item'
11
+ renders_many :items, 'Item'
12
12
 
13
13
  def initialize(flush: false, horizontal: false)
14
14
  @flush = flush
@@ -22,7 +22,10 @@ module Bs5
22
22
  end
23
23
 
24
24
  def actionables?
25
- items.any?(&:actionable?)
25
+ items.any? do |item|
26
+ elements = Nokogiri::HTML::DocumentFragment.parse(item.to_s).elements
27
+ elements.one? && elements.first.name.in?(%w[a button label])
28
+ end
26
29
  end
27
30
 
28
31
  def horizontal?
@@ -48,7 +51,7 @@ module Bs5
48
51
  class_names.join('-')
49
52
  end
50
53
 
51
- class Item < ViewComponent::Slot
54
+ class Item < ViewComponent::Base
52
55
  CLASS_NAME_BASE = 'list-group-item'
53
56
  CLASS_NAME_ACTION = "#{CLASS_NAME_BASE}-action"
54
57
 
@@ -59,11 +62,15 @@ module Bs5
59
62
 
60
63
  @active = @options.delete(:active) || false
61
64
  @disabled = @options.delete(:disabled) || false
62
- @style = @options.delete(:style)
65
+ @color = @options.delete(:color)
63
66
 
64
67
  set_attributes
65
68
  end
66
69
 
70
+ def call
71
+ actionable? ? decorated_content : content
72
+ end
73
+
67
74
  def actionable?
68
75
  !!actionable_element
69
76
  end
@@ -118,7 +125,7 @@ module Bs5
118
125
  class_names = [CLASS_NAME_BASE]
119
126
  class_names << 'active' if active?
120
127
  class_names << 'disabled' if disabled?
121
- class_names << contextual_class if style?
128
+ class_names << contextual_class if color?
122
129
 
123
130
  class_names
124
131
  end
@@ -131,12 +138,12 @@ module Bs5
131
138
  !!@disabled
132
139
  end
133
140
 
134
- def style?
135
- !!@style
141
+ def color?
142
+ !!@color
136
143
  end
137
144
 
138
145
  def contextual_class
139
- [CLASS_NAME_BASE, @style].join('-')
146
+ [CLASS_NAME_BASE, @color].join('-')
140
147
  end
141
148
  end
142
149
  end
@@ -0,0 +1,5 @@
1
+ <%= tag.div(**component_attributes) do %>
2
+ <%- if text %>
3
+ <span class="visually-hidden"><%= text %></span>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class SpinnerComponent < ViewComponent::Base
5
+ STYLES = %i[primary secondary success danger warning info light dark].freeze
6
+ SIZES = { small: :sm, large: :lg }.freeze
7
+
8
+ attr_reader :text, :color, :size, :options
9
+
10
+ include ActiveModel::Validations
11
+ validates :color, style: true, if: -> { color }
12
+
13
+ def initialize(options = {})
14
+ @options = options.symbolize_keys
15
+
16
+ @text = @options.delete(:text)
17
+ @color = @options.delete(:color)&.to_sym
18
+ @grow = @options.delete(:grow)
19
+ @size = @options.delete(:size)&.to_sym
20
+ end
21
+
22
+ def before_render
23
+ raise errors.full_messages.to_sentence if invalid?
24
+ end
25
+
26
+ def component_attributes
27
+ options[:class] = component_class
28
+ options[:role] = 'status'
29
+ options
30
+ end
31
+
32
+ def component_class
33
+ class_names = Array(options[:class])
34
+ class_names << shape_class
35
+ class_names << contextual_class
36
+ class_names << size_class
37
+
38
+ class_names.compact.join(' ')
39
+ end
40
+
41
+ private
42
+
43
+ def shape_class
44
+ grow? ? 'spinner-grow' : 'spinner-border'
45
+ end
46
+
47
+ def contextual_class
48
+ "text-#{@color}" if color
49
+ end
50
+
51
+ def size_class
52
+ return unless size?
53
+
54
+ [shape_class, SIZES[size]].join('-')
55
+ end
56
+
57
+ def grow?
58
+ !!@grow
59
+ end
60
+
61
+ def size?
62
+ !!size
63
+ end
64
+ end
65
+ end