@mozaic-ds/vue 0.35.0-beta.4 → 0.35.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mozaic-ds/vue",
3
- "version": "0.35.0-beta.4",
3
+ "version": "0.35.0",
4
4
  "description": "Vue.js implementation of Mozaic Design System",
5
5
  "author": "Adeo - Mozaic Design System",
6
6
  "scripts": {
@@ -23,9 +23,10 @@
23
23
  "postinstall.js"
24
24
  ],
25
25
  "dependencies": {
26
+ "@linusborg/vue-simple-portal": "^0.1.5",
26
27
  "@mozaic-ds/css-dev-tools": "1.50.0",
27
- "@mozaic-ds/icons": "1.49.0",
28
- "@mozaic-ds/styles": "1.51.0",
28
+ "@mozaic-ds/icons": "1.52.0",
29
+ "@mozaic-ds/styles": "1.52.0",
29
30
  "@mozaic-ds/web-fonts": "1.22.0",
30
31
  "core-js": "^3.27.1",
31
32
  "libphonenumber-js": "^1.10.15",
@@ -34,7 +34,7 @@
34
34
  />
35
35
  <MLoader v-if="loading" class="mc-autocomplete__loader" size="s" />
36
36
  <button
37
- v-if="hasValues"
37
+ v-if="isClearable"
38
38
  type="button"
39
39
  class="mc-autocomplete__clear"
40
40
  @click="onClear"
@@ -193,6 +193,11 @@ export default {
193
193
  type: Boolean,
194
194
  default: true,
195
195
  },
196
+ // Clear Button
197
+ clearable: {
198
+ type: Boolean,
199
+ default: true,
200
+ },
196
201
  // Global
197
202
  maxWidth: {
198
203
  type: String,
@@ -218,7 +223,7 @@ export default {
218
223
  classObject() {
219
224
  return {
220
225
  'mc-autocomplete--multi': this.multiple,
221
- 'mc-autocomplete--clearable': this.hasValues,
226
+ 'mc-autocomplete--clearable': this.isClearable,
222
227
  };
223
228
  },
224
229
  setStyles() {
@@ -230,8 +235,8 @@ export default {
230
235
  setTagLabel() {
231
236
  return this.listboxValue.length.toString() + ' ' + this.tagLabel;
232
237
  },
233
- hasValues() {
234
- return this.inputValue?.length > 0;
238
+ isClearable() {
239
+ return this.clearable && this.inputValue?.length > 0 && !this.disabled;
235
240
  },
236
241
  isInvalid() {
237
242
  return this.invalid || this.isFiltered;
@@ -250,7 +255,6 @@ export default {
250
255
  },
251
256
  localItems: {
252
257
  handler: function (val) {
253
- // this.localItems = val;
254
258
  this.isFiltered = !val.length;
255
259
  this.$emit('list-filtered', val);
256
260
  },
@@ -327,22 +331,13 @@ export default {
327
331
  if (value.length && this.filter) {
328
332
  this.filter(value);
329
333
  } else {
330
- if (!this.filterOnType) {
331
- return;
332
- }
333
-
334
334
  if (value.length) {
335
335
  this.localItems = this.items.filter((item) =>
336
336
  item[this.dataTextExpr].toUpperCase().includes(value.toUpperCase())
337
337
  );
338
-
339
- // this.isFiltered = !this.localItems.length;
340
338
  } else {
341
339
  this.localItems = this.items;
342
- // this.isFiltered = !this.localItems.length;
343
340
  }
344
-
345
- // this.$emit('list-filtered', this.localItems);
346
341
  }
347
342
  },
348
343
  closeListBox() {
@@ -396,7 +391,10 @@ export default {
396
391
  this.$emit('clear-input');
397
392
  }
398
393
  this.$emit('update:input', value);
399
- this.filterList(value);
394
+
395
+ if (this.filterOnType) {
396
+ this.filterList(value);
397
+ }
400
398
  },
401
399
  },
402
400
  };
@@ -4,61 +4,70 @@
4
4
  ref="trigger"
5
5
  type="button"
6
6
  class="mc-listbox-options__trigger"
7
- @click="onClickTrigger($event)"
7
+ @click="onClickTrigger"
8
8
  >
9
9
  <MIcon :name="icon" :color="triggerIconColor" />
10
10
  <span class="mc-listbox-options__trigger-label">{{ triggerLabel }}</span>
11
11
  </button>
12
- <div
13
- v-show="isOpen"
14
- ref="listbox"
15
- class="mc-listbox-options__container"
16
- :class="classObjectListbox"
17
- :style="styleObjectListbox"
18
- role="listbox"
19
- aria-labelledby="listbox"
20
- >
21
- <ul
22
- v-for="(list, i) in getItems"
23
- :key="`list${i}`"
24
- class="mc-listbox-options__list"
25
- >
26
- <li
27
- v-for="(item, j) in list"
28
- :key="`item${j}`"
29
- class="mc-listbox-options__tile"
30
- :class="{ 'is-disabled': item.disabled }"
12
+ <Portal>
13
+ <transition @after-enter="onAfterEnter">
14
+ <div
15
+ v-if="isOpen"
16
+ ref="listbox"
17
+ class="mc-listbox-options__container"
18
+ :class="classObjectListbox"
19
+ :style="styleObjectListbox"
20
+ role="listbox"
21
+ aria-labelledby="listbox"
31
22
  >
32
- <MIcon
33
- v-if="item.icon"
34
- :name="item.icon"
35
- class="mc-listbox-options__icon"
36
- :color="item.danger ? '#C61112' : '#71706B'"
37
- />
38
- <component
39
- :is="item.href ? 'a' : 'button'"
40
- :href="item.href ? item.href : null"
41
- :type="item.href ? null : 'button'"
42
- :disabled="item.disabled ? true : null"
43
- class="mc-listbox-options__item"
44
- :class="{ 'is-danger': item.danger, 'is-disabled': item.disabled }"
45
- @click.self="onClickItem(item, i, j)"
23
+ <ul
24
+ v-for="(list, i) in getItems"
25
+ :key="`list${i}`"
26
+ class="mc-listbox-options__list"
46
27
  >
47
- {{ item.text }}
48
- </component>
49
- </li>
50
- </ul>
51
- </div>
28
+ <li
29
+ v-for="(item, j) in list"
30
+ :key="`item${j}`"
31
+ class="mc-listbox-options__tile"
32
+ :class="{ 'is-disabled': item.disabled }"
33
+ >
34
+ <MIcon
35
+ v-if="item.icon"
36
+ :name="item.icon"
37
+ class="mc-listbox-options__icon"
38
+ :color="item.danger ? '#C61112' : '#71706B'"
39
+ />
40
+ <component
41
+ :is="item.href ? 'a' : 'button'"
42
+ :href="item.href ? item.href : null"
43
+ :type="item.href ? null : 'button'"
44
+ :disabled="item.disabled ? true : null"
45
+ class="mc-listbox-options__item"
46
+ :class="{
47
+ 'is-danger': item.danger,
48
+ 'is-disabled': item.disabled,
49
+ }"
50
+ @click.self="onClickItem(item, i, j)"
51
+ >
52
+ {{ item.text }}
53
+ </component>
54
+ </li>
55
+ </ul>
56
+ </div>
57
+ </transition>
58
+ </Portal>
52
59
  </div>
53
60
  </template>
54
61
 
55
62
  <script>
63
+ import { Portal } from '@linusborg/vue-simple-portal';
56
64
  import MIcon from '../icon/MIcon.vue';
57
65
 
58
66
  export default {
59
67
  name: 'MListBoxActions',
60
68
  components: {
61
69
  MIcon,
70
+ Portal,
62
71
  },
63
72
  directives: {
64
73
  'click-outside': {
@@ -76,6 +85,10 @@ export default {
76
85
  },
77
86
  },
78
87
  props: {
88
+ items: {
89
+ type: Array,
90
+ default: () => [],
91
+ },
79
92
  open: {
80
93
  type: Boolean,
81
94
  default: false,
@@ -84,10 +97,6 @@ export default {
84
97
  type: String,
85
98
  default: 'left',
86
99
  },
87
- items: {
88
- type: Array,
89
- default: () => [],
90
- },
91
100
  triggerLabel: {
92
101
  type: String,
93
102
  default: 'Display options',
@@ -104,16 +113,16 @@ export default {
104
113
  data() {
105
114
  return {
106
115
  isOpen: this.open,
116
+ isVisible: false,
107
117
  displayTop: false,
108
118
  listboxTop: '0px',
109
119
  listboxLeft: '0px',
110
120
  };
111
121
  },
112
-
113
122
  computed: {
114
123
  classObjectListbox() {
115
124
  return {
116
- 'is-open': this.isOpen,
125
+ 'is-open': this.isVisible,
117
126
  'align-right': this.position == 'right',
118
127
  'align-top': this.displayTop,
119
128
  };
@@ -137,9 +146,6 @@ export default {
137
146
  return this.items;
138
147
  },
139
148
  },
140
- mounted() {
141
- this.teleport(this.$refs.listbox);
142
- },
143
149
  created() {
144
150
  window.addEventListener('scroll', this.closeListbox, {
145
151
  capture: true,
@@ -157,29 +163,21 @@ export default {
157
163
  this.$emit('update:itemSelected', valToEmit); // TODO: deprecated
158
164
  this.$emit('item-clicked', valToEmit);
159
165
  },
160
- onClickTrigger(e) {
161
- this.$nextTick(() => {
162
- if (this.$refs.listbox.clientHeight + e.clientY >= window.innerHeight) {
163
- this.displayTop = true;
164
- }
165
- });
166
-
166
+ onClickTrigger() {
167
167
  this.isOpen = !this.isOpen;
168
-
169
- this.setListBoxPosition();
170
168
  },
171
169
  setListBoxPosition() {
172
- const { top, left, height } = this.$refs.trigger.getBoundingClientRect();
173
- const topValue = Math.floor(top) + Math.floor(height) + window.scrollY;
170
+ const trigger = this.$refs.trigger;
171
+ const listboxHeight = this.$refs.listbox.clientHeight;
172
+
173
+ const { top, left, bottom } = trigger.getBoundingClientRect();
174
+ const topValue = Math.floor(bottom) + window.scrollY;
174
175
  const leftValue = Math.floor(left);
175
176
  this.listboxTop = `${topValue}px`;
176
177
  this.listboxLeft = `${leftValue}px`;
177
- },
178
- teleport(elToMove, elTarget) {
179
- const target = elTarget ?? document.body;
180
178
 
181
- if (target && elToMove) {
182
- target.append(elToMove);
179
+ if (top > listboxHeight && listboxHeight + bottom >= window.innerHeight) {
180
+ this.displayTop = true;
183
181
  }
184
182
  },
185
183
  closeListbox() {
@@ -187,6 +185,11 @@ export default {
187
185
  return;
188
186
  }
189
187
  this.isOpen = false;
188
+ this.isVisible = false;
189
+ },
190
+ onAfterEnter() {
191
+ this.setListBoxPosition();
192
+ this.isVisible = true;
190
193
  },
191
194
  },
192
195
  };
@@ -22,7 +22,10 @@
22
22
  :class="setActiveClass(tab)"
23
23
  active-class="mc-tabs__element--selected"
24
24
  >
25
- <span class="mc-tabs__text">{{ tab.text }}</span>
25
+ <span class="mc-tabs__text">
26
+ <MIcon v-if="tab.icon" :name="tab.icon" class="mc-tabs__icon" />
27
+ {{ tab.text }}
28
+ </span>
26
29
  </component>
27
30
  <component
28
31
  :is="tab.href ? (tab.disabled ? 'span' : 'a') : 'button'"
@@ -44,7 +47,10 @@
44
47
  )
45
48
  "
46
49
  >
47
- <span class="mc-tabs__text">{{ tab.text }}</span>
50
+ <span class="mc-tabs__text">
51
+ <MIcon v-if="tab.icon" :name="tab.icon" class="mc-tabs__icon" />
52
+ {{ tab.text }}
53
+ </span>
48
54
  </component>
49
55
  </li>
50
56
  </ul>
@@ -53,12 +59,14 @@
53
59
  </template>
54
60
 
55
61
  <script>
62
+ import MIcon from '../icon/MIcon.vue';
56
63
  import MSelect from '../select/MSelect.vue';
57
64
 
58
65
  export default {
59
66
  name: 'MTab',
60
67
 
61
68
  components: {
69
+ MIcon,
62
70
  MSelect,
63
71
  },
64
72