Spaces:
Running
Running
Update script.js
Browse files
script.js
CHANGED
|
@@ -54,6 +54,11 @@ let modalThinkingBudgetSliderEl, modalThinkingBudgetValueDisplayEl;
|
|
| 54 |
let promptDisplayModalOverlayEl, promptDisplayModalContentEl, fullPromptTextEl, promptDisplayModalCloseBtnEl;
|
| 55 |
let showPromptModalButtonEl; // Added for the new button
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
// --- Constants ---
|
| 59 |
const API_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/models/';
|
|
@@ -282,7 +287,20 @@ async function generateVariations() {
|
|
| 282 |
return;
|
| 283 |
}
|
| 284 |
|
| 285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
const selectedModel = modelSelEl.value;
|
| 287 |
const currentIsRefinementMode = modalRefinementCheckboxEl.checked;
|
| 288 |
const currentNumVariations = parseInt(numVariationsSliderEl.value, 10);
|
|
@@ -290,7 +308,11 @@ async function generateVariations() {
|
|
| 290 |
|
| 291 |
if (!apiKey || !userPrompt) {
|
| 292 |
errorMessageEl.textContent = 'Error: API Key and Prompt (via Alt+P) are required.';
|
| 293 |
-
if (!
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
return;
|
| 295 |
}
|
| 296 |
if (!selectedModel) {
|
|
@@ -320,6 +342,10 @@ async function generateVariations() {
|
|
| 320 |
console.log(`Refining Evolution ${activeTimelineIndex + 1}. Original context: "${contextPromptForRefinement}"`);
|
| 321 |
} else if (currentIsRefinementMode) {
|
| 322 |
errorMessageEl.textContent = 'Error: No active evolution selected to refine. Uncheck "refine" or select an evolution from history.';
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
return;
|
| 324 |
}
|
| 325 |
|
|
@@ -339,6 +365,20 @@ async function generateVariations() {
|
|
| 339 |
fullscreenButtons = Array(numVariationsToGenerate).fill(null);
|
| 340 |
previewItems = Array(numVariationsToGenerate).fill(null);
|
| 341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
|
| 343 |
showFourGridPreviewUI();
|
| 344 |
|
|
@@ -501,6 +541,20 @@ function showSingleLargePreviewUI(htmlContent, titleText, fullPromptText) {
|
|
| 501 |
previewGridWrapperEl.className = 'single-mode';
|
| 502 |
if(perspectiveViewportEl) perspectiveViewportEl.style.perspective = 'none';
|
| 503 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 504 |
const item = document.createElement('div');
|
| 505 |
item.className = 'single-preview-item';
|
| 506 |
|
|
@@ -533,18 +587,52 @@ function showSingleLargePreviewUI(htmlContent, titleText, fullPromptText) {
|
|
| 533 |
}
|
| 534 |
|
| 535 |
function showInitialPreviewStateUI() {
|
| 536 |
-
|
| 537 |
-
previewGridWrapperEl.
|
| 538 |
-
if(perspectiveViewportEl) perspectiveViewportEl.
|
| 539 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 540 |
if (codeOutputEl) codeOutputEl.innerHTML = '<code class="language-html">// Select a variation or history item to view its code.</code>';
|
| 541 |
if (selectedCodeTitleH3El) selectedCodeTitleH3El.textContent = "Selected Code:";
|
| 542 |
selectedVariationGridIndex = -1;
|
| 543 |
-
// Reset subtitle state when going back to initial view
|
| 544 |
if (mainContentSubtitleH2El) {
|
| 545 |
mainContentSubtitleH2El.classList.remove('prompt-truncated');
|
| 546 |
delete mainContentSubtitleH2El.dataset.fullPrompt;
|
| 547 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 548 |
}
|
| 549 |
|
| 550 |
function updateMainContentTitles(title, subtitle) {
|
|
@@ -1196,10 +1284,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 1196 |
promptDisplayModalCloseBtnEl = document.getElementById('prompt-display-modal-close-button');
|
| 1197 |
showPromptModalButtonEl = document.getElementById('show-prompt-modal-button'); // Added
|
| 1198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1199 |
|
| 1200 |
// --- Check if all required elements exist ---
|
| 1201 |
let missingElements = [];
|
| 1202 |
-
const requiredElements = { apiKeyEl, modelSelEl, codeOutputEl, errorMessageEl, refinementLoadingIndicator, mainContentEl, configButtonEl, intervalSliderEl, intervalValueDisplayEl, fullscreenOverlayEl, fullscreenIframeEl, exitFullscreenBtnEl, perspectiveViewportEl, previewGridWrapperEl, historyPanelEl, historyPanelPlaceholderEl, selectedCodeTitleH3El, mainContentTitleH1El, mainContentSubtitleH2El, fullscreenHistoryNavEl, historyNavPrevBtnEl, historyNavNextBtnEl, promptModalOverlayEl, promptModalContentEl, modalUserPromptEl, modalGenerateBtnEl, modalCancelBtnEl, modalLoadingIndicatorEl, modalRefinementCheckboxEl, numVariationsSliderEl, numVariationsValueDisplayEl, configModalOverlayEl, configModalContentEl, configModalCloseBtnEl, copyCodeButtonEl, exportCodeButtonEl, historyToggleButtonEl, historyArrowDownEl, historyArrowUpEl, newButtonEl, confirmModalOverlayEl, confirmModalMessageEl, confirmModalConfirmBtnEl, confirmModalCancelBtnEl, historyNavLeftBtnEl, historyNavRightBtnEl, modalThinkingBudgetSliderEl, modalThinkingBudgetValueDisplayEl, promptDisplayModalOverlayEl, promptDisplayModalContentEl, fullPromptTextEl, promptDisplayModalCloseBtnEl, showPromptModalButtonEl }; // Added showPromptModalButtonEl
|
| 1203 |
for (const key in requiredElements) { if (!requiredElements[key]) { missingElements.push(key); } }
|
| 1204 |
|
| 1205 |
if (missingElements.length > 0) {
|
|
|
|
| 54 |
let promptDisplayModalOverlayEl, promptDisplayModalContentEl, fullPromptTextEl, promptDisplayModalCloseBtnEl;
|
| 55 |
let showPromptModalButtonEl; // Added for the new button
|
| 56 |
|
| 57 |
+
// --- Elements for Initial Setup CTA ---
|
| 58 |
+
let initialSetupCtaEl;
|
| 59 |
+
let initialApiKeyInputEl;
|
| 60 |
+
let examplePromptsContainerEl;
|
| 61 |
+
|
| 62 |
|
| 63 |
// --- Constants ---
|
| 64 |
const API_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/models/';
|
|
|
|
| 287 |
return;
|
| 288 |
}
|
| 289 |
|
| 290 |
+
// Read API key: Prefer config modal, then initial input, then localStorage
|
| 291 |
+
let apiKey = apiKeyEl.value.trim();
|
| 292 |
+
if (!apiKey && initialApiKeyInputEl) {
|
| 293 |
+
apiKey = initialApiKeyInputEl.value.trim();
|
| 294 |
+
}
|
| 295 |
+
if (!apiKey) {
|
| 296 |
+
apiKey = localStorage.getItem('geminiApiKey') || '';
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
// Update input fields with the resolved API key
|
| 300 |
+
if (apiKeyEl && apiKeyEl.value !== apiKey) apiKeyEl.value = apiKey;
|
| 301 |
+
if (initialApiKeyInputEl && initialApiKeyInputEl.value !== apiKey) initialApiKeyInputEl.value = apiKey;
|
| 302 |
+
|
| 303 |
+
|
| 304 |
const selectedModel = modelSelEl.value;
|
| 305 |
const currentIsRefinementMode = modalRefinementCheckboxEl.checked;
|
| 306 |
const currentNumVariations = parseInt(numVariationsSliderEl.value, 10);
|
|
|
|
| 308 |
|
| 309 |
if (!apiKey || !userPrompt) {
|
| 310 |
errorMessageEl.textContent = 'Error: API Key and Prompt (via Alt+P) are required.';
|
| 311 |
+
if (!apiKey && initialSetupCtaEl && initialSetupCtaEl.classList.contains('flex')) {
|
| 312 |
+
if(initialApiKeyInputEl) initialApiKeyInputEl.focus();
|
| 313 |
+
} else if (!userPrompt && !promptModalOverlayEl.classList.contains('visible')) {
|
| 314 |
+
showPromptModal();
|
| 315 |
+
}
|
| 316 |
return;
|
| 317 |
}
|
| 318 |
if (!selectedModel) {
|
|
|
|
| 342 |
console.log(`Refining Evolution ${activeTimelineIndex + 1}. Original context: "${contextPromptForRefinement}"`);
|
| 343 |
} else if (currentIsRefinementMode) {
|
| 344 |
errorMessageEl.textContent = 'Error: No active evolution selected to refine. Uncheck "refine" or select an evolution from history.';
|
| 345 |
+
// Also hide the initial CTA if it's somehow visible
|
| 346 |
+
if (initialSetupCtaEl) initialSetupCtaEl.classList.add('hidden');
|
| 347 |
+
if (initialSetupCtaEl) initialSetupCtaEl.classList.remove('flex');
|
| 348 |
+
if (previewGridWrapperEl) previewGridWrapperEl.classList.remove('hidden');
|
| 349 |
return;
|
| 350 |
}
|
| 351 |
|
|
|
|
| 365 |
fullscreenButtons = Array(numVariationsToGenerate).fill(null);
|
| 366 |
previewItems = Array(numVariationsToGenerate).fill(null);
|
| 367 |
|
| 368 |
+
// Ensure correct layout state for generation
|
| 369 |
+
if (initialSetupCtaEl) {
|
| 370 |
+
initialSetupCtaEl.classList.remove('active-cta'); // Start hide animation
|
| 371 |
+
// Hide example prompt buttons immediately or animate them out too
|
| 372 |
+
if (examplePromptsContainerEl) {
|
| 373 |
+
examplePromptsContainerEl.querySelectorAll('.example-prompt-button').forEach(btn => btn.classList.remove('visible'));
|
| 374 |
+
}
|
| 375 |
+
setTimeout(() => { // Wait for animation to roughly finish
|
| 376 |
+
initialSetupCtaEl.style.display = 'none';
|
| 377 |
+
initialSetupCtaEl.classList.remove('flex', 'flex-grow');
|
| 378 |
+
}, 500); // Corresponds to CSS transition duration
|
| 379 |
+
}
|
| 380 |
+
if (perspectiveViewportEl) perspectiveViewportEl.classList.remove('hidden');
|
| 381 |
+
// previewGridWrapperEl will be managed by showFourGridPreviewUI
|
| 382 |
|
| 383 |
showFourGridPreviewUI();
|
| 384 |
|
|
|
|
| 541 |
previewGridWrapperEl.className = 'single-mode';
|
| 542 |
if(perspectiveViewportEl) perspectiveViewportEl.style.perspective = 'none';
|
| 543 |
|
| 544 |
+
// Ensure correct layout state for single preview
|
| 545 |
+
if (initialSetupCtaEl) {
|
| 546 |
+
initialSetupCtaEl.classList.remove('active-cta');
|
| 547 |
+
if (examplePromptsContainerEl) {
|
| 548 |
+
examplePromptsContainerEl.querySelectorAll('.example-prompt-button').forEach(btn => btn.classList.remove('visible'));
|
| 549 |
+
}
|
| 550 |
+
setTimeout(() => {
|
| 551 |
+
initialSetupCtaEl.style.display = 'none';
|
| 552 |
+
initialSetupCtaEl.classList.remove('flex', 'flex-grow');
|
| 553 |
+
}, 500);
|
| 554 |
+
}
|
| 555 |
+
if (perspectiveViewportEl) perspectiveViewportEl.classList.remove('hidden');
|
| 556 |
+
if (previewGridWrapperEl) previewGridWrapperEl.classList.remove('hidden');
|
| 557 |
+
|
| 558 |
const item = document.createElement('div');
|
| 559 |
item.className = 'single-preview-item';
|
| 560 |
|
|
|
|
| 587 |
}
|
| 588 |
|
| 589 |
function showInitialPreviewStateUI() {
|
| 590 |
+
// Hide the main preview grid and show the initial CTA
|
| 591 |
+
if (previewGridWrapperEl) previewGridWrapperEl.classList.add('hidden');
|
| 592 |
+
if (perspectiveViewportEl) perspectiveViewportEl.classList.add('hidden'); // Hide the whole viewport
|
| 593 |
+
|
| 594 |
+
if (initialSetupCtaEl) {
|
| 595 |
+
initialSetupCtaEl.style.display = 'flex'; // Set display before animation
|
| 596 |
+
initialSetupCtaEl.classList.add('flex-grow');
|
| 597 |
+
// Use requestAnimationFrame to ensure display:flex is applied before adding class for transition
|
| 598 |
+
requestAnimationFrame(() => {
|
| 599 |
+
initialSetupCtaEl.classList.add('active-cta');
|
| 600 |
+
});
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
updateMainContentTitles("Welcome to Live Previews", "Set up your API Key or try an example below.");
|
| 604 |
if (codeOutputEl) codeOutputEl.innerHTML = '<code class="language-html">// Select a variation or history item to view its code.</code>';
|
| 605 |
if (selectedCodeTitleH3El) selectedCodeTitleH3El.textContent = "Selected Code:";
|
| 606 |
selectedVariationGridIndex = -1;
|
|
|
|
| 607 |
if (mainContentSubtitleH2El) {
|
| 608 |
mainContentSubtitleH2El.classList.remove('prompt-truncated');
|
| 609 |
delete mainContentSubtitleH2El.dataset.fullPrompt;
|
| 610 |
}
|
| 611 |
+
|
| 612 |
+
// Populate example prompts
|
| 613 |
+
if (examplePromptsContainerEl) {
|
| 614 |
+
examplePromptsContainerEl.innerHTML = ''; // Clear existing
|
| 615 |
+
const prompts = [
|
| 616 |
+
"A simple landing page for a new SaaS product.",
|
| 617 |
+
"A responsive image gallery with a lightbox.",
|
| 618 |
+
"A futuristic login form.",
|
| 619 |
+
"A personal portfolio website with a blog section."
|
| 620 |
+
];
|
| 621 |
+
prompts.forEach((promptText, index) => {
|
| 622 |
+
const button = document.createElement('button');
|
| 623 |
+
button.className = 'example-prompt-button';
|
| 624 |
+
button.textContent = promptText;
|
| 625 |
+
button.addEventListener('click', () => {
|
| 626 |
+
if (modalUserPromptEl) modalUserPromptEl.value = promptText;
|
| 627 |
+
showPromptModal();
|
| 628 |
+
});
|
| 629 |
+
examplePromptsContainerEl.appendChild(button);
|
| 630 |
+
// Staggered animation for buttons
|
| 631 |
+
setTimeout(() => {
|
| 632 |
+
button.classList.add('visible');
|
| 633 |
+
}, 300 + index * 120); // Delay after panel animation starts, then stagger
|
| 634 |
+
});
|
| 635 |
+
}
|
| 636 |
}
|
| 637 |
|
| 638 |
function updateMainContentTitles(title, subtitle) {
|
|
|
|
| 1284 |
promptDisplayModalCloseBtnEl = document.getElementById('prompt-display-modal-close-button');
|
| 1285 |
showPromptModalButtonEl = document.getElementById('show-prompt-modal-button'); // Added
|
| 1286 |
|
| 1287 |
+
// --- Elements for Initial Setup CTA ---
|
| 1288 |
+
initialSetupCtaEl = document.getElementById('initial-setup-cta');
|
| 1289 |
+
initialApiKeyInputEl = document.getElementById('initial-api-key-input');
|
| 1290 |
+
examplePromptsContainerEl = document.getElementById('example-prompts-container');
|
| 1291 |
+
|
| 1292 |
|
| 1293 |
// --- Check if all required elements exist ---
|
| 1294 |
let missingElements = [];
|
| 1295 |
+
const requiredElements = { apiKeyEl, modelSelEl, codeOutputEl, errorMessageEl, refinementLoadingIndicator, mainContentEl, configButtonEl, intervalSliderEl, intervalValueDisplayEl, fullscreenOverlayEl, fullscreenIframeEl, exitFullscreenBtnEl, perspectiveViewportEl, previewGridWrapperEl, historyPanelEl, historyPanelPlaceholderEl, selectedCodeTitleH3El, mainContentTitleH1El, mainContentSubtitleH2El, fullscreenHistoryNavEl, historyNavPrevBtnEl, historyNavNextBtnEl, promptModalOverlayEl, promptModalContentEl, modalUserPromptEl, modalGenerateBtnEl, modalCancelBtnEl, modalLoadingIndicatorEl, modalRefinementCheckboxEl, numVariationsSliderEl, numVariationsValueDisplayEl, configModalOverlayEl, configModalContentEl, configModalCloseBtnEl, copyCodeButtonEl, exportCodeButtonEl, historyToggleButtonEl, historyArrowDownEl, historyArrowUpEl, newButtonEl, confirmModalOverlayEl, confirmModalMessageEl, confirmModalConfirmBtnEl, confirmModalCancelBtnEl, historyNavLeftBtnEl, historyNavRightBtnEl, modalThinkingBudgetSliderEl, modalThinkingBudgetValueDisplayEl, promptDisplayModalOverlayEl, promptDisplayModalContentEl, fullPromptTextEl, promptDisplayModalCloseBtnEl, showPromptModalButtonEl, initialSetupCtaEl, initialApiKeyInputEl, examplePromptsContainerEl }; // Added showPromptModalButtonEl
|
| 1296 |
for (const key in requiredElements) { if (!requiredElements[key]) { missingElements.push(key); } }
|
| 1297 |
|
| 1298 |
if (missingElements.length > 0) {
|