140 lines
3.7 KiB
TypeScript
140 lines
3.7 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import {
|
|
DockviewReact,
|
|
DockviewReadyEvent,
|
|
DockviewApi,
|
|
themeAbyss,
|
|
themeLight,
|
|
} from 'dockview';
|
|
import { useMantineColorScheme, useComputedColorScheme } from '@mantine/core';
|
|
import { useDockviewStore } from '../stores/useDockviewStore';
|
|
import { Welcome } from './Welcome/Welcome';
|
|
import { ColorSchemeToggle } from './ColorSchemeToggle/ColorSchemeToggle';
|
|
import 'dockview/dist/styles/dockview.css';
|
|
|
|
export function DockviewLayoutManager() {
|
|
const hostRef = useRef<HTMLDivElement | null>(null);
|
|
const apiRef = useRef<DockviewApi | null>(null);
|
|
const { layoutConfig, setLayoutConfig } = useDockviewStore();
|
|
|
|
// 🎨 Detecta automáticamente el tema de Mantine (light / dark / system)
|
|
const { colorScheme } = useMantineColorScheme();
|
|
const computedScheme = useComputedColorScheme('light', {
|
|
getInitialValueInEffect: true,
|
|
});
|
|
|
|
// ⚡ Inicializa Dockview al estar listo
|
|
const onReady = (event: DockviewReadyEvent) => {
|
|
const api = event.api;
|
|
apiRef.current = api;
|
|
|
|
if (layoutConfig) {
|
|
try {
|
|
api.fromJSON(layoutConfig);
|
|
} catch {
|
|
console.warn('Error loading saved Dockview layout, using default');
|
|
createDefaultLayout(api);
|
|
}
|
|
} else {
|
|
createDefaultLayout(api);
|
|
}
|
|
|
|
// 🧠 Guarda el layout cuando cambia
|
|
api.onDidLayoutChange(() => {
|
|
const saved = api.toJSON();
|
|
setLayoutConfig(saved);
|
|
});
|
|
};
|
|
|
|
// 🌗 Sincroniza Dockview con el tema de Mantine automáticamente
|
|
useEffect(() => {
|
|
const el = hostRef.current;
|
|
if (!el) return;
|
|
|
|
// Remueve las clases anteriores
|
|
el.classList.remove('dockview-theme-dark', 'dockview-theme-light');
|
|
|
|
// Aplica el tema adecuado
|
|
const isDark = computedScheme === 'dark';
|
|
el.classList.add(isDark ? 'dockview-theme-dark' : 'dockview-theme-light');
|
|
el.style.backgroundColor = isDark ? '#1A1B1E' : '#f5f6f7';
|
|
}, [computedScheme]);
|
|
|
|
// 🧱 Layout inicial por defecto
|
|
const createDefaultLayout = (api: DockviewApi) => {
|
|
const welcome = api.addPanel({
|
|
id: 'welcome',
|
|
component: 'welcome',
|
|
title: 'Welcome',
|
|
});
|
|
|
|
api.addPanel({
|
|
id: 'toggle',
|
|
component: 'toggle',
|
|
title: 'Theme',
|
|
position: {
|
|
referencePanel: welcome,
|
|
direction: 'right',
|
|
},
|
|
});
|
|
};
|
|
|
|
// ⚙️ Tema de Dockview sincronizado con Mantine
|
|
const dockviewTheme = computedScheme === 'dark' ? themeAbyss : themeLight;
|
|
|
|
return (
|
|
<div
|
|
ref={hostRef}
|
|
style={{
|
|
flex: 1,
|
|
width: '100%',
|
|
height: '100%',
|
|
display: 'flex',
|
|
overflow: 'hidden',
|
|
transition: 'background-color 0.3s ease-in-out',
|
|
}}
|
|
>
|
|
<DockviewReact
|
|
theme={dockviewTheme} // 🔥 Tema dinámico oficial de Dockview
|
|
components={{
|
|
welcome: (props) => (
|
|
<ResponsivePanel component="welcome" {...props} />
|
|
),
|
|
toggle: (props) => (
|
|
<ResponsivePanel component="toggle" {...props} />
|
|
),
|
|
}}
|
|
onReady={onReady}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// ✅ Panel adaptable al tamaño
|
|
function ResponsivePanel({
|
|
component,
|
|
api,
|
|
}: {
|
|
component: 'welcome' | 'toggle';
|
|
api: any;
|
|
}) {
|
|
const [size, setSize] = useState({ width: api.width, height: api.height });
|
|
|
|
useEffect(() => {
|
|
const unsubscribe = api.onDidDimensionsChange(() => {
|
|
setSize({ width: api.width, height: api.height });
|
|
});
|
|
return () => unsubscribe.dispose();
|
|
}, [api]);
|
|
|
|
if (component === 'welcome') {
|
|
return <Welcome width={size.width} height={size.height} />;
|
|
}
|
|
|
|
if (component === 'toggle') {
|
|
return <ColorSchemeToggle width={size.width} height={size.height} />;
|
|
}
|
|
|
|
return null;
|
|
}
|