Skip to content

Commit ea79b6e

Browse files
authored
Merge pull request #1139 from dnum-mi/1132-dsfrrange-la-taille-de-la-barre-ne-se-met-pas-a-jour-au-redimensionnement-de-la-fenetre
DsfrRange : mettre à jour la taille de la barre à chaque redimensionnement de la fenetre
2 parents e2907a5 + 4668fe2 commit ea79b6e

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

demo-app/views/AppForm.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ const cbOptions: DsfrCheckboxSetProps['options'] = [
131131
</template>
132132
</DsfrInput>
133133

134+
<DsfrRange
135+
label="Exemple de DsfrRange"
136+
v-model="rangeValue"
137+
:min="0"
138+
:max="100"
139+
:step="5"
140+
:small="false"
141+
/>
142+
134143
<h2>ChecboxSet :</h2>
135144
<DsfrCheckboxSet
136145
v-model="selectedCheckboxes"

src/components/DsfrRange/DsfrRange.vue

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts" setup>
22
import type { DsfrRangeProps } from './DsfrRange.types'
33
4-
import { computed, onMounted, ref, watch } from 'vue'
4+
import { computed, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue'
55
66
import { useRandomId } from '../../utils/random-utils'
77
@@ -33,9 +33,10 @@ defineSlots<{
3333
/** Pour les messages d’erreur ou de succès */
3434
messages?: (props: Record<string, never>) => any
3535
}>()
36-
const input = ref<HTMLInputElement>()
37-
const output = ref<HTMLSpanElement>()
36+
37+
const input = useTemplateRef('input')
3838
const inputWidth = ref()
39+
let resizeObserver: ResizeObserver | null = null
3940
4041
const double = computed(() => props.lowerValue !== undefined)
4142
const stepped = computed(() => props.step !== undefined)
@@ -45,8 +46,10 @@ const outputStyle = computed(() => {
4546
const translateXValue = (props.modelValue - props.min) / (props.max - props.min) * inputWidth.value
4647
return `transform: translateX(${translateXValue}px) translateX(-${translateXValue / inputWidth.value * 100}%);`
4748
}
48-
const translateXValue = (props.modelValue + props.lowerValue - props.min) / 2 / (props.max - props.min) * inputWidth.value
49-
return `transform: translateX(${translateXValue}px) translateX(-${props.lowerValue + ((props.modelValue - props.lowerValue) / 2)}%);`
49+
// Pour le mode double : calculer la position au milieu des deux valeurs
50+
const middleValue = (props.modelValue + props.lowerValue) / 2
51+
const translateXValue = (middleValue - props.min) / (props.max - props.min) * inputWidth.value
52+
return `transform: translateX(${translateXValue}px) translateX(-${translateXValue / inputWidth.value * 100}%);`
5053
})
5154
5255
const rangeStyle = computed(() => {
@@ -88,6 +91,26 @@ const outputValue = computed(() => {
8891
8992
onMounted(() => {
9093
inputWidth.value = input.value?.offsetWidth
94+
95+
// Observer le redimensionnement de l'input avec ResizeObserver natif
96+
if (input.value && 'ResizeObserver' in window) {
97+
resizeObserver = new ResizeObserver((entries) => {
98+
const { width } = entries[0]?.contentRect || {}
99+
if (width !== undefined) {
100+
inputWidth.value = width
101+
}
102+
})
103+
104+
resizeObserver.observe(input.value)
105+
}
106+
})
107+
108+
onUnmounted(() => {
109+
// Nettoyer l'observer au démontage
110+
if (resizeObserver) {
111+
resizeObserver.disconnect()
112+
resizeObserver = null
113+
}
91114
})
92115
</script>
93116

@@ -131,7 +154,6 @@ onMounted(() => {
131154
:style="rangeStyle"
132155
>
133156
<span
134-
ref="output"
135157
class="fr-range__output"
136158
data-fr-js-range-output="true"
137159
:style="outputStyle"

0 commit comments

Comments
 (0)