@brftech/filex-core 0.7.1 → 0.7.2
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-Qi4L2jj9.js → ArchiveViewer-DAb5peBU.js} +2 -2
- package/dist/{ArchiveViewer-Qi4L2jj9.js.map → ArchiveViewer-DAb5peBU.js.map} +1 -1
- package/dist/{CsvViewer-IOIrJDsJ.js → CsvViewer-_bnmnpjn.js} +2 -2
- package/dist/{CsvViewer-IOIrJDsJ.js.map → CsvViewer-_bnmnpjn.js.map} +1 -1
- package/dist/{DrawioViewer-D0KtUQBO.js → DrawioViewer-Bjns4ob8.js} +2 -2
- package/dist/{DrawioViewer-D0KtUQBO.js.map → DrawioViewer-Bjns4ob8.js.map} +1 -1
- package/dist/{EpubViewer-DJOXiOi4.js → EpubViewer-DoFuZTtA.js} +2 -2
- package/dist/{EpubViewer-DJOXiOi4.js.map → EpubViewer-DoFuZTtA.js.map} +1 -1
- package/dist/{IpynbViewer-D16jXVJc.js → IpynbViewer-eg1ySMD4.js} +2 -2
- package/dist/{IpynbViewer-D16jXVJc.js.map → IpynbViewer-eg1ySMD4.js.map} +1 -1
- package/dist/{MermaidViewer-BnSaVg1L.js → MermaidViewer-BZ13vA6S.js} +2 -2
- package/dist/{MermaidViewer-BnSaVg1L.js.map → MermaidViewer-BZ13vA6S.js.map} +1 -1
- package/dist/{PsdViewer-BUerXaQA.js → PsdViewer-qFkE4KCB.js} +2 -2
- package/dist/{PsdViewer-BUerXaQA.js.map → PsdViewer-qFkE4KCB.js.map} +1 -1
- package/dist/{TiffViewer-D0Qn3IV-.js → TiffViewer-eHJTCYsd.js} +2 -2
- package/dist/{TiffViewer-D0Qn3IV-.js.map → TiffViewer-eHJTCYsd.js.map} +1 -1
- package/dist/{Viewer3D-BtRK-k1B.js → Viewer3D-C4--ljdO.js} +2 -2
- package/dist/{Viewer3D-BtRK-k1B.js.map → Viewer3D-C4--ljdO.js.map} +1 -1
- package/dist/filex-core.js +1 -1
- package/dist/filex-core.umd.cjs +33 -33
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/{index-CGNE1bSv.js → index-BSDT0PU8.js} +4460 -4403
- package/dist/index-BSDT0PU8.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/FileExplorer.vue +79 -6
- package/src/components/SecondaryPane.vue +19 -3
- package/src/styles/base.css +17 -3
- package/dist/index-CGNE1bSv.js.map +0 -1
package/src/FileExplorer.vue
CHANGED
|
@@ -1341,9 +1341,11 @@ function openNodeInNewTab(n: FileNode) {
|
|
|
1341
1341
|
void markRecent(n);
|
|
1342
1342
|
}
|
|
1343
1343
|
|
|
1344
|
-
type ContextMode = 'selection' | 'breadcrumb'
|
|
1344
|
+
type ContextMode = 'selection' | 'breadcrumb' | 'pane' /* ui-fix — yan panel sağ-tık */;
|
|
1345
1345
|
const ctxMode = ref<ContextMode>('selection');
|
|
1346
1346
|
const breadcrumbCtxPath = ref<string>('');
|
|
1347
|
+
/* ui-fix — yan panel sağ-tık menüsünün hedef node'ları (pane selection). */
|
|
1348
|
+
const paneCtxTargets = ref<FileNode[]>([]);
|
|
1347
1349
|
const breadcrumbCtxLabel = ref<string>('');
|
|
1348
1350
|
|
|
1349
1351
|
const selectionMode = computed<SelectionMode>(() => {
|
|
@@ -1388,6 +1390,61 @@ function onCrumbContext(payload: { x: number; y: number; adapterPath: string; la
|
|
|
1388
1390
|
ctxRef.value?.show({ clientX: payload.x, clientY: payload.y }, []);
|
|
1389
1391
|
}
|
|
1390
1392
|
|
|
1393
|
+
/* ui-fix — yan (ikincil) panelde sağ-tık: pane'i aktifleştir, seçili
|
|
1394
|
+
* node'lara göre menüyü aç. Pane "hafif" olduğundan (delete/rename modal'ları
|
|
1395
|
+
* ana panelde) menü aç/yeni-sekme/indir/kopyala/kes/yapıştır ile sınırlı;
|
|
1396
|
+
* hepsi pane-route'lu (dispatchPaneAction). */
|
|
1397
|
+
function onPaneContext(node: FileNode | null, ev: MouseEvent) {
|
|
1398
|
+
activePane.value = 'split';
|
|
1399
|
+
const sel = splitPaneRef.value?.selectedNodes() ?? [];
|
|
1400
|
+
// node=null (boş alana sağ-tık): seçimsiz menü (yalnız Yapıştır). Aksi
|
|
1401
|
+
// halde pane seçimi (yoksa tıklanan node) hedeftir.
|
|
1402
|
+
paneCtxTargets.value = node ? (sel.length > 0 ? sel : [node]) : [];
|
|
1403
|
+
ctxMode.value = 'pane';
|
|
1404
|
+
ctxRef.value?.show({ clientX: ev.clientX, clientY: ev.clientY }, paneCtxTargets.value);
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
function paneActionList(sel: FileNode[]): ContextAction[] {
|
|
1408
|
+
const single = sel.length === 1;
|
|
1409
|
+
const isFile = single && sel[0]?.type === 'file';
|
|
1410
|
+
const isDir = single && sel[0]?.type === 'dir';
|
|
1411
|
+
const any = sel.length > 0;
|
|
1412
|
+
return [
|
|
1413
|
+
{ key: 'open', label: t('ctx.open'), icon: '↗', hidden: !single },
|
|
1414
|
+
{ key: 'open-tab', label: t('ctx.open_new_tab'), icon: '⧉', hidden: !isDir } /* wiring:d1 */,
|
|
1415
|
+
{ key: 'download', label: t('ctx.download'), icon: '⬇', hidden: !single, disabled: !isFile },
|
|
1416
|
+
{ divider: true, key: 'psep', label: '', hidden: !any },
|
|
1417
|
+
{ key: 'copy', label: t('ctx.copy'), icon: '❐', hidden: !any },
|
|
1418
|
+
{ key: 'cut', label: t('ctx.cut'), icon: '✂', hidden: !any },
|
|
1419
|
+
{ key: 'paste', label: t('ctx.paste'), icon: '📋', disabled: !clipboard.value.mode },
|
|
1420
|
+
];
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
async function dispatchPaneAction(key: string, targets: FileNode[]) {
|
|
1424
|
+
switch (key) {
|
|
1425
|
+
case 'open':
|
|
1426
|
+
if (targets[0]) openNodeInNewTab(targets[0]);
|
|
1427
|
+
break;
|
|
1428
|
+
case 'open-tab':
|
|
1429
|
+
if (targets[0]) {
|
|
1430
|
+
tabsApi.openTab(paneToUser(targets[0].path), { viewMode: viewMode.value, background: true });
|
|
1431
|
+
}
|
|
1432
|
+
break;
|
|
1433
|
+
case 'download':
|
|
1434
|
+
if (targets[0]) downloadFile(targets[0]);
|
|
1435
|
+
break;
|
|
1436
|
+
case 'copy':
|
|
1437
|
+
paneCopy();
|
|
1438
|
+
break;
|
|
1439
|
+
case 'cut':
|
|
1440
|
+
paneCut();
|
|
1441
|
+
break;
|
|
1442
|
+
case 'paste':
|
|
1443
|
+
await panePaste();
|
|
1444
|
+
break;
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1391
1448
|
const contextActions = computed<ContextAction[]>(() => {
|
|
1392
1449
|
if (ctxMode.value === 'breadcrumb') {
|
|
1393
1450
|
return [
|
|
@@ -1395,6 +1452,9 @@ const contextActions = computed<ContextAction[]>(() => {
|
|
|
1395
1452
|
{ key: 'copy-path', label: t('breadcrumb.copy_path'), icon: '📋' },
|
|
1396
1453
|
];
|
|
1397
1454
|
}
|
|
1455
|
+
if (ctxMode.value === 'pane' /* ui-fix — yan panel menüsü */) {
|
|
1456
|
+
return paneActionList(paneCtxTargets.value);
|
|
1457
|
+
}
|
|
1398
1458
|
|
|
1399
1459
|
const sel = selection.nodes.value;
|
|
1400
1460
|
const any = sel.length > 0;
|
|
@@ -1517,6 +1577,10 @@ async function onContextAction(action: ContextAction, targets: FileNode[]) {
|
|
|
1517
1577
|
}
|
|
1518
1578
|
return;
|
|
1519
1579
|
}
|
|
1580
|
+
if (ctxMode.value === 'pane' /* ui-fix — yan panel aksiyonları pane-route */) {
|
|
1581
|
+
await dispatchPaneAction(action.key, paneCtxTargets.value);
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1520
1584
|
await dispatchItemAction(action.key, targets);
|
|
1521
1585
|
}
|
|
1522
1586
|
|
|
@@ -2930,6 +2994,18 @@ async function submitEncryptedFolder(payload: { name: string; password: string }
|
|
|
2930
2994
|
@open-recents="showRecents = true"
|
|
2931
2995
|
/>
|
|
2932
2996
|
|
|
2997
|
+
<!-- koru:k1 — fe__main lays the listing body and the inspector panel out
|
|
2998
|
+
as flex siblings (row). Without the inspector open it is visually
|
|
2999
|
+
identical to the previous direct-child fe__body. -->
|
|
3000
|
+
<div class="fe__main" :class="{ 'fe__main--split': splitVisible } /* wiring:d1 */">
|
|
3001
|
+
<!-- ui-fix — sol panelin başlığı (breadcrumb + durum şeritleri + body)
|
|
3002
|
+
tek bir sarmalda: split modunda bu sarmal sol yarıya sığar, böylece
|
|
3003
|
+
breadcrumb tüm sayfayı değil kendi panelini kaplar (SecondaryPane'in
|
|
3004
|
+
kendi kırıntısıyla simetrik). Aktif-panel vurgusu da bu sarmalda. -->
|
|
3005
|
+
<div
|
|
3006
|
+
class="fe__primary"
|
|
3007
|
+
:class="{ 'fe-pane--focus': mainPaneFocus } /* wiring:d1 — aktif panel vurgusu */"
|
|
3008
|
+
>
|
|
2933
3009
|
<Breadcrumb
|
|
2934
3010
|
:dirname="dirname"
|
|
2935
3011
|
:adapter="adapter"
|
|
@@ -2971,13 +3047,8 @@ async function submitEncryptedFolder(payload: { name: string; password: string }
|
|
|
2971
3047
|
</div>
|
|
2972
3048
|
<!-- /wiring:e2 -->
|
|
2973
3049
|
|
|
2974
|
-
<!-- koru:k1 — fe__main lays the listing body and the inspector panel out
|
|
2975
|
-
as flex siblings (row). Without the inspector open it is visually
|
|
2976
|
-
identical to the previous direct-child fe__body. -->
|
|
2977
|
-
<div class="fe__main" :class="{ 'fe__main--split': splitVisible } /* wiring:d1 */">
|
|
2978
3050
|
<div
|
|
2979
3051
|
class="fe__body"
|
|
2980
|
-
:class="{ 'fe-pane--focus': mainPaneFocus } /* wiring:d1 — aktif panel vurgusu */"
|
|
2981
3052
|
@pointerdown.capture="setPaneMain() /* wiring:d1 */"
|
|
2982
3053
|
@click.self="selection.clear()"
|
|
2983
3054
|
>
|
|
@@ -3230,6 +3301,7 @@ async function submitEncryptedFolder(payload: { name: string; password: string }
|
|
|
3230
3301
|
/>
|
|
3231
3302
|
<!-- /wiring:d2 -->
|
|
3232
3303
|
</div>
|
|
3304
|
+
</div><!-- /fe__primary ui-fix -->
|
|
3233
3305
|
|
|
3234
3306
|
<!-- wiring:d1 — tab başına split: sağ ikincil panel (dar modda kapalı).
|
|
3235
3307
|
:key tab kimliğine bağlı — tab geçişinde pane kendi konumuyla temiz
|
|
@@ -3256,6 +3328,7 @@ async function submitEncryptedFolder(payload: { name: string; password: string }
|
|
|
3256
3328
|
@close="closeSplit"
|
|
3257
3329
|
@open-tab="(p: string) => tabsApi.openTab(p, { viewMode: viewMode, background: true })"
|
|
3258
3330
|
@transfer="onPaneTransfer"
|
|
3331
|
+
@context="onPaneContext /* ui-fix — yan panel sağ-tık menüsü */"
|
|
3259
3332
|
/>
|
|
3260
3333
|
<!-- /wiring:d1 -->
|
|
3261
3334
|
|
|
@@ -65,6 +65,9 @@ const emit = defineEmits<{
|
|
|
65
65
|
(e: 'close'): void;
|
|
66
66
|
(e: 'open-tab', path: string): void;
|
|
67
67
|
(e: 'transfer', p: { sources: string[]; targetWire: string; originWire?: string }): void;
|
|
68
|
+
/* ui-fix — yan panelde sağ-tık: menü ana bileşende (FileExplorer) açılır.
|
|
69
|
+
* node=null → boş alana sağ-tık (seçimsiz, yalnız Yapıştır). */
|
|
70
|
+
(e: 'context', node: FileNode | null, ev: MouseEvent): void;
|
|
68
71
|
}>();
|
|
69
72
|
|
|
70
73
|
const { t } = useLocale(() => props.locale);
|
|
@@ -168,14 +171,26 @@ function onViewClick(n: FileNode, mod: { ctrl: boolean; shift: boolean }) {
|
|
|
168
171
|
selected.value = next;
|
|
169
172
|
}
|
|
170
173
|
|
|
171
|
-
/* ui-fix — right-click on a pane item: activate + select it,
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
+
/* ui-fix — right-click on a pane item: activate + select it, then let the
|
|
175
|
+
* host open the pane context menu (its actions are pane-routed). Selecting
|
|
176
|
+
* first keeps the menu's targets on THIS pane, not the main panel. */
|
|
174
177
|
function onViewContext(n: FileNode, ev: MouseEvent) {
|
|
175
178
|
ev.preventDefault();
|
|
176
179
|
ev.stopPropagation();
|
|
177
180
|
emit('activate');
|
|
178
181
|
if (!selected.value.has(n.path)) selected.value = new Set([n.path]);
|
|
182
|
+
emit('context', n, ev);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* ui-fix — boş alana (arka plan) sağ-tık: seçimsiz menü (yalnız Yapıştır)
|
|
186
|
+
* → boş klasöre / mevcut klasöre dosya yapıştırma. Satır menüsü stopProp
|
|
187
|
+
* ettiğinden bu yalnız gerçek boş alanda tetiklenir. */
|
|
188
|
+
function onBgContext(ev: MouseEvent) {
|
|
189
|
+
ev.preventDefault();
|
|
190
|
+
ev.stopPropagation(); // FileExplorer kökündeki canvas menüsüne bubble etmesin
|
|
191
|
+
emit('activate');
|
|
192
|
+
selected.value = new Set();
|
|
193
|
+
emit('context', null, ev);
|
|
179
194
|
}
|
|
180
195
|
|
|
181
196
|
/* ui-fix — drop-into from the shared views: same payload path as the
|
|
@@ -344,6 +359,7 @@ defineExpose({ reload, goUp, selectAll, openSelected, selectedNodes, getPath });
|
|
|
344
359
|
class="fe-split__body"
|
|
345
360
|
:class="{ 'is-dropover': dropBg }"
|
|
346
361
|
@click.self="clearSelection"
|
|
362
|
+
@contextmenu="onBgContext"
|
|
347
363
|
@dragover="onBgDragOver"
|
|
348
364
|
@dragleave="onBgDragLeave"
|
|
349
365
|
@drop="onBgDrop"
|
package/src/styles/base.css
CHANGED
|
@@ -3220,9 +3220,23 @@ filex-explorer {
|
|
|
3220
3220
|
display: none;
|
|
3221
3221
|
}
|
|
3222
3222
|
|
|
3223
|
+
/* ui-fix — sol panel sarmalı: breadcrumb + durum şeritleri + body bir
|
|
3224
|
+
flex-column. Split olmadan tüm genişlik; split olunca sol yarı (böylece
|
|
3225
|
+
breadcrumb kendi panelini kaplar, SecondaryPane ile simetrik). */
|
|
3226
|
+
.fe__primary {
|
|
3227
|
+
display: flex;
|
|
3228
|
+
flex-direction: column;
|
|
3229
|
+
flex: 1 1 auto;
|
|
3230
|
+
min-width: 0;
|
|
3231
|
+
min-height: 0;
|
|
3232
|
+
}
|
|
3233
|
+
.fe__primary > .fe__body {
|
|
3234
|
+
min-width: 0;
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3223
3237
|
/* Split layout — equal halves inside fe__main; the inspector (koru:k1)
|
|
3224
3238
|
keeps its fixed width to the right of both. */
|
|
3225
|
-
.fe__main--split > .
|
|
3239
|
+
.fe__main--split > .fe__primary {
|
|
3226
3240
|
flex: 1 1 50%;
|
|
3227
3241
|
}
|
|
3228
3242
|
.fe-split {
|
|
@@ -3236,11 +3250,11 @@ filex-explorer {
|
|
|
3236
3250
|
color: var(--fe-text);
|
|
3237
3251
|
}
|
|
3238
3252
|
/* Active-panel accent: a thin top line on whichever pane owns the keyboard. */
|
|
3239
|
-
.fe__main--split > .
|
|
3253
|
+
.fe__main--split > .fe__primary,
|
|
3240
3254
|
.fe-split {
|
|
3241
3255
|
box-shadow: inset 0 2px 0 transparent;
|
|
3242
3256
|
}
|
|
3243
|
-
.fe__main--split > .
|
|
3257
|
+
.fe__main--split > .fe__primary.fe-pane--focus,
|
|
3244
3258
|
.fe-split.fe-pane--focus {
|
|
3245
3259
|
box-shadow: inset 0 2px 0 var(--fe-primary);
|
|
3246
3260
|
}
|