@brftech/filex 0.1.56 → 0.1.60
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 -21
- package/dist/{ArchiveViewer-CMaBM4yZ.js → ArchiveViewer-BotnnnoW.js} +13 -13
- package/dist/ArchiveViewer-BotnnnoW.js.map +1 -0
- package/dist/{CsvViewer-D5_c7bkP.js → CsvViewer-CrwZZqmq.js} +3 -3
- package/dist/CsvViewer-CrwZZqmq.js.map +1 -0
- package/dist/{DrawioViewer-CBOqWzaj.js → DrawioViewer-uEJbt6hj.js} +3 -3
- package/dist/DrawioViewer-uEJbt6hj.js.map +1 -0
- package/dist/{EpubViewer-Cs6yZIP2.js → EpubViewer-mCV3ZEXb.js} +3 -3
- package/dist/EpubViewer-mCV3ZEXb.js.map +1 -0
- package/dist/{IpynbViewer-wJhbhUla.js → IpynbViewer-B3g-lJfV.js} +3 -3
- package/dist/IpynbViewer-B3g-lJfV.js.map +1 -0
- package/dist/{MermaidViewer-k_XVXoc5.js → MermaidViewer-B0Q0ghbV.js} +3 -3
- package/dist/MermaidViewer-B0Q0ghbV.js.map +1 -0
- package/dist/{PsdViewer-Bo4imBCF.js → PsdViewer-lk6xrjRB.js} +8 -8
- package/dist/PsdViewer-lk6xrjRB.js.map +1 -0
- package/dist/{TiffViewer-D73-Gyt-.js → TiffViewer-PXjYKqzo.js} +3 -3
- package/dist/TiffViewer-PXjYKqzo.js.map +1 -0
- package/dist/{Viewer3D-Ba-RPIRz.js → Viewer3D-DtT-hBa3.js} +4 -4
- package/dist/Viewer3D-DtT-hBa3.js.map +1 -0
- package/dist/filex.js +1 -1
- package/dist/filex.umd.cjs +13 -13
- package/dist/filex.umd.cjs.map +1 -1
- package/dist/{index-idz8Cz5t.js → index-BNs90VaG.js} +378 -378
- package/dist/index-BNs90VaG.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/useViewerFetch-czqbd2Lj.js.map +1 -1
- package/package.json +2 -2
- package/dist/ArchiveViewer-CMaBM4yZ.js.map +0 -1
- package/dist/CsvViewer-D5_c7bkP.js.map +0 -1
- package/dist/DrawioViewer-CBOqWzaj.js.map +0 -1
- package/dist/EpubViewer-Cs6yZIP2.js.map +0 -1
- package/dist/IpynbViewer-wJhbhUla.js.map +0 -1
- package/dist/MermaidViewer-k_XVXoc5.js.map +0 -1
- package/dist/PsdViewer-Bo4imBCF.js.map +0 -1
- package/dist/TiffViewer-D73-Gyt-.js.map +0 -1
- package/dist/Viewer3D-Ba-RPIRz.js.map +0 -1
- package/dist/index-idz8Cz5t.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,21 +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.
|
|
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.
|
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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-BNs90VaG.js";
|
|
2
2
|
const F = { class: "filex-viewer-archive" }, S = {
|
|
3
3
|
key: 0,
|
|
4
4
|
class: "filex-viewer-fallback"
|
|
@@ -22,7 +22,7 @@ const F = { class: "filex-viewer-archive" }, S = {
|
|
|
22
22
|
authCredentials: {}
|
|
23
23
|
},
|
|
24
24
|
setup(w) {
|
|
25
|
-
const s = w, o = v([]),
|
|
25
|
+
const s = w, o = v([]), u = v(!0), c = v(null);
|
|
26
26
|
function r(e, i) {
|
|
27
27
|
return s.t ? s.t(e) : i;
|
|
28
28
|
}
|
|
@@ -30,8 +30,8 @@ const F = { class: "filex-viewer-archive" }, S = {
|
|
|
30
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
31
|
}
|
|
32
32
|
async function _() {
|
|
33
|
-
if (
|
|
34
|
-
c.value = r("viewer.archive.error", "Could not read archive contents."),
|
|
33
|
+
if (u.value = !0, c.value = null, o.value = [], !s.filePath) {
|
|
34
|
+
c.value = r("viewer.archive.error", "Could not read archive contents."), u.value = !1;
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
try {
|
|
@@ -51,7 +51,7 @@ const F = { class: "filex-viewer-archive" }, S = {
|
|
|
51
51
|
} catch (e) {
|
|
52
52
|
c.value = e instanceof Error ? e.message : r("viewer.archive.error", "Could not read archive contents.");
|
|
53
53
|
} finally {
|
|
54
|
-
|
|
54
|
+
u.value = !1;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
k(_), b(() => s.filePath, _);
|
|
@@ -60,7 +60,7 @@ const F = { class: "filex-viewer-archive" }, S = {
|
|
|
60
60
|
c.value ? (l(), n("div", S, [
|
|
61
61
|
i[0] || (i[0] = t("span", { class: "filex-viewer-fallback__icon" }, "🗜️", -1)),
|
|
62
62
|
t("p", null, a(c.value), 1)
|
|
63
|
-
])) :
|
|
63
|
+
])) : u.value ? (l(), n("div", $, [
|
|
64
64
|
i[1] || (i[1] = t("span", { class: "filex-viewer-fallback__icon" }, "⏳", -1)),
|
|
65
65
|
t("p", null, a(r("viewer.loading", "Loading…")), 1)
|
|
66
66
|
])) : o.value.length === 0 ? (l(), n("div", P, [
|
|
@@ -76,23 +76,23 @@ const F = { class: "filex-viewer-archive" }, S = {
|
|
|
76
76
|
])
|
|
77
77
|
]),
|
|
78
78
|
t("tbody", null, [
|
|
79
|
-
(l(!0), n(g, null, z(o.value, (
|
|
79
|
+
(l(!0), n(g, null, z(o.value, (d, m) => (l(), n("tr", {
|
|
80
80
|
key: m,
|
|
81
|
-
"data-dir":
|
|
81
|
+
"data-dir": d.is_dir ? "1" : "0"
|
|
82
82
|
}, [
|
|
83
83
|
t("td", null, [
|
|
84
|
-
t("span", H, a(
|
|
85
|
-
B(" " + a(
|
|
84
|
+
t("span", H, a(d.is_dir ? "📁" : "📄"), 1),
|
|
85
|
+
B(" " + a(d.name), 1)
|
|
86
86
|
]),
|
|
87
|
-
t("td", j, a(
|
|
87
|
+
t("td", j, a(d.is_dir ? "" : f(d.size)), 1)
|
|
88
88
|
], 8, E))), 128))
|
|
89
89
|
])
|
|
90
90
|
])
|
|
91
91
|
]))
|
|
92
92
|
]));
|
|
93
93
|
}
|
|
94
|
-
}), O = /* @__PURE__ */ C(L, [["__scopeId", "data-v-
|
|
94
|
+
}), O = /* @__PURE__ */ C(L, [["__scopeId", "data-v-d3ad0fc4"]]);
|
|
95
95
|
export {
|
|
96
96
|
O as default
|
|
97
97
|
};
|
|
98
|
-
//# sourceMappingURL=ArchiveViewer-
|
|
98
|
+
//# sourceMappingURL=ArchiveViewer-BotnnnoW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchiveViewer-BotnnnoW.js","sources":["../../core/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 || 'include',\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 scoped>\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,5 +1,5 @@
|
|
|
1
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-
|
|
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-BNs90VaG.js";
|
|
3
3
|
const q = { class: "filex-viewer-csv" }, A = { class: "filex-viewer-csv__pane" }, G = {
|
|
4
4
|
key: 0,
|
|
5
5
|
class: "filex-viewer-fallback"
|
|
@@ -124,8 +124,8 @@ const q = { class: "filex-viewer-csv" }, A = { class: "filex-viewer-csv__pane" }
|
|
|
124
124
|
])) : W("", !0)
|
|
125
125
|
]));
|
|
126
126
|
}
|
|
127
|
-
}), te = /* @__PURE__ */ j(X, [["__scopeId", "data-v-
|
|
127
|
+
}), te = /* @__PURE__ */ j(X, [["__scopeId", "data-v-1a0b9c8e"]]);
|
|
128
128
|
export {
|
|
129
129
|
te as default
|
|
130
130
|
};
|
|
131
|
-
//# sourceMappingURL=CsvViewer-
|
|
131
|
+
//# sourceMappingURL=CsvViewer-CrwZZqmq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CsvViewer-CrwZZqmq.js","sources":["../../core/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 scoped>\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,5 +1,5 @@
|
|
|
1
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-
|
|
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-BNs90VaG.js";
|
|
3
3
|
const T = { class: "filex-viewer-drawio" }, $ = {
|
|
4
4
|
key: 0,
|
|
5
5
|
class: "filex-viewer-fallback"
|
|
@@ -133,8 +133,8 @@ const T = { class: "filex-viewer-drawio" }, $ = {
|
|
|
133
133
|
}, null, 8, N))
|
|
134
134
|
]));
|
|
135
135
|
}
|
|
136
|
-
}), j = /* @__PURE__ */ D(P, [["__scopeId", "data-v-
|
|
136
|
+
}), j = /* @__PURE__ */ D(P, [["__scopeId", "data-v-680c72a8"]]);
|
|
137
137
|
export {
|
|
138
138
|
j as default
|
|
139
139
|
};
|
|
140
|
-
//# sourceMappingURL=DrawioViewer-
|
|
140
|
+
//# sourceMappingURL=DrawioViewer-uEJbt6hj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DrawioViewer-uEJbt6hj.js","sources":["../../core/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,4 +1,4 @@
|
|
|
1
|
-
import { d as U, o as F, h as L, w as V, a as u, c as i, e as c, t as b, F as H, i as g, f as r, _ as R } from "./index-
|
|
1
|
+
import { d as U, o as F, h as L, w as V, a as u, c as i, e as c, t as b, F as H, i as g, f as r, _ as R } from "./index-BNs90VaG.js";
|
|
2
2
|
const S = {
|
|
3
3
|
key: 0,
|
|
4
4
|
class: "filex-viewer-fallback"
|
|
@@ -136,8 +136,8 @@ const S = {
|
|
|
136
136
|
], 64))
|
|
137
137
|
], 512));
|
|
138
138
|
}
|
|
139
|
-
}), j = /* @__PURE__ */ R(T, [["__scopeId", "data-v-
|
|
139
|
+
}), j = /* @__PURE__ */ R(T, [["__scopeId", "data-v-639afd99"]]);
|
|
140
140
|
export {
|
|
141
141
|
j as default
|
|
142
142
|
};
|
|
143
|
-
//# sourceMappingURL=EpubViewer-
|
|
143
|
+
//# sourceMappingURL=EpubViewer-mCV3ZEXb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EpubViewer-mCV3ZEXb.js","sources":["../../core/src/viewers/EpubViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * EpubViewer — flowable EPUB reader via `epubjs`.\n *\n * Lazy-imports `epubjs` (~80 KB gzipped). epub.js renders the publication\n * inside an iframe (default `flow: 'paginated'`), but we use it in\n * scrolled-doc mode only when the user toggles the \"fit-width\" flag — by\n * default we keep paginated since that matches reader-app expectations.\n *\n * UX:\n * - prev/next page buttons (also keyboard arrow keys via composable)\n * - collapsible TOC sidebar (built from `book.loaded.navigation`)\n * - font size +/- (Themes API)\n * - graceful fallback if peer not installed\n */\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue';\n\nconst props = defineProps<{\n url: string;\n mime?: string;\n ext: string;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string>;\n authCredentials?: RequestCredentials;\n}>();\n\ninterface TocNode {\n href: string;\n label: string;\n subitems?: TocNode[];\n}\n\nconst root = ref<HTMLDivElement | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nconst error = ref<string | null>(null);\nconst toc = ref<TocNode[]>([]);\nconst tocOpen = ref(false);\nconst fontSize = ref(100);\nconst ready = ref(false);\nconst loading = ref(true);\n\nlet book: any = null;\nlet rendition: any = null;\n\nasync function load(): Promise<void> {\n loading.value = true;\n ready.value = false;\n error.value = null;\n let mod: any = null;\n try {\n mod = await import(/* @vite-ignore */ 'epubjs');\n } catch {\n error.value = props.t\n ? props.t('viewer.peer_not_installed')\n : 'EPUB viewer requires `epubjs` — install or use download.';\n loading.value = false;\n return;\n }\n try {\n const Epub = mod.default ?? mod;\n // epub.js wants a URL (it then fetches with XHR). When the host\n // site requires auth headers we have to load the file ourselves\n // and pass an ArrayBuffer instead.\n let source: string | ArrayBuffer = props.url;\n if (props.authHeaders) {\n const headers = props.authHeaders();\n const res = await fetch(props.url, {\n headers,\n credentials: props.authCredentials || 'same-origin',\n });\n if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);\n source = await res.arrayBuffer();\n }\n book = Epub(source);\n if (!containerRef.value) {\n throw new Error('EPUB mount target missing');\n }\n rendition = book.renderTo(containerRef.value, {\n width: '100%',\n height: '100%',\n flow: 'paginated',\n manager: 'default',\n });\n await rendition.display();\n rendition.themes.fontSize(fontSize.value + '%');\n const nav = await book.loaded.navigation;\n toc.value = (nav?.toc ?? []) as TocNode[];\n ready.value = true;\n } catch (err) {\n error.value =\n err instanceof Error ? err.message : 'EPUB load failed';\n } finally {\n loading.value = false;\n }\n}\n\nfunction next(): void {\n rendition?.next?.();\n}\nfunction prev(): void {\n rendition?.prev?.();\n}\nfunction gotoHref(href: string): void {\n rendition?.display?.(href);\n tocOpen.value = false;\n}\nfunction bigger(): void {\n fontSize.value = Math.min(200, fontSize.value + 10);\n rendition?.themes?.fontSize(fontSize.value + '%');\n}\nfunction smaller(): void {\n fontSize.value = Math.max(60, fontSize.value - 10);\n rendition?.themes?.fontSize(fontSize.value + '%');\n}\n\nfunction onKey(ev: KeyboardEvent): void {\n if (ev.key === 'ArrowRight' || ev.key === 'PageDown') next();\n else if (ev.key === 'ArrowLeft' || ev.key === 'PageUp') prev();\n}\n\nonMounted(() => {\n load();\n window.addEventListener('keydown', onKey);\n});\n\nonBeforeUnmount(() => {\n window.removeEventListener('keydown', onKey);\n try {\n rendition?.destroy?.();\n } catch {\n /* ignore */\n }\n try {\n book?.destroy?.();\n } catch {\n /* ignore */\n }\n rendition = null;\n book = null;\n});\n\nwatch(\n () => props.url,\n () => {\n if (rendition) {\n try {\n rendition.destroy();\n } catch {\n /* ignore */\n }\n }\n if (book) {\n try {\n book.destroy();\n } catch {\n /* ignore */\n }\n }\n book = null;\n rendition = null;\n load();\n },\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 ref=\"root\" class=\"filex-viewer-epub\">\n <div v-if=\"error\" class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">📖</span>\n <p>{{ error }}</p>\n </div>\n <template v-else>\n <div ref=\"containerRef\" class=\"filex-viewer-epub__rendition\" />\n <div v-if=\"ready\" class=\"filex-viewer-epub__nav\">\n <button type=\"button\" class=\"filex-viewer-btn\" @click=\"prev\" :disabled=\"!ready\">‹</button>\n <button type=\"button\" class=\"filex-viewer-btn\" @click=\"next\" :disabled=\"!ready\">›</button>\n </div>\n <div v-if=\"loading\" class=\"filex-viewer-epub__loading\">\n {{ tt('viewer.loading', 'Loading…') }}\n </div>\n </template>\n </div>\n</template>\n\n<style scoped>\n.filex-viewer-epub__nav {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n gap: 8px;\n padding: 4px 8px;\n background: var(--fe-bg-elev, rgba(255, 255, 255, 0.9));\n border: 1px solid var(--fe-border, #e2e6ed);\n border-radius: 6px;\n backdrop-filter: blur(4px);\n}\n.filex-viewer-epub {\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 position: relative;\n}\n.filex-viewer-epub__bar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n font-size: 13px;\n}\n.filex-viewer-spacer { flex: 1; }\n.filex-viewer-epub__fs {\n display: inline-block;\n min-width: 40px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-epub__main {\n flex: 1;\n min-height: 0;\n display: flex;\n}\n.filex-viewer-epub__rendition {\n flex: 1;\n min-height: 0;\n}\n.filex-viewer-epub__toc {\n width: 260px;\n border-right: 1px solid var(--fe-border, #e2e6ed);\n overflow-y: auto;\n padding: 12px 0;\n background: var(--fe-bg-elev, #f7f8fa);\n}\n.filex-viewer-epub__toc ul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.filex-viewer-epub__toc-link {\n display: block;\n width: 100%;\n text-align: left;\n background: transparent;\n border: 0;\n padding: 6px 14px;\n font: inherit;\n color: inherit;\n cursor: pointer;\n}\n.filex-viewer-epub__toc-link:hover {\n background: var(--fe-bg-hover, #edf0f5);\n}\n.filex-viewer-epub__toc-link.is-child {\n padding-left: 28px;\n color: var(--fe-text-muted, #5a6475);\n font-size: 12px;\n}\n.filex-viewer-epub__loading {\n position: absolute;\n inset: auto 0 0 0;\n text-align: center;\n padding: 6px;\n background: rgba(0, 0, 0, 0.05);\n font-size: 12px;\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.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.5;\n cursor: not-allowed;\n}\n</style>\n"],"names":["props","__props","root","ref","containerRef","error","toc","fontSize","ready","loading","book","rendition","load","mod","Epub","source","headers","res","nav","err","next","_a","prev","onKey","ev","onMounted","onBeforeUnmount","_b","watch","tt","key","fallback","_createElementBlock","_openBlock","_hoisted_1","_cache","_createElementVNode","_Fragment","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_toDisplayString"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { f as J } from "./useViewerFetch-czqbd2Lj.js";
|
|
2
|
-
import { d as R, o as U, h as D, w as q, a as t, c as a, e as o, t as d, F as m, k as C, i as V, f as p, l as z, _ as G } from "./index-
|
|
2
|
+
import { d as R, o as U, h as D, w as q, a as t, c as a, e as o, t as d, F as m, k as C, i as V, f as p, l as z, _ as G } from "./index-BNs90VaG.js";
|
|
3
3
|
const K = { class: "filex-viewer-ipynb" }, P = { class: "filex-viewer-ipynb__pane" }, Q = {
|
|
4
4
|
key: 0,
|
|
5
5
|
class: "filex-viewer-fallback"
|
|
@@ -164,8 +164,8 @@ const K = { class: "filex-viewer-ipynb" }, P = { class: "filex-viewer-ipynb__pan
|
|
|
164
164
|
])
|
|
165
165
|
]));
|
|
166
166
|
}
|
|
167
|
-
}), _e = /* @__PURE__ */ G(oe, [["__scopeId", "data-v-
|
|
167
|
+
}), _e = /* @__PURE__ */ G(oe, [["__scopeId", "data-v-10bd637a"]]);
|
|
168
168
|
export {
|
|
169
169
|
_e as default
|
|
170
170
|
};
|
|
171
|
-
//# sourceMappingURL=IpynbViewer-
|
|
171
|
+
//# sourceMappingURL=IpynbViewer-B3g-lJfV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IpynbViewer-B3g-lJfV.js","sources":["../../core/src/viewers/IpynbViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * IpynbViewer — Jupyter notebook (.ipynb JSON) renderer.\n *\n * Pure-JS render — no peer dependency required:\n * - code cells → `<pre><code>` (highlight.js when available)\n * - markdown cells → markdown-it when available, plain `<pre>` otherwise\n * - output cells → text (stream / display_data 'text/plain'),\n * images (display_data 'image/png' base64),\n * HTML (display_data 'text/html', sanitized via\n * element-only insertion — no script tags)\n *\n * Source list / output count counters at the top so a 200-cell\n * notebook doesn't surprise the user.\n */\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport { fetchViewerText } from '../composables/useViewerFetch';\nimport { ensureHighlight } from '../composables/useMonacoLoader';\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\ninterface Cell {\n cell_type: 'code' | 'markdown' | 'raw' | string;\n source: string | string[];\n outputs?: any[];\n execution_count?: number | null;\n metadata?: Record<string, unknown>;\n}\n\ninterface Notebook {\n cells: Cell[];\n metadata?: { kernelspec?: { language?: string; name?: string } };\n}\n\nconst cells = ref<Cell[]>([]);\nconst language = ref<string>('python');\nconst error = ref<string | null>(null);\nconst loading = ref(true);\nconst renderedSources = ref<Map<number, string>>(new Map());\nconst renderedMarkdown = ref<Map<number, string>>(new Map());\n\nlet renderToken = 0;\nlet highlight: any = null;\nlet mdRenderer: any = null;\n\nasync function ensureMd(): Promise<any | null> {\n if (mdRenderer !== null) return mdRenderer || null;\n try {\n const mod = await import(/* @vite-ignore */ 'markdown-it');\n const Md = (mod as any).default ?? mod;\n mdRenderer = new Md({ html: false, linkify: true, breaks: true });\n return mdRenderer;\n } catch {\n mdRenderer = false;\n return null;\n }\n}\n\nfunction joinSource(source: string | string[]): string {\n return Array.isArray(source) ? source.join('') : (source ?? '');\n}\n\nasync function load(): Promise<void> {\n loading.value = true;\n error.value = null;\n cells.value = [];\n renderedSources.value = new Map();\n renderedMarkdown.value = new Map();\n const myToken = ++renderToken;\n\n let raw: string;\n try {\n raw = 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 let nb: Notebook;\n try {\n nb = JSON.parse(raw);\n } catch (err) {\n error.value = 'Invalid notebook JSON';\n loading.value = false;\n return;\n }\n cells.value = Array.isArray(nb.cells) ? nb.cells : [];\n language.value = nb.metadata?.kernelspec?.language || 'python';\n\n // Best-effort hljs highlight per code cell.\n highlight = (await ensureHighlight()) as any;\n if (myToken !== renderToken) return;\n if (highlight) {\n const hljs = highlight.default ?? highlight;\n const langOk = hljs.getLanguage?.(language.value) ? language.value : null;\n cells.value.forEach((cell, idx) => {\n if (cell.cell_type === 'code') {\n const text = joinSource(cell.source);\n try {\n const result = langOk\n ? hljs.highlight(text, { language: langOk, ignoreIllegals: true })\n : hljs.highlightAuto(text);\n renderedSources.value.set(idx, result.value);\n } catch {\n /* leave unrendered */\n }\n }\n });\n }\n\n const md = await ensureMd();\n if (myToken !== renderToken) return;\n if (md) {\n cells.value.forEach((cell, idx) => {\n if (cell.cell_type === 'markdown') {\n try {\n renderedMarkdown.value.set(idx, md.render(joinSource(cell.source)));\n } catch {\n /* leave plain */\n }\n }\n });\n }\n\n loading.value = false;\n}\n\nfunction outputText(out: any): string | null {\n if (!out) return null;\n if (out.output_type === 'stream') {\n return joinSource(out.text);\n }\n if (out.output_type === 'error') {\n return [out.ename, out.evalue, ...(out.traceback || [])]\n .filter(Boolean)\n .join('\\n');\n }\n if (out.output_type === 'execute_result' || out.output_type === 'display_data') {\n if (out.data?.['text/plain']) {\n return joinSource(out.data['text/plain']);\n }\n }\n return null;\n}\n\nfunction outputImage(out: any): string | null {\n if (!out?.data) return null;\n if (out.data['image/png']) return `data:image/png;base64,${out.data['image/png']}`;\n if (out.data['image/jpeg']) return `data:image/jpeg;base64,${out.data['image/jpeg']}`;\n if (out.data['image/svg+xml']) {\n const svg = joinSource(out.data['image/svg+xml']);\n return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;\n }\n return null;\n}\n\nfunction outputHtml(out: any): string | null {\n if (!out?.data) return null;\n if (out.data['text/html']) {\n const html = joinSource(out.data['text/html']);\n // Strip <script> for safety — outputs from arbitrary notebooks.\n return html.replace(/<script[\\s\\S]*?<\\/script>/gi, '');\n }\n return null;\n}\n\nonMounted(load);\nonBeforeUnmount(() => {\n renderToken++;\n});\nwatch(() => props.url, load);\n\nconst stats = computed(() => {\n const codeCount = cells.value.filter((c) => c.cell_type === 'code').length;\n const mdCount = cells.value.filter((c) => c.cell_type === 'markdown').length;\n return { code: codeCount, md: mdCount, total: cells.value.length };\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-ipynb\">\n <div class=\"filex-viewer-ipynb__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 <div v-else>\n <div\n v-for=\"(cell, idx) in cells\"\n :key=\"idx\"\n class=\"filex-viewer-ipynb__cell\"\n :data-type=\"cell.cell_type\"\n >\n <template v-if=\"cell.cell_type === 'code'\">\n <div class=\"filex-viewer-ipynb__exec\">\n In [{{ cell.execution_count ?? ' ' }}]:\n </div>\n <pre class=\"filex-viewer-ipynb__src hljs\"><code\n v-if=\"renderedSources.get(idx)\"\n v-html=\"renderedSources.get(idx)\"\n /><code v-else>{{ joinSource(cell.source) }}</code></pre>\n <div v-if=\"cell.outputs && cell.outputs.length\" class=\"filex-viewer-ipynb__outputs\">\n <template v-for=\"(out, j) in cell.outputs\" :key=\"j\">\n <img\n v-if=\"outputImage(out)\"\n :src=\"outputImage(out) || ''\"\n class=\"filex-viewer-ipynb__img\"\n :alt=\"`output ${j}`\"\n />\n <div\n v-else-if=\"outputHtml(out)\"\n class=\"filex-viewer-ipynb__html\"\n v-html=\"outputHtml(out)\"\n />\n <pre\n v-else-if=\"outputText(out)\"\n class=\"filex-viewer-ipynb__out\"\n :data-type=\"out.output_type\"\n >{{ outputText(out) }}</pre>\n </template>\n </div>\n </template>\n\n <template v-else-if=\"cell.cell_type === 'markdown'\">\n <div\n v-if=\"renderedMarkdown.get(idx)\"\n class=\"filex-viewer-ipynb__md\"\n v-html=\"renderedMarkdown.get(idx)\"\n />\n <pre v-else class=\"filex-viewer-ipynb__md-raw\">{{ joinSource(cell.source) }}</pre>\n </template>\n\n <template v-else>\n <pre class=\"filex-viewer-ipynb__src\">{{ joinSource(cell.source) }}</pre>\n </template>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.filex-viewer-ipynb {\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-ipynb__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 color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-ipynb__lang {\n font-family: var(--fe-font-mono, monospace);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n.filex-viewer-ipynb__pane {\n flex: 1;\n overflow: auto;\n padding: 16px 24px;\n}\n.filex-viewer-ipynb__cell {\n border: 1px solid var(--fe-border, #e2e6ed);\n border-radius: 6px;\n margin-bottom: 16px;\n overflow: hidden;\n}\n.filex-viewer-ipynb__cell[data-type=\"code\"] {\n background: var(--fe-bg-elev, #f7f8fa);\n}\n.filex-viewer-ipynb__exec {\n padding: 4px 12px;\n font-family: var(--fe-font-mono, monospace);\n font-size: 11px;\n color: var(--fe-text-muted, #5a6475);\n background: rgba(0, 0, 0, 0.04);\n}\n.filex-viewer-ipynb__src {\n margin: 0;\n padding: 12px;\n font-family: var(--fe-font-mono, monospace);\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n overflow-x: auto;\n}\n.filex-viewer-ipynb__outputs {\n border-top: 1px dashed var(--fe-border, #e2e6ed);\n background: var(--fe-bg, #fff);\n padding: 8px 12px;\n}\n.filex-viewer-ipynb__out {\n margin: 0;\n padding: 4px 0;\n font-family: var(--fe-font-mono, monospace);\n font-size: 12px;\n white-space: pre-wrap;\n word-wrap: break-word;\n}\n.filex-viewer-ipynb__out[data-type=\"error\"] {\n color: var(--fe-danger, #dc2626);\n}\n.filex-viewer-ipynb__img {\n display: block;\n max-width: 100%;\n height: auto;\n margin: 8px 0;\n}\n.filex-viewer-ipynb__html {\n font-size: 13px;\n}\n.filex-viewer-ipynb__md {\n padding: 12px 16px;\n font-size: 14px;\n line-height: 1.6;\n}\n.filex-viewer-ipynb__md-raw {\n padding: 12px;\n margin: 0;\n font-family: var(--fe-font-mono, monospace);\n font-size: 12px;\n white-space: pre-wrap;\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","cells","ref","language","error","loading","renderedSources","renderedMarkdown","renderToken","highlight","mdRenderer","ensureMd","mod","Md","joinSource","source","load","myToken","raw","fetchViewerText","_a","err","nb","_c","_b","ensureHighlight","hljs","langOk","_d","cell","idx","text","result","md","outputText","out","outputImage","svg","outputHtml","onMounted","onBeforeUnmount","watch","tt","key","fallback","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_cache","_hoisted_4","_hoisted_5","_Fragment","_renderList","_hoisted_7","_hoisted_8","_hoisted_10","_toDisplayString","_hoisted_11","j","_hoisted_14","_hoisted_16","_hoisted_17"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as E, o as L, h as T, a as _, c as h, e as u, t as k, i as $, j as H, v as Y, n as q, f as c, _ as z } from "./index-
|
|
1
|
+
import { d as E, o as L, h as T, a as _, c as h, e as u, t as k, i as $, j as H, v as Y, n as q, f as c, _ as z } from "./index-BNs90VaG.js";
|
|
2
2
|
import { f as F } from "./useViewerFetch-czqbd2Lj.js";
|
|
3
3
|
const I = { class: "filex-viewer-mermaid" }, K = {
|
|
4
4
|
key: 0,
|
|
@@ -120,8 +120,8 @@ const I = { class: "filex-viewer-mermaid" }, K = {
|
|
|
120
120
|
], 32)
|
|
121
121
|
]));
|
|
122
122
|
}
|
|
123
|
-
}), j = /* @__PURE__ */ z(U, [["__scopeId", "data-v-
|
|
123
|
+
}), j = /* @__PURE__ */ z(U, [["__scopeId", "data-v-e19076c3"]]);
|
|
124
124
|
export {
|
|
125
125
|
j as default
|
|
126
126
|
};
|
|
127
|
-
//# sourceMappingURL=MermaidViewer-
|
|
127
|
+
//# sourceMappingURL=MermaidViewer-B0Q0ghbV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MermaidViewer-B0Q0ghbV.js","sources":["../../core/src/viewers/MermaidViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * MermaidViewer — render a `.mmd` / `.mermaid` source file.\n *\n * Lazy-imports the `mermaid` library (~150 KB gzipped). Source text is\n * fetched from `props.url` (with the auth headers from PreviewModal),\n * then rendered to SVG via `mermaid.render('id', src)`. The resulting\n * SVG node is inserted into a wrapper that supports pan + scale via\n * pure CSS transforms (no extra panzoom dep).\n */\nimport { onBeforeUnmount, onMounted, ref } from 'vue';\nimport { fetchViewerText } from '../composables/useViewerFetch';\n\nconst props = defineProps<{\n url: string;\n mime?: string;\n ext: string;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string>;\n authCredentials?: RequestCredentials;\n}>();\n\nconst surface = ref<HTMLDivElement | null>(null);\nconst error = ref<string | null>(null);\nconst loading = ref(true);\nconst scale = ref(1);\nconst tx = ref(0);\nconst ty = ref(0);\n\nlet dragging = false;\nlet dragStart: { x: number; y: number; tx: number; ty: number } | null = null;\nlet renderToken = 0;\n\nlet cachedMermaid: any = null;\nasync function ensureMermaid(): Promise<any | null> {\n if (cachedMermaid) return cachedMermaid;\n try {\n const mod = await import(/* @vite-ignore */ 'mermaid');\n cachedMermaid = mod.default ?? mod;\n cachedMermaid.initialize?.({\n startOnLoad: false,\n securityLevel: 'strict',\n theme: window.matchMedia?.('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'default',\n });\n return cachedMermaid;\n } catch {\n return null;\n }\n}\n\nasync function load(): Promise<void> {\n loading.value = true;\n error.value = null;\n const myToken = ++renderToken;\n\n const mermaid = await ensureMermaid();\n if (myToken !== renderToken) return;\n if (!mermaid) {\n error.value = props.t\n ? props.t('viewer.peer_not_installed')\n : 'Mermaid viewer requires `mermaid` — install or use download.';\n loading.value = false;\n return;\n }\n\n let src: string;\n try {\n src = 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 try {\n const id = `filex-mermaid-${Date.now()}`;\n const { svg } = await mermaid.render(id, src);\n if (myToken !== renderToken) return;\n if (surface.value) {\n surface.value.innerHTML = svg;\n const svgEl = surface.value.querySelector('svg');\n if (svgEl) {\n svgEl.style.maxWidth = '100%';\n svgEl.style.height = 'auto';\n }\n }\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'render failed';\n } finally {\n loading.value = false;\n }\n}\n\nfunction zoomIn(): void {\n scale.value = Math.min(8, scale.value * 1.25);\n}\nfunction zoomOut(): void {\n scale.value = Math.max(0.2, scale.value / 1.25);\n}\nfunction reset(): void {\n scale.value = 1;\n tx.value = 0;\n ty.value = 0;\n}\n\nfunction onWheel(ev: WheelEvent): void {\n if (!ev.ctrlKey && !ev.metaKey) return;\n ev.preventDefault();\n const delta = -ev.deltaY;\n const factor = delta > 0 ? 1.1 : 1 / 1.1;\n scale.value = Math.max(0.2, Math.min(8, scale.value * factor));\n}\n\nfunction onPointerDown(ev: PointerEvent): void {\n dragging = true;\n dragStart = { x: ev.clientX, y: ev.clientY, tx: tx.value, ty: ty.value };\n (ev.target as HTMLElement).setPointerCapture?.(ev.pointerId);\n}\nfunction onPointerMove(ev: PointerEvent): void {\n if (!dragging || !dragStart) return;\n tx.value = dragStart.tx + (ev.clientX - dragStart.x);\n ty.value = dragStart.ty + (ev.clientY - dragStart.y);\n}\nfunction onPointerUp(): void {\n dragging = false;\n dragStart = null;\n}\n\nonMounted(load);\nonBeforeUnmount(() => {\n renderToken++;\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-mermaid\">\n <div\n class=\"filex-viewer-mermaid__pane\"\n @wheel=\"onWheel\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerUp\"\n >\n <div\n v-if=\"error\"\n class=\"filex-viewer-fallback\"\n >\n <span class=\"filex-viewer-fallback__icon\">📊</span>\n <p>{{ error }}</p>\n </div>\n <div\n v-else-if=\"loading\"\n class=\"filex-viewer-fallback\"\n >\n <span class=\"filex-viewer-fallback__icon\">⏳</span>\n <p>{{ tt('viewer.loading', 'Loading…') }}</p>\n </div>\n <div\n v-show=\"!loading && !error\"\n ref=\"surface\"\n class=\"filex-viewer-mermaid__surface\"\n :style=\"{ transform: `translate(${tx}px, ${ty}px) scale(${scale})` }\"\n />\n </div>\n </div>\n</template>\n\n<style scoped>\n.filex-viewer-mermaid {\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-mermaid__bar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n font-size: 13px;\n}\n.filex-viewer-mermaid__zoom {\n min-width: 50px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n}\n.filex-viewer-mermaid__pane {\n flex: 1;\n overflow: hidden;\n position: relative;\n cursor: grab;\n background: var(--fe-bg-elev, #f7f8fa);\n touch-action: none;\n}\n.filex-viewer-mermaid__pane:active {\n cursor: grabbing;\n}\n.filex-viewer-mermaid__surface {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n transform-origin: center center;\n transition: transform 0.05s linear;\n user-select: none;\n}\n.filex-viewer-mermaid__surface :deep(svg) {\n max-width: 90%;\n max-height: 90%;\n}\n.filex-viewer-fallback {\n text-align: center;\n padding: 32px;\n color: var(--fe-text-muted, #5a6475);\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\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</style>\n"],"names":["props","__props","surface","ref","error","loading","scale","tx","ty","dragging","dragStart","renderToken","cachedMermaid","ensureMermaid","mod","_b","_a","load","myToken","mermaid","src","fetchViewerText","err","id","svg","svgEl","onWheel","ev","factor","onPointerDown","onPointerMove","onPointerUp","onMounted","onBeforeUnmount","tt","key","fallback","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_cache","_hoisted_3","_normalizeStyle","_vShow"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as B, o as E, h as I, w as S, a as m, c as p, e as i, t as x, i as V, j as A, v as L, f as o, _ as T } from "./index-
|
|
1
|
+
import { d as B, o as E, h as I, w as S, a as m, c as p, e as i, t as x, i as V, j as A, v as L, f as o, _ as T } from "./index-BNs90VaG.js";
|
|
2
2
|
import { a as F } from "./useViewerFetch-czqbd2Lj.js";
|
|
3
3
|
const H = { class: "filex-viewer-psd" }, N = { class: "filex-viewer-psd__pane" }, j = {
|
|
4
4
|
key: 0,
|
|
@@ -16,10 +16,10 @@ const H = { class: "filex-viewer-psd" }, N = { class: "filex-viewer-psd__pane" }
|
|
|
16
16
|
authHeaders: { type: Function },
|
|
17
17
|
authCredentials: {}
|
|
18
18
|
},
|
|
19
|
-
setup(
|
|
20
|
-
const a =
|
|
19
|
+
setup(b) {
|
|
20
|
+
const a = b, f = o(null), w = o([]), s = o(null), l = o(!0), D = o({ width: 0, height: 0 });
|
|
21
21
|
let c = 0, u = null;
|
|
22
|
-
async function
|
|
22
|
+
async function P() {
|
|
23
23
|
if (u) return u;
|
|
24
24
|
try {
|
|
25
25
|
return u = await import(
|
|
@@ -42,7 +42,7 @@ const H = { class: "filex-viewer-psd" }, N = { class: "filex-viewer-psd__pane" }
|
|
|
42
42
|
async function g() {
|
|
43
43
|
var n;
|
|
44
44
|
l.value = !0, s.value = null, w.value = [];
|
|
45
|
-
const t = ++c, e = await
|
|
45
|
+
const t = ++c, e = await P();
|
|
46
46
|
if (t === c) {
|
|
47
47
|
if (!e) {
|
|
48
48
|
s.value = a.t ? a.t("viewer.peer_not_installed") : "PSD viewer requires `ag-psd` — install or use download.", l.value = !1;
|
|
@@ -60,7 +60,7 @@ const H = { class: "filex-viewer-psd" }, N = { class: "filex-viewer-psd__pane" }
|
|
|
60
60
|
skipCompositeImageData: !1,
|
|
61
61
|
skipThumbnail: !0
|
|
62
62
|
});
|
|
63
|
-
|
|
63
|
+
D.value = { width: r.width, height: r.height };
|
|
64
64
|
const y = r.canvas;
|
|
65
65
|
if (y && f.value) {
|
|
66
66
|
const h = f.value;
|
|
@@ -102,8 +102,8 @@ const H = { class: "filex-viewer-psd" }, N = { class: "filex-viewer-psd__pane" }
|
|
|
102
102
|
])
|
|
103
103
|
]));
|
|
104
104
|
}
|
|
105
|
-
}), G = /* @__PURE__ */ T(M, [["__scopeId", "data-v-
|
|
105
|
+
}), G = /* @__PURE__ */ T(M, [["__scopeId", "data-v-46b5b3c2"]]);
|
|
106
106
|
export {
|
|
107
107
|
G as default
|
|
108
108
|
};
|
|
109
|
-
//# sourceMappingURL=PsdViewer-
|
|
109
|
+
//# sourceMappingURL=PsdViewer-lk6xrjRB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PsdViewer-lk6xrjRB.js","sources":["../../core/src/viewers/PsdViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * PsdViewer — Photoshop document preview via `ag-psd`.\n *\n * Lazy-imports `ag-psd` (~150 KB). Renders the flattened composite to\n * a canvas via `psd.canvas`. A simple layer panel toggles the rendered\n * preview (V1: just lists names + visibility; full composite swap on\n * toggle requires re-rendering with `applyOpacity`/`composite` logic\n * — left as TODO for V2 since `ag-psd` doesn't ship a composite\n * pipeline of its own).\n */\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport { fetchViewerArrayBuffer } from '../composables/useViewerFetch';\n\nconst props = defineProps<{\n url: string;\n mime?: string;\n ext: string;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string>;\n authCredentials?: RequestCredentials;\n}>();\n\ninterface FlatLayer {\n index: number;\n name: string;\n hidden: boolean;\n}\n\nconst canvasEl = ref<HTMLCanvasElement | null>(null);\nconst layers = ref<FlatLayer[]>([]);\nconst error = ref<string | null>(null);\nconst loading = ref(true);\nconst showLayerPanel = ref(false);\nconst dims = ref<{ width: number; height: number }>({ width: 0, height: 0 });\nconst scale = ref(1);\n\nlet renderToken = 0;\n\nlet agPsd: any = null;\nasync function ensureAgPsd(): Promise<any | null> {\n if (agPsd) return agPsd;\n try {\n const mod = await import(/* @vite-ignore */ 'ag-psd');\n agPsd = mod;\n return agPsd;\n } catch {\n return null;\n }\n}\n\nfunction flattenLayers(node: any, list: FlatLayer[]): void {\n if (!node) return;\n if (Array.isArray(node.children)) {\n for (const child of node.children) {\n list.push({\n index: list.length,\n name: child.name ?? '(unnamed)',\n hidden: !!child.hidden,\n });\n if (child.children) flattenLayers(child, list);\n }\n }\n}\n\nasync function load(): Promise<void> {\n loading.value = true;\n error.value = null;\n layers.value = [];\n const myToken = ++renderToken;\n\n const lib = await ensureAgPsd();\n if (myToken !== renderToken) return;\n if (!lib) {\n error.value = props.t\n ? props.t('viewer.peer_not_installed')\n : 'PSD viewer requires `ag-psd` — install or use download.';\n loading.value = false;\n return;\n }\n\n try {\n const buf = await fetchViewerArrayBuffer({\n url: props.url,\n headers: props.authHeaders?.() ?? {},\n credentials: props.authCredentials,\n });\n if (myToken !== renderToken) return;\n const psd = lib.readPsd(buf, {\n skipLayerImageData: false,\n skipCompositeImageData: false,\n skipThumbnail: true,\n });\n dims.value = { width: psd.width, height: psd.height };\n\n const composite = psd.canvas;\n if (composite && canvasEl.value) {\n const target = canvasEl.value;\n target.width = psd.width;\n target.height = psd.height;\n const ctx = target.getContext('2d');\n ctx?.drawImage(composite, 0, 0);\n } else {\n throw new Error('PSD has no composite image (skipCompositeImageData?)');\n }\n\n const flat: FlatLayer[] = [];\n flattenLayers(psd, flat);\n layers.value = flat;\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'PSD decode failed';\n } finally {\n loading.value = false;\n }\n}\n\nfunction zoomIn(): void {\n scale.value = Math.min(8, scale.value * 1.25);\n}\nfunction zoomOut(): void {\n scale.value = Math.max(0.1, scale.value / 1.25);\n}\nfunction reset(): void {\n scale.value = 1;\n}\n\nonMounted(load);\nonBeforeUnmount(() => {\n renderToken++;\n});\nwatch(() => props.url, load);\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-psd\">\n <div class=\"filex-viewer-psd__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 <canvas\n v-show=\"!loading && !error\"\n ref=\"canvasEl\"\n />\n </div>\n </div>\n</template>\n\n<style scoped>\n.filex-viewer-psd {\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-psd__bar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n font-size: 13px;\n}\n.filex-viewer-spacer { flex: 1; }\n.filex-viewer-psd__dim {\n font-size: 12px;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-psd__zoom {\n min-width: 50px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n}\n.filex-viewer-psd__main {\n flex: 1;\n display: flex;\n min-height: 0;\n}\n.filex-viewer-psd__layers {\n width: 240px;\n border-right: 1px solid var(--fe-border, #e2e6ed);\n overflow-y: auto;\n padding: 8px 0;\n background: var(--fe-bg-elev, #f7f8fa);\n}\n.filex-viewer-psd__layers ul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.filex-viewer-psd__layers li {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n font-size: 12px;\n}\n.filex-viewer-psd__layer-vis {\n width: 14px;\n text-align: center;\n color: var(--fe-text-muted, #5a6475);\n}\n.filex-viewer-psd__layer-vis[data-hidden=\"1\"] { color: var(--fe-border-strong, #c7ced9); }\n.filex-viewer-psd__layer-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.filex-viewer-psd__pane {\n flex: 1;\n overflow: auto;\n padding: 16px;\n background: #2a2d33;\n display: flex;\n align-items: flex-start;\n justify-content: flex-start;\n}\n.filex-viewer-psd__pane canvas {\n background: #fff\n repeating-conic-gradient(#e0e0e0 0% 25%, transparent 0% 50%) 50% / 16px 16px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n}\n.filex-viewer-fallback {\n text-align: center;\n padding: 32px;\n color: #c8cdd6;\n margin: auto;\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.is-active {\n background: var(--fe-bg-selected, #dfe8ff);\n border-color: var(--fe-primary, #3b82f6);\n}\n</style>\n"],"names":["props","__props","canvasEl","ref","layers","error","loading","dims","renderToken","agPsd","ensureAgPsd","flattenLayers","node","list","child","load","myToken","lib","buf","fetchViewerArrayBuffer","_a","psd","composite","target","ctx","flat","err","onMounted","onBeforeUnmount","watch","tt","key","fallback","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_cache","_hoisted_4","_vShow"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as S, o as U, h as M, w as N, a as _, c as h, e as i, t as b, i as C, j as A, v as H, f as d, g as L, _ as R } from "./index-
|
|
1
|
+
import { d as S, o as U, h as M, w as N, a as _, c as h, e as i, t as b, i as C, j as A, v as H, f as d, g as L, _ as R } from "./index-BNs90VaG.js";
|
|
2
2
|
import { a as j } from "./useViewerFetch-czqbd2Lj.js";
|
|
3
3
|
const q = { class: "filex-viewer-tiff" }, G = { class: "filex-viewer-tiff__pane" }, P = {
|
|
4
4
|
key: 0,
|
|
@@ -123,8 +123,8 @@ const q = { class: "filex-viewer-tiff" }, G = { class: "filex-viewer-tiff__pane"
|
|
|
123
123
|
])
|
|
124
124
|
]));
|
|
125
125
|
}
|
|
126
|
-
}), Z = /* @__PURE__ */ R(W, [["__scopeId", "data-v-
|
|
126
|
+
}), Z = /* @__PURE__ */ R(W, [["__scopeId", "data-v-11c3469a"]]);
|
|
127
127
|
export {
|
|
128
128
|
Z as default
|
|
129
129
|
};
|
|
130
|
-
//# sourceMappingURL=TiffViewer-
|
|
130
|
+
//# sourceMappingURL=TiffViewer-PXjYKqzo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TiffViewer-PXjYKqzo.js","sources":["../../core/src/viewers/TiffViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * TiffViewer — multi-page TIFF preview via `utif`.\n *\n * Lazy-imports `utif` (~50 KB). Decodes IFDs once, paints the active\n * page to a `<canvas>` via `UTIF.toRGBA8`. Page navigation (1/N) +\n * zoom in/out controls. Browser <img> can't render TIFF natively, so\n * the canvas pipeline is the only option short of server-side\n * conversion.\n */\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport { fetchViewerArrayBuffer } from '../composables/useViewerFetch';\n\nconst props = defineProps<{\n url: string;\n mime?: string;\n ext: string;\n t?: (key: string) => string;\n authHeaders?: () => Record<string, string>;\n authCredentials?: RequestCredentials;\n}>();\n\nconst canvasEl = ref<HTMLCanvasElement | null>(null);\nconst error = ref<string | null>(null);\nconst loading = ref(true);\nconst scale = ref(1);\nconst pageIndex = ref(0);\nconst pageCount = ref(0);\nconst pageDims = ref<{ width: number; height: number }>({ width: 0, height: 0 });\n\nlet UTIF: any = null;\nlet ifds: any[] | null = null;\nlet renderToken = 0;\n\nasync function ensureUtif(): Promise<any | null> {\n if (UTIF) return UTIF;\n try {\n const mod = await import(/* @vite-ignore */ 'utif');\n UTIF = mod.default ?? mod;\n return UTIF;\n } catch {\n return null;\n }\n}\n\nasync function load(): Promise<void> {\n loading.value = true;\n error.value = null;\n ifds = null;\n pageIndex.value = 0;\n pageCount.value = 0;\n const myToken = ++renderToken;\n\n const lib = await ensureUtif();\n if (myToken !== renderToken) return;\n if (!lib) {\n error.value = props.t\n ? props.t('viewer.peer_not_installed')\n : 'TIFF viewer requires `utif` — install or use download.';\n loading.value = false;\n return;\n }\n\n try {\n const buf = await fetchViewerArrayBuffer({\n url: props.url,\n headers: props.authHeaders?.() ?? {},\n credentials: props.authCredentials,\n });\n if (myToken !== renderToken) return;\n ifds = lib.decode(buf);\n pageCount.value = ifds?.length ?? 0;\n if (pageCount.value === 0) {\n throw new Error('No pages decoded');\n }\n paint();\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'TIFF decode failed';\n } finally {\n loading.value = false;\n }\n}\n\nfunction paint(): void {\n if (!UTIF || !ifds || !canvasEl.value) return;\n const idx = Math.max(0, Math.min(pageIndex.value, ifds.length - 1));\n const ifd = ifds[idx];\n try {\n UTIF.decodeImage(undefined, ifd);\n } catch {\n // some images already decoded — UTIF.decodeImage is idempotent on\n // older versions.\n }\n const rgba = UTIF.toRGBA8(ifd);\n const w = ifd.width;\n const h = ifd.height;\n pageDims.value = { width: w, height: h };\n const canvas = canvasEl.value;\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n const imageData = ctx.createImageData(w, h);\n imageData.data.set(rgba);\n ctx.putImageData(imageData, 0, 0);\n}\n\nfunction next(): void {\n if (pageIndex.value < pageCount.value - 1) {\n pageIndex.value++;\n paint();\n }\n}\nfunction prev(): void {\n if (pageIndex.value > 0) {\n pageIndex.value--;\n paint();\n }\n}\nfunction zoomIn(): void {\n scale.value = Math.min(8, scale.value * 1.25);\n}\nfunction zoomOut(): void {\n scale.value = Math.max(0.1, scale.value / 1.25);\n}\nfunction reset(): void {\n scale.value = 1;\n}\n\nonMounted(load);\nonBeforeUnmount(() => {\n renderToken++;\n ifds = null;\n});\n\nwatch(() => props.url, load);\n\nconst pageLabel = computed(() => {\n const m = (props.t && props.t('viewer.page_n_of_m')) || 'Page {n} of {m}';\n return m.replace('{n}', String(pageIndex.value + 1)).replace('{m}', String(pageCount.value));\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-tiff\">\n <div class=\"filex-viewer-tiff__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 <canvas\n v-show=\"!loading && !error\"\n ref=\"canvasEl\"\n :style=\"{ imageRendering: 'pixelated' }\"\n />\n <div v-if=\"!loading && !error && pageCount > 1\" class=\"filex-viewer-tiff__pager\">\n <button\n type=\"button\"\n class=\"filex-viewer-btn\"\n :disabled=\"pageIndex === 0\"\n @click=\"prev\"\n >‹</button>\n <span class=\"filex-viewer-tiff__pages\">{{ pageLabel }}</span>\n <button\n type=\"button\"\n class=\"filex-viewer-btn\"\n :disabled=\"pageIndex >= pageCount - 1\"\n @click=\"next\"\n >›</button>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.filex-viewer-tiff__pager {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px;\n background: var(--fe-bg-elev, rgba(255, 255, 255, 0.9));\n border: 1px solid var(--fe-border, #e2e6ed);\n border-radius: 6px;\n backdrop-filter: blur(4px);\n}\n.filex-viewer-tiff__pages {\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n}\n.filex-viewer-tiff {\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-tiff__bar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: var(--fe-bg-elev, #f7f8fa);\n border-bottom: 1px solid var(--fe-border, #e2e6ed);\n font-size: 13px;\n}\n.filex-viewer-tiff__pages {\n min-width: 110px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n}\n.filex-viewer-tiff__zoom {\n min-width: 50px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n}\n.filex-viewer-spacer { flex: 1; }\n.filex-viewer-tiff__pane {\n flex: 1;\n overflow: auto;\n padding: 16px;\n background: #2a2d33;\n display: flex;\n align-items: flex-start;\n justify-content: flex-start;\n}\n.filex-viewer-tiff__pane canvas {\n background: #fff;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n}\n.filex-viewer-fallback {\n text-align: center;\n padding: 32px;\n color: #c8cdd6;\n margin: auto;\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":["props","__props","canvasEl","ref","error","loading","pageIndex","pageCount","pageDims","UTIF","ifds","renderToken","ensureUtif","mod","n","load","myToken","lib","buf","fetchViewerArrayBuffer","_a","paint","err","idx","ifd","rgba","w","h","canvas","ctx","imageData","next","prev","onMounted","onBeforeUnmount","watch","pageLabel","computed","tt","key","fallback","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_cache","_hoisted_4","_vShow","_hoisted_5","_hoisted_6","_hoisted_7","_toDisplayString","_hoisted_8"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as w, o as f, w as m, r as _, a as o, c as r, b as x, e as s, t as c, f as
|
|
1
|
+
import { d as w, o as f, w as m, r as _, a as o, c as r, b as x, e as s, t as c, f as u, g as y, _ as k } from "./index-BNs90VaG.js";
|
|
2
2
|
const g = { class: "filex-viewer-3d" }, h = {
|
|
3
3
|
key: 1,
|
|
4
4
|
class: "filex-viewer-fallback"
|
|
@@ -14,7 +14,7 @@ const g = { class: "filex-viewer-3d" }, h = {
|
|
|
14
14
|
t: { type: Function }
|
|
15
15
|
},
|
|
16
16
|
setup(a) {
|
|
17
|
-
const e = a,
|
|
17
|
+
const e = a, d = /* @__PURE__ */ new Set(["glb", "gltf", "usdz"]), v = y(() => d.has((e.ext || "").toLowerCase())), t = u(null), n = u(!1);
|
|
18
18
|
async function i() {
|
|
19
19
|
if (n.value = !1, t.value = null, !v.value) {
|
|
20
20
|
t.value = e.t ? e.t("viewer.format_unsupported_3d") : `3D format ".${e.ext}" not supported in browser preview — please download.`;
|
|
@@ -53,8 +53,8 @@ const g = { class: "filex-viewer-3d" }, h = {
|
|
|
53
53
|
]);
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
|
-
}), C = /* @__PURE__ */ k(D, [["__scopeId", "data-v-
|
|
56
|
+
}), C = /* @__PURE__ */ k(D, [["__scopeId", "data-v-299b3816"]]);
|
|
57
57
|
export {
|
|
58
58
|
C as default
|
|
59
59
|
};
|
|
60
|
-
//# sourceMappingURL=Viewer3D-
|
|
60
|
+
//# sourceMappingURL=Viewer3D-DtT-hBa3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Viewer3D-DtT-hBa3.js","sources":["../../core/src/viewers/Viewer3D.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Viewer3D — 3D model preview via `@google/model-viewer`.\n *\n * Lazy-imports the `@google/model-viewer` web component (~80 KB).\n *\n * Format support: model-viewer **only** understands glTF (`.gltf`,\n * `.glb`) and USDZ (iOS). For unsupported formats (`.stl`, `.obj`,\n * `.fbx`, `.3ds`) we deliberately render a download fallback instead\n * of feeding them to model-viewer — earlier code did the latter,\n * which surfaced as `JSON.parse(<ascii STL>)` SyntaxError because\n * model-viewer parses the response body as glTF JSON. (sweep-2026-05-09\n * bugs 19-20.)\n *\n * GLB rendering size: model-viewer mounts its canvas inside a\n * shadow root that doesn't always inherit `height: 100%` from\n * flexbox parents — we pin explicit sizing on the host element\n * to avoid the \"Framebuffer is incomplete: zero size\" warning.\n * (sweep-2026-05-09 bug 21.)\n */\nimport { computed, onMounted, ref, watch } from 'vue';\n\nconst props = defineProps<{\n url: string;\n mime?: string;\n ext: string;\n /** Locale-aware error/loading messages. */\n t?: (key: string) => string;\n}>();\n\nconst SUPPORTED_EXTS = new Set(['glb', 'gltf', 'usdz']);\n\nconst isSupported = computed(() => SUPPORTED_EXTS.has((props.ext || '').toLowerCase()));\n\nconst error = ref<string | null>(null);\nconst ready = ref(false);\n\nasync function load(): Promise<void> {\n ready.value = false;\n error.value = null;\n // Bail out early for formats model-viewer can't parse — feeding\n // them to <model-viewer> triggers JSON.parse SyntaxError because\n // it expects glTF JSON.\n if (!isSupported.value) {\n error.value = props.t\n ? props.t('viewer.format_unsupported_3d')\n : `3D format \".${props.ext}\" not supported in browser preview — please download.`;\n return;\n }\n try {\n await import(/* @vite-ignore */ '@google/model-viewer');\n ready.value = true;\n } catch {\n error.value = props.t\n ? props.t('viewer.peer_not_installed')\n : '3D viewer requires `@google/model-viewer` — install or use download.';\n }\n}\n\nonMounted(load);\n\nwatch(() => props.url, () => {\n // Re-evaluate on URL change (different file may need different\n // fallback message).\n load();\n});\n</script>\n\n<template>\n <div class=\"filex-viewer-3d\">\n <model-viewer\n v-if=\"ready && !error\"\n :src=\"url\"\n auto-rotate\n camera-controls\n touch-action=\"pan-y\"\n shadow-intensity=\"1\"\n :alt=\"ext + ' model'\"\n style=\"width: 100%; height: 100%; min-height: 480px; display: block\"\n />\n <div v-else-if=\"error\" class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">📦</span>\n <p>{{ error }}</p>\n </div>\n <div v-else class=\"filex-viewer-fallback\">\n <span class=\"filex-viewer-fallback__icon\">⏳</span>\n <p>{{ t ? t('viewer.loading') : 'Loading…' }}</p>\n </div>\n </div>\n</template>\n\n<style scoped>\n.filex-viewer-3d {\n width: 100%;\n height: 100%;\n min-height: 480px;\n background: #1a1a1a;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.filex-viewer-3d :deep(model-viewer) {\n width: 100%;\n height: 100%;\n min-height: 480px;\n background: #1a1a1a;\n display: block;\n}\n.filex-viewer-fallback {\n text-align: center;\n color: #c8cdd6;\n padding: 32px;\n max-width: 480px;\n}\n.filex-viewer-fallback__icon {\n font-size: 48px;\n display: block;\n margin-bottom: 12px;\n}\n</style>\n"],"names":["props","__props","SUPPORTED_EXTS","isSupported","computed","error","ref","ready","load","onMounted","watch","_openBlock","_createElementBlock","_hoisted_1","_createBlock","_component_model_viewer","_hoisted_2","_cache","_createElementVNode","_hoisted_3","_toDisplayString"],"mappings":";;;;;;;;;;;;;;;;AAsBA,UAAMA,IAAQC,GAQRC,IAAiB,oBAAI,IAAI,CAAC,OAAO,QAAQ,MAAM,CAAC,GAEhDC,IAAcC,EAAS,MAAMF,EAAe,KAAKF,EAAM,OAAO,IAAI,YAAA,CAAa,CAAC,GAEhFK,IAAQC,EAAmB,IAAI,GAC/BC,IAAQD,EAAI,EAAK;AAEvB,mBAAeE,IAAsB;AAMnC,UALAD,EAAM,QAAQ,IACdF,EAAM,QAAQ,MAIV,CAACF,EAAY,OAAO;AACtB,QAAAE,EAAM,QAAQL,EAAM,IAChBA,EAAM,EAAE,8BAA8B,IACtC,eAAeA,EAAM,GAAG;AAC5B;AAAA,MACF;AACA,UAAI;AACF,cAAM;AAAA;AAAA,UAA0B;AAAA,QAAA,GAChCO,EAAM,QAAQ;AAAA,MAChB,QAAQ;AACN,QAAAF,EAAM,QAAQL,EAAM,IAChBA,EAAM,EAAE,2BAA2B,IACnC;AAAA,MACN;AAAA,IACF;AAEA,WAAAS,EAAUD,CAAI,GAEdE,EAAM,MAAMV,EAAM,KAAK,MAAM;AAG3B,MAAAQ,EAAA;AAAA,IACF,CAAC;;AAIC,aAAAG,EAAA,GAAAC,EAmBM,OAnBNC,GAmBM;AAAA,QAjBIN,EAAA,UAAUF,EAAA,cADlBS,EASEC,GAAA;AAAA;UAPC,KAAKd,EAAA;AAAA,UACN,eAAA;AAAA,UACA,mBAAA;AAAA,UACA,gBAAa;AAAA,UACb,oBAAiB;AAAA,UAChB,KAAKA,EAAA,MAAG;AAAA,UACT,OAAA,EAAA,OAAA,QAAA,QAAA,QAAA,cAAA,SAAA,SAAA,QAAA;AAAA,QAAA,+BAEcI,EAAA,SAAhBM,EAAA,GAAAC,EAGM,OAHNI,GAGM;AAAA,UAFJC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAC,EAAmD,QAAA,EAA7C,OAAM,8BAAA,GAA8B,MAAE,EAAA;AAAA,UAC5CA,EAAkB,aAAZb,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA,OAEbM,EAAA,GAAAC,EAGM,OAHNO,GAGM;AAAA,UAFJF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAC,EAAkD,QAAA,EAA5C,OAAM,8BAAA,GAA8B,KAAC,EAAA;AAAA,UAC3CA,EAAiD,KAAA,MAAAE,EAA3CnB,EAAA,IAAIA,EAAA,EAAC,gBAAA,IAAA,UAAA,GAAA,CAAA;AAAA,QAAA;;;;;"}
|
package/dist/filex.js
CHANGED