@brftech/filex-core 0.1.82 → 0.1.84

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 (43) hide show
  1. package/README.md +2 -0
  2. package/dist/{ArchiveViewer-BRASXNIS.js → ArchiveViewer-wg4uE-3C.js} +2 -2
  3. package/dist/{ArchiveViewer-BRASXNIS.js.map → ArchiveViewer-wg4uE-3C.js.map} +1 -1
  4. package/dist/{CsvViewer-CgiLiHWw.js → CsvViewer-57uz4UKk.js} +2 -2
  5. package/dist/{CsvViewer-CgiLiHWw.js.map → CsvViewer-57uz4UKk.js.map} +1 -1
  6. package/dist/{DrawioViewer-D2I_uEng.js → DrawioViewer-BfL9Hbyp.js} +2 -2
  7. package/dist/{DrawioViewer-D2I_uEng.js.map → DrawioViewer-BfL9Hbyp.js.map} +1 -1
  8. package/dist/{EpubViewer-6nVPRR6R.js → EpubViewer-CYG2CV_3.js} +2 -2
  9. package/dist/{EpubViewer-6nVPRR6R.js.map → EpubViewer-CYG2CV_3.js.map} +1 -1
  10. package/dist/{IpynbViewer-B7p9hxFx.js → IpynbViewer-DJw34-wV.js} +2 -2
  11. package/dist/{IpynbViewer-B7p9hxFx.js.map → IpynbViewer-DJw34-wV.js.map} +1 -1
  12. package/dist/{MermaidViewer-O9vGvp4y.js → MermaidViewer-C86jjm27.js} +2 -2
  13. package/dist/{MermaidViewer-O9vGvp4y.js.map → MermaidViewer-C86jjm27.js.map} +1 -1
  14. package/dist/{PsdViewer-C6EaEAxF.js → PsdViewer-DGHIqv-x.js} +2 -2
  15. package/dist/{PsdViewer-C6EaEAxF.js.map → PsdViewer-DGHIqv-x.js.map} +1 -1
  16. package/dist/{TiffViewer-Dod4uIXI.js → TiffViewer-gct9Ub3o.js} +2 -2
  17. package/dist/{TiffViewer-Dod4uIXI.js.map → TiffViewer-gct9Ub3o.js.map} +1 -1
  18. package/dist/{Viewer3D-B3kLZrwO.js → Viewer3D-BVt4l2a9.js} +2 -2
  19. package/dist/{Viewer3D-B3kLZrwO.js.map → Viewer3D-BVt4l2a9.js.map} +1 -1
  20. package/dist/filex-core.js +1 -1
  21. package/dist/filex-core.umd.cjs +38 -38
  22. package/dist/filex-core.umd.cjs.map +1 -1
  23. package/dist/index-BeUoODQq.js +6871 -0
  24. package/dist/index-BeUoODQq.js.map +1 -0
  25. package/dist/index.d.ts +6 -0
  26. package/dist/style.css +1 -1
  27. package/package.json +1 -1
  28. package/src/FileExplorer.vue +393 -31
  29. package/src/components/Breadcrumb.vue +100 -5
  30. package/src/components/CommandPalette.vue +299 -0
  31. package/src/components/GridView.vue +8 -13
  32. package/src/components/ListView.vue +173 -20
  33. package/src/components/ShortcutsHelp.vue +59 -0
  34. package/src/components/Toolbar.vue +65 -1
  35. package/src/composables/useKeyboardShortcuts.ts +38 -0
  36. package/src/composables/useRealtime.ts +9 -1
  37. package/src/lib/fileIcons.ts +127 -0
  38. package/src/locales/en.ts +54 -0
  39. package/src/locales/tr.ts +54 -0
  40. package/src/styles/base.css +565 -0
  41. package/src/styles/variables.css +70 -0
  42. package/dist/index-DL6_eaM3.js +0 -5888
  43. package/dist/index-DL6_eaM3.js.map +0 -1
package/src/locales/tr.ts CHANGED
@@ -133,4 +133,58 @@ export const tr: Record<string, string> = {
133
133
  'viewer.archive.error': 'Arşiv okunamadı.',
134
134
  'viewer.name': 'Ad',
135
135
  'viewer.size': 'Boyut',
136
+
137
+ // ——— cila:a — sıralama / tarih grupları / yoğunluk ———
138
+ 'col.sort': 'Sırala',
139
+ 'group.today': 'Bugün',
140
+ 'group.yesterday': 'Dün',
141
+ 'group.this_week': 'Bu Hafta',
142
+ 'group.this_month': 'Bu Ay',
143
+ 'group.no_date': 'Tarihsiz',
144
+ 'toolbar.density.compact': 'Sıkışık görünüm',
145
+ 'toolbar.density.comfortable': 'Rahat görünüm',
146
+
147
+ // ——— cila:c — komut paleti + kısayol yardımı + breadcrumb ———
148
+ 'palette.placeholder': 'Dosya, klasör veya komut ara…',
149
+ 'palette.files': 'Dosyalar',
150
+ 'palette.commands': 'Komutlar',
151
+ 'palette.goto': 'Yola git',
152
+ 'palette.empty': 'Sonuç bulunamadı',
153
+ 'palette.hint': '↑↓ gezin · Enter seç · Esc kapat',
154
+ 'cmd.view_toggle': 'Görünümü değiştir (liste ⇄ ızgara)',
155
+ 'cmd.trash': 'Çöp kutusunu aç',
156
+ 'shortcuts.title': 'Klavye Kısayolları',
157
+ 'shortcuts.group.nav': 'Gezinme',
158
+ 'shortcuts.group.selection': 'Seçim',
159
+ 'shortcuts.group.file': 'Dosya işlemleri',
160
+ 'shortcuts.palette': 'Komut paleti',
161
+ 'shortcuts.search': 'Aramaya odaklan',
162
+ 'shortcuts.go_up': 'Üst klasöre çık',
163
+ 'shortcuts.open': 'Seçili öğeyi aç',
164
+ 'shortcuts.close': 'Kapat / vazgeç',
165
+ 'shortcuts.help': 'Bu yardım penceresi',
166
+ 'shortcuts.select_all': 'Tümünü seç',
167
+ 'shortcuts.rename': 'Yeniden adlandır',
168
+ 'shortcuts.delete': 'Sil',
169
+ 'shortcuts.cut': 'Kes',
170
+ 'shortcuts.copy': 'Kopyala',
171
+ 'shortcuts.paste': 'Yapıştır',
172
+ 'breadcrumb.more': 'Aradaki klasörler',
173
+
174
+ // ——— State screens + undo snackbar + connection badge (cila:b) ———
175
+ 'empty.hint': 'Dosyaları buraya sürükleyip bırakın',
176
+ 'empty.upload': 'Dosya yükle',
177
+ 'empty.search.title': 'Aramanla eşleşen dosya yok',
178
+ 'empty.search.hint': 'Farklı bir arama terimi deneyin',
179
+ 'empty.trash.title': 'Çöp kutusu boş',
180
+ 'error.title': 'Liste yüklenemedi',
181
+ 'error.retry': 'Yeniden dene',
182
+ 'toast.undo': 'Geri Al',
183
+ 'toast.undone': 'Geri alındı',
184
+ 'toast.undo_failed': 'Geri alınamadı',
185
+ 'toast.renamed': 'Yeniden adlandırıldı',
186
+ 'toast.moved': 'Taşındı',
187
+ 'toast.trashed': 'Çöpe taşındı',
188
+ 'conn.offline': 'Canlı bağlantı yok — değişiklikler gecikebilir',
189
+ 'conn.tooltip': 'Sunucuyla canlı bağlantı kurulamadı; liste belirli aralıklarla otomatik yenilenir. Bağlantı geri gelince bu uyarı kaybolur.',
136
190
  };
@@ -23,9 +23,25 @@
23
23
  .fe__body {
24
24
  flex: 1 1 auto;
25
25
  overflow: auto;
26
+ /* Flexbox's default min-height:auto stops a flex item shrinking below its
27
+ content height — in a height-constrained embed the body would stay at
28
+ content height, its overflow:auto never engages and everything past the
29
+ fold is clipped (unreachable) by .fe's overflow:hidden. min-height:0
30
+ caps the body to the remaining space so internal (touch) scroll works. */
31
+ min-height: 0;
26
32
  background: var(--fe-bg);
27
33
  }
28
34
 
35
+ /* Web-component host default: custom elements are display:inline, which
36
+ collapses the height chain. Declared here so embedders don't need inline
37
+ styles on <filex-explorer> — an inline style on the host falls through to
38
+ the .fe root (Vue attr fallthrough) where display:block would kill the
39
+ flex column and with it the internal scroll. */
40
+ filex-explorer {
41
+ display: block;
42
+ height: 100%;
43
+ }
44
+
29
45
  /* Live-presence strip (who else is in this folder) — shown under the breadcrumb. */
30
46
  .fe__presence {
31
47
  flex: 0 0 auto;
@@ -1265,3 +1281,552 @@
1265
1281
  min-width: 120px;
1266
1282
  }
1267
1283
  }
1284
+
1285
+ /* === cila:a — file-type SVG icons + date group headers + density mode === */
1286
+
1287
+ /* SVG icon set (lib/fileIcons) — sized by the wrapper's font-size so the
1288
+ * existing 32px grid / 16px list scales keep working. */
1289
+ .fe-ficon {
1290
+ width: 1em;
1291
+ height: 1em;
1292
+ display: block;
1293
+ flex-shrink: 0;
1294
+ }
1295
+ .fe-ficon--folder { color: var(--fe-icon-folder); }
1296
+ .fe-ficon--image { color: var(--fe-icon-image); }
1297
+ .fe-ficon--video { color: var(--fe-icon-video); }
1298
+ .fe-ficon--audio { color: var(--fe-icon-audio); }
1299
+ .fe-ficon--pdf { color: var(--fe-icon-pdf); }
1300
+ .fe-ficon--doc { color: var(--fe-icon-doc); }
1301
+ .fe-ficon--sheet { color: var(--fe-icon-sheet); }
1302
+ .fe-ficon--slides { color: var(--fe-icon-slides); }
1303
+ .fe-ficon--archive { color: var(--fe-icon-archive); }
1304
+ .fe-ficon--code { color: var(--fe-icon-code); }
1305
+ .fe-ficon--text { color: var(--fe-icon-text); }
1306
+ .fe-ficon--unknown { color: var(--fe-icon-unknown); }
1307
+ .fe-grid__icon--svg {
1308
+ display: flex;
1309
+ align-items: center;
1310
+ justify-content: center;
1311
+ }
1312
+ .fe-list__icon--svg {
1313
+ display: inline-flex;
1314
+ align-items: center;
1315
+ }
1316
+
1317
+ /* Sortable list column headers — plain-looking buttons, arrow only when
1318
+ * the column drives the order. */
1319
+ .fe-list__sort {
1320
+ display: inline-flex;
1321
+ align-items: center;
1322
+ gap: 4px;
1323
+ background: transparent;
1324
+ border: 0;
1325
+ padding: 0;
1326
+ font: inherit;
1327
+ color: inherit;
1328
+ text-transform: inherit;
1329
+ letter-spacing: inherit;
1330
+ cursor: pointer;
1331
+ }
1332
+ .fe-list__sort:hover {
1333
+ color: var(--fe-text);
1334
+ }
1335
+ .fe-list__sort:focus-visible {
1336
+ outline: 2px solid var(--fe-primary);
1337
+ outline-offset: 2px;
1338
+ border-radius: 2px;
1339
+ }
1340
+ .fe-list__sort-arrow {
1341
+ font-size: 11px;
1342
+ color: var(--fe-primary);
1343
+ }
1344
+
1345
+ /* Date group headers (only while sorted by modified date) — thin, muted,
1346
+ * non-interactive. */
1347
+ .fe-list__group {
1348
+ padding: 12px 12px 4px;
1349
+ font-size: 11px;
1350
+ font-weight: 600;
1351
+ text-transform: uppercase;
1352
+ letter-spacing: 0.05em;
1353
+ color: var(--fe-text-muted);
1354
+ user-select: none;
1355
+ }
1356
+
1357
+ /* Density: compact — tighter rows/cards, smaller grid tiles. Toggled from
1358
+ * the toolbar; class lives on the `.fe` root. */
1359
+ .fe--density-compact .fe-toolbar {
1360
+ padding: 6px 8px;
1361
+ gap: 6px;
1362
+ }
1363
+ .fe--density-compact .fe-breadcrumb {
1364
+ padding: 4px 12px;
1365
+ }
1366
+ .fe--density-compact .fe-list__head {
1367
+ padding: 4px 12px;
1368
+ }
1369
+ .fe--density-compact .fe-list__row {
1370
+ padding: 3px 12px;
1371
+ }
1372
+ .fe--density-compact .fe-list__icon {
1373
+ font-size: 14px;
1374
+ }
1375
+ .fe--density-compact .fe-list__group {
1376
+ padding: 8px 12px 2px;
1377
+ }
1378
+ .fe--density-compact .fe-grid {
1379
+ grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
1380
+ gap: 8px;
1381
+ padding: 8px;
1382
+ }
1383
+ .fe--density-compact .fe-grid__card {
1384
+ padding: 6px;
1385
+ }
1386
+ .fe--density-compact .fe-grid__icon {
1387
+ font-size: 24px;
1388
+ }
1389
+
1390
+
1391
+ /* === cila:c — command palette + shortcuts help + breadcrumb overflow === */
1392
+
1393
+ /* Command palette (Ctrl/Cmd+K) — top-anchored launcher card. */
1394
+ .fe-cmdp__backdrop {
1395
+ align-items: flex-start;
1396
+ padding-top: min(18vh, 160px);
1397
+ }
1398
+ .fe-cmdp {
1399
+ background: var(--fe-bg);
1400
+ border: 1px solid var(--fe-border);
1401
+ border-radius: var(--fe-radius-lg);
1402
+ box-shadow: var(--fe-shadow);
1403
+ width: min(560px, calc(100vw - 32px));
1404
+ display: flex;
1405
+ flex-direction: column;
1406
+ overflow: hidden;
1407
+ }
1408
+ .fe-cmdp__inputwrap {
1409
+ display: flex;
1410
+ align-items: center;
1411
+ gap: 8px;
1412
+ padding: 10px 14px;
1413
+ border-bottom: 1px solid var(--fe-border);
1414
+ color: var(--fe-text-muted);
1415
+ }
1416
+ .fe-cmdp__glyph {
1417
+ flex: 0 0 auto;
1418
+ }
1419
+ .fe-cmdp__input {
1420
+ flex: 1 1 auto;
1421
+ min-width: 0;
1422
+ border: 0;
1423
+ outline: none;
1424
+ background: transparent;
1425
+ color: var(--fe-text);
1426
+ font: inherit;
1427
+ font-size: 15px;
1428
+ }
1429
+ .fe-cmdp__input::placeholder {
1430
+ color: var(--fe-text-muted);
1431
+ }
1432
+ .fe-cmdp__list {
1433
+ max-height: min(48vh, 380px);
1434
+ overflow-y: auto;
1435
+ padding: 6px;
1436
+ }
1437
+ .fe-cmdp__group {
1438
+ padding: 8px 10px 4px;
1439
+ font-size: 11px;
1440
+ font-weight: 600;
1441
+ letter-spacing: 0.05em;
1442
+ text-transform: uppercase;
1443
+ color: var(--fe-text-muted);
1444
+ }
1445
+ .fe-cmdp__item {
1446
+ display: flex;
1447
+ align-items: center;
1448
+ gap: 10px;
1449
+ width: 100%;
1450
+ text-align: left;
1451
+ background: transparent;
1452
+ border: 0;
1453
+ border-radius: var(--fe-radius-sm);
1454
+ padding: 8px 10px;
1455
+ color: var(--fe-text);
1456
+ font: inherit;
1457
+ font-size: 14px;
1458
+ cursor: pointer;
1459
+ }
1460
+ .fe-cmdp__item.is-active {
1461
+ background: var(--fe-bg-selected);
1462
+ }
1463
+ .fe-cmdp__item:focus-visible {
1464
+ outline: 2px solid var(--fe-primary);
1465
+ outline-offset: -2px;
1466
+ }
1467
+ .fe-cmdp__icon {
1468
+ flex: 0 0 auto;
1469
+ width: 20px;
1470
+ text-align: center;
1471
+ }
1472
+ .fe-cmdp__label {
1473
+ flex: 1 1 auto;
1474
+ overflow: hidden;
1475
+ text-overflow: ellipsis;
1476
+ white-space: nowrap;
1477
+ }
1478
+ .fe-cmdp__empty {
1479
+ padding: 20px 12px;
1480
+ text-align: center;
1481
+ color: var(--fe-text-muted);
1482
+ font-size: 13px;
1483
+ }
1484
+ .fe-cmdp__hint {
1485
+ padding: 8px 14px;
1486
+ border-top: 1px solid var(--fe-border);
1487
+ background: var(--fe-bg-elev);
1488
+ font-size: 11px;
1489
+ color: var(--fe-text-muted);
1490
+ }
1491
+
1492
+ /* Shortcuts help ("?") — grouped cheat-sheet inside the standard modal. */
1493
+ .fe-shortcuts {
1494
+ display: flex;
1495
+ flex-direction: column;
1496
+ gap: 16px;
1497
+ }
1498
+ .fe-shortcuts__heading {
1499
+ margin: 0 0 6px;
1500
+ font-size: 11px;
1501
+ font-weight: 600;
1502
+ letter-spacing: 0.05em;
1503
+ text-transform: uppercase;
1504
+ color: var(--fe-text-muted);
1505
+ }
1506
+ .fe-shortcuts__table {
1507
+ display: flex;
1508
+ flex-direction: column;
1509
+ }
1510
+ .fe-shortcuts__row {
1511
+ display: flex;
1512
+ align-items: center;
1513
+ gap: 12px;
1514
+ padding: 4px 0;
1515
+ }
1516
+ .fe-shortcuts__keys {
1517
+ flex: 0 0 40%;
1518
+ display: flex;
1519
+ align-items: center;
1520
+ gap: 6px;
1521
+ flex-wrap: wrap;
1522
+ }
1523
+ .fe-shortcuts__desc {
1524
+ flex: 1 1 auto;
1525
+ font-size: 13px;
1526
+ color: var(--fe-text);
1527
+ }
1528
+ .fe-shortcuts__or {
1529
+ color: var(--fe-text-muted);
1530
+ font-size: 11px;
1531
+ }
1532
+ .fe-kbd {
1533
+ display: inline-block;
1534
+ padding: 2px 7px;
1535
+ border: 1px solid var(--fe-border-strong);
1536
+ border-bottom-width: 2px;
1537
+ border-radius: var(--fe-radius-sm);
1538
+ background: var(--fe-bg-elev);
1539
+ color: var(--fe-text);
1540
+ font-family: var(--fe-font-mono);
1541
+ font-size: 11.5px;
1542
+ line-height: 1.4;
1543
+ }
1544
+
1545
+ /* Breadcrumb overflow — "…" trigger + dropdown for the collapsed middle. */
1546
+ .fe-breadcrumb__more-wrap {
1547
+ position: relative;
1548
+ display: inline-flex;
1549
+ align-items: center;
1550
+ gap: 4px;
1551
+ }
1552
+ .fe-breadcrumb__more {
1553
+ background: transparent;
1554
+ border: 0;
1555
+ color: inherit;
1556
+ padding: 2px 8px;
1557
+ border-radius: var(--fe-radius-sm);
1558
+ cursor: pointer;
1559
+ font: inherit;
1560
+ line-height: 1.2;
1561
+ }
1562
+ .fe-breadcrumb__more:hover,
1563
+ .fe-breadcrumb__more[aria-expanded='true'] {
1564
+ background: var(--fe-bg-hover);
1565
+ color: var(--fe-text);
1566
+ }
1567
+ .fe-breadcrumb__more:focus-visible {
1568
+ outline: 2px solid var(--fe-primary);
1569
+ outline-offset: 1px;
1570
+ }
1571
+ .fe-breadcrumb__menu {
1572
+ position: absolute;
1573
+ top: calc(100% + 4px);
1574
+ left: 0;
1575
+ z-index: 80;
1576
+ min-width: 160px;
1577
+ max-width: 280px;
1578
+ max-height: 40vh;
1579
+ overflow-y: auto;
1580
+ display: flex;
1581
+ flex-direction: column;
1582
+ padding: 4px;
1583
+ background: var(--fe-bg);
1584
+ border: 1px solid var(--fe-border);
1585
+ border-radius: var(--fe-radius);
1586
+ box-shadow: var(--fe-shadow);
1587
+ }
1588
+ .fe-breadcrumb__menu-item {
1589
+ text-align: left;
1590
+ background: transparent;
1591
+ border: 0;
1592
+ padding: 6px 10px;
1593
+ border-radius: var(--fe-radius-sm);
1594
+ color: var(--fe-text);
1595
+ font: inherit;
1596
+ font-size: 13px;
1597
+ cursor: pointer;
1598
+ overflow: hidden;
1599
+ text-overflow: ellipsis;
1600
+ white-space: nowrap;
1601
+ }
1602
+ .fe-breadcrumb__menu-item:hover,
1603
+ .fe-breadcrumb__menu-item:focus-visible {
1604
+ background: var(--fe-bg-hover);
1605
+ }
1606
+
1607
+ /* Long folder names shouldn't blow up the crumb row — ellipsize labels. */
1608
+ .fe-breadcrumb__crumb > span:first-child {
1609
+ max-width: 200px;
1610
+ overflow: hidden;
1611
+ text-overflow: ellipsis;
1612
+ white-space: nowrap;
1613
+ }
1614
+ @media (max-width: 640px) {
1615
+ .fe-breadcrumb__crumb > span:first-child {
1616
+ max-width: 110px;
1617
+ }
1618
+ }
1619
+
1620
+ @media (prefers-reduced-motion: reduce) {
1621
+ .fe-modal-enter-active,
1622
+ .fe-modal-leave-active {
1623
+ transition: none !important;
1624
+ }
1625
+ }
1626
+
1627
+
1628
+ /* === cila:b — skeleton loading, state screens, undo snackbar, connection badge === */
1629
+
1630
+ /* Screen-reader-only helper (skeleton announces "loading" without visuals). */
1631
+ .fe-sr-only {
1632
+ position: absolute;
1633
+ width: 1px;
1634
+ height: 1px;
1635
+ padding: 0;
1636
+ margin: -1px;
1637
+ overflow: hidden;
1638
+ clip: rect(0 0 0 0);
1639
+ white-space: nowrap;
1640
+ border: 0;
1641
+ }
1642
+
1643
+ /* ---------- Skeleton (initial load) ---------- */
1644
+
1645
+ .fe__skeleton {
1646
+ min-height: 240px;
1647
+ }
1648
+ .fe-skel {
1649
+ position: relative;
1650
+ overflow: hidden;
1651
+ border-radius: var(--fe-radius-sm);
1652
+ background: color-mix(in srgb, var(--fe-text-muted) 14%, transparent);
1653
+ }
1654
+ .fe-skel::after {
1655
+ content: '';
1656
+ position: absolute;
1657
+ inset: 0;
1658
+ transform: translateX(-100%);
1659
+ background: linear-gradient(
1660
+ 90deg,
1661
+ transparent,
1662
+ color-mix(in srgb, var(--fe-text-muted) 12%, transparent),
1663
+ transparent
1664
+ );
1665
+ animation: fe-skel-shimmer 1.4s ease-in-out infinite;
1666
+ }
1667
+ @keyframes fe-skel-shimmer {
1668
+ to { transform: translateX(100%); }
1669
+ }
1670
+ @media (prefers-reduced-motion: reduce) {
1671
+ /* Static faint blocks — no sweep. */
1672
+ .fe-skel::after {
1673
+ animation: none;
1674
+ content: none;
1675
+ }
1676
+ }
1677
+
1678
+ /* List-mode ghosts mirror .fe-list__row's grid so the swap to real rows
1679
+ doesn't shift the layout. */
1680
+ .fe-skel-list {
1681
+ padding-top: 2px;
1682
+ }
1683
+ .fe-skel-row {
1684
+ display: grid;
1685
+ grid-template-columns: 32px minmax(0, 1fr) 120px 180px;
1686
+ gap: 8px;
1687
+ align-items: center;
1688
+ padding: 12px;
1689
+ border-bottom: 1px solid var(--fe-border);
1690
+ }
1691
+ .fe-skel-row .fe-skel {
1692
+ height: 12px;
1693
+ }
1694
+ .fe-skel-row .fe-skel--icon {
1695
+ width: 20px;
1696
+ height: 20px;
1697
+ border-radius: 6px;
1698
+ }
1699
+ .fe-skel-row .fe-skel--name { width: 55%; }
1700
+ .fe-skel-row:nth-child(2n) .fe-skel--name { width: 38%; }
1701
+ .fe-skel-row:nth-child(3n) .fe-skel--name { width: 70%; }
1702
+ .fe-skel-row .fe-skel--size { width: 56px; justify-self: start; }
1703
+ .fe-skel-row .fe-skel--date { width: 110px; justify-self: start; }
1704
+
1705
+ /* Grid-mode ghosts mirror .fe-grid / .fe-grid__card. */
1706
+ .fe-skel-grid {
1707
+ display: grid;
1708
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
1709
+ gap: var(--fe-gap);
1710
+ padding: var(--fe-gap);
1711
+ }
1712
+ .fe-skel-card {
1713
+ display: flex;
1714
+ flex-direction: column;
1715
+ gap: 8px;
1716
+ padding: 8px;
1717
+ border: 1px solid var(--fe-border);
1718
+ border-radius: var(--fe-radius);
1719
+ background: var(--fe-bg-elev);
1720
+ }
1721
+ .fe-skel-card .fe-skel--thumb {
1722
+ aspect-ratio: 1 / 1;
1723
+ }
1724
+ .fe-skel-card .fe-skel--label {
1725
+ height: 12px;
1726
+ width: 70%;
1727
+ }
1728
+ .fe-skel-card:nth-child(2n) .fe-skel--label { width: 50%; }
1729
+ .fe-skel-card:nth-child(3n) .fe-skel--label { width: 85%; }
1730
+
1731
+ /* ---------- State screens (empty / search-empty / not-found / error) ---------- */
1732
+
1733
+ .fe-state {
1734
+ display: flex;
1735
+ flex-direction: column;
1736
+ align-items: center;
1737
+ justify-content: center;
1738
+ gap: 6px;
1739
+ min-height: 240px;
1740
+ height: 100%;
1741
+ padding: 24px;
1742
+ text-align: center;
1743
+ color: var(--fe-text-muted);
1744
+ }
1745
+ .fe-state__art {
1746
+ color: var(--fe-text-muted);
1747
+ opacity: 0.7;
1748
+ margin-bottom: 4px;
1749
+ flex: 0 0 auto;
1750
+ }
1751
+ .fe-state__title {
1752
+ margin: 2px 0 0;
1753
+ font-size: 15px;
1754
+ font-weight: 600;
1755
+ color: var(--fe-text);
1756
+ }
1757
+ .fe-state__hint {
1758
+ margin: 0;
1759
+ font-size: 13px;
1760
+ max-width: 420px;
1761
+ }
1762
+ .fe-state__path {
1763
+ margin: 0;
1764
+ font-size: 12px;
1765
+ font-family: var(--fe-font-mono);
1766
+ word-break: break-all;
1767
+ max-width: 480px;
1768
+ }
1769
+ .fe-state__actions {
1770
+ margin-top: 12px;
1771
+ display: flex;
1772
+ gap: 8px;
1773
+ }
1774
+
1775
+ /* ---------- Undo snackbar (action-capable toast) ---------- */
1776
+
1777
+ .fe-toast--action {
1778
+ display: flex;
1779
+ align-items: center;
1780
+ gap: 14px;
1781
+ padding: 8px 10px 8px 14px;
1782
+ cursor: pointer;
1783
+ max-width: min(480px, calc(100% - 32px));
1784
+ }
1785
+ .fe-toast__msg {
1786
+ min-width: 0;
1787
+ }
1788
+ .fe-toast__action {
1789
+ flex: 0 0 auto;
1790
+ background: transparent;
1791
+ border: 0;
1792
+ padding: 4px 8px;
1793
+ border-radius: var(--fe-radius-sm);
1794
+ font: inherit;
1795
+ font-weight: 600;
1796
+ color: color-mix(in srgb, var(--fe-primary) 70%, var(--fe-bg));
1797
+ cursor: pointer;
1798
+ }
1799
+ .fe-toast__action:hover {
1800
+ background: color-mix(in srgb, var(--fe-bg) 14%, transparent);
1801
+ }
1802
+ .fe-toast__action:focus-visible {
1803
+ outline: 2px solid var(--fe-bg);
1804
+ outline-offset: 1px;
1805
+ }
1806
+
1807
+ /* ---------- Connection badge (degraded realtime only) ---------- */
1808
+
1809
+ .fe-connbadge {
1810
+ display: inline-flex;
1811
+ align-items: center;
1812
+ gap: 6px;
1813
+ font-size: 12px;
1814
+ line-height: 1.4;
1815
+ color: var(--fe-text-muted);
1816
+ background: var(--fe-bg-elev);
1817
+ border: 1px solid var(--fe-border);
1818
+ border-radius: 999px;
1819
+ padding: 2px 10px;
1820
+ cursor: help;
1821
+ white-space: nowrap;
1822
+ overflow: hidden;
1823
+ text-overflow: ellipsis;
1824
+ max-width: 100%;
1825
+ }
1826
+ .fe-connbadge__dot {
1827
+ flex: 0 0 auto;
1828
+ width: 7px;
1829
+ height: 7px;
1830
+ border-radius: 50%;
1831
+ background: var(--fe-warning, #f59e0b);
1832
+ }
@@ -88,3 +88,73 @@
88
88
  --fe-shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.25);
89
89
  }
90
90
  }
91
+
92
+ /* === cila:a — file-type icon accent tokens (lib/fileIcons families) === */
93
+ :root {
94
+ --fe-icon-folder: #d97706;
95
+ --fe-icon-image: #7c3aed;
96
+ --fe-icon-video: #db2777;
97
+ --fe-icon-audio: #0d9488;
98
+ --fe-icon-pdf: #dc2626;
99
+ --fe-icon-doc: #2563eb;
100
+ --fe-icon-sheet: #16a34a;
101
+ --fe-icon-slides: #ea580c;
102
+ --fe-icon-archive: #78716c;
103
+ --fe-icon-code: #4f46e5;
104
+ --fe-icon-text: #64748b;
105
+ --fe-icon-unknown: #94a3b8;
106
+ }
107
+
108
+ /* Dark values — same selector strategy as the palette blocks above. */
109
+ .fe--theme-dark,
110
+ :root[data-theme='dark'] .fe,
111
+ .fe.fe--theme-dark,
112
+ :root.dark,
113
+ .dark,
114
+ :root.dark .fe,
115
+ .dark .fe,
116
+ .fe-ctx-backdrop--theme-dark,
117
+ .fe-ctx-backdrop--theme-auto[data-prefers-dark='1'] {
118
+ --fe-icon-folder: #fbbf24;
119
+ --fe-icon-image: #a78bfa;
120
+ --fe-icon-video: #f472b6;
121
+ --fe-icon-audio: #2dd4bf;
122
+ --fe-icon-pdf: #f87171;
123
+ --fe-icon-doc: #60a5fa;
124
+ --fe-icon-sheet: #4ade80;
125
+ --fe-icon-slides: #fb923c;
126
+ --fe-icon-archive: #a8a29e;
127
+ --fe-icon-code: #818cf8;
128
+ --fe-icon-text: #94a3b8;
129
+ --fe-icon-unknown: #8b95a7;
130
+ }
131
+
132
+ @media (prefers-color-scheme: dark) {
133
+ .fe:not(.fe--theme-light),
134
+ .fe-ctx-backdrop--theme-auto:not(.fe-ctx-backdrop--theme-light) {
135
+ --fe-icon-folder: #fbbf24;
136
+ --fe-icon-image: #a78bfa;
137
+ --fe-icon-video: #f472b6;
138
+ --fe-icon-audio: #2dd4bf;
139
+ --fe-icon-pdf: #f87171;
140
+ --fe-icon-doc: #60a5fa;
141
+ --fe-icon-sheet: #4ade80;
142
+ --fe-icon-slides: #fb923c;
143
+ --fe-icon-archive: #a8a29e;
144
+ --fe-icon-code: #818cf8;
145
+ --fe-icon-text: #94a3b8;
146
+ --fe-icon-unknown: #8b95a7;
147
+ }
148
+ }
149
+
150
+ /* === cila:b — status tokens === */
151
+ /* Amber status accent (connection badge dot; StarButton already referenced it
152
+ via var(--fe-warning, #f59e0b)). Declared with the SAME value the fallbacks
153
+ used, and identical in light + dark on purpose — amber reads well on both
154
+ palettes, so making the token official changes nothing visually. */
155
+ :root,
156
+ .fe--theme-dark,
157
+ :root.dark,
158
+ .dark {
159
+ --fe-warning: #f59e0b;
160
+ }