@carbon/vue 2.38.0 → 2.40.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,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.38.0",
4
+ "version": "2.40.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -75,5 +75,5 @@
75
75
  "eslint-plugin-prettier": "^3.3.1",
76
76
  "vue-template-compiler": "^2.6.12"
77
77
  },
78
- "gitHead": "378e7d5498d39f70b26badc2155e8e9ba4d71269"
78
+ "gitHead": "1db5405c2ab7fb83019637657bc637f2fc011848"
79
79
  }
@@ -85,80 +85,86 @@
85
85
  </div>
86
86
  </section>
87
87
 
88
- <table
89
- :class="[
90
- `${carbonPrefix}--data-table`,
91
- {
92
- [`${carbonPrefix}--data-table--${rowSize} `]: !(rowSize.length === 0 || rowSize === 'standard'),
93
- [`${carbonPrefix}--data-table--zebra `]: zebra,
94
- [`${carbonPrefix}--data-table--no-border `]: borderless,
95
- [`${carbonPrefix}--skeleton `]: skeleton,
96
- [`${carbonPrefix}--data-table--sort `]: isSortable,
97
- },
98
- ]"
99
- >
100
- <thead>
101
- <tr>
102
- <th
103
- v-if="hasExpandables"
104
- :class="`${carbonPrefix}--table-expand`"
105
- :data-previous-value="dataExpandAll ? 'collapsed' : 'expanded'"
106
- >
107
- <button
108
- v-if="hasExpandAll"
109
- :class="`${carbonPrefix}--table-expand__button`"
110
- @click="toggleExpandAll"
111
- type="button"
112
- :aria-label="dataExpandAll ? collapseAllAriaLabel : expandAllAriaLabel"
113
- >
114
- <ChevronRight16 :class="`${carbonPrefix}--table-expand__svg`" />
115
- </button>
116
- </th>
117
- <th v-if="hasBatchActions" :class="`${carbonPrefix}--table-column-checkbox`">
118
- <cv-checkbox
119
- :form-item="false"
120
- value="headingCheck"
121
- v-model="headingChecked"
122
- @change="onHeadingCheckChange"
123
- :label="selectAllAriaLabel"
124
- hideLabel
125
- />
126
- </th>
127
- <slot name="headings">
128
- <cv-data-table-heading
129
- v-for="(column, index) in columns"
130
- :key="`${index}:${column}`"
131
- :heading="columnHeading(column)"
132
- :sortable="isColSortable(column)"
133
- :order="column.order"
134
- :heading-style="headingStyle(column)"
135
- :skeleton="skeleton"
136
- />
137
- </slot>
138
- <th v-if="hasOverflowMenu"></th>
139
- </tr>
140
- </thead>
88
+ <div :class="`${carbonPrefix}--data-table-content`">
89
+ <cv-wrapper :tagType="stickyHeader ? section : ''" :class="`${carbonPrefix}--data-table_inner-container`">
90
+ <table
91
+ :class="[
92
+ `${carbonPrefix}--data-table`,
93
+ {
94
+ [`${carbonPrefix}--data-table--${rowSize} `]: !(rowSize.length === 0 || rowSize === 'standard'),
95
+ [`${carbonPrefix}--data-table--zebra `]: zebra,
96
+ [`${carbonPrefix}--data-table--sticky-header `]: stickyHeader,
97
+ [`${carbonPrefix}--data-table--no-border `]: borderless,
98
+ [`${carbonPrefix}--skeleton `]: skeleton,
99
+ [`${carbonPrefix}--data-table--sort `]: isSortable,
100
+ [`${carbonPrefix}--data-table--static `]: staticWidth,
101
+ },
102
+ ]"
103
+ >
104
+ <thead>
105
+ <tr>
106
+ <th
107
+ v-if="hasExpandables"
108
+ :class="`${carbonPrefix}--table-expand`"
109
+ :data-previous-value="dataExpandAll ? 'collapsed' : 'expanded'"
110
+ >
111
+ <button
112
+ v-if="hasExpandAll"
113
+ :class="`${carbonPrefix}--table-expand__button`"
114
+ @click="toggleExpandAll"
115
+ type="button"
116
+ :aria-label="dataExpandAll ? collapseAllAriaLabel : expandAllAriaLabel"
117
+ >
118
+ <ChevronRight16 :class="`${carbonPrefix}--table-expand__svg`" />
119
+ </button>
120
+ </th>
121
+ <th v-if="hasBatchActions" :class="`${carbonPrefix}--table-column-checkbox`">
122
+ <cv-checkbox
123
+ :form-item="false"
124
+ value="headingCheck"
125
+ v-model="headingChecked"
126
+ @change="onHeadingCheckChange"
127
+ :label="selectAllAriaLabel"
128
+ hideLabel
129
+ />
130
+ </th>
131
+ <slot name="headings">
132
+ <cv-data-table-heading
133
+ v-for="(column, index) in columns"
134
+ :key="`${index}:${column}`"
135
+ :heading="columnHeading(column)"
136
+ :sortable="isColSortable(column)"
137
+ :order="column.order"
138
+ :heading-style="headingStyle(column)"
139
+ :skeleton="skeleton"
140
+ />
141
+ </slot>
142
+ <th v-if="hasOverflowMenu"></th>
143
+ </tr>
144
+ </thead>
141
145
 
142
- <cv-wrapper :tag-type="hasExpandables ? '' : 'tbody'">
143
- <slot name="data">
144
- <cv-data-table-row
145
- v-for="(row, rowIndex) in data"
146
- :key="`row:${rowIndex}`"
147
- :value="`${rowIndex}`"
148
- ref="dataRows"
149
- :overflow-menu="overflowMenu"
150
- >
151
- <cv-data-table-cell
152
- v-for="(cell, colIndex) in row"
153
- :key="`cell:${colIndex}:${rowIndex}`"
154
- :style="dataStyle(colIndex)"
155
- >
156
- <cv-wrapper :tag-type="skeleton ? 'span' : ''">{{ cell }}</cv-wrapper>
157
- </cv-data-table-cell>
158
- </cv-data-table-row>
159
- </slot>
146
+ <cv-wrapper :tag-type="hasExpandables ? '' : 'tbody'">
147
+ <slot name="data">
148
+ <cv-data-table-row
149
+ v-for="(row, rowIndex) in data"
150
+ :key="`row:${rowIndex}`"
151
+ :value="`${rowIndex}`"
152
+ ref="dataRows"
153
+ :overflow-menu="overflowMenu"
154
+ >
155
+ <cv-data-table-cell
156
+ v-for="(cell, colIndex) in row"
157
+ :key="`cell:${colIndex}:${rowIndex}`"
158
+ :style="dataStyle(colIndex)"
159
+ >
160
+ <cv-wrapper :tag-type="skeleton ? 'span' : ''">{{ cell }}</cv-wrapper>
161
+ </cv-data-table-cell>
162
+ </cv-data-table-row>
163
+ </slot>
164
+ </cv-wrapper>
165
+ </table>
160
166
  </cv-wrapper>
161
- </table>
167
+ </div>
162
168
  </div>
163
169
  <cv-pagination
164
170
  v-if="pagination"
@@ -231,11 +237,13 @@ export default {
231
237
  columns: Array,
232
238
  data: Array,
233
239
  zebra: Boolean,
240
+ stickyHeader: Boolean,
234
241
  rowsSelected: { type: Array, default: () => [] },
235
242
  helperText: { type: String, default: undefined },
236
243
  expandingSearch: { type: Boolean, default: true },
237
244
  skeleton: Boolean,
238
245
  hasExpandAll: Boolean,
246
+ staticWidth: Boolean,
239
247
  },
240
248
  model: {
241
249
  prop: 'rows-selected',
@@ -507,6 +515,7 @@ export default {
507
515
  } else {
508
516
  this.dataExpandAll = false;
509
517
  }
518
+ this.$emit('row-expanded', row);
510
519
  },
511
520
  },
512
521
  };
@@ -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,6 +142,7 @@ 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: {
@@ -210,12 +213,19 @@ export default {
210
213
  },
211
214
  addFiles(files) {
212
215
  for (const file of files) {
213
- this.internalFiles.push({
216
+ const internalFile = {
214
217
  state: this.initialStateUploading ? STATES.UPLOADING : STATES.NONE,
215
218
  file,
216
219
  invalidMessageTitle: '',
217
220
  invalidMessage: '',
218
- });
221
+ };
222
+
223
+ if (file.messageBundle) {
224
+ internalFile.invalidMessageTitle = file.messageBundle.invalidMessageTitle;
225
+ internalFile.invalidMessage = file.messageBundle.invalidMessage;
226
+ delete file.messageBundle;
227
+ }
228
+ this.internalFiles.push(internalFile);
219
229
  }
220
230
  this.$emit('change', this.internalFiles);
221
231
  },
@@ -241,32 +251,55 @@ export default {
241
251
  this.internalFiles[index].invalidMessage = message;
242
252
  },
243
253
  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.
254
+ if (Array.prototype.indexOf.call(evt.dataTransfer.types, 'Files') === -1) {
255
+ return;
256
+ }
247
257
 
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
- }
258
+ if (evt.type === 'dragleave') {
259
+ this.allowDrop = false;
260
+ return;
261
+ }
262
+
263
+ if (evt.type === 'dragover') {
264
+ evt.preventDefault();
265
+ const dropEffect = 'copy';
266
+ if (Array.isArray(evt.dataTransfer.types)) {
267
+ try {
268
+ // IE11 throws a "permission denied" error accessing `.effectAllowed`
269
+ evt.dataTransfer.effectAllowed = dropEffect;
270
+ } catch (e) {
271
+ // ignore
259
272
  }
260
- evt.dataTransfer.dropEffect = dropEffect;
261
- this.allowDrop = true;
262
273
  }
263
- if (evt.type === 'dragleave') {
264
- this.allowDrop = false;
274
+ evt.dataTransfer.dropEffect = dropEffect;
275
+ this.allowDrop = true;
276
+ }
277
+
278
+ if (evt.type === 'drop') {
279
+ evt.preventDefault();
280
+ if (this.accept) {
281
+ this.markInvalidFileTypes(evt.dataTransfer.files);
265
282
  }
266
- if (evt.type === 'drop') {
267
- evt.preventDefault();
268
- this.addFiles(evt.dataTransfer.files);
269
- this.allowDrop = false;
283
+ this.addFiles(evt.dataTransfer.files);
284
+ this.allowDrop = false;
285
+ }
286
+ },
287
+ markInvalidFileTypes(files) {
288
+ const isFileAllowed = file => {
289
+ const extension = '.' + file.name.split('.').pop();
290
+ const allowed = this.accept.split(',').map(x => x.trim());
291
+ if (allowed.includes('.jpg')) {
292
+ allowed.push('.jpeg');
293
+ }
294
+ return allowed.includes(file.type) || allowed.includes(extension);
295
+ };
296
+
297
+ for (const file of files) {
298
+ if (!isFileAllowed(file)) {
299
+ file.messageBundle = {
300
+ invalidMessageTitle: 'Invalid file type',
301
+ invalidMessage: `"${file.name}" does not have a valid file type.`,
302
+ };
270
303
  }
271
304
  }
272
305
  },
@@ -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() {
@@ -71,7 +71,7 @@
71
71
  :disabled="primaryButtonDisabled"
72
72
  type="button"
73
73
  :kind="primaryKind"
74
- @click="() => onPrimaryClick"
74
+ @click="onPrimaryClick"
75
75
  v-if="hasPrimary"
76
76
  ref="primary"
77
77
  >
@@ -279,7 +279,7 @@ export default {
279
279
  this.onFooterButtonClick('primary-click', ev);
280
280
  },
281
281
  onSecondaryClick(ev) {
282
- this.onFooterButtonClick('primary-click', ev);
282
+ this.onFooterButtonClick('secondary-click', ev);
283
283
  },
284
284
  onOtherBtnClick(ev) {
285
285
  this.onFooterButtonClick('other-btn-click', ev);
@@ -18,6 +18,7 @@
18
18
  :class="[`${carbonPrefix}--progress-label`, { [`${carbonPrefix}--progress-label-overflow`]: showOverflow }]"
19
19
  @mouseenter="onMouseEnter"
20
20
  @mouseleave="onMouseLeave"
21
+ @click="$emit('step-clicked', $event)"
21
22
  ref="label"
22
23
  >
23
24
  {{ label }}
@@ -11,6 +11,7 @@
11
11
  :label="step"
12
12
  :complete="initialStep > index"
13
13
  ref="steps"
14
+ @step-clicked="$emit('step-clicked', $event)"
14
15
  />
15
16
  </slot>
16
17
  </ul>
@@ -17,6 +17,7 @@
17
17
  <p :class="`${carbonPrefix}--toast-notification__caption`" v-html="caption"></p>
18
18
  </div>
19
19
  <button
20
+ v-if="!hideCloseButton"
20
21
  :aria-label="closeAriaLabel"
21
22
  type="button"
22
23
  data-notification-btn
@@ -43,6 +44,7 @@ export default {
43
44
  props: {
44
45
  caption: String,
45
46
  closeAriaLabel: { type: String, default: 'Dismiss notification' },
47
+ hideCloseButton: Boolean,
46
48
  kind: {
47
49
  type: String,
48
50
  default: 'info',