primer_view_components 0.0.46 → 0.0.47
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 +45 -0
- data/app/components/primer/avatar_stack_component.rb +2 -2
- data/app/components/primer/beta/auto_complete.rb +159 -0
- data/app/components/primer/beta/auto_complete/auto_complete.d.ts +1 -0
- data/app/components/primer/{auto_complete → beta/auto_complete}/auto_complete.html.erb +0 -0
- data/app/components/primer/beta/auto_complete/auto_complete.js +1 -0
- data/app/components/primer/{auto_complete → beta/auto_complete}/auto_complete.ts +0 -0
- data/app/components/primer/beta/auto_complete/item.rb +44 -0
- data/app/components/primer/beta/avatar.rb +77 -0
- data/app/components/primer/details_component.rb +7 -7
- data/app/components/primer/markdown.rb +9 -9
- data/app/components/primer/popover_component.rb +6 -3
- data/app/components/primer/primer.d.ts +1 -1
- data/app/components/primer/primer.js +1 -1
- data/app/components/primer/primer.ts +1 -1
- data/app/components/primer/timeline_item_component.rb +2 -2
- data/app/components/primer/truncate.rb +5 -0
- data/app/components/primer/underline_nav_component.rb +1 -1
- data/lib/primer/classify.rb +1 -11
- data/lib/primer/classify/utilities.rb +22 -11
- data/lib/primer/view_components/linters/helpers.rb +17 -0
- data/lib/primer/view_components/statuses.rb +14 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/tasks/docs.rake +70 -16
- data/lib/yard/docs_helper.rb +1 -1
- data/static/statuses.json +4 -4
- metadata +10 -7
- data/app/components/primer/auto_complete.rb +0 -157
- data/app/components/primer/auto_complete/item.rb +0 -42
- data/app/components/primer/avatar_component.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b0ba62c9f5f11df09d24b40ca5e61e7d618046aba651ad733c8db06c482fe26
|
4
|
+
data.tar.gz: 34c0b8066b85d5392dd241baeb3b654ba47d7de1f360b793ac893750989d99dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47e1bca34582e4406fcc268ac786a322cc3f99a62789aeece262b91e1ca26a15c145835ad60afbcd85a13b3a37da7a54541aedf8e2af5b60c43d7d6cf6767072
|
7
|
+
data.tar.gz: 2edfb035e82896ea22bec576a98b34eb2e3c18cccf2d3ba18744f7b77135f6a1310b466179025c216d396708fdf5fbe802a2dc436c57d1510632eb9567776df1
|
data/CHANGELOG.md
CHANGED
@@ -30,6 +30,51 @@ The category for changes related to documentation, testing and tooling. Also, fo
|
|
30
30
|
|
31
31
|
## main
|
32
32
|
|
33
|
+
## 0.0.47
|
34
|
+
|
35
|
+
### Breaking changes
|
36
|
+
|
37
|
+
* Restrict tag for `Popover` to `:div` and `Popover` heading slot to headings.
|
38
|
+
|
39
|
+
*Kate Higa*
|
40
|
+
|
41
|
+
* Renames:
|
42
|
+
* `Primer::AutoComplete` to `Primer::Beta::AutoComplete`
|
43
|
+
* `Primer::AutoComplete::Item` to `Primer::Beta::AutoComplete::Item`
|
44
|
+
* `Primer::AvatarComponent` to `Primer::Beta::Avatar`
|
45
|
+
|
46
|
+
*Manuel Puyol*
|
47
|
+
|
48
|
+
### Misc
|
49
|
+
|
50
|
+
* Update `doc_examples_axe_test` to exclude non-standalone components and fix `Markdown` example.
|
51
|
+
|
52
|
+
*Kate Higa*
|
53
|
+
|
54
|
+
* Update `DetailsComponent` examples.
|
55
|
+
|
56
|
+
*Manuel Puyol*
|
57
|
+
|
58
|
+
* Add linter to suggest system arguments instead of classes.
|
59
|
+
|
60
|
+
*Manuel Puyol*
|
61
|
+
|
62
|
+
* Update component generator to create components in the right status module.
|
63
|
+
|
64
|
+
*Manuel Puyol*
|
65
|
+
|
66
|
+
* Add example for truncating HTML to `Truncate`.
|
67
|
+
|
68
|
+
*Joel Hawksley*
|
69
|
+
|
70
|
+
* Update docs generation to point to the correct file sources.
|
71
|
+
|
72
|
+
*Manuel Puyol*
|
73
|
+
|
74
|
+
* Add ENV flag to dump linter data into a file.
|
75
|
+
|
76
|
+
*Manuel Puyol*
|
77
|
+
|
33
78
|
## 0.0.46
|
34
79
|
|
35
80
|
### Updates
|
@@ -15,8 +15,8 @@ module Primer
|
|
15
15
|
BODY_TAG_OPTIONS = TAG_OPTIONS = [DEFAULT_TAG, :span].freeze
|
16
16
|
# Required list of stacked avatars.
|
17
17
|
#
|
18
|
-
# @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::
|
19
|
-
renders_many :avatars, Primer::
|
18
|
+
# @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Avatar) %>.
|
19
|
+
renders_many :avatars, "Primer::Beta::Avatar"
|
20
20
|
|
21
21
|
# @example Default
|
22
22
|
# <%= render(Primer::AvatarStackComponent.new) do |c| %>
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Beta
|
5
|
+
# Use `AutoComplete` to provide a user with a list of selectable suggestions that appear when they type into the
|
6
|
+
# input field. This list is populated by server search results.
|
7
|
+
# @accessibility
|
8
|
+
# Always set an accessible label to help the user interact with the component.
|
9
|
+
#
|
10
|
+
# * Set the `label` slot to render a visible label. Alternatively, associate an existing visible text element
|
11
|
+
# as a label by setting `aria-labelledby`.
|
12
|
+
# * If you must use a non-visible label, set `:"aria-label"` on `AutoComplete` and Primer
|
13
|
+
# will apply it to the correct elements. However, please note that a visible label should almost
|
14
|
+
# always be used unless there is compelling reason not to. A placeholder is not a label.
|
15
|
+
class AutoComplete < Primer::Component
|
16
|
+
status :beta
|
17
|
+
|
18
|
+
# Optionally render a visible label. See <%= link_to_accessibility %>
|
19
|
+
#
|
20
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
21
|
+
renders_one :label, lambda { |**system_arguments|
|
22
|
+
system_arguments[:for] = @input_id
|
23
|
+
system_arguments[:tag] = :label
|
24
|
+
Primer::BaseComponent.new(**system_arguments)
|
25
|
+
}
|
26
|
+
|
27
|
+
# Required input used to search for results
|
28
|
+
#
|
29
|
+
# @param type [Symbol] <%= one_of(Primer::Beta::AutoComplete::Input::TYPE_OPTIONS) %>
|
30
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
31
|
+
renders_one :input, lambda { |**system_arguments|
|
32
|
+
aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label) || @aria_label
|
33
|
+
if aria_label.present?
|
34
|
+
system_arguments[:"aria-label"] = aria_label
|
35
|
+
system_arguments[:aria]&.delete(:label)
|
36
|
+
end
|
37
|
+
|
38
|
+
name = system_arguments[:name] || @input_id
|
39
|
+
Input.new(id: @input_id, name: name, **system_arguments)
|
40
|
+
}
|
41
|
+
|
42
|
+
# Optional icon to be rendered before the input. Has the same arguments as <%= link_to_component(Primer::OcticonComponent) %>.
|
43
|
+
#
|
44
|
+
renders_one :icon, Primer::OcticonComponent
|
45
|
+
|
46
|
+
# Customizable results list.
|
47
|
+
#
|
48
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
49
|
+
renders_one :results, lambda { |**system_arguments|
|
50
|
+
system_arguments[:tag] = :ul
|
51
|
+
system_arguments[:id] = @list_id
|
52
|
+
system_arguments[:classes] = class_names(
|
53
|
+
"autocomplete-results",
|
54
|
+
system_arguments[:classes]
|
55
|
+
)
|
56
|
+
|
57
|
+
aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label) || @aria_label
|
58
|
+
system_arguments[:"aria-label"] = aria_label if aria_label.present?
|
59
|
+
system_arguments[:aria]&.delete(:label)
|
60
|
+
|
61
|
+
Primer::BaseComponent.new(**system_arguments)
|
62
|
+
}
|
63
|
+
|
64
|
+
# @example Default
|
65
|
+
# <%= render(Primer::Beta::AutoComplete.new(src: "/auto_complete", input_id: "fruits-input-1", list_id: "fruits-popup-1", position: :relative)) do |c| %>
|
66
|
+
# <% c.label(classes:"").with_content("Fruits") %>
|
67
|
+
# <% c.input(type: :text) %>
|
68
|
+
# <% end %>
|
69
|
+
#
|
70
|
+
# @example With `aria-label`
|
71
|
+
# <%= render(Primer::Beta::AutoComplete.new("aria-label": "Fruits", src: "/auto_complete", input_id: "fruits-input-2", list_id: "fruits-popup-2", position: :relative)) do |c| %>
|
72
|
+
# <% c.input(type: :text) %>
|
73
|
+
# <% end %>
|
74
|
+
#
|
75
|
+
# @example With `aria-labelledby`
|
76
|
+
# <%= render(Primer::HeadingComponent.new(tag: :h2, id: "search-1")) { "Search" } %>
|
77
|
+
# <%= render(Primer::Beta::AutoComplete.new(src: "/auto_complete", input_id: "fruits-input-3", list_id: "fruits-popup-2", position: :relative)) do |c| %>
|
78
|
+
# <% c.input("aria-labelledby": "search-1") %>
|
79
|
+
# <% end %>
|
80
|
+
#
|
81
|
+
# @example With custom classes for the results
|
82
|
+
# <%= render(Primer::Beta::AutoComplete.new(src: "/auto_complete", input_id: "fruits-input-4", list_id: "fruits-popup-3", position: :relative)) do |c| %>
|
83
|
+
# <% c.label(classes:"").with_content("Fruits") %>
|
84
|
+
# <% c.input(type: :text) %>
|
85
|
+
# <% c.results(classes: "custom-class") do %>
|
86
|
+
# <%= render(Primer::Beta::AutoComplete::Item.new(selected: true, value: "apple")) do |c| %>
|
87
|
+
# Apple
|
88
|
+
# <% end %>
|
89
|
+
# <%= render(Primer::Beta::AutoComplete::Item.new(value: "orange")) do |c| %>
|
90
|
+
# Orange
|
91
|
+
# <% end %>
|
92
|
+
# <% end %>
|
93
|
+
# <% end %>
|
94
|
+
#
|
95
|
+
# @example With Icon
|
96
|
+
# <%= render(Primer::Beta::AutoComplete.new(src: "/auto_complete", list_id: "fruits-popup-4", input_id: "fruits-input-4", position: :relative)) do |c| %>
|
97
|
+
# <% c.label(classes:"").with_content("Fruits") %>
|
98
|
+
# <% c.input(type: :text) %>
|
99
|
+
# <% c.icon(icon: :search) %>
|
100
|
+
# <% end %>
|
101
|
+
#
|
102
|
+
# @param src [String] The route to query.
|
103
|
+
# @param input_id [String] Id of the input element.
|
104
|
+
# @param list_id [String] Id of the list element.
|
105
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
106
|
+
def initialize(src:, list_id:, input_id:, **system_arguments)
|
107
|
+
@list_id = list_id
|
108
|
+
@input_id = input_id
|
109
|
+
@aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label)
|
110
|
+
|
111
|
+
system_arguments.delete(:"aria-label") && system_arguments[:aria]&.delete(:label)
|
112
|
+
|
113
|
+
@system_arguments = system_arguments
|
114
|
+
@system_arguments[:tag] = "auto-complete"
|
115
|
+
@system_arguments[:src] = src
|
116
|
+
@system_arguments[:for] = list_id
|
117
|
+
end
|
118
|
+
|
119
|
+
# add `results` without needing to explicitly call it in the view
|
120
|
+
def before_render
|
121
|
+
raise ArgumentError, "Missing `input` slot" if input.blank?
|
122
|
+
raise ArgumentError, "Accessible label is required." if label.blank? && input.missing_label?
|
123
|
+
|
124
|
+
results(classes: "") unless results
|
125
|
+
end
|
126
|
+
|
127
|
+
# This component is part of `Primer::Beta::AutoCompleteComponent` and should not be
|
128
|
+
# used as a standalone component.
|
129
|
+
class Input < Primer::Component
|
130
|
+
DEFAULT_TYPE = :text
|
131
|
+
TYPE_OPTIONS = [DEFAULT_TYPE, :search].freeze
|
132
|
+
|
133
|
+
# @param type [Symbol] <%= one_of(Primer::Beta::AutoComplete::Input::TYPE_OPTIONS) %>
|
134
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
135
|
+
def initialize(type: DEFAULT_TYPE, **system_arguments)
|
136
|
+
@system_arguments = system_arguments
|
137
|
+
@system_arguments[:tag] = :input
|
138
|
+
|
139
|
+
@aria_label = system_arguments[:"aria-label"]
|
140
|
+
@aria_labelledby = system_arguments[:"aria-labelledby"] || system_arguments.dig(:aria, :labelledby)
|
141
|
+
|
142
|
+
@system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE)
|
143
|
+
@system_arguments[:classes] = class_names(
|
144
|
+
"form-control",
|
145
|
+
system_arguments[:classes]
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
def missing_label?
|
150
|
+
@aria_label.blank? && @aria_labelledby.blank?
|
151
|
+
end
|
152
|
+
|
153
|
+
def call
|
154
|
+
render(Primer::BaseComponent.new(**@system_arguments))
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
import '@github/auto-complete-element';
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
import '@github/auto-complete-element';
|
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Beta
|
5
|
+
class AutoComplete
|
6
|
+
# Use `AutoCompleteItem` to list results of an auto-completed search.
|
7
|
+
class Item < Primer::Component
|
8
|
+
status :beta
|
9
|
+
|
10
|
+
# @example Default
|
11
|
+
# <%= render(Primer::Beta::AutoComplete::Item.new(selected: true, value: "value")) do |c| %>
|
12
|
+
# Selected
|
13
|
+
# <% end %>
|
14
|
+
# <%= render(Primer::Beta::AutoComplete::Item.new(value: "value")) do |c| %>
|
15
|
+
# Not selected
|
16
|
+
# <% end %>
|
17
|
+
#
|
18
|
+
# @param value [String] Value of the item.
|
19
|
+
# @param selected [Boolean] Whether the item is selected.
|
20
|
+
# @param disabled [Boolean] Whether the item is disabled.
|
21
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
22
|
+
def initialize(value:, selected: false, disabled: false, **system_arguments)
|
23
|
+
@system_arguments = system_arguments
|
24
|
+
@system_arguments[:tag] = :li
|
25
|
+
@system_arguments[:role] = :option
|
26
|
+
@system_arguments[:"data-autocomplete-value"] = value
|
27
|
+
|
28
|
+
@system_arguments[:"aria-selected"] = true if selected
|
29
|
+
@system_arguments[:"aria-disabled"] = true if disabled
|
30
|
+
|
31
|
+
@system_arguments[:classes] = class_names(
|
32
|
+
"autocomplete-item",
|
33
|
+
system_arguments[:classes],
|
34
|
+
"disabled" => disabled
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def call
|
39
|
+
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Beta
|
5
|
+
# `Avatar` can be used to represent users and organizations on GitHub.
|
6
|
+
#
|
7
|
+
# - Use the default round avatar for users, and the `square` argument
|
8
|
+
# for organizations or any other non-human avatars.
|
9
|
+
# - By default, `Avatar` will render a static `<img>`. To have `Avatar` function as a link, set the `href` which will wrap the `<img>` in a `<a>`.
|
10
|
+
# - Set `size` to update the height and width of the `Avatar` in pixels.
|
11
|
+
# - To stack multiple avatars together, use <%= link_to_component(Primer::AvatarStackComponent) %>.
|
12
|
+
#
|
13
|
+
# @accessibility
|
14
|
+
# Images should have text alternatives that describe the information or function represented.
|
15
|
+
# If the avatar functions as a link, provide alt text that helps convey the function. For instance,
|
16
|
+
# if `Avatar` is a link to a user profile, the alt attribute should be `@kittenuser profile`
|
17
|
+
# rather than `@kittenuser`.
|
18
|
+
# [Learn more about best image practices (WAI Images)](https://www.w3.org/WAI/tutorials/images/)
|
19
|
+
class Avatar < Primer::Component
|
20
|
+
status :beta
|
21
|
+
|
22
|
+
SMALL_THRESHOLD = 24
|
23
|
+
|
24
|
+
# @example Default
|
25
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser")) %>
|
26
|
+
#
|
27
|
+
# @example Square
|
28
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", square: true)) %>
|
29
|
+
#
|
30
|
+
# @example Link
|
31
|
+
# <%= render(Primer::Beta::Avatar.new(href: "#", src: "http://placekitten.com/200/200", alt: "@kittenuser profile")) %>
|
32
|
+
#
|
33
|
+
# @example With size
|
34
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 16)) %>
|
35
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 20)) %>
|
36
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 24)) %>
|
37
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 28)) %>
|
38
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 32)) %>
|
39
|
+
# <%= render(Primer::Beta::Avatar.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 36)) %>
|
40
|
+
#
|
41
|
+
# @param src [String] The source url of the avatar image.
|
42
|
+
# @param alt [String] Passed through to alt on img tag.
|
43
|
+
# @param size [Integer] Adds the avatar-small class if less than 24.
|
44
|
+
# @param square [Boolean] Used to create a square avatar.
|
45
|
+
# @param href [String] The URL to link to. If used, component will be wrapped by an `<a>` tag.
|
46
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
47
|
+
def initialize(src:, alt:, size: 20, square: false, href: nil, **system_arguments)
|
48
|
+
@href = href
|
49
|
+
@system_arguments = system_arguments
|
50
|
+
@system_arguments[:tag] = :img
|
51
|
+
@system_arguments[:src] = src
|
52
|
+
@system_arguments[:alt] = alt
|
53
|
+
@system_arguments[:size] = size
|
54
|
+
@system_arguments[:height] = size
|
55
|
+
@system_arguments[:width] = size
|
56
|
+
|
57
|
+
@system_arguments[:classes] = class_names(
|
58
|
+
system_arguments[:classes],
|
59
|
+
"avatar",
|
60
|
+
"avatar-small" => size < SMALL_THRESHOLD,
|
61
|
+
"circle" => !square,
|
62
|
+
"lh-0" => href # Addresses an overflow issue with linked avatars
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def call
|
67
|
+
if @href
|
68
|
+
render(Primer::LinkComponent.new(href: @href, classes: @system_arguments[:classes])) do
|
69
|
+
render(Primer::BaseComponent.new(**@system_arguments.except(:classes))) { content }
|
70
|
+
end
|
71
|
+
else
|
72
|
+
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -29,7 +29,7 @@ module Primer
|
|
29
29
|
|
30
30
|
# Use the Body slot as the main content to be shown when triggered by the Summary.
|
31
31
|
#
|
32
|
-
# @param tag [
|
32
|
+
# @param tag [Symbol] (Primer::DetailsComponent::BODY_TAG_DEFAULT) <%= one_of(Primer::DetailsComponent::BODY_TAG_OPTIONS) %>
|
33
33
|
# @param kwargs [Hash] The same arguments as <%= link_to_system_arguments_docs %>.
|
34
34
|
renders_one :body, lambda { |tag: BODY_TAG_DEFAULT, **system_arguments|
|
35
35
|
system_arguments[:tag] = fetch_or_fallback(BODY_TAG_OPTIONS, tag, BODY_TAG_DEFAULT)
|
@@ -40,12 +40,12 @@ module Primer
|
|
40
40
|
# @example Default
|
41
41
|
#
|
42
42
|
# <%= render Primer::DetailsComponent.new do |c| %>
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# end
|
43
|
+
# <% c.summary do %>
|
44
|
+
# Summary
|
45
|
+
# <% end %>
|
46
|
+
# <% c.body do %>
|
47
|
+
# Body
|
48
|
+
# <% end %>
|
49
49
|
# <% end %>
|
50
50
|
#
|
51
51
|
# @param overlay [Symbol] Dictates the type of overlay to render with. <%= one_of(Primer::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
|
@@ -99,17 +99,17 @@ module Primer
|
|
99
99
|
# <p>And an unordered task list:</p>
|
100
100
|
#
|
101
101
|
# <ul>
|
102
|
-
# <li><input type="checkbox" checked
|
103
|
-
# <li><input type="checkbox"
|
104
|
-
# <li><input type="checkbox"
|
102
|
+
# <li><input type="checkbox" id="create-markdown" checked /><label for="create-markdown">Create a sample markdown document</label><br></li>
|
103
|
+
# <li><input type="checkbox" id="tasks-list" checked /><label for="tasks-list">Add tasks list to it</label><br></li>
|
104
|
+
# <li><input type="checkbox" id="take-vacation" checked /><label for="take-vacation">Take a vacation</label><br></li>
|
105
105
|
# </ul>
|
106
106
|
#
|
107
107
|
# <p>And a "mixed" task list:</p>
|
108
108
|
#
|
109
109
|
# <ul>
|
110
|
-
# <li><input type="checkbox"
|
110
|
+
# <li><input type="checkbox"id="steal-underpants"/><label for="steal-underpants">Steal underpants</label></li>
|
111
111
|
# <li>?</li>
|
112
|
-
# <li><input type="checkbox"
|
112
|
+
# <li><input type="checkbox"id="profit"/><label for="profit">Profit!</label></li>
|
113
113
|
# </ul>
|
114
114
|
#
|
115
115
|
# And a nested list:
|
@@ -241,9 +241,9 @@ module Primer
|
|
241
241
|
#
|
242
242
|
# <pre><code>var foo = "bar";</code></pre>
|
243
243
|
#
|
244
|
-
# <pre><code>Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.</code></pre>
|
244
|
+
# <pre tabindex="0"><code>Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.</code></pre>
|
245
245
|
#
|
246
|
-
# <pre><code>var foo = "The same thing is true for code with syntax highlighting. A single line of code should horizontally scroll if it is really long.";</code></pre>
|
246
|
+
# <pre tabindex="0"><code>var foo = "The same thing is true for code with syntax highlighting. A single line of code should horizontally scroll if it is really long.";</code></pre>
|
247
247
|
#
|
248
248
|
# <p>Inline code inside table cells should still be distinguishable.</p>
|
249
249
|
#
|
@@ -270,11 +270,11 @@ module Primer
|
|
270
270
|
#
|
271
271
|
# <p>Small images should be shown at their actual size.</p>
|
272
272
|
#
|
273
|
-
# <p><img src="http://placekitten.com/g/300/200/"/></p>
|
273
|
+
# <p><img alt="kitten" src="http://placekitten.com/g/300/200/"/></p>
|
274
274
|
#
|
275
275
|
# <p>Large images should always scale down and fit in the content container.</p>
|
276
276
|
#
|
277
|
-
# <p><img src="http://placekitten.com/g/1200/800/"/></p>
|
277
|
+
# <p><img alt="kitten" src="http://placekitten.com/g/1200/800/"/></p>
|
278
278
|
#
|
279
279
|
# <pre><code>This is the final element on the page and there should be no margin below this.</code></pre>
|
280
280
|
# <% end %>
|
@@ -23,12 +23,15 @@ module Primer
|
|
23
23
|
:top_right => "Popover-message--top-right"
|
24
24
|
}.freeze
|
25
25
|
|
26
|
+
DEFAULT_HEADING_TAG = :h4
|
27
|
+
|
26
28
|
# The heading
|
27
29
|
#
|
30
|
+
# @param tag [Symbol] (Primer::PopoverComponent::DEFAULT_HEADING_TAG) <%= one_of(Primer::HeadingComponent::TAG_OPTIONS) %>
|
28
31
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
29
|
-
renders_one :heading, lambda {
|
32
|
+
renders_one :heading, lambda { |tag: DEFAULT_HEADING_TAG, **system_arguments|
|
33
|
+
system_arguments[:tag] = tag
|
30
34
|
system_arguments[:mb] ||= 2
|
31
|
-
system_arguments[:tag] ||= :h4 # rubocop:disable Primer/NoTagMemoize
|
32
35
|
|
33
36
|
Primer::HeadingComponent.new(**system_arguments)
|
34
37
|
}
|
@@ -106,7 +109,7 @@ module Primer
|
|
106
109
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
107
110
|
def initialize(**system_arguments)
|
108
111
|
@system_arguments = system_arguments
|
109
|
-
@system_arguments[:tag]
|
112
|
+
@system_arguments[:tag] = :div
|
110
113
|
@system_arguments[:classes] = class_names(
|
111
114
|
system_arguments[:classes],
|
112
115
|
"Popover"
|
@@ -7,14 +7,14 @@ module Primer
|
|
7
7
|
|
8
8
|
# Avatar to be rendered to the left of the Badge.
|
9
9
|
#
|
10
|
-
# @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::
|
10
|
+
# @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Avatar) %>.
|
11
11
|
renders_one :avatar, lambda { |src:, size: 40, square: true, **system_arguments|
|
12
12
|
system_arguments[:classes] = class_names(
|
13
13
|
"TimelineItem-avatar",
|
14
14
|
system_arguments[:classes]
|
15
15
|
)
|
16
16
|
|
17
|
-
Primer::
|
17
|
+
Primer::Beta::Avatar.new(src: src, size: size, square: square, **system_arguments)
|
18
18
|
}
|
19
19
|
|
20
20
|
# Badge that will be connected to other TimelineItems.
|
@@ -22,6 +22,11 @@ module Primer
|
|
22
22
|
# @example Custom size
|
23
23
|
# <%= render(Primer::Truncate.new(tag: :span, inline: true, expandable: true, max_width: 100)) { "branch-name-that-is-really-long" } %>
|
24
24
|
#
|
25
|
+
# @example With HTML content
|
26
|
+
# <%= render(Primer::Truncate.new(tag: :span, inline: true, expandable: true, max_width: 100)) do %>
|
27
|
+
# <span>branch-name-that-is-really-long</span>
|
28
|
+
# <% end %>
|
29
|
+
#
|
25
30
|
# @param tag [Symbol] <%= one_of(Primer::Truncate::TAG_OPTIONS) %>
|
26
31
|
# @param inline [Boolean] Whether the element is inline (or inline-block).
|
27
32
|
# @param expandable [Boolean] Whether the entire string should be revealed on hover. Can only be used in conjunction with `inline`.
|
@@ -38,7 +38,7 @@ module Primer
|
|
38
38
|
|
39
39
|
# Use actions for a call to action.
|
40
40
|
#
|
41
|
-
# @param tag [
|
41
|
+
# @param tag [Symbol] (Primer::UnderlineNavComponent::ACTIONS_TAG_DEFAULT) <%= one_of(Primer::UnderlineNavComponent::ACTIONS_TAG_OPTIONS) %>
|
42
42
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
43
43
|
renders_one :actions, lambda { |tag: ACTIONS_TAG_DEFAULT, **system_arguments|
|
44
44
|
system_arguments[:tag] = fetch_or_fallback(ACTIONS_TAG_OPTIONS, tag, ACTIONS_TAG_DEFAULT)
|
data/lib/primer/classify.rb
CHANGED
@@ -11,16 +11,6 @@ require_relative "classify/utilities"
|
|
11
11
|
module Primer
|
12
12
|
# :nodoc:
|
13
13
|
class Classify
|
14
|
-
# Load the utilities.yml file.
|
15
|
-
# Disabling because we want to load symbols, strings, and integers from the .yml file
|
16
|
-
# rubocop:disable Security/YAMLLoad
|
17
|
-
UTILITIES = YAML.load(
|
18
|
-
File.read(
|
19
|
-
File.join(File.dirname(__FILE__), "./classify/utilities.yml")
|
20
|
-
)
|
21
|
-
).freeze
|
22
|
-
# rubocop:enable Security/YAMLLoad
|
23
|
-
|
24
14
|
# Keys where we can simply translate { key: value } into ".key-value"
|
25
15
|
CONCAT_KEYS = %i[text box_shadow].freeze
|
26
16
|
|
@@ -90,7 +80,7 @@ module Primer
|
|
90
80
|
BORDER_RADIUS_KEY = :border_radius
|
91
81
|
TYPOGRAPHY_KEYS = [:font_size].freeze
|
92
82
|
VALID_KEYS = (
|
93
|
-
UTILITIES.keys +
|
83
|
+
Primer::Classify::Utilities::UTILITIES.keys +
|
94
84
|
CONCAT_KEYS +
|
95
85
|
BOOLEAN_MAPPINGS.keys +
|
96
86
|
BORDER_MARGIN_KEYS +
|
@@ -5,13 +5,24 @@ module Primer
|
|
5
5
|
class Classify
|
6
6
|
# Handler for PrimerCSS utility classes loaded from utilities.rake
|
7
7
|
class Utilities
|
8
|
+
# Load the utilities.yml file.
|
9
|
+
# Disabling because we want to load symbols, strings, and integers from the .yml file
|
10
|
+
# rubocop:disable Security/YAMLLoad
|
11
|
+
UTILITIES = YAML.load(
|
12
|
+
File.read(
|
13
|
+
File.join(File.dirname(__FILE__), "./utilities.yml")
|
14
|
+
)
|
15
|
+
).freeze
|
16
|
+
# rubocop:enable Security/YAMLLoad
|
17
|
+
BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"].freeze
|
18
|
+
|
8
19
|
class << self
|
9
20
|
def classname(key, val, breakpoint = "")
|
10
21
|
if (valid = validate(key, val, breakpoint))
|
11
22
|
valid
|
12
23
|
else
|
13
24
|
# Get selector
|
14
|
-
|
25
|
+
UTILITIES[key][val][BREAKPOINTS.index(breakpoint)]
|
15
26
|
end
|
16
27
|
end
|
17
28
|
|
@@ -19,14 +30,14 @@ module Primer
|
|
19
30
|
#
|
20
31
|
# returns Boolean
|
21
32
|
def supported_key?(key)
|
22
|
-
|
33
|
+
UTILITIES[key].present?
|
23
34
|
end
|
24
35
|
|
25
36
|
# Does the Utilitiy class support the given key and value
|
26
37
|
#
|
27
38
|
# returns Boolean
|
28
39
|
def supported_value?(key, val)
|
29
|
-
supported_key?(key) &&
|
40
|
+
supported_key?(key) && UTILITIES[key][val].present?
|
30
41
|
end
|
31
42
|
|
32
43
|
# Does the given selector exist in the utilities file
|
@@ -34,7 +45,7 @@ module Primer
|
|
34
45
|
# returns Boolean
|
35
46
|
def supported_selector?(selector)
|
36
47
|
# This method is too slow to run in production
|
37
|
-
return false if
|
48
|
+
return false if ENV["RAILS_ENV"] == "production"
|
38
49
|
|
39
50
|
find_selector(selector).present?
|
40
51
|
end
|
@@ -43,7 +54,7 @@ module Primer
|
|
43
54
|
#
|
44
55
|
# returns Boolean
|
45
56
|
def responsive?(key, val)
|
46
|
-
supported_value?(key, val) &&
|
57
|
+
supported_value?(key, val) && UTILITIES[key][val].count > 1
|
47
58
|
end
|
48
59
|
|
49
60
|
# Get the options for the given key
|
@@ -52,13 +63,13 @@ module Primer
|
|
52
63
|
def mappings(key)
|
53
64
|
return unless supported_key?(key)
|
54
65
|
|
55
|
-
|
66
|
+
UTILITIES[key].keys
|
56
67
|
end
|
57
68
|
|
58
69
|
# Extract hash from classes ie. "mr-1 mb-2 foo" => { mr: 1, mb: 2, classes: "foo" }
|
59
70
|
def classes_to_hash(classes)
|
60
71
|
# This method is too slow to run in production
|
61
|
-
return { classes: classes } if
|
72
|
+
return { classes: classes } if ENV["RAILS_ENV"] == "production"
|
62
73
|
|
63
74
|
obj = {}
|
64
75
|
classes = classes.split(" ")
|
@@ -94,7 +105,7 @@ module Primer
|
|
94
105
|
|
95
106
|
def find_selector(selector)
|
96
107
|
# Search each key/value_hash pair, eg. key `:mr` and value_hash `{ 0 => [ "mr-0", "mr-sm-0", "mr-md-0", "mr-lg-0", "mr-xl-0" ] }`
|
97
|
-
|
108
|
+
UTILITIES.each do |key, value_hash|
|
98
109
|
# Each value hash will also contain an array of classnames for breakpoints
|
99
110
|
# Key argument `0`, classes `[ "mr-0", "mr-sm-0", "mr-md-0", "mr-lg-0", "mr-xl-0" ]`
|
100
111
|
value_hash.each do |key_argument, classnames|
|
@@ -112,19 +123,19 @@ module Primer
|
|
112
123
|
|
113
124
|
def validate(key, val, breakpoint)
|
114
125
|
unless supported_key?(key)
|
115
|
-
raise ArgumentError, "#{key} is not a valid Primer utility key" unless
|
126
|
+
raise ArgumentError, "#{key} is not a valid Primer utility key" unless ENV["RAILS_ENV"] == "production"
|
116
127
|
|
117
128
|
return ""
|
118
129
|
end
|
119
130
|
|
120
131
|
unless breakpoint.empty? || responsive?(key, val)
|
121
|
-
raise ArgumentError, "#{key} does not support responsive values" unless
|
132
|
+
raise ArgumentError, "#{key} does not support responsive values" unless ENV["RAILS_ENV"] == "production"
|
122
133
|
|
123
134
|
return ""
|
124
135
|
end
|
125
136
|
|
126
137
|
unless supported_value?(key, val)
|
127
|
-
raise ArgumentError, "#{val} is not a valid value for :#{key}. Use one of #{mappings(key)}" unless
|
138
|
+
raise ArgumentError, "#{val} is not a valid value for :#{key}. Use one of #{mappings(key)}" unless ENV["RAILS_ENV"] == "production"
|
128
139
|
|
129
140
|
return ""
|
130
141
|
end
|
@@ -13,10 +13,13 @@ module ERBLint
|
|
13
13
|
link menuitem meta param source track wbr img
|
14
14
|
].freeze
|
15
15
|
|
16
|
+
DUMP_FILE = ".erblint-counter-ignore.json"
|
17
|
+
|
16
18
|
def self.included(base)
|
17
19
|
base.include(ERBLint::LinterRegistry)
|
18
20
|
|
19
21
|
define_method "run" do |processed_source|
|
22
|
+
@total_offenses = 0
|
20
23
|
@offenses_not_corrected = 0
|
21
24
|
tags = tags(processed_source)
|
22
25
|
tag_tree = build_tag_tree(tags)
|
@@ -43,6 +46,7 @@ module ERBLint
|
|
43
46
|
tag_tree.each do |tag, h|
|
44
47
|
next unless h[:offense]
|
45
48
|
|
49
|
+
@total_offenses += 1
|
46
50
|
# We always fix the offenses using blocks. The closing tag corresponds to `<% end %>`.
|
47
51
|
if h[:correctable]
|
48
52
|
add_offense(tag.loc, h[:message], h[:correction])
|
@@ -54,6 +58,8 @@ module ERBLint
|
|
54
58
|
end
|
55
59
|
|
56
60
|
counter_correct?(processed_source)
|
61
|
+
|
62
|
+
dump_data(processed_source) if ENV["DUMP_LINT_DATA"] == "1"
|
57
63
|
end
|
58
64
|
|
59
65
|
define_method "autocorrect" do |processed_source, offense|
|
@@ -186,6 +192,17 @@ module ERBLint
|
|
186
192
|
offense = ["#{klass_name}:#{message}", tag.node.loc.source].join("\n")
|
187
193
|
add_offense(processed_source.to_source_range(tag.loc), offense, replacement)
|
188
194
|
end
|
195
|
+
|
196
|
+
def dump_data(processed_source)
|
197
|
+
return if @total_offenses.zero?
|
198
|
+
|
199
|
+
data = File.exist?(DUMP_FILE) ? JSON.parse(File.read(DUMP_FILE)) : {}
|
200
|
+
|
201
|
+
data[processed_source.filename] ||= {}
|
202
|
+
data[processed_source.filename][self.class.name.demodulize] = @total_offenses
|
203
|
+
|
204
|
+
File.write(DUMP_FILE, JSON.pretty_generate(data))
|
205
|
+
end
|
189
206
|
end
|
190
207
|
end
|
191
208
|
end
|
data/lib/tasks/docs.rake
CHANGED
@@ -32,9 +32,9 @@ namespace :docs do
|
|
32
32
|
Primer::OcticonSymbolsComponent,
|
33
33
|
Primer::ImageCrop,
|
34
34
|
Primer::IconButton,
|
35
|
-
Primer::AutoComplete,
|
36
|
-
Primer::AutoComplete::Item,
|
37
|
-
Primer::
|
35
|
+
Primer::Beta::AutoComplete,
|
36
|
+
Primer::Beta::AutoComplete::Item,
|
37
|
+
Primer::Beta::Avatar,
|
38
38
|
Primer::AvatarStackComponent,
|
39
39
|
Primer::BaseButton,
|
40
40
|
Primer::BlankslateComponent,
|
@@ -81,7 +81,7 @@ namespace :docs do
|
|
81
81
|
Primer::Dropdown,
|
82
82
|
Primer::LocalTime,
|
83
83
|
Primer::ImageCrop,
|
84
|
-
Primer::AutoComplete,
|
84
|
+
Primer::Beta::AutoComplete,
|
85
85
|
Primer::ClipboardCopy,
|
86
86
|
Primer::TabContainerComponent,
|
87
87
|
Primer::TabNavComponent,
|
@@ -97,28 +97,30 @@ namespace :docs do
|
|
97
97
|
|
98
98
|
errors = []
|
99
99
|
|
100
|
-
|
100
|
+
# Deletes docs before regenerating them, guaranteeing that we don't keep stale docs.
|
101
|
+
FileUtils.rm_rf(Dir.glob("docs/content/components/**/*.md"))
|
102
|
+
|
103
|
+
components.sort_by(&:name).each do |component|
|
101
104
|
documentation = registry.get(component.name)
|
102
105
|
|
103
|
-
|
104
|
-
short_name = component.name.gsub(/Primer|::|Component/, "")
|
106
|
+
data = docs_metadata(component)
|
105
107
|
|
106
|
-
path = Pathname.new(
|
108
|
+
path = Pathname.new(data[:path])
|
107
109
|
path.dirname.mkdir unless path.dirname.exist?
|
108
110
|
File.open(path, "w") do |f|
|
109
111
|
f.puts("---")
|
110
|
-
f.puts("title: #{
|
111
|
-
f.puts("status: #{
|
112
|
-
f.puts("source:
|
113
|
-
f.puts("storybook:
|
112
|
+
f.puts("title: #{data[:title]}")
|
113
|
+
f.puts("status: #{data[:status]}")
|
114
|
+
f.puts("source: #{data[:source]}")
|
115
|
+
f.puts("storybook: #{data[:storybook]}")
|
114
116
|
f.puts("---")
|
115
117
|
f.puts
|
116
|
-
f.puts("import Example from '
|
118
|
+
f.puts("import Example from '#{data[:example_path]}'")
|
117
119
|
|
118
120
|
initialize_method = documentation.meths.find(&:constructor?)
|
119
121
|
|
120
122
|
if js_components.include?(component)
|
121
|
-
f.puts("import RequiresJSFlash from '
|
123
|
+
f.puts("import RequiresJSFlash from '#{data[:require_js_path]}'")
|
122
124
|
f.puts
|
123
125
|
f.puts("<RequiresJSFlash />")
|
124
126
|
end
|
@@ -183,8 +185,8 @@ namespace :docs do
|
|
183
185
|
end
|
184
186
|
|
185
187
|
component_args = {
|
186
|
-
"component" =>
|
187
|
-
"source" =>
|
188
|
+
"component" => data[:title],
|
189
|
+
"source" => data[:source],
|
188
190
|
"parameters" => args
|
189
191
|
}
|
190
192
|
|
@@ -346,6 +348,7 @@ namespace :docs do
|
|
346
348
|
end
|
347
349
|
|
348
350
|
def generate_yard_registry
|
351
|
+
ENV["SKIP_STORYBOOK_PRELOAD"] = "1"
|
349
352
|
require File.expand_path("./../../demo/config/environment.rb", __dir__)
|
350
353
|
require "primer/view_components"
|
351
354
|
require "yard/docs_helper"
|
@@ -384,4 +387,55 @@ namespace :docs do
|
|
384
387
|
|
385
388
|
pretty_value(constant_value)
|
386
389
|
end
|
390
|
+
|
391
|
+
def status_module_and_short_name(component)
|
392
|
+
name_with_status = component.name.gsub(/Primer::|Component/, "")
|
393
|
+
|
394
|
+
m = name_with_status.match(/(?<status>Beta|Alpha|Deprecated)?(::)?(?<name>.*)/)
|
395
|
+
[m[:status]&.downcase, m[:name].gsub("::", "")]
|
396
|
+
end
|
397
|
+
|
398
|
+
def docs_metadata(component)
|
399
|
+
(status_module, short_name) = status_module_and_short_name(component)
|
400
|
+
status_path = status_module.nil? ? "" : "#{status_module}/"
|
401
|
+
status = component.status.to_s
|
402
|
+
|
403
|
+
{
|
404
|
+
title: short_name,
|
405
|
+
status: status.capitalize,
|
406
|
+
source: source_url(component),
|
407
|
+
storybook: storybook_url(component),
|
408
|
+
path: "docs/content/components/#{status_path}#{short_name.downcase}.md",
|
409
|
+
example_path: example_path(component),
|
410
|
+
require_js_path: require_js_path(component)
|
411
|
+
}
|
412
|
+
end
|
413
|
+
|
414
|
+
def source_url(component)
|
415
|
+
path = component.name.split("::").map(&:underscore).join("/")
|
416
|
+
|
417
|
+
"https://github.com/primer/view_components/tree/main/app/components/#{path}.rb"
|
418
|
+
end
|
419
|
+
|
420
|
+
def storybook_url(component)
|
421
|
+
path = component.name.split("::").map { |n| n.underscore.dasherize }.join("-")
|
422
|
+
|
423
|
+
"https://primer.style/view-components/stories/?path=/story/#{path}"
|
424
|
+
end
|
425
|
+
|
426
|
+
def example_path(component)
|
427
|
+
example_path = "../../src/@primer/gatsby-theme-doctocat/components/example"
|
428
|
+
example_path = "../#{example_path}" if status_module?(component)
|
429
|
+
example_path
|
430
|
+
end
|
431
|
+
|
432
|
+
def require_js_path(component)
|
433
|
+
require_js_path = "../../src/@primer/gatsby-theme-doctocat/components/requires-js-flash"
|
434
|
+
require_js_path = "../#{require_js_path}" if status_module?(component)
|
435
|
+
require_js_path
|
436
|
+
end
|
437
|
+
|
438
|
+
def status_module?(component)
|
439
|
+
(%w[Alpha Beta] & component.name.split("::")).any?
|
440
|
+
end
|
387
441
|
end
|
data/lib/yard/docs_helper.rb
CHANGED
@@ -41,7 +41,7 @@ module YARD
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def link_to_component(component)
|
44
|
-
short_name = component.name.gsub(/Primer|::|Component/, "")
|
44
|
+
short_name = component.name.gsub(/Primer|::|Alpha|Beta|Component/, "")
|
45
45
|
"[#{short_name}](/components/#{short_name.downcase})"
|
46
46
|
end
|
47
47
|
|
data/static/statuses.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"Primer::Alpha::ButtonMarketing": "alpha",
|
3
|
-
"Primer::AutoComplete": "beta",
|
4
|
-
"Primer::AutoComplete::Input": "alpha",
|
5
|
-
"Primer::AutoComplete::Item": "beta",
|
6
|
-
"Primer::AvatarComponent": "beta",
|
7
3
|
"Primer::AvatarStackComponent": "beta",
|
8
4
|
"Primer::BaseButton": "beta",
|
9
5
|
"Primer::BaseComponent": "beta",
|
6
|
+
"Primer::Beta::AutoComplete": "beta",
|
7
|
+
"Primer::Beta::AutoComplete::Input": "alpha",
|
8
|
+
"Primer::Beta::AutoComplete::Item": "beta",
|
9
|
+
"Primer::Beta::Avatar": "beta",
|
10
10
|
"Primer::Beta::Text": "beta",
|
11
11
|
"Primer::BlankslateComponent": "beta",
|
12
12
|
"Primer::BorderBoxComponent": "beta",
|
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.47
|
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-
|
11
|
+
date: 2021-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -351,19 +351,21 @@ files:
|
|
351
351
|
- app/assets/javascripts/primer_view_components.js
|
352
352
|
- app/assets/javascripts/primer_view_components.js.map
|
353
353
|
- app/components/primer/alpha/button_marketing.rb
|
354
|
-
- app/components/primer/auto_complete.rb
|
355
354
|
- app/components/primer/auto_complete/auto_complete.d.ts
|
356
|
-
- app/components/primer/auto_complete/auto_complete.html.erb
|
357
355
|
- app/components/primer/auto_complete/auto_complete.js
|
358
|
-
- app/components/primer/auto_complete/auto_complete.ts
|
359
356
|
- app/components/primer/auto_complete/auto_component.d.ts
|
360
357
|
- app/components/primer/auto_complete/auto_component.js
|
361
|
-
- app/components/primer/auto_complete/item.rb
|
362
|
-
- app/components/primer/avatar_component.rb
|
363
358
|
- app/components/primer/avatar_stack_component.html.erb
|
364
359
|
- app/components/primer/avatar_stack_component.rb
|
365
360
|
- app/components/primer/base_button.rb
|
366
361
|
- app/components/primer/base_component.rb
|
362
|
+
- app/components/primer/beta/auto_complete.rb
|
363
|
+
- app/components/primer/beta/auto_complete/auto_complete.d.ts
|
364
|
+
- app/components/primer/beta/auto_complete/auto_complete.html.erb
|
365
|
+
- app/components/primer/beta/auto_complete/auto_complete.js
|
366
|
+
- app/components/primer/beta/auto_complete/auto_complete.ts
|
367
|
+
- app/components/primer/beta/auto_complete/item.rb
|
368
|
+
- app/components/primer/beta/avatar.rb
|
367
369
|
- app/components/primer/beta/text.rb
|
368
370
|
- app/components/primer/blankslate_component.html.erb
|
369
371
|
- app/components/primer/blankslate_component.rb
|
@@ -483,6 +485,7 @@ files:
|
|
483
485
|
- lib/primer/view_components/linters/button_component_migration_counter.rb
|
484
486
|
- lib/primer/view_components/linters/flash_component_migration_counter.rb
|
485
487
|
- lib/primer/view_components/linters/helpers.rb
|
488
|
+
- lib/primer/view_components/statuses.rb
|
486
489
|
- lib/primer/view_components/version.rb
|
487
490
|
- lib/tasks/coverage.rake
|
488
491
|
- lib/tasks/docs.rake
|
@@ -1,157 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Primer
|
4
|
-
# Use `AutoComplete` to provide a user with a list of selectable suggestions that appear when they type into the
|
5
|
-
# input field. This list is populated by server search results.
|
6
|
-
# @accessibility
|
7
|
-
# Always set an accessible label to help the user interact with the component.
|
8
|
-
#
|
9
|
-
# * Set the `label` slot to render a visible label. Alternatively, associate an existing visible text element
|
10
|
-
# as a label by setting `aria-labelledby`.
|
11
|
-
# * If you must use a non-visible label, set `:"aria-label"` on `AutoComplete` and Primer
|
12
|
-
# will apply it to the correct elements. However, please note that a visible label should almost
|
13
|
-
# always be used unless there is compelling reason not to. A placeholder is not a label.
|
14
|
-
class AutoComplete < Primer::Component
|
15
|
-
status :beta
|
16
|
-
|
17
|
-
# Optionally render a visible label. See <%= link_to_accessibility %>
|
18
|
-
#
|
19
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
20
|
-
renders_one :label, lambda { |**system_arguments|
|
21
|
-
system_arguments[:for] = @input_id
|
22
|
-
system_arguments[:tag] = :label
|
23
|
-
Primer::BaseComponent.new(**system_arguments)
|
24
|
-
}
|
25
|
-
|
26
|
-
# Required input used to search for results
|
27
|
-
#
|
28
|
-
# @param type [Symbol] <%= one_of(Primer::AutoComplete::Input::TYPE_OPTIONS) %>
|
29
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
30
|
-
renders_one :input, lambda { |**system_arguments|
|
31
|
-
aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label) || @aria_label
|
32
|
-
if aria_label.present?
|
33
|
-
system_arguments[:"aria-label"] = aria_label
|
34
|
-
system_arguments[:aria]&.delete(:label)
|
35
|
-
end
|
36
|
-
|
37
|
-
name = system_arguments[:name] || @input_id
|
38
|
-
Input.new(id: @input_id, name: name, **system_arguments)
|
39
|
-
}
|
40
|
-
|
41
|
-
# Optional icon to be rendered before the input. Has the same arguments as <%= link_to_component(Primer::OcticonComponent) %>.
|
42
|
-
#
|
43
|
-
renders_one :icon, Primer::OcticonComponent
|
44
|
-
|
45
|
-
# Customizable results list.
|
46
|
-
#
|
47
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
48
|
-
renders_one :results, lambda { |**system_arguments|
|
49
|
-
system_arguments[:tag] = :ul
|
50
|
-
system_arguments[:id] = @list_id
|
51
|
-
system_arguments[:classes] = class_names(
|
52
|
-
"autocomplete-results",
|
53
|
-
system_arguments[:classes]
|
54
|
-
)
|
55
|
-
|
56
|
-
aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label) || @aria_label
|
57
|
-
system_arguments[:"aria-label"] = aria_label if aria_label.present?
|
58
|
-
system_arguments[:aria]&.delete(:label)
|
59
|
-
|
60
|
-
Primer::BaseComponent.new(**system_arguments)
|
61
|
-
}
|
62
|
-
|
63
|
-
# @example Default
|
64
|
-
# <%= render(Primer::AutoComplete.new(src: "/auto_complete", input_id: "fruits-input-1", list_id: "fruits-popup-1", position: :relative)) do |c| %>
|
65
|
-
# <% c.label(classes:"").with_content("Fruits") %>
|
66
|
-
# <% c.input(type: :text) %>
|
67
|
-
# <% end %>
|
68
|
-
#
|
69
|
-
# @example With `aria-label`
|
70
|
-
# <%= render(Primer::AutoComplete.new("aria-label": "Fruits", src: "/auto_complete", input_id: "fruits-input-2", list_id: "fruits-popup-2", position: :relative)) do |c| %>
|
71
|
-
# <% c.input(type: :text) %>
|
72
|
-
# <% end %>
|
73
|
-
#
|
74
|
-
# @example With `aria-labelledby`
|
75
|
-
# <%= render(Primer::HeadingComponent.new(tag: :h2, id: "search-1")) { "Search" } %>
|
76
|
-
# <%= render(Primer::AutoComplete.new(src: "/auto_complete", input_id: "fruits-input-3", list_id: "fruits-popup-2", position: :relative)) do |c| %>
|
77
|
-
# <% c.input("aria-labelledby": "search-1") %>
|
78
|
-
# <% end %>
|
79
|
-
#
|
80
|
-
# @example With custom classes for the results
|
81
|
-
# <%= render(Primer::AutoComplete.new(src: "/auto_complete", input_id: "fruits-input-4", list_id: "fruits-popup-3", position: :relative)) do |c| %>
|
82
|
-
# <% c.label(classes:"").with_content("Fruits") %>
|
83
|
-
# <% c.input(type: :text) %>
|
84
|
-
# <% c.results(classes: "custom-class") do %>
|
85
|
-
# <%= render(Primer::AutoComplete::Item.new(selected: true, value: "apple")) do |c| %>
|
86
|
-
# Apple
|
87
|
-
# <% end %>
|
88
|
-
# <%= render(Primer::AutoComplete::Item.new(value: "orange")) do |c| %>
|
89
|
-
# Orange
|
90
|
-
# <% end %>
|
91
|
-
# <% end %>
|
92
|
-
# <% end %>
|
93
|
-
#
|
94
|
-
# @example With Icon
|
95
|
-
# <%= render(Primer::AutoComplete.new(src: "/auto_complete", list_id: "fruits-popup-4", input_id: "fruits-input-4", position: :relative)) do |c| %>
|
96
|
-
# <% c.label(classes:"").with_content("Fruits") %>
|
97
|
-
# <% c.input(type: :text) %>
|
98
|
-
# <% c.icon(icon: :search) %>
|
99
|
-
# <% end %>
|
100
|
-
#
|
101
|
-
# @param src [String] The route to query.
|
102
|
-
# @param input_id [String] Id of the input element.
|
103
|
-
# @param list_id [String] Id of the list element.
|
104
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
105
|
-
def initialize(src:, list_id:, input_id:, **system_arguments)
|
106
|
-
@list_id = list_id
|
107
|
-
@input_id = input_id
|
108
|
-
@aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label)
|
109
|
-
|
110
|
-
system_arguments.delete(:"aria-label") && system_arguments[:aria]&.delete(:label)
|
111
|
-
|
112
|
-
@system_arguments = system_arguments
|
113
|
-
@system_arguments[:tag] = "auto-complete"
|
114
|
-
@system_arguments[:src] = src
|
115
|
-
@system_arguments[:for] = list_id
|
116
|
-
end
|
117
|
-
|
118
|
-
# add `results` without needing to explicitly call it in the view
|
119
|
-
def before_render
|
120
|
-
raise ArgumentError, "Missing `input` slot" if input.blank?
|
121
|
-
raise ArgumentError, "Accessible label is required." if label.blank? && input.missing_label?
|
122
|
-
|
123
|
-
results(classes: "") unless results
|
124
|
-
end
|
125
|
-
|
126
|
-
# This component is part of `Primer::AutoCompleteComponent` and should not be
|
127
|
-
# used as a standalone component.
|
128
|
-
class Input < Primer::Component
|
129
|
-
DEFAULT_TYPE = :text
|
130
|
-
TYPE_OPTIONS = [DEFAULT_TYPE, :search].freeze
|
131
|
-
|
132
|
-
# @param type [Symbol] <%= one_of(Primer::AutoComplete::Input::TYPE_OPTIONS) %>
|
133
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
134
|
-
def initialize(type: DEFAULT_TYPE, **system_arguments)
|
135
|
-
@system_arguments = system_arguments
|
136
|
-
@system_arguments[:tag] = :input
|
137
|
-
|
138
|
-
@aria_label = system_arguments[:"aria-label"]
|
139
|
-
@aria_labelledby = system_arguments[:"aria-labelledby"] || system_arguments.dig(:aria, :labelledby)
|
140
|
-
|
141
|
-
@system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE)
|
142
|
-
@system_arguments[:classes] = class_names(
|
143
|
-
"form-control",
|
144
|
-
system_arguments[:classes]
|
145
|
-
)
|
146
|
-
end
|
147
|
-
|
148
|
-
def missing_label?
|
149
|
-
@aria_label.blank? && @aria_labelledby.blank?
|
150
|
-
end
|
151
|
-
|
152
|
-
def call
|
153
|
-
render(Primer::BaseComponent.new(**@system_arguments))
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Primer
|
4
|
-
class AutoComplete
|
5
|
-
# Use `AutoCompleteItem` to list results of an auto-completed search.
|
6
|
-
class Item < Primer::Component
|
7
|
-
status :beta
|
8
|
-
|
9
|
-
# @example Default
|
10
|
-
# <%= render(Primer::AutoComplete::Item.new(selected: true, value: "value")) do |c| %>
|
11
|
-
# Selected
|
12
|
-
# <% end %>
|
13
|
-
# <%= render(Primer::AutoComplete::Item.new(value: "value")) do |c| %>
|
14
|
-
# Not selected
|
15
|
-
# <% end %>
|
16
|
-
#
|
17
|
-
# @param value [String] Value of the item.
|
18
|
-
# @param selected [Boolean] Whether the item is selected.
|
19
|
-
# @param disabled [Boolean] Whether the item is disabled.
|
20
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
21
|
-
def initialize(value:, selected: false, disabled: false, **system_arguments)
|
22
|
-
@system_arguments = system_arguments
|
23
|
-
@system_arguments[:tag] = :li
|
24
|
-
@system_arguments[:role] = :option
|
25
|
-
@system_arguments[:"data-autocomplete-value"] = value
|
26
|
-
|
27
|
-
@system_arguments[:"aria-selected"] = true if selected
|
28
|
-
@system_arguments[:"aria-disabled"] = true if disabled
|
29
|
-
|
30
|
-
@system_arguments[:classes] = class_names(
|
31
|
-
"autocomplete-item",
|
32
|
-
system_arguments[:classes],
|
33
|
-
"disabled" => disabled
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
def call
|
38
|
-
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Primer
|
4
|
-
# `Avatar` can be used to represent users and organizations on GitHub.
|
5
|
-
#
|
6
|
-
# - Use the default round avatar for users, and the `square` argument
|
7
|
-
# for organizations or any other non-human avatars.
|
8
|
-
# - By default, `Avatar` will render a static `<img>`. To have `Avatar` function as a link, set the `href` which will wrap the `<img>` in a `<a>`.
|
9
|
-
# - Set `size` to update the height and width of the `Avatar` in pixels.
|
10
|
-
# - To stack multiple avatars together, use <%= link_to_component(Primer::AvatarStackComponent) %>.
|
11
|
-
#
|
12
|
-
# @accessibility
|
13
|
-
# Images should have text alternatives that describe the information or function represented.
|
14
|
-
# If the avatar functions as a link, provide alt text that helps convey the function. For instance,
|
15
|
-
# if `Avatar` is a link to a user profile, the alt attribute should be `@kittenuser profile`
|
16
|
-
# rather than `@kittenuser`.
|
17
|
-
# [Learn more about best image practices (WAI Images)](https://www.w3.org/WAI/tutorials/images/)
|
18
|
-
class AvatarComponent < Primer::Component
|
19
|
-
status :beta
|
20
|
-
|
21
|
-
SMALL_THRESHOLD = 24
|
22
|
-
|
23
|
-
# @example Default
|
24
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser")) %>
|
25
|
-
#
|
26
|
-
# @example Square
|
27
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", square: true)) %>
|
28
|
-
#
|
29
|
-
# @example Link
|
30
|
-
# <%= render(Primer::AvatarComponent.new(href: "#", src: "http://placekitten.com/200/200", alt: "@kittenuser profile")) %>
|
31
|
-
#
|
32
|
-
# @example With size
|
33
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 16)) %>
|
34
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 20)) %>
|
35
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 24)) %>
|
36
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 28)) %>
|
37
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 32)) %>
|
38
|
-
# <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", size: 36)) %>
|
39
|
-
#
|
40
|
-
# @param src [String] The source url of the avatar image.
|
41
|
-
# @param alt [String] Passed through to alt on img tag.
|
42
|
-
# @param size [Integer] Adds the avatar-small class if less than 24.
|
43
|
-
# @param square [Boolean] Used to create a square avatar.
|
44
|
-
# @param href [String] The URL to link to. If used, component will be wrapped by an `<a>` tag.
|
45
|
-
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
46
|
-
def initialize(src:, alt:, size: 20, square: false, href: nil, **system_arguments)
|
47
|
-
@href = href
|
48
|
-
@system_arguments = system_arguments
|
49
|
-
@system_arguments[:tag] = :img
|
50
|
-
@system_arguments[:src] = src
|
51
|
-
@system_arguments[:alt] = alt
|
52
|
-
@system_arguments[:size] = size
|
53
|
-
@system_arguments[:height] = size
|
54
|
-
@system_arguments[:width] = size
|
55
|
-
|
56
|
-
@system_arguments[:classes] = class_names(
|
57
|
-
system_arguments[:classes],
|
58
|
-
"avatar",
|
59
|
-
"avatar-small" => size < SMALL_THRESHOLD,
|
60
|
-
"circle" => !square,
|
61
|
-
"lh-0" => href # Addresses an overflow issue with linked avatars
|
62
|
-
)
|
63
|
-
end
|
64
|
-
|
65
|
-
def call
|
66
|
-
if @href
|
67
|
-
render(Primer::LinkComponent.new(href: @href, classes: @system_arguments[:classes])) do
|
68
|
-
render(Primer::BaseComponent.new(**@system_arguments.except(:classes))) { content }
|
69
|
-
end
|
70
|
-
else
|
71
|
-
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|