@mozaic-ds/vue 0.16.0 → 0.17.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 (34) hide show
  1. package/dist/mozaic-vue.adeo.css +1 -1
  2. package/dist/mozaic-vue.adeo.umd.js +3519 -2060
  3. package/dist/mozaic-vue.common.js +3519 -2060
  4. package/dist/mozaic-vue.common.js.map +1 -1
  5. package/dist/mozaic-vue.css +1 -1
  6. package/dist/mozaic-vue.umd.js +3519 -2060
  7. package/dist/mozaic-vue.umd.js.map +1 -1
  8. package/dist/mozaic-vue.umd.min.js +1 -1
  9. package/dist/mozaic-vue.umd.min.js.map +1 -1
  10. package/package.json +4 -4
  11. package/src/components/autocomplete/MAutocomplete.vue +198 -0
  12. package/src/components/autocomplete/index.js +7 -0
  13. package/src/components/card/MCard.vue +1 -0
  14. package/src/components/checkbox/MCheckboxGroup.vue +8 -2
  15. package/src/components/container/MContainer.vue +4 -2
  16. package/src/components/fileuploader/MFileResult.vue +5 -0
  17. package/src/components/fileuploader/MFileUploader.vue +1 -0
  18. package/src/components/index.js +2 -0
  19. package/src/components/listbox/MListBox.vue +106 -0
  20. package/src/components/listbox/index.js +7 -0
  21. package/src/components/optioncard/MOptionCard.vue +2 -0
  22. package/src/components/tabs/MTab.vue +35 -7
  23. package/src/components/tags/MTag.vue +21 -0
  24. package/src/components/textinput/MTextInput.vue +5 -0
  25. package/src/index.js +2 -0
  26. package/src/tokens/adeo/android/colors.xml +21 -21
  27. package/src/tokens/adeo/css/_variables.scss +21 -21
  28. package/src/tokens/adeo/css/root.scss +21 -21
  29. package/src/tokens/adeo/ios/StyleDictionaryColor.m +21 -21
  30. package/src/tokens/adeo/ios/StyleDictionaryColor.swift +21 -21
  31. package/src/tokens/adeo/js/tokens.js +21 -21
  32. package/src/tokens/adeo/js/tokensObject.js +65 -65
  33. package/src/tokens/adeo/scss/_tokens.scss +21 -21
  34. package/types/index.d.ts +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mozaic-ds/vue",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build ./src/index.js",
@@ -13,9 +13,9 @@
13
13
  "postinstall": "node postinstall.js"
14
14
  },
15
15
  "dependencies": {
16
- "@mozaic-ds/css-dev-tools": "^1.27.1",
17
- "@mozaic-ds/icons": "^1.28.0",
18
- "@mozaic-ds/styles": "^1.28.0",
16
+ "@mozaic-ds/css-dev-tools": "^1.29.1",
17
+ "@mozaic-ds/icons": "^1.30.0",
18
+ "@mozaic-ds/styles": "^1.30.0",
19
19
  "@mozaic-ds/web-fonts": "^1.22.0",
20
20
  "core-js": "^3.18.3",
21
21
  "libphonenumber-js": "1.9.50",
@@ -0,0 +1,198 @@
1
+ <template>
2
+ <div
3
+ ref="autocomplete"
4
+ class="mc-autocomplete"
5
+ :class="{ 'mc-autocomplete--multi': multiple }"
6
+ :style="tagStyle"
7
+ @keyup.esc="isOpen = true"
8
+ >
9
+ <m-tag
10
+ v-if="multiple && selectedItems().length > 0"
11
+ id="tag"
12
+ type="removable"
13
+ :label="selectedItems().length.toString() + ' ' + labelTag"
14
+ class="mc-autocomplete__tag"
15
+ size="s"
16
+ @remove-tag="removeElementsFromList()"
17
+ />
18
+ <m-text-input
19
+ v-model="itemDisplayed"
20
+ :placeholder="placeholder"
21
+ text-input-field-class="mc-autocomplete__trigger"
22
+ icon-position="left"
23
+ icon="DisplaySearch48"
24
+ autocomplete="off"
25
+ :style="{ width: boxWidth + 'px' }"
26
+ @input="filerList"
27
+ @click="isOpen = true"
28
+ />
29
+ <m-list-box
30
+ :open="isOpen"
31
+ :items="sort ? orderedItems() : itemListForDropdown"
32
+ :multiple="multiple"
33
+ :empty-search-label="emptySearchLabel"
34
+ :style="{ width: boxWidth + 'px' }"
35
+ @update:itemSelected="updateList"
36
+ @close-list-box="isOpen = false"
37
+ >
38
+ <template #item="{ item }">
39
+ <slot name="item" :item="item"> </slot>
40
+ </template>
41
+ </m-list-box>
42
+ </div>
43
+ </template>
44
+
45
+ <script>
46
+ import MTextInput from '../textinput/MTextInput';
47
+ import MTag from '../tags/MTag';
48
+ import MListBox from '../listbox/MListBox';
49
+
50
+ export default {
51
+ name: 'MAutocomplete',
52
+
53
+ components: { MListBox, MTag, MTextInput },
54
+
55
+ props: {
56
+ multiple: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
60
+ placeholder: {
61
+ type: String,
62
+ default: '',
63
+ },
64
+ items: {
65
+ type: Array,
66
+ required: true,
67
+ default: () => [],
68
+ },
69
+ filter: {
70
+ type: Function,
71
+ default: null,
72
+ },
73
+ emptySearchLabel: {
74
+ type: String,
75
+ default: 'No item matching your criteria found',
76
+ },
77
+ sort: {
78
+ type: Boolean,
79
+ default: false,
80
+ },
81
+ labelTag: {
82
+ type: String,
83
+ default: '',
84
+ },
85
+ open: {
86
+ type: Boolean,
87
+ default: false,
88
+ },
89
+ },
90
+ data() {
91
+ return {
92
+ itemListForDropdown: this.$props.items,
93
+ selected: this.$props.items,
94
+ itemDisplayed: '',
95
+ isOpen: this.$props.open,
96
+ tagWidth: '0px',
97
+ boxWidth: '288px',
98
+ };
99
+ },
100
+ computed: {
101
+ tagStyle() {
102
+ return {
103
+ '--tag-width': this.tagWidth,
104
+ };
105
+ },
106
+ boxStyle() {
107
+ return {
108
+ '--box-width': this.boxWidth,
109
+ };
110
+ },
111
+ },
112
+ mounted() {
113
+ this.selectedItems();
114
+ this.tagWidthCalcul();
115
+ this.boxWidthCalcul();
116
+ },
117
+ methods: {
118
+ tagWidthCalcul() {
119
+ this.$nextTick(() => {
120
+ this.tagWidth =
121
+ document && document.querySelector('.mc-autocomplete__tag')
122
+ ? document.querySelector('.mc-autocomplete__tag').clientWidth + 'px'
123
+ : '0px';
124
+ });
125
+ },
126
+ selectedItems() {
127
+ return this.selected.filter((item) => {
128
+ return item.selected;
129
+ });
130
+ },
131
+ orderedItems() {
132
+ this.itemListForDropdown.sort((a, b) => {
133
+ if (a.selected === b.selected) {
134
+ return a.id - b.id;
135
+ } else if (a.selected < b.selected) {
136
+ return 1;
137
+ } else {
138
+ return -1;
139
+ }
140
+ });
141
+ },
142
+ updateList(list) {
143
+ if (!this.$props.multiple && list) {
144
+ this.itemDisplayed = list[0].text;
145
+ } else {
146
+ this.isOpen = true;
147
+ this.selectedItems();
148
+ }
149
+ this.itemListForDropdown.forEach((elem) => {
150
+ if (elem.id === list.id) {
151
+ elem.selected = false;
152
+ }
153
+ });
154
+ this.tagWidthCalcul();
155
+ this.$emit(
156
+ 'update:modelValue',
157
+ this.$props.multiple ? this.selectedItems().value : list
158
+ );
159
+ },
160
+ removeElementsFromList() {
161
+ this.itemListForDropdown.forEach((elem) => {
162
+ elem.selected = false;
163
+ });
164
+ this.selectedItems();
165
+ this.tagWidthCalcul();
166
+ this.$emit('list-removed');
167
+ },
168
+ filerList(value) {
169
+ if (value.length && this.$props.filter) {
170
+ this.$props.filter(value);
171
+ } else if (value.length) {
172
+ this.itemListForDropdown = this.itemListForDropdown.filter((item) =>
173
+ item.text.toUpperCase().includes(value.toUpperCase())
174
+ );
175
+ } else {
176
+ this.itemListForDropdown = this.$props.items;
177
+ }
178
+ this.$emit('list-filtered', this.itemListForDropdown);
179
+ },
180
+ boxWidthCalcul() {
181
+ this.$nextTick(() => {
182
+ this.boxWidth = document.querySelector('.mc-autocomplete').clientWidth;
183
+ console.log(this.boxWidth);
184
+ });
185
+ return;
186
+ },
187
+ },
188
+ };
189
+ </script>
190
+
191
+ <style lang="scss">
192
+ @import 'settings-tools/_all-settings';
193
+ @import 'components/_c.autocomplete';
194
+
195
+ .mc-autocomplete--multi .mc-autocomplete__trigger {
196
+ padding-left: calc(2.9375rem + var(--tag-width));
197
+ }
198
+ </style>
@@ -0,0 +1,7 @@
1
+ import MAutocomplete from './MAutocomplete.vue';
2
+
3
+ MAutocomplete.install = function (Vue) {
4
+ Vue.component(MAutocomplete.name, MAutocomplete);
5
+ };
6
+
7
+ export { MAutocomplete };
@@ -5,6 +5,7 @@
5
5
  :class="imageratio ? `mc-card__visual--${imageratio}` : ''"
6
6
  >
7
7
  <img :src="imgSrc" :loading="lazy ? 'lazy' : 'eager'" :alt="imgAlt" class="mc-card__img" />
8
+ <slot name="image" />
8
9
  </figure>
9
10
  <article class="mc-card__content">
10
11
  <component :is="titleTag" class="mc-card__title">
@@ -18,13 +18,19 @@
18
18
  :class="{ 'mc-field__container--inline': inline }"
19
19
  >
20
20
  <m-checkbox
21
- v-for="option in options"
21
+ v-for="(option, index) in options"
22
22
  v-bind="option"
23
23
  :key="option.id ? option.id : option.value"
24
24
  class="mc-field__item"
25
25
  :checked="value ? value.includes(option.value) : undefined"
26
26
  @change="(v) => onChange(v, option.value)"
27
- />
27
+ >
28
+ <template #label>
29
+ <slot :name="`label${index + 1}`">
30
+ {{ option.label }}
31
+ </slot>
32
+ </template>
33
+ </m-checkbox>
28
34
  </div>
29
35
  <span
30
36
  v-if="errorId && errorMessage"
@@ -26,6 +26,8 @@ export default {
26
26
  </script>
27
27
 
28
28
  <style lang="scss">
29
- @import 'settings-tools/_all-settings';
30
- @import 'layouts/_l.container';
29
+ @import 'settings-tools/all-settings';
30
+ @import 'layouts/l.container';
31
+ @import 'utilities/u.margin';
32
+ @import 'utilities/u.padding';
31
33
  </style>
@@ -16,6 +16,7 @@
16
16
  type="button"
17
17
  class="mc-fileuploader__delete"
18
18
  :aria-label="removeLabel"
19
+ :disabled="disabled"
19
20
  @click="deleteFile(file)"
20
21
  ></button>
21
22
  <div
@@ -53,6 +54,10 @@ export default {
53
54
  type: String,
54
55
  default: '',
55
56
  },
57
+ disabled: {
58
+ type: Boolean,
59
+ default: false,
60
+ },
56
61
  },
57
62
  watch: {
58
63
  files: {
@@ -33,6 +33,7 @@
33
33
  :files="uploadedFiles"
34
34
  :allowed-extensions="allowedExtensions"
35
35
  :remove-label="removeLabel"
36
+ :disabled="disabled"
36
37
  @file-removed="deleteRemoteFile"
37
38
  />
38
39
  </div>
@@ -4,6 +4,7 @@ export { MContainer } from './container';
4
4
  export { MHeading } from './heading';
5
5
  // Components
6
6
  export { MAccordion } from './accordion';
7
+ export { MAutocomplete } from './autocomplete';
7
8
  export { MBadge } from './badge';
8
9
  export { MBreadcrumb } from './breadcrumb';
9
10
  export { MButton } from './button';
@@ -17,6 +18,7 @@ export { MHero } from './hero';
17
18
  export { MIcon } from './icon';
18
19
  export { MLayer } from './layer';
19
20
  export { MLink } from './link';
21
+ export { MListBox } from './listbox';
20
22
  export { MLoader } from './loader';
21
23
  export { MModal } from './modal';
22
24
  export { MNotification } from './notification';
@@ -0,0 +1,106 @@
1
+ <template>
2
+ <ul
3
+ v-if="items.length > 0"
4
+ ref="listbox"
5
+ role="listbox"
6
+ class="mc-listbox"
7
+ aria-labelledby="listbox"
8
+ :class="{ 'is-open': open, 'mc-listbox--multi': multiple }"
9
+ >
10
+ <li
11
+ v-for="item in selectableItems"
12
+ :key="item.id"
13
+ class="mc-listbox__item"
14
+ @change="$emit('update:itemSelected', item)"
15
+ @click.self="updateList(item.id, item.text, !item.selected, true)"
16
+ >
17
+ <slot name="item" :item="item">
18
+ <span class="mc-listbox__text">{{ item.text }} </span>
19
+ </slot>
20
+ <m-checkbox
21
+ v-if="multiple"
22
+ :id="`checkbox-dropdown-${item.id}`"
23
+ v-model="selectableItems.find((elem) => elem.id === item.id).selected"
24
+ class="mc-listbox__input"
25
+ @change="updateList(item.id, item.text, !item.selected, $e)"
26
+ />
27
+ </li>
28
+ </ul>
29
+ <div v-else class="mc-list-box__empty">
30
+ {{ emptySearchLabel }}
31
+ </div>
32
+ </template>
33
+ <script>
34
+ import MCheckbox from '../checkbox/MCheckbox';
35
+ export default {
36
+ name: 'MListbox',
37
+
38
+ components: { MCheckbox },
39
+
40
+ props: {
41
+ open: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
45
+ items: {
46
+ type: Array,
47
+ default: () => [],
48
+ },
49
+ multiple: {
50
+ type: Boolean,
51
+ default: false,
52
+ },
53
+ emptySearchLabel: {
54
+ type: String,
55
+ default: 'No item matching your criteria found',
56
+ },
57
+ icon: {
58
+ type: Boolean,
59
+ default: false,
60
+ },
61
+ },
62
+ data() {
63
+ return {
64
+ selectableItems: null,
65
+ selected: [],
66
+ };
67
+ },
68
+ watch: {
69
+ items: {
70
+ handler: function (val) {
71
+ this.selectableItems = val;
72
+ },
73
+ immediate: true,
74
+ },
75
+ },
76
+ methods: {
77
+ updateList(id, text, value, isCheckboxUpdate) {
78
+ if (!this.multiple) {
79
+ this.$emit('update:itemSelected', [{ id, selected: value, text }]);
80
+
81
+ this.$emit('close-list-box');
82
+ return;
83
+ }
84
+
85
+ if (
86
+ isCheckboxUpdate &&
87
+ this.selectableItems.find((item) => item.id === id)
88
+ ) {
89
+ this.selectableItems.find((item) => item.id === id).selected = value;
90
+ }
91
+
92
+ if (value) {
93
+ this.selected = [...this.selected, { id, selected: value, text }];
94
+ } else {
95
+ this.selected = this.selected.filter((item) => item.id !== id);
96
+ }
97
+ this.$emit('update:itemSelected', this.selectableItems);
98
+ },
99
+ },
100
+ };
101
+ </script>
102
+
103
+ <style lang="scss">
104
+ @import 'settings-tools/_all-settings';
105
+ @import 'components/_c.listbox';
106
+ </style>
@@ -0,0 +1,7 @@
1
+ import MListBox from './MListBox.vue';
2
+
3
+ MListBox.install = function (Vue) {
4
+ Vue.component(MListBox.name, MListBox);
5
+ };
6
+
7
+ export { MListBox };
@@ -119,6 +119,8 @@ export default {
119
119
  input,
120
120
  select,
121
121
  textarea,
122
+ label,
123
+ .mc-option-card__focusable,
122
124
  [tabindex]:not([tabindex='-1']) {
123
125
  position: relative;
124
126
  }
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div :class="['mc-tabs', setClasses]">
3
3
  <ul
4
- v-if="type != 'dropdown'"
4
+ v-if="type !== 'dropdown'"
5
5
  ref="tablist"
6
6
  class="mc-tabs__nav"
7
7
  role="tablist"
@@ -82,6 +82,10 @@ export default {
82
82
  type: Object,
83
83
  default: null,
84
84
  },
85
+ activeIndex: {
86
+ type: Number,
87
+ default: 0,
88
+ },
85
89
  },
86
90
 
87
91
  data() {
@@ -105,17 +109,33 @@ export default {
105
109
  },
106
110
  },
107
111
 
112
+ watch: {
113
+ activeIndex(newValue) {
114
+ const tab = this.getTabFromIndex(newValue);
115
+ if (tab && this.tabs[newValue]) {
116
+ this.manageTabs(tab, null, Object.assign({index: newValue}, this.tabs[newValue]));
117
+ }
118
+ }
119
+ },
120
+
108
121
  mounted: function () {
109
122
  this.$nextTick(() => {
110
123
  if (this.type === 'tabs') {
111
124
  this.tablist = this.$refs.tablist;
112
125
 
113
- const isActive = this.tabs.some((tab) =>
114
- Object.prototype.hasOwnProperty.call(tab, 'active')
115
- );
116
- if (!isActive) {
117
- const firstTab = this.tablist.querySelector('.mc-tabs__link');
118
- this.manageTabs(firstTab);
126
+ if (this.activeIndex) {
127
+ const tab = this.getTabFromIndex(this.activeIndex);
128
+ if (tab) {
129
+ this.manageTabs(tab);
130
+ }
131
+ } else {
132
+ const isActive = this.tabs.some((tab) =>
133
+ Object.prototype.hasOwnProperty.call(tab, 'active')
134
+ );
135
+ if (!isActive) {
136
+ const firstTab = this.tablist.querySelector('.mc-tabs__link');
137
+ this.manageTabs(firstTab);
138
+ }
119
139
  }
120
140
  }
121
141
  });
@@ -136,6 +156,9 @@ export default {
136
156
  return tabClasses;
137
157
  },
138
158
  manageTabs: function (el, e, tab) {
159
+ if (tab && tab.disabled) {
160
+ return;
161
+ }
139
162
  if (e) {
140
163
  this.$emit('tab-clicked', e.target, tab);
141
164
  }
@@ -148,6 +171,11 @@ export default {
148
171
  el.classList.add('mc-tabs__link--selected');
149
172
  el.setAttribute('aria-selected', 'true');
150
173
  },
174
+ getTabFromIndex: function (index) {
175
+ if (this.tablist && this.tablist.children[index] && this.tablist.children[index].children[0]) {
176
+ return this.tablist.children[index].children[0];
177
+ }
178
+ },
151
179
  },
152
180
  };
153
181
  </script>
@@ -24,7 +24,11 @@
24
24
  class="mc-tag-selectable__input"
25
25
  type="checkbox"
26
26
  :name="name"
27
+ :value="value"
28
+ :checked="checked"
29
+ :required="required"
27
30
  :disabled="disabled"
31
+ @change="$emit('change', $event.target.checked)"
28
32
  />
29
33
  <label class="mc-tag-selectable__pill" :for="id">
30
34
  <span class="mc-tag-selectable__label">
@@ -57,6 +61,11 @@ import {
57
61
  export default {
58
62
  name: 'MTag',
59
63
 
64
+ model: {
65
+ prop: 'checked',
66
+ event: 'change',
67
+ },
68
+
60
69
  props: {
61
70
  label: {
62
71
  type: String,
@@ -80,10 +89,22 @@ export default {
80
89
  type: String,
81
90
  default: null,
82
91
  },
92
+ value: {
93
+ type: String,
94
+ default: null,
95
+ },
96
+ checked: {
97
+ type: Boolean,
98
+ default: false,
99
+ },
83
100
  disabled: {
84
101
  type: Boolean,
85
102
  default: false,
86
103
  },
104
+ required: {
105
+ type: Boolean,
106
+ default: false,
107
+ },
87
108
  size: {
88
109
  type: String,
89
110
  default: 'm',
@@ -9,6 +9,7 @@
9
9
  <m-text-input-field
10
10
  ref="mField"
11
11
  v-bind="[$attrs, $props]"
12
+ :class="textInputFieldClass"
12
13
  v-on="$listeners"
13
14
  />
14
15
  </div>
@@ -48,6 +49,10 @@ export default {
48
49
  type: String,
49
50
  default: null,
50
51
  },
52
+ textInputFieldClass: {
53
+ type: String,
54
+ default: null,
55
+ },
51
56
  },
52
57
  };
53
58
  </script>
package/src/index.js CHANGED
@@ -23,6 +23,7 @@ export { MContainer } from './components/container/';
23
23
  export { MHeading } from './components/heading';
24
24
  // Components
25
25
  export { MAccordion } from './components/accordion/';
26
+ export { MAutocomplete } from './components/autocomplete';
26
27
  export { MBadge } from './components/badge/';
27
28
  export { MBreadcrumb } from './components/breadcrumb/';
28
29
  export { MButton } from './components/button/';
@@ -36,6 +37,7 @@ export { MHero } from './components/hero';
36
37
  export { MIcon } from './components/icon';
37
38
  export { MLayer } from './components/layer';
38
39
  export { MLink } from './components/link';
40
+ export { MListBox } from './components/listbox';
39
41
  export { MLoader } from './components/loader';
40
42
  export { MModal } from './components/modal';
41
43
  export { MNotification } from './components/notification';