feat: add custom page format with editable width/height fields
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 20s
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 20s
Keep only A4/A5 + "Personnalisé" option. Width/height fields use same layout as margin fields and are editable only in custom mode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b808e22274
commit
9f62d3ae5d
1 changed files with 305 additions and 235 deletions
|
|
@ -1,9 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="settings-section" id="settings-section_page" data-color-type="page">
|
<section
|
||||||
|
class="settings-section"
|
||||||
|
id="settings-section_page"
|
||||||
|
data-color-type="page"
|
||||||
|
>
|
||||||
<h2>Réglage des pages</h2>
|
<h2>Réglage des pages</h2>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="settings-subsection">
|
||||||
<div class="field field-simple">
|
<div class="field field-simple">
|
||||||
<label for="page-format" class="label-with-tooltip" data-css="size"
|
<label for="page-format" class="label-with-tooltip" data-css="size"
|
||||||
|
|
@ -12,38 +14,57 @@
|
||||||
<select id="page-format" v-model="pageFormat">
|
<select id="page-format" v-model="pageFormat">
|
||||||
<option value="A4">A4</option>
|
<option value="A4">A4</option>
|
||||||
<option value="A5">A5</option>
|
<option value="A5">A5</option>
|
||||||
<option value="A3">A3</option>
|
<!-- <option value="A3">A3</option>
|
||||||
<option value="letter">Letter</option>
|
<option value="letter">Letter</option>
|
||||||
<option value="legal">Legal</option>
|
<option value="legal">Legal</option> -->
|
||||||
|
<option value="custom">Personnalisé</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="settings-subsection">
|
||||||
<div class="field field-size field--view-only">
|
<div
|
||||||
|
class="field field-margin"
|
||||||
|
:class="{ 'field--view-only': !isCustomFormat }"
|
||||||
|
>
|
||||||
<label for="page-width" class="label-with-tooltip" data-css="width"
|
<label for="page-width" class="label-with-tooltip" data-css="width"
|
||||||
>Largeur</label
|
>Largeur</label
|
||||||
>
|
>
|
||||||
<input
|
<div class="input-with-unit">
|
||||||
|
<NumberInput
|
||||||
id="page-width"
|
id="page-width"
|
||||||
type="number"
|
:modelValue="customWidth"
|
||||||
:value="parseInt(pageWidth)"
|
@update:modelValue="(v) => (customWidth = v)"
|
||||||
disabled
|
:min="50"
|
||||||
|
:step="1"
|
||||||
|
:disabled="!isCustomFormat"
|
||||||
/>
|
/>
|
||||||
<button type="button" disabled>mm</button>
|
<div class="unit-toggle">
|
||||||
|
<button type="button" class="active">mm</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field field-size field--view-only">
|
<div
|
||||||
|
class="field field-margin"
|
||||||
|
:class="{ 'field--view-only': !isCustomFormat }"
|
||||||
|
>
|
||||||
<label for="page-height" class="label-with-tooltip" data-css="height"
|
<label for="page-height" class="label-with-tooltip" data-css="height"
|
||||||
>Hauteur</label
|
>Hauteur</label
|
||||||
>
|
>
|
||||||
<input
|
<div class="input-with-unit">
|
||||||
|
<NumberInput
|
||||||
id="page-height"
|
id="page-height"
|
||||||
type="number"
|
:modelValue="customHeight"
|
||||||
:value="parseInt(pageHeight)"
|
@update:modelValue="(v) => (customHeight = v)"
|
||||||
disabled
|
:min="50"
|
||||||
|
:step="1"
|
||||||
|
:disabled="!isCustomFormat"
|
||||||
/>
|
/>
|
||||||
<button type="button" disabled>mm</button>
|
<div class="unit-toggle">
|
||||||
|
<button type="button" class="active">mm</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -51,7 +72,10 @@
|
||||||
<h3>Marges</h3>
|
<h3>Marges</h3>
|
||||||
|
|
||||||
<div class="field field-margin">
|
<div class="field field-margin">
|
||||||
<label for="margin-top" class="label-with-tooltip" data-css="margin-top"
|
<label
|
||||||
|
for="margin-top"
|
||||||
|
class="label-with-tooltip"
|
||||||
|
data-css="margin-top"
|
||||||
>Haut</label
|
>Haut</label
|
||||||
>
|
>
|
||||||
<div class="input-with-unit">
|
<div class="input-with-unit">
|
||||||
|
|
@ -60,7 +84,7 @@
|
||||||
:modelValue="margins.top.value"
|
:modelValue="margins.top.value"
|
||||||
:min="0"
|
:min="0"
|
||||||
:step="1"
|
:step="1"
|
||||||
@update:modelValue="(value) => margins.top.value = value"
|
@update:modelValue="(value) => (margins.top.value = value)"
|
||||||
/>
|
/>
|
||||||
<div class="unit-toggle">
|
<div class="unit-toggle">
|
||||||
<button
|
<button
|
||||||
|
|
@ -101,7 +125,7 @@
|
||||||
:modelValue="margins.bottom.value"
|
:modelValue="margins.bottom.value"
|
||||||
:min="0"
|
:min="0"
|
||||||
:step="1"
|
:step="1"
|
||||||
@update:modelValue="(value) => margins.bottom.value = value"
|
@update:modelValue="(value) => (margins.bottom.value = value)"
|
||||||
/>
|
/>
|
||||||
<div class="unit-toggle">
|
<div class="unit-toggle">
|
||||||
<button
|
<button
|
||||||
|
|
@ -142,7 +166,7 @@
|
||||||
:modelValue="margins.left.value"
|
:modelValue="margins.left.value"
|
||||||
:min="0"
|
:min="0"
|
||||||
:step="1"
|
:step="1"
|
||||||
@update:modelValue="(value) => margins.left.value = value"
|
@update:modelValue="(value) => (margins.left.value = value)"
|
||||||
/>
|
/>
|
||||||
<div class="unit-toggle">
|
<div class="unit-toggle">
|
||||||
<button
|
<button
|
||||||
|
|
@ -183,7 +207,7 @@
|
||||||
:modelValue="margins.right.value"
|
:modelValue="margins.right.value"
|
||||||
:min="0"
|
:min="0"
|
||||||
:step="1"
|
:step="1"
|
||||||
@update:modelValue="(value) => margins.right.value = value"
|
@update:modelValue="(value) => (margins.right.value = value)"
|
||||||
/>
|
/>
|
||||||
<div class="unit-toggle">
|
<div class="unit-toggle">
|
||||||
<button
|
<button
|
||||||
|
|
@ -214,7 +238,10 @@
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="settings-subsection">
|
||||||
<div class="field field-simple">
|
<div class="field field-simple">
|
||||||
<label for="background" class="label-with-tooltip" data-css="background"
|
<label
|
||||||
|
for="background"
|
||||||
|
class="label-with-tooltip"
|
||||||
|
data-css="background"
|
||||||
>Arrière-plan</label
|
>Arrière-plan</label
|
||||||
>
|
>
|
||||||
<div class="input-with-color">
|
<div class="input-with-color">
|
||||||
|
|
@ -242,8 +269,7 @@
|
||||||
hex
|
hex
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
-->
|
--></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -308,15 +334,16 @@ let isUpdatingFromStore = false;
|
||||||
const pageFormat = ref('A4');
|
const pageFormat = ref('A4');
|
||||||
|
|
||||||
const pageFormats = {
|
const pageFormats = {
|
||||||
A4: { width: '210mm', height: '297mm' },
|
A4: { width: 210, height: 297 },
|
||||||
A5: { width: '148mm', height: '210mm' },
|
A5: { width: 148, height: 210 },
|
||||||
A3: { width: '297mm', height: '420mm' },
|
// A3: { width: 297, height: 420 },
|
||||||
letter: { width: '8.5in', height: '11in' },
|
// letter: { width: 216, height: 279 },
|
||||||
legal: { width: '8.5in', height: '14in' },
|
// legal: { width: 216, height: 356 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const pageWidth = computed(() => pageFormats[pageFormat.value].width);
|
const customWidth = ref(210);
|
||||||
const pageHeight = computed(() => pageFormats[pageFormat.value].height);
|
const customHeight = ref(297);
|
||||||
|
const isCustomFormat = computed(() => pageFormat.value === 'custom');
|
||||||
|
|
||||||
const margins = ref({
|
const margins = ref({
|
||||||
top: { value: 20, unit: 'mm' },
|
top: { value: 20, unit: 'mm' },
|
||||||
|
|
@ -347,9 +374,37 @@ const immediateUpdate = (callback) => {
|
||||||
watch(pageFormat, (newFormat) => {
|
watch(pageFormat, (newFormat) => {
|
||||||
if (isUpdatingFromStore) return;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
|
if (newFormat === 'custom') {
|
||||||
|
immediateUpdate(() => {
|
||||||
|
stylesheetStore.updateProperty(
|
||||||
|
'@page',
|
||||||
|
'size',
|
||||||
|
`${customWidth.value}mm ${customHeight.value}mm`,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const format = pageFormats[newFormat];
|
||||||
|
if (format) {
|
||||||
|
customWidth.value = format.width;
|
||||||
|
customHeight.value = format.height;
|
||||||
|
}
|
||||||
immediateUpdate(() => {
|
immediateUpdate(() => {
|
||||||
stylesheetStore.updateProperty('@page', 'size', newFormat, '');
|
stylesheetStore.updateProperty('@page', 'size', newFormat, '');
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch([customWidth, customHeight], () => {
|
||||||
|
if (isUpdatingFromStore || !isCustomFormat.value) return;
|
||||||
|
debouncedUpdate(() => {
|
||||||
|
stylesheetStore.updateProperty(
|
||||||
|
'@page',
|
||||||
|
'size',
|
||||||
|
`${customWidth.value}mm ${customHeight.value}mm`,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateMargins = () => {
|
const updateMargins = () => {
|
||||||
|
|
@ -546,9 +601,24 @@ const syncFromStore = () => {
|
||||||
try {
|
try {
|
||||||
const pageBlock = stylesheetStore.extractBlock('@page');
|
const pageBlock = stylesheetStore.extractBlock('@page');
|
||||||
|
|
||||||
const sizeMatch = pageBlock.match(/size:\s*([A-Za-z0-9]+)/);
|
// Try named format first (A4, A5), then custom dimensions
|
||||||
if (sizeMatch) {
|
const namedSizeMatch = pageBlock.match(/size:\s*(A4|A5)\b/);
|
||||||
pageFormat.value = sizeMatch[1];
|
if (namedSizeMatch) {
|
||||||
|
pageFormat.value = namedSizeMatch[1];
|
||||||
|
const format = pageFormats[namedSizeMatch[1]];
|
||||||
|
if (format) {
|
||||||
|
customWidth.value = format.width;
|
||||||
|
customHeight.value = format.height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const customSizeMatch = pageBlock.match(
|
||||||
|
/size:\s*([0-9.]+)mm\s+([0-9.]+)mm/
|
||||||
|
);
|
||||||
|
if (customSizeMatch) {
|
||||||
|
customWidth.value = parseFloat(customSizeMatch[1]);
|
||||||
|
customHeight.value = parseFloat(customSizeMatch[2]);
|
||||||
|
pageFormat.value = 'custom';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const marginMatch = pageBlock.match(
|
const marginMatch = pageBlock.match(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue