primer_view_components 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -1
- data/README.md +135 -0
- data/app/components/primer/avatar_component.rb +28 -0
- data/app/components/primer/base_component.rb +42 -0
- data/app/components/primer/blankslate_component.html.erb +27 -0
- data/app/components/primer/blankslate_component.rb +156 -0
- data/app/components/primer/border_box_component.html.erb +26 -0
- data/app/components/primer/border_box_component.rb +77 -0
- data/app/components/primer/box_component.rb +14 -0
- data/app/components/primer/breadcrumb_component.html.erb +8 -0
- data/app/components/primer/breadcrumb_component.rb +52 -0
- data/app/components/primer/button_component.rb +58 -0
- data/app/components/primer/component.rb +9 -0
- data/app/components/primer/counter_component.rb +78 -0
- data/app/components/primer/details_component.html.erb +6 -0
- data/app/components/primer/details_component.rb +38 -0
- data/app/components/primer/dropdown_menu_component.html.erb +8 -0
- data/app/components/primer/dropdown_menu_component.rb +28 -0
- data/app/components/primer/flex_component.rb +81 -0
- data/app/components/primer/flex_item_component.rb +21 -0
- data/app/components/primer/heading_component.rb +14 -0
- data/app/components/primer/label_component.rb +48 -0
- data/app/components/primer/layout_component.html.erb +17 -0
- data/app/components/primer/layout_component.rb +21 -0
- data/app/components/primer/link_component.rb +19 -0
- data/app/components/primer/progress_bar_component.html.erb +5 -0
- data/app/components/primer/progress_bar_component.rb +66 -0
- data/app/components/primer/slot.rb +8 -0
- data/app/components/primer/state_component.rb +53 -0
- data/app/components/primer/subhead_component.html.erb +17 -0
- data/app/components/primer/subhead_component.rb +89 -0
- data/app/components/primer/text_component.rb +14 -0
- data/app/components/primer/timeline_item_component.html.erb +17 -0
- data/app/components/primer/timeline_item_component.rb +69 -0
- data/app/components/primer/underline_nav_component.html.erb +11 -0
- data/app/components/primer/underline_nav_component.rb +22 -0
- data/app/components/primer/view_components.rb +47 -0
- data/lib/primer/class_name_helper.rb +27 -0
- data/lib/primer/classify.rb +237 -0
- data/lib/primer/fetch_or_fallback_helper.rb +41 -0
- data/lib/primer/view_components.rb +3 -0
- data/lib/primer/view_components/engine.rb +11 -0
- data/lib/primer/view_components/version.rb +1 -1
- metadata +159 -4
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class FlexItemComponent < Primer::Component
|
5
|
+
FLEX_AUTO_DEFAULT = false
|
6
|
+
FLEX_AUTO_ALLOWED_VALUES = [FLEX_AUTO_DEFAULT, true]
|
7
|
+
|
8
|
+
def initialize(flex_auto: FLEX_AUTO_DEFAULT, **kwargs)
|
9
|
+
@kwargs = kwargs
|
10
|
+
@kwargs[:classes] =
|
11
|
+
class_names(
|
12
|
+
@kwargs[:classes],
|
13
|
+
"flex-auto" => fetch_or_fallback(FLEX_AUTO_ALLOWED_VALUES, flex_auto, FLEX_AUTO_DEFAULT)
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
render(Primer::BoxComponent.new(**@kwargs)) { content }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class HeadingComponent < Primer::Component
|
5
|
+
def initialize(**kwargs)
|
6
|
+
@kwargs = kwargs
|
7
|
+
@kwargs[:tag] ||= :h1
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
render(Primer::BaseComponent.new(**@kwargs)) { content }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class LabelComponent < Primer::Component
|
5
|
+
SCHEME_MAPPINGS = {
|
6
|
+
# gray
|
7
|
+
gray: "Label--gray",
|
8
|
+
dark_gray: "Label--gray-darker",
|
9
|
+
|
10
|
+
# colored
|
11
|
+
yellow: "Label--yellow",
|
12
|
+
orange: "Label--orange",
|
13
|
+
red: "Label--red",
|
14
|
+
green: "Label--green",
|
15
|
+
blue: "Label--blue",
|
16
|
+
purple: "Label--purple",
|
17
|
+
pink: "Label--pink",
|
18
|
+
|
19
|
+
# Deprecated
|
20
|
+
outline: "Label--outline",
|
21
|
+
green_outline: "Label--outline-green",
|
22
|
+
}.freeze
|
23
|
+
SCHEME_OPTIONS = SCHEME_MAPPINGS.keys << nil
|
24
|
+
|
25
|
+
VARIANT_MAPPINGS = {
|
26
|
+
large: "Label--large",
|
27
|
+
inline: "Label--inline",
|
28
|
+
}.freeze
|
29
|
+
VARIANT_OPTIONS = VARIANT_MAPPINGS.keys << nil
|
30
|
+
|
31
|
+
def initialize(title:, scheme: nil, variant: nil, **kwargs)
|
32
|
+
@kwargs = kwargs
|
33
|
+
@kwargs[:bg] = :blue if scheme.nil?
|
34
|
+
@kwargs[:tag] ||= :span
|
35
|
+
@kwargs[:title] = title
|
36
|
+
@kwargs[:classes] = class_names(
|
37
|
+
"Label",
|
38
|
+
kwargs[:classes],
|
39
|
+
SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_OPTIONS, scheme)],
|
40
|
+
VARIANT_MAPPINGS[fetch_or_fallback(VARIANT_OPTIONS, variant)]
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def call
|
45
|
+
render(Primer::BaseComponent.new(**@kwargs)) { content }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= render(Primer::FlexComponent.new(**@kwargs)) do %>
|
2
|
+
<% if @side == :left %>
|
3
|
+
<%= render Primer::BaseComponent.new(tag: :div, classes: "flex-shrink-0", col: (@responsive ? [12, nil, 3] : 3), mb: (@responsive ? [4, nil, 0] : nil)) do %>
|
4
|
+
<%= sidebar %>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%= render Primer::BaseComponent.new(tag: :div, classes: "flex-shrink-0", col: (@responsive ? [12, nil, 9] : 9), mb: (@responsive ? [4, nil, 0] : nil)) do %>
|
9
|
+
<%= main %>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<% if @side == :right %>
|
13
|
+
<%= render Primer::BaseComponent.new(tag: :div, classes: "flex-shrink-0", col: (@responsive ? [12, nil, 3] : 3)) do %>
|
14
|
+
<%= sidebar %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class LayoutComponent < Primer::Component
|
5
|
+
with_content_areas :main, :sidebar
|
6
|
+
|
7
|
+
DEFAULT_SIDE = :right
|
8
|
+
ALLOWED_SIDES = [DEFAULT_SIDE, :left]
|
9
|
+
|
10
|
+
def initialize(responsive: false, side: DEFAULT_SIDE, **kwargs)
|
11
|
+
@kwargs = kwargs
|
12
|
+
@side = fetch_or_fallback(ALLOWED_SIDES, side, DEFAULT_SIDE)
|
13
|
+
@responsive = responsive
|
14
|
+
@kwargs[:classes] = class_names(
|
15
|
+
"gutter-condensed gutter-lg",
|
16
|
+
@kwargs[:classes]
|
17
|
+
)
|
18
|
+
@kwargs[:direction] = responsive ? [:column, nil, :row] : nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class LinkComponent < Primer::Component
|
5
|
+
def initialize(href:, muted: false, **kwargs)
|
6
|
+
@kwargs = kwargs
|
7
|
+
@kwargs[:tag] = :a
|
8
|
+
@kwargs[:href] = href
|
9
|
+
@kwargs[:classes] = class_names(
|
10
|
+
@kwargs[:classes],
|
11
|
+
"muted-link" => fetch_or_fallback([true, false], muted, false)
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
render(Primer::BaseComponent.new(**@kwargs)) { content }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Use progress components to visualize task completion.
|
5
|
+
|
6
|
+
## Basic example
|
7
|
+
#
|
8
|
+
# The `Primer::ProgressBarComponent` can take the following arguments:
|
9
|
+
#
|
10
|
+
# 1. `size` (string). Can be "small" or "large". Increases the height of the progress bar.
|
11
|
+
#
|
12
|
+
# The `Primer::ProgressBarComponent` uses the [Slots API](https://github.com/github/view_component#slots-experimental) and at least one slot is required for the component to render. Each slot accepts a `percentage` parameter, which is used to set the width of the completed bar.
|
13
|
+
#
|
14
|
+
# ```ruby
|
15
|
+
# <%= render(Primer::ProgressBarComponent.new(size: :small)) do |component| %>
|
16
|
+
# <% component.slot(:item, bg: :blue-4, percentage: 50) %>
|
17
|
+
# <% end %>
|
18
|
+
# ```
|
19
|
+
##
|
20
|
+
module Primer
|
21
|
+
class ProgressBarComponent < Primer::Component
|
22
|
+
include ViewComponent::Slotable
|
23
|
+
|
24
|
+
with_slot :item, collection: true, class_name: "Item"
|
25
|
+
|
26
|
+
SIZE_DEFAULT = :default
|
27
|
+
|
28
|
+
SIZE_MAPPINGS = {
|
29
|
+
SIZE_DEFAULT => "",
|
30
|
+
:small => "Progress--small",
|
31
|
+
:large => "Progress--large",
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
SIZE_OPTIONS = SIZE_MAPPINGS.keys
|
35
|
+
|
36
|
+
def initialize(size: SIZE_DEFAULT, percentage: 0, **kwargs)
|
37
|
+
@kwargs = kwargs
|
38
|
+
@kwargs[:classes] = class_names(
|
39
|
+
@kwargs[:classes],
|
40
|
+
"Progress",
|
41
|
+
SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)]
|
42
|
+
)
|
43
|
+
@kwargs[:tag] = :span
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def render?
|
48
|
+
items.any?
|
49
|
+
end
|
50
|
+
|
51
|
+
class Item < ViewComponent::Slot
|
52
|
+
include ClassNameHelper
|
53
|
+
attr_reader :kwargs
|
54
|
+
|
55
|
+
def initialize(percentage: 0, bg: :green, **kwargs)
|
56
|
+
@percentage = percentage
|
57
|
+
@kwargs = kwargs
|
58
|
+
|
59
|
+
@kwargs[:tag] = :span
|
60
|
+
@kwargs[:bg] = bg
|
61
|
+
@kwargs[:style] = "width: #{@percentage}%;"
|
62
|
+
@kwargs[:classes] = class_names("Progress-item", @kwargs[:classes])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class StateComponent < Primer::Component
|
5
|
+
# Component for rendering the status of an item
|
6
|
+
#
|
7
|
+
# title(string): (required) title attribute
|
8
|
+
# color(symbol): label background color
|
9
|
+
# size(symbol): label size
|
10
|
+
# counter(integer): counter value
|
11
|
+
# **args(hash): utility parameters for Primer::Classify
|
12
|
+
COLOR_DEFAULT = :default
|
13
|
+
COLOR_MAPPINGS = {
|
14
|
+
COLOR_DEFAULT => "",
|
15
|
+
:green => "State--green",
|
16
|
+
:red => "State--red",
|
17
|
+
:purple => "State--purple",
|
18
|
+
}.freeze
|
19
|
+
COLOR_OPTIONS = COLOR_MAPPINGS.keys
|
20
|
+
|
21
|
+
SIZE_DEFAULT = :default
|
22
|
+
SIZE_MAPPINGS = {
|
23
|
+
SIZE_DEFAULT => "",
|
24
|
+
:small => "State--small",
|
25
|
+
}.freeze
|
26
|
+
SIZE_OPTIONS = SIZE_MAPPINGS.keys
|
27
|
+
|
28
|
+
TAG_DEFAULT = :span
|
29
|
+
TAG_OPTIONS = [TAG_DEFAULT, :div, :a]
|
30
|
+
|
31
|
+
def initialize(
|
32
|
+
title:,
|
33
|
+
color: COLOR_DEFAULT,
|
34
|
+
tag: TAG_DEFAULT,
|
35
|
+
size: SIZE_DEFAULT,
|
36
|
+
**kwargs
|
37
|
+
)
|
38
|
+
@kwargs = kwargs
|
39
|
+
@kwargs[:title] = title
|
40
|
+
@kwargs[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
|
41
|
+
@kwargs[:classes] = class_names(
|
42
|
+
@kwargs[:classes],
|
43
|
+
"State",
|
44
|
+
COLOR_MAPPINGS[fetch_or_fallback(COLOR_OPTIONS, color, COLOR_DEFAULT)],
|
45
|
+
SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)]
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def call
|
50
|
+
render(Primer::BaseComponent.new(**@kwargs)) { content }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= render Primer::BaseComponent.new(**@kwargs) do %>
|
2
|
+
<% if heading.present? %>
|
3
|
+
<%= render Primer::BaseComponent.new(**heading.kwargs) do %>
|
4
|
+
<%= heading.content %>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
<% if actions.present? %>
|
8
|
+
<%= render Primer::BaseComponent.new(**actions.kwargs) do %>
|
9
|
+
<%= actions.content %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
12
|
+
<% if description.present? %>
|
13
|
+
<%= render Primer::BaseComponent.new(**description.kwargs) do %>
|
14
|
+
<%= description.content %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This component consists of a .Subhead container, which has a light gray bottom border.
|
4
|
+
|
5
|
+
# Use a heading element whenever possible as they can be
|
6
|
+
# used as navigation for assistive technologies, and avoid skipping levels.
|
7
|
+
|
8
|
+
# ## Basic example
|
9
|
+
|
10
|
+
# The `Primer::SubheadComponent` can take the following arguments:
|
11
|
+
|
12
|
+
# 1. `heading` (string). The heading to be rendered.
|
13
|
+
# 2. `actions` (content). Slot to render any actions to the right of heading.
|
14
|
+
# 3. `description` (string). Slot to render description under the heading.
|
15
|
+
|
16
|
+
# ```erb
|
17
|
+
# <%= Primer::SubheadComponent.new(heading: "Hello world")) do |component| %>
|
18
|
+
# <% component.slot(:actions) do %>
|
19
|
+
# My Actions
|
20
|
+
# <% end %>
|
21
|
+
# <% end %>
|
22
|
+
# ```
|
23
|
+
module Primer
|
24
|
+
class SubheadComponent < Primer::Component
|
25
|
+
include ViewComponent::Slotable
|
26
|
+
|
27
|
+
with_slot :heading, class_name: "Heading"
|
28
|
+
with_slot :actions, class_name: "Actions"
|
29
|
+
with_slot :description, class_name: "Description"
|
30
|
+
|
31
|
+
def initialize(spacious: false, hide_border: false, **kwargs)
|
32
|
+
@kwargs = kwargs
|
33
|
+
|
34
|
+
@kwargs[:tag] = :div
|
35
|
+
@kwargs[:classes] =
|
36
|
+
class_names(
|
37
|
+
@kwargs[:classes],
|
38
|
+
"Subhead hx_Subhead--responsive",
|
39
|
+
"Subhead--spacious": spacious,
|
40
|
+
"border-bottom-0": hide_border
|
41
|
+
)
|
42
|
+
@kwargs[:mb] ||= hide_border ? 0 : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def render?
|
46
|
+
heading.present?
|
47
|
+
end
|
48
|
+
|
49
|
+
class Heading < ViewComponent::Slot
|
50
|
+
include ClassNameHelper
|
51
|
+
|
52
|
+
attr_reader :kwargs
|
53
|
+
|
54
|
+
def initialize(danger: false, **kwargs)
|
55
|
+
@kwargs = kwargs
|
56
|
+
@kwargs[:tag] ||= :div
|
57
|
+
@kwargs[:classes] = class_names(
|
58
|
+
@kwargs[:classes],
|
59
|
+
"Subhead-heading",
|
60
|
+
"Subhead-heading--danger": danger
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Actions < ViewComponent::Slot
|
66
|
+
include ClassNameHelper
|
67
|
+
|
68
|
+
attr_reader :kwargs
|
69
|
+
|
70
|
+
def initialize(**kwargs)
|
71
|
+
@kwargs = kwargs
|
72
|
+
@kwargs[:tag] = :div
|
73
|
+
@kwargs[:classes] = class_names(@kwargs[:classes], "Subhead-actions")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Description < ViewComponent::Slot
|
78
|
+
include ClassNameHelper
|
79
|
+
|
80
|
+
attr_reader :kwargs
|
81
|
+
|
82
|
+
def initialize(**kwargs)
|
83
|
+
@kwargs = kwargs
|
84
|
+
@kwargs[:tag] = :div
|
85
|
+
@kwargs[:classes] = class_names(@kwargs[:classes], "Subhead-description")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class TextComponent < Primer::Component
|
5
|
+
def initialize(**kwargs)
|
6
|
+
@kwargs = kwargs
|
7
|
+
@kwargs[:tag] ||= :span
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
render(Primer::BaseComponent.new(**@kwargs)) { content }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= render Primer::BaseComponent.new(**kwargs) do %>
|
2
|
+
<% if avatar %>
|
3
|
+
<%= render Primer::AvatarComponent.new(alt: avatar.alt, src: avatar.src, size: avatar.size, square: avatar.square, **avatar.kwargs) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<% if badge %>
|
7
|
+
<%= render Primer::BaseComponent.new(**badge.kwargs) do %>
|
8
|
+
<%= octicon badge.icon %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<% if body %>
|
13
|
+
<%= render Primer::BaseComponent.new(**body.kwargs) do %>
|
14
|
+
<%= body.content %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
class TimelineItemComponent < Primer::Component
|
5
|
+
include ViewComponent::Slotable
|
6
|
+
|
7
|
+
with_slot :avatar, class_name: "Avatar"
|
8
|
+
with_slot :badge, class_name: "Badge"
|
9
|
+
with_slot :body, class_name: "Body"
|
10
|
+
|
11
|
+
attr_reader :kwargs
|
12
|
+
def initialize(condensed: false, **kwargs)
|
13
|
+
@kwargs = kwargs
|
14
|
+
@kwargs[:tag] = :div
|
15
|
+
@kwargs[:classes] = class_names(
|
16
|
+
"TimelineItem",
|
17
|
+
condensed ? "TimelineItem--condensed" : "",
|
18
|
+
kwargs[:classes]
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def render?
|
23
|
+
avatar.present? || badge.present? || body.present?
|
24
|
+
end
|
25
|
+
|
26
|
+
class Avatar < Primer::Slot
|
27
|
+
attr_reader :kwargs, :alt, :src, :size, :square
|
28
|
+
def initialize(alt: nil, src: nil, size: 40, square: true, **kwargs)
|
29
|
+
@alt = alt
|
30
|
+
@src = src
|
31
|
+
@size = size
|
32
|
+
@square = square
|
33
|
+
|
34
|
+
@kwargs = kwargs
|
35
|
+
@kwargs[:tag] = :div
|
36
|
+
@kwargs[:classes] = class_names(
|
37
|
+
"TimelineItem-avatar",
|
38
|
+
kwargs[:classes]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Badge < Primer::Slot
|
44
|
+
attr_reader :kwargs, :icon
|
45
|
+
def initialize(icon: nil, **kwargs)
|
46
|
+
@icon = icon
|
47
|
+
|
48
|
+
@kwargs = kwargs
|
49
|
+
@kwargs[:tag] = :div
|
50
|
+
@kwargs[:classes] = class_names(
|
51
|
+
"TimelineItem-badge",
|
52
|
+
kwargs[:classes]
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Body < Primer::Slot
|
58
|
+
attr_reader :kwargs
|
59
|
+
def initialize(**kwargs)
|
60
|
+
@kwargs = kwargs
|
61
|
+
@kwargs[:tag] = :div
|
62
|
+
@kwargs[:classes] = class_names(
|
63
|
+
"TimelineItem-body",
|
64
|
+
kwargs[:classes]
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|