@mozaic-ds/vue 0.20.0-beta.3 → 0.20.0-beta.6

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