@momentum-design/components 0.92.0 → 0.92.1
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.
- package/dist/browser/index.js +261 -241
- package/dist/browser/index.js.map +3 -3
- package/dist/components/menuitem/menuitem.component.d.ts +11 -0
- package/dist/components/menuitem/menuitem.component.js +11 -0
- package/dist/components/menuitemcheckbox/menuitemcheckbox.component.js +11 -4
- package/dist/components/menuitemcheckbox/menuitemcheckbox.styles.js +3 -0
- package/dist/components/menuitemradio/menuitemradio.component.js +11 -4
- package/dist/components/menuitemradio/menuitemradio.styles.js +3 -0
- package/dist/components/menupopover/menupopover.component.d.ts +49 -1
- package/dist/components/menupopover/menupopover.component.js +125 -17
- package/dist/components/menupopover/menupopover.utils.d.ts +1 -2
- package/dist/components/menupopover/menupopover.utils.js +1 -6
- package/dist/components/popover/popover.component.d.ts +5 -0
- package/dist/components/popover/popover.component.js +10 -1
- package/dist/components/popover/popover.constants.d.ts +1 -0
- package/dist/components/popover/popover.constants.js +1 -0
- package/dist/custom-elements.json +202 -11
- package/dist/react/menupopover/index.d.ts +18 -0
- package/dist/react/menupopover/index.js +18 -0
- package/package.json +1 -1
@@ -61,6 +61,12 @@ declare class MenuItem extends ListItem {
|
|
61
61
|
* Handles the keydown event for the menu item.
|
62
62
|
* If the Enter key is pressed, it triggers a click event on the menu item.
|
63
63
|
* This allows keyboard users to activate the menu item using the Enter key.
|
64
|
+
|
65
|
+
* This follows the native behaviour, actionable element can be triggered by Enter
|
66
|
+
* key on the keydown event.
|
67
|
+
*
|
68
|
+
* Note: Action triggered by Space on the keyup event.
|
69
|
+
*
|
64
70
|
* @param event - The keyboard event that triggered the action.
|
65
71
|
*/
|
66
72
|
handleKeyDown(event: KeyboardEvent): void;
|
@@ -69,6 +75,11 @@ declare class MenuItem extends ListItem {
|
|
69
75
|
* If the Space key is released, it triggers a click event on the menu item.
|
70
76
|
* This allows keyboard users to activate the menu item using the Space key.
|
71
77
|
* It also prevents the default action of the Space key to avoid scrolling the page.
|
78
|
+
*
|
79
|
+
* This follows the native behaviour, actionable element can be triggered by Space
|
80
|
+
* key on the keyup event.
|
81
|
+
*
|
82
|
+
* Note: Action triggered by Enter on the keydown event.
|
72
83
|
* @param event - The keyboard event that triggered the action.
|
73
84
|
*/
|
74
85
|
private handleKeyUp;
|
@@ -64,6 +64,12 @@ class MenuItem extends ListItem {
|
|
64
64
|
* Handles the keydown event for the menu item.
|
65
65
|
* If the Enter key is pressed, it triggers a click event on the menu item.
|
66
66
|
* This allows keyboard users to activate the menu item using the Enter key.
|
67
|
+
|
68
|
+
* This follows the native behaviour, actionable element can be triggered by Enter
|
69
|
+
* key on the keydown event.
|
70
|
+
*
|
71
|
+
* Note: Action triggered by Space on the keyup event.
|
72
|
+
*
|
67
73
|
* @param event - The keyboard event that triggered the action.
|
68
74
|
*/
|
69
75
|
handleKeyDown(event) {
|
@@ -77,6 +83,11 @@ class MenuItem extends ListItem {
|
|
77
83
|
* If the Space key is released, it triggers a click event on the menu item.
|
78
84
|
* This allows keyboard users to activate the menu item using the Space key.
|
79
85
|
* It also prevents the default action of the Space key to avoid scrolling the page.
|
86
|
+
*
|
87
|
+
* This follows the native behaviour, actionable element can be triggered by Space
|
88
|
+
* key on the keyup event.
|
89
|
+
*
|
90
|
+
* Note: Action triggered by Enter on the keydown event.
|
80
91
|
* @param event - The keyboard event that triggered the action.
|
81
92
|
*/
|
82
93
|
handleKeyUp(event) {
|
@@ -9,6 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
};
|
10
10
|
import { html, nothing } from 'lit';
|
11
11
|
import { property } from 'lit/decorators.js';
|
12
|
+
import { classMap } from 'lit-html/directives/class-map.js';
|
12
13
|
import { ROLE } from '../../utils/roles';
|
13
14
|
import MenuItem from '../menuitem/menuitem.component';
|
14
15
|
import { TYPE } from '../text/text.constants';
|
@@ -76,8 +77,7 @@ class MenuItemCheckbox extends MenuItem {
|
|
76
77
|
* If the menuitemcheckbox is disabled, it does nothing.
|
77
78
|
* If the menuitemcheckbox is not disabled, it toggles the `checked` state between `true` and `false`.
|
78
79
|
*/
|
79
|
-
this.handleMouseClick = (
|
80
|
-
event.stopPropagation();
|
80
|
+
this.handleMouseClick = () => {
|
81
81
|
if (this.disabled)
|
82
82
|
return;
|
83
83
|
this.checked = !this.checked;
|
@@ -140,8 +140,15 @@ class MenuItemCheckbox extends MenuItem {
|
|
140
140
|
* @returns TemplateResult | typeof nothing
|
141
141
|
*/
|
142
142
|
getCheckmarkIcon() {
|
143
|
-
if (this.
|
144
|
-
return html `
|
143
|
+
if (this.indicator === INDICATOR.CHECKMARK) {
|
144
|
+
return html `
|
145
|
+
<mdc-icon
|
146
|
+
slot="trailing-controls"
|
147
|
+
name="check-bold"
|
148
|
+
part="checkmark-icon"
|
149
|
+
class=${classMap({ 'hidden-checkmark': !this.checked })}
|
150
|
+
></mdc-icon>
|
151
|
+
`;
|
145
152
|
}
|
146
153
|
return nothing;
|
147
154
|
}
|
@@ -9,6 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
};
|
10
10
|
import { html, nothing } from 'lit';
|
11
11
|
import { property } from 'lit/decorators.js';
|
12
|
+
import { classMap } from 'lit-html/directives/class-map.js';
|
12
13
|
import { ROLE } from '../../utils/roles';
|
13
14
|
import MenuItem from '../menuitem/menuitem.component';
|
14
15
|
import { TYPE } from '../text/text.constants';
|
@@ -79,8 +80,7 @@ class MenuItemRadio extends MenuItem {
|
|
79
80
|
* If the menuitemradio is not checked, it sets its checked state to `true`
|
80
81
|
* and sets all other menuitemradio elements of the same group with checked state to `false`.
|
81
82
|
*/
|
82
|
-
this.handleMouseClick = (
|
83
|
-
event.stopPropagation();
|
83
|
+
this.handleMouseClick = () => {
|
84
84
|
if (this.disabled || this.checked)
|
85
85
|
return;
|
86
86
|
this.updateOtherRadiosCheckedState();
|
@@ -149,8 +149,15 @@ class MenuItemRadio extends MenuItem {
|
|
149
149
|
* @returns TemplateResult | typeof nothing
|
150
150
|
*/
|
151
151
|
renderCheckmarkIcon() {
|
152
|
-
if (this.
|
153
|
-
return html `
|
152
|
+
if (this.indicator === INDICATOR.CHECKMARK) {
|
153
|
+
return html `
|
154
|
+
<mdc-icon
|
155
|
+
slot="trailing-controls"
|
156
|
+
name="check-bold"
|
157
|
+
part="checkmark-icon"
|
158
|
+
class=${classMap({ 'hidden-checkmark': !this.checked })}
|
159
|
+
></mdc-icon>
|
160
|
+
`;
|
154
161
|
}
|
155
162
|
return nothing;
|
156
163
|
}
|
@@ -18,6 +18,24 @@ import { PopoverPlacement } from '../popover/popover.types';
|
|
18
18
|
*
|
19
19
|
* The orientation of the menu popover is always set to `vertical`.
|
20
20
|
*
|
21
|
+
* Submenu opens when:
|
22
|
+
* - Clicked on a menu item with a submenu
|
23
|
+
* - Enter or Space key pressed on a menu item with a submenu
|
24
|
+
*
|
25
|
+
* Menu closes completely (with all sub menus) when:
|
26
|
+
* - A menu item is clicked that does not have a submenu
|
27
|
+
* - Enter key pressed on a menu item (not a submenu trigger), menu item radio or menu item checkbox
|
28
|
+
* - Click outside the menu popover (on the backdrop)
|
29
|
+
*
|
30
|
+
* Close submenus when:
|
31
|
+
* - Esc key pressed, only the current submenu closed
|
32
|
+
* - Arrow Left key pressed, only the current submenu closed
|
33
|
+
* - Open another submenu with Click, Enter or Space key,
|
34
|
+
* closes recursively all submenus until the selected item's submenu
|
35
|
+
*
|
36
|
+
* Menu does not close when:
|
37
|
+
* - Space key pressed on a menu item radio or menu item checkbox
|
38
|
+
*
|
21
39
|
* @tagname mdc-menupopover
|
22
40
|
*
|
23
41
|
* @slot - Default slot for the menu popover content
|
@@ -45,12 +63,19 @@ declare class MenuPopover extends Popover {
|
|
45
63
|
* @default bottom
|
46
64
|
*/
|
47
65
|
placement: PopoverPlacement;
|
66
|
+
private menuItems;
|
48
67
|
constructor();
|
49
68
|
/** @internal */
|
50
|
-
|
69
|
+
collectMenuItems(): void;
|
51
70
|
connectedCallback(): void;
|
52
71
|
protected isOpenUpdated(oldValue: boolean, newValue: boolean): Promise<void>;
|
53
72
|
firstUpdated(changedProperties: PropertyValues): Promise<void>;
|
73
|
+
/**
|
74
|
+
* Reset all tabindex to -1 and set the tabindex of the current menu item to 0
|
75
|
+
*
|
76
|
+
* @param currentIndex - The index of the currently focused menu item.
|
77
|
+
*/
|
78
|
+
private resetTabIndexes;
|
54
79
|
/**
|
55
80
|
* Retrieves the current index of the menu item that triggered the event.
|
56
81
|
* @param target - The target element that triggered the event.
|
@@ -91,6 +116,12 @@ declare class MenuPopover extends Popover {
|
|
91
116
|
*/
|
92
117
|
private hasSubmenuWithTriggerId;
|
93
118
|
togglePopoverVisible: () => void;
|
119
|
+
/**
|
120
|
+
* Determines whether to close the menu based on the clicked target.
|
121
|
+
*
|
122
|
+
* @param target - The target element that was clicked.
|
123
|
+
*/
|
124
|
+
private closeMenu;
|
94
125
|
/**
|
95
126
|
* Handles mouse click events on the menu items.
|
96
127
|
* This method checks if the clicked element is a valid menu item and not a submenu trigger.
|
@@ -112,10 +143,27 @@ declare class MenuPopover extends Popover {
|
|
112
143
|
* Handles keydown events for keyboard navigation within the menu popover.
|
113
144
|
* This method allows users to navigate through the menu items using the keyboard.
|
114
145
|
* It supports Home, End, Arrow Up, Arrow Down, Arrow Left, Arrow Right, and Escape keys.
|
146
|
+
*
|
147
|
+
* Also, it handles Enter key to close the menu popover
|
148
|
+
*
|
115
149
|
* @param event - The keyboard event that triggered the keydown action.
|
116
150
|
* @returns - This method does not return anything.
|
117
151
|
*/
|
118
152
|
private handleKeyDown;
|
153
|
+
/**
|
154
|
+
* Handles keyup events for keyboard navigation within the menu popover.
|
155
|
+
*
|
156
|
+
* Some keys must be handled with keyup event to prevent default action.
|
157
|
+
*
|
158
|
+
* Space key closes the menu when the user presses it on a menu item,
|
159
|
+
* but the same key will trigger a click on the menu opener button.
|
160
|
+
* The button uses the keyup event so we have to handle it here as well
|
161
|
+
* to prevent the meu opener action which would re-open the menu.
|
162
|
+
*
|
163
|
+
* @param event - The keyboard event that triggered the keydown action.
|
164
|
+
* @returns - This method does not return anything.
|
165
|
+
*/
|
166
|
+
private handleKeyUp;
|
119
167
|
static styles: Array<CSSResult>;
|
120
168
|
}
|
121
169
|
export default MenuPopover;
|
@@ -10,14 +10,16 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
11
11
|
import { KEYS } from '../../utils/keys';
|
12
12
|
import { ROLE } from '../../utils/roles';
|
13
|
-
import { TAG_NAME as MENUITEM_TAGNAME } from '../menuitem/menuitem.constants';
|
14
13
|
import { TAG_NAME as MENUSECTION_TAGNAME } from '../menusection/menusection.constants';
|
14
|
+
import { TAG_NAME as MENUITEM_TAGNAME } from '../menuitem/menuitem.constants';
|
15
|
+
import { TAG_NAME as MENUITEMCHECKBOX_TAGNAME } from '../menuitemcheckbox/menuitemcheckbox.constants';
|
16
|
+
import { TAG_NAME as MENUITEMRADIO_TAGNAME } from '../menuitemradio/menuitemradio.constants';
|
15
17
|
import Popover from '../popover/popover.component';
|
16
18
|
import { COLOR } from '../popover/popover.constants';
|
17
19
|
import { popoverStack } from '../popover/popover.stack';
|
18
20
|
import { DEFAULTS, TAG_NAME as MENU_POPOVER } from './menupopover.constants';
|
19
21
|
import styles from './menupopover.styles';
|
20
|
-
import {
|
22
|
+
import { isValidMenuItem, isValidPopover } from './menupopover.utils';
|
21
23
|
/**
|
22
24
|
* A popover menu component that displays a list of menu items in a floating container.
|
23
25
|
* It's designed to work in conjunction with `mdc-menubar` and `mdc-menuitem` to create
|
@@ -35,6 +37,24 @@ import { isActiveMenuItem, isValidMenuItem, isValidPopover } from './menupopover
|
|
35
37
|
*
|
36
38
|
* The orientation of the menu popover is always set to `vertical`.
|
37
39
|
*
|
40
|
+
* Submenu opens when:
|
41
|
+
* - Clicked on a menu item with a submenu
|
42
|
+
* - Enter or Space key pressed on a menu item with a submenu
|
43
|
+
*
|
44
|
+
* Menu closes completely (with all sub menus) when:
|
45
|
+
* - A menu item is clicked that does not have a submenu
|
46
|
+
* - Enter key pressed on a menu item (not a submenu trigger), menu item radio or menu item checkbox
|
47
|
+
* - Click outside the menu popover (on the backdrop)
|
48
|
+
*
|
49
|
+
* Close submenus when:
|
50
|
+
* - Esc key pressed, only the current submenu closed
|
51
|
+
* - Arrow Left key pressed, only the current submenu closed
|
52
|
+
* - Open another submenu with Click, Enter or Space key,
|
53
|
+
* closes recursively all submenus until the selected item's submenu
|
54
|
+
*
|
55
|
+
* Menu does not close when:
|
56
|
+
* - Space key pressed on a menu item radio or menu item checkbox
|
57
|
+
*
|
38
58
|
* @tagname mdc-menupopover
|
39
59
|
*
|
40
60
|
* @slot - Default slot for the menu popover content
|
@@ -64,6 +84,7 @@ class MenuPopover extends Popover {
|
|
64
84
|
* @default bottom
|
65
85
|
*/
|
66
86
|
this.placement = DEFAULTS.PLACEMENT;
|
87
|
+
this.menuItems = [];
|
67
88
|
/**
|
68
89
|
* Handles outside click events to close the popover.
|
69
90
|
* This method checks if the click occurred outside the popover and its trigger element.
|
@@ -100,14 +121,15 @@ class MenuPopover extends Popover {
|
|
100
121
|
}
|
101
122
|
};
|
102
123
|
this.addEventListener('keydown', this.handleKeyDown);
|
124
|
+
this.addEventListener('keyup', this.handleKeyUp);
|
103
125
|
this.addEventListener('click', this.handleMouseClick);
|
104
126
|
}
|
105
127
|
/** @internal */
|
106
|
-
|
128
|
+
collectMenuItems() {
|
107
129
|
var _a;
|
108
130
|
const slot = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot');
|
109
131
|
const allAssignedElements = ((slot === null || slot === void 0 ? void 0 : slot.assignedElements({ flatten: true })) || []);
|
110
|
-
|
132
|
+
this.menuItems = allAssignedElements
|
111
133
|
.map(node => {
|
112
134
|
if (node.tagName.toLowerCase() === MENUSECTION_TAGNAME) {
|
113
135
|
return Array.from(node.children).filter(child => isValidMenuItem(child));
|
@@ -148,12 +170,20 @@ class MenuPopover extends Popover {
|
|
148
170
|
async firstUpdated(changedProperties) {
|
149
171
|
var _a;
|
150
172
|
await super.firstUpdated(changedProperties);
|
151
|
-
|
173
|
+
this.collectMenuItems();
|
174
|
+
this.resetTabIndexes(0);
|
175
|
+
(_a = this.triggerElement) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-haspopup', ROLE.MENU);
|
176
|
+
}
|
177
|
+
/**
|
178
|
+
* Reset all tabindex to -1 and set the tabindex of the current menu item to 0
|
179
|
+
*
|
180
|
+
* @param currentIndex - The index of the currently focused menu item.
|
181
|
+
*/
|
182
|
+
resetTabIndexes(currentIndex) {
|
152
183
|
if (this.menuItems.length > 0) {
|
153
184
|
this.menuItems.forEach(menuitem => menuitem.setAttribute('tabindex', '-1'));
|
154
|
-
this.menuItems[
|
185
|
+
this.menuItems[currentIndex].setAttribute('tabindex', '0');
|
155
186
|
}
|
156
|
-
(_a = this.triggerElement) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-haspopup', ROLE.MENU);
|
157
187
|
}
|
158
188
|
/**
|
159
189
|
* Retrieves the current index of the menu item that triggered the event.
|
@@ -204,8 +234,25 @@ class MenuPopover extends Popover {
|
|
204
234
|
* @returns - A boolean indicating whether a submenu with the specified trigger ID exists.
|
205
235
|
*/
|
206
236
|
hasSubmenuWithTriggerId(id) {
|
207
|
-
var _a;
|
208
|
-
return ((_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector(`${MENU_POPOVER}[triggerid="${id}"]`)) !== null;
|
237
|
+
var _a, _b;
|
238
|
+
return !!id && ((_b = (_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector) === null || _b === void 0 ? void 0 : _b.call(_a, `${MENU_POPOVER}[triggerid="${id}"]`)) !== null;
|
239
|
+
}
|
240
|
+
/**
|
241
|
+
* Determines whether to close the menu based on the clicked target.
|
242
|
+
*
|
243
|
+
* @param target - The target element that was clicked.
|
244
|
+
*/
|
245
|
+
closeMenu(target) {
|
246
|
+
const triggerId = target.getAttribute('id');
|
247
|
+
if (isValidMenuItem(target) &&
|
248
|
+
!this.hasSubmenuWithTriggerId(triggerId) &&
|
249
|
+
this === target.closest(MENU_POPOVER) // Ensure close all popover called only once
|
250
|
+
) {
|
251
|
+
this.closeAllMenuPopovers();
|
252
|
+
if (target.matches(MENUITEM_TAGNAME)) {
|
253
|
+
target.dispatchEvent(new Event('action', { bubbles: true, composed: true }));
|
254
|
+
}
|
255
|
+
}
|
209
256
|
}
|
210
257
|
/**
|
211
258
|
* Handles mouse click events on the menu items.
|
@@ -215,13 +262,9 @@ class MenuPopover extends Popover {
|
|
215
262
|
*/
|
216
263
|
handleMouseClick(event) {
|
217
264
|
const target = event.target;
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
this === target.closest(MENU_POPOVER) // Ensure close all popover called only once
|
222
|
-
) {
|
223
|
-
this.closeAllMenuPopovers();
|
224
|
-
target.dispatchEvent(new Event('action', { bubbles: true, composed: true }));
|
265
|
+
if (event.isTrusted) {
|
266
|
+
// skip manually dispatched clicks from listItem
|
267
|
+
this.closeMenu(target);
|
225
268
|
}
|
226
269
|
}
|
227
270
|
/**
|
@@ -249,37 +292,48 @@ class MenuPopover extends Popover {
|
|
249
292
|
* Handles keydown events for keyboard navigation within the menu popover.
|
250
293
|
* This method allows users to navigate through the menu items using the keyboard.
|
251
294
|
* It supports Home, End, Arrow Up, Arrow Down, Arrow Left, Arrow Right, and Escape keys.
|
295
|
+
*
|
296
|
+
* Also, it handles Enter key to close the menu popover
|
297
|
+
*
|
252
298
|
* @param event - The keyboard event that triggered the keydown action.
|
253
299
|
* @returns - This method does not return anything.
|
254
300
|
*/
|
255
301
|
handleKeyDown(event) {
|
256
302
|
var _a, _b;
|
257
|
-
|
303
|
+
let isKeyHandled = false;
|
304
|
+
this.collectMenuItems();
|
305
|
+
const target = event.target;
|
306
|
+
const currentIndex = this.getCurrentIndex(target);
|
258
307
|
if (currentIndex === -1)
|
259
308
|
return;
|
309
|
+
this.resetTabIndexes(currentIndex);
|
260
310
|
const isRtl = window.getComputedStyle(this).direction === 'rtl';
|
261
311
|
const targetKey = this.resolveDirectionKey(event.key, isRtl);
|
262
312
|
switch (targetKey) {
|
263
313
|
case KEYS.HOME: {
|
264
314
|
// Move focus to the first menu item
|
265
315
|
this.resetTabIndexAndSetFocus(0, currentIndex);
|
316
|
+
isKeyHandled = true;
|
266
317
|
break;
|
267
318
|
}
|
268
319
|
case KEYS.END: {
|
269
320
|
// Move focus to the last menu item
|
270
321
|
this.resetTabIndexAndSetFocus(this.menuItems.length - 1, currentIndex);
|
322
|
+
isKeyHandled = true;
|
271
323
|
break;
|
272
324
|
}
|
273
325
|
case KEYS.ARROW_DOWN: {
|
274
326
|
// Move focus to the next menu item
|
275
327
|
const newIndex = currentIndex + 1 === this.menuItems.length ? 0 : currentIndex + 1;
|
276
328
|
this.resetTabIndexAndSetFocus(newIndex, currentIndex);
|
329
|
+
isKeyHandled = true;
|
277
330
|
break;
|
278
331
|
}
|
279
332
|
case KEYS.ARROW_UP: {
|
280
333
|
// Move focus to the prev menu item
|
281
334
|
const newIndex = currentIndex - 1 === -1 ? this.menuItems.length - 1 : currentIndex - 1;
|
282
335
|
this.resetTabIndexAndSetFocus(newIndex, currentIndex);
|
336
|
+
isKeyHandled = true;
|
283
337
|
break;
|
284
338
|
}
|
285
339
|
case KEYS.ARROW_RIGHT: {
|
@@ -289,6 +343,7 @@ class MenuPopover extends Popover {
|
|
289
343
|
const submenu = (_b = this.parentElement) === null || _b === void 0 ? void 0 : _b.querySelector(`${MENU_POPOVER}[triggerid="${triggerId}"]`);
|
290
344
|
if (submenu) {
|
291
345
|
submenu.showPopover();
|
346
|
+
isKeyHandled = true;
|
292
347
|
}
|
293
348
|
}
|
294
349
|
break;
|
@@ -298,16 +353,69 @@ class MenuPopover extends Popover {
|
|
298
353
|
if (isValidPopover(this.parentElement)) {
|
299
354
|
this.hidePopover();
|
300
355
|
this.resetTabIndexAndSetFocus(0, currentIndex);
|
356
|
+
isKeyHandled = true;
|
301
357
|
}
|
302
358
|
break;
|
303
359
|
}
|
304
360
|
case KEYS.ESCAPE: {
|
305
361
|
this.resetTabIndexAndSetFocus(0, currentIndex);
|
362
|
+
isKeyHandled = true;
|
363
|
+
break;
|
364
|
+
}
|
365
|
+
case KEYS.ENTER: {
|
366
|
+
this.closeMenu(target);
|
367
|
+
isKeyHandled = true;
|
368
|
+
break;
|
369
|
+
}
|
370
|
+
case KEYS.SPACE: {
|
371
|
+
// Prevent page scroll when space is pressed down
|
372
|
+
isKeyHandled = true;
|
306
373
|
break;
|
307
374
|
}
|
308
375
|
default:
|
309
376
|
break;
|
310
377
|
}
|
378
|
+
// When menu consume any of the pressed key, we need to stop propagation
|
379
|
+
// to prevent the event from bubbling up and being handled by parent components which might use the same key.
|
380
|
+
if (isKeyHandled) {
|
381
|
+
event.stopPropagation();
|
382
|
+
event.preventDefault();
|
383
|
+
}
|
384
|
+
}
|
385
|
+
/**
|
386
|
+
* Handles keyup events for keyboard navigation within the menu popover.
|
387
|
+
*
|
388
|
+
* Some keys must be handled with keyup event to prevent default action.
|
389
|
+
*
|
390
|
+
* Space key closes the menu when the user presses it on a menu item,
|
391
|
+
* but the same key will trigger a click on the menu opener button.
|
392
|
+
* The button uses the keyup event so we have to handle it here as well
|
393
|
+
* to prevent the meu opener action which would re-open the menu.
|
394
|
+
*
|
395
|
+
* @param event - The keyboard event that triggered the keydown action.
|
396
|
+
* @returns - This method does not return anything.
|
397
|
+
*/
|
398
|
+
handleKeyUp(event) {
|
399
|
+
let isKeyHandled = false;
|
400
|
+
const target = event.target;
|
401
|
+
switch (event.key) {
|
402
|
+
case KEYS.SPACE: {
|
403
|
+
// If the target is a menu item, trigger its click event
|
404
|
+
if (!target.matches(`${MENUITEMRADIO_TAGNAME}, ${MENUITEMCHECKBOX_TAGNAME}`)) {
|
405
|
+
this.closeMenu(target);
|
406
|
+
isKeyHandled = true;
|
407
|
+
}
|
408
|
+
break;
|
409
|
+
}
|
410
|
+
default:
|
411
|
+
break;
|
412
|
+
}
|
413
|
+
// When menu consume any of the pressed key, we need to stop propagation
|
414
|
+
// to prevent the event from bubbling up and being handled by parent components which might use the same key.
|
415
|
+
if (isKeyHandled) {
|
416
|
+
event.stopPropagation();
|
417
|
+
event.preventDefault();
|
418
|
+
}
|
311
419
|
}
|
312
420
|
}
|
313
421
|
MenuPopover.styles = [...Popover.styles, ...styles];
|
@@ -6,5 +6,4 @@ import type MenuPopover from './menupopover.component';
|
|
6
6
|
*/
|
7
7
|
declare const isValidMenuItem: (menuItem: Element | null) => boolean;
|
8
8
|
declare const isValidPopover: (el: Element | null) => el is MenuPopover;
|
9
|
-
|
10
|
-
export { isValidMenuItem, isValidPopover, isActiveMenuItem };
|
9
|
+
export { isValidMenuItem, isValidPopover };
|
@@ -13,9 +13,4 @@ const isValidMenuItem = (menuItem) => {
|
|
13
13
|
return role === ROLE.MENUITEM || role === ROLE.MENUITEMCHECKBOX || role === ROLE.MENUITEMRADIO;
|
14
14
|
};
|
15
15
|
const isValidPopover = (el) => { var _a; return ((_a = el === null || el === void 0 ? void 0 : el.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === MENUPOPOVER_TAGNAME; };
|
16
|
-
|
17
|
-
var _a;
|
18
|
-
const role = (_a = menuItem === null || menuItem === void 0 ? void 0 : menuItem.getAttribute('role')) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
19
|
-
return !!menuItem && role === ROLE.MENUITEM && !menuItem.hasAttribute('disabled');
|
20
|
-
};
|
21
|
-
export { isValidMenuItem, isValidPopover, isActiveMenuItem };
|
16
|
+
export { isValidMenuItem, isValidPopover };
|
@@ -87,6 +87,11 @@ declare class Popover extends Popover_base {
|
|
87
87
|
* @default 4
|
88
88
|
*/
|
89
89
|
offset: number;
|
90
|
+
/**
|
91
|
+
*Virtual padding around the boundary to check for overflow.
|
92
|
+
* @default 16
|
93
|
+
*/
|
94
|
+
boundaryPadding: number;
|
90
95
|
/**
|
91
96
|
* Determines whether the focus trap is enabled.
|
92
97
|
* If true, focus will be restricted to the content within this component.
|
@@ -106,6 +106,11 @@ class Popover extends PreventScrollMixin(FocusTrapMixin(Component)) {
|
|
106
106
|
* @default 4
|
107
107
|
*/
|
108
108
|
this.offset = DEFAULTS.OFFSET;
|
109
|
+
/**
|
110
|
+
*Virtual padding around the boundary to check for overflow.
|
111
|
+
* @default 16
|
112
|
+
*/
|
113
|
+
this.boundaryPadding = DEFAULTS.BOUNDARY_PADDING;
|
109
114
|
/**
|
110
115
|
* Determines whether the focus trap is enabled.
|
111
116
|
* If true, focus will be restricted to the content within this component.
|
@@ -617,7 +622,7 @@ class Popover extends PreventScrollMixin(FocusTrapMixin(Component)) {
|
|
617
622
|
positionPopover() {
|
618
623
|
if (!this.triggerElement)
|
619
624
|
return;
|
620
|
-
const middleware = [shift()];
|
625
|
+
const middleware = [shift({ padding: this.boundaryPadding })];
|
621
626
|
let popoverOffset = this.offset;
|
622
627
|
if (this.flip) {
|
623
628
|
middleware.push(flip());
|
@@ -725,6 +730,10 @@ __decorate([
|
|
725
730
|
property({ type: Number, reflect: true }),
|
726
731
|
__metadata("design:type", Number)
|
727
732
|
], Popover.prototype, "offset", void 0);
|
733
|
+
__decorate([
|
734
|
+
property({ type: Number, reflect: true, attribute: 'boundary-padding' }),
|
735
|
+
__metadata("design:type", Number)
|
736
|
+
], Popover.prototype, "boundaryPadding", void 0);
|
728
737
|
__decorate([
|
729
738
|
property({ type: Boolean, reflect: true, attribute: 'focus-trap' }),
|
730
739
|
__metadata("design:type", Boolean)
|