@necrolab/dashboard 0.5.16 → 0.5.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/App.vue +14 -480
- package/src/assets/css/components/buttons.scss +12 -68
- package/src/assets/css/components/headers.scss +1 -1
- package/src/assets/css/components/utilities.scss +91 -16
- package/src/assets/css/main.scss +22 -95
- package/src/components/Auth/LoginForm.vue +2 -2
- package/src/components/Console/ConsoleToolbar.vue +123 -0
- package/src/components/Editors/Account/Account.vue +4 -2
- package/src/components/Editors/Account/AccountView.vue +12 -37
- package/src/components/Editors/Account/CreateAccount.vue +3 -11
- package/src/components/Editors/AdminFileEditor.vue +421 -0
- package/src/components/Editors/Profile/CreateProfile.vue +4 -20
- package/src/components/Editors/Profile/Profile.vue +5 -4
- package/src/components/Editors/Profile/ProfileView.vue +13 -38
- package/src/components/Editors/ProxyFileEditor.vue +178 -0
- package/src/components/Filter/Filter.vue +6 -6
- package/src/components/Filter/FilterPreview.vue +4 -12
- package/src/components/Filter/PriceSortToggle.vue +1 -1
- package/src/components/Tasks/QuickSettings.vue +5 -5
- package/src/components/Tasks/Stats.vue +1 -1
- package/src/components/Tasks/Task.vue +5 -8
- package/src/components/Tasks/TaskView.vue +2 -1
- package/src/components/Tasks/ViewTask.vue +2 -2
- package/src/components/icons/index.js +0 -4
- package/src/components/ui/ActionButtonGroup.vue +2 -2
- package/src/components/ui/BalanceIndicator.vue +3 -3
- package/src/components/ui/EnableDisableToggle.vue +2 -2
- package/src/components/ui/FormField.vue +2 -2
- package/src/components/ui/IconLabel.vue +2 -2
- package/src/components/ui/InfoRow.vue +4 -4
- package/src/components/ui/Modal.vue +83 -9
- package/src/components/ui/Navbar.vue +3 -3
- package/src/components/ui/ReadonlyFieldsSection.vue +1 -1
- package/src/components/ui/StatusBadge.vue +1 -1
- package/src/components/ui/controls/CountryChooser.vue +5 -5
- package/src/components/ui/controls/atomic/MultiDropdown.vue +1 -1
- package/src/composables/useCodeEditor.js +117 -0
- package/src/composables/useDropdownPosition.js +0 -2
- package/src/composables/useEnableDisable.js +6 -0
- package/src/composables/useFilterCSS.js +71 -0
- package/src/composables/useFormValidation.js +92 -0
- package/src/composables/useGetAllTags.js +9 -0
- package/src/composables/useIOSViewportHandling.js +76 -0
- package/src/composables/useNotchHandling.js +306 -0
- package/src/composables/useTableRender.js +23 -0
- package/src/composables/useZoomPrevention.js +96 -0
- package/src/constants/tableLayout.js +14 -0
- package/src/libs/utils/array.js +1 -3
- package/src/libs/utils/dataGeneration.js +1 -1
- package/src/libs/utils/string.js +1 -26
- package/src/libs/utils/validation.js +2 -26
- package/src/stores/connection.js +0 -25
- package/src/stores/ui.js +21 -35
- package/src/utils/tableHelpers.js +1 -0
- package/src/views/Accounts.vue +9 -17
- package/src/views/Console.vue +15 -92
- package/src/views/Editor.vue +39 -938
- package/src/views/FilterBuilder.vue +9 -97
- package/src/views/Profiles.vue +9 -17
- package/src/views/Tasks.vue +4 -4
- package/src/assets/img/background.svg.backup +0 -11
- package/src/components/icons/SquareCheck.vue +0 -12
- package/src/components/icons/SquareUncheck.vue +0 -12
- package/src/components/ui/controls/atomic/LoadingButton.vue +0 -45
- /package/src/components/Editors/Account/{AccountCreator.vue → CreateAccountBatch.vue} +0 -0
package/src/views/Editor.vue
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<!-- Heading -->
|
|
4
3
|
<div class="page-header" style="padding-bottom: 1.25rem;">
|
|
5
4
|
<div class="page-header-card">
|
|
6
5
|
<img src="@/assets/img/pencil.svg" />
|
|
@@ -9,200 +8,45 @@
|
|
|
9
8
|
</div>
|
|
10
9
|
|
|
11
10
|
<div class="bg-dark-400 border-2 rounded-lg shadow-sm p-2" style="border-color: var(--color-border);">
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
rightAmount="right-1" />
|
|
25
|
-
<button
|
|
26
|
-
class="refresh-button flex items-center justify-center w-9 h-10 flex-shrink-0 text-white bg-dark-400 transition-all duration-150 hover:bg-dark-450"
|
|
27
|
-
@click="loadAvailableFiles()"
|
|
28
|
-
title="Refresh file list">
|
|
29
|
-
<ReloadIcon class="refresh-icon h-4 w-4" />
|
|
30
|
-
</button>
|
|
31
|
-
</div>
|
|
32
|
-
<!-- Admin editor buttons moved here -->
|
|
33
|
-
<div v-if="textEditorVisible" class="flex gap-1.5 ml-auto">
|
|
34
|
-
<button
|
|
35
|
-
class="button-default bg-dark-400"
|
|
36
|
-
@click="format()"
|
|
37
|
-
v-if="isJsonFile()"
|
|
38
|
-
title="Format JSON">
|
|
39
|
-
<svg
|
|
40
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
41
|
-
width="16"
|
|
42
|
-
height="16"
|
|
43
|
-
viewBox="0 0 24 24"
|
|
44
|
-
fill="none"
|
|
45
|
-
stroke="currentColor"
|
|
46
|
-
stroke-width="2"
|
|
47
|
-
stroke-linecap="round"
|
|
48
|
-
stroke-linejoin="round">
|
|
49
|
-
<path d="M21 10H7" />
|
|
50
|
-
<path d="M21 6H3" />
|
|
51
|
-
<path d="M21 14H3" />
|
|
52
|
-
<path d="M21 18H7" />
|
|
53
|
-
</svg>
|
|
54
|
-
</button>
|
|
55
|
-
<button class="button-default bg-dark-400" @click="saveAll" title="Save File">
|
|
56
|
-
<svg
|
|
57
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
58
|
-
width="16"
|
|
59
|
-
height="16"
|
|
60
|
-
viewBox="0 0 24 24"
|
|
61
|
-
fill="none"
|
|
62
|
-
stroke="currentColor"
|
|
63
|
-
stroke-width="2"
|
|
64
|
-
stroke-linecap="round"
|
|
65
|
-
stroke-linejoin="round">
|
|
66
|
-
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
|
67
|
-
<polyline points="17 21 17 13 7 13 7 21" />
|
|
68
|
-
<polyline points="7 3 7 8 15 8" />
|
|
69
|
-
</svg>
|
|
70
|
-
</button>
|
|
71
|
-
<button class="button-default bg-dark-400" @click="closeFile" title="Close File">
|
|
72
|
-
<svg
|
|
73
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
74
|
-
width="16"
|
|
75
|
-
height="16"
|
|
76
|
-
viewBox="0 0 24 24"
|
|
77
|
-
fill="none"
|
|
78
|
-
stroke="currentColor"
|
|
79
|
-
stroke-width="2"
|
|
80
|
-
stroke-linecap="round"
|
|
81
|
-
stroke-linejoin="round">
|
|
82
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
83
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
84
|
-
</svg>
|
|
85
|
-
</button>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
11
|
+
<AdminFileEditor
|
|
12
|
+
v-if="ui.profile.admin"
|
|
13
|
+
:availableFiles="availableFiles"
|
|
14
|
+
:currentFile="currentFile"
|
|
15
|
+
v-model:content="currentContent"
|
|
16
|
+
:isHidden="!!currentProxyList"
|
|
17
|
+
:logger="ui.logger"
|
|
18
|
+
@load-file="loadFile"
|
|
19
|
+
@refresh-files="loadAvailableFiles"
|
|
20
|
+
@save="saveAll"
|
|
21
|
+
@close="closeFile"
|
|
22
|
+
@format="format" />
|
|
88
23
|
|
|
89
|
-
<transition name="fade">
|
|
90
|
-
<div v-if="textEditorVisible" class="my-3 relative">
|
|
91
|
-
<div class="pb-4">
|
|
92
|
-
<!-- Syntax Highlighting Editor -->
|
|
93
|
-
<div class="editor-container overflow-hidden rounded-lg shadow-card bg-dark-350" :class="{ 'has-error': errorMessage }">
|
|
94
|
-
<div class="relative w-full h-full">
|
|
95
|
-
<pre ref="codeDisplay" class="code-highlight language-json"></pre>
|
|
96
|
-
<textarea
|
|
97
|
-
ref="codeEditor"
|
|
98
|
-
v-model="currentContent"
|
|
99
|
-
class="code-editor"
|
|
100
|
-
spellcheck="false"
|
|
101
|
-
@scroll="syncScroll"
|
|
102
|
-
@input="highlightCode"
|
|
103
|
-
@keydown.tab.prevent="handleTab"></textarea>
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
</div>
|
|
107
|
-
|
|
108
|
-
<div v-if="errorMessage" class="error-container">
|
|
109
|
-
<div class="error-icon">
|
|
110
|
-
<svg
|
|
111
|
-
width="16"
|
|
112
|
-
height="16"
|
|
113
|
-
viewBox="0 0 24 24"
|
|
114
|
-
fill="none"
|
|
115
|
-
stroke="currentColor"
|
|
116
|
-
stroke-width="2">
|
|
117
|
-
<circle cx="12" cy="12" r="10" />
|
|
118
|
-
<line x1="15" y1="9" x2="9" y2="15" />
|
|
119
|
-
<line x1="9" y1="9" x2="15" y2="15" />
|
|
120
|
-
</svg>
|
|
121
|
-
</div>
|
|
122
|
-
<div class="error-content">
|
|
123
|
-
<div class="error-title">JSON Syntax Error</div>
|
|
124
|
-
<div class="error-text">{{ errorMessage }}</div>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
</div>
|
|
128
|
-
</transition>
|
|
129
|
-
</div>
|
|
130
|
-
|
|
131
|
-
<!-- Section Divider - Show when both editors are closed -->
|
|
132
24
|
<div v-if="ui.profile.admin && !textEditorVisible && !currentProxyList" class="section-divider" />
|
|
133
25
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
:onClick="loadProxies"
|
|
144
|
-
:options="proxyLists"
|
|
145
|
-
:allowDefault="false"
|
|
146
|
-
:includeAdjacentButtons="true"
|
|
147
|
-
rightAmount="right-1" />
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
<!-- Proxy save button moved here -->
|
|
151
|
-
<div v-if="currentProxyList" class="flex gap-1.5 ml-auto">
|
|
152
|
-
<button class="button-default bg-dark-400" @click="saveProxies" title="Save Proxies">
|
|
153
|
-
<svg
|
|
154
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
155
|
-
width="16"
|
|
156
|
-
height="16"
|
|
157
|
-
viewBox="0 0 24 24"
|
|
158
|
-
fill="none"
|
|
159
|
-
stroke="currentColor"
|
|
160
|
-
stroke-width="2"
|
|
161
|
-
stroke-linecap="round"
|
|
162
|
-
stroke-linejoin="round">
|
|
163
|
-
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
|
164
|
-
<polyline points="17 21 17 13 7 13 7 21" />
|
|
165
|
-
<polyline points="7 3 7 8 15 8" />
|
|
166
|
-
</svg>
|
|
167
|
-
</button>
|
|
168
|
-
<button class="button-default bg-dark-400" @click="closeProxyFile" title="Close File">
|
|
169
|
-
<svg
|
|
170
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
171
|
-
width="16"
|
|
172
|
-
height="16"
|
|
173
|
-
viewBox="0 0 24 24"
|
|
174
|
-
fill="none"
|
|
175
|
-
stroke="currentColor"
|
|
176
|
-
stroke-width="2"
|
|
177
|
-
stroke-linecap="round"
|
|
178
|
-
stroke-linejoin="round">
|
|
179
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
180
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
181
|
-
</svg>
|
|
182
|
-
</button>
|
|
183
|
-
</div>
|
|
184
|
-
</div>
|
|
185
|
-
<!-- Textarea -->
|
|
186
|
-
<transition name="fade">
|
|
187
|
-
<div v-if="currentProxyList" class="relative my-3">
|
|
188
|
-
<div class="pb-4">
|
|
189
|
-
<div class="proxy-editor-container table-component">
|
|
190
|
-
<textarea v-model="proxyContent" class="proxy-editor" spellcheck="false"></textarea>
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
</transition>
|
|
195
|
-
</div>
|
|
26
|
+
<ProxyFileEditor
|
|
27
|
+
:proxyLists="proxyLists"
|
|
28
|
+
:currentProxyList="currentProxyList"
|
|
29
|
+
v-model:proxyContent="proxyContent"
|
|
30
|
+
:defaultProxyList="ui.profile.proxyList?.checkout || proxyLists[0]"
|
|
31
|
+
:isHidden="textEditorVisible"
|
|
32
|
+
@load-proxies="loadProxies"
|
|
33
|
+
@save-proxies="saveProxies"
|
|
34
|
+
@close-proxy="closeProxyFile" />
|
|
196
35
|
</div>
|
|
197
36
|
</div>
|
|
198
37
|
</template>
|
|
38
|
+
|
|
199
39
|
<script setup>
|
|
200
|
-
import { ref
|
|
201
|
-
import { ReloadIcon } from "@/components/icons";
|
|
40
|
+
import { ref } from "vue";
|
|
202
41
|
import { useUIStore } from "@/stores/ui";
|
|
203
|
-
import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
|
|
204
42
|
import { getProxyLists, getProxyFile, getQuickConfig, sendQuickConfig } from "@/stores/requests";
|
|
205
43
|
import { DEBUG } from "@/utils/debug";
|
|
44
|
+
import { useCodeEditor } from "@/composables/useCodeEditor";
|
|
45
|
+
import AdminFileEditor from "@/components/Editors/AdminFileEditor.vue";
|
|
46
|
+
import ProxyFileEditor from "@/components/Editors/ProxyFileEditor.vue";
|
|
47
|
+
|
|
48
|
+
const ui = useUIStore();
|
|
49
|
+
const { formatJSON } = useCodeEditor(ui.logger);
|
|
206
50
|
|
|
207
51
|
const loadFromApi = async (path) => {
|
|
208
52
|
const res = await fetch(path);
|
|
@@ -211,175 +55,29 @@ const loadFromApi = async (path) => {
|
|
|
211
55
|
|
|
212
56
|
const availableFiles = ref([]);
|
|
213
57
|
if (DEBUG) availableFiles.value.push("used-codes.json", "proxies.txt", "toMonitor.txt", "test.txt");
|
|
58
|
+
|
|
214
59
|
const currentFile = ref("");
|
|
215
60
|
const textEditorVisible = ref(false);
|
|
216
61
|
const currentContent = ref("");
|
|
217
62
|
const proxyContent = ref("");
|
|
218
63
|
const proxyLists = ref(["loading..."]);
|
|
219
64
|
const currentProxyList = ref("");
|
|
220
|
-
const ui = useUIStore();
|
|
221
|
-
|
|
222
|
-
// References to editor elements
|
|
223
|
-
const codeEditor = ref(null);
|
|
224
|
-
const codeDisplay = ref(null);
|
|
225
65
|
|
|
226
66
|
let previous = {
|
|
227
67
|
proxyContent: { list: ui.profile.proxyList, content: "" },
|
|
228
68
|
currentContent: { file: "", content: "" }
|
|
229
69
|
};
|
|
230
70
|
|
|
231
|
-
const errorMessage = computed(() => {
|
|
232
|
-
if (!currentFile.value.endsWith(".json")) return;
|
|
233
|
-
|
|
234
|
-
let err;
|
|
235
|
-
try {
|
|
236
|
-
JSON.parse(currentContent.value);
|
|
237
|
-
} catch (e) {
|
|
238
|
-
err = e;
|
|
239
|
-
}
|
|
240
|
-
return err?.message;
|
|
241
|
-
});
|
|
242
|
-
|
|
243
71
|
const loadAvailableFiles = async () => (availableFiles.value = await loadFromApi("/api/json-files"));
|
|
244
72
|
|
|
245
73
|
const isJsonFile = () => currentFile.value.endsWith(".json");
|
|
246
74
|
|
|
247
|
-
// Debounce timer for highlighting
|
|
248
|
-
let highlightTimer = null;
|
|
249
|
-
|
|
250
|
-
// Function to highlight code using Prism
|
|
251
|
-
const highlightCode = () => {
|
|
252
|
-
if (!codeDisplay.value || !codeEditor.value) return;
|
|
253
|
-
|
|
254
|
-
// Get the language based on file extension
|
|
255
|
-
let language = "javascript";
|
|
256
|
-
|
|
257
|
-
if (currentFile.value) {
|
|
258
|
-
if (currentFile.value.endsWith(".json")) {
|
|
259
|
-
language = "json";
|
|
260
|
-
} else if (currentFile.value.endsWith(".js")) {
|
|
261
|
-
language = "javascript";
|
|
262
|
-
} else if (currentFile.value.endsWith(".txt") || currentFile.value.endsWith(".csv")) {
|
|
263
|
-
language = "text";
|
|
264
|
-
if (codeDisplay.value) {
|
|
265
|
-
codeDisplay.value.textContent = currentContent.value || "";
|
|
266
|
-
codeDisplay.value.className = "language-text code-highlight";
|
|
267
|
-
}
|
|
268
|
-
syncScroll();
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Debounce to avoid excessive highlighting
|
|
274
|
-
if (highlightTimer) clearTimeout(highlightTimer);
|
|
275
|
-
|
|
276
|
-
highlightTimer = setTimeout(() => {
|
|
277
|
-
requestAnimationFrame(() => {
|
|
278
|
-
try {
|
|
279
|
-
// Check if Prism and language are available
|
|
280
|
-
if (typeof window.Prism === "undefined" || !window.Prism.languages?.[language]) {
|
|
281
|
-
if (codeDisplay.value) {
|
|
282
|
-
codeDisplay.value.textContent = currentContent.value || "";
|
|
283
|
-
codeDisplay.value.className = `language-${language} code-highlight`;
|
|
284
|
-
}
|
|
285
|
-
syncScroll();
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Highlight the code (Prism.highlight returns sanitized HTML)
|
|
290
|
-
const highlighted = window.Prism.highlight(
|
|
291
|
-
currentContent.value || "",
|
|
292
|
-
window.Prism.languages[language],
|
|
293
|
-
language
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
if (codeDisplay.value) {
|
|
297
|
-
codeDisplay.value.innerHTML = highlighted;
|
|
298
|
-
codeDisplay.value.className = `language-${language} code-highlight`;
|
|
299
|
-
}
|
|
300
|
-
} catch (e) {
|
|
301
|
-
ui.logger.Error("Highlight error:", e);
|
|
302
|
-
if (codeDisplay.value) {
|
|
303
|
-
codeDisplay.value.textContent = currentContent.value || "";
|
|
304
|
-
}
|
|
305
|
-
} finally {
|
|
306
|
-
syncScroll();
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
}, 50);
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
// Function to sync scrolling between textarea and highlighted code
|
|
313
|
-
const syncScroll = () => {
|
|
314
|
-
if (!codeDisplay.value || !codeEditor.value) return;
|
|
315
|
-
|
|
316
|
-
// Direct synchronization without RAF for immediate response
|
|
317
|
-
codeDisplay.value.scrollTop = codeEditor.value.scrollTop;
|
|
318
|
-
codeDisplay.value.scrollLeft = codeEditor.value.scrollLeft;
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
// Function to handle tab key press in the editor
|
|
322
|
-
const handleTab = () => {
|
|
323
|
-
const textarea = codeEditor.value;
|
|
324
|
-
const start = textarea.selectionStart;
|
|
325
|
-
const end = textarea.selectionEnd;
|
|
326
|
-
|
|
327
|
-
// Insert 4 spaces at cursor position
|
|
328
|
-
const spaces = " ";
|
|
329
|
-
currentContent.value = currentContent.value.substring(0, start) + spaces + currentContent.value.substring(end);
|
|
330
|
-
|
|
331
|
-
// Move cursor position after the inserted tab
|
|
332
|
-
nextTick(() => {
|
|
333
|
-
textarea.selectionStart = textarea.selectionEnd = start + spaces.length;
|
|
334
|
-
highlightCode();
|
|
335
|
-
});
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
const format = () => {
|
|
339
|
-
try {
|
|
340
|
-
if (!isJsonFile()) return;
|
|
341
|
-
|
|
342
|
-
const formatted = JSON.stringify(JSON.parse(currentContent.value), null, 4);
|
|
343
|
-
currentContent.value = formatted;
|
|
344
|
-
|
|
345
|
-
// Apply syntax highlighting after formatting
|
|
346
|
-
nextTick(() => {
|
|
347
|
-
highlightCode();
|
|
348
|
-
});
|
|
349
|
-
} catch (e) {
|
|
350
|
-
ui.logger.Error("Could not format JSON", e);
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
// Watch for content changes to apply syntax highlighting
|
|
355
|
-
watch(currentContent, () => {
|
|
356
|
-
nextTick(() => {
|
|
357
|
-
highlightCode();
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
|
|
361
75
|
const loadFile = async (f) => {
|
|
362
76
|
currentFile.value = f;
|
|
363
77
|
if (DEBUG) {
|
|
364
78
|
textEditorVisible.value = true;
|
|
365
79
|
currentProxyList.value = "";
|
|
366
80
|
currentContent.value = new Array(100).fill(0, 0, 100).join("\n");
|
|
367
|
-
|
|
368
|
-
// Update pre element class based on file type
|
|
369
|
-
if (codeDisplay.value) {
|
|
370
|
-
if (f.endsWith(".json")) {
|
|
371
|
-
codeDisplay.value.className = "language-json";
|
|
372
|
-
} else if (f.endsWith(".js")) {
|
|
373
|
-
codeDisplay.value.className = "language-javascript";
|
|
374
|
-
} else {
|
|
375
|
-
codeDisplay.value.className = "language-text";
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Apply syntax highlighting after content is set
|
|
380
|
-
nextTick(() => {
|
|
381
|
-
highlightCode();
|
|
382
|
-
});
|
|
383
81
|
return;
|
|
384
82
|
}
|
|
385
83
|
|
|
@@ -389,22 +87,6 @@ const loadFile = async (f) => {
|
|
|
389
87
|
currentProxyList.value = "";
|
|
390
88
|
currentContent.value = text;
|
|
391
89
|
previous.currentContent = { file: currentFile.value, content: text };
|
|
392
|
-
|
|
393
|
-
// Update pre element class based on file type
|
|
394
|
-
if (codeDisplay.value) {
|
|
395
|
-
if (f.endsWith(".json")) {
|
|
396
|
-
codeDisplay.value.className = "language-json";
|
|
397
|
-
} else if (f.endsWith(".js")) {
|
|
398
|
-
codeDisplay.value.className = "language-javascript";
|
|
399
|
-
} else {
|
|
400
|
-
codeDisplay.value.className = "language-text";
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Apply syntax highlighting after content is loaded
|
|
405
|
-
nextTick(() => {
|
|
406
|
-
highlightCode();
|
|
407
|
-
});
|
|
408
90
|
};
|
|
409
91
|
|
|
410
92
|
const saveDataToAPI = async (data, endpoint, msg, json = true) => {
|
|
@@ -460,6 +142,10 @@ const saveAll = async () => {
|
|
|
460
142
|
await saveQuickConfig();
|
|
461
143
|
};
|
|
462
144
|
|
|
145
|
+
const format = () => {
|
|
146
|
+
formatJSON(ref(currentContent), currentFile.value, () => {});
|
|
147
|
+
};
|
|
148
|
+
|
|
463
149
|
const closeFile = () => {
|
|
464
150
|
currentFile.value = "";
|
|
465
151
|
currentContent.value = "";
|
|
@@ -513,603 +199,18 @@ const loadProxyLists = async () => {
|
|
|
513
199
|
else ui.showError("Could not load proxylists");
|
|
514
200
|
};
|
|
515
201
|
|
|
516
|
-
// Initialize syntax highlighting
|
|
517
|
-
onMounted(() => {
|
|
518
|
-
// Apply highlighting when the component is mounted
|
|
519
|
-
nextTick(() => {
|
|
520
|
-
highlightCode();
|
|
521
|
-
|
|
522
|
-
// Ensure scroll synchronization on initial load
|
|
523
|
-
if (codeEditor.value && codeDisplay.value) {
|
|
524
|
-
syncScroll();
|
|
525
|
-
}
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
// iOS-specific editor fixes with cursor tracking
|
|
529
|
-
if (
|
|
530
|
-
/iPad|iPhone|iPod/.test(navigator.platform) ||
|
|
531
|
-
(navigator.maxTouchPoints && navigator.maxTouchPoints > 2 && /MacIntel/.test(navigator.platform))
|
|
532
|
-
) {
|
|
533
|
-
const trackCursor = (editor) => {
|
|
534
|
-
const scrollToCursor = () => {
|
|
535
|
-
setTimeout(() => {
|
|
536
|
-
const container = editor.closest(".editor-container") || editor.closest(".proxy-editor-container");
|
|
537
|
-
if (container) {
|
|
538
|
-
// Get cursor position and scroll to it
|
|
539
|
-
const lines = editor.value.substring(0, editor.selectionStart).split("\n");
|
|
540
|
-
const lineHeight = 24; // Approximate line height
|
|
541
|
-
const cursorY = lines.length * lineHeight;
|
|
542
|
-
const containerHeight = container.clientHeight;
|
|
543
|
-
|
|
544
|
-
// Scroll to keep cursor in view
|
|
545
|
-
if (cursorY > container.scrollTop + containerHeight - 60) {
|
|
546
|
-
container.scrollTop = cursorY - containerHeight + 60;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}, 100);
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
editor.addEventListener("focus", scrollToCursor);
|
|
553
|
-
editor.addEventListener("input", scrollToCursor);
|
|
554
|
-
editor.addEventListener("click", scrollToCursor);
|
|
555
|
-
editor.addEventListener("keyup", scrollToCursor);
|
|
556
|
-
};
|
|
557
|
-
|
|
558
|
-
nextTick(() => {
|
|
559
|
-
if (codeEditor.value) {
|
|
560
|
-
trackCursor(codeEditor.value);
|
|
561
|
-
}
|
|
562
|
-
const proxyEditor = document.querySelector(".proxy-editor");
|
|
563
|
-
if (proxyEditor) {
|
|
564
|
-
trackCursor(proxyEditor);
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
// Watch for editor visibility changes
|
|
570
|
-
watch(textEditorVisible, (newValue) => {
|
|
571
|
-
if (newValue) {
|
|
572
|
-
nextTick(() => {
|
|
573
|
-
highlightCode();
|
|
574
|
-
|
|
575
|
-
// Focus the editor when it becomes visible
|
|
576
|
-
if (codeEditor.value) {
|
|
577
|
-
codeEditor.value.focus();
|
|
578
|
-
}
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
});
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
// No cleanup needed - global iOS handling takes care of everything
|
|
585
|
-
|
|
586
202
|
if (ui.profile.admin && !DEBUG) loadAvailableFiles();
|
|
587
203
|
loadProxyLists();
|
|
588
204
|
</script>
|
|
589
|
-
<style lang="scss" scoped>
|
|
590
|
-
/* ==========================================================================
|
|
591
|
-
Z-INDEX MANAGEMENT - Required for dropdown layering
|
|
592
|
-
========================================================================== */
|
|
593
|
-
.z-dropdown-high {
|
|
594
|
-
position: relative;
|
|
595
|
-
z-index: 200;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
.z-dropdown-high .dropdown-menu,
|
|
599
|
-
.z-dropdown-high .option-list {
|
|
600
|
-
z-index: 250;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
.z-dropdown {
|
|
604
|
-
position: relative;
|
|
605
|
-
z-index: 100;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
.z-dropdown .dropdown-menu,
|
|
609
|
-
.z-dropdown .option-list {
|
|
610
|
-
z-index: 150;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/* ==========================================================================
|
|
614
|
-
CONDITIONAL VISIBILITY - Required for editor switching logic
|
|
615
|
-
========================================================================== */
|
|
616
|
-
.admin-editor-section.landscape-hidden,
|
|
617
|
-
.proxy-editor-section.landscape-hidden {
|
|
618
|
-
display: none !important;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
/* ==========================================================================
|
|
622
|
-
FILE DROPDOWN STYLING
|
|
623
|
-
========================================================================== */
|
|
624
|
-
.admin-file-dropdown {
|
|
625
|
-
height: 2.5rem !important;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
.proxy-file-dropdown {
|
|
629
|
-
@apply rounded-lg;
|
|
630
|
-
height: 2.5rem !important;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
.refresh-button {
|
|
634
|
-
height: 2.5rem !important;
|
|
635
|
-
|
|
636
|
-
&:hover {
|
|
637
|
-
.refresh-icon {
|
|
638
|
-
@apply rotate-180;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
.refresh-icon {
|
|
644
|
-
@apply transition-transform duration-500;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/* ==========================================================================
|
|
648
|
-
EDITOR CONTAINERS
|
|
649
|
-
========================================================================== */
|
|
650
|
-
.editor-container {
|
|
651
|
-
position: relative;
|
|
652
|
-
height: 400px;
|
|
653
|
-
max-height: 60vh;
|
|
654
|
-
}
|
|
655
205
|
|
|
656
|
-
|
|
657
|
-
@apply relative overflow-hidden rounded-lg shadow-card bg-dark-350 flex flex-col;
|
|
658
|
-
height: 400px;
|
|
659
|
-
max-height: 60vh;
|
|
660
|
-
transition: height 0.3s ease;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
.proxy-editor-container .pb-4 {
|
|
664
|
-
@apply flex-1 flex flex-col;
|
|
665
|
-
padding-bottom: 0 !important;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
.proxy-editor-container .table-component {
|
|
669
|
-
@apply flex-1 flex flex-col;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
/* ==========================================================================
|
|
673
|
-
EDITOR TEXTAREAS - CRITICAL: Custom font, scrolling behavior
|
|
674
|
-
========================================================================== */
|
|
675
|
-
.proxy-editor {
|
|
676
|
-
@apply w-full h-full overflow-auto resize-none border-none outline-none bg-transparent p-3 m-0 box-border text-light-300 flex-1;
|
|
677
|
-
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
678
|
-
font-size: 14px;
|
|
679
|
-
line-height: 1.6;
|
|
680
|
-
tab-size: 4;
|
|
681
|
-
-webkit-overflow-scrolling: touch;
|
|
682
|
-
min-height: 100%;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
/* EXACT COPY from FilterPreview.vue - Shared base styles for perfect alignment */
|
|
686
|
-
.code-editor,
|
|
687
|
-
.code-highlight {
|
|
688
|
-
position: absolute;
|
|
689
|
-
inset: 0;
|
|
690
|
-
width: 100%;
|
|
691
|
-
height: 100%;
|
|
692
|
-
min-height: 300px;
|
|
693
|
-
max-height: 500px;
|
|
694
|
-
padding: 12px;
|
|
695
|
-
margin: 0;
|
|
696
|
-
overflow: auto;
|
|
697
|
-
white-space: pre;
|
|
698
|
-
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
699
|
-
font-size: 14px;
|
|
700
|
-
line-height: 1.6;
|
|
701
|
-
tab-size: 4;
|
|
702
|
-
-moz-tab-size: 4;
|
|
703
|
-
word-wrap: normal;
|
|
704
|
-
word-break: normal;
|
|
705
|
-
border: 0;
|
|
706
|
-
outline: none;
|
|
707
|
-
background: transparent;
|
|
708
|
-
box-sizing: border-box;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
/* Code editor layer - interactive */
|
|
712
|
-
.code-editor {
|
|
713
|
-
z-index: 2;
|
|
714
|
-
color: transparent !important;
|
|
715
|
-
caret-color: #ffffff;
|
|
716
|
-
resize: none;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
.code-editor::selection {
|
|
720
|
-
background-color: rgba(38, 79, 120, 0.6);
|
|
721
|
-
color: transparent;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
.code-editor::-moz-selection {
|
|
725
|
-
background-color: rgba(38, 79, 120, 0.6);
|
|
726
|
-
color: transparent;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
/* Highlight layer - visual only */
|
|
730
|
-
.code-highlight {
|
|
731
|
-
z-index: 1;
|
|
732
|
-
pointer-events: none;
|
|
733
|
-
user-select: none;
|
|
734
|
-
-webkit-user-select: none;
|
|
735
|
-
-moz-user-select: none;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
/* ==========================================================================
|
|
739
|
-
PRISM.JS SYNTAX HIGHLIGHTING THEME - CRITICAL: Token colors
|
|
740
|
-
========================================================================== */
|
|
741
|
-
code[class*="language-"],
|
|
742
|
-
pre[class*="language-"] {
|
|
743
|
-
@apply bg-transparent text-left;
|
|
744
|
-
color: #f8f8f2;
|
|
745
|
-
text-shadow: 0 1px oklch(0 0 0 / 0.3);
|
|
746
|
-
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
|
747
|
-
white-space: pre;
|
|
748
|
-
word-spacing: normal;
|
|
749
|
-
word-break: normal;
|
|
750
|
-
word-wrap: normal;
|
|
751
|
-
line-height: 1.5;
|
|
752
|
-
tab-size: 4;
|
|
753
|
-
hyphens: none;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
pre[class*="language-"]:not(.code-highlight) {
|
|
757
|
-
@apply p-3 m-0 overflow-auto rounded;
|
|
758
|
-
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
|
759
|
-
font-size: 14px;
|
|
760
|
-
line-height: 1.5;
|
|
761
|
-
tab-size: 4;
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
/* Override for code-highlight to match code-editor */
|
|
765
|
-
.code-highlight.language-json,
|
|
766
|
-
.code-highlight[class*="language-"] {
|
|
767
|
-
line-height: 1.6 !important;
|
|
768
|
-
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace !important;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
:not(pre) > code[class*="language-"],
|
|
772
|
-
pre[class*="language-"] {
|
|
773
|
-
@apply bg-dark-350 whitespace-pre;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
:not(pre) > code[class*="language-"] {
|
|
777
|
-
@apply whitespace-normal rounded-sm;
|
|
778
|
-
padding: 0.1em;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/* CRITICAL: VSCode Dark+ theme for syntax highlighting */
|
|
782
|
-
.token.comment,
|
|
783
|
-
.token.prolog,
|
|
784
|
-
.token.doctype,
|
|
785
|
-
.token.cdata {
|
|
786
|
-
font-style: italic;
|
|
787
|
-
color: #6a9955;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
.token.punctuation {
|
|
791
|
-
color: #d4d4d4;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
.namespace {
|
|
795
|
-
@apply opacity-80;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
.token.property,
|
|
799
|
-
.token.tag,
|
|
800
|
-
.token.constant,
|
|
801
|
-
.token.symbol,
|
|
802
|
-
.token.deleted {
|
|
803
|
-
color: #b5cea8;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
.token.boolean,
|
|
807
|
-
.token.number {
|
|
808
|
-
color: #b5cea8;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
.token.selector,
|
|
812
|
-
.token.attr-name,
|
|
813
|
-
.token.string,
|
|
814
|
-
.token.char,
|
|
815
|
-
.token.builtin,
|
|
816
|
-
.token.inserted {
|
|
817
|
-
color: #ce9178;
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
.token.operator,
|
|
821
|
-
.token.entity,
|
|
822
|
-
.token.url {
|
|
823
|
-
color: #d4d4d4;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
.language-css .token.string,
|
|
827
|
-
.style .token.string {
|
|
828
|
-
color: #ce9178;
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
.token.atrule,
|
|
832
|
-
.token.attr-value,
|
|
833
|
-
.token.keyword {
|
|
834
|
-
color: #c586c0;
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
.token.function,
|
|
838
|
-
.token.class-name {
|
|
839
|
-
color: #dcdcaa;
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
.token.regex,
|
|
843
|
-
.token.important,
|
|
844
|
-
.token.variable {
|
|
845
|
-
color: #9cdcfe;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
.token.important,
|
|
849
|
-
.token.bold {
|
|
850
|
-
font-weight: bold;
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
.token.italic {
|
|
854
|
-
font-style: italic;
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
.token.entity {
|
|
858
|
-
@apply cursor-help;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
.editor-container:hover {
|
|
862
|
-
@apply shadow-xl;
|
|
863
|
-
transition: box-shadow 0.3s ease;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
/* ==========================================================================
|
|
867
|
-
ERROR MESSAGES
|
|
868
|
-
========================================================================== */
|
|
869
|
-
.error-container {
|
|
870
|
-
@apply flex items-start gap-3 p-4 bg-red-500/10 border border-red-500/20 rounded-lg mt-4 mb-4 max-w-full break-words;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
.error-icon {
|
|
874
|
-
@apply flex-shrink-0 text-red-400;
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
.error-content {
|
|
878
|
-
@apply flex-1 min-w-0;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
.error-title {
|
|
882
|
-
@apply text-red-400 font-medium text-sm mb-1;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
.error-text {
|
|
886
|
-
@apply text-red-300 text-xs break-words;
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
/* ==========================================================================
|
|
890
|
-
SECTION DIVIDER - CRITICAL: Gradient effect
|
|
891
|
-
========================================================================== */
|
|
206
|
+
<style lang="scss" scoped>
|
|
892
207
|
.section-divider {
|
|
893
|
-
@apply
|
|
894
|
-
margin: 24px 0;
|
|
895
|
-
height: 1px;
|
|
896
|
-
background: linear-gradient(90deg, transparent 0%, oklch(0.26 0 0) 20%, oklch(0.26 0 0) 80%, transparent 100%);
|
|
897
|
-
box-shadow: 0 0 8px oklch(0.26 0 0 / 0.3);
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
/* ==========================================================================
|
|
901
|
-
MOBILE RESPONSIVE STYLES (max-width: 767px)
|
|
902
|
-
========================================================================== */
|
|
903
|
-
@media (max-width: 767px) {
|
|
904
|
-
.editor-container,
|
|
905
|
-
.proxy-editor-container {
|
|
906
|
-
height: calc(100vh - 380px) !important;
|
|
907
|
-
max-height: 60vh !important;
|
|
908
|
-
min-height: 300px !important;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
.editor-container.has-error {
|
|
912
|
-
height: calc(100vh - 460px) !important;
|
|
913
|
-
max-height: 50vh !important;
|
|
914
|
-
min-height: 250px !important;
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
.error-container {
|
|
918
|
-
@apply my-2 p-2;
|
|
919
|
-
font-size: 11px !important;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
.error-title {
|
|
923
|
-
font-size: 11px !important;
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
.error-text {
|
|
927
|
-
font-size: 10px !important;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
.my-3 {
|
|
931
|
-
@apply my-1.5;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
.pb-4 {
|
|
935
|
-
@apply pb-1;
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
/* ==========================================================================
|
|
940
|
-
DESKTOP RESPONSIVE STYLES
|
|
941
|
-
========================================================================== */
|
|
942
|
-
@media (min-width: 1024px) {
|
|
943
|
-
.editor-container,
|
|
944
|
-
.proxy-editor-container {
|
|
945
|
-
max-height: 60vh;
|
|
946
|
-
}
|
|
208
|
+
@apply my-8 h-px w-full bg-dark-550;
|
|
947
209
|
}
|
|
948
210
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
max-height: 70vh;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
/* ==========================================================================
|
|
957
|
-
LANDSCAPE MODE - CRITICAL: Complex responsive behavior
|
|
958
|
-
========================================================================== */
|
|
959
|
-
@media (max-height: 500px) and (orientation: landscape) and (min-width: 568px) {
|
|
960
|
-
.admin-editor-section:not(.landscape-hidden) + .section-divider + .proxy-editor-section.landscape-hidden {
|
|
961
|
-
@apply hidden;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
h4 {
|
|
965
|
-
@apply pt-4;
|
|
966
|
-
font-size: 16px !important;
|
|
967
|
-
margin-bottom: 6px !important;
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
h5 {
|
|
971
|
-
font-size: 14px !important;
|
|
972
|
-
margin-bottom: 4px !important;
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
.section-divider {
|
|
976
|
-
@apply my-1.5;
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
.my-3 {
|
|
980
|
-
@apply my-1;
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
.pb-4 {
|
|
984
|
-
@apply pb-0.5;
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
.editor-container,
|
|
988
|
-
.proxy-editor-container {
|
|
989
|
-
height: 180px !important;
|
|
990
|
-
max-height: 180px !important;
|
|
991
|
-
min-height: 150px !important;
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
.editor-container.has-error {
|
|
995
|
-
height: 120px !important;
|
|
996
|
-
max-height: 120px !important;
|
|
997
|
-
min-height: 100px !important;
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
.proxy-editor {
|
|
1001
|
-
@apply h-full;
|
|
1002
|
-
min-height: 100% !important;
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
.proxy-editor {
|
|
1006
|
-
@apply p-1.5 text-xs;
|
|
1007
|
-
line-height: 1.4 !important;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
.code-editor,
|
|
1011
|
-
.code-highlight {
|
|
1012
|
-
padding: 6px !important;
|
|
1013
|
-
font-size: 12px !important;
|
|
1014
|
-
line-height: 1.4 !important;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
.error-container {
|
|
1018
|
-
@apply rounded gap-1.5 my-0.5 px-1.5 py-1;
|
|
1019
|
-
font-size: 9px !important;
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
.error-icon {
|
|
1023
|
-
@apply w-3 h-3;
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
.error-title {
|
|
1027
|
-
@apply mb-0.5 font-medium;
|
|
1028
|
-
font-size: 9px !important;
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
.error-text {
|
|
1032
|
-
font-size: 8px !important;
|
|
1033
|
-
line-height: 1.2 !important;
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
/* Very short landscape screens */
|
|
1038
|
-
@media (max-height: 400px) and (orientation: landscape) {
|
|
1039
|
-
.editor-container,
|
|
1040
|
-
.proxy-editor-container {
|
|
1041
|
-
height: 140px !important;
|
|
1042
|
-
max-height: 140px !important;
|
|
1043
|
-
min-height: 120px !important;
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
.editor-container.has-error {
|
|
1047
|
-
height: 90px !important;
|
|
1048
|
-
max-height: 90px !important;
|
|
1049
|
-
min-height: 80px !important;
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
.proxy-editor {
|
|
1053
|
-
@apply h-full p-1;
|
|
1054
|
-
min-height: 100% !important;
|
|
1055
|
-
font-size: 10px !important;
|
|
1056
|
-
line-height: 1.3 !important;
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
.code-editor,
|
|
1060
|
-
.code-highlight {
|
|
1061
|
-
padding: 4px !important;
|
|
1062
|
-
font-size: 10px !important;
|
|
1063
|
-
line-height: 1.3 !important;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
.error-container {
|
|
1067
|
-
@apply rounded-sm gap-1 my-px px-1 py-0.5;
|
|
1068
|
-
font-size: 8px !important;
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
.error-icon {
|
|
1072
|
-
@apply w-2.5 h-2.5;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
.error-title {
|
|
1076
|
-
@apply mb-px font-medium;
|
|
1077
|
-
font-size: 8px !important;
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
.error-text {
|
|
1081
|
-
font-size: 7px !important;
|
|
1082
|
-
line-height: 1.1 !important;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
/* ==========================================================================
|
|
1087
|
-
COMPACT EDITOR BUTTONS
|
|
1088
|
-
========================================================================== */
|
|
1089
|
-
.button-default {
|
|
1090
|
-
@apply h-7 w-7 p-0 rounded-md;
|
|
1091
|
-
min-width: 28px !important;
|
|
1092
|
-
max-width: 28px !important;
|
|
1093
|
-
width: 28px !important;
|
|
1094
|
-
height: 28px !important;
|
|
1095
|
-
padding: 0 !important;
|
|
1096
|
-
|
|
1097
|
-
svg {
|
|
1098
|
-
@apply w-4 h-4;
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
@media (max-width: 640px) {
|
|
1103
|
-
.button-default {
|
|
1104
|
-
@apply h-6 w-6;
|
|
1105
|
-
min-width: 24px !important;
|
|
1106
|
-
max-width: 24px !important;
|
|
1107
|
-
width: 24px !important;
|
|
1108
|
-
height: 24px !important;
|
|
1109
|
-
|
|
1110
|
-
svg {
|
|
1111
|
-
@apply w-3.5 h-3.5;
|
|
1112
|
-
}
|
|
211
|
+
.landscape-hidden {
|
|
212
|
+
@media (max-width: 1023px) and (orientation: landscape) {
|
|
213
|
+
display: none !important;
|
|
1113
214
|
}
|
|
1114
215
|
}
|
|
1115
216
|
</style>
|