@jjlmoya/utils-audiovisual 1.5.0 → 1.7.0
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 +58 -58
- package/src/category/i18n/fr.ts +1 -1
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tool/chromaticLens/component.astro +38 -38
- package/src/tool/chromaticLens/i18n/en.ts +1 -1
- package/src/tool/chromaticLens/i18n/es.ts +1 -1
- package/src/tool/chromaticLens/i18n/fr.ts +1 -1
- package/src/tool/collageMaker/component.astro +47 -47
- package/src/tool/collageMaker/i18n/en.ts +1 -1
- package/src/tool/collageMaker/i18n/es.ts +1 -1
- package/src/tool/collageMaker/i18n/fr.ts +1 -1
- package/src/tool/exifCleaner/component.astro +49 -48
- package/src/tool/exifCleaner/i18n/en.ts +2 -2
- package/src/tool/exifCleaner/i18n/es.ts +2 -2
- package/src/tool/exifCleaner/i18n/fr.ts +3 -3
- package/src/tool/imageCompressor/component.astro +144 -106
- package/src/tool/imageCompressor/i18n/en.ts +12 -2
- package/src/tool/imageCompressor/i18n/es.ts +13 -3
- package/src/tool/imageCompressor/i18n/fr.ts +12 -2
- package/src/tool/imageCompressor/index.ts +10 -0
- package/src/tool/printQualityCalculator/component.astro +129 -104
- package/src/tool/printQualityCalculator/i18n/en.ts +17 -3
- package/src/tool/printQualityCalculator/i18n/es.ts +19 -5
- package/src/tool/printQualityCalculator/i18n/fr.ts +18 -4
- package/src/tool/printQualityCalculator/index.ts +14 -0
- package/src/tool/privacyBlur/component.astro +35 -35
- package/src/tool/privacyBlur/i18n/en.ts +1 -1
- package/src/tool/privacyBlur/i18n/es.ts +1 -1
- package/src/tool/privacyBlur/i18n/fr.ts +1 -1
- package/src/tool/subtitleSync/component.astro +42 -42
- package/src/tool/subtitleSync/i18n/en.ts +1 -1
- package/src/tool/subtitleSync/i18n/es.ts +1 -1
- package/src/tool/subtitleSync/i18n/fr.ts +3 -3
- package/src/tool/timelapseCalculator/component.astro +41 -42
- package/src/tool/tvDistance/component.astro +55 -55
- package/src/tool/tvDistance/i18n/en.ts +1 -1
- package/src/tool/tvDistance/i18n/es.ts +1 -1
- package/src/tool/tvDistance/i18n/fr.ts +1 -1
- package/src/tool/videoFrameExtractor/component.astro +54 -54
- package/src/tool/videoFrameExtractor/i18n/en.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/es.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/fr.ts +1 -1
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
+
import type { ImageCompressorUI } from './index';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
ui: ImageCompressorUI;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { ui } = Astro.props;
|
|
2
9
|
---
|
|
3
10
|
|
|
4
|
-
<div class="ic-dashboard" id="image-compressor-root">
|
|
11
|
+
<div class="ic-dashboard" id="image-compressor-root" data-ui={JSON.stringify(ui)}>
|
|
5
12
|
|
|
6
13
|
<div class="ic-global-settings">
|
|
7
14
|
<div class="ic-toggle-group">
|
|
@@ -9,10 +16,10 @@
|
|
|
9
16
|
<input type="checkbox" id="global-webp-toggle" checked />
|
|
10
17
|
<span class="ic-webp-slider"></span>
|
|
11
18
|
</label>
|
|
12
|
-
<span class="ic-toggle-label">
|
|
19
|
+
<span class="ic-toggle-label">{ui.convertToWebpLabel}</span>
|
|
13
20
|
</div>
|
|
14
21
|
<div class="ic-settings-group">
|
|
15
|
-
<label for="global-quality">
|
|
22
|
+
<label for="global-quality">{ui.compressionLabel}: <span id="global-q-val">80</span>%</label>
|
|
16
23
|
<input type="range" id="global-quality" min="10" max="100" value="80" class="ic-mini-slider" />
|
|
17
24
|
</div>
|
|
18
25
|
</div>
|
|
@@ -24,21 +31,21 @@
|
|
|
24
31
|
<path d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1M16 8l-4-4-4 4M12 4v12" />
|
|
25
32
|
</svg>
|
|
26
33
|
</span>
|
|
27
|
-
<span class="ic-upload-text">
|
|
28
|
-
<span class="ic-upload-subtext">
|
|
29
|
-
<span class="ic-upload-btn">
|
|
34
|
+
<span class="ic-upload-text">{ui.dropTitle}</span>
|
|
35
|
+
<span class="ic-upload-subtext">{ui.dropSubtitle}</span>
|
|
36
|
+
<span class="ic-upload-btn">{ui.browseFilesBtn}</span>
|
|
30
37
|
</label>
|
|
31
38
|
<input type="file" id="image-input" accept="image/jpeg,image/png,image/webp" multiple />
|
|
32
39
|
</div>
|
|
33
40
|
|
|
34
41
|
<div id="file-list-container" class="ic-file-list-container" style="display:none">
|
|
35
42
|
<div class="ic-list-header">
|
|
36
|
-
<h3>
|
|
43
|
+
<h3>{ui.processedFilesTitle}</h3>
|
|
37
44
|
<span id="total-savings" class="ic-total-savings"></span>
|
|
38
45
|
</div>
|
|
39
46
|
<ul id="file-list" class="ic-file-list"></ul>
|
|
40
47
|
<div class="ic-global-actions">
|
|
41
|
-
<button id="download-all" class="ic-primary-btn">
|
|
48
|
+
<button id="download-all" class="ic-primary-btn">{ui.downloadAllBtn}</button>
|
|
42
49
|
</div>
|
|
43
50
|
</div>
|
|
44
51
|
|
|
@@ -70,10 +77,10 @@
|
|
|
70
77
|
<span class="ic-savings-pct"></span>
|
|
71
78
|
</div>
|
|
72
79
|
<div class="ic-item-actions">
|
|
73
|
-
<button class="ic-icon-btn ic-edit-btn" title=
|
|
80
|
+
<button class="ic-icon-btn ic-edit-btn" title={ui.adjustThisImage}>
|
|
74
81
|
<svg viewBox="0 0 24 24" fill="none" width="18" height="18" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.6 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.6a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
|
|
75
82
|
</button>
|
|
76
|
-
<a class="ic-icon-btn ic-download-btn" title=
|
|
83
|
+
<a class="ic-icon-btn ic-download-btn" title={ui.downloadTitle} download>
|
|
77
84
|
<svg viewBox="0 0 24 24" fill="none" width="18" height="18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1M12 4v12M8 12l4 4 4-4"/></svg>
|
|
78
85
|
</a>
|
|
79
86
|
</div>
|
|
@@ -82,15 +89,15 @@
|
|
|
82
89
|
<div class="ic-inline-editor" style="display:none">
|
|
83
90
|
<div class="ic-editor-controls">
|
|
84
91
|
<div class="ic-editor-group">
|
|
85
|
-
<label>
|
|
92
|
+
<label>{ui.qualityLabel}: <span class="ic-local-q-val">80</span>%</label>
|
|
86
93
|
<input type="range" class="ic-local-quality" min="10" max="100" value="80" />
|
|
87
94
|
</div>
|
|
88
95
|
<div class="ic-editor-group">
|
|
89
|
-
<label>
|
|
96
|
+
<label>{ui.maxWidthLabel}:</label>
|
|
90
97
|
<input type="number" class="ic-local-width" placeholder="Original" />
|
|
91
98
|
</div>
|
|
92
99
|
</div>
|
|
93
|
-
<button class="ic-editor-close">
|
|
100
|
+
<button class="ic-editor-close">{ui.closeBtn}</button>
|
|
94
101
|
</div>
|
|
95
102
|
</li>
|
|
96
103
|
</template>
|
|
@@ -98,6 +105,9 @@
|
|
|
98
105
|
<script>
|
|
99
106
|
import { compressImage, formatBytes, generateId, type CompressorSettings } from './logic';
|
|
100
107
|
|
|
108
|
+
const root = document.getElementById('image-compressor-root');
|
|
109
|
+
const ui = root ? JSON.parse(root.dataset.ui || '{}') : {};
|
|
110
|
+
|
|
101
111
|
interface QueueItem {
|
|
102
112
|
id: string;
|
|
103
113
|
file: File;
|
|
@@ -124,12 +134,12 @@
|
|
|
124
134
|
const globalWebp = document.getElementById('global-webp-toggle') as HTMLInputElement;
|
|
125
135
|
|
|
126
136
|
globalQuality?.addEventListener('input', () => {
|
|
127
|
-
globalQVal.textContent = globalQuality.value;
|
|
137
|
+
if (globalQVal) globalQVal.textContent = globalQuality.value;
|
|
128
138
|
});
|
|
129
139
|
|
|
130
140
|
async function handleFiles(files: FileList | File[]) {
|
|
131
141
|
if (!files.length) return;
|
|
132
|
-
container.style.display = '';
|
|
142
|
+
if (container) container.style.display = '';
|
|
133
143
|
|
|
134
144
|
for (let i = 0; i < files.length; i++) {
|
|
135
145
|
const file = files[i];
|
|
@@ -137,7 +147,7 @@
|
|
|
137
147
|
|
|
138
148
|
const id = generateId();
|
|
139
149
|
const settings: CompressorSettings = {
|
|
140
|
-
quality: parseInt(globalQuality
|
|
150
|
+
quality: parseInt(globalQuality?.value || '80'),
|
|
141
151
|
width: null,
|
|
142
152
|
convertToWebp: globalWebp?.checked ?? true,
|
|
143
153
|
};
|
|
@@ -152,12 +162,15 @@
|
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
function appendItem(item: QueueItem) {
|
|
165
|
+
if (!template || !fileList) return;
|
|
155
166
|
const clone = template.content.cloneNode(true) as DocumentFragment;
|
|
156
167
|
const li = clone.querySelector('li') as HTMLLIElement;
|
|
157
168
|
li.dataset.id = item.id;
|
|
158
169
|
|
|
159
|
-
|
|
160
|
-
|
|
170
|
+
const filenameElem = li.querySelector('.ic-filename') as HTMLElement;
|
|
171
|
+
const origSizeElem = li.querySelector('.ic-orig-size') as HTMLElement;
|
|
172
|
+
if (filenameElem) filenameElem.textContent = item.file.name;
|
|
173
|
+
if (origSizeElem) origSizeElem.textContent = formatBytes(item.originalSize);
|
|
161
174
|
|
|
162
175
|
const localQ = li.querySelector('.ic-local-quality') as HTMLInputElement;
|
|
163
176
|
const localQVal = li.querySelector('.ic-local-q-val') as HTMLElement;
|
|
@@ -166,20 +179,31 @@
|
|
|
166
179
|
const editBtn = li.querySelector('.ic-edit-btn') as HTMLButtonElement;
|
|
167
180
|
const closeBtn = li.querySelector('.ic-editor-close') as HTMLButtonElement;
|
|
168
181
|
|
|
169
|
-
|
|
170
|
-
|
|
182
|
+
if (localQ) {
|
|
183
|
+
localQ.value = item.settings.quality.toString();
|
|
184
|
+
if (localQVal) localQVal.textContent = item.settings.quality.toString();
|
|
185
|
+
}
|
|
171
186
|
|
|
172
|
-
editBtn
|
|
173
|
-
|
|
187
|
+
editBtn?.addEventListener('click', () => {
|
|
188
|
+
if (editor) {
|
|
189
|
+
editor.style.display = editor.style.display === 'none' ? '' : 'none';
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
closeBtn?.addEventListener('click', () => {
|
|
194
|
+
if (editor) editor.style.display = 'none';
|
|
174
195
|
});
|
|
175
|
-
closeBtn.addEventListener('click', () => { editor.style.display = 'none'; });
|
|
176
196
|
|
|
177
|
-
localQ
|
|
178
|
-
|
|
197
|
+
localQ?.addEventListener('input', () => {
|
|
198
|
+
if (localQVal) localQVal.textContent = localQ.value;
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
localQ?.addEventListener('change', () => {
|
|
179
202
|
item.settings.quality = parseInt(localQ.value);
|
|
180
203
|
processItem(item).then(() => updateTotals());
|
|
181
204
|
});
|
|
182
|
-
|
|
205
|
+
|
|
206
|
+
localW?.addEventListener('change', () => {
|
|
183
207
|
item.settings.width = localW.value ? parseInt(localW.value) : null;
|
|
184
208
|
processItem(item).then(() => updateTotals());
|
|
185
209
|
});
|
|
@@ -188,6 +212,7 @@
|
|
|
188
212
|
}
|
|
189
213
|
|
|
190
214
|
async function processItem(item: QueueItem): Promise<void> {
|
|
215
|
+
if (!fileList) return;
|
|
191
216
|
const li = fileList.querySelector(`li[data-id="${item.id}"]`) as HTMLLIElement;
|
|
192
217
|
const result = await compressImage(item.file, item.settings);
|
|
193
218
|
|
|
@@ -205,48 +230,61 @@
|
|
|
205
230
|
const pill = li.querySelector('.ic-savings-pill') as HTMLElement;
|
|
206
231
|
const downloadBtn = li.querySelector('.ic-download-btn') as HTMLAnchorElement;
|
|
207
232
|
|
|
208
|
-
previewImg.src = result.dataUrl;
|
|
233
|
+
if (previewImg) previewImg.src = result.dataUrl;
|
|
209
234
|
|
|
210
|
-
newSizeTxt.textContent = formatBytes(result.newSize);
|
|
235
|
+
if (newSizeTxt) newSizeTxt.textContent = formatBytes(result.newSize);
|
|
211
236
|
const savings = ((item.originalSize - result.newSize) / item.originalSize) * 100;
|
|
212
237
|
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
238
|
+
if (savingsPct && pill) {
|
|
239
|
+
if (savings < 0) {
|
|
240
|
+
savingsPct.textContent = `+${Math.abs(savings).toFixed(1)}%`;
|
|
241
|
+
pill.classList.add('ic-savings-pill-negative');
|
|
242
|
+
} else {
|
|
243
|
+
savingsPct.textContent = `-${savings.toFixed(1)}%`;
|
|
244
|
+
pill.classList.remove('ic-savings-pill-negative');
|
|
245
|
+
}
|
|
219
246
|
}
|
|
220
247
|
|
|
221
248
|
const baseName = item.file.name.replace(/\.[^/.]+$/, '');
|
|
222
|
-
downloadBtn
|
|
223
|
-
|
|
249
|
+
if (downloadBtn) {
|
|
250
|
+
downloadBtn.href = result.dataUrl;
|
|
251
|
+
downloadBtn.download = `${baseName}.${item.ext}`;
|
|
252
|
+
}
|
|
224
253
|
}
|
|
225
254
|
|
|
226
255
|
function updateTotals() {
|
|
256
|
+
if (!totalSavingsTxt) return;
|
|
227
257
|
totalCompressedSize = Array.from(queue.values()).reduce((sum, i) => sum + i.newSize, 0);
|
|
228
258
|
const saved = totalOriginalSize - totalCompressedSize;
|
|
229
259
|
if (saved > 0) {
|
|
230
|
-
totalSavingsTxt.textContent =
|
|
260
|
+
totalSavingsTxt.textContent = `${ui.totalSavingsLabel}: ${formatBytes(saved)}`;
|
|
231
261
|
totalSavingsTxt.style.color = '#10b981';
|
|
232
262
|
} else {
|
|
233
|
-
totalSavingsTxt.textContent =
|
|
263
|
+
totalSavingsTxt.textContent = ui.noSavings || '';
|
|
234
264
|
totalSavingsTxt.style.color = '#ef4444';
|
|
235
265
|
}
|
|
236
266
|
}
|
|
237
267
|
|
|
238
|
-
dropZone
|
|
239
|
-
|
|
240
|
-
|
|
268
|
+
dropZone?.addEventListener('dragover', (e) => {
|
|
269
|
+
e.preventDefault();
|
|
270
|
+
dropZone.classList.add('ic-dragover');
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
dropZone?.addEventListener('dragleave', () => {
|
|
274
|
+
dropZone.classList.remove('ic-dragover');
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
dropZone?.addEventListener('drop', (e) => {
|
|
241
278
|
e.preventDefault();
|
|
242
279
|
dropZone.classList.remove('ic-dragover');
|
|
243
280
|
if (e.dataTransfer?.files.length) handleFiles(e.dataTransfer.files);
|
|
244
281
|
});
|
|
245
|
-
|
|
282
|
+
|
|
283
|
+
fileInput?.addEventListener('change', () => {
|
|
246
284
|
if (fileInput.files?.length) handleFiles(fileInput.files);
|
|
247
285
|
});
|
|
248
286
|
|
|
249
|
-
downloadAllBtn
|
|
287
|
+
downloadAllBtn?.addEventListener('click', () => {
|
|
250
288
|
queue.forEach((item) => {
|
|
251
289
|
if (!item.dataUrl) return;
|
|
252
290
|
const a = document.createElement('a');
|
|
@@ -261,7 +299,7 @@
|
|
|
261
299
|
</script>
|
|
262
300
|
|
|
263
301
|
<style>
|
|
264
|
-
.ic-dashboard {
|
|
302
|
+
:global(.ic-dashboard) {
|
|
265
303
|
max-width: 900px;
|
|
266
304
|
margin: 0 auto;
|
|
267
305
|
display: flex;
|
|
@@ -283,7 +321,7 @@
|
|
|
283
321
|
--ic-shadow: rgba(0, 0, 0, 0.03);
|
|
284
322
|
}
|
|
285
323
|
|
|
286
|
-
:global(.theme-dark
|
|
324
|
+
:global(.theme-dark .ic-dashboard) {
|
|
287
325
|
--ic-bg: #0f172a;
|
|
288
326
|
--ic-bg-muted: #1e293b;
|
|
289
327
|
--ic-border: #334155;
|
|
@@ -295,7 +333,7 @@
|
|
|
295
333
|
--ic-shadow: rgba(0, 0, 0, 0.4);
|
|
296
334
|
}
|
|
297
335
|
|
|
298
|
-
.ic-global-settings {
|
|
336
|
+
:global(.ic-global-settings) {
|
|
299
337
|
display: flex;
|
|
300
338
|
justify-content: flex-end;
|
|
301
339
|
gap: 1.5rem;
|
|
@@ -308,32 +346,32 @@
|
|
|
308
346
|
flex-wrap: wrap;
|
|
309
347
|
}
|
|
310
348
|
|
|
311
|
-
:global(.theme-dark
|
|
349
|
+
:global(.theme-dark .ic-global-settings) {
|
|
312
350
|
background: rgba(30, 41, 59, 0.6);
|
|
313
351
|
border-color: rgba(71, 85, 105, 0.5);
|
|
314
352
|
color: var(--ic-text-muted);
|
|
315
353
|
}
|
|
316
354
|
|
|
317
|
-
.ic-toggle-group {
|
|
355
|
+
:global(.ic-toggle-group) {
|
|
318
356
|
display: flex;
|
|
319
357
|
align-items: center;
|
|
320
358
|
gap: 0.5rem;
|
|
321
359
|
}
|
|
322
360
|
|
|
323
|
-
.ic-webp-switch {
|
|
361
|
+
:global(.ic-webp-switch) {
|
|
324
362
|
position: relative;
|
|
325
363
|
display: inline-block;
|
|
326
364
|
width: 44px;
|
|
327
365
|
height: 24px;
|
|
328
366
|
}
|
|
329
367
|
|
|
330
|
-
.ic-webp-switch input {
|
|
368
|
+
:global(.ic-webp-switch input) {
|
|
331
369
|
opacity: 0;
|
|
332
370
|
width: 0;
|
|
333
371
|
height: 0;
|
|
334
372
|
}
|
|
335
373
|
|
|
336
|
-
.ic-webp-slider {
|
|
374
|
+
:global(.ic-webp-slider) {
|
|
337
375
|
position: absolute;
|
|
338
376
|
cursor: pointer;
|
|
339
377
|
inset: 0;
|
|
@@ -342,7 +380,7 @@
|
|
|
342
380
|
transition: 0.3s;
|
|
343
381
|
}
|
|
344
382
|
|
|
345
|
-
.ic-webp-slider::before {
|
|
383
|
+
:global(.ic-webp-slider::before) {
|
|
346
384
|
content: '';
|
|
347
385
|
position: absolute;
|
|
348
386
|
width: 18px;
|
|
@@ -355,20 +393,20 @@
|
|
|
355
393
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
356
394
|
}
|
|
357
395
|
|
|
358
|
-
.ic-webp-switch input:checked + .ic-webp-slider {
|
|
396
|
+
:global(.ic-webp-switch input:checked + .ic-webp-slider) {
|
|
359
397
|
background: var(--ic-accent);
|
|
360
398
|
}
|
|
361
399
|
|
|
362
|
-
.ic-webp-switch input:checked + .ic-webp-slider::before {
|
|
400
|
+
:global(.ic-webp-switch input:checked + .ic-webp-slider::before) {
|
|
363
401
|
transform: translateX(20px);
|
|
364
402
|
}
|
|
365
403
|
|
|
366
|
-
.ic-toggle-label {
|
|
404
|
+
:global(.ic-toggle-label) {
|
|
367
405
|
font-size: 0.9rem;
|
|
368
406
|
font-weight: 600;
|
|
369
407
|
}
|
|
370
408
|
|
|
371
|
-
.ic-settings-group {
|
|
409
|
+
:global(.ic-settings-group) {
|
|
372
410
|
display: flex;
|
|
373
411
|
align-items: center;
|
|
374
412
|
gap: 0.75rem;
|
|
@@ -376,12 +414,12 @@
|
|
|
376
414
|
font-weight: 600;
|
|
377
415
|
}
|
|
378
416
|
|
|
379
|
-
.ic-mini-slider {
|
|
417
|
+
:global(.ic-mini-slider) {
|
|
380
418
|
width: 100px;
|
|
381
419
|
accent-color: var(--ic-accent);
|
|
382
420
|
}
|
|
383
421
|
|
|
384
|
-
.ic-drop-zone {
|
|
422
|
+
:global(.ic-drop-zone) {
|
|
385
423
|
position: relative;
|
|
386
424
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.45) 100%);
|
|
387
425
|
border: 3px dashed var(--ic-accent);
|
|
@@ -394,23 +432,23 @@
|
|
|
394
432
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.04);
|
|
395
433
|
}
|
|
396
434
|
|
|
397
|
-
:global(.theme-dark
|
|
435
|
+
:global(.theme-dark .ic-drop-zone) {
|
|
398
436
|
background: linear-gradient(180deg, rgba(30, 41, 59, 0.85) 0%, rgba(15, 23, 42, 0.6) 100%);
|
|
399
437
|
}
|
|
400
438
|
|
|
401
|
-
.ic-drop-zone.ic-dragover,
|
|
402
|
-
.ic-drop-zone:hover {
|
|
439
|
+
:global(.ic-drop-zone.ic-dragover),
|
|
440
|
+
:global(.ic-drop-zone:hover) {
|
|
403
441
|
transform: scale(1.01);
|
|
404
442
|
border-color: var(--ic-accent-dark);
|
|
405
443
|
background: linear-gradient(180deg, var(--ic-accent-light) 0%, rgba(255, 255, 255, 0.6) 100%);
|
|
406
444
|
}
|
|
407
445
|
|
|
408
|
-
:global(.theme-dark
|
|
409
|
-
:global(.theme-dark
|
|
446
|
+
:global(.theme-dark .ic-drop-zone.ic-dragover),
|
|
447
|
+
:global(.theme-dark .ic-drop-zone:hover) {
|
|
410
448
|
background: linear-gradient(180deg, rgba(6, 78, 59, 0.4) 0%, rgba(15, 23, 42, 0.6) 100%);
|
|
411
449
|
}
|
|
412
450
|
|
|
413
|
-
.ic-file-label {
|
|
451
|
+
:global(.ic-file-label) {
|
|
414
452
|
display: flex;
|
|
415
453
|
flex-direction: column;
|
|
416
454
|
align-items: center;
|
|
@@ -419,24 +457,24 @@
|
|
|
419
457
|
pointer-events: none;
|
|
420
458
|
}
|
|
421
459
|
|
|
422
|
-
.ic-upload-icon {
|
|
460
|
+
:global(.ic-upload-icon) {
|
|
423
461
|
color: var(--ic-accent);
|
|
424
462
|
margin-bottom: 0.5rem;
|
|
425
463
|
}
|
|
426
464
|
|
|
427
|
-
.ic-upload-text {
|
|
465
|
+
:global(.ic-upload-text) {
|
|
428
466
|
font-size: 1.5rem;
|
|
429
467
|
font-weight: 700;
|
|
430
468
|
color: var(--ic-text);
|
|
431
469
|
}
|
|
432
470
|
|
|
433
|
-
.ic-upload-subtext {
|
|
471
|
+
:global(.ic-upload-subtext) {
|
|
434
472
|
color: var(--ic-text-muted);
|
|
435
473
|
font-size: 1rem;
|
|
436
474
|
margin-bottom: 1rem;
|
|
437
475
|
}
|
|
438
476
|
|
|
439
|
-
.ic-upload-btn {
|
|
477
|
+
:global(.ic-upload-btn) {
|
|
440
478
|
background: var(--ic-text);
|
|
441
479
|
color: var(--ic-bg);
|
|
442
480
|
padding: 0.75rem 2rem;
|
|
@@ -447,11 +485,11 @@
|
|
|
447
485
|
transition: background 0.2s;
|
|
448
486
|
}
|
|
449
487
|
|
|
450
|
-
.ic-upload-btn:hover {
|
|
488
|
+
:global(.ic-upload-btn:hover) {
|
|
451
489
|
background: var(--ic-text-muted);
|
|
452
490
|
}
|
|
453
491
|
|
|
454
|
-
.ic-drop-zone input[type="file"] {
|
|
492
|
+
:global(.ic-drop-zone input[type="file"]) {
|
|
455
493
|
position: absolute;
|
|
456
494
|
inset: 0;
|
|
457
495
|
width: 100%;
|
|
@@ -460,11 +498,11 @@
|
|
|
460
498
|
cursor: pointer;
|
|
461
499
|
}
|
|
462
500
|
|
|
463
|
-
.ic-file-list-container {
|
|
501
|
+
:global(.ic-file-list-container) {
|
|
464
502
|
margin-top: 1.5rem;
|
|
465
503
|
}
|
|
466
504
|
|
|
467
|
-
.ic-list-header {
|
|
505
|
+
:global(.ic-list-header) {
|
|
468
506
|
display: flex;
|
|
469
507
|
justify-content: space-between;
|
|
470
508
|
align-items: center;
|
|
@@ -472,19 +510,19 @@
|
|
|
472
510
|
padding: 0 0.5rem;
|
|
473
511
|
}
|
|
474
512
|
|
|
475
|
-
.ic-list-header h3 {
|
|
513
|
+
:global(.ic-list-header h3) {
|
|
476
514
|
font-size: 1.25rem;
|
|
477
515
|
font-weight: 700;
|
|
478
516
|
color: var(--ic-text);
|
|
479
517
|
margin: 0;
|
|
480
518
|
}
|
|
481
519
|
|
|
482
|
-
.ic-total-savings {
|
|
520
|
+
:global(.ic-total-savings) {
|
|
483
521
|
font-weight: 700;
|
|
484
522
|
font-size: 1rem;
|
|
485
523
|
}
|
|
486
524
|
|
|
487
|
-
.ic-file-list {
|
|
525
|
+
:global(.ic-file-list) {
|
|
488
526
|
list-style: none;
|
|
489
527
|
padding: 1rem;
|
|
490
528
|
margin: 0;
|
|
@@ -496,7 +534,7 @@
|
|
|
496
534
|
border: 1px solid var(--ic-border);
|
|
497
535
|
}
|
|
498
536
|
|
|
499
|
-
.ic-file-item {
|
|
537
|
+
:global(.ic-file-item) {
|
|
500
538
|
background: var(--ic-bg);
|
|
501
539
|
border-radius: 0.75rem;
|
|
502
540
|
padding: 0.75rem 1.25rem;
|
|
@@ -508,18 +546,18 @@
|
|
|
508
546
|
transition: box-shadow 0.2s;
|
|
509
547
|
}
|
|
510
548
|
|
|
511
|
-
.ic-file-item:hover {
|
|
549
|
+
:global(.ic-file-item:hover) {
|
|
512
550
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
|
|
513
551
|
}
|
|
514
552
|
|
|
515
|
-
.ic-preview-col {
|
|
553
|
+
:global(.ic-preview-col) {
|
|
516
554
|
display: flex;
|
|
517
555
|
align-items: center;
|
|
518
556
|
gap: 1rem;
|
|
519
557
|
overflow: hidden;
|
|
520
558
|
}
|
|
521
559
|
|
|
522
|
-
.ic-preview-wrapper {
|
|
560
|
+
:global(.ic-preview-wrapper) {
|
|
523
561
|
width: 48px;
|
|
524
562
|
height: 48px;
|
|
525
563
|
border-radius: 0.5rem;
|
|
@@ -528,19 +566,19 @@
|
|
|
528
566
|
flex-shrink: 0;
|
|
529
567
|
}
|
|
530
568
|
|
|
531
|
-
.ic-preview-img {
|
|
569
|
+
:global(.ic-preview-img) {
|
|
532
570
|
width: 100%;
|
|
533
571
|
height: 100%;
|
|
534
572
|
object-fit: cover;
|
|
535
573
|
}
|
|
536
574
|
|
|
537
|
-
.ic-file-info {
|
|
575
|
+
:global(.ic-file-info) {
|
|
538
576
|
display: flex;
|
|
539
577
|
flex-direction: column;
|
|
540
578
|
overflow: hidden;
|
|
541
579
|
}
|
|
542
580
|
|
|
543
|
-
.ic-filename {
|
|
581
|
+
:global(.ic-filename) {
|
|
544
582
|
font-weight: 600;
|
|
545
583
|
color: var(--ic-text);
|
|
546
584
|
white-space: nowrap;
|
|
@@ -549,17 +587,17 @@
|
|
|
549
587
|
font-size: 0.9rem;
|
|
550
588
|
}
|
|
551
589
|
|
|
552
|
-
.ic-orig-size {
|
|
590
|
+
:global(.ic-orig-size) {
|
|
553
591
|
color: var(--ic-text-muted);
|
|
554
592
|
font-size: 0.8rem;
|
|
555
593
|
}
|
|
556
594
|
|
|
557
|
-
.ic-arrow-col {
|
|
595
|
+
:global(.ic-arrow-col) {
|
|
558
596
|
display: flex;
|
|
559
597
|
justify-content: center;
|
|
560
598
|
}
|
|
561
599
|
|
|
562
|
-
.ic-arrow-circle {
|
|
600
|
+
:global(.ic-arrow-circle) {
|
|
563
601
|
background: var(--ic-accent-light);
|
|
564
602
|
color: var(--ic-accent);
|
|
565
603
|
width: 36px;
|
|
@@ -571,41 +609,41 @@
|
|
|
571
609
|
flex-shrink: 0;
|
|
572
610
|
}
|
|
573
611
|
|
|
574
|
-
.ic-result-col {
|
|
612
|
+
:global(.ic-result-col) {
|
|
575
613
|
display: flex;
|
|
576
614
|
align-items: center;
|
|
577
615
|
justify-content: flex-end;
|
|
578
616
|
gap: 1.25rem;
|
|
579
617
|
}
|
|
580
618
|
|
|
581
|
-
.ic-savings-pill {
|
|
619
|
+
:global(.ic-savings-pill) {
|
|
582
620
|
display: flex;
|
|
583
621
|
flex-direction: column;
|
|
584
622
|
align-items: center;
|
|
585
623
|
}
|
|
586
624
|
|
|
587
|
-
.ic-new-size {
|
|
625
|
+
:global(.ic-new-size) {
|
|
588
626
|
font-weight: 700;
|
|
589
627
|
color: var(--ic-text);
|
|
590
628
|
font-size: 0.95rem;
|
|
591
629
|
}
|
|
592
630
|
|
|
593
|
-
.ic-savings-pct {
|
|
631
|
+
:global(.ic-savings-pct) {
|
|
594
632
|
color: var(--ic-accent);
|
|
595
633
|
font-weight: 800;
|
|
596
634
|
font-size: 0.85rem;
|
|
597
635
|
}
|
|
598
636
|
|
|
599
|
-
.ic-savings-pill-negative .ic-savings-pct {
|
|
637
|
+
:global(.ic-savings-pill-negative .ic-savings-pct) {
|
|
600
638
|
color: var(--ic-error);
|
|
601
639
|
}
|
|
602
640
|
|
|
603
|
-
.ic-item-actions {
|
|
641
|
+
:global(.ic-item-actions) {
|
|
604
642
|
display: flex;
|
|
605
643
|
gap: 0.4rem;
|
|
606
644
|
}
|
|
607
645
|
|
|
608
|
-
.ic-icon-btn {
|
|
646
|
+
:global(.ic-icon-btn) {
|
|
609
647
|
background: var(--ic-bg-muted);
|
|
610
648
|
border: none;
|
|
611
649
|
color: var(--ic-text-muted);
|
|
@@ -621,22 +659,22 @@
|
|
|
621
659
|
flex-shrink: 0;
|
|
622
660
|
}
|
|
623
661
|
|
|
624
|
-
.ic-icon-btn:hover {
|
|
662
|
+
:global(.ic-icon-btn:hover) {
|
|
625
663
|
background: var(--ic-border);
|
|
626
664
|
color: var(--ic-text);
|
|
627
665
|
}
|
|
628
666
|
|
|
629
|
-
.ic-download-btn {
|
|
667
|
+
:global(.ic-download-btn) {
|
|
630
668
|
background: var(--ic-accent);
|
|
631
669
|
color: var(--ic-bg);
|
|
632
670
|
}
|
|
633
671
|
|
|
634
|
-
.ic-download-btn:hover {
|
|
672
|
+
:global(.ic-download-btn:hover) {
|
|
635
673
|
background: var(--ic-accent-dark);
|
|
636
674
|
color: var(--ic-bg);
|
|
637
675
|
}
|
|
638
676
|
|
|
639
|
-
.ic-inline-editor {
|
|
677
|
+
:global(.ic-inline-editor) {
|
|
640
678
|
grid-column: 1 / -1;
|
|
641
679
|
background: var(--ic-bg-muted);
|
|
642
680
|
border-radius: 0.75rem;
|
|
@@ -661,13 +699,13 @@
|
|
|
661
699
|
}
|
|
662
700
|
}
|
|
663
701
|
|
|
664
|
-
.ic-editor-controls {
|
|
702
|
+
:global(.ic-editor-controls) {
|
|
665
703
|
display: flex;
|
|
666
704
|
gap: 1.5rem;
|
|
667
705
|
flex-wrap: wrap;
|
|
668
706
|
}
|
|
669
707
|
|
|
670
|
-
.ic-editor-group {
|
|
708
|
+
:global(.ic-editor-group) {
|
|
671
709
|
display: flex;
|
|
672
710
|
flex-direction: column;
|
|
673
711
|
gap: 0.25rem;
|
|
@@ -676,11 +714,11 @@
|
|
|
676
714
|
color: var(--ic-text-muted);
|
|
677
715
|
}
|
|
678
716
|
|
|
679
|
-
.ic-editor-group input[type="range"] {
|
|
717
|
+
:global(.ic-editor-group input[type="range"]) {
|
|
680
718
|
accent-color: var(--ic-accent);
|
|
681
719
|
}
|
|
682
720
|
|
|
683
|
-
.ic-editor-group input[type="number"] {
|
|
721
|
+
:global(.ic-editor-group input[type="number"]) {
|
|
684
722
|
padding: 0.25rem 0.5rem;
|
|
685
723
|
border: 1px solid var(--ic-border);
|
|
686
724
|
border-radius: 0.375rem;
|
|
@@ -689,7 +727,7 @@
|
|
|
689
727
|
color: var(--ic-text);
|
|
690
728
|
}
|
|
691
729
|
|
|
692
|
-
.ic-editor-close {
|
|
730
|
+
:global(.ic-editor-close) {
|
|
693
731
|
background: var(--ic-border);
|
|
694
732
|
border: none;
|
|
695
733
|
padding: 0.4rem 0.875rem;
|
|
@@ -702,17 +740,17 @@
|
|
|
702
740
|
white-space: nowrap;
|
|
703
741
|
}
|
|
704
742
|
|
|
705
|
-
.ic-editor-close:hover {
|
|
743
|
+
:global(.ic-editor-close:hover) {
|
|
706
744
|
background: var(--ic-border);
|
|
707
745
|
}
|
|
708
746
|
|
|
709
|
-
.ic-global-actions {
|
|
747
|
+
:global(.ic-global-actions) {
|
|
710
748
|
margin-top: 1.5rem;
|
|
711
749
|
display: flex;
|
|
712
750
|
justify-content: center;
|
|
713
751
|
}
|
|
714
752
|
|
|
715
|
-
.ic-primary-btn {
|
|
753
|
+
:global(.ic-primary-btn) {
|
|
716
754
|
background: var(--ic-text);
|
|
717
755
|
color: var(--ic-bg);
|
|
718
756
|
border: none;
|
|
@@ -724,11 +762,11 @@
|
|
|
724
762
|
transition: background 0.2s, transform 0.1s;
|
|
725
763
|
}
|
|
726
764
|
|
|
727
|
-
.ic-primary-btn:hover {
|
|
765
|
+
:global(.ic-primary-btn:hover) {
|
|
728
766
|
background: var(--ic-text-muted);
|
|
729
767
|
}
|
|
730
768
|
|
|
731
|
-
.ic-primary-btn:active {
|
|
769
|
+
:global(.ic-primary-btn:active) {
|
|
732
770
|
transform: scale(0.98);
|
|
733
771
|
}
|
|
734
772
|
|