@necrolab/dashboard 0.4.61 → 0.4.208

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.
Files changed (133) hide show
  1. package/.prettierrc +1 -27
  2. package/.vscode/extensions.json +1 -1
  3. package/README.md +79 -43
  4. package/backend/api.js +48 -40
  5. package/backend/auth.js +3 -3
  6. package/backend/batching.js +1 -1
  7. package/backend/endpoints.js +77 -13
  8. package/backend/index.js +2 -2
  9. package/backend/mock-data.js +38 -29
  10. package/backend/mock-src/classes/logger.js +8 -8
  11. package/backend/mock-src/classes/utils.js +3 -7
  12. package/backend/mock-src/database.js +0 -0
  13. package/backend/mock-src/ticketmaster.js +79 -79
  14. package/backend/validator.js +2 -2
  15. package/config/configs.json +3 -2
  16. package/config/filter.json +3 -2
  17. package/index.html +10 -81
  18. package/index.js +1 -1
  19. package/package.json +25 -40
  20. package/postcss.config.js +1 -1
  21. package/postinstall.js +17 -98
  22. package/public/android-chrome-192x192.png +0 -0
  23. package/public/android-chrome-512x512.png +0 -0
  24. package/public/apple-touch-icon.png +0 -0
  25. package/public/favicon-16x16.png +0 -0
  26. package/public/favicon-32x32.png +0 -0
  27. package/public/favicon.ico +0 -0
  28. package/public/manifest.json +7 -12
  29. package/public/sw.js +2 -0
  30. package/public/workbox-49fdaf31.js +2 -0
  31. package/public/workbox-49fdaf31.js.map +1 -0
  32. package/public/workbox-88575b92.js +2 -0
  33. package/public/workbox-88575b92.js.map +1 -0
  34. package/public/workbox-a67a7b11.js +2 -0
  35. package/public/workbox-a67a7b11.js.map +1 -0
  36. package/public/workbox-d4314735.js +2 -0
  37. package/public/workbox-d4314735.js.map +1 -0
  38. package/public/workbox-e0f89ef3.js +2 -0
  39. package/public/workbox-e0f89ef3.js.map +1 -0
  40. package/run +9 -176
  41. package/src/App.vue +85 -498
  42. package/src/assets/css/_input.scss +99 -144
  43. package/src/assets/css/main.scss +99 -450
  44. package/src/assets/img/background.svg +2 -2
  45. package/src/assets/img/logo_icon.png +0 -0
  46. package/src/components/Auth/LoginForm.vue +11 -62
  47. package/src/components/Editors/Account/Account.vue +40 -116
  48. package/src/components/Editors/Account/AccountCreator.vue +39 -88
  49. package/src/components/Editors/Account/AccountView.vue +34 -102
  50. package/src/components/Editors/Account/CreateAccount.vue +32 -80
  51. package/src/components/Editors/Profile/CreateProfile.vue +83 -269
  52. package/src/components/Editors/Profile/Profile.vue +47 -132
  53. package/src/components/Editors/Profile/ProfileCountryChooser.vue +20 -82
  54. package/src/components/Editors/Profile/ProfileView.vue +34 -91
  55. package/src/components/Editors/TagLabel.vue +6 -67
  56. package/src/components/Filter/Filter.vue +72 -289
  57. package/src/components/Filter/FilterPreview.vue +30 -171
  58. package/src/components/Filter/PriceSortToggle.vue +4 -74
  59. package/src/components/Table/Header.vue +1 -1
  60. package/src/components/Table/Row.vue +1 -1
  61. package/src/components/Table/Table.vue +2 -19
  62. package/src/components/Tasks/CheckStock.vue +13 -28
  63. package/src/components/Tasks/Controls/DesktopControls.vue +17 -17
  64. package/src/components/Tasks/Controls/MobileControls.vue +45 -8
  65. package/src/components/Tasks/CreateTaskAXS.vue +73 -79
  66. package/src/components/Tasks/CreateTaskTM.vue +142 -94
  67. package/src/components/Tasks/MassEdit.vue +7 -9
  68. package/src/components/Tasks/QuickSettings.vue +55 -169
  69. package/src/components/Tasks/ScrapeVenue.vue +4 -7
  70. package/src/components/Tasks/Stats.vue +23 -52
  71. package/src/components/Tasks/Task.vue +136 -378
  72. package/src/components/Tasks/TaskView.vue +47 -107
  73. package/src/components/Tasks/Utilities.vue +6 -5
  74. package/src/components/icons/Bag.vue +1 -1
  75. package/src/components/icons/Loyalty.vue +1 -1
  76. package/src/components/icons/Mail.vue +2 -2
  77. package/src/components/icons/Play.vue +2 -2
  78. package/src/components/icons/Reload.vue +5 -4
  79. package/src/components/icons/Sandclock.vue +2 -2
  80. package/src/components/icons/Stadium.vue +1 -1
  81. package/src/components/icons/index.js +1 -24
  82. package/src/components/ui/Modal.vue +13 -105
  83. package/src/components/ui/Navbar.vue +38 -171
  84. package/src/components/ui/ReconnectIndicator.vue +55 -351
  85. package/src/components/ui/Splash.vue +35 -5
  86. package/src/components/ui/controls/CountryChooser.vue +62 -200
  87. package/src/components/ui/controls/atomic/Checkbox.vue +10 -119
  88. package/src/components/ui/controls/atomic/Dropdown.vue +39 -208
  89. package/src/components/ui/controls/atomic/MultiDropdown.vue +37 -300
  90. package/src/libs/Filter.js +170 -200
  91. package/src/registerServiceWorker.js +1 -1
  92. package/src/stores/connection.js +53 -51
  93. package/src/stores/logger.js +3 -11
  94. package/src/stores/sampleData.js +235 -207
  95. package/src/stores/ui.js +44 -112
  96. package/src/stores/utils.js +6 -90
  97. package/src/views/Accounts.vue +35 -44
  98. package/src/views/Console.vue +90 -341
  99. package/src/views/Editor.vue +123 -1176
  100. package/src/views/FilterBuilder.vue +251 -607
  101. package/src/views/Login.vue +14 -76
  102. package/src/views/Profiles.vue +25 -44
  103. package/src/views/Tasks.vue +100 -187
  104. package/static/offline.html +50 -192
  105. package/tailwind.config.js +26 -104
  106. package/vite.config.js +16 -73
  107. package/vue.config.js +32 -0
  108. package/workbox-config.js +11 -0
  109. package/artwork/image.png +0 -0
  110. package/dev-server.js +0 -136
  111. package/exit +0 -209
  112. package/jsconfig.json +0 -16
  113. package/src/assets/css/_utilities.scss +0 -388
  114. package/src/assets/img/background.svg.backup +0 -11
  115. package/src/components/icons/Check.vue +0 -5
  116. package/src/components/icons/Close.vue +0 -21
  117. package/src/components/icons/CloseX.vue +0 -5
  118. package/src/components/icons/Key.vue +0 -21
  119. package/src/components/icons/Pencil.vue +0 -21
  120. package/src/components/icons/Profile.vue +0 -18
  121. package/src/components/icons/Sell.vue +0 -21
  122. package/src/components/icons/Spinner.vue +0 -42
  123. package/src/components/icons/SquareCheck.vue +0 -18
  124. package/src/components/icons/SquareUncheck.vue +0 -18
  125. package/src/components/icons/Wildcard.vue +0 -18
  126. package/src/components/ui/controls/atomic/LoadingButton.vue +0 -45
  127. package/src/composables/useClickOutside.js +0 -21
  128. package/src/composables/useDropdownPosition.js +0 -174
  129. package/src/types/index.js +0 -41
  130. package/src/utils/debug.js +0 -1
  131. package/switch-branch.sh +0 -41
  132. package/workbox-config.cjs +0 -63
  133. /package/src/assets/img/{logo_icon-old.png → logo_icon_2.png} +0 -0
@@ -1,217 +1,122 @@
1
1
  <template>
2
2
  <div>
3
3
  <!-- Heading -->
4
+ <GearIcon class="w-5 cursor-pointer" @click="ui.toggleModal('quick-settings')" />
4
5
  <h4 class="text-white text-xl font-bold mb-5 pt-5 flex gap-2 items-center">
5
- Editor
6
- <img src="@/assets/img/pencil.svg" />
6
+ Editor <img src="@/assets/img/pencil.svg" />
7
7
  </h4>
8
8
 
9
- <div class="card-dark p-2">
10
- <!-- Admin Editor Section - Hidden when proxy editor is open -->
11
- <div v-if="ui.profile.admin" class="admin-editor-section" :class="{ 'landscape-hidden': currentProxyList }">
9
+ <div class="bg-dark-500 p-2 rounded shadow border-2 border-dark-550">
10
+ <div v-if="ui.profile.admin">
12
11
  <h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Admin Editor</h5>
13
- <div class="flex-responsive-wrap editor-controls-row">
14
- <div class="w-full lg:w-64 flex flex-shrink-0 dropdown-container z-dropdown-high">
15
- <div class="relative flex-grow">
16
- <Dropdown
17
- class="bg-dark-500 border-2 border-r-0 border-dark-550 admin-file-dropdown w-full"
18
- default="Select a file"
19
- :onClick="(f) => loadFile(f)"
20
- :options="availableFiles"
21
- :allowDefault="false"
22
- :includeAdjacentButtons="true"
23
- rightAmount="right-1" />
24
- </div>
25
- <button
26
- class="refresh-button flex items-center justify-center w-10 h-10 text-white bg-dark-400 rounded-r-lg border-2 border-dark-550 border-l-0"
27
- @click="loadAvailableFiles()"
28
- title="Refresh file list">
29
- <ReloadIcon class="refresh-icon" />
30
- </button>
31
- </div>
32
- <!-- Admin editor buttons moved here -->
33
- <div
34
- v-if="textEditorVisible"
35
- class="flex flex-wrap gap-responsive justify-center lg:justify-end editor-buttons-responsive">
12
+ <div class="w-52 flex rounded input-default z-50">
13
+ <Dropdown
14
+ class="w-40"
15
+ default="Select a file"
16
+ :onClick="(f) => loadFile(f)"
17
+ :options="availableFiles"
18
+ :allowDefault="false"
19
+ rightAmount="right-1"
20
+ />
21
+
22
+ <button class="p-2 h-10 text-white ml-auto border-none ring-0 mr-3" @click="loadAvailableFiles()">
23
+ <ReloadIcon />
24
+ </button>
25
+ </div>
26
+ </div>
27
+
28
+ <transition name="fade">
29
+ <div v-if="textEditorVisible" class="my-3">
30
+ <!-- Edit -->
31
+ <div class="flex gap-x-4 mb-8">
36
32
  <button
37
- class="btn-action flex-shrink-0"
33
+ class="bg-dark-400 w-32 text-xs h-10 text-white rounded flex items-center justify-center gap-3"
38
34
  @click="format()"
39
- v-if="isJsonFile()"
40
- title="Format JSON">
41
- <svg
42
- xmlns="http://www.w3.org/2000/svg"
43
- width="16"
44
- height="16"
45
- viewBox="0 0 24 24"
46
- fill="none"
47
- stroke="currentColor"
48
- stroke-width="2"
49
- stroke-linecap="round"
50
- stroke-linejoin="round">
51
- <path d="M21 10H7" />
52
- <path d="M21 6H3" />
53
- <path d="M21 14H3" />
54
- <path d="M21 18H7" />
55
- </svg>
56
- <span class="hidden sm:inline">Format</span>
57
- </button>
58
- <button class="btn-action flex-shrink-0" @click="saveAll" title="Save File">
59
- <svg
60
- xmlns="http://www.w3.org/2000/svg"
61
- width="16"
62
- height="16"
63
- viewBox="0 0 24 24"
64
- fill="none"
65
- stroke="currentColor"
66
- stroke-width="2"
67
- stroke-linecap="round"
68
- stroke-linejoin="round">
69
- <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
70
- <polyline points="17 21 17 13 7 13 7 21" />
71
- <polyline points="7 3 7 8 15 8" />
72
- </svg>
73
- <span class="hidden sm:inline">Save File</span>
35
+ >
36
+ <span> Format </span>
37
+ <EditIcon />
74
38
  </button>
75
- <button class="btn-action flex-shrink-0" @click="closeFile" title="Close File">
76
- <svg
77
- xmlns="http://www.w3.org/2000/svg"
78
- width="16"
79
- height="16"
80
- viewBox="0 0 24 24"
81
- fill="none"
82
- stroke="currentColor"
83
- stroke-width="2"
84
- stroke-linecap="round"
85
- stroke-linejoin="round">
86
- <line x1="18" y1="6" x2="6" y2="18"></line>
87
- <line x1="6" y1="6" x2="18" y2="18"></line>
88
- </svg>
89
- <span class="hidden sm:inline">Close File</span>
39
+ <button
40
+ class="bg-dark-400 border border-dark-400 w-32 text-xs h-10 text-white rounded flex items-center justify-center gap-3"
41
+ @click="saveAll"
42
+ >
43
+ <span>Save File</span>
44
+ <img src="/img/save.svg" width="14" class="invert" />
90
45
  </button>
91
46
  </div>
92
- </div>
93
-
94
- <transition name="fade">
95
- <div v-if="textEditorVisible" class="my-3 relative">
96
- <div class="pb-4">
97
- <!-- Syntax Highlighting Editor -->
98
- <div class="editor-container" :class="{ 'has-error': errorMessage }">
99
- <div class="editor-wrapper">
100
- <pre ref="codeDisplay" class="language-json code-highlight"></pre>
101
- <textarea
102
- ref="codeEditor"
103
- v-model="currentContent"
104
- class="code-editor"
105
- spellcheck="false"
106
- @scroll="syncScroll"
107
- @input="highlightCode"
108
- @keydown.tab.prevent="handleTab"></textarea>
109
- </div>
110
- </div>
111
- </div>
112
-
113
- <div v-if="errorMessage" class="error-container">
114
- <div class="error-icon">
115
- <svg
116
- width="16"
117
- height="16"
118
- viewBox="0 0 24 24"
119
- fill="none"
120
- stroke="currentColor"
121
- stroke-width="2">
122
- <circle cx="12" cy="12" r="10" />
123
- <line x1="15" y1="9" x2="9" y2="15" />
124
- <line x1="9" y1="9" x2="15" y2="15" />
125
- </svg>
126
- </div>
127
- <div class="error-content">
128
- <div class="error-title">JSON Syntax Error</div>
129
- <div class="error-text">{{ errorMessage }}</div>
130
- </div>
131
- </div>
47
+ <div class="overflow-scroll max-h-40 lg:max-h-80 hidden-scrollbars">
48
+ <!-- Textarea -->
49
+ <CodeEditor
50
+ v-model="currentContent"
51
+ width="100%"
52
+ spellcheck="false"
53
+ @change="format()"
54
+ :hide_header="true"
55
+ :language_selector="false"
56
+ :languages="[isJsonFile() ? ['json', 'JSON'] : [], ['text']]"
57
+ theme="dark"
58
+ ></CodeEditor>
132
59
  </div>
133
- </transition>
134
- </div>
135
-
136
- <!-- Section Divider - Show when both editors are closed -->
137
- <div v-if="ui.profile.admin && !textEditorVisible && !currentProxyList" class="section-divider" />
138
60
 
139
- <!-- Proxy Editor Section - Hidden when admin editor is open -->
140
- <div class="proxy-editor-section" :class="{ 'landscape-hidden': textEditorVisible }">
141
- <h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Proxy Editor</h5>
142
- <div class="flex-responsive-wrap proxy-controls-row mb-1">
143
- <div class="w-full lg:w-64 flex flex-shrink-0 dropdown-container z-dropdown">
144
- <div class="relative flex-grow">
145
- <Dropdown
146
- class="bg-dark-500 border-2 border-dark-550 proxy-file-dropdown w-full"
147
- :default="ui.profile.proxyList?.checkout || proxyLists[0]"
148
- :onClick="loadProxies"
149
- :options="proxyLists"
150
- :allowDefault="false"
151
- :includeAdjacentButtons="true"
152
- rightAmount="right-1" />
153
- </div>
154
- </div>
155
- <!-- Proxy save button moved here -->
156
- <div
157
- v-if="currentProxyList"
158
- class="flex flex-wrap gap-responsive justify-center lg:justify-end editor-buttons-responsive">
159
- <button class="btn-action flex-shrink-0" @click="saveProxies" title="Save Proxies">
160
- <svg
161
- xmlns="http://www.w3.org/2000/svg"
162
- width="16"
163
- height="16"
164
- viewBox="0 0 24 24"
165
- fill="none"
166
- stroke="currentColor"
167
- stroke-width="2"
168
- stroke-linecap="round"
169
- stroke-linejoin="round">
170
- <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
171
- <polyline points="17 21 17 13 7 13 7 21" />
172
- <polyline points="7 3 7 8 15 8" />
173
- </svg>
174
- <span class="hidden sm:inline">Save Proxies</span>
175
- </button>
176
- <button class="btn-action flex-shrink-0" @click="closeProxyFile" title="Close File">
177
- <svg
178
- xmlns="http://www.w3.org/2000/svg"
179
- width="16"
180
- height="16"
181
- viewBox="0 0 24 24"
182
- fill="none"
183
- stroke="currentColor"
184
- stroke-width="2"
185
- stroke-linecap="round"
186
- stroke-linejoin="round">
187
- <line x1="18" y1="6" x2="6" y2="18"></line>
188
- <line x1="6" y1="6" x2="18" y2="18"></line>
189
- </svg>
190
- <span class="hidden sm:inline">Close File</span>
191
- </button>
192
- </div>
61
+ <p class="text-red-400 text-bold">{{ errorMessage }}</p>
193
62
  </div>
194
- <!-- Textarea -->
195
- <transition name="fade">
196
- <div v-if="currentProxyList" class="relative my-3">
197
- <div class="pb-4">
198
- <div class="proxy-editor-container table-component">
199
- <textarea v-model="proxyContent" class="proxy-editor" spellcheck="false"></textarea>
200
- </div>
201
- </div>
202
- </div>
203
- </transition>
63
+ </transition>
64
+ <div class="border border-light-300 my-8" />
65
+
66
+ <h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Proxy Editor</h5>
67
+ <div class="flex gap-4 justify-start items-center mb-4 relative z-60">
68
+ <Dropdown
69
+ class="rounded text-white bg-dark-500 border-dark-550 border-2 w-52 p-1 pl-2 z-30 special-dropdown"
70
+ :default="ui.profile.proxyList?.checkout || proxyLists[0]"
71
+ :onClick="loadProxies"
72
+ :options="proxyLists"
73
+ :allowDefault="false"
74
+ rightAmount="right-1"
75
+ />
76
+ <button
77
+ v-if="currentProxyList"
78
+ class="bg-dark-500 border-2 border-dark-550 w-32 text-xs h-10 text-white rounded"
79
+ @click="saveProxies"
80
+ >
81
+ <i class="far fa-border-all"></i> Save Proxies
82
+ </button>
204
83
  </div>
84
+ <!-- Textarea -->
85
+ <transition name="fade">
86
+ <div v-if="currentProxyList" class="max-h-64 lg:max-h-80 overflow-auto hidden-scrollbars z-0">
87
+ <CodeEditor
88
+ v-model="proxyContent"
89
+ width="100%"
90
+ spellcheck="false"
91
+ @change="format()"
92
+ :hide_header="true"
93
+ :language_selector="false"
94
+ :languages="[['text']]"
95
+ theme="dark"
96
+ class=""
97
+ ></CodeEditor>
98
+ </div>
99
+ </transition>
205
100
  </div>
101
+ <QuickSettings v-if="activeModal === 'quick-settings'" />
206
102
  </div>
207
103
  </template>
208
104
  <script setup>
209
- import { ref, computed, watch, onMounted, onUnmounted, nextTick } from "vue";
105
+ import { ref, computed, watch } from "vue";
210
106
  import { DownIcon, ReloadIcon, EditIcon } from "@/components/icons";
211
107
  import { useUIStore } from "@/stores/ui";
108
+ import CodeEditor from "simple-code-editor";
109
+
212
110
  import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
111
+
112
+ // needed, even though not used
113
+ import hljs from "highlight.js/lib/core";
114
+ import json from "highlight.js/lib/languages/json";
213
115
  import { getProxyLists, getProxyFile } from "@/stores/requests";
214
- import { DEBUG } from "@/utils/debug";
116
+
117
+ const DEBUG = window.location.href.startsWith("http://localhost:5173");
118
+
119
+ hljs.registerLanguage("json", json);
215
120
 
216
121
  const loadFromApi = async (path) => {
217
122
  const res = await fetch(path);
@@ -229,10 +134,6 @@ const currentProxyList = ref("");
229
134
  const activeModal = computed(() => ui.activeModal);
230
135
  const ui = useUIStore();
231
136
 
232
- // References to editor elements
233
- const codeEditor = ref(null);
234
- const codeDisplay = ref(null);
235
-
236
137
  let previous = {
237
138
  proxyContent: { list: ui.profile.proxyList, content: "" },
238
139
  currentContent: { file: "", content: "" }
@@ -254,149 +155,30 @@ const loadAvailableFiles = async () => (availableFiles.value = await loadFromApi
254
155
 
255
156
  const isJsonFile = () => currentFile.value.endsWith(".json");
256
157
 
257
- // Function to highlight code using Prism
258
- const highlightCode = () => {
259
- if (!codeDisplay.value || !codeEditor.value) return;
260
-
261
- // Get the language based on file extension
262
- let language = "javascript"; // Default language
263
-
264
- if (currentFile.value) {
265
- if (currentFile.value.endsWith(".json")) {
266
- language = "json";
267
- } else if (currentFile.value.endsWith(".js")) {
268
- language = "javascript";
269
- } else if (currentFile.value.endsWith(".txt") || currentFile.value.endsWith(".csv")) {
270
- language = "text";
271
- // Plain text doesn't need highlighting
272
- codeDisplay.value.textContent = currentContent.value || "";
273
- codeDisplay.value.className = "language-text code-highlight";
274
- return;
275
- }
276
- }
277
-
278
- // Ensure Prism is available
279
- if (typeof Prism === "undefined") {
280
- console.error("Prism is not loaded");
281
- return;
282
- }
283
-
284
- // Use requestAnimationFrame for smoother updates
285
- requestAnimationFrame(() => {
286
- try {
287
- // Update the pre element with highlighted HTML
288
- const highlighted = Prism.highlight(currentContent.value || "", Prism.languages[language], language);
289
- codeDisplay.value.innerHTML = highlighted;
290
- codeDisplay.value.className = `language-${language} code-highlight`;
291
- } catch (e) {
292
- console.error("Highlight error:", e);
293
- // Fallback to plain text if highlighting fails
294
- codeDisplay.value.textContent = currentContent.value || "";
295
- }
296
-
297
- // Ensure scroll positions are synced after highlighting
298
- syncScroll();
299
- });
300
- };
301
-
302
- // Function to sync scrolling between textarea and highlighted code
303
- const syncScroll = () => {
304
- if (!codeDisplay.value || !codeEditor.value) return;
305
-
306
- // Synchronize scrolling between the textarea and the highlighted code
307
- requestAnimationFrame(() => {
308
- codeDisplay.value.scrollTop = codeEditor.value.scrollTop;
309
- codeDisplay.value.scrollLeft = codeEditor.value.scrollLeft;
310
- });
311
- };
312
-
313
- // Function to handle tab key press in the editor
314
- const handleTab = (e) => {
315
- const textarea = codeEditor.value;
316
- const start = textarea.selectionStart;
317
- const end = textarea.selectionEnd;
318
-
319
- // Insert 4 spaces at cursor position
320
- const spaces = " ";
321
- currentContent.value = currentContent.value.substring(0, start) + spaces + currentContent.value.substring(end);
322
-
323
- // Move cursor position after the inserted tab
324
- nextTick(() => {
325
- textarea.selectionStart = textarea.selectionEnd = start + spaces.length;
326
- highlightCode();
327
- });
328
- };
329
-
330
158
  const format = () => {
331
159
  try {
332
160
  if (!isJsonFile()) return;
333
161
 
334
162
  const formatted = JSON.stringify(JSON.parse(currentContent.value), null, 4);
335
163
  currentContent.value = formatted;
336
-
337
- // Apply syntax highlighting after formatting
338
- nextTick(() => {
339
- highlightCode();
340
- });
341
164
  } catch (e) {
342
- ui.logger.Error("Could not format JSON", e);
165
+ ui.logger.Error("Could not save filter", e);
343
166
  }
344
167
  };
345
168
 
346
- // Watch for content changes to apply syntax highlighting
347
- watch(currentContent, () => {
348
- nextTick(() => {
349
- highlightCode();
350
- });
351
- });
352
-
353
169
  const loadFile = async (f) => {
354
170
  currentFile.value = f;
355
171
  if (DEBUG) {
356
172
  textEditorVisible.value = true;
357
173
  currentProxyList.value = "";
358
- currentContent.value = new Array(100).fill(0, 0, 100).join("\n");
359
-
360
- // Update pre element class based on file type
361
- if (codeDisplay.value) {
362
- if (f.endsWith(".json")) {
363
- codeDisplay.value.className = "language-json";
364
- } else if (f.endsWith(".js")) {
365
- codeDisplay.value.className = "language-javascript";
366
- } else {
367
- codeDisplay.value.className = "language-text";
368
- }
369
- }
370
-
371
- // Apply syntax highlighting after content is set
372
- nextTick(() => {
373
- highlightCode();
374
- });
375
- return;
174
+ return (currentContent.value = new Array(100).fill(0, 0, 100).join("\n"));
376
175
  }
377
-
378
176
  const res = await loadFromApi("/api/json-file?file=" + currentFile.value);
379
177
  const text = atob(res.content);
380
178
  textEditorVisible.value = true;
381
179
  currentProxyList.value = "";
382
180
  currentContent.value = text;
383
181
  previous.currentContent = { file: currentFile.value, content: text };
384
-
385
- // Update pre element class based on file type
386
- if (codeDisplay.value) {
387
- if (f.endsWith(".json")) {
388
- codeDisplay.value.className = "language-json";
389
- } else if (f.endsWith(".js")) {
390
- codeDisplay.value.className = "language-javascript";
391
- } else {
392
- codeDisplay.value.className = "language-text";
393
- }
394
- }
395
-
396
- // Apply syntax highlighting after content is loaded
397
- nextTick(() => {
398
- highlightCode();
399
- });
400
182
  };
401
183
 
402
184
  const saveDataToAPI = async (data, endpoint, msg, json = true) => {
@@ -435,10 +217,7 @@ const saveFile = async () => {
435
217
  )
436
218
  return ui.logger.Info("Content did not change");
437
219
  saveDataToAPI(btoa(currentContent.value), "/api/json-file?file=" + currentFile.value, "Successfully saved file");
438
- previous.currentContent = {
439
- file: currentFile.value,
440
- content: btoa(currentContent.value)
441
- };
220
+ previous.currentContent = { file: currentFile.value, content: btoa(currentContent.value) };
442
221
  };
443
222
 
444
223
  const saveAll = async () => {
@@ -447,28 +226,13 @@ const saveAll = async () => {
447
226
  await saveQuickConfig();
448
227
  };
449
228
 
450
- const closeFile = () => {
451
- currentFile.value = "";
452
- currentContent.value = "";
453
- textEditorVisible.value = false;
454
- ui.logger.Info("File closed");
455
- };
456
-
457
- const closeProxyFile = () => {
458
- currentProxyList.value = "";
459
- proxyContent.value = "";
460
- ui.logger.Info("Proxy file closed");
461
- };
462
-
463
229
  const loadProxies = async (list) => {
464
230
  try {
465
231
  if (DEBUG) {
466
232
  currentProxyList.value = list;
467
233
  textEditorVisible.value = false;
468
- proxyContent.value = new Array(100).fill(0, 0, 100).join("\n");
469
- return;
234
+ return (proxyContent.value = new Array(100).fill(0, 0, 100).join("\n"));
470
235
  }
471
-
472
236
  ui.logger.Info("Loading proxies: " + list);
473
237
  currentProxyList.value = list;
474
238
  const file = await getProxyFile(list);
@@ -501,469 +265,10 @@ const loadProxyLists = async () => {
501
265
  else ui.showError("Could not load proxylists");
502
266
  };
503
267
 
504
- // Initialize syntax highlighting
505
- onMounted(() => {
506
- // Apply highlighting when the component is mounted
507
- nextTick(() => {
508
- highlightCode();
509
-
510
- // Ensure scroll synchronization on initial load
511
- if (codeEditor.value && codeDisplay.value) {
512
- syncScroll();
513
- }
514
- });
515
-
516
- // iOS-specific editor fixes with cursor tracking
517
- if (
518
- /iPad|iPhone|iPod/.test(navigator.platform) ||
519
- (navigator.maxTouchPoints && navigator.maxTouchPoints > 2 && /MacIntel/.test(navigator.platform))
520
- ) {
521
- const trackCursor = (editor) => {
522
- const scrollToCursor = () => {
523
- setTimeout(() => {
524
- const container = editor.closest(".editor-container") || editor.closest(".proxy-editor-container");
525
- if (container) {
526
- // Get cursor position and scroll to it
527
- const lines = editor.value.substring(0, editor.selectionStart).split("\n");
528
- const lineHeight = 24; // Approximate line height
529
- const cursorY = lines.length * lineHeight;
530
- const containerHeight = container.clientHeight;
531
-
532
- // Scroll to keep cursor in view
533
- if (cursorY > container.scrollTop + containerHeight - 60) {
534
- container.scrollTop = cursorY - containerHeight + 60;
535
- }
536
- }
537
- }, 100);
538
- };
539
-
540
- editor.addEventListener("focus", scrollToCursor);
541
- editor.addEventListener("input", scrollToCursor);
542
- editor.addEventListener("click", scrollToCursor);
543
- editor.addEventListener("keyup", scrollToCursor);
544
- };
545
-
546
- nextTick(() => {
547
- if (codeEditor.value) {
548
- trackCursor(codeEditor.value);
549
- }
550
- const proxyEditor = document.querySelector(".proxy-editor");
551
- if (proxyEditor) {
552
- trackCursor(proxyEditor);
553
- }
554
- });
555
- }
556
-
557
- // Watch for editor visibility changes
558
- watch(textEditorVisible, (newValue) => {
559
- if (newValue) {
560
- nextTick(() => {
561
- highlightCode();
562
-
563
- // Focus the editor when it becomes visible
564
- if (codeEditor.value) {
565
- codeEditor.value.focus();
566
- }
567
- });
568
- }
569
- });
570
- });
571
-
572
- // No cleanup needed - global iOS handling takes care of everything
573
-
574
268
  if (ui.profile.admin && !DEBUG) loadAvailableFiles();
575
269
  loadProxyLists();
576
270
  </script>
577
271
  <style lang="scss" scoped>
578
- /* ==========================================================================
579
- Z-INDEX MANAGEMENT
580
- ========================================================================== */
581
-
582
- .z-dropdown-high {
583
- position: relative;
584
- z-index: 200;
585
- }
586
-
587
- .z-dropdown-high .dropdown-menu,
588
- .z-dropdown-high .option-list {
589
- z-index: 250;
590
- }
591
-
592
- .z-dropdown {
593
- position: relative;
594
- z-index: 100;
595
- }
596
-
597
- .z-dropdown .dropdown-menu,
598
- .z-dropdown .option-list {
599
- z-index: 150;
600
- }
601
-
602
- /* ==========================================================================
603
- CARD CONTAINER RESPONSIVENESS
604
- ========================================================================== */
605
-
606
- .card-dark {
607
- max-height: calc(100vh - 100px) !important; /* Increased from 120px */
608
- overflow-y: auto !important;
609
- -webkit-overflow-scrolling: touch !important;
610
- margin-bottom: 0.5rem !important; /* Reduced from 1rem */
611
- /* Reduced bottom padding to minimize empty space */
612
- padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
613
- }
614
-
615
- /* ==========================================================================
616
- ADMIN EDITOR SECTION CONDITIONAL VISIBILITY
617
- ========================================================================== */
618
-
619
- .admin-editor-section {
620
- /* Default: always visible */
621
- }
622
-
623
- /* Hide admin editor when proxy editor is open - ALL SCREEN SIZES */
624
- .admin-editor-section.landscape-hidden {
625
- display: none !important;
626
- }
627
-
628
- /* ==========================================================================
629
- PROXY EDITOR SECTION CONDITIONAL VISIBILITY
630
- ========================================================================== */
631
-
632
- .proxy-editor-section {
633
- /* Default: always visible */
634
- }
635
-
636
- /* Hide proxy editor when admin editor is open - ALL SCREEN SIZES */
637
- .proxy-editor-section.landscape-hidden {
638
- display: none !important;
639
- }
640
-
641
- /* Ensure card has proper bottom margin when sections are hidden */
642
- .proxy-editor-section.landscape-hidden ~ .card-dark,
643
- .admin-editor-section.landscape-hidden ~ .card-dark {
644
- margin-bottom: 1rem !important;
645
- }
646
-
647
- /* ==========================================================================
648
- SECTION HEADERS
649
- ========================================================================== */
650
-
651
- .admin-editor-section h5,
652
- .proxy-editor-section h5 {
653
- /* Remove the gradient underline styling */
654
- }
655
-
656
- /* ==========================================================================
657
- ADMIN FILE DROPDOWN STYLING
658
- ========================================================================== */
659
-
660
- .admin-file-dropdown {
661
- height: 2.5rem !important;
662
- border-top-right-radius: 0 !important;
663
- border-bottom-right-radius: 0 !important;
664
- border-top-left-radius: 0.5rem !important;
665
- border-bottom-left-radius: 0.5rem !important;
666
- }
667
-
668
- .proxy-file-dropdown {
669
- height: 2.5rem !important;
670
- border-radius: 0.5rem !important;
671
- }
672
-
673
- .refresh-button {
674
- height: 2.5rem !important;
675
- transition: all 0.2s ease;
676
-
677
- &:hover {
678
- .refresh-icon {
679
- transform: rotate(180deg);
680
- }
681
- }
682
- }
683
-
684
- .refresh-icon {
685
- transition: transform 0.5s ease;
686
- }
687
-
688
- /* ==========================================================================
689
- EDITOR CONTAINERS
690
- ========================================================================== */
691
-
692
- .editor-container,
693
- .proxy-editor-container {
694
- position: relative;
695
- overflow: hidden;
696
- height: 400px;
697
- max-height: 60vh;
698
- border-radius: 8px;
699
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
700
- background-color: #2e2f34;
701
- transition: height 0.3s ease;
702
- }
703
-
704
- .proxy-editor-container {
705
- /* Ensure proxy editor takes full container space */
706
- display: flex;
707
- flex-direction: column;
708
- }
709
-
710
- .proxy-editor-container .pb-4 {
711
- /* Remove bottom padding to maximize space */
712
- padding-bottom: 0 !important;
713
- flex: 1;
714
- display: flex;
715
- flex-direction: column;
716
- }
717
-
718
- .proxy-editor-container .table-component {
719
- /* Make proxy editor container take full height */
720
- flex: 1;
721
- display: flex;
722
- flex-direction: column;
723
- }
724
-
725
- .editor-wrapper {
726
- position: relative;
727
- width: 100%;
728
- height: 100%;
729
- overflow: hidden;
730
- border-radius: 8px;
731
- }
732
-
733
- /* ==========================================================================
734
- EDITOR TEXTAREAS
735
- ========================================================================== */
736
-
737
- .code-editor,
738
- .proxy-editor {
739
- font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
740
- font-size: 14px;
741
- line-height: 1.6;
742
- tab-size: 4;
743
- background-color: transparent;
744
- border: none;
745
- outline: none;
746
- resize: none;
747
- width: 100%;
748
- height: 100%;
749
- overflow: auto;
750
- -webkit-overflow-scrolling: touch;
751
- padding: 12px;
752
- margin: 0;
753
- box-sizing: border-box;
754
- }
755
-
756
- .code-editor {
757
- /* Make textarea text transparent so syntax highlighting shows through */
758
- color: transparent !important;
759
- z-index: 2;
760
- position: relative;
761
- background-color: transparent;
762
- caret-color: #ffffff; /* Keep cursor visible */
763
-
764
- /* Selection styling */
765
- &::selection {
766
- background-color: rgba(255, 255, 255, 0.2);
767
- }
768
- }
769
-
770
- .proxy-editor {
771
- @apply w-full h-full resize-none focus:outline-none;
772
- background-color: transparent;
773
- color: #e2e2e5; /* Keep normal text color for proxy editor */
774
- /* Ensure proxy editor takes full height */
775
- flex: 1;
776
- min-height: 100%;
777
- }
778
-
779
- /* ==========================================================================
780
- CODE HIGHLIGHTING
781
- ========================================================================== */
782
-
783
- .code-highlight {
784
- font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
785
- font-size: 14px;
786
- line-height: 1.6;
787
- tab-size: 4;
788
- /* Remove transparent color - let syntax highlighting show */
789
- color: #f8f8f2 !important;
790
- background: transparent;
791
- border: none;
792
- outline: none;
793
- resize: none;
794
- width: 100%;
795
- height: 100%;
796
- overflow: hidden;
797
- white-space: pre;
798
- pointer-events: none;
799
- z-index: 1;
800
- position: absolute;
801
- top: 0;
802
- left: 0;
803
- padding: 12px;
804
- margin: 0;
805
- box-sizing: border-box;
806
- }
807
-
808
- /* ==========================================================================
809
- PRISM.JS SYNTAX HIGHLIGHTING THEME
810
- ========================================================================== */
811
-
812
- code[class*="language-"],
813
- pre[class*="language-"] {
814
- color: #f8f8f2;
815
- background: none;
816
- text-shadow: 0 1px rgba(0, 0, 0, 0.3);
817
- font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
818
- text-align: left;
819
- white-space: pre;
820
- word-spacing: normal;
821
- word-break: normal;
822
- word-wrap: normal;
823
- line-height: 1.5;
824
- tab-size: 4;
825
- hyphens: none;
826
- }
827
-
828
- pre[class*="language-"] {
829
- padding: 12px;
830
- margin: 0;
831
- overflow: auto;
832
- border-radius: 4px;
833
- font-family: "Menlo", "Monaco", "Courier New", monospace;
834
- font-size: 14px;
835
- line-height: 1.5;
836
- tab-size: 4;
837
- }
838
-
839
- :not(pre) > code[class*="language-"],
840
- pre[class*="language-"] {
841
- background: #2e2f34;
842
- white-space: pre;
843
- }
844
-
845
- :not(pre) > code[class*="language-"] {
846
- padding: 0.1em;
847
- border-radius: 0.3em;
848
- white-space: normal;
849
- }
850
-
851
- .token.comment,
852
- .token.prolog,
853
- .token.doctype,
854
- .token.cdata {
855
- color: #676f7d;
856
- font-style: italic;
857
- }
858
-
859
- .token.punctuation {
860
- color: #a9b7c6;
861
- }
862
-
863
- .namespace {
864
- opacity: 0.8;
865
- }
866
-
867
- .token.property,
868
- .token.tag,
869
- .token.constant,
870
- .token.symbol,
871
- .token.deleted {
872
- color: #e06c75;
873
- }
874
-
875
- .token.boolean,
876
- .token.number {
877
- color: #c792ea;
878
- }
879
-
880
- .token.selector,
881
- .token.attr-name,
882
- .token.string,
883
- .token.char,
884
- .token.builtin,
885
- .token.inserted {
886
- color: #98c379;
887
- }
888
-
889
- .token.operator,
890
- .token.entity,
891
- .token.url,
892
- .language-css .token.string,
893
- .style .token.string {
894
- color: #89ddff;
895
- }
896
-
897
- .token.atrule,
898
- .token.attr-value,
899
- .token.keyword {
900
- color: #61afef;
901
- }
902
-
903
- .token.function,
904
- .token.class-name {
905
- color: #ffcb6b;
906
- }
907
-
908
- .token.regex,
909
- .token.important,
910
- .token.variable {
911
- color: #c5e478;
912
- }
913
-
914
- .token.important,
915
- .token.bold {
916
- font-weight: bold;
917
- }
918
-
919
- .token.italic {
920
- font-style: italic;
921
- }
922
-
923
- .token.entity {
924
- cursor: help;
925
- }
926
-
927
- .editor-container:hover {
928
- box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
929
- transition: box-shadow 0.3s ease;
930
- }
931
-
932
- /* ==========================================================================
933
- ERROR MESSAGES
934
- ========================================================================== */
935
-
936
- .error-container {
937
- @apply flex items-start gap-3 p-4 bg-red-500/10 border border-red-500/20 rounded-lg mt-4 mb-4;
938
-
939
- /* Prevent overflow in landscape mode */
940
- max-width: 100%;
941
- word-wrap: break-word;
942
- overflow-wrap: break-word;
943
- }
944
-
945
- .error-icon {
946
- @apply flex-shrink-0 text-red-400;
947
- }
948
-
949
- .error-content {
950
- @apply flex-1;
951
- min-width: 0; /* Allow text to shrink */
952
- }
953
-
954
- .error-title {
955
- @apply text-red-400 font-medium text-sm mb-1;
956
- }
957
-
958
- .error-text {
959
- @apply text-red-300 text-xs;
960
- word-break: break-word;
961
- }
962
-
963
- /* ==========================================================================
964
- CONSOLE STYLES
965
- ========================================================================== */
966
-
967
272
  .console {
968
273
  @apply bg-dark-400 p-7 rounded relative border-dark-550 border-2;
969
274
 
@@ -973,399 +278,41 @@ pre[class*="language-"] {
973
278
  height: calc(100vh - 450px);
974
279
  @apply w-full focus:outline-none text-xs text-white;
975
280
  }
976
- }
977
-
978
- /* ==========================================================================
979
- SECTION DIVIDER
980
- ========================================================================== */
981
281
 
982
- .section-divider {
983
- margin: 24px 0; /* Balanced margin for better centering */
984
- height: 1px;
985
- width: 100%;
986
- position: relative;
282
+ $border: 2px;
987
283
 
988
- /* Add subtle gradient effect for better visual separation */
989
- background: linear-gradient(90deg, transparent 0%, #3d3e44 20%, #3d3e44 80%, transparent 100%);
990
- border: none;
991
-
992
- /* Add a subtle glow effect */
993
- box-shadow: 0 0 8px rgba(61, 62, 68, 0.3);
284
+ // &:before {
285
+ // content: "";
286
+ // @apply absolute top-0 left-0 right-0 bottom-0 opacity-60;
287
+ // z-index: -2;
288
+ // margin: -$border;
289
+ // border-radius: inherit;
290
+ // background: radial-gradient(rgba(96, 66, 255, 0.6), rgba(255, 255, 255, 0));
291
+ // }
994
292
  }
995
293
 
996
- /* ==========================================================================
997
- RESPONSIVE LAYOUT UTILITIES
998
- ========================================================================== */
999
-
1000
- .flex-responsive-wrap {
1001
- @apply flex flex-wrap items-center gap-4;
294
+ .z-inf {
295
+ z-index: 1000;
1002
296
  }
1003
297
 
1004
- /* ==========================================================================
1005
- MOBILE RESPONSIVE STYLES (max-width: 767px)
1006
- ========================================================================== */
1007
-
1008
- @media (max-width: 767px) {
1009
- /* Card container - increased height to use more available space */
1010
- .card-dark {
1011
- max-height: calc(100vh - 100px) !important; /* Increased from 120px */
1012
- overflow-y: auto !important;
1013
- -webkit-overflow-scrolling: touch !important;
1014
- margin-bottom: 0.5rem !important; /* Reduced from 1rem */
1015
- /* Reduced bottom padding to minimize empty space */
1016
- padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
1017
- }
1018
-
1019
- /* Layout adjustments - almost no gap between dropdown and buttons */
1020
- .flex-responsive-wrap {
1021
- @apply flex-col items-stretch !important;
1022
- gap: 0px !important; /* Reduced from 2px to eliminate space between dropdown and buttons */
1023
- }
1024
-
1025
- /* Button container - even spacing across full width */
1026
- .flex-responsive-wrap > div:last-child {
1027
- @apply flex justify-center !important;
1028
- }
1029
-
1030
- /* Smaller buttons on mobile */
1031
- .btn-action {
1032
- height: 32px !important;
1033
- min-height: 32px !important;
1034
- padding: 0 8px !important;
1035
- font-size: 12px !important;
1036
-
1037
- svg {
1038
- width: 14px !important;
1039
- height: 14px !important;
1040
- }
1041
- }
1042
-
1043
- /* Editor container heights - reduced for better mobile experience */
1044
- .editor-container,
1045
- .proxy-editor-container {
1046
- height: 200px !important; /* Reduced from 280px for better mobile experience */
1047
- max-height: 30vh !important; /* Reduced from 35vh */
1048
- min-height: 180px !important; /* Reduced from 220px */
1049
- }
1050
-
1051
- /* Reduce editor height when JSON error is showing in portrait */
1052
- .editor-container.has-error {
1053
- height: 160px !important; /* Reduced to make room for error message */
1054
- max-height: 25vh !important;
1055
- min-height: 140px !important;
1056
- }
1057
-
1058
- /* Error message spacing on mobile */
1059
- .error-container {
1060
- margin: 8px 0 !important;
1061
- padding: 8px !important;
1062
- font-size: 11px !important;
1063
- }
1064
-
1065
- .error-title {
1066
- font-size: 11px !important;
1067
- }
1068
-
1069
- .error-text {
1070
- font-size: 10px !important;
1071
- }
1072
-
1073
- /* Compact editor controls spacing - no margins */
1074
- .editor-controls-row,
1075
- .proxy-controls-row {
1076
- margin-bottom: 0px !important; /* Eliminated margin completely */
1077
- }
1078
-
1079
- /* Compact editor containers - reduced margins for more space */
1080
- .my-3 {
1081
- margin: 6px 0 !important; /* Reduced margin between editor and controls */
1082
- }
1083
-
1084
- .pb-4 {
1085
- padding-bottom: 4px !important; /* Reduced padding */
1086
- }
298
+ .z-inf2 {
299
+ z-index: 2000;
1087
300
  }
1088
301
 
1089
- /* ==========================================================================
1090
- TABLET RESPONSIVE STYLES (min-width: 768px)
1091
- ========================================================================== */
1092
-
1093
- @media (min-width: 768px) {
1094
- .flex-responsive-wrap {
1095
- @apply flex-row justify-between items-center !important;
1096
- }
302
+ .z-inf3 {
303
+ z-index: 3000;
1097
304
  }
1098
305
 
1099
- /* ==========================================================================
1100
- DESKTOP RESPONSIVE STYLES (min-width: 1024px)
1101
- ========================================================================== */
1102
-
1103
- @media (min-width: 1024px) {
1104
- .editor-container,
1105
- .proxy-editor-container {
1106
- max-height: 60vh;
1107
- }
306
+ .special-dropdown {
307
+ margin-left: 0 !important;
1108
308
  }
1109
309
 
1110
- /* ==========================================================================
1111
- LARGE DESKTOP RESPONSIVE STYLES (min-width: 1280px)
1112
- ========================================================================== */
1113
-
1114
- @media (min-width: 1280px) {
1115
- .editor-container,
1116
- .proxy-editor-container {
1117
- max-height: 70vh;
1118
- }
1119
- }
1120
-
1121
- /* ==========================================================================
1122
- MOBILE LANDSCAPE MODE (max-height: 500px + landscape)
1123
- ========================================================================== */
1124
-
1125
- @media (max-height: 500px) and (orientation: landscape) and (min-width: 568px) {
1126
- /* Make card fit in landscape mode with reduced bottom spacing */
1127
- .card-dark {
1128
- max-height: calc(100vh - 80px) !important; /* Increased from 60px to 80px */
1129
- overflow-y: auto !important;
1130
- -webkit-overflow-scrolling: touch !important;
1131
- margin-bottom: 0.5rem !important; /* Reduced from 1rem */
1132
- padding: 8px !important;
1133
- /* Reduced bottom padding to minimize empty space */
1134
- padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
1135
- }
1136
-
1137
- /* Truncate card cleanly when admin editor is open */
1138
- .admin-editor-section:not(.landscape-hidden) + .section-divider + .proxy-editor-section.landscape-hidden {
1139
- display: none !important;
1140
- }
1141
-
1142
- /* Ensure proxy editor takes full space when visible */
1143
- .proxy-editor-container {
1144
- height: 130px !important;
1145
- max-height: 130px !important;
1146
- min-height: 100px !important;
1147
- }
1148
-
1149
- .proxy-editor {
1150
- height: 100% !important;
1151
- min-height: 100% !important;
1152
- }
1153
-
1154
- /* Compact headings */
1155
- h4 {
1156
- font-size: 16px !important;
1157
- margin-bottom: 6px !important;
1158
- padding-top: 1rem !important;
1159
- }
1160
-
1161
- h5 {
1162
- font-size: 14px !important;
1163
- margin-bottom: 4px !important;
1164
- }
1165
-
1166
- /* Section divider */
1167
- .section-divider {
1168
- margin: 6px 0 !important;
1169
- }
1170
-
1171
- /* Editor controls layout */
1172
- .editor-controls-row,
1173
- .proxy-controls-row {
1174
- gap: 6px !important;
1175
- }
1176
-
1177
- /* Compact button styling */
1178
- .btn-action {
1179
- min-height: 28px !important;
1180
- height: 28px !important;
1181
- padding: 0 6px !important;
1182
- font-size: 11px !important;
1183
- }
1184
-
1185
- /* Hide button text to save space */
1186
- .btn-action span {
1187
- display: none !important;
1188
- }
1189
-
1190
- /* Compact editor containers - reduced margins for more space */
1191
- .my-3 {
1192
- margin: 4px 0 !important; /* Reduced from 6px */
1193
- }
1194
-
1195
- .pb-4 {
1196
- padding-bottom: 2px !important; /* Reduced from 4px */
1197
- }
1198
-
1199
- /* Editor container heights - increased to use more available space */
1200
- .editor-container,
1201
- .proxy-editor-container {
1202
- height: 180px !important; /* Increased from 130px */
1203
- max-height: 180px !important;
1204
- min-height: 150px !important; /* Increased from 100px */
1205
- }
1206
-
1207
- /* Reduce editor height when JSON error is showing */
1208
- .editor-container.has-error {
1209
- height: 120px !important; /* Reduced to make room for error message */
1210
- max-height: 120px !important;
1211
- min-height: 100px !important;
1212
- }
1213
-
1214
- /* Ensure proxy editor takes full space when visible - increased height */
1215
- .proxy-editor-container {
1216
- height: 180px !important; /* Increased from 130px */
1217
- max-height: 180px !important;
1218
- min-height: 150px !important;
1219
- }
1220
-
1221
- /* Editor textarea heights - ensure syntax highlighting works */
1222
- .code-editor,
1223
- .proxy-editor {
1224
- font-size: 11px !important;
1225
- line-height: 1.4 !important;
1226
- padding: 6px !important;
1227
- }
1228
-
1229
- /* Syntax highlighting in landscape mode */
1230
- .code-highlight {
1231
- font-size: 11px !important;
1232
- line-height: 1.4 !important;
1233
- padding: 6px !important;
1234
- /* Ensure syntax highlighting is visible in landscape */
1235
- color: #f8f8f2 !important;
1236
- opacity: 1 !important;
1237
- display: block !important;
1238
- }
1239
-
1240
- /* Compact error messages */
1241
- .error-container {
1242
- margin: 2px 0 !important; /* Reduced from 4px */
1243
- padding: 4px 6px !important; /* More compact padding */
1244
- font-size: 9px !important; /* Reduced from 10px */
1245
- border-radius: 4px !important; /* Smaller border radius */
1246
- gap: 6px !important; /* Reduced gap */
1247
- }
1248
-
1249
- .error-icon {
1250
- width: 12px !important;
1251
- height: 12px !important;
1252
- }
1253
-
1254
- .error-icon svg {
1255
- width: 12px !important;
1256
- height: 12px !important;
1257
- }
1258
-
1259
- .error-title {
1260
- font-size: 9px !important; /* Reduced from 10px */
1261
- margin-bottom: 2px !important;
1262
- font-weight: 500 !important;
1263
- }
1264
-
1265
- .error-text {
1266
- font-size: 8px !important; /* Reduced from 9px */
1267
- line-height: 1.2 !important;
1268
- }
1269
- }
1270
-
1271
- /* ==========================================================================
1272
- VERY SHORT LANDSCAPE SCREENS (max-height: 400px + landscape)
1273
- ========================================================================== */
1274
-
1275
- @media (max-height: 400px) and (orientation: landscape) {
1276
- .card-dark {
1277
- max-height: calc(100vh - 70px) !important; /* Increased from 60px */
1278
- padding: 6px !important;
1279
- margin-bottom: 0.5rem !important; /* Reduced from 1rem */
1280
- /* Reduced bottom padding to minimize empty space */
1281
- padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
1282
- }
1283
-
1284
- .editor-container,
1285
- .proxy-editor-container {
1286
- height: 140px !important; /* Increased from 100px */
1287
- max-height: 140px !important;
1288
- min-height: 120px !important; /* Increased from 80px */
1289
- }
1290
-
1291
- /* Reduce editor height when JSON error is showing in very short landscape */
1292
- .editor-container.has-error {
1293
- height: 90px !important; /* Reduced to make room for error message */
1294
- max-height: 90px !important;
1295
- min-height: 80px !important;
1296
- }
1297
-
1298
- /* Ensure proxy editor takes full space in very short landscape */
1299
- .proxy-editor {
1300
- height: 100% !important;
1301
- min-height: 100% !important;
1302
- font-size: 10px !important;
1303
- line-height: 1.3 !important;
1304
- padding: 4px !important;
1305
- }
1306
-
1307
- .code-editor {
1308
- font-size: 10px !important;
1309
- line-height: 1.3 !important;
1310
- padding: 4px !important;
1311
- }
1312
-
1313
- /* Ensure syntax highlighting works in very short landscape */
1314
- .code-highlight {
1315
- font-size: 10px !important;
1316
- line-height: 1.3 !important;
1317
- padding: 4px !important;
1318
- color: #f8f8f2 !important;
1319
- opacity: 1 !important;
1320
- display: block !important;
1321
- }
1322
-
1323
- /* Ultra-compact error messages for very short landscape */
1324
- .error-container {
1325
- margin: 1px 0 !important;
1326
- padding: 2px 4px !important;
1327
- font-size: 8px !important;
1328
- border-radius: 3px !important;
1329
- gap: 4px !important;
1330
- }
1331
-
1332
- .error-icon {
1333
- width: 10px !important;
1334
- height: 10px !important;
1335
- }
1336
-
1337
- .error-icon svg {
1338
- width: 10px !important;
1339
- height: 10px !important;
1340
- }
1341
-
1342
- .error-title {
1343
- font-size: 8px !important;
1344
- margin-bottom: 1px !important;
1345
- font-weight: 500 !important;
1346
- }
1347
-
1348
- .error-text {
1349
- font-size: 7px !important;
1350
- line-height: 1.1 !important;
1351
- }
1352
- }
1353
-
1354
- /* Section divider */
1355
- .section-divider {
1356
- margin: 12px 0 !important;
1357
- /* Reduce glow effect in landscape */
1358
- box-shadow: 0 0 4px rgba(61, 62, 68, 0.2) !important;
1359
- }
1360
-
1361
- /* Compact section headers in landscape */
1362
- .admin-editor-section h5,
1363
- .proxy-editor-section h5 {
1364
- padding-bottom: 4px !important;
1365
-
1366
- &::after {
1367
- width: 30px !important;
1368
- height: 1px !important;
1369
- }
310
+ .button-default-smaller -smaller {
311
+ @apply h-10;
312
+ border-radius: 0.5rem;
313
+ font-weight: 500;
314
+ --tw-text-opacity: 1;
315
+ color: rgb(255 255 255 / 1);
316
+ transition-duration: 150ms;
1370
317
  }
1371
318
  </style>