@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.
Files changed (30) hide show
  1. package/dist/{ArchiveViewer-Qi4L2jj9.js → ArchiveViewer-DAb5peBU.js} +2 -2
  2. package/dist/{ArchiveViewer-Qi4L2jj9.js.map → ArchiveViewer-DAb5peBU.js.map} +1 -1
  3. package/dist/{CsvViewer-IOIrJDsJ.js → CsvViewer-_bnmnpjn.js} +2 -2
  4. package/dist/{CsvViewer-IOIrJDsJ.js.map → CsvViewer-_bnmnpjn.js.map} +1 -1
  5. package/dist/{DrawioViewer-D0KtUQBO.js → DrawioViewer-Bjns4ob8.js} +2 -2
  6. package/dist/{DrawioViewer-D0KtUQBO.js.map → DrawioViewer-Bjns4ob8.js.map} +1 -1
  7. package/dist/{EpubViewer-DJOXiOi4.js → EpubViewer-DoFuZTtA.js} +2 -2
  8. package/dist/{EpubViewer-DJOXiOi4.js.map → EpubViewer-DoFuZTtA.js.map} +1 -1
  9. package/dist/{IpynbViewer-D16jXVJc.js → IpynbViewer-eg1ySMD4.js} +2 -2
  10. package/dist/{IpynbViewer-D16jXVJc.js.map → IpynbViewer-eg1ySMD4.js.map} +1 -1
  11. package/dist/{MermaidViewer-BnSaVg1L.js → MermaidViewer-BZ13vA6S.js} +2 -2
  12. package/dist/{MermaidViewer-BnSaVg1L.js.map → MermaidViewer-BZ13vA6S.js.map} +1 -1
  13. package/dist/{PsdViewer-BUerXaQA.js → PsdViewer-qFkE4KCB.js} +2 -2
  14. package/dist/{PsdViewer-BUerXaQA.js.map → PsdViewer-qFkE4KCB.js.map} +1 -1
  15. package/dist/{TiffViewer-D0Qn3IV-.js → TiffViewer-eHJTCYsd.js} +2 -2
  16. package/dist/{TiffViewer-D0Qn3IV-.js.map → TiffViewer-eHJTCYsd.js.map} +1 -1
  17. package/dist/{Viewer3D-BtRK-k1B.js → Viewer3D-C4--ljdO.js} +2 -2
  18. package/dist/{Viewer3D-BtRK-k1B.js.map → Viewer3D-C4--ljdO.js.map} +1 -1
  19. package/dist/filex-core.js +1 -1
  20. package/dist/filex-core.umd.cjs +33 -33
  21. package/dist/filex-core.umd.cjs.map +1 -1
  22. package/dist/{index-CGNE1bSv.js → index-BSDT0PU8.js} +4460 -4403
  23. package/dist/index-BSDT0PU8.js.map +1 -0
  24. package/dist/index.d.ts +5 -0
  25. package/dist/style.css +1 -1
  26. package/package.json +1 -1
  27. package/src/FileExplorer.vue +79 -6
  28. package/src/components/SecondaryPane.vue +19 -3
  29. package/src/styles/base.css +17 -3
  30. package/dist/index-CGNE1bSv.js.map +0 -1
@@ -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, no menu
172
- * (the pane has no item menu; letting the main panel's menu open here
173
- * would act on the WRONG panel's selection). */
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"
@@ -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 > .fe__body {
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 > .fe__body,
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 > .fe__body.fe-pane--focus,
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
  }