Add editor experience features: auto-run, layouts, resizable panels, Emmet, vim/emacs
- 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
This commit is contained in:
91
public/js/resizer.js
Normal file
91
public/js/resizer.js
Normal file
@@ -0,0 +1,91 @@
|
||||
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 = '';
|
||||
}
|
||||
Reference in New Issue
Block a user