init with kirby, vue and pagedjs interactive

This commit is contained in:
isUnknown 2025-11-24 14:01:48 +01:00
commit dc0ae26464
968 changed files with 211706 additions and 0 deletions

116
src/App.vue Normal file
View file

@ -0,0 +1,116 @@
<script setup>
import PagedJsWrapper from './components/PagedJsWrapper.vue';
import { onMounted, ref, nextTick } from 'vue';
import { Previewer } from 'pagedjs';
const marginTop = ref(20);
let sourceHTML = '';
let editorUIElement = null;
const renderPaged = async () => {
console.log('renderPaged called, marginTop:', marginTop.value);
// Update @page margin dynamically
let styleEl = document.getElementById('dynamic-page-style');
if (!styleEl) {
styleEl = document.createElement('style');
styleEl.id = 'dynamic-page-style';
document.head.appendChild(styleEl);
}
styleEl.textContent = `
@page {
size: A4;
margin: ${marginTop.value}mm 15mm 26mm 15mm;
}
`;
// Detach UI before PagedJS processes body
if (editorUIElement && editorUIElement.parentNode) {
editorUIElement.remove();
}
// Remove previous render
const existingPages = document.querySelector('.pagedjs_pages');
if (existingPages) existingPages.remove();
// Restore source content to body
const printSource = document.getElementById('print-source');
if (printSource && sourceHTML) {
printSource.innerHTML = sourceHTML;
printSource.style.display = 'block';
}
// Render
const paged = new Previewer();
try {
const flow = await paged.preview();
console.log('Rendered', flow.total, 'pages.');
} catch (e) {
console.error('PagedJS error:', e);
}
// Re-inject UI after PagedJS transforms the DOM
if (editorUIElement) {
document.body.appendChild(editorUIElement);
// Apply styles inline since PagedJS removes stylesheets
editorUIElement.style.cssText = `
position: fixed !important;
bottom: 1rem !important;
left: 1rem !important;
z-index: 9999 !important;
background: white;
padding: 0.5rem;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
`;
}
};
const increaseMargin = () => {
marginTop.value += 5;
console.log('Button clicked, new margin:', marginTop.value);
renderPaged();
};
onMounted(async () => {
await nextTick();
// Store source HTML before first render
const source = document.getElementById('print-source');
if (source) {
sourceHTML = source.innerHTML;
console.log('Source HTML stored:', sourceHTML.substring(0, 100));
}
// Store UI element reference
editorUIElement = document.getElementById('editor-ui');
renderPaged();
});
</script>
<template>
<!-- Source content -->
<div id="print-source">
<PagedJsWrapper />
</div>
<!-- Editor UI overlay -->
<div id="editor-ui">
<button id="increase-margin" @click="increaseMargin">+</button>
</div>
</template>
<style>
/* PagedJS print styles */
h2 {
break-before: page;
}
@page {
@bottom-center {
content: string(title);
}
}
.chapter > h2 {
string-set: title content(text);
}
</style>

0
src/assets/editor-ui.css Normal file
View file

View file

@ -0,0 +1,171 @@
/* CSS for Paged.js interface v0.4 */
/* Change the look */
:root {
--color-background: whitesmoke;
--color-pageSheet: #cfcfcf;
--color-pageBox: violet;
--color-paper: white;
--color-marginBox: transparent;
--pagedjs-crop-color: black;
--pagedjs-crop-shadow: white;
--pagedjs-crop-stroke: 1px;
}
/* To define how the book look on the screen: */
@media screen, pagedjs-ignore {
body {
background-color: var(--color-background);
}
.pagedjs_pages {
display: flex;
width: calc(var(--pagedjs-width) * 2);
flex: 0;
flex-wrap: wrap;
margin: 0 auto;
}
.pagedjs_page {
background-color: var(--color-paper);
box-shadow: 0 0 0 1px var(--color-pageSheet);
margin: 0;
flex-shrink: 0;
flex-grow: 0;
margin-top: 10mm;
}
.pagedjs_first_page {
margin-left: var(--pagedjs-width);
}
.pagedjs_page:last-of-type {
margin-bottom: 10mm;
}
.pagedjs_pagebox {
box-shadow: 0 0 0 1px var(--color-pageBox);
}
.pagedjs_left_page {
z-index: 20;
width: calc(
var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width)
) !important;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop {
border-color: transparent;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle {
width: 0;
}
.pagedjs_right_page {
z-index: 10;
position: relative;
left: calc(var(--pagedjs-bleed-left) * -1);
}
/* show the margin-box */
.pagedjs_margin-top-left-corner-holder,
.pagedjs_margin-top,
.pagedjs_margin-top-left,
.pagedjs_margin-top-center,
.pagedjs_margin-top-right,
.pagedjs_margin-top-right-corner-holder,
.pagedjs_margin-bottom-left-corner-holder,
.pagedjs_margin-bottom,
.pagedjs_margin-bottom-left,
.pagedjs_margin-bottom-center,
.pagedjs_margin-bottom-right,
.pagedjs_margin-bottom-right-corner-holder,
.pagedjs_margin-right,
.pagedjs_margin-right-top,
.pagedjs_margin-right-middle,
.pagedjs_margin-right-bottom,
.pagedjs_margin-left,
.pagedjs_margin-left-top,
.pagedjs_margin-left-middle,
.pagedjs_margin-left-bottom {
box-shadow: 0 0 0 1px inset var(--color-marginBox);
}
/* uncomment this part for recto/verso book : ------------------------------------ */
/*
.pagedjs_pages {
flex-direction: column;
width: 100%;
}
.pagedjs_first_page {
margin-left: 0;
}
.pagedjs_page {
margin: 0 auto;
margin-top: 10mm;
}
.pagedjs_left_page{
width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width) + var(--pagedjs-bleed-left))!important;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop{
border-color: var(--pagedjs-crop-color);
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle{
width: var(--pagedjs-cross-size)!important;
}
.pagedjs_right_page{
left: 0;
}
*/
/*--------------------------------------------------------------------------------------*/
/* uncomment this par to see the baseline : -------------------------------------------*/
/* .pagedjs_pagebox {
--pagedjs-baseline: 22px;
--pagedjs-baseline-position: 5px;
--pagedjs-baseline-color: cyan;
background: linear-gradient(transparent 0%, transparent calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) var(--pagedjs-baseline)), transparent;
background-size: 100% var(--pagedjs-baseline);
background-repeat: repeat-y;
background-position-y: var(--pagedjs-baseline-position);
} */
/*--------------------------------------------------------------------------------------*/
}
/* Marks (to delete when merge in paged.js) */
.pagedjs_marks-crop {
z-index: 999999999999;
}
.pagedjs_bleed-top .pagedjs_marks-crop,
.pagedjs_bleed-bottom .pagedjs_marks-crop {
box-shadow: 1px 0px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-top .pagedjs_marks-crop:last-child,
.pagedjs_bleed-bottom .pagedjs_marks-crop:last-child {
box-shadow: -1px 0px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-left .pagedjs_marks-crop,
.pagedjs_bleed-right .pagedjs_marks-crop {
box-shadow: 0px 1px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-left .pagedjs_marks-crop:last-child,
.pagedjs_bleed-right .pagedjs_marks-crop:last-child {
box-shadow: 0px -1px 0px 0px var(--pagedjs-crop-shadow);
}

View file

@ -0,0 +1,29 @@
<template>
<section class="chapter">
<h2>About</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipiscing elit. Duis nibh tortor
</p>
</section>
<section class="chapter">
<h2>Chapter 1</h2>
<p>Lorem ipsum dolor sit amet</p>
</section>
<section class="chapter">
<h2>Chapter 2</h2>
<p>consectetur adipiscing elit</p>
</section>
<section class="chapter">
<h2>Chapter 3</h2>
<p>Duis nibh tortor, pellentesque eu suscipit vel</p>
</section>
</template>
<script setup>
</script>
<style>
</style>

5
src/main.js Normal file
View file

@ -0,0 +1,5 @@
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
createApp(App).mount('#app')

2
src/style.css Normal file
View file

@ -0,0 +1,2 @@
@import url('./assets/pagedjs-interface.css');
@import url('./assets/editor-ui.css');