Compare commits
No commits in common. "9af36fb4221c295e04ea381ba5a36b7be93e2aa1" and "960f509d5c466195ef87ed69030696eeb0400a38" have entirely different histories.
9af36fb422
...
960f509d5c
19 changed files with 209 additions and 851 deletions
7
package-lock.json
generated
7
package-lock.json
generated
|
|
@ -8,7 +8,6 @@
|
||||||
"name": "geoproject",
|
"name": "geoproject",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@melloware/coloris": "^0.25.0",
|
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"pagedjs": "^0.4.3",
|
"pagedjs": "^0.4.3",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
|
|
@ -533,12 +532,6 @@
|
||||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@melloware/coloris": {
|
|
||||||
"version": "0.25.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@melloware/coloris/-/coloris-0.25.0.tgz",
|
|
||||||
"integrity": "sha512-RBWVFLjWbup7GRkOXb9g3+ZtR9AevFtJinrRz2cYPLjZ3TCkNRGMWuNbmQWbZ5cF3VU7aQDZwUsYgIY/bGrh2g==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/pluginutils": {
|
"node_modules/@rolldown/pluginutils": {
|
||||||
"version": "1.0.0-beta.50",
|
"version": "1.0.0-beta.50",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz",
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@melloware/coloris": "^0.25.0",
|
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"pagedjs": "^0.4.3",
|
"pagedjs": "^0.4.3",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
|
|
|
||||||
1
public/assets/css/editor-ui.css
Normal file
1
public/assets/css/editor-ui.css
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
button {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
border: 1px solid var(--color-browngray-300);
|
|
||||||
color: var(--color-browngray-300);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border: 1px solid #000;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.tab {
|
|
||||||
&.active {
|
|
||||||
background-color: #000;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
select,
|
|
||||||
input[type="text"],
|
|
||||||
input[type="number"] {
|
|
||||||
background-color: var(--color-browngray-300);
|
|
||||||
}
|
|
||||||
|
|
||||||
.field--view-only {
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-section {
|
|
||||||
h2 {
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
}
|
|
||||||
.settings-subsection:not(:last-child) {
|
|
||||||
border-bottom: 1px solid var(--color-browngray-050);
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-subsection {
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
|
|
||||||
.field {
|
|
||||||
display: flex;
|
|
||||||
label {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-with-unit {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-with-color {
|
|
||||||
.clr-field {
|
|
||||||
display: flex;
|
|
||||||
button {
|
|
||||||
position: absolute;
|
|
||||||
transform: none;
|
|
||||||
height: 1rem;
|
|
||||||
top: auto;
|
|
||||||
right: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
padding-left: 2.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.margins {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
h3 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.field {
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
label {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-with-unit {
|
|
||||||
input {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
body,
|
|
||||||
html {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
select {
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
body,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6,
|
|
||||||
p,
|
|
||||||
a,
|
|
||||||
input,
|
|
||||||
select,
|
|
||||||
figcaption,
|
|
||||||
label {
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
:root {
|
|
||||||
--color-panel-bg: #e8e6e5;
|
|
||||||
--color-browngray-050: #f5f3f0;
|
|
||||||
--color-browngray-200: #d0c4ba;
|
|
||||||
--color-browngray-300: #b5a9a1;
|
|
||||||
|
|
||||||
--border-radius: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
body,
|
|
||||||
html {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
select {
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--color-panel-bg: #e8e6e5;
|
|
||||||
--color-browngray-050: #f5f3f0;
|
|
||||||
--color-browngray-200: #d0c4ba;
|
|
||||||
--color-browngray-300: #b5a9a1;
|
|
||||||
--border-radius: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6,
|
|
||||||
p,
|
|
||||||
a,
|
|
||||||
input,
|
|
||||||
select,
|
|
||||||
figcaption,
|
|
||||||
label {
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PagedJS print styles */
|
|
||||||
@page {
|
|
||||||
size: A4;
|
|
||||||
margin: 20mm 15mm 26mm 15mm;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
-moz-column-break-before: page;
|
|
||||||
break-before: page;
|
|
||||||
}
|
|
||||||
|
|
||||||
@page {
|
|
||||||
@bottom-center {
|
|
||||||
content: string(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.chapter > h2 {
|
|
||||||
string-set: title content(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
select,
|
|
||||||
input[type=text],
|
|
||||||
input[type=number] {
|
|
||||||
background-color: var(--color-browngray-300);
|
|
||||||
}
|
|
||||||
|
|
||||||
.field--view-only {
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-section h2 {
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection:not(:last-child) {
|
|
||||||
border-bottom: 1px solid var(--color-browngray-050);
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection {
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection .field {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection .field label {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection .field .input-with-unit {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection .field .input-with-color .clr-field {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection .field .input-with-color .clr-field button {
|
|
||||||
position: absolute;
|
|
||||||
transform: none;
|
|
||||||
height: 1rem;
|
|
||||||
top: auto;
|
|
||||||
right: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection .field .input-with-color .clr-field input {
|
|
||||||
padding-left: 2.5rem;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection.margins {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection.margins h3 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection.margins .field {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection.margins .field label {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.settings-section .settings-subsection.margins .field .input-with-unit input {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--color-browngray-300);
|
|
||||||
color: var(--color-browngray-300);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
}
|
|
||||||
button.active {
|
|
||||||
border: 1px solid #000;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
button.tab.active {
|
|
||||||
background-color: #000;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
}/*# sourceMappingURL=style.css.map */
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{"version":3,"sources":["src/_reset.scss","style.css","src/_variables.scss","src/_text.scss","src/_print-styles.scss","src/_forms.scss","src/_buttons.scss"],"names":[],"mappings":"AAAA;;EAEE,UAAA;EACA,SAAA;ACCF;;ADEA;;;;;;EAME,SAAA;ACCF;;ADEA;;EAEE,YAAA;EACA,aAAA;EAEA,mCAAA;ACAF;;ADGA;EACE,6BAAA;EACA,YAAA;ACAF;;ACzBA;EACE,yBAAA;EACA,8BAAA;EACA,8BAAA;EACA,8BAAA;EAEA,uBAAA;AD2BF;;AEjCA;;;;;;;;;;;;;EAaE,uBAAA;AFoCF;;AGjDA,yBAAA;AACA;EACE,QAAA;EACA,2BAAA;AHoDF;AGlDA;EACE,8BAAA;OAAA,kBAAA;AHoDF;;AGjDA;EACE;IACE,sBAAA;EHoDF;AACF;AGlDA;EACE,+BAAA;AHoDF;;AInEA;;;EAGE,4CAAA;AJsEF;;AInEA;EACE,YAAA;AJsEF;;AIlEE;EACE,6BAAA;AJqEJ;AInEE;EACE,mDAAA;AJqEJ;AIlEE;EACE,iBAAA;AJoEJ;AIlEI;EACE,aAAA;AJoEN;AInEM;EACE,UAAA;AJqER;AIlEM;EACE,aAAA;AJoER;AIhEQ;EACE,aAAA;AJkEV;AIjEU;EACE,kBAAA;EACA,eAAA;EACA,YAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;AJmEZ;AIhEU;EACE,oBAAA;AJkEZ;AI5DI;EACE,aAAA;EACA,eAAA;AJ8DN;AI7DM;EACE,WAAA;AJ+DR;AI7DM;EACE,UAAA;AJ+DR;AI7DQ;EACE,UAAA;AJ+DV;AI3DU;EACE,UAAA;AJ6DZ;;AK9HA;EACE,eAAA;EAEA,4CAAA;EACA,iCAAA;EACA,mCAAA;EACA,sBAAA;ALgIF;AK9HE;EACE,sBAAA;EACA,WAAA;ALgIJ;AK5HI;EACE,sBAAA;EACA,WAAA;EACA,YAAA;AL8HN","file":"style.css"}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
@import "src/_reset.scss";
|
|
||||||
@import "src/_variables.scss";
|
|
||||||
@import "src/_text.scss";
|
|
||||||
@import "src/_print-styles.scss";
|
|
||||||
@import "src/_forms.scss";
|
|
||||||
@import "src/_buttons.scss";
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
<?= e($page->isHomePage() != true, $page->title() . ' - ') . $site->title() ?>
|
<?= e($page->isHomePage() != true, $page->title() . ' - ') . $site->title() ?>
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="<?= url('assets/css/style..css') ?>">
|
<link rel="stylesheet" href="<?= url('assets/pagedjs-interface.css') ?>">
|
||||||
<link rel="stylesheet" href="<?= url('assets/css/pagedjs-interface.css') ?>">
|
<link rel="stylesheet" href="<?= url('assets/stylesheet.css') ?>">
|
||||||
|
|
||||||
<!-- À SUPPRIMER EN PRODUCTION -->
|
<!-- À SUPPRIMER EN PRODUCTION -->
|
||||||
<meta name="robots" content="noindex, nofollow, noarchive">
|
<meta name="robots" content="noindex, nofollow, noarchive">
|
||||||
|
|
|
||||||
21
src/App.vue
21
src/App.vue
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import PagedJsWrapper from './components/PagedJsWrapper.vue';
|
import PagedJsWrapper from './components/PagedJsWrapper.vue';
|
||||||
import EditorPanel from './components/editor/EditorPanel.vue';
|
import EditorPanel from './components/editor/EditorPanel.vue';
|
||||||
|
import StylesheetViewer from './components/StylesheetViewer.vue';
|
||||||
import ElementPopup from './components/ElementPopup.vue';
|
import ElementPopup from './components/ElementPopup.vue';
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { useStylesheetStore } from './stores/stylesheet';
|
import { useStylesheetStore } from './stores/stylesheet';
|
||||||
|
|
@ -41,10 +42,7 @@ const renderPreview = async (shouldReloadFromFile = false) => {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
iframe.onload = () => {
|
iframe.onload = () => {
|
||||||
iframe.contentDocument.addEventListener(
|
iframe.contentDocument.addEventListener('click', elementPopup.value.handleIframeClick);
|
||||||
'click',
|
|
||||||
elementPopup.value.handleIframeClick
|
|
||||||
);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const scrollHeight = iframe.contentDocument.documentElement.scrollHeight;
|
const scrollHeight = iframe.contentDocument.documentElement.scrollHeight;
|
||||||
|
|
@ -57,12 +55,9 @@ const renderPreview = async (shouldReloadFromFile = false) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(() => stylesheetStore.content, () => {
|
||||||
() => stylesheetStore.content,
|
renderPreview();
|
||||||
() => {
|
});
|
||||||
renderPreview();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => renderPreview(true));
|
onMounted(() => renderPreview(true));
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -76,6 +71,8 @@ onMounted(() => renderPreview(true));
|
||||||
|
|
||||||
<iframe ref="previewFrame" id="preview-frame"></iframe>
|
<iframe ref="previewFrame" id="preview-frame"></iframe>
|
||||||
|
|
||||||
|
<StylesheetViewer :stylesheet="stylesheetStore.content" />
|
||||||
|
|
||||||
<ElementPopup ref="elementPopup" :iframeRef="previewFrame" />
|
<ElementPopup ref="elementPopup" :iframeRef="previewFrame" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -83,8 +80,8 @@ onMounted(() => renderPreview(true));
|
||||||
#preview-frame {
|
#preview-frame {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 250px;
|
||||||
width: 100vw;
|
width: calc(100% - 600px);
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="stylesheet-viewer">
|
<aside id="stylesheet-viewer">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h3>Stylesheet</h3>
|
<h3>Stylesheet</h3>
|
||||||
<label class="toggle">
|
<label class="toggle">
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
@input="handleInput"
|
@input="handleInput"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</aside>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
@ -53,9 +53,14 @@ const handleInput = (event) => {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#stylesheet-viewer {
|
#stylesheet-viewer {
|
||||||
display: flex;
|
position: fixed;
|
||||||
flex-direction: column;
|
top: 0;
|
||||||
height: 100%;
|
right: 0;
|
||||||
|
width: 350px;
|
||||||
|
height: 100vh;
|
||||||
|
padding: 1rem;
|
||||||
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow-y: auto;
|
||||||
background: #282c34;
|
background: #282c34;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +130,7 @@ h3 {
|
||||||
|
|
||||||
.readonly {
|
.readonly {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
flex: 1;
|
height: calc(100vh - 5rem);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
|
|
@ -140,7 +145,7 @@ h3 {
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: 1;
|
height: calc(100vh - 5rem);
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
color: #abb2bf;
|
color: #abb2bf;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
<nav class="tabs">
|
<nav class="tabs">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="tab"
|
|
||||||
:class="{ active: activeTab === 'document' }"
|
:class="{ active: activeTab === 'document' }"
|
||||||
@click="activeTab = 'document'"
|
@click="activeTab = 'document'"
|
||||||
>
|
>
|
||||||
|
|
@ -11,7 +10,6 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="tab"
|
|
||||||
:class="{ active: activeTab === 'code' }"
|
:class="{ active: activeTab === 'code' }"
|
||||||
@click="activeTab = 'code'"
|
@click="activeTab = 'code'"
|
||||||
>
|
>
|
||||||
|
|
@ -19,7 +17,6 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="tab"
|
|
||||||
:class="{ active: activeTab === 'contenu' }"
|
:class="{ active: activeTab === 'contenu' }"
|
||||||
@click="activeTab = 'contenu'"
|
@click="activeTab = 'contenu'"
|
||||||
>
|
>
|
||||||
|
|
@ -34,7 +31,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'code'" class="tab-panel">
|
<div v-else-if="activeTab === 'code'" class="tab-panel">
|
||||||
<StylesheetViewer />
|
<!-- Code tab content -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'contenu'" class="tab-panel">
|
<div v-else-if="activeTab === 'contenu'" class="tab-panel">
|
||||||
|
|
@ -45,48 +42,43 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, provide } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageSettings from './PageSettings.vue';
|
import PageSettings from './PageSettings.vue';
|
||||||
import TextSettings from './TextSettings.vue';
|
import TextSettings from './TextSettings.vue';
|
||||||
import StylesheetViewer from '../StylesheetViewer.vue';
|
|
||||||
|
|
||||||
// Tab management
|
// Tab management
|
||||||
const activeTab = ref('document');
|
const activeTab = ref('document');
|
||||||
|
|
||||||
// Provide activeTab to child components
|
|
||||||
provide('activeTab', activeTab);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
#editor-panel {
|
#editor-panel {
|
||||||
padding: 1rem;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 30rem;
|
width: 250px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
background: #f5f5f5;
|
||||||
flex-direction: column;
|
padding: 1rem;
|
||||||
z-index: 2;
|
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
background-color: var(--color-panel-bg);
|
|
||||||
box-shadow: -5px 0px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-panel {
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control input {
|
||||||
|
width: 80px;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -2,49 +2,43 @@
|
||||||
<section class="settings-section">
|
<section class="settings-section">
|
||||||
<h2>Réglage des pages</h2>
|
<h2>Réglage des pages</h2>
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="field">
|
||||||
<div class="field">
|
<label for="page-format">Format d'impression</label>
|
||||||
<label for="page-format">Format d'impression</label>
|
<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>
|
</select>
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="field">
|
||||||
<div class="field field--view-only">
|
<label for="page-width">Largeur</label>
|
||||||
<label for="page-width">Largeur</label>
|
<input
|
||||||
<input
|
id="page-width"
|
||||||
id="page-width"
|
type="text"
|
||||||
type="number"
|
:value="pageWidth"
|
||||||
:value="parseInt(pageWidth)"
|
disabled
|
||||||
disabled
|
/>
|
||||||
/>
|
|
||||||
<button type="button" disabled>mm</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field field--view-only">
|
|
||||||
<label for="page-height">Hauteur</label>
|
|
||||||
<input
|
|
||||||
id="page-height"
|
|
||||||
type="number"
|
|
||||||
:value="parseInt(pageHeight)"
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
<button type="button" disabled>mm</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-subsection margins">
|
<div class="field">
|
||||||
|
<label for="page-height">Hauteur</label>
|
||||||
|
<input
|
||||||
|
id="page-height"
|
||||||
|
type="text"
|
||||||
|
:value="pageHeight"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
<h3>Marges</h3>
|
<h3>Marges</h3>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-top">Haut</label>
|
<label for="margin-top">Haut</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-top"
|
id="margin-top"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -72,7 +66,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-bottom">Bas</label>
|
<label for="margin-bottom">Bas</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-bottom"
|
id="margin-bottom"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -100,7 +94,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-left">Gauche</label>
|
<label for="margin-left">Gauche</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-left"
|
id="margin-left"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -128,7 +122,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-right">Droite</label>
|
<label for="margin-right">Droite</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-right"
|
id="margin-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -155,74 +149,68 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="field">
|
||||||
<div class="field">
|
<label for="background">Arrière-plan</label>
|
||||||
<label for="background">Arrière-plan</label>
|
<div class="field-with-unit">
|
||||||
<div class="input-with-color">
|
<input
|
||||||
<input
|
id="background"
|
||||||
ref="backgroundColorInput"
|
type="text"
|
||||||
type="text"
|
v-model="background.value"
|
||||||
id="background"
|
/>
|
||||||
v-model="background.value"
|
<div class="unit-toggle">
|
||||||
data-coloris
|
<button
|
||||||
/>
|
type="button"
|
||||||
<!-- Temporarily commented out
|
:class="{ active: background.format === 'rgb' }"
|
||||||
<div class="unit-toggle">
|
@click="background.format = 'rgb'"
|
||||||
<button
|
>
|
||||||
type="button"
|
rgb
|
||||||
:class="{ active: background.format === 'rgb' }"
|
</button>
|
||||||
@click="background.format = 'rgb'"
|
<button
|
||||||
>
|
type="button"
|
||||||
rgb
|
:class="{ active: background.format === 'hex' }"
|
||||||
</button>
|
@click="background.format = 'hex'"
|
||||||
<button
|
>
|
||||||
type="button"
|
hex
|
||||||
:class="{ active: background.format === 'hex' }"
|
</button>
|
||||||
@click="background.format = 'hex'"
|
|
||||||
>
|
|
||||||
hex
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="field">
|
||||||
<div class="field">
|
<label for="pattern">Motif</label>
|
||||||
<label for="pattern">Motif</label>
|
<select id="pattern" v-model="pattern">
|
||||||
<select id="pattern" v-model="pattern">
|
<option value="">Choisissez</option>
|
||||||
<option value="">Choisissez</option>
|
<option value="dots">Points</option>
|
||||||
<option value="dots">Points</option>
|
<option value="lines">Lignes</option>
|
||||||
<option value="lines">Lignes</option>
|
<option value="grid">Grille</option>
|
||||||
<option value="grid">Grille</option>
|
</select>
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-subsection">
|
<div class="field checkbox-field">
|
||||||
<div class="field checkbox-field">
|
<input
|
||||||
<input id="page-numbers" type="checkbox" v-model="pageNumbers" />
|
id="page-numbers"
|
||||||
<label for="page-numbers">Numéro de page</label>
|
type="checkbox"
|
||||||
</div>
|
v-model="pageNumbers"
|
||||||
|
/>
|
||||||
|
<label for="page-numbers">Numéro de page</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field checkbox-field">
|
<div class="field checkbox-field">
|
||||||
<input id="running-title" type="checkbox" v-model="runningTitle" />
|
<input
|
||||||
<label for="running-title">Titre courant</label>
|
id="running-title"
|
||||||
</div>
|
type="checkbox"
|
||||||
|
v-model="runningTitle"
|
||||||
|
/>
|
||||||
|
<label for="running-title">Titre courant</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onMounted, inject } from 'vue';
|
import { ref, computed, watch, onMounted } from 'vue';
|
||||||
import { useStylesheetStore } from '../../stores/stylesheet';
|
import { useStylesheetStore } from '../../stores/stylesheet';
|
||||||
import Coloris from '@melloware/coloris';
|
|
||||||
import '@melloware/coloris/dist/coloris.css';
|
|
||||||
|
|
||||||
const stylesheetStore = useStylesheetStore();
|
const stylesheetStore = useStylesheetStore();
|
||||||
const backgroundColorInput = ref(null);
|
|
||||||
const activeTab = inject('activeTab', ref('document'));
|
|
||||||
|
|
||||||
let isUpdatingFromStore = false;
|
let isUpdatingFromStore = false;
|
||||||
let updateTimer = null;
|
let updateTimer = null;
|
||||||
|
|
@ -234,7 +222,7 @@ const pageFormats = {
|
||||||
A5: { width: '148mm', height: '210mm' },
|
A5: { width: '148mm', height: '210mm' },
|
||||||
A3: { width: '297mm', height: '420mm' },
|
A3: { width: '297mm', height: '420mm' },
|
||||||
letter: { width: '8.5in', height: '11in' },
|
letter: { width: '8.5in', height: '11in' },
|
||||||
legal: { width: '8.5in', height: '14in' },
|
legal: { width: '8.5in', height: '14in' }
|
||||||
};
|
};
|
||||||
|
|
||||||
const pageWidth = computed(() => pageFormats[pageFormat.value].width);
|
const pageWidth = computed(() => pageFormats[pageFormat.value].width);
|
||||||
|
|
@ -244,12 +232,12 @@ const margins = ref({
|
||||||
top: { value: 20, unit: 'mm' },
|
top: { value: 20, unit: 'mm' },
|
||||||
bottom: { value: 20, unit: 'mm' },
|
bottom: { value: 20, unit: 'mm' },
|
||||||
left: { value: 20, unit: 'mm' },
|
left: { value: 20, unit: 'mm' },
|
||||||
right: { value: 20, unit: 'mm' },
|
right: { value: 20, unit: 'mm' }
|
||||||
});
|
});
|
||||||
|
|
||||||
const background = ref({
|
const background = ref({
|
||||||
value: '',
|
value: '',
|
||||||
format: 'hex',
|
format: 'hex'
|
||||||
});
|
});
|
||||||
|
|
||||||
const pattern = ref('');
|
const pattern = ref('');
|
||||||
|
|
@ -261,109 +249,57 @@ const debouncedUpdate = (callback) => {
|
||||||
updateTimer = setTimeout(callback, 1000);
|
updateTimer = setTimeout(callback, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const immediateUpdate = (callback) => {
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(pageFormat, (newFormat) => {
|
watch(pageFormat, (newFormat) => {
|
||||||
if (isUpdatingFromStore) return;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
immediateUpdate(() => {
|
debouncedUpdate(() => {
|
||||||
stylesheetStore.updateProperty('@page', 'size', newFormat, '');
|
stylesheetStore.updateProperty('@page', 'size', newFormat, '');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateMargins = () => {
|
watch(margins, (newMargins) => {
|
||||||
const marginValue = `${margins.value.top.value}${margins.value.top.unit} ${margins.value.right.value}${margins.value.right.unit} ${margins.value.bottom.value}${margins.value.bottom.unit} ${margins.value.left.value}${margins.value.left.unit}`;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
const currentBlock = stylesheetStore.extractBlock('@page');
|
debouncedUpdate(() => {
|
||||||
const updatedBlock = currentBlock.replace(
|
const marginValue = `${newMargins.top.value}${newMargins.top.unit} ${newMargins.right.value}${newMargins.right.unit} ${newMargins.bottom.value}${newMargins.bottom.unit} ${newMargins.left.value}${newMargins.left.unit}`;
|
||||||
/(margin:\s*)[^;]+/,
|
|
||||||
`$1${marginValue}`
|
|
||||||
);
|
|
||||||
|
|
||||||
stylesheetStore.content = stylesheetStore.content.replace(
|
const currentBlock = stylesheetStore.extractBlock('@page');
|
||||||
currentBlock,
|
|
||||||
updatedBlock
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Watch margin values (number inputs) with debounce
|
|
||||||
watch(
|
|
||||||
() => [
|
|
||||||
margins.value.top.value,
|
|
||||||
margins.value.bottom.value,
|
|
||||||
margins.value.left.value,
|
|
||||||
margins.value.right.value,
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(updateMargins);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Watch margin units (button clicks) without debounce
|
|
||||||
watch(
|
|
||||||
() => [
|
|
||||||
margins.value.top.unit,
|
|
||||||
margins.value.bottom.unit,
|
|
||||||
margins.value.left.unit,
|
|
||||||
margins.value.right.unit,
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(updateMargins);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateBackground = () => {
|
|
||||||
if (!background.value.value) return;
|
|
||||||
|
|
||||||
const currentBlock = stylesheetStore.extractBlock('@page');
|
|
||||||
|
|
||||||
if (currentBlock.includes('background:')) {
|
|
||||||
const updatedBlock = currentBlock.replace(
|
const updatedBlock = currentBlock.replace(
|
||||||
/(background:\s*)[^;]+/,
|
/(margin:\s*)[^;]+/,
|
||||||
`$1${background.value.value}`
|
`$1${marginValue}`
|
||||||
);
|
);
|
||||||
stylesheetStore.content = stylesheetStore.content.replace(
|
|
||||||
currentBlock,
|
|
||||||
updatedBlock
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const updatedBlock = currentBlock.replace(
|
|
||||||
/(\s*})$/,
|
|
||||||
` background: ${background.value.value};\n$1`
|
|
||||||
);
|
|
||||||
stylesheetStore.content = stylesheetStore.content.replace(
|
|
||||||
currentBlock,
|
|
||||||
updatedBlock
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Watch background value (text input) with debounce
|
stylesheetStore.content = stylesheetStore.content.replace(currentBlock, updatedBlock);
|
||||||
watch(
|
});
|
||||||
() => background.value.value,
|
}, { deep: true });
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(updateBackground);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Watch background format (button clicks) without debounce
|
watch(background, (newBg) => {
|
||||||
watch(
|
if (!newBg.value) return;
|
||||||
() => background.value.format,
|
if (isUpdatingFromStore) return;
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
debouncedUpdate(() => {
|
||||||
immediateUpdate(updateBackground);
|
const currentBlock = stylesheetStore.extractBlock('@page');
|
||||||
}
|
|
||||||
);
|
if (currentBlock.includes('background:')) {
|
||||||
|
const updatedBlock = currentBlock.replace(
|
||||||
|
/(background:\s*)[^;]+/,
|
||||||
|
`$1${newBg.value}`
|
||||||
|
);
|
||||||
|
stylesheetStore.content = stylesheetStore.content.replace(currentBlock, updatedBlock);
|
||||||
|
} else {
|
||||||
|
const updatedBlock = currentBlock.replace(
|
||||||
|
/(\s*})$/,
|
||||||
|
` background: ${newBg.value};\n$1`
|
||||||
|
);
|
||||||
|
stylesheetStore.content = stylesheetStore.content.replace(currentBlock, updatedBlock);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, { deep: true });
|
||||||
|
|
||||||
watch(pattern, (newPattern) => {
|
watch(pattern, (newPattern) => {
|
||||||
if (!newPattern || isUpdatingFromStore) return;
|
if (!newPattern || isUpdatingFromStore) return;
|
||||||
|
|
||||||
immediateUpdate(() => {
|
debouncedUpdate(() => {
|
||||||
// TODO: implement pattern application
|
// TODO: implement pattern application
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -371,7 +307,7 @@ watch(pattern, (newPattern) => {
|
||||||
watch(pageNumbers, (enabled) => {
|
watch(pageNumbers, (enabled) => {
|
||||||
if (isUpdatingFromStore) return;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
immediateUpdate(() => {
|
debouncedUpdate(() => {
|
||||||
// TODO: implement page numbers toggle
|
// TODO: implement page numbers toggle
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -379,7 +315,7 @@ watch(pageNumbers, (enabled) => {
|
||||||
watch(runningTitle, (enabled) => {
|
watch(runningTitle, (enabled) => {
|
||||||
if (isUpdatingFromStore) return;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
immediateUpdate(() => {
|
debouncedUpdate(() => {
|
||||||
// TODO: implement running title toggle
|
// TODO: implement running title toggle
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -395,26 +331,12 @@ const syncFromStore = () => {
|
||||||
pageFormat.value = sizeMatch[1];
|
pageFormat.value = sizeMatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
const marginMatch = pageBlock.match(
|
const marginMatch = pageBlock.match(/margin:\s*([0-9.]+)([a-z]+)\s+([0-9.]+)([a-z]+)\s+([0-9.]+)([a-z]+)\s+([0-9.]+)([a-z]+)/i);
|
||||||
/margin:\s*([0-9.]+)([a-z]+)\s+([0-9.]+)([a-z]+)\s+([0-9.]+)([a-z]+)\s+([0-9.]+)([a-z]+)/i
|
|
||||||
);
|
|
||||||
if (marginMatch) {
|
if (marginMatch) {
|
||||||
margins.value.top = {
|
margins.value.top = { value: parseFloat(marginMatch[1]), unit: marginMatch[2] };
|
||||||
value: parseFloat(marginMatch[1]),
|
margins.value.right = { value: parseFloat(marginMatch[3]), unit: marginMatch[4] };
|
||||||
unit: marginMatch[2],
|
margins.value.bottom = { value: parseFloat(marginMatch[5]), unit: marginMatch[6] };
|
||||||
};
|
margins.value.left = { value: parseFloat(marginMatch[7]), unit: marginMatch[8] };
|
||||||
margins.value.right = {
|
|
||||||
value: parseFloat(marginMatch[3]),
|
|
||||||
unit: marginMatch[4],
|
|
||||||
};
|
|
||||||
margins.value.bottom = {
|
|
||||||
value: parseFloat(marginMatch[5]),
|
|
||||||
unit: marginMatch[6],
|
|
||||||
};
|
|
||||||
margins.value.left = {
|
|
||||||
value: parseFloat(marginMatch[7]),
|
|
||||||
unit: marginMatch[8],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bgMatch = pageBlock.match(/background:\s*([^;]+)/);
|
const bgMatch = pageBlock.match(/background:\s*([^;]+)/);
|
||||||
|
|
@ -426,67 +348,13 @@ const syncFromStore = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(() => stylesheetStore.content, () => {
|
||||||
() => stylesheetStore.content,
|
if (!isUpdatingFromStore) {
|
||||||
() => {
|
syncFromStore();
|
||||||
if (!isUpdatingFromStore) {
|
|
||||||
syncFromStore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateColorisButton = () => {
|
|
||||||
const input = backgroundColorInput.value;
|
|
||||||
if (input && background.value.value) {
|
|
||||||
// Force Coloris to update by triggering a change event
|
|
||||||
const event = new Event('input', { bubbles: true });
|
|
||||||
input.dispatchEvent(event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Watch for when the user returns to the "document" tab
|
|
||||||
watch(activeTab, (newTab, oldTab) => {
|
|
||||||
if (newTab === 'document' && oldTab !== 'document' && background.value.value) {
|
|
||||||
// Small delay to ensure DOM is ready
|
|
||||||
setTimeout(updateColorisButton, 100);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
syncFromStore();
|
syncFromStore();
|
||||||
|
|
||||||
// Initialize Coloris
|
|
||||||
Coloris.init();
|
|
||||||
Coloris({
|
|
||||||
el: '[data-coloris]',
|
|
||||||
theme: 'pill',
|
|
||||||
themeMode: 'dark',
|
|
||||||
formatToggle: true,
|
|
||||||
alpha: true,
|
|
||||||
closeButton: true,
|
|
||||||
closeLabel: 'Fermer',
|
|
||||||
clearButton: true,
|
|
||||||
clearLabel: 'Effacer',
|
|
||||||
swatchesOnly: false,
|
|
||||||
inline: false,
|
|
||||||
wrap: true,
|
|
||||||
swatches: [
|
|
||||||
'#264653',
|
|
||||||
'#2a9d8f',
|
|
||||||
'#e9c46a',
|
|
||||||
'#f4a261',
|
|
||||||
'#e76f51',
|
|
||||||
'#d62828',
|
|
||||||
'#023e8a',
|
|
||||||
'#0077b6',
|
|
||||||
'#ffffff',
|
|
||||||
'#000000',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize button color if value exists
|
|
||||||
if (background.value.value) {
|
|
||||||
setTimeout(updateColorisButton, 100);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
<section class="settings-section">
|
<section class="settings-section">
|
||||||
<h2>Réglage du texte</h2>
|
<h2>Réglage du texte</h2>
|
||||||
<p class="infos">
|
<p class="infos">
|
||||||
Ces réglages s'appliquent à l'ensemble des éléments du document. Vous
|
Ces réglages s'appliquent à l'ensemble des éléments du document.
|
||||||
pouvez modifier ensuite les éléments indépendamment.
|
Vous pouvez modifier ensuite les éléments indépendamment.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|
@ -17,7 +17,11 @@
|
||||||
<option value="Times New Roman">Times New Roman</option>
|
<option value="Times New Roman">Times New Roman</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="field-checkbox">
|
<div class="field-checkbox">
|
||||||
<input id="text-italic" type="checkbox" v-model="italic" />
|
<input
|
||||||
|
id="text-italic"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="italic"
|
||||||
|
/>
|
||||||
<label for="text-italic">Italique</label>
|
<label for="text-italic">Italique</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -80,7 +84,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="text-size-range">Taille du texte</label>
|
<label for="text-size-range">Taille du texte</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="text-size-range"
|
id="text-size-range"
|
||||||
type="range"
|
type="range"
|
||||||
|
|
@ -136,7 +140,11 @@
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="text-color">Couleur</label>
|
<label for="text-color">Couleur</label>
|
||||||
<div class="field-with-color">
|
<div class="field-with-color">
|
||||||
<input type="color" v-model="color.picker" class="color-picker" />
|
<input
|
||||||
|
type="color"
|
||||||
|
v-model="color.picker"
|
||||||
|
class="color-picker"
|
||||||
|
/>
|
||||||
<input
|
<input
|
||||||
id="text-color"
|
id="text-color"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -220,7 +228,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer">Marges extérieures</label>
|
<label for="margin-outer">Marges extérieures</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer"
|
id="margin-outer"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -258,7 +266,7 @@
|
||||||
<div v-if="marginOuterExpanded" class="subsection collapsed-section">
|
<div v-if="marginOuterExpanded" class="subsection collapsed-section">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-top">Haut</label>
|
<label for="margin-outer-top">Haut</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-top"
|
id="margin-outer-top"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -286,7 +294,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-bottom">Bas</label>
|
<label for="margin-outer-bottom">Bas</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-bottom"
|
id="margin-outer-bottom"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -314,7 +322,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-left">Gauche</label>
|
<label for="margin-outer-left">Gauche</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-left"
|
id="margin-outer-left"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -342,7 +350,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-right">Droite</label>
|
<label for="margin-outer-right">Droite</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-right"
|
id="margin-outer-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -371,7 +379,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner">Marges intérieures</label>
|
<label for="margin-inner">Marges intérieures</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner"
|
id="margin-inner"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -409,7 +417,7 @@
|
||||||
<div v-if="marginInnerExpanded" class="subsection collapsed-section">
|
<div v-if="marginInnerExpanded" class="subsection collapsed-section">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-top">Haut</label>
|
<label for="margin-inner-top">Haut</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-top"
|
id="margin-inner-top"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -437,7 +445,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-bottom">Bas</label>
|
<label for="margin-inner-bottom">Bas</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-bottom"
|
id="margin-inner-bottom"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -465,7 +473,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-left">Gauche</label>
|
<label for="margin-inner-left">Gauche</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-left"
|
id="margin-inner-left"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -493,7 +501,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-right">Droite</label>
|
<label for="margin-inner-right">Droite</label>
|
||||||
<div class="input-with-unit">
|
<div class="field-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-right"
|
id="margin-inner-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -523,22 +531,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useStylesheetStore } from '../../stores/stylesheet';
|
|
||||||
|
|
||||||
const stylesheetStore = useStylesheetStore();
|
|
||||||
|
|
||||||
let isUpdatingFromStore = false;
|
|
||||||
let updateTimer = null;
|
|
||||||
|
|
||||||
const debouncedUpdate = (callback) => {
|
|
||||||
clearTimeout(updateTimer);
|
|
||||||
updateTimer = setTimeout(callback, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
const immediateUpdate = (callback) => {
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Font
|
// Font
|
||||||
const font = ref('Alegreya Sans');
|
const font = ref('Alegreya Sans');
|
||||||
|
|
@ -550,7 +543,7 @@ const weight = ref('400');
|
||||||
// Font size
|
// Font size
|
||||||
const fontSize = ref({
|
const fontSize = ref({
|
||||||
value: 23,
|
value: 23,
|
||||||
unit: 'px',
|
unit: 'px'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Alignment
|
// Alignment
|
||||||
|
|
@ -560,7 +553,7 @@ const alignment = ref('left');
|
||||||
const color = ref({
|
const color = ref({
|
||||||
picker: '#000000',
|
picker: '#000000',
|
||||||
value: 'rgb(250, 250, 250)',
|
value: 'rgb(250, 250, 250)',
|
||||||
format: 'rgb',
|
format: 'rgb'
|
||||||
});
|
});
|
||||||
|
|
||||||
const clearColor = () => {
|
const clearColor = () => {
|
||||||
|
|
@ -572,7 +565,7 @@ const clearColor = () => {
|
||||||
const background = ref({
|
const background = ref({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
value: 'transparent',
|
value: 'transparent',
|
||||||
format: 'hex',
|
format: 'hex'
|
||||||
});
|
});
|
||||||
|
|
||||||
const clearBackground = () => {
|
const clearBackground = () => {
|
||||||
|
|
@ -582,7 +575,7 @@ const clearBackground = () => {
|
||||||
// Margin outer
|
// Margin outer
|
||||||
const marginOuter = ref({
|
const marginOuter = ref({
|
||||||
value: 23,
|
value: 23,
|
||||||
unit: 'mm',
|
unit: 'mm'
|
||||||
});
|
});
|
||||||
|
|
||||||
const marginOuterExpanded = ref(false);
|
const marginOuterExpanded = ref(false);
|
||||||
|
|
@ -591,13 +584,13 @@ const marginOuterDetailed = ref({
|
||||||
top: { value: 23, unit: 'mm' },
|
top: { value: 23, unit: 'mm' },
|
||||||
bottom: { value: 23, unit: 'mm' },
|
bottom: { value: 23, unit: 'mm' },
|
||||||
left: { value: 23, unit: 'mm' },
|
left: { value: 23, unit: 'mm' },
|
||||||
right: { value: 23, unit: 'mm' },
|
right: { value: 23, unit: 'mm' }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Margin inner
|
// Margin inner
|
||||||
const marginInner = ref({
|
const marginInner = ref({
|
||||||
value: 23,
|
value: 23,
|
||||||
unit: 'mm',
|
unit: 'mm'
|
||||||
});
|
});
|
||||||
|
|
||||||
const marginInnerExpanded = ref(false);
|
const marginInnerExpanded = ref(false);
|
||||||
|
|
@ -606,202 +599,6 @@ const marginInnerDetailed = ref({
|
||||||
top: { value: 23, unit: 'mm' },
|
top: { value: 23, unit: 'mm' },
|
||||||
bottom: { value: 23, unit: 'mm' },
|
bottom: { value: 23, unit: 'mm' },
|
||||||
left: { value: 23, unit: 'mm' },
|
left: { value: 23, unit: 'mm' },
|
||||||
right: { value: 23, unit: 'mm' },
|
right: { value: 23, unit: 'mm' }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Watchers - Immediate updates for select/buttons/checkboxes
|
|
||||||
watch(font, () => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement font update
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(italic, () => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement italic update
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(weight, () => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement weight update
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(alignment, () => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement alignment update
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Font size - debounced for value, immediate for unit
|
|
||||||
watch(
|
|
||||||
() => fontSize.value.value,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement font size update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => fontSize.value.unit,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement font size update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Color - debounced for text value, immediate for format and picker
|
|
||||||
watch(
|
|
||||||
() => color.value.value,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement color update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => [color.value.format, color.value.picker],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement color update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Background - debounced for value, immediate for format and enabled
|
|
||||||
watch(
|
|
||||||
() => background.value.value,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement background update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => [background.value.format, background.value.enabled],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement background update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Margin outer - debounced for value, immediate for unit
|
|
||||||
watch(
|
|
||||||
() => marginOuter.value.value,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement margin outer update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => marginOuter.value.unit,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement margin outer update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Margin outer detailed - debounced for values, immediate for units
|
|
||||||
watch(
|
|
||||||
() => [
|
|
||||||
marginOuterDetailed.value.top.value,
|
|
||||||
marginOuterDetailed.value.bottom.value,
|
|
||||||
marginOuterDetailed.value.left.value,
|
|
||||||
marginOuterDetailed.value.right.value,
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement margin outer detailed update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => [
|
|
||||||
marginOuterDetailed.value.top.unit,
|
|
||||||
marginOuterDetailed.value.bottom.unit,
|
|
||||||
marginOuterDetailed.value.left.unit,
|
|
||||||
marginOuterDetailed.value.right.unit,
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement margin outer detailed update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Margin inner - debounced for value, immediate for unit
|
|
||||||
watch(
|
|
||||||
() => marginInner.value.value,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement margin inner update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => marginInner.value.unit,
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement margin inner update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Margin inner detailed - debounced for values, immediate for units
|
|
||||||
watch(
|
|
||||||
() => [
|
|
||||||
marginInnerDetailed.value.top.value,
|
|
||||||
marginInnerDetailed.value.bottom.value,
|
|
||||||
marginInnerDetailed.value.left.value,
|
|
||||||
marginInnerDetailed.value.right.value,
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
// TODO: implement margin inner detailed update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => [
|
|
||||||
marginInnerDetailed.value.top.unit,
|
|
||||||
marginInnerDetailed.value.bottom.unit,
|
|
||||||
marginInnerDetailed.value.left.unit,
|
|
||||||
marginInnerDetailed.value.right.unit,
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
if (isUpdatingFromStore) return;
|
|
||||||
immediateUpdate(() => {
|
|
||||||
// TODO: implement margin inner detailed update
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
@import url('/assets/css/style.css');
|
@import url('/assets/css/pagedjs-interface.css');
|
||||||
|
@import url('/assets/css/editor-ui.css');
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue