mirror of
https://github.com/olehomelchenko/astrolabe-nvc.git
synced 2025-12-21 13:12:23 +00:00
feat: Add preview fit mode for height and utilize Vega-Lite's 'container' keyword for dynamic sizing.
This commit is contained in:
22
index.html
22
index.html
@@ -233,6 +233,10 @@
|
|||||||
@click="$store.preview.fitMode = 'width'; setPreviewFitMode('width')"
|
@click="$store.preview.fitMode = 'width'; setPreviewFitMode('width')"
|
||||||
id="preview-fit-width"
|
id="preview-fit-width"
|
||||||
title="Scale to fit preview pane width (⚠️ for faceted specs, applies to each facet)">Width</button>
|
title="Scale to fit preview pane width (⚠️ for faceted specs, applies to each facet)">Width</button>
|
||||||
|
<button class="btn btn-toggle" :class="{ 'active': $store.preview.fitMode === 'height' }"
|
||||||
|
@click="$store.preview.fitMode = 'height'; setPreviewFitMode('height')"
|
||||||
|
id="preview-fit-height"
|
||||||
|
title="Scale to fit preview pane height (⚠️ for faceted specs, applies to each facet)">Height</button>
|
||||||
<button class="btn btn-toggle" :class="{ 'active': $store.preview.fitMode === 'full' }"
|
<button class="btn btn-toggle" :class="{ 'active': $store.preview.fitMode === 'full' }"
|
||||||
@click="$store.preview.fitMode = 'full'; setPreviewFitMode('full')"
|
@click="$store.preview.fitMode = 'full'; setPreviewFitMode('full')"
|
||||||
id="preview-fit-full"
|
id="preview-fit-full"
|
||||||
@@ -308,12 +312,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dataset-detail-header">Name</div>
|
<div class="dataset-detail-header">Name</div>
|
||||||
<input type="text" id="dataset-detail-name" class="input"
|
<input type="text" id="dataset-detail-name" class="input" placeholder="Dataset name..."
|
||||||
placeholder="Dataset name..." :value="dataset?.name" @input="handleNameChange" />
|
:value="dataset?.name" @input="handleNameChange" />
|
||||||
|
|
||||||
<div class="dataset-detail-header">Comment</div>
|
<div class="dataset-detail-header">Comment</div>
|
||||||
<textarea id="dataset-detail-comment" class="input textarea"
|
<textarea id="dataset-detail-comment" class="input textarea"
|
||||||
placeholder="Add a comment..." rows="3" :value="dataset?.comment" @input="handleCommentChange"></textarea>
|
placeholder="Add a comment..." rows="3" :value="dataset?.comment"
|
||||||
|
@input="handleCommentChange"></textarea>
|
||||||
|
|
||||||
<div class="dataset-detail-header-row">
|
<div class="dataset-detail-header-row">
|
||||||
<span class="dataset-detail-header">Overview</span>
|
<span class="dataset-detail-header">Overview</span>
|
||||||
@@ -344,7 +349,8 @@
|
|||||||
<div class="columns-list">
|
<div class="columns-list">
|
||||||
<template x-for="col in dataset?.columnTypes" :key="col.name">
|
<template x-for="col in dataset?.columnTypes" :key="col.name">
|
||||||
<div class="column-item">
|
<div class="column-item">
|
||||||
<span class="column-type-icon" x-html="getTypeIcon(col.type)"></span>
|
<span class="column-type-icon"
|
||||||
|
x-html="getTypeIcon(col.type)"></span>
|
||||||
<span class="column-name" x-text="col.name"></span>
|
<span class="column-name" x-text="col.name"></span>
|
||||||
<span class="column-type" x-text="col.type"></span>
|
<span class="column-type" x-text="col.type"></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -361,7 +367,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="stat-item">
|
<div class="stat-item">
|
||||||
<span class="stat-label">Modified:</span>
|
<span class="stat-label">Modified:</span>
|
||||||
<span id="dataset-detail-modified" x-text="formatDate(dataset?.modified)">-</span>
|
<span id="dataset-detail-modified"
|
||||||
|
x-text="formatDate(dataset?.modified)">-</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -372,8 +379,7 @@
|
|||||||
<div class="preview-toggle-group" x-show="showPreviewToggle">
|
<div class="preview-toggle-group" x-show="showPreviewToggle">
|
||||||
<button class="btn btn-toggle small"
|
<button class="btn btn-toggle small"
|
||||||
:class="{ 'active': $store.datasets.previewMode === 'raw' }"
|
:class="{ 'active': $store.datasets.previewMode === 'raw' }"
|
||||||
@click="setPreviewMode('raw')"
|
@click="setPreviewMode('raw')" title="Show raw data preview">Raw</button>
|
||||||
title="Show raw data preview">Raw</button>
|
|
||||||
<button class="btn btn-toggle small"
|
<button class="btn btn-toggle small"
|
||||||
:class="{ 'active': $store.datasets.previewMode === 'table' }"
|
:class="{ 'active': $store.datasets.previewMode === 'table' }"
|
||||||
@click="setPreviewMode('table')"
|
@click="setPreviewMode('table')"
|
||||||
@@ -394,7 +400,7 @@
|
|||||||
<span class="stat-label">📄</span>
|
<span class="stat-label">📄</span>
|
||||||
<span>
|
<span>
|
||||||
<a href="#" @click.prevent="openLinkedSnippet(snippet.id)"
|
<a href="#" @click.prevent="openLinkedSnippet(snippet.id)"
|
||||||
class="snippet-link" x-text="snippet.name"></a>
|
class="snippet-link" x-text="snippet.name"></a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ document.addEventListener('alpine:init', () => {
|
|||||||
|
|
||||||
// Preview panel fit mode store
|
// Preview panel fit mode store
|
||||||
Alpine.store('preview', {
|
Alpine.store('preview', {
|
||||||
fitMode: 'default' // 'default' | 'width' | 'full'
|
fitMode: 'default' // 'default' | 'width' | 'height' | 'full'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +1,53 @@
|
|||||||
// Track preview fit mode
|
// Track preview fit mode
|
||||||
let previewFitMode = 'default'; // 'default', 'width', or 'full'
|
let previewFitMode = 'default'; // 'default', 'width', 'height', or 'full'
|
||||||
|
|
||||||
// Apply fit mode to spec dimensions
|
// Apply fit mode to spec dimensions using Vega-Lite's "container" keyword
|
||||||
function applyPreviewFitMode(spec, fitMode) {
|
function applyPreviewFitMode(spec, fitMode) {
|
||||||
if (!spec || typeof spec !== 'object') return spec;
|
if (!spec || typeof spec !== 'object') return spec;
|
||||||
|
|
||||||
// Clone to avoid mutation
|
// Clone to avoid mutation
|
||||||
const modifiedSpec = JSON.parse(JSON.stringify(spec));
|
const modifiedSpec = JSON.parse(JSON.stringify(spec));
|
||||||
|
|
||||||
if (fitMode === 'width' || fitMode === 'full') {
|
// Apply dimensions recursively to handle nested specs
|
||||||
const previewPane = document.getElementById('vega-preview');
|
function applyDimensions(s) {
|
||||||
if (previewPane) {
|
if (!s || typeof s !== 'object') return;
|
||||||
const containerWidth = previewPane.offsetWidth - 10; // 10px padding for scroll
|
|
||||||
const containerHeight = previewPane.offsetHeight - 10; // 10px padding
|
|
||||||
|
|
||||||
// Apply dimensions recursively to handle nested specs
|
// Apply dimensions based on fit mode
|
||||||
function applyDimensions(s) {
|
if (fitMode === 'width') {
|
||||||
if (!s || typeof s !== 'object') return;
|
s.width = 'container';
|
||||||
|
delete s.height; // Remove height to preserve aspect ratio
|
||||||
|
} else if (fitMode === 'height') {
|
||||||
|
s.height = 'container';
|
||||||
|
delete s.width; // Remove width to preserve aspect ratio
|
||||||
|
} else if (fitMode === 'full') {
|
||||||
|
s.width = 'container';
|
||||||
|
s.height = 'container';
|
||||||
|
}
|
||||||
|
// 'default' mode leaves original dimensions untouched
|
||||||
|
|
||||||
// Set dimensions at current level if this is a unit spec or has width/height
|
// Recursively apply to nested specs
|
||||||
if (fitMode === 'width') {
|
// For facet specs
|
||||||
s.width = containerWidth;
|
if (s.spec) {
|
||||||
delete s.height; // Remove height to preserve aspect ratio
|
applyDimensions(s.spec);
|
||||||
} else if (fitMode === 'full') {
|
}
|
||||||
s.width = containerWidth;
|
// For layer, concat, hconcat, vconcat
|
||||||
s.height = containerHeight;
|
if (Array.isArray(s.layer)) {
|
||||||
}
|
s.layer.forEach(applyDimensions);
|
||||||
|
}
|
||||||
// Recursively apply to nested specs
|
if (Array.isArray(s.concat)) {
|
||||||
// For facet specs
|
s.concat.forEach(applyDimensions);
|
||||||
if (s.spec) {
|
}
|
||||||
applyDimensions(s.spec);
|
if (Array.isArray(s.hconcat)) {
|
||||||
}
|
s.hconcat.forEach(applyDimensions);
|
||||||
// For layer, concat, hconcat, vconcat
|
}
|
||||||
if (Array.isArray(s.layer)) {
|
if (Array.isArray(s.vconcat)) {
|
||||||
s.layer.forEach(applyDimensions);
|
s.vconcat.forEach(applyDimensions);
|
||||||
}
|
|
||||||
if (Array.isArray(s.concat)) {
|
|
||||||
s.concat.forEach(applyDimensions);
|
|
||||||
}
|
|
||||||
if (Array.isArray(s.hconcat)) {
|
|
||||||
s.hconcat.forEach(applyDimensions);
|
|
||||||
}
|
|
||||||
if (Array.isArray(s.vconcat)) {
|
|
||||||
s.vconcat.forEach(applyDimensions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyDimensions(modifiedSpec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 'default' mode leaves original dimensions untouched
|
|
||||||
|
if (fitMode !== 'default') {
|
||||||
|
applyDimensions(modifiedSpec);
|
||||||
|
}
|
||||||
|
|
||||||
return modifiedSpec;
|
return modifiedSpec;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user