Compare commits
No commits in common. "ccdd9bda05bc9c6b76f99a5fefbdb7a32b845fff" and "59f6716121eacf37d1bdfbc67493997e318c6748" have entirely different histories.
ccdd9bda05
...
59f6716121
3 changed files with 9 additions and 87 deletions
21
src/App.vue
21
src/App.vue
|
|
@ -6,7 +6,6 @@ import ElementPopup from './components/ElementPopup.vue';
|
||||||
import PreviewLoader from './components/PreviewLoader.vue';
|
import PreviewLoader from './components/PreviewLoader.vue';
|
||||||
import SaveButton from './components/SaveButton.vue';
|
import SaveButton from './components/SaveButton.vue';
|
||||||
import PrintButton from './components/PrintButton.vue';
|
import PrintButton from './components/PrintButton.vue';
|
||||||
import ZoomControls from './components/ui/ZoomControls.vue';
|
|
||||||
import { onMounted, ref, computed, provide } from 'vue';
|
import { onMounted, ref, computed, provide } from 'vue';
|
||||||
import { useStylesheetStore } from './stores/stylesheet';
|
import { useStylesheetStore } from './stores/stylesheet';
|
||||||
import { useNarrativeStore } from './stores/narrative';
|
import { useNarrativeStore } from './stores/narrative';
|
||||||
|
|
@ -74,10 +73,6 @@ const { handleKeyboardShortcut, isMac } = useKeyboardShortcuts({
|
||||||
// Attach keyboard shortcut handler to renderer
|
// Attach keyboard shortcut handler to renderer
|
||||||
setKeyboardShortcutHandler(handleKeyboardShortcut);
|
setKeyboardShortcutHandler(handleKeyboardShortcut);
|
||||||
|
|
||||||
// Zoom
|
|
||||||
const zoomControls = ref(null);
|
|
||||||
const zoomStyle = computed(() => zoomControls.value?.zoomStyle ?? {});
|
|
||||||
|
|
||||||
// Lifecycle: Initialize app on mount
|
// Lifecycle: Initialize app on mount
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// Load narrative data (narrativeUrl constructed from location, always present)
|
// Load narrative data (narrativeUrl constructed from location, always present)
|
||||||
|
|
@ -104,13 +99,11 @@ onMounted(async () => {
|
||||||
ref="previewFrame1"
|
ref="previewFrame1"
|
||||||
class="preview-frame"
|
class="preview-frame"
|
||||||
:class="{ shifted: activeTab.length > 0 }"
|
:class="{ shifted: activeTab.length > 0 }"
|
||||||
:style="zoomStyle"
|
|
||||||
></iframe>
|
></iframe>
|
||||||
<iframe
|
<iframe
|
||||||
ref="previewFrame2"
|
ref="previewFrame2"
|
||||||
class="preview-frame"
|
class="preview-frame"
|
||||||
:class="{ shifted: activeTab.length > 0 }"
|
:class="{ shifted: activeTab.length > 0 }"
|
||||||
:style="zoomStyle"
|
|
||||||
></iframe>
|
></iframe>
|
||||||
|
|
||||||
<PreviewLoader :isLoading="isTransitioning" :shifted="activeTab.length > 0" />
|
<PreviewLoader :isLoading="isTransitioning" :shifted="activeTab.length > 0" />
|
||||||
|
|
@ -131,8 +124,6 @@ onMounted(async () => {
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
<ZoomControls ref="zoomControls" />
|
|
||||||
|
|
||||||
<div id="group-btn">
|
<div id="group-btn">
|
||||||
<SaveButton />
|
<SaveButton />
|
||||||
<PrintButton :printPreview="printPreview" />
|
<PrintButton :printPreview="printPreview" />
|
||||||
|
|
@ -148,15 +139,17 @@ onMounted(async () => {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
border: none;
|
border: none;
|
||||||
transform-origin: top center;
|
margin-left: 0;
|
||||||
|
transform: scale(1) translateY(0);
|
||||||
|
height: 100vh;
|
||||||
|
transition: all 0.2s ease-in-out var(--curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-frame.shifted {
|
||||||
/* .preview-frame.shifted {
|
|
||||||
margin-left: 17.55rem;
|
margin-left: 17.55rem;
|
||||||
transform: scale(0.65) translateY(-40vh);
|
transform: scale(0.65) translateY(-40vh);
|
||||||
height: 155vh;
|
height: 155vh;
|
||||||
} */
|
}
|
||||||
|
|
||||||
.preview-frame:nth-of-type(1) {
|
.preview-frame:nth-of-type(1) {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
@ -171,7 +164,7 @@ onMounted(async () => {
|
||||||
.print-btn {
|
.print-btn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 2rem;
|
bottom: 2rem;
|
||||||
left: 2rem;
|
right: 2rem;
|
||||||
width: 3.5rem;
|
width: 3.5rem;
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onMounted, inject, nextTick } from 'vue';
|
import { ref, computed, watch, onMounted, inject } from 'vue';
|
||||||
import bookIcon from '/assets/svg/book.svg?raw';
|
import bookIcon from '/assets/svg/book.svg?raw';
|
||||||
import { useStylesheetStore } from '../../stores/stylesheet';
|
import { useStylesheetStore } from '../../stores/stylesheet';
|
||||||
import { useDebounce } from '../../composables/useDebounce';
|
import { useDebounce } from '../../composables/useDebounce';
|
||||||
|
|
@ -518,7 +518,7 @@ const syncFromStore = () => {
|
||||||
(rightPageMatch && rightPageMatch[0].includes('string(title)'));
|
(rightPageMatch && rightPageMatch[0].includes('string(title)'));
|
||||||
runningTitle.value = hasRunningTitle;
|
runningTitle.value = hasRunningTitle;
|
||||||
} finally {
|
} finally {
|
||||||
nextTick(() => { isUpdatingFromStore = false; });
|
isUpdatingFromStore = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="zoom-controls">
|
|
||||||
<button @click="zoomOut" title="Dézoomer">−</button>
|
|
||||||
<button @click="zoomReset" title="Réinitialiser le zoom">{{ Math.round(zoomLevel * 100) }}%</button>
|
|
||||||
<button @click="zoomIn" title="Zoomer">+</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed } from 'vue';
|
|
||||||
|
|
||||||
const zoomLevel = ref(1);
|
|
||||||
|
|
||||||
const zoomIn = () => { triggerZoom(); zoomLevel.value = Math.min(zoomLevel.value + 0.1, 3); };
|
|
||||||
const zoomOut = () => { triggerZoom(); zoomLevel.value = Math.max(zoomLevel.value - 0.1, 0.2); };
|
|
||||||
const zoomReset = () => { triggerZoom(); zoomLevel.value = 1; };
|
|
||||||
|
|
||||||
const isZooming = ref(false);
|
|
||||||
let zoomTimer = null;
|
|
||||||
|
|
||||||
const triggerZoom = () => {
|
|
||||||
isZooming.value = true;
|
|
||||||
clearTimeout(zoomTimer);
|
|
||||||
zoomTimer = setTimeout(() => { isZooming.value = false; }, 350);
|
|
||||||
};
|
|
||||||
|
|
||||||
const zoomStyle = computed(() => ({
|
|
||||||
transform: `scale(${zoomLevel.value})`,
|
|
||||||
height: `${100 / zoomLevel.value}vh`,
|
|
||||||
transition: isZooming.value ? 'transform 0.3s ease' : 'none',
|
|
||||||
}));
|
|
||||||
|
|
||||||
defineExpose({ zoomStyle });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.zoom-controls {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 2rem;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
background: var(--color-interface-100, #fff);
|
|
||||||
border: 1px solid var(--color-interface-200, #ddd);
|
|
||||||
border-radius: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-controls button {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
padding: 0.4rem 0.7rem;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--color-interface-800, #333);
|
|
||||||
min-width: 2.5rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-controls button:hover {
|
|
||||||
background: var(--color-interface-200, #eee);
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-controls button:not(:last-child) {
|
|
||||||
border-right: 1px solid var(--color-interface-200, #ddd);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue