@mgdis/mg-components 5.5.0 → 5.6.0

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 (142) hide show
  1. package/dist/cjs/{index-c3450336.js → index-4dcc1812.js} +11 -1
  2. package/dist/cjs/loader.cjs.js +3 -3
  3. package/dist/cjs/mg-badge_30.cjs.entry.js +742 -244
  4. package/dist/cjs/mg-components.cjs.js +3 -3
  5. package/dist/collection/collection-manifest.json +4 -4
  6. package/dist/collection/components/atoms/mg-badge/mg-badge.conf.js +1 -1
  7. package/dist/collection/components/atoms/mg-badge/mg-badge.css +13 -0
  8. package/dist/collection/components/atoms/mg-badge/mg-badge.js +3 -3
  9. package/dist/collection/components/atoms/mg-button/mg-button.css +2 -1
  10. package/dist/collection/components/atoms/mg-card/mg-card.css +13 -6
  11. package/dist/collection/components/atoms/mg-icon/mg-icon.conf.js +13 -3
  12. package/dist/collection/components/atoms/mg-tag/mg-tag.css +6 -6
  13. package/dist/collection/components/atoms/mg-tag/mg-tag.js +3 -3
  14. package/dist/collection/components/atoms/mg-tooltip/mg-tooltip.css +2 -0
  15. package/dist/collection/components/atoms/mg-tooltip/mg-tooltip.js +3 -3
  16. package/dist/collection/components/molecules/inputs/mg-input-date/mg-input-date.css +3 -3
  17. package/dist/collection/components/molecules/inputs/mg-input-date/mg-input-date.js +4 -1
  18. package/dist/collection/components/molecules/inputs/mg-input-numeric/mg-input-numeric.css +3 -3
  19. package/dist/collection/components/molecules/inputs/mg-input-password/mg-input-password.css +3 -3
  20. package/dist/collection/components/molecules/inputs/mg-input-select/mg-input-select.css +3 -3
  21. package/dist/collection/components/molecules/inputs/mg-input-select/mg-input-select.js +7 -3
  22. package/dist/collection/components/molecules/inputs/mg-input-text/mg-input-text.css +3 -3
  23. package/dist/collection/components/molecules/inputs/mg-input-textarea/mg-input-textarea.css +3 -3
  24. package/dist/collection/components/molecules/menu/mg-menu/doc/mg-menu.stories.js +43 -11
  25. package/dist/collection/components/molecules/menu/mg-menu/mg-menu.conf.js +17 -0
  26. package/dist/collection/components/molecules/menu/mg-menu/mg-menu.css +27 -0
  27. package/dist/collection/components/molecules/menu/mg-menu/mg-menu.js +141 -18
  28. package/dist/collection/components/molecules/menu/mg-menu-item/doc/mg-menu-item.stories.js +5 -10
  29. package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.conf.js +0 -4
  30. package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.css +47 -21
  31. package/dist/collection/components/molecules/menu/mg-menu-item/mg-menu-item.js +118 -70
  32. package/dist/collection/components/molecules/mg-illustrated-message/mg-illustrated-message.js +4 -3
  33. package/dist/collection/components/molecules/mg-message/mg-message.css +7 -0
  34. package/dist/collection/components/molecules/mg-message/mg-message.js +53 -12
  35. package/dist/collection/components/molecules/mg-modal/mg-modal.css +8 -1
  36. package/dist/collection/components/molecules/mg-panel/mg-panel.css +7 -0
  37. package/dist/collection/components/molecules/mg-popover/mg-popover.css +72 -14
  38. package/dist/collection/components/molecules/mg-popover/mg-popover.js +48 -4
  39. package/dist/collection/components/molecules/mg-skip-links/doc/mg-skip-links.stories.js +1 -1
  40. package/dist/collection/components/molecules/mg-skip-links/mg-skip-links.js +32 -1
  41. package/dist/collection/components/molecules/mg-tabs/doc/mg-tabs.stories.js +5 -3
  42. package/dist/collection/components/molecules/mg-tabs/mg-tabs.css +11 -7
  43. package/dist/collection/components/molecules/mg-tabs/mg-tabs.js +101 -54
  44. package/dist/collection/locales/en/messages.json +4 -0
  45. package/dist/collection/locales/fr/messages.json +4 -0
  46. package/dist/collection/locales/index.js +2 -25
  47. package/dist/collection/styles/a11y.scss +32 -0
  48. package/dist/collection/styles/components.scss +3 -0
  49. package/dist/collection/styles/fonts.scss +21 -0
  50. package/dist/collection/styles/form.scss +3 -0
  51. package/dist/collection/styles/global.scss +87 -0
  52. package/dist/collection/styles/layout.scss +29 -0
  53. package/dist/collection/styles/main.scss +23 -0
  54. package/dist/collection/styles/navigation-button.scss +76 -0
  55. package/dist/collection/styles/reset-mg-card-slotted-variables.scss +9 -0
  56. package/dist/collection/styles/typography.scss +75 -0
  57. package/dist/collection/styles/utilities.scss +21 -0
  58. package/dist/collection/utils/behaviors.utils.js +169 -0
  59. package/dist/collection/utils/components.utils.js +50 -0
  60. package/dist/collection/utils/locale.utils.js +22 -0
  61. package/dist/collection/utils/unit.test.utils.js +37 -32
  62. package/dist/collection/variables.css +9 -9
  63. package/dist/components/components.utils.js +51 -1
  64. package/dist/components/index2.js +65 -18
  65. package/dist/components/mg-badge2.js +4 -4
  66. package/dist/components/mg-button2.js +1 -1
  67. package/dist/components/mg-card2.js +1 -1
  68. package/dist/components/mg-icon2.js +13 -3
  69. package/dist/components/mg-illustrated-message.js +4 -3
  70. package/dist/components/mg-input-date.js +6 -4
  71. package/dist/components/mg-input-numeric.js +2 -3
  72. package/dist/components/mg-input-password.js +1 -1
  73. package/dist/components/mg-input-select2.js +8 -4
  74. package/dist/components/mg-input-text2.js +1 -1
  75. package/dist/components/mg-input-textarea.js +1 -1
  76. package/dist/components/mg-menu-item.js +1 -253
  77. package/dist/components/mg-menu-item2.js +517 -0
  78. package/dist/components/mg-menu.js +138 -21
  79. package/dist/components/mg-message.js +54 -13
  80. package/dist/components/mg-modal.js +1 -1
  81. package/dist/components/mg-panel.js +1 -1
  82. package/dist/components/mg-popover.js +1 -190
  83. package/dist/components/mg-popover2.js +212 -0
  84. package/dist/components/mg-skip-links.js +16 -2
  85. package/dist/components/mg-tabs.js +100 -52
  86. package/dist/components/mg-tag.js +4 -4
  87. package/dist/components/mg-tooltip2.js +4 -4
  88. package/dist/esm/{index-78edde1d.js → index-dc9a2348.js} +11 -1
  89. package/dist/esm/loader.js +3 -3
  90. package/dist/esm/mg-badge_30.entry.js +742 -244
  91. package/dist/esm/mg-components.js +3 -3
  92. package/dist/esm/polyfills/css-shim.js +1 -1
  93. package/dist/mg-components/locales/en/messages.json +4 -0
  94. package/dist/mg-components/locales/fr/messages.json +4 -0
  95. package/dist/mg-components/mg-components.css +1 -1
  96. package/dist/mg-components/mg-components.esm.js +1 -1
  97. package/dist/mg-components/{p-125c54ca.js → p-182bd802.js} +2 -2
  98. package/dist/mg-components/p-f7da9dd2.entry.js +1 -0
  99. package/dist/mg-components/styles/a11y.scss +32 -0
  100. package/dist/mg-components/styles/components.scss +3 -0
  101. package/dist/mg-components/styles/fonts.scss +21 -0
  102. package/dist/mg-components/styles/form.scss +3 -0
  103. package/dist/mg-components/styles/global.scss +87 -0
  104. package/dist/mg-components/styles/layout.scss +29 -0
  105. package/dist/mg-components/styles/main.scss +23 -0
  106. package/dist/mg-components/styles/navigation-button.scss +76 -0
  107. package/dist/mg-components/styles/reset-mg-card-slotted-variables.scss +9 -0
  108. package/dist/mg-components/styles/typography.scss +75 -0
  109. package/dist/mg-components/styles/utilities.scss +21 -0
  110. package/dist/mg-components/variables.css +9 -9
  111. package/dist/types/components/atoms/mg-badge/mg-badge.conf.d.ts +2 -2
  112. package/dist/types/components/atoms/mg-button/mg-button.conf.d.ts +2 -2
  113. package/dist/types/components/atoms/mg-icon/mg-icon.conf.d.ts +2 -2
  114. package/dist/types/components/atoms/mg-tag/mg-tag.conf.d.ts +1 -1
  115. package/dist/types/components/molecules/inputs/MgInput.conf.d.ts +2 -2
  116. package/dist/types/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.conf.d.ts +2 -2
  117. package/dist/types/components/molecules/inputs/mg-input-radio/mg-input-radio.conf.d.ts +1 -1
  118. package/dist/types/components/molecules/inputs/mg-input-select/mg-input-select.conf.d.ts +2 -2
  119. package/dist/types/components/molecules/inputs/mg-input-toggle/mg-input-toggle.conf.d.ts +1 -1
  120. package/dist/types/components/molecules/menu/mg-menu/doc/mg-menu.stories.d.ts +5 -0
  121. package/dist/types/components/molecules/menu/mg-menu/mg-menu.conf.d.ts +37 -0
  122. package/dist/types/components/molecules/menu/mg-menu/mg-menu.d.ts +51 -3
  123. package/dist/types/components/molecules/menu/mg-menu-item/mg-menu-item.conf.d.ts +0 -8
  124. package/dist/types/components/molecules/menu/mg-menu-item/mg-menu-item.d.ts +55 -15
  125. package/dist/types/components/molecules/mg-message/mg-message.d.ts +21 -4
  126. package/dist/types/components/molecules/mg-popover/mg-popover.d.ts +12 -0
  127. package/dist/types/components/molecules/mg-skip-links/mg-skip-links.conf.d.ts +1 -1
  128. package/dist/types/components/molecules/mg-skip-links/mg-skip-links.d.ts +15 -0
  129. package/dist/types/components/molecules/mg-tabs/mg-tabs.conf.d.ts +5 -3
  130. package/dist/types/components/molecules/mg-tabs/mg-tabs.d.ts +22 -12
  131. package/dist/types/components.d.ts +44 -12
  132. package/dist/types/locales/index.d.ts +10 -9
  133. package/dist/types/stencil-public-runtime.d.ts +39 -3
  134. package/dist/types/utils/behaviors.utils.d.ts +83 -0
  135. package/dist/types/utils/components.utils.d.ts +14 -0
  136. package/dist/types/utils/locale.utils.d.ts +13 -0
  137. package/dist/types/utils/unit.test.utils.d.ts +50 -14
  138. package/package.json +26 -26
  139. package/readme.md +22 -13
  140. package/dist/components/locale.utils.js +0 -40
  141. package/dist/components/mg-menu.conf.js +0 -10
  142. package/dist/mg-components/p-4961c96c.entry.js +0 -1
@@ -0,0 +1,3 @@
1
+ .is-asterisk {
2
+ color: hsl(var(--color-danger));
3
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Here we building the CSS for the component library
3
+ */
4
+
5
+ // Normalize CSS : https://necolas.github.io/normalize.css/
6
+ @import '~normalize.css/normalize.css';
7
+
8
+ // Fonts
9
+ @import './fonts.scss';
10
+
11
+ // Variables
12
+ @import './variables.css';
13
+
14
+ // Main style
15
+ @import './main.scss';
16
+
17
+ // Typography style
18
+ @import './typography.scss';
19
+
20
+ // Accessibility
21
+ @import './a11y.scss';
22
+
23
+ // Form
24
+ // already included by mg-form
25
+ // @import './form.scss';
26
+
27
+ // Layout
28
+ @import './layout.scss';
29
+
30
+ // Utilities
31
+ @import './utilities.scss';
32
+
33
+ /**
34
+ * Components style
35
+ * molecules
36
+ */
37
+
38
+ @import './components.scss';
39
+
40
+ /* Atoms */
41
+
42
+ // <mg-badge>
43
+ @import '../components/atoms/mg-badge/mg-badge.scss';
44
+
45
+ // <mg-button>
46
+ @import '../components/atoms/mg-button/mg-button.scss';
47
+
48
+ // <mg-character-left>
49
+ @import '../components/atoms/mg-character-left/mg-character-left.scss';
50
+
51
+ // <mg-icon>
52
+ @import '../components/atoms/mg-icon/mg-icon.scss';
53
+
54
+ // <mg-input-title>
55
+ //! For now input style will not be included
56
+ // @import '../components/atoms/mg-input-title/mg-input-title.scss';
57
+
58
+ // <mg-tag>
59
+ @import '../components/atoms/mg-tag/mg-tag.scss';
60
+
61
+ // <mg-tooltip>
62
+ @import '../components/atoms/mg-tooltip/mg-tooltip.scss';
63
+
64
+ /* Molecules */
65
+
66
+ // <mg-input-...>
67
+ //! For now input style will not be included
68
+ // @import '../components/molecules/inputs/styles/mg-input.scss';
69
+ // @import '../components/molecules/inputs/styles/mg-input-box.scss';
70
+ // @import '../components/molecules/inputs/styles/mg-input-charleft.scss';
71
+ // @import '../components/molecules/inputs/styles/mg-input-fieldset.scss';
72
+ // @import '../components/molecules/inputs/styles/mg-input-width.scss';
73
+
74
+ // <mg-form>
75
+ @import '../components/molecules/mg-form/mg-form.scss';
76
+
77
+ // <mg-message>
78
+ @import '../components/molecules/mg-message/mg-message.scss';
79
+
80
+ // <mg-pagination>
81
+ @import '../components/molecules/mg-pagination/mg-pagination.scss';
82
+
83
+ // <mg-popover>
84
+ @import '../components/molecules/mg-popover/mg-popover.scss';
85
+
86
+ // <mg-tabs>
87
+ @import '../components/molecules/mg-tabs/mg-tabs.scss';
@@ -0,0 +1,29 @@
1
+ @use 'sass:math';
2
+
3
+ // Number of column
4
+ $grid-columns: 12;
5
+
6
+ // Calculate width
7
+ @function round-width($i) {
8
+ $width: math.div(100 * $i, $grid-columns);
9
+ @return #{$width}#{'%'};
10
+ }
11
+
12
+ .mg-grid {
13
+ display: flex;
14
+ flex-wrap: wrap;
15
+ }
16
+
17
+ // Those columns will equaly share space
18
+ .mg-grid__col {
19
+ flex: 1 0 0;
20
+ padding: 0 var(--mg-grid-spacing);
21
+
22
+ // Building columns
23
+ @for $i from 1 through $grid-columns {
24
+ &.mg-grid__col-#{$i} {
25
+ flex: 0 0 auto;
26
+ width: round-width($i);
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,23 @@
1
+ // Make all element use the border box model
2
+ *,
3
+ *::before,
4
+ *::after {
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ /**
9
+ * We set html font size to 62.5% to get 10px in most of the case.
10
+ * This is a common use for an easiest calculation : 1rem = 10px
11
+ * Default font size will be defined in body element.
12
+ */
13
+
14
+ html {
15
+ font-size: 62.5%;
16
+ }
17
+
18
+ body {
19
+ font-size: var(--font-size);
20
+ font-family: var(--font-family);
21
+ line-height: var(--line-height);
22
+ -webkit-font-smoothing: antialiased;
23
+ }
@@ -0,0 +1,76 @@
1
+ @use 'sass:map';
2
+
3
+ $border-bottom-size: 0.3rem;
4
+ $font-size-large: calc(var(--font-size) + 0.2rem);
5
+ $navigation-button-column-gap: 1rem;
6
+
7
+ @mixin navigation-button($element, $button-sizes) {
8
+ @each $name, $size in $button-sizes {
9
+ .#{$element}.#{$element}--size-#{$name} .#{$element}__navigation-button,
10
+ .#{$element}__navigation-button.#{$element}__navigation-button--size-#{$name} {
11
+ padding: #{map.get($size, 'vertical')} #{map.get($size, 'horizontal')};
12
+ height: calc(#{map.get($size, 'height')});
13
+ &,
14
+ ::slotted([slot='label']),
15
+ ::slotted([slot='metadata']) {
16
+ @if $name == 'regular' {
17
+ font-size: var(--font-size);
18
+ } @else {
19
+ font-size: $font-size-large;
20
+ }
21
+ }
22
+ &.#{$element}__navigation-button--horizontal {
23
+ padding-bottom: calc(#{map.get($size, 'vertical')} - #{$border-bottom-size});
24
+ }
25
+ &.#{$element}__navigation-button--vertical {
26
+ padding-left: calc(#{map.get($size, 'horizontal')} - #{$border-bottom-size});
27
+ }
28
+ }
29
+ }
30
+
31
+ .#{$element}__navigation-button {
32
+ display: flex;
33
+ align-items: center;
34
+ column-gap: var(--#{$element}-navigation-button-column-gap, $navigation-button-column-gap);
35
+ background-color: unset;
36
+ border: none;
37
+ font-family: var(--font-family);
38
+ color: hsl(var(--#{$element}-color-hsl, var(--color-dark)));
39
+ line-height: var(--line-height);
40
+ text-decoration: none;
41
+ white-space: nowrap;
42
+ box-sizing: border-box;
43
+ cursor: pointer;
44
+ &:disabled,
45
+ &--disabled {
46
+ cursor: default;
47
+ opacity: 0.3;
48
+ }
49
+ &:focus-visible {
50
+ z-index: 10;
51
+ }
52
+ &:hover:not(.#{$element}__navigation-button--disabled),
53
+ &:focus-visible:not(.#{$element}__navigation-button--disabled) {
54
+ background-color: hsl(var(--#{$element}-focused-background-color-hsl), 0.1);
55
+ }
56
+ &.#{$element}__navigation-button--active {
57
+ color: hsl(var(--#{$element}-color-active-hsl));
58
+ font-weight: 600;
59
+ &.#{$element}__navigation-button--horizontal {
60
+ border-bottom-color: hsl(var(--#{$element}-border-color-active-hsl));
61
+ }
62
+ &.#{$element}__navigation-button--vertical {
63
+ border-left-color: hsl(var(--#{$element}-border-color-active-hsl));
64
+ }
65
+ }
66
+ &.#{$element}__navigation-button--hidden {
67
+ display: none;
68
+ }
69
+ &.#{$element}__navigation-button--horizontal {
70
+ border-bottom: $border-bottom-size solid transparent;
71
+ }
72
+ &.#{$element}__navigation-button--vertical {
73
+ border-left: $border-bottom-size solid transparent;
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,9 @@
1
+ @mixin reset-slot-card-variables() {
2
+ ::slotted(*) {
3
+ --mg-card-border: var(--mg-card-border-default);
4
+ --mg-card-padding: var(--mg-card-padding-default);
5
+ --mg-card-border-radius: var(--mg-card-border-radius-default);
6
+ --mg-card-background: var(--mg-card-background-default);
7
+ --mg-card-box-shadow: var(--mg-card-box-shadow-default);
8
+ }
9
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Paragraph
3
+ */
4
+
5
+ p {
6
+ margin: 0;
7
+ & + p {
8
+ margin-top: 1rem;
9
+ }
10
+ }
11
+
12
+ /**
13
+ * Headings
14
+ *
15
+ * Classes can also be used on element to match attending, for exemples :
16
+ * <h4 class="h3">blu</h4>
17
+ * <div role="heading" aria-level="4" class="h4">blu</div>
18
+ */
19
+
20
+ @for $i from 1 through 6 {
21
+ h#{$i},
22
+ .h#{$i} {
23
+ font-family: var(--font-family-heading);
24
+ }
25
+ }
26
+
27
+ //h1
28
+ h1,
29
+ .h1 {
30
+ font-size: calc(var(--font-size) * 1.85);
31
+ }
32
+
33
+ //h2
34
+ h2,
35
+ .h2 {
36
+ font-size: calc(var(--font-size) * 1.65);
37
+ }
38
+
39
+ //h3
40
+ h3,
41
+ .h3 {
42
+ font-size: calc(var(--font-size) * 1.35);
43
+ }
44
+
45
+ //h4
46
+ h4,
47
+ .h4 {
48
+ font-size: calc(var(--font-size) * 1.2);
49
+ }
50
+
51
+ //h5
52
+ h5,
53
+ .h5 {
54
+ font-size: calc(var(--font-size) * 1.1);
55
+ }
56
+
57
+ //h6
58
+ h6,
59
+ .h6 {
60
+ font-size: calc(var(--font-size) * 0.8);
61
+ }
62
+
63
+ /**
64
+ * Links
65
+ */
66
+ a {
67
+ color: hsl(var(--color-primary));
68
+ text-decoration: underline;
69
+
70
+ &:hover,
71
+ &:focus,
72
+ &:active {
73
+ text-decoration: none;
74
+ }
75
+ }
@@ -0,0 +1,21 @@
1
+ // Helper to manage space between elements
2
+ .mg-group-elements {
3
+ display: flex;
4
+ align-items: center;
5
+ flex-wrap: wrap;
6
+ gap: 1rem;
7
+
8
+ // remove default margin
9
+ & > * {
10
+ margin: 0 !important; // I would say important is allowed in utility classes ?
11
+ }
12
+
13
+ // Align button on right side
14
+ &.mg-group-elements--align-right {
15
+ justify-content: flex-end;
16
+ }
17
+ }
18
+
19
+ .no-padding {
20
+ padding: 0;
21
+ }
@@ -0,0 +1,169 @@
1
+ import { Status } from '../components/molecules/menu/mg-menu-item/mg-menu-item.conf';
2
+ /**
3
+ * MgMenuItem type guard
4
+ *
5
+ * @param {HTMLElement} element element to control type
6
+ * @returns {boolean} truthy if element is mg-menu-item
7
+ */
8
+ const isMgMenuItem = (element) => element.nodeName === 'MG-MENU-ITEM';
9
+ export var OverflowBehaviorElements;
10
+ (function (OverflowBehaviorElements) {
11
+ OverflowBehaviorElements["MORE"] = "data-overflow-more";
12
+ OverflowBehaviorElements["BASE_INDEX"] = "data-overflow-base-index";
13
+ OverflowBehaviorElements["PROXY_INDEX"] = "data-overflow-proxy-index";
14
+ })(OverflowBehaviorElements || (OverflowBehaviorElements = {}));
15
+ export class OverflowBehavior {
16
+ constructor(element, render) {
17
+ this.element = element;
18
+ this.render = render;
19
+ /**********
20
+ * Public *
21
+ **********/
22
+ /**
23
+ * Disconnect ResizeObserver
24
+ *
25
+ * @returns {void}
26
+ */
27
+ this.disconnect = () => {
28
+ this.resizeObserver.disconnect();
29
+ };
30
+ /**
31
+ * Update more element status if active child
32
+ *
33
+ * @returns {void}
34
+ */
35
+ this.updateActiveStatus = () => {
36
+ const hasActiveChild = Array.from(this.moreELement.querySelector('mg-menu').children).some(element => element.nodeName === 'MG-MENU-ITEM' && element.getAttribute('status') === Status.ACTIVE && element.getAttribute('hidden') === null);
37
+ this.moreELement.setAttribute('status', hasActiveChild ? Status.ACTIVE : Status.VISIBLE);
38
+ };
39
+ /************
40
+ * Internal *
41
+ ************/
42
+ /**
43
+ * run overflow behavior
44
+ *
45
+ * @param {number} width width of the container
46
+ * @returns {void}
47
+ */
48
+ this.run = (width) => {
49
+ if (this.moreELement === undefined) {
50
+ // set moreElement
51
+ this.moreELement = this.render();
52
+ this.moreELement.setAttribute(OverflowBehaviorElements.MORE, '');
53
+ // set children
54
+ this.children = Array.from(this.element.children);
55
+ let moreELementChildren;
56
+ const allowedElements = ['MG-MENU-ITEM', 'MG-BUTTON'];
57
+ if (isMgMenuItem(this.moreELement)) {
58
+ moreELementChildren = Array.from(this.moreELement.querySelector('mg-menu').children).filter(element => allowedElements.includes(element.nodeName));
59
+ }
60
+ this.children.forEach((child, index) => {
61
+ child.setAttribute(OverflowBehaviorElements.BASE_INDEX, `${index}`);
62
+ if (child.getAttribute(OverflowBehaviorElements.MORE) === null) {
63
+ // set moreElement children
64
+ moreELementChildren[index].setAttribute(OverflowBehaviorElements.PROXY_INDEX, `${index}`);
65
+ }
66
+ });
67
+ }
68
+ this.updateDisplayedItems(width);
69
+ if (isMgMenuItem(this.moreELement))
70
+ this.updateActiveStatus();
71
+ };
72
+ /**
73
+ * Update displayed items in container from a given available space
74
+ *
75
+ * @param {number} availableWidth available width in container to display child items
76
+ * @returns {void}
77
+ */
78
+ this.updateDisplayedItems = (availableWidth) => {
79
+ this.restoreItems();
80
+ this.children.reduce((acc, curr) => {
81
+ acc.accWidth += curr.offsetWidth;
82
+ const isPreviousItemHidden = acc.previousItem !== null && acc.previousItem.getAttribute('hidden') !== null;
83
+ // if previous item is hidden AND is NOT more element we hidde current
84
+ // OR if item has an overflow we hidde current
85
+ // OR if current item is more element AND have NOT previous hidden items, current more element item is an hidden item
86
+ // ELSE current is a display item
87
+ if ((isPreviousItemHidden && !this.isMoreElement(curr)) ||
88
+ this.isOverflowElement(acc.accWidth, curr, availableWidth) ||
89
+ (this.isMoreElement(curr) && !isPreviousItemHidden)) {
90
+ this.toggleItem(curr, true);
91
+ }
92
+ else
93
+ this.toggleItem(curr, false);
94
+ // update previous item with current item
95
+ acc.previousItem = curr;
96
+ return acc;
97
+ }, { accWidth: 0, previousItem: null });
98
+ };
99
+ /**
100
+ * Utility method to know if item overflow partialy or totaly in the container
101
+ *
102
+ * @param {number} cumulateWidth previous sibling elements cumulate width + item width
103
+ * @param {HTMLElement} item item HTML element
104
+ * @param {number} availableWidth container available width
105
+ * @returns {boolean} truthy if element is overflow
106
+ */
107
+ this.isOverflowElement = (cumulateWidth, item, availableWidth) => {
108
+ if (item.previousElementSibling === null || this.isMoreElement(item))
109
+ return false;
110
+ else if (!this.isMoreElement(item.nextElementSibling))
111
+ return cumulateWidth + this.moreELement.offsetWidth > availableWidth;
112
+ else
113
+ return cumulateWidth > availableWidth;
114
+ };
115
+ /**
116
+ * Utility method to know if a given element is the 'MORE' element
117
+ *
118
+ * @param {Element} element element to match with 'MORE' element
119
+ * @returns {boolean} truthy if element is the 'MORE' element
120
+ */
121
+ this.isMoreElement = (element) => element.getAttribute(OverflowBehaviorElements.MORE) !== null;
122
+ /**
123
+ * Toggle display item element
124
+ *
125
+ * @param {HTMLElement} item item to control
126
+ * @param {boolean} isHidden is item hidden
127
+ * @returns {void}
128
+ */
129
+ this.toggleItem = (item, isHidden) => {
130
+ const mgActionMenuindex = Number(item.getAttribute(OverflowBehaviorElements.BASE_INDEX));
131
+ if (this.isMoreElement(item))
132
+ this.toggleElement(this.moreELement, isHidden);
133
+ else if (mgActionMenuindex >= 0) {
134
+ this.toggleElement(item, isHidden);
135
+ this.toggleElement(this.moreELement.querySelector(`[${OverflowBehaviorElements.PROXY_INDEX}="${mgActionMenuindex}"]`), !isHidden);
136
+ }
137
+ };
138
+ /**
139
+ * Toggle element's hidde attribute
140
+ *
141
+ * @param {Element} element element to toggle
142
+ * @param {boolean} isHidden element is hidden
143
+ * @returns {void}
144
+ */
145
+ this.toggleElement = (element, isHidden) => {
146
+ if (isHidden)
147
+ element.setAttribute('hidden', '');
148
+ else
149
+ element.removeAttribute('hidden');
150
+ };
151
+ /**
152
+ * Remove hidden attributes on all items
153
+ *
154
+ * @returns {void}
155
+ */
156
+ this.restoreItems = () => {
157
+ this.children.forEach(item => item.removeAttribute('hidden'));
158
+ };
159
+ if (this.resizeObserver === undefined) {
160
+ // add resize observer
161
+ this.resizeObserver = new ResizeObserver(entries => {
162
+ entries.forEach(entry => {
163
+ this.run(entry.contentRect.width);
164
+ });
165
+ });
166
+ this.resizeObserver.observe(this.element);
167
+ }
168
+ }
169
+ }
@@ -86,3 +86,53 @@ export const isTagName = (element, tagNames) => {
86
86
  * Focusable elements query selector
87
87
  */
88
88
  export const focusableElements = 'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"]), [identifier]';
89
+ /**
90
+ *
91
+ * @param {Window} localWindow the window we are lookink for other windows
92
+ * @returns {Window[]} The list of windows found
93
+ */
94
+ export const getWindows = (localWindow) => {
95
+ const parentWindows = getParentWindows(localWindow);
96
+ const childWindows = getChildWindows(localWindow);
97
+ return [localWindow, ...parentWindows, ...childWindows];
98
+ };
99
+ /**
100
+ * Get parent windows
101
+ *
102
+ * @param {Window} localWindow the window we are lookink for parents
103
+ * @param {Window[]} windows The list of allready found windows
104
+ * @returns {Window[]} The list of windows found
105
+ */
106
+ export const getParentWindows = (localWindow, windows = []) => {
107
+ // Check if is in iframe
108
+ if (localWindow.self !== localWindow.top) {
109
+ // Check if we have permission to access parent
110
+ try {
111
+ const parentWindow = localWindow.parent;
112
+ windows.push(parentWindow);
113
+ return getParentWindows(parentWindow, windows);
114
+ }
115
+ catch (err) {
116
+ console.error('Different hosts between iframes:', err);
117
+ return windows;
118
+ }
119
+ }
120
+ return windows;
121
+ };
122
+ /**
123
+ * Get child windows
124
+ *
125
+ * @param {Window} localWindow the window we are lookink for children
126
+ * @param {Window[]} windows The list of allready found windows
127
+ * @returns {Window[]} The list of windows found
128
+ */
129
+ const getChildWindows = (localWindow, windows = []) => {
130
+ if (localWindow.frames.length > 0) {
131
+ for (let i = 0; i < localWindow.frames.length; i++) {
132
+ const childWindow = localWindow.frames[i];
133
+ windows.push(childWindow);
134
+ windows.concat(getChildWindows(childWindow, windows));
135
+ }
136
+ }
137
+ return windows;
138
+ };
@@ -36,3 +36,25 @@ export function localeDate(date, locale) {
36
36
  }
37
37
  return new Intl.DateTimeFormat(locale).format(new Date(date));
38
38
  }
39
+ /**
40
+ * Get locale and messages
41
+ * We load the defined locale but for now we only support the first subtag for messages
42
+ *
43
+ * @param {HTMLElement} element element we need to get the language
44
+ * @param {unknown} messages messages to use
45
+ * @param {string} defaultLocale default messages locale
46
+ * @returns {{ locale: string; messages: unknown }} messages object
47
+ */
48
+ export const getLocaleMessages = (element, messages, defaultLocale) => {
49
+ var _a;
50
+ // Get local
51
+ const closestLang = Intl.NumberFormat.supportedLocalesOf((_a = element.closest('[lang]')) === null || _a === void 0 ? void 0 : _a.lang);
52
+ const locale = closestLang.length > 0 ? closestLang[0] : navigator.language || defaultLocale;
53
+ // Only keep first subtag
54
+ const localeSubtag = locale.split('-').shift();
55
+ // Return
56
+ return {
57
+ locale,
58
+ messages: messages[localeSubtag] || messages[defaultLocale],
59
+ };
60
+ };
@@ -5,29 +5,6 @@
5
5
  * @returns {unknown} cloned json
6
6
  */
7
7
  export const cloneDeep = (obj) => JSON.parse(JSON.stringify(obj));
8
- /**
9
- * Utility function that mocks the `MutationObserver` API. Recommended to execute inside `beforeEach`.
10
- *
11
- * @param mutationObserverMock - Parameter that is sent to the `Object.defineProperty`
12
- * overwrite method. `jest.fn()` mock functions can be passed here if the goal is to not only
13
- * mock the resize observer, but its methods.
14
- * You can manually fire an intersection entry:
15
- * @param {Function} mutationObserverMock.disconnect disconnect function
16
- * @param {Function} mutationObserverMock.observe observe fnuction
17
- * @param {Function} mutationObserverMock.takeRecords takeRecords fnuction
18
- * @returns {MutationObserver} Mocked MutationObserver
19
- * @example
20
- * ```
21
- * let fireMo;
22
- * setupMutationObserverMock({
23
- * observe: function () {
24
- * fireMo = this.cb;
25
- * },
26
- * });
27
- * ...
28
- * fireMo([{ type: 'childList', addedNodes: [AMockElemenet, AnotherMockElemenet], target: yourMockElemenet }]);;
29
- * ```
30
- */
31
8
  export const setupMutationObserverMock = ({ disconnect, observe, takeRecords }) => {
32
9
  class MockMutationObserver {
33
10
  constructor(fn) {
@@ -37,15 +14,43 @@ export const setupMutationObserverMock = ({ disconnect, observe, takeRecords })
37
14
  this.cb = fn;
38
15
  }
39
16
  }
40
- Object.defineProperty(window, 'MutationObserver', {
41
- writable: true,
42
- configurable: true,
43
- value: MockMutationObserver,
44
- });
45
- Object.defineProperty(global, 'MutationObserver', {
46
- writable: true,
47
- configurable: true,
48
- value: MockMutationObserver,
17
+ [window, global].forEach(element => {
18
+ Object.defineProperty(element, 'MutationObserver', {
19
+ writable: true,
20
+ configurable: true,
21
+ value: MockMutationObserver,
22
+ });
49
23
  });
50
24
  return MockMutationObserver;
51
25
  };
26
+ export const setupResizeObserverMock = ({ disconnect, observe }) => {
27
+ class MockResizeObserver {
28
+ constructor(fn) {
29
+ this.disconnect = disconnect;
30
+ this.observe = observe;
31
+ this.cb = fn;
32
+ }
33
+ }
34
+ [window, global].forEach(element => {
35
+ Object.defineProperty(element, 'ResizeObserver', {
36
+ writable: true,
37
+ configurable: true,
38
+ value: MockResizeObserver,
39
+ });
40
+ });
41
+ return MockResizeObserver;
42
+ };
43
+ /**
44
+ * force popover id when component use randomed identifier
45
+ *
46
+ * @param {Element} item element wich include mg-popover
47
+ * @param {string} id new fixed id
48
+ * @returns {void}
49
+ */
50
+ export const forcePopoverId = (item, id) => {
51
+ const popover = item.shadowRoot.querySelector('mg-popover');
52
+ if (popover !== null) {
53
+ popover.shadowRoot.querySelector('.mg-popover').setAttribute('id', id);
54
+ item.shadowRoot.querySelector('button').setAttribute('aria-controls', id);
55
+ }
56
+ };