@mozaic-ds/vue 1.0.0-rc.0 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +10 -8
  2. package/dist/mozaic-vue.adeo.css +45 -43
  3. package/dist/mozaic-vue.adeo.umd.js +11552 -22322
  4. package/dist/mozaic-vue.common.js +11552 -22322
  5. package/dist/mozaic-vue.common.js.map +1 -1
  6. package/dist/mozaic-vue.css +1 -1
  7. package/dist/mozaic-vue.umd.js +11552 -22322
  8. package/dist/mozaic-vue.umd.js.map +1 -1
  9. package/dist/mozaic-vue.umd.min.js +2 -2
  10. package/dist/mozaic-vue.umd.min.js.map +1 -1
  11. package/package.json +24 -23
  12. package/src/components/autocomplete/MAutocomplete.vue +294 -111
  13. package/src/components/checkbox/MCheckboxGroup.vue +8 -0
  14. package/src/components/dropdown/MDropdown.vue +316 -0
  15. package/src/components/dropdown/index.js +7 -0
  16. package/src/components/flag/MFlag.vue +1 -1
  17. package/src/components/icon/MIcon.vue +18 -2
  18. package/src/components/index.js +2 -1
  19. package/src/components/link/MLink.vue +14 -3
  20. package/src/components/listbox/MListBox.vue +97 -57
  21. package/src/components/listbox/MListBoxActions.vue +251 -0
  22. package/src/components/listbox/index.js +6 -1
  23. package/src/components/phonenumber/MPhoneNumber.vue +10 -3
  24. package/src/components/quantityselector/MQuantitySelector.vue +15 -2
  25. package/src/components/ratingstars/MStarsInput.vue +1 -0
  26. package/src/components/stepper/MStepper.vue +68 -27
  27. package/src/components/tabs/MTab.vue +69 -59
  28. package/src/components/textinput/MTextInputField.vue +0 -1
  29. package/src/index.js +2 -1
  30. package/src/tokens/adeo/android/colors.xml +183 -126
  31. package/src/tokens/adeo/css/_variables.scss +183 -126
  32. package/src/tokens/adeo/css/root.scss +80 -23
  33. package/src/tokens/adeo/ios/StyleDictionaryColor.h +60 -3
  34. package/src/tokens/adeo/ios/StyleDictionaryColor.m +187 -130
  35. package/src/tokens/adeo/ios/StyleDictionaryColor.swift +183 -126
  36. package/src/tokens/adeo/js/tokens.js +183 -126
  37. package/src/tokens/adeo/js/tokensObject.js +1570 -283
  38. package/src/tokens/adeo/scss/_tokens.scss +342 -128
  39. package/types/index.d.ts +4 -0
@@ -0,0 +1,316 @@
1
+ <template>
2
+ <div
3
+ ref="dropdown"
4
+ v-click-outside="onClickOutside"
5
+ class="mc-dropdown"
6
+ :class="{ 'mc-dropdown--multi': multiple }"
7
+ :style="setStyles"
8
+ >
9
+ <MTag
10
+ v-if="multiple && listboxValue.length > 0"
11
+ :id="tagId ? tagId : `autoCompleteTag-${uuid}`"
12
+ ref="tag"
13
+ :label="setTagLabel"
14
+ :disabled="disabled"
15
+ type="removable"
16
+ class="mc-dropdown__tag"
17
+ size="s"
18
+ @remove-tag="clearAutocomplete()"
19
+ />
20
+ <button
21
+ type="button"
22
+ class="mc-select mc-dropdown__trigger"
23
+ :class="{ 'is-open': openState }"
24
+ @click="openState = !openState"
25
+ >
26
+ {{ buttonValue }}
27
+ </button>
28
+ <MListBox
29
+ v-model="listboxValue"
30
+ :open="openState"
31
+ :items="localItems"
32
+ :multiple="multiple"
33
+ :empty-search-label="emptySearchLabel"
34
+ :data-key-expr="dataKeyExpr"
35
+ :data-text-expr="dataTextExpr"
36
+ :data-value-expr="dataValueExpr"
37
+ @change="onChange"
38
+ >
39
+ <template #item="{ item }">
40
+ <slot name="item" :item="item"></slot>
41
+ </template>
42
+ </MListBox>
43
+ </div>
44
+ </template>
45
+
46
+ <script>
47
+ import MTag from '../tags/MTag.vue';
48
+ import MListBox from '../listbox/MListBox.vue';
49
+
50
+ export default {
51
+ name: 'MDropdown',
52
+
53
+ components: {
54
+ MTag,
55
+ MListBox,
56
+ },
57
+
58
+ directives: {
59
+ 'click-outside': {
60
+ bind(el, binding, vnode) {
61
+ el.clickOutsideEvent = (event) => {
62
+ if (!(el === event.target || el.contains(event.target))) {
63
+ vnode.context[binding.expression](event);
64
+ }
65
+ };
66
+ document.body.addEventListener('click', el.clickOutsideEvent);
67
+ },
68
+ unbind(el) {
69
+ document.body.removeEventListener('click', el.clickOutsideEvent);
70
+ },
71
+ },
72
+ },
73
+
74
+ model: {
75
+ event: 'change',
76
+ },
77
+
78
+ props: {
79
+ // Tag Element
80
+ tagId: {
81
+ type: String,
82
+ default: null,
83
+ },
84
+ tagLabel: {
85
+ type: String,
86
+ default: '',
87
+ },
88
+ // Input Element
89
+ placeholder: {
90
+ type: String,
91
+ default: '-- Placeholder --',
92
+ },
93
+ filter: {
94
+ type: Function,
95
+ default: null,
96
+ },
97
+ disabled: {
98
+ type: Boolean,
99
+ default: false,
100
+ },
101
+ // Listbox Element
102
+ items: {
103
+ type: Array,
104
+ required: true,
105
+ },
106
+ value: {
107
+ type: [Array, String, Number],
108
+ default: undefined,
109
+ },
110
+ open: {
111
+ type: Boolean,
112
+ default: false,
113
+ },
114
+ multiple: {
115
+ type: Boolean,
116
+ default: false,
117
+ },
118
+ emptySearchLabel: {
119
+ type: String,
120
+ default: 'No results found',
121
+ },
122
+ dataKeyExpr: {
123
+ type: String,
124
+ default: 'id',
125
+ },
126
+ dataTextExpr: {
127
+ type: String,
128
+ default: 'label',
129
+ },
130
+ dataValueExpr: {
131
+ type: String,
132
+ default: 'value',
133
+ },
134
+ sort: {
135
+ type: Boolean,
136
+ default: true,
137
+ },
138
+ // Global
139
+ maxWidth: {
140
+ type: String,
141
+ default: '17.875rem',
142
+ },
143
+ },
144
+
145
+ data() {
146
+ return {
147
+ uuid: Math.random(),
148
+ openState: this.open,
149
+ tagWidth: '0px',
150
+ tagValue: null,
151
+ buttonValue: this.placeholder,
152
+ localItems: null,
153
+ sortedListItems: null,
154
+ listboxValue: null,
155
+ };
156
+ },
157
+
158
+ computed: {
159
+ setTagLabel() {
160
+ return this.listboxValue.length.toString() + ' ' + this.tagLabel;
161
+ },
162
+ setStyles() {
163
+ return {
164
+ '--tag-width': this.tagWidth,
165
+ '--max-width': this.maxWidth,
166
+ };
167
+ },
168
+ },
169
+
170
+ watch: {
171
+ value: {
172
+ handler: function (val) {
173
+ if (!val && this.multiple) {
174
+ this.listboxValue = [];
175
+ } else {
176
+ this.listboxValue = val;
177
+ }
178
+ },
179
+ immediate: true,
180
+ },
181
+
182
+ items: {
183
+ handler: function (val) {
184
+ this.localItems = val;
185
+ // this.clearAutocomplete();
186
+ },
187
+ immediate: true,
188
+ },
189
+
190
+ listboxValue: function (val) {
191
+ const value = Array.isArray(val) ? val : val.toString();
192
+ const selectedItems = this.getSelectedItems(value);
193
+
194
+ const seletedLabels = selectedItems.map(
195
+ (item) => item[this.dataTextExpr]
196
+ );
197
+
198
+ this.buttonValue = seletedLabels.join(', ');
199
+
200
+ if (val.length === 0) {
201
+ this.buttonValue = this.placeholder;
202
+ }
203
+
204
+ if (this.multiple) {
205
+ this.tagValue = val;
206
+ }
207
+ },
208
+
209
+ tagValue: function () {
210
+ this.setTagWidth();
211
+ },
212
+
213
+ openState: function (val) {
214
+ const eventName = val ? 'open' : 'close';
215
+ this.$emit(eventName);
216
+ this.$emit('update:open', val);
217
+ },
218
+ },
219
+
220
+ methods: {
221
+ setTagWidth() {
222
+ this.$nextTick(() => {
223
+ if (this.$refs.tag && this.$refs.tag.$el) {
224
+ this.tagWidth = this.$refs.tag.$el.clientWidth + 8 + 'px';
225
+ } else {
226
+ this.tagWidth = '0px';
227
+ }
228
+ });
229
+ },
230
+
231
+ clearAutocomplete() {
232
+ this.listboxValue = this.multiple ? [] : undefined;
233
+ this.onChange();
234
+ this.$emit('clear');
235
+ },
236
+
237
+ onClickOutside() {
238
+ this.openState = false;
239
+
240
+ if (this.multiple && this.sort) {
241
+ this.sortItems();
242
+ } else {
243
+ this.localItems = this.items;
244
+ }
245
+ },
246
+
247
+ onChange() {
248
+ this.$emit('change', this.listboxValue);
249
+
250
+ if (!this.multiple) {
251
+ this.onClickOutside();
252
+ }
253
+ },
254
+
255
+ getSelectedItems(val) {
256
+ const value = val ? val : this.listboxValue;
257
+
258
+ const selectedItems = this.items.filter((item) =>
259
+ value.includes(item[this.dataValueExpr])
260
+ );
261
+
262
+ return selectedItems;
263
+ },
264
+
265
+ sortItems() {
266
+ this.sortedListItems = this.items;
267
+ const selectedItems = this.getSelectedItems();
268
+
269
+ this.sortedListItems.sort((a, b) => {
270
+ const hasItemA = selectedItems.includes(a);
271
+ const hasItemB = selectedItems.includes(b);
272
+
273
+ if (hasItemA === hasItemB) {
274
+ return a[this.dataValueExpr] - b[this.dataValueExpr];
275
+ } else if (hasItemA < hasItemB) {
276
+ return 1;
277
+ } else {
278
+ return -1;
279
+ }
280
+ });
281
+ },
282
+ },
283
+ };
284
+ </script>
285
+
286
+ <style lang="scss">
287
+ @import 'settings-tools/all-settings';
288
+ @import 'components/c.checkbox';
289
+ @import 'components/_c.dropdown';
290
+
291
+ .mc-dropdown {
292
+ max-width: var(--max-width);
293
+
294
+ &__tag {
295
+ position: absolute;
296
+ top: 0;
297
+ transform: translateY(50%);
298
+ }
299
+
300
+ &__trigger {
301
+ display: block;
302
+ text-align: left;
303
+
304
+ &.is-open {
305
+ background-image: url(inline-icons('arrow-top-16', black));
306
+ }
307
+ }
308
+ }
309
+
310
+ .mc-dropdown--multi .mc-dropdown__trigger {
311
+ overflow: hidden;
312
+ padding-left: calc(0.75rem + var(--tag-width));
313
+ text-overflow: ellipsis;
314
+ white-space: nowrap;
315
+ }
316
+ </style>
@@ -0,0 +1,7 @@
1
+ import MDropdown from './MDropdown.vue';
2
+
3
+ MDropdown.install = function (Vue) {
4
+ Vue.component(MDropdown.name, MDropdown);
5
+ };
6
+
7
+ export { MDropdown };
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <component :is="htmlTag" class="mc-flag" :class="setClasses">
3
- {{ label }}
3
+ <span class="mc-flag__label">{{ label }}</span>
4
4
  </component>
5
5
  </template>
6
6
 
@@ -25,6 +25,7 @@ export default {
25
25
  viewbox: null,
26
26
  size: null,
27
27
  paths: null,
28
+ type: null,
28
29
  };
29
30
  },
30
31
 
@@ -79,8 +80,17 @@ export default {
79
80
  this.viewbox = selectedIcon.viewBox;
80
81
  this.size = selectedIcon.size;
81
82
  this.paths = selectedIcon.paths;
83
+ this.type = selectedIcon.type;
82
84
  });
83
85
  },
86
+ setSizeFromViewbox(viewbox) {
87
+ const viewboxSizes = viewbox.split(' ').filter((size) => size > 0);
88
+
89
+ return {
90
+ width: `${viewboxSizes[0]}px`,
91
+ height: `${viewboxSizes[1]}px`,
92
+ };
93
+ },
84
94
  },
85
95
 
86
96
  render: function (createElement) {
@@ -88,8 +98,14 @@ export default {
88
98
  const svgAttrs = {
89
99
  id: `MIcon-${this.name}-${this.id}`,
90
100
  viewBox: this.viewbox,
91
- height: this.size,
92
- width: this.size,
101
+ height:
102
+ this.type !== 'logotypes'
103
+ ? this.size
104
+ : this.setSizeFromViewbox(this.viewbox).height,
105
+ width:
106
+ this.type !== 'logotypes'
107
+ ? this.size
108
+ : this.setSizeFromViewbox(this.viewbox).width,
93
109
  fill: this.color,
94
110
  'aria-hidden': 'true',
95
111
  };
@@ -12,13 +12,14 @@ export { MCard } from './card';
12
12
  export { MCheckbox, MCheckboxGroup } from './checkbox';
13
13
  export { MDataTable, MDataTableHeader } from './datatable';
14
14
  export { MField } from './field';
15
+ export { MDropdown } from './dropdown';
15
16
  export { MFileUploader } from './fileuploader';
16
17
  export { MFlag } from './flag';
17
18
  export { MHero } from './hero';
18
19
  export { MIcon } from './icon';
19
20
  export { MLayer } from './layer';
20
21
  export { MLink } from './link';
21
- export { MListBox } from './listbox';
22
+ export { MListBox, MListBoxActions } from './listbox';
22
23
  export { MLoader } from './loader';
23
24
  export { MModal } from './modal';
24
25
  export { MNotification } from './notification';
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <component
3
- :is="router ? router : href && !disabled ? 'a' : 'span'"
3
+ :is="linkComponentName"
4
+ v-bind="linkComponentProps"
4
5
  :href="router ? null : href && !disabled ? href : null"
5
6
  class="mc-link"
6
7
  :class="setClasses"
@@ -37,7 +38,7 @@ export default {
37
38
 
38
39
  props: {
39
40
  router: {
40
- type: [String, Object],
41
+ type: Object,
41
42
  default: null,
42
43
  },
43
44
  href: {
@@ -105,10 +106,20 @@ export default {
105
106
 
106
107
  return classes;
107
108
  },
109
+ linkComponentName() {
110
+ const isLinkValid = this.href && !this.disabled;
111
+ const routerComponent = this.router?.name ?? null;
112
+ const defaultComponent = isLinkValid ? 'a' : 'span';
113
+
114
+ return routerComponent ?? defaultComponent;
115
+ },
116
+ linkComponentProps() {
117
+ return this.router?.props ?? {};
118
+ },
108
119
  },
109
120
  methods: {
110
121
  onClick(event) {
111
- if(!this.disabled){
122
+ if (!this.disabled) {
112
123
  this.$emit('click', event);
113
124
  }
114
125
  },
@@ -1,50 +1,72 @@
1
1
  <template>
2
2
  <ul
3
- v-if="items.length > 0"
4
- ref="listbox"
5
3
  role="listbox"
6
4
  class="mc-listbox"
7
5
  aria-labelledby="listbox"
8
6
  :class="{ 'is-open': open, 'mc-listbox--multi': multiple }"
7
+ :style="{ '--listbox-width': maxWidth }"
9
8
  >
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
- />
9
+ <template v-if="!isFiltered">
10
+ <li
11
+ v-for="(item, index) in localItems"
12
+ :key="item.id"
13
+ class="mc-listbox__item"
14
+ >
15
+ <MIcon
16
+ v-if="item.icon"
17
+ :name="item.icon"
18
+ class="mc-listbox__icon"
19
+ color="#666666"
20
+ />
21
+ <input
22
+ :id="setItemId(index)"
23
+ v-model="localValue"
24
+ class="mc-listbox__input"
25
+ :class="{ 'mc-checkbox__input': multiple }"
26
+ :type="multiple ? 'checkbox' : 'radio'"
27
+ :value="item[dataValueExpr]"
28
+ :name="!multiple ? `listboxradio-${uuid}` : null"
29
+ @change="onChange"
30
+ />
31
+ <label :for="setItemId(index)" class="mc-listbox__label">
32
+ <slot name="item" :item="item">
33
+ {{ item[dataTextExpr] }}
34
+ </slot>
35
+ </label>
36
+ </li>
37
+ </template>
38
+ <li v-else class="mc-listbox__item">
39
+ <span class="mc-listbox__empty">{{ emptySearchLabel }}</span>
27
40
  </li>
28
41
  </ul>
29
- <div v-else class="mc-list-box__empty">
30
- {{ emptySearchLabel }}
31
- </div>
32
42
  </template>
43
+
33
44
  <script>
34
- import MCheckbox from '../checkbox/MCheckbox.vue';
45
+ import MIcon from '../icon/MIcon.vue';
46
+
35
47
  export default {
36
- name: 'MListbox',
48
+ name: 'MListBox',
37
49
 
38
- components: { MCheckbox },
50
+ components: {
51
+ MIcon,
52
+ },
53
+
54
+ model: {
55
+ event: 'change',
56
+ },
39
57
 
40
58
  props: {
59
+ items: {
60
+ type: Array,
61
+ required: true,
62
+ },
41
63
  open: {
42
64
  type: Boolean,
43
65
  default: false,
44
66
  },
45
- items: {
46
- type: Array,
47
- default: () => [],
67
+ isFiltered: {
68
+ type: Boolean,
69
+ default: false,
48
70
  },
49
71
  multiple: {
50
72
  type: Boolean,
@@ -54,53 +76,71 @@ export default {
54
76
  type: String,
55
77
  default: 'No item matching your criteria found',
56
78
  },
57
- icon: {
58
- type: Boolean,
59
- default: false,
79
+ dataKeyExpr: {
80
+ type: String,
81
+ default: 'id',
82
+ },
83
+ dataTextExpr: {
84
+ type: String,
85
+ default: 'label',
86
+ },
87
+ dataValueExpr: {
88
+ type: String,
89
+ default: 'value',
90
+ },
91
+ value: {
92
+ type: [Array, String, Number],
93
+ default: undefined,
94
+ },
95
+ maxWidth: {
96
+ type: String,
97
+ default: '17.875rem',
60
98
  },
61
99
  },
100
+
62
101
  data() {
63
102
  return {
64
- selectableItems: null,
65
- selected: [],
103
+ uuid: Math.random(),
104
+ localItems: undefined,
105
+ localValue: undefined,
66
106
  };
67
107
  },
108
+
109
+ computed: {
110
+ setItemId() {
111
+ return (index) => `listboxItem-${index + this.uuid}`;
112
+ },
113
+ },
114
+
68
115
  watch: {
69
116
  items: {
70
117
  handler: function (val) {
71
- this.selectableItems = val;
118
+ this.localItems = val;
119
+ },
120
+ immediate: true,
121
+ },
122
+ value: {
123
+ handler: function (val) {
124
+ this.localValue = val;
72
125
  },
73
126
  immediate: true,
74
127
  },
75
128
  },
76
- methods: {
77
- updateList(id, text, value, isCheckboxUpdate) {
78
- if (!this.multiple) {
79
- this.$emit('update:itemSelected', [{ id, selected: value, text }]);
80
129
 
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);
130
+ methods: {
131
+ onChange() {
132
+ this.$emit('change', this.localValue);
98
133
  },
99
134
  },
100
135
  };
101
136
  </script>
102
137
 
103
138
  <style lang="scss">
104
- @import 'settings-tools/_all-settings';
105
- @import 'components/_c.listbox';
139
+ @import 'settings-tools/all-settings';
140
+ @import 'components/c.checkbox';
141
+ @import 'components/c.listbox';
142
+
143
+ .mc-listbox__empty {
144
+ margin-top: 0;
145
+ }
106
146
  </style>