primer_view_components 0.0.47 → 0.0.48
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 +18 -0
- data/app/components/primer/avatar_stack_component.rb +1 -1
- data/app/components/primer/beta/auto_complete.rb +2 -2
- data/app/components/primer/component.rb +5 -1
- data/app/components/primer/navigation/tab_component.rb +15 -1
- data/app/components/primer/tab_nav_component.rb +3 -3
- data/app/components/primer/underline_nav_component.rb +2 -2
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/rubocop/config/default.yml +12 -0
- data/lib/rubocop/cop/primer.rb +4 -0
- data/lib/rubocop/cop/primer/no_tag_memoize.rb +42 -0
- data/lib/rubocop/cop/primer/system_argument_instead_of_class.rb +75 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c751bc60362c19e97ba5fbe22227e19186efa799862932a6f7b8541ad8e1eaa
|
4
|
+
data.tar.gz: 4efd584159e4883f8bcc72954fff356c753b0b8980056ee0c58b7a3bd650cb90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6169f90241d046f9cee4faf1fb971cac34360c8ebb116e2c2e39fdd0aeff5e8cca17e899bdd8a97f94ebefa4c3705d6929b0978a96f0264dcab3fa96342faaf
|
7
|
+
data.tar.gz: 8576857a521647f43ccb3fe413b0e24b5d65a8c06e9036dd3035b37d8fb5989aa43a7ac2d33863f5faa022c099c6a8386d30de8b764e19cf93b9dcb207fd4eef
|
data/CHANGELOG.md
CHANGED
@@ -30,6 +30,24 @@ The category for changes related to documentation, testing and tooling. Also, fo
|
|
30
30
|
|
31
31
|
## main
|
32
32
|
|
33
|
+
## 0.0.48
|
34
|
+
|
35
|
+
### Breaking changes
|
36
|
+
|
37
|
+
* Ensure panels in `Navigation::Tab` have a label.
|
38
|
+
|
39
|
+
*Kate Higa*
|
40
|
+
|
41
|
+
### Misc
|
42
|
+
|
43
|
+
* Expose custom cops and default config for erblint.
|
44
|
+
|
45
|
+
*Manuel Puyol*
|
46
|
+
|
47
|
+
* Fix double constant assign.
|
48
|
+
|
49
|
+
*Manuel Puyol*
|
50
|
+
|
33
51
|
## 0.0.47
|
34
52
|
|
35
53
|
### Breaking changes
|
@@ -12,7 +12,7 @@ module Primer
|
|
12
12
|
TAG_OPTIONS = [DEFAULT_TAG, :span].freeze
|
13
13
|
|
14
14
|
DEFAULT_BODY_TAG = :div
|
15
|
-
BODY_TAG_OPTIONS =
|
15
|
+
BODY_TAG_OPTIONS = [DEFAULT_BODY_TAG, :span].freeze
|
16
16
|
# Required list of stacked avatars.
|
17
17
|
#
|
18
18
|
# @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Avatar) %>.
|
@@ -29,7 +29,7 @@ module Primer
|
|
29
29
|
# @param type [Symbol] <%= one_of(Primer::Beta::AutoComplete::Input::TYPE_OPTIONS) %>
|
30
30
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
31
31
|
renders_one :input, lambda { |**system_arguments|
|
32
|
-
aria_label =
|
32
|
+
aria_label = aria("label", system_arguments) || @aria_label
|
33
33
|
if aria_label.present?
|
34
34
|
system_arguments[:"aria-label"] = aria_label
|
35
35
|
system_arguments[:aria]&.delete(:label)
|
@@ -106,7 +106,7 @@ module Primer
|
|
106
106
|
def initialize(src:, list_id:, input_id:, **system_arguments)
|
107
107
|
@list_id = list_id
|
108
108
|
@input_id = input_id
|
109
|
-
@aria_label =
|
109
|
+
@aria_label = aria("label", system_arguments)
|
110
110
|
|
111
111
|
system_arguments.delete(:"aria-label") && system_arguments[:aria]&.delete(:label)
|
112
112
|
|
@@ -29,8 +29,12 @@ module Primer
|
|
29
29
|
ActiveSupport::Deprecation.warn(message)
|
30
30
|
end
|
31
31
|
|
32
|
+
def aria(val, system_arguments)
|
33
|
+
system_arguments[:"aria-#{val}"] || system_arguments.dig(:aria, val.to_sym)
|
34
|
+
end
|
35
|
+
|
32
36
|
def validate_aria_label
|
33
|
-
aria_label =
|
37
|
+
aria_label = aria("label", @system_arguments)
|
34
38
|
raise ArgumentError, "`aria-label` is required." if aria_label.nil? && !Rails.env.production?
|
35
39
|
end
|
36
40
|
|
@@ -18,10 +18,22 @@ module Primer
|
|
18
18
|
#
|
19
19
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
20
20
|
renders_one :panel, lambda { |**system_arguments|
|
21
|
+
return unless @with_panel
|
22
|
+
|
21
23
|
system_arguments[:tag] = :div
|
22
24
|
system_arguments[:role] ||= :tabpanel
|
25
|
+
system_arguments[:tabindex] = 0
|
23
26
|
system_arguments[:hidden] = true unless @selected
|
24
27
|
|
28
|
+
label_present = aria("label", system_arguments) || aria("labelledby", system_arguments)
|
29
|
+
unless label_present
|
30
|
+
if @id.present?
|
31
|
+
system_arguments[:"aria-labelledby"] = @id
|
32
|
+
elsif !Rails.env.production?
|
33
|
+
raise ArgumentError, "Panels must be labelled. Either set a unique `id` on the tab, or set an `aria-label` directly on the panel"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
Primer::BaseComponent.new(**system_arguments)
|
26
38
|
}
|
27
39
|
|
@@ -93,8 +105,10 @@ module Primer
|
|
93
105
|
@selected = selected
|
94
106
|
@icon_classes = icon_classes
|
95
107
|
@list = list
|
108
|
+
@with_panel = with_panel
|
96
109
|
|
97
110
|
@system_arguments = system_arguments
|
111
|
+
@id = @system_arguments[:id]
|
98
112
|
|
99
113
|
if with_panel || @system_arguments[:tag] == :button
|
100
114
|
@system_arguments[:tag] = :button
|
@@ -111,7 +125,7 @@ module Primer
|
|
111
125
|
return unless @selected
|
112
126
|
|
113
127
|
if @system_arguments[:tag] == :a
|
114
|
-
aria_current =
|
128
|
+
aria_current = aria("current", system_arguments) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
|
115
129
|
@system_arguments[:"aria-current"] = fetch_or_fallback(ARIA_CURRENT_OPTIONS_FOR_ANCHOR, aria_current, DEFAULT_ARIA_CURRENT_FOR_ANCHOR)
|
116
130
|
else
|
117
131
|
@system_arguments[:"aria-selected"] = true
|
@@ -63,19 +63,19 @@ module Primer
|
|
63
63
|
#
|
64
64
|
# @example With panels
|
65
65
|
# <%= render(Primer::TabNavComponent.new(label: "With panels", with_panel: true)) do |c| %>
|
66
|
-
# <% c.tab(selected: true) do |t| %>
|
66
|
+
# <% c.tab(selected: true, id: "tab-1") do |t| %>
|
67
67
|
# <% t.text { "Tab 1" } %>
|
68
68
|
# <% t.panel do %>
|
69
69
|
# Panel 1
|
70
70
|
# <% end %>
|
71
71
|
# <% end %>
|
72
|
-
# <% c.tab do |t| %>
|
72
|
+
# <% c.tab(id: "tab-2") do |t| %>
|
73
73
|
# <% t.text { "Tab 2" } %>
|
74
74
|
# <% t.panel do %>
|
75
75
|
# Panel 2
|
76
76
|
# <% end %>
|
77
77
|
# <% end %>
|
78
|
-
# <% c.tab do |t| %>
|
78
|
+
# <% c.tab(id: "tab-3") do |t| %>
|
79
79
|
# <% t.text { "Tab 3" } %>
|
80
80
|
# <% t.panel do %>
|
81
81
|
# Panel 3
|
@@ -104,13 +104,13 @@ module Primer
|
|
104
104
|
#
|
105
105
|
# @example With panels
|
106
106
|
# <%= render(Primer::UnderlineNavComponent.new(label: "With panels", with_panel: true)) do |component| %>
|
107
|
-
# <% component.tab(selected: true) do |t| %>
|
107
|
+
# <% component.tab(selected: true, id: "tab-1") do |t| %>
|
108
108
|
# <% t.text { "Item 1" } %>
|
109
109
|
# <% t.panel do %>
|
110
110
|
# Panel 1
|
111
111
|
# <% end %>
|
112
112
|
# <% end %>
|
113
|
-
# <% component.tab do |t| %>
|
113
|
+
# <% component.tab(id: "tab-2") do |t| %>
|
114
114
|
# <% t.text { "Item 2" } %>
|
115
115
|
# <% t.panel do %>
|
116
116
|
# Panel 2
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubocop"
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Primer
|
8
|
+
# This cop ensures that tags are not set with ||=
|
9
|
+
#
|
10
|
+
# bad
|
11
|
+
# @system_arguments[:tag] ||= :h1
|
12
|
+
#
|
13
|
+
# good
|
14
|
+
# @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
|
15
|
+
#
|
16
|
+
# good
|
17
|
+
# @system_arguments[:tag] = :h2
|
18
|
+
class NoTagMemoize < RuboCop::Cop::Cop
|
19
|
+
INVALID_MESSAGE = <<~STR
|
20
|
+
Avoid `[:tag] ||=`. Instead, try one of the following:
|
21
|
+
- Don't allow consumers to update the tag by having a fixed tag (e.g. `system_arguments[:tag] = :div`)
|
22
|
+
- Use the `fetch_or_fallback` helper to only allow a tag from a restricted list.
|
23
|
+
STR
|
24
|
+
|
25
|
+
def_node_search :tag_memoized?, <<~PATTERN
|
26
|
+
(or-asgn
|
27
|
+
(send
|
28
|
+
_
|
29
|
+
_
|
30
|
+
(sym :tag)
|
31
|
+
)
|
32
|
+
_
|
33
|
+
)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def on_or_asgn(node)
|
37
|
+
add_offense(node, message: INVALID_MESSAGE) if tag_memoized?(node)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubocop"
|
4
|
+
require "primer/classify/utilities"
|
5
|
+
require "primer/view_components/statuses"
|
6
|
+
|
7
|
+
module RuboCop
|
8
|
+
module Cop
|
9
|
+
module Primer
|
10
|
+
# This cop ensures that components use System Arguments instead of CSS classes.
|
11
|
+
#
|
12
|
+
# bad
|
13
|
+
# Component.new(classes: "mr-1")
|
14
|
+
#
|
15
|
+
# good
|
16
|
+
# Component.new(mr: 1)
|
17
|
+
class SystemArgumentInsteadOfClass < RuboCop::Cop::Cop
|
18
|
+
INVALID_MESSAGE = <<~STR
|
19
|
+
Avoid using CSS classes when you can use System Arguments: https://primer.style/view-components/system-arguments.
|
20
|
+
STR
|
21
|
+
|
22
|
+
def on_send(node)
|
23
|
+
return unless node.method_name == :new
|
24
|
+
return unless ::Primer::ViewComponents::STATUSES.key?(node.receiver.const_name)
|
25
|
+
return unless node.arguments?
|
26
|
+
|
27
|
+
# we are looking for hash arguments and they are always last
|
28
|
+
kwargs = node.arguments.last
|
29
|
+
|
30
|
+
return unless kwargs.type == :hash
|
31
|
+
|
32
|
+
# find classes pair
|
33
|
+
classes_arg = kwargs.pairs.find { |kwarg| kwarg.key.value == :classes }
|
34
|
+
|
35
|
+
return if classes_arg.nil?
|
36
|
+
return unless classes_arg.value.type == :str
|
37
|
+
|
38
|
+
# get actual classes
|
39
|
+
classes = classes_arg.value.value
|
40
|
+
|
41
|
+
system_arguments = ::Primer::Classify::Utilities.classes_to_hash(classes)
|
42
|
+
|
43
|
+
# no classes are fixable
|
44
|
+
return if system_arguments[:classes] == classes
|
45
|
+
|
46
|
+
add_offense(classes_arg, message: INVALID_MESSAGE)
|
47
|
+
end
|
48
|
+
|
49
|
+
def autocorrect(node)
|
50
|
+
lambda do |corrector|
|
51
|
+
system_arguments = ::Primer::Classify::Utilities.classes_to_hash(node.value.value)
|
52
|
+
corrector.replace(node.loc.expression, arguments_as_string(system_arguments))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def arguments_as_string(system_arguments)
|
59
|
+
system_arguments.map do |key, value|
|
60
|
+
val = case value
|
61
|
+
when Symbol
|
62
|
+
":#{value}"
|
63
|
+
when String
|
64
|
+
value.to_json
|
65
|
+
else
|
66
|
+
value
|
67
|
+
end
|
68
|
+
|
69
|
+
"#{key}: #{val}"
|
70
|
+
end.join(", ")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: primer_view_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.48
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -487,6 +487,10 @@ files:
|
|
487
487
|
- lib/primer/view_components/linters/helpers.rb
|
488
488
|
- lib/primer/view_components/statuses.rb
|
489
489
|
- lib/primer/view_components/version.rb
|
490
|
+
- lib/rubocop/config/default.yml
|
491
|
+
- lib/rubocop/cop/primer.rb
|
492
|
+
- lib/rubocop/cop/primer/no_tag_memoize.rb
|
493
|
+
- lib/rubocop/cop/primer/system_argument_instead_of_class.rb
|
490
494
|
- lib/tasks/coverage.rake
|
491
495
|
- lib/tasks/docs.rake
|
492
496
|
- lib/tasks/statuses.rake
|