@carbon/vue 2.25.0-canary.0 → 2.26.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.25.0-canary.0",
4
+ "version": "2.26.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -73,5 +73,5 @@
73
73
  "eslint-plugin-prettier": "^3.1.1",
74
74
  "vue-template-compiler": "^2.6.10"
75
75
  },
76
- "gitHead": "a177ab894e5ed3e32c1c538f8e6ffad34ff12019"
76
+ "gitHead": "5bcf4d93005e113e5501524d339f0907f57f1758"
77
77
  }
@@ -9,7 +9,8 @@
9
9
  <li
10
10
  data-accordion-item
11
11
  class="cv-accordion-item bx--accordion__item"
12
- :class="{ 'bx--accordion__item--active': dataOpen }"
12
+ :class="itemClasses"
13
+ @animationend="onAnimationEnd"
13
14
  >
14
15
  <button
15
16
  type="button"
@@ -50,6 +51,7 @@ export default {
50
51
  },
51
52
  data() {
52
53
  return {
54
+ animation: '',
53
55
  dataOpen: false,
54
56
  };
55
57
  },
@@ -58,6 +60,7 @@ export default {
58
60
  },
59
61
  methods: {
60
62
  toggle(force) {
63
+ this.animation = this.dataOpen ? 'collapsing' : 'expanding';
61
64
  const newValue = typeof force === 'boolean' ? !!force : !this.dataOpen;
62
65
  const change = this.dataOpen !== undefined && newValue !== this.dataOpen;
63
66
 
@@ -66,6 +69,21 @@ export default {
66
69
  this.$parent.$emit('cv:change', this);
67
70
  }
68
71
  },
72
+ onAnimationEnd() {
73
+ this.animation = '';
74
+ },
75
+ },
76
+ computed: {
77
+ itemClasses() {
78
+ const classes = [];
79
+ if (this.dataOpen) {
80
+ classes.push('bx--accordion__item--active');
81
+ }
82
+ if (this.animation) {
83
+ classes.push(`bx--accordion__item--${this.animation}`);
84
+ }
85
+ return classes.join(' ');
86
+ },
69
87
  },
70
88
  };
71
89
  </script>
@@ -71,7 +71,7 @@ export default {
71
71
  classes.push(`${carbonSettings.prefix}--btn--field`);
72
72
  }
73
73
 
74
- return classes;
74
+ return classes.join(' ');
75
75
  };
76
76
  },
77
77
  },
@@ -27,13 +27,13 @@ export default {
27
27
  },
28
28
  computed: {
29
29
  buttonClasses() {
30
- return this.buttonClassOpts({ iconOnly: true });
30
+ return `${this.buttonClassOpts({ iconOnly: true })}${this.tipClasses}`;
31
31
  },
32
32
  tipClasses() {
33
33
  const tipPosition = this.tipPosition || 'bottom';
34
34
  const tipAlignment = this.tipAlignment || 'center';
35
35
  if (this.label) {
36
- return `${this.carbonPrefix}--tooltip__trigger ${this.carbonPrefix}--tooltip--a11y ${this.carbonPrefix}--tooltip--${tipPosition} ${this.carbonPrefix}--tooltip--align-${tipAlignment}`;
36
+ return ` ${this.carbonPrefix}--tooltip__trigger ${this.carbonPrefix}--tooltip--a11y ${this.carbonPrefix}--tooltip--${tipPosition} ${this.carbonPrefix}--tooltip--align-${tipAlignment}`;
37
37
  } else {
38
38
  return '';
39
39
  }
@@ -15,6 +15,7 @@
15
15
  :class="{
16
16
  'bx--list-box--light': theme === 'light',
17
17
  'bx--combo-box--expanded': open,
18
+ 'bx--list-box--expanded': open,
18
19
  'bx--combo-box--disabled bx--list-box--disabled': $attrs.disabled,
19
20
  }"
20
21
  :data-invalid="isInvalid"
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <th :aria-sort="sortOrder" :style="skeleton && headingStyle">
2
+ <th :aria-sort="internalOrder" :style="skeleton && headingStyle">
3
3
  <button
4
4
  type="button"
5
5
  v-if="sortable"
@@ -7,13 +7,15 @@
7
7
  @click="onSortClick"
8
8
  :style="headingStyle"
9
9
  >
10
- <cv-wrapper :tag-type="headingLabelTag" class="bx--table-header-label">{{ heading }}</cv-wrapper>
10
+ <cv-wrapper :tag-type="headingLabelTag" class="bx--table-header-label">
11
+ <slot>{{ heading }}</slot>
12
+ </cv-wrapper>
11
13
  <ArrowDown16 class="bx--table-sort__icon" />
12
14
  <Arrows16 class="bx--table-sort__icon-unsorted" />
13
15
  </button>
14
- <cv-wrapper v-else :tag-type="headingLabelTag" class="bx--table-header-label" :style="headingStyle">{{
15
- heading
16
- }}</cv-wrapper>
16
+ <cv-wrapper v-else :tag-type="headingLabelTag" class="bx--table-header-label" :style="headingStyle">
17
+ <slot>{{ heading }}</slot>
18
+ </cv-wrapper>
17
19
  </th>
18
20
  </template>
19
21
 
@@ -21,8 +23,9 @@
21
23
  import ArrowDown16 from '@carbon/icons-vue/es/arrow--down/16';
22
24
  import Arrows16 from '@carbon/icons-vue/es/arrows/16';
23
25
  import CvWrapper from '../cv-wrapper/_cv-wrapper';
26
+ import uidMixin from '../../mixins/uid-mixin';
24
27
 
25
- const nextSortOrder = {
28
+ const nextOrder = {
26
29
  ascending: 'descending',
27
30
  descending: 'none',
28
31
  none: 'ascending',
@@ -31,37 +34,64 @@ const nextSortOrder = {
31
34
  export default {
32
35
  name: 'CvDataTableHeading',
33
36
  components: { ArrowDown16, Arrows16, CvWrapper },
37
+ mixins: [uidMixin],
34
38
  props: {
35
- heading: { type: String, required: true },
39
+ dataStyle: Object,
40
+ heading: String,
36
41
  sortable: Boolean,
37
42
  order: { type: String, default: 'none' },
38
43
  skeleton: Boolean,
39
44
  headingStyle: Object,
40
45
  },
46
+ data() {
47
+ return {
48
+ dataOrder: this.order,
49
+ };
50
+ },
51
+ mounted() {
52
+ this.$_CvDataTableHeading = true; // for use by parent with $children
53
+ this.$parent.$emit('cv:mounted', this);
54
+ },
55
+ beforeDestroy() {
56
+ this.$parent.$emit('cv:beforeDestroy', this);
57
+ },
58
+ watch: {
59
+ order() {
60
+ this.dataOrder = this.order;
61
+ },
62
+ },
41
63
  computed: {
42
- sortOrder() {
43
- if (this.order !== 'ascending' && this.order !== 'descending') {
44
- return 'none';
45
- } else {
46
- return this.order;
47
- }
64
+ internalOrder: {
65
+ get() {
66
+ if (this.dataOrder !== 'ascending' && this.dataOrder !== 'descending') {
67
+ return 'none';
68
+ } else {
69
+ return this.dataOrder;
70
+ }
71
+ },
72
+ set(val) {
73
+ if (['ascending', 'descending', 'none'].includes(val)) {
74
+ this.dataOrder = val;
75
+ }
76
+ },
48
77
  },
49
78
  sortText() {
50
- return this.sortOrder !== 'descending'
79
+ return this.internalOrder !== 'descending'
51
80
  ? 'Sort rows by this header in descending order'
52
81
  : 'Sort rows by this header in ascending order';
53
82
  },
54
83
  orderClass() {
55
84
  let result = '';
56
- if (this.sortOrder === 'descending') {
85
+ if (this.internalOrder === 'descending') {
57
86
  result = 'bx--table-sort--active';
58
- } else if (this.sortOrder === 'ascending') {
87
+ } else if (this.internalOrder === 'ascending') {
59
88
  result = 'bx--table-sort--active bx--table-sort--ascending';
60
89
  }
61
90
  return result;
62
91
  },
63
92
  headingLabelTag() {
64
- return this.heading.length === 0 || !this.skeleton ? 'span' : '';
93
+ // no tag if non-blank skeleton
94
+ return this.skeleton && this.heading && this.heading.length > 0 ? '' : 'span';
65
95
  },
66
96
  },
67
97
  model: {
@@ -70,7 +100,7 @@ export default {
70
100
  },
71
101
  methods: {
72
102
  onSortClick() {
73
- this.$emit('sort', nextSortOrder[this.sortOrder]);
103
+ this.$parent.$emit('cv:sort', this, nextOrder[this.internalOrder]);
74
104
  },
75
105
  },
76
106
  };
@@ -9,10 +9,8 @@
9
9
  </div>
10
10
 
11
11
  <section v-if="hasToolbar" class="bx--table-toolbar">
12
- <div v-if="batchActive" :style="{ minHeight: '48px', maxWidth: '0' }" />
13
-
14
12
  <div
15
- v-if="hasBatchActions"
13
+ v-show="hasBatchActions"
16
14
  class="bx--batch-actions"
17
15
  :class="{ 'bx--batch-actions--active': batchActive }"
18
16
  :aria-label="actionBarAriaLabel"
@@ -34,7 +32,7 @@
34
32
  </div>
35
33
  </div>
36
34
 
37
- <div v-if="(hasActions || $listeners.search) && !batchActive" class="bx--toolbar-content">
35
+ <div class="bx--toolbar-content">
38
36
  <div
39
37
  v-if="$listeners.search"
40
38
  :class="{
@@ -113,16 +111,17 @@
113
111
  @change="onHeadingCheckChange"
114
112
  />
115
113
  </th>
116
- <cv-data-table-heading
117
- v-for="(column, index) in dataColumns"
118
- :key="`${index}:${column}`"
119
- :heading="columnHeading(column)"
120
- :sortable="isColSortable(column)"
121
- :order="column.order"
122
- @sort="val => onSort(index, val)"
123
- :heading-style="headingStyle(index)"
124
- :skeleton="skeleton"
125
- />
114
+ <slot name="headings">
115
+ <cv-data-table-heading
116
+ v-for="(column, index) in columns"
117
+ :key="`${index}:${column}`"
118
+ :heading="columnHeading(column)"
119
+ :sortable="isColSortable(column)"
120
+ :order="column.order"
121
+ :heading-style="headingStyle(column)"
122
+ :skeleton="skeleton"
123
+ />
124
+ </slot>
126
125
  <th v-if="hasOverflowMenu"></th>
127
126
  </tr>
128
127
  </thead>
@@ -148,7 +147,6 @@
148
147
  </cv-wrapper>
149
148
  </table>
150
149
  </div>
151
-
152
150
  <cv-pagination
153
151
  v-if="pagination"
154
152
  v-bind="internalPagination"
@@ -167,7 +165,7 @@
167
165
  </template>
168
166
 
169
167
  <script>
170
- import CvDataTableHeading from './_cv-data-table-heading';
168
+ import CvDataTableHeading from './cv-data-table-heading';
171
169
  import CvDataTableRow from './cv-data-table-row';
172
170
  import CvDataTableCell from './cv-data-table-cell';
173
171
  import CvButton from '../cv-button/cv-button';
@@ -216,7 +214,7 @@ export default {
216
214
  searchClearLabel: { type: String, default: 'Clear search' },
217
215
  sortable: Boolean,
218
216
  title: String,
219
- columns: { type: Array, required: true },
217
+ columns: Array,
220
218
  data: Array,
221
219
  zebra: Boolean,
222
220
  rowsSelected: { type: Array, default: () => [] },
@@ -231,13 +229,6 @@ export default {
231
229
  },
232
230
  data() {
233
231
  return {
234
- dataColumns: this.isSortable
235
- ? this.columns.map(item => ({
236
- label: item.label ? item.label : item,
237
- order: 'none',
238
- sortable: item.sortable,
239
- }))
240
- : this.columns,
241
232
  hasBatchActions: false,
242
233
  hasActions: false,
243
234
  hasToolbar: false,
@@ -249,16 +240,11 @@ export default {
249
240
  clearSearchVisible: false,
250
241
  searchActive: false,
251
242
  registeredRows: [],
243
+ registeredHeadings: [],
252
244
  dataExpandAll: false,
253
245
  };
254
246
  },
255
247
  watch: {
256
- sortable() {
257
- this.watchColumns();
258
- },
259
- columns() {
260
- this.watchColumns();
261
- },
262
248
  rowsSelected() {
263
249
  this.updateRowsSelected();
264
250
  },
@@ -267,9 +253,9 @@ export default {
267
253
  // add these on created otherwise cv:mounted is too late.
268
254
  this.$on('cv:mounted', srcComponent => this.onCvMount(srcComponent));
269
255
  this.$on('cv:beforeDestroy', srcComponent => this.onCvBeforeDestroy(srcComponent));
256
+ this.$on('cv:sort', (srcComponent, value) => this.onSort(srcComponent, value));
270
257
  },
271
258
  mounted() {
272
- this.watchColumns();
273
259
  this.updateRowsSelected();
274
260
  this.checkSlots();
275
261
  },
@@ -288,7 +274,7 @@ export default {
288
274
  },
289
275
  isSortable() {
290
276
  // is any column sortable
291
- return this.sortable || this.columns.some(column => column.sortable);
277
+ return this.sortable || this.registeredHeadings.some(column => column.sortable);
292
278
  },
293
279
  isColSortable() {
294
280
  return col => {
@@ -336,10 +322,10 @@ export default {
336
322
  return `${sizeClass}${zebraClass}${borderlessClass}${skeletonClass}${sortableClass}`.trim();
337
323
  },
338
324
  headingStyle() {
339
- return index => this.dataColumns[index].headingStyle;
325
+ return col => (typeof col === 'object' ? col.headingStyle : {});
340
326
  },
341
327
  dataStyle() {
342
- return index => this.dataColumns[index].dataStyle;
328
+ return index => (this.columns && this.columns[index] && this.columns[index].dataStyle) || {};
343
329
  },
344
330
  selectedRows() {
345
331
  return this.dataRowsSelected;
@@ -353,20 +339,36 @@ export default {
353
339
  this.hasToolbar = !!(this.$slots.actions || this.$listeners.search || this.$slots['batch-actions']);
354
340
  this.isHelper = !!(this.$slots['helper-text'] || (this.helperText && this.helperText.length));
355
341
  },
356
- onCvMount(row) {
357
- this.registeredRows.push(row);
358
- if (this.registeredRows.filter(item => item.uid === row.uid).length > 1) {
359
- console.error(
360
- `CvDataTable: Duplicate ID specified for CvDataTableRow, this may cause issues. {id: ${row.id}, value: ${row.value}}`
361
- );
342
+ onCvMount(thing) {
343
+ if (thing.$_CvDataTableHeading) {
344
+ this.registeredHeadings = this.$children.filter(item => item.$_CvDataTableHeading);
345
+ const heading = thing;
346
+ if (this.registeredHeadings.filter(item => item.uid === heading.uid).length > 1) {
347
+ console.error(
348
+ `CvDataTable: Duplicate ID specified for CvDataTableHeading, this may cause issues. {id: ${heading.id}}`
349
+ );
350
+ }
351
+ } else {
352
+ const row = thing;
353
+ this.registeredRows.push(row);
354
+ if (this.registeredRows.filter(item => item.uid === row.uid).length > 1) {
355
+ console.error(
356
+ `CvDataTable: Duplicate ID specified for CvDataTableRow, this may cause issues. {id: ${row.id}, value: ${row.value}}`
357
+ );
358
+ }
359
+ row.$on('cv:expanded-change', this.onCvExpandedChange);
360
+ this.updateSomeExpandingRows();
362
361
  }
363
- row.$on('cv:expanded-change', this.onCvExpandedChange);
364
- this.updateSomeExpandingRows();
365
362
  },
366
- onCvBeforeDestroy(row) {
367
- const index = this.registeredRows.findIndex(item => row.uid === item.uid);
368
- this.registeredRows.splice(index, 1);
369
- this.updateSomeExpandingRows();
363
+ onCvBeforeDestroy(thing) {
364
+ if (thing.$_CvDataTableHeading) {
365
+ this.registeredHeadings = this.$children.filter(item => item.$_CvDataTableHeading);
366
+ } else {
367
+ const row = thing;
368
+ const index = this.registeredRows.findIndex(item => row.uid === item.uid);
369
+ this.registeredRows.splice(index, 1);
370
+ this.updateSomeExpandingRows();
371
+ }
370
372
  },
371
373
  checkSearchFocus(ev) {
372
374
  if (!this.$refs.searchContainer.contains(ev.relatedTarget)) {
@@ -455,25 +457,21 @@ export default {
455
457
  onMenuItemClick(val) {
456
458
  this.$emit('overflow-menu-click', val);
457
459
  },
458
- watchColumns() {
459
- this.dataColumns = this.isSortable
460
- ? this.columns.map(item => ({
461
- ...item,
462
- label: item.label ? item.label : item,
463
- order: 'none',
464
- sortable: item.sortable,
465
- }))
466
- : this.columns;
467
- },
468
460
  onSearch() {
469
461
  this.clearSearchVisible = this.searchValue.length > 0;
470
462
  this.$emit('search', this.searchValue);
471
463
  },
472
- onSort(index, val) {
473
- for (let column of this.dataColumns) {
474
- column.order = 'none';
464
+ onSort(srcComponent, val) {
465
+ let index;
466
+ for (let colIndex in this.registeredHeadings) {
467
+ const column = this.registeredHeadings[colIndex];
468
+ if (column.uid === srcComponent.uid) {
469
+ column.internalOrder = val;
470
+ index = colIndex;
471
+ } else {
472
+ column.internalOrder = 'none';
473
+ }
475
474
  }
476
- this.dataColumns[index].order = val;
477
475
  this.$emit('sort', { index, order: val });
478
476
  },
479
477
  updateSomeExpandingRows() {
@@ -2,6 +2,7 @@ import CvDataTableAction from './cv-data-table-action';
2
2
  import CvDataTableCell from './cv-data-table-cell';
3
3
  import CvDataTableRow from './cv-data-table-row';
4
4
  import CvDataTable from './cv-data-table';
5
+ import CvDataTableHeading from './cv-data-table-heading';
5
6
  import CvDataTableSkeleton from './cv-data-table-skeleton';
6
7
 
7
- export { CvDataTable, CvDataTableRow, CvDataTableCell, CvDataTableAction, CvDataTableSkeleton };
8
+ export { CvDataTable, CvDataTableRow, CvDataTableCell, CvDataTableAction, CvDataTableHeading, CvDataTableSkeleton };
@@ -124,6 +124,8 @@ export default {
124
124
  name: 'CvPagination',
125
125
  components: { CvSelect, CvSelectOption, CaretLeft16, CaretRight16 },
126
126
  props: {
127
+ backwardsButtonDisabled: Boolean,
128
+ forwardsButtonDisabled: Boolean,
127
129
  backwardText: { type: String, default: 'Prev page' },
128
130
  forwardText: { type: String, default: 'Next page' },
129
131
  pageNumberLabel: { type: String, default: 'Page number:' },
@@ -173,10 +175,10 @@ export default {
173
175
  },
174
176
  computed: {
175
177
  noWayBack() {
176
- return this.pageValue === 1;
178
+ return this.backwardsButtonDisabled || this.pageValue === 1;
177
179
  },
178
180
  noWayForward() {
179
- return this.pageValue === this.pageCount;
181
+ return this.forwardsButtonDisabled || this.pageValue === this.pageCount;
180
182
  },
181
183
  ofNPagesProps() {
182
184
  return {
package/src/index.js CHANGED
@@ -39,6 +39,7 @@ import {
39
39
  CvDataTableCell,
40
40
  CvDataTableAction,
41
41
  CvDataTableSkeleton,
42
+ CvDataTableHeading,
42
43
  } from './components/cv-data-table';
43
44
  import { CvDatePicker } from './components/cv-date-picker';
44
45
  import { CvDropdown, CvDropdownItem, CvDropdownSkeleton } from './components/cv-dropdown';
@@ -107,7 +108,7 @@ export { CvCheckbox, CvCheckboxSkeleton };
107
108
  export { CvCodeSnippet, CvCodeSnippetSkeleton };
108
109
  export { CvComboBox };
109
110
  export { CvContentSwitcher, CvContentSwitcherButton, CvContentSwitcherContent };
110
- export { CvDataTable, CvDataTableRow, CvDataTableCell, CvDataTableAction, CvDataTableSkeleton };
111
+ export { CvDataTable, CvDataTableRow, CvDataTableCell, CvDataTableAction, CvDataTableSkeleton, CvDataTableHeading };
111
112
  export { CvDatePicker };
112
113
  export { CvDropdown, CvDropdownItem, CvDropdownSkeleton };
113
114
  export { CvFileUploader, CvFileUploaderSkeleton };