@mgdis/mg-components 5.8.0 → 5.8.2
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 +2 -2
- package/dist/cjs/mg-action-more_31.cjs.entry.js +148 -48
- package/dist/cjs/mg-components.cjs.js +2 -2
- package/dist/cjs/mg-item-more.cjs.entry.js +3 -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.js +52 -20
- package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.css +4 -2
- package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.js +18 -1
- package/dist/collection/components/molecules/mg-form/mg-form.js +1 -1
- package/dist/collection/components/molecules/mg-item-more/mg-item-more.js +2 -1
- 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/mg-form.js +1 -1
- package/dist/components/mg-input-checkbox.js +5 -4
- package/dist/components/mg-input-select2.js +83 -17
- package/dist/components/mg-item-more.js +2 -1
- package/dist/components/mg-menu-item2.js +5 -2
- package/dist/components/mg-menu2.js +52 -20
- package/dist/esm/loader.js +3 -3
- package/dist/esm/mg-action-more_31.entry.js +148 -48
- package/dist/esm/mg-components.js +3 -3
- package/dist/esm/mg-item-more.entry.js +3 -2
- package/dist/mg-components/mg-components.esm.js +1 -1
- package/dist/mg-components/p-0b68c4b4.entry.js +1 -0
- package/dist/mg-components/{p-1221773c.entry.js → p-67ce7cb8.entry.js} +1 -1
- 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.d.ts +31 -5
- package/dist/types/components/molecules/menu/mg-menu-item/mg-menu-item.d.ts +4 -0
- package/dist/types/components.d.ts +11 -7
- package/dist/types/utils/components.utils.d.ts +2 -2
- package/dist/types/utils/unit.test.utils.d.ts +11 -0
- package/package.json +9 -14
- package/dist/mg-components/p-6aeded97.entry.js +0 -1
- /package/dist/cjs/{index-5e7ede97.js → index-9e1091ab.js} +0 -0
- /package/dist/esm/{index-03cceb11.js → index-3249671d.js} +0 -0
- /package/dist/mg-components/{p-e126dd84.js → p-8fbc0d87.js} +0 -0
|
@@ -6,10 +6,11 @@ import { initLocales } from '../../../../locales';
|
|
|
6
6
|
/**
|
|
7
7
|
* type CheckboxItem validation function
|
|
8
8
|
*
|
|
9
|
-
* @param {
|
|
10
|
-
* @returns {boolean} match item
|
|
9
|
+
* @param {unknown} items Checkbox item
|
|
10
|
+
* @returns {boolean} match item type
|
|
11
11
|
*/
|
|
12
|
-
const
|
|
12
|
+
const isCheckboxItems = (items) => Array.isArray(items) &&
|
|
13
|
+
items.every(item => typeof item === 'object' && typeof item.title === 'string' && (item.value === null || typeof item.value === 'boolean') && item.value !== undefined);
|
|
13
14
|
export class MgInputCheckbox {
|
|
14
15
|
constructor() {
|
|
15
16
|
/************
|
|
@@ -87,7 +88,7 @@ export class MgInputCheckbox {
|
|
|
87
88
|
this.checkboxItems = [];
|
|
88
89
|
}
|
|
89
90
|
validateValue(newValue) {
|
|
90
|
-
if (newValue
|
|
91
|
+
if (isCheckboxItems(newValue)) {
|
|
91
92
|
this.checkboxItems = newValue.map((item, index) => ({
|
|
92
93
|
id: `${this.identifier}_${index.toString()}`,
|
|
93
94
|
title: item.title,
|
|
@@ -437,12 +438,11 @@ export class MgInputCheckbox {
|
|
|
437
438
|
"text": "Emitted event when value change"
|
|
438
439
|
},
|
|
439
440
|
"complexType": {
|
|
440
|
-
"original": "
|
|
441
|
+
"original": "MgInputCheckbox['value']",
|
|
441
442
|
"resolved": "CheckboxValue[]",
|
|
442
443
|
"references": {
|
|
443
|
-
"
|
|
444
|
-
"location": "
|
|
445
|
-
"path": "./mg-input-checkbox.conf"
|
|
444
|
+
"MgInputCheckbox": {
|
|
445
|
+
"location": "global"
|
|
446
446
|
}
|
|
447
447
|
}
|
|
448
448
|
}
|
|
@@ -457,9 +457,13 @@ export class MgInputCheckbox {
|
|
|
457
457
|
"text": "Emited event when checking validity"
|
|
458
458
|
},
|
|
459
459
|
"complexType": {
|
|
460
|
-
"original": "
|
|
460
|
+
"original": "MgInputCheckbox['valid']",
|
|
461
461
|
"resolved": "boolean",
|
|
462
|
-
"references": {
|
|
462
|
+
"references": {
|
|
463
|
+
"MgInputCheckbox": {
|
|
464
|
+
"location": "global"
|
|
465
|
+
}
|
|
466
|
+
}
|
|
463
467
|
}
|
|
464
468
|
}];
|
|
465
469
|
}
|
|
@@ -7,10 +7,24 @@ import { initLocales } from '../../../../locales';
|
|
|
7
7
|
/**
|
|
8
8
|
* Check if item is a well configured option
|
|
9
9
|
*
|
|
10
|
-
* @param {
|
|
10
|
+
* @param {unknown} option select option
|
|
11
11
|
* @returns {boolean} select option type is valid
|
|
12
12
|
*/
|
|
13
13
|
const isOption = (option) => typeof option === 'object' && typeof option.title === 'string';
|
|
14
|
+
/**
|
|
15
|
+
* Check if items[] is SelectOption
|
|
16
|
+
*
|
|
17
|
+
* @param {unknown[]} items select option
|
|
18
|
+
* @returns {boolean} select option array type is valid
|
|
19
|
+
*/
|
|
20
|
+
const allItemsAreOptions = (items) => Array.isArray(items) && items.every(item => isOption(item));
|
|
21
|
+
/**
|
|
22
|
+
* Check if item is a well configured optgroup
|
|
23
|
+
*
|
|
24
|
+
* @param {unknown} optgroup select option
|
|
25
|
+
* @returns {boolean} select optgroup type is valid
|
|
26
|
+
*/
|
|
27
|
+
const isOptGroup = (optgroup) => typeof optgroup === 'object' && typeof optgroup.group === 'string' && allItemsAreOptions(optgroup.options);
|
|
14
28
|
/**
|
|
15
29
|
* Group options
|
|
16
30
|
*
|
|
@@ -46,17 +60,50 @@ export class MgInputSelect {
|
|
|
46
60
|
this.hasDisplayedError = false;
|
|
47
61
|
/**
|
|
48
62
|
* Handle input event
|
|
63
|
+
*
|
|
64
|
+
* @returns {void}
|
|
49
65
|
*/
|
|
50
66
|
this.handleInput = () => {
|
|
51
|
-
this.
|
|
52
|
-
if (this.hasDisplayedError)
|
|
67
|
+
this.updateValue();
|
|
68
|
+
if (this.hasDisplayedError)
|
|
53
69
|
this.setErrorMessage();
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Method to compare item.title with input.value
|
|
73
|
+
*
|
|
74
|
+
* @param {SelectOption} item item to compare with
|
|
75
|
+
* @returns {boolean} truthy if input.value is an item
|
|
76
|
+
*/
|
|
77
|
+
this.isInputValue = (item) => { var _a; return item.title === ((_a = this.input) === null || _a === void 0 ? void 0 : _a.value); };
|
|
78
|
+
/**
|
|
79
|
+
* value props setter
|
|
80
|
+
*
|
|
81
|
+
* @param {MgInputSelect['value']} newValue value to update with
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*/
|
|
84
|
+
this.setValue = (newValue) => {
|
|
85
|
+
this.checkValidity();
|
|
86
|
+
this.value = newValue;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Update value from input.value
|
|
90
|
+
*
|
|
91
|
+
* @returns {void}
|
|
92
|
+
*/
|
|
93
|
+
this.updateValue = () => {
|
|
94
|
+
if (this.input.value === '') {
|
|
95
|
+
this.setValue(null);
|
|
54
96
|
}
|
|
55
|
-
if (this.input.value
|
|
56
|
-
this.
|
|
97
|
+
else if (allItemsAreString(this.items) && this.items.includes(this.input.value)) {
|
|
98
|
+
this.setValue(this.input.value);
|
|
99
|
+
}
|
|
100
|
+
else if (allItemsAreOptions(this.items) && typeof this.input.value === 'string' && this.items.some(this.isInputValue)) {
|
|
101
|
+
this.setValue(this.items.find(this.isInputValue).value);
|
|
57
102
|
}
|
|
58
103
|
else {
|
|
59
|
-
|
|
104
|
+
// before set newValue with push to options[] the unknown input.value with a disable satus
|
|
105
|
+
this.options.push({ title: this.input.value, value: this.input.value, disabled: true });
|
|
106
|
+
this.setValue(this.input.value);
|
|
60
107
|
}
|
|
61
108
|
};
|
|
62
109
|
/**
|
|
@@ -65,12 +112,18 @@ export class MgInputSelect {
|
|
|
65
112
|
this.handleBlur = () => {
|
|
66
113
|
this.displayError();
|
|
67
114
|
};
|
|
115
|
+
/**
|
|
116
|
+
* Input value is disabled
|
|
117
|
+
*
|
|
118
|
+
* @returns {boolean} truthy if input value is disabled
|
|
119
|
+
*/
|
|
120
|
+
this.isDisabledValue = () => { var _a; return allItemsAreOptions(this.options) && ((_a = this.options.find(this.isInputValue)) === null || _a === void 0 ? void 0 : _a.disabled) === true; };
|
|
68
121
|
/**
|
|
69
122
|
* Check if input is valid
|
|
70
123
|
*/
|
|
71
124
|
this.checkValidity = () => {
|
|
72
125
|
var _a;
|
|
73
|
-
this.valid = this.readonly || this.disabled || (((_a = this.input) === null || _a === void 0 ? void 0 : _a.checkValidity) !== undefined ? this.input.checkValidity() : true);
|
|
126
|
+
this.valid = !this.isDisabledValue() && (this.readonly || this.disabled || (((_a = this.input) === null || _a === void 0 ? void 0 : _a.checkValidity) !== undefined ? this.input.checkValidity() : true));
|
|
74
127
|
this.invalid = !this.valid;
|
|
75
128
|
// We need to send valid event even if it is the same value
|
|
76
129
|
this.inputValid.emit(this.valid);
|
|
@@ -85,6 +138,13 @@ export class MgInputSelect {
|
|
|
85
138
|
this.errorMessage = this.messages.errors.required;
|
|
86
139
|
}
|
|
87
140
|
};
|
|
141
|
+
/**
|
|
142
|
+
* Render option
|
|
143
|
+
*
|
|
144
|
+
* @param {SelectOption} option to render
|
|
145
|
+
* @returns {HTMLElement} render option
|
|
146
|
+
*/
|
|
147
|
+
this.renderOption = (option) => (h("option", { key: option.title, value: option.title, selected: JSON.stringify(this.value) === JSON.stringify(option.value), disabled: option.disabled }, option.title));
|
|
88
148
|
this.value = undefined;
|
|
89
149
|
this.items = undefined;
|
|
90
150
|
this.identifier = undefined;
|
|
@@ -109,9 +169,13 @@ export class MgInputSelect {
|
|
|
109
169
|
this.valueExist = undefined;
|
|
110
170
|
this.readonlyValue = undefined;
|
|
111
171
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
172
|
+
validateValue(newValue) {
|
|
173
|
+
var _a, _b;
|
|
174
|
+
if (allItemsAreString(this.items) && typeof newValue === 'string') {
|
|
175
|
+
this.readonlyValue = Boolean((_a = this.input) === null || _a === void 0 ? void 0 : _a.value) ? this.input.value : newValue;
|
|
176
|
+
}
|
|
177
|
+
else if (allItemsAreOptions(this.items)) {
|
|
178
|
+
this.readonlyValue = (_b = this.items.find(item => item.value === newValue)) === null || _b === void 0 ? void 0 : _b.title;
|
|
115
179
|
}
|
|
116
180
|
else {
|
|
117
181
|
this.readonlyValue = null;
|
|
@@ -125,14 +189,15 @@ export class MgInputSelect {
|
|
|
125
189
|
}
|
|
126
190
|
// String array
|
|
127
191
|
else if (allItemsAreString(newValue)) {
|
|
128
|
-
|
|
129
|
-
|
|
192
|
+
if (typeof this.value === 'string')
|
|
193
|
+
this.valueExist = newValue.includes(this.value);
|
|
194
|
+
this.options = newValue.map(item => ({ title: item, value: item }));
|
|
130
195
|
}
|
|
131
196
|
// Object array
|
|
132
|
-
else if (newValue
|
|
197
|
+
else if (allItemsAreOptions(newValue)) {
|
|
133
198
|
this.valueExist = newValue.map(item => item.value).includes(this.value);
|
|
134
199
|
// Grouped object options
|
|
135
|
-
if (newValue.some(item => item.group
|
|
200
|
+
if (newValue.some(item => Boolean(item.group))) {
|
|
136
201
|
this.options = newValue.reduce(groupOptions, []);
|
|
137
202
|
}
|
|
138
203
|
// Standart object options
|
|
@@ -177,6 +242,7 @@ export class MgInputSelect {
|
|
|
177
242
|
this.messages = initLocales(this.element).messages;
|
|
178
243
|
// Validate
|
|
179
244
|
this.validateItems(this.items);
|
|
245
|
+
this.validateValue(this.value);
|
|
180
246
|
// Set default placeholder
|
|
181
247
|
if (this.placeholder === undefined || this.placeholder === '') {
|
|
182
248
|
this.placeholder = this.messages.input.select.placeholder;
|
|
@@ -194,11 +260,11 @@ export class MgInputSelect {
|
|
|
194
260
|
* @returns {HTMLElement} HTML Element
|
|
195
261
|
*/
|
|
196
262
|
render() {
|
|
197
|
-
return (h(MgInput, { identifier: this.identifier, classList: this.classList, ariaDescribedbyIDs: [], label: this.label, labelOnTop: this.labelOnTop, labelHide: this.labelHide, required: this.required, readonly: this.readonly, mgWidth: this.mgWidth, disabled: this.disabled, value:
|
|
263
|
+
return (h(MgInput, { identifier: this.identifier, classList: this.classList, ariaDescribedbyIDs: [], label: this.label, labelOnTop: this.labelOnTop, labelHide: this.labelHide, required: this.required, readonly: this.readonly, mgWidth: this.mgWidth, disabled: this.disabled, value: undefined, readonlyValue: this.readonlyValue, tooltip: this.tooltip, helpText: this.helpText, errorMessage: this.errorMessage, isFieldset: false }, h("select", { class: "mg-input__box", id: this.identifier, name: this.name, title: this.placeholder, disabled: this.disabled, required: this.required, onInput: this.handleInput, onBlur: this.handleBlur, ref: el => {
|
|
198
264
|
if (el !== null)
|
|
199
265
|
this.input = el;
|
|
200
266
|
} }, (!this.placeholderHide || !this.valueExist) && ( // In case passed value does not match any option we display the placeholder
|
|
201
|
-
h("option", { value: "", disabled: this.placeholderDisabled && this.valueExist }, this.placeholder)), this.options.map(option => option
|
|
267
|
+
h("option", { value: "", disabled: this.placeholderDisabled && this.valueExist }, this.placeholder)), this.options.map(option => isOptGroup(option) ? h("optgroup", { label: option.group }, option.options.map(this.renderOption)) : isOption(option) && this.renderOption(option)))));
|
|
202
268
|
}
|
|
203
269
|
static get is() { return "mg-input-select"; }
|
|
204
270
|
static get encapsulation() { return "shadow"; }
|
|
@@ -235,8 +301,8 @@ export class MgInputSelect {
|
|
|
235
301
|
"type": "unknown",
|
|
236
302
|
"mutable": false,
|
|
237
303
|
"complexType": {
|
|
238
|
-
"original": "string
|
|
239
|
-
"resolved": "
|
|
304
|
+
"original": "(string | SelectOption)[]",
|
|
305
|
+
"resolved": "(string | SelectOption)[]",
|
|
240
306
|
"references": {
|
|
241
307
|
"SelectOption": {
|
|
242
308
|
"location": "import",
|
|
@@ -558,9 +624,13 @@ export class MgInputSelect {
|
|
|
558
624
|
"text": "Emited event when value change"
|
|
559
625
|
},
|
|
560
626
|
"complexType": {
|
|
561
|
-
"original": "
|
|
627
|
+
"original": "MgInputSelect['value']",
|
|
562
628
|
"resolved": "any",
|
|
563
|
-
"references": {
|
|
629
|
+
"references": {
|
|
630
|
+
"MgInputSelect": {
|
|
631
|
+
"location": "global"
|
|
632
|
+
}
|
|
633
|
+
}
|
|
564
634
|
}
|
|
565
635
|
}, {
|
|
566
636
|
"method": "inputValid",
|
|
@@ -606,7 +676,7 @@ export class MgInputSelect {
|
|
|
606
676
|
static get watchers() {
|
|
607
677
|
return [{
|
|
608
678
|
"propName": "value",
|
|
609
|
-
"methodName": "
|
|
679
|
+
"methodName": "validateValue"
|
|
610
680
|
}, {
|
|
611
681
|
"propName": "items",
|
|
612
682
|
"methodName": "validateItems"
|
|
@@ -8,6 +8,9 @@ export class MgMenu {
|
|
|
8
8
|
this.name = 'mg-menu';
|
|
9
9
|
this.menuItems = [];
|
|
10
10
|
this.focusedMenuItem = 0;
|
|
11
|
+
/*************
|
|
12
|
+
* Methods *
|
|
13
|
+
*************/
|
|
11
14
|
/**
|
|
12
15
|
* Close matching menu-item
|
|
13
16
|
*
|
|
@@ -20,9 +23,36 @@ export class MgMenu {
|
|
|
20
23
|
item.expanded = false;
|
|
21
24
|
}
|
|
22
25
|
};
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
+
/**
|
|
27
|
+
* get mg-item-more element
|
|
28
|
+
*
|
|
29
|
+
* @returns {HTMLMgItemMoreElement} mg-item-more element
|
|
30
|
+
*/
|
|
31
|
+
this.getItemMore = () => this.element.querySelector('mg-item-more');
|
|
32
|
+
/**
|
|
33
|
+
* get mg-item-more >>> mg-menu-item element
|
|
34
|
+
*
|
|
35
|
+
* @returns {HTMLMgMenuItemElement} mg-item-more >>> mg-menu-item element
|
|
36
|
+
*/
|
|
37
|
+
this.getItemMoreMenuItem = () => { var _a, _b; return (_b = (_a = this.getItemMore()) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('mg-menu-item'); };
|
|
38
|
+
/**
|
|
39
|
+
* Set item listend
|
|
40
|
+
*
|
|
41
|
+
* @param {HTMLMgMenuItemElement} item mg-menu-item element
|
|
42
|
+
* @param {MgMenu['focusedMenuItem']} index number
|
|
43
|
+
* @returns {void}
|
|
44
|
+
*/
|
|
45
|
+
this.setItemListener = (item, index) => {
|
|
46
|
+
['click', 'focus'].forEach(trigger => {
|
|
47
|
+
(item.shadowRoot.querySelector('button') || item.shadowRoot.querySelector('a')).addEventListener(trigger, () => {
|
|
48
|
+
this.focusedMenuItem = index;
|
|
49
|
+
// reset expanded on previous active menu item
|
|
50
|
+
(Boolean(this.getItemMoreMenuItem()) ? [...this.menuItems, this.getItemMoreMenuItem()] : this.menuItems).forEach((item, index) => {
|
|
51
|
+
this.closeMenuItem(item, index !== this.focusedMenuItem);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
};
|
|
26
56
|
/**
|
|
27
57
|
* Store menu-items on component init and add listeners
|
|
28
58
|
*
|
|
@@ -30,18 +60,18 @@ export class MgMenu {
|
|
|
30
60
|
*/
|
|
31
61
|
this.initMenuItemsListeners = () => {
|
|
32
62
|
// add listeners on menu item and edit index
|
|
33
|
-
this.menuItems.forEach((item,
|
|
34
|
-
|
|
35
|
-
(item.shadowRoot.querySelector('button') || item.shadowRoot.querySelector('a')).addEventListener(trigger, () => {
|
|
36
|
-
this.focusedMenuItem = menuItemIndex;
|
|
37
|
-
// reset expanded on previous active menu item
|
|
38
|
-
this.menuItems.forEach((item, index) => {
|
|
39
|
-
this.closeMenuItem(item, index !== this.focusedMenuItem);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|
|
63
|
+
this.menuItems.forEach((item, index) => {
|
|
64
|
+
this.setItemListener(item, index);
|
|
43
65
|
});
|
|
44
66
|
};
|
|
67
|
+
/**
|
|
68
|
+
* Handle item-loaded event on mg-item-more element
|
|
69
|
+
*
|
|
70
|
+
* @returns {void}
|
|
71
|
+
*/
|
|
72
|
+
this.handleItemLoaded = () => {
|
|
73
|
+
this.setItemListener(this.getItemMoreMenuItem(), this.menuItems.length);
|
|
74
|
+
};
|
|
45
75
|
/**
|
|
46
76
|
* render mg-item-more
|
|
47
77
|
*
|
|
@@ -52,12 +82,13 @@ export class MgMenu {
|
|
|
52
82
|
// by doing this we prevent stencil to generate a circular dependencies graph at build time with mg-item-more component.
|
|
53
83
|
const item = 'mg-item-more';
|
|
54
84
|
const mgItemMore = document.createElement(item);
|
|
55
|
-
Object.assign(mgItemMore, this.
|
|
85
|
+
Object.assign(mgItemMore, this.itemmore);
|
|
86
|
+
mgItemMore.addEventListener('item-loaded', this.handleItemLoaded);
|
|
56
87
|
this.element.appendChild(mgItemMore);
|
|
57
88
|
};
|
|
58
89
|
this.label = undefined;
|
|
59
90
|
this.direction = Direction.HORIZONTAL;
|
|
60
|
-
this.
|
|
91
|
+
this.itemmore = undefined;
|
|
61
92
|
this.size = 'regular';
|
|
62
93
|
this.isChildMenu = undefined;
|
|
63
94
|
}
|
|
@@ -73,7 +104,7 @@ export class MgMenu {
|
|
|
73
104
|
}
|
|
74
105
|
validateItemMore(newValue) {
|
|
75
106
|
if (newValue !== undefined && this.direction !== Direction.HORIZONTAL) {
|
|
76
|
-
throw new Error(`<${this.name}> prop "
|
|
107
|
+
throw new Error(`<${this.name}> prop "itemmore" must be paired with direction ${Direction.HORIZONTAL}.`);
|
|
77
108
|
}
|
|
78
109
|
}
|
|
79
110
|
validateSize(newValue) {
|
|
@@ -92,7 +123,7 @@ export class MgMenu {
|
|
|
92
123
|
componentWillLoad() {
|
|
93
124
|
this.validateDirection(this.direction);
|
|
94
125
|
this.validateLabel(this.label);
|
|
95
|
-
this.validateItemMore(this.
|
|
126
|
+
this.validateItemMore(this.itemmore);
|
|
96
127
|
this.validateSize(this.size);
|
|
97
128
|
}
|
|
98
129
|
/**
|
|
@@ -113,13 +144,14 @@ export class MgMenu {
|
|
|
113
144
|
this.renderMgItemMore();
|
|
114
145
|
// use mutation observer to improve reactivity
|
|
115
146
|
new MutationObserver(entries => {
|
|
116
|
-
const mgItemMore = this.
|
|
147
|
+
const mgItemMore = this.getItemMore();
|
|
117
148
|
// prevent infinit loop by exclude mg-item-more deletion entry
|
|
118
149
|
if (entries.some(entry => entry.type === 'childList' && Array.from(entry.removedNodes).some(node => node.nodeName === 'MG-ITEM-MORE')))
|
|
119
150
|
return;
|
|
120
151
|
else if (mgItemMore !== null) {
|
|
121
152
|
// render a new mg-item-more
|
|
122
153
|
mgItemMore.remove();
|
|
154
|
+
mgItemMore.removeEventListener('item-loaded', this.handleItemLoaded);
|
|
123
155
|
this.renderMgItemMore();
|
|
124
156
|
}
|
|
125
157
|
}).observe(this.element, { childList: true, characterData: true, subtree: true });
|
|
@@ -195,7 +227,7 @@ export class MgMenu {
|
|
|
195
227
|
"reflect": true,
|
|
196
228
|
"defaultValue": "Direction.HORIZONTAL"
|
|
197
229
|
},
|
|
198
|
-
"
|
|
230
|
+
"itemmore": {
|
|
199
231
|
"type": "unknown",
|
|
200
232
|
"mutable": false,
|
|
201
233
|
"complexType": {
|
|
@@ -254,7 +286,7 @@ export class MgMenu {
|
|
|
254
286
|
"propName": "direction",
|
|
255
287
|
"methodName": "validateDirection"
|
|
256
288
|
}, {
|
|
257
|
-
"propName": "
|
|
289
|
+
"propName": "itemmore",
|
|
258
290
|
"methodName": "validateItemMore"
|
|
259
291
|
}, {
|
|
260
292
|
"propName": "size",
|
|
@@ -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
|
|
|
@@ -272,6 +272,8 @@ export class MgMenuItem {
|
|
|
272
272
|
this.updatePopoverGuard();
|
|
273
273
|
// manage child dom changes with mutationObserver and listzners
|
|
274
274
|
this.initListeners();
|
|
275
|
+
// emit loaded event when component is fully loaded
|
|
276
|
+
this.itemLoaded.emit();
|
|
275
277
|
new MutationObserver(mutationsList => {
|
|
276
278
|
if (mutationsList.some(mutation => mutation.attributeName === 'hidden'))
|
|
277
279
|
this.updateStatus();
|
|
@@ -302,7 +304,7 @@ export class MgMenuItem {
|
|
|
302
304
|
render() {
|
|
303
305
|
const getContainerClasses = () => ({
|
|
304
306
|
[`${this.name}__collapse-container`]: true,
|
|
305
|
-
[`${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),
|
|
306
308
|
});
|
|
307
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()))) : ([
|
|
308
310
|
this.renderInteractiveElement(),
|
|
@@ -432,6 +434,21 @@ export class MgMenuItem {
|
|
|
432
434
|
}
|
|
433
435
|
}
|
|
434
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
|
+
}
|
|
435
452
|
}];
|
|
436
453
|
}
|
|
437
454
|
static get elementRef() { return "element"; }
|
|
@@ -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
|
});
|
|
@@ -26,7 +26,8 @@ export class MgItemMore {
|
|
|
26
26
|
Array.from(moreElementMenuItem.querySelectorAll('mg-menu-item:not([data-overflow-more])')).forEach((proxy, index) => {
|
|
27
27
|
// manage click on proxy to mirror it on initial element
|
|
28
28
|
proxy.addEventListener('click', () => {
|
|
29
|
-
|
|
29
|
+
// be carefull to use element.click() method instead of dispatchEvent to ensure bubbles outside shadowDom
|
|
30
|
+
allMenuItem[index].shadowRoot.querySelector('a, button').click();
|
|
30
31
|
});
|
|
31
32
|
// add id suffix to prevent duplicate key. default html id is: '';
|
|
32
33
|
if (proxy.id.trim() !== '')
|
|
@@ -66,12 +66,10 @@ export class ClassList {
|
|
|
66
66
|
/**
|
|
67
67
|
* Check if all items are string
|
|
68
68
|
*
|
|
69
|
-
* @param {
|
|
69
|
+
* @param {unknown} items items to check
|
|
70
70
|
* @returns {boolean} all items are string
|
|
71
71
|
*/
|
|
72
|
-
export const allItemsAreString = (items) =>
|
|
73
|
-
return items && items.every(item => typeof item === 'string');
|
|
74
|
-
};
|
|
72
|
+
export const allItemsAreString = (items) => Array.isArray(items) && items.every(item => typeof item === 'string');
|
|
75
73
|
/**
|
|
76
74
|
* Check if element is a heading
|
|
77
75
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MockCustomEvent } from '@stencil/core/mock-doc';
|
|
1
2
|
/**
|
|
2
3
|
* Clone Deep function
|
|
3
4
|
*
|
|
@@ -40,6 +41,30 @@ export const setupResizeObserverMock = ({ disconnect, observe }) => {
|
|
|
40
41
|
});
|
|
41
42
|
return MockResizeObserver;
|
|
42
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Utility function that mocks the `SubmitEvent` API. Recommended to execute inside `beforeEach`.
|
|
46
|
+
*
|
|
47
|
+
* @returns {void}
|
|
48
|
+
* @example
|
|
49
|
+
* ```
|
|
50
|
+
* setupSubmitEventMock();
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export const setupSubmitEventMock = () => {
|
|
54
|
+
class SubmitEvent extends MockCustomEvent {
|
|
55
|
+
constructor(type, eventInitDict) {
|
|
56
|
+
super(type, eventInitDict);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
[window, global].forEach(element => {
|
|
60
|
+
Object.defineProperty(element, 'SubmitEvent', {
|
|
61
|
+
writable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
value: SubmitEvent,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return SubmitEvent;
|
|
67
|
+
};
|
|
43
68
|
/**
|
|
44
69
|
* force popover id when component use randomed identifier
|
|
45
70
|
*
|
|
@@ -66,12 +66,10 @@ class ClassList {
|
|
|
66
66
|
/**
|
|
67
67
|
* Check if all items are string
|
|
68
68
|
*
|
|
69
|
-
* @param {
|
|
69
|
+
* @param {unknown} items items to check
|
|
70
70
|
* @returns {boolean} all items are string
|
|
71
71
|
*/
|
|
72
|
-
const allItemsAreString = (items) =>
|
|
73
|
-
return items && items.every(item => typeof item === 'string');
|
|
74
|
-
};
|
|
72
|
+
const allItemsAreString = (items) => Array.isArray(items) && items.every(item => typeof item === 'string');
|
|
75
73
|
/**
|
|
76
74
|
* Check if element is a heading
|
|
77
75
|
*
|
|
@@ -149,7 +149,7 @@ const MgForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
|
149
149
|
// submit buttons should trigger form submition;
|
|
150
150
|
if (['submit', null].includes(mgButton.getAttribute('type'))) {
|
|
151
151
|
mgButton.addEventListener('click', () => {
|
|
152
|
-
this.form.dispatchEvent(new
|
|
152
|
+
this.form.dispatchEvent(new SubmitEvent('submit', { bubbles: true }));
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
155
|
});
|
|
@@ -11,10 +11,11 @@ const mgInputCheckboxCss = ":host{display:block}.mg-input{display:flex;align-ite
|
|
|
11
11
|
/**
|
|
12
12
|
* type CheckboxItem validation function
|
|
13
13
|
*
|
|
14
|
-
* @param {
|
|
15
|
-
* @returns {boolean} match item
|
|
14
|
+
* @param {unknown} items Checkbox item
|
|
15
|
+
* @returns {boolean} match item type
|
|
16
16
|
*/
|
|
17
|
-
const
|
|
17
|
+
const isCheckboxItems = (items) => Array.isArray(items) &&
|
|
18
|
+
items.every(item => typeof item === 'object' && typeof item.title === 'string' && (item.value === null || typeof item.value === 'boolean') && item.value !== undefined);
|
|
18
19
|
const MgInputCheckbox$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
19
20
|
constructor() {
|
|
20
21
|
super();
|
|
@@ -97,7 +98,7 @@ const MgInputCheckbox$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLEle
|
|
|
97
98
|
this.checkboxItems = [];
|
|
98
99
|
}
|
|
99
100
|
validateValue(newValue) {
|
|
100
|
-
if (newValue
|
|
101
|
+
if (isCheckboxItems(newValue)) {
|
|
101
102
|
this.checkboxItems = newValue.map((item, index) => ({
|
|
102
103
|
id: `${this.identifier}_${index.toString()}`,
|
|
103
104
|
title: item.title,
|