primer_view_components 0.1.8 → 0.1.9
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 +28 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/action_list/item.rb +1 -3
- data/app/components/primer/alpha/action_menu.rb +1 -1
- data/app/components/primer/alpha/modal_dialog.js +6 -0
- data/app/components/primer/alpha/modal_dialog.ts +6 -0
- data/app/components/primer/alpha/overlay/header.html.erb +5 -3
- data/app/components/primer/alpha/overlay/header.rb +4 -1
- data/app/components/primer/alpha/overlay.css +1 -1
- data/app/components/primer/alpha/overlay.css.json +1 -1
- data/app/components/primer/alpha/overlay.css.map +1 -1
- data/app/components/primer/alpha/overlay.pcss +1 -1
- data/app/components/primer/alpha/overlay.rb +1 -0
- data/app/components/primer/alpha/toggle_switch.css +1 -1
- data/app/components/primer/alpha/toggle_switch.css.json +11 -11
- data/app/components/primer/alpha/toggle_switch.css.map +1 -1
- data/app/components/primer/alpha/toggle_switch.d.ts +1 -1
- data/app/components/primer/alpha/toggle_switch.html.erb +2 -2
- data/app/components/primer/alpha/toggle_switch.js +44 -42
- data/app/components/primer/alpha/toggle_switch.pcss +4 -4
- data/app/components/primer/alpha/toggle_switch.rb +7 -0
- data/app/components/primer/alpha/toggle_switch.ts +50 -41
- data/app/components/primer/beta/auto_complete.rb +1 -1
- data/app/components/primer/focus_group.js +10 -6
- data/app/components/primer/focus_group.ts +10 -5
- data/lib/primer/forms/dsl/input.rb +4 -8
- data/lib/primer/forms/dsl/text_field_input.rb +0 -4
- data/lib/primer/forms/dsl/toggle_switch_input.rb +4 -0
- data/lib/primer/forms/form_control.html.erb +3 -5
- data/lib/primer/forms/primer_base_component_wrapper.html.erb +3 -0
- data/lib/primer/forms/primer_base_component_wrapper.rb +24 -0
- data/lib/primer/forms/toggle_switch.html.erb +3 -3
- data/lib/primer/forms/toggle_switch.rb +6 -2
- data/lib/primer/forms/toggle_switch_input.js +7 -2
- data/lib/primer/forms/toggle_switch_input.ts +9 -2
- data/lib/primer/static/generate_info_arch.rb +3 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/primer/yard/component_manifest.rb +1 -1
- data/lib/primer/yard/lookbook_pages_backend.rb +7 -1
- data/lib/primer/yard/registry.rb +4 -0
- data/previews/primer/alpha/overlay_preview/middle_of_page_with_relative_container.html.erb +19 -0
- data/previews/primer/alpha/overlay_preview.rb +31 -0
- data/static/arguments.json +7 -1
- data/static/info_arch.json +312 -1
- data/static/previews.json +5 -0
- metadata +5 -9
- data/lib/tasks/docs.rake +0 -185
- data/lib/tasks/helpers/ast_processor.rb +0 -44
- data/lib/tasks/helpers/ast_traverser.rb +0 -77
- data/lib/tasks/primer_view_components.rake +0 -47
- data/lib/tasks/static.rake +0 -29
- data/lib/tasks/test.rake +0 -83
- data/lib/tasks/utilities.rake +0 -109
@@ -14,11 +14,11 @@ import '@oddbird/popover-polyfill';
|
|
14
14
|
const menuItemSelector = '[role="menuitem"],[role="menuitemcheckbox"],[role="menuitemradio"]';
|
15
15
|
const popoverSelector = (() => {
|
16
16
|
try {
|
17
|
-
document.querySelector(':open');
|
18
|
-
return ':open';
|
17
|
+
document.querySelector(':popover-open');
|
18
|
+
return ':popover-open';
|
19
19
|
}
|
20
20
|
catch (_a) {
|
21
|
-
return '.\\:open';
|
21
|
+
return '.\\:popover-open';
|
22
22
|
}
|
23
23
|
})();
|
24
24
|
const getMnemonicFor = (item) => { var _a; return (_a = item.textContent) === null || _a === void 0 ? void 0 : _a.trim()[0].toLowerCase(); };
|
@@ -80,28 +80,34 @@ export default class FocusGroupElement extends HTMLElement {
|
|
80
80
|
if (key === 'Up' || key === 'ArrowUp') {
|
81
81
|
if (direction === 'vertical' || direction === 'both') {
|
82
82
|
index -= index < 0 ? 0 : 1;
|
83
|
+
event.preventDefault();
|
83
84
|
}
|
84
85
|
}
|
85
86
|
else if (key === 'Down' || key === 'ArrowDown') {
|
86
87
|
if (direction === 'vertical' || direction === 'both') {
|
87
88
|
index += 1;
|
89
|
+
event.preventDefault();
|
88
90
|
}
|
89
91
|
}
|
90
92
|
else if (event.key === 'Left' || event.key === 'ArrowLeft') {
|
91
93
|
if (direction === 'horizontal' || direction === 'both') {
|
92
94
|
index -= 1;
|
95
|
+
event.preventDefault();
|
93
96
|
}
|
94
97
|
}
|
95
98
|
else if (event.key === 'Right' || event.key === 'ArrowRight') {
|
96
99
|
if (direction === 'horizontal' || direction === 'both') {
|
97
100
|
index += 1;
|
101
|
+
event.preventDefault();
|
98
102
|
}
|
99
103
|
}
|
100
104
|
else if (event.key === 'Home' || event.key === 'PageUp') {
|
101
105
|
index = 0;
|
106
|
+
event.preventDefault();
|
102
107
|
}
|
103
108
|
else if (event.key === 'End' || event.key === 'PageDown') {
|
104
109
|
index = items.length - 1;
|
110
|
+
event.preventDefault();
|
105
111
|
}
|
106
112
|
else if (this.mnemonics && printable.test(key)) {
|
107
113
|
const mnemonic = key.toLowerCase();
|
@@ -126,9 +132,7 @@ export default class FocusGroupElement extends HTMLElement {
|
|
126
132
|
if ((el === null || el === void 0 ? void 0 : el.popover) === 'auto') {
|
127
133
|
el.showPopover();
|
128
134
|
}
|
129
|
-
|
130
|
-
el = (el === null || el === void 0 ? void 0 : el.parentElement) || null;
|
131
|
-
}
|
135
|
+
el = (el === null || el === void 0 ? void 0 : el.parentElement) || null;
|
132
136
|
} while (el);
|
133
137
|
}
|
134
138
|
focusEl === null || focusEl === void 0 ? void 0 : focusEl.focus();
|
@@ -4,10 +4,10 @@ const menuItemSelector = '[role="menuitem"],[role="menuitemcheckbox"],[role="men
|
|
4
4
|
|
5
5
|
const popoverSelector = (() => {
|
6
6
|
try {
|
7
|
-
document.querySelector(':open')
|
8
|
-
return ':open'
|
7
|
+
document.querySelector(':popover-open')
|
8
|
+
return ':popover-open'
|
9
9
|
} catch {
|
10
|
-
return '.\\:open'
|
10
|
+
return '.\\:popover-open'
|
11
11
|
}
|
12
12
|
})()
|
13
13
|
|
@@ -79,23 +79,29 @@ export default class FocusGroupElement extends HTMLElement {
|
|
79
79
|
if (key === 'Up' || key === 'ArrowUp') {
|
80
80
|
if (direction === 'vertical' || direction === 'both') {
|
81
81
|
index -= index < 0 ? 0 : 1
|
82
|
+
event.preventDefault()
|
82
83
|
}
|
83
84
|
} else if (key === 'Down' || key === 'ArrowDown') {
|
84
85
|
if (direction === 'vertical' || direction === 'both') {
|
85
86
|
index += 1
|
87
|
+
event.preventDefault()
|
86
88
|
}
|
87
89
|
} else if (event.key === 'Left' || event.key === 'ArrowLeft') {
|
88
90
|
if (direction === 'horizontal' || direction === 'both') {
|
89
91
|
index -= 1
|
92
|
+
event.preventDefault()
|
90
93
|
}
|
91
94
|
} else if (event.key === 'Right' || event.key === 'ArrowRight') {
|
92
95
|
if (direction === 'horizontal' || direction === 'both') {
|
93
96
|
index += 1
|
97
|
+
event.preventDefault()
|
94
98
|
}
|
95
99
|
} else if (event.key === 'Home' || event.key === 'PageUp') {
|
96
100
|
index = 0
|
101
|
+
event.preventDefault()
|
97
102
|
} else if (event.key === 'End' || event.key === 'PageDown') {
|
98
103
|
index = items.length - 1
|
104
|
+
event.preventDefault()
|
99
105
|
} else if (this.mnemonics && printable.test(key)) {
|
100
106
|
const mnemonic = key.toLowerCase()
|
101
107
|
const offset = index > 0 && getMnemonicFor(event.target as Element) === mnemonic ? index : 0
|
@@ -115,9 +121,8 @@ export default class FocusGroupElement extends HTMLElement {
|
|
115
121
|
el = el.closest(`[popover]:not(${popoverSelector})`)
|
116
122
|
if (el?.popover === 'auto') {
|
117
123
|
el.showPopover()
|
118
|
-
} else {
|
119
|
-
el = el?.parentElement || null
|
120
124
|
}
|
125
|
+
el = el?.parentElement || null
|
121
126
|
} while (el)
|
122
127
|
}
|
123
128
|
focusEl?.focus()
|
@@ -47,7 +47,7 @@ module Primer
|
|
47
47
|
|
48
48
|
include Primer::ClassNameHelper
|
49
49
|
|
50
|
-
attr_reader :builder, :form, :input_arguments, :label_arguments, :caption, :validation_message, :ids, :form_control
|
50
|
+
attr_reader :builder, :form, :input_arguments, :label_arguments, :caption, :validation_message, :ids, :form_control, :base_id
|
51
51
|
|
52
52
|
alias form_control? form_control
|
53
53
|
|
@@ -107,11 +107,11 @@ module Primer
|
|
107
107
|
|
108
108
|
@input_arguments[:invalid] = "true" if invalid?
|
109
109
|
|
110
|
-
base_id = SecureRandom.uuid
|
110
|
+
@base_id = SecureRandom.uuid
|
111
111
|
|
112
112
|
@ids = {}.tap do |id_map|
|
113
|
-
id_map[:validation] = "validation-#{base_id}"
|
114
|
-
id_map[:caption] = "caption-#{base_id}" if caption? || caption_template?
|
113
|
+
id_map[:validation] = "validation-#{@base_id}"
|
114
|
+
id_map[:caption] = "caption-#{@base_id}" if caption? || caption_template?
|
115
115
|
end
|
116
116
|
|
117
117
|
add_input_aria(:required, true) if required?
|
@@ -264,10 +264,6 @@ module Primer
|
|
264
264
|
true
|
265
265
|
end
|
266
266
|
|
267
|
-
def need_validation_element?
|
268
|
-
invalid?
|
269
|
-
end
|
270
|
-
|
271
267
|
def validation_arguments
|
272
268
|
{
|
273
269
|
class: "FormControl-inlineValidation",
|
@@ -9,11 +9,9 @@
|
|
9
9
|
<% end %>
|
10
10
|
<% end %>
|
11
11
|
<%= content %>
|
12
|
-
|
13
|
-
<%=
|
14
|
-
|
15
|
-
<%= content_tag(:span, @input.validation_messages.first, **@input.validation_message_arguments) %>
|
16
|
-
<% end %>
|
12
|
+
<%= content_tag(:div, **@input.validation_arguments) do %>
|
13
|
+
<%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %>
|
14
|
+
<%= content_tag(:span, @input.invalid? ? @input.validation_messages.first : "", **@input.validation_message_arguments) %>
|
17
15
|
<% end %>
|
18
16
|
<%= render(Caption.new(input: @input)) %>
|
19
17
|
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "primer/class_name_helper"
|
4
|
+
|
5
|
+
module Primer
|
6
|
+
module Forms
|
7
|
+
# Wraps Primer::BaseComponent.
|
8
|
+
class PrimerBaseComponentWrapper < BaseComponent
|
9
|
+
include Primer::ClassNameHelper
|
10
|
+
|
11
|
+
def initialize(**system_arguments)
|
12
|
+
@system_arguments = system_arguments
|
13
|
+
|
14
|
+
# Extract class and classes so they can be passed to Primer::BaseComponent
|
15
|
+
# as classes:. The class: argument is expected by Rails, but Primer expects
|
16
|
+
# classes:, reminiscent of HashWithIndifferentAccess shenanigans.
|
17
|
+
@classes = class_names(
|
18
|
+
system_arguments.delete(:classes),
|
19
|
+
system_arguments.delete(:class)
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
<%= content_tag("toggle-switch-input",
|
1
|
+
<%= content_tag("toggle-switch-input", class: "FormControl-toggleSwitchInput", hidden: @input.hidden?) do %>
|
2
2
|
<span style="flex-grow: 1">
|
3
|
-
<%=
|
3
|
+
<%= render(Primer::Forms::PrimerBaseComponentWrapper.new(tag: :span, **@input.label_arguments)) do %>
|
4
4
|
<%= @input.label %>
|
5
5
|
<% end %>
|
6
6
|
|
@@ -18,5 +18,5 @@
|
|
18
18
|
}
|
19
19
|
)
|
20
20
|
%>
|
21
|
-
<%= render(Primer::Alpha::ToggleSwitch.new(src: @input.src, csrf: csrf)) %>
|
21
|
+
<%= render(Primer::Alpha::ToggleSwitch.new(src: @input.src, csrf: csrf, **@input.input_arguments)) %>
|
22
22
|
<% end %>
|
@@ -9,8 +9,12 @@ module Primer
|
|
9
9
|
def initialize(input:)
|
10
10
|
@input = input
|
11
11
|
@input.add_label_classes("FormControl-label")
|
12
|
-
@input.
|
13
|
-
@input.
|
12
|
+
@input.label_arguments[:id] = label_id
|
13
|
+
@input.add_input_aria(:labelledby, label_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def label_id
|
17
|
+
@label_id ||= "label-#{@input.base_id}"
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/* eslint-disable custom-elements/expose-class-on-global */
|
1
2
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
@@ -8,11 +9,15 @@ import { controller, target } from '@github/catalyst';
|
|
8
9
|
let ToggleSwitchInputElement = class ToggleSwitchInputElement extends HTMLElement {
|
9
10
|
connectedCallback() {
|
10
11
|
this.addEventListener('toggleSwitchError', (event) => {
|
11
|
-
this.validationMessageElement.
|
12
|
+
this.validationMessageElement.textContent = event.detail;
|
12
13
|
this.validationElement.removeAttribute('hidden');
|
13
14
|
});
|
14
15
|
this.addEventListener('toggleSwitchSuccess', () => {
|
15
|
-
this.validationMessageElement.
|
16
|
+
this.validationMessageElement.textContent = '';
|
17
|
+
this.validationElement.setAttribute('hidden', 'hidden');
|
18
|
+
});
|
19
|
+
this.addEventListener('toggleSwitchLoading', () => {
|
20
|
+
this.validationMessageElement.textContent = '';
|
16
21
|
this.validationElement.setAttribute('hidden', 'hidden');
|
17
22
|
});
|
18
23
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* eslint-disable custom-elements/expose-class-on-global */
|
2
|
+
|
1
3
|
import {controller, target} from '@github/catalyst'
|
2
4
|
|
3
5
|
@controller
|
@@ -7,12 +9,17 @@ export class ToggleSwitchInputElement extends HTMLElement {
|
|
7
9
|
|
8
10
|
connectedCallback() {
|
9
11
|
this.addEventListener('toggleSwitchError', (event: Event) => {
|
10
|
-
this.validationMessageElement.
|
12
|
+
this.validationMessageElement.textContent = (event as CustomEvent).detail
|
11
13
|
this.validationElement.removeAttribute('hidden')
|
12
14
|
})
|
13
15
|
|
14
16
|
this.addEventListener('toggleSwitchSuccess', () => {
|
15
|
-
this.validationMessageElement.
|
17
|
+
this.validationMessageElement.textContent = ''
|
18
|
+
this.validationElement.setAttribute('hidden', 'hidden')
|
19
|
+
})
|
20
|
+
|
21
|
+
this.addEventListener('toggleSwitchLoading', () => {
|
22
|
+
this.validationMessageElement.textContent = ''
|
16
23
|
this.validationElement.setAttribute('hidden', 'hidden')
|
17
24
|
})
|
18
25
|
}
|
@@ -72,6 +72,9 @@ module Primer
|
|
72
72
|
memo[component] = {
|
73
73
|
"fully_qualified_name" => component.name,
|
74
74
|
"description" => description,
|
75
|
+
"is_form_component" => docs.manifest_entry.form_component?,
|
76
|
+
"is_published" => docs.manifest_entry.published?,
|
77
|
+
"requires_js" => docs.manifest_entry.requires_js?,
|
75
78
|
**arg_data,
|
76
79
|
"slots" => slot_docs,
|
77
80
|
"methods" => method_docs,
|
@@ -10,7 +10,7 @@ module Primer
|
|
10
10
|
PREVIEW_MAP = {
|
11
11
|
Primer::Alpha::TextField => [:single_text_field_form, :multi_text_field_form],
|
12
12
|
Primer::Alpha::TextArea => [],
|
13
|
-
Primer::Alpha::Select => [:
|
13
|
+
Primer::Alpha::Select => [:select_form],
|
14
14
|
Primer::Alpha::MultiInput => [:multi_input_form],
|
15
15
|
Primer::Alpha::RadioButton => [:radio_button_with_nested_form],
|
16
16
|
Primer::Alpha::RadioButtonGroup => [:radio_button_group_form],
|
@@ -49,6 +49,12 @@ module Primer
|
|
49
49
|
|
50
50
|
preview_methods = PREVIEW_MAP[component]
|
51
51
|
preview_erbs = preview_methods.map do |preview_method|
|
52
|
+
# rubocop:disable Style/IfUnlessModifier
|
53
|
+
if Primer::Forms::FormsPreview.instance_methods.exclude?(preview_method)
|
54
|
+
raise "Preview '#{preview_method}' does not exist in Primer::Forms::FormsPreview"
|
55
|
+
end
|
56
|
+
# rubocop:enable Style/IfUnlessModifier
|
57
|
+
|
52
58
|
"<%= embed Primer::Forms::FormsPreview, #{preview_method.inspect} %>"
|
53
59
|
end
|
54
60
|
# rubocop:enable Lint/UselessAssignment
|
data/lib/primer/yard/registry.rb
CHANGED
@@ -89,6 +89,10 @@ module Primer
|
|
89
89
|
def a11y_reviewed?
|
90
90
|
metadata[:a11y_reviewed]
|
91
91
|
end
|
92
|
+
|
93
|
+
def manifest_entry
|
94
|
+
@manifest_entry ||= ComponentManifest.ref_for(component)
|
95
|
+
end
|
92
96
|
end
|
93
97
|
|
94
98
|
# Wrapper around an instance of YARD::Registry that provides easy access to component
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div style="width:100%; height: 400px; display: flex; justify-content: center; align-items: center;">
|
2
|
+
<div style="position:relative;">
|
3
|
+
<%= render(Primer::Alpha::Overlay.new(
|
4
|
+
title: title,
|
5
|
+
subtitle: subtitle,
|
6
|
+
role: role,
|
7
|
+
size: size,
|
8
|
+
placement: placement,
|
9
|
+
anchor_align: anchor_align,
|
10
|
+
anchor_side: anchor_side,
|
11
|
+
allow_out_of_bounds: allow_out_of_bounds,
|
12
|
+
visually_hide_title: visually_hide_title,
|
13
|
+
)) do |d| %>
|
14
|
+
<% d.with_header(title: title, size: header_size) %>
|
15
|
+
<% d.with_show_button { button_text } %>
|
16
|
+
<% d.with_body { body_text } %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
@@ -132,6 +132,37 @@ module Primer
|
|
132
132
|
body_text: body_text
|
133
133
|
})
|
134
134
|
end
|
135
|
+
|
136
|
+
# @label Middle Of Page with relative container
|
137
|
+
#
|
138
|
+
# @param title [String] text
|
139
|
+
# @param subtitle [String] text
|
140
|
+
# @param role [Symbol] select [dialog, menu]
|
141
|
+
# @param size [Symbol] select [auto, small, medium, medium_portrait, large, xlarge]
|
142
|
+
# @param anchor_align [Symbol] select [start, center, end]
|
143
|
+
# @param anchor_side [Symbol] select [inside_top, inside_bottom, inside_left, inside_right, inside_center, outside_top, outside_bottom, outside_left, outside_right]
|
144
|
+
# @param allow_out_of_bounds [Boolean] toggle
|
145
|
+
# @param visually_hide_title [Boolean] toggle
|
146
|
+
#
|
147
|
+
# @param header_size [Symbol] select [medium, large]
|
148
|
+
# @param button_text [String] text
|
149
|
+
# @param body_text [String] text
|
150
|
+
def middle_of_page_with_relative_container(title: "Test Overlay", subtitle: nil, role: :dialog, size: :auto, placement: :anchored, anchor_align: :center, anchor_side: :outside_bottom, allow_out_of_bounds: false, visually_hide_title: false, header_size: :medium, button_text: "Show Overlay", body_text: "")
|
151
|
+
render_with_template(locals: {
|
152
|
+
title: title,
|
153
|
+
subtitle: subtitle,
|
154
|
+
role: role,
|
155
|
+
size: size,
|
156
|
+
placement: placement,
|
157
|
+
anchor_align: anchor_align,
|
158
|
+
anchor_side: anchor_side,
|
159
|
+
allow_out_of_bounds: allow_out_of_bounds,
|
160
|
+
visually_hide_title: visually_hide_title,
|
161
|
+
header_size: header_size,
|
162
|
+
button_text: button_text,
|
163
|
+
body_text: body_text
|
164
|
+
})
|
165
|
+
end
|
135
166
|
end
|
136
167
|
end
|
137
168
|
end
|
data/static/arguments.json
CHANGED
@@ -1692,7 +1692,13 @@
|
|
1692
1692
|
"name": "subtitle",
|
1693
1693
|
"type": "String",
|
1694
1694
|
"default": "`nil`",
|
1695
|
-
"description": "Provides
|
1695
|
+
"description": "Provides additional context for the Overlay, also setting the `aria-describedby` attribute."
|
1696
|
+
},
|
1697
|
+
{
|
1698
|
+
"name": "overlay_id",
|
1699
|
+
"type": "String",
|
1700
|
+
"default": "`nil`",
|
1701
|
+
"description": "Provides the id of the overlay element so the close button can close it"
|
1696
1702
|
},
|
1697
1703
|
{
|
1698
1704
|
"name": "size",
|