bh 6.6.0 → 6.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9c573e779abc79338fe373283a0f0e30805337a2daad8804fc826e9b22acd55
4
- data.tar.gz: 7b8041b33fbcccaccb94902bbc8947f88ebc5aa8ccdd5ba5613241a37c777cb7
3
+ metadata.gz: 9161e2164dd9b496c6ad7210d47f43ab01c2dba40101e3f4c7ef90da2d782d82
4
+ data.tar.gz: df825d0fb572112a3c36d3a82b8035b5005e669affe3da80b1f9c792bc78bafc
5
5
  SHA512:
6
- metadata.gz: 65668c148e51ae156e55de930fc3656c91bdecd61ac9b6d555022ffb4a3a6dfc6021cca19e83b6c85e536c712f58665f11e3914dab92834c2d576071c4c63b07
7
- data.tar.gz: 3a0e4eb9fc775a15ecbe432cc09e551f55a06026589bc990b03cd18cf39a2ca4a8f793cd8c07ad35a25703056cbb50144991843883b16888f3dbc37e0f6cd934
6
+ metadata.gz: a83fcd4a1403078a9edc6dda158025b2a05033d849f15373d4fec9d1039ae4eccafd7d250e8767a5b3da60c6d8c6b843807d73d4b87c06d709c7196ea5aff897
7
+ data.tar.gz: cc5f5495354b1e89e046982febfc44635427b23e9089a43e27867552bdce2e881301277849bc8a963f176a4416f3326312e969ec943de9bacb018627f4ef90f9
data/CHANGELOG.md CHANGED
@@ -8,6 +8,74 @@ For more information about changelogs, check
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## 6.7.0 - 2026-09-19
12
+
13
+ * [CHANGE] The signup page goes
14
+
15
+ `flow` drew a page no part of Bootstrap names, out of three `content_for` keys a caller
16
+ never passes, in rules only one product's onboarding wanted. It belongs to whoever ships
17
+ that product, and this gem keeps what Bootstrap defines.
18
+
19
+ The two classes the builder writes go with it in name only: `flow-fieldset` is now
20
+ `bh-fieldset` and `flow-field` is `bh-field`, both being the form's business rather than
21
+ a page's, and the spacing of a fieldset stays here with them.
22
+
23
+ * [CHANGE] The head is the host's to write
24
+
25
+ `bh_head_tags` bundled four metas a page decides for itself with the two files this gem
26
+ serves, all or nothing. `Bh::Engine::PREFIX` is where they are served, and a layout links
27
+ them:
28
+
29
+ ```erb
30
+ <link rel='stylesheet' href='<%= Bh::Engine::PREFIX %>css/bh.css'>
31
+ <script type='module' src='<%= Bh::Engine::PREFIX %>js/bh.js'></script>
32
+ ```
33
+
34
+ * [CHANGE] `notices` is `toasts`
35
+
36
+ It draws a stack of Bootstrap's toasts and says so. `toast` is left for the one a host
37
+ hands over itself.
38
+
39
+ It takes `data:` for a host marking what the page it stands on is about, and a block for
40
+ one splicing a link into the words a message says.
41
+
42
+ * [FEATURE] A control says what it is to a reader who meets it alone
43
+
44
+ Every field the builder dresses carries an `aria-label` off the attribute it sets, which
45
+ a page's own `aria` still overrides key by key.
46
+
47
+ * [FEATURE] Money and a share of a hundred are typed into an adorned control
48
+
49
+ `price_field` and `percentage_field` draw Bootstrap's adorned control: the unit in a span
50
+ and the field inside it wearing no border of its own.
51
+
52
+ * [FEATURE] `file_field`, which Rails handed over undressed
53
+
54
+ * [FEATURE] `confirm_button_to` asks before it acts
55
+
56
+ The bundle draws the question as a dialog, and the form is sent only where it is answered
57
+ yes.
58
+
59
+ * [FEATURE] `tooltip_data` is the data an element wearing a tooltip takes
60
+
61
+ * [FEATURE] A phone field shows the shape it will take
62
+
63
+ `555-555-5555`, from the locale rather than the code, since how a number is written is
64
+ the reader's language and not this gem's. A page saying its own placeholder keeps it.
65
+
66
+ The only field given one: a placeholder is decoration over a label, and it earns its
67
+ place where it shows a shape a reader could get wrong rather than where it repeats what
68
+ the label already says. This is the one field where the gem knows the shape, because the
69
+ gem is what imposes it.
70
+
71
+ * [FIX] A menu, a box and a circle wear what Bootstrap 6 draws
72
+
73
+ A `<select>` wore `form-select form-select-lg`, a ticked box `form-check-input`, and the
74
+ words beside it sat in a `form-check` under a `form-check-label`. Bootstrap 6 defines
75
+ none of those: a menu is a control like any other, a box is a `check`, a circle is a
76
+ `radio`, and the two of them stand in a `form-field`, which lays them out in a row. Every
77
+ one of them was drawing undressed.
78
+
11
79
  ## 6.6.0 - 2026-09-18
12
80
 
13
81
  * [CHANGE] A picture in a bubble is a thumbnail
data/README.md CHANGED
@@ -21,10 +21,10 @@ gem install bh
21
21
 
22
22
  ```ruby
23
23
  # Gemfile
24
- gem 'bh', '~> 6.3.0'
24
+ gem 'bh', '~> 6.7.0'
25
25
  ```
26
26
 
27
- `~> 6.3.0` stops short of `6.4`, and that is the pin to hold: **until this line settles it
27
+ `~> 6.7.0` stops short of `6.8`, and that is the pin to hold: **until this line settles it
28
28
  breaks on a minor, not on a major.** Rails 8.1 and Ruby 3.2 are the minimum.
29
29
 
30
30
  6.2.0 breaks everything before it and keeps its major anyway. 6.0 through 6.1.4 were an alpha
@@ -33,11 +33,12 @@ while Bootstrap 6 was itself pre-release — so there was no settled API to brea
33
33
  are taken and cannot be withdrawn, RubyGems keeping anything published over thirty days ago, so
34
34
  this release steps over them.
35
35
 
36
- With the gem in the bundle an app serves `/bh/css/bh.css` and `/bh/js/bh.js` itself. One helper
37
- puts both in the head, along with everything Bootstrap and Turbo read:
36
+ With the gem in the bundle an app serves `/bh/css/bh.css` and `/bh/js/bh.js` itself, at the
37
+ prefix its engine is mounted at. A layout links both:
38
38
 
39
39
  ```erb
40
- <%= bh_head_tags %>
40
+ <link rel='stylesheet' href='<%= Bh::Engine::PREFIX %>css/bh.css'>
41
+ <script type='module' src='<%= Bh::Engine::PREFIX %>js/bh.js'></script>
41
42
  ```
42
43
 
43
44
  ## The palettes
@@ -83,9 +84,10 @@ end
83
84
  | `pin_field` | one real field drawn as six slots, offered by the phone from the text that brought it |
84
85
  | `combobox` | a `<select>` drawn as a searchable menu, still the one thing the form submits |
85
86
  | `dialog` | a link and the `<dialog>` it opens, sharing an id made from the link's own words |
86
- | `notices` | the flash as toasts, held while they are read |
87
+ | `toasts` | the flash as toasts, held while they are read |
87
88
  | `chat_with` | a thread of bubbles, and the field that posts the next one |
88
- | `flow` | the page of a signup flow: a header, a title, one card, a footer |
89
+ | `confirm_button_to` | a button whose form is sent only where the question it carries is answered yes |
90
+ | `tooltip_data` | the `data` an element wearing a tooltip takes |
89
91
  | 22 Stimulus controllers | registered by the bundle, called by `data-controller` |
90
92
  | 9 palettes | served at `/bh/theme/`, swapped by the `scheme` controller |
91
93
 
@@ -101,8 +103,7 @@ bin/setup
101
103
  rails s
102
104
  ```
103
105
 
104
- `localhost:3000` is every component at once, `?flash=1` adds the toasts, and `/flow` is the
105
- signup page.
106
+ `localhost:3000` is every component at once, and `?flash=1` adds the toasts.
106
107
 
107
108
  ## Elsewhere
108
109
 
@@ -25,3 +25,6 @@ mark { padding: 0; }
25
25
  ::before, so the hover transform on the .bi box itself is untouched. */
26
26
  .icon-link > .bi::before { vertical-align: .0625em; }
27
27
 
28
+ /* A group of controls carries its own spacing, and twice as much under it as over: the words
29
+ over a group belong to it, and even space either side would let them drift between two. */
30
+ .bh-fieldset { margin-block: 1rem 2rem; gap: 1rem }
@@ -10,4 +10,3 @@
10
10
  @import 'bh/values.css';
11
11
  @import 'bh/chat.css';
12
12
  @import 'bh/pin.css';
13
- @import 'bh/flow.css';
@@ -9,6 +9,7 @@ en:
9
9
  no_results: Nothing matches that
10
10
  okay: Okay
11
11
  photo: Photo
12
+ phone: 555-555-5555
12
13
  search: Search
13
14
  send: Send
14
15
  typing: Typing
@@ -0,0 +1,47 @@
1
+ require 'action_view'
2
+
3
+ module Bh
4
+ class FormBuilder < ActionView::Helpers::FormBuilder
5
+ # The two controls that carry a unit inside their border: money, and a share of a hundred.
6
+ module Adornments
7
+ # What a price takes: no less than nothing, and the cents a currency is counted in. A
8
+ # caller knowing its column's scale says so and overrides the step.
9
+ PRICE = { min: 0, step: 0.01 }.freeze
10
+
11
+ # What the wrapper wears. Bootstrap adorns a control by wrapping it, so the border and
12
+ # the padding are the wrapper's and the field inside carries neither.
13
+ ADORN = 'form-control form-adorn d-flex'
14
+
15
+ # What money is typed into: the number and the currency beside it, inside one border.
16
+ def price_field(method, options = {})
17
+ adorned method, currency_unit, PRICE.merge(options)
18
+ end
19
+
20
+ # And a share of a hundred, whose sign follows the number rather than leading it.
21
+ def percentage_field(method, options = {})
22
+ adorned method, '%', options, ending: true
23
+ end
24
+
25
+ private
26
+
27
+ def currency_unit = I18n.t 'number.currency.format.unit', default: '$'
28
+
29
+ def adorned(method, unit, options, ending: false)
30
+ classes = @template.class_names ADORN, ('form-adorn-end' if ending), options[:class]
31
+ unit = @template.tag.span unit, class: 'form-adorn-text'
32
+ inside = @template.safe_join [unit, ghost_field(method, options.except(:class))]
33
+
34
+ @template.tag.div inside, class: classes
35
+ end
36
+
37
+ # The control Rails draws before this builder dresses one, which is what the wrapper
38
+ # holds: `form-ghost` wears neither the border nor the padding a control does.
39
+ def ghost_field(method, options)
40
+ asked = { aria: { label: method } }.deep_merge options
41
+
42
+ @template.number_field @object_name, method,
43
+ objectify_options(asked.merge(class: 'form-ghost'))
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ require 'action_view'
2
+
3
+ module Bh
4
+ class FormBuilder < ActionView::Helpers::FormBuilder
5
+ # What a form is sent with, and what else it offers to press.
6
+ module Buttons
7
+ # What a button wears: the large pill in the primary color, solid or outlined.
8
+ PILL = 'btn btn-lg rounded-5 theme-primary'
9
+
10
+ # What clears a button of the field or the button above it.
11
+ SPACE = 'mt-3 md:mt-4'
12
+
13
+ # A submit is the builder's button, solid.
14
+ def submit(value = nil, options = {})
15
+ super(value, with_classes(options, "#{PILL} btn-solid #{SPACE}"))
16
+ end
17
+
18
+ # A button is the builder's too: solid where it submits, which is what one does unless
19
+ # told `type: :button`, and outlined where it does not. A disabled one given a `title`
20
+ # says why on hover — `Available soon` — from a wrapper around it, since a disabled
21
+ # button hears no mouse; the wrapper then takes the button's place in the column.
22
+ def button(value = nil, options = {}, &)
23
+ return button(nil, value, &) if value.is_a? Hash
24
+
25
+ wrapped = options[:disabled] && options[:title]
26
+ fill = options[:type].to_s == 'button' ? 'btn-outline' : 'btn-solid'
27
+ classes = @template.class_names PILL, fill, (SPACE unless wrapped)
28
+ button = super(value, with_classes(options.except(:title), classes), &)
29
+
30
+ wrapped ? tooltipped(button, options[:title]) : button
31
+ end
32
+
33
+ private
34
+
35
+ def tooltipped(button, title)
36
+ @template.tag.span button, class: "d-grid #{SPACE}", data: @template.tooltip_data(title)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -6,42 +6,40 @@ module Bh
6
6
  # it wants and nothing about how it looks. Rails hands an undressed control to whatever it
7
7
  # has no method for here, which is how a Bootstrap class ends up written in a view.
8
8
  module Controls
9
- # What a menu wears: the control's size, so a menu and a box beside it line up.
10
- MENU = 'form-select form-select-lg'
11
-
12
- # What a box or a circle that is ticked wears.
13
- CHECK = 'form-check-input'
9
+ # What a box that is ticked wears, and what a circle does.
10
+ CHECK = 'check'
11
+ RADIO = 'radio'
14
12
 
15
13
  # An email address.
16
- def email_field(method, options = {}) = super(method, with_classes(options, CONTROL))
14
+ def email_field(method, options = {}) = super(method, dressed(method, options))
17
15
 
18
16
  # A number, which brings the keyboard for one.
19
- def number_field(method, options = {}) = super(method, with_classes(options, CONTROL))
17
+ def number_field(method, options = {}) = super(method, dressed(method, options))
20
18
 
21
19
  # A password, which no name of a column earns on its own.
22
- def password_field(method, options = {}) = super(method, with_classes(options, CONTROL))
20
+ def password_field(method, options = {}) = super(method, dressed(method, options))
23
21
 
24
22
  # A term to search by.
25
- def search_field(method, options = {}) = super(method, with_classes(options, CONTROL))
23
+ def search_field(method, options = {}) = super(method, dressed(method, options))
26
24
 
27
25
  # A web address.
28
- def url_field(method, options = {}) = super(method, with_classes(options, CONTROL))
26
+ def url_field(method, options = {}) = super(method, dressed(method, options))
29
27
 
30
28
  # A day.
31
- def date_field(method, options = {}) = super(method, with_classes(options, CONTROL))
29
+ def date_field(method, options = {}) = super(method, dressed(method, options))
32
30
 
33
31
  # A time of day.
34
- def time_field(method, options = {}) = super(method, with_classes(options, CONTROL))
32
+ def time_field(method, options = {}) = super(method, dressed(method, options))
35
33
 
36
34
  # A day and a time together.
37
- def datetime_field(method, options = {}) = super(method, with_classes(options, CONTROL))
35
+ def datetime_field(method, options = {}) = super(method, dressed(method, options))
38
36
 
39
37
  # More than a line of words.
40
- def text_area(method, options = {}) = super(method, with_classes(options, CONTROL))
38
+ def text_area(method, options = {}) = super(method, dressed(method, options))
41
39
 
42
40
  # A menu of what a column may be.
43
41
  def select(method, choices = nil, options = {}, html_options = {}, &)
44
- super(method, choices, options, with_classes(html_options, MENU), &)
42
+ super(method, choices, options, dressed(method, html_options), &)
45
43
  end
46
44
 
47
45
  # One of several, ticked.
@@ -51,16 +49,16 @@ module Bh
51
49
 
52
50
  # One of several, and only one.
53
51
  def radio_button(method, value, options = {})
54
- super(method, value, with_classes(options, CHECK))
52
+ super(method, value, with_classes(options, RADIO))
55
53
  end
56
54
 
57
55
  # A box and the words beside it, which is the one place words sit after a control rather
58
56
  # than over it -- so they are not the label a field wears, and are written here instead.
59
57
  def check(method, text, options = {})
60
- words = @template.label_tag field_id(method), text, class: 'form-check-label'
58
+ words = @template.label_tag field_id(method), text
61
59
  inside = @template.safe_join [check_box(method, options), words]
62
60
 
63
- @template.tag.div inside, class: 'form-check'
61
+ @template.tag.div inside, class: 'form-field'
64
62
  end
65
63
  end
66
64
  end
@@ -1,4 +1,6 @@
1
1
  require 'action_view'
2
+ require_relative 'form_builder/adornments'
3
+ require_relative 'form_builder/buttons'
2
4
  require_relative 'form_builder/comboboxes'
3
5
  require_relative 'form_builder/controls'
4
6
  require_relative 'form_builder/pins'
@@ -9,17 +11,11 @@ module Bh
9
11
  # `default_form_builder`. What a view passes is kept: its classes join the builder's, its
10
12
  # `data` is merged key by key with the builder's, and any other option of its overrides.
11
13
  class FormBuilder < ActionView::Helpers::FormBuilder
12
- include Comboboxes, Controls, Pins
14
+ include Adornments, Buttons, Comboboxes, Controls, Pins
13
15
 
14
16
  # What a field wears: Bootstrap's control, at the size a thumb finds.
15
17
  CONTROL = 'form-control form-control-lg'
16
18
 
17
- # What a button wears: the large pill in the primary color, solid or outlined.
18
- PILL = 'btn btn-lg rounded-5 theme-primary'
19
-
20
- # What clears a button of the field or the button above it.
21
- SPACE = 'mt-3 md:mt-4'
22
-
23
19
  # What a phone field carries: the bundle's `phone` controller, which shapes the number as
24
20
  # it is typed, and the keyboard and autofill a phone offers for one.
25
21
  PHONE = {
@@ -35,7 +31,7 @@ module Bh
35
31
  heading = (@template.tag.legend legend if legend)
36
32
  inside = @template.safe_join [heading, @template.capture(&)].compact
37
33
 
38
- @template.tag.fieldset inside, **with_classes(options, 'd-grid flow-fieldset')
34
+ @template.tag.fieldset inside, **with_classes(options, 'd-grid bh-fieldset')
39
35
  end
40
36
 
41
37
  # A label is Bootstrap's `form-label`, whatever else it is given -- and given both words
@@ -51,46 +47,35 @@ module Bh
51
47
  words = @template.tag.span text, class: 'form-label'
52
48
  inside = @template.safe_join [words, @template.capture(&block)]
53
49
 
54
- @template.tag.label inside, for: field_id(method), **with_classes(options, 'flow-field')
50
+ @template.tag.label inside, for: field_id(method), **with_classes(options, 'bh-field')
55
51
  end
56
52
 
57
53
  # A text field is a large control.
58
- def text_field(method, options = {}) = super(method, with_classes(options, CONTROL))
59
-
60
- # A phone field is a large control shaped by the `phone` controller as it is typed.
61
- def phone_field(method, options = {})
62
- super(method, PHONE.deep_merge(with_classes(options, CONTROL)))
63
- end
64
-
65
- # A submit is the builder's button, solid.
66
- def submit(value = nil, options = {})
67
- super(value, with_classes(options, "#{PILL} btn-solid #{SPACE}"))
68
- end
54
+ def text_field(method, options = {}) = super(method, dressed(method, options))
69
55
 
70
- # A button is the builder's too: solid where it submits, which is what one does unless told
71
- # `type: :button`, and outlined where it does not. A disabled one given a `title` says why
72
- # on hover — `Available soon` — from a wrapper around it, since a disabled button hears no
73
- # mouse; the wrapper then takes the button's place in the column.
74
- def button(value = nil, options = {}, &)
75
- return button(nil, value, &) if value.is_a? Hash
56
+ # A file to attach, which Rails hands over undressed.
57
+ def file_field(method, options = {}) = super(method, dressed(method, options))
76
58
 
77
- wrapped = options[:disabled] && options[:title]
78
- fill = options[:type].to_s == 'button' ? 'btn-outline' : 'btn-solid'
79
- classes = @template.class_names PILL, fill, (SPACE unless wrapped)
80
- button = super(value, with_classes(options.except(:title), classes), &)
59
+ # A phone field is a large control shaped by the `phone` controller as it is typed, and
60
+ # showing the shape it will take. Read at the call rather than frozen into `PHONE`, since
61
+ # how a number is written is the reader's language and not this gem's.
62
+ def phone_field(method, options = {})
63
+ shown = { placeholder: @template.t('bh.phone') }
81
64
 
82
- wrapped ? tooltipped(button, options[:title]) : button
65
+ super(method, PHONE.merge(shown).deep_merge(dressed(method, options)))
83
66
  end
84
67
 
85
68
  private
86
69
 
87
- def tooltipped(button, title)
88
- @template.tag.span button, class: "d-grid #{SPACE}",
89
- data: { controller: 'tooltip', bs_title: title }
90
- end
91
-
92
70
  def with_classes(options, classes)
93
71
  options.merge class: @template.class_names(classes, options[:class])
94
72
  end
73
+
74
+ # What a control wears, and what names it where the words that do are not beside it: the
75
+ # attribute, as the label a reader meeting the field alone is read it by. A page's own
76
+ # `aria` wins over this one, key by key.
77
+ def dressed(method, options, classes = CONTROL)
78
+ { aria: { label: method } }.deep_merge with_classes(options, classes)
79
+ end
95
80
  end
96
81
  end
@@ -0,0 +1,20 @@
1
+ module Bh
2
+ module Helpers
3
+ # The button that asks before it acts.
4
+ module Confirmations
5
+ # A button whose form is sent only where the question it carries is answered yes.
6
+ # The bundle draws that question as a dialog. Every option is the button's, and the
7
+ # question rides on the form, which is what Turbo asks before submitting either.
8
+ # @param words [String] what the button reads.
9
+ # @param path [String] where the form is sent.
10
+ # @param confirm [String] the question, its first line the title of the dialog.
11
+ # @param options [Hash] anything else the button takes.
12
+ # @return [String] the form and the button in it.
13
+ def confirm_button_to(words, path, confirm:, **options)
14
+ form = { data: { turbo_confirm: confirm } }.deep_merge options.fetch(:form, {})
15
+
16
+ button_to words, path, **options.except(:form), form: form
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,7 +1,7 @@
1
1
  module Bh
2
2
  module Helpers
3
3
  # What the flash says, as the toasts every Bh page shows them in.
4
- module Notices
4
+ module Toasts
5
5
  # Bootstrap's tone for each key, so a notice and an alert read apart; a key of the
6
6
  # host's own reads neutral.
7
7
  TONES = { 'notice' => 'theme-success', 'alert' => 'theme-danger' }.freeze
@@ -16,14 +16,21 @@ module Bh
16
16
  # other part of a host keeps in the flash, and is not something to show. Nothing at all
17
17
  # where there is nothing to say. `data-turbo-temporary`, so a toast born visible does
18
18
  # not replay from the page's snapshot on every Back.
19
- def notices
19
+ # @param data [Hash] anything else the stack of them carries, for a host marking what
20
+ # the page it stands on is about.
21
+ # @yield [key, message] what to draw in place of the message, for a host with a link
22
+ # to splice into it. The message itself where no block is given.
23
+ # @return [String, nil] the toasts, or nothing where the flash says nothing.
24
+ def toasts(data: {}, &)
20
25
  messages = flash.to_hash.select { |_, message| message.is_a? String }
21
26
  return if messages.empty?
22
27
 
23
- toasts = messages.map { |key, message| bh_toast key, message }
28
+ toasts = messages.map do |key, message|
29
+ bh_toast key, block_given? ? yield(key, message) : message
30
+ end
24
31
 
25
32
  tag.div safe_join(toasts), class: 'toast-container position-fixed bottom-0 end-0 p-3',
26
- data: { turbo_temporary: '' }
33
+ data: { turbo_temporary: '' }.merge(data)
27
34
  end
28
35
 
29
36
  private
@@ -0,0 +1,15 @@
1
+ module Bh
2
+ module Helpers
3
+ # The words an element says on hover, which Bootstrap wires nowhere on its own.
4
+ module Tooltips
5
+ # What an element carries to be given a tooltip: the controller that makes one, and
6
+ # what it says. `bs_title` is the name Bootstrap's own tooltip reads.
7
+ # @param title [String] the words the tooltip says.
8
+ # @param placement [String, nil] which side of the element it opens on.
9
+ # @return [Hash] the `data` an element wearing a tooltip takes.
10
+ def tooltip_data(title, placement: nil)
11
+ { controller: 'tooltip', bs_placement: placement, bs_title: title }.compact
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/bh/helpers.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  require_relative 'helpers/chats'
2
+ require_relative 'helpers/confirmations'
2
3
  require_relative 'helpers/dialogs'
3
- require_relative 'helpers/flows'
4
- require_relative 'helpers/heads'
5
- require_relative 'helpers/notices'
4
+ require_relative 'helpers/toasts'
5
+ require_relative 'helpers/tooltips'
6
6
 
7
7
  module Bh
8
8
  # Everything a view may call, in one module the engine puts on every Action View.
9
9
  module Helpers
10
- include Chats, Dialogs, Flows, Heads, Notices
10
+ include Chats, Confirmations, Dialogs, Toasts, Tooltips
11
11
  end
12
12
  end
data/lib/bh/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Bh
2
2
  # Version of the gem, read by the gemspec and by hosts checking compatibility.
3
- VERSION = '6.6.0'
3
+ VERSION = '6.7.0'
4
4
  end