@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,1224 @@
1
+ /* FileExplorer — unscoped stylesheet (lib consumers apply once). */
2
+
3
+ .fe {
4
+ position: relative;
5
+ display: flex;
6
+ flex-direction: column;
7
+ min-height: 420px;
8
+ height: 100%;
9
+ background: var(--fe-bg);
10
+ color: var(--fe-text);
11
+ font-family: var(--fe-font);
12
+ font-size: 14px;
13
+ border: 1px solid var(--fe-border);
14
+ border-radius: var(--fe-radius);
15
+ overflow: hidden;
16
+ outline: none;
17
+ }
18
+
19
+ .fe * {
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ .fe__body {
24
+ flex: 1 1 auto;
25
+ overflow: auto;
26
+ background: var(--fe-bg);
27
+ }
28
+
29
+ /* Initial-load spinner (shown until the first listing arrives). */
30
+ .fe__loading {
31
+ display: flex;
32
+ flex-direction: column;
33
+ align-items: center;
34
+ justify-content: center;
35
+ gap: 14px;
36
+ min-height: 240px;
37
+ height: 100%;
38
+ color: var(--fe-text-muted);
39
+ }
40
+ .fe__spinner {
41
+ width: 34px;
42
+ height: 34px;
43
+ border-radius: 50%;
44
+ border: 3px solid color-mix(in srgb, var(--fe-text-muted) 30%, transparent);
45
+ border-top-color: var(--fe-primary);
46
+ animation: fe-spin 0.7s linear infinite;
47
+ }
48
+ .fe__loading-text {
49
+ margin: 0;
50
+ font-size: 13px;
51
+ }
52
+ @keyframes fe-spin {
53
+ to { transform: rotate(360deg); }
54
+ }
55
+
56
+ .fe__file-input {
57
+ position: absolute;
58
+ left: -9999px;
59
+ width: 1px;
60
+ height: 1px;
61
+ opacity: 0;
62
+ }
63
+
64
+ /* ---------- Buttons ---------- */
65
+
66
+ .fe-btn {
67
+ display: inline-flex;
68
+ align-items: center;
69
+ gap: 6px;
70
+ padding: 6px 12px;
71
+ background: var(--fe-bg-elev);
72
+ border: 1px solid var(--fe-border);
73
+ border-radius: var(--fe-radius-sm);
74
+ color: var(--fe-text);
75
+ font: inherit;
76
+ cursor: pointer;
77
+ transition: background 0.12s, border-color 0.12s;
78
+ white-space: nowrap;
79
+ }
80
+ .fe-btn:hover:not(:disabled) {
81
+ background: var(--fe-bg-hover);
82
+ border-color: var(--fe-border-strong);
83
+ }
84
+ .fe-btn:disabled {
85
+ opacity: 0.5;
86
+ cursor: not-allowed;
87
+ }
88
+ .fe-btn--primary {
89
+ background: var(--fe-primary);
90
+ border-color: var(--fe-primary);
91
+ color: var(--fe-text-on-primary);
92
+ }
93
+ .fe-btn--primary:hover:not(:disabled) {
94
+ background: var(--fe-primary-hover);
95
+ border-color: var(--fe-primary-hover);
96
+ }
97
+ .fe-btn--danger {
98
+ background: var(--fe-danger);
99
+ border-color: var(--fe-danger);
100
+ color: var(--fe-text-on-primary);
101
+ }
102
+ .fe-btn--danger:hover:not(:disabled) {
103
+ background: var(--fe-danger-hover);
104
+ border-color: var(--fe-danger-hover);
105
+ }
106
+ .fe-btn--icon-only {
107
+ padding: 6px 8px;
108
+ }
109
+ .fe-btn.is-active {
110
+ background: var(--fe-bg-selected);
111
+ border-color: var(--fe-primary);
112
+ }
113
+ .fe-btn__label {
114
+ line-height: 1;
115
+ }
116
+
117
+ .fe-icon {
118
+ font-size: 1.05em;
119
+ line-height: 1;
120
+ }
121
+
122
+ /* ---------- Toolbar ---------- */
123
+
124
+ .fe-toolbar {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 8px;
128
+ padding: 10px 12px;
129
+ background: var(--fe-bg-elev);
130
+ border-bottom: 1px solid var(--fe-border);
131
+ flex-wrap: wrap;
132
+ }
133
+ .fe-toolbar__primary {
134
+ display: inline-flex;
135
+ align-items: center;
136
+ gap: 6px;
137
+ flex-wrap: wrap;
138
+ }
139
+ .fe-toolbar__spacer {
140
+ flex: 1 1 auto;
141
+ }
142
+ /* Search + Yükle + Yenile pinned together so the cluster doesn't get
143
+ * orphaned by the wrap point on narrow widths. */
144
+ .fe-toolbar__search-group {
145
+ display: inline-flex;
146
+ align-items: center;
147
+ gap: 4px;
148
+ background: var(--fe-bg);
149
+ border: 1px solid var(--fe-border);
150
+ border-radius: var(--fe-radius-sm);
151
+ padding: 2px;
152
+ }
153
+ .fe-toolbar__search-group .fe-search__input {
154
+ border: 0;
155
+ background: transparent;
156
+ padding: 4px 8px;
157
+ }
158
+ .fe-toolbar__search-group .fe-btn {
159
+ border: 0;
160
+ background: transparent;
161
+ padding: 4px 6px;
162
+ }
163
+ .fe-toolbar__search-group .fe-btn:hover:not(:disabled) {
164
+ background: var(--fe-bg-hover);
165
+ }
166
+ .fe-toolbar__view {
167
+ display: inline-flex;
168
+ gap: 2px;
169
+ padding: 2px;
170
+ background: var(--fe-bg);
171
+ border: 1px solid var(--fe-border);
172
+ border-radius: var(--fe-radius-sm);
173
+ }
174
+ .fe-toolbar__view .fe-btn {
175
+ border: 0;
176
+ background: transparent;
177
+ }
178
+ .fe-toolbar__view .fe-btn.is-active {
179
+ background: var(--fe-bg-selected);
180
+ }
181
+
182
+ /* ---------- Search ---------- */
183
+
184
+ .fe-search {
185
+ position: relative;
186
+ }
187
+ .fe-search__input {
188
+ background: var(--fe-bg);
189
+ border: 1px solid var(--fe-border);
190
+ border-radius: var(--fe-radius-sm);
191
+ padding: 6px 10px;
192
+ font: inherit;
193
+ color: var(--fe-text);
194
+ min-width: 200px;
195
+ }
196
+ .fe-search__input:focus-visible {
197
+ outline: 2px solid var(--fe-primary);
198
+ outline-offset: 1px;
199
+ }
200
+
201
+ /* ---------- Breadcrumb ---------- */
202
+
203
+ .fe-breadcrumb {
204
+ display: flex;
205
+ align-items: center;
206
+ gap: 4px;
207
+ flex-wrap: wrap;
208
+ padding: 6px 12px;
209
+ background: var(--fe-bg);
210
+ border-bottom: 1px solid var(--fe-border);
211
+ font-size: 13px;
212
+ color: var(--fe-text-muted);
213
+ }
214
+ .fe-breadcrumb__crumb {
215
+ display: inline-flex;
216
+ align-items: center;
217
+ gap: 4px;
218
+ background: transparent;
219
+ border: 0;
220
+ color: inherit;
221
+ padding: 2px 6px;
222
+ border-radius: var(--fe-radius-sm);
223
+ cursor: pointer;
224
+ font: inherit;
225
+ }
226
+ .fe-breadcrumb__crumb:hover {
227
+ background: var(--fe-bg-hover);
228
+ color: var(--fe-text);
229
+ }
230
+ .fe-breadcrumb__crumb.is-last {
231
+ color: var(--fe-text);
232
+ font-weight: 600;
233
+ }
234
+ .fe-breadcrumb__sep {
235
+ color: var(--fe-text-muted);
236
+ }
237
+ /* Edit pencil button — V1.5: "yolu yazıp gideyim" */
238
+ .fe-breadcrumb__edit {
239
+ margin-left: auto;
240
+ background: none;
241
+ border: 1px solid transparent;
242
+ color: var(--fe-text-muted);
243
+ cursor: pointer;
244
+ font-size: 14px;
245
+ line-height: 1;
246
+ padding: 4px 8px;
247
+ border-radius: 4px;
248
+ }
249
+ .fe-breadcrumb__edit:hover {
250
+ background: var(--fe-bg-hover);
251
+ color: var(--fe-text);
252
+ border-color: var(--fe-border);
253
+ }
254
+ /* Inline path input — replaces the crumbs while editing */
255
+ .fe-breadcrumb__input {
256
+ flex: 1;
257
+ background: var(--fe-bg);
258
+ color: var(--fe-text);
259
+ border: 1px solid var(--fe-accent, #2563eb);
260
+ border-radius: 4px;
261
+ padding: 4px 8px;
262
+ font-family: var(--fe-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
263
+ font-size: 13px;
264
+ outline: none;
265
+ }
266
+
267
+ /* ---------- List view ---------- */
268
+
269
+ .fe-list {
270
+ display: flex;
271
+ flex-direction: column;
272
+ }
273
+ .fe-list__head {
274
+ display: grid;
275
+ grid-template-columns: 32px minmax(0, 1fr) 120px 180px;
276
+ gap: 8px;
277
+ padding: 8px 12px;
278
+ font-weight: 600;
279
+ color: var(--fe-text-muted);
280
+ font-size: 12px;
281
+ text-transform: uppercase;
282
+ letter-spacing: 0.04em;
283
+ background: var(--fe-bg-elev);
284
+ border-bottom: 1px solid var(--fe-border);
285
+ }
286
+ .fe-list__body {
287
+ display: flex;
288
+ flex-direction: column;
289
+ }
290
+ .fe-list__row {
291
+ display: grid;
292
+ grid-template-columns: 32px minmax(0, 1fr) 120px 180px;
293
+ gap: 8px;
294
+ padding: 8px 12px;
295
+ align-items: center;
296
+ cursor: pointer;
297
+ border-bottom: 1px solid var(--fe-border);
298
+ transition: background 0.08s;
299
+ user-select: none;
300
+ }
301
+ .fe-list__row:hover {
302
+ background: var(--fe-bg-hover);
303
+ }
304
+ .fe-list__row.is-selected {
305
+ background: var(--fe-bg-selected);
306
+ }
307
+ .fe-list__row.is-trash {
308
+ opacity: 0.7;
309
+ }
310
+ .fe-list__row.is-clipped,
311
+ .fe-grid__card.is-clipped {
312
+ opacity: 0.45;
313
+ font-style: italic;
314
+ }
315
+ .fe-list__row:focus-visible {
316
+ outline: 2px solid var(--fe-primary);
317
+ outline-offset: -2px;
318
+ }
319
+ .fe-list__col--star {
320
+ display: flex;
321
+ align-items: center;
322
+ justify-content: center;
323
+ opacity: 0;
324
+ transition: opacity 0.12s;
325
+ }
326
+ .fe-list__row:hover .fe-list__col--star,
327
+ .fe-list__row:focus-within .fe-list__col--star,
328
+ .fe-list__col--star:has(.is-starred) {
329
+ opacity: 1;
330
+ }
331
+ .fe-list__col--star .filex-star-btn.is-starred {
332
+ color: var(--fe-warning, #f59e0b);
333
+ }
334
+ .fe-list__col--name {
335
+ display: flex;
336
+ align-items: center;
337
+ gap: 8px;
338
+ min-width: 0;
339
+ }
340
+ .fe-list__icon {
341
+ flex-shrink: 0;
342
+ font-size: 16px;
343
+ }
344
+ .fe-list__name-wrap {
345
+ display: flex;
346
+ flex-direction: column;
347
+ min-width: 0;
348
+ flex: 1 1 auto;
349
+ }
350
+ .fe-list__name {
351
+ overflow: hidden;
352
+ text-overflow: ellipsis;
353
+ white-space: nowrap;
354
+ }
355
+ .fe-list__parent {
356
+ font-size: 11px;
357
+ color: var(--fe-text-muted);
358
+ overflow: hidden;
359
+ text-overflow: ellipsis;
360
+ white-space: nowrap;
361
+ margin-top: 2px;
362
+ }
363
+ .fe-list__col--size,
364
+ .fe-list__col--mod {
365
+ color: var(--fe-text-muted);
366
+ font-size: 13px;
367
+ }
368
+ .fe-list__empty {
369
+ padding: 40px 20px;
370
+ text-align: center;
371
+ color: var(--fe-text-muted);
372
+ }
373
+
374
+ /* ---------- Grid view ---------- */
375
+
376
+ .fe-grid {
377
+ display: grid;
378
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
379
+ gap: var(--fe-gap);
380
+ padding: var(--fe-gap);
381
+ }
382
+ .fe-grid__card {
383
+ display: flex;
384
+ flex-direction: column;
385
+ align-items: stretch;
386
+ padding: 8px;
387
+ border: 1px solid var(--fe-border);
388
+ border-radius: var(--fe-radius);
389
+ background: var(--fe-bg-elev);
390
+ cursor: pointer;
391
+ transition: background 0.08s, border-color 0.08s;
392
+ user-select: none;
393
+ }
394
+ .fe-grid__card:hover {
395
+ background: var(--fe-bg-hover);
396
+ border-color: var(--fe-border-strong);
397
+ }
398
+ .fe-grid__card.is-selected {
399
+ background: var(--fe-bg-selected);
400
+ border-color: var(--fe-primary);
401
+ }
402
+ .fe-grid__card.is-trash {
403
+ opacity: 0.7;
404
+ }
405
+ .fe-grid__thumb {
406
+ display: flex;
407
+ align-items: center;
408
+ justify-content: center;
409
+ aspect-ratio: 1 / 1;
410
+ background: var(--fe-bg);
411
+ border-radius: var(--fe-radius-sm);
412
+ margin-bottom: 8px;
413
+ overflow: hidden;
414
+ }
415
+ .fe-grid__thumb img {
416
+ width: 100%;
417
+ height: 100%;
418
+ object-fit: cover;
419
+ }
420
+ .fe-grid__icon {
421
+ font-size: 32px;
422
+ }
423
+ .fe-grid__label {
424
+ font-size: 13px;
425
+ overflow: hidden;
426
+ text-overflow: ellipsis;
427
+ white-space: nowrap;
428
+ }
429
+ .fe-grid__meta {
430
+ font-size: 11px;
431
+ color: var(--fe-text-muted);
432
+ margin-top: 2px;
433
+ }
434
+ .fe-grid__parent {
435
+ font-size: 11px;
436
+ color: var(--fe-text-muted);
437
+ overflow: hidden;
438
+ text-overflow: ellipsis;
439
+ white-space: nowrap;
440
+ margin-top: 2px;
441
+ font-style: italic;
442
+ }
443
+ .fe-grid__empty {
444
+ grid-column: 1 / -1;
445
+ padding: 40px 20px;
446
+ text-align: center;
447
+ color: var(--fe-text-muted);
448
+ }
449
+
450
+ /* ---------- Drag overlay ---------- */
451
+
452
+ .fe__dragover {
453
+ position: absolute;
454
+ inset: 0;
455
+ z-index: 30;
456
+ display: flex;
457
+ align-items: center;
458
+ justify-content: center;
459
+ background: rgba(59, 130, 246, 0.12);
460
+ border: 3px dashed var(--fe-primary);
461
+ pointer-events: none;
462
+ }
463
+ .fe__dragover-card {
464
+ background: var(--fe-bg);
465
+ border-radius: var(--fe-radius-lg);
466
+ padding: 24px 40px;
467
+ box-shadow: var(--fe-shadow);
468
+ text-align: center;
469
+ }
470
+ .fe__dragover-card .fe-icon {
471
+ font-size: 32px;
472
+ display: block;
473
+ margin-bottom: 8px;
474
+ }
475
+
476
+ /* ---------- Upload progress ---------- */
477
+
478
+ .fe-upload {
479
+ position: absolute;
480
+ right: 16px;
481
+ bottom: 16px;
482
+ width: min(360px, calc(100% - 32px));
483
+ background: var(--fe-bg);
484
+ border: 1px solid var(--fe-border);
485
+ border-radius: var(--fe-radius);
486
+ box-shadow: var(--fe-shadow);
487
+ z-index: 40;
488
+ max-height: 40vh;
489
+ display: flex;
490
+ flex-direction: column;
491
+ overflow: hidden;
492
+ }
493
+ .fe-upload__header {
494
+ display: flex;
495
+ align-items: center;
496
+ justify-content: space-between;
497
+ padding: 10px 14px;
498
+ background: var(--fe-bg-elev);
499
+ border-bottom: 1px solid var(--fe-border);
500
+ font-size: 13px;
501
+ }
502
+ .fe-upload__count {
503
+ background: var(--fe-primary);
504
+ color: var(--fe-text-on-primary);
505
+ font-size: 12px;
506
+ padding: 1px 7px;
507
+ border-radius: 999px;
508
+ }
509
+ .fe-upload__list {
510
+ list-style: none;
511
+ padding: 0;
512
+ margin: 0;
513
+ overflow: auto;
514
+ }
515
+ .fe-upload__item {
516
+ padding: 10px 14px;
517
+ border-bottom: 1px solid var(--fe-border);
518
+ }
519
+ .fe-upload__item:last-child {
520
+ border-bottom: 0;
521
+ }
522
+ .fe-upload__name {
523
+ overflow: hidden;
524
+ text-overflow: ellipsis;
525
+ white-space: nowrap;
526
+ font-size: 13px;
527
+ margin-bottom: 4px;
528
+ }
529
+ .fe-upload__bar {
530
+ background: var(--fe-bg-elev);
531
+ border-radius: 99px;
532
+ height: 6px;
533
+ overflow: hidden;
534
+ margin-bottom: 4px;
535
+ }
536
+ .fe-upload__bar-fill {
537
+ background: var(--fe-primary);
538
+ height: 100%;
539
+ transition: width 0.2s;
540
+ }
541
+ .fe-upload__item.is-error .fe-upload__bar-fill,
542
+ .fe-upload__item.is-aborted .fe-upload__bar-fill {
543
+ background: var(--fe-danger);
544
+ }
545
+ .fe-upload__item.is-done .fe-upload__bar-fill {
546
+ background: #16a34a;
547
+ }
548
+ .fe-upload__meta {
549
+ display: flex;
550
+ align-items: center;
551
+ justify-content: space-between;
552
+ gap: 6px;
553
+ font-size: 11px;
554
+ color: var(--fe-text-muted);
555
+ }
556
+ .fe-upload__cancel {
557
+ background: transparent;
558
+ border: 0;
559
+ color: var(--fe-primary);
560
+ cursor: pointer;
561
+ font: inherit;
562
+ }
563
+
564
+ .fe-upload-slide-enter-active,
565
+ .fe-upload-slide-leave-active {
566
+ transition: transform 0.2s, opacity 0.2s;
567
+ }
568
+ .fe-upload-slide-enter-from,
569
+ .fe-upload-slide-leave-to {
570
+ opacity: 0;
571
+ transform: translateY(10px);
572
+ }
573
+
574
+ /* ---------- Pending ops tray ---------- */
575
+
576
+ /* Sits to the left of UploadProgress (which uses right: 16px) so the
577
+ * two stacks don't overlap when both are active. */
578
+ .fe-ops {
579
+ position: absolute;
580
+ left: 16px;
581
+ bottom: 16px;
582
+ width: min(320px, calc(100% - 32px));
583
+ display: flex;
584
+ flex-direction: column;
585
+ gap: 8px;
586
+ z-index: 40;
587
+ }
588
+ .fe-ops__item {
589
+ background: var(--fe-bg);
590
+ border: 1px solid var(--fe-border);
591
+ border-radius: var(--fe-radius);
592
+ box-shadow: var(--fe-shadow);
593
+ padding: 10px 14px;
594
+ font-size: 13px;
595
+ }
596
+ .fe-ops__item.is-done {
597
+ border-color: #16a34a;
598
+ }
599
+ .fe-ops__item.is-error {
600
+ border-color: var(--fe-danger);
601
+ }
602
+ .fe-ops__row {
603
+ display: flex;
604
+ align-items: center;
605
+ justify-content: space-between;
606
+ gap: 8px;
607
+ margin-bottom: 6px;
608
+ }
609
+ .fe-ops__title {
610
+ overflow: hidden;
611
+ text-overflow: ellipsis;
612
+ white-space: nowrap;
613
+ flex: 1 1 auto;
614
+ }
615
+ .fe-ops__dismiss {
616
+ background: transparent;
617
+ border: 0;
618
+ color: var(--fe-text-muted);
619
+ cursor: pointer;
620
+ font-size: 18px;
621
+ line-height: 1;
622
+ padding: 0 4px;
623
+ }
624
+ .fe-ops__bar {
625
+ background: var(--fe-bg-elev);
626
+ border-radius: 99px;
627
+ height: 6px;
628
+ overflow: hidden;
629
+ }
630
+ .fe-ops__bar-fill {
631
+ background: var(--fe-primary);
632
+ height: 100%;
633
+ transition: width 0.25s;
634
+ }
635
+ .fe-ops__item.is-done .fe-ops__bar-fill {
636
+ background: #16a34a;
637
+ }
638
+ .fe-ops__item.is-error .fe-ops__bar-fill {
639
+ background: var(--fe-danger);
640
+ }
641
+ .fe-ops__error {
642
+ margin-top: 6px;
643
+ font-size: 11px;
644
+ color: var(--fe-danger);
645
+ }
646
+ .fe-ops-slide-enter-active,
647
+ .fe-ops-slide-leave-active {
648
+ transition: transform 0.2s, opacity 0.2s;
649
+ }
650
+ .fe-ops-slide-enter-from,
651
+ .fe-ops-slide-leave-to {
652
+ opacity: 0;
653
+ transform: translateY(10px);
654
+ }
655
+
656
+ /* ---------- Context menu ---------- */
657
+
658
+ .fe-ctx-backdrop {
659
+ position: fixed;
660
+ inset: 0;
661
+ z-index: 80;
662
+ /* Make the backdrop itself the variable scope. After teleporting under
663
+ * <body> we lose the `.fe` parent, so without explicit `color` here
664
+ * the menu inherits Filament's body color (white on dark) and the
665
+ * labels disappear against `--fe-bg` (white). V1.1 bug list update. */
666
+ color: var(--fe-text);
667
+ font-family: var(--fe-font);
668
+ font-size: 14px;
669
+ }
670
+ .fe-ctx {
671
+ position: absolute;
672
+ min-width: 180px;
673
+ background: var(--fe-bg);
674
+ border: 1px solid var(--fe-border);
675
+ border-radius: var(--fe-radius);
676
+ box-shadow: var(--fe-shadow);
677
+ padding: 4px;
678
+ z-index: 90;
679
+ color: var(--fe-text);
680
+ }
681
+ .fe-ctx__item {
682
+ display: flex;
683
+ align-items: center;
684
+ gap: 8px;
685
+ padding: 6px 10px;
686
+ border-radius: var(--fe-radius-sm);
687
+ border: 0;
688
+ background: transparent;
689
+ color: var(--fe-text);
690
+ font: inherit;
691
+ width: 100%;
692
+ text-align: left;
693
+ cursor: pointer;
694
+ }
695
+ .fe-ctx__item:hover:not(.is-disabled) {
696
+ background: var(--fe-bg-hover);
697
+ }
698
+ .fe-ctx__item.is-danger {
699
+ color: var(--fe-danger);
700
+ }
701
+ .fe-ctx__item.is-disabled {
702
+ opacity: 0.45;
703
+ cursor: not-allowed;
704
+ }
705
+ .fe-ctx__icon {
706
+ width: 1.2em;
707
+ text-align: center;
708
+ }
709
+ .fe-ctx__sep {
710
+ height: 1px;
711
+ background: var(--fe-border);
712
+ margin: 4px 0;
713
+ }
714
+ .fe-ctx-enter-active,
715
+ .fe-ctx-leave-active {
716
+ transition: opacity 0.1s;
717
+ }
718
+ .fe-ctx-enter-from,
719
+ .fe-ctx-leave-to {
720
+ opacity: 0;
721
+ }
722
+
723
+ /* ---------- Modal ---------- */
724
+
725
+ .fe-modal__backdrop {
726
+ position: fixed;
727
+ inset: 0;
728
+ z-index: 70;
729
+ display: flex;
730
+ align-items: center;
731
+ justify-content: center;
732
+ background: rgba(13, 19, 27, 0.48);
733
+ padding: 16px;
734
+ }
735
+ .fe-modal__card {
736
+ background: var(--fe-bg);
737
+ border-radius: var(--fe-radius);
738
+ box-shadow: var(--fe-shadow);
739
+ width: 100%;
740
+ max-height: calc(100vh - 32px);
741
+ display: flex;
742
+ flex-direction: column;
743
+ overflow: hidden;
744
+ }
745
+ .fe-modal__card--sm { max-width: 420px; }
746
+ .fe-modal__card--md { max-width: 560px; }
747
+ .fe-modal__card--lg { max-width: 800px; }
748
+ .fe-modal__card--xl { max-width: 1080px; height: calc(100vh - 64px); }
749
+
750
+ /* Recently-opened tray — anchored modal that drops down from the
751
+ * toolbar. Re-uses fe-modal__backdrop, just pins the panel to the top. */
752
+ .fe-recents__backdrop {
753
+ align-items: flex-start !important;
754
+ padding-top: 60px;
755
+ }
756
+ .fe-recents__panel {
757
+ background: var(--fe-bg, #fff);
758
+ border-radius: var(--fe-radius, 8px);
759
+ box-shadow: var(--fe-shadow, 0 6px 24px rgba(0, 0, 0, 0.18));
760
+ width: min(480px, calc(100vw - 32px));
761
+ max-height: calc(100vh - 96px);
762
+ display: flex;
763
+ flex-direction: column;
764
+ overflow: hidden;
765
+ }
766
+ .fe-recents__header {
767
+ display: flex;
768
+ align-items: center;
769
+ justify-content: space-between;
770
+ padding: 10px 14px;
771
+ border-bottom: 1px solid var(--fe-border, #e2e6ed);
772
+ }
773
+ .fe-recents__close {
774
+ appearance: none;
775
+ background: transparent;
776
+ border: 0;
777
+ font-size: 22px;
778
+ line-height: 1;
779
+ cursor: pointer;
780
+ color: var(--fe-text-muted, #6b7280);
781
+ padding: 0 4px;
782
+ }
783
+ .fe-recents__close:hover {
784
+ color: var(--fe-text, #111);
785
+ }
786
+
787
+ /* Markdown split editor — textarea (raw) | rendered HTML preview.
788
+ * The chromeless modal's full viewport makes the side-by-side feasible;
789
+ * on narrower screens it collapses to a vertical stack. */
790
+ .fe-preview__md-split {
791
+ display: flex;
792
+ flex-direction: column;
793
+ height: 100%;
794
+ width: 100%;
795
+ min-height: 0;
796
+ }
797
+ .fe-preview__md-split-bar {
798
+ display: flex;
799
+ align-items: center;
800
+ justify-content: space-between;
801
+ gap: 12px;
802
+ padding: 8px 14px;
803
+ background: var(--fe-bg-elev, #f6f7f9);
804
+ border-bottom: 1px solid var(--fe-border, #e2e6ed);
805
+ flex: 0 0 auto;
806
+ }
807
+ .fe-preview__md-split-label {
808
+ font-family: var(--fe-font-mono, ui-monospace, monospace);
809
+ font-size: 11px;
810
+ letter-spacing: 0.06em;
811
+ color: var(--fe-text-muted, #6b7280);
812
+ }
813
+ .fe-preview__md-split-error {
814
+ flex: 1 1 auto;
815
+ font-size: 12px;
816
+ color: var(--fe-danger, #dc2626);
817
+ text-align: center;
818
+ }
819
+ .fe-preview__md-split-body {
820
+ flex: 1 1 auto;
821
+ display: grid;
822
+ grid-template-columns: 1fr 1fr;
823
+ min-height: 0;
824
+ }
825
+ .fe-preview__md-split-input {
826
+ resize: none;
827
+ border: 0;
828
+ outline: 0;
829
+ padding: 16px 20px;
830
+ font-family: var(--fe-font-mono, ui-monospace, monospace);
831
+ font-size: 13px;
832
+ line-height: 1.6;
833
+ background: var(--fe-bg, #fff);
834
+ color: var(--fe-text, #111);
835
+ border-right: 1px solid var(--fe-border, #e2e6ed);
836
+ overflow: auto;
837
+ tab-size: 2;
838
+ }
839
+ .fe-preview__md-split-output {
840
+ overflow: auto;
841
+ padding: 16px 24px;
842
+ background: var(--fe-bg, #fff);
843
+ }
844
+ /* The split-output element carries BOTH `fe-preview__md-split-output` and
845
+ * `fe-preview__md`. The shared `.fe-preview__md` rule caps height at 70vh
846
+ * (right for the standalone modal preview, wrong here) and — being later in
847
+ * source order at equal specificity — wins over a plain
848
+ * `.fe-preview__md-split-output { max-height: none }`. The compound selector
849
+ * below raises specificity so the cap is dropped regardless of order, letting
850
+ * the rendered pane fill the grid row (tall docs scroll inside it) instead of
851
+ * leaving a dead gap below the content. */
852
+ .fe-preview__md-split-output.fe-preview__md {
853
+ max-height: none;
854
+ min-height: 0;
855
+ height: 100%;
856
+ }
857
+ @media (max-width: 900px) {
858
+ .fe-preview__md-split-body {
859
+ grid-template-columns: 1fr;
860
+ grid-template-rows: 1fr 1fr;
861
+ }
862
+ .fe-preview__md-split-input {
863
+ border-right: 0;
864
+ border-bottom: 1px solid var(--fe-border, #e2e6ed);
865
+ }
866
+ }
867
+
868
+ /* Chromeless — used by the standalone /files/edit route. Drops the
869
+ * dialog frame entirely so the viewport belongs to the viewer. */
870
+ .fe-modal__backdrop--chromeless {
871
+ background: transparent;
872
+ padding: 0;
873
+ }
874
+ .fe-modal__card--chromeless {
875
+ max-width: none;
876
+ width: 100vw;
877
+ height: 100vh;
878
+ max-height: 100vh;
879
+ border-radius: 0;
880
+ box-shadow: none;
881
+ }
882
+ .fe-modal__card--chromeless .fe-modal__body {
883
+ flex: 1 1 auto;
884
+ min-height: 0;
885
+ padding: 0;
886
+ }
887
+ .fe-modal__card--chromeless .fe-preview {
888
+ /* Override center-alignment so split editors + iframes fill the
889
+ * full chromeless viewport instead of floating in the middle. */
890
+ align-items: stretch;
891
+ justify-content: stretch;
892
+ min-height: 0;
893
+ flex: 1 1 auto;
894
+ }
895
+ .fe-modal__card--chromeless .fe-preview > * {
896
+ width: 100%;
897
+ height: 100%;
898
+ }
899
+
900
+ .fe-modal__head {
901
+ display: flex;
902
+ align-items: center;
903
+ justify-content: space-between;
904
+ padding: 12px 16px;
905
+ border-bottom: 1px solid var(--fe-border);
906
+ }
907
+ .fe-modal__title {
908
+ font-size: 16px;
909
+ font-weight: 600;
910
+ margin: 0;
911
+ }
912
+ .fe-modal__close {
913
+ background: transparent;
914
+ border: 0;
915
+ color: var(--fe-text-muted);
916
+ font-size: 22px;
917
+ cursor: pointer;
918
+ padding: 0 4px;
919
+ line-height: 1;
920
+ }
921
+ .fe-modal__body {
922
+ padding: 16px;
923
+ overflow: auto;
924
+ flex: 1 1 auto;
925
+ }
926
+ .fe-modal__actions {
927
+ display: flex;
928
+ justify-content: flex-end;
929
+ gap: 8px;
930
+ padding: 12px 16px;
931
+ border-top: 1px solid var(--fe-border);
932
+ background: var(--fe-bg-elev);
933
+ }
934
+
935
+ .fe-modal-enter-active,
936
+ .fe-modal-leave-active {
937
+ transition: opacity 0.15s;
938
+ }
939
+ .fe-modal-enter-from,
940
+ .fe-modal-leave-to {
941
+ opacity: 0;
942
+ }
943
+
944
+ /* ---------- Form ---------- */
945
+
946
+ .fe-input {
947
+ width: 100%;
948
+ padding: 8px 10px;
949
+ background: var(--fe-bg);
950
+ border: 1px solid var(--fe-border);
951
+ border-radius: var(--fe-radius-sm);
952
+ font: inherit;
953
+ color: var(--fe-text);
954
+ }
955
+ .fe-input:focus-visible {
956
+ outline: 2px solid var(--fe-primary);
957
+ outline-offset: 1px;
958
+ }
959
+ .fe-input--mono {
960
+ font-family: var(--fe-font-mono);
961
+ letter-spacing: 0.1em;
962
+ }
963
+ .fe-form {
964
+ display: flex;
965
+ flex-direction: column;
966
+ gap: 12px;
967
+ }
968
+ .fe-form__row {
969
+ display: flex;
970
+ align-items: center;
971
+ gap: 8px;
972
+ }
973
+ .fe-form__row--stack {
974
+ flex-direction: column;
975
+ align-items: stretch;
976
+ }
977
+ .fe-form__error {
978
+ color: var(--fe-danger);
979
+ font-size: 12px;
980
+ margin: 6px 0 0;
981
+ }
982
+
983
+ /* Share result */
984
+ .fe-share-result {
985
+ display: flex;
986
+ flex-direction: column;
987
+ gap: 12px;
988
+ }
989
+ .fe-share-result__row label {
990
+ display: block;
991
+ font-size: 12px;
992
+ font-weight: 600;
993
+ color: var(--fe-text-muted);
994
+ margin-bottom: 4px;
995
+ }
996
+ .fe-share-result__copy {
997
+ display: flex;
998
+ gap: 6px;
999
+ }
1000
+
1001
+ /* ---------- Preview ---------- */
1002
+
1003
+ .fe-preview {
1004
+ display: flex;
1005
+ align-items: center;
1006
+ justify-content: center;
1007
+ width: 100%;
1008
+ height: 100%;
1009
+ min-height: 50vh;
1010
+ background: var(--fe-bg-elev);
1011
+ }
1012
+ .fe-preview__image {
1013
+ max-width: 100%;
1014
+ max-height: 70vh;
1015
+ object-fit: contain;
1016
+ }
1017
+ .fe-preview__video,
1018
+ .fe-preview__audio {
1019
+ max-width: 100%;
1020
+ max-height: 70vh;
1021
+ }
1022
+ .fe-preview__iframe {
1023
+ width: 100%;
1024
+ height: 70vh;
1025
+ border: 0;
1026
+ background: #fff;
1027
+ }
1028
+ .fe-preview__office {
1029
+ width: 100%;
1030
+ height: 78vh;
1031
+ background: var(--fe-bg);
1032
+ }
1033
+ /* CodeMirror 6 editor surface — Burak (V1.5 follow-up #4): "monaco
1034
+ editör çalışmıyor" → CodeMirror replacement. */
1035
+ .fe-preview__code-wrap {
1036
+ display: flex;
1037
+ flex-direction: column;
1038
+ width: 100%;
1039
+ height: 78vh;
1040
+ }
1041
+ .fe-preview__code-toolbar {
1042
+ display: flex;
1043
+ align-items: center;
1044
+ gap: 12px;
1045
+ padding: 8px 12px;
1046
+ background: var(--fe-bg-hover, #f3f4f6);
1047
+ border-bottom: 1px solid var(--fe-border, #e5e7eb);
1048
+ font-size: 12px;
1049
+ }
1050
+ .fe-preview__code-lang {
1051
+ font-family: var(--fe-font-mono, ui-monospace, monospace);
1052
+ color: var(--fe-text-muted);
1053
+ text-transform: uppercase;
1054
+ letter-spacing: 0.04em;
1055
+ }
1056
+ .fe-preview__code-toolbar > .fe-btn {
1057
+ margin-left: auto;
1058
+ }
1059
+ .fe-preview__code-status {
1060
+ font-size: 12px;
1061
+ font-weight: 500;
1062
+ }
1063
+ .fe-preview__code-status--ok { color: #059669; }
1064
+ .fe-preview__code-status--err { color: #dc2626; cursor: help; }
1065
+ .fe-preview__code-editor {
1066
+ flex: 1;
1067
+ min-height: 0;
1068
+ overflow: hidden;
1069
+ }
1070
+ .fe-preview__code-editor .cm-editor {
1071
+ height: 100%;
1072
+ font-size: 13px;
1073
+ }
1074
+ .fe-preview__code-editor .cm-scroller {
1075
+ font-family: var(--fe-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
1076
+ }
1077
+ .fe-preview__fallback {
1078
+ text-align: center;
1079
+ color: var(--fe-text-muted);
1080
+ padding: 40px 20px;
1081
+ }
1082
+ .fe-preview__fallback-icon {
1083
+ font-size: 48px;
1084
+ display: block;
1085
+ margin-bottom: 12px;
1086
+ }
1087
+ .fe-preview__pre {
1088
+ margin: 0;
1089
+ padding: 16px;
1090
+ width: 100%;
1091
+ max-height: 70vh;
1092
+ overflow: auto;
1093
+ background: var(--fe-bg);
1094
+ color: var(--fe-text);
1095
+ font-family: var(--fe-font-mono);
1096
+ font-size: 13px;
1097
+ line-height: 1.5;
1098
+ white-space: pre-wrap;
1099
+ word-wrap: break-word;
1100
+ }
1101
+ .fe-preview__code {
1102
+ white-space: pre;
1103
+ word-wrap: normal;
1104
+ }
1105
+ /* Minimal highlight.js theme — host can override by importing one of
1106
+ * highlight.js's stylesheets ahead of file-explorer.css. We ship
1107
+ * something usable so the unstyled colour-class spans don't render as
1108
+ * raw text in the wild. */
1109
+ .hljs { background: var(--fe-bg); color: var(--fe-text); }
1110
+ .hljs-comment, .hljs-quote { color: var(--fe-text-muted); font-style: italic; }
1111
+ .hljs-keyword, .hljs-selector-tag, .hljs-built_in, .hljs-section,
1112
+ .hljs-meta { color: #c678dd; }
1113
+ .hljs-string, .hljs-attr, .hljs-symbol, .hljs-bullet, .hljs-addition,
1114
+ .hljs-link { color: #98c379; }
1115
+ .hljs-number, .hljs-literal, .hljs-deletion { color: #d19a66; }
1116
+ .hljs-title, .hljs-name, .hljs-selector-id, .hljs-selector-class,
1117
+ .hljs-template-tag, .hljs-template-variable { color: #61aeee; }
1118
+ .hljs-type, .hljs-tag { color: #e06c75; }
1119
+ .hljs-variable, .hljs-attribute { color: #d19a66; }
1120
+ .hljs-emphasis { font-style: italic; }
1121
+ .hljs-strong { font-weight: bold; }
1122
+ .fe-preview__md {
1123
+ width: 100%;
1124
+ max-height: 70vh;
1125
+ overflow: auto;
1126
+ padding: 24px 32px;
1127
+ background: var(--fe-bg);
1128
+ color: var(--fe-text);
1129
+ line-height: 1.6;
1130
+ font-size: 15px;
1131
+ }
1132
+ .fe-preview__md h1,
1133
+ .fe-preview__md h2,
1134
+ .fe-preview__md h3,
1135
+ .fe-preview__md h4 {
1136
+ margin: 1.2em 0 0.6em;
1137
+ font-weight: 600;
1138
+ }
1139
+ .fe-preview__md h1 { font-size: 1.8em; border-bottom: 1px solid var(--fe-border); padding-bottom: 0.3em; }
1140
+ .fe-preview__md h2 { font-size: 1.4em; border-bottom: 1px solid var(--fe-border); padding-bottom: 0.3em; }
1141
+ .fe-preview__md h3 { font-size: 1.2em; }
1142
+ .fe-preview__md p { margin: 0.8em 0; }
1143
+ .fe-preview__md a { color: var(--fe-primary); text-decoration: underline; }
1144
+ .fe-preview__md code {
1145
+ font-family: var(--fe-font-mono);
1146
+ background: var(--fe-bg-elev);
1147
+ padding: 1px 5px;
1148
+ border-radius: 3px;
1149
+ font-size: 0.92em;
1150
+ }
1151
+ .fe-preview__md pre {
1152
+ background: var(--fe-bg-elev);
1153
+ border: 1px solid var(--fe-border);
1154
+ border-radius: var(--fe-radius-sm);
1155
+ padding: 12px 16px;
1156
+ overflow: auto;
1157
+ font-size: 0.9em;
1158
+ }
1159
+ .fe-preview__md pre code { background: transparent; padding: 0; }
1160
+ .fe-preview__md ul,
1161
+ .fe-preview__md ol { padding-left: 2em; margin: 0.8em 0; }
1162
+ .fe-preview__md li { margin: 0.3em 0; }
1163
+ .fe-preview__md blockquote {
1164
+ border-left: 3px solid var(--fe-border-strong);
1165
+ padding: 0 1em;
1166
+ color: var(--fe-text-muted);
1167
+ margin: 0.8em 0;
1168
+ }
1169
+ .fe-preview__md table {
1170
+ border-collapse: collapse;
1171
+ margin: 1em 0;
1172
+ width: 100%;
1173
+ }
1174
+ .fe-preview__md th,
1175
+ .fe-preview__md td {
1176
+ border: 1px solid var(--fe-border);
1177
+ padding: 6px 10px;
1178
+ text-align: left;
1179
+ }
1180
+ .fe-preview__md th { background: var(--fe-bg-elev); }
1181
+ .fe-preview__md img { max-width: 100%; }
1182
+
1183
+ /* ---------- Toast ---------- */
1184
+
1185
+ .fe-toast {
1186
+ position: absolute;
1187
+ bottom: 24px;
1188
+ left: 50%;
1189
+ transform: translateX(-50%);
1190
+ background: var(--fe-text);
1191
+ color: var(--fe-bg);
1192
+ padding: 8px 14px;
1193
+ border-radius: var(--fe-radius);
1194
+ font-size: 13px;
1195
+ box-shadow: var(--fe-shadow-sm);
1196
+ z-index: 95;
1197
+ }
1198
+ .fe-toast-enter-active,
1199
+ .fe-toast-leave-active {
1200
+ transition: opacity 0.2s, transform 0.2s;
1201
+ }
1202
+ .fe-toast-enter-from,
1203
+ .fe-toast-leave-to {
1204
+ opacity: 0;
1205
+ transform: translate(-50%, 10px);
1206
+ }
1207
+
1208
+ /* ---------- Responsive ---------- */
1209
+
1210
+ @media (max-width: 640px) {
1211
+ .fe-list__head,
1212
+ .fe-list__row {
1213
+ grid-template-columns: 28px minmax(0, 1fr) 90px;
1214
+ }
1215
+ .fe-list__col--mod {
1216
+ display: none;
1217
+ }
1218
+ .fe-toolbar {
1219
+ padding: 8px;
1220
+ }
1221
+ .fe-search__input {
1222
+ min-width: 120px;
1223
+ }
1224
+ }