- Auto-run toggle with localStorage persistence (toolbar checkbox) - Layout selector: default, top/bottom, editor-only, preview-only - Resizable panels via drag dividers with double-click reset - Emmet abbreviation expansion for HTML, CSS, and JSX - Vim and Emacs keybinding modes with lazy-loaded CDN libraries - Shared preferences module for localStorage management - Editor hooks for tab switch and mode change callbacks
92 lines
2.5 KiB
JavaScript
92 lines
2.5 KiB
JavaScript
import { getPref, setPref } from './preferences.js';
|
|
import { relayoutEditors } from './editors.js';
|
|
|
|
let grid = null;
|
|
let colDivider = null;
|
|
let rowDivider = null;
|
|
let dragging = null; // 'col' | 'row' | null
|
|
|
|
export function initResizer() {
|
|
grid = document.querySelector('.grid');
|
|
colDivider = document.getElementById('divider-col');
|
|
rowDivider = document.getElementById('divider-row');
|
|
|
|
if (!grid || !colDivider || !rowDivider) return;
|
|
|
|
// Restore saved sizes
|
|
const saved = getPref('panelSizes');
|
|
if (saved) applySizes(saved);
|
|
|
|
// Column divider (horizontal drag)
|
|
colDivider.addEventListener('mousedown', (e) => startDrag(e, 'col'));
|
|
colDivider.addEventListener('dblclick', () => resetSizes());
|
|
|
|
// Row divider (vertical drag)
|
|
rowDivider.addEventListener('mousedown', (e) => startDrag(e, 'row'));
|
|
rowDivider.addEventListener('dblclick', () => resetSizes());
|
|
|
|
document.addEventListener('mousemove', onMouseMove);
|
|
document.addEventListener('mouseup', onMouseUp);
|
|
}
|
|
|
|
function startDrag(e, type) {
|
|
e.preventDefault();
|
|
dragging = type;
|
|
document.body.classList.add('resizing');
|
|
}
|
|
|
|
function onMouseMove(e) {
|
|
if (!dragging) return;
|
|
|
|
const rect = grid.getBoundingClientRect();
|
|
|
|
if (dragging === 'col') {
|
|
const x = e.clientX - rect.left;
|
|
const total = rect.width;
|
|
const pct = Math.max(0.15, Math.min(0.85, x / total));
|
|
const left = pct;
|
|
const right = 1 - pct;
|
|
grid.style.gridTemplateColumns = `${left}fr 4px ${right}fr`;
|
|
} else if (dragging === 'row') {
|
|
const y = e.clientY - rect.top;
|
|
const total = rect.height;
|
|
const pct = Math.max(0.15, Math.min(0.85, y / total));
|
|
const top = pct;
|
|
const bottom = 1 - pct;
|
|
grid.style.gridTemplateRows = `${top}fr 4px ${bottom}fr`;
|
|
}
|
|
|
|
relayoutEditors();
|
|
}
|
|
|
|
function onMouseUp() {
|
|
if (!dragging) return;
|
|
dragging = null;
|
|
document.body.classList.remove('resizing');
|
|
|
|
// Persist current sizes
|
|
const sizes = {
|
|
cols: grid.style.gridTemplateColumns || null,
|
|
rows: grid.style.gridTemplateRows || null,
|
|
};
|
|
setPref('panelSizes', sizes);
|
|
relayoutEditors();
|
|
}
|
|
|
|
function applySizes(sizes) {
|
|
if (sizes.cols) grid.style.gridTemplateColumns = sizes.cols;
|
|
if (sizes.rows) grid.style.gridTemplateRows = sizes.rows;
|
|
}
|
|
|
|
export function resetSizes() {
|
|
grid.style.gridTemplateColumns = '';
|
|
grid.style.gridTemplateRows = '';
|
|
setPref('panelSizes', null);
|
|
relayoutEditors();
|
|
}
|
|
|
|
export function clearInlineSizes() {
|
|
grid.style.gridTemplateColumns = '';
|
|
grid.style.gridTemplateRows = '';
|
|
}
|