@brftech/filex-core 0.13.1 → 0.13.3
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.
- package/dist/{ArchiveViewer-Brzg_0Xj.js → ArchiveViewer-CxdOyBhs.js} +35 -36
- package/dist/ArchiveViewer-CxdOyBhs.js.map +1 -0
- package/dist/{CsvViewer-T7W9mqZB.js → CsvViewer-JG3nzTgf.js} +52 -53
- package/dist/CsvViewer-JG3nzTgf.js.map +1 -0
- package/dist/{DrawioViewer-DReOOHRc.js → DrawioViewer-BEYLdtPG.js} +22 -23
- package/dist/{DrawioViewer-DReOOHRc.js.map → DrawioViewer-BEYLdtPG.js.map} +1 -1
- package/dist/{EpubViewer-yf9zJXXg.js → EpubViewer-BwUDmJm4.js} +31 -32
- package/dist/EpubViewer-BwUDmJm4.js.map +1 -0
- package/dist/{IpynbViewer-Dt_l00CD.js → IpynbViewer-CuHQoAHU.js} +35 -35
- package/dist/IpynbViewer-CuHQoAHU.js.map +1 -0
- package/dist/{MermaidViewer-Nbv27ana.js → MermaidViewer-DLmijDXo.js} +47 -48
- package/dist/MermaidViewer-DLmijDXo.js.map +1 -0
- package/dist/{PsdViewer-1nRpsuvz.js → PsdViewer-D-FM4eNi.js} +38 -39
- package/dist/PsdViewer-D-FM4eNi.js.map +1 -0
- package/dist/{TiffViewer-Djawe0Rq.js → TiffViewer-DOw4z_dO.js} +36 -37
- package/dist/TiffViewer-DOw4z_dO.js.map +1 -0
- package/dist/{Viewer3D-D7EtANiH.js → Viewer3D-CJJJgkuv.js} +15 -16
- package/dist/{Viewer3D-D7EtANiH.js.map → Viewer3D-CJJJgkuv.js.map} +1 -1
- package/dist/filex-core.js +11942 -66
- package/dist/filex-core.js.map +1 -1
- package/dist/filex-core.umd.cjs +29 -29
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/PresenceBar.vue +13 -5
- package/src/components/RecentlyOpened.vue +9 -1
- package/src/components/StarButton.vue +9 -1
- package/src/components/TagPicker.vue +9 -1
- package/src/modals/ConvertModal.vue +10 -2
- package/src/modals/PermissionsModal.vue +9 -1
- package/src/viewers/ArchiveViewer.vue +9 -1
- package/src/viewers/CsvViewer.vue +9 -1
- package/src/viewers/DrawioViewer.vue +9 -1
- package/src/viewers/EpubViewer.vue +9 -1
- package/src/viewers/IpynbViewer.vue +9 -1
- package/src/viewers/MermaidViewer.vue +10 -2
- package/src/viewers/PdfViewer.vue +9 -1
- package/src/viewers/PsdViewer.vue +9 -1
- package/src/viewers/TiffViewer.vue +9 -1
- package/src/viewers/Viewer3D.vue +10 -2
- package/dist/ArchiveViewer-Brzg_0Xj.js.map +0 -1
- package/dist/CsvViewer-T7W9mqZB.js.map +0 -1
- package/dist/EpubViewer-yf9zJXXg.js.map +0 -1
- package/dist/IpynbViewer-Dt_l00CD.js.map +0 -1
- package/dist/MermaidViewer-Nbv27ana.js.map +0 -1
- package/dist/PsdViewer-1nRpsuvz.js.map +0 -1
- package/dist/TiffViewer-Djawe0Rq.js.map +0 -1
- package/dist/index-DeVgQCwW.js +0 -11951
- package/dist/index-DeVgQCwW.js.map +0 -1
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { defineComponent as y, ref as d, onMounted as k, watch as b, computed as p, openBlock as s, createElementBlock as n, createElementVNode as t, toDisplayString as
|
|
2
|
-
|
|
3
|
-
const B = { class: "filex-viewer-archive" }, F = {
|
|
1
|
+
import { defineComponent as y, ref as d, onMounted as k, watch as b, computed as p, openBlock as s, createElementBlock as n, createElementVNode as t, toDisplayString as a, Fragment as g, renderList as z, createTextVNode as C } from "vue";
|
|
2
|
+
const S = { class: "filex-viewer-archive" }, B = {
|
|
4
3
|
key: 0,
|
|
5
4
|
class: "filex-viewer-fallback"
|
|
6
|
-
},
|
|
5
|
+
}, F = {
|
|
7
6
|
key: 1,
|
|
8
7
|
class: "filex-viewer-fallback"
|
|
9
|
-
},
|
|
8
|
+
}, $ = {
|
|
10
9
|
key: 2,
|
|
11
10
|
class: "filex-viewer-fallback"
|
|
12
|
-
},
|
|
11
|
+
}, P = {
|
|
13
12
|
key: 3,
|
|
14
13
|
class: "filex-viewer-archive__pane"
|
|
15
|
-
},
|
|
14
|
+
}, E = { class: "filex-viewer-archive__summary" }, N = { class: "filex-viewer-archive__table" }, T = { class: "filex-viewer-archive__size" }, H = ["data-dir"], V = { class: "filex-viewer-archive__icon" }, j = { class: "filex-viewer-archive__size" }, L = /* @__PURE__ */ y({
|
|
16
15
|
__name: "ArchiveViewer",
|
|
17
16
|
props: {
|
|
18
17
|
url: {},
|
|
@@ -23,27 +22,27 @@ const B = { class: "filex-viewer-archive" }, F = {
|
|
|
23
22
|
authCredentials: {}
|
|
24
23
|
},
|
|
25
24
|
setup(w) {
|
|
26
|
-
const
|
|
25
|
+
const r = w, o = d([]), v = d(!0), c = d(null);
|
|
27
26
|
function l(e, i) {
|
|
28
|
-
return
|
|
27
|
+
return r.t ? r.t(e) : i;
|
|
29
28
|
}
|
|
30
29
|
function f(e) {
|
|
31
30
|
return e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(1)} KB` : e < 1024 * 1024 * 1024 ? `${(e / (1024 * 1024)).toFixed(1)} MB` : `${(e / (1024 * 1024 * 1024)).toFixed(2)} GB`;
|
|
32
31
|
}
|
|
33
32
|
async function _() {
|
|
34
|
-
if (v.value = !0, c.value = null, o.value = [], !
|
|
33
|
+
if (v.value = !0, c.value = null, o.value = [], !r.filePath) {
|
|
35
34
|
c.value = l("viewer.archive.error", "Could not read archive contents."), v.value = !1;
|
|
36
35
|
return;
|
|
37
36
|
}
|
|
38
37
|
try {
|
|
39
38
|
const e = await fetch("/api/files/archive/list", {
|
|
40
39
|
method: "POST",
|
|
41
|
-
credentials:
|
|
40
|
+
credentials: r.authCredentials || "same-origin",
|
|
42
41
|
headers: {
|
|
43
42
|
"Content-Type": "application/json",
|
|
44
|
-
...
|
|
43
|
+
...r.authHeaders ? r.authHeaders() : {}
|
|
45
44
|
},
|
|
46
|
-
body: JSON.stringify({ path:
|
|
45
|
+
body: JSON.stringify({ path: r.filePath })
|
|
47
46
|
});
|
|
48
47
|
if (!e.ok)
|
|
49
48
|
throw new Error(`${e.status} ${e.statusText}`);
|
|
@@ -55,45 +54,45 @@ const B = { class: "filex-viewer-archive" }, F = {
|
|
|
55
54
|
v.value = !1;
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
|
-
k(_), b(() =>
|
|
59
|
-
const
|
|
60
|
-
return (e, i) => (s(), n("div",
|
|
61
|
-
c.value ? (s(), n("div",
|
|
57
|
+
k(_), b(() => r.filePath, _);
|
|
58
|
+
const x = p(() => o.value.reduce((e, i) => e + (i.size || 0), 0)), h = p(() => o.value.filter((e) => !e.is_dir).length);
|
|
59
|
+
return (e, i) => (s(), n("div", S, [
|
|
60
|
+
c.value ? (s(), n("div", B, [
|
|
62
61
|
i[0] || (i[0] = t("span", { class: "filex-viewer-fallback__icon" }, "🗜️", -1)),
|
|
63
|
-
t("p", null,
|
|
64
|
-
])) : v.value ? (s(), n("div",
|
|
62
|
+
t("p", null, a(c.value), 1)
|
|
63
|
+
])) : v.value ? (s(), n("div", F, [
|
|
65
64
|
i[1] || (i[1] = t("span", { class: "filex-viewer-fallback__icon" }, "⏳", -1)),
|
|
66
|
-
t("p", null,
|
|
67
|
-
])) : o.value.length === 0 ? (s(), n("div",
|
|
65
|
+
t("p", null, a(l("viewer.loading", "Loading…")), 1)
|
|
66
|
+
])) : o.value.length === 0 ? (s(), n("div", $, [
|
|
68
67
|
i[2] || (i[2] = t("span", { class: "filex-viewer-fallback__icon" }, "🗜️", -1)),
|
|
69
|
-
t("p", null,
|
|
70
|
-
])) : (s(), n("div",
|
|
71
|
-
t("div",
|
|
72
|
-
t("table",
|
|
68
|
+
t("p", null, a(l("viewer.archive.empty", "Archive is empty.")), 1)
|
|
69
|
+
])) : (s(), n("div", P, [
|
|
70
|
+
t("div", E, a(h.value) + " " + a(l("viewer.archive.entries", "{n} files").replace("{n}", String(h.value))) + " · " + a(f(x.value)), 1),
|
|
71
|
+
t("table", N, [
|
|
73
72
|
t("thead", null, [
|
|
74
73
|
t("tr", null, [
|
|
75
|
-
t("th", null,
|
|
76
|
-
t("th",
|
|
74
|
+
t("th", null, a(l("viewer.name", "Name")), 1),
|
|
75
|
+
t("th", T, a(l("viewer.size", "Size")), 1)
|
|
77
76
|
])
|
|
78
77
|
]),
|
|
79
78
|
t("tbody", null, [
|
|
80
|
-
(s(!0), n(g, null, z(o.value, (u,
|
|
81
|
-
key:
|
|
79
|
+
(s(!0), n(g, null, z(o.value, (u, m) => (s(), n("tr", {
|
|
80
|
+
key: m,
|
|
82
81
|
"data-dir": u.is_dir ? "1" : "0"
|
|
83
82
|
}, [
|
|
84
83
|
t("td", null, [
|
|
85
|
-
t("span",
|
|
86
|
-
C(" " +
|
|
84
|
+
t("span", V, a(u.is_dir ? "📁" : "📄"), 1),
|
|
85
|
+
C(" " + a(u.name), 1)
|
|
87
86
|
]),
|
|
88
|
-
t("td", j,
|
|
89
|
-
], 8,
|
|
87
|
+
t("td", j, a(u.is_dir ? "" : f(u.size)), 1)
|
|
88
|
+
], 8, H))), 128))
|
|
90
89
|
])
|
|
91
90
|
])
|
|
92
91
|
]))
|
|
93
92
|
]));
|
|
94
93
|
}
|
|
95
|
-
})
|
|
94
|
+
});
|
|
96
95
|
export {
|
|
97
|
-
|
|
96
|
+
L as default
|
|
98
97
|
};
|
|
99
|
-
//# sourceMappingURL=ArchiveViewer-
|
|
98
|
+
//# sourceMappingURL=ArchiveViewer-CxdOyBhs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchiveViewer-CxdOyBhs.js","sources":["../src/viewers/ArchiveViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * ArchiveViewer — minimal zip / archive contents preview.\n *\n * Hits `POST /api/files/archive/list` with the adapter-qualified path\n * and renders the member list as a flat table (name, size, mtime).\n * Read-only — extraction is exposed elsewhere (context menu / actions\n * panel). The viewer's job is just \"what's inside?\" so the user can\n * decide whether to extract or download.\n */\nimport { computed, onMounted, ref, watch } from 'vue';\n\ninterface ArchiveEntry {\n name: string;\n size: number;\n mtime?: string;\n is_dir?: boolean;\n}\n\nconst props = defineProps<{\n url: string;\n filePath?: string;\n ext: string;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string>;\n authCredentials?: RequestCredentials;\n}>();\n\nconst entries = ref<ArchiveEntry[]>([]);\nconst loading = ref(true);\nconst error = ref<string | null>(null);\n\nfunction tt(key: string, fallback: string): string {\n return props.t ? props.t(key) : fallback;\n}\n\nfunction fmtSize(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;\n}\n\nasync function load(): Promise<void> {\n loading.value = true;\n error.value = null;\n entries.value = [];\n // The viewer is mounted with the resolved file path. Hit the API\n // endpoint with the same adapter-qualified path the preview URL\n // points at — the backend resolves storage + relative path itself.\n if (!props.filePath) {\n error.value = tt('viewer.archive.error', 'Could not read archive contents.');\n loading.value = false;\n return;\n }\n try {\n const res = await fetch('/api/files/archive/list', {\n method: 'POST',\n credentials: props.authCredentials || 'same-origin',\n headers: {\n 'Content-Type': 'application/json',\n ...(props.authHeaders ? props.authHeaders() : {}),\n },\n body: JSON.stringify({ path: props.filePath }),\n });\n if (!res.ok) {\n throw new Error(`${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as { entries?: ArchiveEntry[] };\n entries.value = body.entries ?? [];\n } catch (err) {\n error.value = err instanceof Error ? err.message : tt('viewer.archive.error', 'Could not read archive contents.');\n } finally {\n loading.value = false;\n }\n}\n\nonMounted(load);\nwatch(() => props.filePath, load);\n\nconst totalSize = computed(() => entries.value.reduce((sum, e) => sum + (e.size || 0), 0));\nconst fileCount = computed(() => entries.value.filter((e) => !e.is_dir).length);\n</script>\n\n<template>\n <div class=\"filex-viewer-archive\">\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 <div v-else-if=\"entries.length === 0\" class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">🗜️</span>\n <p>{{ tt('viewer.archive.empty', 'Archive is empty.') }}</p>\n </div>\n <div v-else class=\"filex-viewer-archive__pane\">\n <div class=\"filex-viewer-archive__summary\">\n {{ fileCount }} {{ tt('viewer.archive.entries', '{n} files').replace('{n}', String(fileCount)) }}\n · {{ fmtSize(totalSize) }}\n </div>\n <table class=\"filex-viewer-archive__table\">\n <thead>\n <tr>\n <th>{{ tt('viewer.name', 'Name') }}</th>\n <th class=\"filex-viewer-archive__size\">{{ tt('viewer.size', 'Size') }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(e, i) in entries\" :key=\"i\" :data-dir=\"e.is_dir ? '1' : '0'\">\n <td>\n <span class=\"filex-viewer-archive__icon\">{{ e.is_dir ? '📁' : '📄' }}</span>\n {{ e.name }}\n </td>\n <td class=\"filex-viewer-archive__size\">{{ e.is_dir ? '' : fmtSize(e.size) }}</td>\n </tr>\n </tbody>\n </table>\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-archive {\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-archive__pane {\n flex: 1;\n overflow: auto;\n padding: 16px 20px;\n}\n.filex-viewer-archive__summary {\n font-size: 12px;\n color: var(--fe-text-muted, #5a6475);\n margin-bottom: 12px;\n font-variant-numeric: tabular-nums;\n}\n.filex-viewer-archive__table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n font-family: var(--fe-font-mono, monospace);\n}\n.filex-viewer-archive__table th,\n.filex-viewer-archive__table td {\n padding: 6px 12px;\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n text-align: left;\n}\n.filex-viewer-archive__table th {\n background: var(--fe-bg-elev, #f7f8fa);\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n.filex-viewer-archive__size {\n text-align: right;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-archive__icon {\n margin-right: 6px;\n}\n.filex-viewer-archive__table tr[data-dir=\"1\"] {\n color: var(--fe-text-muted, #5a6475);\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","entries","ref","loading","error","tt","key","fallback","fmtSize","n","load","res","body","err","onMounted","watch","totalSize","computed","sum","e","fileCount","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_cache","_createElementVNode","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_toDisplayString","_hoisted_7","_hoisted_8","_Fragment","_renderList","i","_hoisted_10","_hoisted_11"],"mappings":"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"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { defineComponent as B, ref as v, onMounted as N, watch as y, computed as
|
|
1
|
+
import { defineComponent as B, ref as v, onMounted as N, watch as y, computed as p, openBlock as s, createElementBlock as r, createElementVNode as a, toDisplayString as d, Fragment as k, renderList as C, createCommentVNode as S } from "vue";
|
|
2
2
|
import { f as W } from "./useViewerFetch-czqbd2Lj.js";
|
|
3
|
-
|
|
4
|
-
const q = { class: "filex-viewer-csv" }, A = { class: "filex-viewer-csv__pane" }, G = {
|
|
3
|
+
const j = { class: "filex-viewer-csv" }, q = { class: "filex-viewer-csv__pane" }, A = {
|
|
5
4
|
key: 0,
|
|
6
5
|
class: "filex-viewer-fallback"
|
|
7
|
-
},
|
|
6
|
+
}, G = {
|
|
8
7
|
key: 1,
|
|
9
8
|
class: "filex-viewer-fallback"
|
|
10
|
-
},
|
|
9
|
+
}, O = {
|
|
11
10
|
key: 2,
|
|
12
11
|
class: "filex-viewer-csv__table"
|
|
13
|
-
},
|
|
12
|
+
}, Z = { class: "filex-viewer-csv__rownum" }, z = {
|
|
14
13
|
key: 0,
|
|
15
14
|
class: "filex-viewer-csv__pager"
|
|
16
|
-
},
|
|
15
|
+
}, J = ["disabled"], K = { class: "filex-viewer-csv__pageno" }, Q = ["disabled"], L = 100, R = 1e3, Y = /* @__PURE__ */ B({
|
|
17
16
|
__name: "CsvViewer",
|
|
18
17
|
props: {
|
|
19
18
|
url: {},
|
|
@@ -22,15 +21,15 @@ const q = { class: "filex-viewer-csv" }, A = { class: "filex-viewer-csv__pane" }
|
|
|
22
21
|
authHeaders: { type: Function },
|
|
23
22
|
authCredentials: {}
|
|
24
23
|
},
|
|
25
|
-
setup(
|
|
26
|
-
const
|
|
27
|
-
let
|
|
28
|
-
function
|
|
24
|
+
setup(T) {
|
|
25
|
+
const u = T, i = v([]), f = v(null), m = v(!0), E = v(!0), D = v(""), o = v(1), _ = v(","), h = v("auto");
|
|
26
|
+
let M = 0;
|
|
27
|
+
function V(l) {
|
|
29
28
|
const e = l.split(/\r?\n/).slice(0, 5).join(`
|
|
30
|
-
`), t = (e.match(/\t/g) || []).length,
|
|
31
|
-
return t > c && t >
|
|
29
|
+
`), t = (e.match(/\t/g) || []).length, n = (e.match(/;/g) || []).length, c = (e.match(/,/g) || []).length;
|
|
30
|
+
return t > c && t > n ? " " : n > c && n > t ? ";" : ",";
|
|
32
31
|
}
|
|
33
|
-
async function
|
|
32
|
+
async function F(l, e) {
|
|
34
33
|
try {
|
|
35
34
|
const t = await import(
|
|
36
35
|
/* @vite-ignore */
|
|
@@ -40,93 +39,93 @@ const q = { class: "filex-viewer-csv" }, A = { class: "filex-viewer-csv__pane" }
|
|
|
40
39
|
delimiter: e,
|
|
41
40
|
skipEmptyLines: !0,
|
|
42
41
|
header: !1
|
|
43
|
-
}).data.slice(0,
|
|
42
|
+
}).data.slice(0, R);
|
|
44
43
|
} catch {
|
|
45
|
-
return l.split(/\r?\n/).filter((t) => t.length > 0).slice(0,
|
|
44
|
+
return l.split(/\r?\n/).filter((t) => t.length > 0).slice(0, R).map((t) => t.split(e));
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
async function w() {
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
-
const l = ++
|
|
48
|
+
var n;
|
|
49
|
+
m.value = !0, f.value = null, i.value = [], o.value = 1;
|
|
50
|
+
const l = ++M;
|
|
52
51
|
let e;
|
|
53
52
|
try {
|
|
54
53
|
e = await W({
|
|
55
|
-
url:
|
|
56
|
-
headers: ((
|
|
57
|
-
credentials:
|
|
54
|
+
url: u.url,
|
|
55
|
+
headers: ((n = u.authHeaders) == null ? void 0 : n.call(u)) ?? {},
|
|
56
|
+
credentials: u.authCredentials
|
|
58
57
|
});
|
|
59
58
|
} catch (c) {
|
|
60
|
-
f.value = c instanceof Error ? c.message : "fetch failed",
|
|
59
|
+
f.value = c instanceof Error ? c.message : "fetch failed", m.value = !1;
|
|
61
60
|
return;
|
|
62
61
|
}
|
|
63
|
-
if (l !==
|
|
64
|
-
|
|
65
|
-
const t = h.value === "auto" ?
|
|
66
|
-
|
|
62
|
+
if (l !== M) return;
|
|
63
|
+
u.ext === "tsv" ? _.value = " " : _.value = V(e.slice(0, 4096));
|
|
64
|
+
const t = h.value === "auto" ? _.value : h.value;
|
|
65
|
+
i.value = await F(e, t), m.value = !1;
|
|
67
66
|
}
|
|
68
|
-
N(w), y(() =>
|
|
69
|
-
|
|
67
|
+
N(w), y(() => u.url, w), y(() => h.value, () => {
|
|
68
|
+
i.value.length !== 0 && w();
|
|
70
69
|
});
|
|
71
|
-
const
|
|
72
|
-
const l =
|
|
73
|
-
return l ?
|
|
70
|
+
const H = p(() => !E.value || i.value.length === 0 ? i.value.length === 0 ? [] : i.value[0].map((l, e) => `Col ${e + 1}`) : i.value[0]), P = p(() => E.value ? i.value.slice(1) : i.value), g = p(() => {
|
|
71
|
+
const l = D.value.trim().toLowerCase();
|
|
72
|
+
return l ? P.value.filter(
|
|
74
73
|
(e) => e.some((t) => (t || "").toLowerCase().includes(l))
|
|
75
|
-
) :
|
|
76
|
-
}), b =
|
|
74
|
+
) : P.value;
|
|
75
|
+
}), b = p(
|
|
77
76
|
() => Math.max(1, Math.ceil(g.value.length / L))
|
|
78
|
-
),
|
|
77
|
+
), I = p(() => {
|
|
79
78
|
const l = (o.value - 1) * L;
|
|
80
79
|
return g.value.slice(l, l + L);
|
|
81
80
|
});
|
|
82
|
-
y(
|
|
81
|
+
y(D, () => {
|
|
83
82
|
o.value = 1;
|
|
84
83
|
});
|
|
85
84
|
function $(l, e) {
|
|
86
|
-
return
|
|
85
|
+
return u.t ? u.t(l) : e;
|
|
87
86
|
}
|
|
88
|
-
return (l, e) => (
|
|
89
|
-
a("div",
|
|
90
|
-
f.value ? (
|
|
87
|
+
return (l, e) => (s(), r("div", j, [
|
|
88
|
+
a("div", q, [
|
|
89
|
+
f.value ? (s(), r("div", A, [
|
|
91
90
|
e[2] || (e[2] = a("span", { class: "filex-viewer-fallback__icon" }, "📊", -1)),
|
|
92
91
|
a("p", null, d(f.value), 1)
|
|
93
|
-
])) :
|
|
92
|
+
])) : m.value ? (s(), r("div", G, [
|
|
94
93
|
e[3] || (e[3] = a("span", { class: "filex-viewer-fallback__icon" }, "⏳", -1)),
|
|
95
94
|
a("p", null, d($("viewer.loading", "Loading…")), 1)
|
|
96
|
-
])) : (
|
|
95
|
+
])) : (s(), r("table", O, [
|
|
97
96
|
a("thead", null, [
|
|
98
97
|
a("tr", null, [
|
|
99
98
|
e[4] || (e[4] = a("th", { class: "filex-viewer-csv__rownum" }, "#", -1)),
|
|
100
|
-
(
|
|
99
|
+
(s(!0), r(k, null, C(H.value, (t, n) => (s(), r("th", { key: n }, d(t), 1))), 128))
|
|
101
100
|
])
|
|
102
101
|
]),
|
|
103
102
|
a("tbody", null, [
|
|
104
|
-
(
|
|
105
|
-
a("td",
|
|
106
|
-
(
|
|
103
|
+
(s(!0), r(k, null, C(I.value, (t, n) => (s(), r("tr", { key: n }, [
|
|
104
|
+
a("td", Z, d((o.value - 1) * 100 + n + 1), 1),
|
|
105
|
+
(s(!0), r(k, null, C(t, (c, x) => (s(), r("td", { key: x }, d(c), 1))), 128))
|
|
107
106
|
]))), 128))
|
|
108
107
|
])
|
|
109
108
|
]))
|
|
110
109
|
]),
|
|
111
|
-
!
|
|
110
|
+
!m.value && !f.value && b.value > 1 ? (s(), r("div", z, [
|
|
112
111
|
a("button", {
|
|
113
112
|
type: "button",
|
|
114
113
|
class: "filex-viewer-btn",
|
|
115
114
|
disabled: o.value <= 1,
|
|
116
115
|
onClick: e[0] || (e[0] = (t) => o.value--)
|
|
117
|
-
}, "‹", 8,
|
|
118
|
-
a("span",
|
|
116
|
+
}, "‹", 8, J),
|
|
117
|
+
a("span", K, d(o.value) + " / " + d(b.value) + " (" + d(g.value.length) + " satır)", 1),
|
|
119
118
|
a("button", {
|
|
120
119
|
type: "button",
|
|
121
120
|
class: "filex-viewer-btn",
|
|
122
121
|
disabled: o.value >= b.value,
|
|
123
122
|
onClick: e[1] || (e[1] = (t) => o.value++)
|
|
124
|
-
}, "›", 8,
|
|
123
|
+
}, "›", 8, Q)
|
|
125
124
|
])) : S("", !0)
|
|
126
125
|
]));
|
|
127
126
|
}
|
|
128
|
-
})
|
|
127
|
+
});
|
|
129
128
|
export {
|
|
130
|
-
|
|
129
|
+
Y as default
|
|
131
130
|
};
|
|
132
|
-
//# sourceMappingURL=CsvViewer-
|
|
131
|
+
//# sourceMappingURL=CsvViewer-JG3nzTgf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CsvViewer-JG3nzTgf.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>;\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: 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":"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"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { defineComponent as U, ref as
|
|
1
|
+
import { defineComponent as U, ref as s, computed as h, onMounted as E, watch as S, onBeforeUnmount as B, openBlock as d, createElementBlock as u, createElementVNode as g, toDisplayString as O } from "vue";
|
|
2
2
|
import { f as C } from "./useViewerFetch-czqbd2Lj.js";
|
|
3
|
-
import { _ as D } from "./index-DeVgQCwW.js";
|
|
4
3
|
const T = { class: "filex-viewer-drawio" }, $ = {
|
|
5
4
|
key: 0,
|
|
6
5
|
class: "filex-viewer-fallback"
|
|
7
|
-
},
|
|
6
|
+
}, D = ["src"], R = /* @__PURE__ */ U({
|
|
8
7
|
__name: "DrawioViewer",
|
|
9
8
|
props: {
|
|
10
9
|
url: {},
|
|
@@ -17,11 +16,11 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
17
16
|
authHeaders: { type: Function },
|
|
18
17
|
authCredentials: {}
|
|
19
18
|
},
|
|
20
|
-
setup(
|
|
21
|
-
const e =
|
|
19
|
+
setup(x) {
|
|
20
|
+
const e = x, c = s(null), i = s(null), n = s("loading"), f = s(!!e.readOnly || !e.saveUrl), o = h(
|
|
22
21
|
() => e.drawioUrl ? e.drawioUrl.replace(/\/$/, "") : null
|
|
23
|
-
),
|
|
24
|
-
if (!
|
|
22
|
+
), _ = h(() => {
|
|
23
|
+
if (!o.value) return "";
|
|
25
24
|
const a = new URLSearchParams({
|
|
26
25
|
embed: "1",
|
|
27
26
|
proto: "json",
|
|
@@ -32,10 +31,10 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
32
31
|
ui: "kennedy",
|
|
33
32
|
modified: "unsavedChanges"
|
|
34
33
|
});
|
|
35
|
-
return `${
|
|
34
|
+
return `${o.value}/?${a.toString()}`;
|
|
36
35
|
});
|
|
37
36
|
let v = "";
|
|
38
|
-
async function
|
|
37
|
+
async function k() {
|
|
39
38
|
var a;
|
|
40
39
|
n.value = "loading", i.value = null;
|
|
41
40
|
try {
|
|
@@ -48,7 +47,7 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
48
47
|
i.value = t instanceof Error ? t.message : "fetch failed", n.value = "error";
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
function
|
|
50
|
+
function b(a) {
|
|
52
51
|
var t, r;
|
|
53
52
|
(r = (t = c.value) == null ? void 0 : t.contentWindow) == null || r.postMessage(JSON.stringify(a), "*");
|
|
54
53
|
}
|
|
@@ -89,7 +88,7 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
89
88
|
if (!(!r || typeof r != "object"))
|
|
90
89
|
switch (r.event) {
|
|
91
90
|
case "init":
|
|
92
|
-
|
|
91
|
+
b({
|
|
93
92
|
action: "load",
|
|
94
93
|
xml: v,
|
|
95
94
|
autosave: 0
|
|
@@ -105,19 +104,19 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
105
104
|
break;
|
|
106
105
|
}
|
|
107
106
|
}
|
|
108
|
-
function
|
|
109
|
-
if (!
|
|
110
|
-
i.value =
|
|
107
|
+
function y() {
|
|
108
|
+
if (!o.value) {
|
|
109
|
+
i.value = p("viewer.drawio.disabled", "Drawio (diagrams.net) yapılandırılmamış."), n.value = "error";
|
|
111
110
|
return;
|
|
112
111
|
}
|
|
113
|
-
i.value ===
|
|
112
|
+
i.value === p("viewer.drawio.disabled", "Drawio (diagrams.net) yapılandırılmamış.") && (i.value = null, n.value = "loading"), k();
|
|
114
113
|
}
|
|
115
114
|
E(() => {
|
|
116
|
-
window.addEventListener("message", w),
|
|
117
|
-
}), S(() => e.drawioUrl,
|
|
115
|
+
window.addEventListener("message", w), y();
|
|
116
|
+
}), S(() => e.drawioUrl, y), B(() => {
|
|
118
117
|
window.removeEventListener("message", w);
|
|
119
118
|
});
|
|
120
|
-
function
|
|
119
|
+
function p(a, t) {
|
|
121
120
|
return e.t ? e.t(a) : t;
|
|
122
121
|
}
|
|
123
122
|
return (a, t) => (d(), u("div", T, [
|
|
@@ -128,14 +127,14 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
128
127
|
key: 1,
|
|
129
128
|
ref_key: "iframeRef",
|
|
130
129
|
ref: c,
|
|
131
|
-
src:
|
|
130
|
+
src: _.value,
|
|
132
131
|
class: "filex-viewer-drawio__frame",
|
|
133
132
|
title: "diagrams.net editor"
|
|
134
|
-
}, null, 8,
|
|
133
|
+
}, null, 8, D))
|
|
135
134
|
]));
|
|
136
135
|
}
|
|
137
|
-
})
|
|
136
|
+
});
|
|
138
137
|
export {
|
|
139
|
-
|
|
138
|
+
R as default
|
|
140
139
|
};
|
|
141
|
-
//# sourceMappingURL=DrawioViewer-
|
|
140
|
+
//# sourceMappingURL=DrawioViewer-BEYLdtPG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrawioViewer-DReOOHRc.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>;\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: 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 ...(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 scoped>\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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"}
|
|
1
|
+
{"version":3,"file":"DrawioViewer-BEYLdtPG.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>;\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: 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 ...(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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"}
|