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
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>
This commit is contained in:
parent
342a6eccf1
commit
de3bb2a274
5 changed files with 92 additions and 33 deletions
|
|
@ -56,7 +56,7 @@
|
|||
type="button"
|
||||
:class="{ active: fontSize.unit === 'px' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="fontSize.unit = 'px'"
|
||||
@click="updateFontSizeUnit('px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
type="button"
|
||||
:class="{ active: fontSize.unit === 'em' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="fontSize.unit = 'em'"
|
||||
@click="updateFontSizeUnit('em')"
|
||||
>
|
||||
em
|
||||
</button>
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
type="button"
|
||||
:class="{ active: fontSize.unit === 'rem' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="fontSize.unit = 'rem'"
|
||||
@click="updateFontSizeUnit('rem')"
|
||||
>
|
||||
rem
|
||||
</button>
|
||||
|
|
@ -142,7 +142,7 @@
|
|||
type="button"
|
||||
:class="{ active: marginOuter.unit === 'mm' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="marginOuter.unit = 'mm'"
|
||||
@click="updateMarginOuterUnit('mm')"
|
||||
>
|
||||
mm
|
||||
</button>
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
type="button"
|
||||
:class="{ active: marginOuter.unit === 'px' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="marginOuter.unit = 'px'"
|
||||
@click="updateMarginOuterUnit('px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
|
|
@ -175,7 +175,7 @@
|
|||
type="button"
|
||||
:class="{ active: paddingInner.unit === 'mm' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="paddingInner.unit = 'mm'"
|
||||
@click="updatePaddingInnerUnit('mm')"
|
||||
>
|
||||
mm
|
||||
</button>
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
type="button"
|
||||
:class="{ active: paddingInner.unit === 'px' }"
|
||||
:disabled="inheritanceLocked"
|
||||
@click="paddingInner.unit = 'px'"
|
||||
@click="updatePaddingInnerUnit('px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
|
|
@ -264,6 +264,7 @@ import { usePopupPosition } from '../composables/usePopupPosition';
|
|||
import { useDebounce } from '../composables/useDebounce';
|
||||
import NumberInput from './ui/NumberInput.vue';
|
||||
import UnitToggle from './ui/UnitToggle.vue';
|
||||
import { convertUnit } from '../utils/unit-conversion';
|
||||
import Coloris from '@melloware/coloris';
|
||||
import '@melloware/coloris/dist/coloris.css';
|
||||
import hljs from 'highlight.js/lib/core';
|
||||
|
|
@ -325,6 +326,21 @@ const immediateUpdate = (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) => {
|
||||
// Try to build a meaningful selector
|
||||
if (element.id) {
|
||||
|
|
|
|||
|
|
@ -66,21 +66,21 @@
|
|||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.top.unit === 'mm' }"
|
||||
@click="margins.top.unit = 'mm'"
|
||||
@click="updateMarginUnit('top', 'mm')"
|
||||
>
|
||||
mm
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.top.unit === 'px' }"
|
||||
@click="margins.top.unit = 'px'"
|
||||
@click="updateMarginUnit('top', 'px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.top.unit === 'rem' }"
|
||||
@click="margins.top.unit = 'rem'"
|
||||
@click="updateMarginUnit('top', 'rem')"
|
||||
>
|
||||
rem
|
||||
</button>
|
||||
|
|
@ -107,21 +107,21 @@
|
|||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.bottom.unit === 'mm' }"
|
||||
@click="margins.bottom.unit = 'mm'"
|
||||
@click="updateMarginUnit('bottom', 'mm')"
|
||||
>
|
||||
mm
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.bottom.unit === 'px' }"
|
||||
@click="margins.bottom.unit = 'px'"
|
||||
@click="updateMarginUnit('bottom', 'px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.bottom.unit === 'rem' }"
|
||||
@click="margins.bottom.unit = 'rem'"
|
||||
@click="updateMarginUnit('bottom', 'rem')"
|
||||
>
|
||||
rem
|
||||
</button>
|
||||
|
|
@ -148,21 +148,21 @@
|
|||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.left.unit === 'mm' }"
|
||||
@click="margins.left.unit = 'mm'"
|
||||
@click="updateMarginUnit('left', 'mm')"
|
||||
>
|
||||
mm
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.left.unit === 'px' }"
|
||||
@click="margins.left.unit = 'px'"
|
||||
@click="updateMarginUnit('left', 'px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.left.unit === 'rem' }"
|
||||
@click="margins.left.unit = 'rem'"
|
||||
@click="updateMarginUnit('left', 'rem')"
|
||||
>
|
||||
rem
|
||||
</button>
|
||||
|
|
@ -189,21 +189,21 @@
|
|||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.right.unit === 'mm' }"
|
||||
@click="margins.right.unit = 'mm'"
|
||||
@click="updateMarginUnit('right', 'mm')"
|
||||
>
|
||||
mm
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.right.unit === 'px' }"
|
||||
@click="margins.right.unit = 'px'"
|
||||
@click="updateMarginUnit('right', 'px')"
|
||||
>
|
||||
px
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: margins.right.unit === 'rem' }"
|
||||
@click="margins.right.unit = 'rem'"
|
||||
@click="updateMarginUnit('right', 'rem')"
|
||||
>
|
||||
rem
|
||||
</button>
|
||||
|
|
@ -295,6 +295,7 @@ import { useStylesheetStore } from '../../stores/stylesheet';
|
|||
import { useDebounce } from '../../composables/useDebounce';
|
||||
import Coloris from '@melloware/coloris';
|
||||
import NumberInput from '../ui/NumberInput.vue';
|
||||
import { convertUnit } from '../../utils/unit-conversion';
|
||||
import '@melloware/coloris/dist/coloris.css';
|
||||
|
||||
const stylesheetStore = useStylesheetStore();
|
||||
|
|
@ -324,6 +325,12 @@ const margins = ref({
|
|||
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({
|
||||
value: '',
|
||||
format: 'hex',
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ import NumberInput from '../ui/NumberInput.vue';
|
|||
import { useCssUpdater } from '../../composables/useCssUpdater';
|
||||
import { useCssSync } from '../../composables/useCssSync';
|
||||
import { useDebounce } from '../../composables/useDebounce';
|
||||
import { convertUnit } from '../../utils/unit-conversion';
|
||||
|
||||
const { updateStyle, setMargin, setDetailedMargins, setPadding, setDetailedPadding } = useCssUpdater();
|
||||
const { extractValue, extractNumericValue, extractSpacing } = useCssSync();
|
||||
|
|
@ -439,20 +440,24 @@ const prevMarginInner = ref({
|
|||
|
||||
let isUpdatingFromStore = false;
|
||||
|
||||
// Update margin outer unit for all sides
|
||||
const updateMarginOuterUnit = (unit) => {
|
||||
marginOuterDetailed.value.top.unit = unit;
|
||||
marginOuterDetailed.value.right.unit = unit;
|
||||
marginOuterDetailed.value.bottom.unit = unit;
|
||||
marginOuterDetailed.value.left.unit = unit;
|
||||
// Update margin outer unit for all sides with conversion
|
||||
const updateMarginOuterUnit = (newUnit) => {
|
||||
const sides = ['top', 'right', 'bottom', 'left'];
|
||||
sides.forEach((side) => {
|
||||
const s = marginOuterDetailed.value[side];
|
||||
s.value = convertUnit(s.value, s.unit, newUnit);
|
||||
s.unit = newUnit;
|
||||
});
|
||||
};
|
||||
|
||||
// Update margin inner unit for all sides
|
||||
const updateMarginInnerUnit = (unit) => {
|
||||
marginInnerDetailed.value.top.unit = unit;
|
||||
marginInnerDetailed.value.right.unit = unit;
|
||||
marginInnerDetailed.value.bottom.unit = unit;
|
||||
marginInnerDetailed.value.left.unit = unit;
|
||||
// Update margin inner unit for all sides with conversion
|
||||
const updateMarginInnerUnit = (newUnit) => {
|
||||
const sides = ['top', 'right', 'bottom', 'left'];
|
||||
sides.forEach((side) => {
|
||||
const s = marginInnerDetailed.value[side];
|
||||
s.value = convertUnit(s.value, s.unit, newUnit);
|
||||
s.unit = newUnit;
|
||||
});
|
||||
};
|
||||
|
||||
// Watchers for body styles
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
<script setup>
|
||||
import NumberInput from './NumberInput.vue';
|
||||
import UnitToggle from './UnitToggle.vue';
|
||||
import { convertUnit } from '../../utils/unit-conversion';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
|
@ -64,7 +65,8 @@ const updateValue = (value) => {
|
|||
emit('update:modelValue', { ...props.modelValue, value });
|
||||
};
|
||||
|
||||
const updateUnit = (unit) => {
|
||||
emit('update:modelValue', { ...props.modelValue, unit });
|
||||
const updateUnit = (newUnit) => {
|
||||
const converted = convertUnit(props.modelValue.value, props.modelValue.unit, newUnit);
|
||||
emit('update:modelValue', { value: converted, unit: newUnit });
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
29
src/utils/unit-conversion.js
Normal file
29
src/utils/unit-conversion.js
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue