feat: implement preview fit mode controls and overlay for improved visualization management

This commit is contained in:
2025-10-18 02:52:48 +03:00
parent 73a5f69dde
commit 9ef7b1188f
5 changed files with 120 additions and 3 deletions

View File

@@ -378,6 +378,19 @@ document.addEventListener('DOMContentLoaded', function () {
switchViewMode('published');
});
// Preview fit mode buttons
document.getElementById('preview-fit-default').addEventListener('click', () => {
setPreviewFitMode('default');
});
document.getElementById('preview-fit-width').addEventListener('click', () => {
setPreviewFitMode('width');
});
document.getElementById('preview-fit-full').addEventListener('click', () => {
setPreviewFitMode('full');
});
// Publish and Revert buttons
document.getElementById('publish-btn').addEventListener('click', publishDraft);
document.getElementById('revert-btn').addEventListener('click', revertDraft);

View File

@@ -1,3 +1,34 @@
// Track preview fit mode
let previewFitMode = 'default'; // 'default', 'width', or 'full'
// Apply fit mode to spec dimensions
function applyPreviewFitMode(spec, fitMode) {
if (!spec || typeof spec !== 'object') return spec;
// Clone to avoid mutation
const modifiedSpec = JSON.parse(JSON.stringify(spec));
if (fitMode === 'width') {
// Fit to width - get preview pane width
const previewPane = document.getElementById('vega-preview');
if (previewPane) {
const containerWidth = previewPane.offsetWidth;
modifiedSpec.width = containerWidth - 10; // 10px padding for scroll
// Keep original aspect ratio by not setting height
}
} else if (fitMode === 'full') {
// Fit to full pane - get both dimensions
const previewPane = document.getElementById('vega-preview');
if (previewPane) {
modifiedSpec.width = previewPane.offsetWidth - 10; // 10px padding
modifiedSpec.height = previewPane.offsetHeight - 10; // 10px padding
}
}
// 'default' mode leaves original dimensions untouched
return modifiedSpec;
}
// Resolve dataset references in a spec
async function resolveDatasetReferences(spec) {
// If spec has data.name, look it up
@@ -83,12 +114,18 @@ async function renderVisualization() {
// Resolve dataset references
spec = await resolveDatasetReferences(spec);
// Apply preview fit mode
spec = applyPreviewFitMode(spec, previewFitMode);
// Render with Vega-Embed (use global variable)
await window.vegaEmbed('#vega-preview', spec, {
actions: false, // Hide action menu for cleaner look
renderer: 'svg' // Use SVG for better quality
});
// Hide overlay after successful render
hidePreviewOverlay();
} catch (error) {
// Handle rendering errors gracefully
previewContainer.innerHTML = `
@@ -99,6 +136,9 @@ async function renderVisualization() {
<em>Check your JSON syntax and Vega-Lite specification.</em>
</div>
`;
// Hide overlay after error
hidePreviewOverlay();
}
}
@@ -110,6 +150,9 @@ function debouncedRender() {
return;
}
// Show overlay to indicate rendering is pending
showPreviewOverlay();
clearTimeout(renderTimeout);
const debounceTime = getSetting('performance.renderDebounce') || 1500;
renderTimeout = setTimeout(renderVisualization, debounceTime);
@@ -121,6 +164,42 @@ function updateRenderDebounce(newDebounce) {
// No need to do anything special here
}
// Set preview fit mode and update button states
function setPreviewFitMode(mode) {
previewFitMode = mode;
// Update button states
document.getElementById('preview-fit-default').classList.toggle('active', mode === 'default');
document.getElementById('preview-fit-width').classList.toggle('active', mode === 'width');
document.getElementById('preview-fit-full').classList.toggle('active', mode === 'full');
// Re-render with new fit mode
renderVisualization();
}
// Show preview overlay (dims the visualization)
function showPreviewOverlay() {
const overlay = document.getElementById('preview-overlay');
if (overlay) {
overlay.style.display = 'block';
// Trigger reflow to enable transition
void overlay.offsetHeight;
overlay.classList.add('active');
}
}
// Hide preview overlay
function hidePreviewOverlay() {
const overlay = document.getElementById('preview-overlay');
if (overlay) {
overlay.classList.remove('active');
// Wait for transition to finish before hiding
setTimeout(() => {
overlay.style.display = 'none';
}, 200);
}
}
// Load Vega libraries dynamically with UMD builds
function loadVegaLibraries() {
return new Promise((resolve, reject) => {

View File

@@ -148,6 +148,11 @@ function initializeResize() {
document.body.style.cursor = 'col-resize';
document.body.style.userSelect = 'none';
// Show overlay if resizing preview panel (in non-default fit mode)
if (typeof previewFitMode !== 'undefined' && previewFitMode !== 'default') {
showPreviewOverlay();
}
e.preventDefault();
});
});
@@ -194,6 +199,11 @@ function initializeResize() {
updatePanelMemory();
saveLayoutToStorage();
// Re-render preview if fit mode is not 'default' (adaptive re-render on resize)
if (typeof previewFitMode !== 'undefined' && previewFitMode !== 'default') {
debouncedRender();
}
}
});
}