@mozaic-ds/vue 0.38.0 → 0.39.0-beta.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.38.0",
3
+ "version": "0.39.0-beta.0",
4
4
  "description": "Vue.js implementation of Mozaic Design System",
5
5
  "author": "Adeo - Mozaic Design System",
6
6
  "scripts": {
@@ -7,6 +7,13 @@
7
7
  <table aria-describedby="data" :class="getTableClasses">
8
8
  <thead>
9
9
  <tr v-if="!hideHeader">
10
+ <th
11
+ v-if="expandable"
12
+ scope="col"
13
+ class="mc-datatable__cell-button"
14
+ >
15
+ &nbsp;
16
+ </th>
10
17
  <th
11
18
  v-for="(header, index) in getHeaders"
12
19
  :key="`header-${index}`"
@@ -40,30 +47,68 @@
40
47
  </tr>
41
48
  </thead>
42
49
  <tbody>
43
- <tr
44
- v-for="(item, rowIndex) in getSource"
45
- :key="item[dataKeyExpr]"
46
- :class="rowClasses(item)"
47
- >
48
- <td
49
- v-for="(header, index) in getHeaders"
50
- :key="`${index}-${getItemValue(item, dataKeyExpr)}-${
51
- header.dataFieldExpr
52
- }`"
53
- :class="header.cssClass"
54
- @click="
55
- allowRowClick && onRowClick({ event: $event, item: item })
56
- "
50
+ <template v-for="(item, rowIndex) in getSource">
51
+ <tr
52
+ :key="item[dataKeyExpr]"
53
+ :class="[rowClasses(item), parentRowClasses]"
57
54
  >
58
- <slot
59
- :name="`item.${header.dataFieldExpr}`"
60
- :item="item"
61
- :index="rowIndex"
55
+ <td v-if="expandable">
56
+ <button
57
+ v-if="expandableList?.includes(item.id) || !expandableList"
58
+ type="button"
59
+ class="mc-datatable__expand mc-datatable__btn"
60
+ @click="onClickExpander($event, item, rowIndex)"
61
+ >
62
+ <span class="mc-datatable__btn-label">
63
+ {{ expanderAccessibleLabel }}
64
+ </span>
65
+ <MIcon
66
+ name="ControlCircleMore24"
67
+ class="mc-datatable__btn-icon expand-more"
68
+ />
69
+ <MIcon
70
+ name="ControlCircleLess24"
71
+ class="mc-datatable__btn-icon expand-less"
72
+ />
73
+ </button>
74
+ </td>
75
+ <td
76
+ v-for="(header, index) in getHeaders"
77
+ :key="`${index}-${getItemValue(item, dataKeyExpr)}-${
78
+ header.dataFieldExpr
79
+ }`"
80
+ :class="header.cssClass"
81
+ @click="
82
+ allowRowClick && onRowClick({ event: $event, item: item })
83
+ "
62
84
  >
63
- {{ getItemValue(item, header.dataFieldExpr) }}
64
- </slot>
65
- </td>
66
- </tr>
85
+ <slot
86
+ :name="`item.${header.dataFieldExpr}`"
87
+ :item="item"
88
+ :index="rowIndex"
89
+ >
90
+ {{ getItemValue(item, header.dataFieldExpr) }}
91
+ </slot>
92
+ </td>
93
+ </tr>
94
+ <tr
95
+ v-if="expandable"
96
+ :key="'subrow' + item[dataKeyExpr]"
97
+ class="mc-datatable__row-expandable"
98
+ :class="expandableRowClasses"
99
+ >
100
+ <td :colspan="getHeaders.length + 1">
101
+ <div class="mc-datatable__row-inner">
102
+ <slot
103
+ name="expandContent"
104
+ :item="item"
105
+ :row-index="rowIndex"
106
+ >
107
+ </slot>
108
+ </div>
109
+ </td>
110
+ </tr>
111
+ </template>
67
112
  <tr v-if="getSource.length == 0">
68
113
  <td :colspan="getHeaders.length">
69
114
  <slot name="no-data" />
@@ -300,6 +345,18 @@ export default {
300
345
  type: [String, Function, Object],
301
346
  default: '',
302
347
  },
348
+ expandable: {
349
+ type: Boolean,
350
+ default: false,
351
+ },
352
+ expandableList: {
353
+ type: Array,
354
+ default: undefined,
355
+ },
356
+ expanderAccessibleLabel: {
357
+ type: String,
358
+ default: 'Déplier la ligne',
359
+ },
303
360
  },
304
361
 
305
362
  data() {
@@ -388,6 +445,18 @@ export default {
388
445
  const on = skip + take;
389
446
  return `${skip + 1} - ${on >= this.total ? this.total : on}`;
390
447
  },
448
+
449
+ parentRowClasses() {
450
+ return {
451
+ 'mc-datatable__row-parent': this.expandable,
452
+ };
453
+ },
454
+
455
+ expandableRowClasses() {
456
+ return {
457
+ 'mc-datatable__row-expandable--offset-1': this.expandable,
458
+ };
459
+ },
391
460
  },
392
461
 
393
462
  watch: {
@@ -591,13 +660,30 @@ export default {
591
660
  onRowClick(e) {
592
661
  this.$emit('row-click', e);
593
662
  },
663
+
664
+ onClickExpander(e, rowData, rowIndex) {
665
+ const button = e.currentTarget;
666
+ const row = button.closest('tr');
667
+
668
+ button.classList.toggle('is-expand');
669
+ row.classList.toggle('mc-datatable__row-parent--expanded');
670
+
671
+ const isExpanded = button.classList.contains('is-expand');
672
+
673
+ const eventName = isExpanded ? 'expand-row' : 'retract-row';
674
+ const eventArg = { data: rowData, index: rowIndex };
675
+
676
+ this.$emit(eventName, eventArg);
677
+ },
594
678
  },
595
679
  };
596
680
  </script>
597
681
 
598
682
  <style lang="scss">
599
683
  /* stylelint-disable */
600
- @import 'settings-tools/_all-settings';
684
+ @import 'settings-tools/all-settings';
685
+ @import 'components/c.datatable-tools';
686
+ @import 'components/c.datatable-subtable';
601
687
 
602
688
  .mc-data-table {
603
689
  @include set-font-family;
@@ -728,6 +814,62 @@ export default {
728
814
  vertical-align: middle;
729
815
  padding: 0 $mu100;
730
816
  }
817
+
818
+ .mc-datatable__row {
819
+ $datatable-row: &;
820
+
821
+ &-parent:not(.mc-datatable__row-parent--expanded)
822
+ + .mc-datatable__row-expandable {
823
+ height: 0;
824
+
825
+ .mc-datatable__row-inner {
826
+ overflow: hidden;
827
+ max-height: 0;
828
+ }
829
+ }
830
+
831
+ &-parent.mc-datatable__row-parent--expanded
832
+ + .mc-datatable__row-expandable {
833
+ .mc-datatable__row-inner {
834
+ max-height: 100%;
835
+ }
836
+ }
837
+
838
+ &-expandable {
839
+ height: auto;
840
+
841
+ & > td {
842
+ padding: 0;
843
+ border-bottom: 0;
844
+ }
845
+
846
+ &--offset {
847
+ &-1 {
848
+ table {
849
+ th:first-child,
850
+ td:first-child {
851
+ padding-left: $width-cell-checkbox + $mu100;
852
+ }
853
+ }
854
+ }
855
+
856
+ &-2 {
857
+ table {
858
+ th:first-child,
859
+ td:first-child {
860
+ padding-left: $width-cell-checkbox + $width-cell-button +
861
+ $mu100;
862
+ }
863
+ }
864
+ }
865
+ }
866
+ }
867
+
868
+ &__inner,
869
+ &-inner {
870
+ background-color: $color-background-datatable-subtable;
871
+ }
872
+ }
731
873
  }
732
874
  }
733
875
 
@@ -765,7 +907,6 @@ export default {
765
907
  }
766
908
 
767
909
  // footer
768
-
769
910
  &__footer {
770
911
  @include set-box-shadow('s');
771
912
 
@@ -808,6 +949,40 @@ export default {
808
949
  background-color: $color-background-datatable-container;
809
950
  overflow: hidden;
810
951
  }
952
+
953
+ &__cell {
954
+ &-checkbox {
955
+ width: $width-cell-checkbox;
956
+ }
957
+
958
+ &-button {
959
+ width: $width-cell-button;
960
+ }
961
+
962
+ &-field {
963
+ min-width: $width-cell-field;
964
+ }
965
+
966
+ &-number {
967
+ @at-root td#{&} {
968
+ text-align: right;
969
+ }
970
+ }
971
+ }
972
+
973
+ &__expand {
974
+ &:not(.is-expand) {
975
+ .expand-less {
976
+ display: none;
977
+ }
978
+ }
979
+
980
+ &.is-expand {
981
+ .expand-more {
982
+ display: none;
983
+ }
984
+ }
985
+ }
811
986
  }
812
987
  /* stylelint-enable */
813
988
  </style>
@@ -25,7 +25,7 @@
25
25
  :disabled="disabled"
26
26
  @click="openState = !openState"
27
27
  >
28
- {{ buttonValue }}
28
+ {{ getButtonLabel }}
29
29
  </button>
30
30
  <button
31
31
  v-if="isClearable"
@@ -174,7 +174,6 @@ export default {
174
174
  openState: this.open,
175
175
  tagWidth: '0px',
176
176
  tagValue: null,
177
- buttonValue: this.placeholder,
178
177
  localItems: null,
179
178
  sortedListItems: null,
180
179
  listboxValue: null,
@@ -210,6 +209,25 @@ export default {
210
209
  'mc-select--s': this.size === 's',
211
210
  };
212
211
  },
212
+ getButtonLabel() {
213
+ let label = this.placeholder;
214
+
215
+ if (this.modelValue && !this.items.length) {
216
+ return label;
217
+ }
218
+
219
+ const value = this.listboxValue;
220
+ const selectedItems = this.getSelectedItems(value);
221
+ const selectedLabels = selectedItems.map(
222
+ (item) => item[this.dataTextExpr]
223
+ );
224
+
225
+ label =
226
+ ((!value || value.length === 0) && this.placeholder) ||
227
+ selectedLabels.join(', ');
228
+
229
+ return label;
230
+ },
213
231
  },
214
232
 
215
233
  watch: {
@@ -231,15 +249,6 @@ export default {
231
249
  },
232
250
  listboxValue: {
233
251
  handler: function (val) {
234
- const selectedItems = this.getSelectedItems(val);
235
- const seletedLabels = selectedItems.map(
236
- (item) => item[this.dataTextExpr]
237
- );
238
-
239
- this.buttonValue =
240
- ((!val || val.length === 0) && this.placeholder) ||
241
- seletedLabels.join(', ');
242
-
243
252
  if (this.multiple) {
244
253
  this.tagValue = val;
245
254
  }
@@ -258,7 +267,6 @@ export default {
258
267
  this.$emit('update:open', val);
259
268
  },
260
269
  },
261
-
262
270
  methods: {
263
271
  setTagWidth() {
264
272
  this.$nextTick(() => {