bootstrap4_rails_components 0.1.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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +362 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/config/bootstrap4_rails_components_manifest.js +3 -0
  6. data/app/assets/javascripts/bootstrap4_rails_components/application.js +8 -0
  7. data/app/assets/javascripts/bootstrap4_rails_components/vendor/tooltips.js +42 -0
  8. data/app/assets/stylesheets/bootstrap4_rails_components/bootstrap/application.scss +2 -0
  9. data/app/controllers/bootstrap4_rails_components/application_controller.rb +5 -0
  10. data/app/helpers/bootstrap4_rails_components/application_helper.rb +38 -0
  11. data/app/models/bootstrap4_rails_components/application_record.rb +5 -0
  12. data/config/initializers/web_app_manifest.rb +3 -0
  13. data/config/locales/en.yml +63 -0
  14. data/config/routes.rb +2 -0
  15. data/config/spring.rb +1 -0
  16. data/lib/bootstrap4_rails_components.rb +75 -0
  17. data/lib/bootstrap4_rails_components/bootstrap/components/alert.rb +52 -0
  18. data/lib/bootstrap4_rails_components/bootstrap/components/badge.rb +39 -0
  19. data/lib/bootstrap4_rails_components/bootstrap/components/base.rb +151 -0
  20. data/lib/bootstrap4_rails_components/bootstrap/components/breadcrumb.rb +23 -0
  21. data/lib/bootstrap4_rails_components/bootstrap/components/breadcrumb_item.rb +28 -0
  22. data/lib/bootstrap4_rails_components/bootstrap/components/button.rb +74 -0
  23. data/lib/bootstrap4_rails_components/bootstrap/components/button_group.rb +36 -0
  24. data/lib/bootstrap4_rails_components/bootstrap/components/button_toolbar.rb +21 -0
  25. data/lib/bootstrap4_rails_components/bootstrap/components/card.rb +81 -0
  26. data/lib/bootstrap4_rails_components/bootstrap/components/card_body.rb +15 -0
  27. data/lib/bootstrap4_rails_components/bootstrap/components/card_footer.rb +15 -0
  28. data/lib/bootstrap4_rails_components/bootstrap/components/card_header.rb +35 -0
  29. data/lib/bootstrap4_rails_components/bootstrap/components/card_image.rb +33 -0
  30. data/lib/bootstrap4_rails_components/bootstrap/components/card_image_overlay.rb +46 -0
  31. data/lib/bootstrap4_rails_components/bootstrap/components/carousel.rb +57 -0
  32. data/lib/bootstrap4_rails_components/bootstrap/components/carousel_caption.rb +34 -0
  33. data/lib/bootstrap4_rails_components/bootstrap/components/carousel_control.rb +73 -0
  34. data/lib/bootstrap4_rails_components/bootstrap/components/carousel_indicators.rb +54 -0
  35. data/lib/bootstrap4_rails_components/bootstrap/components/carousel_item.rb +49 -0
  36. data/lib/bootstrap4_rails_components/bootstrap/components/collapse.rb +32 -0
  37. data/lib/bootstrap4_rails_components/bootstrap/components/dropdown.rb +51 -0
  38. data/lib/bootstrap4_rails_components/bootstrap/components/dropdown_divider.rb +19 -0
  39. data/lib/bootstrap4_rails_components/bootstrap/components/dropdown_header.rb +23 -0
  40. data/lib/bootstrap4_rails_components/bootstrap/components/dropdown_item.rb +41 -0
  41. data/lib/bootstrap4_rails_components/bootstrap/components/dropdown_menu.rb +32 -0
  42. data/lib/bootstrap4_rails_components/bootstrap/components/dropdown_toggle.rb +82 -0
  43. data/lib/bootstrap4_rails_components/bootstrap/components/embed.rb +80 -0
  44. data/lib/bootstrap4_rails_components/bootstrap/components/form.rb +13 -0
  45. data/lib/bootstrap4_rails_components/bootstrap/components/input_group.rb +13 -0
  46. data/lib/bootstrap4_rails_components/bootstrap/components/jumbotron.rb +13 -0
  47. data/lib/bootstrap4_rails_components/bootstrap/components/list_group.rb +39 -0
  48. data/lib/bootstrap4_rails_components/bootstrap/components/list_group_item.rb +69 -0
  49. data/lib/bootstrap4_rails_components/bootstrap/components/media.rb +15 -0
  50. data/lib/bootstrap4_rails_components/bootstrap/components/media_body.rb +15 -0
  51. data/lib/bootstrap4_rails_components/bootstrap/components/media_object.rb +23 -0
  52. data/lib/bootstrap4_rails_components/bootstrap/components/modal.rb +66 -0
  53. data/lib/bootstrap4_rails_components/bootstrap/components/modal_body.rb +16 -0
  54. data/lib/bootstrap4_rails_components/bootstrap/components/modal_footer.rb +16 -0
  55. data/lib/bootstrap4_rails_components/bootstrap/components/modal_header.rb +37 -0
  56. data/lib/bootstrap4_rails_components/bootstrap/components/nav.rb +71 -0
  57. data/lib/bootstrap4_rails_components/bootstrap/components/nav_item.rb +103 -0
  58. data/lib/bootstrap4_rails_components/bootstrap/components/nav_link.rb +62 -0
  59. data/lib/bootstrap4_rails_components/bootstrap/components/navbar.rb +97 -0
  60. data/lib/bootstrap4_rails_components/bootstrap/components/navbar_brand.rb +25 -0
  61. data/lib/bootstrap4_rails_components/bootstrap/components/navbar_nav.rb +48 -0
  62. data/lib/bootstrap4_rails_components/bootstrap/components/navbar_text.rb +21 -0
  63. data/lib/bootstrap4_rails_components/bootstrap/components/navbar_toggler.rb +38 -0
  64. data/lib/bootstrap4_rails_components/bootstrap/components/page_item.rb +66 -0
  65. data/lib/bootstrap4_rails_components/bootstrap/components/pagination.rb +30 -0
  66. data/lib/bootstrap4_rails_components/bootstrap/components/popover.rb +12 -0
  67. data/lib/bootstrap4_rails_components/bootstrap/components/progress.rb +44 -0
  68. data/lib/bootstrap4_rails_components/bootstrap/components/progress_bar.rb +51 -0
  69. data/lib/bootstrap4_rails_components/bootstrap/components/tab_content.rb +15 -0
  70. data/lib/bootstrap4_rails_components/bootstrap/components/tab_pane.rb +49 -0
  71. data/lib/bootstrap4_rails_components/bootstrap/components/table.rb +17 -0
  72. data/lib/bootstrap4_rails_components/bootstrap/readme.md +1 -0
  73. data/lib/bootstrap4_rails_components/bootstrap/utilities/activatable.rb +32 -0
  74. data/lib/bootstrap4_rails_components/bootstrap/utilities/alignable.rb +33 -0
  75. data/lib/bootstrap4_rails_components/bootstrap/utilities/collapse_toggleable.rb +35 -0
  76. data/lib/bootstrap4_rails_components/bootstrap/utilities/collapsible.rb +42 -0
  77. data/lib/bootstrap4_rails_components/bootstrap/utilities/disableable.rb +49 -0
  78. data/lib/bootstrap4_rails_components/bootstrap/utilities/dismissible.rb +24 -0
  79. data/lib/bootstrap4_rails_components/bootstrap/utilities/dropdown_directionable.rb +40 -0
  80. data/lib/bootstrap4_rails_components/bootstrap/utilities/headable.rb +20 -0
  81. data/lib/bootstrap4_rails_components/bootstrap/utilities/modalable.rb +104 -0
  82. data/lib/bootstrap4_rails_components/bootstrap/utilities/progressable.rb +42 -0
  83. data/lib/bootstrap4_rails_components/bootstrap/utilities/remotable.rb +24 -0
  84. data/lib/bootstrap4_rails_components/bootstrap/utilities/sizable.rb +40 -0
  85. data/lib/bootstrap4_rails_components/bootstrap/utilities/themeable.rb +51 -0
  86. data/lib/bootstrap4_rails_components/bootstrap/utilities/titleable.rb +20 -0
  87. data/lib/bootstrap4_rails_components/bootstrap/utilities/tooltipable.rb +95 -0
  88. data/lib/bootstrap4_rails_components/bootstrap/utilities/wrappable.rb +48 -0
  89. data/lib/bootstrap4_rails_components/engine.rb +38 -0
  90. data/lib/bootstrap4_rails_components/ui/base.rb +42 -0
  91. data/lib/bootstrap4_rails_components/ui/bootstrap.rb +44 -0
  92. data/lib/bootstrap4_rails_components/ui/utilities.rb +10 -0
  93. data/lib/bootstrap4_rails_components/ui/utilities/initializer.rb +88 -0
  94. data/lib/bootstrap4_rails_components/version.rb +5 -0
  95. metadata +372 -0
@@ -0,0 +1,5 @@
1
+ module Bootstrap4RailsComponents
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bootstrap4RailsComponents
4
+ # Core rendering helper methods
5
+ module ApplicationHelper
6
+ # `ui` is an initiator method so that this system allows for
7
+ # extension when used in a cascade of frameworks, for example when
8
+ # building a custom design system that is based on Bootstrap4.
9
+ # One would utilize this the `ui` method to initiate this engine
10
+ # and then call a specific framework / system as a second method.
11
+ #
12
+ # Example use for bootstrap4:
13
+ # <%= ui.bootstrap(:my_component, :optional_trait1, :optional_trait2, option: :value, option2: :value2) %>
14
+ #
15
+ # Real-world usage:
16
+ # A normal button link with a tooltip:
17
+ # <%= ui.bootstrap(:button, :primary, body: 'Get Started', href: marketing_page_path, tooltip: 'Save big!') %>
18
+ #
19
+ # A complex ajax-y delete button:
20
+ # <%= ui.bootstrap(:button, :primary, disabled: user.payments.any?, method: :delete, href: user_path(user), confirm: "Please confirm #{user.name} should be deleted", disable_with: ui.bootstrap(:icon, :loader), remote: true, tooltip: "Permanently delete #{user.name}" render_if: user.admin?) %>
21
+ def ui
22
+ @ui ||= Bootstrap4RailsComponents::UI::Base.new(get_view_context)
23
+ end
24
+
25
+ private
26
+
27
+ # In the event that a controller isn't defined, we'll supply ApplicationController's view_context, instead.
28
+ # While not ideal, this'll work for basic implementation scenarios that aren't leaning heavily on the
29
+ # view_context in play.
30
+ def get_view_context
31
+ if defined?(controller) && controller.present?
32
+ controller.view_context
33
+ else
34
+ ApplicationController.new.view_context
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ module Bootstrap4RailsComponents
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.config.assets.configure do |env|
2
+ env.register_mime_type('application/manifest+json', extensions: ['.webmanifest'])
3
+ end
@@ -0,0 +1,63 @@
1
+ en:
2
+ bootstrap4_rails_components:
3
+ errors:
4
+ argument_error:
5
+ # required keys -- :modal, :class_name, :options, :file, :method
6
+ #
7
+ # Example keys:
8
+ #
9
+ # modal: '#example'
10
+ # class_name: self.class.name
11
+ # options: options
12
+ # file: __FILE__
13
+ # method: __method__
14
+ modalable:
15
+ tooltip: |
16
+ ArgumentError: :modal & :tooltip may not both be present in :options hash
17
+
18
+ Raised from gem file: %{file}
19
+ Raised from gem method: #%{method}
20
+
21
+ To fix this error:
22
+ Remove `tooltip: [the tooltip]` or `modal: '%{modal}'` from your component's :options hash
23
+
24
+ Component Reference:
25
+ Invalid component: %{class_name}
26
+ Component options: %{options}
27
+
28
+ About:
29
+ Modal and Tooltip both utilize the data-toggle HTML data attribute. When :modal is present,
30
+ it will always overwrite the tooltip's data-toggle attribute causing a silent failure
31
+ in which the tooltip does not render (though the modal HTML does).
32
+
33
+ remote: |
34
+ ArgumentError: :modal & remote: true may not both be present in :options hash
35
+
36
+ Raised from gem file: %{file}
37
+ Raised from gem method: #%{method}
38
+
39
+ To fix this error:
40
+ Remove `remote: true` or `modal: '%{modal}'` from your component's :options hash
41
+
42
+ Example incorrect usage:
43
+ = ui.bootstrap :button, remote: true, modal: '%{modal}', ...
44
+
45
+ Component Reference:
46
+ Invalid component: %{class_name}
47
+ Component options: %{options}
48
+
49
+ About:
50
+ Components may not include both `modal: %{modal}` and `remote: true` in their options because modalable components
51
+ that fire remote actions can result in undesirable modal activation behavior.
52
+
53
+ This tends to occur when a modal is injected into the page from a remote action, is subsequently dismissed
54
+ and then opened again from the same remote link.
55
+
56
+ The previously dismissed modal appears (because it's still on the page, and referenced in the component's HTML)
57
+ and the modal is then, visibly to the user, re-animated (overwritten and re-started) by the newly injected modal from the remote ajax action.
58
+
59
+
60
+
61
+
62
+
63
+
@@ -0,0 +1,2 @@
1
+ Bootstrap4RailsComponents::Engine.routes.draw do
2
+ end
@@ -0,0 +1 @@
1
+ Spring.application_root = './spec/test_app'
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bootstrap4_rails_components/engine'
4
+
5
+ module Bootstrap4RailsComponents
6
+ require 'bootstrap'
7
+ require 'haml'
8
+ require 'jquery-rails'
9
+ require 'sass-rails'
10
+
11
+ DEFAULT_BOOTSTRAP_THEME = :primary
12
+
13
+ BOOTSTRAP_THEMES = %i[primary
14
+ secondary
15
+ success
16
+ danger
17
+ warning
18
+ info
19
+ light
20
+ dark].freeze
21
+
22
+ BOOTSTRAP_COMPONENT_NAMES = %i[alert
23
+ badge
24
+ breadcrumb
25
+ breadcrumb_item
26
+ button
27
+ button_group
28
+ button_toolbar
29
+ card
30
+ card_body
31
+ card_footer
32
+ card_header
33
+ card_image
34
+ card_image_overlay
35
+ carousel
36
+ carousel_caption
37
+ carousel_control
38
+ carousel_indicators
39
+ carousel_item
40
+ collapse
41
+ dropdown
42
+ dropdown_divider
43
+ dropdown_header
44
+ dropdown_item
45
+ dropdown_menu
46
+ dropdown_toggle
47
+ embed
48
+ form
49
+ input_group
50
+ jumbotron
51
+ list_group
52
+ list_group_item
53
+ media
54
+ media_body
55
+ media_object
56
+ modal
57
+ modal_body
58
+ modal_footer
59
+ modal_header
60
+ nav
61
+ nav_item
62
+ nav_link
63
+ navbar
64
+ navbar_brand
65
+ navbar_nav
66
+ navbar_text
67
+ navbar_toggler
68
+ page_item
69
+ pagination
70
+ popover
71
+ progress
72
+ tab_content
73
+ tab_pane
74
+ table].freeze
75
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bootstrap4RailsComponents
4
+ module Bootstrap
5
+ module Components
6
+ # Bootstrap Alert Component
7
+ # https://getbootstrap.com/docs/4.1/components/alerts/
8
+ class Alert < Bootstrap4RailsComponents::Bootstrap::Components::Base
9
+ include Bootstrap::Utilities::Dismissible
10
+ include Bootstrap::Utilities::Headable
11
+ include Bootstrap::Utilities::Themeable
12
+
13
+ def render
14
+ content_tag(:div, html_options) do
15
+ capture do
16
+ if dismissible
17
+ concat(
18
+ Bootstrap4RailsComponents::Bootstrap::Components::Button.new({ as: :button, class: 'close', theme: nil, data: { dismiss: 'alert' }, aria: { label: 'Close' } }, view_context).render do
19
+ content_tag(:span, "&times;".html_safe, aria: { hidden: 'true' } )
20
+ end
21
+ )
22
+ end
23
+ if heading
24
+ concat(content_tag(:h4, heading, class: 'alert-heading'))
25
+ end
26
+ concat(block_given? ? yield : body)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def assistive_html_attributes
34
+ super.merge!(role: 'alert')
35
+ end
36
+
37
+ def css_classes
38
+ [
39
+ super,
40
+ ("#{component_css_class}-dismissible" if dismissible),
41
+ ('fade' if dismissible),
42
+ ('show' if dismissible)
43
+ ].join(' ').squish
44
+ end
45
+
46
+ def outlineable?
47
+ false
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bootstrap4RailsComponents
4
+ module Bootstrap
5
+ module Components
6
+ # Bootstrap Badge Component
7
+ # https://getbootstrap.com/docs/4.1/components/badge/
8
+ class Badge < Bootstrap4RailsComponents::Bootstrap::Components::Base
9
+ include Bootstrap::Utilities::Themeable
10
+ include Bootstrap::Utilities::Wrappable
11
+
12
+ def pill
13
+ options.fetch(:pill, false)
14
+ end
15
+
16
+ private
17
+
18
+ def base_element
19
+ as #comes from the wrappable module
20
+ end
21
+
22
+ def css_classes
23
+ [
24
+ super,
25
+ ("#{component_css_class}-pill" if pill)
26
+ ].join(' ').squish
27
+ end
28
+
29
+ def default_html_wrapper_element
30
+ :span
31
+ end
32
+
33
+ def non_html_attribute_options
34
+ super.push(:pill)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bootstrap4RailsComponents
4
+ module Bootstrap
5
+ module Components
6
+ # Base Component
7
+ # Defines conventional, shared behavior across
8
+ # Bootstrap components
9
+ class Base
10
+ include ActionView::Helpers::TagHelper
11
+ include ActionView::Helpers::TextHelper
12
+ include ActionView::Helpers::AssetTagHelper
13
+ include ActionView::Context
14
+
15
+ attr_reader :body
16
+
17
+ attr_accessor :options,
18
+ :view_context
19
+
20
+ def initialize(component_options, view_context)
21
+ self.options = defaults.merge!(component_options)
22
+ self.view_context = view_context
23
+ @body = options.fetch(:body, '')
24
+ utility_initialize
25
+ component_initialize
26
+ end
27
+
28
+
29
+ # This base render handles many of the components and
30
+ # can be changed to have a different base element by
31
+ # overriding the base_element.
32
+ # in some cases, the child component can also call
33
+ # super with a block to have this render as the wrapping
34
+ # element.
35
+ def render
36
+ content_tag(base_element, html_options) do
37
+ (block_given? ? yield : body)
38
+ end
39
+ end
40
+
41
+ # This is used to help identify where to find partials for rendering components.
42
+ #
43
+ # Set the component family, e.g.: :breadcrumb
44
+ # on any sibling components.
45
+ #
46
+ # For example:
47
+ # BreadcrumbItem & Breadcrumb are members of the :breadcrumb component_family
48
+ def component_family
49
+ nil
50
+ end
51
+
52
+ def data
53
+ options[:data] || {}
54
+ end
55
+
56
+ def html_options
57
+ options.except(*non_html_attribute_options.uniq)
58
+ .merge!(id: id,
59
+ class: css_classes,
60
+ data: data,
61
+ href: href,
62
+ style: style,
63
+ **assistive_html_attributes)
64
+ .reject { |_k, v| v.blank? } # prevent empty attributes from showing up
65
+ # Example: <div class>Text</div>
66
+ end
67
+
68
+ def href
69
+ options[:href]
70
+ end
71
+
72
+ def id
73
+ options[:id]
74
+ end
75
+
76
+ # For components that inherit bootstrap, provide a second
77
+ # layer of initialization, for example:
78
+ # to initialize traits on design system components
79
+ # (which are not available on bootstrap)
80
+ def component_initialize; end
81
+ def utility_initialize; end
82
+
83
+ def style
84
+ options[:style]
85
+ end
86
+
87
+ private
88
+
89
+ # Assigned on individual components as needed
90
+ # Ex: { role: 'alert' }
91
+ #
92
+ # If aria assistive html is needed, see:
93
+ # Bootstrap::Utilities::AriaAssistable
94
+ # avoid passing aria to assistive_html_attributes directly
95
+ def assistive_html_attributes
96
+ @assistive_html_attributes ||= {}
97
+ end
98
+
99
+ # the base_element is used in the default render for all components
100
+ # as the outer wrapping element. Typically, this is a div, but
101
+ # can be overriddent as a different static element in a child class
102
+ # or as a dynamic element in the child class.
103
+ # this allows most child components to not have to have their
104
+ # own render statement if their wrapping element is not a div
105
+ def base_element
106
+ :div
107
+ end
108
+
109
+ # Fallback component css class name.
110
+ # Overwritten within individual classes for situations like
111
+ # Button's css class is 'btn'...
112
+ # Example: returns 'alert' from Bootstrap4RailsComponents::Bootstrap::Components::Alert
113
+ def component_css_class
114
+ @component_css_class ||= component_class_name_string.underscore.dasherize.downcase
115
+ end
116
+
117
+ def component_class_name_string
118
+ self.class.name.demodulize.to_s
119
+ end
120
+
121
+ # Manage or adjust the css_classes of the component by
122
+ # adding a new string of css classes to this method
123
+ # ex: super.push('new-class')
124
+ def css_classes
125
+ @css_classes ||= [component_css_class, options[:class]].reject(&:nil?).uniq.join(' ').squish
126
+ end
127
+
128
+ def defaults
129
+ {
130
+ # HTML Defaults
131
+ class: '',
132
+ id: nil,
133
+
134
+ # Content
135
+ # heading: (nil if heading.present?),
136
+ body: nil,
137
+ data: {},
138
+
139
+ # Configuration
140
+ # traits: ([] if traits.present?)
141
+ }
142
+ end
143
+ # Remove attributes from html_options that shouldn't show up in the
144
+ # html element, ex: <div body='should not be here'>
145
+ def non_html_attribute_options
146
+ @non_html_attribute_options ||= %i[body heading traits render_if render_unless]
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end