@brftech/filex 0.1.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/ArchiveViewer-CMaBM4yZ.js +98 -0
- package/dist/ArchiveViewer-CMaBM4yZ.js.map +1 -0
- package/dist/CsvViewer-D5_c7bkP.js +131 -0
- package/dist/CsvViewer-D5_c7bkP.js.map +1 -0
- package/dist/DrawioViewer-CBOqWzaj.js +140 -0
- package/dist/DrawioViewer-CBOqWzaj.js.map +1 -0
- package/dist/EpubViewer-Cs6yZIP2.js +143 -0
- package/dist/EpubViewer-Cs6yZIP2.js.map +1 -0
- package/dist/IpynbViewer-wJhbhUla.js +171 -0
- package/dist/IpynbViewer-wJhbhUla.js.map +1 -0
- package/dist/MermaidViewer-k_XVXoc5.js +127 -0
- package/dist/MermaidViewer-k_XVXoc5.js.map +1 -0
- package/dist/PsdViewer-Bo4imBCF.js +109 -0
- package/dist/PsdViewer-Bo4imBCF.js.map +1 -0
- package/dist/TiffViewer-D73-Gyt-.js +130 -0
- package/dist/TiffViewer-D73-Gyt-.js.map +1 -0
- package/dist/UTIF-DSbsvqXu.js +3104 -0
- package/dist/UTIF-DSbsvqXu.js.map +1 -0
- package/dist/Viewer3D-Ba-RPIRz.js +60 -0
- package/dist/Viewer3D-Ba-RPIRz.js.map +1 -0
- package/dist/_commonjsHelpers-DaMA6jEr.js +9 -0
- package/dist/_commonjsHelpers-DaMA6jEr.js.map +1 -0
- package/dist/filex.js +5 -0
- package/dist/filex.js.map +1 -0
- package/dist/filex.umd.cjs +304 -0
- package/dist/filex.umd.cjs.map +1 -0
- package/dist/index-UFULWo35.js +10736 -0
- package/dist/index-UFULWo35.js.map +1 -0
- package/dist/index-idz8Cz5t.js +10623 -0
- package/dist/index-idz8Cz5t.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/katex-yuB6V-q6.js +11616 -0
- package/dist/katex-yuB6V-q6.js.map +1 -0
- package/dist/papaparse.min-VB1HBwYX.js +441 -0
- package/dist/papaparse.min-VB1HBwYX.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/useViewerFetch-czqbd2Lj.js +25 -0
- package/dist/useViewerFetch-czqbd2Lj.js.map +1 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BRF Tech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @brftech/filex
|
|
2
|
+
|
|
3
|
+
Drop-in **`<filex-explorer>` Web Component** for the
|
|
4
|
+
[filex](https://github.com/brf-tech/filex) file manager. Wraps the
|
|
5
|
+
Vue 3 `<FileExplorer>` SFC from `@brftech/filex-core` and ships with
|
|
6
|
+
the Vue runtime bundled in — load it from any CDN, embed in any
|
|
7
|
+
framework, no peers required.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
### npm
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i @brftech/filex
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
// Side-effect import registers the element.
|
|
19
|
+
import '@brftech/filex';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### CDN (no build step)
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@brftech/filex/dist/filex.js"></script>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Use
|
|
29
|
+
|
|
30
|
+
### Plain HTML
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<filex-explorer
|
|
34
|
+
api-base="https://files.example.com"
|
|
35
|
+
locale="tr"
|
|
36
|
+
theme="auto"
|
|
37
|
+
></filex-explorer>
|
|
38
|
+
|
|
39
|
+
<script type="module">
|
|
40
|
+
import '@brftech/filex';
|
|
41
|
+
const el = document.querySelector('filex-explorer');
|
|
42
|
+
el.config = {
|
|
43
|
+
auth: { kind: 'bearer', token: '<jwt>' },
|
|
44
|
+
shareBase: 'https://files.example.com/shared',
|
|
45
|
+
};
|
|
46
|
+
el.addEventListener('error', (e) => console.error(e.detail));
|
|
47
|
+
el.addEventListener('share-created', (e) => navigator.clipboard.writeText(e.detail.url));
|
|
48
|
+
</script>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Inside a non-Vue framework
|
|
52
|
+
|
|
53
|
+
The element is just a normal DOM custom element — Angular, Svelte,
|
|
54
|
+
plain JS, no problem.
|
|
55
|
+
|
|
56
|
+
## Attributes
|
|
57
|
+
|
|
58
|
+
Simple attributes are auto-parsed into the underlying `config` prop:
|
|
59
|
+
|
|
60
|
+
| Attribute | Maps to |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `api-base` | `config.apiBase` |
|
|
63
|
+
| `endpoint` | `config.endpoint` (legacy Vuefinder-compat) |
|
|
64
|
+
| `locale` | `config.locale` (`tr` / `en`) |
|
|
65
|
+
| `theme` | `config.theme` (`light` / `dark` / `auto`) |
|
|
66
|
+
| `trash-visible` | `config.trashVisible` |
|
|
67
|
+
|
|
68
|
+
For anything richer (auth, custom endpoints, share base, …) set the
|
|
69
|
+
`config` JS property after element creation. Properties merge on top
|
|
70
|
+
of attributes.
|
|
71
|
+
|
|
72
|
+
## Events
|
|
73
|
+
|
|
74
|
+
Native `CustomEvent`s — listen with `addEventListener`. The original
|
|
75
|
+
SFC payload is on `event.detail`.
|
|
76
|
+
|
|
77
|
+
| Event | Detail shape |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `error` | `{ message, context? }` |
|
|
80
|
+
| `share-created` | `{ path, url, pin }` |
|
|
81
|
+
| `file-opened` | `{ path, basename }` |
|
|
82
|
+
| `upload-progress` | `{ uploadId, percent, done }` |
|
|
83
|
+
| `selection-change` | `Array<{ path, basename, type }>` |
|
|
84
|
+
|
|
85
|
+
## Build
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pnpm build # vue-tsc + vite lib build → dist/filex.js + dist/style.css
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { d as y, o as k, w as b, a as l, c as n, e as t, t as a, F as g, k as z, m as B, f as v, g as p, _ as C } from "./index-idz8Cz5t.js";
|
|
2
|
+
const F = { class: "filex-viewer-archive" }, S = {
|
|
3
|
+
key: 0,
|
|
4
|
+
class: "filex-viewer-fallback"
|
|
5
|
+
}, $ = {
|
|
6
|
+
key: 1,
|
|
7
|
+
class: "filex-viewer-fallback"
|
|
8
|
+
}, P = {
|
|
9
|
+
key: 2,
|
|
10
|
+
class: "filex-viewer-fallback"
|
|
11
|
+
}, N = {
|
|
12
|
+
key: 3,
|
|
13
|
+
class: "filex-viewer-archive__pane"
|
|
14
|
+
}, T = { class: "filex-viewer-archive__summary" }, V = { class: "filex-viewer-archive__table" }, A = { class: "filex-viewer-archive__size" }, E = ["data-dir"], H = { class: "filex-viewer-archive__icon" }, j = { class: "filex-viewer-archive__size" }, L = /* @__PURE__ */ y({
|
|
15
|
+
__name: "ArchiveViewer",
|
|
16
|
+
props: {
|
|
17
|
+
url: {},
|
|
18
|
+
filePath: {},
|
|
19
|
+
ext: {},
|
|
20
|
+
t: { type: Function },
|
|
21
|
+
authHeaders: { type: Function },
|
|
22
|
+
authCredentials: {}
|
|
23
|
+
},
|
|
24
|
+
setup(w) {
|
|
25
|
+
const s = w, o = v([]), d = v(!0), c = v(null);
|
|
26
|
+
function r(e, i) {
|
|
27
|
+
return s.t ? s.t(e) : i;
|
|
28
|
+
}
|
|
29
|
+
function f(e) {
|
|
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`;
|
|
31
|
+
}
|
|
32
|
+
async function _() {
|
|
33
|
+
if (d.value = !0, c.value = null, o.value = [], !s.filePath) {
|
|
34
|
+
c.value = r("viewer.archive.error", "Could not read archive contents."), d.value = !1;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const e = await fetch("/api/files/archive/list", {
|
|
39
|
+
method: "POST",
|
|
40
|
+
credentials: s.authCredentials || "include",
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
...s.authHeaders ? s.authHeaders() : {}
|
|
44
|
+
},
|
|
45
|
+
body: JSON.stringify({ path: s.filePath })
|
|
46
|
+
});
|
|
47
|
+
if (!e.ok)
|
|
48
|
+
throw new Error(`${e.status} ${e.statusText}`);
|
|
49
|
+
const i = await e.json();
|
|
50
|
+
o.value = i.entries ?? [];
|
|
51
|
+
} catch (e) {
|
|
52
|
+
c.value = e instanceof Error ? e.message : r("viewer.archive.error", "Could not read archive contents.");
|
|
53
|
+
} finally {
|
|
54
|
+
d.value = !1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
k(_), b(() => s.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) => (l(), n("div", F, [
|
|
60
|
+
c.value ? (l(), n("div", S, [
|
|
61
|
+
i[0] || (i[0] = t("span", { class: "filex-viewer-fallback__icon" }, "🗜️", -1)),
|
|
62
|
+
t("p", null, a(c.value), 1)
|
|
63
|
+
])) : d.value ? (l(), n("div", $, [
|
|
64
|
+
i[1] || (i[1] = t("span", { class: "filex-viewer-fallback__icon" }, "⏳", -1)),
|
|
65
|
+
t("p", null, a(r("viewer.loading", "Loading…")), 1)
|
|
66
|
+
])) : o.value.length === 0 ? (l(), n("div", P, [
|
|
67
|
+
i[2] || (i[2] = t("span", { class: "filex-viewer-fallback__icon" }, "🗜️", -1)),
|
|
68
|
+
t("p", null, a(r("viewer.archive.empty", "Archive is empty.")), 1)
|
|
69
|
+
])) : (l(), n("div", N, [
|
|
70
|
+
t("div", T, a(h.value) + " " + a(r("viewer.archive.entries", "{n} files").replace("{n}", String(h.value))) + " · " + a(f(x.value)), 1),
|
|
71
|
+
t("table", V, [
|
|
72
|
+
t("thead", null, [
|
|
73
|
+
t("tr", null, [
|
|
74
|
+
t("th", null, a(r("viewer.name", "Name")), 1),
|
|
75
|
+
t("th", A, a(r("viewer.size", "Size")), 1)
|
|
76
|
+
])
|
|
77
|
+
]),
|
|
78
|
+
t("tbody", null, [
|
|
79
|
+
(l(!0), n(g, null, z(o.value, (u, m) => (l(), n("tr", {
|
|
80
|
+
key: m,
|
|
81
|
+
"data-dir": u.is_dir ? "1" : "0"
|
|
82
|
+
}, [
|
|
83
|
+
t("td", null, [
|
|
84
|
+
t("span", H, a(u.is_dir ? "📁" : "📄"), 1),
|
|
85
|
+
B(" " + a(u.name), 1)
|
|
86
|
+
]),
|
|
87
|
+
t("td", j, a(u.is_dir ? "" : f(u.size)), 1)
|
|
88
|
+
], 8, E))), 128))
|
|
89
|
+
])
|
|
90
|
+
])
|
|
91
|
+
]))
|
|
92
|
+
]));
|
|
93
|
+
}
|
|
94
|
+
}), O = /* @__PURE__ */ C(L, [["__scopeId", "data-v-95e6ab29"]]);
|
|
95
|
+
export {
|
|
96
|
+
O as default
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=ArchiveViewer-CMaBM4yZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchiveViewer-CMaBM4yZ.js","sources":["../../core/src/viewers/ArchiveViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\n/**\r\n * ArchiveViewer — minimal zip / archive contents preview.\r\n *\r\n * Hits `POST /api/files/archive/list` with the adapter-qualified path\r\n * and renders the member list as a flat table (name, size, mtime).\r\n * Read-only — extraction is exposed elsewhere (context menu / actions\r\n * panel). The viewer's job is just \"what's inside?\" so the user can\r\n * decide whether to extract or download.\r\n */\r\nimport { computed, onMounted, ref, watch } from 'vue';\r\n\r\ninterface ArchiveEntry {\r\n name: string;\r\n size: number;\r\n mtime?: string;\r\n is_dir?: boolean;\r\n}\r\n\r\nconst props = defineProps<{\r\n url: string;\r\n filePath?: string;\r\n ext: string;\r\n t?: (key: string) => string;\r\n authHeaders?: () => Record<string, string>;\r\n authCredentials?: RequestCredentials;\r\n}>();\r\n\r\nconst entries = ref<ArchiveEntry[]>([]);\r\nconst loading = ref(true);\r\nconst error = ref<string | null>(null);\r\n\r\nfunction tt(key: string, fallback: string): string {\r\n return props.t ? props.t(key) : fallback;\r\n}\r\n\r\nfunction fmtSize(n: number): string {\r\n if (n < 1024) return `${n} B`;\r\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\r\n if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;\r\n return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;\r\n}\r\n\r\nasync function load(): Promise<void> {\r\n loading.value = true;\r\n error.value = null;\r\n entries.value = [];\r\n // The viewer is mounted with the resolved file path. Hit the API\r\n // endpoint with the same adapter-qualified path the preview URL\r\n // points at — the backend resolves storage + relative path itself.\r\n if (!props.filePath) {\r\n error.value = tt('viewer.archive.error', 'Could not read archive contents.');\r\n loading.value = false;\r\n return;\r\n }\r\n try {\r\n const res = await fetch('/api/files/archive/list', {\r\n method: 'POST',\r\n credentials: props.authCredentials || 'include',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(props.authHeaders ? props.authHeaders() : {}),\r\n },\r\n body: JSON.stringify({ path: props.filePath }),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`${res.status} ${res.statusText}`);\r\n }\r\n const body = (await res.json()) as { entries?: ArchiveEntry[] };\r\n entries.value = body.entries ?? [];\r\n } catch (err) {\r\n error.value = err instanceof Error ? err.message : tt('viewer.archive.error', 'Could not read archive contents.');\r\n } finally {\r\n loading.value = false;\r\n }\r\n}\r\n\r\nonMounted(load);\r\nwatch(() => props.filePath, load);\r\n\r\nconst totalSize = computed(() => entries.value.reduce((sum, e) => sum + (e.size || 0), 0));\r\nconst fileCount = computed(() => entries.value.filter((e) => !e.is_dir).length);\r\n</script>\r\n\r\n<template>\r\n <div class=\"filex-viewer-archive\">\r\n <div v-if=\"error\" class=\"filex-viewer-fallback\">\r\n <span class=\"filex-viewer-fallback__icon\">🗜️</span>\r\n <p>{{ error }}</p>\r\n </div>\r\n <div v-else-if=\"loading\" class=\"filex-viewer-fallback\">\r\n <span class=\"filex-viewer-fallback__icon\">⏳</span>\r\n <p>{{ tt('viewer.loading', 'Loading…') }}</p>\r\n </div>\r\n <div v-else-if=\"entries.length === 0\" class=\"filex-viewer-fallback\">\r\n <span class=\"filex-viewer-fallback__icon\">🗜️</span>\r\n <p>{{ tt('viewer.archive.empty', 'Archive is empty.') }}</p>\r\n </div>\r\n <div v-else class=\"filex-viewer-archive__pane\">\r\n <div class=\"filex-viewer-archive__summary\">\r\n {{ fileCount }} {{ tt('viewer.archive.entries', '{n} files').replace('{n}', String(fileCount)) }}\r\n · {{ fmtSize(totalSize) }}\r\n </div>\r\n <table class=\"filex-viewer-archive__table\">\r\n <thead>\r\n <tr>\r\n <th>{{ tt('viewer.name', 'Name') }}</th>\r\n <th class=\"filex-viewer-archive__size\">{{ tt('viewer.size', 'Size') }}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"(e, i) in entries\" :key=\"i\" :data-dir=\"e.is_dir ? '1' : '0'\">\r\n <td>\r\n <span class=\"filex-viewer-archive__icon\">{{ e.is_dir ? '📁' : '📄' }}</span>\r\n {{ e.name }}\r\n </td>\r\n <td class=\"filex-viewer-archive__size\">{{ e.is_dir ? '' : fmtSize(e.size) }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.filex-viewer-archive {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 70vh;\r\n background: var(--fe-bg, #fff);\r\n color: var(--fe-text, #1a1e27);\r\n}\r\n.filex-viewer-archive__pane {\r\n flex: 1;\r\n overflow: auto;\r\n padding: 16px 20px;\r\n}\r\n.filex-viewer-archive__summary {\r\n font-size: 12px;\r\n color: var(--fe-text-muted, #5a6475);\r\n margin-bottom: 12px;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n.filex-viewer-archive__table {\r\n width: 100%;\r\n border-collapse: collapse;\r\n font-size: 13px;\r\n font-family: var(--fe-font-mono, monospace);\r\n}\r\n.filex-viewer-archive__table th,\r\n.filex-viewer-archive__table td {\r\n padding: 6px 12px;\r\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\r\n text-align: left;\r\n}\r\n.filex-viewer-archive__table th {\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n font-weight: 600;\r\n position: sticky;\r\n top: 0;\r\n}\r\n.filex-viewer-archive__size {\r\n text-align: right;\r\n font-variant-numeric: tabular-nums;\r\n white-space: nowrap;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-archive__icon {\r\n margin-right: 6px;\r\n}\r\n.filex-viewer-archive__table tr[data-dir=\"1\"] {\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-fallback {\r\n text-align: center;\r\n padding: 32px;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-fallback__icon {\r\n font-size: 48px;\r\n display: block;\r\n margin-bottom: 12px;\r\n}\r\n</style>\r\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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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { f as $ } from "./useViewerFetch-czqbd2Lj.js";
|
|
2
|
+
import { d as N, o as S, w as k, a as n, c as r, e as a, t as v, F as y, k as C, i as W, f as d, g as p, _ as j } from "./index-idz8Cz5t.js";
|
|
3
|
+
const q = { class: "filex-viewer-csv" }, A = { class: "filex-viewer-csv__pane" }, G = {
|
|
4
|
+
key: 0,
|
|
5
|
+
class: "filex-viewer-fallback"
|
|
6
|
+
}, O = {
|
|
7
|
+
key: 1,
|
|
8
|
+
class: "filex-viewer-fallback"
|
|
9
|
+
}, Z = {
|
|
10
|
+
key: 2,
|
|
11
|
+
class: "filex-viewer-csv__table"
|
|
12
|
+
}, z = { class: "filex-viewer-csv__rownum" }, J = {
|
|
13
|
+
key: 0,
|
|
14
|
+
class: "filex-viewer-csv__pager"
|
|
15
|
+
}, K = ["disabled"], Q = { class: "filex-viewer-csv__pageno" }, U = ["disabled"], L = 100, I = 1e3, X = /* @__PURE__ */ N({
|
|
16
|
+
__name: "CsvViewer",
|
|
17
|
+
props: {
|
|
18
|
+
url: {},
|
|
19
|
+
ext: {},
|
|
20
|
+
t: { type: Function },
|
|
21
|
+
authHeaders: { type: Function },
|
|
22
|
+
authCredentials: {}
|
|
23
|
+
},
|
|
24
|
+
setup(M) {
|
|
25
|
+
const i = M, u = d([]), f = d(null), _ = d(!0), E = d(!0), V = d(""), o = d(1), m = d(","), h = d("auto");
|
|
26
|
+
let D = 0;
|
|
27
|
+
function P(l) {
|
|
28
|
+
const e = l.split(/\r?\n/).slice(0, 5).join(`
|
|
29
|
+
`), t = (e.match(/\t/g) || []).length, s = (e.match(/;/g) || []).length, c = (e.match(/,/g) || []).length;
|
|
30
|
+
return t > c && t > s ? " " : s > c && s > t ? ";" : ",";
|
|
31
|
+
}
|
|
32
|
+
async function R(l, e) {
|
|
33
|
+
try {
|
|
34
|
+
const t = await import(
|
|
35
|
+
/* @vite-ignore */
|
|
36
|
+
"./papaparse.min-VB1HBwYX.js"
|
|
37
|
+
).then((x) => x.p);
|
|
38
|
+
return (t.default ?? t).parse(l, {
|
|
39
|
+
delimiter: e,
|
|
40
|
+
skipEmptyLines: !0,
|
|
41
|
+
header: !1
|
|
42
|
+
}).data.slice(0, I);
|
|
43
|
+
} catch {
|
|
44
|
+
return l.split(/\r?\n/).filter((t) => t.length > 0).slice(0, I).map((t) => t.split(e));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function w() {
|
|
48
|
+
var s;
|
|
49
|
+
_.value = !0, f.value = null, u.value = [], o.value = 1;
|
|
50
|
+
const l = ++D;
|
|
51
|
+
let e;
|
|
52
|
+
try {
|
|
53
|
+
e = await $({
|
|
54
|
+
url: i.url,
|
|
55
|
+
headers: ((s = i.authHeaders) == null ? void 0 : s.call(i)) ?? {},
|
|
56
|
+
credentials: i.authCredentials
|
|
57
|
+
});
|
|
58
|
+
} catch (c) {
|
|
59
|
+
f.value = c instanceof Error ? c.message : "fetch failed", _.value = !1;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (l !== D) return;
|
|
63
|
+
i.ext === "tsv" ? m.value = " " : m.value = P(e.slice(0, 4096));
|
|
64
|
+
const t = h.value === "auto" ? m.value : h.value;
|
|
65
|
+
u.value = await R(e, t), _.value = !1;
|
|
66
|
+
}
|
|
67
|
+
S(w), k(() => i.url, w), k(() => h.value, () => {
|
|
68
|
+
u.value.length !== 0 && w();
|
|
69
|
+
});
|
|
70
|
+
const T = p(() => !E.value || u.value.length === 0 ? u.value.length === 0 ? [] : u.value[0].map((l, e) => `Col ${e + 1}`) : u.value[0]), F = p(() => E.value ? u.value.slice(1) : u.value), g = p(() => {
|
|
71
|
+
const l = V.value.trim().toLowerCase();
|
|
72
|
+
return l ? F.value.filter(
|
|
73
|
+
(e) => e.some((t) => (t || "").toLowerCase().includes(l))
|
|
74
|
+
) : F.value;
|
|
75
|
+
}), b = p(
|
|
76
|
+
() => Math.max(1, Math.ceil(g.value.length / L))
|
|
77
|
+
), B = p(() => {
|
|
78
|
+
const l = (o.value - 1) * L;
|
|
79
|
+
return g.value.slice(l, l + L);
|
|
80
|
+
});
|
|
81
|
+
k(V, () => {
|
|
82
|
+
o.value = 1;
|
|
83
|
+
});
|
|
84
|
+
function H(l, e) {
|
|
85
|
+
return i.t ? i.t(l) : e;
|
|
86
|
+
}
|
|
87
|
+
return (l, e) => (n(), r("div", q, [
|
|
88
|
+
a("div", A, [
|
|
89
|
+
f.value ? (n(), r("div", G, [
|
|
90
|
+
e[2] || (e[2] = a("span", { class: "filex-viewer-fallback__icon" }, "📊", -1)),
|
|
91
|
+
a("p", null, v(f.value), 1)
|
|
92
|
+
])) : _.value ? (n(), r("div", O, [
|
|
93
|
+
e[3] || (e[3] = a("span", { class: "filex-viewer-fallback__icon" }, "⏳", -1)),
|
|
94
|
+
a("p", null, v(H("viewer.loading", "Loading…")), 1)
|
|
95
|
+
])) : (n(), r("table", Z, [
|
|
96
|
+
a("thead", null, [
|
|
97
|
+
a("tr", null, [
|
|
98
|
+
e[4] || (e[4] = a("th", { class: "filex-viewer-csv__rownum" }, "#", -1)),
|
|
99
|
+
(n(!0), r(y, null, C(T.value, (t, s) => (n(), r("th", { key: s }, v(t), 1))), 128))
|
|
100
|
+
])
|
|
101
|
+
]),
|
|
102
|
+
a("tbody", null, [
|
|
103
|
+
(n(!0), r(y, null, C(B.value, (t, s) => (n(), r("tr", { key: s }, [
|
|
104
|
+
a("td", z, v((o.value - 1) * 100 + s + 1), 1),
|
|
105
|
+
(n(!0), r(y, null, C(t, (c, x) => (n(), r("td", { key: x }, v(c), 1))), 128))
|
|
106
|
+
]))), 128))
|
|
107
|
+
])
|
|
108
|
+
]))
|
|
109
|
+
]),
|
|
110
|
+
!_.value && !f.value && b.value > 1 ? (n(), r("div", J, [
|
|
111
|
+
a("button", {
|
|
112
|
+
type: "button",
|
|
113
|
+
class: "filex-viewer-btn",
|
|
114
|
+
disabled: o.value <= 1,
|
|
115
|
+
onClick: e[0] || (e[0] = (t) => o.value--)
|
|
116
|
+
}, "‹", 8, K),
|
|
117
|
+
a("span", Q, v(o.value) + " / " + v(b.value) + " (" + v(g.value.length) + " satır)", 1),
|
|
118
|
+
a("button", {
|
|
119
|
+
type: "button",
|
|
120
|
+
class: "filex-viewer-btn",
|
|
121
|
+
disabled: o.value >= b.value,
|
|
122
|
+
onClick: e[1] || (e[1] = (t) => o.value++)
|
|
123
|
+
}, "›", 8, U)
|
|
124
|
+
])) : W("", !0)
|
|
125
|
+
]));
|
|
126
|
+
}
|
|
127
|
+
}), te = /* @__PURE__ */ j(X, [["__scopeId", "data-v-fc9f1e8b"]]);
|
|
128
|
+
export {
|
|
129
|
+
te as default
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=CsvViewer-D5_c7bkP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CsvViewer-D5_c7bkP.js","sources":["../../core/src/viewers/CsvViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\n/**\r\n * CsvViewer — lightweight CSV / TSV table preview.\r\n *\r\n * Lazy-imports `papaparse` when available (best-quality parser — handles\r\n * embedded quotes, multi-line cells, etc). Falls back to a simple\r\n * `split` parser when the peer is missing — workable for the trivial\r\n * \"first 1000 rows\" preview case but loses fidelity on complex files.\r\n *\r\n * UX:\r\n * - first-row-as-header toggle\r\n * - filter input that case-insensitively matches any cell\r\n * - 100-rows-per-page pagination\r\n * - tab vs comma auto-detection (manual override via toolbar)\r\n */\r\nimport { computed, onMounted, ref, watch } from 'vue';\r\nimport { fetchViewerText } from '../composables/useViewerFetch';\r\n\r\nconst props = defineProps<{\r\n url: string;\r\n ext: string;\r\n t?: (key: string) => string;\r\n authHeaders?: () => Record<string, string>;\r\n authCredentials?: RequestCredentials;\r\n}>();\r\n\r\nconst PAGE_SIZE = 100;\r\nconst ROW_LIMIT = 1000;\r\n\r\nconst rows = ref<string[][]>([]);\r\nconst error = ref<string | null>(null);\r\nconst loading = ref(true);\r\nconst firstRowHeader = ref(true);\r\nconst filter = ref('');\r\nconst page = ref(1);\r\nconst detectedDelim = ref<',' | '\\t' | ';'>(',');\r\nconst userDelim = ref<'auto' | ',' | '\\t' | ';'>('auto');\r\n\r\nlet renderToken = 0;\r\n\r\nfunction detectDelimiter(sample: string): ',' | '\\t' | ';' {\r\n const sampleLines = sample.split(/\\r?\\n/).slice(0, 5).join('\\n');\r\n const tab = (sampleLines.match(/\\t/g) || []).length;\r\n const semi = (sampleLines.match(/;/g) || []).length;\r\n const comma = (sampleLines.match(/,/g) || []).length;\r\n if (tab > comma && tab > semi) return '\\t';\r\n if (semi > comma && semi > tab) return ';';\r\n return ',';\r\n}\r\n\r\nasync function parseWith(text: string, delim: string): Promise<string[][]> {\r\n try {\r\n const mod = await import(/* @vite-ignore */ 'papaparse');\r\n const Papa = (mod as any).default ?? mod;\r\n const result = Papa.parse(text, {\r\n delimiter: delim,\r\n skipEmptyLines: true,\r\n header: false,\r\n });\r\n return (result.data as string[][]).slice(0, ROW_LIMIT);\r\n } catch {\r\n // Fallback: naive line/column split. Loses quoted-comma support\r\n // but renders something reasonable.\r\n return text\r\n .split(/\\r?\\n/)\r\n .filter((l) => l.length > 0)\r\n .slice(0, ROW_LIMIT)\r\n .map((line) => line.split(delim));\r\n }\r\n}\r\n\r\nasync function load(): Promise<void> {\r\n loading.value = true;\r\n error.value = null;\r\n rows.value = [];\r\n page.value = 1;\r\n const myToken = ++renderToken;\r\n\r\n let text: string;\r\n try {\r\n text = await fetchViewerText({\r\n url: props.url,\r\n headers: props.authHeaders?.() ?? {},\r\n credentials: props.authCredentials,\r\n });\r\n } catch (err) {\r\n error.value = err instanceof Error ? err.message : 'fetch failed';\r\n loading.value = false;\r\n return;\r\n }\r\n\r\n if (myToken !== renderToken) return;\r\n\r\n if (props.ext === 'tsv') {\r\n detectedDelim.value = '\\t';\r\n } else {\r\n detectedDelim.value = detectDelimiter(text.slice(0, 4096));\r\n }\r\n\r\n const delim = userDelim.value === 'auto' ? detectedDelim.value : userDelim.value;\r\n rows.value = await parseWith(text, delim);\r\n loading.value = false;\r\n}\r\n\r\nonMounted(load);\r\nwatch(() => props.url, load);\r\nwatch(() => userDelim.value, () => {\r\n if (rows.value.length === 0) return;\r\n // Re-parse with the new delimiter using the cached source — but we\r\n // didn't keep it. Cheapest path is a refetch.\r\n load();\r\n});\r\n\r\nconst headers = computed<string[]>(() => {\r\n if (!firstRowHeader.value || rows.value.length === 0) {\r\n if (rows.value.length === 0) return [];\r\n return rows.value[0].map((_, i) => `Col ${i + 1}`);\r\n }\r\n return rows.value[0];\r\n});\r\n\r\nconst dataRows = computed<string[][]>(() => {\r\n return firstRowHeader.value ? rows.value.slice(1) : rows.value;\r\n});\r\n\r\nconst filtered = computed<string[][]>(() => {\r\n const q = filter.value.trim().toLowerCase();\r\n if (!q) return dataRows.value;\r\n return dataRows.value.filter((r) =>\r\n r.some((c) => (c || '').toLowerCase().includes(q)),\r\n );\r\n});\r\n\r\nconst totalPages = computed(() =>\r\n Math.max(1, Math.ceil(filtered.value.length / PAGE_SIZE)),\r\n);\r\n\r\nconst visibleRows = computed<string[][]>(() => {\r\n const start = (page.value - 1) * PAGE_SIZE;\r\n return filtered.value.slice(start, start + PAGE_SIZE);\r\n});\r\n\r\nwatch(filter, () => {\r\n page.value = 1;\r\n});\r\n\r\nfunction tt(key: string, fallback: string): string {\r\n return props.t ? props.t(key) : fallback;\r\n}\r\n</script>\r\n\r\n<template>\r\n <div class=\"filex-viewer-csv\">\r\n <div class=\"filex-viewer-csv__pane\">\r\n <div v-if=\"error\" class=\"filex-viewer-fallback\">\r\n <span class=\"filex-viewer-fallback__icon\">📊</span>\r\n <p>{{ error }}</p>\r\n </div>\r\n <div v-else-if=\"loading\" class=\"filex-viewer-fallback\">\r\n <span class=\"filex-viewer-fallback__icon\">⏳</span>\r\n <p>{{ tt('viewer.loading', 'Loading…') }}</p>\r\n </div>\r\n <table v-else class=\"filex-viewer-csv__table\">\r\n <thead>\r\n <tr>\r\n <th class=\"filex-viewer-csv__rownum\">#</th>\r\n <th v-for=\"(h, i) in headers\" :key=\"i\">{{ h }}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"(row, ri) in visibleRows\" :key=\"ri\">\r\n <td class=\"filex-viewer-csv__rownum\">{{ (page - 1) * 100 + ri + 1 }}</td>\r\n <td v-for=\"(c, ci) in row\" :key=\"ci\">{{ c }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div v-if=\"!loading && !error && totalPages > 1\" class=\"filex-viewer-csv__pager\">\r\n <button\r\n type=\"button\"\r\n class=\"filex-viewer-btn\"\r\n :disabled=\"page <= 1\"\r\n @click=\"page--\"\r\n >‹</button>\r\n <span class=\"filex-viewer-csv__pageno\">{{ page }} / {{ totalPages }} ({{ filtered.length }} satır)</span>\r\n <button\r\n type=\"button\"\r\n class=\"filex-viewer-btn\"\r\n :disabled=\"page >= totalPages\"\r\n @click=\"page++\"\r\n >›</button>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.filex-viewer-csv {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 70vh;\r\n background: var(--fe-bg, #fff);\r\n color: var(--fe-text, #1a1e27);\r\n}\r\n.filex-viewer-csv__bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 8px 12px;\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\r\n font-size: 12px;\r\n}\r\n.filex-viewer-csv__check {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-csv__select,\r\n.filex-viewer-csv__filter {\r\n border: 1px solid var(--fe-border, #e2e6ed);\r\n background: var(--fe-bg, #fff);\r\n color: inherit;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n font: inherit;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-csv__filter {\r\n flex: 0 1 240px;\r\n}\r\n.filex-viewer-spacer { flex: 1; }\r\n.filex-viewer-csv__count {\r\n font-size: 11px;\r\n color: var(--fe-text-muted, #5a6475);\r\n font-variant-numeric: tabular-nums;\r\n}\r\n.filex-viewer-csv__pane {\r\n flex: 1;\r\n overflow: auto;\r\n}\r\n.filex-viewer-csv__table {\r\n border-collapse: collapse;\r\n width: max-content;\r\n min-width: 100%;\r\n font-size: 12px;\r\n font-family: var(--fe-font-mono, monospace);\r\n}\r\n.filex-viewer-csv__table th,\r\n.filex-viewer-csv__table td {\r\n padding: 4px 10px;\r\n border: 1px solid var(--fe-border, #e2e6ed);\r\n white-space: nowrap;\r\n max-width: 320px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n.filex-viewer-csv__table th {\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n position: sticky;\r\n top: 0;\r\n font-weight: 600;\r\n text-align: left;\r\n}\r\n.filex-viewer-csv__table tbody tr:nth-child(even) {\r\n background: var(--fe-bg-hover, rgba(0, 0, 0, 0.02));\r\n}\r\n.filex-viewer-csv__rownum {\r\n color: var(--fe-text-muted, #5a6475);\r\n text-align: right;\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n font-variant-numeric: tabular-nums;\r\n position: sticky;\r\n left: 0;\r\n}\r\n.filex-viewer-csv__pager {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 6px;\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n border-top: 1px solid var(--fe-border, #e2e6ed);\r\n font-size: 12px;\r\n}\r\n.filex-viewer-csv__pageno {\r\n font-variant-numeric: tabular-nums;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-fallback {\r\n text-align: center;\r\n padding: 32px;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-fallback__icon {\r\n font-size: 48px;\r\n display: block;\r\n margin-bottom: 12px;\r\n}\r\n.filex-viewer-btn {\r\n border: 1px solid var(--fe-border, #e2e6ed);\r\n background: var(--fe-bg, #fff);\r\n color: var(--fe-text, #1a1e27);\r\n padding: 4px 10px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font: inherit;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-btn:hover:not(:disabled) {\r\n background: var(--fe-bg-hover, #edf0f5);\r\n}\r\n.filex-viewer-btn:disabled {\r\n opacity: 0.4;\r\n cursor: not-allowed;\r\n}\r\n</style>\r\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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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { f as U } from "./useViewerFetch-czqbd2Lj.js";
|
|
2
|
+
import { d as S, f as i, o as B, w as E, h as O, a as d, c as u, e as h, t as C, g, _ as D } from "./index-idz8Cz5t.js";
|
|
3
|
+
const T = { class: "filex-viewer-drawio" }, $ = {
|
|
4
|
+
key: 0,
|
|
5
|
+
class: "filex-viewer-fallback"
|
|
6
|
+
}, N = ["src"], P = /* @__PURE__ */ S({
|
|
7
|
+
__name: "DrawioViewer",
|
|
8
|
+
props: {
|
|
9
|
+
url: {},
|
|
10
|
+
filePath: {},
|
|
11
|
+
ext: {},
|
|
12
|
+
drawioUrl: {},
|
|
13
|
+
saveUrl: {},
|
|
14
|
+
readOnly: { type: Boolean },
|
|
15
|
+
t: { type: Function },
|
|
16
|
+
authHeaders: { type: Function },
|
|
17
|
+
authCredentials: {}
|
|
18
|
+
},
|
|
19
|
+
setup(_) {
|
|
20
|
+
const e = _, c = i(null), s = i(null), n = i("loading"), f = i(!!e.readOnly || !e.saveUrl), o = g(
|
|
21
|
+
() => e.drawioUrl ? e.drawioUrl.replace(/\/$/, "") : null
|
|
22
|
+
), x = g(() => {
|
|
23
|
+
if (!o.value) return "";
|
|
24
|
+
const a = new URLSearchParams({
|
|
25
|
+
embed: "1",
|
|
26
|
+
proto: "json",
|
|
27
|
+
spin: "1",
|
|
28
|
+
saveAndExit: "0",
|
|
29
|
+
noSaveBtn: f.value ? "1" : "0",
|
|
30
|
+
noExitBtn: "1",
|
|
31
|
+
ui: "kennedy",
|
|
32
|
+
modified: "unsavedChanges"
|
|
33
|
+
});
|
|
34
|
+
return `${o.value}/?${a.toString()}`;
|
|
35
|
+
});
|
|
36
|
+
let v = "";
|
|
37
|
+
async function k() {
|
|
38
|
+
var a;
|
|
39
|
+
n.value = "loading", s.value = null;
|
|
40
|
+
try {
|
|
41
|
+
v = await U({
|
|
42
|
+
url: e.url,
|
|
43
|
+
headers: ((a = e.authHeaders) == null ? void 0 : a.call(e)) ?? {},
|
|
44
|
+
credentials: e.authCredentials
|
|
45
|
+
});
|
|
46
|
+
} catch (t) {
|
|
47
|
+
s.value = t instanceof Error ? t.message : "fetch failed", n.value = "error";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function b(a) {
|
|
51
|
+
var t, r;
|
|
52
|
+
(r = (t = c.value) == null ? void 0 : t.contentWindow) == null || r.postMessage(JSON.stringify(a), "*");
|
|
53
|
+
}
|
|
54
|
+
async function m(a) {
|
|
55
|
+
var t;
|
|
56
|
+
if (e.saveUrl) {
|
|
57
|
+
n.value = "saving";
|
|
58
|
+
try {
|
|
59
|
+
const r = {
|
|
60
|
+
"Content-Type": "application/json",
|
|
61
|
+
...((t = e.authHeaders) == null ? void 0 : t.call(e)) ?? {}
|
|
62
|
+
}, l = await fetch(e.saveUrl, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: r,
|
|
65
|
+
credentials: e.authCredentials || "same-origin",
|
|
66
|
+
body: JSON.stringify({ path: e.filePath, content: a })
|
|
67
|
+
});
|
|
68
|
+
if (!l.ok)
|
|
69
|
+
throw new Error(`${l.status} ${l.statusText}`);
|
|
70
|
+
n.value = "saved", setTimeout(() => {
|
|
71
|
+
n.value === "saved" && (n.value = "ready");
|
|
72
|
+
}, 2500);
|
|
73
|
+
} catch (r) {
|
|
74
|
+
s.value = r instanceof Error ? r.message : "save failed", n.value = "error";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function w(a) {
|
|
79
|
+
if (typeof a.data != "string" || a.data.length === 0) return;
|
|
80
|
+
const t = a.data[0];
|
|
81
|
+
if (t !== "{" && t !== "<") return;
|
|
82
|
+
let r;
|
|
83
|
+
try {
|
|
84
|
+
r = JSON.parse(a.data);
|
|
85
|
+
} catch {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!(!r || typeof r != "object"))
|
|
89
|
+
switch (r.event) {
|
|
90
|
+
case "init":
|
|
91
|
+
b({
|
|
92
|
+
action: "load",
|
|
93
|
+
xml: v,
|
|
94
|
+
autosave: 0
|
|
95
|
+
}), n.value = "ready";
|
|
96
|
+
break;
|
|
97
|
+
case "save":
|
|
98
|
+
typeof r.xml == "string" && m(r.xml);
|
|
99
|
+
break;
|
|
100
|
+
case "export":
|
|
101
|
+
break;
|
|
102
|
+
case "autosave":
|
|
103
|
+
typeof r.xml == "string" && !f.value && m(r.xml);
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function p() {
|
|
108
|
+
if (!o.value) {
|
|
109
|
+
s.value = y("viewer.drawio.disabled", "Drawio (diagrams.net) yapılandırılmamış."), n.value = "error";
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
s.value === y("viewer.drawio.disabled", "Drawio (diagrams.net) yapılandırılmamış.") && (s.value = null, n.value = "loading"), k();
|
|
113
|
+
}
|
|
114
|
+
B(() => {
|
|
115
|
+
window.addEventListener("message", w), p();
|
|
116
|
+
}), E(() => e.drawioUrl, p), O(() => {
|
|
117
|
+
window.removeEventListener("message", w);
|
|
118
|
+
});
|
|
119
|
+
function y(a, t) {
|
|
120
|
+
return e.t ? e.t(a) : t;
|
|
121
|
+
}
|
|
122
|
+
return (a, t) => (d(), u("div", T, [
|
|
123
|
+
s.value ? (d(), u("div", $, [
|
|
124
|
+
t[0] || (t[0] = h("span", { class: "filex-viewer-fallback__icon" }, "📐", -1)),
|
|
125
|
+
h("p", null, C(s.value), 1)
|
|
126
|
+
])) : (d(), u("iframe", {
|
|
127
|
+
key: 1,
|
|
128
|
+
ref_key: "iframeRef",
|
|
129
|
+
ref: c,
|
|
130
|
+
src: x.value,
|
|
131
|
+
class: "filex-viewer-drawio__frame",
|
|
132
|
+
title: "diagrams.net editor"
|
|
133
|
+
}, null, 8, N))
|
|
134
|
+
]));
|
|
135
|
+
}
|
|
136
|
+
}), j = /* @__PURE__ */ D(P, [["__scopeId", "data-v-699c407a"]]);
|
|
137
|
+
export {
|
|
138
|
+
j as default
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=DrawioViewer-CBOqWzaj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DrawioViewer-CBOqWzaj.js","sources":["../../core/src/viewers/DrawioViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\n/**\r\n * DrawioViewer — embed diagrams.net via iframe + postMessage handshake.\r\n *\r\n * The diagrams.net embed mode (`?embed=1&proto=json`) handshakes via\r\n * window.postMessage:\r\n *\r\n * 1. iframe sends {event:'init'} ← bootstrap\r\n * 2. parent sends {action:'load', xml} ← our payload\r\n * 3. iframe sends {event:'save', xml} on save ← we POST back\r\n *\r\n * No external library required — diagrams.net hosts the entire editor\r\n * inside the iframe. We just fetch the source XML on mount and route\r\n * `save` events back to the configured `pdfSaveUrl`-style endpoint\r\n * (drawio uses the same shape: POST `{path, content}` body).\r\n */\r\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\r\nimport { fetchViewerText } from '../composables/useViewerFetch';\r\n\r\nconst props = defineProps<{\r\n url: string;\r\n filePath: string;\r\n ext: string;\r\n drawioUrl?: string;\r\n /** Optional save endpoint. When unset the iframe stays read-only. */\r\n saveUrl?: string;\r\n readOnly?: boolean;\r\n t?: (key: string) => string;\r\n authHeaders?: () => Record<string, string>;\r\n authCredentials?: RequestCredentials;\r\n}>();\r\n\r\nconst iframeRef = ref<HTMLIFrameElement | null>(null);\r\nconst error = ref<string | null>(null);\r\nconst status = ref<'loading' | 'ready' | 'saving' | 'saved' | 'error'>('loading');\r\nconst readOnly = ref(!!props.readOnly || !props.saveUrl);\r\n\r\n// drawioUrl=null is the operator's \"off\" signal — FileExplorer wipes it\r\n// when the capabilities probe reports drawio offline. Don't silently fall\r\n// back to the public embed.diagrams.net iframe, that defeats the point of\r\n// gating: render a \"not configured\" pane instead so the user understands\r\n// why the editor isn't loading.\r\n//\r\n// `drawioBase` MUST be a computed (not a const), otherwise a stale null\r\n// at mount time (capabilities probe still inflight) gets cached for the\r\n// component's lifetime — leading to the spurious\r\n// \"viewer.drawio.disabled\" fallback after the capability flips to \"ok\".\r\nconst drawioBase = computed<string | null>(() =>\r\n props.drawioUrl ? props.drawioUrl.replace(/\\/$/, '') : null,\r\n);\r\nconst iframeSrc = computed<string>(() => {\r\n if (!drawioBase.value) return '';\r\n const params = new URLSearchParams({\r\n embed: '1',\r\n proto: 'json',\r\n spin: '1',\r\n saveAndExit: '0',\r\n noSaveBtn: readOnly.value ? '1' : '0',\r\n noExitBtn: '1',\r\n ui: 'kennedy',\r\n modified: 'unsavedChanges',\r\n });\r\n return `${drawioBase.value}/?${params.toString()}`;\r\n});\r\n\r\nlet pendingXml: string = '';\r\n\r\nasync function loadXml(): Promise<void> {\r\n status.value = 'loading';\r\n error.value = null;\r\n try {\r\n pendingXml = await fetchViewerText({\r\n url: props.url,\r\n headers: props.authHeaders?.() ?? {},\r\n credentials: props.authCredentials,\r\n });\r\n } catch (err) {\r\n error.value = err instanceof Error ? err.message : 'fetch failed';\r\n status.value = 'error';\r\n }\r\n}\r\n\r\nfunction send(msg: unknown): void {\r\n iframeRef.value?.contentWindow?.postMessage(JSON.stringify(msg), '*');\r\n}\r\n\r\nasync function persist(xml: string): Promise<void> {\r\n if (!props.saveUrl) return;\r\n status.value = 'saving';\r\n try {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(props.authHeaders?.() ?? {}),\r\n };\r\n const res = await fetch(props.saveUrl, {\r\n method: 'POST',\r\n headers,\r\n credentials: props.authCredentials || 'same-origin',\r\n body: JSON.stringify({ path: props.filePath, content: xml }),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`${res.status} ${res.statusText}`);\r\n }\r\n status.value = 'saved';\r\n setTimeout(() => {\r\n if (status.value === 'saved') status.value = 'ready';\r\n }, 2500);\r\n } catch (err) {\r\n error.value = err instanceof Error ? err.message : 'save failed';\r\n status.value = 'error';\r\n }\r\n}\r\n\r\nfunction onMessage(ev: MessageEvent): void {\r\n if (typeof ev.data !== 'string' || ev.data.length === 0) return;\r\n // Drawio messages always start with '{' or '<'. Ignore anything else\r\n // (devtools / unrelated postMessage senders inside the same window).\r\n const first = ev.data[0];\r\n if (first !== '{' && first !== '<') return;\r\n let payload: any;\r\n try {\r\n payload = JSON.parse(ev.data);\r\n } catch {\r\n return;\r\n }\r\n if (!payload || typeof payload !== 'object') return;\r\n switch (payload.event) {\r\n case 'init':\r\n send({\r\n action: 'load',\r\n xml: pendingXml,\r\n autosave: 0,\r\n });\r\n status.value = 'ready';\r\n break;\r\n case 'save':\r\n if (typeof payload.xml === 'string') {\r\n persist(payload.xml);\r\n }\r\n break;\r\n case 'export':\r\n // Could persist a PNG/SVG render; out of V1 scope.\r\n break;\r\n case 'autosave':\r\n if (typeof payload.xml === 'string' && !readOnly.value) {\r\n persist(payload.xml);\r\n }\r\n break;\r\n default:\r\n break;\r\n }\r\n}\r\n\r\nfunction bootIfReady(): void {\r\n if (!drawioBase.value) {\r\n error.value = tt('viewer.drawio.disabled', 'Drawio (diagrams.net) yapılandırılmamış.');\r\n status.value = 'error';\r\n return;\r\n }\r\n // Clear a previous \"disabled\" error in case the prop just became\r\n // available (capability probe finished after mount).\r\n if (error.value === tt('viewer.drawio.disabled', 'Drawio (diagrams.net) yapılandırılmamış.')) {\r\n error.value = null;\r\n status.value = 'loading';\r\n }\r\n loadXml();\r\n}\r\n\r\nonMounted(() => {\r\n window.addEventListener('message', onMessage);\r\n bootIfReady();\r\n});\r\n\r\nwatch(() => props.drawioUrl, bootIfReady);\r\n\r\nonBeforeUnmount(() => {\r\n window.removeEventListener('message', onMessage);\r\n});\r\n\r\nfunction tt(key: string, fallback: string): string {\r\n return props.t ? props.t(key) : fallback;\r\n}\r\n</script>\r\n\r\n<template>\r\n <div class=\"filex-viewer-drawio\">\r\n <div v-if=\"error\" class=\"filex-viewer-fallback\">\r\n <span class=\"filex-viewer-fallback__icon\">📐</span>\r\n <p>{{ error }}</p>\r\n </div>\r\n <iframe\r\n v-else\r\n ref=\"iframeRef\"\r\n :src=\"iframeSrc\"\r\n class=\"filex-viewer-drawio__frame\"\r\n title=\"diagrams.net editor\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.filex-viewer-drawio {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 70vh;\r\n background: var(--fe-bg, #fff);\r\n}\r\n.filex-viewer-drawio__bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 6px 12px;\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\r\n font-size: 12px;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-drawio__status[data-state=\"error\"] { color: var(--fe-danger, #dc2626); }\r\n.filex-viewer-drawio__status[data-state=\"saved\"] { color: #059669; }\r\n.filex-viewer-drawio__readonly {\r\n font-style: italic;\r\n margin-left: auto;\r\n}\r\n.filex-viewer-drawio__frame {\r\n flex: 1;\r\n width: 100%;\r\n border: 0;\r\n background: #fafafa;\r\n min-height: 0;\r\n}\r\n.filex-viewer-fallback {\r\n text-align: center;\r\n padding: 32px;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-fallback__icon {\r\n font-size: 48px;\r\n display: block;\r\n margin-bottom: 12px;\r\n}\r\n</style>\r\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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"}
|