- Device breakpoint toggles (mobile 375px / tablet 768px / desktop 100%) - Editor theme selector with 6 themes (VS Dark/Light, High Contrast, Monokai, Dracula, GitHub Dark) - Starter template gallery with 8 pre-built templates (Todo, API Fetch, CSS Animation, etc.) - Code autocomplete with DOM/React type definitions and snippet completions - Devtools panels: console, network, elements, performance - Code formatter (Prettier), diff view, and linter integration
115 lines
3.2 KiB
JavaScript
115 lines
3.2 KiB
JavaScript
import { getActiveEditor, getActiveTab, getEditorValues, getCurrentMode, MODE_TABS } from './editors.js';
|
|
|
|
let diffEditor = null;
|
|
let isActive = false;
|
|
let savedValues = { html: '', css: '', js: '' };
|
|
|
|
export function snapshotValues() {
|
|
const vals = getEditorValues();
|
|
savedValues = { ...vals };
|
|
}
|
|
|
|
export function isDiffActive() {
|
|
return isActive;
|
|
}
|
|
|
|
export function toggleDiff() {
|
|
if (isActive) {
|
|
deactivateDiff();
|
|
} else {
|
|
activateDiff();
|
|
}
|
|
// Update button state
|
|
const btn = document.querySelector('.tab-bar-btn.diff-btn');
|
|
if (btn) btn.classList.toggle('active', isActive);
|
|
}
|
|
|
|
function activateDiff() {
|
|
const tabId = getActiveTab();
|
|
const editor = getActiveEditor();
|
|
if (!editor) return;
|
|
|
|
const container = document.getElementById(`editor-${tabId}`);
|
|
if (!container) return;
|
|
|
|
// Hide the regular editor
|
|
const regularEditorNode = container.querySelector('.monaco-editor');
|
|
if (regularEditorNode) regularEditorNode.style.display = 'none';
|
|
|
|
// Create diff editor container
|
|
const diffContainer = document.createElement('div');
|
|
diffContainer.id = 'diff-editor-container';
|
|
diffContainer.style.cssText = 'position:absolute;top:0;left:0;right:0;bottom:0;';
|
|
container.appendChild(diffContainer);
|
|
|
|
const currentCode = editor.getValue();
|
|
const originalCode = savedValues[tabId] || '';
|
|
|
|
// Determine language from mode tabs
|
|
const mode = getCurrentMode();
|
|
const tabs = MODE_TABS[mode];
|
|
const tabDef = tabs.find(t => t.id === tabId);
|
|
const lang = tabDef ? tabDef.lang : 'plaintext';
|
|
|
|
const originalModel = monaco.editor.createModel(originalCode, lang);
|
|
const modifiedModel = monaco.editor.createModel(currentCode, lang);
|
|
|
|
diffEditor = monaco.editor.createDiffEditor(diffContainer, {
|
|
automaticLayout: true,
|
|
readOnly: false,
|
|
originalEditable: false,
|
|
renderSideBySide: false, // inline diff
|
|
theme: 'vs-dark',
|
|
minimap: { enabled: false },
|
|
fontSize: 13,
|
|
scrollBeyondLastLine: false,
|
|
});
|
|
|
|
diffEditor.setModel({ original: originalModel, modified: modifiedModel });
|
|
isActive = true;
|
|
}
|
|
|
|
function deactivateDiff() {
|
|
const tabId = getActiveTab();
|
|
const editor = getActiveEditor();
|
|
|
|
if (diffEditor) {
|
|
// Sync changes back
|
|
const modified = diffEditor.getModifiedEditor();
|
|
const newCode = modified.getValue();
|
|
if (editor) editor.setValue(newCode);
|
|
|
|
// Dispose models and diff editor
|
|
const model = diffEditor.getModel();
|
|
if (model) {
|
|
if (model.original) model.original.dispose();
|
|
if (model.modified) model.modified.dispose();
|
|
}
|
|
diffEditor.dispose();
|
|
diffEditor = null;
|
|
}
|
|
|
|
// Remove diff container
|
|
const diffContainer = document.getElementById('diff-editor-container');
|
|
if (diffContainer) diffContainer.remove();
|
|
|
|
// Show regular editor
|
|
const container = document.getElementById(`editor-${tabId}`);
|
|
if (container) {
|
|
const regularEditorNode = container.querySelector('.monaco-editor');
|
|
if (regularEditorNode) regularEditorNode.style.display = '';
|
|
}
|
|
|
|
if (editor) editor.layout();
|
|
isActive = false;
|
|
}
|
|
|
|
// Deactivate diff when switching tabs (to avoid stale state)
|
|
export function onTabSwitch() {
|
|
if (isActive) {
|
|
deactivateDiff();
|
|
const btn = document.querySelector('.tab-bar-btn.diff-btn');
|
|
if (btn) btn.classList.remove('active');
|
|
}
|
|
}
|