@carbon/vue 2.39.0 → 2.43.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.
Files changed (45) hide show
  1. package/dist/carbon-vue.common.js +981 -853
  2. package/dist/carbon-vue.common.js.map +1 -1
  3. package/dist/carbon-vue.umd.js +981 -853
  4. package/dist/carbon-vue.umd.js.map +1 -1
  5. package/dist/carbon-vue.umd.min.js +3 -3
  6. package/dist/carbon-vue.umd.min.js.map +1 -1
  7. package/package.json +7 -7
  8. package/src/components/cv-accordion/cv-accordion-skeleton.vue +1 -1
  9. package/src/components/cv-accordion/cv-accordion.vue +1 -1
  10. package/src/components/cv-aspect-ratio/cv-aspect-ratio.vue +3 -2
  11. package/src/components/cv-aspect-ratio/index.js +2 -2
  12. package/src/components/cv-breadcrumb/cv-breadcrumb-skeleton.vue +8 -1
  13. package/src/components/cv-button/button-mixin.js +7 -4
  14. package/src/components/cv-button/consts.js +14 -0
  15. package/src/components/cv-button/cv-icon-button.vue +1 -1
  16. package/src/components/cv-code-snippet/cv-code-snippet-skeleton.vue +1 -1
  17. package/src/components/cv-code-snippet/cv-code-snippet.vue +1 -1
  18. package/src/components/cv-data-table/cv-data-table-heading.vue +1 -1
  19. package/src/components/cv-data-table/cv-data-table-skeleton.vue +1 -2
  20. package/src/components/cv-data-table/cv-data-table.vue +2 -1
  21. package/src/components/cv-date-picker/cv-date-picker.vue +11 -10
  22. package/src/components/cv-feedback-button/_cv-feedback-button.vue +1 -1
  23. package/src/components/cv-file-uploader/cv-file-uploader.vue +72 -28
  24. package/src/components/cv-inline-loading/cv-inline-loading.vue +1 -0
  25. package/src/components/cv-inline-notification/cv-inline-notification.vue +2 -0
  26. package/src/components/cv-link/cv-link.vue +8 -1
  27. package/src/components/cv-loading/cv-loading.vue +4 -1
  28. package/src/components/cv-multi-select/cv-multi-select.vue +17 -11
  29. package/src/components/cv-number-input/cv-number-input.vue +38 -30
  30. package/src/components/cv-overflow-menu/cv-overflow-menu.vue +3 -3
  31. package/src/components/cv-search/cv-search.vue +17 -12
  32. package/src/components/cv-tabs/cv-tabs-skeleton.vue +7 -19
  33. package/src/components/cv-tabs/cv-tabs.vue +1 -1
  34. package/src/components/cv-tag/cv-tag-skeleton.vue +1 -3
  35. package/src/components/cv-tag/cv-tag.vue +6 -7
  36. package/src/components/cv-tag/index.js +3 -2
  37. package/src/components/cv-tile/_cv-tile-selectable.vue +0 -1
  38. package/src/components/cv-toast-notification/cv-toast-notification.vue +3 -1
  39. package/src/components/cv-tooltip/consts.js +2 -0
  40. package/src/components/cv-tooltip/cv-definition-tooltip.vue +5 -5
  41. package/src/components/cv-tooltip/cv-interactive-tooltip.vue +7 -7
  42. package/src/components/cv-tooltip/cv-tooltip.vue +5 -5
  43. package/src/components/cv-tooltip/index.js +1 -0
  44. package/src/components/cv-ui-shell/cv-header-global-action.vue +1 -1
  45. package/CHANGELOG.md +0 -1191
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/vue",
3
3
  "description": "A collection of components for the Carbon Design System built using Vue.js",
4
- "version": "2.39.0",
4
+ "version": "2.43.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -64,16 +64,16 @@
64
64
  },
65
65
  "sideEffects": true,
66
66
  "dependencies": {
67
- "@carbon/icons-vue": "10.27.0",
68
- "@carbon/telemetry": "^0.0.0-alpha.6",
69
- "carbon-components": "10.30.0",
67
+ "@carbon/icons-vue": "10.49.1",
68
+ "@carbon/telemetry": "^0.1.0",
69
+ "carbon-components": "10.56.0",
70
70
  "flatpickr": "4.6.9",
71
- "vue": "^2.6.12"
71
+ "vue": "^2.6.14"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@vue/cli-service": "^3.11.0",
75
75
  "eslint-plugin-prettier": "^3.3.1",
76
- "vue-template-compiler": "^2.6.12"
76
+ "vue-template-compiler": "^2.6.14"
77
77
  },
78
- "gitHead": "f0b00ac6c8bfaf0f92bebd7776fa5c507d86a7e2"
78
+ "gitHead": "fead16d4b7d1f363f99c49aaeb614749ddf128ec"
79
79
  }
@@ -31,7 +31,7 @@ export default {
31
31
  size: {
32
32
  type: String,
33
33
  default: '',
34
- validator: val => ['sm', 'xl', ''].includes(val),
34
+ validator: val => ['sm', 'md', 'lg', 'xl', ''].includes(val),
35
35
  },
36
36
  },
37
37
  mixins: [carbonPrefixMixin],
@@ -23,7 +23,7 @@ export default {
23
23
  size: {
24
24
  type: String,
25
25
  default: '',
26
- validator: val => ['sm', 'xl', ''].includes(val),
26
+ validator: val => ['sm', 'md', 'lg', 'xl', ''].includes(val),
27
27
  },
28
28
  },
29
29
  mixins: [carbonPrefixMixin],
@@ -4,6 +4,8 @@
4
4
 
5
5
  <script>
6
6
  import { carbonPrefixMixin } from '../../mixins';
7
+
8
+ export const ratios = ['16x9', '9x16', '2x1', '1x2', '4x3', '3x4', '1x1'];
7
9
  export default {
8
10
  name: 'CvAspectRatio',
9
11
  mixins: [carbonPrefixMixin],
@@ -11,8 +13,7 @@ export default {
11
13
  ratio: {
12
14
  type: String,
13
15
  validator: val => {
14
- const options = ['16x9', '9x16', '2x1', '1x2', '4x3', '3x4', '1x1'];
15
- const result = options.includes(val);
16
+ const result = ratios.includes(val);
16
17
  if (!result) {
17
18
  console.warn(`Invalid options supplied to "CvAspectRation"-"${val}".`);
18
19
  }
@@ -1,2 +1,2 @@
1
- import CvAspectRatio from './cv-aspect-ratio';
2
- export { CvAspectRatio };
1
+ import CvAspectRatio, { ratios } from './cv-aspect-ratio';
2
+ export { CvAspectRatio, ratios };
@@ -1,5 +1,11 @@
1
1
  <template>
2
- <nav :class="`${carbonPrefix}--breadcrumb ${carbonPrefix}--skeleton`" :aria-label="ariaLabel">
2
+ <nav
3
+ :class="[
4
+ `${carbonPrefix}--breadcrumb ${carbonPrefix}--skeleton`,
5
+ { [`${carbonPrefix}--breadcrumb--no-trailing-slash`]: noTrailingSlash },
6
+ ]"
7
+ :aria-label="ariaLabel"
8
+ >
3
9
  <cv-breadcrumb-item-skeleton></cv-breadcrumb-item-skeleton>
4
10
  <cv-breadcrumb-item-skeleton></cv-breadcrumb-item-skeleton>
5
11
  <cv-breadcrumb-item-skeleton></cv-breadcrumb-item-skeleton>
@@ -18,6 +24,7 @@ export default {
18
24
  },
19
25
  props: {
20
26
  ariaLabel: { type: String, default: 'breadcrumb' },
27
+ noTrailingSlash: Boolean,
21
28
  },
22
29
  };
23
30
  </script>
@@ -13,6 +13,7 @@ export default {
13
13
  },
14
14
  },
15
15
  iconHref: {
16
+ deprecated: true,
16
17
  type: String,
17
18
  default: undefined,
18
19
  validator(val) {
@@ -29,6 +30,7 @@ export default {
29
30
  ['', 'primary', 'secondary', 'tertiary', 'ghost', 'danger', 'danger--ghost', 'danger--tertiary'].includes(val),
30
31
  },
31
32
  small: {
33
+ deprecated: true,
32
34
  type: Boolean,
33
35
  default: undefined,
34
36
  validator(val) {
@@ -56,7 +58,8 @@ export default {
56
58
  buttonClassOpts() {
57
59
  return (opts = {}) => {
58
60
  const classes = [`${carbonSettings.prefix}--btn`];
59
- const lowerCaseKind = this.kind.toLowerCase();
61
+ // ensure lower case and default to primary
62
+ const _kind = this.kind ? this.kind.toLowerCase() : 'primary';
60
63
 
61
64
  if (opts.skeleton) {
62
65
  classes.push(`${carbonSettings.prefix}--skeleton`);
@@ -64,13 +67,13 @@ export default {
64
67
 
65
68
  if (opts.iconOnly) {
66
69
  classes.push(`${carbonSettings.prefix}--btn--icon-only`);
67
- if (this.selected && lowerCaseKind === 'ghost') {
70
+ if (this.selected && _kind === 'ghost') {
68
71
  classes.push(`${carbonSettings.prefix}--btn--selected`);
69
72
  }
70
73
  }
71
74
 
72
- if (this.kind && !opts.skeleton) {
73
- classes.push(`${carbonSettings.prefix}--btn--${lowerCaseKind}`);
75
+ if (_kind && !opts.skeleton) {
76
+ classes.push(`${carbonSettings.prefix}--btn--${_kind}`);
74
77
  }
75
78
 
76
79
  let size = this.size ? this.size : this.small && 'sm';
@@ -0,0 +1,14 @@
1
+ export const buttonKinds = [
2
+ '',
3
+ 'primary',
4
+ 'secondary',
5
+ 'tertiary',
6
+ 'ghost',
7
+ 'danger',
8
+ 'danger--ghost',
9
+ 'danger--tertiary',
10
+ ];
11
+ export const buttonSizes = ['', 'default', 'field', 'small', 'sm', 'lg', 'xl'];
12
+
13
+ const CvButtonConsts = { buttonKinds, buttonSizes };
14
+ export default CvButtonConsts;
@@ -34,7 +34,7 @@ export default {
34
34
  tipPosition: {
35
35
  type: String,
36
36
  default: 'bottom',
37
- validator: val => ['top', 'left', 'bottom', 'right'.includes(val)],
37
+ validator: val => ['top', 'left', 'bottom', 'right'].includes(val),
38
38
  },
39
39
  tipAlignment: { type: String, default: 'center', validator: val => ['start', 'center', 'end'].includes(val) },
40
40
  },
@@ -19,7 +19,7 @@ export default {
19
19
  name: 'CvCodeSnippetSkeleton',
20
20
  mixins: [carbonPrefixMixin],
21
21
  props: {
22
- kind: { type: String, default: 'oneline' },
22
+ kind: { type: String, default: 'oneline', validator: val => ['multiline', 'oneline'].includes(val) },
23
23
  },
24
24
  computed: {
25
25
  multi() {
@@ -14,7 +14,7 @@
14
14
  <!-- textarea cannot be fully hidden for clipboard to work -->
15
15
  <textarea
16
16
  class="cv-code-snippet__clippy"
17
- style="position: absolute; left: -9999px; max-width: 0; opacity: 0; overflow: hidden;"
17
+ style="position: absolute; left: -9999px; max-width: 0; opacity: 0; overflow: hidden"
18
18
  aria-hidden="true"
19
19
  ref="clippy"
20
20
  ></textarea>
@@ -28,7 +28,7 @@
28
28
 
29
29
  <script>
30
30
  import ArrowDown16 from '@carbon/icons-vue/es/arrow--down/16';
31
- import Arrows16 from '@carbon/icons-vue/es/arrows/16';
31
+ import Arrows16 from '@carbon/icons-vue/es/arrows--vertical/16';
32
32
  import CvWrapper from '../cv-wrapper/_cv-wrapper';
33
33
  import { uidMixin, carbonPrefixMixin } from '../../mixins';
34
34
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <cv-data-table skeleton :data="data" :columns="cols" v-on="$listeners" v-bind="$attrs">
3
- <template v-if="hasBatchActions" slot="helper-text">
3
+ <template v-if="hasHelperText" slot="helper-text">
4
4
  <slot name="helper-text" />
5
5
  </template>
6
6
 
@@ -29,7 +29,6 @@ export default {
29
29
  },
30
30
  props: {
31
31
  columns: { type: [Array, Number], default: DEFAULTS.COLS },
32
- hasExpandables: Boolean,
33
32
  rows: { type: Number, default: DEFAULTS.ROWS },
34
33
  },
35
34
  data() {
@@ -232,6 +232,7 @@ export default {
232
232
  searchLabel: { type: String, default: 'Search' },
233
233
  searchPlaceholder: { type: String, default: 'Search' },
234
234
  searchClearLabel: { type: String, default: 'Clear search' },
235
+ initialSearchValue: { type: String, default: '' },
235
236
  sortable: Boolean,
236
237
  title: String,
237
238
  columns: Array,
@@ -258,7 +259,7 @@ export default {
258
259
  batchActive: false,
259
260
  headingChecked: false,
260
261
  dataRowsSelected: this.rowsSelected,
261
- searchValue: '',
262
+ searchValue: this.initialSearchValue,
262
263
  clearSearchVisible: false,
263
264
  searchActive: false,
264
265
  registeredRows: [],
@@ -81,16 +81,6 @@ import { uidMixin, themeMixin, carbonPrefixMixin } from '../../mixins';
81
81
  import Calendar16 from '@carbon/icons-vue/es/calendar/16';
82
82
  import CvWrapper from '../cv-wrapper/_cv-wrapper';
83
83
 
84
- // Weekdays shorthand for english locale
85
- l10n.en.weekdays.shorthand.forEach((day, index) => {
86
- const currentDay = l10n.en.weekdays.shorthand;
87
- if (currentDay[index] === 'Thu' || currentDay[index] === 'Th') {
88
- currentDay[index] = 'Th';
89
- } else {
90
- currentDay[index] = currentDay[index].charAt(0);
91
- }
92
- });
93
-
94
84
  export default {
95
85
  name: 'CvDatePicker',
96
86
  mixins: [uidMixin, themeMixin, carbonPrefixMixin],
@@ -338,6 +328,17 @@ export default {
338
328
  this.$refs.todate.click();
339
329
  },
340
330
  },
331
+ created() {
332
+ // Weekdays shorthand for english locale
333
+ l10n.en.weekdays.shorthand.forEach((day, index) => {
334
+ const currentDay = l10n.en.weekdays.shorthand;
335
+ if (currentDay[index] === 'Thu' || currentDay[index] === 'Th') {
336
+ currentDay[index] = 'Th';
337
+ } else {
338
+ currentDay[index] = currentDay[index].charAt(0);
339
+ }
340
+ });
341
+ },
341
342
  mounted() {
342
343
  this.initFlatpickr();
343
344
  this.checkSlots();
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <button
3
- aria-label="ariaLabel"
3
+ :aria-label="ariaLabel"
4
4
  type="button"
5
5
  class="cv-feedback-button"
6
6
  v-bind="$attrs"
@@ -32,6 +32,7 @@
32
32
  v-if="kind !== 'button'"
33
33
  v-bind="$attrs"
34
34
  type="file"
35
+ :accept="accept"
35
36
  :class="`${carbonPrefix}--file-input`"
36
37
  :id="uid"
37
38
  data-file-uploader
@@ -45,6 +46,7 @@
45
46
  v-if="kind === 'button'"
46
47
  v-bind="$attrs"
47
48
  type="file"
49
+ :accept="accept"
48
50
  :class="`${carbonPrefix}--file-input`"
49
51
  :id="uid"
50
52
  data-file-uploader
@@ -140,11 +142,13 @@ export default {
140
142
  },
141
143
  label: String,
142
144
  helperText: String,
145
+ accept: String,
143
146
  initialStateUploading: Boolean,
144
147
  removable: Boolean,
145
148
  buttonLabel: {
146
149
  type: String,
147
150
  default: undefined,
151
+ deprecated: true,
148
152
  validator: val => {
149
153
  if (val !== undefined && process.env.NODE_ENV === 'development') {
150
154
  console.warn('CvFileUploader: button-label prop deprecated in favour of drop-target-label');
@@ -210,13 +214,30 @@ export default {
210
214
  },
211
215
  addFiles(files) {
212
216
  for (const file of files) {
213
- this.internalFiles.push({
214
- state: this.initialStateUploading ? STATES.UPLOADING : STATES.NONE,
215
- file,
216
- invalidMessageTitle: '',
217
- invalidMessage: '',
218
- });
217
+ const internalFile = this.internalFiles.find(item => item.file.name === file.name);
218
+
219
+ if (internalFile) {
220
+ internalFile.state = this.initialStateUploading ? STATES.UPLOADING : STATES.NONE;
221
+ internalFile.invalidMessageTitle = '';
222
+ internalFile.invalidMessage = '';
223
+ } else {
224
+ const internalFile = {
225
+ state: this.initialStateUploading ? STATES.UPLOADING : STATES.NONE,
226
+ file,
227
+ invalidMessageTitle: '',
228
+ invalidMessage: '',
229
+ };
230
+
231
+ if (file.messageBundle) {
232
+ internalFile.invalidMessageTitle = file.messageBundle.invalidMessageTitle;
233
+ internalFile.invalidMessage = file.messageBundle.invalidMessage;
234
+ delete file.messageBundle;
235
+ }
236
+ this.internalFiles.push(internalFile);
237
+ }
219
238
  }
239
+ // clear input we do not need to maintain it
240
+ this.$refs['file-input'].value = '';
220
241
  this.$emit('change', this.internalFiles);
221
242
  },
222
243
  onChange(ev) {
@@ -241,32 +262,55 @@ export default {
241
262
  this.internalFiles[index].invalidMessage = message;
242
263
  },
243
264
  onDragEvent(evt) {
244
- // NOTE: Validation of dragged files is not currently done.
245
- // It may be possible to do this here or defer to the caller.
246
- // It is certainly possible for the user to remove files after they are dropped.
265
+ if (Array.prototype.indexOf.call(evt.dataTransfer.types, 'Files') === -1) {
266
+ return;
267
+ }
268
+
269
+ if (evt.type === 'dragleave') {
270
+ this.allowDrop = false;
271
+ return;
272
+ }
247
273
 
248
- if (Array.prototype.indexOf.call(evt.dataTransfer.types, 'Files') >= 0) {
249
- if (evt.type === 'dragover') {
250
- evt.preventDefault();
251
- const dropEffect = 'copy';
252
- if (Array.isArray(evt.dataTransfer.types)) {
253
- try {
254
- // IE11 throws a "permission denied" error accessing `.effectAllowed`
255
- evt.dataTransfer.effectAllowed = dropEffect;
256
- } catch (e) {
257
- // ignore
258
- }
274
+ if (evt.type === 'dragover') {
275
+ evt.preventDefault();
276
+ const dropEffect = 'copy';
277
+ if (Array.isArray(evt.dataTransfer.types)) {
278
+ try {
279
+ // IE11 throws a "permission denied" error accessing `.effectAllowed`
280
+ evt.dataTransfer.effectAllowed = dropEffect;
281
+ } catch (e) {
282
+ // ignore
259
283
  }
260
- evt.dataTransfer.dropEffect = dropEffect;
261
- this.allowDrop = true;
262
284
  }
263
- if (evt.type === 'dragleave') {
264
- this.allowDrop = false;
285
+ evt.dataTransfer.dropEffect = dropEffect;
286
+ this.allowDrop = true;
287
+ }
288
+
289
+ if (evt.type === 'drop') {
290
+ evt.preventDefault();
291
+ if (this.accept) {
292
+ this.markInvalidFileTypes(evt.dataTransfer.files);
293
+ }
294
+ this.addFiles(evt.dataTransfer.files);
295
+ this.allowDrop = false;
296
+ }
297
+ },
298
+ markInvalidFileTypes(files) {
299
+ const isFileAllowed = file => {
300
+ const extension = '.' + file.name.split('.').pop();
301
+ const allowed = this.accept.split(',').map(x => x.trim());
302
+ if (allowed.includes('.jpg')) {
303
+ allowed.push('.jpeg');
265
304
  }
266
- if (evt.type === 'drop') {
267
- evt.preventDefault();
268
- this.addFiles(evt.dataTransfer.files);
269
- this.allowDrop = false;
305
+ return allowed.includes(file.type) || allowed.includes(extension);
306
+ };
307
+
308
+ for (const file of files) {
309
+ if (!isFileAllowed(file)) {
310
+ file.messageBundle = {
311
+ invalidMessageTitle: 'Invalid file type',
312
+ invalidMessage: `"${file.name}" does not have a valid file type.`,
313
+ };
270
314
  }
271
315
  }
272
316
  },
@@ -40,6 +40,7 @@ export default {
40
40
  active: {
41
41
  type: Boolean,
42
42
  default: undefined,
43
+ deprecated: true,
43
44
  validator: val => {
44
45
  if (val !== undefined && process.env.NODE_ENV === 'development') {
45
46
  console.warn('CvInlineLoading: active prop deprecated in favour of state prop');
@@ -34,6 +34,7 @@
34
34
  {{ actionLabel }}
35
35
  </button>
36
36
  <button
37
+ v-if="!hideCloseButton"
37
38
  type="button"
38
39
  :aria-label="closeAriaLabel"
39
40
  data-notification-btn
@@ -66,6 +67,7 @@ export default {
66
67
  validator: val => ['error', 'info', 'warning', 'success'].includes(val),
67
68
  },
68
69
  lowContrast: Boolean,
70
+ hideCloseButton: Boolean,
69
71
  },
70
72
  computed: {
71
73
  icon() {
@@ -4,7 +4,13 @@
4
4
  v-on="$listeners"
5
5
  v-bind="linkProps"
6
6
  class="cv-link"
7
- :class="[`${carbonPrefix}--link`, { [`${carbonPrefix}--link--inline`]: inline }]"
7
+ :class="[
8
+ `${carbonPrefix}--link`,
9
+ {
10
+ [`${carbonPrefix}--link--disabled`]: disabled,
11
+ [`${carbonPrefix}--link--inline`]: inline,
12
+ },
13
+ ]"
8
14
  >
9
15
  <slot></slot>
10
16
  </component>
@@ -17,6 +23,7 @@ export default {
17
23
  name: 'CvLink',
18
24
  mixins: [linkMixin, carbonPrefixMixin],
19
25
  props: {
26
+ disabled: Boolean,
20
27
  inline: Boolean,
21
28
  },
22
29
  };
@@ -5,7 +5,7 @@
5
5
  :class="{
6
6
  'cv-loading': !overlay,
7
7
  [`${carbonPrefix}--loading`]: active || stopping,
8
- [`${carbonPrefix}--loading--stop`]: !active && stopping,
8
+ [`${carbonPrefix}--loading--stop`]: (!active && stopping) || stopped,
9
9
  [`${carbonPrefix}--loading--small`]: small,
10
10
  }"
11
11
  ref="loading"
@@ -55,6 +55,7 @@ export default {
55
55
  },
56
56
  data() {
57
57
  return {
58
+ stopped: false,
58
59
  stopping: false,
59
60
  };
60
61
  },
@@ -69,10 +70,12 @@ export default {
69
70
  this.$refs.loading.removeEventListener('animationend', this.onEnd);
70
71
 
71
72
  this.stopping = false;
73
+ this.stopped = true;
72
74
  this.$emit('loading-end');
73
75
  }
74
76
  },
75
77
  onActiveUpdate(newValue) {
78
+ this.stopped = false;
76
79
  this.stopping = !newValue;
77
80
  if (!newValue) {
78
81
  this.$refs.loading.addEventListener('animationend', this.onEnd);
@@ -131,6 +131,7 @@
131
131
  :name="item.name"
132
132
  :data-test="item.name"
133
133
  :label="item.label"
134
+ :disabled="item.disabled"
134
135
  style="pointer-events: none;"
135
136
  />
136
137
  </div>
@@ -407,7 +408,9 @@ export default {
407
408
  onEnter() {
408
409
  if (this.open) {
409
410
  this.onItemClick(this.highlighted);
410
- this.$refs.input.focus();
411
+ if (this.$refs.input) {
412
+ this.$refs.input.focus();
413
+ }
411
414
  this.filter = '';
412
415
 
413
416
  this.doOpen(false);
@@ -446,17 +449,20 @@ export default {
446
449
  this.highlighted = val;
447
450
  },
448
451
  onItemClick(val) {
449
- const index = this.dataValue.findIndex(item => val === item);
450
- if (index > -1) {
451
- this.dataValue.splice(index, 1);
452
- } else {
453
- this.dataValue.push(val);
454
- }
455
- if (this.selectionFeedback === selectionFeedbackOptions[TOP]) {
456
- this.updateOptions();
452
+ const option = this.options.find(item => item.value === val);
453
+ if (option && !option.disabled) {
454
+ const index = this.dataValue.findIndex(item => val === item);
455
+ if (index > -1) {
456
+ this.dataValue.splice(index, 1);
457
+ } else {
458
+ this.dataValue.push(val);
459
+ }
460
+ if (this.selectionFeedback === selectionFeedbackOptions[TOP]) {
461
+ this.updateOptions();
462
+ }
463
+ this.$refs.button.focus();
464
+ this.$emit('change', this.dataValue);
457
465
  }
458
- this.$refs.button.focus();
459
- this.$emit('change', this.dataValue);
460
466
  },
461
467
  inputClick() {
462
468
  if (!this.open) {