Expose combined files (page files + map children files) for the cover
field query in the geoformat blueprint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorganize narrative, geoformat, chapter, project and map blueprints
to use tabs layout. Add shared blueprint fields and files tab partials.
Update map block query for new page hierarchy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standardize French template names to English across blueprints,
content files, PHP templates, Vue components and Pinia stores.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Save map data directly via API instead of emit('input') to avoid
draft state. Capture image, clear flag, then reload — the panel
shows the correct image in a single reload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both use field--view-only styling with disabled inputs and
"Fonctionnalité à venir" tooltip. Italic checkbox remains active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep only A4/A5 + "Personnalisé" option. Width/height fields use same
layout as margin fields and are editable only in custom mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Margins: px + mm only. Font sizes: px only.
em/rem buttons are commented out, not deleted, for potential future use.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously, changing unit (e.g. mm → px) kept the numeric value unchanged,
causing visual changes. Now values are converted through a px pivot unit
so the rendered size stays the same.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dispatch input events on color inputs after syncFromStore so Coloris
updates its ::before pseudo-element swatches with loaded values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Properly organize routes following design-to-pack pattern:
- routes/markers/get.php
- routes/markers/create.php
- routes/markers/update.php
- routes/markers/delete.php
- routes/position/update.php
- routes/image/capture.php
- routes/image/check-flag.php
- routes/image/clear-flag.php
Each route in its own file for better maintainability.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Reorganize routes following design-to-pack pattern:
- routes/markers.php: CRUD operations for markers
- routes/position.php: Position update (single mode)
- routes/image.php: Image capture and regeneration flag management
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add html-to-image for capturing map container with markers
- Auto-generate map image on page/marker save via hooks
- Use flag system (.regenerate-map-image) to trigger generation on Panel reload
- Create file using Kirby API for proper indexing
- Add mapStaticImage field in blueprint to display generated image
- Wait for map to be fully loaded before capture
- Capture entire container (map + custom markers)
- Filter MapLibre controls from capture
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add "Définir le cadrage" button in multi mode to save current map
center and zoom as default framing
- Add getCurrentZoom() method in MapPreview to retrieve current zoom level
- Fix: prevent automatic save on initial load with isInitialLoad flag
to avoid marking page as modified when loading existing data
- Style: dark button theme for save framing button
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Generate marker slugs from title (e.g., "marqueur-2") instead of
timestamp-based slugs (e.g., "marker-1770362950"). Also fix panelUrl
generation to use Kirby's panel URL method.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
API now returns iconUrl and iconSize for each marker, allowing custom
marker icons defined in marker.yml to be displayed on the map-editor
field of the parent map page.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Return title directly instead of reading from page object
- Prevents showing identifier/slug before reload
- New markers now display "Marqueur [index]" immediately in list
- Also return num directly for consistency
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add markerIcon files field to marker.yml for custom JPG/PNG/SVG icons
- Add markerIconSize range field (20-500px, default 40px) with unit display
- Layout icon fields side-by-side (50/50 width) in marker blueprint
- Add markerIconUrl prop in index.php to auto-detect uploaded icon
- Add markerIconSize prop in index.php to read size from page data
- Update MapPreview.vue to display custom images instead of default pins
- Set icon dimensions dynamically based on markerIconSize value
- Icon size updates on save/reload (reactive implementation deferred)
- Remove custom tiles background functionality (not needed)
Note: Custom icons show uploaded image, may have white background on
transparent PNGs depending on image processing. Size is non-reactive
and requires save + reload to update in preview.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove custom title field from marker.yml blueprint
- Use default Kirby page title for marker names in MarkerList
- Add French tooltips to MarkerList buttons (Ajouter, Modifier, Supprimer)
- API already uses page title via $marker->title()->value()
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhanced coordinate synchronization in single mode to handle Panel
actions like "Supprimer" (reset to saved values).
Issues Fixed:
- Marker not updating when clicking "Supprimer" button in Panel
- Panel "Supprimer" restores saved coordinates but marker didn't move
- No detection of programmatic field value changes
Solution:
- Add MutationObserver to detect attribute changes on input fields
- Add 500ms polling as fallback for value detection
- Add nextTick() for reactive updates to ensure proper timing
- Handle coordinate reset: when invalid, return to default center
- Proper cleanup with onBeforeUnmount for observers and intervals
Behavior:
- User changes field → marker updates immediately
- User drags marker → fields update immediately
- User clicks "Supprimer" → marker returns to saved position
- Fields cleared → marker disappears, map resets to default center
Technical Details:
- MutationObserver watches 'value' attribute on lat/lon inputs
- Polling checks every 500ms for changes missed by events
- Watcher uses nextTick() to ensure DOM updates complete
- All event listeners and observers properly cleaned up on unmount
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed marker display and centering in single mode (marker pages) by
changing from props-based to form-based coordinate synchronization.
Issues Fixed:
- Kirby blueprint query syntax {{ page.field }} passed literal strings
instead of values to component props
- Invalid coordinates (NaN, NaN) caused map initialization errors
- Marker not displaying in marker page position tab
- Map not centering on marker location
Solution:
- Remove latitude/longitude props from marker.yml blueprint
- Read coordinates directly from Panel form fields via DOM
- Add event listeners to sync form changes with map
- Bidirectional sync: drag marker → updates form fields
- Robust coordinate validation (check for NaN, null, 0)
Changes:
- MapEditor.vue: Add form field reading and event listeners
- MapEditor.vue: Replace props-based coords with reactive refs
- MapEditor.vue: Update marker drag handler to modify form inputs
- marker.yml: Remove non-functional query string props
- routes.php: Use data() instead of body() for all routes
Single Mode Flow:
1. Component reads latitude/longitude from form inputs on mount
2. Creates marker and centers map on valid coordinates
3. Form changes → updates marker position
4. Marker drag → updates form fields (triggers save on user action)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Major refactoring of the map-editor plugin to store markers as Kirby
subpages instead of YAML data, enabling extensible block content.
Backend Changes:
- Add API routes for marker CRUD operations (GET, POST, PATCH, DELETE)
- Create marker.yml blueprint with content & position tabs
- Add markers section to map.yml blueprint
- Update useMapData to only handle center/zoom/background
- Create useMarkersApi composable for API communication
Frontend Changes:
- Refactor MapEditor.vue to support multi/single modes
- Multi mode: loads markers via API, redirects to Panel for editing
- Single mode: displays single marker for position tab in marker page
- Remove MarkerEditor.vue modal (replaced by Panel editing)
- Normalize position format handling (lon vs lng)
API Features:
- Session-based auth for Panel requests (no CSRF needed)
- Proper error handling and validation
- Markers created as listed pages (not drafts)
- Uses Kirby's data() method for JSON parsing
Documentation:
- Add IMPLEMENTATION_SUMMARY.md with technical details
- Add TESTING_CHECKLIST.md with 38 test cases
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement marker editing modal with comprehensive content management:
- MarkerEditor.vue modal with custom overlay (replaces k-dialog)
- Edit marker on double-click or via edit button in list
- Required fields: title (validated), optional description
- Editable position (lat/lon) and custom icon support
- Content blocks system: add/remove/reorder text and image blocks
- French translations for all UI elements
- Click marker in list to center map on it with smooth animation
- Fix marker anchor to bottom (pin tip) for accurate positioning
- Auto-save with isDirty flag to detect any form changes
Modal features:
- Title field (required)
- Description textarea (optional)
- Position inputs (latitude/longitude)
- Icon selector (default or custom via UUID/filename)
- Content builder with text and image blocks
- Block reordering (up/down) and deletion
- Validation: save button enabled only when title filled and form modified
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement Phase 1 of custom Kirby plugin for editing interactive maps:
- OpenStreetMap base layer with MapLibre GL JS
- Click to add markers, drag to reposition
- Marker list sidebar with selection and deletion
- Auto-save with debounce (YAML format)
- Add marker button creates marker at current map center
- Max 50 markers per map (configurable)
- Clean UI with marker counter
Blueprint updated to use new map-editor field type instead of placeholder.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Rename all carte.yml files to map.yml and update references in blueprints to use English naming convention consistently across the codebase. This includes renaming 5 content files and updating template references in narrative and block blueprints.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added Cmd+P (Mac) or Ctrl+P (Windows/Linux) to trigger printPreview():
- Prevents default browser print dialog
- Triggers custom print preview function
- Updated print button tooltip to show keyboard shortcut
- Added platform detection for correct symbol display (⌘ or Ctrl)
Works in all contexts (main document and iframe).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added \ key to toggle the editor panel open/closed:
- Opens to 'document' tab when panel is closed
- Closes panel when it's open
- Updated button tooltips to indicate the keyboard shortcut
Works in all contexts (main document and iframe).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added Escape key handler to close ElementPopup or PagePopup when open.
The handler checks which popup is visible and calls its close method.
Works in all contexts (main document and iframe) using the existing
handleKeyboardShortcut function.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added keyboard event listener to iframe document to capture shortcuts
when user is focused inside the preview. Previously, keyboard events
inside iframes didn't bubble up to the parent document.
Changes:
- Add handleKeyboardShortcut function in App.vue
- Attach keydown listener to main document (for focus outside iframe)
- Attach keydown listener to iframe document (for focus inside iframe)
- Clean up listener on unmount
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix grid layout: add second column for input (grid-template-columns: var(--input-h) 1fr)
- Ensure color picker button is clickable with cursor pointer and pointer-events auto
- Set color picker z-index to 10000 to display above all UI elements
- Add global styles to ensure Coloris button is always clickable
Fixes issues where:
- Color picker appeared behind ElementPopup
- Button was not consistently clickable
- Grid layout was missing second column definition
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add Cmd+S (Mac) or Ctrl+S (Windows/Linux) keyboard shortcut to save CSS
- Detect platform to display correct shortcut symbol (⌘ or Ctrl)
- Prevent default browser save behavior
- Translate tooltips to French
- Show shortcut in button tooltip
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>