codevdesign 1.0.47 → 1.0.49
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/composants/csqcAide.vue +55 -55
- package/composants/csqcAlerteErreur.vue +87 -87
- package/composants/csqcChaise/chaiseItem.vue +54 -54
- package/composants/csqcConfirmation.vue +75 -75
- package/composants/csqcDate.vue +57 -57
- package/composants/csqcEntete.vue +79 -55
- package/composants/csqcImportCSV.vue +125 -125
- package/composants/csqcOptionSwitch.vue +193 -102
- package/composants/csqcSnackbar.vue +207 -207
- package/composants/csqcTexteBilingue.vue +175 -175
- package/composants/gabarit/csqcMenu.vue +281 -281
- package/locales/fr.json +3 -0
- package/modeles/composants/csqcMenuModele.ts +18 -18
- package/modeles/composants/datatableColonne.ts +31 -31
- package/outils/appAxios.ts +116 -116
- package/package.json +1 -1
|
@@ -1,102 +1,193 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<v-row
|
|
3
|
-
dense
|
|
4
|
-
class="align-center"
|
|
5
|
-
>
|
|
6
|
-
<!-- Texte + détails -->
|
|
7
|
-
<v-col
|
|
8
|
-
cols="10"
|
|
9
|
-
xl="11"
|
|
10
|
-
class="py-0"
|
|
11
|
-
>
|
|
12
|
-
<component
|
|
13
|
-
:is="labelCliquable ? 'label' : 'div'"
|
|
14
|
-
:for="labelCliquable ? switchId : undefined"
|
|
15
|
-
class="labelSwitchSiSwitchApres"
|
|
16
|
-
:class="{ 'label-cliquable': labelCliquable && !desactiver }"
|
|
17
|
-
>
|
|
18
|
-
<slot name="label">
|
|
19
|
-
{{ texte }}
|
|
20
|
-
</slot>
|
|
21
|
-
</component>
|
|
22
|
-
|
|
23
|
-
<div
|
|
24
|
-
v-if="afficherDetails"
|
|
25
|
-
class="details"
|
|
26
|
-
>
|
|
27
|
-
<slot name="details">
|
|
28
|
-
<span v-html="texteDetaille"></span>
|
|
29
|
-
</slot>
|
|
30
|
-
</div>
|
|
31
|
-
</v-col>
|
|
32
|
-
|
|
33
|
-
<!-- Switch -->
|
|
34
|
-
<v-col
|
|
35
|
-
cols="2"
|
|
36
|
-
xl="1"
|
|
37
|
-
class="d-flex align-center justify-end py-0"
|
|
38
|
-
>
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<v-row
|
|
3
|
+
dense
|
|
4
|
+
class="align-center"
|
|
5
|
+
>
|
|
6
|
+
<!-- Texte + détails -->
|
|
7
|
+
<v-col
|
|
8
|
+
cols="10"
|
|
9
|
+
xl="11"
|
|
10
|
+
class="py-0"
|
|
11
|
+
>
|
|
12
|
+
<component
|
|
13
|
+
:is="labelCliquable ? 'label' : 'div'"
|
|
14
|
+
:for="labelCliquable ? switchId : undefined"
|
|
15
|
+
class="labelSwitchSiSwitchApres"
|
|
16
|
+
:class="{ 'label-cliquable': labelCliquable && !desactiver }"
|
|
17
|
+
>
|
|
18
|
+
<slot name="label">
|
|
19
|
+
{{ texte }}
|
|
20
|
+
</slot>
|
|
21
|
+
</component>
|
|
22
|
+
|
|
23
|
+
<div
|
|
24
|
+
v-if="afficherDetails"
|
|
25
|
+
class="details"
|
|
26
|
+
>
|
|
27
|
+
<slot name="details">
|
|
28
|
+
<span v-html="texteDetaille"></span>
|
|
29
|
+
</slot>
|
|
30
|
+
</div>
|
|
31
|
+
</v-col>
|
|
32
|
+
|
|
33
|
+
<!-- Switch -->
|
|
34
|
+
<v-col
|
|
35
|
+
cols="2"
|
|
36
|
+
xl="1"
|
|
37
|
+
class="d-flex align-center justify-end py-0"
|
|
38
|
+
>
|
|
39
|
+
<span class="d-inline-flex">
|
|
40
|
+
<v-switch
|
|
41
|
+
:id="switchId"
|
|
42
|
+
class="switch-compact switch-tristate"
|
|
43
|
+
:class="{
|
|
44
|
+
'is-null': maValeur === null,
|
|
45
|
+
'is-true': maValeur === true,
|
|
46
|
+
'is-false': maValeur === false,
|
|
47
|
+
}"
|
|
48
|
+
:disabled="desactiver"
|
|
49
|
+
hide-details
|
|
50
|
+
v-bind="$attrs"
|
|
51
|
+
:model-value="switchChecked"
|
|
52
|
+
:indeterminate="isIndeterminate"
|
|
53
|
+
indeterminate-icon="mdi-minus"
|
|
54
|
+
@click.prevent="onToggle"
|
|
55
|
+
@keydown.enter.prevent="onToggle"
|
|
56
|
+
@keydown.space.prevent="onToggle"
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<v-tooltip
|
|
60
|
+
v-if="maValeur === null"
|
|
61
|
+
activator="parent"
|
|
62
|
+
>
|
|
63
|
+
{{ $t("csqc.csqcOptionSwitch.indeterminee") }}
|
|
64
|
+
</v-tooltip>
|
|
65
|
+
</span>
|
|
66
|
+
</v-col>
|
|
67
|
+
</v-row>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<script setup lang="ts">
|
|
71
|
+
import { computed, useSlots } from 'vue'
|
|
72
|
+
|
|
73
|
+
type TriBool = boolean | null
|
|
74
|
+
|
|
75
|
+
const props = defineProps({
|
|
76
|
+
valeurInverse: { type: Boolean, default: false },
|
|
77
|
+
desactiver: { type: Boolean, default: false },
|
|
78
|
+
modelValue: { type: [Boolean, null] as unknown as () => TriBool, default: false },
|
|
79
|
+
autoriserNull: { type: Boolean, default: false },
|
|
80
|
+
texte: { type: String, required: true },
|
|
81
|
+
texteDetaille: { type: String, default: '' },
|
|
82
|
+
labelCliquable: { type: Boolean, default: true },
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const emit = defineEmits<{
|
|
86
|
+
(e: 'update:modelValue', v: TriBool): void
|
|
87
|
+
}>()
|
|
88
|
+
const isIndeterminate = computed(() => maValeur.value === null)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
const slots = useSlots()
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Valeur "logique" du composant (après inversion).
|
|
95
|
+
* Peut être true/false/null si allowNull=true.
|
|
96
|
+
*/
|
|
97
|
+
const maValeur = computed<TriBool>({
|
|
98
|
+
get: () => (props.valeurInverse ? inverseTri(props.modelValue) : props.modelValue),
|
|
99
|
+
set: v => emit('update:modelValue', props.valeurInverse ? inverseTri(v) : v),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
function inverseTri(v: TriBool): TriBool {
|
|
103
|
+
if (v === null) return null
|
|
104
|
+
return !v
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* v-switch attend un bool pour afficher ON/OFF.
|
|
109
|
+
* - null => on affiche OFF (false) visuellement
|
|
110
|
+
*/
|
|
111
|
+
const switchChecked = computed(() => maValeur.value === true)
|
|
112
|
+
|
|
113
|
+
function onToggle() {
|
|
114
|
+
if (props.desactiver) return
|
|
115
|
+
|
|
116
|
+
// Mode tri-state
|
|
117
|
+
if (props.autoriserNull) {
|
|
118
|
+
// cycle: null -> true -> false -> null
|
|
119
|
+
const cur = maValeur.value
|
|
120
|
+
const next: TriBool = cur === null ? true : cur === true ? false : null
|
|
121
|
+
maValeur.value = next
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Mode classique (ne change rien vs avant)
|
|
126
|
+
maValeur.value = !switchChecked.value
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const afficherDetails = computed(() => {
|
|
130
|
+
const slotExiste = !!slots.details?.().length
|
|
131
|
+
return slotExiste || props.texteDetaille.trim().length > 0
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
const switchId = `sw_${Math.random().toString(36).slice(2)}`
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<style scoped>
|
|
138
|
+
/* OFF (false) */
|
|
139
|
+
:deep(.switch-tristate.is-false .v-switch__track) {
|
|
140
|
+
opacity: 0.22 !important;
|
|
141
|
+
}
|
|
142
|
+
:deep(.switch-tristate.is-false .v-switch__thumb) {
|
|
143
|
+
opacity: 0.65 !important;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* NULL (centre + très distinct) */
|
|
147
|
+
:deep(.switch-tristate.is-null .v-switch__track) {
|
|
148
|
+
opacity: 1 !important;
|
|
149
|
+
background:
|
|
150
|
+
repeating-linear-gradient(
|
|
151
|
+
45deg,
|
|
152
|
+
rgba(255, 255, 255, 0.22),
|
|
153
|
+
rgba(255, 255, 255, 0.22) 6px,
|
|
154
|
+
rgba(255, 255, 255, 0.05) 6px,
|
|
155
|
+
rgba(255, 255, 255, 0.05) 12px
|
|
156
|
+
),
|
|
157
|
+
rgb(var(--v-theme-warning)) !important;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
:deep(.switch-tristate.is-null .v-switch__thumb) {
|
|
161
|
+
transform: translateX(calc((100% - 20px) / 2)) !important;
|
|
162
|
+
background: white !important;
|
|
163
|
+
opacity: 1 !important;
|
|
164
|
+
box-shadow:
|
|
165
|
+
0 0 0 2px rgba(var(--v-theme-warning), 0.55),
|
|
166
|
+
0 2px 6px rgba(0, 0, 0, 0.18) !important;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Icône minus visible sur fond blanc */
|
|
170
|
+
:deep(.switch-tristate.is-null .v-selection-control__input-icon) {
|
|
171
|
+
color: rgb(var(--v-theme-warning)) !important;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Transition */
|
|
175
|
+
:deep(.switch-tristate .v-switch__thumb) {
|
|
176
|
+
transition:
|
|
177
|
+
transform 0.18s ease,
|
|
178
|
+
background 0.18s ease,
|
|
179
|
+
box-shadow 0.18s ease;
|
|
180
|
+
}
|
|
181
|
+
.labelSwitchSiSwitchApres {
|
|
182
|
+
font-weight: bold;
|
|
183
|
+
line-height: 1.2;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.label-cliquable {
|
|
187
|
+
cursor: pointer;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.details {
|
|
191
|
+
margin-top: 4px;
|
|
192
|
+
}
|
|
193
|
+
</style>
|