This repository has been archived on 2025-11-27. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
better_appshell/src/components/DockviewLayoutManager.tsx
T

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;
}