primer_view_components 0.0.13 → 0.0.18
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/app/components/primer/base_component.rb +63 -15
- data/app/components/primer/blankslate_component.html.erb +4 -4
- data/app/components/primer/blankslate_component.rb +28 -2
- data/app/components/primer/border_box_component.rb +4 -0
- data/app/components/primer/box_component.rb +10 -0
- data/app/components/primer/breadcrumb_component.rb +2 -1
- data/app/components/primer/button_component.rb +1 -1
- data/app/components/primer/button_group_component.html.erb +5 -0
- data/app/components/primer/button_group_component.rb +34 -0
- data/app/components/primer/button_marketing_component.rb +73 -0
- data/app/components/primer/component.rb +14 -0
- data/app/components/primer/counter_component.rb +16 -12
- data/app/components/primer/details_component.rb +10 -6
- data/app/components/primer/dropdown_menu_component.rb +31 -3
- data/app/components/primer/flash_component.rb +2 -3
- data/app/components/primer/flex_component.rb +10 -9
- data/app/components/primer/flex_item_component.rb +2 -1
- data/app/components/primer/heading_component.rb +7 -0
- data/app/components/primer/label_component.rb +15 -9
- data/app/components/primer/link_component.rb +1 -1
- data/app/components/primer/octicon_component.rb +4 -3
- data/app/components/primer/popover_component.rb +3 -1
- data/app/components/primer/progress_bar_component.rb +5 -5
- data/app/components/primer/slot.rb +1 -0
- data/app/components/primer/spinner_component.rb +3 -4
- data/app/components/primer/state_component.rb +3 -3
- data/app/components/primer/subhead_component.rb +3 -0
- data/app/components/primer/timeline_item_component.rb +3 -0
- data/app/components/primer/tooltip_component.rb +88 -0
- data/app/components/primer/truncate_component.rb +41 -0
- data/app/components/primer/underline_nav_component.rb +26 -1
- data/app/components/primer/view_components.rb +5 -0
- data/lib/primer/class_name_helper.rb +1 -0
- data/lib/primer/classify.rb +129 -107
- data/lib/primer/fetch_or_fallback_helper.rb +9 -0
- data/lib/primer/join_style_arguments_helper.rb +14 -0
- data/lib/primer/view_components.rb +1 -0
- data/lib/primer/view_components/engine.rb +1 -0
- data/lib/primer/view_components/version.rb +1 -1
- metadata +42 -22
@@ -8,19 +8,19 @@ module Primer
|
|
8
8
|
COLOR_DEFAULT => "",
|
9
9
|
:green => "State--green",
|
10
10
|
:red => "State--red",
|
11
|
-
:purple => "State--purple"
|
11
|
+
:purple => "State--purple"
|
12
12
|
}.freeze
|
13
13
|
COLOR_OPTIONS = COLOR_MAPPINGS.keys
|
14
14
|
|
15
15
|
SIZE_DEFAULT = :default
|
16
16
|
SIZE_MAPPINGS = {
|
17
17
|
SIZE_DEFAULT => "",
|
18
|
-
:small => "State--small"
|
18
|
+
:small => "State--small"
|
19
19
|
}.freeze
|
20
20
|
SIZE_OPTIONS = SIZE_MAPPINGS.keys
|
21
21
|
|
22
22
|
TAG_DEFAULT = :span
|
23
|
-
TAG_OPTIONS = [TAG_DEFAULT, :div, :a]
|
23
|
+
TAG_OPTIONS = [TAG_DEFAULT, :div, :a].freeze
|
24
24
|
|
25
25
|
# @example 40|Default
|
26
26
|
# <%= render(Primer::StateComponent.new(title: "title")) { "State" } %>
|
@@ -67,6 +67,7 @@ module Primer
|
|
67
67
|
heading.present?
|
68
68
|
end
|
69
69
|
|
70
|
+
# :nodoc
|
70
71
|
class Heading < ViewComponent::Slot
|
71
72
|
include ClassNameHelper
|
72
73
|
|
@@ -85,6 +86,7 @@ module Primer
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
89
|
+
# :nodoc
|
88
90
|
class Actions < ViewComponent::Slot
|
89
91
|
include ClassNameHelper
|
90
92
|
|
@@ -98,6 +100,7 @@ module Primer
|
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
103
|
+
# :nodoc
|
101
104
|
class Description < ViewComponent::Slot
|
102
105
|
include ClassNameHelper
|
103
106
|
|
@@ -36,6 +36,7 @@ module Primer
|
|
36
36
|
avatar.present? || badge.present? || body.present?
|
37
37
|
end
|
38
38
|
|
39
|
+
# :nodoc
|
39
40
|
class Avatar < Primer::Slot
|
40
41
|
attr_reader :system_arguments, :alt, :src, :size, :square
|
41
42
|
|
@@ -59,6 +60,7 @@ module Primer
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
63
|
+
# :nodoc
|
62
64
|
class Badge < Primer::Slot
|
63
65
|
attr_reader :system_arguments, :icon
|
64
66
|
|
@@ -76,6 +78,7 @@ module Primer
|
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
81
|
+
# :nodoc
|
79
82
|
class Body < Primer::Slot
|
80
83
|
attr_reader :system_arguments
|
81
84
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
# The Tooltip component is a wrapper component that will apply a tooltip to the provided content.
|
5
|
+
class TooltipComponent < Primer::Component
|
6
|
+
DIRECTION_DEFAULT = :n
|
7
|
+
ALIGN_DEFAULT = :default
|
8
|
+
MULTILINE_DEFAULT = false
|
9
|
+
DELAY_DEFAULT = false
|
10
|
+
|
11
|
+
ALIGN_MAPPING = {
|
12
|
+
ALIGN_DEFAULT => "",
|
13
|
+
:left_1 => "tooltipped-align-left-1",
|
14
|
+
:right_1 => "tooltipped-align-right-1",
|
15
|
+
:left_2 => "tooltipped-align-left-2",
|
16
|
+
:right_2 => "tooltipped-align-right-2"
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
DIRECTION_OPTIONS = [DIRECTION_DEFAULT] + %i[
|
20
|
+
nw
|
21
|
+
ne
|
22
|
+
w
|
23
|
+
e
|
24
|
+
sw
|
25
|
+
s
|
26
|
+
se
|
27
|
+
]
|
28
|
+
|
29
|
+
# @example 100|Default
|
30
|
+
# <div class="pt-5">
|
31
|
+
# <%= render(Primer::TooltipComponent.new(label: "Even bolder")) { "Default Bold Text" } %>
|
32
|
+
# </div>
|
33
|
+
#
|
34
|
+
# @example 100|Wrapping another component
|
35
|
+
# <div class="pt-5">
|
36
|
+
# <%= render(Primer::TooltipComponent.new(label: "Even bolder")) do %>
|
37
|
+
# <%= render(Primer::ButtonComponent.new) { "Bold Button" } %>
|
38
|
+
# <% end %>
|
39
|
+
# </div>
|
40
|
+
#
|
41
|
+
# @example 100|With a direction
|
42
|
+
# <div class="pt-5">
|
43
|
+
# <%= render(Primer::TooltipComponent.new(label: "Even bolder", direction: :s)) { "Bold Text With a Direction" } %>
|
44
|
+
# </div>
|
45
|
+
#
|
46
|
+
# @example 100|With an alignment
|
47
|
+
# <div class="pt-5">
|
48
|
+
# <%= render(Primer::TooltipComponent.new(label: "Even bolder", direction: :s, alignment: :right_1)) { "Bold Text With an Alignment" } %>
|
49
|
+
# </div>
|
50
|
+
#
|
51
|
+
# @example 100|Without a delay
|
52
|
+
# <div class="pt-5">
|
53
|
+
# <%= render(Primer::TooltipComponent.new(label: "Even bolder", direction: :s, no_delay: true)) { "Bold Text without a delay" } %>
|
54
|
+
# </div>
|
55
|
+
#
|
56
|
+
# @param label [String] the text to appear in the tooltip
|
57
|
+
# @param direction [String] Direction of the tooltip. <%= one_of(Primer::TooltipComponent::DIRECTION_OPTIONS) %>
|
58
|
+
# @param align [String] Align tooltips to the left or right of an element, combined with a `direction` to specify north or south. <%= one_of(Primer::TooltipComponent::ALIGN_MAPPING.keys) %>
|
59
|
+
# @param multiline [Boolean] Use this when you have long content
|
60
|
+
# @param no_delay [Boolean] By default the tooltips have a slight delay before appearing. Set true to override this
|
61
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
62
|
+
def initialize(
|
63
|
+
label:,
|
64
|
+
direction: DIRECTION_DEFAULT,
|
65
|
+
align: ALIGN_DEFAULT,
|
66
|
+
multiline: MULTILINE_DEFAULT,
|
67
|
+
no_delay: DELAY_DEFAULT,
|
68
|
+
**system_arguments
|
69
|
+
)
|
70
|
+
@system_arguments = system_arguments
|
71
|
+
@system_arguments[:tag] ||= :span
|
72
|
+
@system_arguments[:aria] = { label: label }
|
73
|
+
|
74
|
+
@system_arguments[:classes] = class_names(
|
75
|
+
@system_arguments[:classes],
|
76
|
+
"tooltipped",
|
77
|
+
"tooltipped-#{fetch_or_fallback(DIRECTION_OPTIONS, direction, DIRECTION_DEFAULT)}",
|
78
|
+
ALIGN_MAPPING[fetch_or_fallback(ALIGN_MAPPING.keys, align, ALIGN_DEFAULT)],
|
79
|
+
"tooltipped-no-delay" => fetch_or_fallback_boolean(no_delay, DELAY_DEFAULT),
|
80
|
+
"tooltipped-multiline" => fetch_or_fallback_boolean(multiline, MULTILINE_DEFAULT)
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def call
|
85
|
+
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
# Use TruncateComponent to shorten overflowing text with an ellipsis.
|
5
|
+
class TruncateComponent < Primer::Component
|
6
|
+
# @example 25|Default
|
7
|
+
# <div class="col-2">
|
8
|
+
# <%= render(Primer::TruncateComponent.new(tag: :p)) { "branch-name-that-is-really-long" } %>
|
9
|
+
# </div>
|
10
|
+
#
|
11
|
+
# @example 25|Inline
|
12
|
+
# <%= render(Primer::TruncateComponent.new(tag: :span, inline: true)) { "branch-name-that-is-really-long" } %>
|
13
|
+
#
|
14
|
+
# @example 25|Expandable
|
15
|
+
# <%= render(Primer::TruncateComponent.new(tag: :span, inline: true, expandable: true)) { "branch-name-that-is-really-long" } %>
|
16
|
+
#
|
17
|
+
# @example 25|Custom size
|
18
|
+
# <%= render(Primer::TruncateComponent.new(tag: :span, inline: true, expandable: true, max_width: 100)) { "branch-name-that-is-really-long" } %>
|
19
|
+
#
|
20
|
+
# @param inline [Boolean] Whether the element is inline (or inline-block).
|
21
|
+
# @param expandable [Boolean] Whether the entire string should be revealed on hover. Can only be used in conjunction with `inline`.
|
22
|
+
# @param max_width [Integer] Sets the max-width of the text.
|
23
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
24
|
+
def initialize(inline: false, expandable: false, max_width: nil, **system_arguments)
|
25
|
+
@system_arguments = system_arguments
|
26
|
+
@system_arguments[:tag] ||= :div
|
27
|
+
@system_arguments[:classes] = class_names(
|
28
|
+
@system_arguments[:classes],
|
29
|
+
"css-truncate",
|
30
|
+
"css-truncate-overflow" => !inline,
|
31
|
+
"css-truncate-target" => inline,
|
32
|
+
"expandable" => inline && expandable
|
33
|
+
)
|
34
|
+
@system_arguments[:style] = join_style_arguments(@system_arguments[:style], "max-width: #{max_width}px;") unless max_width.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
def call
|
38
|
+
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,12 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Primer
|
4
|
+
# Use the UnderlineNav component to style navigation with a minimal
|
5
|
+
# underlined selected state, typically used for navigation placed at the top
|
6
|
+
# of the page.
|
4
7
|
class UnderlineNavComponent < Primer::Component
|
5
8
|
ALIGN_DEFAULT = :left
|
6
|
-
ALIGN_OPTIONS = [ALIGN_DEFAULT, :right]
|
9
|
+
ALIGN_OPTIONS = [ALIGN_DEFAULT, :right].freeze
|
7
10
|
|
8
11
|
with_content_areas :body, :actions
|
9
12
|
|
13
|
+
# @example 70|Default
|
14
|
+
# <%= render(Primer::UnderlineNavComponent.new) do |component| %>
|
15
|
+
# <% component.with(:body) do %>
|
16
|
+
# <%= render(Primer::LinkComponent.new(href: "#url")) { "Item 1" } %>
|
17
|
+
# <% end %>
|
18
|
+
# <% component.with(:actions) do %>
|
19
|
+
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
20
|
+
# <% end %>
|
21
|
+
# <% end %>
|
22
|
+
#
|
23
|
+
# @example 70|Align right
|
24
|
+
# <%= render(Primer::UnderlineNavComponent.new(align: :right)) do |component| %>
|
25
|
+
# <% component.with(:body) do %>
|
26
|
+
# <%= render(Primer::LinkComponent.new(href: "#url")) { "Item 1" } %>
|
27
|
+
# <% end %>
|
28
|
+
# <% component.with(:actions) do %>
|
29
|
+
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
30
|
+
# <% end %>
|
31
|
+
# <% end %>
|
32
|
+
#
|
33
|
+
# @param align [Symbol] <%= one_of(Primer::UnderlineNavComponent::ALIGN_OPTIONS) %> - Defaults to <%= Primer::UnderlineNavComponent::ALIGN_DEFAULT %>
|
34
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
10
35
|
def initialize(align: ALIGN_DEFAULT, **system_arguments)
|
11
36
|
@align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
|
12
37
|
|
@@ -15,6 +15,7 @@ require "octicons_helper/helper"
|
|
15
15
|
require "primer/class_name_helper"
|
16
16
|
require "primer/classify"
|
17
17
|
require "primer/fetch_or_fallback_helper"
|
18
|
+
require "primer/join_style_arguments_helper"
|
18
19
|
|
19
20
|
# Base configurations
|
20
21
|
|
@@ -30,6 +31,8 @@ require_relative "border_box_component"
|
|
30
31
|
require_relative "box_component"
|
31
32
|
require_relative "breadcrumb_component"
|
32
33
|
require_relative "button_component"
|
34
|
+
require_relative "button_group_component"
|
35
|
+
require_relative "button_marketing_component"
|
33
36
|
require_relative "counter_component"
|
34
37
|
require_relative "details_component"
|
35
38
|
require_relative "dropdown_menu_component"
|
@@ -48,4 +51,6 @@ require_relative "state_component"
|
|
48
51
|
require_relative "subhead_component"
|
49
52
|
require_relative "text_component"
|
50
53
|
require_relative "timeline_item_component"
|
54
|
+
require_relative "tooltip_component"
|
55
|
+
require_relative "truncate_component"
|
51
56
|
require_relative "underline_nav_component"
|
data/lib/primer/classify.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Primer
|
4
|
+
# :nodoc:
|
4
5
|
class Classify
|
5
|
-
MARGIN_DIRECTION_KEYS = [
|
6
|
-
SPACING_KEYS = ([
|
6
|
+
MARGIN_DIRECTION_KEYS = %i[mt ml mb mr].freeze
|
7
|
+
SPACING_KEYS = (%i[m my mx p py px pt pl pb pr] + MARGIN_DIRECTION_KEYS).freeze
|
7
8
|
DIRECTION_KEY = :direction
|
8
9
|
JUSTIFY_CONTENT_KEY = :justify_content
|
9
10
|
ALIGN_ITEMS_KEY = :align_items
|
10
11
|
DISPLAY_KEY = :display
|
11
12
|
RESPONSIVE_KEYS = ([DISPLAY_KEY, DIRECTION_KEY, JUSTIFY_CONTENT_KEY, ALIGN_ITEMS_KEY, :col, :float] + SPACING_KEYS).freeze
|
12
|
-
BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"]
|
13
|
+
BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"].freeze
|
13
14
|
|
14
15
|
# Keys where we can simply translate { key: value } into ".key-value"
|
15
|
-
CONCAT_KEYS = SPACING_KEYS + [
|
16
|
+
CONCAT_KEYS = SPACING_KEYS + %i[hide position v float col text box_shadow].freeze
|
16
17
|
|
17
18
|
INVALID_CLASS_NAME_PREFIXES =
|
18
19
|
(["bg-", "color-", "text-", "d-", "v-align-", "wb-", "text-", "box-shadow-"] + CONCAT_KEYS.map { |k| "#{k}-" }).freeze
|
@@ -21,7 +22,7 @@ module Primer
|
|
21
22
|
BG_KEY = :bg
|
22
23
|
VERTICAL_ALIGN_KEY = :vertical_align
|
23
24
|
WORD_BREAK_KEY = :word_break
|
24
|
-
TEXT_KEYS = [
|
25
|
+
TEXT_KEYS = %i[text_align font_weight].freeze
|
25
26
|
FLEX_KEY = :flex
|
26
27
|
FLEX_GROW_KEY = :flex_grow
|
27
28
|
FLEX_SHRINK_KEY = :flex_shrink
|
@@ -29,20 +30,21 @@ module Primer
|
|
29
30
|
WIDTH_KEY = :width
|
30
31
|
HEIGHT_KEY = :height
|
31
32
|
BOX_SHADOW_KEY = :box_shadow
|
32
|
-
|
33
|
+
VISIBILITY_KEY = :visibility
|
34
|
+
ANIMATION_KEY = :animation
|
33
35
|
|
34
36
|
BOOLEAN_MAPPINGS = {
|
35
37
|
underline: {
|
36
38
|
mappings: [
|
37
39
|
{
|
38
40
|
value: true,
|
39
|
-
css_class: "text-underline"
|
41
|
+
css_class: "text-underline"
|
40
42
|
},
|
41
43
|
{
|
42
44
|
value: false,
|
43
|
-
css_class: "no-underline"
|
44
|
-
}
|
45
|
-
]
|
45
|
+
css_class: "no-underline"
|
46
|
+
}
|
47
|
+
]
|
46
48
|
},
|
47
49
|
top: {
|
48
50
|
mappings: [
|
@@ -77,8 +79,9 @@ module Primer
|
|
77
79
|
]
|
78
80
|
}
|
79
81
|
}.freeze
|
80
|
-
BORDER_KEYS = [
|
81
|
-
BORDER_MARGIN_KEYS = [
|
82
|
+
BORDER_KEYS = %i[border border_color].freeze
|
83
|
+
BORDER_MARGIN_KEYS = %i[border_top border_bottom border_left border_right].freeze
|
84
|
+
BORDER_RADIUS_KEY = :border_radius
|
82
85
|
TYPOGRAPHY_KEYS = [:font_size].freeze
|
83
86
|
VALID_KEYS = (
|
84
87
|
CONCAT_KEYS +
|
@@ -88,6 +91,7 @@ module Primer
|
|
88
91
|
TYPOGRAPHY_KEYS +
|
89
92
|
TEXT_KEYS +
|
90
93
|
[
|
94
|
+
BORDER_RADIUS_KEY,
|
91
95
|
COLOR_KEY,
|
92
96
|
BG_KEY,
|
93
97
|
DISPLAY_KEY,
|
@@ -102,7 +106,9 @@ module Primer
|
|
102
106
|
ALIGN_SELF_KEY,
|
103
107
|
WIDTH_KEY,
|
104
108
|
HEIGHT_KEY,
|
105
|
-
BOX_SHADOW_KEY
|
109
|
+
BOX_SHADOW_KEY,
|
110
|
+
VISIBILITY_KEY,
|
111
|
+
ANIMATION_KEY
|
106
112
|
]
|
107
113
|
).freeze
|
108
114
|
|
@@ -110,30 +116,31 @@ module Primer
|
|
110
116
|
def call(classes: "", style: nil, **args)
|
111
117
|
extracted_results = extract_hash(args)
|
112
118
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
119
|
+
extracted_results[:class] = [
|
120
|
+
validated_class_names(classes),
|
121
|
+
extracted_results.delete(:classes)
|
122
|
+
].compact.join(" ").presence
|
123
|
+
|
124
|
+
extracted_results[:style] = [
|
125
|
+
extracted_results.delete(:styles),
|
126
|
+
style
|
127
|
+
].compact.join("").presence
|
128
|
+
|
129
|
+
extracted_results
|
117
130
|
end
|
118
131
|
|
119
132
|
private
|
120
133
|
|
121
134
|
def validated_class_names(classes)
|
122
|
-
return
|
135
|
+
return if classes.blank?
|
123
136
|
|
124
137
|
if ENV["RAILS_ENV"] == "development"
|
125
138
|
invalid_class_names =
|
126
139
|
classes.split(" ").each_with_object([]) do |class_name, memo|
|
127
|
-
if INVALID_CLASS_NAME_PREFIXES.any? { |prefix| class_name.start_with?(prefix) }
|
128
|
-
memo << class_name
|
129
|
-
end
|
140
|
+
memo << class_name if INVALID_CLASS_NAME_PREFIXES.any? { |prefix| class_name.start_with?(prefix) }
|
130
141
|
end
|
131
142
|
|
132
|
-
if invalid_class_names.any?
|
133
|
-
raise ArgumentError.new(
|
134
|
-
"Use System Arguments (https://primer.style/view-components/system-arguments) instead of Primer CSS class #{'name'.pluralize(invalid_class_names.length)} #{invalid_class_names.to_sentence}. This warning will not be raised in production.",
|
135
|
-
)
|
136
|
-
end
|
143
|
+
raise ArgumentError, "Use System Arguments (https://primer.style/view-components/system-arguments) instead of Primer CSS class #{'name'.pluralize(invalid_class_names.length)} #{invalid_class_names.to_sentence}. This warning will not be raised in production." if invalid_class_names.any?
|
137
144
|
end
|
138
145
|
|
139
146
|
classes
|
@@ -151,96 +158,111 @@ module Primer
|
|
151
158
|
# Example usage:
|
152
159
|
# extract_hash({ mt: 4, py: 2 }) => "mt-4 py-2"
|
153
160
|
def extract_hash(styles_hash)
|
154
|
-
|
161
|
+
memo = { classes: [], styles: +"" }
|
162
|
+
styles_hash.each do |key, value|
|
155
163
|
next unless VALID_KEYS.include?(key)
|
156
164
|
|
157
|
-
if value.is_a?(Array)
|
158
|
-
raise ArgumentError, "#{key} does not support responsive values"
|
165
|
+
if value.is_a?(Array)
|
166
|
+
raise ArgumentError, "#{key} does not support responsive values" unless RESPONSIVE_KEYS.include?(key)
|
167
|
+
|
168
|
+
value.each_with_index do |val, index|
|
169
|
+
extract_value(memo, key, val, BREAKPOINTS[index])
|
170
|
+
end
|
171
|
+
else
|
172
|
+
extract_value(memo, key, value, BREAKPOINTS[0])
|
159
173
|
end
|
174
|
+
end
|
160
175
|
|
161
|
-
|
162
|
-
next if val.nil?
|
176
|
+
memo[:classes] = memo[:classes].join(" ")
|
163
177
|
|
164
|
-
|
165
|
-
|
166
|
-
raise ArgumentError, "value of #{key} must be between -6 and 6" if (val < -6 || val > 6)
|
167
|
-
elsif !((key == :mx || key == :my) && val == :auto)
|
168
|
-
raise ArgumentError, "value of #{key} must be between 0 and 6" if (val < 0 || val > 6)
|
169
|
-
end
|
170
|
-
end
|
178
|
+
memo
|
179
|
+
end
|
171
180
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
if val.to_s.starts_with?("#")
|
181
|
-
memo[:styles] << "background-color: #{val};"
|
182
|
-
else
|
183
|
-
memo[:classes] << "bg-#{dasherized_val}"
|
184
|
-
end
|
185
|
-
elsif key == COLOR_KEY
|
186
|
-
if val.to_s.chars.last !~ /\D/
|
187
|
-
memo[:classes] << "color-#{dasherized_val}"
|
188
|
-
else
|
189
|
-
memo[:classes] << "text-#{dasherized_val}"
|
190
|
-
end
|
191
|
-
elsif key == DISPLAY_KEY
|
192
|
-
memo[:classes] << "d#{breakpoint}-#{dasherized_val}"
|
193
|
-
elsif key == VERTICAL_ALIGN_KEY
|
194
|
-
memo[:classes] << "v-align-#{dasherized_val}"
|
195
|
-
elsif key == WORD_BREAK_KEY
|
196
|
-
memo[:classes] << "wb-#{dasherized_val}"
|
197
|
-
elsif BORDER_KEYS.include?(key)
|
198
|
-
memo[:classes] << "border-#{dasherized_val}"
|
199
|
-
elsif BORDER_MARGIN_KEYS.include?(key)
|
200
|
-
memo[:classes] << "#{key.to_s.dasherize}-#{val}"
|
201
|
-
elsif key == DIRECTION_KEY
|
202
|
-
memo[:classes] << "flex#{breakpoint}-#{dasherized_val}"
|
203
|
-
elsif key == JUSTIFY_CONTENT_KEY
|
204
|
-
formatted_value = val.to_s.gsub(/(flex\_|space\_)/, "")
|
205
|
-
memo[:classes] << "flex#{breakpoint}-justify-#{formatted_value}"
|
206
|
-
elsif key == ALIGN_ITEMS_KEY
|
207
|
-
memo[:classes] << "flex#{breakpoint}-items-#{val.to_s.gsub("flex_", "")}"
|
208
|
-
elsif key == FLEX_KEY
|
209
|
-
memo[:classes] << "flex-#{val}"
|
210
|
-
elsif key == FLEX_GROW_KEY
|
211
|
-
memo[:classes] << "flex-grow-#{val}"
|
212
|
-
elsif key == FLEX_SHRINK_KEY
|
213
|
-
memo[:classes] << "flex-shrink-#{val}"
|
214
|
-
elsif key == ALIGN_SELF_KEY
|
215
|
-
memo[:classes] << "flex-self-#{val}"
|
216
|
-
elsif key == WIDTH_KEY || key == HEIGHT_KEY
|
217
|
-
if val == :fit || val == :fill
|
218
|
-
memo[:classes] << "#{key}-#{val}"
|
219
|
-
else
|
220
|
-
memo[key] = val
|
221
|
-
end
|
222
|
-
elsif TEXT_KEYS.include?(key)
|
223
|
-
memo[:classes] << "text-#{dasherized_val}"
|
224
|
-
elsif TYPOGRAPHY_KEYS.include?(key)
|
225
|
-
memo[:classes] << "f#{dasherized_val}"
|
226
|
-
elsif MARGIN_DIRECTION_KEYS.include?(key) && val < 0
|
227
|
-
memo[:classes] << "#{key.to_s.dasherize}#{breakpoint}-n#{val.abs}"
|
228
|
-
elsif key == BOX_SHADOW_KEY
|
229
|
-
if val == true
|
230
|
-
memo[:classes] << "box-shadow"
|
231
|
-
else
|
232
|
-
memo[:classes] << "box-shadow-#{dasherized_val}"
|
233
|
-
end
|
234
|
-
else
|
235
|
-
memo[:classes] << "#{key.to_s.dasherize}#{breakpoint}-#{dasherized_val}"
|
236
|
-
end
|
181
|
+
def extract_value(memo, key, val, breakpoint)
|
182
|
+
return if val.nil?
|
183
|
+
|
184
|
+
if SPACING_KEYS.include?(key)
|
185
|
+
if MARGIN_DIRECTION_KEYS.include?(key)
|
186
|
+
raise ArgumentError, "value of #{key} must be between -6 and 6" if val < -6 || val > 6
|
187
|
+
elsif !((key == :mx || key == :my) && val == :auto)
|
188
|
+
raise ArgumentError, "value of #{key} must be between 0 and 6" if val.negative? || val > 6
|
237
189
|
end
|
238
190
|
end
|
239
191
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
192
|
+
if BOOLEAN_MAPPINGS.key?(key)
|
193
|
+
BOOLEAN_MAPPINGS[key][:mappings].map { |m| m[:css_class] if m[:value] == val }.compact.each do |css_class|
|
194
|
+
memo[:classes] << css_class
|
195
|
+
end
|
196
|
+
elsif key == BG_KEY
|
197
|
+
if val.to_s.starts_with?("#")
|
198
|
+
memo[:styles] << "background-color: #{val};"
|
199
|
+
else
|
200
|
+
memo[:classes] << "bg-#{val.to_s.dasherize}"
|
201
|
+
end
|
202
|
+
elsif key == COLOR_KEY
|
203
|
+
char_code = val[-1].ord
|
204
|
+
# Does this string end in a character that is NOT a number?
|
205
|
+
memo[:classes] << if char_code >= 48 && char_code <= 57 # 48 is the charcode for 0; 57 is the charcode for 9
|
206
|
+
"color-#{val.to_s.dasherize}"
|
207
|
+
else
|
208
|
+
"text-#{val.to_s.dasherize}"
|
209
|
+
end
|
210
|
+
elsif key == DISPLAY_KEY
|
211
|
+
memo[:classes] << "d#{breakpoint}-#{val.to_s.dasherize}"
|
212
|
+
elsif key == VERTICAL_ALIGN_KEY
|
213
|
+
memo[:classes] << "v-align-#{val.to_s.dasherize}"
|
214
|
+
elsif key == WORD_BREAK_KEY
|
215
|
+
memo[:classes] << "wb-#{val.to_s.dasherize}"
|
216
|
+
elsif BORDER_KEYS.include?(key)
|
217
|
+
memo[:classes] << "border-#{val.to_s.dasherize}"
|
218
|
+
elsif BORDER_MARGIN_KEYS.include?(key)
|
219
|
+
memo[:classes] << "#{key.to_s.dasherize}-#{val}"
|
220
|
+
elsif key == BORDER_RADIUS_KEY
|
221
|
+
memo[:classes] << "rounded-#{val}"
|
222
|
+
elsif key == DIRECTION_KEY
|
223
|
+
memo[:classes] << "flex#{breakpoint}-#{val.to_s.dasherize}"
|
224
|
+
elsif key == JUSTIFY_CONTENT_KEY
|
225
|
+
formatted_value = val.to_s.gsub(/(flex\_|space\_)/, "")
|
226
|
+
memo[:classes] << "flex#{breakpoint}-justify-#{formatted_value}"
|
227
|
+
elsif key == ALIGN_ITEMS_KEY
|
228
|
+
memo[:classes] << "flex#{breakpoint}-items-#{val.to_s.gsub('flex_', '')}"
|
229
|
+
elsif key == FLEX_KEY
|
230
|
+
memo[:classes] << "flex-#{val}"
|
231
|
+
elsif key == FLEX_GROW_KEY
|
232
|
+
memo[:classes] << "flex-grow-#{val}"
|
233
|
+
elsif key == FLEX_SHRINK_KEY
|
234
|
+
memo[:classes] << "flex-shrink-#{val}"
|
235
|
+
elsif key == ALIGN_SELF_KEY
|
236
|
+
memo[:classes] << "flex-self-#{val}"
|
237
|
+
elsif key == WIDTH_KEY || key == HEIGHT_KEY
|
238
|
+
if val == :fit || val == :fill
|
239
|
+
memo[:classes] << "#{key}-#{val}"
|
240
|
+
else
|
241
|
+
memo[key] = val
|
242
|
+
end
|
243
|
+
elsif TEXT_KEYS.include?(key)
|
244
|
+
memo[:classes] << "text-#{val.to_s.dasherize}"
|
245
|
+
elsif TYPOGRAPHY_KEYS.include?(key)
|
246
|
+
memo[:classes] << "f#{val.to_s.dasherize}"
|
247
|
+
elsif MARGIN_DIRECTION_KEYS.include?(key) && val.negative?
|
248
|
+
memo[:classes] << "#{key.to_s.dasherize}#{breakpoint}-n#{val.abs}"
|
249
|
+
elsif key == BOX_SHADOW_KEY
|
250
|
+
memo[:classes] << if val == true
|
251
|
+
"box-shadow"
|
252
|
+
else
|
253
|
+
"box-shadow-#{val.to_s.dasherize}"
|
254
|
+
end
|
255
|
+
elsif key == VISIBILITY_KEY
|
256
|
+
memo[:classes] << "v-#{val.to_s.dasherize}"
|
257
|
+
elsif key == ANIMATION_KEY
|
258
|
+
memo[:classes] << if val == :grow
|
259
|
+
"hover-grow"
|
260
|
+
else
|
261
|
+
"anim-#{val.to_s.dasherize}"
|
262
|
+
end
|
263
|
+
else
|
264
|
+
memo[:classes] << "#{key.to_s.dasherize}#{breakpoint}-#{val.to_s.dasherize}"
|
265
|
+
end
|
244
266
|
end
|
245
267
|
end
|
246
268
|
end
|