@mozaic-ds/vue 0.20.0-beta.4 → 0.20.0-beta.5

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.20.0-beta.4",
3
+ "version": "0.20.0-beta.5",
4
4
  "description": "Vue.js implementation of Mozaic Design System",
5
5
  "author": "Adeo - Mozaic Design System",
6
6
  "scripts": {
@@ -1,102 +1,70 @@
1
1
  <template>
2
2
  <div
3
3
  ref="autocomplete"
4
- v-click-outside="onClickOutside"
5
4
  class="mc-autocomplete"
6
5
  :class="{ 'mc-autocomplete--multi': multiple }"
7
6
  :style="tagStyle"
7
+ @keyup.esc="isOpen = true"
8
8
  >
9
9
  <m-tag
10
- v-if="multiple && tagValue.length > 1"
10
+ v-if="multiple && selectedItems().length > 0"
11
+ id="tag"
11
12
  type="removable"
12
- :label="tagValue.length.toString() + ' ' + tagLabel"
13
+ :label="selectedItems().length.toString() + ' ' + labelTag"
13
14
  class="mc-autocomplete__tag"
14
15
  size="s"
15
- @remove-tag="clearAutocomplete()"
16
+ @remove-tag="removeElementsFromList()"
16
17
  />
17
18
  <m-text-input
18
- v-model="inputValue"
19
+ v-model="itemDisplayed"
19
20
  :placeholder="placeholder"
20
21
  text-input-field-class="mc-autocomplete__trigger"
21
22
  icon-position="left"
22
23
  icon="DisplaySearch48"
23
24
  autocomplete="off"
24
- @input="filterList"
25
+ :style="{ width: boxWidth + 'px' }"
26
+ @input="filerList"
25
27
  @click="isOpen = true"
26
28
  />
27
29
  <m-list-box
28
- v-model="listboxValue"
29
30
  :open="isOpen"
30
- :items="itemListForDropdown"
31
+ :items="sort ? orderedItems() : itemListForDropdown"
31
32
  :multiple="multiple"
32
33
  :empty-search-label="emptySearchLabel"
33
- :data-key-expr="dataKeyExpr"
34
- :data-text-expr="dataTextExpr"
35
- :data-value-expr="dataValueExpr"
36
- @change="onChange"
34
+ :style="{ width: boxWidth + 'px' }"
35
+ @update:itemSelected="updateList"
36
+ @close-list-box="isOpen = false"
37
37
  >
38
38
  <template #item="{ item }">
39
- <slot name="item" :item="item" />
39
+ <slot name="item" :item="item"> </slot>
40
40
  </template>
41
41
  </m-list-box>
42
42
  </div>
43
43
  </template>
44
44
 
45
45
  <script>
46
- import MListBox from '../listbox/MListBox.vue';
47
- import MTag from '../tags/MTag.vue';
48
46
  import MTextInput from '../textinput/MTextInput.vue';
47
+ import MTag from '../tags/MTag.vue';
48
+ import MListBox from '../listbox/MListBox.vue';
49
49
 
50
50
  export default {
51
51
  name: 'MAutocomplete',
52
52
 
53
- components: {
54
- MListBox,
55
- MTag,
56
- MTextInput,
57
- },
58
-
59
- directives: {
60
- 'click-outside': {
61
- bind(el, binding, vnode) {
62
- el.clickOutsideEvent = (event) => {
63
- if (!(el === event.target || el.contains(event.target))) {
64
- vnode.context[binding.expression](event);
65
- }
66
- };
67
- document.body.addEventListener('click', el.clickOutsideEvent);
68
- },
69
- unbind(el) {
70
- document.body.removeEventListener('click', el.clickOutsideEvent);
71
- },
72
- },
73
- },
74
-
75
- model: {
76
- event: 'change',
77
- },
53
+ components: { MListBox, MTag, MTextInput },
78
54
 
79
55
  props: {
80
- open: {
56
+ multiple: {
81
57
  type: Boolean,
82
58
  default: false,
83
59
  },
84
- tagLabel: {
85
- type: String,
86
- default: 'voitures',
87
- },
88
60
  placeholder: {
89
61
  type: String,
90
62
  default: '',
91
63
  },
92
64
  items: {
93
65
  type: Array,
94
- default: () => [],
95
66
  required: true,
96
- },
97
- multiple: {
98
- type: Boolean,
99
- default: false,
67
+ default: () => [],
100
68
  },
101
69
  filter: {
102
70
  type: Function,
@@ -106,80 +74,48 @@ export default {
106
74
  type: String,
107
75
  default: 'No item matching your criteria found',
108
76
  },
109
- dataKeyExpr: {
110
- type: String,
111
- default: 'id',
112
- },
113
- dataTextExpr: {
114
- type: String,
115
- default: 'text',
77
+ sort: {
78
+ type: Boolean,
79
+ default: false,
116
80
  },
117
- dataValueExpr: {
81
+ labelTag: {
118
82
  type: String,
119
- default: 'text',
83
+ default: '',
120
84
  },
121
- value: {
122
- type: Array,
123
- default: () => [],
85
+ open: {
86
+ type: Boolean,
87
+ default: false,
124
88
  },
125
89
  },
126
-
127
90
  data() {
128
91
  return {
129
- itemListForDropdown: this.items,
130
- selected: this.items,
92
+ itemListForDropdown: this.$props.items,
93
+ selected: this.$props.items,
131
94
  itemDisplayed: '',
132
- isOpen: this.open,
95
+ isOpen: this.$props.open,
133
96
  tagWidth: '0px',
134
- uuid: undefined,
135
- tagValue: '',
136
- inputValue: '',
137
- listboxValue: [],
97
+ boxWidth: '288px',
138
98
  };
139
99
  },
140
-
141
100
  computed: {
142
101
  tagStyle() {
143
102
  return {
144
103
  '--tag-width': this.tagWidth,
145
104
  };
146
105
  },
147
- },
148
-
149
- watch: {
150
- listboxValue: function (newValue) {
151
- if (newValue.length === 1) {
152
- const valueToDisplay = this.items.find(
153
- (item) => item.value == newValue
154
- );
155
- this.inputValue = valueToDisplay.text;
156
- } else {
157
- this.inputValue = '';
158
- this.tagValue = newValue;
159
- }
160
- },
161
-
162
- tagValue: {
163
- handler: function () {
164
- this.setTagWidth();
165
- },
166
- immediate: true,
167
- },
168
-
169
- value: {
170
- handler: function (value) {
171
- this.listboxValue = value;
172
- },
173
- immediate: true,
106
+ boxStyle() {
107
+ return {
108
+ '--box-width': this.boxWidth,
109
+ };
174
110
  },
175
111
  },
176
-
177
112
  mounted() {
178
- this.uuid = this._uid;
113
+ this.selectedItems();
114
+ this.tagWidthCalcul();
115
+ this.boxWidthCalcul();
179
116
  },
180
-
181
117
  methods: {
182
- setTagWidth() {
118
+ tagWidthCalcul() {
183
119
  this.$nextTick(() => {
184
120
  this.tagWidth =
185
121
  document && document.querySelector('.mc-autocomplete__tag')
@@ -187,45 +123,74 @@ export default {
187
123
  : '0px';
188
124
  });
189
125
  },
190
-
191
- clearAutocomplete() {
192
- this.listboxValue = [];
193
- this.onChange();
194
- this.$emit('clear');
126
+ selectedItems() {
127
+ return this.selected.filter((item) => {
128
+ return item.selected;
129
+ });
195
130
  },
196
-
197
- filterList(value) {
198
- if (value.length && this.filter) {
199
- this.filter(value);
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);
200
171
  } else if (value.length) {
201
172
  this.itemListForDropdown = this.itemListForDropdown.filter((item) =>
202
173
  item.text.toUpperCase().includes(value.toUpperCase())
203
174
  );
204
175
  } else {
205
- this.itemListForDropdown = this.items;
176
+ this.itemListForDropdown = this.$props.items;
206
177
  }
207
178
  this.$emit('list-filtered', this.itemListForDropdown);
208
179
  },
209
-
210
- onClickOutside() {
211
- this.isOpen = false;
212
- },
213
-
214
- onChange() {
215
- this.$emit('change', this.listboxValue);
180
+ boxWidthCalcul() {
181
+ this.$nextTick(() => {
182
+ this.boxWidth = document.querySelector('.mc-autocomplete').clientWidth;
183
+ console.log(this.boxWidth);
184
+ });
185
+ return;
216
186
  },
217
187
  },
218
188
  };
219
-
220
- // TODO:
221
- // - boxWidth ?
222
- // - dataSelectedExpr ?
223
189
  </script>
224
190
 
225
191
  <style lang="scss">
226
- @import 'settings-tools/all-settings';
227
- @import 'components/c.checkbox';
228
- @import 'components/c.autocomplete';
192
+ @import 'settings-tools/_all-settings';
193
+ @import 'components/_c.autocomplete';
229
194
 
230
195
  .mc-autocomplete--multi .mc-autocomplete__trigger {
231
196
  padding-left: calc(2.9375rem + var(--tag-width));
@@ -18,7 +18,7 @@ export { MHero } from './hero';
18
18
  export { MIcon } from './icon';
19
19
  export { MLayer } from './layer';
20
20
  export { MLink } from './link';
21
- export { MListBox } from './listbox';
21
+ export { MListBox, MListBoxOptions } from './listbox';
22
22
  export { MLoader } from './loader';
23
23
  export { MModal } from './modal';
24
24
  export { MNotification } from './notification';
@@ -7,23 +7,22 @@
7
7
  aria-labelledby="listbox"
8
8
  :class="{ 'is-open': open, 'mc-listbox--multi': multiple }"
9
9
  >
10
- <li v-for="item in selectableItems" :key="item.id" class="mc-listbox__item">
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
+ >
11
17
  <slot name="item" :item="item">
12
- <label
13
- :for="`checkbox-dropdown-${item[dataKeyExpr]}-${uuid}`"
14
- class="mc-listbox__label"
15
- >{{ item[dataTextExpr] }}
16
- </label>
18
+ <span class="mc-listbox__text">{{ item.text }} </span>
17
19
  </slot>
18
- <input
19
- :id="`checkbox-dropdown-${item[dataKeyExpr]}-${uuid}`"
20
- ref="input"
21
- v-model="localValue"
22
- class="mc-checkbox__input mc-listbox__input"
23
- :class="{ hideCheckbox: !multiple }"
24
- type="checkbox"
25
- :value="item.value"
26
- @change="onChange"
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)"
27
26
  />
28
27
  </li>
29
28
  </ul>
@@ -31,14 +30,12 @@
31
30
  {{ emptySearchLabel }}
32
31
  </div>
33
32
  </template>
34
-
35
33
  <script>
34
+ import MCheckbox from '../checkbox/MCheckbox.vue';
36
35
  export default {
37
36
  name: 'MListbox',
38
37
 
39
- model: {
40
- event: 'change',
41
- },
38
+ components: { MCheckbox },
42
39
 
43
40
  props: {
44
41
  open: {
@@ -61,34 +58,13 @@ export default {
61
58
  type: Boolean,
62
59
  default: false,
63
60
  },
64
- dataKeyExpr: {
65
- type: String,
66
- default: 'id',
67
- },
68
- dataTextExpr: {
69
- type: String,
70
- default: 'text',
71
- },
72
- dataValueExpr: {
73
- type: String,
74
- default: 'text',
75
- },
76
- value: {
77
- type: [Array, String],
78
- default: undefined,
79
- },
80
61
  },
81
-
82
62
  data() {
83
63
  return {
84
64
  selectableItems: null,
85
- localValue: [],
86
65
  selected: [],
87
- uuid: null,
88
- inputBaseId: 'listboxInput',
89
66
  };
90
67
  },
91
-
92
68
  watch: {
93
69
  items: {
94
70
  handler: function (val) {
@@ -96,180 +72,35 @@ export default {
96
72
  },
97
73
  immediate: true,
98
74
  },
99
- value: {
100
- handler: function (value) {
101
- this.localValue = value;
102
- },
103
- immediate: true,
104
- },
105
- localValue: {
106
- handler: function (localValue) {
107
- const inputs = this.$refs.input;
108
- if (!this.multiple && inputs) {
109
- const selectedValue = Array.from(localValue);
110
-
111
- inputs.forEach(function (input) {
112
- const listItem = input.closest('.mc-listbox__item');
113
-
114
- if (input.value == selectedValue[0]) {
115
- listItem.classList.add('is-checked');
116
- } else {
117
- listItem.classList.remove('is-checked');
118
- }
119
- });
120
- }
121
- },
122
- immediate: true,
123
- },
124
75
  },
125
-
126
- mounted() {
127
- this.uuid = Math.random();
128
- },
129
-
130
76
  methods: {
131
- onChange() {
77
+ updateList(id, text, value, isCheckboxUpdate) {
132
78
  if (!this.multiple) {
133
- const currentValue = this.localValue;
134
- this.localValue = [];
135
- this.localValue = currentValue.slice(-1);
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;
136
90
  }
137
91
 
138
- this.$emit('change', this.localValue);
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);
139
98
  },
140
99
  },
141
100
  };
142
101
  </script>
143
102
 
144
103
  <style lang="scss">
145
- @import 'settings-tools/all-settings';
146
-
147
- .mc-listbox {
148
- $parent: get-parent-selector(&);
149
-
150
- @include unstyle-list();
151
-
152
- background-color: $color-grey-000;
153
- border: 1px solid $color-grey-600;
154
- border-radius: 3px;
155
- position: absolute;
156
- overflow-y: auto;
157
- margin-top: 5px;
158
- margin-bottom: 0;
159
- // max-height: 13.5rem;
160
- // min-width: 18rem;
161
- opacity: 0;
162
- visibility: hidden;
163
- width: 100%;
164
-
165
- &.is-open {
166
- opacity: 1;
167
- visibility: visible;
168
- z-index: 11;
169
- }
170
-
171
- &::-webkit-scrollbar {
172
- background-color: $color-grey-100;
173
- width: $mu025;
174
-
175
- &-thumb {
176
- background: $color-grey-600;
177
- }
178
- }
179
-
180
- &__item {
181
- align-items: center;
182
- display: flex;
183
- gap: $mu050;
184
- min-height: $mu300;
185
- padding-left: $mu075;
186
- padding-right: $mu075;
187
- position: relative;
188
- justify-content: space-between;
189
-
190
- &:not(:last-child) {
191
- border-bottom: 1px solid $color-grey-300;
192
- }
193
-
194
- &:hover {
195
- background-color: $color-grey-100;
196
- box-shadow: inset 9px 0 0 -7px $color-grey-900;
197
- }
198
- }
199
-
200
- &__flag,
201
- &__icon {
202
- width: $mu200;
203
- height: $mu200;
204
- }
205
-
206
- &__flag {
207
- @include set-font-scale('07', 'm');
208
-
209
- text-align: center;
210
- }
211
-
212
- &__empty {
213
- align-items: center;
214
- border: 1px solid $color-grey-600;
215
- border-radius: get-border-radius('m');
216
- padding: $mu100 $mu050;
217
- }
218
-
219
- &__label {
220
- cursor: pointer;
221
-
222
- &::after {
223
- content: '';
224
- position: absolute;
225
- inset: 0;
226
- z-index: 2;
227
- }
228
- }
229
-
230
- &__input {
231
- position: absolute;
232
- right: $mu075;
233
- }
234
-
235
- .is-focus {
236
- background-color: $color-grey-100;
237
- box-shadow: inset 9px 0 0 -7px $color-grey-900;
238
- }
239
-
240
- .is-disabled {
241
- cursor: not-allowed;
242
- box-shadow: none;
243
- background-color: $color-grey-200;
244
- color: $color-grey-600;
245
- pointer-events: none;
246
- }
247
-
248
- &--left {
249
- right: 0;
250
- transform: translateX(-100%);
251
- }
252
-
253
- &:not(.mc-listbox--multi) {
254
- .is-checked {
255
- background-size: $mu150;
256
- background-image: url(inline-icons(
257
- 'notification-available-24',
258
- $color-grey-900
259
- ));
260
- background-repeat: no-repeat;
261
- background-position: right $mu075 center;
262
- }
263
-
264
- #{$parent} {
265
- &__input {
266
- @include visually-hidden();
267
- }
268
- }
269
- }
270
- }
271
-
272
- .hideCheckbox {
273
- opacity: 0;
274
- }
104
+ @import 'settings-tools/_all-settings';
105
+ @import 'components/_c.listbox';
275
106
  </style>