161 lines
4.9 KiB
Vue
161 lines
4.9 KiB
Vue
<template>
|
|
<section class="settings-section" id="settings-section_elem" data-color-type="elem">
|
|
<h2>Réglage du texte par défaut</h2>
|
|
<div class="container">
|
|
|
|
<p class="infos">
|
|
Ces réglages s'appliquent à l'ensemble des éléments du document. Vous
|
|
pouvez modifier ensuite les éléments indépendamment.
|
|
</p>
|
|
|
|
<!-- Police -->
|
|
<div class="settings-subsection">
|
|
<div class="field field-font">
|
|
<label for="text-font" class="label-with-tooltip field--view-only" data-css="font-family" title="Fonctionnalité à venir">Police</label>
|
|
<div class="field-font__options">
|
|
<select id="text-font" v-model="font" disabled class="field--view-only" title="Fonctionnalité à venir">
|
|
<option v-for="f in fonts" :key="f" :value="f">{{ f }}</option>
|
|
</select>
|
|
<div class="field-checkbox">
|
|
<input id="text-italic" type="checkbox" v-model="italic" />
|
|
<label for="text-italic" class="label-with-tooltip" data-css="font-style">Italique</label>
|
|
</div>
|
|
<div class="field-checkbox">
|
|
<input id="text-bold" type="checkbox" v-model="bold" />
|
|
<label for="text-bold" class="label-with-tooltip" data-css="font-weight">Gras</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Taille du texte -->
|
|
<div class="settings-subsection">
|
|
<div class="field field-text-size">
|
|
<label for="text-size-range" class="label-with-tooltip" data-css="font-size">Taille du texte</label>
|
|
<InputWithUnit
|
|
v-model="fontSize"
|
|
:units="['px']"
|
|
:min="8"
|
|
:max="72"
|
|
showRange
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Couleurs -->
|
|
<div class="settings-subsection">
|
|
<div class="field field-simple">
|
|
<label for="text-color" class="label-with-tooltip" data-css="color">Couleur</label>
|
|
<div class="input-with-color">
|
|
<input
|
|
ref="colorInput"
|
|
id="text-color"
|
|
type="text"
|
|
v-model="color"
|
|
class="color-input"
|
|
data-coloris
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, watch, onMounted } from 'vue';
|
|
import { initColoris } from '../../composables/useColoris';
|
|
import InputWithUnit from '../ui/InputWithUnit.vue';
|
|
import { useCssUpdater } from '../../composables/useCssUpdater';
|
|
import { useCssSync } from '../../composables/useCssSync';
|
|
import { useDebounce } from '../../composables/useDebounce';
|
|
import { useTextDefaults } from '../../composables/useTextDefaults';
|
|
|
|
const { updateStyle } = useCssUpdater();
|
|
const { extractValue, extractNumericValue } = useCssSync();
|
|
const { debouncedUpdate } = useDebounce(500);
|
|
const textDefaults = useTextDefaults();
|
|
|
|
// Constants
|
|
const fonts = ['Alegreya Sans', 'Arial', 'Georgia', 'Helvetica', 'Times New Roman'];
|
|
|
|
// State
|
|
const font = ref('Alegreya Sans');
|
|
const italic = ref(false);
|
|
const bold = ref(false);
|
|
const fontSize = ref({ value: 16, unit: 'px' });
|
|
const color = ref('rgb(0, 0, 0)');
|
|
const colorInput = ref(null);
|
|
|
|
let isUpdatingFromStore = false;
|
|
|
|
// Watchers for body styles
|
|
watch(font, (val) => {
|
|
if (isUpdatingFromStore) return;
|
|
updateStyle('body', 'font-family', `"${val}"`);
|
|
});
|
|
|
|
watch(italic, (val) => {
|
|
if (isUpdatingFromStore) return;
|
|
updateStyle('p', 'font-style', val ? 'italic' : 'normal');
|
|
});
|
|
|
|
watch(color, (val) => {
|
|
if (isUpdatingFromStore) return;
|
|
updateStyle('body', 'color', val);
|
|
});
|
|
|
|
// Watchers for paragraph styles
|
|
watch(bold, (val) => {
|
|
if (isUpdatingFromStore) return;
|
|
updateStyle('p', 'font-weight', val ? 'bold' : 'normal');
|
|
});
|
|
|
|
watch(fontSize, (val) => {
|
|
textDefaults.fontSize = { value: val.value, unit: val.unit };
|
|
if (isUpdatingFromStore) return;
|
|
debouncedUpdate(() => {
|
|
updateStyle('p', 'font-size', `${val.value}${val.unit}`);
|
|
});
|
|
}, { deep: true, immediate: true });
|
|
|
|
|
|
// Sync from store
|
|
const syncFromStore = () => {
|
|
isUpdatingFromStore = true;
|
|
|
|
// Body styles
|
|
const fontStyle = extractValue('p', 'font-style');
|
|
if (fontStyle) italic.value = fontStyle === 'italic';
|
|
|
|
const colorVal = extractValue('body', 'color');
|
|
if (colorVal) color.value = colorVal;
|
|
|
|
// Paragraph styles
|
|
const fontWeight = extractValue('p', 'font-weight');
|
|
if (fontWeight) bold.value = fontWeight === 'bold' || parseInt(fontWeight) >= 700;
|
|
|
|
const fontSizeVal = extractNumericValue('p', 'font-size', ['px']); // ['px', 'em', 'rem']
|
|
if (fontSizeVal) fontSize.value = fontSizeVal;
|
|
|
|
isUpdatingFromStore = false;
|
|
};
|
|
|
|
const updateColorisButtons = () => {
|
|
if (colorInput.value) {
|
|
colorInput.value.dispatchEvent(new Event('input', { bubbles: true }));
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
initColoris({
|
|
format: 'auto',
|
|
swatches: ['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', 'transparent'],
|
|
});
|
|
syncFromStore();
|
|
setTimeout(updateColorisButtons, 100);
|
|
});
|
|
</script>
|
|
|