Compare commits

...

2 commits

Author SHA1 Message Date
isUnknown
f760e1942a fix: race condition on custom styles loading + misc cleanup
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 22s
Guard watcher-triggered renders in usePreviewRenderer until first
explicit render completes, preventing premature renders with default
styles. Also: disable Contenu tab, update content/blueprints, add
global disabled button styles, minor formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:53:55 +01:00
isUnknown
59dfa18ec7 disable: comment out PagePopup and page hover/highlight feature
Keep the code aside for potential re-activation later.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:37:07 +01:00
16 changed files with 95 additions and 81 deletions

View file

@ -0,0 +1,8 @@
button[disabled] {
cursor: not-allowed !important;
opacity: 0.6;
}
button[disabled]:hover {
background-color: inherit !important;
}

View file

@ -234,8 +234,8 @@ img {
--space-m: 2rem;
--space-big: 3em;
--curve: cubic-bezier(0.86, 0, 0.07, 1);
--sans-serif: "DM Sans", sans-serif;
--mono: "Inconsolata", monospace;
--sans-serif: 'DM Sans', sans-serif;
--mono: 'Inconsolata', monospace;
--input-h: 26px;
--input-w: 160px;
--input-w-small: 45px;
@ -688,4 +688,13 @@ input[type=number] {
line-height: 1.5;
resize: none;
outline: none;
}
button[disabled] {
cursor: not-allowed !important;
opacity: 0.6;
}
button[disabled]:hover {
background-color: inherit !important;
}/*# sourceMappingURL=style.css.map */

File diff suppressed because one or more lines are too long

View file

@ -8,3 +8,4 @@
@use "src/_forms-section.scss" as *;
@use "src/_buttons.scss" as *;
@use "src/_settings-popup.scss" as *;
@use "src/_global.scss" as *;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 2.4 MiB

Before After
Before After

View file

@ -15,9 +15,9 @@ Mapdata:
background:
type: osm
center:
lat: 43.82684265866453
lon: 4.3375882121084715
zoom: 11.37799302158894
lat: 43.484330002696964
lon: 4.029111008525206
zoom: 6.503825883663738
----

View file

@ -26,7 +26,6 @@ body {
font-family: "DM Sans", sans-serif;
text-align: left;
color: rgb(190, 9, 9);
background: blue;
}
p {

View file

@ -35,6 +35,7 @@ columns:
template:
- map
- geoformat
info: "{{ page.intendedTemplate }}"
sidebar:
width: 1/3
sections:

View file

@ -7,17 +7,17 @@ columns:
fields:
type: fields
fields:
subtitle:
subtitle:
label: Sous-titre
type: text
width: 1/2
cover:
cover:
label: Image de couverture
type: files
multiple: false
width: 1/2
pages:
label: Narratives
label: Récits
type: pages
template: narrative
sidebar:
@ -26,6 +26,3 @@ columns:
files:
label: Fichiers
type: files

View file

@ -2,7 +2,7 @@
import PagedJsWrapper from './components/PagedJsWrapper.vue';
import EditorPanel from './components/editor/EditorPanel.vue';
import ElementPopup from './components/ElementPopup.vue';
import PagePopup from './components/PagePopup.vue';
// import PagePopup from './components/PagePopup.vue'; // DISABLED: page template styling feature
import PreviewLoader from './components/PreviewLoader.vue';
import SaveButton from './components/SaveButton.vue';
import { onMounted, ref, computed, provide } from 'vue';
@ -19,22 +19,22 @@ const narrativeStore = useNarrativeStore();
const previewFrame1 = ref(null);
const previewFrame2 = ref(null);
const elementPopup = ref(null);
const pagePopup = ref(null);
// const pagePopup = ref(null); // DISABLED: page template styling feature
const activeTab = ref('');
provide('activeTab', activeTab);
// Setup iframe interactions (hover, click, labels)
const {
hoveredPage,
selectedPages,
// hoveredPage, // DISABLED: page template styling feature
// selectedPages, // DISABLED: page template styling feature
hoveredElement,
selectedElement,
handleIframeMouseMove,
handleIframeClick,
handlePagePopupClose,
// handlePagePopupClose, // DISABLED: page template styling feature
handleElementPopupClose,
} = useIframeInteractions({ elementPopup, pagePopup });
} = useIframeInteractions({ elementPopup });
// Setup preview renderer with double buffering
const {
@ -61,13 +61,10 @@ const activeFrame = computed(() => {
const { printPreview } = usePrintPreview(activeFrame);
// Setup keyboard shortcuts (depends on printPreview)
const {
handleKeyboardShortcut,
isMac
} = useKeyboardShortcuts({
const { handleKeyboardShortcut, isMac } = useKeyboardShortcuts({
stylesheetStore,
elementPopup,
pagePopup,
// pagePopup, // DISABLED: page template styling feature
activeTab,
printPreview,
});
@ -117,13 +114,19 @@ onMounted(async () => {
:iframeRef="activeFrame"
@close="handleElementPopupClose"
/>
<!-- DISABLED: page template styling feature
<PagePopup
ref="pagePopup"
:iframeRef="activeFrame"
@close="handlePagePopupClose"
/>
-->
<button class="print-btn" @click="printPreview" :title="`Imprimer (${isMac ? '⌘' : 'Ctrl'}+P)`">
<button
class="print-btn"
@click="printPreview"
:title="`Imprimer (${isMac ? '⌘' : 'Ctrl'}+P)`"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"

View file

@ -24,7 +24,8 @@
class="tab"
:class="{ active: activeTab === 'contenu' }"
@click="activeTab = 'contenu'"
title="Ouvrir l'onglet Contenu"
title="fonctionnalité à venir"
disabled
>
Contenu
</button>
@ -131,11 +132,9 @@ nav {
position: relative;
left: calc(var(--panel-w) * -1);
background-color: var(--color-panel-bg);
box-shadow: -5px 0px 12px;
transition: left 0.3s var(--curve);
pointer-events: all;
}
@ -145,7 +144,7 @@ nav {
}
.tab-panel {
height: calc(100% - var(--panel-nav-h)*2);
height: calc(100% - var(--panel-nav-h) * 2);
overflow-y: auto;
overflow-x: hidden;
padding: 0 2em;

View file

@ -4,13 +4,13 @@ import { ref } from 'vue';
* Composable for managing interactions with pages and elements in the iframe
* Handles hover effects, labels, and click events for both pages and content elements
*/
export function useIframeInteractions({ elementPopup, pagePopup }) {
// Page interaction state
const hoveredPage = ref(null);
const selectedPages = ref([]); // Pages with active border (when popup is open)
export function useIframeInteractions({ elementPopup /*, pagePopup // DISABLED: page template styling feature */ }) {
// DISABLED: page template styling feature
// const hoveredPage = ref(null);
// const selectedPages = ref([]); // Pages with active border (when popup is open)
const hoveredElement = ref(null); // Currently hovered content element
const selectedElement = ref(null); // Selected element (when popup is open)
const EDGE_THRESHOLD = 30; // px from edge to trigger hover
// const EDGE_THRESHOLD = 30; // px from edge to trigger hover // DISABLED: page template styling feature
// Text elements that can trigger ElementPopup (excluding containers, images, etc.)
const CONTENT_ELEMENTS = [
@ -34,6 +34,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
'FIGCAPTION',
];
/* DISABLED: page template styling feature
// Check if mouse position is near the edges of a page element
const isNearPageEdge = (pageElement, mouseX, mouseY) => {
const rect = pageElement.getBoundingClientRect();
@ -64,6 +65,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
(p) => (p.getAttribute('data-page-type') || 'default') === pageType
);
};
*/
// Get selector for element (same logic as ElementPopup)
const getSelectorFromElement = (element) => {
@ -117,6 +119,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
}
};
/* DISABLED: page template styling feature
// Create and position page label on hover
const createPageLabel = (page) => {
const doc = page.ownerDocument;
@ -148,6 +151,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
label.remove();
}
};
*/
// Check if element is a content element (or find closest content parent)
const getContentElement = (element) => {
@ -161,6 +165,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
return null;
};
/* DISABLED: page template styling feature
// Clear selection highlight from all selected pages
const clearSelectedPages = () => {
selectedPages.value.forEach((page) => {
@ -168,6 +173,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
});
selectedPages.value = [];
};
*/
// Clear selected element highlight
const clearSelectedElement = () => {
@ -188,6 +194,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
// Handle mouse movement in iframe
const handleIframeMouseMove = (event) => {
/* DISABLED: page template styling feature
const pages = event.target.ownerDocument.querySelectorAll('.pagedjs_page');
let foundPage = null;
@ -217,44 +224,31 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
hoveredPage.value = foundPage;
}
*/
// If not near page edge, check for content element hover
if (!foundPage) {
const contentElement = getContentElement(event.target);
const doc = event.target.ownerDocument;
// Check for content element hover
const contentElement = getContentElement(event.target);
const doc = event.target.ownerDocument;
if (contentElement !== hoveredElement.value) {
// Remove highlight from previous element (only if not selected)
if (
hoveredElement.value &&
hoveredElement.value !== selectedElement.value
) {
hoveredElement.value.classList.remove('element-hovered');
}
// Remove previous labels
removeElementLabel(doc);
removePageLabel(doc);
// Add highlight to new element (only if not already selected)
if (contentElement && contentElement !== selectedElement.value) {
contentElement.classList.add('element-hovered');
createElementLabel(contentElement);
}
hoveredElement.value = contentElement;
}
} else {
// Clear element hover when hovering page edge
if (contentElement !== hoveredElement.value) {
// Remove highlight from previous element (only if not selected)
if (
hoveredElement.value &&
hoveredElement.value !== selectedElement.value
) {
hoveredElement.value.classList.remove('element-hovered');
hoveredElement.value = null;
}
// Remove element label when hovering page edge
removeElementLabel(event.target.ownerDocument);
// Remove previous label
removeElementLabel(doc);
// Add highlight to new element (only if not already selected)
if (contentElement && contentElement !== selectedElement.value) {
contentElement.classList.add('element-hovered');
createElementLabel(contentElement);
}
hoveredElement.value = contentElement;
}
};
@ -262,6 +256,7 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
const handleIframeClick = (event) => {
const element = event.target;
/* DISABLED: page template styling feature
// Check if clicking near a page edge
if (hoveredPage.value) {
event.stopPropagation();
@ -286,35 +281,28 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
elementPopup.value.close();
return;
}
*/
// Only show popup for elements inside the page template
const isInsidePage = element.closest('.pagedjs_page');
if (!isInsidePage) {
clearSelectedPages();
clearSelectedElement();
elementPopup.value.close();
pagePopup.value.close();
return;
}
// Only show ElementPopup for content elements, not divs
const contentElement = getContentElement(element);
if (!contentElement) {
clearSelectedPages();
clearSelectedElement();
elementPopup.value.close();
pagePopup.value.close();
return;
}
// Clear page selections
clearSelectedPages();
// If popup is already open and we're clicking another element, close it
if (elementPopup.value.visible) {
clearSelectedElement();
elementPopup.value.close();
pagePopup.value.close();
return;
}
@ -332,7 +320,6 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
// Get document and remove labels when opening popup
const doc = event.target.ownerDocument;
removeElementLabel(doc);
removePageLabel(doc);
// Select the new element
selectedElement.value = contentElement;
@ -342,13 +329,14 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
const count = getSimilarElementsCount(contentElement, doc);
elementPopup.value.handleIframeClick(event, contentElement, count);
pagePopup.value.close();
};
// Handlers for popup close events
/* DISABLED: page template styling feature
const handlePagePopupClose = () => {
clearSelectedPages();
};
*/
const handleElementPopupClose = () => {
clearSelectedElement();
@ -356,17 +344,17 @@ export function useIframeInteractions({ elementPopup, pagePopup }) {
return {
// State
hoveredPage,
selectedPages,
// hoveredPage, // DISABLED: page template styling feature
// selectedPages, // DISABLED: page template styling feature
hoveredElement,
selectedElement,
// Handlers
handleIframeMouseMove,
handleIframeClick,
handlePagePopupClose,
// handlePagePopupClose, // DISABLED: page template styling feature
handleElementPopupClose,
// Utilities
clearSelectedPages,
// clearSelectedPages, // DISABLED: page template styling feature
clearSelectedElement,
};
}

View file

@ -7,7 +7,7 @@ import { onMounted, onUnmounted } from 'vue';
export function useKeyboardShortcuts({
stylesheetStore,
elementPopup,
pagePopup,
// pagePopup, // DISABLED: page template styling feature
activeTab,
printPreview
}) {
@ -22,10 +22,12 @@ export function useKeyboardShortcuts({
elementPopup.value.close();
return;
}
/* DISABLED: page template styling feature
if (pagePopup.value?.visible) {
pagePopup.value.close();
return;
}
*/
}
// Backslash key - toggle editor panel

View file

@ -16,6 +16,7 @@ export function usePreviewRenderer({
let savedScrollPercentage = 0;
const currentFrameIndex = ref(1); // 1 or 2, which iframe is currently visible
const isTransitioning = ref(false);
const initialized = ref(false);
let keyboardShortcutHandler = null;
/**
@ -117,6 +118,9 @@ export function usePreviewRenderer({
// Swap current frame
currentFrameIndex.value = currentFrameIndex.value === 1 ? 2 : 1;
isTransitioning.value = false;
if (!initialized.value) {
initialized.value = true;
}
}, 200); // Match CSS transition duration
}, 50); // Small delay to ensure scroll is set
}, 200); // Wait for PagedJS
@ -127,6 +131,7 @@ export function usePreviewRenderer({
watch(
() => stylesheetStore.content,
() => {
if (!initialized.value) return;
renderPreview();
}
);
@ -135,6 +140,7 @@ export function usePreviewRenderer({
watch(
() => narrativeStore.data,
() => {
if (!initialized.value) return;
if (narrativeStore.data) {
renderPreview();
}
@ -152,6 +158,7 @@ export function usePreviewRenderer({
renderPreview,
currentFrameIndex,
isTransitioning,
initialized,
setKeyboardShortcutHandler,
};
}

View file

@ -1 +1 @@
@import '../public/assets/css/style.scss';
/* @import '../public/assets/css/style.scss'; */