Compare commits
4 commits
960f509d5c
...
9af36fb422
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9af36fb422 | ||
|
|
467ae905bd | ||
|
|
7ed57d000b | ||
|
|
19077fb133 |
19 changed files with 851 additions and 209 deletions
7
package-lock.json
generated
7
package-lock.json
generated
|
|
@ -8,6 +8,7 @@
|
||||||
"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",
|
||||||
|
|
@ -532,6 +533,12 @@
|
||||||
"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,6 +9,7 @@
|
||||||
"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 +0,0 @@
|
||||||
|
|
||||||
21
public/assets/css/src/_buttons.scss
Normal file
21
public/assets/css/src/_buttons.scss
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
public/assets/css/src/_forms.scss
Normal file
72
public/assets/css/src/_forms.scss
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
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%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
public/assets/css/src/_reset.scss
Normal file
27
public/assets/css/src/_reset.scss
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
15
public/assets/css/src/_text.scss
Normal file
15
public/assets/css/src/_text.scss
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
body,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
p,
|
||||||
|
a,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
figcaption,
|
||||||
|
label {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
8
public/assets/css/src/_variables.scss
Normal file
8
public/assets/css/src/_variables.scss
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
:root {
|
||||||
|
--color-panel-bg: #e8e6e5;
|
||||||
|
--color-browngray-050: #f5f3f0;
|
||||||
|
--color-browngray-200: #d0c4ba;
|
||||||
|
--color-browngray-300: #b5a9a1;
|
||||||
|
|
||||||
|
--border-radius: 0.2rem;
|
||||||
|
}
|
||||||
145
public/assets/css/style.css
Normal file
145
public/assets/css/style.css
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
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
public/assets/css/style.css.map
Normal file
1
public/assets/css/style.css.map
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"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"}
|
||||||
6
public/assets/css/style.scss
Normal file
6
public/assets/css/style.scss
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
@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/pagedjs-interface.css') ?>">
|
<link rel="stylesheet" href="<?= url('assets/css/style..css') ?>">
|
||||||
<link rel="stylesheet" href="<?= url('assets/stylesheet.css') ?>">
|
<link rel="stylesheet" href="<?= url('assets/css/pagedjs-interface.css') ?>">
|
||||||
|
|
||||||
<!-- À SUPPRIMER EN PRODUCTION -->
|
<!-- À SUPPRIMER EN PRODUCTION -->
|
||||||
<meta name="robots" content="noindex, nofollow, noarchive">
|
<meta name="robots" content="noindex, nofollow, noarchive">
|
||||||
|
|
|
||||||
19
src/App.vue
19
src/App.vue
|
|
@ -1,7 +1,6 @@
|
||||||
<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';
|
||||||
|
|
@ -42,7 +41,10 @@ const renderPreview = async (shouldReloadFromFile = false) => {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
iframe.onload = () => {
|
iframe.onload = () => {
|
||||||
iframe.contentDocument.addEventListener('click', elementPopup.value.handleIframeClick);
|
iframe.contentDocument.addEventListener(
|
||||||
|
'click',
|
||||||
|
elementPopup.value.handleIframeClick
|
||||||
|
);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const scrollHeight = iframe.contentDocument.documentElement.scrollHeight;
|
const scrollHeight = iframe.contentDocument.documentElement.scrollHeight;
|
||||||
|
|
@ -55,9 +57,12 @@ const renderPreview = async (shouldReloadFromFile = false) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => stylesheetStore.content, () => {
|
watch(
|
||||||
|
() => stylesheetStore.content,
|
||||||
|
() => {
|
||||||
renderPreview();
|
renderPreview();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(() => renderPreview(true));
|
onMounted(() => renderPreview(true));
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -71,8 +76,6 @@ 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>
|
||||||
|
|
||||||
|
|
@ -80,8 +83,8 @@ onMounted(() => renderPreview(true));
|
||||||
#preview-frame {
|
#preview-frame {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 250px;
|
left: 0;
|
||||||
width: calc(100% - 600px);
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<aside id="stylesheet-viewer">
|
<div 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>
|
||||||
</aside>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
@ -53,14 +53,9 @@ const handleInput = (event) => {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#stylesheet-viewer {
|
#stylesheet-viewer {
|
||||||
position: fixed;
|
display: flex;
|
||||||
top: 0;
|
flex-direction: column;
|
||||||
right: 0;
|
height: 100%;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +125,7 @@ h3 {
|
||||||
|
|
||||||
.readonly {
|
.readonly {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: calc(100vh - 5rem);
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
|
|
@ -145,7 +140,7 @@ h3 {
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 5rem);
|
flex: 1;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
color: #abb2bf;
|
color: #abb2bf;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<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'"
|
||||||
>
|
>
|
||||||
|
|
@ -10,6 +11,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="tab"
|
||||||
:class="{ active: activeTab === 'code' }"
|
:class="{ active: activeTab === 'code' }"
|
||||||
@click="activeTab = 'code'"
|
@click="activeTab = 'code'"
|
||||||
>
|
>
|
||||||
|
|
@ -17,6 +19,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="tab"
|
||||||
:class="{ active: activeTab === 'contenu' }"
|
:class="{ active: activeTab === 'contenu' }"
|
||||||
@click="activeTab = 'contenu'"
|
@click="activeTab = 'contenu'"
|
||||||
>
|
>
|
||||||
|
|
@ -31,7 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'code'" class="tab-panel">
|
<div v-else-if="activeTab === 'code'" class="tab-panel">
|
||||||
<!-- Code tab content -->
|
<StylesheetViewer />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'contenu'" class="tab-panel">
|
<div v-else-if="activeTab === 'contenu'" class="tab-panel">
|
||||||
|
|
@ -42,43 +45,48 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, provide } 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 scoped>
|
<style lang="scss" scoped>
|
||||||
#editor-panel {
|
#editor-panel {
|
||||||
|
padding: 1rem;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 250px;
|
width: 30rem;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: #f5f5f5;
|
display: flex;
|
||||||
padding: 1rem;
|
flex-direction: column;
|
||||||
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
|
z-index: 2;
|
||||||
|
|
||||||
|
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,6 +2,7 @@
|
||||||
<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">
|
||||||
|
|
@ -12,33 +13,38 @@
|
||||||
<option value="legal">Legal</option>
|
<option value="legal">Legal</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="settings-subsection">
|
||||||
|
<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>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field field--view-only">
|
||||||
<label for="page-height">Hauteur</label>
|
<label for="page-height">Hauteur</label>
|
||||||
<input
|
<input
|
||||||
id="page-height"
|
id="page-height"
|
||||||
type="text"
|
type="number"
|
||||||
:value="pageHeight"
|
:value="parseInt(pageHeight)"
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
|
<button type="button" disabled>mm</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="subsection">
|
<div class="settings-subsection margins">
|
||||||
<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="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-top"
|
id="margin-top"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -66,7 +72,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-bottom">Bas</label>
|
<label for="margin-bottom">Bas</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-bottom"
|
id="margin-bottom"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -94,7 +100,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-left">Gauche</label>
|
<label for="margin-left">Gauche</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-left"
|
id="margin-left"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -122,7 +128,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-right">Droite</label>
|
<label for="margin-right">Droite</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-right"
|
id="margin-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -149,14 +155,18 @@
|
||||||
</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"
|
||||||
|
id="background"
|
||||||
v-model="background.value"
|
v-model="background.value"
|
||||||
|
data-coloris
|
||||||
/>
|
/>
|
||||||
|
<!-- Temporarily commented out
|
||||||
<div class="unit-toggle">
|
<div class="unit-toggle">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -173,9 +183,12 @@
|
||||||
hex
|
hex
|
||||||
</button>
|
</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">
|
||||||
|
|
@ -185,32 +198,31 @@
|
||||||
<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"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="pageNumbers"
|
|
||||||
/>
|
|
||||||
<label for="page-numbers">Numéro de page</label>
|
<label for="page-numbers">Numéro de page</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field checkbox-field">
|
<div class="field checkbox-field">
|
||||||
<input
|
<input id="running-title" type="checkbox" v-model="runningTitle" />
|
||||||
id="running-title"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="runningTitle"
|
|
||||||
/>
|
|
||||||
<label for="running-title">Titre courant</label>
|
<label for="running-title">Titre courant</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onMounted } from 'vue';
|
import { ref, computed, watch, onMounted, inject } 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;
|
||||||
|
|
@ -222,7 +234,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);
|
||||||
|
|
@ -232,12 +244,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('');
|
||||||
|
|
@ -249,19 +261,20 @@ 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;
|
||||||
|
|
||||||
debouncedUpdate(() => {
|
immediateUpdate(() => {
|
||||||
stylesheetStore.updateProperty('@page', 'size', newFormat, '');
|
stylesheetStore.updateProperty('@page', 'size', newFormat, '');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(margins, (newMargins) => {
|
const updateMargins = () => {
|
||||||
if (isUpdatingFromStore) return;
|
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}`;
|
||||||
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
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}`;
|
|
||||||
|
|
||||||
const currentBlock = stylesheetStore.extractBlock('@page');
|
const currentBlock = stylesheetStore.extractBlock('@page');
|
||||||
const updatedBlock = currentBlock.replace(
|
const updatedBlock = currentBlock.replace(
|
||||||
|
|
@ -269,37 +282,88 @@ watch(margins, (newMargins) => {
|
||||||
`$1${marginValue}`
|
`$1${marginValue}`
|
||||||
);
|
);
|
||||||
|
|
||||||
stylesheetStore.content = stylesheetStore.content.replace(currentBlock, updatedBlock);
|
stylesheetStore.content = stylesheetStore.content.replace(
|
||||||
});
|
currentBlock,
|
||||||
}, { deep: true });
|
updatedBlock
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
watch(background, (newBg) => {
|
// Watch margin values (number inputs) with debounce
|
||||||
if (!newBg.value) return;
|
watch(
|
||||||
|
() => [
|
||||||
|
margins.value.top.value,
|
||||||
|
margins.value.bottom.value,
|
||||||
|
margins.value.left.value,
|
||||||
|
margins.value.right.value,
|
||||||
|
],
|
||||||
|
() => {
|
||||||
if (isUpdatingFromStore) return;
|
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;
|
||||||
|
|
||||||
debouncedUpdate(() => {
|
|
||||||
const currentBlock = stylesheetStore.extractBlock('@page');
|
const currentBlock = stylesheetStore.extractBlock('@page');
|
||||||
|
|
||||||
if (currentBlock.includes('background:')) {
|
if (currentBlock.includes('background:')) {
|
||||||
const updatedBlock = currentBlock.replace(
|
const updatedBlock = currentBlock.replace(
|
||||||
/(background:\s*)[^;]+/,
|
/(background:\s*)[^;]+/,
|
||||||
`$1${newBg.value}`
|
`$1${background.value.value}`
|
||||||
|
);
|
||||||
|
stylesheetStore.content = stylesheetStore.content.replace(
|
||||||
|
currentBlock,
|
||||||
|
updatedBlock
|
||||||
);
|
);
|
||||||
stylesheetStore.content = stylesheetStore.content.replace(currentBlock, updatedBlock);
|
|
||||||
} else {
|
} else {
|
||||||
const updatedBlock = currentBlock.replace(
|
const updatedBlock = currentBlock.replace(
|
||||||
/(\s*})$/,
|
/(\s*})$/,
|
||||||
` background: ${newBg.value};\n$1`
|
` background: ${background.value.value};\n$1`
|
||||||
|
);
|
||||||
|
stylesheetStore.content = stylesheetStore.content.replace(
|
||||||
|
currentBlock,
|
||||||
|
updatedBlock
|
||||||
);
|
);
|
||||||
stylesheetStore.content = stylesheetStore.content.replace(currentBlock, updatedBlock);
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}, { deep: true });
|
|
||||||
|
// Watch background value (text input) with debounce
|
||||||
|
watch(
|
||||||
|
() => background.value.value,
|
||||||
|
() => {
|
||||||
|
if (isUpdatingFromStore) return;
|
||||||
|
debouncedUpdate(updateBackground);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Watch background format (button clicks) without debounce
|
||||||
|
watch(
|
||||||
|
() => background.value.format,
|
||||||
|
() => {
|
||||||
|
if (isUpdatingFromStore) return;
|
||||||
|
immediateUpdate(updateBackground);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(pattern, (newPattern) => {
|
watch(pattern, (newPattern) => {
|
||||||
if (!newPattern || isUpdatingFromStore) return;
|
if (!newPattern || isUpdatingFromStore) return;
|
||||||
|
|
||||||
debouncedUpdate(() => {
|
immediateUpdate(() => {
|
||||||
// TODO: implement pattern application
|
// TODO: implement pattern application
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -307,7 +371,7 @@ watch(pattern, (newPattern) => {
|
||||||
watch(pageNumbers, (enabled) => {
|
watch(pageNumbers, (enabled) => {
|
||||||
if (isUpdatingFromStore) return;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
debouncedUpdate(() => {
|
immediateUpdate(() => {
|
||||||
// TODO: implement page numbers toggle
|
// TODO: implement page numbers toggle
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -315,7 +379,7 @@ watch(pageNumbers, (enabled) => {
|
||||||
watch(runningTitle, (enabled) => {
|
watch(runningTitle, (enabled) => {
|
||||||
if (isUpdatingFromStore) return;
|
if (isUpdatingFromStore) return;
|
||||||
|
|
||||||
debouncedUpdate(() => {
|
immediateUpdate(() => {
|
||||||
// TODO: implement running title toggle
|
// TODO: implement running title toggle
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -331,12 +395,26 @@ const syncFromStore = () => {
|
||||||
pageFormat.value = sizeMatch[1];
|
pageFormat.value = sizeMatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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
|
||||||
|
);
|
||||||
if (marginMatch) {
|
if (marginMatch) {
|
||||||
margins.value.top = { value: parseFloat(marginMatch[1]), unit: marginMatch[2] };
|
margins.value.top = {
|
||||||
margins.value.right = { value: parseFloat(marginMatch[3]), unit: marginMatch[4] };
|
value: parseFloat(marginMatch[1]),
|
||||||
margins.value.bottom = { value: parseFloat(marginMatch[5]), unit: marginMatch[6] };
|
unit: marginMatch[2],
|
||||||
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*([^;]+)/);
|
||||||
|
|
@ -348,13 +426,67 @@ const syncFromStore = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => stylesheetStore.content, () => {
|
watch(
|
||||||
|
() => stylesheetStore.content,
|
||||||
|
() => {
|
||||||
if (!isUpdatingFromStore) {
|
if (!isUpdatingFromStore) {
|
||||||
syncFromStore();
|
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.
|
Ces réglages s'appliquent à l'ensemble des éléments du document. Vous
|
||||||
Vous pouvez modifier ensuite les éléments indépendamment.
|
pouvez modifier ensuite les éléments indépendamment.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|
@ -17,11 +17,7 @@
|
||||||
<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
|
<input id="text-italic" type="checkbox" v-model="italic" />
|
||||||
id="text-italic"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="italic"
|
|
||||||
/>
|
|
||||||
<label for="text-italic">Italique</label>
|
<label for="text-italic">Italique</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -84,7 +80,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="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="text-size-range"
|
id="text-size-range"
|
||||||
type="range"
|
type="range"
|
||||||
|
|
@ -140,11 +136,7 @@
|
||||||
<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
|
<input type="color" v-model="color.picker" class="color-picker" />
|
||||||
type="color"
|
|
||||||
v-model="color.picker"
|
|
||||||
class="color-picker"
|
|
||||||
/>
|
|
||||||
<input
|
<input
|
||||||
id="text-color"
|
id="text-color"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -228,7 +220,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="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer"
|
id="margin-outer"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -266,7 +258,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="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-top"
|
id="margin-outer-top"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -294,7 +286,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-bottom">Bas</label>
|
<label for="margin-outer-bottom">Bas</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-bottom"
|
id="margin-outer-bottom"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -322,7 +314,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-left">Gauche</label>
|
<label for="margin-outer-left">Gauche</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-left"
|
id="margin-outer-left"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -350,7 +342,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-outer-right">Droite</label>
|
<label for="margin-outer-right">Droite</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-outer-right"
|
id="margin-outer-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -379,7 +371,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="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner"
|
id="margin-inner"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -417,7 +409,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="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-top"
|
id="margin-inner-top"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -445,7 +437,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-bottom">Bas</label>
|
<label for="margin-inner-bottom">Bas</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-bottom"
|
id="margin-inner-bottom"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -473,7 +465,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-left">Gauche</label>
|
<label for="margin-inner-left">Gauche</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-left"
|
id="margin-inner-left"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -501,7 +493,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="margin-inner-right">Droite</label>
|
<label for="margin-inner-right">Droite</label>
|
||||||
<div class="field-with-unit">
|
<div class="input-with-unit">
|
||||||
<input
|
<input
|
||||||
id="margin-inner-right"
|
id="margin-inner-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -531,7 +523,22 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, watch } 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');
|
||||||
|
|
@ -543,7 +550,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
|
||||||
|
|
@ -553,7 +560,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 = () => {
|
||||||
|
|
@ -565,7 +572,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 = () => {
|
||||||
|
|
@ -575,7 +582,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);
|
||||||
|
|
@ -584,13 +591,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);
|
||||||
|
|
@ -599,6 +606,202 @@ 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,2 +1 @@
|
||||||
@import url('/assets/css/pagedjs-interface.css');
|
@import url('/assets/css/style.css');
|
||||||
@import url('/assets/css/editor-ui.css');
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue