@mozaic-ds/vue 0.37.2-beta.0 → 0.38.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.37.2-beta.0",
3
+ "version": "0.38.0-beta.0",
4
4
  "description": "Vue.js implementation of Mozaic Design System",
5
5
  "author": "Adeo - Mozaic Design System",
6
6
  "scripts": {
@@ -28,7 +28,7 @@
28
28
  "@mozaic-ds/icons": "1.52.0",
29
29
  "@mozaic-ds/styles": "1.53.0",
30
30
  "@mozaic-ds/web-fonts": "1.22.0",
31
- "core-js": "^3.27.2",
31
+ "core-js": "^3.28.0",
32
32
  "libphonenumber-js": "^1.10.19",
33
33
  "vue": "^2.6.14",
34
34
  "vue-country-flag": "2.3.2"
@@ -42,14 +42,14 @@
42
42
  "@vue/compiler-sfc": "^3.2.45",
43
43
  "@vue/eslint-config-prettier": "^7.0.0",
44
44
  "babel-eslint": "^10.1.0",
45
- "eslint": "^8.33.0",
45
+ "eslint": "^8.34.0",
46
46
  "eslint-config-prettier": "^8.6.0",
47
47
  "eslint-plugin-vue": "^9.9.0",
48
48
  "postcss": "^8.4.21",
49
49
  "postcss-loader": "^7.0.2",
50
50
  "postcss-scss": "^4.0.6",
51
- "prettier": "^2.8.3",
52
- "sass": "^1.58.0",
51
+ "prettier": "^2.8.4",
52
+ "sass": "^1.58.1",
53
53
  "sass-loader": "^13.2.0",
54
54
  "vue-template-compiler": "^2.7.14"
55
55
  },
@@ -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"
@@ -179,7 +179,6 @@ export default {
179
179
  openState: this.open,
180
180
  tagWidth: '0px',
181
181
  tagValue: null,
182
- buttonValue: this.placeholder,
183
182
  localItems: null,
184
183
  sortedListItems: null,
185
184
  listboxValue: null,
@@ -215,6 +214,25 @@ export default {
215
214
  'mc-select--s': this.size === 's',
216
215
  };
217
216
  },
217
+ getButtonLabel() {
218
+ let label = this.placeholder;
219
+
220
+ if (this.modelValue && !this.items.length) {
221
+ return label;
222
+ }
223
+
224
+ const value = this.listboxValue;
225
+ const selectedItems = this.getSelectedItems(value);
226
+ const selectedLabels = selectedItems.map(
227
+ (item) => item[this.dataTextExpr]
228
+ );
229
+
230
+ label =
231
+ ((!value || value.length === 0) && this.placeholder) ||
232
+ selectedLabels.join(', ');
233
+
234
+ return label;
235
+ },
218
236
  },
219
237
 
220
238
  watch: {
@@ -236,15 +254,6 @@ export default {
236
254
  },
237
255
  listboxValue: {
238
256
  handler: function (val) {
239
- const selectedItems = this.getSelectedItems(val);
240
- const seletedLabels = selectedItems.map(
241
- (item) => item[this.dataTextExpr]
242
- );
243
-
244
- this.buttonValue =
245
- ((!val || val.length === 0) && this.placeholder) ||
246
- seletedLabels.join(', ');
247
-
248
257
  if (this.multiple) {
249
258
  this.tagValue = val;
250
259
  }
@@ -263,7 +272,6 @@ export default {
263
272
  this.$emit('update:open', val);
264
273
  },
265
274
  },
266
-
267
275
  methods: {
268
276
  setTagWidth() {
269
277
  this.$nextTick(() => {
@@ -237,44 +237,55 @@ export default {
237
237
  <style lang="scss">
238
238
  @import 'settings-tools/all-settings';
239
239
  @import 'components/c.divider';
240
+
240
241
  .mc-header {
241
242
  @include set-font-face();
243
+
242
244
  background-color: $color-grey-000;
243
- z-index: 10;
245
+ z-index: 5;
246
+
244
247
  &__container {
245
248
  display: grid;
246
249
  padding: $mu050 $mu150 $mu100;
250
+
247
251
  @include set-from-screen('l') {
248
252
  padding-left: $mu200;
249
253
  padding-right: $mu200;
250
254
  }
251
255
  }
256
+
252
257
  &__breadcrumb {
253
258
  grid-column: 1;
254
259
  grid-row: auto;
255
260
  }
261
+
256
262
  &__content {
257
263
  color: $color-font-darkest;
258
264
  grid-column: 1;
259
265
  grid-row: auto;
260
266
  padding-top: $mu050;
267
+
261
268
  &-main {
262
269
  display: flex;
263
270
  align-items: center;
264
271
  gap: $mu100;
272
+
265
273
  &:not(:only-child) {
266
274
  margin-bottom: $mu025;
267
275
  }
268
276
  }
277
+
269
278
  &-aside {
270
279
  display: flex;
271
280
  align-items: flex-start;
272
281
  flex-direction: column;
273
282
  gap: $mu050;
274
283
  padding-bottom: $mu050;
284
+
275
285
  &.can-navigate {
276
286
  padding-left: $mu300;
277
287
  }
288
+
278
289
  @include set-from-screen('l') {
279
290
  align-items: center;
280
291
  flex-direction: row;
@@ -283,8 +294,10 @@ export default {
283
294
  }
284
295
  }
285
296
  }
297
+
286
298
  &__back {
287
299
  @include unstyle-button();
300
+
288
301
  align-items: center;
289
302
  background-color: transparent;
290
303
  justify-content: center;
@@ -292,39 +305,51 @@ export default {
292
305
  display: flex;
293
306
  height: $mu200;
294
307
  width: $mu200;
308
+
295
309
  &-icon {
296
310
  color: $color-grey-800;
297
311
  height: $mu150;
298
312
  width: $mu150;
299
313
  }
314
+
300
315
  &-label {
301
316
  @include visually-hidden();
302
317
  }
303
318
  }
319
+
304
320
  &__title {
321
+ @include set-font-weight('semi-bold');
322
+
305
323
  margin-top: 0;
306
324
  margin-bottom: 0;
325
+
307
326
  &--s {
308
327
  @include set-font-scale('07', 'm'); // 23px / 32px
309
328
  }
329
+
310
330
  &--m {
311
331
  @include set-font-scale('08', 'm'); // 28px / 36px
312
332
  }
333
+
313
334
  &--l {
314
335
  @include set-font-scale('09', 'm'); // 34px / 44px
315
336
  }
337
+
316
338
  &--xl {
317
339
  @include set-font-scale('10', 'm'); // 41px / 56px
318
340
  }
319
341
  }
342
+
320
343
  &__subtitle {
321
344
  @include set-font-scale('05', 'm'); // 16px / 22px
322
345
  }
346
+
323
347
  &__actions,
324
348
  &__icons {
325
349
  display: flex;
326
350
  gap: $mu150;
327
351
  }
352
+
328
353
  &__actions {
329
354
  align-items: flex-end;
330
355
  align-self: flex-start;
@@ -333,40 +358,49 @@ export default {
333
358
  justify-self: end;
334
359
  margin-bottom: $mu050;
335
360
  min-height: $mu250;
361
+
336
362
  @include set-from-screen('l') {
337
363
  grid-column: 2;
338
364
  grid-row: 1;
339
365
  margin-bottom: 0;
340
366
  }
341
367
  }
368
+
342
369
  &__selector {
343
370
  &:not(:only-child) {
344
371
  @include set-divider('left', 'light', '100%', 's');
372
+
345
373
  padding-left: px-to-rem(25);
346
374
  position: relative;
347
375
  }
348
376
  }
377
+
349
378
  &__tabs {
350
379
  padding-left: $mu200;
351
380
  padding-right: $mu200;
352
381
  }
382
+
353
383
  // Modifiers
354
384
  &--shadow {
355
385
  @include set-box-shadow('s');
356
386
  }
387
+
357
388
  &--animate {
358
389
  left: 0;
359
390
  position: absolute;
360
391
  right: 0;
361
392
  transition: transform ease-out 0.4s;
362
393
  }
394
+
363
395
  &--sticky {
364
396
  position: sticky;
365
397
  top: 0;
366
398
  }
399
+
367
400
  &--up {
368
401
  transform: translateY(0);
369
402
  }
403
+
370
404
  &--down {
371
405
  transform: translateY(calc(-100% - 5px));
372
406
  }