Files
agent-ui/frontend/src/components/Canvas.vue
2026-02-18 12:13:22 -06:00

110 lines
3.0 KiB
Vue

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { renderInlineComponent, type VueComponentDefinition } from '../services/dynamicComponents'
import { useCanvasStore } from '../stores/canvas'
import CanvasGallery from './CanvasGallery.vue'
const canvasStore = useCanvasStore()
const showGallery = ref(true)
function handleLoadComponent(e: Event) {
const detail = (e as CustomEvent).detail
if (!detail) return
const container = document.getElementById('canvas-content')
if (!container) return
// Hide gallery when MCP renders content
showGallery.value = false
const placeholder = container.querySelector('.canvas-placeholder')
if (placeholder) placeholder.remove()
const definition: VueComponentDefinition = {
id: detail.id,
name: detail.name,
template: detail.template,
setup: detail.setup,
style: detail.style,
props: detail.props,
imports: detail.imports || ['ref', 'reactive', 'computed']
}
const result = renderInlineComponent(definition, container, {}, false)
;(window as any).__vueComponentUnmount = result.unmount
window.dispatchEvent(new CustomEvent('vue-component-rendered', { detail }))
canvasStore.addToHistory({ tool: 'load_vue_component', args: detail, timestamp: Date.now() })
}
function handleContentRendered() {
showGallery.value = false
canvasStore.isAnonymousCanvas = false
}
function handleStartAnonymous() {
showGallery.value = false
canvasStore.isAnonymousCanvas = true
}
function handleClearCanvas() {
showGallery.value = true
canvasStore.isAnonymousCanvas = false
const container = document.getElementById('canvas-content')
if (container) {
// Remove all non-gallery content
const children = Array.from(container.children)
for (const child of children) {
if (!(child as HTMLElement).classList?.contains('canvas-placeholder')) {
child.remove()
}
}
}
}
onMounted(() => {
window.addEventListener('load-vue-component', handleLoadComponent)
window.addEventListener('clear-canvas', handleClearCanvas)
window.addEventListener('canvas-content-rendered', handleContentRendered)
})
onUnmounted(() => {
window.removeEventListener('load-vue-component', handleLoadComponent)
window.removeEventListener('clear-canvas', handleClearCanvas)
window.removeEventListener('canvas-content-rendered', handleContentRendered)
})
</script>
<template>
<div class="canvas-container">
<div id="canvas-content" class="canvas-content">
<div v-if="showGallery" class="canvas-placeholder">
<CanvasGallery @snapshot-restored="showGallery = false" @component-loaded="showGallery = false" @start-anonymous="handleStartAnonymous" />
</div>
</div>
</div>
</template>
<style scoped>
.canvas-container {
flex: 1;
display: flex;
flex-direction: column;
background: var(--bg-primary);
overflow: hidden;
position: relative;
}
.canvas-content {
flex: 1;
position: relative;
min-height: 100%;
overflow: auto;
}
.canvas-placeholder {
height: 100%;
min-height: 400px;
}
</style>