Spaces:
Paused
Paused
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Structured Prompt Studio</title> | |
| <style> | |
| %%CSS%% | |
| </style> | |
| </head> | |
| <body data-generated="%%GENERATION_TIME%%"> | |
| <div class="app"> | |
| <!-- ==================== History Bar ==================== --> | |
| <div class="history-bar"> | |
| <div class="history-title">History</div> | |
| <div class="history-scroll" id="historyScroll"> | |
| <div class="history-empty" id="historyEmpty">No history yet</div> | |
| </div> | |
| <button class="tool-btn history-clear-btn" id="historyClearBtn" onclick="clearHistory()" title="Clear history" style="display:none;"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg> | |
| </button> | |
| </div> | |
| <!-- ==================== Workspace (CSS Grid) ==================== --> | |
| <div class="workspace"> | |
| <!-- Image Panel (row 1, col 1) --> | |
| <div class="panel image-panel" id="imagePanel"> | |
| <div class="panel-toolbar"> | |
| <span class="panel-label">Image</span> | |
| <div class="panel-actions"> | |
| <button class="tool-btn" onclick="triggerImageUpload()" title="Import image"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> | |
| </button> | |
| <button class="tool-btn" id="btnBboxShow" onclick="showAllBboxes()" title="Show all bboxes" style="display:none;"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg> | |
| </button> | |
| <button class="tool-btn" id="btnBboxHide" onclick="hideAllBboxes()" title="Hide all bboxes" style="display:none;"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg> | |
| </button> | |
| <button class="tool-btn" id="btnImageZoom" onclick="handleImageEnlarge()" title="Zoom" style="display:none;"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg> | |
| </button> | |
| <button class="tool-btn" id="btnImageDelete" onclick="handleImageDelete()" title="Delete image" style="display:none;"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="image-area" id="imageArea"> | |
| <div class="dropzone" id="dropzone" onclick="triggerImageUpload()"> | |
| <div class="dropzone-icon">πΌοΈ</div> | |
| <div class="dropzone-text">Drop an image here or click to upload</div> | |
| </div> | |
| <div class="image-display" id="imageDisplay" style="display:none;"> | |
| <img id="displayImage" onclick="handleImageClick(event)" title="Click to select a bbox" /> | |
| <div class="bbox-container" id="bboxContainer"></div> | |
| </div> | |
| </div> | |
| <input type="file" id="imageFileInput" accept="image/*" onchange="handleImageFileSelected(event)" style="display:none;"> | |
| </div> | |
| <!-- Structured Prompt Panel (row 1, col 2) --> | |
| <div class="panel sp-panel" id="spPanel"> | |
| <div class="panel-toolbar"> | |
| <span class="panel-label">Structured Prompt</span> | |
| <div class="panel-actions"> | |
| <button class="tool-btn" id="btnSPRaw" onclick="toggleSPRawMode()" title="Toggle raw JSON"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg> | |
| </button> | |
| <button class="tool-btn" onclick="triggerSPImport()" title="Import JSON"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> | |
| </button> | |
| <button class="tool-btn" id="btnSPUndo" onclick="handleSPUndo()" title="Undo" style="display:none;"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 102.13-9.36L1 10"/></svg> | |
| </button> | |
| <button class="tool-btn" id="btnSPDelete" onclick="handleSPDelete()" title="Clear" style="display:none;"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="sp-area" id="spArea"> | |
| <div class="sp-empty" id="spEmpty"> | |
| <div class="sp-empty-icon">π</div> | |
| <div>Structured Prompt is empty</div> | |
| <div class="sp-empty-hint">Generate one with the button, or paste / import JSON</div> | |
| </div> | |
| <div class="sp-structured" id="spStructured" style="display:none;"></div> | |
| <textarea id="spTextarea" style="display:none;" spellcheck="false" | |
| placeholder="Paste Structured Prompt JSON here..."></textarea> | |
| </div> | |
| <input type="file" id="spFileInput" accept=".json,.txt" onchange="handleSPFileSelected(event)" style="display:none;"> | |
| </div> | |
| <!-- Params Bar (row 2, col 1) --> | |
| <div class="panel params-bar"> | |
| <div class="params-label">Params</div> | |
| <div class="params-group"> | |
| <label>CFG</label> | |
| <input type="number" id="paramCfgScale" value="4.0" min="0" max="20" step="0.1"> | |
| </div> | |
| <div class="params-group"> | |
| <label>Steps</label> | |
| <input type="number" id="paramSteps" value="25" min="1" max="100" step="1"> | |
| </div> | |
| <div class="params-spacer"></div> | |
| <div class="params-group"> | |
| <label>H</label> | |
| <input type="number" id="paramHeight" value="1024" min="64" max="4096" step="32"> | |
| </div> | |
| <div class="params-group"> | |
| <label>W</label> | |
| <input type="number" id="paramWidth" value="1024" min="64" max="4096" step="32"> | |
| </div> | |
| <div class="params-group"> | |
| <label>Seed</label> | |
| <input type="number" id="paramSeed" value="42" min="-1" max="999999"> | |
| </div> | |
| </div> | |
| <!-- Generate SP Button (row 2, col 2) --> | |
| <button class="action-btn gen-sp-btn" id="genSPBtn" onclick="handleGenerateSP()"> | |
| Generate SP | |
| </button> | |
| <!-- User Prompt Bar (row 3, col 1) --> | |
| <div class="panel prompt-bar"> | |
| <div class="prompt-label">User Prompt</div> | |
| <textarea id="userPromptInput" placeholder="Describe the image you want..." rows="1"></textarea> | |
| </div> | |
| <!-- Generate Image Button (row 3, col 2) --> | |
| <button class="action-btn gen-image-btn" id="genImageBtn" onclick="handleGenerateImage()"> | |
| Generate Image | |
| </button> | |
| </div> | |
| </div> | |
| <!-- ==================== Image Enlarge Modal ==================== --> | |
| <div class="modal-overlay" id="imageModal" onclick="closeImageModal()"> | |
| <div class="modal-image-container" id="modalImageContainer" onclick="event.stopPropagation()"> | |
| <img id="modalImage" class="modal-image" /> | |
| </div> | |
| <button class="modal-close-btn" onclick="closeImageModal()">β</button> | |
| </div> | |
| <!-- ==================== Diff Confirmation Dialog ==================== --> | |
| <div class="modal-overlay" id="diffModal"> | |
| <div class="diff-dialog" onclick="event.stopPropagation()"> | |
| <div class="diff-header"> | |
| <span>Review changes</span> | |
| <button class="modal-close-btn-sm" onclick="cancelGeneration()">β</button> | |
| </div> | |
| <div class="diff-content" id="diffContent"></div> | |
| <div class="diff-actions"> | |
| <button class="action-btn cancel-btn" onclick="cancelGeneration()">Cancel</button> | |
| <button class="action-btn confirm-btn" onclick="confirmGeneration()">Confirm & generate</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ==================== History Detail Modal ==================== --> | |
| <div class="modal-overlay" id="historyModal" onclick="closeHistoryModal()"> | |
| <div class="history-detail" onclick="event.stopPropagation()"> | |
| <div class="history-detail-header"> | |
| <span>History entry</span> | |
| <button class="modal-close-btn-sm" onclick="closeHistoryModal()">β</button> | |
| </div> | |
| <div class="history-detail-body" id="historyDetailBody"></div> | |
| <div class="history-detail-footer"> | |
| <button class="action-btn restore-part-btn" onclick="restoreImageFromHistory()" title="Restore image only">πΌοΈ Image</button> | |
| <button class="action-btn restore-part-btn" onclick="restorePromptFromHistory()" title="Restore User Prompt & SP">π Prompt</button> | |
| <button class="action-btn restore-part-btn" onclick="restoreParamsFromHistory()" title="Restore params only">βοΈ Params</button> | |
| <button class="action-btn restore-btn" onclick="restoreFromHistory()">Restore all</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ==================== Toast Container ==================== --> | |
| <div class="toast-container" id="toastContainer"></div> | |
| <!-- ==================== Add Field Dropdown ==================== --> | |
| <div class="sp-add-dropdown" id="spAddDropdown" style="display:none;"></div> | |
| <!-- ==================== Scripts ==================== --> | |
| <script src="https://cdn.jsdelivr.net/npm/jsonrepair@3/lib/umd/jsonrepair.min.js"></script> | |
| <script> | |
| %%SCRIPT%% | |
| </script> | |
| </body> | |
| </html> | |