@fdls/file-viewer 0.2.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.
- package/LICENSE +21 -0
- package/README.md +524 -0
- package/dist/index.css +30 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +309 -0
- package/dist/index.js +3351 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +2 -0
- package/package.json +100 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3351 @@
|
|
|
1
|
+
import "./style.css";
|
|
2
|
+
import { createContext, lazy, useState, useRef, useEffect, useCallback, useMemo, useId, useLayoutEffect, forwardRef, isValidElement, Suspense, useContext, cloneElement } from 'react';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { Document, Page, pdfjs } from 'react-pdf';
|
|
6
|
+
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';
|
|
7
|
+
import { useReactToPrint } from 'react-to-print';
|
|
8
|
+
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __esm = (fn, res) => function __init() {
|
|
12
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
13
|
+
};
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
function assignRef(ref, value) {
|
|
19
|
+
if (typeof ref === "function") {
|
|
20
|
+
ref(value);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (ref && typeof ref === "object") {
|
|
24
|
+
ref.current = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function mergeRefs(...refs) {
|
|
28
|
+
return (value) => {
|
|
29
|
+
refs.forEach((ref) => assignRef(ref, value));
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function renderAsChild(asChild, child, props) {
|
|
33
|
+
if (!isValidElement(child)) {
|
|
34
|
+
return child;
|
|
35
|
+
}
|
|
36
|
+
const element = child;
|
|
37
|
+
const mergedClassName = [props.className, element.props.className].filter(Boolean).join(" ");
|
|
38
|
+
const mergedStyle = {
|
|
39
|
+
...props.style,
|
|
40
|
+
...element.props.style
|
|
41
|
+
};
|
|
42
|
+
const propsOnClick = props.onClick;
|
|
43
|
+
const propsRef = props.ref;
|
|
44
|
+
return cloneElement(element, {
|
|
45
|
+
...props,
|
|
46
|
+
...element.props,
|
|
47
|
+
className: mergedClassName || void 0,
|
|
48
|
+
style: Object.keys(mergedStyle).length > 0 ? mergedStyle : void 0,
|
|
49
|
+
ref: mergeRefs(propsRef, element.props.ref),
|
|
50
|
+
onClick: (event) => {
|
|
51
|
+
propsOnClick?.(event);
|
|
52
|
+
element.props.onClick?.(event);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
var init_as_child = __esm({
|
|
57
|
+
"src/features/file-viewer/primitives/as-child.ts"() {
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
function IconBase({ children, ...props }) {
|
|
61
|
+
return /* @__PURE__ */ jsx("svg", { ...ICON_DEFAULTS, ...props, children });
|
|
62
|
+
}
|
|
63
|
+
var ICON_DEFAULTS;
|
|
64
|
+
var init_icon = __esm({
|
|
65
|
+
"src/features/file-viewer/components/icons/icon.tsx"() {
|
|
66
|
+
ICON_DEFAULTS = {
|
|
67
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
68
|
+
width: 24,
|
|
69
|
+
height: 24,
|
|
70
|
+
viewBox: "0 0 24 24",
|
|
71
|
+
fill: "none",
|
|
72
|
+
stroke: "currentColor",
|
|
73
|
+
strokeWidth: 2,
|
|
74
|
+
strokeLinecap: "round",
|
|
75
|
+
strokeLinejoin: "round"
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
function X(props) {
|
|
80
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
81
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
82
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
83
|
+
] });
|
|
84
|
+
}
|
|
85
|
+
var init_X = __esm({
|
|
86
|
+
"src/features/file-viewer/components/icons/X.tsx"() {
|
|
87
|
+
init_icon();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
function Download(props) {
|
|
91
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
92
|
+
/* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
93
|
+
/* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
|
|
94
|
+
/* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "15", y2: "3" })
|
|
95
|
+
] });
|
|
96
|
+
}
|
|
97
|
+
var init_Download = __esm({
|
|
98
|
+
"src/features/file-viewer/components/icons/Download.tsx"() {
|
|
99
|
+
init_icon();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
function Printer(props) {
|
|
103
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
104
|
+
/* @__PURE__ */ jsx("path", { d: "M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" }),
|
|
105
|
+
/* @__PURE__ */ jsx("path", { d: "M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6" }),
|
|
106
|
+
/* @__PURE__ */ jsx("rect", { x: "6", y: "14", width: "12", height: "8", rx: "1" })
|
|
107
|
+
] });
|
|
108
|
+
}
|
|
109
|
+
var init_Printer = __esm({
|
|
110
|
+
"src/features/file-viewer/components/icons/Printer.tsx"() {
|
|
111
|
+
init_icon();
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
function Maximize2(props) {
|
|
115
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
116
|
+
/* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
|
|
117
|
+
/* @__PURE__ */ jsx("polyline", { points: "9 21 3 21 3 15" }),
|
|
118
|
+
/* @__PURE__ */ jsx("line", { x1: "21", x2: "14", y1: "3", y2: "10" }),
|
|
119
|
+
/* @__PURE__ */ jsx("line", { x1: "3", x2: "10", y1: "21", y2: "14" })
|
|
120
|
+
] });
|
|
121
|
+
}
|
|
122
|
+
var init_Maximize2 = __esm({
|
|
123
|
+
"src/features/file-viewer/components/icons/Maximize2.tsx"() {
|
|
124
|
+
init_icon();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
function LoaderCircle(props) {
|
|
128
|
+
return /* @__PURE__ */ jsx(IconBase, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
129
|
+
}
|
|
130
|
+
var init_LoaderCircle = __esm({
|
|
131
|
+
"src/features/file-viewer/components/icons/LoaderCircle.tsx"() {
|
|
132
|
+
init_icon();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
function ChevronLeft(props) {
|
|
136
|
+
return /* @__PURE__ */ jsx(IconBase, { ...props, children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) });
|
|
137
|
+
}
|
|
138
|
+
var init_ChevronLeft = __esm({
|
|
139
|
+
"src/features/file-viewer/components/icons/ChevronLeft.tsx"() {
|
|
140
|
+
init_icon();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
function ChevronRight(props) {
|
|
144
|
+
return /* @__PURE__ */ jsx(IconBase, { ...props, children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) });
|
|
145
|
+
}
|
|
146
|
+
var init_ChevronRight = __esm({
|
|
147
|
+
"src/features/file-viewer/components/icons/ChevronRight.tsx"() {
|
|
148
|
+
init_icon();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
function ZoomIn(props) {
|
|
152
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
153
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
154
|
+
/* @__PURE__ */ jsx("line", { x1: "21", x2: "16.65", y1: "21", y2: "16.65" }),
|
|
155
|
+
/* @__PURE__ */ jsx("line", { x1: "11", x2: "11", y1: "8", y2: "14" }),
|
|
156
|
+
/* @__PURE__ */ jsx("line", { x1: "8", x2: "14", y1: "11", y2: "11" })
|
|
157
|
+
] });
|
|
158
|
+
}
|
|
159
|
+
var init_ZoomIn = __esm({
|
|
160
|
+
"src/features/file-viewer/components/icons/ZoomIn.tsx"() {
|
|
161
|
+
init_icon();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
function ZoomOut(props) {
|
|
165
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
166
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
167
|
+
/* @__PURE__ */ jsx("line", { x1: "21", x2: "16.65", y1: "21", y2: "16.65" }),
|
|
168
|
+
/* @__PURE__ */ jsx("line", { x1: "8", x2: "14", y1: "11", y2: "11" })
|
|
169
|
+
] });
|
|
170
|
+
}
|
|
171
|
+
var init_ZoomOut = __esm({
|
|
172
|
+
"src/features/file-viewer/components/icons/ZoomOut.tsx"() {
|
|
173
|
+
init_icon();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
function Scan(props) {
|
|
177
|
+
return /* @__PURE__ */ jsxs(IconBase, { ...props, children: [
|
|
178
|
+
/* @__PURE__ */ jsx("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }),
|
|
179
|
+
/* @__PURE__ */ jsx("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }),
|
|
180
|
+
/* @__PURE__ */ jsx("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }),
|
|
181
|
+
/* @__PURE__ */ jsx("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })
|
|
182
|
+
] });
|
|
183
|
+
}
|
|
184
|
+
var init_Scan = __esm({
|
|
185
|
+
"src/features/file-viewer/components/icons/Scan.tsx"() {
|
|
186
|
+
init_icon();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// src/features/file-viewer/components/icons/index.ts
|
|
191
|
+
var init_icons = __esm({
|
|
192
|
+
"src/features/file-viewer/components/icons/index.ts"() {
|
|
193
|
+
init_X();
|
|
194
|
+
init_Download();
|
|
195
|
+
init_Printer();
|
|
196
|
+
init_Maximize2();
|
|
197
|
+
init_LoaderCircle();
|
|
198
|
+
init_ChevronLeft();
|
|
199
|
+
init_ChevronRight();
|
|
200
|
+
init_ZoomIn();
|
|
201
|
+
init_ZoomOut();
|
|
202
|
+
init_Scan();
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// src/features/file-viewer/utils/deep-partial.ts
|
|
207
|
+
function deepMergePartial(base, patch) {
|
|
208
|
+
if (!patch) {
|
|
209
|
+
return { ...base };
|
|
210
|
+
}
|
|
211
|
+
const result = { ...base };
|
|
212
|
+
const patchRecord = patch;
|
|
213
|
+
const resultRecord = result;
|
|
214
|
+
const baseRecord = base;
|
|
215
|
+
for (const key of Object.keys(patchRecord)) {
|
|
216
|
+
const patchValue = patchRecord[key];
|
|
217
|
+
if (patchValue === void 0) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const baseValue = baseRecord[key];
|
|
221
|
+
if (typeof patchValue === "object" && patchValue !== null && !Array.isArray(patchValue) && typeof baseValue === "object" && baseValue !== null && !Array.isArray(baseValue)) {
|
|
222
|
+
resultRecord[key] = deepMergePartial(
|
|
223
|
+
baseValue,
|
|
224
|
+
patchValue
|
|
225
|
+
);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
resultRecord[key] = patchValue;
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
var init_deep_partial = __esm({
|
|
233
|
+
"src/features/file-viewer/utils/deep-partial.ts"() {
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// src/features/file-viewer/utils/merge-slot-props.ts
|
|
238
|
+
function mergeClassNames(...classNames) {
|
|
239
|
+
return classNames.filter(Boolean).join(" ");
|
|
240
|
+
}
|
|
241
|
+
function mergeStyles(...styles) {
|
|
242
|
+
return Object.assign({}, ...styles.filter(Boolean));
|
|
243
|
+
}
|
|
244
|
+
function mergeSlotClassNames(...layers) {
|
|
245
|
+
const result = {};
|
|
246
|
+
for (const layer of layers) {
|
|
247
|
+
if (!layer) continue;
|
|
248
|
+
for (const key of Object.keys(layer)) {
|
|
249
|
+
const value = layer[key];
|
|
250
|
+
if (value !== void 0) {
|
|
251
|
+
result[key] = mergeClassNames(result[key], value);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
function mergeSlotStyles(...layers) {
|
|
258
|
+
const result = {};
|
|
259
|
+
for (const layer of layers) {
|
|
260
|
+
if (!layer) continue;
|
|
261
|
+
for (const key of Object.keys(layer)) {
|
|
262
|
+
const value = layer[key];
|
|
263
|
+
if (value !== void 0) {
|
|
264
|
+
result[key] = mergeStyles(result[key], value);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
var init_merge_slot_props = __esm({
|
|
271
|
+
"src/features/file-viewer/utils/merge-slot-props.ts"() {
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// src/features/file-viewer/config.ts
|
|
276
|
+
function mergePdfViewerLayer(current, partial) {
|
|
277
|
+
if (!partial) {
|
|
278
|
+
return current;
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
...current,
|
|
282
|
+
...partial,
|
|
283
|
+
classNames: mergeSlotClassNames(
|
|
284
|
+
current?.classNames,
|
|
285
|
+
partial.classNames
|
|
286
|
+
),
|
|
287
|
+
styles: mergeSlotStyles(current?.styles, partial.styles)
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function mergeFileViewerDefaults(current, partial) {
|
|
291
|
+
return {
|
|
292
|
+
...current,
|
|
293
|
+
...partial,
|
|
294
|
+
dialogClassNames: mergeSlotClassNames(
|
|
295
|
+
current?.dialogClassNames,
|
|
296
|
+
partial.dialogClassNames
|
|
297
|
+
),
|
|
298
|
+
dialogStyles: mergeSlotStyles(current?.dialogStyles, partial.dialogStyles),
|
|
299
|
+
classNames: mergeSlotClassNames(current?.classNames, partial.classNames),
|
|
300
|
+
styles: mergeSlotStyles(current?.styles, partial.styles),
|
|
301
|
+
pdfViewerProps: mergePdfViewerLayer(current?.pdfViewerProps, partial.pdfViewerProps)
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function mergeImageViewerDefaults(current, partial) {
|
|
305
|
+
return {
|
|
306
|
+
...current,
|
|
307
|
+
...partial,
|
|
308
|
+
classNames: mergeSlotClassNames(
|
|
309
|
+
current?.classNames,
|
|
310
|
+
partial.classNames
|
|
311
|
+
),
|
|
312
|
+
styles: mergeSlotStyles(current?.styles, partial.styles)
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function mergeToolbarDefaults(current, partial) {
|
|
316
|
+
return {
|
|
317
|
+
...current,
|
|
318
|
+
...partial,
|
|
319
|
+
classNames: mergeSlotClassNames(current?.classNames, partial.classNames),
|
|
320
|
+
styles: mergeSlotStyles(current?.styles, partial.styles)
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function mergeTooltipDefaults(current, partial) {
|
|
324
|
+
return {
|
|
325
|
+
...current,
|
|
326
|
+
...partial,
|
|
327
|
+
classNames: mergeSlotClassNames(current?.classNames, partial.classNames),
|
|
328
|
+
styles: mergeSlotStyles(current?.styles, partial.styles)
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function mergeTranslationDefaults(current, partial) {
|
|
332
|
+
const next = {
|
|
333
|
+
...current
|
|
334
|
+
};
|
|
335
|
+
for (const language of Object.keys(partial)) {
|
|
336
|
+
const patch = partial[language];
|
|
337
|
+
if (!patch) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
next[language] = deepMergePartial(
|
|
341
|
+
next[language] ?? {},
|
|
342
|
+
patch
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
return next;
|
|
346
|
+
}
|
|
347
|
+
function setFileViewerDefaults(partial) {
|
|
348
|
+
const next = { ...globalDefaults };
|
|
349
|
+
if (partial.language !== void 0) {
|
|
350
|
+
next.language = partial.language;
|
|
351
|
+
}
|
|
352
|
+
if (partial.fileViewer) {
|
|
353
|
+
next.fileViewer = mergeFileViewerDefaults(
|
|
354
|
+
next.fileViewer,
|
|
355
|
+
partial.fileViewer
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
if (partial.pdfViewer) {
|
|
359
|
+
next.pdfViewer = mergePdfViewerLayer(
|
|
360
|
+
next.pdfViewer,
|
|
361
|
+
partial.pdfViewer
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
if (partial.imageViewer) {
|
|
365
|
+
next.imageViewer = mergeImageViewerDefaults(
|
|
366
|
+
next.imageViewer,
|
|
367
|
+
partial.imageViewer
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
if (partial.toolbar) {
|
|
371
|
+
next.toolbar = mergeToolbarDefaults(
|
|
372
|
+
next.toolbar,
|
|
373
|
+
partial.toolbar
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
if (partial.tooltip) {
|
|
377
|
+
next.tooltip = mergeTooltipDefaults(
|
|
378
|
+
next.tooltip,
|
|
379
|
+
partial.tooltip
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
if (partial.autoHide) {
|
|
383
|
+
next.autoHide = { ...next.autoHide, ...partial.autoHide };
|
|
384
|
+
}
|
|
385
|
+
if (partial.translations) {
|
|
386
|
+
next.translations = mergeTranslationDefaults(
|
|
387
|
+
next.translations,
|
|
388
|
+
partial.translations
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
globalDefaults = next;
|
|
392
|
+
}
|
|
393
|
+
function getFileViewerDefaults() {
|
|
394
|
+
return globalDefaults;
|
|
395
|
+
}
|
|
396
|
+
function resetFileViewerDefaults() {
|
|
397
|
+
globalDefaults = {};
|
|
398
|
+
}
|
|
399
|
+
function resolvePdfViewerProps(instance = {}) {
|
|
400
|
+
const defaults = getFileViewerDefaults();
|
|
401
|
+
const merged = mergePdfViewerLayer(
|
|
402
|
+
mergePdfViewerLayer(defaults.pdfViewer, defaults.fileViewer?.pdfViewerProps),
|
|
403
|
+
instance
|
|
404
|
+
) ?? {};
|
|
405
|
+
const legacyClassNames = {
|
|
406
|
+
...instance.className || merged.className ? { root: instance.className ?? merged.className } : {},
|
|
407
|
+
...instance.pageClassName || merged.pageClassName ? { page: instance.pageClassName ?? merged.pageClassName } : {},
|
|
408
|
+
...instance.paginationClassName || merged.paginationClassName ? {
|
|
409
|
+
pagination: instance.paginationClassName ?? merged.paginationClassName
|
|
410
|
+
} : {}
|
|
411
|
+
};
|
|
412
|
+
return {
|
|
413
|
+
...merged,
|
|
414
|
+
classNames: mergeSlotClassNames(
|
|
415
|
+
merged.classNames,
|
|
416
|
+
legacyClassNames
|
|
417
|
+
)
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function resolveImageViewerProps(instance = {}) {
|
|
421
|
+
const defaults = getFileViewerDefaults();
|
|
422
|
+
const merged = mergeImageViewerDefaults(defaults.imageViewer, instance) ?? {};
|
|
423
|
+
return merged;
|
|
424
|
+
}
|
|
425
|
+
var globalDefaults;
|
|
426
|
+
var init_config = __esm({
|
|
427
|
+
"src/features/file-viewer/config.ts"() {
|
|
428
|
+
init_deep_partial();
|
|
429
|
+
init_merge_slot_props();
|
|
430
|
+
globalDefaults = {};
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
// src/features/file-viewer/primitives/compute-tooltip-placement.ts
|
|
435
|
+
function resolveSide({
|
|
436
|
+
preferredSide,
|
|
437
|
+
triggerRect,
|
|
438
|
+
contentHeight,
|
|
439
|
+
sideOffset,
|
|
440
|
+
padding,
|
|
441
|
+
viewportHeight
|
|
442
|
+
}) {
|
|
443
|
+
const spaceAbove = triggerRect.top - padding;
|
|
444
|
+
const spaceBelow = viewportHeight - triggerRect.bottom - padding;
|
|
445
|
+
const needed = contentHeight + sideOffset;
|
|
446
|
+
if (preferredSide === "top") {
|
|
447
|
+
if (spaceAbove >= needed) return "top";
|
|
448
|
+
if (spaceBelow >= needed) return "bottom";
|
|
449
|
+
return spaceBelow > spaceAbove ? "bottom" : "top";
|
|
450
|
+
}
|
|
451
|
+
if (spaceBelow >= needed) return "bottom";
|
|
452
|
+
if (spaceAbove >= needed) return "top";
|
|
453
|
+
return spaceAbove > spaceBelow ? "top" : "bottom";
|
|
454
|
+
}
|
|
455
|
+
function computeTooltipPlacement(input) {
|
|
456
|
+
const padding = input.padding ?? 8;
|
|
457
|
+
const viewportWidth = input.viewportWidth ?? window.innerWidth;
|
|
458
|
+
const viewportHeight = input.viewportHeight ?? window.innerHeight;
|
|
459
|
+
const side = resolveSide({
|
|
460
|
+
...input,
|
|
461
|
+
padding,
|
|
462
|
+
viewportHeight});
|
|
463
|
+
const top = side === "top" ? input.triggerRect.top - input.sideOffset - input.contentHeight : input.triggerRect.bottom + input.sideOffset;
|
|
464
|
+
let left = input.triggerRect.left + input.triggerRect.width / 2 - input.contentWidth / 2;
|
|
465
|
+
const maxLeft = viewportWidth - padding - input.contentWidth;
|
|
466
|
+
if (left < padding) {
|
|
467
|
+
left = padding;
|
|
468
|
+
} else if (left > maxLeft) {
|
|
469
|
+
left = Math.max(padding, maxLeft);
|
|
470
|
+
}
|
|
471
|
+
let clampedTop = top;
|
|
472
|
+
const maxTop = viewportHeight - padding - input.contentHeight;
|
|
473
|
+
if (clampedTop < padding) {
|
|
474
|
+
clampedTop = padding;
|
|
475
|
+
} else if (clampedTop > maxTop) {
|
|
476
|
+
clampedTop = Math.max(padding, maxTop);
|
|
477
|
+
}
|
|
478
|
+
return { top: clampedTop, left, side };
|
|
479
|
+
}
|
|
480
|
+
var init_compute_tooltip_placement = __esm({
|
|
481
|
+
"src/features/file-viewer/primitives/compute-tooltip-placement.ts"() {
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
function useTooltipGroup() {
|
|
485
|
+
const context = useContext(TooltipGroupContext);
|
|
486
|
+
if (!context) {
|
|
487
|
+
throw new Error("Tooltip components must be used within TooltipProvider");
|
|
488
|
+
}
|
|
489
|
+
return context;
|
|
490
|
+
}
|
|
491
|
+
function useCloseActiveTooltip() {
|
|
492
|
+
const context = useContext(TooltipGroupContext);
|
|
493
|
+
return context?.closeActiveTooltip ?? (() => void 0);
|
|
494
|
+
}
|
|
495
|
+
function TooltipProvider({
|
|
496
|
+
children,
|
|
497
|
+
delayDuration = 300,
|
|
498
|
+
skipDelayDuration = 500,
|
|
499
|
+
closeDelayDuration = DEFAULT_CLOSE_DELAY_MS
|
|
500
|
+
}) {
|
|
501
|
+
const isOpenDelayedRef = useRef(true);
|
|
502
|
+
const skipDelayTimerRef = useRef(null);
|
|
503
|
+
const activeCloseRef = useRef(null);
|
|
504
|
+
const onTooltipOpened = useCallback(() => {
|
|
505
|
+
if (skipDelayTimerRef.current !== null) {
|
|
506
|
+
window.clearTimeout(skipDelayTimerRef.current);
|
|
507
|
+
}
|
|
508
|
+
isOpenDelayedRef.current = false;
|
|
509
|
+
skipDelayTimerRef.current = window.setTimeout(() => {
|
|
510
|
+
isOpenDelayedRef.current = true;
|
|
511
|
+
skipDelayTimerRef.current = null;
|
|
512
|
+
}, skipDelayDuration);
|
|
513
|
+
}, [skipDelayDuration]);
|
|
514
|
+
const getOpenDelay = useCallback(
|
|
515
|
+
() => isOpenDelayedRef.current ? delayDuration : 0,
|
|
516
|
+
[delayDuration]
|
|
517
|
+
);
|
|
518
|
+
const requestExclusiveOpen = useCallback((closeCallback) => {
|
|
519
|
+
activeCloseRef.current?.();
|
|
520
|
+
activeCloseRef.current = closeCallback;
|
|
521
|
+
}, []);
|
|
522
|
+
const releaseExclusiveOpen = useCallback((closeCallback) => {
|
|
523
|
+
if (activeCloseRef.current === closeCallback) {
|
|
524
|
+
activeCloseRef.current = null;
|
|
525
|
+
}
|
|
526
|
+
}, []);
|
|
527
|
+
const closeActiveTooltip = useCallback(() => {
|
|
528
|
+
activeCloseRef.current?.();
|
|
529
|
+
activeCloseRef.current = null;
|
|
530
|
+
}, []);
|
|
531
|
+
useEffect(
|
|
532
|
+
() => () => {
|
|
533
|
+
if (skipDelayTimerRef.current !== null) {
|
|
534
|
+
window.clearTimeout(skipDelayTimerRef.current);
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
[]
|
|
538
|
+
);
|
|
539
|
+
useEffect(() => {
|
|
540
|
+
const handleDismiss = () => closeActiveTooltip();
|
|
541
|
+
const handlePointerOut = (event) => {
|
|
542
|
+
if (event.pointerType !== "mouse") return;
|
|
543
|
+
const related = event.relatedTarget;
|
|
544
|
+
if (related instanceof Node && document.documentElement.contains(related)) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
closeActiveTooltip();
|
|
548
|
+
};
|
|
549
|
+
window.addEventListener("blur", handleDismiss);
|
|
550
|
+
window.addEventListener("scroll", handleDismiss, true);
|
|
551
|
+
document.documentElement.addEventListener("pointerout", handlePointerOut);
|
|
552
|
+
return () => {
|
|
553
|
+
window.removeEventListener("blur", handleDismiss);
|
|
554
|
+
window.removeEventListener("scroll", handleDismiss, true);
|
|
555
|
+
document.documentElement.removeEventListener("pointerout", handlePointerOut);
|
|
556
|
+
};
|
|
557
|
+
}, [closeActiveTooltip]);
|
|
558
|
+
return /* @__PURE__ */ jsx(
|
|
559
|
+
TooltipGroupContext.Provider,
|
|
560
|
+
{
|
|
561
|
+
value: {
|
|
562
|
+
delayDuration,
|
|
563
|
+
skipDelayDuration,
|
|
564
|
+
closeDelayDuration,
|
|
565
|
+
getOpenDelay,
|
|
566
|
+
onTooltipOpened,
|
|
567
|
+
closeActiveTooltip,
|
|
568
|
+
requestExclusiveOpen,
|
|
569
|
+
releaseExclusiveOpen
|
|
570
|
+
},
|
|
571
|
+
children
|
|
572
|
+
}
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
function useTooltipRoot() {
|
|
576
|
+
const context = useContext(TooltipRootContext);
|
|
577
|
+
if (!context) {
|
|
578
|
+
throw new Error("Tooltip components must be used within TooltipRoot");
|
|
579
|
+
}
|
|
580
|
+
return context;
|
|
581
|
+
}
|
|
582
|
+
function TooltipRoot({ children }) {
|
|
583
|
+
const group = useTooltipGroup();
|
|
584
|
+
const [open, setOpen] = useState(false);
|
|
585
|
+
const triggerRef = useRef(null);
|
|
586
|
+
const contentId = useId();
|
|
587
|
+
const openTimerRef = useRef(null);
|
|
588
|
+
const closeTimerRef = useRef(null);
|
|
589
|
+
const closeTooltip = useCallback(() => {
|
|
590
|
+
setOpen(false);
|
|
591
|
+
group.releaseExclusiveOpen(closeTooltip);
|
|
592
|
+
}, [group]);
|
|
593
|
+
const clearTimers = useCallback(() => {
|
|
594
|
+
if (openTimerRef.current !== null) {
|
|
595
|
+
window.clearTimeout(openTimerRef.current);
|
|
596
|
+
openTimerRef.current = null;
|
|
597
|
+
}
|
|
598
|
+
if (closeTimerRef.current !== null) {
|
|
599
|
+
window.clearTimeout(closeTimerRef.current);
|
|
600
|
+
closeTimerRef.current = null;
|
|
601
|
+
}
|
|
602
|
+
}, []);
|
|
603
|
+
const openImmediately = useCallback(() => {
|
|
604
|
+
clearTimers();
|
|
605
|
+
group.requestExclusiveOpen(closeTooltip);
|
|
606
|
+
setOpen(true);
|
|
607
|
+
group.onTooltipOpened();
|
|
608
|
+
}, [clearTimers, closeTooltip, group]);
|
|
609
|
+
const scheduleOpen = useCallback(() => {
|
|
610
|
+
clearTimers();
|
|
611
|
+
const delay = group.getOpenDelay();
|
|
612
|
+
openTimerRef.current = window.setTimeout(() => {
|
|
613
|
+
openImmediately();
|
|
614
|
+
openTimerRef.current = null;
|
|
615
|
+
}, delay);
|
|
616
|
+
}, [clearTimers, group, openImmediately]);
|
|
617
|
+
const scheduleClose = useCallback(() => {
|
|
618
|
+
clearTimers();
|
|
619
|
+
closeTimerRef.current = window.setTimeout(() => {
|
|
620
|
+
closeTooltip();
|
|
621
|
+
closeTimerRef.current = null;
|
|
622
|
+
}, group.closeDelayDuration);
|
|
623
|
+
}, [clearTimers, closeTooltip, group.closeDelayDuration]);
|
|
624
|
+
useEffect(() => {
|
|
625
|
+
return () => {
|
|
626
|
+
clearTimers();
|
|
627
|
+
group.releaseExclusiveOpen(closeTooltip);
|
|
628
|
+
};
|
|
629
|
+
}, [clearTimers, closeTooltip, group]);
|
|
630
|
+
return /* @__PURE__ */ jsx(
|
|
631
|
+
TooltipRootContext.Provider,
|
|
632
|
+
{
|
|
633
|
+
value: {
|
|
634
|
+
open,
|
|
635
|
+
triggerRef,
|
|
636
|
+
contentId,
|
|
637
|
+
scheduleOpen,
|
|
638
|
+
scheduleClose,
|
|
639
|
+
openImmediately
|
|
640
|
+
},
|
|
641
|
+
children
|
|
642
|
+
}
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
function TooltipTrigger({
|
|
646
|
+
asChild,
|
|
647
|
+
children
|
|
648
|
+
}) {
|
|
649
|
+
const {
|
|
650
|
+
open,
|
|
651
|
+
triggerRef,
|
|
652
|
+
scheduleOpen,
|
|
653
|
+
scheduleClose,
|
|
654
|
+
openImmediately,
|
|
655
|
+
contentId
|
|
656
|
+
} = useTooltipRoot();
|
|
657
|
+
const triggerProps = {
|
|
658
|
+
ref: (node) => {
|
|
659
|
+
triggerRef.current = node;
|
|
660
|
+
},
|
|
661
|
+
"aria-describedby": open ? contentId : void 0,
|
|
662
|
+
onMouseEnter: () => scheduleOpen(),
|
|
663
|
+
onMouseLeave: () => scheduleClose(),
|
|
664
|
+
onFocus: () => openImmediately(),
|
|
665
|
+
onBlur: () => scheduleClose()
|
|
666
|
+
};
|
|
667
|
+
if (asChild) {
|
|
668
|
+
return renderAsChild(true, children, triggerProps);
|
|
669
|
+
}
|
|
670
|
+
return /* @__PURE__ */ jsx("span", { ...triggerProps, children });
|
|
671
|
+
}
|
|
672
|
+
function TooltipPortal({ children }) {
|
|
673
|
+
const { open } = useTooltipRoot();
|
|
674
|
+
if (!open || typeof document === "undefined") return null;
|
|
675
|
+
return createPortal(children, document.body);
|
|
676
|
+
}
|
|
677
|
+
function TooltipContent({
|
|
678
|
+
children,
|
|
679
|
+
side: preferredSide = "top",
|
|
680
|
+
sideOffset = 6,
|
|
681
|
+
className,
|
|
682
|
+
style
|
|
683
|
+
}) {
|
|
684
|
+
const { open, triggerRef, contentId } = useTooltipRoot();
|
|
685
|
+
const contentRef = useRef(null);
|
|
686
|
+
const [placement, setPlacement] = useState(null);
|
|
687
|
+
useLayoutEffect(() => {
|
|
688
|
+
if (!open) {
|
|
689
|
+
setPlacement(null);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
const updatePlacement = () => {
|
|
693
|
+
const trigger = triggerRef.current;
|
|
694
|
+
const content = contentRef.current;
|
|
695
|
+
if (!trigger || !content) return;
|
|
696
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
697
|
+
const { width, height } = content.getBoundingClientRect();
|
|
698
|
+
if (width === 0 || height === 0) {
|
|
699
|
+
requestAnimationFrame(updatePlacement);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
setPlacement(
|
|
703
|
+
computeTooltipPlacement({
|
|
704
|
+
triggerRect,
|
|
705
|
+
contentWidth: width,
|
|
706
|
+
contentHeight: height,
|
|
707
|
+
preferredSide,
|
|
708
|
+
sideOffset
|
|
709
|
+
})
|
|
710
|
+
);
|
|
711
|
+
};
|
|
712
|
+
updatePlacement();
|
|
713
|
+
window.addEventListener("scroll", updatePlacement, true);
|
|
714
|
+
window.addEventListener("resize", updatePlacement);
|
|
715
|
+
return () => {
|
|
716
|
+
window.removeEventListener("scroll", updatePlacement, true);
|
|
717
|
+
window.removeEventListener("resize", updatePlacement);
|
|
718
|
+
};
|
|
719
|
+
}, [open, preferredSide, sideOffset, triggerRef]);
|
|
720
|
+
if (!open) return null;
|
|
721
|
+
const isPositioned = placement !== null;
|
|
722
|
+
return /* @__PURE__ */ jsx(
|
|
723
|
+
"div",
|
|
724
|
+
{
|
|
725
|
+
ref: contentRef,
|
|
726
|
+
id: contentId,
|
|
727
|
+
role: "tooltip",
|
|
728
|
+
className: [TOOLTIP_CONTENT_BASE, className].filter(Boolean).join(" "),
|
|
729
|
+
style: {
|
|
730
|
+
top: placement?.top ?? -9999,
|
|
731
|
+
left: placement?.left ?? -9999,
|
|
732
|
+
visibility: isPositioned ? "visible" : "hidden",
|
|
733
|
+
opacity: isPositioned ? 1 : 0,
|
|
734
|
+
...style
|
|
735
|
+
},
|
|
736
|
+
children
|
|
737
|
+
}
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
var TooltipGroupContext, DEFAULT_CLOSE_DELAY_MS, TooltipRootContext, TOOLTIP_CONTENT_BASE;
|
|
741
|
+
var init_tooltip = __esm({
|
|
742
|
+
"src/features/file-viewer/primitives/tooltip.tsx"() {
|
|
743
|
+
init_as_child();
|
|
744
|
+
init_compute_tooltip_placement();
|
|
745
|
+
TooltipGroupContext = createContext(null);
|
|
746
|
+
DEFAULT_CLOSE_DELAY_MS = 0;
|
|
747
|
+
TooltipRootContext = createContext(null);
|
|
748
|
+
TOOLTIP_CONTENT_BASE = "pointer-events-none fixed z-[200] w-max max-w-xs transition-opacity duration-200";
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
function FileViewerTooltipProvider({
|
|
752
|
+
children
|
|
753
|
+
}) {
|
|
754
|
+
const tooltipDefaults = getFileViewerDefaults().tooltip;
|
|
755
|
+
return /* @__PURE__ */ jsx(
|
|
756
|
+
TooltipProvider,
|
|
757
|
+
{
|
|
758
|
+
delayDuration: tooltipDefaults?.delayDuration ?? 300,
|
|
759
|
+
skipDelayDuration: tooltipDefaults?.skipDelayDuration ?? 500,
|
|
760
|
+
children
|
|
761
|
+
}
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
function TooltipDisabledTarget({ children }) {
|
|
765
|
+
const closeActiveTooltip = useCloseActiveTooltip();
|
|
766
|
+
return renderAsChild(true, children, {
|
|
767
|
+
className: "pointer-events-auto",
|
|
768
|
+
onMouseEnter: () => closeActiveTooltip(),
|
|
769
|
+
onFocus: () => closeActiveTooltip()
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
function FileViewerTooltip({
|
|
773
|
+
content,
|
|
774
|
+
children,
|
|
775
|
+
disabled = false,
|
|
776
|
+
classNames,
|
|
777
|
+
styles
|
|
778
|
+
}) {
|
|
779
|
+
if (disabled) {
|
|
780
|
+
return /* @__PURE__ */ jsx(TooltipDisabledTarget, { children });
|
|
781
|
+
}
|
|
782
|
+
const tooltipDefaults = getFileViewerDefaults().tooltip;
|
|
783
|
+
return /* @__PURE__ */ jsxs(TooltipRoot, { children: [
|
|
784
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
|
|
785
|
+
/* @__PURE__ */ jsx(TooltipPortal, { children: /* @__PURE__ */ jsx(
|
|
786
|
+
TooltipContent,
|
|
787
|
+
{
|
|
788
|
+
side: "top",
|
|
789
|
+
sideOffset: 6,
|
|
790
|
+
className: mergeClassNames(
|
|
791
|
+
FILE_VIEWER_TOOLTIP_CONTENT_DEFAULT,
|
|
792
|
+
tooltipDefaults?.classNames?.content,
|
|
793
|
+
classNames?.content
|
|
794
|
+
),
|
|
795
|
+
style: mergeStyles(
|
|
796
|
+
tooltipDefaults?.styles?.content,
|
|
797
|
+
styles?.content
|
|
798
|
+
),
|
|
799
|
+
children: content
|
|
800
|
+
}
|
|
801
|
+
) })
|
|
802
|
+
] });
|
|
803
|
+
}
|
|
804
|
+
var FILE_VIEWER_TOOLTIP_CONTENT_DEFAULT;
|
|
805
|
+
var init_FileViewerTooltip = __esm({
|
|
806
|
+
"src/features/file-viewer/components/FileViewerTooltip.tsx"() {
|
|
807
|
+
init_config();
|
|
808
|
+
init_tooltip();
|
|
809
|
+
init_as_child();
|
|
810
|
+
init_merge_slot_props();
|
|
811
|
+
FILE_VIEWER_TOOLTIP_CONTENT_DEFAULT = "select-none rounded-md border border-neutral-700/50 bg-neutral-900/75 px-2 py-1.5 text-xs text-white/90 shadow-lg backdrop-blur-sm";
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
// src/features/file-viewer/translations.ts
|
|
816
|
+
function applyTranslationOverlay(builtIn, overlay) {
|
|
817
|
+
if (!overlay) return builtIn;
|
|
818
|
+
return {
|
|
819
|
+
fileViewer: { ...builtIn.fileViewer, ...overlay.fileViewer },
|
|
820
|
+
imageViewer: { ...builtIn.imageViewer, ...overlay.imageViewer },
|
|
821
|
+
pdfViewer: { ...builtIn.pdfViewer, ...overlay.pdfViewer }
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
function getFileViewerTranslations(language) {
|
|
825
|
+
const builtIn = fileViewerTranslationsByLanguage[language];
|
|
826
|
+
const overlay = getFileViewerDefaults().translations?.[language];
|
|
827
|
+
if (!overlay) {
|
|
828
|
+
return builtIn;
|
|
829
|
+
}
|
|
830
|
+
return applyTranslationOverlay(
|
|
831
|
+
builtIn,
|
|
832
|
+
overlay
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
function resolveFormattedMessage(message, params) {
|
|
836
|
+
return typeof message === "function" ? message(params) : message;
|
|
837
|
+
}
|
|
838
|
+
var fileViewerTranslationsByLanguage, defaultFileViewerTranslations;
|
|
839
|
+
var init_translations = __esm({
|
|
840
|
+
"src/features/file-viewer/translations.ts"() {
|
|
841
|
+
init_config();
|
|
842
|
+
fileViewerTranslationsByLanguage = {
|
|
843
|
+
english: {
|
|
844
|
+
fileViewer: {
|
|
845
|
+
closeAriaLabel: "Close",
|
|
846
|
+
printAriaLabel: "Print",
|
|
847
|
+
printTooltip: "Print",
|
|
848
|
+
downloadAriaLabel: "Download",
|
|
849
|
+
downloadTooltip: "Download",
|
|
850
|
+
downloadInProgressAriaLabel: "Downloading\u2026",
|
|
851
|
+
downloadInProgressTooltip: "Downloading\u2026",
|
|
852
|
+
openInModalAriaLabel: "Open in full screen",
|
|
853
|
+
openInModalTooltip: "Open in full screen",
|
|
854
|
+
unsupportedFileType: ({ extension }) => `No preview is available for file type "${extension}".`
|
|
855
|
+
},
|
|
856
|
+
imageViewer: {
|
|
857
|
+
zoomOutAriaLabel: "Zoom out",
|
|
858
|
+
fitScreenAriaLabel: "Fit image",
|
|
859
|
+
zoomInAriaLabel: "Zoom in",
|
|
860
|
+
zoomOutTooltip: "Zoom out",
|
|
861
|
+
fitScreenTooltip: "Fit image",
|
|
862
|
+
zoomInTooltip: "Zoom in"
|
|
863
|
+
},
|
|
864
|
+
pdfViewer: {
|
|
865
|
+
pageLabel: "Page",
|
|
866
|
+
pageInputAriaLabel: ({ value }) => `Page ${value}`,
|
|
867
|
+
previousPageAriaLabel: "Previous page",
|
|
868
|
+
nextPageAriaLabel: "Next page",
|
|
869
|
+
previousPageTooltip: "Previous page",
|
|
870
|
+
nextPageTooltip: "Next page",
|
|
871
|
+
zoomOutAriaLabel: "Zoom out",
|
|
872
|
+
fitWidthAriaLabel: "Fit width",
|
|
873
|
+
zoomInAriaLabel: "Zoom in",
|
|
874
|
+
zoomOutTooltip: "Zoom out",
|
|
875
|
+
fitWidthTooltip: "Fit width",
|
|
876
|
+
zoomInTooltip: "Zoom in"
|
|
877
|
+
}
|
|
878
|
+
},
|
|
879
|
+
portuguese: {
|
|
880
|
+
fileViewer: {
|
|
881
|
+
closeAriaLabel: "Fechar",
|
|
882
|
+
printAriaLabel: "Imprimir",
|
|
883
|
+
printTooltip: "Imprimir",
|
|
884
|
+
downloadAriaLabel: "Transferir",
|
|
885
|
+
downloadTooltip: "Transferir",
|
|
886
|
+
downloadInProgressAriaLabel: "A transferir\u2026",
|
|
887
|
+
downloadInProgressTooltip: "A transferir\u2026",
|
|
888
|
+
openInModalAriaLabel: "Visualizar em tela cheia",
|
|
889
|
+
openInModalTooltip: "Visualizar em tela cheia",
|
|
890
|
+
unsupportedFileType: ({ extension }) => `Ainda n\xE3o existem visualiza\xE7\xF5es para arquivos do tipo "${extension}".`
|
|
891
|
+
},
|
|
892
|
+
imageViewer: {
|
|
893
|
+
zoomOutAriaLabel: "Diminuir zoom",
|
|
894
|
+
fitScreenAriaLabel: "Ajustar imagem",
|
|
895
|
+
zoomInAriaLabel: "Aumentar zoom",
|
|
896
|
+
zoomOutTooltip: "Diminuir zoom",
|
|
897
|
+
fitScreenTooltip: "Ajustar imagem",
|
|
898
|
+
zoomInTooltip: "Aumentar zoom"
|
|
899
|
+
},
|
|
900
|
+
pdfViewer: {
|
|
901
|
+
pageLabel: "P\xE1gina",
|
|
902
|
+
pageInputAriaLabel: ({ value }) => `P\xE1gina ${value}`,
|
|
903
|
+
previousPageAriaLabel: "P\xE1gina anterior",
|
|
904
|
+
nextPageAriaLabel: "Pr\xF3xima p\xE1gina",
|
|
905
|
+
previousPageTooltip: "P\xE1gina anterior",
|
|
906
|
+
nextPageTooltip: "Pr\xF3xima p\xE1gina",
|
|
907
|
+
zoomOutAriaLabel: "Diminuir zoom",
|
|
908
|
+
fitWidthAriaLabel: "Ajustar \xE0 largura",
|
|
909
|
+
zoomInAriaLabel: "Aumentar zoom",
|
|
910
|
+
zoomOutTooltip: "Diminuir zoom",
|
|
911
|
+
fitWidthTooltip: "Ajustar \xE0 largura",
|
|
912
|
+
zoomInTooltip: "Aumentar zoom"
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
defaultFileViewerTranslations = fileViewerTranslationsByLanguage.english;
|
|
917
|
+
}
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
// src/features/file-viewer/utils/resolve-options.ts
|
|
921
|
+
function resolveOption(instance, global, builtIn) {
|
|
922
|
+
if (instance !== void 0) {
|
|
923
|
+
return instance;
|
|
924
|
+
}
|
|
925
|
+
if (global !== void 0) {
|
|
926
|
+
return global;
|
|
927
|
+
}
|
|
928
|
+
return builtIn;
|
|
929
|
+
}
|
|
930
|
+
function resolveHideCloseButton(instance, global, mode) {
|
|
931
|
+
if (instance !== void 0) {
|
|
932
|
+
return instance;
|
|
933
|
+
}
|
|
934
|
+
if (global !== void 0) {
|
|
935
|
+
return global;
|
|
936
|
+
}
|
|
937
|
+
return mode === "inline";
|
|
938
|
+
}
|
|
939
|
+
var init_resolve_options = __esm({
|
|
940
|
+
"src/features/file-viewer/utils/resolve-options.ts"() {
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
// src/features/file-viewer/primitives/scroll-area-math.ts
|
|
945
|
+
function getThumbRatio(viewportSize, contentSize) {
|
|
946
|
+
const ratio = viewportSize / contentSize;
|
|
947
|
+
return Number.isNaN(ratio) ? 0 : ratio;
|
|
948
|
+
}
|
|
949
|
+
function getThumbSize(sizes) {
|
|
950
|
+
const ratio = getThumbRatio(sizes.viewport, sizes.content);
|
|
951
|
+
const scrollbarPadding = sizes.scrollbar.paddingStart + sizes.scrollbar.paddingEnd;
|
|
952
|
+
const thumbSize = (sizes.scrollbar.size - scrollbarPadding) * ratio;
|
|
953
|
+
return Math.max(thumbSize, 18);
|
|
954
|
+
}
|
|
955
|
+
function hasScrollAreaThumb(sizes) {
|
|
956
|
+
if (sizes.viewport <= 0 || sizes.content <= 0 || sizes.scrollbar.size <= 0) {
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
return sizes.content > sizes.viewport + 1;
|
|
960
|
+
}
|
|
961
|
+
function clamp(value, [min, max]) {
|
|
962
|
+
return Math.min(Math.max(value, min), max);
|
|
963
|
+
}
|
|
964
|
+
function linearScale(input, output) {
|
|
965
|
+
return (value) => {
|
|
966
|
+
if (input[0] === input[1] || output[0] === output[1]) return output[0];
|
|
967
|
+
const ratio = (output[1] - output[0]) / (input[1] - input[0]);
|
|
968
|
+
return output[0] + ratio * (value - input[0]);
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
function getThumbOffsetFromScroll(scrollPos, sizes) {
|
|
972
|
+
const thumbSizePx = getThumbSize(sizes);
|
|
973
|
+
const scrollbarPadding = sizes.scrollbar.paddingStart + sizes.scrollbar.paddingEnd;
|
|
974
|
+
const scrollbarTrack = sizes.scrollbar.size - scrollbarPadding;
|
|
975
|
+
const maxScrollPos = sizes.content - sizes.viewport;
|
|
976
|
+
const maxThumbPos = scrollbarTrack - thumbSizePx;
|
|
977
|
+
const scrollWithoutMomentum = clamp(scrollPos, [0, maxScrollPos]);
|
|
978
|
+
const interpolate = linearScale([0, maxScrollPos], [0, maxThumbPos]);
|
|
979
|
+
return interpolate(scrollWithoutMomentum);
|
|
980
|
+
}
|
|
981
|
+
function getScrollPositionFromPointer(pointerPos, pointerOffset, sizes) {
|
|
982
|
+
const thumbSizePx = getThumbSize(sizes);
|
|
983
|
+
const thumbCenter = thumbSizePx / 2;
|
|
984
|
+
const offset = pointerOffset || thumbCenter;
|
|
985
|
+
const thumbOffsetFromEnd = thumbSizePx - offset;
|
|
986
|
+
const minPointerPos = sizes.scrollbar.paddingStart + offset;
|
|
987
|
+
const maxPointerPos = sizes.scrollbar.size - sizes.scrollbar.paddingEnd - thumbOffsetFromEnd;
|
|
988
|
+
const maxScrollPos = sizes.content - sizes.viewport;
|
|
989
|
+
const interpolate = linearScale([minPointerPos, maxPointerPos], [0, maxScrollPos]);
|
|
990
|
+
return interpolate(pointerPos);
|
|
991
|
+
}
|
|
992
|
+
var init_scroll_area_math = __esm({
|
|
993
|
+
"src/features/file-viewer/primitives/scroll-area-math.ts"() {
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
function useScrollAreaContext(component) {
|
|
997
|
+
const context = useContext(ScrollAreaContext);
|
|
998
|
+
if (!context) {
|
|
999
|
+
throw new Error(`${component} must be used within ScrollAreaRoot`);
|
|
1000
|
+
}
|
|
1001
|
+
return context;
|
|
1002
|
+
}
|
|
1003
|
+
function assignRef2(ref, value) {
|
|
1004
|
+
if (typeof ref === "function") {
|
|
1005
|
+
ref(value);
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
if (ref && typeof ref === "object") {
|
|
1009
|
+
ref.current = value;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
function mergeRefs2(...refs) {
|
|
1013
|
+
return (value) => {
|
|
1014
|
+
refs.forEach((ref) => assignRef2(ref, value));
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
function readScrollbarPadding(track) {
|
|
1018
|
+
const computed = getComputedStyle(track);
|
|
1019
|
+
return {
|
|
1020
|
+
paddingStart: Number.parseInt(computed.paddingTop, 10) || 0,
|
|
1021
|
+
paddingEnd: Number.parseInt(computed.paddingBottom, 10) || 0,
|
|
1022
|
+
paddingLeft: Number.parseInt(computed.paddingLeft, 10) || 0,
|
|
1023
|
+
paddingRight: Number.parseInt(computed.paddingRight, 10) || 0
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
function ScrollAreaRoot({
|
|
1027
|
+
className,
|
|
1028
|
+
style,
|
|
1029
|
+
children,
|
|
1030
|
+
...rest
|
|
1031
|
+
}) {
|
|
1032
|
+
const viewportRef = useRef(null);
|
|
1033
|
+
const [cornerWidth, setCornerWidth] = useState(0);
|
|
1034
|
+
const [cornerHeight, setCornerHeight] = useState(0);
|
|
1035
|
+
return /* @__PURE__ */ jsx(
|
|
1036
|
+
ScrollAreaContext.Provider,
|
|
1037
|
+
{
|
|
1038
|
+
value: {
|
|
1039
|
+
viewportRef,
|
|
1040
|
+
cornerWidth,
|
|
1041
|
+
cornerHeight,
|
|
1042
|
+
setCornerWidth,
|
|
1043
|
+
setCornerHeight
|
|
1044
|
+
},
|
|
1045
|
+
children: /* @__PURE__ */ jsx(
|
|
1046
|
+
"div",
|
|
1047
|
+
{
|
|
1048
|
+
className,
|
|
1049
|
+
style: {
|
|
1050
|
+
position: "relative",
|
|
1051
|
+
overflow: "hidden",
|
|
1052
|
+
["--scroll-area-corner-width"]: `${cornerWidth}px`,
|
|
1053
|
+
["--scroll-area-corner-height"]: `${cornerHeight}px`,
|
|
1054
|
+
...style
|
|
1055
|
+
},
|
|
1056
|
+
...rest,
|
|
1057
|
+
children
|
|
1058
|
+
}
|
|
1059
|
+
)
|
|
1060
|
+
}
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
function ScrollAreaScrollbar({
|
|
1064
|
+
orientation,
|
|
1065
|
+
className,
|
|
1066
|
+
style,
|
|
1067
|
+
children,
|
|
1068
|
+
...rest
|
|
1069
|
+
}) {
|
|
1070
|
+
const context = useScrollAreaContext("ScrollAreaScrollbar");
|
|
1071
|
+
const trackRef = useRef(null);
|
|
1072
|
+
const thumbRef = useRef(null);
|
|
1073
|
+
const pointerOffsetRef = useRef(0);
|
|
1074
|
+
const [sizes, setSizes] = useState(EMPTY_SIZES);
|
|
1075
|
+
const isVertical = orientation === "vertical";
|
|
1076
|
+
const showThumb = hasScrollAreaThumb(sizes);
|
|
1077
|
+
const updateSizes = useCallback(() => {
|
|
1078
|
+
const viewport = context.viewportRef.current;
|
|
1079
|
+
const track = trackRef.current;
|
|
1080
|
+
if (!viewport || !track) return;
|
|
1081
|
+
const padding = readScrollbarPadding(track);
|
|
1082
|
+
if (isVertical) {
|
|
1083
|
+
setSizes({
|
|
1084
|
+
content: viewport.scrollHeight,
|
|
1085
|
+
viewport: viewport.offsetHeight,
|
|
1086
|
+
scrollbar: {
|
|
1087
|
+
size: track.clientHeight,
|
|
1088
|
+
paddingStart: padding.paddingStart,
|
|
1089
|
+
paddingEnd: padding.paddingEnd
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1092
|
+
context.setCornerWidth(track.offsetWidth);
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
setSizes({
|
|
1096
|
+
content: viewport.scrollWidth,
|
|
1097
|
+
viewport: viewport.offsetWidth,
|
|
1098
|
+
scrollbar: {
|
|
1099
|
+
size: track.clientWidth,
|
|
1100
|
+
paddingStart: padding.paddingLeft,
|
|
1101
|
+
paddingEnd: padding.paddingRight
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
context.setCornerHeight(track.offsetHeight);
|
|
1105
|
+
}, [context, isVertical]);
|
|
1106
|
+
const updateThumbPosition = useCallback(() => {
|
|
1107
|
+
const viewport = context.viewportRef.current;
|
|
1108
|
+
const thumb = thumbRef.current;
|
|
1109
|
+
if (!viewport || !thumb || !showThumb) return;
|
|
1110
|
+
const scrollPos = isVertical ? viewport.scrollTop : viewport.scrollLeft;
|
|
1111
|
+
const offset = getThumbOffsetFromScroll(scrollPos, sizes);
|
|
1112
|
+
thumb.style.transform = isVertical ? `translate3d(0, ${offset}px, 0)` : `translate3d(${offset}px, 0, 0)`;
|
|
1113
|
+
}, [context.viewportRef, isVertical, showThumb, sizes]);
|
|
1114
|
+
useEffect(() => {
|
|
1115
|
+
const viewport = context.viewportRef.current;
|
|
1116
|
+
const track = trackRef.current;
|
|
1117
|
+
if (!viewport || !track) return;
|
|
1118
|
+
const runUpdate = () => {
|
|
1119
|
+
requestAnimationFrame(updateSizes);
|
|
1120
|
+
};
|
|
1121
|
+
runUpdate();
|
|
1122
|
+
const resizeObserver = new ResizeObserver(runUpdate);
|
|
1123
|
+
resizeObserver.observe(viewport);
|
|
1124
|
+
resizeObserver.observe(track);
|
|
1125
|
+
const contentRoot = viewport.firstElementChild;
|
|
1126
|
+
if (contentRoot) {
|
|
1127
|
+
resizeObserver.observe(contentRoot);
|
|
1128
|
+
}
|
|
1129
|
+
const mutationObserver = new MutationObserver(runUpdate);
|
|
1130
|
+
mutationObserver.observe(viewport, {
|
|
1131
|
+
childList: true,
|
|
1132
|
+
subtree: true,
|
|
1133
|
+
attributes: true
|
|
1134
|
+
});
|
|
1135
|
+
return () => {
|
|
1136
|
+
resizeObserver.disconnect();
|
|
1137
|
+
mutationObserver.disconnect();
|
|
1138
|
+
};
|
|
1139
|
+
}, [context.viewportRef, updateSizes]);
|
|
1140
|
+
useEffect(() => {
|
|
1141
|
+
updateThumbPosition();
|
|
1142
|
+
}, [sizes, updateThumbPosition]);
|
|
1143
|
+
useEffect(() => {
|
|
1144
|
+
const viewport = context.viewportRef.current;
|
|
1145
|
+
if (!viewport) return;
|
|
1146
|
+
let frame = 0;
|
|
1147
|
+
const handleScroll = () => {
|
|
1148
|
+
if (frame) cancelAnimationFrame(frame);
|
|
1149
|
+
frame = requestAnimationFrame(() => {
|
|
1150
|
+
updateThumbPosition();
|
|
1151
|
+
frame = 0;
|
|
1152
|
+
});
|
|
1153
|
+
};
|
|
1154
|
+
viewport.addEventListener("scroll", handleScroll, { passive: true });
|
|
1155
|
+
return () => {
|
|
1156
|
+
viewport.removeEventListener("scroll", handleScroll);
|
|
1157
|
+
if (frame) cancelAnimationFrame(frame);
|
|
1158
|
+
};
|
|
1159
|
+
}, [context.viewportRef, updateThumbPosition]);
|
|
1160
|
+
const getPointerOnTrack = useCallback(
|
|
1161
|
+
(clientX, clientY) => {
|
|
1162
|
+
const track = trackRef.current;
|
|
1163
|
+
if (!track) return 0;
|
|
1164
|
+
const rect = track.getBoundingClientRect();
|
|
1165
|
+
return isVertical ? clientY - rect.top : clientX - rect.left;
|
|
1166
|
+
},
|
|
1167
|
+
[isVertical]
|
|
1168
|
+
);
|
|
1169
|
+
const setScrollFromPointer = useCallback(
|
|
1170
|
+
(pointerPos) => {
|
|
1171
|
+
const viewport = context.viewportRef.current;
|
|
1172
|
+
if (!viewport) return;
|
|
1173
|
+
const scrollPos = getScrollPositionFromPointer(
|
|
1174
|
+
pointerPos,
|
|
1175
|
+
pointerOffsetRef.current,
|
|
1176
|
+
sizes
|
|
1177
|
+
);
|
|
1178
|
+
if (isVertical) {
|
|
1179
|
+
viewport.scrollTop = scrollPos;
|
|
1180
|
+
} else {
|
|
1181
|
+
viewport.scrollLeft = scrollPos;
|
|
1182
|
+
}
|
|
1183
|
+
},
|
|
1184
|
+
[context.viewportRef, isVertical, sizes]
|
|
1185
|
+
);
|
|
1186
|
+
const handleTrackPointerDown = (event) => {
|
|
1187
|
+
if (event.button !== 0) return;
|
|
1188
|
+
const track = trackRef.current;
|
|
1189
|
+
if (!track) return;
|
|
1190
|
+
if (event.target === track) {
|
|
1191
|
+
pointerOffsetRef.current = 0;
|
|
1192
|
+
}
|
|
1193
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
1194
|
+
setScrollFromPointer(getPointerOnTrack(event.clientX, event.clientY));
|
|
1195
|
+
};
|
|
1196
|
+
const handleTrackPointerMove = (event) => {
|
|
1197
|
+
if (!event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
setScrollFromPointer(getPointerOnTrack(event.clientX, event.clientY));
|
|
1201
|
+
};
|
|
1202
|
+
const handleTrackPointerUp = (event) => {
|
|
1203
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
1204
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1205
|
+
}
|
|
1206
|
+
pointerOffsetRef.current = 0;
|
|
1207
|
+
};
|
|
1208
|
+
const thumbProps = children.props;
|
|
1209
|
+
const thumbClassName = thumbProps.className;
|
|
1210
|
+
const thumbStyleProp = thumbProps.style;
|
|
1211
|
+
const {
|
|
1212
|
+
className: _ignoredClassName,
|
|
1213
|
+
style: _ignoredStyle,
|
|
1214
|
+
...thumbRest
|
|
1215
|
+
} = thumbProps;
|
|
1216
|
+
const thumbSizePx = getThumbSize(sizes);
|
|
1217
|
+
const thumbDimensionStyle = isVertical ? { height: thumbSizePx, width: "100%" } : { width: thumbSizePx, height: "100%" };
|
|
1218
|
+
const trackStyle = isVertical ? {
|
|
1219
|
+
position: "absolute",
|
|
1220
|
+
top: 0,
|
|
1221
|
+
right: 0,
|
|
1222
|
+
bottom: "var(--scroll-area-corner-height)"
|
|
1223
|
+
} : {
|
|
1224
|
+
position: "absolute",
|
|
1225
|
+
bottom: 0,
|
|
1226
|
+
left: 0,
|
|
1227
|
+
right: "var(--scroll-area-corner-width)"
|
|
1228
|
+
};
|
|
1229
|
+
return /* @__PURE__ */ jsx(
|
|
1230
|
+
"div",
|
|
1231
|
+
{
|
|
1232
|
+
ref: trackRef,
|
|
1233
|
+
"data-orientation": orientation,
|
|
1234
|
+
className,
|
|
1235
|
+
style: { ...trackStyle, ...style },
|
|
1236
|
+
onPointerDown: handleTrackPointerDown,
|
|
1237
|
+
onPointerMove: handleTrackPointerMove,
|
|
1238
|
+
onPointerUp: handleTrackPointerUp,
|
|
1239
|
+
onPointerCancel: handleTrackPointerUp,
|
|
1240
|
+
...rest,
|
|
1241
|
+
children: showThumb ? /* @__PURE__ */ jsx(
|
|
1242
|
+
"div",
|
|
1243
|
+
{
|
|
1244
|
+
ref: thumbRef,
|
|
1245
|
+
"data-state": "visible",
|
|
1246
|
+
className: thumbClassName,
|
|
1247
|
+
style: {
|
|
1248
|
+
flex: "none",
|
|
1249
|
+
...thumbDimensionStyle,
|
|
1250
|
+
...thumbStyleProp
|
|
1251
|
+
},
|
|
1252
|
+
onPointerDownCapture: (event) => {
|
|
1253
|
+
thumbProps.onPointerDownCapture?.(event);
|
|
1254
|
+
const thumbRect = event.currentTarget.getBoundingClientRect();
|
|
1255
|
+
pointerOffsetRef.current = isVertical ? event.clientY - thumbRect.top : event.clientX - thumbRect.left;
|
|
1256
|
+
},
|
|
1257
|
+
...thumbRest
|
|
1258
|
+
}
|
|
1259
|
+
) : null
|
|
1260
|
+
}
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
function ScrollAreaThumb({ className, style, ...rest }) {
|
|
1264
|
+
return /* @__PURE__ */ jsx(
|
|
1265
|
+
"div",
|
|
1266
|
+
{
|
|
1267
|
+
"data-state": "hidden",
|
|
1268
|
+
className,
|
|
1269
|
+
style,
|
|
1270
|
+
...rest
|
|
1271
|
+
}
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1274
|
+
function ScrollAreaCorner({ className, style, ...rest }) {
|
|
1275
|
+
const { cornerWidth, cornerHeight } = useScrollAreaContext("ScrollAreaCorner");
|
|
1276
|
+
if (!cornerWidth || !cornerHeight) {
|
|
1277
|
+
return null;
|
|
1278
|
+
}
|
|
1279
|
+
return /* @__PURE__ */ jsx(
|
|
1280
|
+
"div",
|
|
1281
|
+
{
|
|
1282
|
+
className,
|
|
1283
|
+
style: {
|
|
1284
|
+
position: "absolute",
|
|
1285
|
+
right: 0,
|
|
1286
|
+
bottom: 0,
|
|
1287
|
+
width: cornerWidth,
|
|
1288
|
+
height: cornerHeight,
|
|
1289
|
+
...style
|
|
1290
|
+
},
|
|
1291
|
+
...rest
|
|
1292
|
+
}
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
var EMPTY_SIZES, ScrollAreaContext, ScrollAreaViewport;
|
|
1296
|
+
var init_scroll_area = __esm({
|
|
1297
|
+
"src/features/file-viewer/primitives/scroll-area.tsx"() {
|
|
1298
|
+
init_merge_slot_props();
|
|
1299
|
+
init_scroll_area_math();
|
|
1300
|
+
EMPTY_SIZES = {
|
|
1301
|
+
content: 0,
|
|
1302
|
+
viewport: 0,
|
|
1303
|
+
scrollbar: { size: 0, paddingStart: 0, paddingEnd: 0 }
|
|
1304
|
+
};
|
|
1305
|
+
ScrollAreaContext = createContext(null);
|
|
1306
|
+
ScrollAreaViewport = forwardRef(
|
|
1307
|
+
({ className, children, onScroll, ...rest }, forwardedRef) => {
|
|
1308
|
+
const { viewportRef } = useScrollAreaContext("ScrollAreaViewport");
|
|
1309
|
+
return /* @__PURE__ */ jsx(
|
|
1310
|
+
"div",
|
|
1311
|
+
{
|
|
1312
|
+
ref: mergeRefs2(forwardedRef, viewportRef),
|
|
1313
|
+
onScroll,
|
|
1314
|
+
className: mergeClassNames(
|
|
1315
|
+
"size-full overflow-x-scroll overflow-y-scroll pdf-scroll-viewport",
|
|
1316
|
+
className
|
|
1317
|
+
),
|
|
1318
|
+
...rest,
|
|
1319
|
+
children: /* @__PURE__ */ jsx(
|
|
1320
|
+
"div",
|
|
1321
|
+
{
|
|
1322
|
+
className: "scroll-area-viewport-inner",
|
|
1323
|
+
style: { minWidth: "100%", display: "table" },
|
|
1324
|
+
children
|
|
1325
|
+
}
|
|
1326
|
+
)
|
|
1327
|
+
}
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
);
|
|
1331
|
+
ScrollAreaViewport.displayName = "ScrollAreaViewport";
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
// src/features/file-viewer/pdf-viewer.css
|
|
1336
|
+
var init_pdf_viewer = __esm({
|
|
1337
|
+
"src/features/file-viewer/pdf-viewer.css"() {
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
function ViewerToolbarDivider({
|
|
1341
|
+
className = "",
|
|
1342
|
+
style,
|
|
1343
|
+
classNames,
|
|
1344
|
+
styles
|
|
1345
|
+
}) {
|
|
1346
|
+
const globalToolbar = getFileViewerDefaults().toolbar;
|
|
1347
|
+
return /* @__PURE__ */ jsx(
|
|
1348
|
+
"div",
|
|
1349
|
+
{
|
|
1350
|
+
className: mergeClassNames(
|
|
1351
|
+
VIEWER_TOOLBAR_DIVIDER_DEFAULT,
|
|
1352
|
+
globalToolbar?.classNames?.divider,
|
|
1353
|
+
classNames?.divider,
|
|
1354
|
+
className
|
|
1355
|
+
),
|
|
1356
|
+
style: mergeStyles(globalToolbar?.styles?.divider, styles?.divider, style),
|
|
1357
|
+
"aria-hidden": true
|
|
1358
|
+
}
|
|
1359
|
+
);
|
|
1360
|
+
}
|
|
1361
|
+
function ViewerToolbarIconButton({
|
|
1362
|
+
className = "",
|
|
1363
|
+
style,
|
|
1364
|
+
classNames,
|
|
1365
|
+
styles,
|
|
1366
|
+
...rest
|
|
1367
|
+
}) {
|
|
1368
|
+
const globalToolbar = getFileViewerDefaults().toolbar;
|
|
1369
|
+
return /* @__PURE__ */ jsx(
|
|
1370
|
+
"button",
|
|
1371
|
+
{
|
|
1372
|
+
type: "button",
|
|
1373
|
+
className: mergeClassNames(
|
|
1374
|
+
VIEWER_TOOLBAR_ICON_BUTTON_DEFAULT,
|
|
1375
|
+
globalToolbar?.classNames?.iconButton,
|
|
1376
|
+
classNames?.iconButton,
|
|
1377
|
+
className
|
|
1378
|
+
),
|
|
1379
|
+
style: mergeStyles(
|
|
1380
|
+
globalToolbar?.styles?.iconButton,
|
|
1381
|
+
styles?.iconButton,
|
|
1382
|
+
style
|
|
1383
|
+
),
|
|
1384
|
+
...rest
|
|
1385
|
+
}
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
var VIEWER_TOOLBAR_DEFAULT, VIEWER_TOOLBAR_DIVIDER_DEFAULT, VIEWER_TOOLBAR_ICON_BUTTON_DEFAULT, ViewerFloatingToolbar;
|
|
1389
|
+
var init_ViewerToolbar = __esm({
|
|
1390
|
+
"src/features/file-viewer/components/ViewerToolbar.tsx"() {
|
|
1391
|
+
init_config();
|
|
1392
|
+
init_merge_slot_props();
|
|
1393
|
+
VIEWER_TOOLBAR_DEFAULT = "absolute bottom-4 left-1/2 z-10 flex h-[3.25rem] -translate-x-1/2 items-center gap-2 rounded-full border border-neutral-700/50 bg-neutral-900/60 px-4 text-white/90 shadow-lg backdrop-blur-sm transition-opacity duration-300";
|
|
1394
|
+
VIEWER_TOOLBAR_DIVIDER_DEFAULT = "mx-1 h-full w-px bg-white/20";
|
|
1395
|
+
VIEWER_TOOLBAR_ICON_BUTTON_DEFAULT = "cursor-pointer rounded-full p-2 text-white/70 transition-colors hover:bg-white/10 hover:text-white disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-white/40";
|
|
1396
|
+
ViewerFloatingToolbar = forwardRef(({ children, className = "", style, classNames, styles }, ref) => {
|
|
1397
|
+
const globalToolbar = getFileViewerDefaults().toolbar;
|
|
1398
|
+
return /* @__PURE__ */ jsx(
|
|
1399
|
+
"div",
|
|
1400
|
+
{
|
|
1401
|
+
ref,
|
|
1402
|
+
className: mergeClassNames(
|
|
1403
|
+
VIEWER_TOOLBAR_DEFAULT,
|
|
1404
|
+
globalToolbar?.classNames?.toolbar,
|
|
1405
|
+
classNames?.toolbar,
|
|
1406
|
+
className
|
|
1407
|
+
),
|
|
1408
|
+
style: mergeStyles(globalToolbar?.styles?.toolbar, styles?.toolbar, style),
|
|
1409
|
+
children
|
|
1410
|
+
}
|
|
1411
|
+
);
|
|
1412
|
+
});
|
|
1413
|
+
ViewerFloatingToolbar.displayName = "ViewerFloatingToolbar";
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
function getDistanceToElement(x, y, element) {
|
|
1417
|
+
const rect = element.getBoundingClientRect();
|
|
1418
|
+
const dx = Math.max(rect.left - x, 0, x - rect.right);
|
|
1419
|
+
const dy = Math.max(rect.top - y, 0, y - rect.bottom);
|
|
1420
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1421
|
+
}
|
|
1422
|
+
function useAutoHide(targetRef, containerRef, options = {}) {
|
|
1423
|
+
const { proximityThreshold = 160, timeout = 3e3, activityDeps = [] } = options;
|
|
1424
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
1425
|
+
const timerRef = useRef(null);
|
|
1426
|
+
const isNearRef = useRef(false);
|
|
1427
|
+
const startTimer = () => {
|
|
1428
|
+
if (timerRef.current !== null) {
|
|
1429
|
+
window.clearTimeout(timerRef.current);
|
|
1430
|
+
}
|
|
1431
|
+
timerRef.current = window.setTimeout(() => {
|
|
1432
|
+
setIsVisible(false);
|
|
1433
|
+
timerRef.current = null;
|
|
1434
|
+
}, timeout);
|
|
1435
|
+
};
|
|
1436
|
+
useEffect(() => {
|
|
1437
|
+
setIsVisible(true);
|
|
1438
|
+
if (!isNearRef.current) {
|
|
1439
|
+
startTimer();
|
|
1440
|
+
}
|
|
1441
|
+
return () => {
|
|
1442
|
+
if (timerRef.current !== null) {
|
|
1443
|
+
window.clearTimeout(timerRef.current);
|
|
1444
|
+
timerRef.current = null;
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
}, activityDeps);
|
|
1448
|
+
useEffect(() => {
|
|
1449
|
+
const container = containerRef.current;
|
|
1450
|
+
if (!container) return;
|
|
1451
|
+
const handleMouseMove = (e) => {
|
|
1452
|
+
if (!targetRef.current) return;
|
|
1453
|
+
const distance = getDistanceToElement(e.clientX, e.clientY, targetRef.current);
|
|
1454
|
+
const isNear = distance <= proximityThreshold;
|
|
1455
|
+
if (isNear) {
|
|
1456
|
+
setIsVisible(true);
|
|
1457
|
+
if (timerRef.current !== null) {
|
|
1458
|
+
window.clearTimeout(timerRef.current);
|
|
1459
|
+
timerRef.current = null;
|
|
1460
|
+
}
|
|
1461
|
+
} else {
|
|
1462
|
+
if (isNearRef.current) {
|
|
1463
|
+
startTimer();
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
isNearRef.current = isNear;
|
|
1467
|
+
};
|
|
1468
|
+
const handleMouseLeave = () => {
|
|
1469
|
+
isNearRef.current = false;
|
|
1470
|
+
startTimer();
|
|
1471
|
+
};
|
|
1472
|
+
container.addEventListener("mousemove", handleMouseMove);
|
|
1473
|
+
container.addEventListener("mouseleave", handleMouseLeave);
|
|
1474
|
+
return () => {
|
|
1475
|
+
container.removeEventListener("mousemove", handleMouseMove);
|
|
1476
|
+
container.removeEventListener("mouseleave", handleMouseLeave);
|
|
1477
|
+
};
|
|
1478
|
+
}, [proximityThreshold, timeout, targetRef, containerRef]);
|
|
1479
|
+
return isVisible;
|
|
1480
|
+
}
|
|
1481
|
+
var init_useAutoHide = __esm({
|
|
1482
|
+
"src/features/file-viewer/hooks/useAutoHide.ts"() {
|
|
1483
|
+
}
|
|
1484
|
+
});
|
|
1485
|
+
|
|
1486
|
+
// src/features/file-viewer/PdfViewer.tsx
|
|
1487
|
+
var PdfViewer_exports = {};
|
|
1488
|
+
__export(PdfViewer_exports, {
|
|
1489
|
+
default: () => PdfViewer
|
|
1490
|
+
});
|
|
1491
|
+
function PdfViewer(props) {
|
|
1492
|
+
const { url, language: languageProp, ...instanceProps } = props;
|
|
1493
|
+
const resolved = resolvePdfViewerProps(instanceProps);
|
|
1494
|
+
const viewMode = resolved.viewMode ?? "continuous";
|
|
1495
|
+
const debounceDelay = resolved.debounceDelay ?? 300;
|
|
1496
|
+
const zoomDebounceDelay = resolved.zoomDebounceDelay ?? 500;
|
|
1497
|
+
const renderTextLayer = resolved.renderTextLayer ?? true;
|
|
1498
|
+
const renderAnnotationLayer = resolved.renderAnnotationLayer ?? true;
|
|
1499
|
+
const renderLoading = resolved.renderLoading ?? null;
|
|
1500
|
+
const preloadAhead = resolved.preloadAhead ?? 1;
|
|
1501
|
+
const onLoadSuccess = resolved.onLoadSuccess;
|
|
1502
|
+
const onLoadError = resolved.onLoadError;
|
|
1503
|
+
const onPageChange = resolved.onPageChange;
|
|
1504
|
+
const defaultPage = resolved.defaultPage ?? 1;
|
|
1505
|
+
const renderPagination = resolved.renderPagination;
|
|
1506
|
+
const paginationClassName = resolved.paginationClassName;
|
|
1507
|
+
const className = resolved.className;
|
|
1508
|
+
const pageClassName = resolved.pageClassName;
|
|
1509
|
+
const classNames = resolved.classNames;
|
|
1510
|
+
const styles = resolved.styles;
|
|
1511
|
+
const language = resolveOption(
|
|
1512
|
+
languageProp,
|
|
1513
|
+
getFileViewerDefaults().language,
|
|
1514
|
+
"english"
|
|
1515
|
+
);
|
|
1516
|
+
const pdfT = getFileViewerTranslations(language).pdfViewer;
|
|
1517
|
+
const autoHideDefaults = getFileViewerDefaults().autoHide;
|
|
1518
|
+
const pdfClassName = (key, builtIn, extra) => mergeClassNames(
|
|
1519
|
+
builtIn,
|
|
1520
|
+
classNames?.[key],
|
|
1521
|
+
key === "root" ? className : void 0,
|
|
1522
|
+
key === "page" ? pageClassName : void 0,
|
|
1523
|
+
key === "pagination" ? paginationClassName : void 0,
|
|
1524
|
+
extra
|
|
1525
|
+
);
|
|
1526
|
+
const pdfStyle = (key) => styles?.[key];
|
|
1527
|
+
const [numPages, setNumPages] = useState(0);
|
|
1528
|
+
const [pageNumber, setPageNumber] = useState(defaultPage);
|
|
1529
|
+
const [visibleRange, setVisibleRange] = useState({ start: defaultPage, end: defaultPage });
|
|
1530
|
+
const [inputPage, setInputPage] = useState(String(defaultPage));
|
|
1531
|
+
const containerRef = useRef(null);
|
|
1532
|
+
const toolbarRef = useRef(null);
|
|
1533
|
+
const pageRefs = useRef(/* @__PURE__ */ new Map());
|
|
1534
|
+
const [instantSize, setInstantSize] = useState({ width: 0, height: 0 });
|
|
1535
|
+
const [renderedSize, setRenderedSize] = useState({ width: 0, height: 0 });
|
|
1536
|
+
const [pageOriginalSize, setPageOriginalSize] = useState({
|
|
1537
|
+
width: 0,
|
|
1538
|
+
height: 0
|
|
1539
|
+
});
|
|
1540
|
+
const renderedHeights = useRef(/* @__PURE__ */ new Map());
|
|
1541
|
+
const [instantZoom, setInstantZoom] = useState(1);
|
|
1542
|
+
const [renderedZoom, setRenderedZoom] = useState(1);
|
|
1543
|
+
const isToolbarVisible = useAutoHide(toolbarRef, containerRef, {
|
|
1544
|
+
proximityThreshold: autoHideDefaults?.proximityThreshold,
|
|
1545
|
+
timeout: autoHideDefaults?.timeout,
|
|
1546
|
+
activityDeps: [pageNumber, instantZoom]
|
|
1547
|
+
});
|
|
1548
|
+
const [hasZoomed, setHasZoomed] = useState(false);
|
|
1549
|
+
useEffect(() => {
|
|
1550
|
+
setInstantZoom(1);
|
|
1551
|
+
setRenderedZoom(1);
|
|
1552
|
+
setHasZoomed(false);
|
|
1553
|
+
renderedHeights.current.clear();
|
|
1554
|
+
}, [url, viewMode]);
|
|
1555
|
+
useEffect(() => {
|
|
1556
|
+
if (instantZoom === renderedZoom) return;
|
|
1557
|
+
const timerId = window.setTimeout(() => {
|
|
1558
|
+
setRenderedZoom(instantZoom);
|
|
1559
|
+
renderedHeights.current.clear();
|
|
1560
|
+
}, zoomDebounceDelay);
|
|
1561
|
+
return () => window.clearTimeout(timerId);
|
|
1562
|
+
}, [instantZoom, renderedZoom, zoomDebounceDelay]);
|
|
1563
|
+
const pendingInputPageRef = useRef(null);
|
|
1564
|
+
const pendingInputPageTimerRef = useRef(null);
|
|
1565
|
+
useEffect(() => {
|
|
1566
|
+
const pending = pendingInputPageRef.current;
|
|
1567
|
+
if (pending !== null) {
|
|
1568
|
+
if (pageNumber === pending) {
|
|
1569
|
+
pendingInputPageRef.current = null;
|
|
1570
|
+
if (pendingInputPageTimerRef.current !== null) {
|
|
1571
|
+
window.clearTimeout(pendingInputPageTimerRef.current);
|
|
1572
|
+
pendingInputPageTimerRef.current = null;
|
|
1573
|
+
}
|
|
1574
|
+
setInputPage(String(pageNumber));
|
|
1575
|
+
}
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
setInputPage(String(pageNumber));
|
|
1579
|
+
}, [pageNumber]);
|
|
1580
|
+
useEffect(() => {
|
|
1581
|
+
const updateSize = () => {
|
|
1582
|
+
if (containerRef.current) {
|
|
1583
|
+
const newSize = {
|
|
1584
|
+
width: Math.trunc(containerRef.current.clientWidth),
|
|
1585
|
+
height: Math.trunc(containerRef.current.clientHeight)
|
|
1586
|
+
};
|
|
1587
|
+
setInstantSize((prev) => {
|
|
1588
|
+
if (prev.width === newSize.width && prev.height === newSize.height) return prev;
|
|
1589
|
+
return newSize;
|
|
1590
|
+
});
|
|
1591
|
+
setRenderedSize(
|
|
1592
|
+
(prev) => prev.width === 0 && newSize.width > 0 ? newSize : prev
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
};
|
|
1596
|
+
const observer = new ResizeObserver(() => updateSize());
|
|
1597
|
+
if (containerRef.current) observer.observe(containerRef.current);
|
|
1598
|
+
updateSize();
|
|
1599
|
+
return () => observer.disconnect();
|
|
1600
|
+
}, []);
|
|
1601
|
+
useEffect(() => {
|
|
1602
|
+
if (instantSize.width === 0) return;
|
|
1603
|
+
const timerId = window.setTimeout(() => {
|
|
1604
|
+
setRenderedSize(instantSize);
|
|
1605
|
+
}, debounceDelay);
|
|
1606
|
+
return () => window.clearTimeout(timerId);
|
|
1607
|
+
}, [instantSize, debounceDelay]);
|
|
1608
|
+
const calculateDimensions = useCallback(
|
|
1609
|
+
(container) => {
|
|
1610
|
+
if (!container.width || !container.height) {
|
|
1611
|
+
return {
|
|
1612
|
+
width: container.width ? Math.trunc(container.width) : void 0,
|
|
1613
|
+
height: container.height ? Math.trunc(container.height) : void 0
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
let remToPx = 16;
|
|
1617
|
+
if (typeof document !== "undefined") {
|
|
1618
|
+
remToPx = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
1619
|
+
}
|
|
1620
|
+
const width = Math.trunc(Math.min(container.width, remToPx * 50));
|
|
1621
|
+
if (!pageOriginalSize.width || !pageOriginalSize.height) {
|
|
1622
|
+
return {
|
|
1623
|
+
width,
|
|
1624
|
+
height: Math.trunc(width * 1.414)
|
|
1625
|
+
// Approximate A4 ratio
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
const pageRatio = pageOriginalSize.width / pageOriginalSize.height;
|
|
1629
|
+
return { width, height: Math.trunc(width / pageRatio) };
|
|
1630
|
+
},
|
|
1631
|
+
[pageOriginalSize]
|
|
1632
|
+
);
|
|
1633
|
+
const instantDimensions = useMemo(
|
|
1634
|
+
() => calculateDimensions(instantSize),
|
|
1635
|
+
[calculateDimensions, instantSize]
|
|
1636
|
+
);
|
|
1637
|
+
const renderedDimensions = useMemo(
|
|
1638
|
+
() => calculateDimensions(renderedSize),
|
|
1639
|
+
[calculateDimensions, renderedSize]
|
|
1640
|
+
);
|
|
1641
|
+
const zoomedRenderedDimensions = useMemo(() => {
|
|
1642
|
+
return {
|
|
1643
|
+
width: renderedDimensions.width ? Math.trunc(renderedDimensions.width * renderedZoom) : void 0,
|
|
1644
|
+
height: renderedDimensions.height ? Math.trunc(renderedDimensions.height * renderedZoom) : void 0
|
|
1645
|
+
};
|
|
1646
|
+
}, [renderedDimensions, renderedZoom]);
|
|
1647
|
+
const zoomedInstantDimensions = useMemo(() => {
|
|
1648
|
+
return {
|
|
1649
|
+
width: instantDimensions.width ? Math.trunc(instantDimensions.width * instantZoom) : void 0,
|
|
1650
|
+
height: instantDimensions.height ? Math.trunc(instantDimensions.height * instantZoom) : void 0
|
|
1651
|
+
};
|
|
1652
|
+
}, [instantDimensions, instantZoom]);
|
|
1653
|
+
const layoutScale = useMemo(() => {
|
|
1654
|
+
const renderedWidth = zoomedRenderedDimensions.width;
|
|
1655
|
+
const renderedHeight = zoomedRenderedDimensions.height;
|
|
1656
|
+
const instantWidth = zoomedInstantDimensions.width;
|
|
1657
|
+
const instantHeight = zoomedInstantDimensions.height;
|
|
1658
|
+
if (!renderedWidth || !instantWidth || !instantHeight) {
|
|
1659
|
+
return 1;
|
|
1660
|
+
}
|
|
1661
|
+
if (!renderedHeight) {
|
|
1662
|
+
return Number((instantWidth / renderedWidth).toFixed(4));
|
|
1663
|
+
}
|
|
1664
|
+
return Number(
|
|
1665
|
+
Math.min(
|
|
1666
|
+
instantWidth / renderedWidth,
|
|
1667
|
+
instantHeight / renderedHeight
|
|
1668
|
+
).toFixed(4)
|
|
1669
|
+
);
|
|
1670
|
+
}, [zoomedInstantDimensions, zoomedRenderedDimensions]);
|
|
1671
|
+
const isLayoutSyncing = useMemo(() => {
|
|
1672
|
+
if (instantZoom !== renderedZoom) return true;
|
|
1673
|
+
if (instantSize.width !== renderedSize.width || instantSize.height !== renderedSize.height) {
|
|
1674
|
+
return true;
|
|
1675
|
+
}
|
|
1676
|
+
return Math.abs(layoutScale - 1) > 1e-3;
|
|
1677
|
+
}, [
|
|
1678
|
+
instantZoom,
|
|
1679
|
+
renderedZoom,
|
|
1680
|
+
instantSize,
|
|
1681
|
+
renderedSize,
|
|
1682
|
+
layoutScale
|
|
1683
|
+
]);
|
|
1684
|
+
const handleDocumentLoadSuccess = ({
|
|
1685
|
+
numPages: loadedNumPages
|
|
1686
|
+
}) => {
|
|
1687
|
+
setNumPages(loadedNumPages);
|
|
1688
|
+
onLoadSuccess?.(loadedNumPages);
|
|
1689
|
+
};
|
|
1690
|
+
const handleDocumentLoadError = (error) => {
|
|
1691
|
+
console.error(error);
|
|
1692
|
+
onLoadError?.(error);
|
|
1693
|
+
};
|
|
1694
|
+
const handlePageLoadSuccess = (pageIndex, page) => {
|
|
1695
|
+
if (pageIndex === 1) {
|
|
1696
|
+
setPageOriginalSize({
|
|
1697
|
+
width: Math.trunc(page.width),
|
|
1698
|
+
height: Math.trunc(page.height)
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1701
|
+
renderedHeights.current.set(pageIndex, Math.trunc(page.height));
|
|
1702
|
+
};
|
|
1703
|
+
const setPage = useCallback(
|
|
1704
|
+
(newPage) => {
|
|
1705
|
+
setPageNumber(newPage);
|
|
1706
|
+
onPageChange?.(newPage);
|
|
1707
|
+
},
|
|
1708
|
+
[onPageChange]
|
|
1709
|
+
);
|
|
1710
|
+
const previousPage = useCallback(() => {
|
|
1711
|
+
if (pendingInputPageRef.current !== null) return;
|
|
1712
|
+
const p = Math.max(pageNumber - 1, 1);
|
|
1713
|
+
if (viewMode === "continuous") {
|
|
1714
|
+
setTimeout(() => {
|
|
1715
|
+
pageRefs.current.get(p)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
1716
|
+
}, 10);
|
|
1717
|
+
} else {
|
|
1718
|
+
setPage(p);
|
|
1719
|
+
}
|
|
1720
|
+
}, [pageNumber, viewMode, setPage]);
|
|
1721
|
+
const nextPage = useCallback(() => {
|
|
1722
|
+
if (pendingInputPageRef.current !== null) return;
|
|
1723
|
+
const p = Math.min(pageNumber + 1, numPages || 1);
|
|
1724
|
+
if (viewMode === "continuous") {
|
|
1725
|
+
setTimeout(() => {
|
|
1726
|
+
pageRefs.current.get(p)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
1727
|
+
}, 10);
|
|
1728
|
+
} else {
|
|
1729
|
+
setPage(p);
|
|
1730
|
+
}
|
|
1731
|
+
}, [pageNumber, numPages, viewMode, setPage]);
|
|
1732
|
+
const goToPage = useCallback(
|
|
1733
|
+
(p) => {
|
|
1734
|
+
const validPage = Math.max(1, Math.min(p, numPages || 1));
|
|
1735
|
+
if (viewMode === "continuous") {
|
|
1736
|
+
pendingInputPageRef.current = validPage;
|
|
1737
|
+
setInputPage(String(validPage));
|
|
1738
|
+
if (pendingInputPageTimerRef.current !== null) {
|
|
1739
|
+
window.clearTimeout(pendingInputPageTimerRef.current);
|
|
1740
|
+
}
|
|
1741
|
+
pendingInputPageTimerRef.current = window.setTimeout(() => {
|
|
1742
|
+
pendingInputPageRef.current = null;
|
|
1743
|
+
pendingInputPageTimerRef.current = null;
|
|
1744
|
+
setInputPage(String(pageNumberRef.current));
|
|
1745
|
+
}, 750);
|
|
1746
|
+
setTimeout(() => {
|
|
1747
|
+
pageRefs.current.get(validPage)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
1748
|
+
}, 10);
|
|
1749
|
+
} else {
|
|
1750
|
+
setPage(validPage);
|
|
1751
|
+
}
|
|
1752
|
+
},
|
|
1753
|
+
[numPages, viewMode, setPage]
|
|
1754
|
+
);
|
|
1755
|
+
const pageNumberRef = useRef(pageNumber);
|
|
1756
|
+
useEffect(() => {
|
|
1757
|
+
pageNumberRef.current = pageNumber;
|
|
1758
|
+
}, [pageNumber]);
|
|
1759
|
+
const CONTINUOUS_PAGE_GAP_PX = 16;
|
|
1760
|
+
const isPreservingScrollRef = useRef(false);
|
|
1761
|
+
const updateVisiblePagesFromScroll = useCallback(() => {
|
|
1762
|
+
const container = containerRef.current;
|
|
1763
|
+
if (!container || viewMode !== "continuous" || numPages <= 0 || isPreservingScrollRef.current) {
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
const scrollTop = container.scrollTop;
|
|
1767
|
+
const viewBottom = scrollTop + container.clientHeight;
|
|
1768
|
+
const defaultPageHeight = zoomedRenderedDimensions.height ?? 0;
|
|
1769
|
+
let offset = 0;
|
|
1770
|
+
let minVisible = Number.POSITIVE_INFINITY;
|
|
1771
|
+
let maxVisible = 0;
|
|
1772
|
+
for (let page = 1; page <= numPages; page++) {
|
|
1773
|
+
const renderedPageHeight = renderedHeights.current.get(page) ?? defaultPageHeight;
|
|
1774
|
+
const slotHeight = Math.trunc(renderedPageHeight * layoutScale);
|
|
1775
|
+
const pageTop = offset;
|
|
1776
|
+
const pageBottom = offset + slotHeight;
|
|
1777
|
+
if (pageBottom > scrollTop && pageTop < viewBottom) {
|
|
1778
|
+
minVisible = Math.min(minVisible, page);
|
|
1779
|
+
maxVisible = Math.max(maxVisible, page);
|
|
1780
|
+
}
|
|
1781
|
+
offset = pageBottom + CONTINUOUS_PAGE_GAP_PX;
|
|
1782
|
+
}
|
|
1783
|
+
if (minVisible === Number.POSITIVE_INFINITY) return;
|
|
1784
|
+
setVisibleRange(
|
|
1785
|
+
(prev) => prev.start !== minVisible || prev.end !== maxVisible ? { start: minVisible, end: maxVisible } : prev
|
|
1786
|
+
);
|
|
1787
|
+
}, [
|
|
1788
|
+
viewMode,
|
|
1789
|
+
numPages,
|
|
1790
|
+
layoutScale,
|
|
1791
|
+
zoomedRenderedDimensions.height
|
|
1792
|
+
]);
|
|
1793
|
+
useEffect(() => {
|
|
1794
|
+
if (viewMode !== "continuous" || !numPages || !containerRef.current) return;
|
|
1795
|
+
const container = containerRef.current;
|
|
1796
|
+
const handleScroll = () => {
|
|
1797
|
+
requestAnimationFrame(updateVisiblePagesFromScroll);
|
|
1798
|
+
};
|
|
1799
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
1800
|
+
updateVisiblePagesFromScroll();
|
|
1801
|
+
return () => container.removeEventListener("scroll", handleScroll);
|
|
1802
|
+
}, [numPages, viewMode, updateVisiblePagesFromScroll]);
|
|
1803
|
+
useEffect(() => {
|
|
1804
|
+
if (instantZoom === renderedZoom) {
|
|
1805
|
+
updateVisiblePagesFromScroll();
|
|
1806
|
+
}
|
|
1807
|
+
}, [instantZoom, renderedZoom, updateVisiblePagesFromScroll]);
|
|
1808
|
+
useEffect(() => {
|
|
1809
|
+
if (viewMode !== "continuous" || !numPages || !containerRef.current) return;
|
|
1810
|
+
const ratios = /* @__PURE__ */ new Map();
|
|
1811
|
+
const observer = new IntersectionObserver(
|
|
1812
|
+
(entries) => {
|
|
1813
|
+
for (const entry of entries) {
|
|
1814
|
+
const pStr = entry.target.getAttribute("data-page-number");
|
|
1815
|
+
if (!pStr) continue;
|
|
1816
|
+
const p = parseInt(pStr, 10);
|
|
1817
|
+
if (!Number.isFinite(p)) continue;
|
|
1818
|
+
ratios.set(p, entry.intersectionRatio);
|
|
1819
|
+
}
|
|
1820
|
+
let bestPage = 0;
|
|
1821
|
+
let bestRatio = 0;
|
|
1822
|
+
let minVisible = Infinity;
|
|
1823
|
+
let maxVisible = -Infinity;
|
|
1824
|
+
ratios.forEach((ratio, page) => {
|
|
1825
|
+
if (ratio > 0) {
|
|
1826
|
+
minVisible = Math.min(minVisible, page);
|
|
1827
|
+
maxVisible = Math.max(maxVisible, page);
|
|
1828
|
+
}
|
|
1829
|
+
if (ratio > bestRatio) {
|
|
1830
|
+
bestRatio = ratio;
|
|
1831
|
+
bestPage = page;
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
if (bestPage > 0 && bestRatio > 0 && bestPage !== pageNumberRef.current) {
|
|
1835
|
+
setPage(bestPage);
|
|
1836
|
+
}
|
|
1837
|
+
if (minVisible !== Infinity && maxVisible !== -Infinity) {
|
|
1838
|
+
setVisibleRange((prev) => {
|
|
1839
|
+
if (prev.start !== minVisible || prev.end !== maxVisible) {
|
|
1840
|
+
return { start: minVisible, end: maxVisible };
|
|
1841
|
+
}
|
|
1842
|
+
return prev;
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
},
|
|
1846
|
+
{
|
|
1847
|
+
root: containerRef.current,
|
|
1848
|
+
threshold: [0, 0.1, 0.25, 0.5, 0.75, 1]
|
|
1849
|
+
}
|
|
1850
|
+
);
|
|
1851
|
+
const currentRefs = pageRefs.current;
|
|
1852
|
+
currentRefs.forEach((ref) => {
|
|
1853
|
+
if (ref) observer.observe(ref);
|
|
1854
|
+
});
|
|
1855
|
+
return () => observer.disconnect();
|
|
1856
|
+
}, [numPages, viewMode, setPage]);
|
|
1857
|
+
const scrollRatioRef = useRef({ x: 0, y: 0 });
|
|
1858
|
+
const zoomAnimFrameRef = useRef(null);
|
|
1859
|
+
useEffect(() => {
|
|
1860
|
+
return () => {
|
|
1861
|
+
if (zoomAnimFrameRef.current !== null) {
|
|
1862
|
+
cancelAnimationFrame(zoomAnimFrameRef.current);
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
}, []);
|
|
1866
|
+
const preserveScrollPosition = useCallback(() => {
|
|
1867
|
+
const container = containerRef.current;
|
|
1868
|
+
if (!container) return;
|
|
1869
|
+
isPreservingScrollRef.current = true;
|
|
1870
|
+
const centerY = container.scrollTop + container.clientHeight / 2;
|
|
1871
|
+
const ratioY = container.scrollHeight > 0 ? centerY / container.scrollHeight : 0;
|
|
1872
|
+
const centerX = container.scrollLeft + container.clientWidth / 2;
|
|
1873
|
+
const ratioX = container.scrollWidth > 0 ? centerX / container.scrollWidth : 0;
|
|
1874
|
+
scrollRatioRef.current = { x: ratioX, y: ratioY };
|
|
1875
|
+
if (zoomAnimFrameRef.current !== null) {
|
|
1876
|
+
cancelAnimationFrame(zoomAnimFrameRef.current);
|
|
1877
|
+
}
|
|
1878
|
+
const startTime = performance.now();
|
|
1879
|
+
const duration = 250;
|
|
1880
|
+
const step = (time) => {
|
|
1881
|
+
const currentContainer = containerRef.current;
|
|
1882
|
+
if (!currentContainer) return;
|
|
1883
|
+
const newCenterY = currentContainer.scrollHeight * scrollRatioRef.current.y;
|
|
1884
|
+
const newCenterX = currentContainer.scrollWidth * scrollRatioRef.current.x;
|
|
1885
|
+
currentContainer.scrollTop = newCenterY - currentContainer.clientHeight / 2;
|
|
1886
|
+
currentContainer.scrollLeft = newCenterX - currentContainer.clientWidth / 2;
|
|
1887
|
+
if (time - startTime < duration) {
|
|
1888
|
+
zoomAnimFrameRef.current = requestAnimationFrame(step);
|
|
1889
|
+
} else {
|
|
1890
|
+
zoomAnimFrameRef.current = null;
|
|
1891
|
+
isPreservingScrollRef.current = false;
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
zoomAnimFrameRef.current = requestAnimationFrame(step);
|
|
1895
|
+
}, []);
|
|
1896
|
+
const handleZoomIn = useCallback(() => {
|
|
1897
|
+
setHasZoomed(true);
|
|
1898
|
+
preserveScrollPosition();
|
|
1899
|
+
setInstantZoom((prev) => Math.min(prev * 1.3, 4));
|
|
1900
|
+
}, [preserveScrollPosition]);
|
|
1901
|
+
const handleZoomOut = useCallback(() => {
|
|
1902
|
+
setHasZoomed(true);
|
|
1903
|
+
preserveScrollPosition();
|
|
1904
|
+
setInstantZoom((prev) => Math.max(prev / 1.3, 0.5));
|
|
1905
|
+
}, [preserveScrollPosition]);
|
|
1906
|
+
const handleZoomReset = useCallback(() => {
|
|
1907
|
+
setHasZoomed(true);
|
|
1908
|
+
preserveScrollPosition();
|
|
1909
|
+
setInstantZoom(1);
|
|
1910
|
+
}, [preserveScrollPosition]);
|
|
1911
|
+
const zoomOutDisabled = instantZoom <= 0.501;
|
|
1912
|
+
const zoomInDisabled = instantZoom >= 3.99;
|
|
1913
|
+
const fitDisabled = Math.abs(instantZoom - 1) < 0.01;
|
|
1914
|
+
const renderPaginationElement = () => {
|
|
1915
|
+
if (renderPagination === null || numPages <= 1) return null;
|
|
1916
|
+
const props2 = {
|
|
1917
|
+
pageNumber,
|
|
1918
|
+
numPages,
|
|
1919
|
+
previousPage,
|
|
1920
|
+
nextPage,
|
|
1921
|
+
goToPage,
|
|
1922
|
+
isFirstPage: pageNumber <= 1,
|
|
1923
|
+
isLastPage: pageNumber >= numPages,
|
|
1924
|
+
viewMode
|
|
1925
|
+
};
|
|
1926
|
+
if (renderPagination) {
|
|
1927
|
+
return renderPagination(props2);
|
|
1928
|
+
}
|
|
1929
|
+
const paginationBody = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1930
|
+
/* @__PURE__ */ jsx("div", { className: "bg-black/20 rounded px-1 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
1931
|
+
"input",
|
|
1932
|
+
{
|
|
1933
|
+
type: "text",
|
|
1934
|
+
inputMode: "numeric",
|
|
1935
|
+
value: inputPage,
|
|
1936
|
+
onChange: (event) => setInputPage(event.target.value),
|
|
1937
|
+
onKeyDown: (event) => {
|
|
1938
|
+
if (event.key === "Enter") {
|
|
1939
|
+
const p = parseInt(inputPage, 10);
|
|
1940
|
+
if (!isNaN(p)) goToPage(p);
|
|
1941
|
+
} else if (event.key === "ArrowUp") {
|
|
1942
|
+
event.preventDefault();
|
|
1943
|
+
const p = parseInt(inputPage, 10);
|
|
1944
|
+
if (!isNaN(p)) {
|
|
1945
|
+
setInputPage(String(Math.min(p + 1, numPages)));
|
|
1946
|
+
}
|
|
1947
|
+
} else if (event.key === "ArrowDown") {
|
|
1948
|
+
event.preventDefault();
|
|
1949
|
+
const p = parseInt(inputPage, 10);
|
|
1950
|
+
if (!isNaN(p)) {
|
|
1951
|
+
setInputPage(String(Math.max(p - 1, 1)));
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
},
|
|
1955
|
+
onBlur: () => {
|
|
1956
|
+
const p = parseInt(inputPage, 10);
|
|
1957
|
+
if (!isNaN(p)) goToPage(p);
|
|
1958
|
+
else setInputPage(String(pageNumber));
|
|
1959
|
+
},
|
|
1960
|
+
className: pdfClassName("pageInput", PDF_PAGE_INPUT_DEFAULT),
|
|
1961
|
+
style: pdfStyle("pageInput"),
|
|
1962
|
+
"aria-label": resolveFormattedMessage(pdfT.pageInputAriaLabel, {
|
|
1963
|
+
value: inputPage
|
|
1964
|
+
})
|
|
1965
|
+
}
|
|
1966
|
+
) }),
|
|
1967
|
+
/* @__PURE__ */ jsx("span", { className: "opacity-60 mx-1", children: "/" }),
|
|
1968
|
+
/* @__PURE__ */ jsx("span", { children: numPages })
|
|
1969
|
+
] });
|
|
1970
|
+
return /* @__PURE__ */ jsxs(
|
|
1971
|
+
ViewerFloatingToolbar,
|
|
1972
|
+
{
|
|
1973
|
+
ref: toolbarRef,
|
|
1974
|
+
className: mergeClassNames(
|
|
1975
|
+
pdfClassName("pagination", ""),
|
|
1976
|
+
isToolbarVisible ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
|
1977
|
+
),
|
|
1978
|
+
style: pdfStyle("pagination"),
|
|
1979
|
+
children: [
|
|
1980
|
+
/* @__PURE__ */ jsx(
|
|
1981
|
+
FileViewerTooltip,
|
|
1982
|
+
{
|
|
1983
|
+
content: pdfT.previousPageTooltip,
|
|
1984
|
+
disabled: props2.isFirstPage,
|
|
1985
|
+
children: /* @__PURE__ */ jsx(
|
|
1986
|
+
ViewerToolbarIconButton,
|
|
1987
|
+
{
|
|
1988
|
+
disabled: props2.isFirstPage,
|
|
1989
|
+
onClick: previousPage,
|
|
1990
|
+
"aria-label": pdfT.previousPageAriaLabel,
|
|
1991
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5", "aria-hidden": true })
|
|
1992
|
+
}
|
|
1993
|
+
)
|
|
1994
|
+
}
|
|
1995
|
+
),
|
|
1996
|
+
paginationBody,
|
|
1997
|
+
/* @__PURE__ */ jsx(
|
|
1998
|
+
FileViewerTooltip,
|
|
1999
|
+
{
|
|
2000
|
+
content: pdfT.nextPageTooltip,
|
|
2001
|
+
disabled: props2.isLastPage,
|
|
2002
|
+
children: /* @__PURE__ */ jsx(
|
|
2003
|
+
ViewerToolbarIconButton,
|
|
2004
|
+
{
|
|
2005
|
+
disabled: props2.isLastPage,
|
|
2006
|
+
onClick: nextPage,
|
|
2007
|
+
"aria-label": pdfT.nextPageAriaLabel,
|
|
2008
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5", "aria-hidden": true })
|
|
2009
|
+
}
|
|
2010
|
+
)
|
|
2011
|
+
}
|
|
2012
|
+
),
|
|
2013
|
+
/* @__PURE__ */ jsx(ViewerToolbarDivider, {}),
|
|
2014
|
+
/* @__PURE__ */ jsx(
|
|
2015
|
+
FileViewerTooltip,
|
|
2016
|
+
{
|
|
2017
|
+
content: pdfT.zoomOutTooltip,
|
|
2018
|
+
disabled: zoomOutDisabled,
|
|
2019
|
+
children: /* @__PURE__ */ jsx(
|
|
2020
|
+
ViewerToolbarIconButton,
|
|
2021
|
+
{
|
|
2022
|
+
disabled: zoomOutDisabled,
|
|
2023
|
+
onClick: handleZoomOut,
|
|
2024
|
+
"aria-label": pdfT.zoomOutAriaLabel,
|
|
2025
|
+
children: /* @__PURE__ */ jsx(ZoomOut, { className: "h-5 w-5" })
|
|
2026
|
+
}
|
|
2027
|
+
)
|
|
2028
|
+
}
|
|
2029
|
+
),
|
|
2030
|
+
/* @__PURE__ */ jsx(
|
|
2031
|
+
FileViewerTooltip,
|
|
2032
|
+
{
|
|
2033
|
+
content: pdfT.fitWidthTooltip,
|
|
2034
|
+
disabled: fitDisabled,
|
|
2035
|
+
children: /* @__PURE__ */ jsx(
|
|
2036
|
+
ViewerToolbarIconButton,
|
|
2037
|
+
{
|
|
2038
|
+
disabled: fitDisabled,
|
|
2039
|
+
onClick: handleZoomReset,
|
|
2040
|
+
"aria-label": pdfT.fitWidthAriaLabel,
|
|
2041
|
+
children: /* @__PURE__ */ jsx(Scan, { className: "h-5 w-5" })
|
|
2042
|
+
}
|
|
2043
|
+
)
|
|
2044
|
+
}
|
|
2045
|
+
),
|
|
2046
|
+
/* @__PURE__ */ jsx(
|
|
2047
|
+
FileViewerTooltip,
|
|
2048
|
+
{
|
|
2049
|
+
content: pdfT.zoomInTooltip,
|
|
2050
|
+
disabled: zoomInDisabled,
|
|
2051
|
+
children: /* @__PURE__ */ jsx(
|
|
2052
|
+
ViewerToolbarIconButton,
|
|
2053
|
+
{
|
|
2054
|
+
disabled: zoomInDisabled,
|
|
2055
|
+
onClick: handleZoomIn,
|
|
2056
|
+
"aria-label": pdfT.zoomInAriaLabel,
|
|
2057
|
+
children: /* @__PURE__ */ jsx(ZoomIn, { className: "h-5 w-5" })
|
|
2058
|
+
}
|
|
2059
|
+
)
|
|
2060
|
+
}
|
|
2061
|
+
)
|
|
2062
|
+
]
|
|
2063
|
+
}
|
|
2064
|
+
);
|
|
2065
|
+
};
|
|
2066
|
+
const pageTransitionClass = hasZoomed && pageOriginalSize.width ? "transition-[width,height] duration-200 ease-out" : "";
|
|
2067
|
+
return /* @__PURE__ */ jsx(FileViewerTooltipProvider, { children: /* @__PURE__ */ jsxs(
|
|
2068
|
+
"div",
|
|
2069
|
+
{
|
|
2070
|
+
className: pdfClassName("root", PDF_VIEWER_ROOT_DEFAULT),
|
|
2071
|
+
style: pdfStyle("root"),
|
|
2072
|
+
children: [
|
|
2073
|
+
/* @__PURE__ */ jsxs(
|
|
2074
|
+
ScrollAreaRoot,
|
|
2075
|
+
{
|
|
2076
|
+
className: pdfClassName("scrollArea", PDF_SCROLL_AREA_DEFAULT),
|
|
2077
|
+
style: pdfStyle("scrollArea"),
|
|
2078
|
+
children: [
|
|
2079
|
+
/* @__PURE__ */ jsx(
|
|
2080
|
+
ScrollAreaViewport,
|
|
2081
|
+
{
|
|
2082
|
+
ref: containerRef,
|
|
2083
|
+
className: pdfClassName(
|
|
2084
|
+
"scrollViewport",
|
|
2085
|
+
`${PDF_SCROLL_VIEWPORT_DEFAULT} pdf-scroll-viewport`
|
|
2086
|
+
),
|
|
2087
|
+
style: pdfStyle("scrollViewport"),
|
|
2088
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex min-h-full min-w-full flex-col", children: /* @__PURE__ */ jsxs(
|
|
2089
|
+
Document,
|
|
2090
|
+
{
|
|
2091
|
+
file: url,
|
|
2092
|
+
onLoadSuccess: handleDocumentLoadSuccess,
|
|
2093
|
+
onLoadError: handleDocumentLoadError,
|
|
2094
|
+
loading: renderLoading,
|
|
2095
|
+
className: "flex w-full flex-col gap-4",
|
|
2096
|
+
children: [
|
|
2097
|
+
viewMode === "single" && zoomedRenderedDimensions.width && zoomedInstantDimensions.width && zoomedInstantDimensions.height ? /* @__PURE__ */ jsx(
|
|
2098
|
+
"div",
|
|
2099
|
+
{
|
|
2100
|
+
"data-layout-syncing": isLayoutSyncing ? "true" : void 0,
|
|
2101
|
+
className: pdfClassName(
|
|
2102
|
+
"page",
|
|
2103
|
+
PDF_PAGE_DEFAULT,
|
|
2104
|
+
pageTransitionClass
|
|
2105
|
+
),
|
|
2106
|
+
style: {
|
|
2107
|
+
width: zoomedInstantDimensions.width,
|
|
2108
|
+
height: zoomedInstantDimensions.height,
|
|
2109
|
+
...pdfStyle("page")
|
|
2110
|
+
},
|
|
2111
|
+
children: /* @__PURE__ */ jsx(
|
|
2112
|
+
"div",
|
|
2113
|
+
{
|
|
2114
|
+
className: pdfClassName("pageInner", PDF_PAGE_INNER_DEFAULT),
|
|
2115
|
+
style: pdfStyle("pageInner"),
|
|
2116
|
+
children: /* @__PURE__ */ jsx(
|
|
2117
|
+
Page,
|
|
2118
|
+
{
|
|
2119
|
+
pageNumber,
|
|
2120
|
+
onLoadSuccess: (page) => handlePageLoadSuccess(pageNumber, page),
|
|
2121
|
+
renderTextLayer,
|
|
2122
|
+
renderAnnotationLayer,
|
|
2123
|
+
className: "flex h-full w-full shrink flex-1 items-center justify-center !bg-transparent [&_canvas]:!h-full [&_canvas]:!w-full",
|
|
2124
|
+
renderMode: "canvas",
|
|
2125
|
+
width: zoomedRenderedDimensions.width,
|
|
2126
|
+
loading: null
|
|
2127
|
+
}
|
|
2128
|
+
)
|
|
2129
|
+
}
|
|
2130
|
+
)
|
|
2131
|
+
}
|
|
2132
|
+
) : null,
|
|
2133
|
+
viewMode === "continuous" && numPages > 0 && zoomedRenderedDimensions.width && zoomedRenderedDimensions.height && zoomedInstantDimensions.width && Array.from(new Array(numPages), (_, index) => {
|
|
2134
|
+
const p = index + 1;
|
|
2135
|
+
const isInWindow = p >= visibleRange.start - preloadAhead && p <= visibleRange.end + preloadAhead;
|
|
2136
|
+
const renderedPageHeight = renderedHeights.current.get(p) ?? zoomedRenderedDimensions.height ?? 0;
|
|
2137
|
+
const slotWidth = zoomedInstantDimensions.width ? Math.trunc(zoomedInstantDimensions.width) : void 0;
|
|
2138
|
+
const slotHeight = Math.trunc(renderedPageHeight * layoutScale);
|
|
2139
|
+
const placeholderStyle = !isInWindow && slotHeight ? {
|
|
2140
|
+
width: slotWidth,
|
|
2141
|
+
height: slotHeight,
|
|
2142
|
+
backgroundColor: "#80808040"
|
|
2143
|
+
} : {
|
|
2144
|
+
width: slotWidth,
|
|
2145
|
+
height: slotHeight
|
|
2146
|
+
};
|
|
2147
|
+
return /* @__PURE__ */ jsx(
|
|
2148
|
+
"div",
|
|
2149
|
+
{
|
|
2150
|
+
"data-layout-syncing": isLayoutSyncing ? "true" : void 0,
|
|
2151
|
+
"data-page-number": p,
|
|
2152
|
+
ref: (el) => {
|
|
2153
|
+
if (el) pageRefs.current.set(p, el);
|
|
2154
|
+
else pageRefs.current.delete(p);
|
|
2155
|
+
},
|
|
2156
|
+
className: pdfClassName(
|
|
2157
|
+
"page",
|
|
2158
|
+
PDF_PAGE_DEFAULT,
|
|
2159
|
+
pageTransitionClass
|
|
2160
|
+
),
|
|
2161
|
+
style: { ...placeholderStyle, ...pdfStyle("page") },
|
|
2162
|
+
children: isInWindow ? /* @__PURE__ */ jsx(
|
|
2163
|
+
"div",
|
|
2164
|
+
{
|
|
2165
|
+
className: pdfClassName(
|
|
2166
|
+
"pageInner",
|
|
2167
|
+
PDF_PAGE_INNER_DEFAULT
|
|
2168
|
+
),
|
|
2169
|
+
style: pdfStyle("pageInner"),
|
|
2170
|
+
children: /* @__PURE__ */ jsx(
|
|
2171
|
+
Page,
|
|
2172
|
+
{
|
|
2173
|
+
pageNumber: p,
|
|
2174
|
+
onLoadSuccess: (page) => handlePageLoadSuccess(p, page),
|
|
2175
|
+
renderTextLayer,
|
|
2176
|
+
renderAnnotationLayer,
|
|
2177
|
+
className: "flex h-full w-full shrink flex-1 items-center justify-center !bg-transparent [&_canvas]:!h-full [&_canvas]:!w-full",
|
|
2178
|
+
renderMode: "canvas",
|
|
2179
|
+
width: zoomedRenderedDimensions.width,
|
|
2180
|
+
loading: null
|
|
2181
|
+
}
|
|
2182
|
+
)
|
|
2183
|
+
}
|
|
2184
|
+
) : null
|
|
2185
|
+
},
|
|
2186
|
+
`page_${p}`
|
|
2187
|
+
);
|
|
2188
|
+
})
|
|
2189
|
+
]
|
|
2190
|
+
}
|
|
2191
|
+
) })
|
|
2192
|
+
}
|
|
2193
|
+
),
|
|
2194
|
+
/* @__PURE__ */ jsx(
|
|
2195
|
+
ScrollAreaScrollbar,
|
|
2196
|
+
{
|
|
2197
|
+
orientation: "vertical",
|
|
2198
|
+
className: pdfClassName("scrollbar", PDF_SCROLLBAR_VERTICAL_DEFAULT),
|
|
2199
|
+
style: pdfStyle("scrollbar"),
|
|
2200
|
+
children: /* @__PURE__ */ jsx(
|
|
2201
|
+
ScrollAreaThumb,
|
|
2202
|
+
{
|
|
2203
|
+
className: pdfClassName("scrollbarThumb", PDF_SCROLLBAR_THUMB_DEFAULT),
|
|
2204
|
+
style: pdfStyle("scrollbarThumb")
|
|
2205
|
+
}
|
|
2206
|
+
)
|
|
2207
|
+
}
|
|
2208
|
+
),
|
|
2209
|
+
/* @__PURE__ */ jsx(
|
|
2210
|
+
ScrollAreaScrollbar,
|
|
2211
|
+
{
|
|
2212
|
+
orientation: "horizontal",
|
|
2213
|
+
className: pdfClassName(
|
|
2214
|
+
"scrollbar",
|
|
2215
|
+
PDF_SCROLLBAR_HORIZONTAL_DEFAULT
|
|
2216
|
+
),
|
|
2217
|
+
style: pdfStyle("scrollbar"),
|
|
2218
|
+
children: /* @__PURE__ */ jsx(
|
|
2219
|
+
ScrollAreaThumb,
|
|
2220
|
+
{
|
|
2221
|
+
className: pdfClassName("scrollbarThumb", PDF_SCROLLBAR_THUMB_DEFAULT),
|
|
2222
|
+
style: pdfStyle("scrollbarThumb")
|
|
2223
|
+
}
|
|
2224
|
+
)
|
|
2225
|
+
}
|
|
2226
|
+
),
|
|
2227
|
+
/* @__PURE__ */ jsx(ScrollAreaCorner, { className: "bg-transparent" })
|
|
2228
|
+
]
|
|
2229
|
+
}
|
|
2230
|
+
),
|
|
2231
|
+
renderPaginationElement()
|
|
2232
|
+
]
|
|
2233
|
+
}
|
|
2234
|
+
) });
|
|
2235
|
+
}
|
|
2236
|
+
var PDF_VIEWER_ROOT_DEFAULT, PDF_SCROLL_AREA_DEFAULT, PDF_SCROLL_VIEWPORT_DEFAULT, PDF_SCROLLBAR_VERTICAL_DEFAULT, PDF_SCROLLBAR_HORIZONTAL_DEFAULT, PDF_SCROLLBAR_THUMB_DEFAULT, PDF_PAGE_DEFAULT, PDF_PAGE_INNER_DEFAULT, PDF_PAGE_INPUT_DEFAULT;
|
|
2237
|
+
var init_PdfViewer = __esm({
|
|
2238
|
+
"src/features/file-viewer/PdfViewer.tsx"() {
|
|
2239
|
+
"use client";
|
|
2240
|
+
init_icons();
|
|
2241
|
+
init_scroll_area();
|
|
2242
|
+
init_pdf_viewer();
|
|
2243
|
+
init_FileViewerTooltip();
|
|
2244
|
+
init_ViewerToolbar();
|
|
2245
|
+
init_useAutoHide();
|
|
2246
|
+
init_config();
|
|
2247
|
+
init_translations();
|
|
2248
|
+
init_resolve_options();
|
|
2249
|
+
init_merge_slot_props();
|
|
2250
|
+
PDF_VIEWER_ROOT_DEFAULT = "pdf-viewer flex flex-col items-center gap-4 w-full h-full max-h-full overflow-hidden relative";
|
|
2251
|
+
PDF_SCROLL_AREA_DEFAULT = "size-full min-h-0 min-w-0";
|
|
2252
|
+
PDF_SCROLL_VIEWPORT_DEFAULT = "w-full h-full rounded-[inherit] [&>div]:min-h-full";
|
|
2253
|
+
PDF_SCROLLBAR_VERTICAL_DEFAULT = "flex flex-col touch-none select-none transition-colors w-4 border-l border-l-transparent p-0.5 hover:bg-black/10 z-20";
|
|
2254
|
+
PDF_SCROLLBAR_HORIZONTAL_DEFAULT = "flex flex-col touch-none select-none transition-colors h-4 border-t border-t-transparent p-0.5 hover:bg-black/10 z-20";
|
|
2255
|
+
PDF_SCROLLBAR_THUMB_DEFAULT = "relative shrink-0 rounded-full bg-neutral-500/50 hover:bg-neutral-500/80";
|
|
2256
|
+
PDF_PAGE_DEFAULT = "relative flex shrink-0 items-center justify-center overflow-hidden m-auto";
|
|
2257
|
+
PDF_PAGE_INNER_DEFAULT = "relative flex h-full w-full items-center justify-center overflow-hidden bg-white shadow-lg";
|
|
2258
|
+
PDF_PAGE_INPUT_DEFAULT = "w-10 bg-transparent text-center focus:outline-none transition-colors";
|
|
2259
|
+
}
|
|
2260
|
+
});
|
|
2261
|
+
|
|
2262
|
+
// src/features/file-viewer/utils/zoom-utils.ts
|
|
2263
|
+
function calculateMultiplicativeZoom({
|
|
2264
|
+
scale,
|
|
2265
|
+
positionX,
|
|
2266
|
+
positionY,
|
|
2267
|
+
deltaY,
|
|
2268
|
+
clientX,
|
|
2269
|
+
clientY,
|
|
2270
|
+
wrapperComponent,
|
|
2271
|
+
minScale = 0.2,
|
|
2272
|
+
maxScale = 8,
|
|
2273
|
+
zoomFactor = 0.15
|
|
2274
|
+
}) {
|
|
2275
|
+
const isZoomIn = deltaY < 0;
|
|
2276
|
+
const factor = isZoomIn ? 1 + zoomFactor : 1 / (1 + zoomFactor);
|
|
2277
|
+
const newScale = Math.max(minScale, Math.min(scale * factor, maxScale));
|
|
2278
|
+
if (newScale === scale || !wrapperComponent) {
|
|
2279
|
+
return { newX: positionX, newY: positionY, newScale: scale };
|
|
2280
|
+
}
|
|
2281
|
+
const rect = wrapperComponent.getBoundingClientRect();
|
|
2282
|
+
const mx = clientX - rect.left;
|
|
2283
|
+
const my = clientY - rect.top;
|
|
2284
|
+
const ratio = newScale / scale;
|
|
2285
|
+
const newX = mx - (mx - positionX) * ratio;
|
|
2286
|
+
const newY = my - (my - positionY) * ratio;
|
|
2287
|
+
return { newX, newY, newScale };
|
|
2288
|
+
}
|
|
2289
|
+
var init_zoom_utils = __esm({
|
|
2290
|
+
"src/features/file-viewer/utils/zoom-utils.ts"() {
|
|
2291
|
+
}
|
|
2292
|
+
});
|
|
2293
|
+
|
|
2294
|
+
// src/features/file-viewer/utils/image-viewport-clamp.ts
|
|
2295
|
+
function roundNumber(num, decimal) {
|
|
2296
|
+
return Number(num.toFixed(decimal));
|
|
2297
|
+
}
|
|
2298
|
+
function getComponentsSizes(wrapperComponent, contentComponent, newScale) {
|
|
2299
|
+
const wrapperWidth = wrapperComponent.offsetWidth;
|
|
2300
|
+
const wrapperHeight = wrapperComponent.offsetHeight;
|
|
2301
|
+
const contentWidth = contentComponent.offsetWidth;
|
|
2302
|
+
const contentHeight = contentComponent.offsetHeight;
|
|
2303
|
+
const newContentWidth = contentWidth * newScale;
|
|
2304
|
+
const newContentHeight = contentHeight * newScale;
|
|
2305
|
+
const newDiffWidth = wrapperWidth - newContentWidth;
|
|
2306
|
+
const newDiffHeight = wrapperHeight - newContentHeight;
|
|
2307
|
+
return {
|
|
2308
|
+
wrapperWidth,
|
|
2309
|
+
wrapperHeight,
|
|
2310
|
+
newContentWidth,
|
|
2311
|
+
newDiffWidth,
|
|
2312
|
+
newContentHeight,
|
|
2313
|
+
newDiffHeight
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
function getBoundsFromSizes(wrapperWidth, newContentWidth, diffWidth, wrapperHeight, newContentHeight, diffHeight, centerZoomedOut) {
|
|
2317
|
+
const scaleWidthFactor = wrapperWidth > newContentWidth ? diffWidth * (centerZoomedOut ? 0.5 : 1) : 0;
|
|
2318
|
+
const scaleHeightFactor = wrapperHeight > newContentHeight ? diffHeight * (centerZoomedOut ? 0.5 : 1) : 0;
|
|
2319
|
+
const minPositionX = wrapperWidth - newContentWidth - scaleWidthFactor;
|
|
2320
|
+
const maxPositionX = scaleWidthFactor;
|
|
2321
|
+
const minPositionY = wrapperHeight - newContentHeight - scaleHeightFactor;
|
|
2322
|
+
const maxPositionY = scaleHeightFactor;
|
|
2323
|
+
return {
|
|
2324
|
+
minPositionX,
|
|
2325
|
+
maxPositionX,
|
|
2326
|
+
minPositionY,
|
|
2327
|
+
maxPositionY
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2330
|
+
function boundLimiter(value, minBound, maxBound, isActive) {
|
|
2331
|
+
if (!isActive) return roundNumber(value, 2);
|
|
2332
|
+
if (value < minBound) return roundNumber(minBound, 2);
|
|
2333
|
+
if (value > maxBound) return roundNumber(maxBound, 2);
|
|
2334
|
+
return roundNumber(value, 2);
|
|
2335
|
+
}
|
|
2336
|
+
function getMouseBoundedPosition(positionX, positionY, bounds, limitToBounds, paddingValueX, paddingValueY, wrapperComponent) {
|
|
2337
|
+
const { minPositionX, minPositionY, maxPositionX, maxPositionY } = bounds;
|
|
2338
|
+
const paddingX = wrapperComponent ? paddingValueX : 0;
|
|
2339
|
+
const paddingY = wrapperComponent ? paddingValueY : 0;
|
|
2340
|
+
const x = boundLimiter(
|
|
2341
|
+
positionX,
|
|
2342
|
+
minPositionX - paddingX,
|
|
2343
|
+
maxPositionX + paddingX,
|
|
2344
|
+
limitToBounds
|
|
2345
|
+
);
|
|
2346
|
+
const y = boundLimiter(
|
|
2347
|
+
positionY,
|
|
2348
|
+
minPositionY - paddingY,
|
|
2349
|
+
maxPositionY + paddingY,
|
|
2350
|
+
limitToBounds
|
|
2351
|
+
);
|
|
2352
|
+
return { x, y };
|
|
2353
|
+
}
|
|
2354
|
+
function clampPanToImageBounds(wrapperComponent, contentComponent, scale, positionX, positionY, setup) {
|
|
2355
|
+
const {
|
|
2356
|
+
wrapperWidth,
|
|
2357
|
+
wrapperHeight,
|
|
2358
|
+
newContentWidth,
|
|
2359
|
+
newContentHeight,
|
|
2360
|
+
newDiffWidth,
|
|
2361
|
+
newDiffHeight
|
|
2362
|
+
} = getComponentsSizes(wrapperComponent, contentComponent, scale);
|
|
2363
|
+
const bounds = getBoundsFromSizes(
|
|
2364
|
+
wrapperWidth,
|
|
2365
|
+
newContentWidth,
|
|
2366
|
+
newDiffWidth,
|
|
2367
|
+
wrapperHeight,
|
|
2368
|
+
newContentHeight,
|
|
2369
|
+
newDiffHeight,
|
|
2370
|
+
Boolean(setup.centerZoomedOut)
|
|
2371
|
+
);
|
|
2372
|
+
const contentFitsCompletely = wrapperWidth >= newContentWidth && wrapperHeight >= newContentHeight;
|
|
2373
|
+
if (setup.disablePadding && contentFitsCompletely && !setup.centerZoomedOut) {
|
|
2374
|
+
bounds.minPositionX = 0;
|
|
2375
|
+
bounds.maxPositionX = 0;
|
|
2376
|
+
bounds.minPositionY = 0;
|
|
2377
|
+
bounds.maxPositionY = 0;
|
|
2378
|
+
}
|
|
2379
|
+
const {
|
|
2380
|
+
minPositionX: propMinX,
|
|
2381
|
+
maxPositionX: propMaxX,
|
|
2382
|
+
minPositionY: propMinY,
|
|
2383
|
+
maxPositionY: propMaxY
|
|
2384
|
+
} = setup;
|
|
2385
|
+
if (propMinX != null) {
|
|
2386
|
+
bounds.minPositionX = wrapperWidth * (1 - scale) + propMinX * scale;
|
|
2387
|
+
}
|
|
2388
|
+
if (propMaxX != null) {
|
|
2389
|
+
bounds.maxPositionX = propMaxX * scale;
|
|
2390
|
+
}
|
|
2391
|
+
if (propMinY != null) {
|
|
2392
|
+
bounds.minPositionY = wrapperHeight * (1 - scale) + propMinY * scale;
|
|
2393
|
+
}
|
|
2394
|
+
if (propMaxY != null) {
|
|
2395
|
+
bounds.maxPositionY = propMaxY * scale;
|
|
2396
|
+
}
|
|
2397
|
+
const { x, y } = getMouseBoundedPosition(
|
|
2398
|
+
positionX,
|
|
2399
|
+
positionY,
|
|
2400
|
+
bounds,
|
|
2401
|
+
setup.limitToBounds,
|
|
2402
|
+
0,
|
|
2403
|
+
0,
|
|
2404
|
+
wrapperComponent
|
|
2405
|
+
);
|
|
2406
|
+
return { positionX: x, positionY: y };
|
|
2407
|
+
}
|
|
2408
|
+
var init_image_viewport_clamp = __esm({
|
|
2409
|
+
"src/features/file-viewer/utils/image-viewport-clamp.ts"() {
|
|
2410
|
+
}
|
|
2411
|
+
});
|
|
2412
|
+
|
|
2413
|
+
// src/features/file-viewer/ImageViewer.tsx
|
|
2414
|
+
var ImageViewer_exports = {};
|
|
2415
|
+
__export(ImageViewer_exports, {
|
|
2416
|
+
default: () => ImageViewer
|
|
2417
|
+
});
|
|
2418
|
+
function ImageViewer({
|
|
2419
|
+
url,
|
|
2420
|
+
name,
|
|
2421
|
+
language: languageProp,
|
|
2422
|
+
classNames: classNamesProp,
|
|
2423
|
+
styles: stylesProp
|
|
2424
|
+
}) {
|
|
2425
|
+
const resolved = resolveImageViewerProps({
|
|
2426
|
+
classNames: classNamesProp,
|
|
2427
|
+
styles: stylesProp
|
|
2428
|
+
});
|
|
2429
|
+
const classNames = resolved.classNames;
|
|
2430
|
+
const styles = resolved.styles;
|
|
2431
|
+
const language = resolveOption(
|
|
2432
|
+
languageProp,
|
|
2433
|
+
getFileViewerDefaults().language,
|
|
2434
|
+
"english"
|
|
2435
|
+
);
|
|
2436
|
+
const imageT = getFileViewerTranslations(language).imageViewer;
|
|
2437
|
+
const autoHideDefaults = getFileViewerDefaults().autoHide;
|
|
2438
|
+
const imageClassName = (key, builtIn, extra) => mergeClassNames(builtIn, classNames?.[key], extra);
|
|
2439
|
+
const imageStyle = (key) => styles?.[key];
|
|
2440
|
+
const [maxZoom, setMaxZoom] = useState(16);
|
|
2441
|
+
const [isPanning, setIsPanning] = useState(false);
|
|
2442
|
+
const [hasImageLoaded, setHasImageLoaded] = useState(false);
|
|
2443
|
+
const [viewport, setViewport] = useState({
|
|
2444
|
+
scale: 1,
|
|
2445
|
+
positionX: 0,
|
|
2446
|
+
positionY: 0
|
|
2447
|
+
});
|
|
2448
|
+
const minZoom = 0.5;
|
|
2449
|
+
const scaleRef = useRef(null);
|
|
2450
|
+
const transformRef = useRef(null);
|
|
2451
|
+
const containerRef = useRef(null);
|
|
2452
|
+
const toolbarRef = useRef(null);
|
|
2453
|
+
const wheelClampTimerRef = useRef(null);
|
|
2454
|
+
const libraryChangeUnsubscribeRef = useRef(null);
|
|
2455
|
+
const isToolbarVisible = useAutoHide(toolbarRef, containerRef, {
|
|
2456
|
+
proximityThreshold: autoHideDefaults?.proximityThreshold,
|
|
2457
|
+
timeout: autoHideDefaults?.timeout,
|
|
2458
|
+
activityDeps: [viewport.scale]
|
|
2459
|
+
});
|
|
2460
|
+
const updateScaleText = useCallback((scale) => {
|
|
2461
|
+
if (scaleRef.current) {
|
|
2462
|
+
scaleRef.current.innerText = `${Math.round(scale * 100)}%`;
|
|
2463
|
+
}
|
|
2464
|
+
}, []);
|
|
2465
|
+
const syncViewportFromLibrary = useCallback(
|
|
2466
|
+
(libraryRef) => {
|
|
2467
|
+
const { scale, positionX, positionY } = libraryRef.instance.state;
|
|
2468
|
+
setViewport({ scale, positionX, positionY });
|
|
2469
|
+
updateScaleText(scale);
|
|
2470
|
+
},
|
|
2471
|
+
[updateScaleText]
|
|
2472
|
+
);
|
|
2473
|
+
const handleLibraryInit = useCallback(
|
|
2474
|
+
(libraryRef) => {
|
|
2475
|
+
libraryChangeUnsubscribeRef.current?.();
|
|
2476
|
+
libraryChangeUnsubscribeRef.current = null;
|
|
2477
|
+
syncViewportFromLibrary(libraryRef);
|
|
2478
|
+
libraryChangeUnsubscribeRef.current = libraryRef.instance.onChange(
|
|
2479
|
+
(nextRef) => {
|
|
2480
|
+
syncViewportFromLibrary(nextRef);
|
|
2481
|
+
}
|
|
2482
|
+
);
|
|
2483
|
+
},
|
|
2484
|
+
[syncViewportFromLibrary]
|
|
2485
|
+
);
|
|
2486
|
+
const scheduleWheelViewportClamp = useCallback(() => {
|
|
2487
|
+
if (wheelClampTimerRef.current !== null) {
|
|
2488
|
+
clearTimeout(wheelClampTimerRef.current);
|
|
2489
|
+
}
|
|
2490
|
+
wheelClampTimerRef.current = window.setTimeout(() => {
|
|
2491
|
+
wheelClampTimerRef.current = null;
|
|
2492
|
+
const ref = transformRef.current;
|
|
2493
|
+
if (!ref) return;
|
|
2494
|
+
const { instance } = ref;
|
|
2495
|
+
const { scale, positionX, positionY } = instance.state;
|
|
2496
|
+
const wrapper = instance.wrapperComponent;
|
|
2497
|
+
const content = instance.contentComponent;
|
|
2498
|
+
if (!wrapper || !content) return;
|
|
2499
|
+
const setup = instance.setup;
|
|
2500
|
+
const clamped = clampPanToImageBounds(
|
|
2501
|
+
wrapper,
|
|
2502
|
+
content,
|
|
2503
|
+
scale,
|
|
2504
|
+
positionX,
|
|
2505
|
+
positionY,
|
|
2506
|
+
{
|
|
2507
|
+
centerZoomedOut: Boolean(setup.centerZoomedOut),
|
|
2508
|
+
disablePadding: Boolean(setup.disablePadding),
|
|
2509
|
+
minPositionX: setup.minPositionX ?? null,
|
|
2510
|
+
maxPositionX: setup.maxPositionX ?? null,
|
|
2511
|
+
minPositionY: setup.minPositionY ?? null,
|
|
2512
|
+
maxPositionY: setup.maxPositionY ?? null,
|
|
2513
|
+
limitToBounds: Boolean(setup.limitToBounds)
|
|
2514
|
+
}
|
|
2515
|
+
);
|
|
2516
|
+
if (Math.abs(clamped.positionX - positionX) > 0.01 || Math.abs(clamped.positionY - positionY) > 0.01) {
|
|
2517
|
+
ref.setTransform(
|
|
2518
|
+
clamped.positionX,
|
|
2519
|
+
clamped.positionY,
|
|
2520
|
+
scale,
|
|
2521
|
+
WHEEL_CLAMP_ANIMATION_MS,
|
|
2522
|
+
"easeOut"
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
}, WHEEL_VIEWPORT_CLAMP_DEBOUNCE_MS);
|
|
2526
|
+
}, []);
|
|
2527
|
+
useEffect(() => {
|
|
2528
|
+
return () => {
|
|
2529
|
+
if (wheelClampTimerRef.current !== null) {
|
|
2530
|
+
clearTimeout(wheelClampTimerRef.current);
|
|
2531
|
+
}
|
|
2532
|
+
libraryChangeUnsubscribeRef.current?.();
|
|
2533
|
+
libraryChangeUnsubscribeRef.current = null;
|
|
2534
|
+
};
|
|
2535
|
+
}, []);
|
|
2536
|
+
useEffect(() => {
|
|
2537
|
+
setHasImageLoaded(false);
|
|
2538
|
+
}, [url]);
|
|
2539
|
+
const handleImageLoad = (event) => {
|
|
2540
|
+
const img = event.currentTarget;
|
|
2541
|
+
const naturalWidth = img.naturalWidth;
|
|
2542
|
+
const currentWidth = img.clientWidth;
|
|
2543
|
+
if (naturalWidth && currentWidth) {
|
|
2544
|
+
const nativeScale = naturalWidth / currentWidth;
|
|
2545
|
+
const calculatedMax = Math.max(4, Math.min(16, nativeScale * 2));
|
|
2546
|
+
setMaxZoom(calculatedMax);
|
|
2547
|
+
}
|
|
2548
|
+
setHasImageLoaded(true);
|
|
2549
|
+
};
|
|
2550
|
+
const handleImageError = () => {
|
|
2551
|
+
setHasImageLoaded(true);
|
|
2552
|
+
};
|
|
2553
|
+
const applyWheelZoom = useCallback(
|
|
2554
|
+
(event) => {
|
|
2555
|
+
if (!hasImageLoaded) return;
|
|
2556
|
+
const ref = transformRef.current;
|
|
2557
|
+
if (!ref) return;
|
|
2558
|
+
event.preventDefault();
|
|
2559
|
+
event.stopPropagation();
|
|
2560
|
+
const { scale, positionX, positionY } = ref.state;
|
|
2561
|
+
const { newX, newY, newScale } = calculateMultiplicativeZoom({
|
|
2562
|
+
scale,
|
|
2563
|
+
positionX,
|
|
2564
|
+
positionY,
|
|
2565
|
+
deltaY: event.deltaY,
|
|
2566
|
+
clientX: event.clientX,
|
|
2567
|
+
clientY: event.clientY,
|
|
2568
|
+
wrapperComponent: ref.instance.wrapperComponent,
|
|
2569
|
+
minScale: minZoom,
|
|
2570
|
+
maxScale: maxZoom
|
|
2571
|
+
});
|
|
2572
|
+
if (newScale !== scale) {
|
|
2573
|
+
ref.setTransform(newX, newY, newScale, 0);
|
|
2574
|
+
scheduleWheelViewportClamp();
|
|
2575
|
+
}
|
|
2576
|
+
},
|
|
2577
|
+
[hasImageLoaded, maxZoom, scheduleWheelViewportClamp]
|
|
2578
|
+
);
|
|
2579
|
+
useEffect(() => {
|
|
2580
|
+
const container = containerRef.current;
|
|
2581
|
+
if (!container) return;
|
|
2582
|
+
const handleWheel = (event) => {
|
|
2583
|
+
if (!container.contains(event.target)) return;
|
|
2584
|
+
applyWheelZoom(event);
|
|
2585
|
+
};
|
|
2586
|
+
container.addEventListener("wheel", handleWheel, { passive: false });
|
|
2587
|
+
return () => container.removeEventListener("wheel", handleWheel);
|
|
2588
|
+
}, [applyWheelZoom, hasImageLoaded]);
|
|
2589
|
+
const zoomOutDisabled = viewport.scale <= minZoom + SCALE_EPSILON;
|
|
2590
|
+
const zoomInDisabled = viewport.scale >= maxZoom - SCALE_EPSILON;
|
|
2591
|
+
const nearDefaultPan = Math.abs(viewport.positionX) < 12 && Math.abs(viewport.positionY) < 12;
|
|
2592
|
+
const fitDisabled = Math.abs(viewport.scale - 1) < FIT_AT_ONE_EPSILON && nearDefaultPan;
|
|
2593
|
+
const wrapperCursorClass = isPanning ? "cursor-move" : "";
|
|
2594
|
+
return /* @__PURE__ */ jsx(FileViewerTooltipProvider, { children: /* @__PURE__ */ jsxs(
|
|
2595
|
+
"div",
|
|
2596
|
+
{
|
|
2597
|
+
ref: containerRef,
|
|
2598
|
+
className: imageClassName("root", IMAGE_ROOT_DEFAULT),
|
|
2599
|
+
style: imageStyle("root"),
|
|
2600
|
+
children: [
|
|
2601
|
+
!hasImageLoaded ? /* @__PURE__ */ jsx(
|
|
2602
|
+
"div",
|
|
2603
|
+
{
|
|
2604
|
+
className: imageClassName("loader", IMAGE_LOADER_OVERLAY_DEFAULT),
|
|
2605
|
+
style: imageStyle("loader"),
|
|
2606
|
+
"aria-busy": true,
|
|
2607
|
+
"aria-live": "polite",
|
|
2608
|
+
children: /* @__PURE__ */ jsx(LoaderCircle, { className: IMAGE_LOADER_ICON_DEFAULT, "aria-hidden": true })
|
|
2609
|
+
}
|
|
2610
|
+
) : null,
|
|
2611
|
+
/* @__PURE__ */ jsx(
|
|
2612
|
+
TransformWrapper,
|
|
2613
|
+
{
|
|
2614
|
+
ref: transformRef,
|
|
2615
|
+
initialScale: 1,
|
|
2616
|
+
minScale: minZoom,
|
|
2617
|
+
maxScale: maxZoom,
|
|
2618
|
+
centerOnInit: true,
|
|
2619
|
+
limitToBounds: true,
|
|
2620
|
+
wheel: { disabled: true },
|
|
2621
|
+
onInit: handleLibraryInit,
|
|
2622
|
+
onPanningStart: () => setIsPanning(true),
|
|
2623
|
+
onPanningStop: () => setIsPanning(false),
|
|
2624
|
+
children: ({ zoomIn, zoomOut, resetTransform }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2625
|
+
/* @__PURE__ */ jsx(
|
|
2626
|
+
TransformComponent,
|
|
2627
|
+
{
|
|
2628
|
+
wrapperClass: `!size-full ${wrapperCursorClass}`,
|
|
2629
|
+
contentClass: "!size-full flex items-center justify-center",
|
|
2630
|
+
children: /* @__PURE__ */ jsx(
|
|
2631
|
+
"img",
|
|
2632
|
+
{
|
|
2633
|
+
src: url,
|
|
2634
|
+
alt: name,
|
|
2635
|
+
onLoad: handleImageLoad,
|
|
2636
|
+
onError: handleImageError,
|
|
2637
|
+
className: imageClassName("image", IMAGE_IMG_DEFAULT),
|
|
2638
|
+
style: imageStyle("image")
|
|
2639
|
+
}
|
|
2640
|
+
)
|
|
2641
|
+
}
|
|
2642
|
+
),
|
|
2643
|
+
/* @__PURE__ */ jsxs(
|
|
2644
|
+
ViewerFloatingToolbar,
|
|
2645
|
+
{
|
|
2646
|
+
ref: toolbarRef,
|
|
2647
|
+
className: mergeClassNames(
|
|
2648
|
+
imageClassName("toolbar", ""),
|
|
2649
|
+
isToolbarVisible ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
|
2650
|
+
),
|
|
2651
|
+
style: imageStyle("toolbar"),
|
|
2652
|
+
children: [
|
|
2653
|
+
/* @__PURE__ */ jsx(
|
|
2654
|
+
"span",
|
|
2655
|
+
{
|
|
2656
|
+
ref: scaleRef,
|
|
2657
|
+
className: "w-12 text-center text-sm font-medium text-white/90",
|
|
2658
|
+
children: "100%"
|
|
2659
|
+
}
|
|
2660
|
+
),
|
|
2661
|
+
/* @__PURE__ */ jsx(ViewerToolbarDivider, {}),
|
|
2662
|
+
/* @__PURE__ */ jsx(
|
|
2663
|
+
FileViewerTooltip,
|
|
2664
|
+
{
|
|
2665
|
+
content: imageT.zoomOutTooltip,
|
|
2666
|
+
disabled: zoomOutDisabled,
|
|
2667
|
+
children: /* @__PURE__ */ jsx(
|
|
2668
|
+
ViewerToolbarIconButton,
|
|
2669
|
+
{
|
|
2670
|
+
disabled: zoomOutDisabled,
|
|
2671
|
+
onClick: () => zoomOut(),
|
|
2672
|
+
"aria-label": imageT.zoomOutAriaLabel,
|
|
2673
|
+
children: /* @__PURE__ */ jsx(ZoomOut, { className: "size-5" })
|
|
2674
|
+
}
|
|
2675
|
+
)
|
|
2676
|
+
}
|
|
2677
|
+
),
|
|
2678
|
+
/* @__PURE__ */ jsx(
|
|
2679
|
+
FileViewerTooltip,
|
|
2680
|
+
{
|
|
2681
|
+
content: imageT.fitScreenTooltip,
|
|
2682
|
+
disabled: fitDisabled,
|
|
2683
|
+
children: /* @__PURE__ */ jsx(
|
|
2684
|
+
ViewerToolbarIconButton,
|
|
2685
|
+
{
|
|
2686
|
+
disabled: fitDisabled,
|
|
2687
|
+
onClick: () => {
|
|
2688
|
+
resetTransform();
|
|
2689
|
+
updateScaleText(1);
|
|
2690
|
+
},
|
|
2691
|
+
"aria-label": imageT.fitScreenAriaLabel,
|
|
2692
|
+
children: /* @__PURE__ */ jsx(Scan, { className: "size-5" })
|
|
2693
|
+
}
|
|
2694
|
+
)
|
|
2695
|
+
}
|
|
2696
|
+
),
|
|
2697
|
+
/* @__PURE__ */ jsx(
|
|
2698
|
+
FileViewerTooltip,
|
|
2699
|
+
{
|
|
2700
|
+
content: imageT.zoomInTooltip,
|
|
2701
|
+
disabled: zoomInDisabled,
|
|
2702
|
+
children: /* @__PURE__ */ jsx(
|
|
2703
|
+
ViewerToolbarIconButton,
|
|
2704
|
+
{
|
|
2705
|
+
disabled: zoomInDisabled,
|
|
2706
|
+
onClick: () => zoomIn(),
|
|
2707
|
+
"aria-label": imageT.zoomInAriaLabel,
|
|
2708
|
+
children: /* @__PURE__ */ jsx(ZoomIn, { className: "size-5" })
|
|
2709
|
+
}
|
|
2710
|
+
)
|
|
2711
|
+
}
|
|
2712
|
+
)
|
|
2713
|
+
]
|
|
2714
|
+
}
|
|
2715
|
+
)
|
|
2716
|
+
] })
|
|
2717
|
+
},
|
|
2718
|
+
url
|
|
2719
|
+
)
|
|
2720
|
+
]
|
|
2721
|
+
}
|
|
2722
|
+
) });
|
|
2723
|
+
}
|
|
2724
|
+
var IMAGE_ROOT_DEFAULT, IMAGE_LOADER_OVERLAY_DEFAULT, IMAGE_LOADER_ICON_DEFAULT, IMAGE_IMG_DEFAULT, SCALE_EPSILON, FIT_AT_ONE_EPSILON, WHEEL_VIEWPORT_CLAMP_DEBOUNCE_MS, WHEEL_CLAMP_ANIMATION_MS;
|
|
2725
|
+
var init_ImageViewer = __esm({
|
|
2726
|
+
"src/features/file-viewer/ImageViewer.tsx"() {
|
|
2727
|
+
"use client";
|
|
2728
|
+
init_icons();
|
|
2729
|
+
init_ViewerToolbar();
|
|
2730
|
+
init_config();
|
|
2731
|
+
init_useAutoHide();
|
|
2732
|
+
init_FileViewerTooltip();
|
|
2733
|
+
init_zoom_utils();
|
|
2734
|
+
init_image_viewport_clamp();
|
|
2735
|
+
init_translations();
|
|
2736
|
+
init_merge_slot_props();
|
|
2737
|
+
init_resolve_options();
|
|
2738
|
+
IMAGE_ROOT_DEFAULT = "relative flex size-full items-center justify-center overflow-hidden";
|
|
2739
|
+
IMAGE_LOADER_OVERLAY_DEFAULT = "absolute inset-0 z-30 flex items-center justify-center bg-neutral-950/40";
|
|
2740
|
+
IMAGE_LOADER_ICON_DEFAULT = "size-10 animate-spin text-white";
|
|
2741
|
+
IMAGE_IMG_DEFAULT = "max-h-[calc(100dvh-10rem)] max-w-full shadow";
|
|
2742
|
+
SCALE_EPSILON = 0.012;
|
|
2743
|
+
FIT_AT_ONE_EPSILON = 0.018;
|
|
2744
|
+
WHEEL_VIEWPORT_CLAMP_DEBOUNCE_MS = 500;
|
|
2745
|
+
WHEEL_CLAMP_ANIMATION_MS = 320;
|
|
2746
|
+
}
|
|
2747
|
+
});
|
|
2748
|
+
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
2749
|
+
function useFocusTrap(containerRef, active) {
|
|
2750
|
+
useEffect(() => {
|
|
2751
|
+
if (!active) return;
|
|
2752
|
+
const container = containerRef.current;
|
|
2753
|
+
if (!container) return;
|
|
2754
|
+
const focusable = container.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
2755
|
+
const first = focusable[0];
|
|
2756
|
+
const last = focusable[focusable.length - 1];
|
|
2757
|
+
first?.focus();
|
|
2758
|
+
const handleKeyDown = (event) => {
|
|
2759
|
+
if (event.key !== "Tab" || focusable.length === 0) return;
|
|
2760
|
+
if (event.shiftKey) {
|
|
2761
|
+
if (document.activeElement === first) {
|
|
2762
|
+
event.preventDefault();
|
|
2763
|
+
last?.focus();
|
|
2764
|
+
}
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2767
|
+
if (document.activeElement === last) {
|
|
2768
|
+
event.preventDefault();
|
|
2769
|
+
first?.focus();
|
|
2770
|
+
}
|
|
2771
|
+
};
|
|
2772
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2773
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
2774
|
+
}, [active, containerRef]);
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
// src/features/file-viewer/primitives/dialog.tsx
|
|
2778
|
+
init_as_child();
|
|
2779
|
+
var DialogContext = createContext(null);
|
|
2780
|
+
function useDialogContext(component) {
|
|
2781
|
+
const context = useContext(DialogContext);
|
|
2782
|
+
if (!context) {
|
|
2783
|
+
throw new Error(`${component} must be used within Dialog.Root`);
|
|
2784
|
+
}
|
|
2785
|
+
return context;
|
|
2786
|
+
}
|
|
2787
|
+
function Root({
|
|
2788
|
+
open,
|
|
2789
|
+
onOpenChange,
|
|
2790
|
+
children
|
|
2791
|
+
}) {
|
|
2792
|
+
const titleId = useId();
|
|
2793
|
+
return /* @__PURE__ */ jsx(DialogContext.Provider, { value: { open, onOpenChange, titleId }, children });
|
|
2794
|
+
}
|
|
2795
|
+
function Portal({ children }) {
|
|
2796
|
+
const { open } = useDialogContext("Dialog.Portal");
|
|
2797
|
+
if (!open || typeof document === "undefined") {
|
|
2798
|
+
return null;
|
|
2799
|
+
}
|
|
2800
|
+
return createPortal(children, document.body);
|
|
2801
|
+
}
|
|
2802
|
+
function Content({
|
|
2803
|
+
children,
|
|
2804
|
+
className,
|
|
2805
|
+
style,
|
|
2806
|
+
"aria-describedby": ariaDescribedBy,
|
|
2807
|
+
...rest
|
|
2808
|
+
}) {
|
|
2809
|
+
const { open, onOpenChange, titleId } = useDialogContext("Dialog.Content");
|
|
2810
|
+
const contentRef = useRef(null);
|
|
2811
|
+
useFocusTrap(contentRef, open);
|
|
2812
|
+
useEffect(() => {
|
|
2813
|
+
if (!open) {
|
|
2814
|
+
return;
|
|
2815
|
+
}
|
|
2816
|
+
const previousOverflow = document.body.style.overflow;
|
|
2817
|
+
document.body.style.overflow = "hidden";
|
|
2818
|
+
return () => {
|
|
2819
|
+
document.body.style.overflow = previousOverflow;
|
|
2820
|
+
};
|
|
2821
|
+
}, [open]);
|
|
2822
|
+
useEffect(() => {
|
|
2823
|
+
if (!open) {
|
|
2824
|
+
return;
|
|
2825
|
+
}
|
|
2826
|
+
const handleKeyDown = (event) => {
|
|
2827
|
+
if (event.key === "Escape") {
|
|
2828
|
+
onOpenChange(false);
|
|
2829
|
+
}
|
|
2830
|
+
};
|
|
2831
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2832
|
+
return () => {
|
|
2833
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
2834
|
+
};
|
|
2835
|
+
}, [open, onOpenChange]);
|
|
2836
|
+
if (!open) {
|
|
2837
|
+
return null;
|
|
2838
|
+
}
|
|
2839
|
+
return /* @__PURE__ */ jsx(
|
|
2840
|
+
"div",
|
|
2841
|
+
{
|
|
2842
|
+
ref: contentRef,
|
|
2843
|
+
role: "dialog",
|
|
2844
|
+
"aria-modal": "true",
|
|
2845
|
+
"aria-labelledby": titleId,
|
|
2846
|
+
"aria-describedby": ariaDescribedBy,
|
|
2847
|
+
"data-visible": open ? "true" : "false",
|
|
2848
|
+
className,
|
|
2849
|
+
style,
|
|
2850
|
+
...rest,
|
|
2851
|
+
children
|
|
2852
|
+
}
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
function Close({
|
|
2856
|
+
asChild,
|
|
2857
|
+
children
|
|
2858
|
+
}) {
|
|
2859
|
+
const { onOpenChange } = useDialogContext("Dialog.Close");
|
|
2860
|
+
const handleClick = (event) => {
|
|
2861
|
+
children.props.onClick?.(event);
|
|
2862
|
+
onOpenChange(false);
|
|
2863
|
+
};
|
|
2864
|
+
if (asChild) {
|
|
2865
|
+
return renderAsChild(true, children, { onClick: handleClick });
|
|
2866
|
+
}
|
|
2867
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick: handleClick, children });
|
|
2868
|
+
}
|
|
2869
|
+
function Title({
|
|
2870
|
+
asChild,
|
|
2871
|
+
children
|
|
2872
|
+
}) {
|
|
2873
|
+
const { titleId } = useDialogContext("Dialog.Title");
|
|
2874
|
+
if (asChild && isValidElement(children)) {
|
|
2875
|
+
return renderAsChild(true, children, { id: titleId });
|
|
2876
|
+
}
|
|
2877
|
+
return /* @__PURE__ */ jsx("p", { id: titleId, children });
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
// src/features/file-viewer/FileViewer.tsx
|
|
2881
|
+
init_icons();
|
|
2882
|
+
init_FileViewerTooltip();
|
|
2883
|
+
init_config();
|
|
2884
|
+
init_translations();
|
|
2885
|
+
|
|
2886
|
+
// src/features/file-viewer/utils/file-actions.ts
|
|
2887
|
+
function printPdfFromUrl(url) {
|
|
2888
|
+
const iframe = document.createElement("iframe");
|
|
2889
|
+
iframe.setAttribute(
|
|
2890
|
+
"style",
|
|
2891
|
+
"position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden"
|
|
2892
|
+
);
|
|
2893
|
+
iframe.setAttribute("aria-hidden", "true");
|
|
2894
|
+
iframe.src = url;
|
|
2895
|
+
const removeIframe = () => {
|
|
2896
|
+
iframe.remove();
|
|
2897
|
+
};
|
|
2898
|
+
const onLoad = () => {
|
|
2899
|
+
try {
|
|
2900
|
+
iframe.contentWindow?.focus();
|
|
2901
|
+
iframe.contentWindow?.print();
|
|
2902
|
+
} finally {
|
|
2903
|
+
window.setTimeout(removeIframe, 500);
|
|
2904
|
+
}
|
|
2905
|
+
};
|
|
2906
|
+
iframe.addEventListener("load", onLoad, { once: true });
|
|
2907
|
+
iframe.addEventListener("error", removeIframe, { once: true });
|
|
2908
|
+
document.body.appendChild(iframe);
|
|
2909
|
+
}
|
|
2910
|
+
async function downloadFileFromUrl(url, filename) {
|
|
2911
|
+
try {
|
|
2912
|
+
const response = await fetch(url);
|
|
2913
|
+
const blob = await response.blob();
|
|
2914
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
2915
|
+
const anchor = document.createElement("a");
|
|
2916
|
+
anchor.href = objectUrl;
|
|
2917
|
+
anchor.download = filename;
|
|
2918
|
+
anchor.rel = "noopener";
|
|
2919
|
+
document.body.appendChild(anchor);
|
|
2920
|
+
anchor.click();
|
|
2921
|
+
anchor.remove();
|
|
2922
|
+
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 2e3);
|
|
2923
|
+
} catch {
|
|
2924
|
+
const anchor = document.createElement("a");
|
|
2925
|
+
anchor.href = url;
|
|
2926
|
+
anchor.download = filename;
|
|
2927
|
+
anchor.target = "_blank";
|
|
2928
|
+
anchor.rel = "noopener noreferrer";
|
|
2929
|
+
document.body.appendChild(anchor);
|
|
2930
|
+
anchor.click();
|
|
2931
|
+
anchor.remove();
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
// src/features/file-viewer/FileViewer.tsx
|
|
2936
|
+
init_resolve_options();
|
|
2937
|
+
init_merge_slot_props();
|
|
2938
|
+
var LazyPdfViewer = lazy(() => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)));
|
|
2939
|
+
var LazyImageViewer = lazy(() => Promise.resolve().then(() => (init_ImageViewer(), ImageViewer_exports)));
|
|
2940
|
+
var FILE_VIEWER_DIALOG_BACKDROP_DEFAULT = "fixed inset-0 z-[100] cursor-default border-0 bg-black/80 p-0 data-[visible=true]:animate-in data-[visible=false]:animate-out data-[visible=false]:fade-out-0 data-[visible=true]:fade-in-0";
|
|
2941
|
+
var FILE_VIEWER_DIALOG_CONTENT_DEFAULT = "fixed inset-0 z-[101] flex h-full w-full min-h-0 cursor-default flex-col border-none bg-transparent p-0 shadow-none outline-none pointer-events-none duration-200 data-[visible=true]:animate-in data-[visible=false]:animate-out data-[visible=false]:fade-out-0 data-[visible=true]:fade-in-0 focus:outline-none";
|
|
2942
|
+
var FILE_VIEWER_DIALOG_PANEL_DEFAULT = "pointer-events-auto flex h-full w-full min-h-0 flex-col overflow-hidden rounded-none border-0 bg-neutral-800/95 shadow-none";
|
|
2943
|
+
var FILE_VIEWER_ROOT_DEFAULT = "flex min-h-0 flex-1 flex-col overflow-hidden";
|
|
2944
|
+
var FILE_VIEWER_HEADER_DEFAULT = "flex w-full shrink-0 justify-between gap-2 rounded-t-lg p-4 font-medium text-white";
|
|
2945
|
+
var FILE_VIEWER_HEADER_TITLE_WRAP_DEFAULT = "flex items-center gap-2";
|
|
2946
|
+
var FILE_VIEWER_CLOSE_BUTTON_DEFAULT = "cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus-visible:opacity-100 focus-visible:ring-1 focus-visible:ring-white focus-visible:ring-offset-0 disabled:pointer-events-none";
|
|
2947
|
+
var FILE_VIEWER_TITLE_MODAL_DEFAULT = "truncate";
|
|
2948
|
+
var FILE_VIEWER_TITLE_INLINE_DEFAULT = "truncate font-semibold";
|
|
2949
|
+
var FILE_VIEWER_HEADER_ACTIONS_DEFAULT = "flex gap-3";
|
|
2950
|
+
var FILE_VIEWER_ACTION_BUTTON_DEFAULT = "cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus-visible:opacity-100 focus-visible:ring-1 focus-visible:ring-white focus-visible:ring-offset-0";
|
|
2951
|
+
var FILE_VIEWER_ACTION_BUTTON_DOWNLOAD_DEFAULT = "cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus-visible:opacity-100 focus-visible:ring-1 focus-visible:ring-white focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50";
|
|
2952
|
+
var FILE_VIEWER_VIEWER_DEFAULT = "flex min-h-0 w-full flex-1 items-center justify-center overflow-hidden text-white";
|
|
2953
|
+
var FILE_VIEWER_LOADER_DEFAULT = "size-10 animate-spin";
|
|
2954
|
+
function mergeFileViewerSlotClassName(builtIn, globalValue, instanceValue) {
|
|
2955
|
+
return mergeClassNames(builtIn, globalValue, instanceValue);
|
|
2956
|
+
}
|
|
2957
|
+
function FileViewer({
|
|
2958
|
+
mode: modeProp,
|
|
2959
|
+
open,
|
|
2960
|
+
onOpenChange,
|
|
2961
|
+
name,
|
|
2962
|
+
extension,
|
|
2963
|
+
url,
|
|
2964
|
+
isLoading,
|
|
2965
|
+
onDownload,
|
|
2966
|
+
pdfViewerProps,
|
|
2967
|
+
renderUnsupported,
|
|
2968
|
+
language: languageProp,
|
|
2969
|
+
hideCloseButton: hideCloseButtonProp,
|
|
2970
|
+
showOpenInModalButton: showOpenInModalButtonProp,
|
|
2971
|
+
onOpenInModal,
|
|
2972
|
+
classNames,
|
|
2973
|
+
styles,
|
|
2974
|
+
dialogClassNames,
|
|
2975
|
+
dialogStyles
|
|
2976
|
+
}) {
|
|
2977
|
+
const globalFileViewer = getFileViewerDefaults().fileViewer;
|
|
2978
|
+
const mode = resolveOption(modeProp, globalFileViewer?.mode, "inline");
|
|
2979
|
+
const language = resolveOption(
|
|
2980
|
+
languageProp,
|
|
2981
|
+
getFileViewerDefaults().language,
|
|
2982
|
+
"english"
|
|
2983
|
+
);
|
|
2984
|
+
const contentRef = useRef(null);
|
|
2985
|
+
const printImage = useReactToPrint({ contentRef });
|
|
2986
|
+
const t = getFileViewerTranslations(language);
|
|
2987
|
+
const ext = extension.toLowerCase();
|
|
2988
|
+
const isPdf = ext === "pdf";
|
|
2989
|
+
const isImage = ["jpg", "png", "jpeg"].includes(ext);
|
|
2990
|
+
const supportedForPreview = isPdf || isImage;
|
|
2991
|
+
const [isMounted, setIsMounted] = useState(false);
|
|
2992
|
+
const [isDownloading, setIsDownloading] = useState(false);
|
|
2993
|
+
const [isModalPreviewOpen, setIsModalPreviewOpen] = useState(false);
|
|
2994
|
+
const showOpenInModalButton = mode === "inline" && resolveOption(
|
|
2995
|
+
showOpenInModalButtonProp,
|
|
2996
|
+
globalFileViewer?.showOpenInModalButton,
|
|
2997
|
+
true
|
|
2998
|
+
);
|
|
2999
|
+
const mergedPdfViewerProps = resolvePdfViewerProps(pdfViewerProps);
|
|
3000
|
+
const mergedImageViewerProps = resolveImageViewerProps();
|
|
3001
|
+
useEffect(() => {
|
|
3002
|
+
setIsMounted(true);
|
|
3003
|
+
}, []);
|
|
3004
|
+
useEffect(() => {
|
|
3005
|
+
setIsDownloading(false);
|
|
3006
|
+
}, [open, url]);
|
|
3007
|
+
useEffect(() => {
|
|
3008
|
+
if (!open) {
|
|
3009
|
+
setIsModalPreviewOpen(false);
|
|
3010
|
+
}
|
|
3011
|
+
}, [open]);
|
|
3012
|
+
const slotClassName = (key, builtIn) => mergeFileViewerSlotClassName(
|
|
3013
|
+
builtIn,
|
|
3014
|
+
globalFileViewer?.classNames?.[key],
|
|
3015
|
+
classNames?.[key]
|
|
3016
|
+
);
|
|
3017
|
+
const slotStyle = (key) => mergeStyles(globalFileViewer?.styles?.[key], styles?.[key]);
|
|
3018
|
+
const backdropClasses = mergeFileViewerSlotClassName(
|
|
3019
|
+
FILE_VIEWER_DIALOG_BACKDROP_DEFAULT,
|
|
3020
|
+
globalFileViewer?.dialogClassNames?.backdrop,
|
|
3021
|
+
dialogClassNames?.backdrop
|
|
3022
|
+
);
|
|
3023
|
+
const contentClasses = mergeFileViewerSlotClassName(
|
|
3024
|
+
FILE_VIEWER_DIALOG_CONTENT_DEFAULT,
|
|
3025
|
+
globalFileViewer?.dialogClassNames?.content,
|
|
3026
|
+
dialogClassNames?.content
|
|
3027
|
+
);
|
|
3028
|
+
const panelClasses = mergeFileViewerSlotClassName(
|
|
3029
|
+
FILE_VIEWER_DIALOG_PANEL_DEFAULT,
|
|
3030
|
+
globalFileViewer?.dialogClassNames?.panel,
|
|
3031
|
+
dialogClassNames?.panel
|
|
3032
|
+
);
|
|
3033
|
+
const backdropStyle = mergeStyles(
|
|
3034
|
+
globalFileViewer?.dialogStyles?.backdrop,
|
|
3035
|
+
dialogStyles?.backdrop
|
|
3036
|
+
);
|
|
3037
|
+
const contentStyle = mergeStyles(
|
|
3038
|
+
globalFileViewer?.dialogStyles?.content,
|
|
3039
|
+
dialogStyles?.content
|
|
3040
|
+
);
|
|
3041
|
+
const panelStyle = mergeStyles(
|
|
3042
|
+
globalFileViewer?.dialogStyles?.panel,
|
|
3043
|
+
dialogStyles?.panel
|
|
3044
|
+
);
|
|
3045
|
+
const renderPdf = () => {
|
|
3046
|
+
if (!isMounted) return null;
|
|
3047
|
+
return /* @__PURE__ */ jsx(
|
|
3048
|
+
Suspense,
|
|
3049
|
+
{
|
|
3050
|
+
fallback: /* @__PURE__ */ jsx(
|
|
3051
|
+
LoaderCircle,
|
|
3052
|
+
{
|
|
3053
|
+
className: slotClassName("loader", "animate-spin size-10 text-white"),
|
|
3054
|
+
style: slotStyle("loader")
|
|
3055
|
+
}
|
|
3056
|
+
),
|
|
3057
|
+
children: /* @__PURE__ */ jsx(LazyPdfViewer, { url, ...mergedPdfViewerProps, language })
|
|
3058
|
+
}
|
|
3059
|
+
);
|
|
3060
|
+
};
|
|
3061
|
+
const renderImage = () => {
|
|
3062
|
+
if (!isMounted) return null;
|
|
3063
|
+
return /* @__PURE__ */ jsx(
|
|
3064
|
+
Suspense,
|
|
3065
|
+
{
|
|
3066
|
+
fallback: /* @__PURE__ */ jsx(
|
|
3067
|
+
LoaderCircle,
|
|
3068
|
+
{
|
|
3069
|
+
className: slotClassName("loader", "animate-spin size-10 text-white"),
|
|
3070
|
+
style: slotStyle("loader")
|
|
3071
|
+
}
|
|
3072
|
+
),
|
|
3073
|
+
children: /* @__PURE__ */ jsx(
|
|
3074
|
+
LazyImageViewer,
|
|
3075
|
+
{
|
|
3076
|
+
url,
|
|
3077
|
+
name,
|
|
3078
|
+
language,
|
|
3079
|
+
...mergedImageViewerProps
|
|
3080
|
+
}
|
|
3081
|
+
)
|
|
3082
|
+
}
|
|
3083
|
+
);
|
|
3084
|
+
};
|
|
3085
|
+
const handlePrint = () => {
|
|
3086
|
+
if (!url) return;
|
|
3087
|
+
if (isPdf) {
|
|
3088
|
+
printPdfFromUrl(url);
|
|
3089
|
+
} else {
|
|
3090
|
+
printImage();
|
|
3091
|
+
}
|
|
3092
|
+
};
|
|
3093
|
+
const handleDownload = async () => {
|
|
3094
|
+
if (!url || isDownloading) return;
|
|
3095
|
+
setIsDownloading(true);
|
|
3096
|
+
try {
|
|
3097
|
+
if (onDownload) {
|
|
3098
|
+
await Promise.resolve(onDownload());
|
|
3099
|
+
} else {
|
|
3100
|
+
await downloadFileFromUrl(url, name);
|
|
3101
|
+
}
|
|
3102
|
+
} finally {
|
|
3103
|
+
setIsDownloading(false);
|
|
3104
|
+
}
|
|
3105
|
+
};
|
|
3106
|
+
const handleOpenInModal = () => {
|
|
3107
|
+
if (onOpenInModal) {
|
|
3108
|
+
onOpenInModal();
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
setIsModalPreviewOpen(true);
|
|
3112
|
+
};
|
|
3113
|
+
const renderCloseButton = (activeMode) => {
|
|
3114
|
+
const hideClose = resolveHideCloseButton(
|
|
3115
|
+
hideCloseButtonProp,
|
|
3116
|
+
globalFileViewer?.hideCloseButton,
|
|
3117
|
+
activeMode
|
|
3118
|
+
);
|
|
3119
|
+
if (hideClose) {
|
|
3120
|
+
return null;
|
|
3121
|
+
}
|
|
3122
|
+
if (activeMode === "modal") {
|
|
3123
|
+
return /* @__PURE__ */ jsx(Close, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3124
|
+
"button",
|
|
3125
|
+
{
|
|
3126
|
+
type: "button",
|
|
3127
|
+
"aria-label": t.fileViewer.closeAriaLabel,
|
|
3128
|
+
className: slotClassName("closeButton", FILE_VIEWER_CLOSE_BUTTON_DEFAULT),
|
|
3129
|
+
style: slotStyle("closeButton"),
|
|
3130
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-7", "aria-hidden": true })
|
|
3131
|
+
}
|
|
3132
|
+
) });
|
|
3133
|
+
}
|
|
3134
|
+
return /* @__PURE__ */ jsx(
|
|
3135
|
+
"button",
|
|
3136
|
+
{
|
|
3137
|
+
type: "button",
|
|
3138
|
+
onClick: () => onOpenChange(false),
|
|
3139
|
+
"aria-label": t.fileViewer.closeAriaLabel,
|
|
3140
|
+
className: slotClassName("closeButton", FILE_VIEWER_CLOSE_BUTTON_DEFAULT),
|
|
3141
|
+
style: slotStyle("closeButton"),
|
|
3142
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-7", "aria-hidden": true })
|
|
3143
|
+
}
|
|
3144
|
+
);
|
|
3145
|
+
};
|
|
3146
|
+
const renderPanelContent = (activeMode) => {
|
|
3147
|
+
const closeButton = renderCloseButton(activeMode);
|
|
3148
|
+
return /* @__PURE__ */ jsxs(
|
|
3149
|
+
"div",
|
|
3150
|
+
{
|
|
3151
|
+
className: slotClassName("root", FILE_VIEWER_ROOT_DEFAULT),
|
|
3152
|
+
style: slotStyle("root"),
|
|
3153
|
+
children: [
|
|
3154
|
+
/* @__PURE__ */ jsxs(
|
|
3155
|
+
"div",
|
|
3156
|
+
{
|
|
3157
|
+
className: slotClassName("header", FILE_VIEWER_HEADER_DEFAULT),
|
|
3158
|
+
style: slotStyle("header"),
|
|
3159
|
+
children: [
|
|
3160
|
+
/* @__PURE__ */ jsxs("span", { className: FILE_VIEWER_HEADER_TITLE_WRAP_DEFAULT, children: [
|
|
3161
|
+
closeButton,
|
|
3162
|
+
activeMode === "modal" ? /* @__PURE__ */ jsx(Title, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3163
|
+
"p",
|
|
3164
|
+
{
|
|
3165
|
+
className: slotClassName(
|
|
3166
|
+
"headerTitle",
|
|
3167
|
+
FILE_VIEWER_TITLE_MODAL_DEFAULT
|
|
3168
|
+
),
|
|
3169
|
+
style: slotStyle("headerTitle"),
|
|
3170
|
+
children: name
|
|
3171
|
+
}
|
|
3172
|
+
) }) : /* @__PURE__ */ jsx(
|
|
3173
|
+
"p",
|
|
3174
|
+
{
|
|
3175
|
+
className: slotClassName(
|
|
3176
|
+
"headerTitle",
|
|
3177
|
+
FILE_VIEWER_TITLE_INLINE_DEFAULT
|
|
3178
|
+
),
|
|
3179
|
+
style: slotStyle("headerTitle"),
|
|
3180
|
+
children: name
|
|
3181
|
+
}
|
|
3182
|
+
)
|
|
3183
|
+
] }),
|
|
3184
|
+
url && !isLoading && supportedForPreview ? /* @__PURE__ */ jsxs(
|
|
3185
|
+
"span",
|
|
3186
|
+
{
|
|
3187
|
+
className: slotClassName(
|
|
3188
|
+
"headerActions",
|
|
3189
|
+
FILE_VIEWER_HEADER_ACTIONS_DEFAULT
|
|
3190
|
+
),
|
|
3191
|
+
style: slotStyle("headerActions"),
|
|
3192
|
+
children: [
|
|
3193
|
+
showOpenInModalButton && activeMode === "inline" ? /* @__PURE__ */ jsx(FileViewerTooltip, { content: t.fileViewer.openInModalTooltip, children: /* @__PURE__ */ jsx(
|
|
3194
|
+
"button",
|
|
3195
|
+
{
|
|
3196
|
+
type: "button",
|
|
3197
|
+
onClick: handleOpenInModal,
|
|
3198
|
+
className: slotClassName(
|
|
3199
|
+
"openInModalButton",
|
|
3200
|
+
FILE_VIEWER_ACTION_BUTTON_DEFAULT
|
|
3201
|
+
),
|
|
3202
|
+
style: slotStyle("openInModalButton"),
|
|
3203
|
+
"aria-label": t.fileViewer.openInModalAriaLabel,
|
|
3204
|
+
children: /* @__PURE__ */ jsx(Maximize2, { className: "size-6", "aria-hidden": true })
|
|
3205
|
+
}
|
|
3206
|
+
) }) : null,
|
|
3207
|
+
/* @__PURE__ */ jsx(FileViewerTooltip, { content: t.fileViewer.printTooltip, children: /* @__PURE__ */ jsx(
|
|
3208
|
+
"button",
|
|
3209
|
+
{
|
|
3210
|
+
type: "button",
|
|
3211
|
+
onClick: handlePrint,
|
|
3212
|
+
className: slotClassName(
|
|
3213
|
+
"printButton",
|
|
3214
|
+
FILE_VIEWER_ACTION_BUTTON_DEFAULT
|
|
3215
|
+
),
|
|
3216
|
+
style: slotStyle("printButton"),
|
|
3217
|
+
"aria-label": t.fileViewer.printAriaLabel,
|
|
3218
|
+
children: /* @__PURE__ */ jsx(Printer, { className: "size-6", "aria-hidden": true })
|
|
3219
|
+
}
|
|
3220
|
+
) }),
|
|
3221
|
+
/* @__PURE__ */ jsx(
|
|
3222
|
+
FileViewerTooltip,
|
|
3223
|
+
{
|
|
3224
|
+
content: isDownloading ? t.fileViewer.downloadInProgressTooltip : t.fileViewer.downloadTooltip,
|
|
3225
|
+
children: /* @__PURE__ */ jsx(
|
|
3226
|
+
"button",
|
|
3227
|
+
{
|
|
3228
|
+
type: "button",
|
|
3229
|
+
disabled: isDownloading,
|
|
3230
|
+
onClick: () => {
|
|
3231
|
+
void handleDownload();
|
|
3232
|
+
},
|
|
3233
|
+
className: slotClassName(
|
|
3234
|
+
"downloadButton",
|
|
3235
|
+
FILE_VIEWER_ACTION_BUTTON_DOWNLOAD_DEFAULT
|
|
3236
|
+
),
|
|
3237
|
+
style: slotStyle("downloadButton"),
|
|
3238
|
+
"aria-busy": isDownloading,
|
|
3239
|
+
"aria-label": isDownloading ? t.fileViewer.downloadInProgressAriaLabel : t.fileViewer.downloadAriaLabel,
|
|
3240
|
+
children: isDownloading ? /* @__PURE__ */ jsx(LoaderCircle, { className: "size-6 animate-spin", "aria-hidden": true }) : /* @__PURE__ */ jsx(Download, { className: "size-6", "aria-hidden": true })
|
|
3241
|
+
}
|
|
3242
|
+
)
|
|
3243
|
+
}
|
|
3244
|
+
)
|
|
3245
|
+
]
|
|
3246
|
+
}
|
|
3247
|
+
) : null
|
|
3248
|
+
]
|
|
3249
|
+
}
|
|
3250
|
+
),
|
|
3251
|
+
/* @__PURE__ */ jsx(
|
|
3252
|
+
"div",
|
|
3253
|
+
{
|
|
3254
|
+
className: slotClassName("viewer", FILE_VIEWER_VIEWER_DEFAULT),
|
|
3255
|
+
style: slotStyle("viewer"),
|
|
3256
|
+
children: !url || isLoading ? /* @__PURE__ */ jsx(
|
|
3257
|
+
LoaderCircle,
|
|
3258
|
+
{
|
|
3259
|
+
className: slotClassName("loader", FILE_VIEWER_LOADER_DEFAULT),
|
|
3260
|
+
style: slotStyle("loader")
|
|
3261
|
+
}
|
|
3262
|
+
) : isImage ? renderImage() : isPdf ? renderPdf() : renderUnsupported || /* @__PURE__ */ jsx(
|
|
3263
|
+
"p",
|
|
3264
|
+
{
|
|
3265
|
+
className: slotClassName("unsupported", ""),
|
|
3266
|
+
style: slotStyle("unsupported"),
|
|
3267
|
+
children: resolveFormattedMessage(t.fileViewer.unsupportedFileType, {
|
|
3268
|
+
extension
|
|
3269
|
+
})
|
|
3270
|
+
}
|
|
3271
|
+
)
|
|
3272
|
+
}
|
|
3273
|
+
)
|
|
3274
|
+
]
|
|
3275
|
+
}
|
|
3276
|
+
);
|
|
3277
|
+
};
|
|
3278
|
+
const renderModalShell = (modalOpen, onModalOpenChange, content) => /* @__PURE__ */ jsx(Root, { open: modalOpen, onOpenChange: onModalOpenChange, children: /* @__PURE__ */ jsxs(Portal, { children: [
|
|
3279
|
+
/* @__PURE__ */ jsx(Close, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3280
|
+
"button",
|
|
3281
|
+
{
|
|
3282
|
+
type: "button",
|
|
3283
|
+
tabIndex: -1,
|
|
3284
|
+
"data-visible": modalOpen,
|
|
3285
|
+
className: backdropClasses,
|
|
3286
|
+
style: backdropStyle,
|
|
3287
|
+
"aria-hidden": true
|
|
3288
|
+
}
|
|
3289
|
+
) }),
|
|
3290
|
+
/* @__PURE__ */ jsx(
|
|
3291
|
+
Content,
|
|
3292
|
+
{
|
|
3293
|
+
"aria-describedby": void 0,
|
|
3294
|
+
className: contentClasses,
|
|
3295
|
+
style: contentStyle,
|
|
3296
|
+
children: /* @__PURE__ */ jsx(
|
|
3297
|
+
"div",
|
|
3298
|
+
{
|
|
3299
|
+
className: panelClasses,
|
|
3300
|
+
style: panelStyle,
|
|
3301
|
+
onClick: (event) => event.stopPropagation(),
|
|
3302
|
+
children: content
|
|
3303
|
+
}
|
|
3304
|
+
)
|
|
3305
|
+
}
|
|
3306
|
+
)
|
|
3307
|
+
] }) });
|
|
3308
|
+
const printOnlyNode = isImage && url ? /* @__PURE__ */ jsx("div", { className: "hidden", children: /* @__PURE__ */ jsx("div", { ref: contentRef, children: /* @__PURE__ */ jsx("img", { src: url, className: "max-h-[105dvh]", alt: name }) }) }) : null;
|
|
3309
|
+
if (mode === "inline") {
|
|
3310
|
+
if (!open) return null;
|
|
3311
|
+
return /* @__PURE__ */ jsxs(FileViewerTooltipProvider, { children: [
|
|
3312
|
+
/* @__PURE__ */ jsx("div", { className: panelClasses, style: panelStyle, children: renderPanelContent("inline") }),
|
|
3313
|
+
isModalPreviewOpen ? renderModalShell(
|
|
3314
|
+
isModalPreviewOpen,
|
|
3315
|
+
setIsModalPreviewOpen,
|
|
3316
|
+
renderPanelContent("modal")
|
|
3317
|
+
) : null,
|
|
3318
|
+
printOnlyNode
|
|
3319
|
+
] });
|
|
3320
|
+
}
|
|
3321
|
+
return /* @__PURE__ */ jsxs(FileViewerTooltipProvider, { children: [
|
|
3322
|
+
renderModalShell(open, onOpenChange, renderPanelContent("modal")),
|
|
3323
|
+
printOnlyNode
|
|
3324
|
+
] });
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
// src/features/file-viewer/index.ts
|
|
3328
|
+
init_PdfViewer();
|
|
3329
|
+
init_ImageViewer();
|
|
3330
|
+
init_FileViewerTooltip();
|
|
3331
|
+
var configuredWorkerSrc;
|
|
3332
|
+
function getFileViewerPdfWorkerSrc() {
|
|
3333
|
+
return `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
3334
|
+
}
|
|
3335
|
+
var getFileViewerPdfWorkerCdnUrl = getFileViewerPdfWorkerSrc;
|
|
3336
|
+
function isFileViewerPdfWorkerConfigured() {
|
|
3337
|
+
return configuredWorkerSrc !== void 0;
|
|
3338
|
+
}
|
|
3339
|
+
function configureFileViewerPdfWorker(options = {}) {
|
|
3340
|
+
const workerSrc = options.workerSrc ?? getFileViewerPdfWorkerSrc();
|
|
3341
|
+
pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
3342
|
+
configuredWorkerSrc = workerSrc;
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3345
|
+
// src/features/file-viewer/index.ts
|
|
3346
|
+
init_config();
|
|
3347
|
+
init_translations();
|
|
3348
|
+
|
|
3349
|
+
export { FileViewer, FileViewerTooltip, FileViewerTooltipProvider, ImageViewer, PdfViewer, configureFileViewerPdfWorker, defaultFileViewerTranslations, fileViewerTranslationsByLanguage, getFileViewerDefaults, getFileViewerPdfWorkerCdnUrl, getFileViewerPdfWorkerSrc, getFileViewerTranslations, isFileViewerPdfWorkerConfigured, resetFileViewerDefaults, resolveFormattedMessage, resolveImageViewerProps, resolvePdfViewerProps, setFileViewerDefaults };
|
|
3350
|
+
//# sourceMappingURL=index.js.map
|
|
3351
|
+
//# sourceMappingURL=index.js.map
|