@virtualansoftware/vs-office-viewer 1.0.1 → 1.0.2

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 (33) hide show
  1. package/dist/client/assets/DocxViewer-BcXhLJfm.css +1 -0
  2. package/dist/client/assets/DocxViewer-CPMpeQTq.js +58 -0
  3. package/dist/client/assets/LogoIcon-CTf12WP0.js +1 -0
  4. package/dist/client/assets/PptxViewer-Bvr-20MJ.js +59 -0
  5. package/dist/client/assets/PptxViewer-Cn8CqLfg.css +1 -0
  6. package/dist/client/assets/XlsxViewer-CGc0vtBk.js +63 -0
  7. package/dist/client/assets/XlsxViewer-DTxE-neD.css +1 -0
  8. package/dist/client/assets/chevron-right-D0jHq8Hg.js +1 -0
  9. package/dist/client/assets/form-KvBV47dq.js +1 -0
  10. package/dist/client/assets/index-DATp3RB-.js +12 -0
  11. package/dist/client/assets/jszip.min-DhiFe-R7.js +2 -0
  12. package/dist/client/assets/login-aBY8Ktaw.js +1 -0
  13. package/dist/client/assets/register-BB43pNvY.js +1 -0
  14. package/dist/client/assets/rolldown-runtime-aKtaBQYM.js +1 -0
  15. package/dist/client/assets/routes-1JmKig5J.js +2 -0
  16. package/dist/client/assets/styles-F8oSmVJa.css +2 -0
  17. package/dist/client/robots.txt +2 -0
  18. package/dist/server/assets/DocxViewer-Bvu47Jxr.js +544 -0
  19. package/dist/server/assets/LogoIcon-D2qIWtkU.js +93 -0
  20. package/dist/server/assets/PptxViewer-CjRu82CL.js +209 -0
  21. package/dist/server/assets/XlsxViewer-CtBSfYb7.js +870 -0
  22. package/dist/server/assets/_tanstack-start-manifest_v-CQ5gmg8o.js +43 -0
  23. package/dist/server/assets/createMiddleware-BnSPczhK.js +24 -0
  24. package/dist/server/assets/empty-plugin-adapters-D9UWiqvJ.js +5 -0
  25. package/dist/server/assets/form-DY0gQsTv.js +249 -0
  26. package/dist/server/assets/login-hnUq0LLL.js +122 -0
  27. package/dist/server/assets/register-DIFjHkZS.js +164 -0
  28. package/dist/server/assets/router-CJA4LnAB.js +281 -0
  29. package/dist/server/assets/routes-DT9ZAw-E.js +481 -0
  30. package/dist/server/assets/server-vIOK9n3w.js +1595 -0
  31. package/dist/server/assets/start-RYa-0bjt.js +43 -0
  32. package/dist/server/server.js +86 -0
  33. package/package.json +7 -6
@@ -0,0 +1,209 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { ChevronLeft, ChevronRight, Loader2 } from "lucide-react";
4
+ import { init } from "pptx-preview";
5
+ //#region src/viewers/PptxViewer.tsx
6
+ function fixImageSizing(host) {
7
+ host.querySelectorAll("img").forEach((img) => {
8
+ const w = img.getAttribute("width");
9
+ const h = img.getAttribute("height");
10
+ if (w && !img.style.width) img.style.setProperty("width", `${w}px`);
11
+ if (h && !img.style.height) img.style.setProperty("height", `${h}px`);
12
+ });
13
+ }
14
+ function fixTextRendering(host) {
15
+ host.querySelectorAll(".text-wrapper span").forEach((span) => {
16
+ if (!span.style.fontFamily && parseFloat(span.style.letterSpacing) < 0) span.style.letterSpacing = "";
17
+ });
18
+ host.querySelectorAll(".text-wrapper p").forEach((p) => {
19
+ if (p.style.lineHeight === "1") p.style.lineHeight = "1.15";
20
+ });
21
+ }
22
+ function styleSlides(slides, mode, activeIndex) {
23
+ slides.forEach((s, i) => {
24
+ if (mode === "navigation") {
25
+ s.style.display = i === activeIndex ? "" : "none";
26
+ s.style.marginBottom = "0";
27
+ s.style.marginTop = "0";
28
+ } else {
29
+ s.style.display = "";
30
+ s.style.marginBottom = "";
31
+ s.style.marginTop = "";
32
+ }
33
+ });
34
+ }
35
+ function PptxViewer({ data, mode = "scroll", className, onError }) {
36
+ const outerRef = useRef(null);
37
+ const slideAreaRef = useRef(null);
38
+ const hostRef = useRef(null);
39
+ const slidesRef = useRef([]);
40
+ const currentSlideRef = useRef(0);
41
+ const modeRef = useRef(mode);
42
+ const [loading, setLoading] = useState(false);
43
+ const [error, setError] = useState(null);
44
+ const [currentSlide, setCurrentSlide] = useState(0);
45
+ const [totalSlides, setTotalSlides] = useState(0);
46
+ useEffect(() => {
47
+ modeRef.current = mode;
48
+ }, [mode]);
49
+ const isNavMode = mode === "navigation";
50
+ const canPrev = currentSlide > 0;
51
+ const canNext = currentSlide < totalSlides - 1;
52
+ const goToSlide = useCallback((index) => {
53
+ const slides = slidesRef.current;
54
+ if (!slides.length || index < 0 || index >= slides.length) return;
55
+ styleSlides(slides, "navigation", index);
56
+ currentSlideRef.current = index;
57
+ setCurrentSlide(index);
58
+ }, []);
59
+ const applyMode = useCallback((m) => {
60
+ const slides = slidesRef.current;
61
+ if (!slides.length) return;
62
+ const idx = Math.min(currentSlideRef.current, slides.length - 1);
63
+ styleSlides(slides, m, idx);
64
+ if (m === "navigation") {
65
+ currentSlideRef.current = idx;
66
+ setCurrentSlide(idx);
67
+ }
68
+ }, []);
69
+ useEffect(() => {
70
+ applyMode(mode);
71
+ }, [mode, applyMode]);
72
+ useEffect(() => {
73
+ if (mode !== "navigation") return;
74
+ const handleKey = (e) => {
75
+ if (e.target instanceof HTMLSelectElement) return;
76
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
77
+ e.preventDefault();
78
+ goToSlide(currentSlideRef.current + 1);
79
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
80
+ e.preventDefault();
81
+ goToSlide(currentSlideRef.current - 1);
82
+ }
83
+ };
84
+ window.addEventListener("keydown", handleKey);
85
+ return () => window.removeEventListener("keydown", handleKey);
86
+ }, [mode, goToSlide]);
87
+ const renderPptx = useCallback(async (containerWidth) => {
88
+ const host = hostRef.current;
89
+ if (!host || containerWidth === 0) return;
90
+ setLoading(true);
91
+ setError(null);
92
+ host.innerHTML = "";
93
+ slidesRef.current = [];
94
+ try {
95
+ await init(host, {
96
+ width: containerWidth,
97
+ mode: "list"
98
+ }).preview(data.slice(0));
99
+ fixImageSizing(host);
100
+ fixTextRendering(host);
101
+ const slides = Array.from(host.querySelectorAll(".pptx-preview-slide-wrapper"));
102
+ slidesRef.current = slides;
103
+ setTotalSlides(slides.length);
104
+ const m = modeRef.current;
105
+ const idx = Math.min(currentSlideRef.current, slides.length - 1);
106
+ styleSlides(slides, m, idx);
107
+ if (m === "navigation") {
108
+ currentSlideRef.current = idx;
109
+ setCurrentSlide(idx);
110
+ }
111
+ } catch (e) {
112
+ const err = e instanceof Error ? e : /* @__PURE__ */ new Error("Failed to render presentation");
113
+ setError(err.message);
114
+ onError?.(err);
115
+ } finally {
116
+ setLoading(false);
117
+ }
118
+ }, [data, onError]);
119
+ useEffect(() => {
120
+ let cancelled = false;
121
+ let lastWidth = 0;
122
+ let ro = null;
123
+ let debounceTimer;
124
+ function triggerRender() {
125
+ if (cancelled || !hostRef.current) return;
126
+ const w = Math.floor(hostRef.current.getBoundingClientRect().width);
127
+ if (w === 0 || w === lastWidth) return;
128
+ lastWidth = w;
129
+ renderPptx(w);
130
+ }
131
+ const rafId = requestAnimationFrame(() => {
132
+ if (cancelled) return;
133
+ triggerRender();
134
+ if (slideAreaRef.current) {
135
+ ro = new ResizeObserver(() => {
136
+ clearTimeout(debounceTimer);
137
+ debounceTimer = setTimeout(triggerRender, 250);
138
+ });
139
+ ro.observe(slideAreaRef.current);
140
+ }
141
+ });
142
+ return () => {
143
+ cancelled = true;
144
+ cancelAnimationFrame(rafId);
145
+ clearTimeout(debounceTimer);
146
+ ro?.disconnect();
147
+ };
148
+ }, [data, renderPptx]);
149
+ return /* @__PURE__ */ jsxs("div", {
150
+ ref: outerRef,
151
+ className: `ov-pptx${isNavMode ? " ov-pptx--nav" : ""}${className ? ` ${className}` : ""}`,
152
+ children: [
153
+ loading && /* @__PURE__ */ jsxs("div", {
154
+ className: `ov-pptx__loading${isNavMode ? " ov-pptx__loading--nav" : ""}`,
155
+ children: [/* @__PURE__ */ jsx(Loader2, { className: "ov-pptx__loading-icon" }), /* @__PURE__ */ jsx("span", {
156
+ className: "ov-pptx__loading-text",
157
+ children: "Rendering slides…"
158
+ })]
159
+ }),
160
+ error && /* @__PURE__ */ jsx("div", {
161
+ className: "ov-pptx__error",
162
+ children: error
163
+ }),
164
+ /* @__PURE__ */ jsx("div", {
165
+ ref: slideAreaRef,
166
+ className: "ov-pptx__slide-area",
167
+ style: { visibility: loading ? "hidden" : "visible" },
168
+ children: /* @__PURE__ */ jsx("div", {
169
+ ref: hostRef,
170
+ className: "pptx-host ov-pptx__host"
171
+ })
172
+ }),
173
+ isNavMode && !loading && totalSlides > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
174
+ /* @__PURE__ */ jsx("button", {
175
+ onClick: () => goToSlide(currentSlideRef.current - 1),
176
+ disabled: !canPrev,
177
+ "aria-label": "Previous slide",
178
+ className: "ov-pptx__nav-btn ov-pptx__nav-btn--prev",
179
+ children: /* @__PURE__ */ jsx(ChevronLeft, {
180
+ className: "ov-pptx__nav-btn-icon",
181
+ strokeWidth: 2
182
+ })
183
+ }),
184
+ /* @__PURE__ */ jsx("button", {
185
+ onClick: () => goToSlide(currentSlideRef.current + 1),
186
+ disabled: !canNext,
187
+ "aria-label": "Next slide",
188
+ className: "ov-pptx__nav-btn ov-pptx__nav-btn--next",
189
+ children: /* @__PURE__ */ jsx(ChevronRight, {
190
+ className: "ov-pptx__nav-btn-icon",
191
+ strokeWidth: 2
192
+ })
193
+ }),
194
+ /* @__PURE__ */ jsxs("div", {
195
+ className: "ov-pptx__nav-counter",
196
+ children: [/* @__PURE__ */ jsx("span", {
197
+ className: "ov-pptx__nav-current",
198
+ children: currentSlide + 1
199
+ }), /* @__PURE__ */ jsxs("span", {
200
+ className: "ov-pptx__nav-total",
201
+ children: [" of ", totalSlides]
202
+ })]
203
+ })
204
+ ] })
205
+ ]
206
+ });
207
+ }
208
+ //#endregion
209
+ export { PptxViewer };