@brftech/filex-core 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/{CsvViewer-DxujFEM3.js → CsvViewer-CqWeV8VO.js} +22 -22
  2. package/dist/CsvViewer-CqWeV8VO.js.map +1 -0
  3. package/dist/{DrawioViewer-DCvWnX2t.js → DrawioViewer-BNALOB04.js} +16 -16
  4. package/dist/DrawioViewer-BNALOB04.js.map +1 -0
  5. package/dist/filex-core.js +5932 -5841
  6. package/dist/filex-core.js.map +1 -1
  7. package/dist/filex-core.umd.cjs +43 -43
  8. package/dist/filex-core.umd.cjs.map +1 -1
  9. package/dist/index.d.ts +49 -8
  10. package/package.json +1 -1
  11. package/src/FileExplorer.vue +267 -235
  12. package/src/components/CommandPalette.vue +3 -3
  13. package/src/components/ConnectionsPanel.vue +2 -1
  14. package/src/components/GalleryView.vue +3 -3
  15. package/src/components/GridView.vue +4 -4
  16. package/src/components/ListView.vue +4 -4
  17. package/src/components/NFSExportsPanel.vue +2 -1
  18. package/src/components/PendingOpsTray.vue +1 -1
  19. package/src/components/PresenceBar.vue +3 -2
  20. package/src/components/S3KeysPanel.vue +2 -1
  21. package/src/components/SSHKeysPanel.vue +2 -1
  22. package/src/components/SecondaryPane.vue +13 -12
  23. package/src/components/StarButton.vue +2 -1
  24. package/src/components/TabBar.vue +2 -2
  25. package/src/components/ThemeGallery.vue +1 -1
  26. package/src/components/TokensPanel.vue +2 -1
  27. package/src/components/Toolbar.vue +9 -9
  28. package/src/composables/useFileApi.ts +4 -2
  29. package/src/composables/useLocale.ts +1 -1
  30. package/src/composables/useOperations.ts +3 -3
  31. package/src/composables/usePendingOps.ts +1 -1
  32. package/src/composables/useTabs.ts +1 -1
  33. package/src/composables/useUploadChunked.ts +39 -7
  34. package/src/index.ts +2 -2
  35. package/src/lib/themes.ts +7 -7
  36. package/src/lib/transfer.ts +6 -6
  37. package/src/locales/en.ts +32 -0
  38. package/src/locales/index.ts +1 -0
  39. package/src/locales/resolve.ts +66 -0
  40. package/src/locales/tr.ts +33 -0
  41. package/src/modals/ConvertModal.vue +14 -12
  42. package/src/modals/NewFolderModal.vue +1 -1
  43. package/src/modals/PermissionsModal.vue +12 -11
  44. package/src/modals/PreviewModal.vue +9 -9
  45. package/src/styles/base.css +29 -26
  46. package/src/styles/variables.css +1 -1
  47. package/src/types/ExplorerConfig.ts +1 -1
  48. package/src/types/FileNode.ts +1 -1
  49. package/src/viewers/CsvViewer.vue +4 -4
  50. package/src/viewers/DrawioViewer.vue +2 -2
  51. package/dist/CsvViewer-DxujFEM3.js.map +0 -1
  52. package/dist/DrawioViewer-DCvWnX2t.js.map +0 -1
@@ -275,7 +275,7 @@ filex-explorer {
275
275
  .fe-toolbar__spacer {
276
276
  flex: 1 1 auto;
277
277
  }
278
- /* Search + Yükle + Yenile pinned together so the cluster doesn't get
278
+ /* Search + Upload + Refresh pinned together so the cluster doesn't get
279
279
  * orphaned by the wrap point on narrow widths. */
280
280
  .fe-toolbar__search-group {
281
281
  display: inline-flex;
@@ -342,8 +342,9 @@ filex-explorer {
342
342
  gap: 4px;
343
343
  flex-wrap: wrap;
344
344
  padding: 6px 12px;
345
- /* ui-fix — split'te yan panel .fe-split__crumbs ile aynı yükseklik (ana
346
- panelin "Yola Git" butonu yoksa da satırlar aynı y'den başlasın). */
345
+ /* ui-fix — same height as the side pane's .fe-split__crumbs in split mode
346
+ (so both rows start at the same y even without the main pane's "Yola Git"
347
+ ✏ button). */
347
348
  min-height: 37px;
348
349
  background: var(--fe-bg);
349
350
  border-bottom: 1px solid var(--fe-border);
@@ -373,7 +374,7 @@ filex-explorer {
373
374
  .fe-breadcrumb__sep {
374
375
  color: var(--fe-text-muted);
375
376
  }
376
- /* Edit pencil button — V1.5: "yolu yazıp gideyim" */
377
+ /* Edit pencil button — V1.5, verbatim (translated): "let me type a path and go" */
377
378
  .fe-breadcrumb__edit {
378
379
  margin-left: auto;
379
380
  background: none;
@@ -2952,7 +2953,7 @@ filex-explorer {
2952
2953
  }
2953
2954
  }
2954
2955
  /* /wiring:c3 */
2955
- /* === wiring:c4 — onboarding turu, erişilebilirlik ve etkileşim cilası === */
2956
+ /* === wiring:c4 — onboarding tour, accessibility and interaction polish === */
2956
2957
 
2957
2958
  /* ---------- Focus ring: grid cards (list rows already had one) ---------- */
2958
2959
  .fe-grid__card:focus-visible {
@@ -3164,7 +3165,7 @@ filex-explorer {
3164
3165
  }
3165
3166
  /* === /wiring:c4 === */
3166
3167
 
3167
- /* === wiring:d1 — sekmeler (tab şeridi) + split panel === */
3168
+ /* === wiring:d1 — tabs (tab strip) + split pane === */
3168
3169
 
3169
3170
  /* Tab strip — thin row ABOVE the toolbar. The host renders it only with
3170
3171
  2+ tabs, so the default single-tab embed stays pixel-identical. */
@@ -3331,9 +3332,9 @@ filex-explorer {
3331
3332
  display: none;
3332
3333
  }
3333
3334
 
3334
- /* ui-fix — sol panel sarmalı: breadcrumb + durum şeritleri + body bir
3335
- flex-column. Split olmadan tüm genişlik; split olunca sol yarı (böylece
3336
- breadcrumb kendi panelini kaplar, SecondaryPane ile simetrik). */
3335
+ /* ui-fix — left pane wrapper: breadcrumb + status strips + body in one
3336
+ flex-column. Full width without split; the left half once split (so the
3337
+ breadcrumb spans its own pane only, symmetric with SecondaryPane). */
3337
3338
  .fe__primary {
3338
3339
  display: flex;
3339
3340
  flex-direction: column;
@@ -3373,12 +3374,13 @@ filex-explorer {
3373
3374
  .fe-split__crumbs {
3374
3375
  display: flex;
3375
3376
  align-items: center;
3376
- /* ui-fix — ana panel .fe-breadcrumb ile BİREBİR aynı ölçüler (gap/padding/
3377
- font) → split'te iki breadcrumb tam hizalı, ince kayma yok. */
3377
+ /* ui-fix — EXACTLY the same metrics as the main pane's .fe-breadcrumb
3378
+ (gap/padding/font) → in split mode the two breadcrumbs line up perfectly,
3379
+ with no hairline drift. */
3378
3380
  gap: 4px;
3379
3381
  flex: 0 0 auto;
3380
3382
  padding: 6px 12px;
3381
- min-height: 37px; /* ui-fix — ana panel .fe-breadcrumb ile aynı yükseklik */
3383
+ min-height: 37px; /* ui-fix — same height as the main pane's .fe-breadcrumb */
3382
3384
  border-bottom: 1px solid var(--fe-border);
3383
3385
  font-size: 13px;
3384
3386
  color: var(--fe-text-muted);
@@ -3390,7 +3392,7 @@ filex-explorer {
3390
3392
  background: transparent;
3391
3393
  color: inherit;
3392
3394
  font: inherit;
3393
- padding: 2px 6px; /* ui-fix — .fe-breadcrumb__crumb ile aynı */
3395
+ padding: 2px 6px; /* ui-fix — same as .fe-breadcrumb__crumb */
3394
3396
  border-radius: var(--fe-radius-sm);
3395
3397
  cursor: pointer;
3396
3398
  max-width: 140px;
@@ -3506,9 +3508,9 @@ filex-explorer {
3506
3508
  }
3507
3509
  /* === /wiring:d1 === */
3508
3510
 
3509
- /* === wiring:d2 — galeri görünümü (GalleryView.vue) === */
3511
+ /* === wiring:d2 — gallery view (GalleryView.vue) === */
3510
3512
 
3511
- /* Büyük thumbnail ızgarası: kare kartlar, ad altta, boyut+tarih hover'da. */
3513
+ /* Large thumbnail grid: square cards, name below, size+date on hover. */
3512
3514
  .fe-gal {
3513
3515
  display: grid;
3514
3516
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
@@ -3573,8 +3575,9 @@ filex-explorer {
3573
3575
  width: 64px;
3574
3576
  height: 64px;
3575
3577
  }
3576
- /* Hover meta bandıthumbnail'ın altına oturan yarı saydam şerit; yalnız
3577
- hover/klavye odağında görünür (dokunmatikte kartın title'ı yeterli). */
3578
+ /* Hover meta banda translucent strip sitting at the bottom of the
3579
+ thumbnail; visible only on hover/keyboard focus (on touch the card's
3580
+ title is enough). */
3578
3581
  .fe-gal__meta {
3579
3582
  position: absolute;
3580
3583
  left: 0;
@@ -3622,11 +3625,11 @@ filex-explorer {
3622
3625
  text-align: center;
3623
3626
  color: var(--fe-text-muted);
3624
3627
  }
3625
- /* Dar/embed mini modda daha küçük döşemeler (2-3 sütun sığar). */
3628
+ /* Smaller tiles in narrow/embed mini mode (2-3 columns fit). */
3626
3629
  .fe--narrow .fe-gal {
3627
3630
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
3628
3631
  }
3629
- /* Yoğunluk: kompakt tercihte döşemeler küçülür (grid'le aynı mantık). */
3632
+ /* Density: tiles shrink under the compact preference (same logic as grid). */
3630
3633
  .fe--density-compact .fe-gal {
3631
3634
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
3632
3635
  gap: calc(var(--fe-gap) * 0.6);
@@ -3750,8 +3753,8 @@ filex-explorer {
3750
3753
  }
3751
3754
  /* === /wiring:d3 === */
3752
3755
 
3753
- /* === wiring:e2 — uçtan uca şifreli klasörler === */
3754
- /* Kilit açık şeridi (presence şeridiyle aynı yatay dil). */
3756
+ /* === wiring:e2 — end-to-end encrypted folders === */
3757
+ /* Unlocked strip (same horizontal language as the presence strip). */
3755
3758
  .fe-e2e-strip {
3756
3759
  display: flex;
3757
3760
  align-items: center;
@@ -3777,7 +3780,7 @@ filex-explorer {
3777
3780
  font-size: 12px;
3778
3781
  }
3779
3782
 
3780
- /* Kilit ekranı: fe-state dilinin üstüne parola formu. */
3783
+ /* Lock screen: a passphrase form on top of the fe-state language. */
3781
3784
  .fe-e2e-lock__form {
3782
3785
  display: flex;
3783
3786
  gap: 8px;
@@ -3790,7 +3793,7 @@ filex-explorer {
3790
3793
  min-width: 0;
3791
3794
  }
3792
3795
 
3793
- /* Şifreli klasör oluşturma modalı. */
3796
+ /* Encrypted-folder creation modal. */
3794
3797
  .fe-e2e-form {
3795
3798
  display: flex;
3796
3799
  flex-direction: column;
@@ -3826,7 +3829,7 @@ filex-explorer {
3826
3829
  accent-color: var(--fe-primary);
3827
3830
  }
3828
3831
 
3829
- /* NewFolderModal içindeki "şifreli klasör" giriş linki. */
3832
+ /* The "şifreli klasör" (encrypted folder) entry link inside NewFolderModal. */
3830
3833
  .fe-e2e-optlink {
3831
3834
  margin-top: 10px;
3832
3835
  padding: 0;
@@ -4034,7 +4037,7 @@ filex-explorer {
4034
4037
  }
4035
4038
  /* === /wiring:e2 === */
4036
4039
 
4037
- /* === ui-fix — toolbar tek satır + katlama + ölçüm şeridi ============= */
4040
+ /* === ui-fix — toolbar single row + folding + measure strip ============ */
4038
4041
  .fe:not(.fe--narrow) .fe-toolbar {
4039
4042
  flex-wrap: nowrap;
4040
4043
  }
@@ -4061,7 +4064,7 @@ filex-explorer {
4061
4064
  /* === /ui-fix ========================================================= */
4062
4065
 
4063
4066
 
4064
- /* === wiring:c1 — gündüz / gece / otomatik =============================
4067
+ /* === wiring:c1 — day / night / auto ====================================
4065
4068
  Lives at the top of the theme gallery: "night mode" is what people open the
4066
4069
  theme button looking for, and a palette picker that cannot answer that
4067
4070
  question is the wrong place to stop. */
@@ -106,7 +106,7 @@
106
106
  --fe-icon-archive: #78716c;
107
107
  --fe-icon-code: #4f46e5;
108
108
  --fe-icon-text: #64748b;
109
- --fe-icon-unknown: #64748b; /* ui-fix: acik temada 3:1 UI kontrasti */
109
+ --fe-icon-unknown: #64748b; /* ui-fix: 3:1 UI contrast on the light theme */
110
110
  }
111
111
 
112
112
  /* Dark values — same selector strategy as the palette blocks above. */
@@ -137,7 +137,7 @@ export interface ExplorerConfig {
137
137
  onlyOfficeConfig?: string;
138
138
 
139
139
  /**
140
- * Standalone editor page base — when set, "" on an office file
140
+ * Standalone editor page base — when set, "Open" on an office file
141
141
  * opens `${openPageBase}?path=...&mode=edit` in a new tab instead
142
142
  * of the modal preview.
143
143
  */
@@ -146,7 +146,7 @@ export interface ArchiveEntry {
146
146
  lastModified?: number;
147
147
  }
148
148
 
149
- export type ViewMode = 'list' | 'grid' | 'gallery'; /* wiring:d2 — üçüncü görünüm: galeri */
149
+ export type ViewMode = 'list' | 'grid' | 'gallery'; /* wiring:d2 — the third view: gallery */
150
150
 
151
151
  export interface ClipboardState {
152
152
  mode: 'cut' | 'copy' | null;
@@ -19,7 +19,7 @@ import { fetchViewerText } from '../composables/useViewerFetch';
19
19
  const props = defineProps<{
20
20
  url: string;
21
21
  ext: string;
22
- t?: (key: string) => string;
22
+ t?: (key: string, vars?: Record<string, string | number>) => string;
23
23
  authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
24
24
  authCredentials?: RequestCredentials;
25
25
  }>();
@@ -144,8 +144,8 @@ watch(filter, () => {
144
144
  page.value = 1;
145
145
  });
146
146
 
147
- function tt(key: string, fallback: string): string {
148
- return props.t ? props.t(key) : fallback;
147
+ function tt(key: string, fallback: string, vars?: Record<string, string | number>): string {
148
+ return props.t ? props.t(key, vars) : fallback;
149
149
  }
150
150
  </script>
151
151
 
@@ -182,7 +182,7 @@ function tt(key: string, fallback: string): string {
182
182
  :disabled="page <= 1"
183
183
  @click="page--"
184
184
  >‹</button>
185
- <span class="filex-viewer-csv__pageno">{{ page }} / {{ totalPages }} ({{ filtered.length }} satır)</span>
185
+ <span class="filex-viewer-csv__pageno">{{ page }} / {{ totalPages }} ({{ tt('viewer.csv_rows', `${filtered.length} rows`, { n: filtered.length }) }})</span>
186
186
  <button
187
187
  type="button"
188
188
  class="filex-viewer-btn"
@@ -153,13 +153,13 @@ function onMessage(ev: MessageEvent): void {
153
153
 
154
154
  function bootIfReady(): void {
155
155
  if (!drawioBase.value) {
156
- error.value = tt('viewer.drawio.disabled', 'Drawio (diagrams.net) yapılandırılmamış.');
156
+ error.value = tt('viewer.drawio.disabled', 'diagrams.net is not configured for this filex instance.');
157
157
  status.value = 'error';
158
158
  return;
159
159
  }
160
160
  // Clear a previous "disabled" error in case the prop just became
161
161
  // available (capability probe finished after mount).
162
- if (error.value === tt('viewer.drawio.disabled', 'Drawio (diagrams.net) yapılandırılmamış.')) {
162
+ if (error.value === tt('viewer.drawio.disabled', 'diagrams.net is not configured for this filex instance.')) {
163
163
  error.value = null;
164
164
  status.value = 'loading';
165
165
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"CsvViewer-DxujFEM3.js","sources":["../src/viewers/CsvViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * CsvViewer — lightweight CSV / TSV table preview.\n *\n * Lazy-imports `papaparse` when available (best-quality parser — handles\n * embedded quotes, multi-line cells, etc). Falls back to a simple\n * `split` parser when the peer is missing — workable for the trivial\n * \"first 1000 rows\" preview case but loses fidelity on complex files.\n *\n * UX:\n * - first-row-as-header toggle\n * - filter input that case-insensitively matches any cell\n * - 100-rows-per-page pagination\n * - tab vs comma auto-detection (manual override via toolbar)\n */\nimport { computed, onMounted, ref, watch } from 'vue';\nimport { fetchViewerText } from '../composables/useViewerFetch';\n\nconst props = defineProps<{\n url: string;\n ext: string;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n authCredentials?: RequestCredentials;\n}>();\n\nconst PAGE_SIZE = 100;\nconst ROW_LIMIT = 1000;\n\nconst rows = ref<string[][]>([]);\nconst error = ref<string | null>(null);\nconst loading = ref(true);\nconst firstRowHeader = ref(true);\nconst filter = ref('');\nconst page = ref(1);\nconst detectedDelim = ref<',' | '\\t' | ';'>(',');\nconst userDelim = ref<'auto' | ',' | '\\t' | ';'>('auto');\n\nlet renderToken = 0;\n\nfunction detectDelimiter(sample: string): ',' | '\\t' | ';' {\n const sampleLines = sample.split(/\\r?\\n/).slice(0, 5).join('\\n');\n const tab = (sampleLines.match(/\\t/g) || []).length;\n const semi = (sampleLines.match(/;/g) || []).length;\n const comma = (sampleLines.match(/,/g) || []).length;\n if (tab > comma && tab > semi) return '\\t';\n if (semi > comma && semi > tab) return ';';\n return ',';\n}\n\nasync function parseWith(text: string, delim: string): Promise<string[][]> {\n try {\n const mod = await import(/* @vite-ignore */ 'papaparse');\n const Papa = (mod as any).default ?? mod;\n const result = Papa.parse(text, {\n delimiter: delim,\n skipEmptyLines: true,\n header: false,\n });\n return (result.data as string[][]).slice(0, ROW_LIMIT);\n } catch {\n // Fallback: naive line/column split. Loses quoted-comma support\n // but renders something reasonable.\n return text\n .split(/\\r?\\n/)\n .filter((l) => l.length > 0)\n .slice(0, ROW_LIMIT)\n .map((line) => line.split(delim));\n }\n}\n\nasync function load(): Promise<void> {\n loading.value = true;\n error.value = null;\n rows.value = [];\n page.value = 1;\n const myToken = ++renderToken;\n\n let text: string;\n try {\n text = await fetchViewerText({\n url: props.url,\n headers: (await props.authHeaders?.()) ?? {},\n credentials: props.authCredentials,\n });\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'fetch failed';\n loading.value = false;\n return;\n }\n\n if (myToken !== renderToken) return;\n\n if (props.ext === 'tsv') {\n detectedDelim.value = '\\t';\n } else {\n detectedDelim.value = detectDelimiter(text.slice(0, 4096));\n }\n\n const delim = userDelim.value === 'auto' ? detectedDelim.value : userDelim.value;\n rows.value = await parseWith(text, delim);\n loading.value = false;\n}\n\nonMounted(load);\nwatch(() => props.url, load);\nwatch(() => userDelim.value, () => {\n if (rows.value.length === 0) return;\n // Re-parse with the new delimiter using the cached source — but we\n // didn't keep it. Cheapest path is a refetch.\n load();\n});\n\nconst headers = computed<string[]>(() => {\n if (!firstRowHeader.value || rows.value.length === 0) {\n if (rows.value.length === 0) return [];\n return rows.value[0].map((_, i) => `Col ${i + 1}`);\n }\n return rows.value[0];\n});\n\nconst dataRows = computed<string[][]>(() => {\n return firstRowHeader.value ? rows.value.slice(1) : rows.value;\n});\n\nconst filtered = computed<string[][]>(() => {\n const q = filter.value.trim().toLowerCase();\n if (!q) return dataRows.value;\n return dataRows.value.filter((r) =>\n r.some((c) => (c || '').toLowerCase().includes(q)),\n );\n});\n\nconst totalPages = computed(() =>\n Math.max(1, Math.ceil(filtered.value.length / PAGE_SIZE)),\n);\n\nconst visibleRows = computed<string[][]>(() => {\n const start = (page.value - 1) * PAGE_SIZE;\n return filtered.value.slice(start, start + PAGE_SIZE);\n});\n\nwatch(filter, () => {\n page.value = 1;\n});\n\nfunction tt(key: string, fallback: string): string {\n return props.t ? props.t(key) : fallback;\n}\n</script>\n\n<template>\n <div class=\"filex-viewer-csv\">\n <div class=\"filex-viewer-csv__pane\">\n <div v-if=\"error\" class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">📊</span>\n <p>{{ error }}</p>\n </div>\n <div v-else-if=\"loading\" class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">⏳</span>\n <p>{{ tt('viewer.loading', 'Loading…') }}</p>\n </div>\n <table v-else class=\"filex-viewer-csv__table\">\n <thead>\n <tr>\n <th class=\"filex-viewer-csv__rownum\">#</th>\n <th v-for=\"(h, i) in headers\" :key=\"i\">{{ h }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, ri) in visibleRows\" :key=\"ri\">\n <td class=\"filex-viewer-csv__rownum\">{{ (page - 1) * 100 + ri + 1 }}</td>\n <td v-for=\"(c, ci) in row\" :key=\"ci\">{{ c }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n <div v-if=\"!loading && !error && totalPages > 1\" class=\"filex-viewer-csv__pager\">\n <button\n type=\"button\"\n class=\"filex-viewer-btn\"\n :disabled=\"page <= 1\"\n @click=\"page--\"\n >‹</button>\n <span class=\"filex-viewer-csv__pageno\">{{ page }} / {{ totalPages }} ({{ filtered.length }} satır)</span>\n <button\n type=\"button\"\n class=\"filex-viewer-btn\"\n :disabled=\"page >= totalPages\"\n @click=\"page++\"\n >›</button>\n </div>\n </div>\n</template>\n\n<style>\n/* ⚠ NOT `scoped`, deliberately. Vue's scoped styles compile to\n `.cls[data-v-HASH]`, and in the web-component build the hash baked into\n this CSS does not match the one Vue stamps onto the DOM — so every rule\n here silently stopped applying. Measured in the desktop app: the share\n dialog had `position: static`, no background and no radius, i.e. raw\n unstyled HTML, in EVERY embedded surface.\n Safe to drop: every selector below is prefixed (fx-/fe-/filex-), so\n there is nothing here that can leak into a host page. */\n.filex-viewer-csv {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 70vh;\n background: var(--fe-bg, #fff);\n color: var(--fe-text, #1a1e27);\n}\n.filex-viewer-csv__bar {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n font-size: 12px;\n}\n.filex-viewer-csv__check {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n}\n.filex-viewer-csv__select,\n.filex-viewer-csv__filter {\n border: 1px solid var(--fe-border, #e2e6ed);\n background: var(--fe-bg, #fff);\n color: inherit;\n padding: 4px 8px;\n border-radius: 4px;\n font: inherit;\n font-size: 12px;\n}\n.filex-viewer-csv__filter {\n flex: 0 1 240px;\n}\n.filex-viewer-spacer { flex: 1; }\n.filex-viewer-csv__count {\n font-size: 11px;\n color: var(--fe-text-muted, #5a6475);\n font-variant-numeric: tabular-nums;\n}\n.filex-viewer-csv__pane {\n flex: 1;\n overflow: auto;\n}\n.filex-viewer-csv__table {\n border-collapse: collapse;\n width: max-content;\n min-width: 100%;\n font-size: 12px;\n font-family: var(--fe-font-mono, monospace);\n}\n.filex-viewer-csv__table th,\n.filex-viewer-csv__table td {\n padding: 4px 10px;\n border: 1px solid var(--fe-border, #e2e6ed);\n white-space: nowrap;\n max-width: 320px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.filex-viewer-csv__table th {\n background: var(--fe-bg-elev, #f7f8fa);\n position: sticky;\n top: 0;\n font-weight: 600;\n text-align: left;\n}\n.filex-viewer-csv__table tbody tr:nth-child(even) {\n background: var(--fe-bg-hover, rgba(0, 0, 0, 0.02));\n}\n.filex-viewer-csv__rownum {\n color: var(--fe-text-muted, #5a6475);\n text-align: right;\n background: var(--fe-bg-elev, #f7f8fa);\n font-variant-numeric: tabular-nums;\n position: sticky;\n left: 0;\n}\n.filex-viewer-csv__pager {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 8px;\n padding: 6px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-top: 1px solid var(--fe-border, #e2e6ed);\n font-size: 12px;\n}\n.filex-viewer-csv__pageno {\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n}\n.filex-viewer-fallback {\n text-align: center;\n padding: 32px;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-fallback__icon {\n font-size: 48px;\n display: block;\n margin-bottom: 12px;\n}\n.filex-viewer-btn {\n border: 1px solid var(--fe-border, #e2e6ed);\n background: var(--fe-bg, #fff);\n color: var(--fe-text, #1a1e27);\n padding: 4px 10px;\n border-radius: 4px;\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n}\n.filex-viewer-btn:hover:not(:disabled) {\n background: var(--fe-bg-hover, #edf0f5);\n}\n.filex-viewer-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n</style>\n"],"names":["PAGE_SIZE","ROW_LIMIT","props","__props","rows","ref","error","loading","firstRowHeader","filter","page","detectedDelim","userDelim","renderToken","detectDelimiter","sample","sampleLines","tab","semi","comma","parseWith","text","delim","mod","n","l","line","load","myToken","fetchViewerText","_a","err","onMounted","watch","headers","computed","_","i","dataRows","filtered","q","r","c","totalPages","visibleRows","start","tt","key","fallback","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_cache","_hoisted_4","_hoisted_5","_Fragment","_renderList","h","row","ri","_hoisted_6","_toDisplayString","ci","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10"],"mappings":";;;;;;;;;;;;;;kFA0BMA,IAAY,KACZC,IAAY;;;;;;;;;;AATlB,UAAMC,IAAQC,GAWRC,IAAOC,EAAgB,EAAE,GACzBC,IAAQD,EAAmB,IAAI,GAC/BE,IAAUF,EAAI,EAAI,GAClBG,IAAiBH,EAAI,EAAI,GACzBI,IAASJ,EAAI,EAAE,GACfK,IAAOL,EAAI,CAAC,GACZM,IAAgBN,EAAsB,GAAG,GACzCO,IAAYP,EAA+B,MAAM;AAEvD,QAAIQ,IAAc;AAElB,aAASC,EAAgBC,GAAkC;AACzD,YAAMC,IAAcD,EAAO,MAAM,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK;AAAA,CAAI,GACzDE,KAAOD,EAAY,MAAM,KAAK,KAAK,CAAA,GAAI,QACvCE,KAAQF,EAAY,MAAM,IAAI,KAAK,CAAA,GAAI,QACvCG,KAASH,EAAY,MAAM,IAAI,KAAK,CAAA,GAAI;AAC9C,aAAIC,IAAME,KAASF,IAAMC,IAAa,MAClCA,IAAOC,KAASD,IAAOD,IAAY,MAChC;AAAA,IACT;AAEA,mBAAeG,EAAUC,GAAcC,GAAoC;AACzE,UAAI;AACF,cAAMC,IAAM,MAAM;AAAA;AAAA,UAA0B;AAAA,QAAA,EAAA,KAAA,CAAAC,MAAAA,EAAA,CAAA;AAO5C,gBANcD,EAAY,WAAWA,GACjB,MAAMF,GAAM;AAAA,UAC9B,WAAWC;AAAA,UACX,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QAAA,CACT,EACc,KAAoB,MAAM,GAAGrB,CAAS;AAAA,MACvD,QAAQ;AAGN,eAAOoB,EACJ,MAAM,OAAO,EACb,OAAO,CAACI,MAAMA,EAAE,SAAS,CAAC,EAC1B,MAAM,GAAGxB,CAAS,EAClB,IAAI,CAACyB,MAASA,EAAK,MAAMJ,CAAK,CAAC;AAAA,MACpC;AAAA,IACF;AAEA,mBAAeK,IAAsB;;AACnC,MAAApB,EAAQ,QAAQ,IAChBD,EAAM,QAAQ,MACdF,EAAK,QAAQ,CAAA,GACbM,EAAK,QAAQ;AACb,YAAMkB,IAAU,EAAEf;AAElB,UAAIQ;AACJ,UAAI;AACF,QAAAA,IAAO,MAAMQ,EAAgB;AAAA,UAC3B,KAAK3B,EAAM;AAAA,UACX,SAAU,QAAM4B,IAAA5B,EAAM,gBAAN,gBAAA4B,EAAA,KAAA5B,OAA0B,CAAA;AAAA,UAC1C,aAAaA,EAAM;AAAA,QAAA,CACpB;AAAA,MACH,SAAS6B,GAAK;AACZ,QAAAzB,EAAM,QAAQyB,aAAe,QAAQA,EAAI,UAAU,gBACnDxB,EAAQ,QAAQ;AAChB;AAAA,MACF;AAEA,UAAIqB,MAAYf,EAAa;AAE7B,MAAIX,EAAM,QAAQ,QAChBS,EAAc,QAAQ,MAEtBA,EAAc,QAAQG,EAAgBO,EAAK,MAAM,GAAG,IAAI,CAAC;AAG3D,YAAMC,IAAQV,EAAU,UAAU,SAASD,EAAc,QAAQC,EAAU;AAC3E,MAAAR,EAAK,QAAQ,MAAMgB,EAAUC,GAAMC,CAAK,GACxCf,EAAQ,QAAQ;AAAA,IAClB;AAEA,IAAAyB,EAAUL,CAAI,GACdM,EAAM,MAAM/B,EAAM,KAAKyB,CAAI,GAC3BM,EAAM,MAAMrB,EAAU,OAAO,MAAM;AACjC,MAAIR,EAAK,MAAM,WAAW,KAG1BuB,EAAA;AAAA,IACF,CAAC;AAED,UAAMO,IAAUC,EAAmB,MAC7B,CAAC3B,EAAe,SAASJ,EAAK,MAAM,WAAW,IAC7CA,EAAK,MAAM,WAAW,IAAU,CAAA,IAC7BA,EAAK,MAAM,CAAC,EAAE,IAAI,CAACgC,GAAGC,MAAM,OAAOA,IAAI,CAAC,EAAE,IAE5CjC,EAAK,MAAM,CAAC,CACpB,GAEKkC,IAAWH,EAAqB,MAC7B3B,EAAe,QAAQJ,EAAK,MAAM,MAAM,CAAC,IAAIA,EAAK,KAC1D,GAEKmC,IAAWJ,EAAqB,MAAM;AAC1C,YAAMK,IAAI/B,EAAO,MAAM,KAAA,EAAO,YAAA;AAC9B,aAAK+B,IACEF,EAAS,MAAM;AAAA,QAAO,CAACG,MAC5BA,EAAE,KAAK,CAACC,OAAOA,KAAK,IAAI,cAAc,SAASF,CAAC,CAAC;AAAA,MAAA,IAFpCF,EAAS;AAAA,IAI1B,CAAC,GAEKK,IAAaR;AAAA,MAAS,MAC1B,KAAK,IAAI,GAAG,KAAK,KAAKI,EAAS,MAAM,SAASvC,CAAS,CAAC;AAAA,IAAA,GAGpD4C,IAAcT,EAAqB,MAAM;AAC7C,YAAMU,KAASnC,EAAK,QAAQ,KAAKV;AACjC,aAAOuC,EAAS,MAAM,MAAMM,GAAOA,IAAQ7C,CAAS;AAAA,IACtD,CAAC;AAED,IAAAiC,EAAMxB,GAAQ,MAAM;AAClB,MAAAC,EAAK,QAAQ;AAAA,IACf,CAAC;AAED,aAASoC,EAAGC,GAAaC,GAA0B;AACjD,aAAO9C,EAAM,IAAIA,EAAM,EAAE6C,CAAG,IAAIC;AAAA,IAClC;sBAIEC,EAAA,GAAAC,EAwCM,OAxCNC,GAwCM;AAAA,MAvCJC,EAuBM,OAvBNC,GAuBM;AAAA,QAtBO/C,EAAA,SAAX2C,EAAA,GAAAC,EAGM,OAHNI,GAGM;AAAA,UAFJC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAAmD,QAAA,EAA7C,OAAM,8BAAA,GAA8B,MAAE,EAAA;AAAA,UAC5CA,EAAkB,aAAZ9C,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA,MAEGC,EAAA,SAAhB0C,KAAAC,EAGM,OAHNM,GAGM;AAAA,UAFJD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAAkD,QAAA,EAA5C,OAAM,8BAAA,GAA8B,KAAC,EAAA;AAAA,UAC3CA,EAA6C,aAAvCN,EAAE,kBAAA,UAAA,CAAA,GAAA,CAAA;AAAA,QAAA,OAEVG,EAAA,GAAAC,EAaQ,SAbRO,GAaQ;AAAA,UAZNL,EAKQ,SAAA,MAAA;AAAA,YAJNA,EAGK,MAAA,MAAA;AAAA,cAFHG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAA2C,MAAA,EAAvC,OAAM,2BAAA,GAA2B,KAAC,EAAA;AAAA,eACtCH,EAAA,EAAA,GAAAC,EAAmDQ,GAAA,MAAAC,EAA9BzB,EAAA,OAAO,CAAhB0B,GAAGvB,OAAfY,EAAA,GAAAC,EAAmD,MAAA,EAApB,KAAKb,EAAA,KAAMuB,CAAC,GAAA,CAAA;;;UAG/CR,EAKQ,SAAA,MAAA;AAAA,aAJNH,EAAA,EAAA,GAAAC,EAGKQ,GAAA,MAAAC,EAHmBf,EAAA,OAAW,CAAvBiB,GAAKC,YAAjBZ,EAGK,MAAA,EAHiC,KAAKY,KAAE;AAAA,cAC3CV,EAAyE,MAAzEW,GAAyEC,GAAhCtD,EAAA,mBAAkBoD,IAAE,CAAA,GAAA,CAAA;AAAA,eAC7Db,EAAA,EAAA,GAAAC,EAAiDQ,GAAA,MAAAC,EAA3BE,GAAG,CAAb,GAAGI,OAAfhB,EAAA,GAAAC,EAAiD,MAAA,EAArB,KAAKe,EAAA,KAAO,CAAC,GAAA,CAAA;;;;;OAKrC1D,EAAA,SAAO,CAAKD,EAAA,SAASqC,EAAA,QAAU,KAA3CM,EAAA,GAAAC,EAcM,OAdNgB,GAcM;AAAA,QAbJd,EAKW,UAAA;AAAA,UAJT,MAAK;AAAA,UACL,OAAM;AAAA,UACL,UAAU1C,EAAA,SAAI;AAAA,UACd,gCAAOA,EAAA;AAAA,QAAA,GACT,KAAC,GAAAyD,CAAA;AAAA,QACFf,EAAyG,QAAzGgB,GAAyGJ,EAA/DtD,EAAA,KAAI,IAAG,QAAGsD,EAAGrB,EAAA,KAAU,IAAG,OAAEqB,EAAGzB,EAAA,MAAS,MAAM,IAAG,WAAO,CAAA;AAAA,QAClGa,EAKW,UAAA;AAAA,UAJT,MAAK;AAAA,UACL,OAAM;AAAA,UACL,UAAU1C,EAAA,SAAQiC,EAAA;AAAA,UAClB,gCAAOjC,EAAA;AAAA,QAAA,GACT,KAAC,GAAA2D,CAAA;AAAA,MAAA;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DrawioViewer-DCvWnX2t.js","sources":["../src/viewers/DrawioViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * DrawioViewer — embed diagrams.net via iframe + postMessage handshake.\n *\n * The diagrams.net embed mode (`?embed=1&proto=json`) handshakes via\n * window.postMessage:\n *\n * 1. iframe sends {event:'init'} ← bootstrap\n * 2. parent sends {action:'load', xml} ← our payload\n * 3. iframe sends {event:'save', xml} on save ← we POST back\n *\n * No external library required — diagrams.net hosts the entire editor\n * inside the iframe. We just fetch the source XML on mount and route\n * `save` events back to the configured `pdfSaveUrl`-style endpoint\n * (drawio uses the same shape: POST `{path, content}` body).\n */\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport { fetchViewerText } from '../composables/useViewerFetch';\n\nconst props = defineProps<{\n url: string;\n filePath: string;\n ext: string;\n drawioUrl?: string;\n /** Optional save endpoint. When unset the iframe stays read-only. */\n saveUrl?: string;\n readOnly?: boolean;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n authCredentials?: RequestCredentials;\n}>();\n\nconst iframeRef = ref<HTMLIFrameElement | null>(null);\nconst error = ref<string | null>(null);\nconst status = ref<'loading' | 'ready' | 'saving' | 'saved' | 'error'>('loading');\nconst readOnly = ref(!!props.readOnly || !props.saveUrl);\n\n// drawioUrl=null is the operator's \"off\" signal — FileExplorer wipes it\n// when the capabilities probe reports drawio offline. Don't silently fall\n// back to the public embed.diagrams.net iframe, that defeats the point of\n// gating: render a \"not configured\" pane instead so the user understands\n// why the editor isn't loading.\n//\n// `drawioBase` MUST be a computed (not a const), otherwise a stale null\n// at mount time (capabilities probe still inflight) gets cached for the\n// component's lifetime — leading to the spurious\n// \"viewer.drawio.disabled\" fallback after the capability flips to \"ok\".\nconst drawioBase = computed<string | null>(() =>\n props.drawioUrl ? props.drawioUrl.replace(/\\/$/, '') : null,\n);\nconst iframeSrc = computed<string>(() => {\n if (!drawioBase.value) return '';\n const params = new URLSearchParams({\n embed: '1',\n proto: 'json',\n spin: '1',\n saveAndExit: '0',\n noSaveBtn: readOnly.value ? '1' : '0',\n noExitBtn: '1',\n ui: 'kennedy',\n modified: 'unsavedChanges',\n });\n return `${drawioBase.value}/?${params.toString()}`;\n});\n\nlet pendingXml: string = '';\n\nasync function loadXml(): Promise<void> {\n status.value = 'loading';\n error.value = null;\n try {\n pendingXml = await fetchViewerText({\n url: props.url,\n headers: (await props.authHeaders?.()) ?? {},\n credentials: props.authCredentials,\n });\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'fetch failed';\n status.value = 'error';\n }\n}\n\nfunction send(msg: unknown): void {\n iframeRef.value?.contentWindow?.postMessage(JSON.stringify(msg), '*');\n}\n\nasync function persist(xml: string): Promise<void> {\n if (!props.saveUrl) return;\n status.value = 'saving';\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...((await props.authHeaders?.()) ?? {}),\n };\n const res = await fetch(props.saveUrl, {\n method: 'POST',\n headers,\n credentials: props.authCredentials || 'same-origin',\n body: JSON.stringify({ path: props.filePath, content: xml }),\n });\n if (!res.ok) {\n throw new Error(`${res.status} ${res.statusText}`);\n }\n status.value = 'saved';\n setTimeout(() => {\n if (status.value === 'saved') status.value = 'ready';\n }, 2500);\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'save failed';\n status.value = 'error';\n }\n}\n\nfunction onMessage(ev: MessageEvent): void {\n if (typeof ev.data !== 'string' || ev.data.length === 0) return;\n // Drawio messages always start with '{' or '<'. Ignore anything else\n // (devtools / unrelated postMessage senders inside the same window).\n const first = ev.data[0];\n if (first !== '{' && first !== '<') return;\n let payload: any;\n try {\n payload = JSON.parse(ev.data);\n } catch {\n return;\n }\n if (!payload || typeof payload !== 'object') return;\n switch (payload.event) {\n case 'init':\n send({\n action: 'load',\n xml: pendingXml,\n autosave: 0,\n });\n status.value = 'ready';\n break;\n case 'save':\n if (typeof payload.xml === 'string') {\n persist(payload.xml);\n }\n break;\n case 'export':\n // Could persist a PNG/SVG render; out of V1 scope.\n break;\n case 'autosave':\n if (typeof payload.xml === 'string' && !readOnly.value) {\n persist(payload.xml);\n }\n break;\n default:\n break;\n }\n}\n\nfunction bootIfReady(): void {\n if (!drawioBase.value) {\n error.value = tt('viewer.drawio.disabled', 'Drawio (diagrams.net) yapılandırılmamış.');\n status.value = 'error';\n return;\n }\n // Clear a previous \"disabled\" error in case the prop just became\n // available (capability probe finished after mount).\n if (error.value === tt('viewer.drawio.disabled', 'Drawio (diagrams.net) yapılandırılmamış.')) {\n error.value = null;\n status.value = 'loading';\n }\n loadXml();\n}\n\nonMounted(() => {\n window.addEventListener('message', onMessage);\n bootIfReady();\n});\n\nwatch(() => props.drawioUrl, bootIfReady);\n\nonBeforeUnmount(() => {\n window.removeEventListener('message', onMessage);\n});\n\nfunction tt(key: string, fallback: string): string {\n return props.t ? props.t(key) : fallback;\n}\n</script>\n\n<template>\n <div class=\"filex-viewer-drawio\">\n <div v-if=\"error\" class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">📐</span>\n <p>{{ error }}</p>\n </div>\n <iframe\n v-else\n ref=\"iframeRef\"\n :src=\"iframeSrc\"\n class=\"filex-viewer-drawio__frame\"\n title=\"diagrams.net editor\"\n />\n </div>\n</template>\n\n<style>\n/* ⚠ NOT `scoped`, deliberately. Vue's scoped styles compile to\n `.cls[data-v-HASH]`, and in the web-component build the hash baked into\n this CSS does not match the one Vue stamps onto the DOM — so every rule\n here silently stopped applying. Measured in the desktop app: the share\n dialog had `position: static`, no background and no radius, i.e. raw\n unstyled HTML, in EVERY embedded surface.\n Safe to drop: every selector below is prefixed (fx-/fe-/filex-), so\n there is nothing here that can leak into a host page. */\n.filex-viewer-drawio {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 70vh;\n background: var(--fe-bg, #fff);\n}\n.filex-viewer-drawio__bar {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 6px 12px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n font-size: 12px;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-drawio__status[data-state=\"error\"] { color: var(--fe-danger, #dc2626); }\n.filex-viewer-drawio__status[data-state=\"saved\"] { color: #059669; }\n.filex-viewer-drawio__readonly {\n font-style: italic;\n margin-left: auto;\n}\n.filex-viewer-drawio__frame {\n flex: 1;\n width: 100%;\n border: 0;\n background: #fafafa;\n min-height: 0;\n}\n.filex-viewer-fallback {\n text-align: center;\n padding: 32px;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-fallback__icon {\n font-size: 48px;\n display: block;\n margin-bottom: 12px;\n}\n</style>\n"],"names":["props","__props","iframeRef","ref","error","status","readOnly","drawioBase","computed","iframeSrc","params","pendingXml","loadXml","fetchViewerText","_a","err","send","msg","_b","persist","xml","headers","res","onMessage","ev","first","payload","bootIfReady","tt","onMounted","watch","onBeforeUnmount","key","fallback","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_cache","_createElementVNode"],"mappings":"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"}