Compare commits

...
Sign in to create a new pull request.

9 commits
main ... styles

Author SHA1 Message Date
Julie Blanc
b99ff90cab add position num/running 2025-12-10 17:48:10 +01:00
Julie Blanc
e279941168 styles infos 2025-12-10 17:26:12 +01:00
Julie Blanc
cb7a43d564 checkbox 2025-12-10 17:02:44 +01:00
Julie Blanc
46eaf01111 styles infos 2025-12-10 16:45:13 +01:00
Julie Blanc
202b7aeab4 sliders personnalisés 2025-12-10 16:24:58 +01:00
Julie Blanc
68343a52f5 add line height value + gestion passage px/em 2025-12-10 16:01:36 +01:00
Julie Blanc
7f3aff948b change colors 2025-12-10 15:18:12 +01:00
Julie Blanc
a42f5e48ca popup style 2025-12-10 13:48:45 +01:00
Julie Blanc
d88758b226 filed font-size 2025-12-10 13:29:14 +01:00
21 changed files with 686 additions and 303 deletions

View file

@ -1,5 +1,5 @@
.unit-toggle{
.field{
button:not(.spinner-btn) {
cursor: pointer;

View file

@ -1,28 +1,46 @@
.settings-section {
margin-top: 3em;
// .cons
margin: var(--space-m) 0;
h2 {
margin-bottom: var(--space);
font-weight: 600;
font-size: 1.4rem;
border-bottom: 1px solid var(--color-200);
color: var(--color-800);
}
.infos{
font-size: 0.8rem;
color: var(--color-interface-400);
position: relative;
padding-left: 2.5ch;
.info-icon{
position: absolute;
left: 0px;
top: -5px;
svg{
width: 16px;
fill: var(--color-interface-400);
}
}
p{
font-size: 0.8rem;
color: var(--color-interface-400);
}
}
.settings-subsection:not(:last-child) {
.container{
margin-top: var(--space-xs);
}
}
.settings-subsection {
border-bottom: 1px solid var(--color-interface-100);
}
@ -34,10 +52,6 @@
margin-bottom: calc(var(--space-xs)*2);
font-size: 1rem;
font-weight: 600;
color: var(--color-800);
}
}
}
}

View file

@ -5,29 +5,134 @@ input[type="number"] {
border: 1px solid var(--color-interface-200);
background-color: var(--color-interface-100);
font-family: var(--sans-serif);
color: var(--color-txt);
font-size: 1rem;
// min-width: var(--input-w);
// width: 100%;
// padding: 0 1ch;
padding-left: 0.5ch;
&:focus{
border-color: var(--color-interface-400);
}
}
/// RANGE---------------------------------------------------------------------------------
input[type="range"]{
-webkit-appearance: none;
background: transparent;
}
@mixin thumb(){
border: 2px solid var(--color-panel-bg);
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--color-interface-500);
position: relative;
top: -6px;
cursor: pointer;
}
@mixin track(){
width: 100%;
height: 4px;
cursor: pointer;
background: var(--color-interface-200);
border-radius: 2px;
}
/* WebKit/Blink */
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
@include thumb();
}
input[type=range]::-webkit-slider-runnable-track {
@include track();
}
/* Firefox */
input[type=range]::-moz-range-thumb {
@include thumb();
}
input[type=range]::-moz-range-track{
@include track();
}
/* IE */
input[type=range]::-ms-thumb {
@include thumb();
}
input[type=range]::-ms-track{
background: transparent;
border-color: transparent;
color: transparent;
@include track();
}
// Checkbox ===============================================
input[type="checkbox"]{
display: none;
}
input[type="checkbox"] + label{
position: relative;
padding-left: 24px;
}
input[type="checkbox"] + label::before{
content: "";
font-size: 11px;
padding-bottom: 3px;
padding-left: 3px;
--size: 11px;
width: var(--size);
height: var(--size);
border-radius: var(--border-radius);
display: block;
position: absolute;
top: 0px;
border: 1px solid var(--color-interface-400);
background-color: var(--color-interface-100);
color: transparent;
}
input[type="checkbox"]:checked + label::before{
background-color: var(--color-interface-600);
border-color: var(--color-interface-600);
color: var(--color-panel-bg);
}
// GENERALFIELD ===========================================
.field--view-only {
opacity: 0.3;
}
.field {
display: flex;
display: grid;
grid-template-columns: var(--label-w) 1fr;
label {
font-weight: 600;
color: var(--color-800);
align-self: center;
}
.input-with-unit {
.input-with-range {
display: flex;
gap: 0.3rem;
}
.unit-toggle {
@ -59,13 +164,8 @@ input[type="number"] {
}
.field{
display: grid;
grid-template-columns: var(--label-w) 1fr;
label{
align-self: center;
}
}
.field-font{
display: grid;
@ -75,15 +175,29 @@ input[type="number"] {
select{
width: 100%;
}
.field-checkbox{
.checkbox-field{
grid-column: 2;
padding-top: var(--space-xs);
margin: 0;
label{
font-weight: 400;
margin-left: 0.75ch;
color: var(--color-txt);
text-decoration-color: var(--color-interface-300)!important;
}
}
}
.field-text-size{
input[type="number"]{
width: var(--input-w-small);
padding-left: 0.75ch;
}
input[type="range"]{
flex-grow: 2;
flex-shrink: 2;
}
}
.field-margin, .field-size{
display: inline-grid;
width: calc(50% - 1ch);
@ -97,28 +211,40 @@ input[type="number"] {
margin-right: 2ch;
}
}
.checkbox-field{
margin: calc(var(--space-xs)*2) 0;
grid-template-columns: 3ch 1fr;
input{
justify-self: left;
margin: 0;
.margins label{
color: var(--color-txt);
font-weight: normal;
text-decoration-color: var(--color-interface-300)!important;
}
.field-generated-content{
.positions{
display: flex;
gap: 2em;
}
.group-position{
display: flex;
gap: 0.3em;
}
}
.field--view-only {
opacity: 0.3;
}
/* Label with CSS tooltip */
// TOOLTIP ===============================================
.label-with-tooltip {
text-decoration: underline dotted 1px var(--color-200);
text-decoration: underline dotted 1px var(--color-400);
text-underline-offset: 2px;
cursor: help;
position: relative;
@ -158,7 +284,6 @@ input[type="number"] {
// INPUTNUMBER ===============================================
// Masquer les spinners natifs partout
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
@ -173,7 +298,6 @@ input[type="number"] {
.number-input{
position: relative;
// padding: 0 1ch!important;
input{
padding-top: 0;
padding-bottom: 0;
@ -188,89 +312,18 @@ input[type="number"] {
top: 0;
button{
height: calc(var(--input-h)*0.6);
height: calc(var(--input-h)*0.5);
cursor: pointer;
padding: 0;
svg path{
fill: var(--color-interface-600);
}
&:hover{
svg path{
fill: var(--color-interface-900);
}
}
}
.spinner-down{
svg{
position: relative;
top: -2px;
width: 10px;
height: auto;
}
svg path{ fill: var(--color-interface-600); }
&:hover{
svg path{ fill: var(--color-interface-900); }
}
}
}
}
// Composant NumberInput avec boutons personnalisés
// .number-input {
// position: relative;
// display: flex;
// align-items: center;
// width: 100%;
// position: relative;
// input[type="number"] {
// width: 100%;
// box-sizing: border-box;
// }
// .spinner-buttons {
// background-color: red;
// position: absolute;
// right: 1px;
// top: 1px;
// bottom: 1px;
// display: flex;
// flex-direction: column;
// justify-content: center;
// gap: 1px;
// z-index: 10;
// .spinner-btn {
// display: flex;
// align-items: center;
// justify-content: center;
// width: 20px;
// height: 10px;
// padding: 0;
// margin: 0;
// background-color: var(--color-interface-200);
// border: 1px solid var(--color-interface-300);
// border-radius: 2px;
// cursor: pointer;
// transition: background-color 0.15s ease;
// color: var(--color-interface-700);
// line-height: 0;
// svg {
// width: 8px;
// height: 6px;
// display: block;
// }
// &:hover:not(:disabled) {
// background-color: var(--color-interface-300);
// color: var(--color-interface-900);
// }
// &:active:not(:disabled) {
// background-color: var(--color-interface-400);
// }
// &:disabled {
// opacity: 0.3;
// cursor: not-allowed;
// }
// }
// }
// }

View file

@ -6,7 +6,7 @@
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
z-index: 10000;
width: 71rem;
width: 860px;
max-height: 600px;
display: flex;
flex-direction: column;
@ -47,10 +47,7 @@
flex: 1;
padding: 1rem;
overflow-y: auto;
background: white;
display: flex;
flex-direction: column;
gap: 1rem;
background-color: var(--color-panel-bg);
}
.settings-subsection h4 {

View file

@ -9,7 +9,7 @@
--color-txt: var(--color-interface-800);
--color-txt: var(--color-interface-900);
--color-panel-bg: var(--color-interface-050);
--color-page-highlight: #ff8a50;
@ -20,6 +20,8 @@
--space-xs: 0.5rem;
--space-s: 1rem;
--space: 1.5rem;
--space-m: 2rem;
--space-big: 3em;
--curve: cubic-bezier(0.86, 0, 0.07, 1);
@ -34,4 +36,5 @@
font-size: 14px;
--panel-w: 540px;
--panel-nav-h: 60px;
}

View file

@ -1,3 +1,4 @@
@charset "UTF-8";
@font-face {
font-family: "DM Sans";
src: url("/assets/fonts/DMSans/DMSans[opsz,wght].woff2") format("woff2-variations");
@ -223,7 +224,7 @@ img {
:root {
--color-browngray-050: #f5f3f0;
--color-browngray-200: #d0c4ba;
--color-txt: var(--color-interface-800);
--color-txt: var(--color-interface-900);
--color-panel-bg: var(--color-interface-050);
--color-page-highlight: #ff8a50;
--color-purple: #7136ff;
@ -231,6 +232,8 @@ img {
--space-xs: 0.5rem;
--space-s: 1rem;
--space: 1.5rem;
--space-m: 2rem;
--space-big: 3em;
--curve: cubic-bezier(0.86, 0, 0.07, 1);
--sans-serif: "DM Sans", sans-serif;
--mono: "Inconsolata", monospace;
@ -240,6 +243,7 @@ img {
--label-w: 18ch;
font-size: 14px;
--panel-w: 540px;
--panel-nav-h: 60px;
}
body {
@ -273,17 +277,131 @@ input[type=number] {
border: 1px solid var(--color-interface-200);
background-color: var(--color-interface-100);
font-family: var(--sans-serif);
color: var(--color-txt);
font-size: 1rem;
padding-left: 0.5ch;
}
select:focus,
input[type=text]:focus,
input[type=number]:focus {
border-color: var(--color-interface-400);
}
input[type=range] {
-webkit-appearance: none;
background: transparent;
}
/* WebKit/Blink */
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
border: 2px solid var(--color-panel-bg);
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--color-interface-500);
position: relative;
top: -6px;
cursor: pointer;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: var(--color-interface-200);
border-radius: 2px;
}
/* Firefox */
input[type=range]::-moz-range-thumb {
border: 2px solid var(--color-panel-bg);
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--color-interface-500);
position: relative;
top: -6px;
cursor: pointer;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 4px;
cursor: pointer;
background: var(--color-interface-200);
border-radius: 2px;
}
/* IE */
input[type=range]::-ms-thumb {
border: 2px solid var(--color-panel-bg);
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--color-interface-500);
position: relative;
top: -6px;
cursor: pointer;
}
input[type=range]::-ms-track {
background: transparent;
border-color: transparent;
color: transparent;
width: 100%;
height: 4px;
cursor: pointer;
background: var(--color-interface-200);
border-radius: 2px;
}
input[type=checkbox] {
display: none;
}
input[type=checkbox] + label {
position: relative;
padding-left: 24px;
}
input[type=checkbox] + label::before {
content: "✔";
font-size: 11px;
padding-bottom: 3px;
padding-left: 3px;
--size: 11px;
width: var(--size);
height: var(--size);
border-radius: var(--border-radius);
display: block;
position: absolute;
top: 0px;
border: 1px solid var(--color-interface-400);
background-color: var(--color-interface-100);
color: transparent;
}
input[type=checkbox]:checked + label::before {
background-color: var(--color-interface-600);
border-color: var(--color-interface-600);
color: var(--color-panel-bg);
}
.field--view-only {
opacity: 0.3;
}
.field {
display: flex;
display: grid;
grid-template-columns: var(--label-w) 1fr;
}
.field label {
font-weight: 600;
color: var(--color-800);
align-self: center;
}
.field .input-with-unit {
.field .input-with-range {
display: flex;
gap: 0.3rem;
}
@ -311,14 +429,6 @@ input[type=number] {
grid-column: 2;
}
.field {
display: grid;
grid-template-columns: var(--label-w) 1fr;
}
.field label {
align-self: center;
}
.field-font {
display: grid;
grid-template-columns: var(--label-w) 1fr;
@ -327,12 +437,24 @@ input[type=number] {
.field-font select {
width: 100%;
}
.field-font .field-checkbox {
.field-font .checkbox-field {
grid-column: 2;
padding-top: var(--space-xs);
margin: 0;
}
.field-font .field-checkbox label {
.field-font .checkbox-field label {
font-weight: 400;
margin-left: 0.75ch;
color: var(--color-txt);
text-decoration-color: var(--color-interface-300) !important;
}
.field-text-size input[type=number] {
width: var(--input-w-small);
padding-left: 0.75ch;
}
.field-text-size input[type=range] {
flex-grow: 2;
flex-shrink: 2;
}
.field-margin, .field-size {
@ -349,23 +471,24 @@ input[type=number] {
margin-right: 2ch;
}
.checkbox-field {
margin: calc(var(--space-xs) * 2) 0;
grid-template-columns: 3ch 1fr;
}
.checkbox-field input {
justify-self: left;
margin: 0;
.margins label {
color: var(--color-txt);
font-weight: normal;
text-decoration-color: var(--color-interface-300) !important;
}
.field--view-only {
opacity: 0.3;
.field-generated-content .positions {
display: flex;
gap: 2em;
}
.field-generated-content .group-position {
display: flex;
gap: 0.3em;
}
/* Label with CSS tooltip */
.label-with-tooltip {
-webkit-text-decoration: underline dotted 1px var(--color-200);
text-decoration: underline dotted 1px var(--color-200);
-webkit-text-decoration: underline dotted 1px var(--color-400);
text-decoration: underline dotted 1px var(--color-400);
text-underline-offset: 2px;
cursor: help;
position: relative;
@ -421,49 +544,67 @@ input[type=number] {
top: 0;
}
.number-input .spinner-buttons button {
height: calc(var(--input-h) * 0.6);
height: calc(var(--input-h) * 0.5);
cursor: pointer;
padding: 0;
}
.number-input .spinner-buttons button svg {
width: 10px;
height: auto;
}
.number-input .spinner-buttons button svg path {
fill: var(--color-interface-600);
}
.number-input .spinner-buttons button:hover svg path {
fill: var(--color-interface-900);
}
.number-input .spinner-buttons .spinner-down svg {
position: relative;
top: -2px;
}
.settings-section {
margin-top: 3em;
margin: var(--space-m) 0;
}
.settings-section h2 {
margin-bottom: var(--space);
font-weight: 600;
font-size: 1.4rem;
border-bottom: 1px solid var(--color-200);
color: var(--color-800);
}
.settings-section .infos {
position: relative;
padding-left: 2.5ch;
}
.settings-section .infos .info-icon {
position: absolute;
left: 0px;
top: -5px;
}
.settings-section .infos .info-icon svg {
width: 16px;
fill: var(--color-interface-400);
}
.settings-section .infos p {
font-size: 0.8rem;
color: var(--color-interface-400);
}
.settings-section .settings-subsection:not(:last-child) {
.settings-section .container {
margin-top: var(--space-xs);
}
.settings-subsection {
border-bottom: 1px solid var(--color-interface-100);
}
.settings-section .settings-subsection {
.settings-subsection {
padding: var(--space-xs) 0;
}
.settings-section .settings-subsection h3 {
.settings-subsection h3 {
margin-top: calc(var(--space-xs) * 1.5);
margin-bottom: calc(var(--space-xs) * 2);
font-size: 1rem;
font-weight: 600;
color: var(--color-800);
}
.unit-toggle button:not(.spinner-btn) {
.field button:not(.spinner-btn) {
cursor: pointer;
border: 1px solid var(--color-interface-400);
color: var(--color-interface-400);
@ -472,10 +613,10 @@ input[type=number] {
padding: 0.1rem 0.3rem;
height: calc(var(--input-h) * 0.75);
}
.unit-toggle button:not(.spinner-btn):not(.active):hover {
.field button:not(.spinner-btn):not(.active):hover {
background-color: var(--color-interface-100);
}
.unit-toggle button:not(.spinner-btn).active {
.field button:not(.spinner-btn).active {
color: var(--color-interface-050);
background-color: var(--color-interface-500);
cursor: auto;
@ -508,7 +649,7 @@ input[type=number] {
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
z-index: 10000;
width: 71rem;
width: 860px;
max-height: 600px;
display: flex;
flex-direction: column;
@ -549,10 +690,7 @@ input[type=number] {
flex: 1;
padding: 1rem;
overflow-y: auto;
background: white;
display: flex;
flex-direction: column;
gap: 1rem;
background-color: var(--color-panel-bg);
}
.settings-subsection h4 {

File diff suppressed because one or more lines are too long

View file

@ -31,7 +31,7 @@ h2 {
}
p {
font-size: 1rem;
font-size: 16px;
margin: 0mm 0mm 5mm 0mm;
}

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12.002 2.005c5.518 0 9.998 4.48 9.998 9.997 0 5.518-4.48 9.998-9.998 9.998-5.517 0-9.997-4.48-9.997-9.998 0-5.517 4.48-9.997 9.997-9.997zm0 1.5c-4.69 0-8.497 3.807-8.497 8.497s3.807 8.498 8.497 8.498 8.498-3.808 8.498-8.498-3.808-8.497-8.498-8.497zm0 6.5c-.414 0-.75.336-.75.75v5.5c0 .414.336.75.75.75s.75-.336.75-.75v-5.5c0-.414-.336-.75-.75-.75zm-.002-3c.552 0 1 .448 1 1s-.448 1-1 1-1-.448-1-1 .448-1 1-1z" fill-rule="nonzero"/></svg>

After

Width:  |  Height:  |  Size: 593 B

View file

@ -16,7 +16,7 @@ return array(
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
'League\\ColorExtractor\\' => array($vendorDir . '/league/color-extractor/src'),
'Laminas\\Escaper\\' => array($vendorDir . '/laminas/laminas-escaper/src'),
'Kirby\\' => array($vendorDir . '/getkirby/composer-installer/src', $baseDir . '/kirby/src'),
'Kirby\\' => array($baseDir . '/kirby/src', $vendorDir . '/getkirby/composer-installer/src'),
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
'Base32\\' => array($vendorDir . '/christian-riesen/base32/src'),
);

View file

@ -96,8 +96,8 @@ class ComposerStaticInit0b7fb803e22a45eb87e24172337208aa
),
'Kirby\\' =>
array (
0 => __DIR__ . '/..' . '/getkirby/composer-installer/src',
1 => __DIR__ . '/../..' . '/kirby/src',
0 => __DIR__ . '/../..' . '/kirby/src',
1 => __DIR__ . '/..' . '/getkirby/composer-installer/src',
),
'Composer\\Semver\\' =>
array (

View file

@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'getkirby/plainkit',
'pretty_version' => '5.1.4',
'version' => '5.1.4.0',
'reference' => null,
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '76274fff04c54514230ad2bb0aca362139618411',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -65,9 +65,9 @@
'dev_requirement' => false,
),
'getkirby/plainkit' => array(
'pretty_version' => '5.1.4',
'version' => '5.1.4.0',
'reference' => null,
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '76274fff04c54514230ad2bb0aca362139618411',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View file

@ -18,19 +18,17 @@
<div class="popup-controls">
<!-- Font Family -->
<div class="settings-subsection">
<div class="field" :class="{ 'field--view-only': inheritanceLocked }">
<div class="field field-font" :class="{ 'field--view-only': inheritanceLocked }">
<label class="label-with-tooltip" data-css="font-family">Police</label>
<select v-model="fontFamily.value" :disabled="inheritanceLocked">
<option value="Alegreya Sans">Alegreya Sans</option>
<option value="Alegreya">Alegreya</option>
<option value="Arial">Arial</option>
<option value="Georgia">Georgia</option>
<option value="Times New Roman">Times New Roman</option>
</select>
<label class="checkbox-inline label-with-tooltip" data-css="font-style">
<input type="checkbox" v-model="fontStyle.italic" :disabled="inheritanceLocked" />
<span>Italique</span>
</label>
<div class="field-with-option">
<select v-model="fontFamily.value" :disabled="inheritanceLocked">
<option v-for="f in fonts" :key="f" :value="f">{{ f }}</option>
</select>
<div class="checkbox-field">
<input type="checkbox" v-model="fontStyle.italic" :disabled="inheritanceLocked" />
<label class="label-with-tooltip" data-css="font-style">Italique</label>
</div>
</div>
</div>
</div>
@ -38,18 +36,7 @@
<div class="settings-subsection">
<div class="field" :class="{ 'field--view-only': inheritanceLocked }">
<label class="label-with-tooltip" data-css="font-weight">Graisse</label>
<div class="button-group">
<button
v-for="weight in [200, 300, 400, 600, 800]"
:key="weight"
type="button"
:class="{ active: fontWeight.value === weight }"
:disabled="inheritanceLocked"
@click="fontWeight.value = weight"
>
{{ weight }}
</button>
</div>
<UnitToggle v-model="fontWeightString" :units="weights" :disabled="inheritanceLocked" />
</div>
</div>
@ -57,7 +44,7 @@
<div class="settings-subsection">
<div class="field" :class="{ 'field--view-only': inheritanceLocked }">
<label class="label-with-tooltip" data-css="font-size">Taille du texte</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="fontSize.value"
:min="0"
@ -143,7 +130,7 @@
<div class="settings-subsection">
<div class="field" :class="{ 'field--view-only': inheritanceLocked }">
<label class="label-with-tooltip" data-css="margin">Marges extérieures</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="marginOuter.value"
:min="0"
@ -176,7 +163,7 @@
<div class="settings-subsection">
<div class="field" :class="{ 'field--view-only': inheritanceLocked }">
<label class="label-with-tooltip" data-css="padding">Marges intérieures</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="paddingInner.value"
:min="0"
@ -276,6 +263,7 @@ import { useStylesheetStore } from '../stores/stylesheet';
import { usePopupPosition } from '../composables/usePopupPosition';
import { useDebounce } from '../composables/useDebounce';
import NumberInput from './ui/NumberInput.vue';
import UnitToggle from './ui/UnitToggle.vue';
import Coloris from '@melloware/coloris';
import '@melloware/coloris/dist/coloris.css';
import hljs from 'highlight.js/lib/core';
@ -321,6 +309,18 @@ const background = ref({ value: 'transparent' });
const marginOuter = ref({ value: 0, unit: 'mm' });
const paddingInner = ref({ value: 0, unit: 'mm' });
// Constants
const fonts = ['Alegreya Sans', 'Alegreya', 'Arial', 'Georgia', 'Times New Roman'];
const weights = ['200', '300', '400', '600', '800'];
// Computed to adapt fontWeight for UnitToggle
const fontWeightString = computed({
get: () => String(fontWeight.value.value),
set: (val) => {
fontWeight.value.value = parseInt(val);
}
});
const immediateUpdate = (callback) => {
callback();
};
@ -794,43 +794,4 @@ defineExpose({ handleIframeClick, close, visible });
color: var(--color-purple);
font-size: 0.875rem;
}
.button-group {
display: flex;
gap: 0.25rem;
}
.button-group button {
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
border: 1px solid #ddd;
background: white;
cursor: pointer;
transition: all 0.2s;
}
.button-group button.active {
background: #61afef;
color: white;
border-color: #61afef;
}
.button-group button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.checkbox-inline {
display: inline-flex;
align-items: center;
gap: 0.25rem;
margin-left: 1rem;
font-size: 0.875rem;
cursor: pointer;
}
.checkbox-inline input[type="checkbox"] {
margin: 0;
cursor: pointer;
}
</style>

View file

@ -26,7 +26,7 @@
:class="{ 'field--view-only': inheritanceLocked }"
>
<label class="label-with-tooltip" data-css="margin-top">Haut</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="margins.top.value"
:min="0"
@ -67,7 +67,7 @@
:class="{ 'field--view-only': inheritanceLocked }"
>
<label class="label-with-tooltip" data-css="margin-bottom">Bas</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="margins.bottom.value"
:min="0"
@ -108,7 +108,7 @@
:class="{ 'field--view-only': inheritanceLocked }"
>
<label class="label-with-tooltip" data-css="margin-left">Gauche</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="margins.left.value"
:min="0"
@ -149,7 +149,7 @@
:class="{ 'field--view-only': inheritanceLocked }"
>
<label class="label-with-tooltip" data-css="margin-right">Droite</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
v-model="margins.right.value"
:min="0"

View file

@ -127,12 +127,8 @@ nav {
overflow: hidden;
position: relative;
left: calc(var(--panel-w) * -1);
padding: 4rem 0;
background-color: var(--color-panel-bg);
box-shadow: -5px 0px 12px;
transition: left 0.3s var(--curve);
pointer-events: all;
}
@ -142,10 +138,11 @@ nav {
}
.tab-panel {
height: 100%;
height: calc(100% - var(--panel-nav-h));
overflow-y: auto;
overflow-x: hidden;
padding: 0 2em;
// padding-left: 1em;
padding-bottom: 20vh;
margin-top: var(--panel-nav-h);
}
</style>

View file

@ -2,7 +2,17 @@
<section class="settings-section" id="settings-section_page" data-color-type="page">
<h2>Réglage des pages</h2>
<div class="container">
<div class="infos">
<span class="info-icon">
<svg width="24" height="24" clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m12.002 2.005c5.518 0 9.998 4.48 9.998 9.997 0 5.518-4.48 9.998-9.998 9.998-5.517 0-9.997-4.48-9.997-9.998 0-5.517 4.48-9.997 9.997-9.997zm0 1.5c-4.69 0-8.497 3.807-8.497 8.497s3.807 8.498 8.497 8.498 8.498-3.808 8.498-8.498-3.808-8.497-8.498-8.497zm0 6.5c-.414 0-.75.336-.75.75v5.5c0 .414.336.75.75.75s.75-.336.75-.75v-5.5c0-.414-.336-.75-.75-.75zm-.002-3c.552 0 1 .448 1 1s-.448 1-1 1-1-.448-1-1 .448-1 1-1z" fill-rule="nonzero"/>
</svg>
</span>
<p>
Ces réglages s'appliquent à l'ensemble des pages du document. Vous
pouvez modifier ensuite les pages des gabarits indépendamment.
</p>
</div>
<div class="settings-subsection">
<div class="field field-simple">
@ -54,7 +64,7 @@
<label for="margin-top" class="label-with-tooltip" data-css="margin-top"
>Haut</label
>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
id="margin-top"
v-model="margins.top.value"
@ -94,7 +104,7 @@
data-css="margin-bottom"
>Bas</label
>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
id="margin-bottom"
v-model="margins.bottom.value"
@ -134,7 +144,7 @@
data-css="margin-left"
>Gauche</label
>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
id="margin-left"
v-model="margins.left.value"
@ -174,7 +184,7 @@
data-css="margin-right"
>Droite</label
>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
id="margin-right"
v-model="margins.right.value"
@ -261,25 +271,65 @@
</div>
<div class="settings-subsection">
<div class="field checkbox-field">
<div class="field field-generated-content">
<div class="checkbox-field">
<input id="page-numbers" type="checkbox" v-model="pageNumbers" />
<label
for="page-numbers"
class="label-with-tooltip"
data-css="@bottom-left/right"
>Numéro de page</label
>
data-css="content: counter(page)"
>
Numéro de page
</label>
</div>
<div class="positions">
<div class="group-position">
<button data-css="@top/bottom-left">Gauche</button>
<button data-css="@top/bottom-center">Centre</button>
<button data-css="@top/bottom-right">Droite</button>
</div>
<div class="group-position">
<button data-css="@top-left/center/right">Haut</button>
<button data-css="@bottom-left/center/right">Bas</button>
</div>
</div>
</div>
</div>
<div class="settings-subsection">
<div class="field field-generated-content">
<div class="checkbox-field">
<input id="running-title" type="checkbox" v-model="runningTitle" />
<label
for="running-title"
class="label-with-tooltip"
data-css="string-set"
>Titre courant</label
>
</div>
<div class="positions">
<div class="group-position">
<button data-css="@top/bottom-left">Gauche</button>
<button data-css="@top/bottom-center">Centre</button>
<button data-css="@top/bottom-right">Droite</button>
</div>
<div class="group-position">
<button data-css="@top-left/center/right">Haut</button>
<button data-css="@bottom-left/center/right">Bas</button>
</div>
</div>
</div>
<div class="field checkbox-field">
<input id="running-title" type="checkbox" v-model="runningTitle" />
<label
for="running-title"
class="label-with-tooltip"
data-css="string-set"
>Titre courant</label
>
</div>
</div>
</div>
</section>

View file

@ -2,11 +2,18 @@
<section class="settings-section" id="settings-section_elem" data-color-type="elem">
<h2>Réglage du texte</h2>
<div class="container">
<p class="infos">
<div class="infos">
<span class="info-icon">
<svg width="24" height="24" clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m12.002 2.005c5.518 0 9.998 4.48 9.998 9.997 0 5.518-4.48 9.998-9.998 9.998-5.517 0-9.997-4.48-9.997-9.998 0-5.517 4.48-9.997 9.997-9.997zm0 1.5c-4.69 0-8.497 3.807-8.497 8.497s3.807 8.498 8.497 8.498 8.498-3.808 8.498-8.498-3.808-8.497-8.498-8.497zm0 6.5c-.414 0-.75.336-.75.75v5.5c0 .414.336.75.75.75s.75-.336.75-.75v-5.5c0-.414-.336-.75-.75-.75zm-.002-3c.552 0 1 .448 1 1s-.448 1-1 1-1-.448-1-1 .448-1 1-1z" fill-rule="nonzero"/>
</svg>
</span>
<p>
Ces réglages s'appliquent à l'ensemble des éléments du document. Vous
pouvez modifier ensuite les éléments indépendamment.
</p>
</p>
</div>
<!-- Police -->
<div class="settings-subsection">
@ -16,7 +23,7 @@
<select id="text-font" v-model="font">
<option v-for="f in fonts" :key="f" :value="f">{{ f }}</option>
</select>
<div class="field-checkbox">
<div class="checkbox-field">
<input id="text-italic" type="checkbox" v-model="italic" />
<label for="text-italic" class="label-with-tooltip" data-css="font-style">Italique</label>
</div>
@ -34,11 +41,11 @@
<!-- Taille du texte -->
<div class="settings-subsection">
<div class="field">
<div class="field field-text-size">
<label for="text-size-range" class="label-with-tooltip" data-css="font-size">Taille du texte</label>
<InputWithUnit
v-model="fontSize"
:units="['px', 'em', 'rem']"
:units="['px']"
:min="8"
:max="72"
showRange
@ -46,6 +53,20 @@
</div>
</div>
<!-- line height -->
<div class="settings-subsection">
<div class="field field-text-size">
<label for="line-height-range" class="label-with-tooltip" data-css="line-height">Interlignage</label>
<InputWithUnit
v-model="lineHeight"
:units="['px', 'em', 'rem']"
:min="0"
:max="72"
showRange
/>
</div>
</div>
<!-- Alignement -->
<div class="settings-subsection">
<div class="field field-simple">
@ -151,6 +172,7 @@ const font = ref('Alegreya Sans');
const italic = ref(false);
const weight = ref('400');
const fontSize = ref({ value: 16, unit: 'px' });
const lineHeight = ref({ value: 1.2, unit: 'em' });
const alignment = ref('left');
const color = ref('rgb(0, 0, 0)');
const background = ref('transparent');
@ -203,10 +225,92 @@ watch(weight, (val) => {
updateStyle('p', 'font-weight', val);
});
watch(fontSize, (val) => {
watch(fontSize, (newVal, oldVal) => {
if (isUpdatingFromStore) return;
// If unit changed, convert the value
if (oldVal && newVal.unit !== oldVal.unit) {
const baseFontSize = 16; // Default base font size for rem
let convertedValue = newVal.value;
// Convert from px to em/rem
if (oldVal.unit === 'px' && (newVal.unit === 'em' || newVal.unit === 'rem')) {
convertedValue = newVal.value / baseFontSize;
// Round to 1 decimal place
convertedValue = Math.round(convertedValue * 10) / 10;
}
// Convert from em/rem to px
else if ((oldVal.unit === 'em' || oldVal.unit === 'rem') && newVal.unit === 'px') {
convertedValue = newVal.value * baseFontSize;
// Round to whole number for px
convertedValue = Math.round(convertedValue);
}
// Clamp to valid range based on new unit
if (newVal.unit === 'em' || newVal.unit === 'rem') {
convertedValue = Math.max(0, Math.min(4, convertedValue));
} else {
convertedValue = Math.max(8, Math.min(72, convertedValue));
}
// Update with converted value - create new object to trigger reactivity
fontSize.value = { value: convertedValue, unit: newVal.unit };
return; // Exit early to avoid double update
}
debouncedUpdate(() => {
updateStyle('p', 'font-size', `${val.value}${val.unit}`);
updateStyle('p', 'font-size', `${newVal.value}${newVal.unit}`);
});
}, { deep: true });
watch(lineHeight, (newVal, oldVal) => {
if (isUpdatingFromStore) return;
// If unit changed, convert the value
if (oldVal && newVal.unit !== oldVal.unit) {
const baseFontSize = 16; // Default base font size for rem
let convertedValue = newVal.value;
// Convert from px to em/rem
if (oldVal.unit === 'px' && (newVal.unit === 'em' || newVal.unit === 'rem')) {
const divisor = newVal.unit === 'em' ? fontSize.value.value : baseFontSize;
convertedValue = newVal.value / divisor;
// Round to 1 decimal place
convertedValue = Math.round(convertedValue * 10) / 10;
}
// Convert from em/rem to px
else if ((oldVal.unit === 'em' || oldVal.unit === 'rem') && newVal.unit === 'px') {
const multiplier = oldVal.unit === 'em' ? fontSize.value.value : baseFontSize;
convertedValue = newVal.value * multiplier;
// Round to whole number for px
convertedValue = Math.round(convertedValue);
}
// Convert between em and rem
else if (oldVal.unit === 'em' && newVal.unit === 'rem') {
convertedValue = (newVal.value * fontSize.value.value) / baseFontSize;
// Round to 1 decimal place
convertedValue = Math.round(convertedValue * 10) / 10;
}
else if (oldVal.unit === 'rem' && newVal.unit === 'em') {
convertedValue = (newVal.value * baseFontSize) / fontSize.value.value;
// Round to 1 decimal place
convertedValue = Math.round(convertedValue * 10) / 10;
}
// Clamp to valid range based on new unit
if (newVal.unit === 'em' || newVal.unit === 'rem') {
convertedValue = Math.max(0, Math.min(4, convertedValue));
} else {
convertedValue = Math.max(0, Math.min(72, convertedValue));
}
// Update with converted value - create new object to trigger reactivity
lineHeight.value = { value: convertedValue, unit: newVal.unit };
return; // Exit early to avoid double update
}
debouncedUpdate(() => {
updateStyle('p', 'line-height', `${newVal.value}${newVal.unit}`);
});
}, { deep: true });
@ -257,6 +361,9 @@ const syncFromStore = () => {
const fontSizeVal = extractNumericValue('p', 'font-size', ['px', 'em', 'rem']);
if (fontSizeVal) fontSize.value = fontSizeVal;
const lineHeightVal = extractNumericValue('p', 'line-height', ['px', 'em', 'rem']);
if (lineHeightVal) lineHeight.value = lineHeightVal;
// Margins
const margins = extractSpacing('p', 'margin');
if (margins) {

View file

@ -1,19 +1,19 @@
<template>
<div class="input-with-unit">
<div class="input-with-range">
<input
v-if="showRange"
type="range"
:value="modelValue.value"
:min="min"
:max="max"
:step="step"
:min="computedMin"
:max="computedMax"
:step="computedStep"
@input="updateValue(Number($event.target.value))"
/>
<NumberInput
:modelValue="modelValue.value"
:min="min"
:max="max"
:step="step"
:min="computedMin"
:max="computedMax"
:step="computedStep"
inputClass="size-input"
@update:modelValue="updateValue"
/>
@ -27,6 +27,7 @@
</template>
<script setup>
import { computed } from 'vue';
import NumberInput from './NumberInput.vue';
import UnitToggle from './UnitToggle.vue';
@ -60,11 +61,36 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']);
// Compute step based on unit
const computedStep = computed(() => {
if (props.modelValue.unit === 'em' || props.modelValue.unit === 'rem') {
return 0.1;
}
return props.step;
});
// Compute min based on unit
const computedMin = computed(() => {
if (props.modelValue.unit === 'em' || props.modelValue.unit === 'rem') {
return 0;
}
return props.min;
});
// Compute max based on unit
const computedMax = computed(() => {
if (props.modelValue.unit === 'em' || props.modelValue.unit === 'rem') {
return 4;
}
return props.max;
});
const updateValue = (value) => {
emit('update:modelValue', { ...props.modelValue, value });
};
const updateUnit = (unit) => {
// Just emit the unit change, let parent handle any conversion
emit('update:modelValue', { ...props.modelValue, unit });
};
</script>

View file

@ -2,7 +2,7 @@
<div class="margin-editor">
<div class="field field-margin-all">
<label :for="id" class="label-with-tooltip" :data-css="cssProperty">{{ label }}</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
:id="id"
:modelValue="simple.value"
@ -30,7 +30,7 @@
<div v-if="expanded" class="subsection collapsed-section">
<div v-for="side in sides" :key="side.key" class="field field-margin">
<label :for="`${id}-${side.key}`" class="label-with-tooltip" :data-css="`${cssProperty}-${side.key}`">{{ side.label }}</label>
<div class="input-with-unit">
<div class="input-with-range">
<NumberInput
:id="`${id}-${side.key}`"
:modelValue="detailed[side.key].value"

View file

@ -1,8 +1,9 @@
<template>
<div class="number-input">
<input
ref="inputRef"
type="number"
:value="modelValue"
:value="displayValue"
:min="min"
:max="max"
:step="step"
@ -15,6 +16,7 @@
<button
type="button"
class="spinner-btn spinner-up"
@mousedown.prevent
@click="increment"
:disabled="disabled || (max !== undefined && modelValue >= max)"
tabindex="-1"
@ -26,6 +28,7 @@
<button
type="button"
class="spinner-btn spinner-down"
@mousedown.prevent
@click="decrement"
:disabled="disabled || (min !== undefined && modelValue <= min)"
tabindex="-1"
@ -39,6 +42,10 @@
</template>
<script setup>
import { computed, ref } from 'vue';
const inputRef = ref(null);
const props = defineProps({
modelValue: {
type: Number,
@ -72,22 +79,46 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']);
// Round to 1 decimal place for display, but show whole numbers without decimals
const displayValue = computed(() => {
const rounded = Math.round(props.modelValue * 10) / 10;
// If it's a whole number, return it as is (no decimal)
if (Number.isInteger(rounded)) {
return rounded;
}
return rounded;
});
const handleInput = (event) => {
const value = Number(event.target.value);
let value = Number(event.target.value);
// Round to 1 decimal place
value = Math.round(value * 10) / 10;
emit('update:modelValue', value);
};
const increment = () => {
const newValue = props.modelValue + props.step;
let newValue = props.modelValue + props.step;
// Round to 1 decimal place
newValue = Math.round(newValue * 10) / 10;
if (props.max === undefined || newValue <= props.max) {
emit('update:modelValue', newValue);
}
// Give focus to input
if (inputRef.value) {
inputRef.value.focus();
}
};
const decrement = () => {
const newValue = props.modelValue - props.step;
let newValue = props.modelValue - props.step;
// Round to 1 decimal place
newValue = Math.round(newValue * 10) / 10;
if (props.min === undefined || newValue >= props.min) {
emit('update:modelValue', newValue);
}
// Give focus to input
if (inputRef.value) {
inputRef.value.focus();
}
};
</script>

View file

@ -5,6 +5,7 @@
:key="unit"
type="button"
:class="{ active: modelValue === unit }"
:disabled="disabled"
@click="$emit('update:modelValue', unit)"
>
{{ unit }}
@ -21,6 +22,10 @@ defineProps({
units: {
type: Array,
default: () => ['mm', 'px']
},
disabled: {
type: Boolean,
default: false
}
});