@primer/view-components 0.10.0 → 0.10.1-rc.26c7a5a1
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.
@@ -15,7 +15,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
15
15
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
16
16
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
17
17
|
};
|
18
|
-
var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput,
|
18
|
+
var _ActionMenuElement_instances, _ActionMenuElement_abortController, _ActionMenuElement_originalLabel, _ActionMenuElement_inputName, _ActionMenuElement_invokerBeingClicked, _ActionMenuElement_softDisableItems, _ActionMenuElement_potentiallyDisallowActivation, _ActionMenuElement_isKeyboardActivation, _ActionMenuElement_isMouseActivation, _ActionMenuElement_isActivation, _ActionMenuElement_handleInvokerActivated, _ActionMenuElement_handleDialogItemActivated, _ActionMenuElement_handleItemActivated, _ActionMenuElement_activateItem, _ActionMenuElement_handleIncludeFragmentReplaced, _ActionMenuElement_handleFocusOut, _ActionMenuElement_show, _ActionMenuElement_hide, _ActionMenuElement_isOpen, _ActionMenuElement_setDynamicLabel, _ActionMenuElement_updateInput, _ActionMenuElement_firstItem_get, _ActionMenuElement_items_get;
|
19
19
|
import { controller, target } from '@github/catalyst';
|
20
20
|
import '@oddbird/popover-polyfill';
|
21
21
|
const validSelectors = ['[role="menuitem"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]'];
|
@@ -27,6 +27,7 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
|
|
27
27
|
_ActionMenuElement_abortController.set(this, void 0);
|
28
28
|
_ActionMenuElement_originalLabel.set(this, '');
|
29
29
|
_ActionMenuElement_inputName.set(this, '');
|
30
|
+
_ActionMenuElement_invokerBeingClicked.set(this, false);
|
30
31
|
}
|
31
32
|
get selectVariant() {
|
32
33
|
return this.getAttribute('data-select-variant');
|
@@ -94,8 +95,10 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
|
|
94
95
|
this.addEventListener('click', this, { signal });
|
95
96
|
this.addEventListener('mouseover', this, { signal });
|
96
97
|
this.addEventListener('focusout', this, { signal });
|
98
|
+
this.addEventListener('mousedown', this, { signal });
|
97
99
|
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
|
98
100
|
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
|
101
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_softDisableItems).call(this);
|
99
102
|
if (this.includeFragment) {
|
100
103
|
this.includeFragment.addEventListener('include-fragment-replaced', this, {
|
101
104
|
signal
|
@@ -106,98 +109,182 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
|
|
106
109
|
__classPrivateFieldGet(this, _ActionMenuElement_abortController, "f").abort();
|
107
110
|
}
|
108
111
|
handleEvent(event) {
|
109
|
-
var _a, _b, _c
|
110
|
-
const
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get).focus();
|
116
|
-
return;
|
117
|
-
}
|
112
|
+
var _a, _b, _c;
|
113
|
+
const targetIsInvoker = (_a = this.invokerElement) === null || _a === void 0 ? void 0 : _a.contains(event.target);
|
114
|
+
const eventIsActivation = __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivation).call(this, event);
|
115
|
+
if (targetIsInvoker && event.type === 'mousedown') {
|
116
|
+
__classPrivateFieldSet(this, _ActionMenuElement_invokerBeingClicked, true, "f");
|
117
|
+
return;
|
118
118
|
}
|
119
|
-
//
|
120
|
-
|
119
|
+
// Prevent safari bug that dismisses menu on mousedown instead of allowing
|
120
|
+
// the click event to propagate to the button
|
121
|
+
if (event.type === 'mousedown') {
|
122
|
+
event.preventDefault();
|
121
123
|
return;
|
122
124
|
}
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
const dialogInvoker = event.target.closest('[data-show-dialog-id]');
|
128
|
-
const dialog = this.ownerDocument.getElementById((dialogInvoker === null || dialogInvoker === void 0 ? void 0 : dialogInvoker.getAttribute('data-show-dialog-id')) || '');
|
129
|
-
if (dialogInvoker && dialog && this.contains(dialogInvoker) && this.contains(dialog)) {
|
130
|
-
this.querySelector('.ActionListWrap').style.display = 'none';
|
131
|
-
const dialog_controller = new AbortController();
|
132
|
-
const { signal } = dialog_controller;
|
133
|
-
const handleDialogClose = () => {
|
134
|
-
var _a, _b;
|
135
|
-
dialog_controller.abort();
|
136
|
-
this.querySelector('.ActionListWrap').style.display = '';
|
137
|
-
if ((_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.matches(':popover-open')) {
|
138
|
-
(_b = this.popoverElement) === null || _b === void 0 ? void 0 : _b.hidePopover();
|
139
|
-
}
|
140
|
-
};
|
141
|
-
dialog.addEventListener('close', handleDialogClose, { signal });
|
142
|
-
dialog.addEventListener('cancel', handleDialogClose, { signal });
|
143
|
-
return;
|
144
|
-
}
|
125
|
+
if (targetIsInvoker && eventIsActivation) {
|
126
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleInvokerActivated).call(this, event);
|
127
|
+
__classPrivateFieldSet(this, _ActionMenuElement_invokerBeingClicked, false, "f");
|
128
|
+
return;
|
145
129
|
}
|
146
|
-
|
130
|
+
// Ignore events within dialogs within menus
|
131
|
+
if (((_b = event.target) === null || _b === void 0 ? void 0 : _b.closest('dialog')) || ((_c = event.target) === null || _c === void 0 ? void 0 : _c.closest('modal-dialog'))) {
|
147
132
|
return;
|
148
|
-
if (event.type === 'include-fragment-replaced') {
|
149
|
-
if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get))
|
150
|
-
__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get).focus();
|
151
133
|
}
|
152
|
-
|
153
|
-
|
154
|
-
// altering the target of the event. Not doing this specifically affects
|
155
|
-
// <a> tags. It causes the event to be sent to the currently focused element
|
156
|
-
// instead of the anchor, which effectively prevents navigation, i.e. it
|
157
|
-
// appears as if hitting enter does nothing. Curiously, clicking instead
|
158
|
-
// works fine.
|
159
|
-
if (this.selectVariant !== 'multiple') {
|
160
|
-
setTimeout(() => {
|
161
|
-
var _a, _b;
|
162
|
-
if ((_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.matches(':popover-open')) {
|
163
|
-
(_b = this.popoverElement) === null || _b === void 0 ? void 0 : _b.hidePopover();
|
164
|
-
}
|
165
|
-
});
|
166
|
-
}
|
167
|
-
// The rest of the code below deals with single/multiple selection behavior, and should not
|
168
|
-
// interfere with events fired by menu items whose behavior is specified outside the library.
|
169
|
-
if (this.selectVariant !== 'multiple' && this.selectVariant !== 'single')
|
170
|
-
return;
|
171
|
-
const item = event.target.closest(menuItemSelectors.join(','));
|
172
|
-
if (!item)
|
134
|
+
if (event.type === 'focusout') {
|
135
|
+
if (__classPrivateFieldGet(this, _ActionMenuElement_invokerBeingClicked, "f"))
|
173
136
|
return;
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
if (checked) {
|
179
|
-
item.setAttribute('aria-checked', 'true');
|
137
|
+
// Give the browser time to focus the next element
|
138
|
+
requestAnimationFrame(() => {
|
139
|
+
if (!this.contains(document.activeElement) || document.activeElement === this.invokerElement) {
|
140
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleFocusOut).call(this);
|
180
141
|
}
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
142
|
+
});
|
143
|
+
return;
|
144
|
+
}
|
145
|
+
const item = event.target.closest(menuItemSelectors.join(','));
|
146
|
+
const targetIsItem = item !== null;
|
147
|
+
if (targetIsItem && eventIsActivation) {
|
148
|
+
const dialogInvoker = item.closest('[data-show-dialog-id]');
|
149
|
+
if (dialogInvoker) {
|
150
|
+
const dialog = this.ownerDocument.getElementById(dialogInvoker.getAttribute('data-show-dialog-id') || '');
|
151
|
+
if (dialog && this.contains(dialogInvoker) && this.contains(dialog)) {
|
152
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleDialogItemActivated).call(this, event, dialog);
|
153
|
+
return;
|
185
154
|
}
|
186
|
-
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
|
187
155
|
}
|
188
|
-
|
189
|
-
|
190
|
-
|
156
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_activateItem).call(this, event, item);
|
157
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleItemActivated).call(this, event, item);
|
158
|
+
return;
|
159
|
+
}
|
160
|
+
if (event.type === 'include-fragment-replaced') {
|
161
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_handleIncludeFragmentReplaced).call(this);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
};
|
165
|
+
_ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalLabel = new WeakMap(), _ActionMenuElement_inputName = new WeakMap(), _ActionMenuElement_invokerBeingClicked = new WeakMap(), _ActionMenuElement_instances = new WeakSet(), _ActionMenuElement_softDisableItems = function _ActionMenuElement_softDisableItems() {
|
166
|
+
const { signal } = __classPrivateFieldGet(this, _ActionMenuElement_abortController, "f");
|
167
|
+
for (const item of __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_items_get)) {
|
168
|
+
item.addEventListener('click', __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_potentiallyDisallowActivation).bind(this), { signal });
|
169
|
+
item.addEventListener('keydown', __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_potentiallyDisallowActivation).bind(this), { signal });
|
170
|
+
}
|
171
|
+
}, _ActionMenuElement_potentiallyDisallowActivation = function _ActionMenuElement_potentiallyDisallowActivation(event) {
|
172
|
+
if (!__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivation).call(this, event))
|
173
|
+
return;
|
174
|
+
const item = event.target.closest(menuItemSelectors.join(','));
|
175
|
+
if (!item)
|
176
|
+
return;
|
177
|
+
if (item.getAttribute('aria-disabled')) {
|
178
|
+
event.preventDefault();
|
179
|
+
event.stopPropagation();
|
180
|
+
event.stopImmediatePropagation();
|
181
|
+
}
|
182
|
+
}, _ActionMenuElement_isKeyboardActivation = function _ActionMenuElement_isKeyboardActivation(event) {
|
183
|
+
return (event instanceof KeyboardEvent &&
|
184
|
+
event.type === 'keydown' &&
|
185
|
+
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
186
|
+
(event.key === 'Enter' || event.key === ' '));
|
187
|
+
}, _ActionMenuElement_isMouseActivation = function _ActionMenuElement_isMouseActivation(event) {
|
188
|
+
return event instanceof MouseEvent && event.type === 'click';
|
189
|
+
}, _ActionMenuElement_isActivation = function _ActionMenuElement_isActivation(event) {
|
190
|
+
return __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isMouseActivation).call(this, event) || __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isKeyboardActivation).call(this, event);
|
191
|
+
}, _ActionMenuElement_handleInvokerActivated = function _ActionMenuElement_handleInvokerActivated(event) {
|
192
|
+
var _a;
|
193
|
+
event.preventDefault();
|
194
|
+
event.stopPropagation();
|
195
|
+
if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
|
196
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_show).call(this);
|
200
|
+
(_a = __classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get)) === null || _a === void 0 ? void 0 : _a.focus();
|
201
|
+
}
|
202
|
+
}, _ActionMenuElement_handleDialogItemActivated = function _ActionMenuElement_handleDialogItemActivated(event, dialog) {
|
203
|
+
this.querySelector('.ActionListWrap').style.display = 'none';
|
204
|
+
const dialog_controller = new AbortController();
|
205
|
+
const { signal } = dialog_controller;
|
206
|
+
const handleDialogClose = () => {
|
207
|
+
dialog_controller.abort();
|
208
|
+
this.querySelector('.ActionListWrap').style.display = '';
|
209
|
+
if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
|
210
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
|
211
|
+
}
|
212
|
+
};
|
213
|
+
dialog.addEventListener('close', handleDialogClose, { signal });
|
214
|
+
dialog.addEventListener('cancel', handleDialogClose, { signal });
|
215
|
+
}, _ActionMenuElement_handleItemActivated = function _ActionMenuElement_handleItemActivated(event, item) {
|
216
|
+
// Hide popover after current event loop to prevent changes in focus from
|
217
|
+
// altering the target of the event. Not doing this specifically affects
|
218
|
+
// <a> tags. It causes the event to be sent to the currently focused element
|
219
|
+
// instead of the anchor, which effectively prevents navigation, i.e. it
|
220
|
+
// appears as if hitting enter does nothing. Curiously, clicking instead
|
221
|
+
// works fine.
|
222
|
+
if (this.selectVariant !== 'multiple') {
|
223
|
+
setTimeout(() => {
|
224
|
+
if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isOpen).call(this)) {
|
225
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
|
191
226
|
}
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
227
|
+
});
|
228
|
+
}
|
229
|
+
// The rest of the code below deals with single/multiple selection behavior, and should not
|
230
|
+
// interfere with events fired by menu items whose behavior is specified outside the library.
|
231
|
+
if (this.selectVariant !== 'multiple' && this.selectVariant !== 'single')
|
232
|
+
return;
|
233
|
+
const ariaChecked = item.getAttribute('aria-checked');
|
234
|
+
const checked = ariaChecked !== 'true';
|
235
|
+
if (this.selectVariant === 'single') {
|
236
|
+
// Only check, never uncheck here. Single-select mode does not allow unchecking a checked item.
|
237
|
+
if (checked) {
|
238
|
+
item.setAttribute('aria-checked', 'true');
|
239
|
+
}
|
240
|
+
for (const checkedItem of this.querySelectorAll('[aria-checked]')) {
|
241
|
+
if (checkedItem !== item) {
|
242
|
+
checkedItem.setAttribute('aria-checked', 'false');
|
196
243
|
}
|
197
244
|
}
|
245
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_setDynamicLabel).call(this);
|
198
246
|
}
|
199
|
-
|
200
|
-
|
247
|
+
else {
|
248
|
+
// multi-select mode allows unchecking a checked item
|
249
|
+
item.setAttribute('aria-checked', `${checked}`);
|
250
|
+
}
|
251
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
|
252
|
+
if (event instanceof KeyboardEvent && event.target instanceof HTMLButtonElement) {
|
253
|
+
// prevent buttons from being clicked twice
|
254
|
+
event.preventDefault();
|
255
|
+
return;
|
256
|
+
}
|
257
|
+
}, _ActionMenuElement_activateItem = function _ActionMenuElement_activateItem(event, item) {
|
258
|
+
const eventWillActivateByDefault = (event instanceof MouseEvent && event.type === 'click') ||
|
259
|
+
(event instanceof KeyboardEvent &&
|
260
|
+
event.type === 'keydown' &&
|
261
|
+
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
262
|
+
event.key === 'Enter');
|
263
|
+
// if the event will result in activating the current item by default, i.e. is a
|
264
|
+
// mouse click or keyboard enter, bail out
|
265
|
+
if (eventWillActivateByDefault)
|
266
|
+
return;
|
267
|
+
// otherwise, event will not result in activation by default, so we stop it and
|
268
|
+
// simulate a click
|
269
|
+
event.stopPropagation();
|
270
|
+
const elem = item;
|
271
|
+
elem.click();
|
272
|
+
}, _ActionMenuElement_handleIncludeFragmentReplaced = function _ActionMenuElement_handleIncludeFragmentReplaced() {
|
273
|
+
if (__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get))
|
274
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "a", _ActionMenuElement_firstItem_get).focus();
|
275
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_softDisableItems).call(this);
|
276
|
+
}, _ActionMenuElement_handleFocusOut = function _ActionMenuElement_handleFocusOut() {
|
277
|
+
__classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_hide).call(this);
|
278
|
+
}, _ActionMenuElement_show = function _ActionMenuElement_show() {
|
279
|
+
var _a;
|
280
|
+
(_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.showPopover();
|
281
|
+
}, _ActionMenuElement_hide = function _ActionMenuElement_hide() {
|
282
|
+
var _a;
|
283
|
+
(_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.hidePopover();
|
284
|
+
}, _ActionMenuElement_isOpen = function _ActionMenuElement_isOpen() {
|
285
|
+
var _a;
|
286
|
+
return (_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.matches(':popover-open');
|
287
|
+
}, _ActionMenuElement_setDynamicLabel = function _ActionMenuElement_setDynamicLabel() {
|
201
288
|
if (!this.dynamicLabel)
|
202
289
|
return;
|
203
290
|
const invokerLabel = this.invokerLabel;
|
@@ -252,13 +339,10 @@ _ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalL
|
|
252
339
|
input.remove();
|
253
340
|
}
|
254
341
|
}
|
255
|
-
}, _ActionMenuElement_isActivationKeydown = function _ActionMenuElement_isActivationKeydown(event) {
|
256
|
-
return (event instanceof KeyboardEvent &&
|
257
|
-
event.type === 'keydown' &&
|
258
|
-
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
259
|
-
(event.key === 'Enter' || event.key === ' '));
|
260
342
|
}, _ActionMenuElement_firstItem_get = function _ActionMenuElement_firstItem_get() {
|
261
343
|
return this.querySelector(menuItemSelectors.join(','));
|
344
|
+
}, _ActionMenuElement_items_get = function _ActionMenuElement_items_get() {
|
345
|
+
return Array.from(this.querySelectorAll(menuItemSelectors.join(',')));
|
262
346
|
};
|
263
347
|
__decorate([
|
264
348
|
target
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@primer/view-components",
|
3
|
-
"version": "0.10.
|
3
|
+
"version": "0.10.1-rc.26c7a5a1",
|
4
4
|
"description": "ViewComponents for the Primer Design System",
|
5
5
|
"main": "app/assets/javascripts/primer_view_components.js",
|
6
6
|
"module": "app/components/primer/primer.js",
|
@@ -45,7 +45,7 @@
|
|
45
45
|
"@github/auto-check-element": "^5.2.0",
|
46
46
|
"@github/auto-complete-element": "^3.3.4",
|
47
47
|
"@github/catalyst": "^1.6.0",
|
48
|
-
"@github/clipboard-copy-element": "^1.
|
48
|
+
"@github/clipboard-copy-element": "^1.3.0",
|
49
49
|
"@github/details-menu-element": "^1.0.12",
|
50
50
|
"@github/image-crop-element": "^5.0.0",
|
51
51
|
"@github/include-fragment-element": "^6.1.1",
|