import { h, ref, computed, onMounted, watch } from 'vue'; import { PaneCP } from './PaneCP.js'; import { PaneFO } from './PaneFO.js'; import { PaneSubObjects } from './PaneSubObjects.js'; import { ImportDialog } from './ImportDialog.js'; import { getKindGroups, KIND_LABEL } from '../subobject-kinds.js'; const FIXED_PANES = [ { id: 'cp', label: 'CP', title: 'Current position' }, { id: 'fo', label: 'FO', title: 'Focused object' }, ]; export const AppShell = { props: ['store', 'importOnLoad'], setup(props) { const activePane = ref('cp'); const showImport = ref(false); function focusedNode() { const fp = props.store.focusPath; return fp.length ? fp[fp.length - 1] : props.store.scoreModel; } const subPanes = computed(() => getKindGroups(focusedNode()).map(g => ({ id: `sub:${g.kind}`, kind: g.kind, label: KIND_LABEL[g.kind] ?? g.kind.slice(0, 2).toUpperCase(), title: g.kind, }))); const panes = computed(() => [...FIXED_PANES, ...subPanes.value]); // If active pane disappears after focus change, drop back to FO. watch(panes, ps => { if (!ps.some(p => p.id === activePane.value)) activePane.value = 'fo'; }); function openImport() { if (!props.store.isDirty) showImport.value = true; } onMounted(() => { if (props.importOnLoad && !props.store.isDirty) showImport.value = true; }); return () => { const store = props.store; const ap = activePane.value; const subPaneNodes = subPanes.value.map(p => h('div', { key: p.id, class: ['se-pane', ap === p.id ? 'active' : null] }, h(PaneSubObjects, { store, kind: p.kind, onFocusFO: () => { activePane.value = 'fo'; } }))); return h('div', { class: 'se-shell' }, [ h('div', { class: 'se-pane-area' }, [ h('div', { class: ['se-pane', ap === 'cp' ? 'active' : null] }, h(PaneCP, { store, onImportClick: openImport, onFocusFO: () => { activePane.value = 'fo'; } })), h('div', { class: ['se-pane', ap === 'fo' ? 'active' : null] }, h(PaneFO, { store })), ...subPaneNodes, ]), h('div', { class: 'se-handle-bar' }, panes.value.map(p => h('button', { key: p.id, class: ['se-handle', ap === p.id ? 'active' : null], title: p.title, onClick: () => { activePane.value = p.id; }, }, p.label) )), store.errorMessage ? h('div', { class: 'se-error', style: 'margin:0' }, store.errorMessage) : null, showImport.value ? h(ImportDialog, { store, onClose: () => { showImport.value = false; } }) : null, ]); }; }, };