@brftech/filex-core 0.44.2 → 0.45.1

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 (50) hide show
  1. package/dist/{ArchiveViewer-D_tJxJhJ.js → ArchiveViewer-QuNXAECN.js} +2 -2
  2. package/dist/{ArchiveViewer-D_tJxJhJ.js.map → ArchiveViewer-QuNXAECN.js.map} +1 -1
  3. package/dist/{CsvViewer-B95fArq0.js → CsvViewer-niuoz1Uk.js} +2 -2
  4. package/dist/{CsvViewer-B95fArq0.js.map → CsvViewer-niuoz1Uk.js.map} +1 -1
  5. package/dist/{DrawioViewer-BAaPMTge.js → DrawioViewer-BtqMiasr.js} +2 -2
  6. package/dist/{DrawioViewer-BAaPMTge.js.map → DrawioViewer-BtqMiasr.js.map} +1 -1
  7. package/dist/{EpubViewer-B-B7bRW7.js → EpubViewer-ERm7L1WN.js} +2 -2
  8. package/dist/{EpubViewer-B-B7bRW7.js.map → EpubViewer-ERm7L1WN.js.map} +1 -1
  9. package/dist/{IpynbViewer-COOTyOcu.js → IpynbViewer-Cmz5n0VR.js} +2 -2
  10. package/dist/{IpynbViewer-COOTyOcu.js.map → IpynbViewer-Cmz5n0VR.js.map} +1 -1
  11. package/dist/{MermaidViewer-CjVCmR3s.js → MermaidViewer-BJ5uOyhc.js} +2 -2
  12. package/dist/{MermaidViewer-CjVCmR3s.js.map → MermaidViewer-BJ5uOyhc.js.map} +1 -1
  13. package/dist/{PsdViewer-xsIYL9Gu.js → PsdViewer-DYCJF2BM.js} +2 -2
  14. package/dist/{PsdViewer-xsIYL9Gu.js.map → PsdViewer-DYCJF2BM.js.map} +1 -1
  15. package/dist/{TiffViewer-CtwnTxqL.js → TiffViewer-DbJv_0El.js} +2 -2
  16. package/dist/{TiffViewer-CtwnTxqL.js.map → TiffViewer-DbJv_0El.js.map} +1 -1
  17. package/dist/{Viewer3D-xYMwndEy.js → Viewer3D-DwZfYoO3.js} +2 -2
  18. package/dist/{Viewer3D-xYMwndEy.js.map → Viewer3D-DwZfYoO3.js.map} +1 -1
  19. package/dist/filex-core.js +298 -291
  20. package/dist/filex-core.umd.cjs +61 -61
  21. package/dist/filex-core.umd.cjs.map +1 -1
  22. package/dist/{index-BBToAjwL.js → index-1RaeWGFO.js} +14218 -13831
  23. package/dist/index-1RaeWGFO.js.map +1 -0
  24. package/dist/index.d.ts +253 -31
  25. package/dist/style.css +1 -1
  26. package/package.json +1 -1
  27. package/src/FileExplorer.vue +265 -99
  28. package/src/components/AdvancedSearch.vue +3 -3
  29. package/src/components/CommandPalette.vue +166 -42
  30. package/src/components/ConnectionsPanel.vue +3 -11
  31. package/src/components/SideNav.vue +16 -11
  32. package/src/components/plugin/PluginViewModal.vue +7 -0
  33. package/src/components/plugin/nodes/SurfacePdfFields.vue +16 -1
  34. package/src/components/public/PublicLinkPage.vue +6 -5
  35. package/src/composables/useFileApi.ts +32 -1
  36. package/src/composables/usePluginSurface.ts +12 -0
  37. package/src/composables/useSystemDark.ts +32 -0
  38. package/src/index.ts +16 -0
  39. package/src/lib/connectionGuides.ts +11 -15
  40. package/src/lib/downloadSelection.ts +34 -0
  41. package/src/lib/dragOut.ts +0 -0
  42. package/src/lib/searchHit.ts +129 -0
  43. package/src/lib/storageLine.ts +124 -0
  44. package/src/lib/webdavMount.ts +120 -0
  45. package/src/locales/en.ts +13 -0
  46. package/src/locales/tr.ts +13 -0
  47. package/src/styles/base.css +84 -7
  48. package/src/types/ExplorerConfig.ts +65 -1
  49. package/src/types/Plugins.ts +12 -0
  50. package/dist/index-BBToAjwL.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1127,11 +1127,11 @@ store: ComputedRef<ColumnStore<string>>;
1127
1127
  layout: ComputedRef<GenericTableLayout<string>>;
1128
1128
  pinLead: ComputedRef<boolean>;
1129
1129
  }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
1130
- page: (page: number) => any;
1131
1130
  sort: (payload: {
1132
1131
  key: string;
1133
1132
  dir: "asc" | "desc";
1134
1133
  }) => any;
1134
+ page: (page: number) => any;
1135
1135
  "row-click": (row: any, ev: MouseEvent) => any;
1136
1136
  "row-dblclick": (row: any, ev: MouseEvent) => any;
1137
1137
  "row-contextmenu": (row: any, ev: MouseEvent) => any;
@@ -1145,11 +1145,11 @@ dir: "asc" | "desc";
1145
1145
  "row-touchend": (ev: TouchEvent) => any;
1146
1146
  "row-touchmove": (ev: TouchEvent) => any;
1147
1147
  }, string, PublicProps, Readonly<__VLS_Props_45> & Readonly<{
1148
- onPage?: ((page: number) => any) | undefined;
1149
1148
  onSort?: ((payload: {
1150
1149
  key: string;
1151
1150
  dir: "asc" | "desc";
1152
1151
  }) => any) | undefined;
1152
+ onPage?: ((page: number) => any) | undefined;
1153
1153
  "onRow-click"?: ((row: any, ev: MouseEvent) => any) | undefined;
1154
1154
  "onRow-dblclick"?: ((row: any, ev: MouseEvent) => any) | undefined;
1155
1155
  "onRow-contextmenu"?: ((row: any, ev: MouseEvent) => any) | undefined;
@@ -1163,12 +1163,12 @@ dir: "asc" | "desc";
1163
1163
  "onRow-touchend"?: ((ev: TouchEvent) => any) | undefined;
1164
1164
  "onRow-touchmove"?: ((ev: TouchEvent) => any) | undefined;
1165
1165
  }>, {
1166
- page: number;
1166
+ total: number;
1167
1167
  sort: {
1168
1168
  key: string;
1169
1169
  dir: "asc" | "desc";
1170
1170
  } | null;
1171
- total: number;
1171
+ page: number;
1172
1172
  locale: LocaleCode;
1173
1173
  theme: ThemeMode;
1174
1174
  ariaLabel: string;
@@ -3249,6 +3249,30 @@ export declare function accentStyleOf(raw: string | undefined | null): Record<st
3249
3249
  */
3250
3250
  export declare function acceptableLocale(code: string | undefined | null): boolean;
3251
3251
 
3252
+ /** See `ExplorerConfig.accountSearch`. */
3253
+ export declare interface AccountSearchHook {
3254
+ /** The account THIS explorer is mounted for — heads its own group. */
3255
+ self: SearchAccount;
3256
+ /** Every OTHER account signed in right now. Read on each query, so an
3257
+ * account added or signed out while the explorer is mounted counts. */
3258
+ others: () => SearchAccount[] | Promise<SearchAccount[]>;
3259
+ /** `/api/files/search` on that account's server, with its credential. */
3260
+ search: (accountId: string, query: string, opts: {
3261
+ limit: number;
3262
+ scope: GlobalSearchScope;
3263
+ }) => Promise<GlobalSearchHit[]>;
3264
+ /**
3265
+ * Open another account's hit — the host switches to that account. The hit
3266
+ * arrives ADDRESSED (`name://rel`, as a listing row carries it): the host
3267
+ * never re-derives where a file is.
3268
+ */
3269
+ open: (accountId: string, item: SearchHitItem) => void | Promise<void>;
3270
+ /** Download another account's hit. Absent: its rows offer no Download. */
3271
+ download?: (accountId: string, item: SearchHitItem) => void | Promise<void>;
3272
+ /** Drag another account's hit out to the OS. Absent: its rows do not drag. */
3273
+ dragStart?: (accountId: string, items: SearchHitItem[]) => void | Promise<unknown>;
3274
+ }
3275
+
3252
3276
  /** The account zone `owner` last recorded (`null` = none recorded). Reactive. */
3253
3277
  export declare function accountTimeZoneOf(owner: symbol): string | null;
3254
3278
 
@@ -4620,6 +4644,48 @@ export declare function downloadArchive(api: Pick<FileApi, 'jsonFetch' | 'endpoi
4620
4644
  doc?: Document;
4621
4645
  }): Promise<ArchiveTicket>;
4622
4646
 
4647
+ /**
4648
+ * Dragging files OUT of filex — onto the desktop, into another app.
4649
+ *
4650
+ * There are exactly two ways a page can hand real files to the operating
4651
+ * system, and filex uses both because neither one alone covers the ask:
4652
+ *
4653
+ * 1. **`DownloadURL`** (any Chromium browser, so the web explorer AND the
4654
+ * desktop app get it for free). One `dataTransfer.setData('DownloadURL',
4655
+ * 'mime:name:url')` and the browser downloads that URL into wherever the
4656
+ * drop landed. Costs nothing until the drop happens — but Chromium carries
4657
+ * exactly ONE such entry, so it is a single-file gesture, and the URL is
4658
+ * fetched by the browser's own download stack, which sends cookies but no
4659
+ * Authorization header (see `canDownloadUrlDrag`).
4660
+ *
4661
+ * 2. **A native OS drag** (`webContents.startDrag`, desktop app only). Takes a
4662
+ * list of real paths, so folders and multi-selections drop as separate real
4663
+ * files — the WinRAR gesture. The catch is in the word *real*: the shell
4664
+ * copies the bytes at DROP time, from a path, so the file has to be on this
4665
+ * computer BEFORE the drag starts. There is no lazy/virtual-file API to
4666
+ * borrow (that is a Win32 `IDataObject` affair Chromium does not expose).
4667
+ *
4668
+ * ⚠ The native drag REPLACES the HTML5 drag — `startDrag` requires
4669
+ * `preventDefault()` on `dragstart`, and after that the app's own drop targets
4670
+ * see an OS file drag instead of `application/x-brf-files`. Dropping a row on a
4671
+ * folder inside filex would then UPLOAD the temp copy back to the server: a
4672
+ * round trip of the same bytes, a copy instead of a move, and the original left
4673
+ * behind. That is what `beginNativeDrag` is for — the payload is remembered on
4674
+ * this side, and every drop target asks `internalDragItems(ev)` rather than
4675
+ * reading the dataTransfer directly. An OS drag we started is still an internal
4676
+ * drag when it lands inside our own window.
4677
+ *
4678
+ * Because the bytes must exist first, the shell is asked to prepare them on
4679
+ * `mousedown` — before the gesture becomes a drag — and the native path is only
4680
+ * taken when it answered "ready". Anything else keeps the ordinary HTML5 drag,
4681
+ * so an internal move never waits on a download it does not need.
4682
+ */
4683
+ declare interface DragItem {
4684
+ path: string;
4685
+ basename: string;
4686
+ type: 'file' | 'dir';
4687
+ }
4688
+
4623
4689
  declare interface DriveFilters {
4624
4690
  type: TypeFilter;
4625
4691
  modified: ModifiedFilter;
@@ -5565,7 +5631,9 @@ export declare interface ExplorerConfig {
5565
5631
  /**
5566
5632
  * gorunum:v3-shell — bytes this storage holds, when the host knows. Drawn
5567
5633
  * as the caption on the Home view's storage card; absent means the card
5568
- * names the kind of thing instead.
5634
+ * names the kind of thing instead. For a person without a quota the
5635
+ * storage line under the navigation sums these (lib/storageLine), and a
5636
+ * storage left without one is measured by the explorer itself.
5569
5637
  *
5570
5638
  * ⚠ It must be the SAME quantity for every caller who gets it (in our own
5571
5639
  * app: `/api/admin/storages` for an operator, the RBAC-filtered
@@ -5677,6 +5745,21 @@ export declare interface ExplorerConfig {
5677
5745
  * ONE subscriber (the mounted explorer) and overwrites it on remount. */
5678
5746
  onChange?: (cb: () => void) => void;
5679
5747
  };
5748
+ /**
5749
+ * #47 — the host holds several accounts at once (the desktop app's rail),
5750
+ * and ⌘K's "Everywhere" group should search all of them.
5751
+ *
5752
+ * The explorer never talks to another account's server itself: it has no
5753
+ * credential for one, and it must not be handed any. Every call that reaches
5754
+ * another account goes through this hook, and the host answers it with the
5755
+ * credential it already keeps for that account. Hits come back tagged with
5756
+ * the account they belong to (`GlobalSearchHit.account`) and the palette
5757
+ * draws one group per account under a badge, this mount's own first.
5758
+ *
5759
+ * Absent — the web admin, every embed, a desktop with one account — and the
5760
+ * palette is exactly what it was: this account's hits, no badges.
5761
+ */
5762
+ accountSearch?: AccountSearchHook;
5680
5763
  }
5681
5764
 
5682
5765
  /** Component emits — the parent listens for these events. */
@@ -6213,6 +6296,15 @@ export declare interface GlobalSearchHit {
6213
6296
  snippet?: string;
6214
6297
  /** Where the hit matched: name | content | both. */
6215
6298
  matched?: 'name' | 'content' | 'both';
6299
+ /** Drive NAME the hit lives on (the server fills it; older ones did not). */
6300
+ storage?: string;
6301
+ /**
6302
+ * #47 — which signed-in account the hit came from. Never on the wire: the
6303
+ * explorer stamps it when the host searches several accounts
6304
+ * (`ExplorerConfig.accountSearch`). Absent = this mount's own account, with
6305
+ * no other account in play.
6306
+ */
6307
+ account?: SearchAccount;
6216
6308
  [k: string]: unknown;
6217
6309
  }
6218
6310
 
@@ -6242,6 +6334,13 @@ declare interface Group {
6242
6334
 
6243
6335
  export declare function groupByDate<T>(items: readonly T[], opts: DateGroupOptions<T>): DateGrouping<T>;
6244
6336
 
6337
+ /**
6338
+ * Hits → one group per account, in the order accounts first appear (the
6339
+ * explorer lists its own account first), each capped at `limit` on its own —
6340
+ * a busy account must not push a quieter one off the list.
6341
+ */
6342
+ export declare function groupHitsByAccount(hits: GlobalSearchHit[], limit: number): HitGroup[];
6343
+
6245
6344
  /**
6246
6345
  * Is a date heading honest over THIS listing?
6247
6346
  *
@@ -6360,6 +6459,9 @@ export declare function guideProtocols(): string[];
6360
6459
  /** Is there anything in this value at all? `false` and `0` count as answers. */
6361
6460
  export declare function hasAnswer(v: unknown): boolean;
6362
6461
 
6462
+ /** The person has a ceiling: a positive quota the server did not call unlimited. */
6463
+ export declare function hasCeiling(p: PersonUsage | null | undefined): boolean;
6464
+
6363
6465
  /** Is this a language the interface can actually be set to? (Reactive.) */
6364
6466
  export declare function hasLocale(code: string | undefined | null): boolean;
6365
6467
 
@@ -6381,6 +6483,48 @@ export declare function hasSteps(nodes: SurfaceNode[] | undefined): boolean;
6381
6483
  /** The keys a surface is currently NOT showing (across every form on it). */
6382
6484
  export declare function hiddenKeys(nodes: SurfaceNode[] | undefined, values: Record<string, unknown>): string[];
6383
6485
 
6486
+ /** What the explorer knows about drives when a hit does not say its own. */
6487
+ export declare interface HitDriveContext {
6488
+ /** Drive names the host configured (`config.storages`). */
6489
+ configured: string[];
6490
+ /** The drive the explorer has open right now. */
6491
+ current: string;
6492
+ }
6493
+
6494
+ /** One account's hits, in the server's order. `account` undefined = no rail. */
6495
+ export declare interface HitGroup {
6496
+ account?: SearchAccount;
6497
+ hits: GlobalSearchHit[];
6498
+ }
6499
+
6500
+ /**
6501
+ * The hit as a drag-out / download item (`name://rel`, its name, its kind) —
6502
+ * or null when there is nothing to address: no path, or no drive to put it on.
6503
+ * The same `{path, basename, type}` a listing row hands the drag-out hook.
6504
+ */
6505
+ export declare function hitItem(hit: GlobalSearchHit, ctx: HitDriveContext): DragItem | null;
6506
+
6507
+ /**
6508
+ * Which drive a hit lives on: the name the server sent > `storage_name`
6509
+ * (older servers) > the only configured drive > the drive that is open.
6510
+ * A wrong last-resort guess lands on the listing's "folder not found" state,
6511
+ * which is a graceful dead end — not a request against the wrong file.
6512
+ */
6513
+ export declare function hitStorageName(hit: GlobalSearchHit, ctx: HitDriveContext): string;
6514
+
6515
+ /**
6516
+ * Map one raw search hit onto the listing shape.
6517
+ *
6518
+ * ⚠ The drive comes from the HIT (`describeHits` puts it there), not from the
6519
+ * pane we happen to be standing in — a content search spans storages, so the
6520
+ * open drive is only the right answer by accident. `storageName` stays as the
6521
+ * fallback for a backend older than that field.
6522
+ *
6523
+ * (Moved here from FileExplorer's `advHitToNode` for #47, unchanged: the
6524
+ * palette's download and drag-out need the same row the advanced search draws.)
6525
+ */
6526
+ export declare function hitToNode(h: GlobalSearchHit, storageName: string): FileNode;
6527
+
6384
6528
  /** `https://fm.example.com` → `fm.example.com`; anything unparseable comes back whole. */
6385
6529
  export declare function hostOf(origin: string): string;
6386
6530
 
@@ -6517,6 +6661,23 @@ export declare function isPagePlacement(placement: string | undefined | null): b
6517
6661
  /** Is this box on the page yet? Absent `placed` means yes. */
6518
6662
  export declare function isPlaced(f: PdfField): boolean;
6519
6663
 
6664
+ /**
6665
+ * webdavMount — the forms of a filex WebDAV address, and the operating
6666
+ * systems' own commands that attach one as a drive.
6667
+ *
6668
+ * Two readers, one source:
6669
+ * - the connection guide (`connectionGuides.ts`) PRINTS these for a person to
6670
+ * copy;
6671
+ * - the desktop app's "Mount as a drive" (`desktop/src/drive.ts`) RUNS them.
6672
+ * Written twice, the command the guide teaches and the one the button runs
6673
+ * would drift apart, and the person who copied the guide's version would hit
6674
+ * a failure the button never shows — or the other way round.
6675
+ *
6676
+ * ⚠ No imports, and none may be added. The desktop main process and its
6677
+ * `node --test` runner import this file by relative path (the way
6678
+ * `web/src/lib/notificationTarget.ts` is imported), and plain node does not
6679
+ * resolve an extensionless specifier.
6680
+ */
6520
6681
  /** True when the deployment is not on TLS — several clients refuse that,
6521
6682
  * and Windows refuses it silently, which is worse. */
6522
6683
  export declare function isPlainHttp(origin: string): boolean;
@@ -7030,6 +7191,14 @@ export declare function markTourSeen(): void;
7030
7191
  /** True when the hit matched (at least partly) inside file CONTENT. */
7031
7192
  export declare function matchedInContent(matched: unknown): boolean;
7032
7193
 
7194
+ /** One row of `GET /api/files/quota/storages` (handlers.StorageUsageRow). */
7195
+ export declare interface MeasuredDrive {
7196
+ name: string;
7197
+ used_bytes: number;
7198
+ file_count?: number;
7199
+ coverage?: CatalogCoverage | null;
7200
+ }
7201
+
7033
7202
  /**
7034
7203
  * A backing that lives in this component's memory only — for a table on a
7035
7204
  * surface with no account behind it (a public page), and for tests.
@@ -7083,6 +7252,13 @@ export declare interface NavApp {
7083
7252
  icon?: string;
7084
7253
  }
7085
7254
 
7255
+ /**
7256
+ * Whether the line has to ask the server for drive sizes: there is no
7257
+ * ceiling, and the host left at least one of the panel's drives unsized (the
7258
+ * desktop app hands over names only) — or listed none at all.
7259
+ */
7260
+ export declare function needsMeasuredDrives(p: PersonUsage | null | undefined, panel: readonly PanelDrive[]): boolean;
7261
+
7086
7262
  /** The request never got an answer (offline, DNS, CORS, a dropped socket). */
7087
7263
  export declare function networkFailure(locale: string | undefined, cause?: unknown): RequestFailure;
7088
7264
 
@@ -7528,6 +7704,13 @@ export declare function pageRoot(base: string | undefined, token: string): Publi
7528
7704
 
7529
7705
  declare type PaneId = 'main' | 'split';
7530
7706
 
7707
+ /** One drive as the navigation panel holds it (`ExplorerConfig.storages`). */
7708
+ export declare interface PanelDrive {
7709
+ name: string;
7710
+ usedBytes?: number;
7711
+ usedPartial?: boolean;
7712
+ }
7713
+
7531
7714
  /**
7532
7715
  * The wire path one level up, or null when there is nowhere further up.
7533
7716
  *
@@ -7877,6 +8060,13 @@ export declare interface PersonLike {
7877
8060
 
7878
8061
  export declare function personName(p: PersonLike | null | undefined): string;
7879
8062
 
8063
+ /** The fields of `GET /api/files/quota/me` (quota.Snapshot) the line reads. */
8064
+ export declare interface PersonUsage {
8065
+ used_bytes: number;
8066
+ quota_bytes: number;
8067
+ unlimited?: boolean;
8068
+ }
8069
+
7880
8070
  export declare type PinFailure = '' | 'wrong' | 'locked';
7881
8071
 
7882
8072
  export declare interface PinInputNodeProps {
@@ -8257,6 +8447,13 @@ export declare interface PluginSurfaceHost {
8257
8447
  view: string;
8258
8448
  /** Adapter-qualified path the view was opened on — echoed on every event. */
8259
8449
  path?: () => string | undefined;
8450
+ /**
8451
+ * Every row the view was opened on (a selection) — echoed on every event
8452
+ * as `paths`, beside `path`. Absent or empty for a frame opened on one
8453
+ * row or on none (a deep link, a home page, the inspector, a public page),
8454
+ * which then sends `path` alone, exactly as before.
8455
+ */
8456
+ paths?: () => readonly string[] | undefined;
8260
8457
  locale: () => string;
8261
8458
  /** The words for an answer without a surface. */
8262
8459
  errorText: () => string;
@@ -8308,6 +8505,18 @@ export declare interface PluginUsersResponse {
8308
8505
  export declare interface PluginViewEventBody {
8309
8506
  /** Adapter-qualified wire path of the row the view was opened on. */
8310
8507
  path?: string;
8508
+ /**
8509
+ * Every row the view was opened on, adapter-qualified, in selection order.
8510
+ *
8511
+ * ⚠⚠ Sent on EVERY event of a screen opened on a selection, not only the
8512
+ * first: the server builds the event's inputs from it (and falls back to
8513
+ * `path` only when it is absent), so a conversation that echoed `path`
8514
+ * alone shrank to the first file after the opening screen — the second
8515
+ * screen said "a.txt" where the first said "3 files", and the job its
8516
+ * submit queued ran on one file (#64). The server re-checks each path for
8517
+ * the person asking; this is a report of the selection, not a grant.
8518
+ */
8519
+ paths?: string[];
8311
8520
  storage_id?: number;
8312
8521
  state?: Record<string, unknown>;
8313
8522
  event: 'open' | 'change' | 'submit' | 'action';
@@ -8497,14 +8706,14 @@ export declare function prefsSettled(): boolean;
8497
8706
  export declare function preloadEditor(): void;
8498
8707
 
8499
8708
  export declare const PreviewModal: DefineComponent<__VLS_Props_2, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
8500
- starred: (value: boolean) => any;
8501
8709
  close: () => any;
8502
8710
  nav: (delta: number) => any;
8711
+ starred: (value: boolean) => any;
8503
8712
  share: () => any;
8504
8713
  }, string, PublicProps, Readonly<__VLS_Props_2> & Readonly<{
8505
- onStarred?: ((value: boolean) => any) | undefined;
8506
8714
  onClose?: (() => any) | undefined;
8507
8715
  onNav?: ((delta: number) => any) | undefined;
8716
+ onStarred?: ((value: boolean) => any) | undefined;
8508
8717
  onShare?: (() => any) | undefined;
8509
8718
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {
8510
8719
  viewerEl: HTMLDivElement;
@@ -9010,15 +9219,15 @@ declare interface PublicUploadOptions {
9010
9219
  }
9011
9220
 
9012
9221
  export declare const QuickLook: DefineComponent<__VLS_Props_30, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
9013
- starred: (value: boolean) => any;
9014
9222
  close: () => any;
9015
9223
  nav: (delta: number) => any;
9224
+ starred: (value: boolean) => any;
9016
9225
  share: () => any;
9017
9226
  "open-full": () => any;
9018
9227
  }, string, PublicProps, Readonly<__VLS_Props_30> & Readonly<{
9019
- onStarred?: ((value: boolean) => any) | undefined;
9020
9228
  onClose?: (() => any) | undefined;
9021
9229
  onNav?: ((delta: number) => any) | undefined;
9230
+ onStarred?: ((value: boolean) => any) | undefined;
9022
9231
  onShare?: (() => any) | undefined;
9023
9232
  "onOpen-full"?: (() => any) | undefined;
9024
9233
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
@@ -9539,6 +9748,26 @@ export declare function sayFailure(err: unknown, fallback: string, opts?: {
9539
9748
  /** This document is a public link: the answer is no, and it is not remembered. */
9540
9749
  export declare function sealSessionless(): void;
9541
9750
 
9751
+ /** One signed-in account, as the palette's group badge draws it. */
9752
+ export declare interface SearchAccount {
9753
+ /** The host's own id for the account; passed back on every hook call. */
9754
+ id: string;
9755
+ /** Short name on the badge — the server's brand name or its host. */
9756
+ label: string;
9757
+ /** Second line, quieter — typically the email signed in there. */
9758
+ detail?: string;
9759
+ /** The account's colour on the host (the rail avatar's), for the badge dot. */
9760
+ color?: string;
9761
+ }
9762
+
9763
+ /** A search hit, addressed — the `{path, basename, type}` a listing row hands
9764
+ * the drag-out hook, with `path` = `name://rel`. */
9765
+ export declare interface SearchHitItem {
9766
+ path: string;
9767
+ basename: string;
9768
+ type: 'file' | 'dir';
9769
+ }
9770
+
9542
9771
  /** Matched-in values the search contract allows on a hit. */
9543
9772
  export declare type SearchMatched = 'name' | 'content' | 'both';
9544
9773
 
@@ -10250,6 +10479,20 @@ export declare interface StorageInfo {
10250
10479
  coverage?: CatalogCoverage | null;
10251
10480
  }
10252
10481
 
10482
+ /** What the line says. */
10483
+ export declare interface StorageLine {
10484
+ /** The bytes it reports. */
10485
+ used: number;
10486
+ /** The person's ceiling; 0 when there is none. */
10487
+ total: number;
10488
+ /** No ceiling — `used` is the drives' size, not the person's uploads. */
10489
+ unlimited: boolean;
10490
+ /** `used` is a lower bound. */
10491
+ partial: boolean;
10492
+ }
10493
+
10494
+ export declare function storageLine(p: PersonUsage | null | undefined, panel: readonly PanelDrive[], measured: readonly MeasuredDrive[] | null | undefined): StorageLine | null;
10495
+
10253
10496
  /** A configured storage, as `GET /api/admin/storages` returns it. */
10254
10497
  export declare interface StorageRow {
10255
10498
  id: number;
@@ -10917,28 +11160,6 @@ export declare function tourSeen(): boolean;
10917
11160
  /** Turkish UI strings. */
10918
11161
  export declare const tr: Record<string, string>;
10919
11162
 
10920
- /**
10921
- * connectionGuides — "how do I connect to this thing?", generated from the
10922
- * live deployment instead of written as prose.
10923
- *
10924
- * A published document says `https://fm.example.com/dav/` and leaves the
10925
- * reader to substitute three values, one of which (their own username) they
10926
- * usually get wrong. What ships here is the real host, the real storage
10927
- * name and the caller's own credential, with a copy button — which is the
10928
- * difference between a doc and a working paste. No surveyed product
10929
- * (Backblaze, R2, Storj, MinIO, Garage) does this; it is the cheapest win
10930
- * on the whole surface.
10931
- *
10932
- * Shape of the thing: a protocol is a `GuideBuilder` registered in
10933
- * `GUIDE_BUILDERS`. WebDAV is built here because WebDAV is what filex
10934
- * serves today; S3 and SFTP are a builder each and a registry line when
10935
- * their servers land — no second implementation, no second UI.
10936
- *
10937
- * The commands are not invented. They are the ones verified on 2026-08-14
10938
- * and written down in `docs/WEBDAV.md` and §13.5 of the write-path
10939
- * handover, including the three Windows registry limits that otherwise
10940
- * look exactly like filex bugs.
10941
- */
10942
11163
  export declare type Translate = (key: string, vars?: Record<string, string | number>) => string;
10943
11164
 
10944
11165
  /**
@@ -11256,6 +11477,7 @@ export declare function useFileApi(config: ExplorerConfig): {
11256
11477
  scope?: GlobalSearchScope;
11257
11478
  }) => Promise<GlobalSearchHit[]>;
11258
11479
  quotaMe: () => Promise<QuotaSnapshot | null>;
11480
+ storageUsage: () => Promise<MeasuredDrive[] | null>;
11259
11481
  subfolders: (path: string) => Promise<{
11260
11482
  folders: FileNode[];
11261
11483
  }>;