codevdesign 0.0.1 → 0.0.2

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.
@@ -0,0 +1,567 @@
1
+ <template>
2
+ <csqc-modale
3
+ ref="modale"
4
+ :titre="$tc('csqc-table.choixColonnes.titre')"
5
+ v-on:fermer="fermer"
6
+ :afficherOk="false"
7
+ :afficherAnnuler="!sauvegardeEnCours"
8
+ width="90vw"
9
+ maxWidth="4000px"
10
+ >
11
+ <v-alert
12
+ v-model="afficherErreur"
13
+ type="error"
14
+ dismissible
15
+ >{{ erreur }}</v-alert>
16
+ <v-row>
17
+ <v-col
18
+ cols="12"
19
+ class="pa-0 relative"
20
+ >
21
+ <v-btn
22
+ v-show="choixRetourEnHaut"
23
+ class="BarreRechercheBackIcone retourHautChoix"
24
+ bottom
25
+ fab
26
+ absolute
27
+ right
28
+ color="primary"
29
+ @click="retourEnHaut('#choixColonnes-choix > .v-data-table__wrapper')"
30
+ >
31
+ <v-icon>mdi-arrow-up</v-icon>
32
+ </v-btn>
33
+ <v-data-table
34
+ class="limiteHauteurChoix"
35
+ id="choixColonnes-choix"
36
+ :headers="colonnesChoix"
37
+ item-key="nomVue"
38
+ :items="choix"
39
+ single-expand
40
+ :expanded.sync="choixEnCours"
41
+ @click:row="cliquer"
42
+ disable-pagination
43
+ hide-default-footer
44
+ fixed-header
45
+ >
46
+ <template #header.action>
47
+ <v-btn
48
+ color="primary"
49
+ class="float-right"
50
+ small
51
+ @click.stop="ajouter"
52
+ :disabled="desactiverAjout"
53
+ >
54
+ {{ $tc('csqc-table.button.ajouter') }}
55
+ </v-btn>
56
+ </template>
57
+
58
+ <template #expanded-item="{headers}">
59
+ <td
60
+ :colspan="headers.length"
61
+ class="pa-0 ma-0"
62
+ >
63
+ <v-row
64
+ class="pa-0 ma-0"
65
+ no-gutters
66
+ >
67
+ <v-col
68
+ cols="12"
69
+ class="pa-0 ma-0"
70
+ >
71
+ <v-btn
72
+ v-show="colonnesRetourEnHaut"
73
+ class="BarreRechercheBackIcone retourHautChoix colonnes"
74
+ bottom
75
+ fab
76
+ absolute
77
+ right
78
+ color="primary"
79
+ @click="retourEnHaut('#choixColonnes-vue > .v-data-table__wrapper')"
80
+ >
81
+ <v-icon>mdi-arrow-up</v-icon>
82
+ </v-btn>
83
+ <v-data-table
84
+ class="limiteHauteurChoix colonnes mt-1 mb-4 ml-2 ordonable"
85
+ id="choixColonnes-vue"
86
+ :headers="colonnesChoixColonne"
87
+ v-sortable-data-table
88
+ @sorted="changeOrdre"
89
+ :sort-by.sync="triColonnesChoix"
90
+ :items="colonnesEnCours"
91
+ item-key="value"
92
+ hide-default-footer
93
+ disable-pagination
94
+ fixed-header
95
+ :style="`margin-right: ${90 - $vuetify.breakpoint.scrollBarWidth}px;`"
96
+ >
97
+ <template
98
+ #header.action
99
+ v-if="choixEnCours[0]?.colonnes.length <= 0"
100
+ >
101
+ <v-tooltip
102
+ left
103
+ color="warning"
104
+ >
105
+ <template #activator="{ on }">
106
+ <v-icon
107
+ color="warning"
108
+ v-on="on"
109
+ >mdi-alert</v-icon>
110
+ </template>
111
+ {{ $tc('csqc-table.choixColonnes.activezUneColonne') }}
112
+ </v-tooltip>
113
+ </template>
114
+
115
+ <template #item.action="{ item }">
116
+ <v-btn
117
+ class="mr-1"
118
+ icon
119
+ @click.stop="basculeColonneClique(item)"
120
+ >
121
+ <v-icon :color="couleurColonneCliquee(item)">{{ colonneEstClique(item) ? 'mdi-eye' : 'mdi-eye-off' }}</v-icon>
122
+ </v-btn>
123
+ </template>
124
+ <template #item.text="{ item }">{{ item.text ? item.text : item.value }}</template>
125
+ </v-data-table>
126
+ </v-col>
127
+ </v-row>
128
+ </td>
129
+ </template>
130
+
131
+ <template #item.nomVue="{ item }">
132
+ <v-text-field
133
+ :label="$tc('csqc-table.choixColonnes.nomVue')"
134
+ v-model.trim="nomVueEnCours"
135
+ single-line
136
+ dense
137
+ autofocus
138
+ class="py-0 my-0"
139
+ :rules="regles.nomVue"
140
+ hide-details
141
+ v-if="item.nomVue === vueEnEdition"
142
+ @keydown.enter="accepterEdition"
143
+ @keydown.esc.stop="annulerEdition"
144
+ ></v-text-field>
145
+ <span
146
+ :class="{ 'error--text': !item.nomVue }"
147
+ v-else
148
+ >
149
+ {{ item.nomVue || $tc('csqc-table.choixColonnes.nomVueRequis') }}
150
+ </span>
151
+ </template>
152
+ <template #item.action="{ item }">
153
+ <template v-if="item.nomVue === vueEnEdition">
154
+ <v-btn
155
+ icon
156
+ @click.stop.prevent="annulerEdition"
157
+ ><v-icon class="iconeSupprimer">mdi-window-close</v-icon></v-btn>
158
+ <v-btn
159
+ icon
160
+ @click.stop.prevent="accepterEdition"
161
+ ><v-icon class="couleurHover">mdi-check</v-icon></v-btn>
162
+ </template>
163
+ <template v-else>
164
+ <v-btn
165
+ icon
166
+ @click.stop.prevent="selectionner(item)"
167
+ ><v-icon class="couleurHover">mdi-eye</v-icon></v-btn>
168
+ <v-btn
169
+ icon
170
+ @click.stop.prevent="mettreDefaut(item)"
171
+ >
172
+ <v-icon
173
+ class="couleurHover"
174
+ :color="couleurDefaut(item)"
175
+ >mdi-star</v-icon>
176
+ </v-btn>
177
+ <v-btn
178
+ icon
179
+ @click.stop.prevent="editer(item)"
180
+ ><v-icon class="couleurHover">mdi-pencil</v-icon></v-btn>
181
+ <v-btn
182
+ icon
183
+ @click.stop.prevent="supprimer(item)"
184
+ ><v-icon class="iconeSupprimer">mdi-delete</v-icon></v-btn>
185
+ </template>
186
+ </template>
187
+ </v-data-table>
188
+ </v-col>
189
+ </v-row>
190
+
191
+ <template #actions>
192
+ <v-btn
193
+ @click.stop="sauvegarder"
194
+ color="primary"
195
+ class="elevation-0"
196
+ :disabled="!formValide"
197
+ :loading="sauvegardeEnCours"
198
+ >
199
+ {{ $tc('csqc-table.choixColonnes.ok') }}
200
+ </v-btn>
201
+ </template>
202
+ </csqc-modale>
203
+ </template>
204
+
205
+ <script>
206
+ import Sortable from 'sortablejs';
207
+ import axios from 'axios';
208
+ import CsqcModale from '../CsqcDialogue/csqc-boite-dialogue.vue';
209
+
210
+ export default {
211
+ directives: {
212
+ sortableDataTable: {
213
+ bind(el, binding, vnode) {
214
+ const options = {
215
+ animation: 150,
216
+ onUpdate(event) {
217
+ vnode.child.$emit('sorted', event);
218
+ },
219
+ };
220
+ Sortable.create(el.getElementsByTagName('tbody')[0], options);
221
+ },
222
+ },
223
+ },
224
+ components: {
225
+ 'csqc-modale': CsqcModale,
226
+ },
227
+ props: {
228
+ urlbase: {
229
+ required: true,
230
+ type: String,
231
+ },
232
+ formulaireId: {
233
+ required: true,
234
+ type: Number,
235
+ },
236
+ identifiant: {
237
+ required: true,
238
+ type: String,
239
+ },
240
+ colonnes: {
241
+ required: true,
242
+ type: Array,
243
+ },
244
+ choixOrigine: {
245
+ required: true,
246
+ type: Array,
247
+ },
248
+ },
249
+ data() {
250
+ return {
251
+ erreur: '',
252
+ afficherErreur: false,
253
+ choixEnCours: [],
254
+ choix: [],
255
+ colonnesEnCours: [],
256
+ triColonnesChoix: ['ordre'],
257
+ sauvegardeEnCours: false,
258
+ choixRetourEnHaut: false,
259
+ colonnesRetourEnHaut: false,
260
+ nomVueEnCours: '',
261
+ vueEnEdition: '',
262
+ desactiverAjout: false,
263
+ regles: {
264
+ nomVue: [
265
+ (v) => (v && v.trim().length >= 1) || this.$tc('csqc-table.choixColonnes.nomVueRequis'),
266
+ (v) => !this.choix.some(({ nomVue }) => v.trim() === nomVue) || this.$tc('csqc-table.choixColonnes.nomVueExiste'),
267
+ ],
268
+ },
269
+ };
270
+ },
271
+ methods: {
272
+ ouvrir() {
273
+ this.choix = JSON.parse(JSON.stringify(this.choixOrigine));
274
+ this.$refs.modale.ouvrir();
275
+ this.ecouteDefilerChoix();
276
+ },
277
+
278
+ fermer() {
279
+ this.sauvegardeEnCours = false;
280
+ this.desactiverAjout = false;
281
+ this.vueEnEdition = '';
282
+ this.choixEnCours = [];
283
+ this.colonnesEnCours = [];
284
+ this.erreur = '';
285
+ this.$refs.modale.fermer();
286
+ },
287
+
288
+ ajouter() {
289
+ const ch = {
290
+ nomVue: '',
291
+ colonnes: [],
292
+ defaut: this.choix.length === 0,
293
+ };
294
+ this.choix.push(ch);
295
+
296
+ this.cliquer(ch);
297
+ this.editer(ch);
298
+ },
299
+ editer(ch) {
300
+ this.desactiverAjout = true;
301
+ if (ch.nomVue !== '') this.supprimer({ nomVue: '' });
302
+
303
+ this.erreur = '';
304
+ this.nomVueEnCours = ch.nomVue;
305
+ this.vueEnEdition = ch.nomVue;
306
+ },
307
+ accepterEdition() {
308
+ if (!this.nomVueEnCours) {
309
+ this.erreur = this.$tc('csqc-table.choixColonnes.nomVueRequis');
310
+ return;
311
+ }
312
+
313
+ if (this.choix.some(({ nomVue }) => nomVue === this.nomVueEnCours)) {
314
+ this.erreur = this.$tc('csqc-table.choixColonnes.nomVueExiste');
315
+ return;
316
+ }
317
+
318
+ const ch = this.choix.find(({ nomVue }) => nomVue === this.vueEnEdition);
319
+ const choixClique = this.choixEstClique(ch);
320
+
321
+ ch.nomVue = this.nomVueEnCours;
322
+ if (choixClique) this.choixEnCours = [ch];
323
+ this.vueEnEdition = '';
324
+ this.nomVueEnCours = '';
325
+ this.desactiverAjout = false;
326
+ },
327
+ annulerEdition() {
328
+ const ch = this.choix.find(({ nomVue }) => nomVue === this.vueEnEdition);
329
+ if (ch.nomVue === '') this.supprimer(ch);
330
+ this.vueEnEdition = '';
331
+ this.nomVueEnCours = '';
332
+ this.desactiverAjout = false;
333
+ },
334
+
335
+ selectionner(ch) {
336
+ this.$emit('selection', ch);
337
+ this.fermer();
338
+ },
339
+
340
+ cliquer(ch) {
341
+ if (this.choixEnCours.length > 0) this.retourEnHaut('#choixColonnes-vue > .v-data-table__wrapper');
342
+ if (this.choixEstClique(ch)) {
343
+ this.choixEnCours = [];
344
+ this.colonnesEnCours = [];
345
+ return;
346
+ }
347
+
348
+ this.colonnesEnCours = JSON.parse(JSON.stringify(this.colonnes)); // Toujours commencer avec les colonnes par défaut
349
+ this.choixEnCours = [ch];
350
+ const tempCols = [];
351
+ const colsPlusDispo = [];
352
+
353
+ this.choixEnCours[0].colonnes.forEach((colonne) => {
354
+ const tCol = this.colonnesEnCours.find((c) => c.value === colonne);
355
+ if (tCol == null) colsPlusDispo.push(colonne); // Ne supprime pas dans la collection lors son itération
356
+ else tempCols.push(tCol);
357
+ });
358
+
359
+ // Nettoyer la vue au besoin (effectif seulement si l'utilisateur sauve les choix)
360
+ if (colsPlusDispo.length > 0) {
361
+ this.choixEnCours[0].colonnes = this.choixEnCours[0].colonnes.filter((c) => !colsPlusDispo.some((cpd) => c === cpd));
362
+ }
363
+
364
+ this.colonnesEnCours = tempCols.concat(this.colonnesEnCours.filter((c) => !this.choixEnCours[0].colonnes.some((cch) => cch === c.value)));
365
+ this.calculOrdreColonnes();
366
+ this.ecouteDefilerColonnes();
367
+ },
368
+
369
+ choixEstClique(ch) {
370
+ return ch.nomVue === this.choixEnCours[0]?.nomVue;
371
+ },
372
+
373
+ mettreDefaut(ch) {
374
+ this.choix.find(({ defaut }) => defaut).defaut = false;
375
+ this.choix.find(({ nomVue }) => nomVue === ch.nomVue).defaut = true;
376
+ },
377
+ couleurDefaut(ch) {
378
+ if (ch.defaut === true) {
379
+ return '#daa520';
380
+ }
381
+
382
+ return 'gray';
383
+ },
384
+
385
+ colonneEstClique(colonne) {
386
+ if (this.choixEnCours.length <= 0) { return false; }
387
+
388
+ return this.choixEnCours[0].colonnes.some((x) => x === colonne.value);
389
+ },
390
+ couleurColonneCliquee(colonne) {
391
+ if (this.colonneEstClique(colonne)) return 'primary';
392
+ return 'gray';
393
+ },
394
+ basculeColonneClique(colonne) {
395
+ if (this.colonneEstClique(colonne)) {
396
+ this.choixEnCours[0].colonnes = this.choixEnCours[0].colonnes.filter((x) => x !== colonne.value);
397
+ return;
398
+ }
399
+
400
+ this.choixEnCours[0].colonnes.push(colonne.value);
401
+ },
402
+
403
+ changeOrdre(event) {
404
+ const movedItem = this.colonnesEnCours.splice(event.oldIndex, 1)[0];
405
+ this.colonnesEnCours.splice(event.newIndex, 0, movedItem);
406
+ this.calculOrdreColonnes();
407
+ this.choixEnCours[0].colonnes = this.colonnesCliquees;
408
+ },
409
+ calculOrdreColonnes() {
410
+ for (let i = 0; i < this.colonnesEnCours.length; i += 1) {
411
+ this.colonnesEnCours[i].ordre = 1 + i;
412
+ }
413
+ },
414
+
415
+ supprimer(ch) {
416
+ if (this.choixEstClique(ch)) this.choixEnCours = [];
417
+
418
+ const index = this.choix.findIndex(({ nomVue }) => nomVue === ch.nomVue);
419
+ if (index === -1) {
420
+ return;
421
+ }
422
+
423
+ if (this.choix[index].defaut) {
424
+ const nonDefaut = this.choix.find(({ nomVue }) => nomVue !== ch.nomVue);
425
+ if (nonDefaut) {
426
+ nonDefaut.defaut = true;
427
+ }
428
+ }
429
+
430
+ this.choix.splice(index, 1);
431
+ },
432
+
433
+ // ENREGISTREMENT
434
+ sauvegarder() {
435
+ axios.post(`${this.urlbase}/api/ComposantUI/Colonnes/${this.formulaireId}/Identifiant/${this.identifiant}`,
436
+ { valeur: JSON.stringify(this.choix) })
437
+ .then(({ data }) => {
438
+ this.choix = JSON.parse(data.resultat);
439
+ this.$emit('sauvegarde', this.choix);
440
+ if (this.choixEnCours.length > 0) this.$emit('selection', this.choixEnCours[0]);
441
+ this.fermer();
442
+ })
443
+ .catch((e) => {
444
+ this.erreur = e;
445
+ });
446
+ },
447
+
448
+ retourEnHaut(cible) {
449
+ this.$vuetify.goTo(0, { container: cible });
450
+ },
451
+ defilerChoix(e) {
452
+ this.choixRetourEnHaut = e.target.scrollTop >= 200;
453
+ },
454
+ ecouteDefilerChoix() {
455
+ const vdtwChoix = document.querySelector('#choixColonnes-choix > .v-data-table__wrapper');
456
+ if (vdtwChoix == null) {
457
+ setTimeout(this.ecouteDefilerChoix.bind(this), 100);
458
+ return;
459
+ }
460
+ vdtwChoix.addEventListener('scroll', this.defilerChoix.bind(this));
461
+ },
462
+ defilerColonnes(e) {
463
+ this.colonnesRetourEnHaut = e.target.scrollTop >= 200;
464
+ },
465
+ ecouteDefilerColonnes() {
466
+ const vdtwCols = document.querySelector('#choixColonnes-vue > .v-data-table__wrapper');
467
+ if (vdtwCols == null) {
468
+ setTimeout(this.ecouteDefilerColonnes.bind(this), 100);
469
+ return;
470
+ }
471
+ vdtwCols.addEventListener('scroll', this.defilerColonnes.bind(this));
472
+ },
473
+ },
474
+
475
+ computed:
476
+ {
477
+ colonnesCliquees() {
478
+ if (this.choixEnCours.length <= 0) return [];
479
+
480
+ const retour = this.colonnesEnCours
481
+ .filter((c) => this.choixEnCours[0].colonnes.some((x) => x === c.value))
482
+ .map((c) => c.value);
483
+ return retour;
484
+ },
485
+ colonnesChoixColonne() {
486
+ const cols = [
487
+ {
488
+ text: this.$tc('csqc-table.choixColonnes.ordre'),
489
+ align: 'start',
490
+ sortable: false,
491
+ value: 'ordre',
492
+ width: '5%',
493
+ },
494
+ {
495
+ text: this.$tc('csqc-table.choixColonnes.nomColonne', this.colonnesEnCours.length),
496
+ align: 'start',
497
+ sortable: false,
498
+ value: 'text',
499
+ width: '85%',
500
+ },
501
+ {
502
+ value: 'action',
503
+ sortable: false,
504
+ width: '10%',
505
+ align: 'right',
506
+ },
507
+ ];
508
+ return cols;
509
+ },
510
+ colonnesChoix() {
511
+ return [
512
+ {
513
+ text: this.$tc('csqc-table.choixColonnes.vues', this.choix.length),
514
+ value: 'nomVue',
515
+ width: '70%',
516
+ align: 'start',
517
+ },
518
+ {
519
+ value: 'action',
520
+ width: '30%',
521
+ align: 'right',
522
+ sortable: false,
523
+ }];
524
+ },
525
+ formValide() {
526
+ return !this.choix.some((vue) => vue.nomVue === '' || vue.colonnes.length <= 0);
527
+ },
528
+ },
529
+
530
+ watch: {
531
+ erreur() {
532
+ this.afficherErreur = this.erreur !== '';
533
+ },
534
+ afficherErreur() {
535
+ if (this.afficherErreur === false) { this.erreur = ''; }
536
+ },
537
+ },
538
+ };
539
+ </script>
540
+ <style scoped>
541
+ .relative {
542
+ position: relative;
543
+ }
544
+ .retourHautChoix {
545
+ bottom: 4px !important;
546
+ right: 4px;
547
+ }
548
+ .retourHautChoix.colonnes {
549
+ bottom: 8px !important;
550
+ right: 48px;
551
+ }
552
+ </style>
553
+ <style>
554
+ .limiteHauteurChoix > .v-data-table__wrapper {
555
+ max-height: min(80vh - 200px, 900px);
556
+ overflow-y: auto;
557
+ }
558
+ #choixColonnes-choix > .v-data-table__wrapper > table > thead > tr > th {
559
+ z-index: 3;
560
+ }
561
+ .limiteHauteurChoix.colonnes > .v-data-table__wrapper {
562
+ max-height: min(80vh - 294px, 600px);
563
+ }
564
+ .v-data-table.ordonable > .v-data-table__wrapper > table > tbody > tr {
565
+ cursor: move;
566
+ }
567
+ </style>
@@ -0,0 +1,150 @@
1
+ <template>
2
+ <v-navigation-drawer
3
+ v-model="visible"
4
+ location="right"
5
+ temporary
6
+ class="pa-0 elevation-2"
7
+ :width="grosseurTiroir"
8
+ :persistent="persistant"
9
+ @keydown.esc="!persistant ? fermeture : ''"
10
+ @click:outside="!persistant ? fermeture : ''"
11
+ >
12
+ <v-card class="pa-0 ma-0 pl-8 pt-8">
13
+ <!-- Bouton en haut à droite -->
14
+ <v-btn
15
+ icon="mdi-close"
16
+ variant="text"
17
+ class="position-absolute couleurHover"
18
+ style="top: 5px; right: 5px"
19
+ @click="fermeture"
20
+ ></v-btn>
21
+
22
+ <v-card-title
23
+ class="pa-0 ma-0 pb-6 text-wrap"
24
+ style="font-size: 24px"
25
+ >
26
+ <slot name="titre"></slot>
27
+ <div class="headline">{{ titre }}</div>
28
+ </v-card-title>
29
+
30
+ <v-card-text class="pa-0 ma-0 pb-6 pr-6">
31
+ <v-container>
32
+ <slot></slot>
33
+ <slot name="content"></slot>
34
+ </v-container>
35
+ </v-card-text>
36
+ <v-card-actions class="my-2 d-flex justify-end pr-6 pb-5">
37
+ <slot name="actions"></slot>
38
+ <v-btn
39
+ v-if="btnAnnuler"
40
+ color="primary"
41
+ variant="text"
42
+ :loading="operationEnCours"
43
+ @click="fermeture"
44
+ >
45
+ {{ props.btnAnnulerTexte ? props.btnAnnulerTexte : $t('csqc-composants-ui.boutton.annuler') }}
46
+ </v-btn>
47
+
48
+ <v-btn
49
+ v-if="btnOk"
50
+ class="Gouttiere"
51
+ color="primary"
52
+ variant="flat"
53
+ :loading="operationEnCours"
54
+ :disabled="btnOkDesactiver || operationEnCours"
55
+ @click="okBouton"
56
+ outlined
57
+ >
58
+ {{ props.btnOkTexte ? props.btnOkTexte : $t('csqc-composants-ui.boutton.ok') }}
59
+ </v-btn>
60
+ </v-card-actions>
61
+ </v-card>
62
+ </v-navigation-drawer>
63
+ </template>
64
+ <script lang="ts" setup>
65
+ import { ref, computed } from 'vue'
66
+ import { useDisplay } from 'vuetify'
67
+
68
+ const visible = ref(false)
69
+ const display = useDisplay()
70
+
71
+ // Déclaration des props
72
+ const props = defineProps({
73
+ titre: {
74
+ type: String,
75
+ default: '',
76
+ required: false,
77
+ },
78
+ btnAnnuler: {
79
+ type: Boolean,
80
+ default: true,
81
+ required: false,
82
+ },
83
+ btnOk: {
84
+ type: Boolean,
85
+ default: true,
86
+ required: false,
87
+ },
88
+ btnAnnulerTexte: {
89
+ type: String,
90
+ default: '',
91
+ required: false,
92
+ },
93
+ btnOkDesactiver: {
94
+ type: Boolean,
95
+ default: false,
96
+ required: false,
97
+ },
98
+ operationEnCours: { type: Boolean, default: false },
99
+ persistant: { type: Boolean, default: true },
100
+ btnOkTexte: {
101
+ type: String,
102
+ default: '',
103
+ required: false,
104
+ },
105
+ })
106
+
107
+ // Déclaration des événements
108
+ const emit = defineEmits(['fermer', 'ok'])
109
+
110
+ // Méthodes
111
+ const ouvrir = () => {
112
+ visible.value = true
113
+ }
114
+
115
+ const fermer = () => {
116
+ visible.value = false
117
+ }
118
+
119
+ const fermeture = () => {
120
+ emit('fermer')
121
+ fermer()
122
+ }
123
+
124
+ const okBouton = () => {
125
+ emit('ok')
126
+ fermer()
127
+ }
128
+
129
+ // Calcul des tailles du tiroir en fonction du breakpoint
130
+ const grosseurTiroir = computed(() => {
131
+ switch (display.name.value) {
132
+ case 'xs':
133
+ return ''
134
+ case 'sm':
135
+ return 0.95 * display.width.value
136
+ case 'md':
137
+ return 0.8 * display.width.value
138
+ case 'lg':
139
+ return 0.7 * display.width.value
140
+ case 'xl':
141
+ return 0.6 * display.width.value
142
+ case 'xxl':
143
+ return 0.5 * display.width.value
144
+ default:
145
+ return ''
146
+ }
147
+ })
148
+
149
+ defineExpose({ ouvrir, fermer })
150
+ </script>