@brftech/filex-core 0.1.56

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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/dist/ArchiveViewer-CJdaw5x3.js +99 -0
  4. package/dist/ArchiveViewer-CJdaw5x3.js.map +1 -0
  5. package/dist/CsvViewer-QYx_tePQ.js +132 -0
  6. package/dist/CsvViewer-QYx_tePQ.js.map +1 -0
  7. package/dist/DrawioViewer-GWt0TyB7.js +141 -0
  8. package/dist/DrawioViewer-GWt0TyB7.js.map +1 -0
  9. package/dist/EpubViewer-Je0ywklQ.js +146 -0
  10. package/dist/EpubViewer-Je0ywklQ.js.map +1 -0
  11. package/dist/IpynbViewer-TsB4gqP-.js +175 -0
  12. package/dist/IpynbViewer-TsB4gqP-.js.map +1 -0
  13. package/dist/MermaidViewer-CXfeDS-7.js +128 -0
  14. package/dist/MermaidViewer-CXfeDS-7.js.map +1 -0
  15. package/dist/PsdViewer-VtPpxKVe.js +113 -0
  16. package/dist/PsdViewer-VtPpxKVe.js.map +1 -0
  17. package/dist/TiffViewer-OINn9bbb.js +133 -0
  18. package/dist/TiffViewer-OINn9bbb.js.map +1 -0
  19. package/dist/UTIF-Cjsrlm0l.js +3104 -0
  20. package/dist/UTIF-Cjsrlm0l.js.map +1 -0
  21. package/dist/Viewer3D-xvvyiWHd.js +61 -0
  22. package/dist/Viewer3D-xvvyiWHd.js.map +1 -0
  23. package/dist/_commonjsHelpers-DaMA6jEr.js +9 -0
  24. package/dist/_commonjsHelpers-DaMA6jEr.js.map +1 -0
  25. package/dist/filex-core.js +26 -0
  26. package/dist/filex-core.js.map +1 -0
  27. package/dist/filex-core.umd.cjs +285 -0
  28. package/dist/filex-core.umd.cjs.map +1 -0
  29. package/dist/index-CmSYzt6L.js +5404 -0
  30. package/dist/index-CmSYzt6L.js.map +1 -0
  31. package/dist/index-UFULWo35.js +10736 -0
  32. package/dist/index-UFULWo35.js.map +1 -0
  33. package/dist/index.d.ts +1089 -0
  34. package/dist/katex-yuB6V-q6.js +11616 -0
  35. package/dist/katex-yuB6V-q6.js.map +1 -0
  36. package/dist/papaparse.min-VB1HBwYX.js +441 -0
  37. package/dist/papaparse.min-VB1HBwYX.js.map +1 -0
  38. package/dist/style.css +1 -0
  39. package/dist/useViewerFetch-czqbd2Lj.js +25 -0
  40. package/dist/useViewerFetch-czqbd2Lj.js.map +1 -0
  41. package/package.json +113 -0
  42. package/src/FileExplorer.vue +1872 -0
  43. package/src/components/Breadcrumb.vue +282 -0
  44. package/src/components/ContextMenu.vue +152 -0
  45. package/src/components/GridView.vue +166 -0
  46. package/src/components/ListView.vue +212 -0
  47. package/src/components/PendingOpsTray.vue +91 -0
  48. package/src/components/RecentlyOpened.vue +155 -0
  49. package/src/components/StarButton.vue +101 -0
  50. package/src/components/TagPicker.vue +184 -0
  51. package/src/components/Toolbar.vue +220 -0
  52. package/src/components/UploadProgress.vue +78 -0
  53. package/src/composables/useFileApi.ts +692 -0
  54. package/src/composables/useKeyboardShortcuts.ts +144 -0
  55. package/src/composables/useLocale.ts +60 -0
  56. package/src/composables/useMonacoLoader.ts +98 -0
  57. package/src/composables/usePendingOps.ts +200 -0
  58. package/src/composables/useSelection.ts +81 -0
  59. package/src/composables/useUploadChunked.ts +250 -0
  60. package/src/composables/useViewerFetch.ts +58 -0
  61. package/src/index.ts +80 -0
  62. package/src/locales/en.ts +122 -0
  63. package/src/locales/index.ts +12 -0
  64. package/src/locales/tr.ts +122 -0
  65. package/src/modals/ConvertModal.vue +254 -0
  66. package/src/modals/DeleteConfirmModal.vue +32 -0
  67. package/src/modals/Modal.vue +104 -0
  68. package/src/modals/NewFolderModal.vue +64 -0
  69. package/src/modals/PermissionsModal.vue +815 -0
  70. package/src/modals/PreviewModal.vue +1070 -0
  71. package/src/modals/RenameModal.vue +58 -0
  72. package/src/modals/ShareModal.vue +135 -0
  73. package/src/styles/base.css +1224 -0
  74. package/src/styles/variables.css +90 -0
  75. package/src/types/ExplorerConfig.ts +282 -0
  76. package/src/types/FileNode.ts +136 -0
  77. package/src/types/index.ts +27 -0
  78. package/src/types/peers.d.ts +45 -0
  79. package/src/viewers/ArchiveViewer.vue +186 -0
  80. package/src/viewers/CsvViewer.vue +319 -0
  81. package/src/viewers/DrawioViewer.vue +243 -0
  82. package/src/viewers/EpubViewer.vue +307 -0
  83. package/src/viewers/IpynbViewer.vue +365 -0
  84. package/src/viewers/MermaidViewer.vue +259 -0
  85. package/src/viewers/PdfViewer.vue +562 -0
  86. package/src/viewers/PsdViewer.vue +264 -0
  87. package/src/viewers/TiffViewer.vue +273 -0
  88. package/src/viewers/Viewer3D.vue +120 -0
@@ -0,0 +1,90 @@
1
+ /**
2
+ * CSS variables — theme hooks.
3
+ *
4
+ * Consumer overrides by setting `--fe-*` on a higher scope.
5
+ */
6
+ :root {
7
+ --fe-bg: #ffffff;
8
+ --fe-bg-elev: #f7f8fa;
9
+ --fe-bg-hover: #edf0f5;
10
+ --fe-bg-selected: #dfe8ff;
11
+ --fe-border: #e2e6ed;
12
+ --fe-border-strong: #c7ced9;
13
+ --fe-text: #1a1e27;
14
+ --fe-text-muted: #5a6475;
15
+ --fe-text-on-primary: #ffffff;
16
+ --fe-primary: #3b82f6;
17
+ --fe-primary-hover: #2563eb;
18
+ --fe-danger: #dc2626;
19
+ --fe-danger-hover: #b91c1c;
20
+ --fe-shadow: 0 10px 32px rgba(15, 23, 42, 0.14);
21
+ --fe-shadow-sm: 0 2px 6px rgba(15, 23, 42, 0.08);
22
+ --fe-radius: 8px;
23
+ --fe-radius-sm: 4px;
24
+ --fe-radius-lg: 12px;
25
+ --fe-font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
26
+ --fe-font-mono: ui-monospace, "SF Mono", Consolas, Menlo, monospace;
27
+ --fe-gap: 12px;
28
+ }
29
+
30
+ .fe--theme-dark,
31
+ :root[data-theme='dark'] .fe,
32
+ .fe.fe--theme-dark,
33
+ /* Tailwind dark-mode class shipped by the host admin shell —
34
+ * web/src/lib/theme.ts toggles document.documentElement.classList
35
+ * .toggle('dark', dark), so we adopt the same hook here. Without
36
+ * this selector the embedded explorer stayed on the :root light
37
+ * defaults even when the rest of the admin UI flipped dark.
38
+ *
39
+ * The bare `:root.dark` / `.dark` selectors (no `.fe` descendant)
40
+ * also publish the variables at the html-level so non-SFC consumers —
41
+ * the standalone /files/edit Editor.vue route, which doesn't wrap its
42
+ * host div in `.fe` — pick up the dark palette via CSS-variable
43
+ * cascade. v0.1.11 added the bare selectors after operators reported
44
+ * the new tab opening light when the admin panel was dark. */
45
+ :root.dark,
46
+ .dark,
47
+ :root.dark .fe,
48
+ .dark .fe,
49
+ /* Teleported context menu lives outside the `.fe` parent, so we have
50
+ * to apply the same dark-mode variable overrides on its backdrop too —
51
+ * otherwise it stays on the :root light defaults and the menu renders
52
+ * as white-on-white inside dark hosts. */
53
+ .fe-ctx-backdrop--theme-dark,
54
+ .fe-ctx-backdrop--theme-auto[data-prefers-dark='1'] {
55
+ --fe-bg: #0f1419;
56
+ --fe-bg-elev: #161c25;
57
+ --fe-bg-hover: #1f2733;
58
+ --fe-bg-selected: #23324a;
59
+ --fe-border: #2a323e;
60
+ --fe-border-strong: #3a4453;
61
+ --fe-text: #e5e9f0;
62
+ --fe-text-muted: #8b95a7;
63
+ --fe-primary: #60a5fa;
64
+ --fe-primary-hover: #3b82f6;
65
+ --fe-danger: #f87171;
66
+ --fe-danger-hover: #ef4444;
67
+ --fe-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
68
+ --fe-shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.25);
69
+ }
70
+
71
+ @media (prefers-color-scheme: dark) {
72
+ .fe:not(.fe--theme-light),
73
+ /* Same trick for the teleported backdrop in auto mode. */
74
+ .fe-ctx-backdrop--theme-auto:not(.fe-ctx-backdrop--theme-light) {
75
+ --fe-bg: #0f1419;
76
+ --fe-bg-elev: #161c25;
77
+ --fe-bg-hover: #1f2733;
78
+ --fe-bg-selected: #23324a;
79
+ --fe-border: #2a323e;
80
+ --fe-border-strong: #3a4453;
81
+ --fe-text: #e5e9f0;
82
+ --fe-text-muted: #8b95a7;
83
+ --fe-primary: #60a5fa;
84
+ --fe-primary-hover: #3b82f6;
85
+ --fe-danger: #f87171;
86
+ --fe-danger-hover: #ef4444;
87
+ --fe-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
88
+ --fe-shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.25);
89
+ }
90
+ }
@@ -0,0 +1,282 @@
1
+ /**
2
+ * ExplorerConfig — props passed to the FileExplorer component.
3
+ *
4
+ * Two equivalent ways to wire it up:
5
+ *
6
+ * 1. New clean API (preferred — RESTful, server-agnostic):
7
+ * { apiBase: 'https://files.example.com', auth: { kind: 'bearer', token } }
8
+ * → URLs like `${apiBase}/api/files/manager`, `${apiBase}/api/files/upload/init`.
9
+ *
10
+ * 2. Legacy API (Vuefinder-compat — for embedders that mounted the
11
+ * old `@brftech/file-explorer` package against their own routes):
12
+ * { endpoint: '/api/files/manager', uploadInit: '/api/files/upload/init', … }
13
+ * → caller fully controls every URL.
14
+ *
15
+ * If both `apiBase` AND any explicit `endpoint`/`uploadInit`/etc. are
16
+ * present, the explicit field wins (lets you override one route while
17
+ * keeping the auto-derived rest).
18
+ */
19
+
20
+ /**
21
+ * Auth strategy. Discriminated union so request building is type-safe.
22
+ *
23
+ * - `bearer` — `Authorization: Bearer <token>`. Token may be a string
24
+ * OR a sync/async function (auto-refresh).
25
+ * - `csrf` — `X-CSRF-TOKEN` + `credentials: include` (Laravel/Filament).
26
+ * - `basic` — `Authorization: Basic <base64(user:pass)>`.
27
+ * - `none` — no auth (development / public sandbox).
28
+ */
29
+ export type AuthConfig =
30
+ | { kind: 'bearer'; token: string | (() => string | Promise<string>) }
31
+ | { kind: 'csrf'; csrf: string }
32
+ | { kind: 'basic'; user: string; pass: string }
33
+ | { kind: 'none' }
34
+ /**
35
+ * Legacy `type` field (back-compat with @brftech/file-explorer 0.1.0).
36
+ * Internally normalized to the `kind`-tagged shape.
37
+ */
38
+ | { type: 'bearer'; token: string }
39
+ | { type: 'csrf'; csrf: string };
40
+
41
+ export type ThemeMode = 'light' | 'dark' | 'auto';
42
+ export type LocaleCode = 'tr' | 'en';
43
+
44
+ /**
45
+ * Resolved endpoint map. `useFileApi` derives this once on construction
46
+ * — components never need to think about config/apiBase precedence.
47
+ */
48
+ export interface EndpointMap {
49
+ manager: string;
50
+ uploadInit: string | null;
51
+ uploadFinalize: string | null;
52
+ uploadAbort: string | null;
53
+ shareCreate: string | null;
54
+ shareList: string | null;
55
+ shareDelete: string | null;
56
+ limits: string | null;
57
+ capabilities: string | null;
58
+ archiveList: string | null;
59
+ archiveExtract: string | null;
60
+ archiveAdd: string | null;
61
+ copy: string | null;
62
+ moveAsync: string | null;
63
+ deleteAsync: string | null;
64
+ opsList: string | null;
65
+ opsShow: string | null;
66
+ onlyOfficeConfig: string | null;
67
+ saveText: string | null;
68
+ restore: string | null;
69
+ trashList: string | null;
70
+ trashRestore: string | null;
71
+ }
72
+
73
+ export interface ExplorerConfig {
74
+ /**
75
+ * Modern shorthand: URL prefix for the standard /api/files/* layout.
76
+ * Example: `https://files.example.com` → `${apiBase}/api/files/manager`,
77
+ * `${apiBase}/api/files/upload/init`, etc. Any explicit endpoint*
78
+ * field below overrides the derived URL.
79
+ */
80
+ apiBase?: string;
81
+
82
+ /** Legacy main endpoint (Vuefinder-compat: GET/POST `?q=…`). */
83
+ endpoint?: string;
84
+
85
+ // ——— Per-route overrides (optional; auto-derived from apiBase if absent) ———
86
+ uploadInit?: string;
87
+ uploadFinalize?: string;
88
+ uploadAbort?: string;
89
+
90
+ shareCreate?: string;
91
+ shareList?: string;
92
+ /** DELETE template; `{uuid}` placeholder is replaced at call time. */
93
+ shareDelete?: string;
94
+
95
+ limits?: string;
96
+ capabilities?: string;
97
+
98
+ archiveList?: string;
99
+ archiveExtract?: string;
100
+ archiveAdd?: string;
101
+
102
+ /** Recursive S3-side copy with "-copy" collision suffix (async). */
103
+ copy?: string;
104
+
105
+ /** Async move endpoint — returns {op}, client polls /opsList. */
106
+ moveAsync?: string;
107
+
108
+ /** Async delete endpoint — returns {op}, client polls /opsList. */
109
+ deleteAsync?: string;
110
+
111
+ /** Pending ops list endpoint (poll target). */
112
+ opsList?: string;
113
+
114
+ /** Single op show endpoint — `{id}` placeholder. */
115
+ opsShow?: string;
116
+
117
+ /**
118
+ * OnlyOffice config endpoint. Backend POST returns
119
+ * `{ config, documentServerUrl }` where `config` is a JWT-signed
120
+ * DocEditor config. PreviewModal mounts the editor against this
121
+ * when the user opens an office file with mode=edit.
122
+ */
123
+ onlyOfficeConfig?: string;
124
+
125
+ /**
126
+ * Standalone editor page base — when set, "Aç" on an office file
127
+ * opens `${openPageBase}?path=...&mode=edit` in a new tab instead
128
+ * of the modal preview.
129
+ */
130
+ openPageBase?: string;
131
+
132
+ /**
133
+ * Plain-text save endpoint — POST `{path, content}`. When set, code
134
+ * preview gains an editable mode + save button. Falsy = read-only.
135
+ */
136
+ saveText?: string;
137
+
138
+ /**
139
+ * Trash restore endpoint — `POST {source: string[]}`. When set, a
140
+ * "Geri Getir" action shows up in `.trash/` listings.
141
+ */
142
+ restore?: string;
143
+
144
+ /** filex trash listing endpoint — `GET → { entries: TrashEntry[] }`. */
145
+ trashList?: string;
146
+ /** filex trash restore endpoint — `POST { node_id }`. */
147
+ trashRestore?: string;
148
+
149
+ /** Public share base URL — `${shareBase}/${uuid}` */
150
+ shareBase?: string;
151
+
152
+ /** Auth strategy (see AuthConfig). */
153
+ auth?: AuthConfig;
154
+
155
+ /** Show the virtual `.trash/` entry in the root listing. */
156
+ trashVisible?: boolean;
157
+
158
+ /** UI dil kodu */
159
+ locale?: LocaleCode;
160
+
161
+ /** OnlyOffice iframe base (e.g. `https://docs.example.com`). */
162
+ onlyOfficeBase?: string;
163
+
164
+ /** Drawio iframe base. */
165
+ drawioBase?: string;
166
+
167
+ /** Universal converter (p2r3/convert fork) iframe base, e.g. `https://fm.example.com/convert`. */
168
+ convertBase?: string;
169
+
170
+ /**
171
+ * Drawio embed URL (full URL to the embed endpoint). Defaults to
172
+ * `https://embed.diagrams.net`. The DrawioViewer iframes this with
173
+ * `?embed=1&proto=json` postMessage handshake to load + save XML.
174
+ */
175
+ drawioUrl?: string;
176
+
177
+ /**
178
+ * Optional URL where serialized PDF annotations / form data is
179
+ * persisted. POST `{ path, base64 }` — the rich PdfViewer uses
180
+ * `pdf.saveDocument()` and forwards the saved bytes here when the
181
+ * user clicks the save annotation button.
182
+ */
183
+ pdfSaveUrl?: string;
184
+
185
+ /**
186
+ * Override the pdf.js worker URL. Defaults to a CDN copy matching
187
+ * the version pdfjs-dist resolves to at runtime — hosts can pin
188
+ * their own self-hosted worker for CSP-strict environments.
189
+ */
190
+ pdfWorkerUrl?: string;
191
+
192
+ /**
193
+ * Standalone full-screen viewer route. The PreviewModal toolbar's
194
+ * "Open in new tab" button navigates to
195
+ * `${viewerBaseUrl}?path=…&storage=…&type=…`. The consumer wires
196
+ * that route to mount the same viewer fullscreen (admin UI / fishapp
197
+ * embed). Defaults to `/files/viewer`.
198
+ */
199
+ viewerBaseUrl?: string;
200
+
201
+ /** Upload chunk size (bytes). Default 5 MB. */
202
+ chunkSize?: number;
203
+
204
+ /** Parallel chunks. Default 4. */
205
+ parallelChunks?: number;
206
+
207
+ /** Theme. */
208
+ theme?: ThemeMode;
209
+
210
+ /** Initial path (storage-prefix included: `local://`). Default: root. */
211
+ initialPath?: string;
212
+
213
+ /**
214
+ * Confine the explorer to this folder (qualified: `main://projeler/acme`).
215
+ * The UI opens here, hides the multi-storage drives root, and blocks
216
+ * navigation above it. SECURITY IS NOT THIS — enforce it server-side with an
217
+ * X-Filex-Root header / root-scoped API token; this is the clean-embed UX.
218
+ */
219
+ rootPath?: string;
220
+
221
+ /** Whether the info panel toggle is visible. */
222
+ showInfoPanel?: boolean;
223
+
224
+ /** Default view. */
225
+ viewMode?: 'list' | 'grid';
226
+
227
+ /** Override max upload size (MB) — falls back to /limits otherwise. */
228
+ maxFileSizeMb?: number;
229
+
230
+ /** Accept patterns (MIME or extension). Empty = unrestricted. */
231
+ acceptTypes?: string[];
232
+
233
+ /** Storage adapter to default to (avoids the initial flash). */
234
+ defaultAdapter?: string;
235
+
236
+ /**
237
+ * Where to persist the current path so reload lands the user back
238
+ * in the same folder.
239
+ * 'hash' — URL hash. Default — works on plain web pages.
240
+ * 'localStorage' — `brf-file-explorer:path` key. Best for SPAs that
241
+ * already own the URL (Ionic / Vue Router / Next).
242
+ * 'none' — don't persist. Embedder controls path externally.
243
+ */
244
+ pathPersist?: 'hash' | 'localStorage' | 'none';
245
+
246
+ /**
247
+ * Multi-storage root mode. When true, the explorer's "/" virtual
248
+ * folder lists every entry in `storages` as a clickable directory.
249
+ * Clicking one drills into that storage's root; the breadcrumb
250
+ * walks `/ › <storage> › <sub> › …`.
251
+ *
252
+ * When false (default) the SFC still works against a single
253
+ * storage — `defaultAdapter` / `initialPath` decide which one.
254
+ *
255
+ * Pair with `storages` so the SFC has labels + driver hints to
256
+ * render even before the first API call.
257
+ */
258
+ multiStorageRoot?: boolean;
259
+
260
+ /**
261
+ * Storage list for `multiStorageRoot` mode. Provide name + driver
262
+ * + (optional) display label / read-only flag. The SFC mirrors
263
+ * each entry as a virtual `dir` row at "/".
264
+ */
265
+ storages?: Array<{
266
+ name: string;
267
+ label?: string;
268
+ driver?: string;
269
+ readOnly?: boolean;
270
+ }>;
271
+ }
272
+
273
+ /** Component emits — the parent listens for these events. */
274
+ export interface ExplorerEmits {
275
+ 'share-created': (payload: { path: string; url: string; pin: string | null }) => void;
276
+ 'file-opened': (file: { path: string; basename: string }) => void;
277
+ error: (err: { message: string; context?: unknown }) => void;
278
+ 'upload-progress': (p: { uploadId: string; percent: number; done: boolean }) => void;
279
+ 'selection-change': (
280
+ items: Array<{ path: string; basename: string; type: 'file' | 'dir' }>,
281
+ ) => void;
282
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * FileNode — node shape returned by the manager endpoint.
3
+ *
4
+ * Backend `?q=index` (or `GET /api/files/manager?action=index`) returns:
5
+ * { adapter, storages, dirname, files: FileNode[] }
6
+ */
7
+ export interface FileNode {
8
+ /** DB node ID — needed by the per-user meta routes (starred, tags,
9
+ * recently-opened). Backend's projectFileNodes() emits it for every
10
+ * row; only client-synthesized rows (e.g. multi-storage virtual
11
+ * folders) lack one. */
12
+ id?: number;
13
+ /** Full adapter-qualified path: `local://receipts/2024/invoice.pdf` */
14
+ path: string;
15
+ /** Relative basename: `invoice.pdf` */
16
+ basename: string;
17
+ /** Adapter-stripped relative path: `receipts/2024/invoice.pdf` */
18
+ relativePath?: string;
19
+ /** `file` or `dir` */
20
+ type: 'file' | 'dir';
21
+ /** Extension (lowercased, no dot). Empty string = no extension. */
22
+ extension?: string;
23
+ /** Bytes. 0 = directory. */
24
+ size?: number;
25
+ /** Unix ms (backend "last_modified"). */
26
+ last_modified?: number;
27
+ /** MIME. */
28
+ mime_type?: string;
29
+ /** Optional thumbnail URL (backend may inline). */
30
+ thumb_url?: string | null;
31
+ /** Visibility: private | public. */
32
+ visibility?: 'private' | 'public';
33
+ /** File count for directories. */
34
+ count?: number;
35
+ /** Client-side tag (localStorage or backend). */
36
+ starred?: boolean;
37
+ /** Hex color tag. */
38
+ color?: string | null;
39
+ /** Server-side trash marker. */
40
+ trashed?: boolean;
41
+ /** RBAC effective level for the current user on this entry (backend
42
+ * projectFileNodes emits it when a storage has RBAC on). '' / undefined =
43
+ * ACL not enforced. Used to gate edit/manage affordances client-side. */
44
+ perm?: 'none' | 'viewer' | 'editor' | 'owner';
45
+ /** Generic — any additional fields the backend wants to inline. */
46
+ [k: string]: unknown;
47
+ }
48
+
49
+ export interface ShareInfo {
50
+ uuid: string;
51
+ url: string;
52
+ password_pin?: string | null;
53
+ expires_at?: string | null;
54
+ max_downloads?: number | null;
55
+ downloads?: number;
56
+ created_at?: string;
57
+ }
58
+
59
+ export interface UploadLimits {
60
+ max_upload_mb: number;
61
+ }
62
+
63
+ export type ExternalServiceState = 'ok' | 'error' | 'disabled' | 'unknown';
64
+
65
+ export interface ExternalServiceStatus {
66
+ enabled: boolean;
67
+ state: ExternalServiceState;
68
+ url?: string;
69
+ last_check?: string;
70
+ detail?: string;
71
+ }
72
+
73
+ export interface Capabilities {
74
+ ffmpeg?: boolean;
75
+ ghostscript?: boolean;
76
+ libreoffice?: boolean;
77
+ onlyoffice_url?: string | null;
78
+ drawio_url?: string | null;
79
+ convert_url?: string | null;
80
+ max_chunk_mb?: number;
81
+ upload_limit_mb?: number;
82
+ external?: {
83
+ onlyoffice?: ExternalServiceStatus;
84
+ drawio?: ExternalServiceStatus;
85
+ mermaid?: ExternalServiceStatus;
86
+ };
87
+ }
88
+
89
+ /** Single source of truth for "is the IdP/editor/diagram service ready?".
90
+ * A capability is usable only when both flags say so — `enabled=true` but
91
+ * `state='error'` means an operator turned it on but a probe just failed,
92
+ * and we'd rather hide the entry than offer a button that 500s on click.
93
+ */
94
+ export function isExternalUsable(s: ExternalServiceStatus | undefined): boolean {
95
+ return !!s && s.enabled && s.state === 'ok';
96
+ }
97
+
98
+ export interface UploadInitResponse {
99
+ uploadId: string;
100
+ parts: Array<{ partNumber: number; presignedUrl: string }>;
101
+ expiresAt: string;
102
+ s3Key?: string;
103
+ }
104
+
105
+ export interface UploadFinalizeResponse {
106
+ s3Key: string;
107
+ url?: string;
108
+ }
109
+
110
+ export interface ArchiveEntry {
111
+ name: string;
112
+ size: number;
113
+ isDir: boolean;
114
+ lastModified?: number;
115
+ }
116
+
117
+ export type ViewMode = 'list' | 'grid';
118
+
119
+ export interface ClipboardState {
120
+ mode: 'cut' | 'copy' | null;
121
+ items: FileNode[];
122
+ sourcePath: string | null;
123
+ }
124
+
125
+ /** A soft-deleted node as returned by the filex trash listing endpoint. */
126
+ export interface TrashEntry {
127
+ id: number;
128
+ storage_id: number;
129
+ storage_name?: string;
130
+ path: string;
131
+ name: string;
132
+ size: number;
133
+ mime?: string;
134
+ deleted_at: string;
135
+ ttl_days?: number | null;
136
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @brftech/filex-core — public types.
3
+ *
4
+ * Types are split across two files for legacy reasons; this barrel
5
+ * re-exports the lot so consumers only ever need the package root.
6
+ */
7
+
8
+ export type {
9
+ ExplorerConfig,
10
+ ExplorerEmits,
11
+ AuthConfig,
12
+ ThemeMode,
13
+ LocaleCode,
14
+ EndpointMap,
15
+ } from './ExplorerConfig';
16
+
17
+ export type {
18
+ FileNode,
19
+ ShareInfo,
20
+ UploadLimits,
21
+ Capabilities,
22
+ UploadInitResponse,
23
+ UploadFinalizeResponse,
24
+ ArchiveEntry,
25
+ ViewMode,
26
+ ClipboardState,
27
+ } from './FileNode';
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Type shims for peer-style optional dependencies.
3
+ *
4
+ * These libraries are lazy-loaded via dynamic import and listed under
5
+ * `peerDependenciesMeta.optional` (and `optionalDependencies` for
6
+ * convenience). We don't want hard `@types/*` deps just to please the
7
+ * compiler, so we declare them as `any` here. The dynamic import call
8
+ * sites cast through `any` anyway.
9
+ *
10
+ * Keep in sync with packages/webcomponent/src/peers.d.ts and
11
+ * packages/react/src/peers.d.ts — the rolled-up `dist/index.d.ts`
12
+ * forwards these references and vue-tsc walks the type graph in the
13
+ * sibling packages, so the same shims must live there too.
14
+ */
15
+ declare module 'markdown-it';
16
+ declare module 'highlight.js';
17
+ declare module 'monaco-editor';
18
+ declare module '@google/model-viewer';
19
+ declare module 'epubjs';
20
+ declare module 'mermaid';
21
+ declare module 'utif';
22
+ declare module 'ag-psd';
23
+ declare module 'pdfjs-dist';
24
+ declare module 'pdfjs-dist/legacy/build/pdf';
25
+ declare module 'pdfjs-dist/build/pdf.worker.min';
26
+ declare module 'papaparse';
27
+ declare module 'katex';
28
+
29
+ /**
30
+ * Custom element registered by `@google/model-viewer` — keeps the
31
+ * compiler happy when the SFC template includes `<model-viewer>`.
32
+ */
33
+ declare namespace JSX {
34
+ interface IntrinsicElements {
35
+ 'model-viewer': {
36
+ src?: string;
37
+ alt?: string;
38
+ 'auto-rotate'?: boolean | string;
39
+ 'camera-controls'?: boolean | string;
40
+ 'touch-action'?: string;
41
+ 'shadow-intensity'?: string | number;
42
+ [key: string]: unknown;
43
+ };
44
+ }
45
+ }