@mgdis/mg-components 5.7.0 → 5.8.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/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mg-action-more_31.cjs.entry.js +351 -600
- package/dist/cjs/mg-components.cjs.js +1 -1
- package/dist/cjs/mg-item-more.cjs.entry.js +273 -0
- package/dist/cjs/mg-menu.conf-9afe6571.js +242 -0
- package/dist/collection/collection-manifest.json +2 -1
- package/dist/collection/components/atoms/mg-button/mg-button.js +24 -0
- package/dist/collection/components/atoms/mg-icon/mg-icon.conf.js +8 -0
- package/dist/collection/components/atoms/mg-tooltip/mg-tooltip.js +6 -2
- package/dist/collection/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.js +14 -10
- package/dist/collection/components/molecules/inputs/mg-input-select/mg-input-select.js +91 -21
- package/dist/collection/components/molecules/menu/mg-menu/mg-menu.conf.js +0 -13
- package/dist/collection/components/molecules/menu/mg-menu/mg-menu.js +80 -76
- package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.css +7 -5
- package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.js +174 -78
- package/dist/collection/components/molecules/mg-form/mg-form.js +1 -1
- package/dist/collection/components/molecules/mg-item-more/mg-item-more.conf.js +1 -0
- package/dist/collection/components/molecules/mg-item-more/mg-item-more.css +30 -0
- package/dist/collection/components/molecules/mg-item-more/mg-item-more.js +200 -0
- package/dist/collection/components/molecules/mg-tabs/mg-tabs.css +0 -2
- package/dist/collection/styles/navigation-button.scss +1 -1
- package/dist/collection/utils/behaviors.utils.js +33 -29
- package/dist/collection/utils/components.utils.js +2 -4
- package/dist/collection/utils/unit.test.utils.js +25 -0
- package/dist/components/components.utils.js +2 -4
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/mg-action-more.js +2 -1
- package/dist/components/mg-button2.js +4 -1
- package/dist/components/mg-form.js +1 -1
- package/dist/components/mg-icon2.js +8 -0
- package/dist/components/mg-input-checkbox.js +5 -4
- package/dist/components/mg-input-select2.js +83 -17
- package/dist/components/mg-item-more.d.ts +11 -0
- package/dist/components/mg-item-more.js +336 -0
- package/dist/components/mg-menu-item2.js +138 -251
- package/dist/components/mg-menu.conf.js +14 -0
- package/dist/components/mg-menu2.js +76 -111
- package/dist/components/mg-tabs.js +1 -1
- package/dist/components/mg-tooltip2.js +6 -2
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mg-action-more_31.entry.js +321 -570
- package/dist/esm/mg-components.js +1 -1
- package/dist/esm/mg-item-more.entry.js +269 -0
- package/dist/esm/mg-menu.conf-881fbd82.js +235 -0
- package/dist/mg-components/mg-components.css +1 -1
- package/dist/mg-components/mg-components.esm.js +1 -1
- package/dist/mg-components/p-1221773c.entry.js +1 -0
- package/dist/mg-components/p-30bc87db.entry.js +1 -0
- package/dist/mg-components/p-367f92d2.js +1 -0
- package/dist/mg-components/styles/navigation-button.scss +1 -1
- package/dist/types/components/atoms/mg-button/mg-button.d.ts +5 -0
- package/dist/types/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.d.ts +3 -3
- package/dist/types/components/molecules/inputs/mg-input-select/mg-input-select.d.ts +39 -4
- package/dist/types/components/molecules/menu/mg-menu/mg-menu.conf.d.ts +3 -27
- package/dist/types/components/molecules/menu/mg-menu/mg-menu.d.ts +38 -30
- package/dist/types/components/molecules/menu/mg-menu-item/mg-menu-item.conf.d.ts +5 -0
- package/dist/types/components/molecules/menu/mg-menu-item/mg-menu-item.d.ts +69 -16
- package/dist/types/components/molecules/mg-item-more/mg-item-more.conf.d.ts +26 -0
- package/dist/types/components/molecules/mg-item-more/mg-item-more.d.ts +74 -0
- package/dist/types/components.d.ts +75 -17
- package/dist/types/utils/behaviors.utils.d.ts +12 -5
- package/dist/types/utils/components.utils.d.ts +2 -2
- package/dist/types/utils/unit.test.utils.d.ts +11 -0
- package/package.json +1 -1
- package/dist/mg-components/p-4cfd5423.entry.js +0 -1
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
.mg-menu-item.mg-menu-item--size-regular .mg-menu-item__navigation-button,
|
|
29
29
|
.mg-menu-item__navigation-button.mg-menu-item__navigation-button--size-regular {
|
|
30
30
|
padding: 1rem 2rem;
|
|
31
|
-
height:
|
|
31
|
+
height: 3.8rem;
|
|
32
32
|
}
|
|
33
33
|
.mg-menu-item.mg-menu-item--size-regular .mg-menu-item__navigation-button,
|
|
34
34
|
.mg-menu-item.mg-menu-item--size-regular .mg-menu-item__navigation-button ::slotted([slot=label]),
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
.mg-menu-item.mg-menu-item--size-medium .mg-menu-item__navigation-button,
|
|
51
51
|
.mg-menu-item__navigation-button.mg-menu-item__navigation-button--size-medium {
|
|
52
52
|
padding: 1rem 3rem;
|
|
53
|
-
height:
|
|
53
|
+
height: 5.1rem;
|
|
54
54
|
}
|
|
55
55
|
.mg-menu-item.mg-menu-item--size-medium .mg-menu-item__navigation-button,
|
|
56
56
|
.mg-menu-item.mg-menu-item--size-medium .mg-menu-item__navigation-button ::slotted([slot=label]),
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
.mg-menu-item.mg-menu-item--size-large .mg-menu-item__navigation-button,
|
|
73
73
|
.mg-menu-item__navigation-button.mg-menu-item__navigation-button--size-large {
|
|
74
74
|
padding: 1rem 4rem;
|
|
75
|
-
height:
|
|
75
|
+
height: 7.1rem;
|
|
76
76
|
}
|
|
77
77
|
.mg-menu-item.mg-menu-item--size-large .mg-menu-item__navigation-button,
|
|
78
78
|
.mg-menu-item.mg-menu-item--size-large .mg-menu-item__navigation-button ::slotted([slot=label]),
|
|
@@ -303,10 +303,12 @@
|
|
|
303
303
|
margin-left: auto;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
:host([data-style-direction-horizontal]) .mg-menu-item__collapse-container.mg-menu-item__collapse-container--first-level
|
|
306
|
+
:host([data-style-direction-horizontal]) .mg-menu-item__collapse-container.mg-menu-item__collapse-container--first-level,
|
|
307
|
+
:host([data-overflow-more]) .mg-menu-item__collapse-container.mg-menu-item__collapse-container--first-level {
|
|
307
308
|
background-color: hsl(var(--color-light));
|
|
308
309
|
}
|
|
309
|
-
:host([data-style-direction-horizontal]) .mg-menu-item__collapse-container.mg-menu-item__collapse-container--first-level ::slotted(mg-menu)
|
|
310
|
+
:host([data-style-direction-horizontal]) .mg-menu-item__collapse-container.mg-menu-item__collapse-container--first-level ::slotted(mg-menu),
|
|
311
|
+
:host([data-overflow-more]) .mg-menu-item__collapse-container.mg-menu-item__collapse-container--first-level ::slotted(mg-menu) {
|
|
310
312
|
padding: 1rem 0;
|
|
311
313
|
}
|
|
312
314
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { h, Host } from '@stencil/core';
|
|
2
|
-
import {
|
|
3
|
-
import { ClassList } from '../../../../utils/components.utils';
|
|
2
|
+
import { ClassList, createID } from '../../../../utils/components.utils';
|
|
4
3
|
import { initLocales } from '../../../../locales';
|
|
5
4
|
import { Direction } from '../mg-menu/mg-menu.conf';
|
|
6
5
|
import { Status } from './mg-menu-item.conf';
|
|
@@ -34,9 +33,91 @@ export class MgMenuItem {
|
|
|
34
33
|
* Is component contextual direction match the given direction
|
|
35
34
|
*
|
|
36
35
|
* @param {MgMenuItem['direction']} direction in parent menu
|
|
36
|
+
* @param {MgMenuItem['direction']} compareWith direction to compare with. Default: `this.direction`
|
|
37
37
|
* @returns {boolean} true is direction match the direction propertie
|
|
38
38
|
*/
|
|
39
|
-
this.isDirection = (direction
|
|
39
|
+
this.isDirection = (direction, compareWith = this.direction) => direction === compareWith;
|
|
40
|
+
/**
|
|
41
|
+
* Update displayNotificationBadge
|
|
42
|
+
* current component notification badge have priority over the slot badge when submenu contain badge
|
|
43
|
+
*
|
|
44
|
+
* @returns {void} update displayNotificationBadge value
|
|
45
|
+
*/
|
|
46
|
+
this.updateDisplayNotificationBadge = () => {
|
|
47
|
+
const childMenu = this.element.querySelector('mg-menu');
|
|
48
|
+
this.displayNotificationBadge =
|
|
49
|
+
childMenu !== null &&
|
|
50
|
+
Array.from(childMenu.children).some((subItem) => subItem.querySelector('mg-badge') !== null && subItem.getAttribute('hidden') === null);
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Method to control if one of component children have active status
|
|
54
|
+
*
|
|
55
|
+
* @returns {boolean} truthy if component has active child
|
|
56
|
+
*/
|
|
57
|
+
this.hasActiveChild = () => {
|
|
58
|
+
var _a;
|
|
59
|
+
return Array.from(((_a = this.element.querySelector('mg-menu')) === null || _a === void 0 ? void 0 : _a.children) || []).some((element) => element.nodeName === 'MG-MENU-ITEM' && this.hasStatus(element, Status.ACTIVE) && element.getAttribute('hidden') === null);
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Validate slots
|
|
63
|
+
*
|
|
64
|
+
* @param {boolean} guard prevent action whith guard. Default: false.
|
|
65
|
+
* @returns {void}
|
|
66
|
+
*/
|
|
67
|
+
this.validateSlot = (guard = false) => {
|
|
68
|
+
// slot title AND metadata validation
|
|
69
|
+
// add title on label AND metada slots due to text-overflow on these element
|
|
70
|
+
if (Array.from(this.element.children).find(child => child.getAttribute('slot') === 'label') === undefined)
|
|
71
|
+
throw new Error(`<${this.name}> slot "label" is required.`);
|
|
72
|
+
['label', 'metadata'].forEach(slot => {
|
|
73
|
+
Array.from(this.element.querySelectorAll(`[slot="${slot}"]`)).forEach(element => {
|
|
74
|
+
if (element.textContent.trim().length < 1)
|
|
75
|
+
throw new Error(`<${this.name}> slot "${slot}" must have text content.`);
|
|
76
|
+
if ((guard && element.getAttribute('title') === null) || !guard)
|
|
77
|
+
element.setAttribute('title', element.textContent);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Update status
|
|
83
|
+
*
|
|
84
|
+
* @param {Status[]} guard status to exclude from process in addition to [Status.HIDDEN, Status.DISABLED] . Default: [].
|
|
85
|
+
* @returns {void}
|
|
86
|
+
*/
|
|
87
|
+
this.updateStatus = (guard = []) => {
|
|
88
|
+
if (![Status.HIDDEN, Status.DISABLED, ...guard].includes(this.status)) {
|
|
89
|
+
this.status = this.hasActiveChild() ? Status.ACTIVE : Status.VISIBLE;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Init event-listeners
|
|
94
|
+
*
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
this.initListeners = () => {
|
|
98
|
+
var _a;
|
|
99
|
+
// manage first sub-level menu-items
|
|
100
|
+
Array.from(((_a = this.element.querySelector('mg-menu')) === null || _a === void 0 ? void 0 : _a.children) || []).forEach(item => {
|
|
101
|
+
if (item.nodeName === 'MG-MENU-ITEM') {
|
|
102
|
+
// manage child menu listener
|
|
103
|
+
item.addEventListener('status-change', () => {
|
|
104
|
+
this.updateStatus();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Get mg-popover identifier
|
|
111
|
+
*
|
|
112
|
+
* @returns {MgPopover['identifier']} generated mg-popover identifier
|
|
113
|
+
*/
|
|
114
|
+
this.getPopoverIdentifier = () => `${this.identifier}-popover`;
|
|
115
|
+
/**
|
|
116
|
+
* Condition to know if component should display a mg-popover
|
|
117
|
+
*
|
|
118
|
+
* @returns {boolean} truthy if component display popover
|
|
119
|
+
*/
|
|
120
|
+
this.displayPopover = () => this.isDirection(Direction.HORIZONTAL) && this.hasChildren && this.href === undefined;
|
|
40
121
|
/************
|
|
41
122
|
* Handlers *
|
|
42
123
|
************/
|
|
@@ -64,35 +145,13 @@ export class MgMenuItem {
|
|
|
64
145
|
this.handlePopoverDisplay = (event) => {
|
|
65
146
|
this.expanded = event.detail;
|
|
66
147
|
};
|
|
67
|
-
/**
|
|
68
|
-
* Update displayNotificationBadge
|
|
69
|
-
* current component notification badge have priority over the slot badge when submenu contain badge
|
|
70
|
-
*
|
|
71
|
-
* @returns {void} update displayNotificationBadge value
|
|
72
|
-
*/
|
|
73
|
-
this.updateDisplayNotificationBadge = () => {
|
|
74
|
-
const childMenu = this.element.querySelector('mg-menu');
|
|
75
|
-
this.displayNotificationBadge =
|
|
76
|
-
childMenu !== null &&
|
|
77
|
-
Array.from(childMenu.children).some((subItem) => subItem.querySelector('mg-badge') !== null && subItem.getAttribute('hidden') === null);
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* Method to control if one of component children have active status
|
|
81
|
-
*
|
|
82
|
-
* @returns {boolean} truthy if component has active child
|
|
83
|
-
*/
|
|
84
|
-
this.hasActiveChild = () => {
|
|
85
|
-
var _a;
|
|
86
|
-
return Array.from(((_a = this.element.querySelector('mg-menu')) === null || _a === void 0 ? void 0 : _a.children) || [])
|
|
87
|
-
.filter(element => element.nodeName === 'MG-MENU-ITEM')
|
|
88
|
-
.some((element) => this.hasStatus(element, Status.ACTIVE) && element.getAttribute('hidden') === null);
|
|
89
|
-
};
|
|
90
148
|
/**
|
|
91
149
|
* Render slot
|
|
92
150
|
*
|
|
93
151
|
* @returns {HTMLElement} HTML Element
|
|
94
152
|
*/
|
|
95
153
|
this.renderSlot = () => h("slot", null);
|
|
154
|
+
this.identifier = createID('mg-menu-item');
|
|
96
155
|
this.href = undefined;
|
|
97
156
|
this.status = Status.VISIBLE;
|
|
98
157
|
this.expanded = false;
|
|
@@ -100,6 +159,7 @@ export class MgMenuItem {
|
|
|
100
159
|
this.navigationButtonClassList = new ClassList([this.navigationButton]);
|
|
101
160
|
this.direction = undefined;
|
|
102
161
|
this.isInMainMenu = undefined;
|
|
162
|
+
this.isItemMore = undefined;
|
|
103
163
|
this.hasChildren = false;
|
|
104
164
|
this.displayNotificationBadge = undefined;
|
|
105
165
|
}
|
|
@@ -136,11 +196,33 @@ export class MgMenuItem {
|
|
|
136
196
|
this.navigationButtonClassList.delete(`${this.navigationButton}--size-${oldValue}`);
|
|
137
197
|
this.navigationButtonClassList.add(`${this.navigationButton}--size-${newValue}`);
|
|
138
198
|
}
|
|
199
|
+
validateDirection(newValue) {
|
|
200
|
+
// manage menu items style depending to parent menu horientation
|
|
201
|
+
this.element.setAttribute(`data-style-direction-${newValue}`, '');
|
|
202
|
+
this.navigationButtonClassList.add(`${this.navigationButton}--${newValue}`);
|
|
203
|
+
// manage all sub levels child menu-items level with data-level attribut
|
|
204
|
+
if (this.isDirection(Direction.VERTICAL, newValue)) {
|
|
205
|
+
Array.from(this.element.querySelectorAll('mg-menu-item')).forEach(item => {
|
|
206
|
+
item.dataset.level = `${(Number(item.dataset.level) || 1) + 1}`;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
139
210
|
validateHasChildren(newValue) {
|
|
140
211
|
if (newValue && this.element.href !== undefined) {
|
|
141
212
|
throw new Error(`<${this.name}> prop "href" is unauthorizied when element is a parent.`);
|
|
142
213
|
}
|
|
143
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Render popover clickoutside guard for content slot
|
|
217
|
+
*
|
|
218
|
+
* @returns {void}
|
|
219
|
+
*/
|
|
220
|
+
updatePopoverGuard() {
|
|
221
|
+
if (this.displayPopover())
|
|
222
|
+
Array.from(this.element.children)
|
|
223
|
+
.filter((child) => child.getAttribute('slot') === null && child.nodeName !== 'MG-MENU' && Boolean(child.dataset))
|
|
224
|
+
.forEach((slot) => (slot.dataset.mgPopoverGuard = this.getPopoverIdentifier()));
|
|
225
|
+
}
|
|
144
226
|
/*************
|
|
145
227
|
* Lifecycle *
|
|
146
228
|
*************/
|
|
@@ -153,11 +235,13 @@ export class MgMenuItem {
|
|
|
153
235
|
// has children items that is NOT [slot='image' | 'information' | 'label' | 'metadata'] element
|
|
154
236
|
// we store only matching elements
|
|
155
237
|
this.hasChildren = Array.from(this.element.children).some(child => !['image', 'information', 'label', 'metadata'].includes(child.getAttribute('slot')));
|
|
238
|
+
this.badgeLabel = initLocales(this.element).messages.plusMenu.badgeLabel;
|
|
239
|
+
this.isItemMore = this.element.dataset.overflowMore !== undefined;
|
|
156
240
|
// Validate props
|
|
157
|
-
this.validateSize(this.size);
|
|
158
241
|
this.validateStatus(this.status);
|
|
159
242
|
this.validateExpanded(this.expanded);
|
|
160
|
-
|
|
243
|
+
// Validate states
|
|
244
|
+
this.validateSize(this.size);
|
|
161
245
|
}
|
|
162
246
|
/**
|
|
163
247
|
* Check if component slots configuration
|
|
@@ -165,63 +249,38 @@ export class MgMenuItem {
|
|
|
165
249
|
* @returns {ReturnType<typeof setTimeout>} timeout
|
|
166
250
|
*/
|
|
167
251
|
componentDidLoad() {
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
if (Array.from(this.element.children).find(child => child.getAttribute('slot') === 'label') === undefined)
|
|
171
|
-
throw new Error(`<${this.name}> slot "label" is required.`);
|
|
172
|
-
['label', 'metadata'].forEach(slot => {
|
|
173
|
-
Array.from(this.element.querySelectorAll(`[slot="${slot}"]`)).forEach(element => {
|
|
174
|
-
if (element.textContent.trim().length < 1)
|
|
175
|
-
throw new Error(`<${this.name}> slot "${slot}" must have text content.`);
|
|
176
|
-
if (element.getAttribute('title') === null)
|
|
177
|
-
element.setAttribute('title', element.textContent);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
252
|
+
// validation
|
|
253
|
+
this.validateSlot(true);
|
|
180
254
|
// update props and states after componentDidLoad hook
|
|
181
255
|
// return a promise to process action only in the FIRST render().
|
|
182
256
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
183
257
|
return setTimeout(() => {
|
|
184
|
-
var _a;
|
|
185
258
|
// define menu-item context states
|
|
186
259
|
const menu = this.element.closest('mg-menu');
|
|
187
|
-
this.direction = this.
|
|
188
|
-
this.
|
|
189
|
-
|
|
260
|
+
this.direction = this.isItemMore || menu === null ? Direction.HORIZONTAL : menu.direction;
|
|
261
|
+
this.isInMainMenu = menu !== null && this.element.parentElement.closest('mg-menu-item') === null;
|
|
262
|
+
if ((menu === null || menu === void 0 ? void 0 : menu.size) !== undefined)
|
|
263
|
+
this.size = menu.size;
|
|
264
|
+
if (this.isItemMore)
|
|
265
|
+
this.size = this.element.dataset.size;
|
|
190
266
|
// when main menu item contain an active item it will get the active style
|
|
191
267
|
// AND if item is in vertical menu it will be expanded
|
|
192
|
-
if (this.hasActiveChild())
|
|
193
|
-
this.
|
|
194
|
-
|
|
195
|
-
this.expanded = this.isDirection(Direction.VERTICAL);
|
|
196
|
-
}
|
|
197
|
-
// manage menu items style depending to parent menu horientation
|
|
198
|
-
this.element.setAttribute(`data-style-direction-${this.direction}`, '');
|
|
199
|
-
this.navigationButtonClassList.add(`${this.navigationButton}--${this.direction}`);
|
|
268
|
+
if (this.hasActiveChild() && this.isInMainMenu)
|
|
269
|
+
this.expanded = this.isDirection(Direction.VERTICAL);
|
|
270
|
+
this.updateStatus([Status.ACTIVE]);
|
|
200
271
|
this.updateDisplayNotificationBadge();
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
// manage child menu listener
|
|
216
|
-
item.addEventListener('status-change', () => {
|
|
217
|
-
updateStatus();
|
|
218
|
-
});
|
|
219
|
-
new MutationObserver(mutationsList => {
|
|
220
|
-
if (mutationsList.some(mutation => mutation.attributeName === 'hidden'))
|
|
221
|
-
updateStatus();
|
|
222
|
-
this.updateDisplayNotificationBadge();
|
|
223
|
-
}).observe(item, { attributes: true });
|
|
224
|
-
});
|
|
272
|
+
this.updatePopoverGuard();
|
|
273
|
+
// manage child dom changes with mutationObserver and listzners
|
|
274
|
+
this.initListeners();
|
|
275
|
+
// emit loaded event when component is fully loaded
|
|
276
|
+
this.itemLoaded.emit();
|
|
277
|
+
new MutationObserver(mutationsList => {
|
|
278
|
+
if (mutationsList.some(mutation => mutation.attributeName === 'hidden'))
|
|
279
|
+
this.updateStatus();
|
|
280
|
+
if (mutationsList.some(mutation => mutation.type === 'characterData'))
|
|
281
|
+
this.validateSlot();
|
|
282
|
+
this.updateDisplayNotificationBadge();
|
|
283
|
+
}).observe(this.element, { attributes: true, childList: true, characterData: true, subtree: true });
|
|
225
284
|
}, 0);
|
|
226
285
|
}
|
|
227
286
|
/**
|
|
@@ -245,9 +304,9 @@ export class MgMenuItem {
|
|
|
245
304
|
render() {
|
|
246
305
|
const getContainerClasses = () => ({
|
|
247
306
|
[`${this.name}__collapse-container`]: true,
|
|
248
|
-
[`${this.name}__collapse-container--first-level`]: this.isInMainMenu && this.isDirection(Direction.HORIZONTAL),
|
|
307
|
+
[`${this.name}__collapse-container--first-level`]: (this.isInMainMenu || this.isItemMore) && this.isDirection(Direction.HORIZONTAL),
|
|
249
308
|
});
|
|
250
|
-
return (h(Host, { role:
|
|
309
|
+
return (h(Host, { role: !this.isItemMore && 'menuitem', "aria-haspopup": !this.isItemMore && this.hasChildren.toString() }, this.displayPopover() ? (h("mg-popover", { display: this.expanded, placement: "bottom-start", arrowHide: true, "onDisplay-change": this.handlePopoverDisplay, identifier: this.getPopoverIdentifier() }, this.renderInteractiveElement(), h("div", { class: getContainerClasses(), slot: "content" }, this.renderSlot()))) : ([
|
|
251
310
|
this.renderInteractiveElement(),
|
|
252
311
|
h("div", { key: "vertical-container", class: getContainerClasses(), hidden: !this.expanded }, this.renderSlot()),
|
|
253
312
|
])));
|
|
@@ -266,6 +325,24 @@ export class MgMenuItem {
|
|
|
266
325
|
}
|
|
267
326
|
static get properties() {
|
|
268
327
|
return {
|
|
328
|
+
"identifier": {
|
|
329
|
+
"type": "string",
|
|
330
|
+
"mutable": false,
|
|
331
|
+
"complexType": {
|
|
332
|
+
"original": "string",
|
|
333
|
+
"resolved": "string",
|
|
334
|
+
"references": {}
|
|
335
|
+
},
|
|
336
|
+
"required": false,
|
|
337
|
+
"optional": false,
|
|
338
|
+
"docs": {
|
|
339
|
+
"tags": [],
|
|
340
|
+
"text": "Identifier is used to control mg-popover\nDefault: createID('mg-menu-item');"
|
|
341
|
+
},
|
|
342
|
+
"attribute": "identifier",
|
|
343
|
+
"reflect": false,
|
|
344
|
+
"defaultValue": "createID('mg-menu-item')"
|
|
345
|
+
},
|
|
269
346
|
"href": {
|
|
270
347
|
"type": "string",
|
|
271
348
|
"mutable": false,
|
|
@@ -332,6 +409,7 @@ export class MgMenuItem {
|
|
|
332
409
|
"navigationButtonClassList": {},
|
|
333
410
|
"direction": {},
|
|
334
411
|
"isInMainMenu": {},
|
|
412
|
+
"isItemMore": {},
|
|
335
413
|
"hasChildren": {},
|
|
336
414
|
"displayNotificationBadge": {}
|
|
337
415
|
};
|
|
@@ -356,6 +434,21 @@ export class MgMenuItem {
|
|
|
356
434
|
}
|
|
357
435
|
}
|
|
358
436
|
}
|
|
437
|
+
}, {
|
|
438
|
+
"method": "itemLoaded",
|
|
439
|
+
"name": "item-loaded",
|
|
440
|
+
"bubbles": true,
|
|
441
|
+
"cancelable": true,
|
|
442
|
+
"composed": true,
|
|
443
|
+
"docs": {
|
|
444
|
+
"tags": [],
|
|
445
|
+
"text": "Emited event when item is loaded"
|
|
446
|
+
},
|
|
447
|
+
"complexType": {
|
|
448
|
+
"original": "void",
|
|
449
|
+
"resolved": "void",
|
|
450
|
+
"references": {}
|
|
451
|
+
}
|
|
359
452
|
}];
|
|
360
453
|
}
|
|
361
454
|
static get elementRef() { return "element"; }
|
|
@@ -369,6 +462,9 @@ export class MgMenuItem {
|
|
|
369
462
|
}, {
|
|
370
463
|
"propName": "size",
|
|
371
464
|
"methodName": "validateSize"
|
|
465
|
+
}, {
|
|
466
|
+
"propName": "direction",
|
|
467
|
+
"methodName": "validateDirection"
|
|
372
468
|
}, {
|
|
373
469
|
"propName": "hasChildren",
|
|
374
470
|
"methodName": "validateHasChildren"
|
|
@@ -141,7 +141,7 @@ export class MgForm {
|
|
|
141
141
|
// submit buttons should trigger form submition;
|
|
142
142
|
if (['submit', null].includes(mgButton.getAttribute('type'))) {
|
|
143
143
|
mgButton.addEventListener('click', () => {
|
|
144
|
-
this.form.dispatchEvent(new
|
|
144
|
+
this.form.dispatchEvent(new SubmitEvent('submit', { bubbles: true }));
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
147
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A11Y
|
|
3
|
+
*/
|
|
4
|
+
.sr-only {
|
|
5
|
+
border: 0 !important;
|
|
6
|
+
clip: rect(1px, 1px, 1px, 1px) !important;
|
|
7
|
+
-webkit-clip-path: inset(50%) !important;
|
|
8
|
+
clip-path: inset(50%) !important;
|
|
9
|
+
height: 1px !important;
|
|
10
|
+
margin: -1px !important;
|
|
11
|
+
overflow: hidden !important;
|
|
12
|
+
padding: 0 !important;
|
|
13
|
+
position: absolute !important;
|
|
14
|
+
width: 1px !important;
|
|
15
|
+
white-space: nowrap !important;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
*:focus:not(:focus-visible) {
|
|
19
|
+
outline: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@media (prefers-reduced-motion) {
|
|
23
|
+
.mg-a11y-animation {
|
|
24
|
+
animation: none !important;
|
|
25
|
+
transition: none !important;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
:host {
|
|
29
|
+
display: flex;
|
|
30
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { h, Host } from '@stencil/core';
|
|
2
|
+
import { initLocales } from '../../../locales';
|
|
3
|
+
import { OverflowBehavior } from '../../../utils/behaviors.utils';
|
|
4
|
+
import { Direction } from '../menu/mg-menu/mg-menu.conf';
|
|
5
|
+
export class MgItemMore {
|
|
6
|
+
constructor() {
|
|
7
|
+
/************
|
|
8
|
+
* Internal *
|
|
9
|
+
************/
|
|
10
|
+
this.name = 'mg-item-more';
|
|
11
|
+
/***********
|
|
12
|
+
* Methods *
|
|
13
|
+
***********/
|
|
14
|
+
/**
|
|
15
|
+
* render mg-item-more overflow element
|
|
16
|
+
*
|
|
17
|
+
* @returns {HTMLMgItemMoreElement} mg-item-more element
|
|
18
|
+
*/
|
|
19
|
+
this.renderMgMenuItemOverflowElement = () => {
|
|
20
|
+
// create menu items proxy element from item clones
|
|
21
|
+
const moreElementMenuItem = this.element.shadowRoot.querySelector('mg-menu-item');
|
|
22
|
+
this.menuItems.forEach((child) => {
|
|
23
|
+
moreElementMenuItem.querySelector('mg-menu').appendChild(child.cloneNode(true));
|
|
24
|
+
});
|
|
25
|
+
const allMenuItem = Array.from(this.parentMenu.querySelectorAll('mg-menu-item:not([data-overflow-more])'));
|
|
26
|
+
Array.from(moreElementMenuItem.querySelectorAll('mg-menu-item:not([data-overflow-more])')).forEach((proxy, index) => {
|
|
27
|
+
// manage click on proxy to mirror it on initial element
|
|
28
|
+
proxy.addEventListener('click', () => {
|
|
29
|
+
(allMenuItem[index].shadowRoot.querySelector('a') || allMenuItem[index].shadowRoot.querySelector('button')).dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
30
|
+
});
|
|
31
|
+
// add id suffix to prevent duplicate key. default html id is: '';
|
|
32
|
+
if (proxy.id.trim() !== '')
|
|
33
|
+
proxy.id = `${proxy.id}-proxy`;
|
|
34
|
+
// manage status change miror in proxy
|
|
35
|
+
allMenuItem[index].addEventListener('status-change', (event) => {
|
|
36
|
+
proxy.setAttribute('status', event.detail);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
return this.element;
|
|
40
|
+
};
|
|
41
|
+
this.icon = { icon: 'ellipsis-vertical' };
|
|
42
|
+
this.slotlabel = { display: false };
|
|
43
|
+
this.size = undefined;
|
|
44
|
+
this.parentMenu = undefined;
|
|
45
|
+
}
|
|
46
|
+
validateIcon(newValue) {
|
|
47
|
+
if (typeof newValue !== 'object' || (typeof newValue === 'object' && typeof newValue.icon !== 'string'))
|
|
48
|
+
throw new Error(`<${this.name}> prop "icon" must match MgItemMore['icon'] type.`);
|
|
49
|
+
}
|
|
50
|
+
validateSlotLabel(newValue) {
|
|
51
|
+
if (typeof newValue !== 'object' || (typeof newValue === 'object' && typeof newValue.display !== 'boolean'))
|
|
52
|
+
throw new Error(`<${this.name}> prop "slotlabel" must match MgItemMore['slotlabel'] type.`);
|
|
53
|
+
else if (typeof newValue.label !== 'string')
|
|
54
|
+
this.slotlabel.label = this.messages.moreLabel;
|
|
55
|
+
}
|
|
56
|
+
validateSize(newValue) {
|
|
57
|
+
if (newValue && typeof newValue !== 'string')
|
|
58
|
+
throw new Error(`<${this.name}> prop "size" must match MgItemMore['size'] type.`);
|
|
59
|
+
}
|
|
60
|
+
/*************
|
|
61
|
+
* Lifecycle *
|
|
62
|
+
*************/
|
|
63
|
+
/**
|
|
64
|
+
* Disconnect overflow ResizeObserver
|
|
65
|
+
*
|
|
66
|
+
* @returns {void} run overflow resize obeserver disconnexion
|
|
67
|
+
*/
|
|
68
|
+
disconnectedCallback() {
|
|
69
|
+
this.overflowBehavior.disconnect();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Set variables and validate props
|
|
73
|
+
*
|
|
74
|
+
* @returns {void}
|
|
75
|
+
*/
|
|
76
|
+
componentWillLoad() {
|
|
77
|
+
// init variables
|
|
78
|
+
this.messages = initLocales(this.element).messages.plusMenu;
|
|
79
|
+
this.parentMenu = this.element.closest('mg-menu');
|
|
80
|
+
this.menuItems = Array.from(this.parentMenu.children).filter(item => item.nodeName === 'MG-MENU-ITEM');
|
|
81
|
+
// validate props
|
|
82
|
+
this.validateIcon(this.icon);
|
|
83
|
+
this.validateSlotLabel(this.slotlabel);
|
|
84
|
+
this.validateSize(this.size);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Add overflow behavior
|
|
88
|
+
*
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
91
|
+
componentDidLoad() {
|
|
92
|
+
this.overflowBehavior = new OverflowBehavior(this.parentMenu, this.renderMgMenuItemOverflowElement);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Render
|
|
96
|
+
*
|
|
97
|
+
* @returns {HTMLElement} HTML Element
|
|
98
|
+
*/
|
|
99
|
+
render() {
|
|
100
|
+
return (h(Host, { role: "menuitem", "aria-haspopup": "true" }, h("mg-menu-item", { "data-overflow-more": true, "data-size": this.parentMenu.size }, h("mg-icon", { icon: this.icon.icon, slot: "image" }), h("span", { class: { 'sr-only': !this.slotlabel.display }, slot: "label" }, this.slotlabel.label), h("mg-menu", { direction: Direction.VERTICAL, label: this.messages.moreLabel, size: this.size }))));
|
|
101
|
+
}
|
|
102
|
+
static get is() { return "mg-item-more"; }
|
|
103
|
+
static get encapsulation() { return "shadow"; }
|
|
104
|
+
static get originalStyleUrls() {
|
|
105
|
+
return {
|
|
106
|
+
"$": ["mg-item-more.scss"]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
static get styleUrls() {
|
|
110
|
+
return {
|
|
111
|
+
"$": ["mg-item-more.css"]
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
static get properties() {
|
|
115
|
+
return {
|
|
116
|
+
"icon": {
|
|
117
|
+
"type": "unknown",
|
|
118
|
+
"mutable": false,
|
|
119
|
+
"complexType": {
|
|
120
|
+
"original": "IconType",
|
|
121
|
+
"resolved": "{ icon: string; }",
|
|
122
|
+
"references": {
|
|
123
|
+
"IconType": {
|
|
124
|
+
"location": "import",
|
|
125
|
+
"path": "./mg-item-more.conf"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"required": false,
|
|
130
|
+
"optional": false,
|
|
131
|
+
"docs": {
|
|
132
|
+
"tags": [],
|
|
133
|
+
"text": "Define icon\nDefault: {icon: 'ellipsis-vertical'}"
|
|
134
|
+
},
|
|
135
|
+
"defaultValue": "{ icon: 'ellipsis-vertical' }"
|
|
136
|
+
},
|
|
137
|
+
"slotlabel": {
|
|
138
|
+
"type": "unknown",
|
|
139
|
+
"mutable": false,
|
|
140
|
+
"complexType": {
|
|
141
|
+
"original": "SlotLabelType",
|
|
142
|
+
"resolved": "{ label?: string; display?: boolean; }",
|
|
143
|
+
"references": {
|
|
144
|
+
"SlotLabelType": {
|
|
145
|
+
"location": "import",
|
|
146
|
+
"path": "./mg-item-more.conf"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"required": false,
|
|
151
|
+
"optional": false,
|
|
152
|
+
"docs": {
|
|
153
|
+
"tags": [],
|
|
154
|
+
"text": "Define slot label element\nDefault: {display: false}"
|
|
155
|
+
},
|
|
156
|
+
"defaultValue": "{ display: false }"
|
|
157
|
+
},
|
|
158
|
+
"size": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"mutable": false,
|
|
161
|
+
"complexType": {
|
|
162
|
+
"original": "SizeType",
|
|
163
|
+
"resolved": "\"large\" | \"medium\" | \"regular\"",
|
|
164
|
+
"references": {
|
|
165
|
+
"SizeType": {
|
|
166
|
+
"location": "import",
|
|
167
|
+
"path": "./mg-item-more.conf"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
"required": false,
|
|
172
|
+
"optional": false,
|
|
173
|
+
"docs": {
|
|
174
|
+
"tags": [],
|
|
175
|
+
"text": "Define component child menu size."
|
|
176
|
+
},
|
|
177
|
+
"attribute": "size",
|
|
178
|
+
"reflect": false
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
static get states() {
|
|
183
|
+
return {
|
|
184
|
+
"parentMenu": {}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
static get elementRef() { return "element"; }
|
|
188
|
+
static get watchers() {
|
|
189
|
+
return [{
|
|
190
|
+
"propName": "icon",
|
|
191
|
+
"methodName": "validateIcon"
|
|
192
|
+
}, {
|
|
193
|
+
"propName": "slotlabel",
|
|
194
|
+
"methodName": "validateSlotLabel"
|
|
195
|
+
}, {
|
|
196
|
+
"propName": "size",
|
|
197
|
+
"methodName": "validateSize"
|
|
198
|
+
}];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
.mg-tabs.mg-tabs--size-regular .mg-tabs__navigation-button,
|
|
2
2
|
.mg-tabs__navigation-button.mg-tabs__navigation-button--size-regular {
|
|
3
3
|
padding: 1rem 2rem;
|
|
4
|
-
height: calc();
|
|
5
4
|
}
|
|
6
5
|
.mg-tabs.mg-tabs--size-regular .mg-tabs__navigation-button,
|
|
7
6
|
.mg-tabs.mg-tabs--size-regular .mg-tabs__navigation-button ::slotted([slot=label]),
|
|
@@ -23,7 +22,6 @@
|
|
|
23
22
|
.mg-tabs.mg-tabs--size-large .mg-tabs__navigation-button,
|
|
24
23
|
.mg-tabs__navigation-button.mg-tabs__navigation-button--size-large {
|
|
25
24
|
padding: 1.5rem 3rem;
|
|
26
|
-
height: calc();
|
|
27
25
|
}
|
|
28
26
|
.mg-tabs.mg-tabs--size-large .mg-tabs__navigation-button,
|
|
29
27
|
.mg-tabs.mg-tabs--size-large .mg-tabs__navigation-button ::slotted([slot=label]),
|
|
@@ -9,7 +9,7 @@ $navigation-button-column-gap: 1rem;
|
|
|
9
9
|
.#{$element}.#{$element}--size-#{$name} .#{$element}__navigation-button,
|
|
10
10
|
.#{$element}__navigation-button.#{$element}__navigation-button--size-#{$name} {
|
|
11
11
|
padding: #{map.get($size, 'vertical')} #{map.get($size, 'horizontal')};
|
|
12
|
-
height:
|
|
12
|
+
height: #{map.get($size, 'height')};
|
|
13
13
|
&,
|
|
14
14
|
::slotted([slot='label']),
|
|
15
15
|
::slotted([slot='metadata']) {
|