bh 6.1.4 → 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 +38 -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 -137
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.4
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,137 +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
- <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css" rel="stylesheet">
21
- #{stylesheet_link_tag :app, 'data-turbo-track': 'reload'}
22
- #{stylesheet_link_tag :bh, 'data-turbo-track': 'reload'}
23
- HEAD
24
- end
25
-
26
- def script_tags
27
- <<~SCRIPTS.html_safe
28
- <script src='https://assets.houseaccount.com/js/bootstrap.bundle.min.js'></script>
29
- <!-- 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> -->
30
- SCRIPTS
31
- end
32
-
33
- def navbar(options = {}, &block)
34
- tag.div class: 'mb-4 border-bottom shadow-sm' do
35
- tag.nav class: 'navbar navbar-expand-lg' do
36
- tag.div **options, &block
37
- end
38
- end
39
- end
40
-
41
- def navbar_brand(brand)
42
- tag.div brand, class: 'navbar-brand', data: { controller: 'bh--theme', action: 'dblclick->bh--theme#toggle' }
43
- end
44
-
45
- def card(tabs:, &block)
46
- tag.div class: 'card' do
47
- safe_join [card_header(tabs: tabs), card_body(&block)]
48
- end
49
- end
50
-
51
- def nav(pills:)
52
- tag.ul pills, class:'nav nav-pills border-bottom pb-3 mb-3'
53
- end
54
-
55
- def navbar_nav(&block)
56
- tag.ul class: 'nav navbar-nav me-auto', &block
57
- end
58
-
59
- # @return [String] wraps link_to into a nav-item tab.
60
- def nav_link_to(name, options, &block)
61
- options.merge! nav_link_options_for(options) if block_given?
62
- tag.li(class: 'nav-item') { link_to name, options, nav_link_options_for(options), &block }
63
- end
64
-
65
- def nav_link_options_for(path)
66
- if current_page?(path) # request.path.starts_with? path
67
- { class: 'nav-link active', aria: { current: :page } }
68
- else
69
- { class: 'nav-link' }
70
- end
71
- end
72
-
73
- def navbar_collapsable(&block)
74
- safe_join [navbar_toggler, navbar_collapse(&block)]
75
- end
76
-
77
- def navbar_toggler
78
- tag.button class: 'navbar-toggler', type: 'button', data: {'bs-toggle': 'collapse', 'bs-target': '#navbarSupportedContent'}, aria: {controls: 'navbarSupportedContent', expanded: 'false', label: 'Toggle navigation'} do
79
- tag.span nil, class: 'navbar-toggler-icon'
80
- end
81
- end
82
-
83
- def navbar_collapse(&block)
84
- tag.div class: 'collapse navbar-collapse', id: 'navbarSupportedContent', &block
85
- end
86
-
87
- def table(items:, empty_label:, positioned: false, cached: true, pagy: nil, &block)
88
- render 'bh/table', items: items, empty_label: empty_label, positioned: positioned, cached: cached, headers: headers, pagy: pagy, &block
89
- end
90
-
91
- def column(header:, section:, **options, &block)
92
- case section
93
- when :header then tag.th(header, **options.merge(scope: :col))
94
- when :body then tag.td(**options, &block)
95
- end
96
- end
97
-
98
- # Renders the block inside a grid row.
99
- def grid_row(&block)
100
- tag.div class: 'row p-2 border-bottom border-subtle', &block
101
- end
102
-
103
- # Renders key and value next to each other inside a grid row.
104
- def grid_column(key, value)
105
- left = tag.div key, class: 'col-3 p-2 fst-italic'
106
- right = tag.div value, class: 'col p-2'
107
- safe_join [ left, right ]
108
- end
109
-
110
- def grid(item:, cached: true, &block)
111
- render 'bh/grid', item: item, cached: cached, &block
112
- end
113
-
114
- # Returns a link_to that opens the link outside of the current turbo frame.
115
- # @note Helpful for links within an administered/table that uses +turbo_action: :advance+.
116
- def turbo_link_to(name, options, html_options = {})
117
- link_to name, options, html_options.merge(data: { turbo_frame: '_top' })
118
- end
119
-
120
- # Display a link with an emoji to edit a resource inside a table.
121
- def edit_link_to(path)
122
- turbo_link_to '➡️', path, class: 'text-decoration-none'
123
- end
124
-
125
- private
126
-
127
- def card_header(tabs:)
128
- tag.div class:'card-header' do
129
- tag.ul tabs, class: 'nav nav-tabs card-header-tabs'
130
- end
131
- end
132
-
133
- def card_body(&block)
134
- tag.div class: 'card-body py-4', &block
135
- end
136
- end
137
- end