@mozaic-ds/vue 0.11.2-beta.0 → 0.13.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.11.2-beta.0",
3
+ "version": "0.13.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.20.0",
16
+ "@mozaic-ds/css-dev-tools": "^1.24.0",
17
17
  "@mozaic-ds/icons": "^1.20.0",
18
- "@mozaic-ds/styles": "^1.23.0",
18
+ "@mozaic-ds/styles": "^1.24.1",
19
19
  "@mozaic-ds/web-fonts": "^1.22.0",
20
20
  "core-js": "^3.18.3",
21
21
  "libphonenumber-js": "^1.9.37",
@@ -26,9 +26,8 @@
26
26
  "devDependencies": {
27
27
  "@babel/core": "^7.15.8",
28
28
  "@babel/eslint-parser": "^7.15.8",
29
- "@vue/cli-plugin-babel": "^4.5.13",
30
- "@vue/cli-plugin-eslint": "^4.5.13",
31
- "@vue/cli-service": "^4.5.13",
29
+ "@vue/cli-plugin-babel": "^4.5.15",
30
+ "@vue/cli-service": "^4.5.15",
32
31
  "@vue/compiler-sfc": "^3.2.20",
33
32
  "@vue/eslint-config-prettier": "^6.0.0",
34
33
  "babel-eslint": "^10.1.0",
@@ -2,20 +2,22 @@
2
2
  <div class="mc-accordion" :class="{ 'mc-accordion--s': size === 's' }">
3
3
  <input
4
4
  :id="id"
5
- v-model="checked"
5
+ ref="checkbox"
6
6
  type="checkbox"
7
7
  class="mc-accordion__trigger"
8
8
  :disabled="disabled"
9
+ :checked="open"
10
+ @change="$emit('update:open', $event.target.checked)"
9
11
  />
10
12
  <div
11
13
  :class="['mc-accordion__header', setHeaderClasses]"
12
- :aria-expanded="checked"
13
- @click="onClick"
14
+ :aria-expanded="open"
15
+ @click="$refs.checkbox.click()"
14
16
  >
15
17
  <slot name="beforeLabel" />
16
18
  <label
17
19
  :for="id"
18
- :aria-expanded="checked"
20
+ :aria-expanded="open"
19
21
  :class="['mc-accordion__header__label', setLabelClasses]"
20
22
  @click.stop
21
23
  >
@@ -40,6 +42,11 @@ export default {
40
42
  MIcon,
41
43
  },
42
44
 
45
+ model: {
46
+ prop: 'open',
47
+ event: 'change',
48
+ },
49
+
43
50
  props: {
44
51
  id: {
45
52
  type: String,
@@ -72,12 +79,6 @@ export default {
72
79
  },
73
80
  },
74
81
 
75
- data: function () {
76
- return {
77
- checked: this.open,
78
- };
79
- },
80
-
81
82
  computed: {
82
83
  setHeaderClasses() {
83
84
  return {
@@ -95,23 +96,6 @@ export default {
95
96
  };
96
97
  },
97
98
  },
98
-
99
- watch: {
100
- open: function () {
101
- this.checked = !this.checked;
102
- },
103
- checked: function () {
104
- this.$emit('update:open', this.checked);
105
- },
106
- },
107
-
108
- methods: {
109
- onClick() {
110
- if (this.disabled === false) {
111
- this.checked = !this.checked;
112
- }
113
- },
114
- },
115
99
  };
116
100
  </script>
117
101
 
@@ -22,6 +22,7 @@
22
22
  ]"
23
23
  :aria-current="index != items.length - 1 ? null : 'page'"
24
24
  size="s"
25
+ :router="item.router"
25
26
  @click="$emit('link-clicked', item)"
26
27
  >
27
28
  {{ item.text }}
@@ -23,6 +23,9 @@
23
23
  <script>
24
24
  export default {
25
25
  name: 'MField',
26
+ provide: {
27
+ cssFieldElementClass: 'mc-field__element',
28
+ },
26
29
  props: {
27
30
  id: {
28
31
  type: String,
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="mc-fileuploader">
2
+ <div class="mc-fileuploader" :class="cssFieldElementClass">
3
3
  <input
4
4
  :id="id"
5
5
  ref="fileUpload"
@@ -45,6 +45,11 @@ export default {
45
45
  components: {
46
46
  MFileResult,
47
47
  },
48
+ inject: {
49
+ cssFieldElementClass: {
50
+ default: '',
51
+ },
52
+ },
48
53
  inheritAttrs: false,
49
54
  props: {
50
55
  id: {
@@ -19,7 +19,9 @@ export { MLayer } from './layer';
19
19
  export { MLink } from './link';
20
20
  export { MModal } from './modal';
21
21
  export { MNotification } from './notification';
22
+ export { MOptionButton } from './optionbutton';
22
23
  export { MPagination } from './pagination';
24
+ export { MPasswordInput } from './passwordinput';
23
25
  export { MPhoneNumber } from './phonenumber';
24
26
  export { MProgress } from './progressbar';
25
27
  export { MQuantitySelector } from './quantityselector';
@@ -7,6 +7,7 @@
7
7
  role="dialog"
8
8
  aria-labelledby="modal_title"
9
9
  :aria-hidden="!open"
10
+ @keyup.esc="closeModal()"
10
11
  >
11
12
  <div
12
13
  class="mc-modal__dialog"
@@ -26,7 +27,6 @@
26
27
  ref="close"
27
28
  class="mc-modal__close"
28
29
  type="button"
29
- @keyup.esc="closeModal()"
30
30
  @click="closeModal()"
31
31
  >
32
32
  <span class="mc-modal__close-text">
@@ -101,6 +101,7 @@ export default {
101
101
  this.$nextTick(() => {
102
102
  if (isOpen) {
103
103
  this.trapFocus();
104
+ this.setFocusOnModal();
104
105
  this.setOverflow();
105
106
  this.$emit('modal-opened');
106
107
  } else {
@@ -158,6 +159,12 @@ export default {
158
159
  modal.classList.add('mc-modal--overflow');
159
160
  }
160
161
  },
162
+
163
+ setFocusOnModal() {
164
+ const modal = this.$refs.modal;
165
+
166
+ modal.focus();
167
+ },
161
168
  },
162
169
  };
163
170
  </script>
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <div class="mc-option-group">
3
+ <template v-for="(option, index) in options">
4
+ <div
5
+ :key="index"
6
+ class="mc-option-button"
7
+ :class="{ 'mc-option-button--full': option.full }"
8
+ >
9
+ <input
10
+ :id="option.id"
11
+ type="radio"
12
+ class="mc-option-button__input"
13
+ :name="option.name"
14
+ :value="option.value"
15
+ :disabled="option.disabled"
16
+ :checked="checked"
17
+ @change="$emit('change', $event.target.checked)"
18
+ />
19
+ <label :for="option.id" class="mc-option-button__label">
20
+ {{ option.label }}
21
+ </label>
22
+ </div>
23
+ </template>
24
+ </div>
25
+ </template>
26
+
27
+ <script>
28
+ export default {
29
+ name: 'MOptionButton',
30
+
31
+ model: {
32
+ prop: 'checked',
33
+ event: 'change',
34
+ },
35
+
36
+ props: {
37
+ options: {
38
+ type: Array,
39
+ required: true,
40
+ },
41
+ checked: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
45
+ },
46
+ };
47
+ </script>
48
+
49
+ <style lang="scss">
50
+ @import 'settings-tools/_all-settings';
51
+ @import 'components/c.option-button';
52
+ </style>
@@ -0,0 +1,7 @@
1
+ import MOptionButton from './MOptionButton.vue';
2
+
3
+ MOptionButton.install = function (Vue) {
4
+ Vue.component(MOptionButton.name, MOptionButton);
5
+ };
6
+
7
+ export { MOptionButton };
@@ -0,0 +1,96 @@
1
+ <template>
2
+ <div class="mc-password-input" :class="cssFieldElementClass">
3
+ <input
4
+ :type="setType"
5
+ :required="required"
6
+ class="mc-text-input mc-password-input__control"
7
+ :class="setInputClasses"
8
+ :aria-invalid="isInvalid"
9
+ />
10
+
11
+ <button
12
+ ref="button"
13
+ type="button"
14
+ class="mc-password-input__button"
15
+ role="switch"
16
+ :aria-pressed="setAriaPressed"
17
+ @click="onClick"
18
+ >
19
+ {{ setButtonLabel }}
20
+ </button>
21
+ </div>
22
+ </template>
23
+
24
+ <script>
25
+ export default {
26
+ name: 'MPasswordInput',
27
+
28
+ inject: {
29
+ cssFieldElementClass: {
30
+ default: '',
31
+ },
32
+ },
33
+
34
+ props: {
35
+ required: {
36
+ type: Boolean,
37
+ default: false,
38
+ },
39
+ value: {
40
+ type: [String, Number],
41
+ default: null,
42
+ },
43
+ isValid: {
44
+ type: Boolean,
45
+ default: false,
46
+ },
47
+ isInvalid: {
48
+ type: Boolean,
49
+ default: false,
50
+ },
51
+ buttonLabel: {
52
+ type: Object,
53
+ default: function () {
54
+ return { show: 'Show', hide: 'Hide' };
55
+ },
56
+ },
57
+ },
58
+
59
+ data: function () {
60
+ return {
61
+ isVisible: false,
62
+ };
63
+ },
64
+
65
+ computed: {
66
+ setType() {
67
+ return this.isVisible ? 'text' : 'password';
68
+ },
69
+ setInputClasses() {
70
+ return {
71
+ 'is-valid': this.isValid,
72
+ 'is-invalid': this.isInvalid,
73
+ };
74
+ },
75
+ setAriaPressed() {
76
+ return this.isVisible ? 'true' : 'false';
77
+ },
78
+ setButtonLabel() {
79
+ return this.isVisible ? this.buttonLabel.hide : this.buttonLabel.show;
80
+ },
81
+ },
82
+
83
+ methods: {
84
+ onClick() {
85
+ const aria = this.$refs.button.getAttribute('aria-pressed') === 'false';
86
+ this.isVisible = aria;
87
+ },
88
+ },
89
+ };
90
+ </script>
91
+
92
+ <style lang="scss">
93
+ @import 'settings-tools/_all-settings';
94
+ @import 'components/_c.text-input';
95
+ @import 'components/_c.password-input';
96
+ </style>
@@ -0,0 +1,7 @@
1
+ import MPasswordInput from './MPasswordInput.vue';
2
+
3
+ MPasswordInput.install = function (Vue) {
4
+ Vue.component(MPasswordInput.name, MPasswordInput);
5
+ };
6
+
7
+ export { MPasswordInput };
@@ -1,7 +1,10 @@
1
1
  <template>
2
2
  <div
3
3
  class="mc-phone-number"
4
- :class="{ 'mc-phone-number--focused': isCountriesListOpened }"
4
+ :class="[
5
+ { 'mc-phone-number--focused': isCountriesListOpened },
6
+ cssFieldElementClass,
7
+ ]"
5
8
  >
6
9
  <div
7
10
  v-if="isCountriesListOpened"
@@ -72,9 +75,11 @@
72
75
  :placeholder="placeholder"
73
76
  :maxlength="maxlength"
74
77
  @blur="onChangePhoneNumber"
75
- @focus="(event) => formatOnBlur ? cleanFormat(event) : null"
78
+ @focus="(event) => (formatOnBlur ? cleanFormat(event) : null)"
76
79
  @keyup="onKeyPressPhoneNumber"
77
- @keydown.backspace="(event) => formatOnBlur ? null : backspaceFunction(event)"
80
+ @keydown.backspace="
81
+ (event) => (formatOnBlur ? null : backspaceFunction(event))
82
+ "
78
83
  />
79
84
  </div>
80
85
  </template>
@@ -85,7 +90,7 @@ import CountryFlag from 'vue-country-flag';
85
90
  import {
86
91
  parsePhoneNumber,
87
92
  formatIncompletePhoneNumber,
88
- AsYouType
93
+ AsYouType,
89
94
  } from 'libphonenumber-js';
90
95
  import { getExampleNumber } from 'libphonenumber-js/max';
91
96
  import examples from 'libphonenumber-js/examples.mobile.json';
@@ -95,6 +100,11 @@ export default {
95
100
  components: {
96
101
  CountryFlag,
97
102
  },
103
+ inject: {
104
+ cssFieldElementClass: {
105
+ default: '',
106
+ },
107
+ },
98
108
  props: {
99
109
  countries: {
100
110
  type: Array,
@@ -156,7 +166,10 @@ export default {
156
166
  init() {
157
167
  if (this.hasValue) {
158
168
  try {
159
- const parsedValue = parsePhoneNumber(this.value, this.countries[0].shortName);
169
+ const parsedValue = parsePhoneNumber(
170
+ this.value,
171
+ this.countries[0].shortName
172
+ );
160
173
  this.phoneNumber = parsedValue.formatNational();
161
174
  this.selectedCountry =
162
175
  this.countries.find(
@@ -224,7 +237,7 @@ export default {
224
237
  },
225
238
 
226
239
  onKeyPressPhoneNumber(event) {
227
- if(this.formatOnBlur){
240
+ if (this.formatOnBlur) {
228
241
  const phoneNumber = event ? event.target.value : this.phoneNumber;
229
242
  try {
230
243
  this.$emit(
@@ -245,21 +258,36 @@ export default {
245
258
  }
246
259
  } else {
247
260
  let caretPosition = event.target.selectionStart;
248
- if ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode<= 105)) {
261
+ if (
262
+ (event.keyCode >= 48 && event.keyCode <= 57) ||
263
+ (event.keyCode >= 96 && event.keyCode <= 105)
264
+ ) {
249
265
  const asYouType = new AsYouType(this.selectedCountry.shortName);
250
266
  const phone = asYouType.input(event.target.value);
251
267
  event.target.value = phone;
252
268
  this.$nextTick(() => {
253
269
  const charBefore = event.target.value.charAt(caretPosition - 1);
254
270
  const charAfter = event.target.value.charAt(caretPosition + 1);
255
- caretPosition = charBefore === ' ' || charBefore === '-' ? caretPosition + 1 : caretPosition;
256
- caretPosition = charAfter === '-' || charAfter === ')' ? caretPosition + 2 : caretPosition;
271
+ caretPosition =
272
+ charBefore === ' ' || charBefore === '-'
273
+ ? caretPosition + 1
274
+ : caretPosition;
275
+ caretPosition =
276
+ charAfter === '-' || charAfter === ')'
277
+ ? caretPosition + 2
278
+ : caretPosition;
257
279
  event.target.setSelectionRange(caretPosition, caretPosition);
258
- });
280
+ });
259
281
  try {
260
282
  this.$emit('input', asYouType.input(event.target.value));
261
283
  } catch (error) {
262
- this.$emit('input', formatIncompletePhoneNumber(event.target.value, this.selectedCountry.shortName));
284
+ this.$emit(
285
+ 'input',
286
+ formatIncompletePhoneNumber(
287
+ event.target.value,
288
+ this.selectedCountry.shortName
289
+ )
290
+ );
263
291
  }
264
292
  }
265
293
  }
@@ -285,14 +313,14 @@ export default {
285
313
  );
286
314
  }
287
315
  this.phoneNumber = parsePhoneNumber(
288
- phoneNumber,
289
- this.selectedCountry.shortName
290
- ).formatNational();
291
- if(event && event.target) {
316
+ phoneNumber,
317
+ this.selectedCountry.shortName
318
+ ).formatNational();
319
+ if (event && event.target) {
292
320
  event.target.value = parsePhoneNumber(
293
- phoneNumber,
294
- this.selectedCountry.shortName
295
- ).formatNational();
321
+ phoneNumber,
322
+ this.selectedCountry.shortName
323
+ ).formatNational();
296
324
  }
297
325
  },
298
326
  onChangeCountry(country) {
@@ -316,9 +344,9 @@ export default {
316
344
  this.$emit('close-countries-list');
317
345
  this.isCountriesListOpened = false;
318
346
  },
319
- cleanFormat(event){
347
+ cleanFormat(event) {
320
348
  this.phoneNumber = formatIncompletePhoneNumber(event.target.value);
321
- }
349
+ },
322
350
  },
323
351
  };
324
352
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="mc-quantity-selector">
2
+ <div class="mc-quantity-selector" :class="cssFieldElementClass">
3
3
  <m-button
4
4
  class="mc-quantity-selector__button-left"
5
5
  theme="bordered"
@@ -58,7 +58,11 @@ export default {
58
58
  MButton,
59
59
  MTextInputField,
60
60
  },
61
-
61
+ inject: {
62
+ cssFieldElementClass: {
63
+ default: '',
64
+ },
65
+ },
62
66
  props: {
63
67
  id: {
64
68
  type: String,
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div :class="['mc-stars-input', setClasses]">
3
3
  <input
4
- id="no-rate"
4
+ :id="name + '0'"
5
5
  type="radio"
6
- :name="name"
6
+ :name="required ? name + '-unselected' : name"
7
7
  value="0"
8
8
  class="mc-stars-input__radio"
9
9
  checked
@@ -18,6 +18,7 @@
18
18
  :name="name"
19
19
  :value="rateId"
20
20
  class="mc-stars-input__radio"
21
+ :required="required"
21
22
  />
22
23
 
23
24
  <label
@@ -74,6 +75,10 @@ export default {
74
75
  );
75
76
  },
76
77
  },
78
+ required: {
79
+ type: Boolean,
80
+ default: false,
81
+ },
77
82
  },
78
83
 
79
84
  data() {
@@ -1,11 +1,12 @@
1
1
  <template>
2
2
  <select
3
3
  :id="id"
4
+ ref="select"
4
5
  class="mc-select"
5
- :class="setClasses"
6
+ :class="[setClasses, cssFieldElementClass]"
6
7
  :value="getSelectValue"
7
8
  :disabled="disabled"
8
- @change="$emit('change', $event.target.value)"
9
+ @change="onChange($event.target.value)"
9
10
  >
10
11
  <option v-if="placeholder" value="" disabled="disabled">
11
12
  -- {{ placeholder }} --
@@ -27,6 +28,16 @@
27
28
  <script>
28
29
  export default {
29
30
  name: 'MSelect',
31
+ inject: {
32
+ cssFieldElementClass: {
33
+ default: '',
34
+ },
35
+ },
36
+
37
+ model: {
38
+ prop: 'value',
39
+ event: 'change',
40
+ },
30
41
 
31
42
  props: {
32
43
  id: {
@@ -102,6 +113,17 @@ export default {
102
113
  this.optionValue = firstOption.value;
103
114
  }
104
115
  },
116
+ onChange(value) {
117
+ const optionText = this.$refs.select
118
+ .querySelector(`option[value="${value}"]`)
119
+ .textContent.trim();
120
+ const optionData = {
121
+ text: optionText,
122
+ value: value,
123
+ };
124
+
125
+ this.$emit('change', value, optionData);
126
+ },
105
127
  },
106
128
  };
107
129
  </script>
@@ -1,17 +1,24 @@
1
1
  <template>
2
2
  <textarea
3
3
  class="mc-textarea"
4
- :class="{ 'is-valid': isValid, 'is-invalid': isInvalid }"
4
+ :class="[
5
+ { 'is-valid': isValid, 'is-invalid': isInvalid },
6
+ cssFieldElementClass,
7
+ ]"
5
8
  :aria-invalid="isInvalid"
6
9
  :value="value"
7
- @change="$emit('input', $event.target.value)"
10
+ @input="$emit('input', $event.target.value)"
8
11
  />
9
12
  </template>
10
13
 
11
14
  <script>
12
15
  export default {
13
16
  name: 'MTextArea',
14
-
17
+ inject: {
18
+ cssFieldElementClass: {
19
+ default: '',
20
+ },
21
+ },
15
22
  props: {
16
23
  value: {
17
24
  type: String,
@@ -1,12 +1,26 @@
1
1
  <template>
2
- <div key="icon-input" :class="{ 'mc-left-icon-input': icon }">
3
- <m-text-input-icon v-if="icon" :icon="icon" />
2
+ <div
3
+ v-if="icon"
4
+ key="icon-input"
5
+ class="mc-left-icon-input"
6
+ :class="cssFieldElementClass"
7
+ >
8
+ <m-text-input-icon :icon="icon" />
4
9
  <m-text-input-field
5
10
  ref="mField"
6
11
  v-bind="[$attrs, $props]"
7
12
  v-on="$listeners"
8
13
  />
9
14
  </div>
15
+
16
+ <m-text-input-field
17
+ v-else
18
+ key="input-only"
19
+ ref="mField"
20
+ v-bind="[$attrs, $props]"
21
+ :class="cssFieldElementClass"
22
+ v-on="$listeners"
23
+ />
10
24
  </template>
11
25
 
12
26
  <script>
@@ -21,6 +35,12 @@ export default {
21
35
  MTextInputIcon,
22
36
  },
23
37
 
38
+ inject: {
39
+ cssFieldElementClass: {
40
+ default: '',
41
+ },
42
+ },
43
+
24
44
  inheritAttrs: false,
25
45
 
26
46
  props: {
@@ -24,6 +24,7 @@ const supportedTypes = [
24
24
  'password',
25
25
  'tel',
26
26
  'text',
27
+ 'time',
27
28
  'search',
28
29
  ];
29
30