codevdesign 2.0.5 → 2.0.6

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.
@@ -1,345 +1,345 @@
1
- <template>
2
- <v-menu
3
- v-if="!isXs"
4
- ref="menuRef"
5
- v-model="ouvert"
6
- :open-on-hover="hover"
7
- :location="positionEffective"
8
- :close-on-content-click="false"
9
- :offset="10"
10
- >
11
- <template #activator="{ props: activatorProps }">
12
- <slot name="icone">
13
- <v-btn
14
- v-bind="activatorProps"
15
- :style="styleCss"
16
- :size="grosseurEffective"
17
- color="primary"
18
- icon
19
- variant="text"
20
- @click.stop
21
- >
22
- <span
23
- class="csqc-aide__pastille"
24
- :style="stylePastille"
25
- >{{ caractereIcone }}</span
26
- >
27
- </v-btn>
28
- </slot>
29
- </template>
30
-
31
- <slot name="carte">
32
- <div :class="['csqc-infobulle', classFleche]">
33
- <v-btn
34
- class="csqc-infobulle__fermer"
35
- color="primary"
36
- icon
37
- size="small"
38
- variant="text"
39
- @click="ouvert = false"
40
- >
41
- <v-icon
42
- variant="text"
43
- size="24"
44
- >mdi-close</v-icon
45
- >
46
- </v-btn>
47
- <div class="csqc-infobulle__corps">
48
- <div
49
- v-if="titre"
50
- class="csqc-infobulle__titre"
51
- >
52
- {{ titre }}
53
- </div>
54
- <span v-html="aide"></span>
55
- </div>
56
- </div>
57
- </slot>
58
- </v-menu>
59
- </template>
60
-
61
- <script setup lang="ts">
62
- import { ref, computed, watch } from 'vue'
63
- import { useDisplay } from 'vuetify'
64
-
65
- const props = withDefaults(
66
- defineProps<{
67
- aide: string
68
- grosseur?: 'default' | 'small' | 'large' | 'x-large' | 'x-small'
69
- hover?: boolean
70
- styleCss?: string
71
- titre?: string
72
- position?: 'top' | 'top-debut' | 'top-fin' | 'bottom' | 'start' | 'end'
73
- typeIcone?: 'information' | 'aide'
74
- }>(),
75
- {
76
- grosseur: 'small',
77
- hover: false,
78
- styleCss: '',
79
- position: 'top',
80
- typeIcone: 'aide',
81
- },
82
- )
83
-
84
- const ouvert = ref(false)
85
-
86
- const caractereIcone = computed(() => (props.typeIcone === 'aide' ? '?' : 'i'))
87
-
88
- const stylePastille = computed(() => {
89
- const tailles: Record<string, { cercle: number; police: number }> = {
90
- 'x-small': { cercle: 16, police: 10 },
91
- small: { cercle: 20, police: 12 },
92
- large: { cercle: 32, police: 20 },
93
- 'x-large': { cercle: 40, police: 26 },
94
- }
95
- const { cercle, police } = tailles[props.grosseur] ?? { cercle: 24, police: 15 }
96
- return {
97
- width: `${cercle}px`,
98
- height: `${cercle}px`,
99
- fontSize: `${police}px`,
100
- fontStyle: 'normal',
101
- fontFamily: props.typeIcone === 'aide' ? 'Arial, sans-serif' : "Georgia, 'Times New Roman', serif",
102
- }
103
- })
104
-
105
- const grosseurEffective = computed(() => {
106
- const val = props.grosseur
107
- return val && val.trim() !== '' ? val : 'default'
108
- })
109
-
110
- const positionEffective = computed(() => {
111
- switch (props.position) {
112
- case 'top-debut':
113
- return 'top start' as const
114
- case 'top-fin':
115
- return 'top end' as const
116
- default:
117
- return props.position as 'top' | 'bottom' | 'start' | 'end'
118
- }
119
- })
120
-
121
- const menuRef = ref()
122
- const classFleche = ref('csqc-infobulle--fleche-bas-gauche')
123
-
124
- function detecterPosition() {
125
- const activateurEl = menuRef.value?.activatorEl as HTMLElement | undefined
126
- if (!activateurEl) return
127
-
128
- const overlays = document.querySelectorAll('.v-overlay--active .v-overlay__content')
129
- if (!overlays.length) return
130
- const contentEl = overlays[overlays.length - 1] as HTMLElement
131
-
132
- const ar = activateurEl.getBoundingClientRect()
133
- const ir = contentEl.getBoundingClientRect()
134
-
135
- if (ir.width === 0 || ir.height === 0) return
136
-
137
- const centreActX = ar.left + ar.width / 2
138
- const centreActY = ar.top + ar.height / 2
139
-
140
- if (ir.bottom <= centreActY) {
141
- const ratioX = (centreActX - ir.left) / ir.width
142
- if (ratioX < 0.33) {
143
- classFleche.value = 'csqc-infobulle--fleche-bas-gauche'
144
- } else if (ratioX > 0.66) {
145
- classFleche.value = 'csqc-infobulle--fleche-bas-droite'
146
- } else {
147
- classFleche.value = 'csqc-infobulle--fleche-bas'
148
- }
149
- } else if (ir.top >= centreActY) {
150
- classFleche.value = 'csqc-infobulle--fleche-haut'
151
- } else if (ir.right <= centreActX) {
152
- classFleche.value = 'csqc-infobulle--fleche-droite'
153
- } else {
154
- classFleche.value = 'csqc-infobulle--fleche-gauche'
155
- }
156
- }
157
-
158
- watch(ouvert, val => {
159
- if (!val) return
160
- setTimeout(detecterPosition, 50)
161
- })
162
-
163
- const { name } = useDisplay()
164
- const isXs = computed(() => name.value === 'xs')
165
- </script>
166
-
167
- <style scoped>
168
- @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap');
169
- .csqc-aide__pastille {
170
- align-items: center;
171
- background-color: #095797;
172
- border-radius: 50%;
173
- color: #ffffff;
174
- display: inline-flex;
175
- font-weight: 700;
176
- justify-content: center;
177
- line-height: 1;
178
- pointer-events: none;
179
- user-select: none;
180
- }
181
-
182
- .csqc-infobulle {
183
- background-color: #ffffff;
184
- border: 1px solid #c5cad2;
185
- border-radius: 4px;
186
- box-shadow: 0 2px 8px rgba(34, 54, 84, 0.15);
187
- max-width: 320px;
188
- min-width: 216px;
189
- position: relative;
190
- }
191
-
192
- .csqc-infobulle__fermer {
193
- position: absolute !important;
194
- right: 0;
195
- top: 0;
196
- }
197
-
198
- .csqc-infobulle__titre {
199
- color: #223654;
200
- font-size: 0.875rem;
201
- font-weight: 600;
202
- line-height: 1.4;
203
- margin-bottom: 4px;
204
- }
205
-
206
- .csqc-infobulle__corps {
207
- color: #223654;
208
- font-family: 'Open Sans', sans-serif;
209
- font-size: 0.875rem;
210
- line-height: 1.4;
211
- max-height: 128px;
212
- overflow-y: auto;
213
- padding: 26px 32px 12px 12px;
214
- }
215
-
216
- /* Flèche vers le bas — tooltip au-dessus de l'activateur */
217
- .csqc-infobulle--fleche-bas::before,
218
- .csqc-infobulle--fleche-bas::after {
219
- border-left: 9px solid transparent;
220
- border-right: 9px solid transparent;
221
- bottom: -9px;
222
- content: '';
223
- left: 50%;
224
- position: absolute;
225
- transform: translateX(-50%);
226
- }
227
-
228
- .csqc-infobulle--fleche-bas::before {
229
- border-top: 9px solid #c5cad2;
230
- }
231
-
232
- .csqc-infobulle--fleche-bas::after {
233
- border-top: 8px solid #ffffff;
234
- bottom: -8px;
235
- z-index: 1;
236
- }
237
-
238
- /* Flèche vers le haut — tooltip en dessous de l'activateur */
239
- .csqc-infobulle--fleche-haut::before,
240
- .csqc-infobulle--fleche-haut::after {
241
- border-left: 9px solid transparent;
242
- border-right: 9px solid transparent;
243
- content: '';
244
- left: 50%;
245
- position: absolute;
246
- top: -9px;
247
- transform: translateX(-50%);
248
- }
249
-
250
- .csqc-infobulle--fleche-haut::before {
251
- border-bottom: 9px solid #c5cad2;
252
- }
253
-
254
- .csqc-infobulle--fleche-haut::after {
255
- border-bottom: 8px solid #ffffff;
256
- top: -8px;
257
- z-index: 1;
258
- }
259
-
260
- /* Flèche vers la droite — tooltip à gauche de l'activateur */
261
- .csqc-infobulle--fleche-droite::before,
262
- .csqc-infobulle--fleche-droite::after {
263
- border-bottom: 9px solid transparent;
264
- border-top: 9px solid transparent;
265
- content: '';
266
- position: absolute;
267
- right: -9px;
268
- top: 50%;
269
- transform: translateY(-50%);
270
- }
271
-
272
- .csqc-infobulle--fleche-droite::before {
273
- border-left: 9px solid #c5cad2;
274
- }
275
-
276
- .csqc-infobulle--fleche-droite::after {
277
- border-left: 8px solid #ffffff;
278
- right: -8px;
279
- z-index: 1;
280
- }
281
-
282
- /* Flèche bas-gauche — tooltip au-dessus, aligné à gauche de l'activateur */
283
- .csqc-infobulle--fleche-bas-gauche::before,
284
- .csqc-infobulle--fleche-bas-gauche::after {
285
- border-left: 9px solid transparent;
286
- border-right: 9px solid transparent;
287
- bottom: -9px;
288
- content: '';
289
- left: 20px;
290
- position: absolute;
291
- }
292
-
293
- .csqc-infobulle--fleche-bas-gauche::before {
294
- border-top: 9px solid #c5cad2;
295
- }
296
-
297
- .csqc-infobulle--fleche-bas-gauche::after {
298
- border-top: 8px solid #ffffff;
299
- bottom: -8px;
300
- z-index: 1;
301
- }
302
-
303
- /* Flèche bas-droite — tooltip au-dessus, aligné à droite de l'activateur */
304
- .csqc-infobulle--fleche-bas-droite::before,
305
- .csqc-infobulle--fleche-bas-droite::after {
306
- border-left: 9px solid transparent;
307
- border-right: 9px solid transparent;
308
- bottom: -9px;
309
- content: '';
310
- position: absolute;
311
- right: 20px;
312
- }
313
-
314
- .csqc-infobulle--fleche-bas-droite::before {
315
- border-top: 9px solid #c5cad2;
316
- }
317
-
318
- .csqc-infobulle--fleche-bas-droite::after {
319
- border-top: 8px solid #ffffff;
320
- bottom: -8px;
321
- z-index: 1;
322
- }
323
-
324
- /* Flèche vers la gauche — tooltip à droite de l'activateur */
325
- .csqc-infobulle--fleche-gauche::before,
326
- .csqc-infobulle--fleche-gauche::after {
327
- border-bottom: 9px solid transparent;
328
- border-top: 9px solid transparent;
329
- content: '';
330
- left: -9px;
331
- position: absolute;
332
- top: 50%;
333
- transform: translateY(-50%);
334
- }
335
-
336
- .csqc-infobulle--fleche-gauche::before {
337
- border-right: 9px solid #c5cad2;
338
- }
339
-
340
- .csqc-infobulle--fleche-gauche::after {
341
- border-right: 8px solid #ffffff;
342
- left: -8px;
343
- z-index: 1;
344
- }
345
- </style>
1
+ <template>
2
+ <v-menu
3
+ v-if="!isXs"
4
+ ref="menuRef"
5
+ v-model="ouvert"
6
+ :open-on-hover="hover"
7
+ :location="positionEffective"
8
+ :close-on-content-click="false"
9
+ :offset="10"
10
+ >
11
+ <template #activator="{ props: activatorProps }">
12
+ <slot name="icone">
13
+ <v-btn
14
+ v-bind="activatorProps"
15
+ :style="styleCss"
16
+ :size="grosseurEffective"
17
+ color="primary"
18
+ icon
19
+ variant="text"
20
+ @click.stop
21
+ >
22
+ <span
23
+ class="csqc-aide__pastille"
24
+ :style="stylePastille"
25
+ >{{ caractereIcone }}</span
26
+ >
27
+ </v-btn>
28
+ </slot>
29
+ </template>
30
+
31
+ <slot name="carte">
32
+ <div :class="['csqc-infobulle', classFleche]">
33
+ <v-btn
34
+ class="csqc-infobulle__fermer"
35
+ color="primary"
36
+ icon
37
+ size="small"
38
+ variant="text"
39
+ @click="ouvert = false"
40
+ >
41
+ <v-icon
42
+ variant="text"
43
+ size="24"
44
+ >mdi-close</v-icon
45
+ >
46
+ </v-btn>
47
+ <div class="csqc-infobulle__corps">
48
+ <div
49
+ v-if="titre"
50
+ class="csqc-infobulle__titre"
51
+ >
52
+ {{ titre }}
53
+ </div>
54
+ <span v-html="aide"></span>
55
+ </div>
56
+ </div>
57
+ </slot>
58
+ </v-menu>
59
+ </template>
60
+
61
+ <script setup lang="ts">
62
+ import { ref, computed, watch } from 'vue'
63
+ import { useDisplay } from 'vuetify'
64
+
65
+ const props = withDefaults(
66
+ defineProps<{
67
+ aide: string
68
+ grosseur?: 'default' | 'small' | 'large' | 'x-large' | 'x-small'
69
+ hover?: boolean
70
+ styleCss?: string
71
+ titre?: string
72
+ position?: 'top' | 'top-debut' | 'top-fin' | 'bottom' | 'start' | 'end'
73
+ typeIcone?: 'information' | 'aide'
74
+ }>(),
75
+ {
76
+ grosseur: 'small',
77
+ hover: false,
78
+ styleCss: '',
79
+ position: 'top',
80
+ typeIcone: 'aide',
81
+ },
82
+ )
83
+
84
+ const ouvert = ref(false)
85
+
86
+ const caractereIcone = computed(() => (props.typeIcone === 'aide' ? '?' : 'i'))
87
+
88
+ const stylePastille = computed(() => {
89
+ const tailles: Record<string, { cercle: number; police: number }> = {
90
+ 'x-small': { cercle: 16, police: 10 },
91
+ small: { cercle: 20, police: 12 },
92
+ large: { cercle: 32, police: 20 },
93
+ 'x-large': { cercle: 40, police: 26 },
94
+ }
95
+ const { cercle, police } = tailles[props.grosseur] ?? { cercle: 24, police: 15 }
96
+ return {
97
+ width: `${cercle}px`,
98
+ height: `${cercle}px`,
99
+ fontSize: `${police}px`,
100
+ fontStyle: 'normal',
101
+ fontFamily: props.typeIcone === 'aide' ? 'Arial, sans-serif' : "Georgia, 'Times New Roman', serif",
102
+ }
103
+ })
104
+
105
+ const grosseurEffective = computed(() => {
106
+ const val = props.grosseur
107
+ return val && val.trim() !== '' ? val : 'default'
108
+ })
109
+
110
+ const positionEffective = computed(() => {
111
+ switch (props.position) {
112
+ case 'top-debut':
113
+ return 'top start' as const
114
+ case 'top-fin':
115
+ return 'top end' as const
116
+ default:
117
+ return props.position as 'top' | 'bottom' | 'start' | 'end'
118
+ }
119
+ })
120
+
121
+ const menuRef = ref()
122
+ const classFleche = ref('csqc-infobulle--fleche-bas-gauche')
123
+
124
+ function detecterPosition() {
125
+ const activateurEl = menuRef.value?.activatorEl as HTMLElement | undefined
126
+ if (!activateurEl) return
127
+
128
+ const overlays = document.querySelectorAll('.v-overlay--active .v-overlay__content')
129
+ if (!overlays.length) return
130
+ const contentEl = overlays[overlays.length - 1] as HTMLElement
131
+
132
+ const ar = activateurEl.getBoundingClientRect()
133
+ const ir = contentEl.getBoundingClientRect()
134
+
135
+ if (ir.width === 0 || ir.height === 0) return
136
+
137
+ const centreActX = ar.left + ar.width / 2
138
+ const centreActY = ar.top + ar.height / 2
139
+
140
+ if (ir.bottom <= centreActY) {
141
+ const ratioX = (centreActX - ir.left) / ir.width
142
+ if (ratioX < 0.33) {
143
+ classFleche.value = 'csqc-infobulle--fleche-bas-gauche'
144
+ } else if (ratioX > 0.66) {
145
+ classFleche.value = 'csqc-infobulle--fleche-bas-droite'
146
+ } else {
147
+ classFleche.value = 'csqc-infobulle--fleche-bas'
148
+ }
149
+ } else if (ir.top >= centreActY) {
150
+ classFleche.value = 'csqc-infobulle--fleche-haut'
151
+ } else if (ir.right <= centreActX) {
152
+ classFleche.value = 'csqc-infobulle--fleche-droite'
153
+ } else {
154
+ classFleche.value = 'csqc-infobulle--fleche-gauche'
155
+ }
156
+ }
157
+
158
+ watch(ouvert, val => {
159
+ if (!val) return
160
+ setTimeout(detecterPosition, 50)
161
+ })
162
+
163
+ const { name } = useDisplay()
164
+ const isXs = computed(() => name.value === 'xs')
165
+ </script>
166
+
167
+ <style scoped>
168
+ @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap');
169
+ .csqc-aide__pastille {
170
+ align-items: center;
171
+ background-color: #095797;
172
+ border-radius: 50%;
173
+ color: #ffffff;
174
+ display: inline-flex;
175
+ font-weight: 700;
176
+ justify-content: center;
177
+ line-height: 1;
178
+ pointer-events: none;
179
+ user-select: none;
180
+ }
181
+
182
+ .csqc-infobulle {
183
+ background-color: #ffffff;
184
+ border: 1px solid #c5cad2;
185
+ border-radius: 4px;
186
+ box-shadow: 0 2px 8px rgba(34, 54, 84, 0.15);
187
+ max-width: 320px;
188
+ min-width: 216px;
189
+ position: relative;
190
+ }
191
+
192
+ .csqc-infobulle__fermer {
193
+ position: absolute !important;
194
+ right: 0;
195
+ top: 0;
196
+ }
197
+
198
+ .csqc-infobulle__titre {
199
+ color: #223654;
200
+ font-size: 0.875rem;
201
+ font-weight: 600;
202
+ line-height: 1.4;
203
+ margin-bottom: 4px;
204
+ }
205
+
206
+ .csqc-infobulle__corps {
207
+ color: #223654;
208
+ font-family: 'Open Sans', sans-serif;
209
+ font-size: 0.875rem;
210
+ line-height: 1.4;
211
+ max-height: 128px;
212
+ overflow-y: auto;
213
+ padding: 26px 32px 12px 12px;
214
+ }
215
+
216
+ /* Flèche vers le bas — tooltip au-dessus de l'activateur */
217
+ .csqc-infobulle--fleche-bas::before,
218
+ .csqc-infobulle--fleche-bas::after {
219
+ border-left: 9px solid transparent;
220
+ border-right: 9px solid transparent;
221
+ bottom: -9px;
222
+ content: '';
223
+ left: 50%;
224
+ position: absolute;
225
+ transform: translateX(-50%);
226
+ }
227
+
228
+ .csqc-infobulle--fleche-bas::before {
229
+ border-top: 9px solid #c5cad2;
230
+ }
231
+
232
+ .csqc-infobulle--fleche-bas::after {
233
+ border-top: 8px solid #ffffff;
234
+ bottom: -8px;
235
+ z-index: 1;
236
+ }
237
+
238
+ /* Flèche vers le haut — tooltip en dessous de l'activateur */
239
+ .csqc-infobulle--fleche-haut::before,
240
+ .csqc-infobulle--fleche-haut::after {
241
+ border-left: 9px solid transparent;
242
+ border-right: 9px solid transparent;
243
+ content: '';
244
+ left: 50%;
245
+ position: absolute;
246
+ top: -9px;
247
+ transform: translateX(-50%);
248
+ }
249
+
250
+ .csqc-infobulle--fleche-haut::before {
251
+ border-bottom: 9px solid #c5cad2;
252
+ }
253
+
254
+ .csqc-infobulle--fleche-haut::after {
255
+ border-bottom: 8px solid #ffffff;
256
+ top: -8px;
257
+ z-index: 1;
258
+ }
259
+
260
+ /* Flèche vers la droite — tooltip à gauche de l'activateur */
261
+ .csqc-infobulle--fleche-droite::before,
262
+ .csqc-infobulle--fleche-droite::after {
263
+ border-bottom: 9px solid transparent;
264
+ border-top: 9px solid transparent;
265
+ content: '';
266
+ position: absolute;
267
+ right: -9px;
268
+ top: 50%;
269
+ transform: translateY(-50%);
270
+ }
271
+
272
+ .csqc-infobulle--fleche-droite::before {
273
+ border-left: 9px solid #c5cad2;
274
+ }
275
+
276
+ .csqc-infobulle--fleche-droite::after {
277
+ border-left: 8px solid #ffffff;
278
+ right: -8px;
279
+ z-index: 1;
280
+ }
281
+
282
+ /* Flèche bas-gauche — tooltip au-dessus, aligné à gauche de l'activateur */
283
+ .csqc-infobulle--fleche-bas-gauche::before,
284
+ .csqc-infobulle--fleche-bas-gauche::after {
285
+ border-left: 9px solid transparent;
286
+ border-right: 9px solid transparent;
287
+ bottom: -9px;
288
+ content: '';
289
+ left: 20px;
290
+ position: absolute;
291
+ }
292
+
293
+ .csqc-infobulle--fleche-bas-gauche::before {
294
+ border-top: 9px solid #c5cad2;
295
+ }
296
+
297
+ .csqc-infobulle--fleche-bas-gauche::after {
298
+ border-top: 8px solid #ffffff;
299
+ bottom: -8px;
300
+ z-index: 1;
301
+ }
302
+
303
+ /* Flèche bas-droite — tooltip au-dessus, aligné à droite de l'activateur */
304
+ .csqc-infobulle--fleche-bas-droite::before,
305
+ .csqc-infobulle--fleche-bas-droite::after {
306
+ border-left: 9px solid transparent;
307
+ border-right: 9px solid transparent;
308
+ bottom: -9px;
309
+ content: '';
310
+ position: absolute;
311
+ right: 20px;
312
+ }
313
+
314
+ .csqc-infobulle--fleche-bas-droite::before {
315
+ border-top: 9px solid #c5cad2;
316
+ }
317
+
318
+ .csqc-infobulle--fleche-bas-droite::after {
319
+ border-top: 8px solid #ffffff;
320
+ bottom: -8px;
321
+ z-index: 1;
322
+ }
323
+
324
+ /* Flèche vers la gauche — tooltip à droite de l'activateur */
325
+ .csqc-infobulle--fleche-gauche::before,
326
+ .csqc-infobulle--fleche-gauche::after {
327
+ border-bottom: 9px solid transparent;
328
+ border-top: 9px solid transparent;
329
+ content: '';
330
+ left: -9px;
331
+ position: absolute;
332
+ top: 50%;
333
+ transform: translateY(-50%);
334
+ }
335
+
336
+ .csqc-infobulle--fleche-gauche::before {
337
+ border-right: 9px solid #c5cad2;
338
+ }
339
+
340
+ .csqc-infobulle--fleche-gauche::after {
341
+ border-right: 8px solid #ffffff;
342
+ left: -8px;
343
+ z-index: 1;
344
+ }
345
+ </style>