@cherrystudio/file-preview 0.1.3 → 0.2.1
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/README.md +48 -5
- package/dist/{Combination-BLg27FvF.js → Combination-i8Z9CJHc.js} +2 -1
- package/dist/{FilePreviewTooLarge-DkHa6toZ.js → FilePreviewTooLarge-DC7vPyMI.js} +1 -1
- package/dist/{useTranslation-DMhY277o.js → FilePreviewToolbarButton-ptqwCTnz.js} +11 -3634
- package/dist/{ImageFilePreview-Be0jdBJ-.js → ImageFilePreview-C_P1iIEi.js} +27 -11
- package/dist/{PdfFilePreview-D3Ie0_mm.js → PdfFilePreview-CbrMcPzo.js} +132 -25
- package/dist/{PowerPointFilePreview-CyQHTp4B.js → PowerPointFilePreview-9E6kUy_A.js} +55 -21
- package/dist/RtfFilePreview-Bgl6lmWy.js +21434 -0
- package/dist/{SpreadsheetFilePreview-DJdoyeis.js → SpreadsheetFilePreview-PWFG3UY3.js} +61 -32
- package/dist/{WordFilePreview-Tvm-vK91.js → WordFilePreview-hfALJk2N.js} +26 -23
- package/dist/circle-alert-sByhBDN4.js +31 -0
- package/dist/{imageFilePreviewPlugin-CYLM2bwR.js → imageFilePreviewPlugin-D6hV1Hm1.js} +1 -1
- package/dist/react.js +55 -24
- package/dist/{rotate-ccw-YWx7RzY9.js → rotate-ccw-Bx-jjhVm.js} +1 -1
- package/dist/{selection-CQPD5a6C.js → selection-B0INvh6t.js} +1 -31
- package/dist/styles.css +44 -1
- package/dist/useTranslation-BJY4EKsz.js +3631 -0
- package/dist/{zoom-out-DLOQGt1e.js → zoom-out-B2XJ64Kx.js} +1 -1
- package/package.json +2 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import "./documentAnchor-J7GGLU15.js";
|
|
2
2
|
import { r as readPreviewDocument, t as PreviewError } from "./source-Rx3etU3y.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { n as ZoomIn, t as ZoomOut } from "./zoom-out-
|
|
6
|
-
import { t as
|
|
3
|
+
import { _ as cva, a as usePreviewHost, d as EmptyState, m as LoaderCircle, o as usePreviewLogger, p as cn, r as FilePreviewLayout, t as useTranslation } from "./useTranslation-BJY4EKsz.js";
|
|
4
|
+
import { t as CircleAlert } from "./circle-alert-sByhBDN4.js";
|
|
5
|
+
import { n as ZoomIn, t as ZoomOut } from "./zoom-out-B2XJ64Kx.js";
|
|
6
|
+
import { t as FilePreviewToolbarButton } from "./FilePreviewToolbarButton-ptqwCTnz.js";
|
|
7
|
+
import { t as FilePreviewTooLarge } from "./FilePreviewTooLarge-DC7vPyMI.js";
|
|
8
|
+
import { n as normalizeSelectionText, t as createPreviewSelection } from "./selection-B0INvh6t.js";
|
|
7
9
|
import * as React$1 from "react";
|
|
8
|
-
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
10
|
+
import React, { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
9
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
12
|
import { flushSync } from "react-dom";
|
|
11
13
|
typeof window !== "undefined" && window.document && window.document.createElement;
|
|
@@ -971,7 +973,7 @@ function SpreadsheetFilePreviewToolbar({ canZoomIn, canZoomOut, onZoomIn, onZoom
|
|
|
971
973
|
var XLSX_PREVIEW_MAX_SIZE_BYTES = 20971520;
|
|
972
974
|
function useXlsxWorkbook(document, fileName) {
|
|
973
975
|
const logger = usePreviewLogger("useXlsxWorkbook");
|
|
974
|
-
const { failDocument, resources } = usePreviewHost();
|
|
976
|
+
const { failDocument, resources, isCurrentDocument } = usePreviewHost();
|
|
975
977
|
const { baseUrl, createWorker } = resources ?? {};
|
|
976
978
|
const [state, setState] = useState({ status: "idle" });
|
|
977
979
|
const workerRef = useRef(null);
|
|
@@ -981,6 +983,7 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
981
983
|
let cancelled = false;
|
|
982
984
|
const controller = new AbortController();
|
|
983
985
|
const requestId = ++requestIdRef.current;
|
|
986
|
+
const isCurrent = () => !cancelled && requestId === requestIdRef.current && isCurrentDocument?.() !== false;
|
|
984
987
|
if (document.size > 20971520) {
|
|
985
988
|
failDocument?.(new PreviewError("too_large", "Workbook exceeds the preview size limit"));
|
|
986
989
|
setState({
|
|
@@ -989,15 +992,18 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
989
992
|
});
|
|
990
993
|
return;
|
|
991
994
|
}
|
|
992
|
-
setState(
|
|
995
|
+
setState((current) => ({
|
|
996
|
+
status: "loading",
|
|
997
|
+
model: "model" in current ? current.model : void 0
|
|
998
|
+
}));
|
|
993
999
|
(async () => {
|
|
994
1000
|
let bytes;
|
|
995
1001
|
try {
|
|
996
1002
|
const raw = await readPreviewDocument(document, XLSX_PREVIEW_MAX_SIZE_BYTES, controller.signal);
|
|
997
|
-
if (
|
|
1003
|
+
if (!isCurrent()) return;
|
|
998
1004
|
bytes = raw.slice().buffer;
|
|
999
1005
|
} catch (error) {
|
|
1000
|
-
if (
|
|
1006
|
+
if (!isCurrent()) return;
|
|
1001
1007
|
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
1002
1008
|
failDocument?.(normalized);
|
|
1003
1009
|
setState({
|
|
@@ -1010,7 +1016,7 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
1010
1016
|
try {
|
|
1011
1017
|
worker = createXlsxWorker(baseUrl, createWorker);
|
|
1012
1018
|
} catch (error) {
|
|
1013
|
-
if (
|
|
1019
|
+
if (!isCurrent()) return;
|
|
1014
1020
|
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
1015
1021
|
failDocument?.(normalized);
|
|
1016
1022
|
setState({
|
|
@@ -1019,7 +1025,7 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
1019
1025
|
});
|
|
1020
1026
|
return;
|
|
1021
1027
|
}
|
|
1022
|
-
if (
|
|
1028
|
+
if (!isCurrent()) {
|
|
1023
1029
|
worker.terminate();
|
|
1024
1030
|
return;
|
|
1025
1031
|
}
|
|
@@ -1028,6 +1034,7 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
1028
1034
|
if (cancelled || event.data.id !== requestIdRef.current) return;
|
|
1029
1035
|
worker.terminate();
|
|
1030
1036
|
if (workerRef.current === worker) workerRef.current = null;
|
|
1037
|
+
if (!isCurrent()) return;
|
|
1031
1038
|
if (event.data.ok) {
|
|
1032
1039
|
for (const warning of event.data.model.warnings) {
|
|
1033
1040
|
if (loggedWarningsRef.current.has(warning)) continue;
|
|
@@ -1050,6 +1057,7 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
1050
1057
|
if (cancelled || requestId !== requestIdRef.current) return;
|
|
1051
1058
|
worker.terminate();
|
|
1052
1059
|
if (workerRef.current === worker) workerRef.current = null;
|
|
1060
|
+
if (!isCurrent()) return;
|
|
1053
1061
|
failDocument?.(event.error instanceof Error ? event.error : new Error(event.message));
|
|
1054
1062
|
setState({
|
|
1055
1063
|
status: "error",
|
|
@@ -1066,7 +1074,7 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
1066
1074
|
} catch (error) {
|
|
1067
1075
|
worker.terminate();
|
|
1068
1076
|
if (workerRef.current === worker) workerRef.current = null;
|
|
1069
|
-
if (
|
|
1077
|
+
if (!isCurrent()) return;
|
|
1070
1078
|
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
1071
1079
|
failDocument?.(normalized);
|
|
1072
1080
|
setState({
|
|
@@ -1087,7 +1095,8 @@ function useXlsxWorkbook(document, fileName) {
|
|
|
1087
1095
|
logger,
|
|
1088
1096
|
failDocument,
|
|
1089
1097
|
baseUrl,
|
|
1090
|
-
createWorker
|
|
1098
|
+
createWorker,
|
|
1099
|
+
isCurrentDocument
|
|
1091
1100
|
]);
|
|
1092
1101
|
return state;
|
|
1093
1102
|
}
|
|
@@ -2172,7 +2181,7 @@ var CellView = memo(function CellView({ cell, style, covered = false, isFirstRow
|
|
|
2172
2181
|
borderLeft: covered ? void 0 : isFirstCol ? css.borderLeft ?? DEFAULT_GRID_LINE : css.borderLeft
|
|
2173
2182
|
};
|
|
2174
2183
|
return /* @__PURE__ */ jsx("div", {
|
|
2175
|
-
className: "absolute px-1 text-
|
|
2184
|
+
className: "absolute px-1 text-sm text-foreground",
|
|
2176
2185
|
style: finalCss,
|
|
2177
2186
|
children: cell && /* @__PURE__ */ jsx("span", {
|
|
2178
2187
|
className: cn(cell.formulaState === "unevaluated" && "text-muted-foreground italic"),
|
|
@@ -2206,7 +2215,7 @@ var SelectedCellOverlay = ({ cell, style, rect }) => {
|
|
|
2206
2215
|
};
|
|
2207
2216
|
return /* @__PURE__ */ jsx("div", {
|
|
2208
2217
|
"data-testid": "xlsx-grid-selected-overlay",
|
|
2209
|
-
className: "z-10 px-1 text-
|
|
2218
|
+
className: "z-10 px-1 text-sm text-foreground shadow-md outline outline-primary",
|
|
2210
2219
|
style: finalCss,
|
|
2211
2220
|
children: cell && /* @__PURE__ */ jsx("span", {
|
|
2212
2221
|
className: cn(cell.formulaState === "unevaluated" && "text-muted-foreground italic"),
|
|
@@ -2219,7 +2228,7 @@ var SelectedCellOverlay = ({ cell, style, rect }) => {
|
|
|
2219
2228
|
var UnsupportedChartPlaceholder = ({ chart }) => {
|
|
2220
2229
|
const { t } = useTranslation();
|
|
2221
2230
|
return /* @__PURE__ */ jsxs("div", {
|
|
2222
|
-
className: "flex h-full w-full flex-col items-center justify-center gap-1 rounded-md border border-
|
|
2231
|
+
className: "text-muted-foreground flex h-full w-full flex-col items-center justify-center gap-1 rounded-md border border-dashed border-border text-center text-xs",
|
|
2223
2232
|
children: [/* @__PURE__ */ jsx("span", { children: t("xlsx_preview.chart_unsupported") }), chart.rawTypeName && /* @__PURE__ */ jsx("span", { children: chart.rawTypeName })]
|
|
2224
2233
|
});
|
|
2225
2234
|
};
|
|
@@ -2292,6 +2301,20 @@ var XlsxGrid = ({ sheet, styles, imageUrls, zoom, onSelectCell, pickerActive, re
|
|
|
2292
2301
|
estimateSize: (index) => colLayout.sizes[index] * zoom,
|
|
2293
2302
|
overscan: OVERSCAN
|
|
2294
2303
|
});
|
|
2304
|
+
useLayoutEffect(() => {
|
|
2305
|
+
rowVirtualizer.measure();
|
|
2306
|
+
}, [
|
|
2307
|
+
rowVirtualizer,
|
|
2308
|
+
rowLayout,
|
|
2309
|
+
zoom
|
|
2310
|
+
]);
|
|
2311
|
+
useLayoutEffect(() => {
|
|
2312
|
+
colVirtualizer.measure();
|
|
2313
|
+
}, [
|
|
2314
|
+
colVirtualizer,
|
|
2315
|
+
colLayout,
|
|
2316
|
+
zoom
|
|
2317
|
+
]);
|
|
2295
2318
|
const virtualRows = rowVirtualizer.getVirtualItems();
|
|
2296
2319
|
const virtualCols = colVirtualizer.getVirtualItems();
|
|
2297
2320
|
const readViewport = useCallback((el) => ({
|
|
@@ -2406,6 +2429,12 @@ var XlsxGrid = ({ sheet, styles, imageUrls, zoom, onSelectCell, pickerActive, re
|
|
|
2406
2429
|
commitSelection(null);
|
|
2407
2430
|
}, [applySelection, commitSelection]);
|
|
2408
2431
|
const pickerWasActiveRef = useRef(false);
|
|
2432
|
+
const previousSheetRef = useRef(sheet);
|
|
2433
|
+
useEffect(() => {
|
|
2434
|
+
if (previousSheetRef.current === sheet) return;
|
|
2435
|
+
previousSheetRef.current = sheet;
|
|
2436
|
+
clearSelection();
|
|
2437
|
+
}, [sheet, clearSelection]);
|
|
2409
2438
|
useEffect(() => {
|
|
2410
2439
|
const isActive = Boolean(pickerActive);
|
|
2411
2440
|
if (pickerWasActiveRef.current === isActive) return;
|
|
@@ -2776,7 +2805,7 @@ var XlsxGrid = ({ sheet, styles, imageUrls, zoom, onSelectCell, pickerActive, re
|
|
|
2776
2805
|
className: "absolute",
|
|
2777
2806
|
style: zoomTransform,
|
|
2778
2807
|
children: virtualCols.map((vc) => /* @__PURE__ */ jsx("div", {
|
|
2779
|
-
className: "absolute flex items-center justify-center border-
|
|
2808
|
+
className: "text-muted-foreground absolute flex items-center justify-center border-r border-border text-xs",
|
|
2780
2809
|
style: {
|
|
2781
2810
|
left: axisOffset(colLayout, vc.index),
|
|
2782
2811
|
width: colLayout.sizes[vc.index],
|
|
@@ -2798,7 +2827,7 @@ var XlsxGrid = ({ sheet, styles, imageUrls, zoom, onSelectCell, pickerActive, re
|
|
|
2798
2827
|
className: "absolute",
|
|
2799
2828
|
style: zoomTransform,
|
|
2800
2829
|
children: virtualRows.map((vr) => /* @__PURE__ */ jsx("div", {
|
|
2801
|
-
className: "absolute flex items-center justify-center border-
|
|
2830
|
+
className: "text-muted-foreground absolute flex items-center justify-center border-b border-border text-xs",
|
|
2802
2831
|
style: {
|
|
2803
2832
|
top: axisOffset(rowLayout, vr.index),
|
|
2804
2833
|
height: rowLayout.sizes[vr.index],
|
|
@@ -3037,23 +3066,21 @@ function SpreadsheetFilePreview({ sourceId, fileName, document: previewDocument,
|
|
|
3037
3066
|
const [selectedCell, setSelectedCell] = useState(null);
|
|
3038
3067
|
const [chartRenderer, setChartRenderer] = useState(null);
|
|
3039
3068
|
const [imageUrls, setImageUrls] = useState({});
|
|
3040
|
-
const model =
|
|
3069
|
+
const model = "model" in state ? state.model : null;
|
|
3041
3070
|
const sheets = useMemo(() => model ? visibleSheets(model) : [], [model]);
|
|
3042
3071
|
const activeSheet = sheets.find((sheet) => sheet.name === activeSheetName) ?? sheets[0] ?? null;
|
|
3043
3072
|
useEffect(() => {
|
|
3044
3073
|
setSelectedCell(null);
|
|
3045
|
-
if (sheets.length === 0)
|
|
3046
|
-
setActiveSheetName(null);
|
|
3047
|
-
return;
|
|
3048
|
-
}
|
|
3074
|
+
if (sheets.length === 0) return;
|
|
3049
3075
|
if (!sheets.some((sheet) => sheet.name === activeSheetName)) setActiveSheetName(sheets[0].name);
|
|
3050
3076
|
}, [sheets, activeSheetName]);
|
|
3051
3077
|
const handleSelectCell = useCallback((info) => setSelectedCell(info && activeSheet ? {
|
|
3052
3078
|
...info,
|
|
3053
|
-
sheet: activeSheet
|
|
3054
|
-
|
|
3079
|
+
sheet: activeSheet,
|
|
3080
|
+
document: previewDocument
|
|
3081
|
+
} : null), [activeSheet, previewDocument]);
|
|
3055
3082
|
const selectionReference = useMemo(() => {
|
|
3056
|
-
if (!selectedCell || !activeSheet || selectedCell.sheet !== activeSheet) return null;
|
|
3083
|
+
if (state.status !== "ready" || !selectedCell || !activeSheet || selectedCell.sheet !== activeSheet || selectedCell.document !== previewDocument) return null;
|
|
3057
3084
|
return createPreviewSelection({
|
|
3058
3085
|
sourceId,
|
|
3059
3086
|
anchor: {
|
|
@@ -3068,7 +3095,8 @@ function SpreadsheetFilePreview({ sourceId, fileName, document: previewDocument,
|
|
|
3068
3095
|
selectedCell,
|
|
3069
3096
|
activeSheet,
|
|
3070
3097
|
sourceId,
|
|
3071
|
-
previewDocument
|
|
3098
|
+
previewDocument,
|
|
3099
|
+
state.status
|
|
3072
3100
|
]);
|
|
3073
3101
|
const captureArmedRef = useRef(false);
|
|
3074
3102
|
useEffect(() => {
|
|
@@ -3127,9 +3155,9 @@ function SpreadsheetFilePreview({ sourceId, fileName, document: previewDocument,
|
|
|
3127
3155
|
});
|
|
3128
3156
|
}, []);
|
|
3129
3157
|
let content;
|
|
3130
|
-
if (state.status === "loading" || state.status === "idle") content = /* @__PURE__ */ jsxs("div", {
|
|
3158
|
+
if (state.status === "loading" && !model || state.status === "idle") content = /* @__PURE__ */ jsxs("div", {
|
|
3131
3159
|
role: "status",
|
|
3132
|
-
className: "flex h-full w-full items-center justify-center gap-2 bg-background text-
|
|
3160
|
+
className: "text-muted-foreground flex h-full w-full items-center justify-center gap-2 bg-background text-sm",
|
|
3133
3161
|
children: [/* @__PURE__ */ jsx(LoaderCircle, {
|
|
3134
3162
|
className: "size-4 animate-spin",
|
|
3135
3163
|
"aria-hidden": true
|
|
@@ -3157,13 +3185,14 @@ function SpreadsheetFilePreview({ sourceId, fileName, document: previewDocument,
|
|
|
3157
3185
|
className: "relative flex h-full w-full flex-col overflow-hidden bg-background",
|
|
3158
3186
|
children: [/* @__PURE__ */ jsx("div", {
|
|
3159
3187
|
className: "min-h-0 flex-1",
|
|
3188
|
+
inert: state.status !== "ready",
|
|
3160
3189
|
children: /* @__PURE__ */ jsx(XlsxGrid_default, {
|
|
3161
3190
|
sheet: activeSheet,
|
|
3162
3191
|
styles: model.styles,
|
|
3163
3192
|
imageUrls,
|
|
3164
3193
|
zoom,
|
|
3165
3194
|
onSelectCell: handleSelectCell,
|
|
3166
|
-
pickerActive: onSelection !== void 0,
|
|
3195
|
+
pickerActive: state.status === "ready" && onSelection !== void 0,
|
|
3167
3196
|
renderChart
|
|
3168
3197
|
}, activeSheet.name)
|
|
3169
3198
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -3187,9 +3216,9 @@ function SpreadsheetFilePreview({ sourceId, fileName, document: previewDocument,
|
|
|
3187
3216
|
})
|
|
3188
3217
|
}),
|
|
3189
3218
|
/* @__PURE__ */ jsxs("div", {
|
|
3190
|
-
className: "flex min-w-0 flex-1 items-center justify-end gap-2 text-
|
|
3219
|
+
className: "text-muted-foreground flex min-w-0 flex-1 items-center justify-end gap-2 text-xs",
|
|
3191
3220
|
children: [statusBarText ? /* @__PURE__ */ jsx("span", {
|
|
3192
|
-
className: "selectable cursor-text select-text
|
|
3221
|
+
className: "selectable cursor-text truncate select-text",
|
|
3193
3222
|
"data-testid": "xlsx-preview-status-bar",
|
|
3194
3223
|
children: statusBarText
|
|
3195
3224
|
}) : null, cellOnActiveSheet?.cell?.formulaState === "unevaluated" ? /* @__PURE__ */ jsx("span", {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { i as __toESM } from "./rolldown-runtime-B-lAHAz2.js";
|
|
2
2
|
import { r as readPreviewDocument, t as PreviewError } from "./source-Rx3etU3y.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as ChevronRight, r as ChevronLeft, t as RotateCcw } from "./rotate-ccw-
|
|
5
|
-
import {
|
|
6
|
-
import { n as ZoomIn, t as ZoomOut } from "./zoom-out-
|
|
7
|
-
import { t as
|
|
3
|
+
import { a as usePreviewHost, d as EmptyState, m as LoaderCircle, r as FilePreviewLayout, s as FilePreviewToolbar, t as useTranslation } from "./useTranslation-BJY4EKsz.js";
|
|
4
|
+
import { n as ChevronRight, r as ChevronLeft, t as RotateCcw } from "./rotate-ccw-Bx-jjhVm.js";
|
|
5
|
+
import { t as CircleAlert } from "./circle-alert-sByhBDN4.js";
|
|
6
|
+
import { n as ZoomIn, t as ZoomOut } from "./zoom-out-B2XJ64Kx.js";
|
|
7
|
+
import { t as FilePreviewToolbarButton } from "./FilePreviewToolbarButton-ptqwCTnz.js";
|
|
8
|
+
import { t as FilePreviewTooLarge } from "./FilePreviewTooLarge-DC7vPyMI.js";
|
|
9
|
+
import { t as createPreviewSelection } from "./selection-B0INvh6t.js";
|
|
8
10
|
import { t as attachTouchPinch } from "./touchPinch-C4fl-9fg.js";
|
|
9
11
|
import { t as require_jszip_min } from "./jszip.min-uwqlc4KL.js";
|
|
10
12
|
import { useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
@@ -3834,7 +3836,7 @@ function sanitizeHyperlinks(body) {
|
|
|
3834
3836
|
});
|
|
3835
3837
|
}
|
|
3836
3838
|
function WordFilePreview({ sourceId, fileName, document: previewDocument, onSelection }) {
|
|
3837
|
-
const { options, failDocument } = usePreviewHost();
|
|
3839
|
+
const { options, failDocument, isCurrentDocument } = usePreviewHost();
|
|
3838
3840
|
const { t } = useTranslation();
|
|
3839
3841
|
const docxClassName = `docx-preview-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
3840
3842
|
const containerRef = useRef(null);
|
|
@@ -3851,7 +3853,10 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
3851
3853
|
const [zoom, setZoom] = useState(DOCX_PREVIEW_DEFAULT_ZOOM);
|
|
3852
3854
|
const [fitZoom, setFitZoom] = useState(DOCX_PREVIEW_DEFAULT_ZOOM);
|
|
3853
3855
|
const [manualZoom, setManualZoom] = useState(false);
|
|
3854
|
-
const
|
|
3856
|
+
const normalizeSymbolBulletsRef = useRef(options?.docx?.normalizeSymbolBullets === true);
|
|
3857
|
+
useLayoutEffect(() => {
|
|
3858
|
+
normalizeSymbolBulletsRef.current = options?.docx?.normalizeSymbolBullets === true;
|
|
3859
|
+
}, [options?.docx?.normalizeSymbolBullets]);
|
|
3855
3860
|
const fitWidth = options?.docx?.initialZoom === "fit-width";
|
|
3856
3861
|
const minZoom = fitWidth ? Math.min(DOCX_PREVIEW_MIN_ZOOM, fitZoom) : DOCX_PREVIEW_MIN_ZOOM;
|
|
3857
3862
|
useLayoutEffect(() => {
|
|
@@ -3921,16 +3926,10 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
3921
3926
|
if (!bodyContainer || !styleContainer) return;
|
|
3922
3927
|
const controller = new AbortController();
|
|
3923
3928
|
const token = ++renderTokenRef.current;
|
|
3924
|
-
const isCurrent = () => renderTokenRef.current === token;
|
|
3929
|
+
const isCurrent = () => renderTokenRef.current === token && isCurrentDocument?.() !== false;
|
|
3930
|
+
const normalizeSymbolBullets = normalizeSymbolBulletsRef.current;
|
|
3925
3931
|
setError(null);
|
|
3926
3932
|
setLoading(true);
|
|
3927
|
-
setCurrentPage(0);
|
|
3928
|
-
setPageCount(0);
|
|
3929
|
-
setZoom(DOCX_PREVIEW_DEFAULT_ZOOM);
|
|
3930
|
-
setFitZoom(DOCX_PREVIEW_DEFAULT_ZOOM);
|
|
3931
|
-
setManualZoom(false);
|
|
3932
|
-
fitScrollTopRef.current = null;
|
|
3933
|
-
pinchAnchorRef.current = null;
|
|
3934
3933
|
const stagingHost = document.createElement("div");
|
|
3935
3934
|
const stagingBody = document.createElement("div");
|
|
3936
3935
|
const stagingStyle = document.createElement("div");
|
|
@@ -3965,11 +3964,17 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
3965
3964
|
page.classList.add("docx-preview-page", "docx-preview");
|
|
3966
3965
|
});
|
|
3967
3966
|
sanitizeHyperlinks(stagingBody);
|
|
3967
|
+
const scrollTop = containerRef.current?.scrollTop ?? 0;
|
|
3968
|
+
const scrollLeft = containerRef.current?.scrollLeft ?? 0;
|
|
3968
3969
|
bodyContainer.replaceChildren(...stagingBody.childNodes);
|
|
3969
3970
|
styleContainer.replaceChildren(...stagingStyle.childNodes);
|
|
3971
|
+
if (containerRef.current) {
|
|
3972
|
+
containerRef.current.scrollTop = scrollTop;
|
|
3973
|
+
containerRef.current.scrollLeft = scrollLeft;
|
|
3974
|
+
}
|
|
3970
3975
|
const nextPageCount = Math.max(pages.length, 1);
|
|
3971
3976
|
setPageCount(nextPageCount);
|
|
3972
|
-
setCurrentPage(
|
|
3977
|
+
setCurrentPage((page) => clamp(page, 1, nextPageCount));
|
|
3973
3978
|
focusContainer();
|
|
3974
3979
|
} catch (loadError) {
|
|
3975
3980
|
if (!isCurrent()) return;
|
|
@@ -3984,8 +3989,6 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
3984
3989
|
return () => {
|
|
3985
3990
|
controller.abort();
|
|
3986
3991
|
renderTokenRef.current += 1;
|
|
3987
|
-
bodyContainer.innerHTML = "";
|
|
3988
|
-
styleContainer.innerHTML = "";
|
|
3989
3992
|
stagingHost.remove();
|
|
3990
3993
|
};
|
|
3991
3994
|
}, [
|
|
@@ -3994,12 +3997,12 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
3994
3997
|
previewDocument,
|
|
3995
3998
|
failDocument,
|
|
3996
3999
|
docxClassName,
|
|
3997
|
-
|
|
4000
|
+
isCurrentDocument
|
|
3998
4001
|
]);
|
|
3999
4002
|
useEffect(() => {
|
|
4000
4003
|
const scrollRoot = containerRef.current;
|
|
4001
4004
|
const bodyContainer = bodyRef.current;
|
|
4002
|
-
if (!scrollRoot || !bodyContainer || pageCount <= 0) return;
|
|
4005
|
+
if (!scrollRoot || !bodyContainer || pageCount <= 0 || loading) return;
|
|
4003
4006
|
const pages = Array.from(bodyContainer.querySelectorAll(".docx-preview-page"));
|
|
4004
4007
|
if (pages.length === 0) return;
|
|
4005
4008
|
const visiblePages = /* @__PURE__ */ new Set();
|
|
@@ -4022,7 +4025,7 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
4022
4025
|
});
|
|
4023
4026
|
pages.forEach((page) => observer.observe(page));
|
|
4024
4027
|
return () => observer.disconnect();
|
|
4025
|
-
}, [pageCount]);
|
|
4028
|
+
}, [pageCount, loading]);
|
|
4026
4029
|
const handlePick = useCallback((event) => {
|
|
4027
4030
|
if (!onSelection || !(event.target instanceof Element)) return;
|
|
4028
4031
|
if (event.target.closest("a[href]")) event.preventDefault();
|
|
@@ -4105,12 +4108,12 @@ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSele
|
|
|
4105
4108
|
"data-picker": onSelection ? "true" : void 0,
|
|
4106
4109
|
onClick: handlePick,
|
|
4107
4110
|
style: contentStyle,
|
|
4108
|
-
className: "mx-auto w-fit min-w-0 [&
|
|
4111
|
+
className: "mx-auto w-fit min-w-0 [&_.docx-preview]:box-border [&_.docx-preview]:max-w-full [&_.docx-preview-wrapper]:mx-auto [&_p[data-docx-picked=true]]:bg-primary/15 [&_p[data-docx-picked=true]]:outline [&_p[data-docx-picked=true]]:outline-1 [&_p[data-docx-picked=true]]:outline-primary/60 [&_section]:overflow-hidden [&_section]:rounded-sm [&_section]:shadow-md [&[data-picker=true]_p[data-docx-part=body]]:cursor-pointer [&[data-picker=true]_p[data-docx-part=body]:not([data-docx-picked=true]):hover]:bg-primary/10"
|
|
4109
4112
|
})]
|
|
4110
4113
|
}),
|
|
4111
4114
|
loading ? /* @__PURE__ */ jsxs("div", {
|
|
4112
4115
|
role: "status",
|
|
4113
|
-
className: "absolute inset-0 flex items-center justify-center gap-2 bg-background text-sm
|
|
4116
|
+
className: "text-muted-foreground absolute inset-0 flex items-center justify-center gap-2 bg-background text-sm",
|
|
4114
4117
|
children: [/* @__PURE__ */ jsx(LoaderCircle, {
|
|
4115
4118
|
className: "size-4 animate-spin",
|
|
4116
4119
|
"aria-hidden": true
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { g as createLucideIcon } from "./useTranslation-BJY4EKsz.js";
|
|
2
|
+
/**
|
|
3
|
+
* @license lucide-react v0.545.0 - ISC
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the ISC license.
|
|
6
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
var CircleAlert = createLucideIcon("circle-alert", [
|
|
9
|
+
["circle", {
|
|
10
|
+
cx: "12",
|
|
11
|
+
cy: "12",
|
|
12
|
+
r: "10",
|
|
13
|
+
key: "1mglay"
|
|
14
|
+
}],
|
|
15
|
+
["line", {
|
|
16
|
+
x1: "12",
|
|
17
|
+
x2: "12",
|
|
18
|
+
y1: "8",
|
|
19
|
+
y2: "12",
|
|
20
|
+
key: "1pkeuh"
|
|
21
|
+
}],
|
|
22
|
+
["line", {
|
|
23
|
+
x1: "12",
|
|
24
|
+
x2: "12.01",
|
|
25
|
+
y1: "16",
|
|
26
|
+
y2: "16",
|
|
27
|
+
key: "4dfq90"
|
|
28
|
+
}]
|
|
29
|
+
]);
|
|
30
|
+
//#endregion
|
|
31
|
+
export { CircleAlert as t };
|
|
@@ -23,7 +23,7 @@ var imageFilePreviewPlugin = {
|
|
|
23
23
|
"image/vnd.microsoft.icon",
|
|
24
24
|
"image/svg+xml"
|
|
25
25
|
],
|
|
26
|
-
load: () => import("./ImageFilePreview-
|
|
26
|
+
load: () => import("./ImageFilePreview-C_P1iIEi.js")
|
|
27
27
|
};
|
|
28
28
|
//#endregion
|
|
29
29
|
export { imageFilePreviewPlugin as t };
|
package/dist/react.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { n as assertPreviewRange, t as PreviewError } from "./source-Rx3etU3y.js";
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import {
|
|
2
|
+
import { a as usePreviewHost, c as FilePreviewToolbarPortalHost, d as EmptyState, g as createLucideIcon, h as FileWarning, i as PreviewHostContext, l as FilePreviewToolbarPortalProvider, m as LoaderCircle, n as I18nContext, p as cn, r as FilePreviewLayout, s as FilePreviewToolbar, t as useTranslation } from "./useTranslation-BJY4EKsz.js";
|
|
3
|
+
import { n as DialogPortalContainerProvider, r as PortalContainerProvider, t as FilePreviewToolbarButton } from "./FilePreviewToolbarButton-ptqwCTnz.js";
|
|
4
|
+
import { t as imageFilePreviewPlugin } from "./imageFilePreviewPlugin-D6hV1Hm1.js";
|
|
5
|
+
import { Component, Suspense, createContext, createElement, lazy, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
/**
|
|
7
8
|
* @license lucide-react v0.545.0 - ISC
|
|
@@ -31,28 +32,38 @@ var plugins = [
|
|
|
31
32
|
id: "pdf",
|
|
32
33
|
extensions: ["pdf"],
|
|
33
34
|
mediaTypes: ["application/pdf"],
|
|
34
|
-
load: () => import("./PdfFilePreview-
|
|
35
|
+
load: () => import("./PdfFilePreview-CbrMcPzo.js"),
|
|
35
36
|
supportsSelectionReference: true
|
|
36
37
|
},
|
|
37
38
|
{
|
|
38
39
|
id: "powerpoint",
|
|
39
40
|
extensions: ["pptx"],
|
|
40
41
|
mediaTypes: ["application/vnd.openxmlformats-officedocument.presentationml.presentation"],
|
|
41
|
-
load: () => import("./PowerPointFilePreview-
|
|
42
|
+
load: () => import("./PowerPointFilePreview-9E6kUy_A.js"),
|
|
42
43
|
supportsSelectionReference: true
|
|
43
44
|
},
|
|
45
|
+
{
|
|
46
|
+
id: "rtf",
|
|
47
|
+
extensions: ["rtf"],
|
|
48
|
+
mediaTypes: [
|
|
49
|
+
"application/rtf",
|
|
50
|
+
"text/rtf",
|
|
51
|
+
"application/x-rtf"
|
|
52
|
+
],
|
|
53
|
+
load: () => import("./RtfFilePreview-Bgl6lmWy.js")
|
|
54
|
+
},
|
|
44
55
|
{
|
|
45
56
|
id: "spreadsheet",
|
|
46
57
|
extensions: ["xlsx"],
|
|
47
58
|
mediaTypes: ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
|
|
48
|
-
load: () => import("./SpreadsheetFilePreview-
|
|
59
|
+
load: () => import("./SpreadsheetFilePreview-PWFG3UY3.js"),
|
|
49
60
|
supportsSelectionReference: true
|
|
50
61
|
},
|
|
51
62
|
{
|
|
52
63
|
id: "word",
|
|
53
64
|
extensions: ["docx"],
|
|
54
65
|
mediaTypes: ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
|
|
55
|
-
load: () => import("./WordFilePreview-
|
|
66
|
+
load: () => import("./WordFilePreview-hfALJk2N.js"),
|
|
56
67
|
supportsSelectionReference: true
|
|
57
68
|
}
|
|
58
69
|
];
|
|
@@ -2997,6 +3008,8 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
2997
3008
|
const [session, setSession] = useState(null);
|
|
2998
3009
|
const [failure, setFailure] = useState(null);
|
|
2999
3010
|
const closeRef = useRef(void 0);
|
|
3011
|
+
const plugin = useMemo(() => resolvePreviewPlugin(source.name, source.mediaType), [source.name, source.mediaType]);
|
|
3012
|
+
const Plugin = useMemo(() => plugin ? lazy(plugin.load) : null, [plugin]);
|
|
3000
3013
|
const hasFailedRef = useRef(false);
|
|
3001
3014
|
const callbacks = useRef({
|
|
3002
3015
|
onSelection,
|
|
@@ -3010,7 +3023,7 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3010
3023
|
onError,
|
|
3011
3024
|
onRequestOpen
|
|
3012
3025
|
};
|
|
3013
|
-
const
|
|
3026
|
+
const reportFailure = useCallback((error) => {
|
|
3014
3027
|
if (hasFailedRef.current) return;
|
|
3015
3028
|
hasFailedRef.current = true;
|
|
3016
3029
|
closeRef.current?.();
|
|
@@ -3024,7 +3037,24 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3024
3037
|
});
|
|
3025
3038
|
callbacks.current.onError?.(normalized);
|
|
3026
3039
|
}, []);
|
|
3027
|
-
const
|
|
3040
|
+
const requestIdRef = useRef(0);
|
|
3041
|
+
useLayoutEffect(() => {
|
|
3042
|
+
requestIdRef.current += 1;
|
|
3043
|
+
return () => {
|
|
3044
|
+
requestIdRef.current += 1;
|
|
3045
|
+
};
|
|
3046
|
+
}, [
|
|
3047
|
+
source,
|
|
3048
|
+
refreshKey,
|
|
3049
|
+
plugin
|
|
3050
|
+
]);
|
|
3051
|
+
const isCurrentSession = useCallback(() => session?.requestId === requestIdRef.current, [session]);
|
|
3052
|
+
const failDocument = useCallback((error) => {
|
|
3053
|
+
if (isCurrentSession()) reportFailure(error);
|
|
3054
|
+
}, [isCurrentSession, reportFailure]);
|
|
3055
|
+
const reportSelection = useCallback((selection) => {
|
|
3056
|
+
if (isCurrentSession()) callbacks.current.onSelection?.(selection);
|
|
3057
|
+
}, [isCurrentSession]);
|
|
3028
3058
|
const reportDiagnostic = useCallback((diagnostic) => callbacks.current.onDiagnostic?.(diagnostic), []);
|
|
3029
3059
|
const requestOpen = useCallback((reason) => callbacks.current.onRequestOpen?.(reason), []);
|
|
3030
3060
|
const hasOpenAction = onRequestOpen !== void 0;
|
|
@@ -3034,7 +3064,8 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3034
3064
|
options,
|
|
3035
3065
|
onDiagnostic: reportDiagnostic,
|
|
3036
3066
|
onRequestOpen: hasOpenAction ? requestOpen : void 0,
|
|
3037
|
-
failDocument
|
|
3067
|
+
failDocument,
|
|
3068
|
+
isCurrentDocument: isCurrentSession
|
|
3038
3069
|
}), [
|
|
3039
3070
|
root,
|
|
3040
3071
|
resources,
|
|
@@ -3042,15 +3073,14 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3042
3073
|
reportDiagnostic,
|
|
3043
3074
|
requestOpen,
|
|
3044
3075
|
hasOpenAction,
|
|
3045
|
-
failDocument
|
|
3076
|
+
failDocument,
|
|
3077
|
+
isCurrentSession
|
|
3046
3078
|
]);
|
|
3047
|
-
const plugin = useMemo(() => resolvePreviewPlugin(source.name, source.mediaType), [source.name, source.mediaType]);
|
|
3048
|
-
const Plugin = useMemo(() => plugin ? lazy(plugin.load) : null, [plugin]);
|
|
3049
3079
|
useEffect(() => {
|
|
3050
|
-
setSession(null);
|
|
3051
3080
|
setFailure(null);
|
|
3052
3081
|
hasFailedRef.current = false;
|
|
3053
3082
|
if (!plugin) return;
|
|
3083
|
+
const requestId = requestIdRef.current;
|
|
3054
3084
|
const controller = new AbortController();
|
|
3055
3085
|
let opened = null;
|
|
3056
3086
|
let closed = false;
|
|
@@ -3075,8 +3105,9 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3075
3105
|
assertPreviewRange(opened.size, 0, opened.size);
|
|
3076
3106
|
setSession({
|
|
3077
3107
|
source,
|
|
3078
|
-
|
|
3079
|
-
document: opened
|
|
3108
|
+
requestId,
|
|
3109
|
+
document: opened,
|
|
3110
|
+
plugin
|
|
3080
3111
|
});
|
|
3081
3112
|
} catch (error) {
|
|
3082
3113
|
close();
|
|
@@ -3085,7 +3116,7 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3085
3116
|
source,
|
|
3086
3117
|
refreshKey
|
|
3087
3118
|
});
|
|
3088
|
-
|
|
3119
|
+
reportFailure(error);
|
|
3089
3120
|
}
|
|
3090
3121
|
})();
|
|
3091
3122
|
return () => {
|
|
@@ -3097,9 +3128,9 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3097
3128
|
source,
|
|
3098
3129
|
refreshKey,
|
|
3099
3130
|
plugin,
|
|
3100
|
-
|
|
3131
|
+
reportFailure
|
|
3101
3132
|
]);
|
|
3102
|
-
const ready = session?.source === source && session.
|
|
3133
|
+
const ready = session?.source.id === source.id && session.plugin === plugin ? session : null;
|
|
3103
3134
|
const failed = failure?.source === source && failure.refreshKey === refreshKey;
|
|
3104
3135
|
const content = !Plugin ? /* @__PURE__ */ jsx(PreviewState, { kind: "unsupported" }) : failed ? /* @__PURE__ */ jsx(PreviewState, { kind: "error" }) : !ready ? /* @__PURE__ */ jsx(PreviewState, { kind: "loading" }) : /* @__PURE__ */ jsx(m, {
|
|
3105
3136
|
resetKeys: [ready.document],
|
|
@@ -3108,14 +3139,14 @@ function PreviewSession({ source, header, className, style, refreshKey = 0, reso
|
|
|
3108
3139
|
children: /* @__PURE__ */ jsx(Suspense, {
|
|
3109
3140
|
fallback: /* @__PURE__ */ jsx(PreviewState, { kind: "loading" }),
|
|
3110
3141
|
children: /* @__PURE__ */ jsx(Plugin, {
|
|
3111
|
-
sourceId: source.id,
|
|
3112
|
-
fileName: source.name,
|
|
3113
|
-
mediaType: source.mediaType,
|
|
3142
|
+
sourceId: ready.source.id,
|
|
3143
|
+
fileName: ready.source.name,
|
|
3144
|
+
mediaType: ready.source.mediaType,
|
|
3114
3145
|
document: ready.document,
|
|
3115
3146
|
onSelection: onSelection ? reportSelection : void 0
|
|
3116
|
-
}
|
|
3147
|
+
})
|
|
3117
3148
|
})
|
|
3118
|
-
}, `${source.id}:${
|
|
3149
|
+
}, `${source.id}:${plugin?.id}`);
|
|
3119
3150
|
return /* @__PURE__ */ jsx("div", {
|
|
3120
3151
|
ref: setRoot,
|
|
3121
3152
|
"data-file-preview-root": "",
|
|
@@ -1,34 +1,4 @@
|
|
|
1
1
|
import { n as SELECTION_EXCERPT_MAX_LENGTH } from "./documentAnchor-J7GGLU15.js";
|
|
2
|
-
import { R as createLucideIcon } from "./useTranslation-DMhY277o.js";
|
|
3
|
-
/**
|
|
4
|
-
* @license lucide-react v0.545.0 - ISC
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the ISC license.
|
|
7
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
8
|
-
*/
|
|
9
|
-
var CircleAlert = createLucideIcon("circle-alert", [
|
|
10
|
-
["circle", {
|
|
11
|
-
cx: "12",
|
|
12
|
-
cy: "12",
|
|
13
|
-
r: "10",
|
|
14
|
-
key: "1mglay"
|
|
15
|
-
}],
|
|
16
|
-
["line", {
|
|
17
|
-
x1: "12",
|
|
18
|
-
x2: "12",
|
|
19
|
-
y1: "8",
|
|
20
|
-
y2: "12",
|
|
21
|
-
key: "1pkeuh"
|
|
22
|
-
}],
|
|
23
|
-
["line", {
|
|
24
|
-
x1: "12",
|
|
25
|
-
x2: "12.01",
|
|
26
|
-
y1: "16",
|
|
27
|
-
y2: "16",
|
|
28
|
-
key: "4dfq90"
|
|
29
|
-
}]
|
|
30
|
-
]);
|
|
31
|
-
//#endregion
|
|
32
2
|
//#region src/selection.ts
|
|
33
3
|
var SELECTION_WHITESPACE = /[\t\n\v\f\r \u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff\u001c-\u001f]+/g;
|
|
34
4
|
function normalizeSelectionText(text) {
|
|
@@ -44,4 +14,4 @@ function createPreviewSelection(input) {
|
|
|
44
14
|
} : null;
|
|
45
15
|
}
|
|
46
16
|
//#endregion
|
|
47
|
-
export { normalizeSelectionText as n,
|
|
17
|
+
export { normalizeSelectionText as n, createPreviewSelection as t };
|