office-viewer-react 1.0.0

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