bootstrap4_helper 0.0.0 → 1.0.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.
@@ -0,0 +1,24 @@
1
+ # @root
2
+ #
3
+ #
4
+ module Bootstrap4Helper
5
+ # @description
6
+ # - Naming convention used as to not pollute views where the module is
7
+ # included. @config is a common instance variable name. We don't want
8
+ # to risk overriding another developers variable.
9
+ #
10
+ @_bs4h_config = Configuration.new
11
+
12
+ class << self
13
+ # @description
14
+ # - Simple interface for exposing the configuration object.
15
+ #
16
+ # @return [Bootstrap4Helper::Configuration]
17
+ #
18
+ def config
19
+ yield @_bs4h_config if block_given?
20
+
21
+ @_bs4h_config
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,150 @@
1
+ # @root
2
+ #
3
+ #
4
+ module Bootstrap4Helper
5
+ # @description
6
+ #
7
+ #
8
+ class Modal < Component
9
+ # @description
10
+ # -
11
+ #
12
+ # @param [ActionView] template
13
+ # @param [Hash]
14
+ #
15
+ def initialize(template, opts = {}, &block)
16
+ super(template)
17
+
18
+ @id = opts.fetch(:id, uuid)
19
+ @class = opts.fetch(:class, '')
20
+ @data = opts.fetch(:data, {})
21
+ @scrollable = opts.fetch(:scrollable, false)
22
+ @vcentered = opts.fetch(:vcentered, false)
23
+ @content = block || proc { '' }
24
+ end
25
+
26
+ # @description
27
+ # - Build the header component for the modal.
28
+ #
29
+ # @param [Hash] opts
30
+ #
31
+ def header(opts = {}, &block)
32
+ build_main_component :header, opts, &block
33
+ end
34
+
35
+ # @description
36
+ # - Builds the body component.
37
+ #
38
+ # @param [Hash] opts
39
+ #
40
+ def body(opts = {}, &block)
41
+ build_main_component :body, opts, &block
42
+ end
43
+
44
+ # @description
45
+ # - Builds the footer component.
46
+ #
47
+ # @param [Hash] opts
48
+ #
49
+ def footer(opts = {}, &block)
50
+ build_main_component :footer, opts, &block
51
+ end
52
+
53
+ # @description
54
+ # - Builds a title component.
55
+ #
56
+ # @param [Hash] opts
57
+ #
58
+ def title(opts = {}, &block)
59
+ build_sub_component :h5, :title, opts, &block
60
+ end
61
+
62
+ # @description
63
+ # - Builds a close button component.
64
+ #
65
+ # @param [Hash] opts
66
+ #
67
+ def close_button(opts = {})
68
+ klass = opts.fetch(:class, '')
69
+
70
+ content_tag(
71
+ :button,
72
+ type: 'button',
73
+ class: block_given? ? klass : 'close',
74
+ data: { dismiss: 'modal' },
75
+ aria: { label: 'Close' }
76
+ ) do
77
+ block_given? ? yield : xbutton
78
+ end
79
+ end
80
+
81
+ # @description
82
+ # -
83
+ #
84
+ def to_s
85
+ content_tag :div, id: @id, class: "modal #{@class}", tabindex: -1, role: 'dialog', data: @data do
86
+ content_tag :div, class: "modal-dialog #{scrollable} #{vcentered}", role: 'document' do
87
+ content_tag(:div, class: 'modal-content') { @content.call(self) }
88
+ end
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ # @description
95
+ # - Used to build main components, usually divs.
96
+ #
97
+ # @param [Symbol|String] type
98
+ # @param [Hash] opts
99
+ #
100
+ def build_main_component(type, opts = {}, &block)
101
+ build_sub_component :div, type, opts, &block
102
+ end
103
+
104
+ # @description
105
+ # - Used to build more specific components.
106
+ #
107
+ # @param [Symbol] tag
108
+ # @param [Symbol|String] type
109
+ # @param [Hash] opts
110
+ #
111
+ def build_sub_component(tag, type, opts = {}, &block)
112
+ id = opts.fetch(:id, nil)
113
+ klass = opts.fetch(:class, '')
114
+ data = opts.fetch(:data, {})
115
+
116
+ content_tag(
117
+ tag,
118
+ id: id,
119
+ class: "modal-#{type} #{klass}",
120
+ data: data,
121
+ &block
122
+ )
123
+ end
124
+
125
+ # @description
126
+ # - Builds the `x` button normally used in the header.
127
+ #
128
+ def xbutton
129
+ content_tag :span, '&times;'.html_safe, aria: { hidden: true }
130
+ end
131
+
132
+ # @description
133
+ # - Gets the scrollable CSS class.
134
+ #
135
+ # @return [String]
136
+ #
137
+ def scrollable
138
+ @scrollable ? 'modal-dialog-scrollable' : ''
139
+ end
140
+
141
+ # @description
142
+ # - Gets the vertical-center CSS class.
143
+ #
144
+ # @return [String]
145
+ #
146
+ def vcentered
147
+ @vcentered ? 'modal-dialog-centered' : ''
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,100 @@
1
+ # @root
2
+ #
3
+ #
4
+ module Bootstrap4Helper
5
+ # @description
6
+ # -
7
+ #
8
+ class Nav < Component
9
+ # @description
10
+ # -
11
+ #
12
+ # @param [ActionView] template
13
+ # @param [NilClass|String|Symbol|Hash] context_or_options
14
+ # @param [Hash]
15
+ #
16
+ def initialize(template, opts = {}, &block)
17
+ super(template)
18
+
19
+ @id = opts.fetch(:id, uuid)
20
+ @class = opts.fetch(:class, '')
21
+ @data = opts.fetch(:data, {})
22
+ @child = opts.fetch(:child, {})
23
+ @content = block || proc { '' }
24
+
25
+ @dropdown = Dropdown.new(@template)
26
+ end
27
+
28
+ # @description
29
+ # - Adds an nav-item to the nav component. this method gets used when the nav-item
30
+ # links to content in a tab or something.
31
+ #
32
+ # @param [Symbol|String] target
33
+ # @param [Hash] opts
34
+ #
35
+ # rubocop:disable Metrics/MethodLength
36
+ def item(target, opts = {})
37
+ id = opts.fetch(:id, nil)
38
+ klass = opts.fetch(:class, '')
39
+ data = opts.fetch(:data, {})
40
+ aria = opts.fetch(:aria, {})
41
+
42
+ content_tag :li, id: id, class: 'nav-item', data: data do
43
+ content_tag(
44
+ :a,
45
+ class: "nav-link #{klass}",
46
+ href: "##{target}",
47
+ tabindex: -1,
48
+ data: @child[:data],
49
+ aria: aria
50
+ ) do
51
+ block_given? ? yield : target.to_s.titleize
52
+ end
53
+ end
54
+ end
55
+ # rubocop:enable Metrics/MethodLength
56
+
57
+ # @description
58
+ # - Use this when the nav item is nothing more than a hyperlink.
59
+ #
60
+ def link(name = nil, options = nil, html_options = nil, &block)
61
+ html_options = (html_options || {}).merge(class: 'nav-link')
62
+
63
+ @template.link_to(name, options, html_options, &block)
64
+ end
65
+
66
+ # @description
67
+ # - Creates a dropdown menu for the nav.
68
+ #
69
+ # @param [NilClass|Symbol|String] name
70
+ # @param [Hash] opts
71
+ #
72
+ def dropdown(name, opts = {}, &block)
73
+ id = opts.fetch(:id, nil)
74
+ klass = opts.fetch(:class, '')
75
+ data = opts.fetch(:data, {})
76
+ aria = opts.fetch(:aria, {}).merge(haspopup: true, expanded: false)
77
+
78
+ content_tag :li, id: id, class: 'nav-item dropdown', data: data do
79
+ content_tag(
80
+ :a,
81
+ name,
82
+ class: "nav-link dropdown-toggle #{klass}",
83
+ href: '#',
84
+ data: { toggle: 'dropdown' },
85
+ role: 'button',
86
+ aria: aria
87
+ ) + @dropdown.menu(opts, &block).to_s.html_safe
88
+ end
89
+ end
90
+
91
+ # @description
92
+ # -
93
+ #
94
+ def to_s
95
+ content_tag :ul, id: @id, class: "nav #{@class}" do
96
+ @content.call(self)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -1,4 +1,12 @@
1
1
  module Bootstrap4Helper
2
+ # @description
3
+ #
4
+ #
2
5
  class Railtie < ::Rails::Railtie
6
+ config.after_initialize do
7
+ ActiveSupport.on_load(:action_view) do
8
+ include Bootstrap4Helper if Bootstrap4Helper.config.autoload_in_views?
9
+ end
10
+ end
3
11
  end
4
12
  end
@@ -0,0 +1,41 @@
1
+ # @root
2
+ #
3
+ #
4
+ module Bootstrap4Helper
5
+ # @description
6
+ # - a simple CSS spinner component.
7
+ #
8
+ class Spinner < Component
9
+ # @description
10
+ # -
11
+ #
12
+ # @param [ActionView] template
13
+ # @param [Hash] opts
14
+ #
15
+ def initialize(template, opts = {}, &block)
16
+ super(template)
17
+
18
+ @type = opts.fetch(:type, :border)
19
+ @id = opts.fetch(:id, uuid)
20
+ @class = opts.fetch(:class, '')
21
+ @data = opts.fetch(:data, {})
22
+ @content = block || proc { '' }
23
+ end
24
+
25
+ # @description
26
+ # -
27
+ #
28
+ def to_s
29
+ content_tag(
30
+ :span,
31
+ id: @id,
32
+ class: "spinner-#{@type} #{@class}",
33
+ role: 'status',
34
+ aria: { hidden: true },
35
+ data: @data
36
+ ) do
37
+ content_tag :span, 'Loading', class: 'sr-only'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,66 @@
1
+ # @root
2
+ #
3
+ #
4
+ module Bootstrap4Helper
5
+ # @description
6
+ #
7
+ #
8
+ class Tab < Component
9
+ # @description
10
+ # -
11
+ #
12
+ # @param [ActionView] template
13
+ # @param [Hash] opts
14
+ # @param [Hash]
15
+ #
16
+ def initialize(template, opts = {}, &block)
17
+ super(template)
18
+
19
+ @type = opts.fetch(:type, :tabs)
20
+ @id = opts.fetch(:id, uuid)
21
+ @class = opts.fetch(:class, '')
22
+ @data = opts.fetch(:data, {})
23
+ @content = block || proc { '' }
24
+ end
25
+
26
+ # @description
27
+ # - Builds a custom Nav component for the tabs.
28
+ #
29
+ # @param [Hash] opts
30
+ # @return [Nav]
31
+ #
32
+ def nav(opts = {}, &block)
33
+ opts[:class] = (opts[:class] || '') << " nav-#{@type}"
34
+ opts[:data] = (opts[:data] || {}).merge(toggle: 'tab')
35
+ opts[:child] = {
36
+ data: {
37
+ toggle: 'tab'
38
+ }
39
+ }
40
+
41
+ Nav.new(@template, opts, &block)
42
+ end
43
+
44
+ # @description
45
+ # - Builds the Content object for the Tab.
46
+ #
47
+ # @param [Hash] opts
48
+ # @return [Tab::Content]
49
+ #
50
+ def content(opts = {}, &block)
51
+ Content.new(@template, opts, &block)
52
+ end
53
+
54
+ # @description
55
+ # - This has a weird interaction. Because this object doesn't actually return any wrapping
56
+ # string or DOM element, we want to return nil, so that only the output buffer on the sub components are returned.
57
+ # If we return the return value of the block, we will get the last element added to the input
58
+ # buffer as an unescaped string.
59
+ #
60
+ def to_s
61
+ @content.call(self)
62
+
63
+ nil
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,50 @@
1
+ # @root
2
+ #
3
+ #
4
+ module Bootstrap4Helper
5
+ #
6
+ #
7
+ #
8
+ class Tab
9
+ #
10
+ #
11
+ #
12
+ class Content < Component
13
+ # @description
14
+ # -
15
+ #
16
+ # @param [ActionView] template
17
+ # @param [NilClass|String|Symbol|Hash] context_or_options
18
+ # @param [Hash]
19
+ #
20
+ def initialize(template, opts = {}, &block)
21
+ super(template)
22
+
23
+ @id = opts.fetch(:id, uuid)
24
+ @class = opts.fetch(:class, '')
25
+ @data = opts.fetch(:data, {})
26
+ @content = block || proc { '' }
27
+ end
28
+
29
+ # @description
30
+ # -
31
+ #
32
+ def pane(source, opts = {}, &block)
33
+ id = opts.fetch(:id, nil)
34
+ klass = opts.fetch(:class, '')
35
+ data = opts.fetch(:data, {})
36
+
37
+ content_tag :div, id: source, class: "tab-pane #{klass}", role: 'tabpanel', &block
38
+ end
39
+
40
+ # @description
41
+ # -
42
+ #
43
+ def to_s
44
+ content_tag :div, id: @id, class: "tab-content #{@class}" do
45
+ @content.call(self)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end