2025-12-03 15:20:49 +01:00
|
|
|
<template>
|
2025-12-10 11:10:14 +01:00
|
|
|
<section class="settings-section" id="settings-section_elem" data-color-type="elem">
|
2026-03-05 11:42:18 +01:00
|
|
|
<h2>Réglage du texte par défaut</h2>
|
2025-12-09 17:08:40 +01:00
|
|
|
<div class="container">
|
|
|
|
|
|
2025-12-03 15:20:49 +01:00
|
|
|
<p class="infos">
|
refactor: optimize EditorPanel updates with selective debouncing
Implement immediate vs debounced updates based on input type to improve
UX responsiveness while preventing excessive re-renders.
Update strategy:
- Immediate (0ms): select, buttons, checkboxes, color picker
- Debounced (1s): text inputs, number inputs, range sliders
Changes:
- PageSettings.vue: Split watchers for margin values/units and background
value/format. Extract update logic into reusable functions.
- TextSettings.vue: Add comprehensive watcher system with selective
debouncing for all settings (font, size, color, margins, etc.)
This ensures button clicks (unit toggles, format switches) apply instantly
while typed values (numbers, text) batch updates to reduce CSS re-parsing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:03:40 +01:00
|
|
|
Ces réglages s'appliquent à l'ensemble des éléments du document. Vous
|
|
|
|
|
pouvez modifier ensuite les éléments indépendamment.
|
2025-12-03 15:20:49 +01:00
|
|
|
</p>
|
|
|
|
|
|
2025-12-05 16:30:44 +01:00
|
|
|
<!-- Police -->
|
2025-12-04 16:21:50 +01:00
|
|
|
<div class="settings-subsection">
|
2025-12-09 17:08:40 +01:00
|
|
|
<div class="field field-font">
|
2026-03-05 16:29:42 +01:00
|
|
|
<label for="text-font" class="label-with-tooltip" data-css="font-family">Police</label>
|
2026-03-05 11:08:44 +01:00
|
|
|
<div class="field-font__options">
|
2026-03-05 16:29:42 +01:00
|
|
|
<select id="text-font" v-model="font">
|
|
|
|
|
<option value="sans-serif">Police système (sans-serif)</option>
|
|
|
|
|
<option v-for="f in projectFonts" :key="f.name" :value="f.name" :style="{ fontFamily: `'${f.name}', ${f.category}` }">{{ f.name }}</option>
|
2025-12-04 16:21:50 +01:00
|
|
|
</select>
|
2025-12-03 15:20:49 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-12-05 16:30:44 +01:00
|
|
|
<!-- Taille du texte -->
|
2025-12-04 16:21:50 +01:00
|
|
|
<div class="settings-subsection">
|
2025-12-11 13:38:27 +01:00
|
|
|
<div class="field field-text-size">
|
2025-12-05 18:21:54 +01:00
|
|
|
<label for="text-size-range" class="label-with-tooltip" data-css="font-size">Taille du texte</label>
|
2025-12-05 16:30:44 +01:00
|
|
|
<InputWithUnit
|
|
|
|
|
v-model="fontSize"
|
2026-02-24 14:16:54 +01:00
|
|
|
:units="['px']"
|
2025-12-05 16:30:44 +01:00
|
|
|
:min="8"
|
|
|
|
|
:max="72"
|
|
|
|
|
showRange
|
|
|
|
|
/>
|
2025-12-03 15:20:49 +01:00
|
|
|
</div>
|
2025-12-04 16:21:50 +01:00
|
|
|
</div>
|
2025-12-03 15:20:49 +01:00
|
|
|
|
2026-03-05 15:59:38 +01:00
|
|
|
<!-- Interlignage -->
|
|
|
|
|
<div class="settings-subsection">
|
|
|
|
|
<div class="field field-text-size">
|
|
|
|
|
<label for="text-lineheight-range" class="label-with-tooltip" data-css="line-height">Interlignage</label>
|
|
|
|
|
<InputWithUnit
|
|
|
|
|
v-model="lineHeight"
|
|
|
|
|
:units="['px']"
|
|
|
|
|
:min="0"
|
|
|
|
|
:max="72"
|
|
|
|
|
showRange
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-12-05 16:30:44 +01:00
|
|
|
<!-- Couleurs -->
|
2025-12-04 16:21:50 +01:00
|
|
|
<div class="settings-subsection">
|
2025-12-09 17:08:40 +01:00
|
|
|
<div class="field field-simple">
|
2025-12-05 18:21:54 +01:00
|
|
|
<label for="text-color" class="label-with-tooltip" data-css="color">Couleur</label>
|
2025-12-04 16:21:50 +01:00
|
|
|
<div class="input-with-color">
|
2025-12-03 15:20:49 +01:00
|
|
|
<input
|
2026-02-24 14:02:33 +01:00
|
|
|
ref="colorInput"
|
2025-12-04 16:21:50 +01:00
|
|
|
id="text-color"
|
|
|
|
|
type="text"
|
2025-12-05 16:30:44 +01:00
|
|
|
v-model="color"
|
2025-12-04 16:21:50 +01:00
|
|
|
class="color-input"
|
|
|
|
|
data-coloris
|
2025-12-03 15:20:49 +01:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-12-09 17:08:40 +01:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
2025-12-03 15:20:49 +01:00
|
|
|
</section>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2026-03-05 19:00:29 +01:00
|
|
|
import { ref, watch, onMounted, nextTick } from 'vue';
|
2026-02-26 15:35:45 +01:00
|
|
|
import { initColoris } from '../../composables/useColoris';
|
2025-12-05 16:30:44 +01:00
|
|
|
import InputWithUnit from '../ui/InputWithUnit.vue';
|
|
|
|
|
import { useCssUpdater } from '../../composables/useCssUpdater';
|
|
|
|
|
import { useCssSync } from '../../composables/useCssSync';
|
2025-12-10 11:51:53 +01:00
|
|
|
import { useDebounce } from '../../composables/useDebounce';
|
2026-03-05 14:49:58 +01:00
|
|
|
import { useTextDefaults } from '../../composables/useTextDefaults';
|
2026-03-05 16:29:42 +01:00
|
|
|
import { useProjectFonts } from '../../composables/useProjectFonts';
|
2025-12-05 16:30:44 +01:00
|
|
|
|
2026-03-05 11:42:18 +01:00
|
|
|
const { updateStyle } = useCssUpdater();
|
|
|
|
|
const { extractValue, extractNumericValue } = useCssSync();
|
2025-12-10 11:51:53 +01:00
|
|
|
const { debouncedUpdate } = useDebounce(500);
|
2026-03-05 14:49:58 +01:00
|
|
|
const textDefaults = useTextDefaults();
|
2026-03-05 16:29:42 +01:00
|
|
|
const { fonts: projectFonts, loadFont, loadAllFontPreviews } = useProjectFonts();
|
2025-12-05 16:30:44 +01:00
|
|
|
|
2026-03-05 19:00:29 +01:00
|
|
|
// State — initial values match stylesheet.print.css (overwritten by syncFromStore)
|
2026-03-05 19:06:27 +01:00
|
|
|
const font = ref('sans-serif');
|
2026-03-05 19:00:29 +01:00
|
|
|
const fontSize = ref({ value: 14, unit: 'px' });
|
|
|
|
|
const lineHeight = ref({ value: 18, unit: 'px' });
|
2025-12-05 16:30:44 +01:00
|
|
|
const color = ref('rgb(0, 0, 0)');
|
2026-02-24 14:02:33 +01:00
|
|
|
const colorInput = ref(null);
|
2025-12-03 15:20:49 +01:00
|
|
|
|
2026-03-05 19:00:29 +01:00
|
|
|
// Start true to block immediate watchers from overwriting textDefaults during setup
|
|
|
|
|
let isUpdatingFromStore = true;
|
2025-12-05 16:35:53 +01:00
|
|
|
|
2025-12-05 16:30:44 +01:00
|
|
|
// Watchers for body styles
|
2026-03-05 16:29:42 +01:00
|
|
|
watch(font, async (val) => {
|
2026-03-05 19:00:29 +01:00
|
|
|
if (isUpdatingFromStore) return;
|
2026-03-05 15:59:38 +01:00
|
|
|
textDefaults.fontFamily = val;
|
2026-03-05 16:29:42 +01:00
|
|
|
if (val !== 'sans-serif') await loadFont(val);
|
|
|
|
|
const cssValue = val === 'sans-serif' ? 'sans-serif' : `"${val}"`;
|
|
|
|
|
updateStyle('body', 'font-family', cssValue);
|
2026-03-05 15:59:38 +01:00
|
|
|
}, { immediate: true });
|
refactor: optimize EditorPanel updates with selective debouncing
Implement immediate vs debounced updates based on input type to improve
UX responsiveness while preventing excessive re-renders.
Update strategy:
- Immediate (0ms): select, buttons, checkboxes, color picker
- Debounced (1s): text inputs, number inputs, range sliders
Changes:
- PageSettings.vue: Split watchers for margin values/units and background
value/format. Extract update logic into reusable functions.
- TextSettings.vue: Add comprehensive watcher system with selective
debouncing for all settings (font, size, color, margins, etc.)
This ensures button clicks (unit toggles, format switches) apply instantly
while typed values (numbers, text) batch updates to reduce CSS re-parsing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:03:40 +01:00
|
|
|
|
2025-12-05 16:30:44 +01:00
|
|
|
watch(color, (val) => {
|
refactor: optimize EditorPanel updates with selective debouncing
Implement immediate vs debounced updates based on input type to improve
UX responsiveness while preventing excessive re-renders.
Update strategy:
- Immediate (0ms): select, buttons, checkboxes, color picker
- Debounced (1s): text inputs, number inputs, range sliders
Changes:
- PageSettings.vue: Split watchers for margin values/units and background
value/format. Extract update logic into reusable functions.
- TextSettings.vue: Add comprehensive watcher system with selective
debouncing for all settings (font, size, color, margins, etc.)
This ensures button clicks (unit toggles, format switches) apply instantly
while typed values (numbers, text) batch updates to reduce CSS re-parsing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:03:40 +01:00
|
|
|
if (isUpdatingFromStore) return;
|
2026-03-05 19:00:29 +01:00
|
|
|
textDefaults.color = val;
|
2025-12-05 16:30:44 +01:00
|
|
|
updateStyle('body', 'color', val);
|
2026-03-05 15:59:38 +01:00
|
|
|
}, { immediate: true });
|
2025-12-05 16:18:31 +01:00
|
|
|
|
2025-12-05 16:30:44 +01:00
|
|
|
watch(fontSize, (val) => {
|
|
|
|
|
if (isUpdatingFromStore) return;
|
2026-03-05 19:00:29 +01:00
|
|
|
textDefaults.fontSize = { value: val.value, unit: val.unit };
|
2025-12-10 11:51:53 +01:00
|
|
|
debouncedUpdate(() => {
|
|
|
|
|
updateStyle('p', 'font-size', `${val.value}${val.unit}`);
|
|
|
|
|
});
|
2026-03-05 14:49:58 +01:00
|
|
|
}, { deep: true, immediate: true });
|
2025-12-05 16:18:31 +01:00
|
|
|
|
2026-03-05 15:59:38 +01:00
|
|
|
watch(lineHeight, (val) => {
|
|
|
|
|
if (isUpdatingFromStore) return;
|
2026-03-05 19:00:29 +01:00
|
|
|
textDefaults.lineHeight = { value: val.value, unit: val.unit };
|
2026-03-05 15:59:38 +01:00
|
|
|
debouncedUpdate(() => {
|
|
|
|
|
updateStyle('p', 'line-height', `${val.value}${val.unit}`);
|
|
|
|
|
});
|
|
|
|
|
}, { deep: true, immediate: true });
|
|
|
|
|
|
refactor: optimize EditorPanel updates with selective debouncing
Implement immediate vs debounced updates based on input type to improve
UX responsiveness while preventing excessive re-renders.
Update strategy:
- Immediate (0ms): select, buttons, checkboxes, color picker
- Debounced (1s): text inputs, number inputs, range sliders
Changes:
- PageSettings.vue: Split watchers for margin values/units and background
value/format. Extract update logic into reusable functions.
- TextSettings.vue: Add comprehensive watcher system with selective
debouncing for all settings (font, size, color, margins, etc.)
This ensures button clicks (unit toggles, format switches) apply instantly
while typed values (numbers, text) batch updates to reduce CSS re-parsing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:03:40 +01:00
|
|
|
|
2026-03-05 19:00:29 +01:00
|
|
|
// Sync from store (first mount) or from textDefaults (subsequent mounts)
|
2025-12-05 16:30:44 +01:00
|
|
|
const syncFromStore = () => {
|
|
|
|
|
isUpdatingFromStore = true;
|
refactor: optimize EditorPanel updates with selective debouncing
Implement immediate vs debounced updates based on input type to improve
UX responsiveness while preventing excessive re-renders.
Update strategy:
- Immediate (0ms): select, buttons, checkboxes, color picker
- Debounced (1s): text inputs, number inputs, range sliders
Changes:
- PageSettings.vue: Split watchers for margin values/units and background
value/format. Extract update logic into reusable functions.
- TextSettings.vue: Add comprehensive watcher system with selective
debouncing for all settings (font, size, color, margins, etc.)
This ensures button clicks (unit toggles, format switches) apply instantly
while typed values (numbers, text) batch updates to reduce CSS re-parsing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:03:40 +01:00
|
|
|
|
2026-03-05 19:00:29 +01:00
|
|
|
if (textDefaults._initialized) {
|
|
|
|
|
// Already initialized — restore from textDefaults (not from CSS which may contain popup values)
|
|
|
|
|
font.value = textDefaults.fontFamily;
|
|
|
|
|
fontSize.value = { value: textDefaults.fontSize.value, unit: textDefaults.fontSize.unit };
|
|
|
|
|
lineHeight.value = { value: textDefaults.lineHeight.value, unit: textDefaults.lineHeight.unit };
|
|
|
|
|
color.value = textDefaults.color;
|
|
|
|
|
} else {
|
|
|
|
|
// First mount — read from CSS store
|
2026-03-05 19:06:27 +01:00
|
|
|
// For font-family, only accept known project fonts (ignore baseCss fonts like "DM Sans")
|
2026-03-05 19:00:29 +01:00
|
|
|
const fontVal = extractValue('body', 'font-family');
|
|
|
|
|
if (fontVal) {
|
|
|
|
|
const cleaned = fontVal.replace(/['"]/g, '').trim();
|
2026-03-05 19:06:27 +01:00
|
|
|
const isKnownFont = cleaned === 'sans-serif' || projectFonts.some(f => f.name === cleaned);
|
|
|
|
|
font.value = isKnownFont ? cleaned : 'sans-serif';
|
2026-03-05 19:00:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const colorVal = extractValue('body', 'color');
|
|
|
|
|
if (colorVal) color.value = colorVal;
|
|
|
|
|
|
|
|
|
|
const fontSizeVal = extractNumericValue('p', 'font-size', ['px']);
|
|
|
|
|
if (fontSizeVal) fontSize.value = fontSizeVal;
|
|
|
|
|
|
|
|
|
|
const lineHeightVal = extractNumericValue('p', 'line-height', ['px']);
|
|
|
|
|
if (lineHeightVal) lineHeight.value = lineHeightVal;
|
|
|
|
|
|
|
|
|
|
// Persist to textDefaults from CSS-synced values
|
|
|
|
|
textDefaults.fontFamily = font.value;
|
|
|
|
|
textDefaults.fontSize = { value: fontSize.value.value, unit: fontSize.value.unit };
|
|
|
|
|
textDefaults.lineHeight = { value: lineHeight.value.value, unit: lineHeight.value.unit };
|
|
|
|
|
textDefaults.color = color.value;
|
|
|
|
|
textDefaults._initialized = true;
|
2026-03-05 16:29:42 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-05 19:00:29 +01:00
|
|
|
// Release flag after watchers triggered by ref changes have been skipped
|
|
|
|
|
nextTick(() => { isUpdatingFromStore = false; });
|
2025-12-05 16:30:44 +01:00
|
|
|
};
|
2025-12-05 16:18:31 +01:00
|
|
|
|
2026-02-24 14:02:33 +01:00
|
|
|
const updateColorisButtons = () => {
|
2026-03-05 11:42:18 +01:00
|
|
|
if (colorInput.value) {
|
|
|
|
|
colorInput.value.dispatchEvent(new Event('input', { bubbles: true }));
|
|
|
|
|
}
|
2026-02-24 14:02:33 +01:00
|
|
|
};
|
|
|
|
|
|
2025-12-04 16:21:50 +01:00
|
|
|
onMounted(() => {
|
2026-02-26 15:35:45 +01:00
|
|
|
initColoris({
|
2025-12-04 16:21:50 +01:00
|
|
|
format: 'auto',
|
2026-02-26 15:35:45 +01:00
|
|
|
swatches: ['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', 'transparent'],
|
2025-12-04 16:21:50 +01:00
|
|
|
});
|
2025-12-05 16:18:31 +01:00
|
|
|
syncFromStore();
|
2026-02-24 14:02:33 +01:00
|
|
|
setTimeout(updateColorisButtons, 100);
|
2026-03-05 16:29:42 +01:00
|
|
|
loadAllFontPreviews();
|
2025-12-04 16:21:50 +01:00
|
|
|
});
|
2025-12-03 15:20:49 +01:00
|
|
|
</script>
|
2025-12-10 13:47:49 +01:00
|
|
|
|