Compare commits

..

2 commits

Author SHA1 Message Date
isUnknown
de3bb2a274 fix: convert values when switching CSS units to preserve visual size
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 21s
Previously, changing unit (e.g. mm → px) kept the numeric value unchanged,
causing visual changes. Now values are converted through a px pivot unit
so the rendered size stays the same.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:08:30 +01:00
isUnknown
342a6eccf1 fix: update Coloris color swatches in TextSettings after loading custom styles
Dispatch input events on color inputs after syncFromStore so Coloris
updates its ::before pseudo-element swatches with loaded values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:02:33 +01:00
6 changed files with 110 additions and 38 deletions

View file

@ -19,7 +19,7 @@ Customcss:
@page { @page {
size: A4; size: A4;
margin: 50mm 15mm 26mm 15mm; margin: 50mm 15mm 26mm 15mm;
background: rgba(255, 255, 255, 1); background: rgb(227, 33, 33);
} }
body { body {
@ -35,10 +35,10 @@ p {
font-weight: 300; font-weight: 300;
font-family: Arial; font-family: Arial;
font-style: italic; font-style: italic;
padding-top: 20mm; padding-top: 0mm;
padding-right: 20mm; padding-right: 0mm;
padding-bottom: 20mm; padding-bottom: 0mm;
padding-left: 20mm; padding-left: 0mm;
} }
h1 { h1 {

View file

@ -56,7 +56,7 @@
type="button" type="button"
:class="{ active: fontSize.unit === 'px' }" :class="{ active: fontSize.unit === 'px' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="fontSize.unit = 'px'" @click="updateFontSizeUnit('px')"
> >
px px
</button> </button>
@ -64,7 +64,7 @@
type="button" type="button"
:class="{ active: fontSize.unit === 'em' }" :class="{ active: fontSize.unit === 'em' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="fontSize.unit = 'em'" @click="updateFontSizeUnit('em')"
> >
em em
</button> </button>
@ -72,7 +72,7 @@
type="button" type="button"
:class="{ active: fontSize.unit === 'rem' }" :class="{ active: fontSize.unit === 'rem' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="fontSize.unit = 'rem'" @click="updateFontSizeUnit('rem')"
> >
rem rem
</button> </button>
@ -142,7 +142,7 @@
type="button" type="button"
:class="{ active: marginOuter.unit === 'mm' }" :class="{ active: marginOuter.unit === 'mm' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="marginOuter.unit = 'mm'" @click="updateMarginOuterUnit('mm')"
> >
mm mm
</button> </button>
@ -150,7 +150,7 @@
type="button" type="button"
:class="{ active: marginOuter.unit === 'px' }" :class="{ active: marginOuter.unit === 'px' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="marginOuter.unit = 'px'" @click="updateMarginOuterUnit('px')"
> >
px px
</button> </button>
@ -175,7 +175,7 @@
type="button" type="button"
:class="{ active: paddingInner.unit === 'mm' }" :class="{ active: paddingInner.unit === 'mm' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="paddingInner.unit = 'mm'" @click="updatePaddingInnerUnit('mm')"
> >
mm mm
</button> </button>
@ -183,7 +183,7 @@
type="button" type="button"
:class="{ active: paddingInner.unit === 'px' }" :class="{ active: paddingInner.unit === 'px' }"
:disabled="inheritanceLocked" :disabled="inheritanceLocked"
@click="paddingInner.unit = 'px'" @click="updatePaddingInnerUnit('px')"
> >
px px
</button> </button>
@ -264,6 +264,7 @@ import { usePopupPosition } from '../composables/usePopupPosition';
import { useDebounce } from '../composables/useDebounce'; import { useDebounce } from '../composables/useDebounce';
import NumberInput from './ui/NumberInput.vue'; import NumberInput from './ui/NumberInput.vue';
import UnitToggle from './ui/UnitToggle.vue'; import UnitToggle from './ui/UnitToggle.vue';
import { convertUnit } from '../utils/unit-conversion';
import Coloris from '@melloware/coloris'; import Coloris from '@melloware/coloris';
import '@melloware/coloris/dist/coloris.css'; import '@melloware/coloris/dist/coloris.css';
import hljs from 'highlight.js/lib/core'; import hljs from 'highlight.js/lib/core';
@ -325,6 +326,21 @@ const immediateUpdate = (callback) => {
callback(); callback();
}; };
const updateFontSizeUnit = (newUnit) => {
fontSize.value.value = convertUnit(fontSize.value.value, fontSize.value.unit, newUnit);
fontSize.value.unit = newUnit;
};
const updateMarginOuterUnit = (newUnit) => {
marginOuter.value.value = convertUnit(marginOuter.value.value, marginOuter.value.unit, newUnit);
marginOuter.value.unit = newUnit;
};
const updatePaddingInnerUnit = (newUnit) => {
paddingInner.value.value = convertUnit(paddingInner.value.value, paddingInner.value.unit, newUnit);
paddingInner.value.unit = newUnit;
};
const getSelectorFromElement = (element) => { const getSelectorFromElement = (element) => {
// Try to build a meaningful selector // Try to build a meaningful selector
if (element.id) { if (element.id) {

View file

@ -66,21 +66,21 @@
<button <button
type="button" type="button"
:class="{ active: margins.top.unit === 'mm' }" :class="{ active: margins.top.unit === 'mm' }"
@click="margins.top.unit = 'mm'" @click="updateMarginUnit('top', 'mm')"
> >
mm mm
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.top.unit === 'px' }" :class="{ active: margins.top.unit === 'px' }"
@click="margins.top.unit = 'px'" @click="updateMarginUnit('top', 'px')"
> >
px px
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.top.unit === 'rem' }" :class="{ active: margins.top.unit === 'rem' }"
@click="margins.top.unit = 'rem'" @click="updateMarginUnit('top', 'rem')"
> >
rem rem
</button> </button>
@ -107,21 +107,21 @@
<button <button
type="button" type="button"
:class="{ active: margins.bottom.unit === 'mm' }" :class="{ active: margins.bottom.unit === 'mm' }"
@click="margins.bottom.unit = 'mm'" @click="updateMarginUnit('bottom', 'mm')"
> >
mm mm
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.bottom.unit === 'px' }" :class="{ active: margins.bottom.unit === 'px' }"
@click="margins.bottom.unit = 'px'" @click="updateMarginUnit('bottom', 'px')"
> >
px px
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.bottom.unit === 'rem' }" :class="{ active: margins.bottom.unit === 'rem' }"
@click="margins.bottom.unit = 'rem'" @click="updateMarginUnit('bottom', 'rem')"
> >
rem rem
</button> </button>
@ -148,21 +148,21 @@
<button <button
type="button" type="button"
:class="{ active: margins.left.unit === 'mm' }" :class="{ active: margins.left.unit === 'mm' }"
@click="margins.left.unit = 'mm'" @click="updateMarginUnit('left', 'mm')"
> >
mm mm
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.left.unit === 'px' }" :class="{ active: margins.left.unit === 'px' }"
@click="margins.left.unit = 'px'" @click="updateMarginUnit('left', 'px')"
> >
px px
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.left.unit === 'rem' }" :class="{ active: margins.left.unit === 'rem' }"
@click="margins.left.unit = 'rem'" @click="updateMarginUnit('left', 'rem')"
> >
rem rem
</button> </button>
@ -189,21 +189,21 @@
<button <button
type="button" type="button"
:class="{ active: margins.right.unit === 'mm' }" :class="{ active: margins.right.unit === 'mm' }"
@click="margins.right.unit = 'mm'" @click="updateMarginUnit('right', 'mm')"
> >
mm mm
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.right.unit === 'px' }" :class="{ active: margins.right.unit === 'px' }"
@click="margins.right.unit = 'px'" @click="updateMarginUnit('right', 'px')"
> >
px px
</button> </button>
<button <button
type="button" type="button"
:class="{ active: margins.right.unit === 'rem' }" :class="{ active: margins.right.unit === 'rem' }"
@click="margins.right.unit = 'rem'" @click="updateMarginUnit('right', 'rem')"
> >
rem rem
</button> </button>
@ -295,6 +295,7 @@ import { useStylesheetStore } from '../../stores/stylesheet';
import { useDebounce } from '../../composables/useDebounce'; import { useDebounce } from '../../composables/useDebounce';
import Coloris from '@melloware/coloris'; import Coloris from '@melloware/coloris';
import NumberInput from '../ui/NumberInput.vue'; import NumberInput from '../ui/NumberInput.vue';
import { convertUnit } from '../../utils/unit-conversion';
import '@melloware/coloris/dist/coloris.css'; import '@melloware/coloris/dist/coloris.css';
const stylesheetStore = useStylesheetStore(); const stylesheetStore = useStylesheetStore();
@ -324,6 +325,12 @@ const margins = ref({
right: { value: 20, unit: 'mm' }, right: { value: 20, unit: 'mm' },
}); });
const updateMarginUnit = (side, newUnit) => {
const m = margins.value[side];
m.value = convertUnit(m.value, m.unit, newUnit);
m.unit = newUnit;
};
const background = ref({ const background = ref({
value: '', value: '',
format: 'hex', format: 'hex',

View file

@ -64,6 +64,7 @@
<label for="text-color" class="label-with-tooltip" data-css="color">Couleur</label> <label for="text-color" class="label-with-tooltip" data-css="color">Couleur</label>
<div class="input-with-color"> <div class="input-with-color">
<input <input
ref="colorInput"
id="text-color" id="text-color"
type="text" type="text"
v-model="color" v-model="color"
@ -80,6 +81,7 @@
<label for="text-background" class="label-with-tooltip" data-css="background">Arrière-plan</label> <label for="text-background" class="label-with-tooltip" data-css="background">Arrière-plan</label>
<div class="input-with-color"> <div class="input-with-color">
<input <input
ref="backgroundInput"
id="text-background" id="text-background"
type="text" type="text"
v-model="background" v-model="background"
@ -377,6 +379,7 @@ import NumberInput from '../ui/NumberInput.vue';
import { useCssUpdater } from '../../composables/useCssUpdater'; import { useCssUpdater } from '../../composables/useCssUpdater';
import { useCssSync } from '../../composables/useCssSync'; import { useCssSync } from '../../composables/useCssSync';
import { useDebounce } from '../../composables/useDebounce'; import { useDebounce } from '../../composables/useDebounce';
import { convertUnit } from '../../utils/unit-conversion';
const { updateStyle, setMargin, setDetailedMargins, setPadding, setDetailedPadding } = useCssUpdater(); const { updateStyle, setMargin, setDetailedMargins, setPadding, setDetailedPadding } = useCssUpdater();
const { extractValue, extractNumericValue, extractSpacing } = useCssSync(); const { extractValue, extractNumericValue, extractSpacing } = useCssSync();
@ -400,6 +403,8 @@ const fontSize = ref({ value: 16, unit: 'px' });
const alignment = ref('left'); const alignment = ref('left');
const color = ref('rgb(0, 0, 0)'); const color = ref('rgb(0, 0, 0)');
const background = ref('transparent'); const background = ref('transparent');
const colorInput = ref(null);
const backgroundInput = ref(null);
const marginOuterDetailed = ref({ const marginOuterDetailed = ref({
top: { value: 0, unit: 'mm' }, top: { value: 0, unit: 'mm' },
@ -435,20 +440,24 @@ const prevMarginInner = ref({
let isUpdatingFromStore = false; let isUpdatingFromStore = false;
// Update margin outer unit for all sides // Update margin outer unit for all sides with conversion
const updateMarginOuterUnit = (unit) => { const updateMarginOuterUnit = (newUnit) => {
marginOuterDetailed.value.top.unit = unit; const sides = ['top', 'right', 'bottom', 'left'];
marginOuterDetailed.value.right.unit = unit; sides.forEach((side) => {
marginOuterDetailed.value.bottom.unit = unit; const s = marginOuterDetailed.value[side];
marginOuterDetailed.value.left.unit = unit; s.value = convertUnit(s.value, s.unit, newUnit);
s.unit = newUnit;
});
}; };
// Update margin inner unit for all sides // Update margin inner unit for all sides with conversion
const updateMarginInnerUnit = (unit) => { const updateMarginInnerUnit = (newUnit) => {
marginInnerDetailed.value.top.unit = unit; const sides = ['top', 'right', 'bottom', 'left'];
marginInnerDetailed.value.right.unit = unit; sides.forEach((side) => {
marginInnerDetailed.value.bottom.unit = unit; const s = marginInnerDetailed.value[side];
marginInnerDetailed.value.left.unit = unit; s.value = convertUnit(s.value, s.unit, newUnit);
s.unit = newUnit;
});
}; };
// Watchers for body styles // Watchers for body styles
@ -739,6 +748,14 @@ const syncFromStore = () => {
isUpdatingFromStore = false; isUpdatingFromStore = false;
}; };
const updateColorisButtons = () => {
[colorInput.value, backgroundInput.value].forEach((input) => {
if (input) {
input.dispatchEvent(new Event('input', { bubbles: true }));
}
});
};
onMounted(() => { onMounted(() => {
Coloris.init(); Coloris.init();
Coloris({ Coloris({
@ -749,6 +766,7 @@ onMounted(() => {
swatches: ['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', 'transparent'] swatches: ['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', 'transparent']
}); });
syncFromStore(); syncFromStore();
setTimeout(updateColorisButtons, 100);
}); });
</script> </script>

View file

@ -29,6 +29,7 @@
<script setup> <script setup>
import NumberInput from './NumberInput.vue'; import NumberInput from './NumberInput.vue';
import UnitToggle from './UnitToggle.vue'; import UnitToggle from './UnitToggle.vue';
import { convertUnit } from '../../utils/unit-conversion';
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -64,7 +65,8 @@ const updateValue = (value) => {
emit('update:modelValue', { ...props.modelValue, value }); emit('update:modelValue', { ...props.modelValue, value });
}; };
const updateUnit = (unit) => { const updateUnit = (newUnit) => {
emit('update:modelValue', { ...props.modelValue, unit }); const converted = convertUnit(props.modelValue.value, props.modelValue.unit, newUnit);
emit('update:modelValue', { value: converted, unit: newUnit });
}; };
</script> </script>

View file

@ -0,0 +1,29 @@
const PX_PER_MM = 3.7795275591;
const PX_PER_REM = 16;
const PX_PER_EM = 16;
const toPx = {
px: (v) => v,
mm: (v) => v * PX_PER_MM,
rem: (v) => v * PX_PER_REM,
em: (v) => v * PX_PER_EM,
};
const fromPx = {
px: (v) => v,
mm: (v) => v / PX_PER_MM,
rem: (v) => v / PX_PER_REM,
em: (v) => v / PX_PER_EM,
};
export function convertUnit(value, fromUnit, toUnit) {
if (fromUnit === toUnit) return value;
const converterTo = toPx[fromUnit];
const converterFrom = fromPx[toUnit];
if (!converterTo || !converterFrom) return value;
const px = converterTo(value);
return Math.round(converterFrom(px) * 100) / 100;
}