bh 6.1.3 → 6.2.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +87 -15
  4. data/app/javascript/bh/bookmark_controller.js +97 -0
  5. data/app/javascript/bh/clear_controller.js +22 -0
  6. data/app/javascript/bh/combobox/menu.js +93 -0
  7. data/app/javascript/bh/combobox_controller.js +82 -0
  8. data/app/javascript/bh/confirm.js +100 -0
  9. data/app/javascript/bh/density_controller.js +21 -0
  10. data/app/javascript/bh/deselect_controller.js +37 -0
  11. data/app/javascript/bh/flash.js +35 -0
  12. data/app/javascript/bh/limit_controller.js +23 -0
  13. data/app/javascript/bh/map/loader.js +20 -0
  14. data/app/javascript/bh/map_controller.js +88 -0
  15. data/app/javascript/bh/otp/slots.js +27 -0
  16. data/app/javascript/bh/otp_controller.js +98 -0
  17. data/app/javascript/bh/phone_controller.js +89 -0
  18. data/app/javascript/bh/placeholder_controller.js +28 -0
  19. data/app/javascript/bh/relative_time_controller.js +45 -0
  20. data/app/javascript/bh/require_controller.js +18 -0
  21. data/app/javascript/bh/reveal_controller.js +16 -0
  22. data/app/javascript/bh/scheme_controller.js +99 -0
  23. data/app/javascript/bh/search_controller.js +78 -0
  24. data/app/javascript/bh/shortcuts_controller.js +42 -0
  25. data/app/javascript/bh/sortable_controller.js +84 -0
  26. data/app/javascript/bh/thread_controller.js +47 -0
  27. data/app/javascript/bh/timezone_controller.js +27 -0
  28. data/app/javascript/bh/toast_controller.js +35 -0
  29. data/app/javascript/bh/tooltip_controller.js +23 -0
  30. data/app/javascript/bh/written.js +20 -0
  31. data/app/javascript/bh/written_controller.js +28 -0
  32. data/app/javascript/bh.js +60 -0
  33. data/app/stylesheets/bh/base.css +27 -0
  34. data/app/stylesheets/bh/chat.css +77 -0
  35. data/app/stylesheets/bh/flow.css +94 -0
  36. data/app/stylesheets/bh/map.css +3 -0
  37. data/app/stylesheets/bh/pin.css +34 -0
  38. data/app/stylesheets/bh/search.css +60 -0
  39. data/app/stylesheets/bh/shell.css +202 -0
  40. data/app/stylesheets/bh/table.css +130 -0
  41. data/app/stylesheets/bh/values.css +41 -0
  42. data/app/stylesheets/bh.css +13 -0
  43. data/build.mjs +15 -0
  44. data/config/locales/bh.en.yml +13 -0
  45. data/lib/bh/engine.rb +21 -6
  46. data/lib/bh/form_builder/comboboxes.rb +38 -0
  47. data/lib/bh/form_builder/controls.rb +67 -0
  48. data/lib/bh/form_builder/pins.rb +30 -0
  49. data/lib/bh/form_builder.rb +96 -0
  50. data/lib/bh/helpers/chats/asides.rb +49 -0
  51. data/lib/bh/helpers/chats/asks.rb +41 -0
  52. data/lib/bh/helpers/chats.rb +42 -0
  53. data/lib/bh/helpers/dialogs.rb +47 -0
  54. data/lib/bh/helpers/flows.rb +49 -0
  55. data/lib/bh/helpers/heads.rb +27 -0
  56. data/lib/bh/helpers/notices.rb +55 -0
  57. data/lib/bh/helpers.rb +12 -0
  58. data/lib/bh/message.rb +11 -0
  59. data/lib/bh/version.rb +2 -3
  60. data/lib/bh.rb +8 -6
  61. data/package.json +32 -0
  62. data/public/bh/css/bh.css +1 -0
  63. data/public/bh/js/bh.js +152 -0
  64. data/vendor/bootstrap.bundle.min.js +9 -0
  65. data/vendor/bootstrap.min.css +2 -0
  66. metadata +101 -23
  67. data/.gitignore +0 -23
  68. data/.rspec +0 -3
  69. data/.travis.yml +0 -15
  70. data/.yardopts +0 -3
  71. data/Gemfile +0 -4
  72. data/app/assets/stylesheets/bh.css +0 -29
  73. data/app/javascript/controllers/bh/theme_controller.js +0 -16
  74. data/app/javascript/controllers/phone_controller.js +0 -33
  75. data/app/javascript/controllers/require_controller.js +0 -20
  76. data/app/javascript/controllers/submit_controller.js +0 -24
  77. data/app/views/bh/_grid.html.erb +0 -6
  78. data/app/views/bh/_table.html.erb +0 -44
  79. data/bh.gemspec +0 -19
  80. data/lib/bh/bootstrap_helpers.rb +0 -136
metadata CHANGED
@@ -1,45 +1,124 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bh
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.3
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Claudio Baccigalupo
7
+ - claudiob
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
12
- description: Bh - Bootstrap Helpers
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: actionview
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '8.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '8.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: railties
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '8.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '8.1'
40
+ description: A form builder that dresses every field a page asks for, the components
41
+ Bootstrap ships behavior for and no markup — a combobox, a 6-digit code, a dialog,
42
+ a toast, a thread of messages — and the one stylesheet and script that carry them,
43
+ served by the engine.
13
44
  email:
14
45
  - claudio@houseaccount.com
15
46
  executables: []
16
47
  extensions: []
17
48
  extra_rdoc_files: []
18
49
  files:
19
- - ".gitignore"
20
- - ".rspec"
21
- - ".travis.yml"
22
- - ".yardopts"
23
50
  - CHANGELOG.md
24
- - Gemfile
25
51
  - MIT-LICENSE
26
52
  - README.md
27
- - app/assets/stylesheets/bh.css
28
- - app/javascript/controllers/bh/theme_controller.js
29
- - app/javascript/controllers/phone_controller.js
30
- - app/javascript/controllers/require_controller.js
31
- - app/javascript/controllers/submit_controller.js
32
- - app/views/bh/_grid.html.erb
33
- - app/views/bh/_table.html.erb
34
- - bh.gemspec
53
+ - app/javascript/bh.js
54
+ - app/javascript/bh/bookmark_controller.js
55
+ - app/javascript/bh/clear_controller.js
56
+ - app/javascript/bh/combobox/menu.js
57
+ - app/javascript/bh/combobox_controller.js
58
+ - app/javascript/bh/confirm.js
59
+ - app/javascript/bh/density_controller.js
60
+ - app/javascript/bh/deselect_controller.js
61
+ - app/javascript/bh/flash.js
62
+ - app/javascript/bh/limit_controller.js
63
+ - app/javascript/bh/map/loader.js
64
+ - app/javascript/bh/map_controller.js
65
+ - app/javascript/bh/otp/slots.js
66
+ - app/javascript/bh/otp_controller.js
67
+ - app/javascript/bh/phone_controller.js
68
+ - app/javascript/bh/placeholder_controller.js
69
+ - app/javascript/bh/relative_time_controller.js
70
+ - app/javascript/bh/require_controller.js
71
+ - app/javascript/bh/reveal_controller.js
72
+ - app/javascript/bh/scheme_controller.js
73
+ - app/javascript/bh/search_controller.js
74
+ - app/javascript/bh/shortcuts_controller.js
75
+ - app/javascript/bh/sortable_controller.js
76
+ - app/javascript/bh/thread_controller.js
77
+ - app/javascript/bh/timezone_controller.js
78
+ - app/javascript/bh/toast_controller.js
79
+ - app/javascript/bh/tooltip_controller.js
80
+ - app/javascript/bh/written.js
81
+ - app/javascript/bh/written_controller.js
82
+ - app/stylesheets/bh.css
83
+ - app/stylesheets/bh/base.css
84
+ - app/stylesheets/bh/chat.css
85
+ - app/stylesheets/bh/flow.css
86
+ - app/stylesheets/bh/map.css
87
+ - app/stylesheets/bh/pin.css
88
+ - app/stylesheets/bh/search.css
89
+ - app/stylesheets/bh/shell.css
90
+ - app/stylesheets/bh/table.css
91
+ - app/stylesheets/bh/values.css
92
+ - build.mjs
93
+ - config/locales/bh.en.yml
35
94
  - lib/bh.rb
36
- - lib/bh/bootstrap_helpers.rb
37
95
  - lib/bh/engine.rb
96
+ - lib/bh/form_builder.rb
97
+ - lib/bh/form_builder/comboboxes.rb
98
+ - lib/bh/form_builder/controls.rb
99
+ - lib/bh/form_builder/pins.rb
100
+ - lib/bh/helpers.rb
101
+ - lib/bh/helpers/chats.rb
102
+ - lib/bh/helpers/chats/asides.rb
103
+ - lib/bh/helpers/chats/asks.rb
104
+ - lib/bh/helpers/dialogs.rb
105
+ - lib/bh/helpers/flows.rb
106
+ - lib/bh/helpers/heads.rb
107
+ - lib/bh/helpers/notices.rb
108
+ - lib/bh/message.rb
38
109
  - lib/bh/version.rb
39
- homepage: http://github.com/claudiob/bh
110
+ - package.json
111
+ - public/bh/css/bh.css
112
+ - public/bh/js/bh.js
113
+ - vendor/bootstrap.bundle.min.js
114
+ - vendor/bootstrap.min.css
115
+ homepage: https://github.com/claudiob/bh
40
116
  licenses:
41
117
  - MIT
42
- metadata: {}
118
+ metadata:
119
+ source_code_uri: https://github.com/claudiob/bh
120
+ changelog_uri: https://github.com/claudiob/bh/blob/master/CHANGELOG.md
121
+ documentation_uri: https://rubydoc.info/gems/bh
43
122
  rdoc_options: []
44
123
  require_paths:
45
124
  - lib
@@ -47,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
47
126
  requirements:
48
127
  - - ">="
49
128
  - !ruby/object:Gem::Version
50
- version: '3.0'
129
+ version: 3.2.0
51
130
  required_rubygems_version: !ruby/object:Gem::Requirement
52
131
  requirements:
53
132
  - - ">="
@@ -56,6 +135,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
135
  requirements: []
57
136
  rubygems_version: 4.0.3
58
137
  specification_version: 4
59
- summary: Bh provides a set of powerful helpers that streamlines the use of Bootstrap
60
- components in Rails views.
138
+ summary: Bootstrap 6 in a Rails app, with the markup already written.
61
139
  test_files: []
data/.gitignore DELETED
@@ -1,23 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- *.bundle
19
- *.so
20
- *.o
21
- *.a
22
- _site/
23
- mkmf.log
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --fail-fast
data/.travis.yml DELETED
@@ -1,15 +0,0 @@
1
- language: ruby
2
- notifications:
3
- email: true
4
- sudo: false
5
- matrix:
6
- include:
7
- - rvm: 1.9.3
8
- gemfile: gemfiles/Gemfile.rails-3.x
9
- before_install:
10
- - gem update --system 2.4.8
11
- - rvm: 2.0.0
12
- gemfile: gemfiles/Gemfile.rails-4.x
13
- - rvm: 2.2.4
14
- gemfile: gemfiles/Gemfile.rails-5.x
15
- env: ONLY_RAILS=true
data/.yardopts DELETED
@@ -1,3 +0,0 @@
1
- --no-private
2
- --markup markdown
3
- --hide-api private
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in bh.gemspec
4
- gemspec
@@ -1,29 +0,0 @@
1
- /*
2
- * This file contains overrides to Bootstrap styles.
3
- *
4
- * Each override must be justified and explained with a comment.
5
- */
6
-
7
- /* ensure highlighted text from a search is not separated from the rest of the word */
8
- mark { padding: 0 }
9
-
10
- /* make the base font size readable */
11
- :root {--bs-body-font-size: 1rem}
12
-
13
- /* ensure a field placeholder is not confused for an actual value */
14
- .form-control::placeholder { opacity: 0.35 }
15
-
16
- /* make radio buttons bigger */
17
- input[type=radio] { transform:scale(1.5); margin-right: .75rem }
18
-
19
- /* make the label around radio buttons colored when checked */
20
- label:has(input[type=radio]:checked) { background-color: var(--bs-primary-bg-subtle); border-color: var(--bs-primary-border) }
21
-
22
- /* Fixes bugs in Bootstrap 6.0@alpha1 where some colors are undefined */
23
- .form-text { color: var(--bs-secondary-text) }
24
- :root {
25
- --bs-form-valid-color: var(--bs-success-text);
26
- --bs-form-valid-border-color: var(--bs-success-border);
27
- --bs-form-invalid-color: var(--bs-danger-text);
28
- --bs-form-invalid-border-color: var(--bs-danger-border);
29
- }
@@ -1,16 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
-
3
- // Toggle color theme between dark and light when the element is clicked.
4
- export default class extends Controller {
5
- connect() {
6
- document.documentElement.setAttribute('data-bs-theme', localStorage.getItem('theme'))
7
- }
8
-
9
- // Toggle color theme between dark and light when the element is clicked.
10
- toggle() {
11
- const oldTheme = localStorage.getItem('theme') || 'light'
12
- const newTheme = ((oldTheme == 'light') ? 'dark' : 'light')
13
- document.documentElement.setAttribute('data-bs-theme', newTheme)
14
- localStorage.setItem('theme', newTheme)
15
- }
16
- }
@@ -1,33 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
-
3
- export default class extends Controller {
4
- connect() {
5
- this.#format(this.element)
6
- }
7
-
8
- down(event) {
9
- if (!event.key) { return }
10
- if (event.ctrlKey) { return }
11
- if (event.metaKey) { return }
12
- if (event.key.length > 1) { return }
13
- if (/[0-9.]/.test(event.key)) { return }
14
- event.preventDefault()
15
- }
16
-
17
- input(event) {
18
- if (event.inputType === 'deleteContentBackward') { return }
19
- if (/[\d-]{12}/.test(event.target.value)) { event.preventDefault() }
20
- this.#format(event.target)
21
- }
22
-
23
- #format(element) {
24
- const digits = element.value.replace(/\D/g,'').substring(0, 10)
25
- const areaCode = digits.substring(0, 3)
26
- const prefix = digits.substring(3, 6)
27
- const suffix = digits.substring(6, 10)
28
-
29
- if (digits.length > 5) { element.value = `${areaCode}-${prefix}-${suffix}` }
30
- else if (digits.length > 2) { element.value = `${areaCode}-${prefix}` }
31
- else if (digits.length > 0) { element.value = `${areaCode}` }
32
- }
33
- }
@@ -1,20 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
-
3
- // If enabled on a form then disables any submit button in the form unless
4
- // all the required inputs have values.
5
- export default class extends Controller {
6
- connect() {
7
- this.toggle()
8
- this.element.querySelectorAll('[required').forEach((input) =>
9
- input.addEventListener('input', () => {this.toggle()})
10
- )
11
- }
12
-
13
- // Disables the button if all chekboxes are unchecked.
14
- toggle() {
15
- const invalidValues = this.element.querySelectorAll('[required]:invalid')
16
- const submitButtons = this.element.querySelectorAll('input[type="submit"]')
17
- const disable = (invalidValues.length > 0);
18
- [...submitButtons].map(button => button.disabled = disable)
19
- }
20
- }
@@ -1,24 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
-
3
- // If enabled on a collection of checkboxes or radio buttons then disables any submit button in the
4
- // form unless at least one checkbox/radio with a value is picked or a textarea is filled.
5
- export default class extends Controller {
6
- static targets = [ 'textarea' ]
7
-
8
- connect() {
9
- this.#toggle()
10
- this.element.querySelectorAll('input').forEach((input) =>
11
- input.addEventListener('change', () => {this.#toggle()})
12
- )
13
- this.textareaTarget.addEventListener('input', () => {this.#toggle()})
14
- }
15
-
16
- // Disables the button if all valued chekboxes are unchecked and textareas are empty.
17
- #toggle() {
18
- const textareaValue = this.textareaTarget.value.trim()
19
- const checkedBoxes = this.element.querySelectorAll('input:checked:not([value=""])')
20
- const submitButtons = this.element.querySelectorAll('input[type="submit"]')
21
- const disable = (checkedBoxes.length == 0 && textareaValue.length == 0);
22
- [...submitButtons].map(button => button.disabled = disable)
23
- }
24
- }
@@ -1,6 +0,0 @@
1
- <%# locals: (item:, cached: true) -%>
2
- <% cache_if cached, item do %>
3
- <div class='container-fluid m-0'>
4
- <%= yield item %>
5
- </div>
6
- <% end %>
@@ -1,44 +0,0 @@
1
- <%# locals: (items:, empty_label:, positioned: false, cached: true, headers: [], pagy: nil) -%>
2
- <% cache_if cached, [items, (items.unscoped.size if cached)].compact do %>
3
- <%= turbo_frame_tag :results, data: { turbo_action: :advance }, class: 'w-100' do %>
4
- <% if items.present? %>
5
- <table class='table caption-top table-hover table-responsive'>
6
- <thead>
7
- <tr>
8
- <% if positioned %>
9
- <th scope='col'></th>
10
- <% end %>
11
- <%= yield items.first, :header %>
12
- </tr>
13
- </thead>
14
- <% if positioned %>
15
- <tbody class='table-group-divider' data-controller='sortable' data-sortable-handle-value='.sortable-handle' data-sortable-resource-name-value='<%= ActiveModel::Naming.param_key items %>' data-sortable-animation-value='200'>
16
- <% else %>
17
- <tbody class='table-group-divider'>
18
- <% end %>
19
- <% items.each do |item| %>
20
- <% if positioned %>
21
- <tr data-sortable-update-url='<%= url_for(action: :update, id: item) %>'>
22
- <td class='sortable-handle text-center' style='cursor: pointer; width: 40px'>⇅</td>
23
- <% else %>
24
- <tr>
25
- <% end %>
26
- <% cache_if (cached && !params.key?(:q)), item do %>
27
- <%= yield item, :body %>
28
- <% end %>
29
- </tr>
30
- <% end %>
31
- </tbody>
32
- </table>
33
-
34
- <% if pagy %>
35
- <div class='d-flex align-items-center'>
36
- <div class='ps-2 flex-grow-1'><%== pagy.info_tag %></div>
37
- <div class='pe-2'><%== pagy.series_nav(:bootstrap, classes: 'pagination mb-0') if pagy.last > 1 %></div>
38
- </div>
39
- <% end %>
40
- <% else %>
41
- <p><%= empty_label %>.</p>
42
- <% end %>
43
- <% end %>
44
- <% end %>
data/bh.gemspec DELETED
@@ -1,19 +0,0 @@
1
- require_relative 'lib/bh/version'
2
-
3
- Gem::Specification.new do |spec|
4
- spec.name = 'bh'
5
- spec.version = Bh::VERSION
6
- spec.authors = ['Claudio Baccigalupo']
7
- spec.email = ['claudio@houseaccount.com']
8
- spec.description = %q{Bh - Bootstrap Helpers}
9
- spec.summary = %q{Bh provides a set of powerful helpers that
10
- streamlines the use of Bootstrap components in Rails views.}
11
- spec.homepage = 'http://github.com/claudiob/bh'
12
- spec.license = 'MIT'
13
-
14
- spec.files = `git ls-files`.split($/)
15
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
- spec.require_paths = ['lib']
17
-
18
- spec.required_ruby_version = '>= 3.0'
19
- end
@@ -1,136 +0,0 @@
1
- module Bh
2
- module BootstrapHelpers
3
- def head_tags
4
- <<~HEAD.html_safe
5
- <meta name='viewport' content='width=device-width,initial-scale=1'>
6
- <meta name='view-transition' content='same-origin'>
7
- <meta name='turbo-refresh-method' content='morph'>
8
- <meta name='turbo-refresh-scroll' content='preserve'>
9
- <meta name='apple-mobile-web-app-capable' content='yes'>
10
- <meta name='mobile-web-app-capable' content='yes'>
11
- <meta name='color-scheme' content='light dark'>
12
- #{csrf_meta_tags}
13
- #{csp_meta_tag}
14
- <script async src="https://ga.jspm.io/npm:es-module-shims@1.8.2/dist/es-module-shims.js" data-turbo-track="reload"></script>
15
- #{javascript_importmap_tags}
16
- <link rel='icon' href="/favicon#{'-dev' if Rails.env.development?}.png" type='image/png'>
17
- <link rel="apple-touch-icon" href="/apple-touch-icon.png">
18
- <link href='https://assets.houseaccount.com/css/bootstrap.min.css' rel='stylesheet'>
19
- <!-- once it's live: <link href="https://cdn.jsdelivr.net/npm/bootstrap@6.0.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-VuYVTUAUbEW1A1EgqVmiLTxfqmvVgsV8yG3KeYZmz8aLednYx2pzlYdT4NS041oo" crossorigin="anonymous"> -->
20
- #{stylesheet_link_tag :app, 'data-turbo-track': 'reload'}
21
- #{stylesheet_link_tag :bh, 'data-turbo-track': 'reload'}
22
- HEAD
23
- end
24
-
25
- def script_tags
26
- <<~SCRIPTS.html_safe
27
- <script src='https://assets.houseaccount.com/js/bootstrap.bundle.min.js'></script>
28
- <!-- once it's live: <script src="https://cdn.jsdelivr.net/npm/bootstrap@6.0.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-kBqjI9J+3T2+popvAtxRzS3v5xO7BkyKlAyF/GZgnB0kZ2HoQdx6V1I/EX8ljPWj" crossorigin="anonymous"></script> -->
29
- SCRIPTS
30
- end
31
-
32
- def navbar(options = {}, &block)
33
- tag.div class: 'mb-4 border-bottom shadow-sm' do
34
- tag.nav class: 'navbar navbar-expand-lg' do
35
- tag.div **options, &block
36
- end
37
- end
38
- end
39
-
40
- def navbar_brand(brand)
41
- tag.div brand, class: 'navbar-brand', data: { controller: 'bh--theme', action: 'dblclick->bh--theme#toggle' }
42
- end
43
-
44
- def card(tabs:, &block)
45
- tag.div class: 'card' do
46
- safe_join [card_header(tabs: tabs), card_body(&block)]
47
- end
48
- end
49
-
50
- def nav(pills:)
51
- tag.ul pills, class:'nav nav-pills border-bottom pb-3 mb-3'
52
- end
53
-
54
- def navbar_nav(&block)
55
- tag.ul class: 'nav navbar-nav me-auto', &block
56
- end
57
-
58
- # @return [String] wraps link_to into a nav-item tab.
59
- def nav_link_to(name, options, &block)
60
- options.merge! nav_link_options_for(options) if block_given?
61
- tag.li(class: 'nav-item') { link_to name, options, nav_link_options_for(options), &block }
62
- end
63
-
64
- def nav_link_options_for(path)
65
- if current_page?(path) # request.path.starts_with? path
66
- { class: 'nav-link active', aria: { current: :page } }
67
- else
68
- { class: 'nav-link' }
69
- end
70
- end
71
-
72
- def navbar_collapsable(&block)
73
- safe_join [navbar_toggler, navbar_collapse(&block)]
74
- end
75
-
76
- def navbar_toggler
77
- tag.button class: 'navbar-toggler', type: 'button', data: {'bs-toggle': 'collapse', 'bs-target': '#navbarSupportedContent'}, aria: {controls: 'navbarSupportedContent', expanded: 'false', label: 'Toggle navigation'} do
78
- tag.span nil, class: 'navbar-toggler-icon'
79
- end
80
- end
81
-
82
- def navbar_collapse(&block)
83
- tag.div class: 'collapse navbar-collapse', id: 'navbarSupportedContent', &block
84
- end
85
-
86
- def table(items:, empty_label:, positioned: false, cached: true, pagy: nil, &block)
87
- render 'bh/table', items: items, empty_label: empty_label, positioned: positioned, cached: cached, headers: headers, pagy: pagy, &block
88
- end
89
-
90
- def column(header:, section:, **options, &block)
91
- case section
92
- when :header then tag.th(header, **options.merge(scope: :col))
93
- when :body then tag.td(**options, &block)
94
- end
95
- end
96
-
97
- # Renders the block inside a grid row.
98
- def grid_row(&block)
99
- tag.div class: 'row p-2 border-bottom border-subtle', &block
100
- end
101
-
102
- # Renders key and value next to each other inside a grid row.
103
- def grid_column(key, value)
104
- left = tag.div key, class: 'col-3 p-2 fst-italic'
105
- right = tag.div value, class: 'col p-2'
106
- safe_join [ left, right ]
107
- end
108
-
109
- def grid(item:, cached: true, &block)
110
- render 'bh/grid', item: item, cached: cached, &block
111
- end
112
-
113
- # Returns a link_to that opens the link outside of the current turbo frame.
114
- # @note Helpful for links within an administered/table that uses +turbo_action: :advance+.
115
- def turbo_link_to(name, options, html_options = {})
116
- link_to name, options, html_options.merge(data: { turbo_frame: '_top' })
117
- end
118
-
119
- # Display a link with an emoji to edit a resource inside a table.
120
- def edit_link_to(path)
121
- turbo_link_to '➡️', path, class: 'text-decoration-none'
122
- end
123
-
124
- private
125
-
126
- def card_header(tabs:)
127
- tag.div class:'card-header' do
128
- tag.ul tabs, class: 'nav nav-tabs card-header-tabs'
129
- end
130
- end
131
-
132
- def card_body(&block)
133
- tag.div class: 'card-body py-4', &block
134
- end
135
- end
136
- end