@brftech/filex-core 0.41.4 → 0.42.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-oqaEyqcB.js → ArchiveViewer-CGl_J_qE.js} +2 -2
- package/dist/{ArchiveViewer-oqaEyqcB.js.map → ArchiveViewer-CGl_J_qE.js.map} +1 -1
- package/dist/{CsvViewer-BfT-4WpB.js → CsvViewer-D-na6SEG.js} +2 -2
- package/dist/{CsvViewer-BfT-4WpB.js.map → CsvViewer-D-na6SEG.js.map} +1 -1
- package/dist/{DrawioViewer-Cu2ZquNO.js → DrawioViewer-BFkTSrNc.js} +2 -2
- package/dist/{DrawioViewer-Cu2ZquNO.js.map → DrawioViewer-BFkTSrNc.js.map} +1 -1
- package/dist/{EpubViewer-yfAfnrYF.js → EpubViewer-BfRE0DTL.js} +2 -2
- package/dist/{EpubViewer-yfAfnrYF.js.map → EpubViewer-BfRE0DTL.js.map} +1 -1
- package/dist/{IpynbViewer-DLSOs3yU.js → IpynbViewer-BpBlICH-.js} +2 -2
- package/dist/{IpynbViewer-DLSOs3yU.js.map → IpynbViewer-BpBlICH-.js.map} +1 -1
- package/dist/{MermaidViewer-D2AsT14x.js → MermaidViewer-Ry5Ma463.js} +2 -2
- package/dist/{MermaidViewer-D2AsT14x.js.map → MermaidViewer-Ry5Ma463.js.map} +1 -1
- package/dist/{PsdViewer-DOza4QJt.js → PsdViewer-BmTlq1Gh.js} +2 -2
- package/dist/{PsdViewer-DOza4QJt.js.map → PsdViewer-BmTlq1Gh.js.map} +1 -1
- package/dist/{TiffViewer-24MCOn1t.js → TiffViewer-DE5bKDDx.js} +2 -2
- package/dist/{TiffViewer-24MCOn1t.js.map → TiffViewer-DE5bKDDx.js.map} +1 -1
- package/dist/{Viewer3D-BVjtbhhc.js → Viewer3D-DefcNYOm.js} +2 -2
- package/dist/{Viewer3D-BVjtbhhc.js.map → Viewer3D-DefcNYOm.js.map} +1 -1
- package/dist/filex-core.js +1 -1
- package/dist/filex-core.umd.cjs +8 -8
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/{index-B8PLGR-X.js → index-B0N5qiyj.js} +401 -386
- package/dist/{index-B8PLGR-X.js.map → index-B0N5qiyj.js.map} +1 -1
- package/dist/index.d.ts +59 -4
- package/package.json +1 -1
- package/src/FileExplorer.vue +19 -0
- package/src/components/FilePane.vue +22 -7
- package/src/types/ExplorerConfig.ts +32 -0
package/dist/index.d.ts
CHANGED
|
@@ -484,6 +484,7 @@ readonly authHeaders?: (() => Record<string, string> | Promise<Record<string, st
|
|
|
484
484
|
readonly authCredentials?: RequestCredentials | undefined;
|
|
485
485
|
readonly e2eActive?: boolean | undefined;
|
|
486
486
|
readonly bodyOverride?: boolean | undefined;
|
|
487
|
+
readonly openTrigger?: "single" | "double" | undefined;
|
|
487
488
|
} & VNodeProps & AllowedComponentProps & ComponentCustomProps;
|
|
488
489
|
$attrs: Attrs;
|
|
489
490
|
$refs: {
|
|
@@ -548,6 +549,7 @@ authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
|
548
549
|
authCredentials?: RequestCredentials;
|
|
549
550
|
e2eActive?: boolean;
|
|
550
551
|
bodyOverride?: boolean;
|
|
552
|
+
openTrigger?: "single" | "double";
|
|
551
553
|
}> & Readonly<{
|
|
552
554
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
553
555
|
}>, {
|
|
@@ -566,6 +568,7 @@ trashVisible: boolean;
|
|
|
566
568
|
showCrumbs: boolean;
|
|
567
569
|
showFilterBar: boolean;
|
|
568
570
|
showViewSwitcher: boolean;
|
|
571
|
+
openTrigger: "single" | "double";
|
|
569
572
|
}, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & {
|
|
570
573
|
beforeCreate?: (() => void) | (() => void)[];
|
|
571
574
|
created?: (() => void) | (() => void)[];
|
|
@@ -655,6 +658,7 @@ trashVisible: boolean;
|
|
|
655
658
|
showCrumbs: boolean;
|
|
656
659
|
showFilterBar: boolean;
|
|
657
660
|
showViewSwitcher: boolean;
|
|
661
|
+
openTrigger: "single" | "double";
|
|
658
662
|
}> & Omit<Readonly<{
|
|
659
663
|
paneId: PaneId;
|
|
660
664
|
api: FileApi;
|
|
@@ -706,9 +710,10 @@ authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
|
706
710
|
authCredentials?: RequestCredentials;
|
|
707
711
|
e2eActive?: boolean;
|
|
708
712
|
bodyOverride?: boolean;
|
|
713
|
+
openTrigger?: "single" | "double";
|
|
709
714
|
}> & Readonly<{
|
|
710
715
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
711
|
-
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher")> & {
|
|
716
|
+
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher" | "openTrigger")> & {
|
|
712
717
|
reload: () => Promise<void>;
|
|
713
718
|
goUp: () => void;
|
|
714
719
|
getPath: () => string;
|
|
@@ -780,6 +785,7 @@ readonly authHeaders?: (() => Record<string, string> | Promise<Record<string, st
|
|
|
780
785
|
readonly authCredentials?: RequestCredentials | undefined;
|
|
781
786
|
readonly e2eActive?: boolean | undefined;
|
|
782
787
|
readonly bodyOverride?: boolean | undefined;
|
|
788
|
+
readonly openTrigger?: "single" | "double" | undefined;
|
|
783
789
|
} & VNodeProps & AllowedComponentProps & ComponentCustomProps;
|
|
784
790
|
$attrs: Attrs;
|
|
785
791
|
$refs: {
|
|
@@ -844,6 +850,7 @@ authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
|
844
850
|
authCredentials?: RequestCredentials;
|
|
845
851
|
e2eActive?: boolean;
|
|
846
852
|
bodyOverride?: boolean;
|
|
853
|
+
openTrigger?: "single" | "double";
|
|
847
854
|
}> & Readonly<{
|
|
848
855
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
849
856
|
}>, {
|
|
@@ -862,6 +869,7 @@ trashVisible: boolean;
|
|
|
862
869
|
showCrumbs: boolean;
|
|
863
870
|
showFilterBar: boolean;
|
|
864
871
|
showViewSwitcher: boolean;
|
|
872
|
+
openTrigger: "single" | "double";
|
|
865
873
|
}, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & {
|
|
866
874
|
beforeCreate?: (() => void) | (() => void)[];
|
|
867
875
|
created?: (() => void) | (() => void)[];
|
|
@@ -951,6 +959,7 @@ trashVisible: boolean;
|
|
|
951
959
|
showCrumbs: boolean;
|
|
952
960
|
showFilterBar: boolean;
|
|
953
961
|
showViewSwitcher: boolean;
|
|
962
|
+
openTrigger: "single" | "double";
|
|
954
963
|
}> & Omit<Readonly<{
|
|
955
964
|
paneId: PaneId;
|
|
956
965
|
api: FileApi;
|
|
@@ -1002,9 +1011,10 @@ authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
|
1002
1011
|
authCredentials?: RequestCredentials;
|
|
1003
1012
|
e2eActive?: boolean;
|
|
1004
1013
|
bodyOverride?: boolean;
|
|
1014
|
+
openTrigger?: "single" | "double";
|
|
1005
1015
|
}> & Readonly<{
|
|
1006
1016
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
1007
|
-
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher")> & {
|
|
1017
|
+
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher" | "openTrigger")> & {
|
|
1008
1018
|
reload: () => Promise<void>;
|
|
1009
1019
|
goUp: () => void;
|
|
1010
1020
|
getPath: () => string;
|
|
@@ -1081,6 +1091,7 @@ trashVisible: boolean;
|
|
|
1081
1091
|
showCrumbs: boolean;
|
|
1082
1092
|
showFilterBar: boolean;
|
|
1083
1093
|
showViewSwitcher: boolean;
|
|
1094
|
+
openTrigger: "single" | "double";
|
|
1084
1095
|
}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLElement>;
|
|
1085
1096
|
|
|
1086
1097
|
declare type __VLS_Props = {
|
|
@@ -1284,6 +1295,10 @@ declare type __VLS_Props_15 = {
|
|
|
1284
1295
|
* encrypted lock screen) — those are WINDOW states with no listing
|
|
1285
1296
|
* behind them, so the pane's own state chain must not also run. */
|
|
1286
1297
|
bodyOverride?: boolean;
|
|
1298
|
+
/** Mouse open gesture — 'double' (single selects, double opens) or
|
|
1299
|
+
* 'single' (first click opens). Touch always opens on tap; the checkbox
|
|
1300
|
+
* always selects. See onViewClick. */
|
|
1301
|
+
openTrigger?: 'single' | 'double';
|
|
1287
1302
|
};
|
|
1288
1303
|
|
|
1289
1304
|
declare type __VLS_Props_16 = {
|
|
@@ -1979,6 +1994,7 @@ declare function __VLS_template(): {
|
|
|
1979
1994
|
readonly authCredentials?: RequestCredentials | undefined;
|
|
1980
1995
|
readonly e2eActive?: boolean | undefined;
|
|
1981
1996
|
readonly bodyOverride?: boolean | undefined;
|
|
1997
|
+
readonly openTrigger?: "single" | "double" | undefined;
|
|
1982
1998
|
} & VNodeProps & AllowedComponentProps & ComponentCustomProps;
|
|
1983
1999
|
$attrs: Attrs;
|
|
1984
2000
|
$refs: {
|
|
@@ -2043,6 +2059,7 @@ declare function __VLS_template(): {
|
|
|
2043
2059
|
authCredentials?: RequestCredentials;
|
|
2044
2060
|
e2eActive?: boolean;
|
|
2045
2061
|
bodyOverride?: boolean;
|
|
2062
|
+
openTrigger?: "single" | "double";
|
|
2046
2063
|
}> & Readonly<{
|
|
2047
2064
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
2048
2065
|
}>, {
|
|
@@ -2061,6 +2078,7 @@ declare function __VLS_template(): {
|
|
|
2061
2078
|
showCrumbs: boolean;
|
|
2062
2079
|
showFilterBar: boolean;
|
|
2063
2080
|
showViewSwitcher: boolean;
|
|
2081
|
+
openTrigger: "single" | "double";
|
|
2064
2082
|
}, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & {
|
|
2065
2083
|
beforeCreate?: (() => void) | (() => void)[];
|
|
2066
2084
|
created?: (() => void) | (() => void)[];
|
|
@@ -2150,6 +2168,7 @@ declare function __VLS_template(): {
|
|
|
2150
2168
|
showCrumbs: boolean;
|
|
2151
2169
|
showFilterBar: boolean;
|
|
2152
2170
|
showViewSwitcher: boolean;
|
|
2171
|
+
openTrigger: "single" | "double";
|
|
2153
2172
|
}> & Omit<Readonly<{
|
|
2154
2173
|
paneId: PaneId;
|
|
2155
2174
|
api: FileApi;
|
|
@@ -2201,9 +2220,10 @@ declare function __VLS_template(): {
|
|
|
2201
2220
|
authCredentials?: RequestCredentials;
|
|
2202
2221
|
e2eActive?: boolean;
|
|
2203
2222
|
bodyOverride?: boolean;
|
|
2223
|
+
openTrigger?: "single" | "double";
|
|
2204
2224
|
}> & Readonly<{
|
|
2205
2225
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
2206
|
-
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher")> & {
|
|
2226
|
+
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher" | "openTrigger")> & {
|
|
2207
2227
|
reload: () => Promise<void>;
|
|
2208
2228
|
goUp: () => void;
|
|
2209
2229
|
getPath: () => string;
|
|
@@ -2275,6 +2295,7 @@ declare function __VLS_template(): {
|
|
|
2275
2295
|
readonly authCredentials?: RequestCredentials | undefined;
|
|
2276
2296
|
readonly e2eActive?: boolean | undefined;
|
|
2277
2297
|
readonly bodyOverride?: boolean | undefined;
|
|
2298
|
+
readonly openTrigger?: "single" | "double" | undefined;
|
|
2278
2299
|
} & VNodeProps & AllowedComponentProps & ComponentCustomProps;
|
|
2279
2300
|
$attrs: Attrs;
|
|
2280
2301
|
$refs: {
|
|
@@ -2339,6 +2360,7 @@ declare function __VLS_template(): {
|
|
|
2339
2360
|
authCredentials?: RequestCredentials;
|
|
2340
2361
|
e2eActive?: boolean;
|
|
2341
2362
|
bodyOverride?: boolean;
|
|
2363
|
+
openTrigger?: "single" | "double";
|
|
2342
2364
|
}> & Readonly<{
|
|
2343
2365
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
2344
2366
|
}>, {
|
|
@@ -2357,6 +2379,7 @@ declare function __VLS_template(): {
|
|
|
2357
2379
|
showCrumbs: boolean;
|
|
2358
2380
|
showFilterBar: boolean;
|
|
2359
2381
|
showViewSwitcher: boolean;
|
|
2382
|
+
openTrigger: "single" | "double";
|
|
2360
2383
|
}, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & {
|
|
2361
2384
|
beforeCreate?: (() => void) | (() => void)[];
|
|
2362
2385
|
created?: (() => void) | (() => void)[];
|
|
@@ -2446,6 +2469,7 @@ declare function __VLS_template(): {
|
|
|
2446
2469
|
showCrumbs: boolean;
|
|
2447
2470
|
showFilterBar: boolean;
|
|
2448
2471
|
showViewSwitcher: boolean;
|
|
2472
|
+
openTrigger: "single" | "double";
|
|
2449
2473
|
}> & Omit<Readonly<{
|
|
2450
2474
|
paneId: PaneId;
|
|
2451
2475
|
api: FileApi;
|
|
@@ -2497,9 +2521,10 @@ declare function __VLS_template(): {
|
|
|
2497
2521
|
authCredentials?: RequestCredentials;
|
|
2498
2522
|
e2eActive?: boolean;
|
|
2499
2523
|
bodyOverride?: boolean;
|
|
2524
|
+
openTrigger?: "single" | "double";
|
|
2500
2525
|
}> & Readonly<{
|
|
2501
2526
|
[x: `on${Capitalize<any>}`]: ((...args: any) => any) | undefined;
|
|
2502
|
-
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher")> & {
|
|
2527
|
+
}>, "reload" | "dirPerm" | "goUp" | "getPath" | "visibleNodes" | "loadFolder" | "rowCount" | "rowPaths" | ("trashVisible" | "showCrumbs" | "showFilterBar" | "showViewSwitcher" | "openTrigger")> & {
|
|
2503
2528
|
reload: () => Promise<void>;
|
|
2504
2529
|
goUp: () => void;
|
|
2505
2530
|
getPath: () => string;
|
|
@@ -4188,6 +4213,36 @@ export declare interface ExplorerConfig {
|
|
|
4188
4213
|
* Starred row that then disappears. A value here wins over the server's.
|
|
4189
4214
|
*/
|
|
4190
4215
|
callerKind?: 'user' | 'app';
|
|
4216
|
+
/**
|
|
4217
|
+
* How a mouse opens an item.
|
|
4218
|
+
*
|
|
4219
|
+
* 'double' (default) — a single click SELECTS, a double click OPENS
|
|
4220
|
+
* (classic desktop file-manager). This is a
|
|
4221
|
+
* per-viewer preference the host may expose as a
|
|
4222
|
+
* setting.
|
|
4223
|
+
* 'single' — a single click OPENS (the item is opened on the
|
|
4224
|
+
* first click; the checkbox is still the one click
|
|
4225
|
+
* that selects).
|
|
4226
|
+
*
|
|
4227
|
+
* ⚠ TOUCH is not governed by this: a finger tap always opens (the mobile
|
|
4228
|
+
* convention, and there is no hover-to-select on a touchscreen). The
|
|
4229
|
+
* checkbox always selects, on every device and in either mode. See
|
|
4230
|
+
* FilePane.onViewClick + composables/useRowTouch.
|
|
4231
|
+
*/
|
|
4232
|
+
openTrigger?: 'single' | 'double';
|
|
4233
|
+
/**
|
|
4234
|
+
* Hand the OPEN of a file to the host instead of opening the in-page
|
|
4235
|
+
* preview/editor overlay. When true, opening a file emits `file-opened`
|
|
4236
|
+
* (path + basename) and the explorer does NOT mount its own PreviewModal —
|
|
4237
|
+
* the host decides what to do (the desktop app opens the file in its own
|
|
4238
|
+
* window per document). Directories still navigate inline, and Space
|
|
4239
|
+
* quick-look still peeks in-page. Default false (web/embeds preview inline).
|
|
4240
|
+
*
|
|
4241
|
+
* ⚠ Ignored inside an unlocked E2E-encrypted folder: the host window would
|
|
4242
|
+
* fetch raw server bytes (ciphertext), so those keep the in-page decrypted
|
|
4243
|
+
* preview.
|
|
4244
|
+
*/
|
|
4245
|
+
openInHost?: boolean;
|
|
4191
4246
|
/** Default view. */
|
|
4192
4247
|
viewMode?: 'list' | 'grid';
|
|
4193
4248
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brftech/filex-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"description": "filex core — Vue 3 source of truth for the filex file manager (FileExplorer + ConnectionsPanel SFCs, composables, types)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/filex-core.umd.cjs",
|
package/src/FileExplorer.vue
CHANGED
|
@@ -3090,6 +3090,16 @@ function openNode(n: FileNode) {
|
|
|
3090
3090
|
}
|
|
3091
3091
|
if (e2eLocked.value && n.type === 'file') return;
|
|
3092
3092
|
/* /wiring:e2 */
|
|
3093
|
+
// Host-owned open (desktop app): a file opens in the host's OWN window per
|
|
3094
|
+
// document, not in the in-page overlay. Emit and stop — the host listens on
|
|
3095
|
+
// `file-opened` and spawns the window. Directories still navigate inline
|
|
3096
|
+
// (handled above); Space quick-look still peeks in-page. E2E files fell into
|
|
3097
|
+
// the decrypted in-page branch above, so a host window never gets ciphertext.
|
|
3098
|
+
if (props.config.openInHost && n.type === 'file') {
|
|
3099
|
+
emit('file-opened', { path: n.path, basename: n.basename });
|
|
3100
|
+
void markRecent(n);
|
|
3101
|
+
return;
|
|
3102
|
+
}
|
|
3093
3103
|
// "Aç" / double-click contract: open in a new tab against the
|
|
3094
3104
|
// standalone editor route, regardless of file type. The editor page
|
|
3095
3105
|
// picks the right viewer (OnlyOffice for office, Monaco for code/
|
|
@@ -3204,6 +3214,13 @@ function openNodeInNewTab(n: FileNode) {
|
|
|
3204
3214
|
return;
|
|
3205
3215
|
}
|
|
3206
3216
|
/* /wiring:e2 */
|
|
3217
|
+
// Host-owned open (desktop): the context-menu "Aç" opens the host window
|
|
3218
|
+
// too, so Enter/double-click/"Aç" are ONE open path — not a window here and
|
|
3219
|
+
// a system-browser tab there. openNode carries the `file-opened` emit.
|
|
3220
|
+
if (props.config.openInHost) {
|
|
3221
|
+
openNode(n);
|
|
3222
|
+
return;
|
|
3223
|
+
}
|
|
3207
3224
|
// RBAC: a viewer (no edit on this item) can't use the editable "Aç"
|
|
3208
3225
|
// surface — drop to the read-only in-page preview instead.
|
|
3209
3226
|
if (!permCanEdit((n.perm as string) ?? dirPerm.value)) {
|
|
@@ -6365,6 +6382,7 @@ function closeRecoveryKey() {
|
|
|
6365
6382
|
:order="listingOrder"
|
|
6366
6383
|
:view-mode="viewMode"
|
|
6367
6384
|
:view-modes="allowedViewModes"
|
|
6385
|
+
:open-trigger="props.config.openTrigger"
|
|
6368
6386
|
:show-crumbs="navView !== 'home' /* Home has no address: its cards come
|
|
6369
6387
|
from every folder in every storage, so a trail would have to name
|
|
6370
6388
|
one */"
|
|
@@ -6843,6 +6861,7 @@ function closeRecoveryKey() {
|
|
|
6843
6861
|
:nav-offers-trash="navOffersTrash"
|
|
6844
6862
|
:view-mode="paneViewMode"
|
|
6845
6863
|
:view-modes="allowedViewModes"
|
|
6864
|
+
:open-trigger="props.config.openTrigger"
|
|
6846
6865
|
:clipped="clippedPaths"
|
|
6847
6866
|
:can-write="canWriteHere"
|
|
6848
6867
|
:can-paste="!!clipboard.mode"
|
|
@@ -217,12 +217,18 @@ const props = withDefaults(
|
|
|
217
217
|
* encrypted lock screen) — those are WINDOW states with no listing
|
|
218
218
|
* behind them, so the pane's own state chain must not also run. */
|
|
219
219
|
bodyOverride?: boolean;
|
|
220
|
+
|
|
221
|
+
/** Mouse open gesture — 'double' (single selects, double opens) or
|
|
222
|
+
* 'single' (first click opens). Touch always opens on tap; the checkbox
|
|
223
|
+
* always selects. See onViewClick. */
|
|
224
|
+
openTrigger?: 'single' | 'double';
|
|
220
225
|
}>(),
|
|
221
226
|
{
|
|
222
227
|
showCrumbs: true,
|
|
223
228
|
showFilterBar: true,
|
|
224
229
|
showViewSwitcher: true,
|
|
225
230
|
trashVisible: true,
|
|
231
|
+
openTrigger: 'double',
|
|
226
232
|
},
|
|
227
233
|
);
|
|
228
234
|
|
|
@@ -458,22 +464,31 @@ function withinOpenGuard(): boolean {
|
|
|
458
464
|
|
|
459
465
|
function onViewClick(n: FileNode, mod: ClickMod) {
|
|
460
466
|
if (withinOpenGuard()) return;
|
|
461
|
-
/*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
* on the item opens it, Ctrl/Shift held or not, selection or not. See
|
|
465
|
-
* composables/useRowTouch. */
|
|
467
|
+
/* The checkbox is the one click that always reaches the selection — issue
|
|
468
|
+
* #26's rule, kept on every device and in either open mode. A shift-tick
|
|
469
|
+
* still extends the range; a plain tick toggles (ctrl: true). */
|
|
466
470
|
if (mod.check) {
|
|
467
471
|
emit('activate');
|
|
468
472
|
emit('click-row', n, { ctrl: true, shift: mod.shift });
|
|
469
473
|
return;
|
|
470
474
|
}
|
|
471
|
-
|
|
472
|
-
|
|
475
|
+
/* A finger tap always OPENS (the mobile convention — there is no
|
|
476
|
+
* hover-to-select on a touchscreen). For a mouse the host's `openTrigger`
|
|
477
|
+
* decides: 'single' opens on this click; 'double' (default) makes a single
|
|
478
|
+
* click SELECT and leaves opening to onViewDbl. issue #26's "any click
|
|
479
|
+
* opens" is `openTrigger: 'single'`. */
|
|
480
|
+
if (mod.touch || props.openTrigger === 'single') {
|
|
481
|
+
openedAt = Date.now();
|
|
482
|
+
onRowOpen(n);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
emit('activate');
|
|
486
|
+
emit('click-row', n, { ctrl: mod.ctrl, shift: mod.shift });
|
|
473
487
|
}
|
|
474
488
|
|
|
475
489
|
function onViewDbl(n: FileNode) {
|
|
476
490
|
if (withinOpenGuard()) return;
|
|
491
|
+
openedAt = Date.now();
|
|
477
492
|
onRowOpen(n);
|
|
478
493
|
}
|
|
479
494
|
|
|
@@ -454,6 +454,38 @@ export interface ExplorerConfig {
|
|
|
454
454
|
callerKind?: 'user' | 'app';
|
|
455
455
|
|
|
456
456
|
|
|
457
|
+
/**
|
|
458
|
+
* How a mouse opens an item.
|
|
459
|
+
*
|
|
460
|
+
* 'double' (default) — a single click SELECTS, a double click OPENS
|
|
461
|
+
* (classic desktop file-manager). This is a
|
|
462
|
+
* per-viewer preference the host may expose as a
|
|
463
|
+
* setting.
|
|
464
|
+
* 'single' — a single click OPENS (the item is opened on the
|
|
465
|
+
* first click; the checkbox is still the one click
|
|
466
|
+
* that selects).
|
|
467
|
+
*
|
|
468
|
+
* ⚠ TOUCH is not governed by this: a finger tap always opens (the mobile
|
|
469
|
+
* convention, and there is no hover-to-select on a touchscreen). The
|
|
470
|
+
* checkbox always selects, on every device and in either mode. See
|
|
471
|
+
* FilePane.onViewClick + composables/useRowTouch.
|
|
472
|
+
*/
|
|
473
|
+
openTrigger?: 'single' | 'double';
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Hand the OPEN of a file to the host instead of opening the in-page
|
|
477
|
+
* preview/editor overlay. When true, opening a file emits `file-opened`
|
|
478
|
+
* (path + basename) and the explorer does NOT mount its own PreviewModal —
|
|
479
|
+
* the host decides what to do (the desktop app opens the file in its own
|
|
480
|
+
* window per document). Directories still navigate inline, and Space
|
|
481
|
+
* quick-look still peeks in-page. Default false (web/embeds preview inline).
|
|
482
|
+
*
|
|
483
|
+
* ⚠ Ignored inside an unlocked E2E-encrypted folder: the host window would
|
|
484
|
+
* fetch raw server bytes (ciphertext), so those keep the in-page decrypted
|
|
485
|
+
* preview.
|
|
486
|
+
*/
|
|
487
|
+
openInHost?: boolean;
|
|
488
|
+
|
|
457
489
|
/** Default view. */
|
|
458
490
|
viewMode?: 'list' | 'grid';
|
|
459
491
|
|