feat: Add floating window system for canvas components

- Add WindowContainer.vue with Liquid Glass styling, drag, resize, close
- Add windows store for managing window state (position, size, z-index)
- Modify dynamicComponents.ts to wrap Vue components in floating windows
- Add MCP tools: move_window, resize_window, close_window, list_windows
- Add isolated Claude profiles (ejecutor, nucleo000) with versioned configs
This commit is contained in:
2026-02-14 20:04:11 -06:00
parent 39faf4bf77
commit d9eaba393b
15 changed files with 1008 additions and 23 deletions

View File

@@ -0,0 +1,125 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export interface WindowState {
id: string
title: string
x: number
y: number
width: number
height: number
zIndex: number
}
export const useWindowsStore = defineStore('windows', () => {
const windows = ref<Map<string, WindowState>>(new Map())
const maxZIndex = ref(100)
const windowOffset = ref(0)
// Getters
const windowsList = computed(() => Array.from(windows.value.values()))
const windowCount = computed(() => windows.value.size)
// Obtener siguiente posición para ventana nueva (cascada)
function getNextPosition() {
const offset = windowOffset.value * 30
windowOffset.value = (windowOffset.value + 1) % 10
return { x: 50 + offset, y: 50 + offset }
}
// Registrar nueva ventana
function register(id: string, state: Partial<WindowState> = {}) {
const pos = state.x !== undefined && state.y !== undefined
? { x: state.x, y: state.y }
: getNextPosition()
windows.value.set(id, {
id,
title: state.title ?? id,
x: pos.x,
y: pos.y,
width: state.width ?? 400,
height: state.height ?? 300,
zIndex: ++maxZIndex.value
})
return windows.value.get(id)!
}
// Traer ventana al frente
function bringToFront(id: string) {
const win = windows.value.get(id)
if (win) {
win.zIndex = ++maxZIndex.value
}
}
// Actualizar posición
function updatePosition(id: string, x: number, y: number) {
const win = windows.value.get(id)
if (win) {
win.x = x
win.y = y
}
}
// Actualizar tamaño
function updateSize(id: string, width: number, height: number) {
const win = windows.value.get(id)
if (win) {
win.width = width
win.height = height
}
}
// Actualizar título
function updateTitle(id: string, title: string) {
const win = windows.value.get(id)
if (win) {
win.title = title
}
}
// Eliminar ventana
function remove(id: string) {
windows.value.delete(id)
}
// Obtener ventana por ID
function get(id: string) {
return windows.value.get(id)
}
// Verificar si existe
function has(id: string) {
return windows.value.has(id)
}
// Limpiar todas las ventanas
function clear() {
windows.value.clear()
windowOffset.value = 0
}
return {
// State
windows,
maxZIndex,
// Getters
windowsList,
windowCount,
// Actions
register,
bringToFront,
updatePosition,
updateSize,
updateTitle,
remove,
get,
has,
clear,
getNextPosition
}
})