@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.
Files changed (39) hide show
  1. package/dist/cjs/loader.cjs.js +2 -2
  2. package/dist/cjs/mg-action-more_31.cjs.entry.js +148 -48
  3. package/dist/cjs/mg-components.cjs.js +2 -2
  4. package/dist/cjs/mg-item-more.cjs.entry.js +3 -2
  5. package/dist/collection/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.js +14 -10
  6. package/dist/collection/components/molecules/inputs/mg-input-select/mg-input-select.js +91 -21
  7. package/dist/collection/components/molecules/menu/mg-menu/mg-menu.js +52 -20
  8. package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.css +4 -2
  9. package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.js +18 -1
  10. package/dist/collection/components/molecules/mg-form/mg-form.js +1 -1
  11. package/dist/collection/components/molecules/mg-item-more/mg-item-more.js +2 -1
  12. package/dist/collection/utils/components.utils.js +2 -4
  13. package/dist/collection/utils/unit.test.utils.js +25 -0
  14. package/dist/components/components.utils.js +2 -4
  15. package/dist/components/mg-form.js +1 -1
  16. package/dist/components/mg-input-checkbox.js +5 -4
  17. package/dist/components/mg-input-select2.js +83 -17
  18. package/dist/components/mg-item-more.js +2 -1
  19. package/dist/components/mg-menu-item2.js +5 -2
  20. package/dist/components/mg-menu2.js +52 -20
  21. package/dist/esm/loader.js +3 -3
  22. package/dist/esm/mg-action-more_31.entry.js +148 -48
  23. package/dist/esm/mg-components.js +3 -3
  24. package/dist/esm/mg-item-more.entry.js +3 -2
  25. package/dist/mg-components/mg-components.esm.js +1 -1
  26. package/dist/mg-components/p-0b68c4b4.entry.js +1 -0
  27. package/dist/mg-components/{p-1221773c.entry.js → p-67ce7cb8.entry.js} +1 -1
  28. package/dist/types/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.d.ts +3 -3
  29. package/dist/types/components/molecules/inputs/mg-input-select/mg-input-select.d.ts +39 -4
  30. package/dist/types/components/molecules/menu/mg-menu/mg-menu.d.ts +31 -5
  31. package/dist/types/components/molecules/menu/mg-menu-item/mg-menu-item.d.ts +4 -0
  32. package/dist/types/components.d.ts +11 -7
  33. package/dist/types/utils/components.utils.d.ts +2 -2
  34. package/dist/types/utils/unit.test.utils.d.ts +11 -0
  35. package/package.json +9 -14
  36. package/dist/mg-components/p-6aeded97.entry.js +0 -1
  37. /package/dist/cjs/{index-5e7ede97.js → index-9e1091ab.js} +0 -0
  38. /package/dist/esm/{index-03cceb11.js → index-3249671d.js} +0 -0
  39. /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 {CheckboxItem} item Checkbox item
10
- * @returns {boolean} match item expectations
9
+ * @param {unknown} items Checkbox item
10
+ * @returns {boolean} match item type
11
11
  */
12
- const isCheckboxItem = (item) => typeof item === 'object' && typeof item.title === 'string' && (item.value === null || typeof item.value === 'boolean') && item.value !== undefined;
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 && newValue.every(item => isCheckboxItem(item))) {
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": "CheckboxValue[]",
441
+ "original": "MgInputCheckbox['value']",
441
442
  "resolved": "CheckboxValue[]",
442
443
  "references": {
443
- "CheckboxValue": {
444
- "location": "import",
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": "boolean",
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 {SelectOption} option select option
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.checkValidity();
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.value = allItemsAreString(this.items) ? this.input.value : this.items.find(item => item.title === this.input.value).value;
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
- this.value = null;
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
- handleValue(newValue) {
113
- if (newValue !== null) {
114
- this.readonlyValue = allItemsAreString(this.items) ? this.input.value : this.items.find(item => item.value === newValue).title;
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
- this.valueExist = newValue.includes(this.value);
129
- this.options = newValue.map((item) => ({ title: item, value: item }));
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.every(item => isOption(item))) {
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 !== undefined)) {
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: this.value, 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 => {
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.group !== undefined ? (h("optgroup", { label: option.group }, option.options.map(optgroup => (h("option", { key: optgroup.title, value: optgroup.title, selected: JSON.stringify(this.value) === JSON.stringify(optgroup.value), disabled: optgroup.disabled }, optgroup.title))))) : (h("option", { value: option.title, selected: JSON.stringify(this.value) === JSON.stringify(option.value), disabled: option.disabled }, option.title))))));
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[] | SelectOption[]",
239
- "resolved": "SelectOption[] | string[]",
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": "any",
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": "handleValue"
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
- * Methods *
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, menuItemIndex) => {
34
- ['click', 'focus'].forEach(trigger => {
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.itemMore);
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.itemMore = undefined;
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 "itemMore" must be paired with direction ${Direction.HORIZONTAL}.`);
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.itemMore);
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.element.querySelector('mg-item-more');
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
- "itemMore": {
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": "itemMore",
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 CustomEvent('submit', { bubbles: true }));
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
- (allMenuItem[index].shadowRoot.querySelector('a') || allMenuItem[index].shadowRoot.querySelector('button')).dispatchEvent(new MouseEvent('click', { bubbles: true }));
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 {string[]} items items to check
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 {string[]} items items to check
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 CustomEvent('submit', { bubbles: true }));
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 {CheckboxItem} item Checkbox item
15
- * @returns {boolean} match item expectations
14
+ * @param {unknown} items Checkbox item
15
+ * @returns {boolean} match item type
16
16
  */
17
- const isCheckboxItem = (item) => typeof item === 'object' && typeof item.title === 'string' && (item.value === null || typeof item.value === 'boolean') && item.value !== undefined;
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 && newValue.every(item => isCheckboxItem(item))) {
101
+ if (isCheckboxItems(newValue)) {
101
102
  this.checkboxItems = newValue.map((item, index) => ({
102
103
  id: `${this.identifier}_${index.toString()}`,
103
104
  title: item.title,