primer_view_components 0.0.40 → 0.0.45
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +239 -1
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/components/primer/alpha/button_marketing.rb +70 -0
- data/app/components/primer/auto_complete.rb +99 -41
- data/app/components/primer/auto_complete/auto_complete.html.erb +1 -0
- data/app/components/primer/{auto_complete/auto_component.d.ts → auto_complete_component.d.ts} +0 -0
- data/app/components/primer/{auto_complete/auto_component.js → auto_complete_component.js} +0 -0
- data/app/components/primer/avatar_stack_component.rb +2 -2
- data/app/components/primer/base_component.rb +31 -21
- data/app/components/primer/beta/text.rb +27 -0
- data/app/components/primer/blankslate_component.html.erb +1 -0
- data/app/components/primer/blankslate_component.rb +65 -46
- data/app/components/primer/button_component.rb +3 -2
- data/app/components/primer/button_group.rb +1 -1
- data/app/components/primer/clipboard_copy.rb +25 -7
- data/app/components/primer/clipboard_copy_component.js +13 -2
- data/app/components/primer/clipboard_copy_component.ts +15 -2
- data/app/components/primer/component.rb +1 -1
- data/app/components/primer/details_component.rb +12 -1
- data/app/components/primer/details_menu_component.d.ts +1 -0
- data/app/components/primer/details_menu_component.js +1 -0
- data/app/components/primer/dropdown.d.ts +1 -0
- data/app/components/primer/{dropdown_component.html.erb → dropdown.html.erb} +2 -1
- data/app/components/primer/dropdown.js +1 -0
- data/app/components/primer/dropdown.rb +149 -0
- data/app/components/primer/dropdown.ts +1 -0
- data/app/components/primer/dropdown/menu.d.ts +1 -0
- data/app/components/primer/dropdown/menu.html.erb +25 -0
- data/app/components/primer/dropdown/menu.js +1 -0
- data/app/components/primer/dropdown/menu.rb +99 -0
- data/app/components/primer/dropdown/menu.ts +1 -0
- data/app/components/primer/flash_component.rb +2 -2
- data/app/components/primer/heading_component.rb +1 -1
- data/app/components/primer/hidden_text_expander.rb +2 -2
- data/app/components/primer/icon_button.rb +1 -1
- data/app/components/primer/image.rb +46 -0
- data/app/components/primer/image_crop.rb +2 -2
- data/app/components/primer/label_component.rb +6 -2
- data/app/components/primer/local_time.d.ts +1 -0
- data/app/components/primer/local_time.js +1 -0
- data/app/components/primer/local_time.rb +59 -0
- data/app/components/primer/local_time.ts +1 -0
- data/app/components/primer/markdown.rb +6 -2
- data/app/components/primer/navigation/tab_component.rb +10 -3
- data/app/components/primer/octicon_component.rb +15 -12
- data/app/components/primer/primer.d.ts +2 -0
- data/app/components/primer/primer.js +2 -0
- data/app/components/primer/primer.ts +2 -0
- data/app/components/primer/spinner_component.rb +2 -0
- data/app/components/primer/tab_nav_component.html.erb +5 -1
- data/app/components/primer/tab_nav_component.rb +62 -9
- data/app/components/primer/{tooltip_component.rb → tooltip.rb} +10 -8
- data/app/components/primer/truncate.rb +6 -2
- data/app/components/primer/underline_nav_component.html.erb +1 -1
- data/app/components/primer/underline_nav_component.rb +17 -1
- data/app/lib/primer/classify.rb +35 -12
- data/app/lib/primer/classify/cache.rb +12 -17
- data/app/lib/primer/classify/grid.rb +45 -0
- data/app/lib/primer/classify/utilities.rb +137 -0
- data/app/lib/primer/classify/utilities.yml +1147 -0
- data/app/lib/primer/tabbed_component_helper.rb +2 -2
- data/app/lib/primer/view_helper.rb +2 -1
- data/lib/primer/view_components/engine.rb +2 -0
- data/lib/primer/view_components/linters.rb +3 -0
- data/lib/primer/view_components/linters/argument_mappers/button.rb +82 -0
- data/lib/primer/view_components/linters/argument_mappers/conversion_error.rb +10 -0
- data/lib/primer/view_components/linters/argument_mappers/system_arguments.rb +48 -0
- data/lib/primer/view_components/linters/button_component_migration_counter.rb +39 -0
- data/lib/primer/view_components/linters/flash_component_migration_counter.rb +16 -0
- data/lib/primer/view_components/linters/helpers.rb +191 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/tasks/docs.rake +184 -109
- data/lib/tasks/utilities.rake +99 -0
- data/lib/yard/docs_helper.rb +12 -2
- data/static/statuses.json +10 -6
- metadata +65 -14
- data/app/components/primer/button_marketing_component.rb +0 -68
- data/app/components/primer/dropdown/menu_component.html.erb +0 -12
- data/app/components/primer/dropdown/menu_component.rb +0 -46
- data/app/components/primer/dropdown_component.rb +0 -73
- data/app/components/primer/text_component.rb +0 -25
- data/app/lib/primer/classify/spacing.rb +0 -63
data/app/components/primer/{auto_complete/auto_component.d.ts → auto_complete_component.d.ts}
RENAMED
File without changes
|
File without changes
|
@@ -39,7 +39,7 @@ module Primer
|
|
39
39
|
# @param tag [Symbol] <%= one_of(Primer::AvatarStackComponent::TAG_OPTIONS) %>
|
40
40
|
# @param align [Symbol] <%= one_of(Primer::AvatarStackComponent::ALIGN_OPTIONS) %>
|
41
41
|
# @param tooltipped [Boolean] Whether to add a tooltip to the stack or not.
|
42
|
-
# @param body_arguments [Hash] Parameters to add to the Body. If `tooltipped` is set, has the same arguments as <%= link_to_component(Primer::
|
42
|
+
# @param body_arguments [Hash] Parameters to add to the Body. If `tooltipped` is set, has the same arguments as <%= link_to_component(Primer::Tooltip) %>.
|
43
43
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
44
44
|
def initialize(tag: DEFAULT_TAG, align: ALIGN_DEFAULT, tooltipped: false, body_arguments: {}, **system_arguments)
|
45
45
|
@align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
|
@@ -63,7 +63,7 @@ module Primer
|
|
63
63
|
|
64
64
|
def body_component
|
65
65
|
if @tooltipped
|
66
|
-
Primer::
|
66
|
+
Primer::Tooltip.new(**@body_arguments)
|
67
67
|
else
|
68
68
|
Primer::BaseComponent.new(**@body_arguments)
|
69
69
|
end
|
@@ -83,7 +83,9 @@ module Primer
|
|
83
83
|
#
|
84
84
|
# | Name | Type | Description |
|
85
85
|
# | :- | :- | :- |
|
86
|
-
# | `
|
86
|
+
# | `clearfix` | Boolean | Wether to assign the `clearfix` class. |
|
87
|
+
# | `col` | Integer | Number of columns. <%= one_of(Primer::Classify::Grid::COL_VALUES) %> |
|
88
|
+
# | `container` | Symbol | Size of the container. <%= one_of(Primer::Classify::Grid::CONTAINER_VALUES) %> |
|
87
89
|
#
|
88
90
|
# ## Layout
|
89
91
|
#
|
@@ -91,7 +93,7 @@ module Primer
|
|
91
93
|
# | :- | :- | :- |
|
92
94
|
# | `display` | Symbol | <%= one_of([:none, :block, :flex, :inline, :inline_block, :inline_flex, :table, :table_cell]) %> |
|
93
95
|
# | `height` | Symbol | <%= one_of([:fit]) %> |
|
94
|
-
# | `hide` | Symbol | Hide the element at a specific breakpoint. <%= one_of(
|
96
|
+
# | `hide` | Symbol | Hide the element at a specific breakpoint. <%= one_of(Primer::Classify::Utilities.mappings(:hide)) %> |
|
95
97
|
# | `v` | Symbol | Visibility. <%= one_of([:hidden, :visible]) %> |
|
96
98
|
# | `vertical_align` | Symbol | <%= one_of([:baseline, :top, :middle, :bottom, :text_top, :text_bottom]) %> |
|
97
99
|
#
|
@@ -100,7 +102,7 @@ module Primer
|
|
100
102
|
# | Name | Type | Description |
|
101
103
|
# | :- | :- | :- |
|
102
104
|
# | `bottom` | Boolean | If `false`, sets `bottom: 0`. |
|
103
|
-
# | `float` | Symbol | <%= one_of(
|
105
|
+
# | `float` | Symbol | <%= one_of(Primer::Classify::Utilities.mappings(:float)) %> |
|
104
106
|
# | `left` | Boolean | If `false`, sets `left: 0`. |
|
105
107
|
# | `position` | Symbol | <%= one_of([:relative, :absolute, :fixed]) %> |
|
106
108
|
# | `right` | Boolean | If `false`, sets `right: 0`. |
|
@@ -110,28 +112,31 @@ module Primer
|
|
110
112
|
#
|
111
113
|
# | Name | Type | Description |
|
112
114
|
# | :- | :- | :- |
|
113
|
-
# | `m` | Integer | Margin. <%= one_of(Primer::Classify::
|
114
|
-
# | `mb` | Integer | Margin bottom. <%= one_of(Primer::Classify::
|
115
|
-
# | `ml` | Integer | Margin left. <%= one_of(Primer::Classify::
|
116
|
-
# | `mr` | Integer | Margin right. <%= one_of(Primer::Classify::
|
117
|
-
# | `mt` | Integer | Margin top. <%= one_of(Primer::Classify::
|
118
|
-
# | `mx` | Integer | Horizontal margins. <%= one_of(Primer::Classify::
|
119
|
-
# | `my` | Integer | Vertical margins. <%= one_of(Primer::Classify::
|
120
|
-
# | `p` | Integer | Padding. <%= one_of(Primer::Classify::
|
121
|
-
# | `pb` | Integer | Padding bottom. <%= one_of(Primer::Classify::
|
122
|
-
# | `pl` | Integer | Padding left. <%= one_of(Primer::Classify::
|
123
|
-
# | `pr` | Integer | Padding right. <%= one_of(Primer::Classify::
|
124
|
-
# | `pt` | Integer | Padding left. <%= one_of(Primer::Classify::
|
125
|
-
# | `px` | Integer | Horizontal padding. <%= one_of(Primer::Classify::
|
126
|
-
# | `py` | Integer | Vertical padding. <%= one_of(Primer::Classify::
|
115
|
+
# | `m` | Integer | Margin. <%= one_of(Primer::Classify::Utilities.mappings(:m)) %> |
|
116
|
+
# | `mb` | Integer | Margin bottom. <%= one_of(Primer::Classify::Utilities.mappings(:mb)) %> |
|
117
|
+
# | `ml` | Integer | Margin left. <%= one_of(Primer::Classify::Utilities.mappings(:ml)) %> |
|
118
|
+
# | `mr` | Integer | Margin right. <%= one_of(Primer::Classify::Utilities.mappings(:mr)) %> |
|
119
|
+
# | `mt` | Integer | Margin top. <%= one_of(Primer::Classify::Utilities.mappings(:mt)) %> |
|
120
|
+
# | `mx` | Integer | Horizontal margins. <%= one_of(Primer::Classify::Utilities.mappings(:mx)) %> |
|
121
|
+
# | `my` | Integer | Vertical margins. <%= one_of(Primer::Classify::Utilities.mappings(:my)) %> |
|
122
|
+
# | `p` | Integer | Padding. <%= one_of(Primer::Classify::Utilities.mappings(:p)) %> |
|
123
|
+
# | `pb` | Integer | Padding bottom. <%= one_of(Primer::Classify::Utilities.mappings(:pb)) %> |
|
124
|
+
# | `pl` | Integer | Padding left. <%= one_of(Primer::Classify::Utilities.mappings(:pl)) %> |
|
125
|
+
# | `pr` | Integer | Padding right. <%= one_of(Primer::Classify::Utilities.mappings(:pr)) %> |
|
126
|
+
# | `pt` | Integer | Padding left. <%= one_of(Primer::Classify::Utilities.mappings(:pt)) %> |
|
127
|
+
# | `px` | Integer | Horizontal padding. <%= one_of(Primer::Classify::Utilities.mappings(:px)) %> |
|
128
|
+
# | `py` | Integer | Vertical padding. <%= one_of(Primer::Classify::Utilities.mappings(:py)) %> |
|
127
129
|
#
|
128
130
|
# ## Typography
|
129
131
|
#
|
130
132
|
# | Name | Type | Description |
|
131
133
|
# | :- | :- | :- |
|
132
|
-
# | `
|
133
|
-
# | `
|
134
|
+
# | `font_family` | Symbol | Font weight. <%= one_of([:mono]) %> |
|
135
|
+
# | `font_size` | String, Integer, Symbol | <%= one_of(["00", 0, 1, 2, 3, 4, 5, 6, :small, :normal]) %> |
|
136
|
+
# | `font_style` | Symbol | Font weight. <%= one_of([:italic]) %> |
|
137
|
+
# | `font_weight` | Symbol | Font weight. <%= one_of([:light, :normal, :bold, :emphasized]) %> |
|
134
138
|
# | `text_align` | Symbol | Text alignment. <%= one_of([:left, :right, :center]) %> |
|
139
|
+
# | `text_transform` | Symbol | Text alignment. <%= one_of([:uppercase]) %> |
|
135
140
|
# | `underline` | Boolean | Whether text should be underlined. |
|
136
141
|
# | `word_break` | Symbol | Whether to break words on line breaks. Can only be `:break_all`. |
|
137
142
|
#
|
@@ -143,10 +148,15 @@ module Primer
|
|
143
148
|
# | test_selector | String | Adds `data-test-selector='given value'` in non-Production environments for testing purposes. |
|
144
149
|
def initialize(tag:, classes: nil, **system_arguments)
|
145
150
|
@tag = tag
|
146
|
-
@
|
151
|
+
@system_arguments = system_arguments
|
147
152
|
|
153
|
+
raise ArgumentError, "`class` is an invalid argument. Use `classes` instead." if system_arguments.key?(:class) && !Rails.env.production?
|
154
|
+
|
155
|
+
@result = Primer::Classify.call(**@system_arguments.merge(classes: classes))
|
156
|
+
|
157
|
+
@system_arguments[:"data-view-component"] = true
|
148
158
|
# Filter out Primer keys so they don't get assigned as HTML attributes
|
149
|
-
@content_tag_args = add_test_selector(system_arguments).except(*Primer::Classify::VALID_KEYS)
|
159
|
+
@content_tag_args = add_test_selector(@system_arguments).except(*Primer::Classify::VALID_KEYS)
|
150
160
|
end
|
151
161
|
|
152
162
|
def call
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Primer
|
4
|
+
module Beta
|
5
|
+
# `Text` is a wrapper component that will apply typography styles to the text inside.
|
6
|
+
class Text < Primer::Component
|
7
|
+
status :beta
|
8
|
+
|
9
|
+
DEFAULT_TAG = :span
|
10
|
+
|
11
|
+
# @example Default
|
12
|
+
# <%= render(Primer::Beta::Text.new(tag: :p, font_weight: :bold)) { "Bold Text" } %>
|
13
|
+
# <%= render(Primer::Beta::Text.new(tag: :p, color: :text_danger)) { "Danger Text" } %>
|
14
|
+
#
|
15
|
+
# @param tag [Symbol]
|
16
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
17
|
+
def initialize(tag: DEFAULT_TAG, **system_arguments)
|
18
|
+
@system_arguments = system_arguments
|
19
|
+
@system_arguments[:tag] = tag
|
20
|
+
end
|
21
|
+
|
22
|
+
def call
|
23
|
+
render(Primer::BaseComponent.new(**@system_arguments)) { content }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -23,61 +23,79 @@ module Primer
|
|
23
23
|
# description: "Description",
|
24
24
|
# ) %>
|
25
25
|
#
|
26
|
-
# @example Icon
|
27
|
-
#
|
28
|
-
# icon
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
26
|
+
# @example Icon
|
27
|
+
# @description
|
28
|
+
# Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
|
29
|
+
# @code
|
30
|
+
# <%= render Primer::BlankslateComponent.new(
|
31
|
+
# icon: :globe,
|
32
|
+
# title: "Title",
|
33
|
+
# description: "Description",
|
34
|
+
# ) %>
|
32
35
|
#
|
33
|
-
# @example Loading
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
36
|
+
# @example Loading
|
37
|
+
# @description
|
38
|
+
# Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
|
39
|
+
# @code
|
40
|
+
# <%= render Primer::BlankslateComponent.new(
|
41
|
+
# title: "Title",
|
42
|
+
# description: "Description",
|
43
|
+
# ) do |component| %>
|
44
|
+
# <% component.spinner(size: :large) %>
|
45
|
+
# <% end %>
|
40
46
|
#
|
41
|
-
# @example Custom content
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
+
# @example Custom content
|
48
|
+
# @description
|
49
|
+
# Pass custom content as a block in place of `description`.
|
50
|
+
# @code
|
51
|
+
# <%= render Primer::BlankslateComponent.new(
|
52
|
+
# title: "Title",
|
53
|
+
# ) do %>
|
54
|
+
# <em>Your custom content here</em>
|
55
|
+
# <% end %>
|
47
56
|
#
|
48
|
-
# @example Action button
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
57
|
+
# @example Action button
|
58
|
+
# @description
|
59
|
+
# Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
|
60
|
+
# @code
|
61
|
+
# <%= render Primer::BlankslateComponent.new(
|
62
|
+
# icon: :book,
|
63
|
+
# title: "Welcome to the mona wiki!",
|
64
|
+
# description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
|
53
65
|
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
66
|
+
# button_text: "Create the first page",
|
67
|
+
# button_url: "https://github.com/monalisa/mona/wiki/_new",
|
68
|
+
# ) %>
|
57
69
|
#
|
58
|
-
# @example Link
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
70
|
+
# @example Link
|
71
|
+
# @description
|
72
|
+
# Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
|
73
|
+
# @code
|
74
|
+
# <%= render Primer::BlankslateComponent.new(
|
75
|
+
# icon: :book,
|
76
|
+
# title: "Welcome to the mona wiki!",
|
77
|
+
# description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
|
78
|
+
# link_text: "Learn more about wikis",
|
79
|
+
# link_url: "https://docs.github.com/en/github/building-a-strong-community/about-wikis",
|
80
|
+
# ) %>
|
66
81
|
#
|
67
|
-
# @example Variations
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
82
|
+
# @example Variations
|
83
|
+
# @description
|
84
|
+
# There are a few variations of how the Blankslate appears: `narrow` adds a maximum width, `large` increases the font size, and `spacious` adds extra padding.
|
85
|
+
# @code
|
86
|
+
# <%= render Primer::BlankslateComponent.new(
|
87
|
+
# icon: :book,
|
88
|
+
# title: "Welcome to the mona wiki!",
|
89
|
+
# description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
|
90
|
+
# narrow: true,
|
91
|
+
# large: true,
|
92
|
+
# spacious: true,
|
93
|
+
# ) %>
|
76
94
|
#
|
77
95
|
# @param title [String] Text that appears in a larger bold font.
|
78
96
|
# @param title_tag [Symbol] HTML tag to use for title.
|
79
|
-
# @param icon [
|
80
|
-
# @param icon_size [Symbol] <%= one_of(Primer::OcticonComponent::SIZE_MAPPINGS) %>
|
97
|
+
# @param icon [Symbol] Octicon icon to use at top of component.
|
98
|
+
# @param icon_size [Symbol] <%= one_of(Primer::OcticonComponent::SIZE_MAPPINGS, sort: false) %>
|
81
99
|
# @param image_src [String] Image to display.
|
82
100
|
# @param image_alt [String] Alt text for image.
|
83
101
|
# @param description [String] Text that appears below the title. Typically a whole sentence.
|
@@ -89,6 +107,7 @@ module Primer
|
|
89
107
|
# @param narrow [Boolean] Adds a maximum width.
|
90
108
|
# @param large [Boolean] Increases the font size.
|
91
109
|
# @param spacious [Boolean] Adds extra padding.
|
110
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
92
111
|
def initialize(
|
93
112
|
title: "",
|
94
113
|
title_tag: :h3,
|
@@ -78,11 +78,12 @@ module Primer
|
|
78
78
|
#
|
79
79
|
# @param scheme [Symbol] <%= one_of(Primer::ButtonComponent::SCHEME_OPTIONS) %>
|
80
80
|
# @param variant [Symbol] <%= one_of(Primer::ButtonComponent::VARIANT_OPTIONS) %>
|
81
|
-
# @param tag [Symbol] <%= one_of(Primer::BaseButton::TAG_OPTIONS) %>
|
82
|
-
# @param type [Symbol] <%= one_of(Primer::BaseButton::TYPE_OPTIONS) %>
|
81
|
+
# @param tag [Symbol] (Primer::BaseButton::DEFAULT_TAG) <%= one_of(Primer::BaseButton::TAG_OPTIONS) %>
|
82
|
+
# @param type [Symbol] (Primer::BaseButton::DEFAULT_TYPE) <%= one_of(Primer::BaseButton::TYPE_OPTIONS) %>
|
83
83
|
# @param group_item [Boolean] Whether button is part of a ButtonGroup.
|
84
84
|
# @param block [Boolean] Whether button is full-width with `display: block`.
|
85
85
|
# @param caret [Boolean] Whether or not to render a caret.
|
86
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
86
87
|
def initialize(
|
87
88
|
scheme: DEFAULT_SCHEME,
|
88
89
|
variant: DEFAULT_VARIANT,
|
@@ -22,7 +22,7 @@ module Primer
|
|
22
22
|
# <% component.button(scheme: :primary) { "Primary" } %>
|
23
23
|
# <% component.button(scheme: :danger) { "Danger" } %>
|
24
24
|
# <% component.button(scheme: :outline) { "Outline" } %>
|
25
|
-
# <% component.button(classes: "
|
25
|
+
# <% component.button(classes: "custom-class") { "Custom class" } %>
|
26
26
|
# <% end %>
|
27
27
|
#
|
28
28
|
# @example Variants
|
@@ -2,25 +2,43 @@
|
|
2
2
|
|
3
3
|
module Primer
|
4
4
|
# Use `ClipboardCopy` to copy element text content or input values to the clipboard.
|
5
|
+
#
|
6
|
+
# @accessibility
|
7
|
+
# Always set an accessible label to help the user interact with the component.
|
5
8
|
class ClipboardCopy < Primer::Component
|
6
9
|
status :alpha
|
7
10
|
|
8
11
|
# @example Default
|
9
|
-
# <%= render(Primer::ClipboardCopy.new(value: "Text to copy", label: "Copy text to the system clipboard")) %>
|
12
|
+
# <%= render(Primer::ClipboardCopy.new(value: "Text to copy", "aria-label": "Copy text to the system clipboard")) %>
|
10
13
|
#
|
11
14
|
# @example With text instead of icons
|
12
|
-
# <%= render(Primer::ClipboardCopy.new(value: "Text to copy", label: "Copy text to the system clipboard")) do %>
|
15
|
+
# <%= render(Primer::ClipboardCopy.new(value: "Text to copy", "aria-label": "Copy text to the system clipboard")) do %>
|
13
16
|
# Click to copy!
|
14
17
|
# <% end %>
|
15
18
|
#
|
16
|
-
# @
|
17
|
-
#
|
19
|
+
# @example Copying from an element
|
20
|
+
# <%= render(Primer::ClipboardCopy.new(for: "blob-path", "aria-label": "Copy text to the system clipboard")) %>
|
21
|
+
# <div id="blob-path">src/index.js</div>
|
22
|
+
#
|
23
|
+
# @param aria-label [String] String that will be read to screenreaders when the component is focused
|
24
|
+
# @param value [String] Text to copy into the users clipboard when they click the component.
|
25
|
+
# @param for [String] Element id from where to get the copied value.
|
18
26
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
19
|
-
def initialize(
|
27
|
+
def initialize(value: nil, **system_arguments)
|
20
28
|
@system_arguments = system_arguments
|
29
|
+
@value = value
|
30
|
+
|
31
|
+
validate!
|
32
|
+
|
21
33
|
@system_arguments[:tag] = "clipboard-copy"
|
22
|
-
@system_arguments[:value] = value
|
23
|
-
|
34
|
+
@system_arguments[:value] = value if value.present?
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def validate!
|
40
|
+
validate_aria_label
|
41
|
+
raise ArgumentError, "Must provide either `value` or `for`" if @value.nil? && @system_arguments[:for].nil?
|
24
42
|
end
|
25
43
|
end
|
26
44
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import '@github/clipboard-copy-element';
|
2
|
+
const CLIPBOARD_COPY_TIMER_DURATION = 2000;
|
2
3
|
function toggleSVG(svg) {
|
3
4
|
if (svg.style.display === '' || svg.style.display === 'block') {
|
4
5
|
svg.style.display = 'none';
|
@@ -15,9 +16,19 @@ function toggleCopyButton(button) {
|
|
15
16
|
toggleSVG(clippyIcon);
|
16
17
|
toggleSVG(checkIcon);
|
17
18
|
}
|
19
|
+
const clipboardCopyElementTimers = new WeakMap();
|
18
20
|
document.addEventListener('clipboard-copy', function ({ target }) {
|
19
21
|
if (!(target instanceof HTMLElement))
|
20
22
|
return;
|
21
|
-
|
22
|
-
|
23
|
+
if (!target.hasAttribute('data-view-component'))
|
24
|
+
return;
|
25
|
+
const currentTimeout = clipboardCopyElementTimers.get(target);
|
26
|
+
if (currentTimeout) {
|
27
|
+
clearTimeout(currentTimeout);
|
28
|
+
clipboardCopyElementTimers.delete(target);
|
29
|
+
}
|
30
|
+
else {
|
31
|
+
toggleCopyButton(target);
|
32
|
+
}
|
33
|
+
clipboardCopyElementTimers.set(target, setTimeout(toggleCopyButton, CLIPBOARD_COPY_TIMER_DURATION, target));
|
23
34
|
});
|
@@ -1,5 +1,7 @@
|
|
1
1
|
import '@github/clipboard-copy-element'
|
2
2
|
|
3
|
+
const CLIPBOARD_COPY_TIMER_DURATION = 2000
|
4
|
+
|
3
5
|
function toggleSVG(svg: SVGElement) {
|
4
6
|
if (svg.style.display === '' || svg.style.display === 'block') {
|
5
7
|
svg.style.display = 'none'
|
@@ -18,9 +20,20 @@ function toggleCopyButton(button: HTMLElement) {
|
|
18
20
|
toggleSVG(checkIcon)
|
19
21
|
}
|
20
22
|
|
23
|
+
const clipboardCopyElementTimers = new WeakMap<HTMLElement, number>()
|
24
|
+
|
21
25
|
document.addEventListener('clipboard-copy', function ({target}) {
|
22
26
|
if (!(target instanceof HTMLElement)) return
|
23
|
-
|
27
|
+
if (!target.hasAttribute('data-view-component')) return
|
28
|
+
|
29
|
+
const currentTimeout = clipboardCopyElementTimers.get(target)
|
30
|
+
|
31
|
+
if (currentTimeout) {
|
32
|
+
clearTimeout(currentTimeout)
|
33
|
+
clipboardCopyElementTimers.delete(target)
|
34
|
+
} else {
|
35
|
+
toggleCopyButton(target)
|
36
|
+
}
|
24
37
|
|
25
|
-
setTimeout(toggleCopyButton,
|
38
|
+
clipboardCopyElementTimers.set(target, setTimeout(toggleCopyButton, CLIPBOARD_COPY_TIMER_DURATION, target))
|
26
39
|
})
|
@@ -5,7 +5,7 @@ require "view_component/version"
|
|
5
5
|
module Primer
|
6
6
|
# @private
|
7
7
|
class Component < ViewComponent::Base
|
8
|
-
include ViewComponent::SlotableV2 unless ViewComponent::
|
8
|
+
include ViewComponent::SlotableV2 unless ViewComponent::Base < ViewComponent::SlotableV2
|
9
9
|
include ClassNameHelper
|
10
10
|
include FetchOrFallbackHelper
|
11
11
|
include TestSelectorHelper
|
@@ -14,7 +14,7 @@ module Primer
|
|
14
14
|
|
15
15
|
# Use the Summary slot as a trigger to reveal the content.
|
16
16
|
#
|
17
|
-
# @param button [Boolean] Whether to render the Summary as a button or not.
|
17
|
+
# @param button [Boolean] (true) Whether to render the Summary as a button or not.
|
18
18
|
# @param kwargs [Hash] The same arguments as <%= link_to_system_arguments_docs %>.
|
19
19
|
renders_one :summary, lambda { |button: true, **system_arguments|
|
20
20
|
system_arguments[:tag] = :summary
|
@@ -33,6 +33,17 @@ module Primer
|
|
33
33
|
Primer::BaseComponent.new(**system_arguments)
|
34
34
|
}
|
35
35
|
|
36
|
+
# @example Default
|
37
|
+
#
|
38
|
+
# <%= render Primer::DetailsComponent.new do |c| %>
|
39
|
+
# component.summary do
|
40
|
+
# "Summary"
|
41
|
+
# end
|
42
|
+
# component.body do
|
43
|
+
# "Body"
|
44
|
+
# end
|
45
|
+
# <% end %>
|
46
|
+
#
|
36
47
|
# @param overlay [Symbol] Dictates the type of overlay to render with. <%= one_of(Primer::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
|
37
48
|
# @param reset [Boolean] Defatuls to false. If set to true, it will remove the default caret and remove style from the summary element
|
38
49
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|