geoproject-app/src/components/ElementPopup.vue
isUnknown e8298a9fbf refactor: implement Pinia store for stylesheet management
- Add Pinia state management
- Create centralized stylesheet store with utility methods
- Extract CSS parsing utilities to src/utils/css-parsing.js
- Refactor ElementPopup to manage state independently via store
- Simplify App.vue by removing prop drilling
- Fix iframe rendering with srcdoc instead of document.write
- Improve API: updateProperty uses object parameter for clarity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 17:55:42 +01:00

172 lines
3.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
v-if="visible"
id="element-popup"
:style="{ top: position.y + 'px', left: position.x + 'px' }"
>
<div class="popup-header">
<span>{{ selector }}</span>
<button class="close-btn" @click="$emit('close')">×</button>
</div>
<div class="popup-body">
<div class="popup-controls">
<div class="control" v-if="fontSizeData">
<label>font-size</label>
<input
type="number"
step="0.1"
:value="fontSizeData.value"
@input="updateFontSize(parseFloat($event.target.value))"
/>
<span>{{ fontSizeData.unit }}</span>
</div>
<p v-else class="no-styles">Aucun style éditable</p>
</div>
<div class="popup-css">
<pre><code class="hljs language-css" v-html="highlightedCss"></code></pre>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useStylesheetStore } from '../stores/stylesheet';
import hljs from 'highlight.js/lib/core';
import css from 'highlight.js/lib/languages/css';
import 'highlight.js/styles/github.css';
hljs.registerLanguage('css', css);
const stylesheetStore = useStylesheetStore();
const props = defineProps({
visible: Boolean,
position: Object,
selector: String
});
defineEmits(['close']);
const elementCss = computed(() => {
if (!props.selector) return '';
return stylesheetStore.extractBlock(props.selector);
});
const fontSizeData = computed(() => {
if (!props.selector) return null;
return stylesheetStore.extractValue(props.selector, 'font-size');
});
const highlightedCss = computed(() => {
if (!elementCss.value) return '<span class="no-css">Aucun style défini</span>';
return hljs.highlight(elementCss.value, { language: 'css' }).value;
});
const updateFontSize = (value) => {
if (!fontSizeData.value) return;
stylesheetStore.updateProperty(
props.selector,
'font-size',
value,
fontSizeData.value.unit
);
};
</script>
<style scoped>
#element-popup {
position: fixed;
background: white;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 10000;
min-width: 400px;
max-width: 500px;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 0.75rem;
border-bottom: 1px solid #eee;
font-size: 0.875rem;
font-weight: bold;
background: #f5f5f5;
}
.close-btn {
background: none;
border: none;
cursor: pointer;
font-size: 1.25rem;
line-height: 1;
padding: 0;
}
.popup-body {
display: flex;
gap: 1px;
background: #eee;
}
.popup-controls {
flex: 1;
padding: 0.75rem;
background: white;
}
.popup-css {
flex: 1;
padding: 0.75rem;
background: #1e1e1e;
max-height: 200px;
overflow-y: auto;
}
.popup-css pre {
margin: 0;
font-size: 0.75rem;
line-height: 1.4;
}
.popup-css code {
background: transparent;
color: #fff;
}
.control {
margin-bottom: 0.5rem;
}
.control label {
display: block;
font-size: 0.75rem;
margin-bottom: 0.25rem;
color: #666;
}
.control input {
width: 60px;
padding: 0.25rem;
font-size: 0.875rem;
}
.control span {
font-size: 0.75rem;
color: #666;
margin-left: 0.25rem;
}
.no-styles {
font-size: 0.75rem;
color: #999;
margin: 0;
}
.no-css {
color: #666;
font-style: italic;
}
</style>