@brftech/filex-core 0.4.2 → 0.5.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/dist/{ArchiveViewer-B_0IQExT.js → ArchiveViewer-DKW-HyXT.js} +2 -2
- package/dist/{ArchiveViewer-B_0IQExT.js.map → ArchiveViewer-DKW-HyXT.js.map} +1 -1
- package/dist/{CsvViewer-maMfUy5i.js → CsvViewer-D2HmP2yr.js} +2 -2
- package/dist/{CsvViewer-maMfUy5i.js.map → CsvViewer-D2HmP2yr.js.map} +1 -1
- package/dist/{DrawioViewer-DP_pXI00.js → DrawioViewer-DPNvOFCs.js} +2 -2
- package/dist/{DrawioViewer-DP_pXI00.js.map → DrawioViewer-DPNvOFCs.js.map} +1 -1
- package/dist/{EpubViewer-DSaqGnVx.js → EpubViewer-ByqjNuNL.js} +2 -2
- package/dist/{EpubViewer-DSaqGnVx.js.map → EpubViewer-ByqjNuNL.js.map} +1 -1
- package/dist/{IpynbViewer-BmdBanF1.js → IpynbViewer-2iONhbuJ.js} +2 -2
- package/dist/{IpynbViewer-BmdBanF1.js.map → IpynbViewer-2iONhbuJ.js.map} +1 -1
- package/dist/{MermaidViewer-Drlkl0Z5.js → MermaidViewer-CmiU7hIT.js} +2 -2
- package/dist/{MermaidViewer-Drlkl0Z5.js.map → MermaidViewer-CmiU7hIT.js.map} +1 -1
- package/dist/{PsdViewer-gftUJrsm.js → PsdViewer-Inhl2yN9.js} +2 -2
- package/dist/{PsdViewer-gftUJrsm.js.map → PsdViewer-Inhl2yN9.js.map} +1 -1
- package/dist/{TiffViewer-0Uv0-Lxh.js → TiffViewer-C2AFFEze.js} +2 -2
- package/dist/{TiffViewer-0Uv0-Lxh.js.map → TiffViewer-C2AFFEze.js.map} +1 -1
- package/dist/{Viewer3D-Gu3kUpxV.js → Viewer3D-YdW14q_n.js} +2 -2
- package/dist/{Viewer3D-Gu3kUpxV.js.map → Viewer3D-YdW14q_n.js.map} +1 -1
- package/dist/filex-core.js +47 -25
- package/dist/filex-core.umd.cjs +40 -40
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/index-eARevpz0.js +9952 -0
- package/dist/index-eARevpz0.js.map +1 -0
- package/dist/index.d.ts +363 -3
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/FileExplorer.vue +269 -1
- package/src/components/CommandPalette.vue +12 -0
- package/src/components/ContextMenu.vue +114 -8
- package/src/components/GridView.vue +33 -1
- package/src/components/ListView.vue +39 -6
- package/src/components/OnboardingTour.vue +332 -0
- package/src/components/OperationsCenter.vue +284 -0
- package/src/components/PendingOpsTray.vue +50 -66
- package/src/components/QuickLook.vue +142 -0
- package/src/components/ShortcutSettings.vue +270 -0
- package/src/components/ShortcutsHelp.vue +30 -9
- package/src/components/ThemeGallery.vue +253 -0
- package/src/components/Toolbar.vue +52 -6
- package/src/components/UploadProgress.vue +49 -57
- package/src/composables/useKeyboardShortcuts.ts +321 -137
- package/src/composables/useOperations.ts +291 -0
- package/src/index.ts +45 -0
- package/src/lib/dragGhost.ts +41 -0
- package/src/lib/themes.ts +505 -0
- package/src/locales/en.ts +92 -0
- package/src/locales/tr.ts +92 -0
- package/src/modals/Modal.vue +41 -5
- package/src/styles/base.css +672 -0
- package/dist/index-BLocdbmc.js +0 -7993
- package/dist/index-BLocdbmc.js.map +0 -1
|
@@ -86,6 +86,8 @@ const emit = defineEmits<{
|
|
|
86
86
|
(e: 'open-recents'): void;
|
|
87
87
|
(e: 'update:density', v: Density): void;
|
|
88
88
|
(e: 'toggle-inspector'): void /* koru:k1 */;
|
|
89
|
+
(e: 'open-theme'): void /* wiring:c1 — tema galerisi */;
|
|
90
|
+
(e: 'open-shortcut-settings'): void /* wiring:c2 */;
|
|
89
91
|
}>();
|
|
90
92
|
|
|
91
93
|
// Density toggle — the toolbar owns the persisted preference; the parent
|
|
@@ -226,6 +228,10 @@ const moreActions = computed<ContextAction[]>(() => {
|
|
|
226
228
|
);
|
|
227
229
|
/* koru:k1 — inspector toggle also reachable from the narrow overflow menu */
|
|
228
230
|
list.push({ key: 'inspector', label: t('toolbar.inspector'), icon: 'ℹ' });
|
|
231
|
+
/* wiring:c1 — tema galerisi de dar modda ⋯ menüsünden açılır */
|
|
232
|
+
list.push({ key: 'theme', label: t('theme.menu'), icon: '🎨' });
|
|
233
|
+
list.push({ key: 'shortcut-settings', label: t('shortcuts.settings.menu'), icon: '⌨' }) /* wiring:c2 */;
|
|
234
|
+
list.push({ key: 'tour', label: t('tour.restart'), icon: '🎓' }); /* wiring:c4 */
|
|
229
235
|
return list;
|
|
230
236
|
});
|
|
231
237
|
|
|
@@ -254,6 +260,15 @@ function onMoreSelect(a: ContextAction) {
|
|
|
254
260
|
case 'inspector' /* koru:k1 */:
|
|
255
261
|
emit('toggle-inspector');
|
|
256
262
|
break;
|
|
263
|
+
case 'theme' /* wiring:c1 */:
|
|
264
|
+
emit('open-theme');
|
|
265
|
+
break;
|
|
266
|
+
case 'shortcut-settings' /* wiring:c2 */:
|
|
267
|
+
emit('open-shortcut-settings');
|
|
268
|
+
break;
|
|
269
|
+
case 'tour' /* wiring:c4 — bubbles to the FileExplorer root listener */:
|
|
270
|
+
moreBtnEl.value?.dispatchEvent(new CustomEvent('fe:tour-restart', { bubbles: true }));
|
|
271
|
+
break;
|
|
257
272
|
default:
|
|
258
273
|
fire(a.key);
|
|
259
274
|
}
|
|
@@ -331,7 +346,7 @@ function onMoreSelect(a: ContextAction) {
|
|
|
331
346
|
class="fe-search__input"
|
|
332
347
|
:placeholder="t('toolbar.search.placeholder')"
|
|
333
348
|
:value="localSearch"
|
|
334
|
-
aria-label="
|
|
349
|
+
:aria-label="t('toolbar.search') /* wiring:c4 — was hardcoded EN */"
|
|
335
350
|
@input="onSearchInput"
|
|
336
351
|
/>
|
|
337
352
|
</div>
|
|
@@ -340,17 +355,19 @@ function onMoreSelect(a: ContextAction) {
|
|
|
340
355
|
type="button"
|
|
341
356
|
class="fe-btn fe-btn--icon-only"
|
|
342
357
|
:title="t('toolbar.upload')"
|
|
358
|
+
:aria-label="t('toolbar.upload') /* wiring:c4 */"
|
|
343
359
|
@click="emit('upload')"
|
|
344
360
|
>
|
|
345
|
-
<span class="fe-icon">⬆</span>
|
|
361
|
+
<span class="fe-icon" aria-hidden="true">⬆</span>
|
|
346
362
|
</button>
|
|
347
363
|
<button
|
|
348
364
|
type="button"
|
|
349
365
|
class="fe-btn fe-btn--icon-only"
|
|
350
366
|
:title="t('toolbar.refresh')"
|
|
367
|
+
:aria-label="t('toolbar.refresh') /* wiring:c4 */"
|
|
351
368
|
@click="emit('refresh')"
|
|
352
369
|
>
|
|
353
|
-
<span class="fe-icon">↻</span>
|
|
370
|
+
<span class="fe-icon" aria-hidden="true">↻</span>
|
|
354
371
|
</button>
|
|
355
372
|
</div>
|
|
356
373
|
|
|
@@ -418,7 +435,34 @@ function onMoreSelect(a: ContextAction) {
|
|
|
418
435
|
</svg>
|
|
419
436
|
</button>
|
|
420
437
|
|
|
421
|
-
|
|
438
|
+
<!-- wiring:c1 — tema galerisi (palet ikonu) -->
|
|
439
|
+
<button
|
|
440
|
+
type="button"
|
|
441
|
+
class="fe-btn fe-btn--icon-only fe-toolbar__theme"
|
|
442
|
+
:title="t('theme.menu')"
|
|
443
|
+
:aria-label="t('theme.menu')"
|
|
444
|
+
@click="emit('open-theme')"
|
|
445
|
+
>
|
|
446
|
+
<svg
|
|
447
|
+
class="fe-ficon"
|
|
448
|
+
viewBox="0 0 24 24"
|
|
449
|
+
fill="none"
|
|
450
|
+
stroke="currentColor"
|
|
451
|
+
stroke-width="1.8"
|
|
452
|
+
stroke-linecap="round"
|
|
453
|
+
stroke-linejoin="round"
|
|
454
|
+
aria-hidden="true"
|
|
455
|
+
focusable="false"
|
|
456
|
+
>
|
|
457
|
+
<path d="M12 3a9 9 0 1 0 0 18h1.4a2.1 2.1 0 0 0 1.5-3.6 2.1 2.1 0 0 1 1.5-3.6H19a2 2 0 0 0 2-2A9 9 0 0 0 12 3z" />
|
|
458
|
+
<circle cx="7.8" cy="10.2" r="1.15" fill="currentColor" stroke="none" />
|
|
459
|
+
<circle cx="11.6" cy="7.2" r="1.15" fill="currentColor" stroke="none" />
|
|
460
|
+
<circle cx="16" cy="8.6" r="1.15" fill="currentColor" stroke="none" />
|
|
461
|
+
</svg>
|
|
462
|
+
</button>
|
|
463
|
+
<!-- /wiring:c1 -->
|
|
464
|
+
|
|
465
|
+
<div class="fe-toolbar__view" role="tablist" :aria-label="t('toolbar.view_label') /* wiring:c4 — was hardcoded EN */">
|
|
422
466
|
<button
|
|
423
467
|
type="button"
|
|
424
468
|
class="fe-btn fe-btn--icon-only"
|
|
@@ -426,9 +470,10 @@ function onMoreSelect(a: ContextAction) {
|
|
|
426
470
|
role="tab"
|
|
427
471
|
:aria-selected="viewMode === 'list'"
|
|
428
472
|
:title="t('toolbar.view.list')"
|
|
473
|
+
:aria-label="t('toolbar.view.list') /* wiring:c4 */"
|
|
429
474
|
@click="emit('update:viewMode', 'list')"
|
|
430
475
|
>
|
|
431
|
-
<span class="fe-icon">☰</span>
|
|
476
|
+
<span class="fe-icon" aria-hidden="true">☰</span>
|
|
432
477
|
</button>
|
|
433
478
|
<button
|
|
434
479
|
type="button"
|
|
@@ -437,9 +482,10 @@ function onMoreSelect(a: ContextAction) {
|
|
|
437
482
|
role="tab"
|
|
438
483
|
:aria-selected="viewMode === 'grid'"
|
|
439
484
|
:title="t('toolbar.view.grid')"
|
|
485
|
+
:aria-label="t('toolbar.view.grid') /* wiring:c4 */"
|
|
440
486
|
@click="emit('update:viewMode', 'grid')"
|
|
441
487
|
>
|
|
442
|
-
<span class="fe-icon">▦</span>
|
|
488
|
+
<span class="fe-icon" aria-hidden="true">▦</span>
|
|
443
489
|
</button>
|
|
444
490
|
</div>
|
|
445
491
|
</template>
|
|
@@ -1,78 +1,70 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
* UploadProgress —
|
|
3
|
+
* UploadProgress — renderless upload publisher (wiring:c3).
|
|
4
|
+
*
|
|
5
|
+
* Historically this drew its own floating bottom-right footer. Since the
|
|
6
|
+
* unified operations center it renders NOTHING: it reconciles the host's
|
|
7
|
+
* `jobs` list into the shared useOperations store, and the visible UI is
|
|
8
|
+
* OperationsCenter's badge + panel. The original emit contract is kept —
|
|
9
|
+
* cancel/dismiss (and the new retry) still bubble to the host, which owns
|
|
10
|
+
* the actual upload machinery. Mount it exactly as before; just pass the
|
|
11
|
+
* store via `center`.
|
|
4
12
|
*/
|
|
5
|
-
import {
|
|
13
|
+
import { watch } from 'vue';
|
|
6
14
|
import type { UploadJob } from '../composables/useUploadChunked';
|
|
7
15
|
import type { LocaleCode } from '../types/ExplorerConfig';
|
|
8
|
-
import {
|
|
16
|
+
import type { OperationsStore, OperationStatus } from '../composables/useOperations';
|
|
9
17
|
|
|
10
18
|
const props = defineProps<{
|
|
11
19
|
jobs: UploadJob[];
|
|
20
|
+
/** Kept for mount compatibility — strings now render in OperationsCenter. */
|
|
12
21
|
locale: LocaleCode;
|
|
22
|
+
center: OperationsStore;
|
|
13
23
|
}>();
|
|
14
24
|
|
|
15
25
|
const emit = defineEmits<{
|
|
16
26
|
(e: 'cancel', job: UploadJob): void;
|
|
17
27
|
(e: 'dismiss', job: UploadJob): void;
|
|
28
|
+
(e: 'retry', job: UploadJob): void;
|
|
18
29
|
}>();
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
switch (j.status) {
|
|
26
|
-
case 'done':
|
|
27
|
-
return t('upload.done');
|
|
28
|
-
case 'error':
|
|
29
|
-
return `${t('upload.error')}: ${j.error ?? ''}`;
|
|
30
|
-
case 'aborted':
|
|
31
|
-
return t('upload.aborted');
|
|
32
|
-
default:
|
|
33
|
-
return t('upload.progress');
|
|
34
|
-
}
|
|
31
|
+
function mapStatus(s: UploadJob['status']): OperationStatus {
|
|
32
|
+
if (s === 'done') return 'done';
|
|
33
|
+
if (s === 'error') return 'error';
|
|
34
|
+
if (s === 'aborted') return 'aborted';
|
|
35
|
+
return 'running'; // pending | initializing | uploading | finalizing
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
watch(
|
|
39
|
+
() => props.jobs,
|
|
40
|
+
(jobs) => {
|
|
41
|
+
props.center.sync(
|
|
42
|
+
'upload',
|
|
43
|
+
jobs.map((j) => ({
|
|
44
|
+
input: {
|
|
45
|
+
id: j.id,
|
|
46
|
+
kind: 'upload' as const,
|
|
47
|
+
name: j.file.name,
|
|
48
|
+
percent: j.totalBytes > 0 || j.status === 'done' ? j.percent : null,
|
|
49
|
+
status: mapStatus(j.status),
|
|
50
|
+
error: j.error ?? null,
|
|
51
|
+
uploadedBytes: j.uploadedBytes,
|
|
52
|
+
totalBytes: j.totalBytes,
|
|
53
|
+
cancellable: j.status === 'uploading' || j.status === 'initializing',
|
|
54
|
+
retryable: j.status === 'error',
|
|
55
|
+
},
|
|
56
|
+
actions: {
|
|
57
|
+
cancel: () => emit('cancel', j),
|
|
58
|
+
dismiss: () => emit('dismiss', j),
|
|
59
|
+
retry: () => emit('retry', j),
|
|
60
|
+
},
|
|
61
|
+
})),
|
|
62
|
+
);
|
|
63
|
+
},
|
|
64
|
+
{ immediate: true },
|
|
65
|
+
);
|
|
36
66
|
</script>
|
|
37
67
|
|
|
38
68
|
<template>
|
|
39
|
-
<
|
|
40
|
-
<div v-if="visible.length > 0" class="fe-upload">
|
|
41
|
-
<div class="fe-upload__header">
|
|
42
|
-
<strong>{{ t('upload.progress') }}</strong>
|
|
43
|
-
<span class="fe-upload__count">{{ visible.length }}</span>
|
|
44
|
-
</div>
|
|
45
|
-
<ul class="fe-upload__list">
|
|
46
|
-
<li
|
|
47
|
-
v-for="j in visible"
|
|
48
|
-
:key="j.id"
|
|
49
|
-
class="fe-upload__item"
|
|
50
|
-
:class="`is-${j.status}`"
|
|
51
|
-
>
|
|
52
|
-
<div class="fe-upload__name" :title="j.file.name">{{ j.file.name }}</div>
|
|
53
|
-
<div class="fe-upload__bar" :aria-valuenow="j.percent" role="progressbar">
|
|
54
|
-
<div class="fe-upload__bar-fill" :style="{ width: j.percent + '%' }" />
|
|
55
|
-
</div>
|
|
56
|
-
<div class="fe-upload__meta">
|
|
57
|
-
<span>{{ statusLabel(j) }}</span>
|
|
58
|
-
<span>{{ formatSize(j.uploadedBytes) }} / {{ formatSize(j.totalBytes) }}</span>
|
|
59
|
-
<button
|
|
60
|
-
v-if="j.status === 'uploading' || j.status === 'initializing'"
|
|
61
|
-
type="button"
|
|
62
|
-
class="fe-upload__cancel"
|
|
63
|
-
@click="emit('cancel', j)"
|
|
64
|
-
>
|
|
65
|
-
{{ t('upload.cancel') }}
|
|
66
|
-
</button>
|
|
67
|
-
<button
|
|
68
|
-
v-else
|
|
69
|
-
type="button"
|
|
70
|
-
class="fe-upload__cancel"
|
|
71
|
-
@click="emit('dismiss', j)"
|
|
72
|
-
>×</button>
|
|
73
|
-
</div>
|
|
74
|
-
</li>
|
|
75
|
-
</ul>
|
|
76
|
-
</div>
|
|
77
|
-
</transition>
|
|
69
|
+
<i v-if="false" />
|
|
78
70
|
</template>
|