File size: 11,932 Bytes
b5f60e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!DOCTYPE html>
<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 &amp; 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 &amp; 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>