@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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/ArchiveViewer-CMaBM4yZ.js +98 -0
  4. package/dist/ArchiveViewer-CMaBM4yZ.js.map +1 -0
  5. package/dist/CsvViewer-D5_c7bkP.js +131 -0
  6. package/dist/CsvViewer-D5_c7bkP.js.map +1 -0
  7. package/dist/DrawioViewer-CBOqWzaj.js +140 -0
  8. package/dist/DrawioViewer-CBOqWzaj.js.map +1 -0
  9. package/dist/EpubViewer-Cs6yZIP2.js +143 -0
  10. package/dist/EpubViewer-Cs6yZIP2.js.map +1 -0
  11. package/dist/IpynbViewer-wJhbhUla.js +171 -0
  12. package/dist/IpynbViewer-wJhbhUla.js.map +1 -0
  13. package/dist/MermaidViewer-k_XVXoc5.js +127 -0
  14. package/dist/MermaidViewer-k_XVXoc5.js.map +1 -0
  15. package/dist/PsdViewer-Bo4imBCF.js +109 -0
  16. package/dist/PsdViewer-Bo4imBCF.js.map +1 -0
  17. package/dist/TiffViewer-D73-Gyt-.js +130 -0
  18. package/dist/TiffViewer-D73-Gyt-.js.map +1 -0
  19. package/dist/UTIF-DSbsvqXu.js +3104 -0
  20. package/dist/UTIF-DSbsvqXu.js.map +1 -0
  21. package/dist/Viewer3D-Ba-RPIRz.js +60 -0
  22. package/dist/Viewer3D-Ba-RPIRz.js.map +1 -0
  23. package/dist/_commonjsHelpers-DaMA6jEr.js +9 -0
  24. package/dist/_commonjsHelpers-DaMA6jEr.js.map +1 -0
  25. package/dist/filex.js +5 -0
  26. package/dist/filex.js.map +1 -0
  27. package/dist/filex.umd.cjs +304 -0
  28. package/dist/filex.umd.cjs.map +1 -0
  29. package/dist/index-UFULWo35.js +10736 -0
  30. package/dist/index-UFULWo35.js.map +1 -0
  31. package/dist/index-idz8Cz5t.js +10623 -0
  32. package/dist/index-idz8Cz5t.js.map +1 -0
  33. package/dist/index.d.ts +23 -0
  34. package/dist/katex-yuB6V-q6.js +11616 -0
  35. package/dist/katex-yuB6V-q6.js.map +1 -0
  36. package/dist/papaparse.min-VB1HBwYX.js +441 -0
  37. package/dist/papaparse.min-VB1HBwYX.js.map +1 -0
  38. package/dist/style.css +1 -0
  39. package/dist/useViewerFetch-czqbd2Lj.js +25 -0
  40. package/dist/useViewerFetch-czqbd2Lj.js.map +1 -0
  41. package/package.json +63 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PsdViewer-Bo4imBCF.js","sources":["../../core/src/viewers/PsdViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\n/**\r\n * PsdViewer — Photoshop document preview via `ag-psd`.\r\n *\r\n * Lazy-imports `ag-psd` (~150 KB). Renders the flattened composite to\r\n * a canvas via `psd.canvas`. A simple layer panel toggles the rendered\r\n * preview (V1: just lists names + visibility; full composite swap on\r\n * toggle requires re-rendering with `applyOpacity`/`composite` logic\r\n * — left as TODO for V2 since `ag-psd` doesn't ship a composite\r\n * pipeline of its own).\r\n */\r\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue';\r\nimport { fetchViewerArrayBuffer } from '../composables/useViewerFetch';\r\n\r\nconst props = defineProps<{\r\n url: string;\r\n mime?: 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\ninterface FlatLayer {\r\n index: number;\r\n name: string;\r\n hidden: boolean;\r\n}\r\n\r\nconst canvasEl = ref<HTMLCanvasElement | null>(null);\r\nconst layers = ref<FlatLayer[]>([]);\r\nconst error = ref<string | null>(null);\r\nconst loading = ref(true);\r\nconst showLayerPanel = ref(false);\r\nconst dims = ref<{ width: number; height: number }>({ width: 0, height: 0 });\r\nconst scale = ref(1);\r\n\r\nlet renderToken = 0;\r\n\r\nlet agPsd: any = null;\r\nasync function ensureAgPsd(): Promise<any | null> {\r\n if (agPsd) return agPsd;\r\n try {\r\n const mod = await import(/* @vite-ignore */ 'ag-psd');\r\n agPsd = mod;\r\n return agPsd;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction flattenLayers(node: any, list: FlatLayer[]): void {\r\n if (!node) return;\r\n if (Array.isArray(node.children)) {\r\n for (const child of node.children) {\r\n list.push({\r\n index: list.length,\r\n name: child.name ?? '(unnamed)',\r\n hidden: !!child.hidden,\r\n });\r\n if (child.children) flattenLayers(child, list);\r\n }\r\n }\r\n}\r\n\r\nasync function load(): Promise<void> {\r\n loading.value = true;\r\n error.value = null;\r\n layers.value = [];\r\n const myToken = ++renderToken;\r\n\r\n const lib = await ensureAgPsd();\r\n if (myToken !== renderToken) return;\r\n if (!lib) {\r\n error.value = props.t\r\n ? props.t('viewer.peer_not_installed')\r\n : 'PSD viewer requires `ag-psd` — install or use download.';\r\n loading.value = false;\r\n return;\r\n }\r\n\r\n try {\r\n const buf = await fetchViewerArrayBuffer({\r\n url: props.url,\r\n headers: props.authHeaders?.() ?? {},\r\n credentials: props.authCredentials,\r\n });\r\n if (myToken !== renderToken) return;\r\n const psd = lib.readPsd(buf, {\r\n skipLayerImageData: false,\r\n skipCompositeImageData: false,\r\n skipThumbnail: true,\r\n });\r\n dims.value = { width: psd.width, height: psd.height };\r\n\r\n const composite = psd.canvas;\r\n if (composite && canvasEl.value) {\r\n const target = canvasEl.value;\r\n target.width = psd.width;\r\n target.height = psd.height;\r\n const ctx = target.getContext('2d');\r\n ctx?.drawImage(composite, 0, 0);\r\n } else {\r\n throw new Error('PSD has no composite image (skipCompositeImageData?)');\r\n }\r\n\r\n const flat: FlatLayer[] = [];\r\n flattenLayers(psd, flat);\r\n layers.value = flat;\r\n } catch (err) {\r\n error.value = err instanceof Error ? err.message : 'PSD decode failed';\r\n } finally {\r\n loading.value = false;\r\n }\r\n}\r\n\r\nfunction zoomIn(): void {\r\n scale.value = Math.min(8, scale.value * 1.25);\r\n}\r\nfunction zoomOut(): void {\r\n scale.value = Math.max(0.1, scale.value / 1.25);\r\n}\r\nfunction reset(): void {\r\n scale.value = 1;\r\n}\r\n\r\nonMounted(load);\r\nonBeforeUnmount(() => {\r\n renderToken++;\r\n});\r\nwatch(() => props.url, load);\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-psd\">\r\n <div class=\"filex-viewer-psd__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 <canvas\r\n v-show=\"!loading && !error\"\r\n ref=\"canvasEl\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.filex-viewer-psd {\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-psd__bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\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: 13px;\r\n}\r\n.filex-viewer-spacer { flex: 1; }\r\n.filex-viewer-psd__dim {\r\n font-size: 12px;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-psd__zoom {\r\n min-width: 50px;\r\n text-align: center;\r\n font-variant-numeric: tabular-nums;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-psd__main {\r\n flex: 1;\r\n display: flex;\r\n min-height: 0;\r\n}\r\n.filex-viewer-psd__layers {\r\n width: 240px;\r\n border-right: 1px solid var(--fe-border, #e2e6ed);\r\n overflow-y: auto;\r\n padding: 8px 0;\r\n background: var(--fe-bg-elev, #f7f8fa);\r\n}\r\n.filex-viewer-psd__layers ul {\r\n list-style: none;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n.filex-viewer-psd__layers li {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 4px 12px;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-psd__layer-vis {\r\n width: 14px;\r\n text-align: center;\r\n color: var(--fe-text-muted, #5a6475);\r\n}\r\n.filex-viewer-psd__layer-vis[data-hidden=\"1\"] { color: var(--fe-border-strong, #c7ced9); }\r\n.filex-viewer-psd__layer-name {\r\n flex: 1;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n.filex-viewer-psd__pane {\r\n flex: 1;\r\n overflow: auto;\r\n padding: 16px;\r\n background: #2a2d33;\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: flex-start;\r\n}\r\n.filex-viewer-psd__pane canvas {\r\n background: #fff\r\n repeating-conic-gradient(#e0e0e0 0% 25%, transparent 0% 50%) 50% / 16px 16px;\r\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\r\n}\r\n.filex-viewer-fallback {\r\n text-align: center;\r\n padding: 32px;\r\n color: #c8cdd6;\r\n margin: auto;\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.is-active {\r\n background: var(--fe-bg-selected, #dfe8ff);\r\n border-color: var(--fe-primary, #3b82f6);\r\n}\r\n</style>\r\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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"}
@@ -0,0 +1,130 @@
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-idz8Cz5t.js";
2
+ import { a as j } from "./useViewerFetch-czqbd2Lj.js";
3
+ const q = { class: "filex-viewer-tiff" }, G = { class: "filex-viewer-tiff__pane" }, P = {
4
+ key: 0,
5
+ class: "filex-viewer-fallback"
6
+ }, z = {
7
+ key: 1,
8
+ class: "filex-viewer-fallback"
9
+ }, J = {
10
+ key: 2,
11
+ class: "filex-viewer-tiff__pager"
12
+ }, K = ["disabled"], O = { class: "filex-viewer-tiff__pages" }, Q = ["disabled"], W = /* @__PURE__ */ S({
13
+ __name: "TiffViewer",
14
+ props: {
15
+ url: {},
16
+ mime: {},
17
+ ext: {},
18
+ t: { type: Function },
19
+ authHeaders: { type: Function },
20
+ authCredentials: {}
21
+ },
22
+ setup(I) {
23
+ const t = I, p = d(null), o = d(null), c = d(!0), n = d(0), r = d(0), F = d({ width: 0, height: 0 });
24
+ let u = null, l = null, f = 0;
25
+ async function T() {
26
+ if (u) return u;
27
+ try {
28
+ const a = await import(
29
+ /* @vite-ignore */
30
+ "./UTIF-DSbsvqXu.js"
31
+ ).then((e) => e.U);
32
+ return u = a.default ?? a, u;
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+ async function y() {
38
+ var v;
39
+ c.value = !0, o.value = null, l = null, n.value = 0, r.value = 0;
40
+ const a = ++f, e = await T();
41
+ if (a === f) {
42
+ if (!e) {
43
+ o.value = t.t ? t.t("viewer.peer_not_installed") : "TIFF viewer requires `utif` — install or use download.", c.value = !1;
44
+ return;
45
+ }
46
+ try {
47
+ const s = await j({
48
+ url: t.url,
49
+ headers: ((v = t.authHeaders) == null ? void 0 : v.call(t)) ?? {},
50
+ credentials: t.authCredentials
51
+ });
52
+ if (a !== f) return;
53
+ if (l = e.decode(s), r.value = (l == null ? void 0 : l.length) ?? 0, r.value === 0)
54
+ throw new Error("No pages decoded");
55
+ w();
56
+ } catch (s) {
57
+ o.value = s instanceof Error ? s.message : "TIFF decode failed";
58
+ } finally {
59
+ c.value = !1;
60
+ }
61
+ }
62
+ }
63
+ function w() {
64
+ if (!u || !l || !p.value) return;
65
+ const a = Math.max(0, Math.min(n.value, l.length - 1)), e = l[a];
66
+ try {
67
+ u.decodeImage(void 0, e);
68
+ } catch {
69
+ }
70
+ const v = u.toRGBA8(e), s = e.width, g = e.height;
71
+ F.value = { width: s, height: g };
72
+ const m = p.value;
73
+ m.width = s, m.height = g;
74
+ const x = m.getContext("2d");
75
+ if (!x) return;
76
+ const k = x.createImageData(s, g);
77
+ k.data.set(v), x.putImageData(k, 0, 0);
78
+ }
79
+ function B() {
80
+ n.value < r.value - 1 && (n.value++, w());
81
+ }
82
+ function D() {
83
+ n.value > 0 && (n.value--, w());
84
+ }
85
+ U(y), M(() => {
86
+ f++, l = null;
87
+ }), N(() => t.url, y);
88
+ const E = L(() => (t.t && t.t("viewer.page_n_of_m") || "Page {n} of {m}").replace("{n}", String(n.value + 1)).replace("{m}", String(r.value)));
89
+ function V(a, e) {
90
+ return t.t ? t.t(a) : e;
91
+ }
92
+ return (a, e) => (_(), h("div", q, [
93
+ i("div", G, [
94
+ o.value ? (_(), h("div", P, [
95
+ e[0] || (e[0] = i("span", { class: "filex-viewer-fallback__icon" }, "🖼️", -1)),
96
+ i("p", null, b(o.value), 1)
97
+ ])) : c.value ? (_(), h("div", z, [
98
+ e[1] || (e[1] = i("span", { class: "filex-viewer-fallback__icon" }, "⏳", -1)),
99
+ i("p", null, b(V("viewer.loading", "Loading…")), 1)
100
+ ])) : C("", !0),
101
+ A(i("canvas", {
102
+ ref_key: "canvasEl",
103
+ ref: p,
104
+ style: { imageRendering: "pixelated" }
105
+ }, null, 512), [
106
+ [H, !c.value && !o.value]
107
+ ]),
108
+ !c.value && !o.value && r.value > 1 ? (_(), h("div", J, [
109
+ i("button", {
110
+ type: "button",
111
+ class: "filex-viewer-btn",
112
+ disabled: n.value === 0,
113
+ onClick: D
114
+ }, "‹", 8, K),
115
+ i("span", O, b(E.value), 1),
116
+ i("button", {
117
+ type: "button",
118
+ class: "filex-viewer-btn",
119
+ disabled: n.value >= r.value - 1,
120
+ onClick: B
121
+ }, "›", 8, Q)
122
+ ])) : C("", !0)
123
+ ])
124
+ ]));
125
+ }
126
+ }), Z = /* @__PURE__ */ R(W, [["__scopeId", "data-v-9c711133"]]);
127
+ export {
128
+ Z as default
129
+ };
130
+ //# sourceMappingURL=TiffViewer-D73-Gyt-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TiffViewer-D73-Gyt-.js","sources":["../../core/src/viewers/TiffViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\n/**\r\n * TiffViewer — multi-page TIFF preview via `utif`.\r\n *\r\n * Lazy-imports `utif` (~50 KB). Decodes IFDs once, paints the active\r\n * page to a `<canvas>` via `UTIF.toRGBA8`. Page navigation (1/N) +\r\n * zoom in/out controls. Browser <img> can't render TIFF natively, so\r\n * the canvas pipeline is the only option short of server-side\r\n * conversion.\r\n */\r\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\r\nimport { fetchViewerArrayBuffer } from '../composables/useViewerFetch';\r\n\r\nconst props = defineProps<{\r\n url: string;\r\n mime?: 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 canvasEl = ref<HTMLCanvasElement | null>(null);\r\nconst error = ref<string | null>(null);\r\nconst loading = ref(true);\r\nconst scale = ref(1);\r\nconst pageIndex = ref(0);\r\nconst pageCount = ref(0);\r\nconst pageDims = ref<{ width: number; height: number }>({ width: 0, height: 0 });\r\n\r\nlet UTIF: any = null;\r\nlet ifds: any[] | null = null;\r\nlet renderToken = 0;\r\n\r\nasync function ensureUtif(): Promise<any | null> {\r\n if (UTIF) return UTIF;\r\n try {\r\n const mod = await import(/* @vite-ignore */ 'utif');\r\n UTIF = mod.default ?? mod;\r\n return UTIF;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nasync function load(): Promise<void> {\r\n loading.value = true;\r\n error.value = null;\r\n ifds = null;\r\n pageIndex.value = 0;\r\n pageCount.value = 0;\r\n const myToken = ++renderToken;\r\n\r\n const lib = await ensureUtif();\r\n if (myToken !== renderToken) return;\r\n if (!lib) {\r\n error.value = props.t\r\n ? props.t('viewer.peer_not_installed')\r\n : 'TIFF viewer requires `utif` — install or use download.';\r\n loading.value = false;\r\n return;\r\n }\r\n\r\n try {\r\n const buf = await fetchViewerArrayBuffer({\r\n url: props.url,\r\n headers: props.authHeaders?.() ?? {},\r\n credentials: props.authCredentials,\r\n });\r\n if (myToken !== renderToken) return;\r\n ifds = lib.decode(buf);\r\n pageCount.value = ifds?.length ?? 0;\r\n if (pageCount.value === 0) {\r\n throw new Error('No pages decoded');\r\n }\r\n paint();\r\n } catch (err) {\r\n error.value = err instanceof Error ? err.message : 'TIFF decode failed';\r\n } finally {\r\n loading.value = false;\r\n }\r\n}\r\n\r\nfunction paint(): void {\r\n if (!UTIF || !ifds || !canvasEl.value) return;\r\n const idx = Math.max(0, Math.min(pageIndex.value, ifds.length - 1));\r\n const ifd = ifds[idx];\r\n try {\r\n UTIF.decodeImage(undefined, ifd);\r\n } catch {\r\n // some images already decoded — UTIF.decodeImage is idempotent on\r\n // older versions.\r\n }\r\n const rgba = UTIF.toRGBA8(ifd);\r\n const w = ifd.width;\r\n const h = ifd.height;\r\n pageDims.value = { width: w, height: h };\r\n const canvas = canvasEl.value;\r\n canvas.width = w;\r\n canvas.height = h;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n const imageData = ctx.createImageData(w, h);\r\n imageData.data.set(rgba);\r\n ctx.putImageData(imageData, 0, 0);\r\n}\r\n\r\nfunction next(): void {\r\n if (pageIndex.value < pageCount.value - 1) {\r\n pageIndex.value++;\r\n paint();\r\n }\r\n}\r\nfunction prev(): void {\r\n if (pageIndex.value > 0) {\r\n pageIndex.value--;\r\n paint();\r\n }\r\n}\r\nfunction zoomIn(): void {\r\n scale.value = Math.min(8, scale.value * 1.25);\r\n}\r\nfunction zoomOut(): void {\r\n scale.value = Math.max(0.1, scale.value / 1.25);\r\n}\r\nfunction reset(): void {\r\n scale.value = 1;\r\n}\r\n\r\nonMounted(load);\r\nonBeforeUnmount(() => {\r\n renderToken++;\r\n ifds = null;\r\n});\r\n\r\nwatch(() => props.url, load);\r\n\r\nconst pageLabel = computed(() => {\r\n const m = (props.t && props.t('viewer.page_n_of_m')) || 'Page {n} of {m}';\r\n return m.replace('{n}', String(pageIndex.value + 1)).replace('{m}', String(pageCount.value));\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-tiff\">\r\n <div class=\"filex-viewer-tiff__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 <canvas\r\n v-show=\"!loading && !error\"\r\n ref=\"canvasEl\"\r\n :style=\"{ imageRendering: 'pixelated' }\"\r\n />\r\n <div v-if=\"!loading && !error && pageCount > 1\" class=\"filex-viewer-tiff__pager\">\r\n <button\r\n type=\"button\"\r\n class=\"filex-viewer-btn\"\r\n :disabled=\"pageIndex === 0\"\r\n @click=\"prev\"\r\n >‹</button>\r\n <span class=\"filex-viewer-tiff__pages\">{{ pageLabel }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"filex-viewer-btn\"\r\n :disabled=\"pageIndex >= pageCount - 1\"\r\n @click=\"next\"\r\n >›</button>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.filex-viewer-tiff__pager {\r\n position: absolute;\r\n bottom: 12px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 4px 8px;\r\n background: var(--fe-bg-elev, rgba(255, 255, 255, 0.9));\r\n border: 1px solid var(--fe-border, #e2e6ed);\r\n border-radius: 6px;\r\n backdrop-filter: blur(4px);\r\n}\r\n.filex-viewer-tiff__pages {\r\n font-size: 12px;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n.filex-viewer-tiff {\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-tiff__bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\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: 13px;\r\n}\r\n.filex-viewer-tiff__pages {\r\n min-width: 110px;\r\n text-align: center;\r\n font-variant-numeric: tabular-nums;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-tiff__zoom {\r\n min-width: 50px;\r\n text-align: center;\r\n font-variant-numeric: tabular-nums;\r\n font-size: 12px;\r\n}\r\n.filex-viewer-spacer { flex: 1; }\r\n.filex-viewer-tiff__pane {\r\n flex: 1;\r\n overflow: auto;\r\n padding: 16px;\r\n background: #2a2d33;\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: flex-start;\r\n}\r\n.filex-viewer-tiff__pane canvas {\r\n background: #fff;\r\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\r\n}\r\n.filex-viewer-fallback {\r\n text-align: center;\r\n padding: 32px;\r\n color: #c8cdd6;\r\n margin: auto;\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":["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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"}