refactor: integrate StylesheetViewer into EditorPanel code tab
Move StylesheetViewer from standalone fixed panel to integrated component within EditorPanel's "code" tab. Maintains full functionality including: - Bidirectional sync with Pinia store and PagedJS preview - Toggle between read/edit modes - CSS syntax highlighting - Debounced updates Changes: - EditorPanel.vue: Import and render StylesheetViewer in code tab - EditorPanel.vue: Add flexbox layout for proper height management - StylesheetViewer.vue: Convert from fixed positioning to flex container - App.vue: Remove standalone StylesheetViewer component 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
19077fb133
commit
7ed57d000b
3 changed files with 49 additions and 46 deletions
19
src/App.vue
19
src/App.vue
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import PagedJsWrapper from './components/PagedJsWrapper.vue';
|
import PagedJsWrapper from './components/PagedJsWrapper.vue';
|
||||||
import EditorPanel from './components/editor/EditorPanel.vue';
|
import EditorPanel from './components/editor/EditorPanel.vue';
|
||||||
import StylesheetViewer from './components/StylesheetViewer.vue';
|
|
||||||
import ElementPopup from './components/ElementPopup.vue';
|
import ElementPopup from './components/ElementPopup.vue';
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { useStylesheetStore } from './stores/stylesheet';
|
import { useStylesheetStore } from './stores/stylesheet';
|
||||||
|
|
@ -42,7 +41,10 @@ const renderPreview = async (shouldReloadFromFile = false) => {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
iframe.onload = () => {
|
iframe.onload = () => {
|
||||||
iframe.contentDocument.addEventListener('click', elementPopup.value.handleIframeClick);
|
iframe.contentDocument.addEventListener(
|
||||||
|
'click',
|
||||||
|
elementPopup.value.handleIframeClick
|
||||||
|
);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const scrollHeight = iframe.contentDocument.documentElement.scrollHeight;
|
const scrollHeight = iframe.contentDocument.documentElement.scrollHeight;
|
||||||
|
|
@ -55,9 +57,12 @@ const renderPreview = async (shouldReloadFromFile = false) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => stylesheetStore.content, () => {
|
watch(
|
||||||
|
() => stylesheetStore.content,
|
||||||
|
() => {
|
||||||
renderPreview();
|
renderPreview();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(() => renderPreview(true));
|
onMounted(() => renderPreview(true));
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -71,8 +76,6 @@ onMounted(() => renderPreview(true));
|
||||||
|
|
||||||
<iframe ref="previewFrame" id="preview-frame"></iframe>
|
<iframe ref="previewFrame" id="preview-frame"></iframe>
|
||||||
|
|
||||||
<StylesheetViewer :stylesheet="stylesheetStore.content" />
|
|
||||||
|
|
||||||
<ElementPopup ref="elementPopup" :iframeRef="previewFrame" />
|
<ElementPopup ref="elementPopup" :iframeRef="previewFrame" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -80,8 +83,8 @@ onMounted(() => renderPreview(true));
|
||||||
#preview-frame {
|
#preview-frame {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 250px;
|
left: 0;
|
||||||
width: calc(100% - 600px);
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<aside id="stylesheet-viewer">
|
<div id="stylesheet-viewer">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h3>Stylesheet</h3>
|
<h3>Stylesheet</h3>
|
||||||
<label class="toggle">
|
<label class="toggle">
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
@input="handleInput"
|
@input="handleInput"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
></textarea>
|
></textarea>
|
||||||
</aside>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
@ -53,14 +53,9 @@ const handleInput = (event) => {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#stylesheet-viewer {
|
#stylesheet-viewer {
|
||||||
position: fixed;
|
display: flex;
|
||||||
top: 0;
|
flex-direction: column;
|
||||||
right: 0;
|
height: 100%;
|
||||||
width: 350px;
|
|
||||||
height: 100vh;
|
|
||||||
padding: 1rem;
|
|
||||||
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
||||||
overflow-y: auto;
|
|
||||||
background: #282c34;
|
background: #282c34;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +125,7 @@ h3 {
|
||||||
|
|
||||||
.readonly {
|
.readonly {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: calc(100vh - 5rem);
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
|
|
@ -145,7 +140,7 @@ h3 {
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 5rem);
|
flex: 1;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
color: #abb2bf;
|
color: #abb2bf;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<nav class="tabs">
|
<nav class="tabs">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="tab"
|
||||||
:class="{ active: activeTab === 'document' }"
|
:class="{ active: activeTab === 'document' }"
|
||||||
@click="activeTab = 'document'"
|
@click="activeTab = 'document'"
|
||||||
>
|
>
|
||||||
|
|
@ -10,6 +11,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="tab"
|
||||||
:class="{ active: activeTab === 'code' }"
|
:class="{ active: activeTab === 'code' }"
|
||||||
@click="activeTab = 'code'"
|
@click="activeTab = 'code'"
|
||||||
>
|
>
|
||||||
|
|
@ -17,6 +19,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="tab"
|
||||||
:class="{ active: activeTab === 'contenu' }"
|
:class="{ active: activeTab === 'contenu' }"
|
||||||
@click="activeTab = 'contenu'"
|
@click="activeTab = 'contenu'"
|
||||||
>
|
>
|
||||||
|
|
@ -31,7 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'code'" class="tab-panel">
|
<div v-else-if="activeTab === 'code'" class="tab-panel">
|
||||||
<!-- Code tab content -->
|
<StylesheetViewer />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'contenu'" class="tab-panel">
|
<div v-else-if="activeTab === 'contenu'" class="tab-panel">
|
||||||
|
|
@ -45,40 +48,42 @@
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageSettings from './PageSettings.vue';
|
import PageSettings from './PageSettings.vue';
|
||||||
import TextSettings from './TextSettings.vue';
|
import TextSettings from './TextSettings.vue';
|
||||||
|
import StylesheetViewer from '../StylesheetViewer.vue';
|
||||||
|
|
||||||
// Tab management
|
// Tab management
|
||||||
const activeTab = ref('document');
|
const activeTab = ref('document');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
#editor-panel {
|
#editor-panel {
|
||||||
|
padding: 1rem;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 250px;
|
width: 25rem;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: #f5f5f5;
|
display: flex;
|
||||||
padding: 1rem;
|
flex-direction: column;
|
||||||
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
|
z-index: 2;
|
||||||
|
|
||||||
|
background-color: var(--color-panel-bg);
|
||||||
|
box-shadow: -5px 0px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-panel {
|
||||||
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control input {
|
|
||||||
width: 80px;
|
|
||||||
padding: 0.25rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue