@particle-academy/react-fancy 5.53.1 → 5.54.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/dist/PdfViewer.types-BEk2Jq6p.d.ts +97 -0
- package/dist/PdfViewer.types-DyoUBa2g.d.cts +97 -0
- package/dist/button.cjs +4 -4
- package/dist/button.js +2 -2
- package/dist/chat-drawer.cjs +3 -3
- package/dist/chat-drawer.js +2 -2
- package/dist/chunk-2O5UXH5R.cjs +191 -0
- package/dist/chunk-2O5UXH5R.cjs.map +1 -0
- package/dist/{chunk-26JZ47BJ.js → chunk-45JO5BEZ.js} +17 -11
- package/dist/chunk-45JO5BEZ.js.map +1 -0
- package/dist/{chunk-TFKG5FSG.cjs → chunk-4I4Y5MZO.cjs} +4 -4
- package/dist/{chunk-TFKG5FSG.cjs.map → chunk-4I4Y5MZO.cjs.map} +1 -1
- package/dist/{chunk-2KFHSFFY.cjs → chunk-6GKR5OAW.cjs} +4 -4
- package/dist/{chunk-2KFHSFFY.cjs.map → chunk-6GKR5OAW.cjs.map} +1 -1
- package/dist/chunk-7MDHCYEB.cjs +414 -0
- package/dist/chunk-7MDHCYEB.cjs.map +1 -0
- package/dist/{chunk-X7H75WVP.cjs → chunk-BJKKW77L.cjs} +17 -8
- package/dist/chunk-BJKKW77L.cjs.map +1 -0
- package/dist/chunk-DXZCKDYS.js +189 -0
- package/dist/chunk-DXZCKDYS.js.map +1 -0
- package/dist/{chunk-EJ6P7K4G.js → chunk-EULOJOTU.js} +3 -3
- package/dist/{chunk-EJ6P7K4G.js.map → chunk-EULOJOTU.js.map} +1 -1
- package/dist/chunk-I27K6NLX.cjs +15 -0
- package/dist/chunk-I27K6NLX.cjs.map +1 -0
- package/dist/{chunk-N7ABDCQ6.cjs → chunk-I2TBENUQ.cjs} +11 -11
- package/dist/{chunk-N7ABDCQ6.cjs.map → chunk-I2TBENUQ.cjs.map} +1 -1
- package/dist/{chunk-IVRYSSM7.js → chunk-J3A4Z2P7.js} +2 -2
- package/dist/chunk-J3A4Z2P7.js.map +1 -0
- package/dist/{chunk-EEFWVFKO.js → chunk-KUJ5XRBD.js} +7 -4
- package/dist/chunk-KUJ5XRBD.js.map +1 -0
- package/dist/chunk-MORXQ5UM.js +412 -0
- package/dist/chunk-MORXQ5UM.js.map +1 -0
- package/dist/{chunk-D4QOV56U.js → chunk-MTTRPPHH.js} +3 -3
- package/dist/{chunk-D4QOV56U.js.map → chunk-MTTRPPHH.js.map} +1 -1
- package/dist/{chunk-QKFOJKVE.cjs → chunk-MXWR3T3N.cjs} +2 -2
- package/dist/chunk-MXWR3T3N.cjs.map +1 -0
- package/dist/{chunk-G4M3MCJO.cjs → chunk-ONHT2PDW.cjs} +4 -4
- package/dist/{chunk-G4M3MCJO.cjs.map → chunk-ONHT2PDW.cjs.map} +1 -1
- package/dist/{chunk-2MUGEPRD.js → chunk-REKY2CM6.js} +5 -5
- package/dist/{chunk-2MUGEPRD.js.map → chunk-REKY2CM6.js.map} +1 -1
- package/dist/{chunk-E4TRDGSU.cjs → chunk-SLCR7A6W.cjs} +4 -4
- package/dist/{chunk-E4TRDGSU.cjs.map → chunk-SLCR7A6W.cjs.map} +1 -1
- package/dist/chunk-SV5BW3IA.js +13 -0
- package/dist/chunk-SV5BW3IA.js.map +1 -0
- package/dist/{chunk-OC5OUZSD.js → chunk-TBXZ3NGR.js} +4 -4
- package/dist/{chunk-OC5OUZSD.js.map → chunk-TBXZ3NGR.js.map} +1 -1
- package/dist/{chunk-VP7MT7LH.cjs → chunk-TCW72JBU.cjs} +17 -17
- package/dist/{chunk-VP7MT7LH.cjs.map → chunk-TCW72JBU.cjs.map} +1 -1
- package/dist/{chunk-CF5KRDN4.js → chunk-TGBLDJ72.js} +18 -9
- package/dist/chunk-TGBLDJ72.js.map +1 -0
- package/dist/{chunk-QFC736WY.js → chunk-WE5WGVVX.js} +3 -3
- package/dist/{chunk-QFC736WY.js.map → chunk-WE5WGVVX.js.map} +1 -1
- package/dist/{chunk-YVTFODCJ.cjs → chunk-WUG646R4.cjs} +6 -3
- package/dist/chunk-WUG646R4.cjs.map +1 -0
- package/dist/{chunk-CAMQ5B3V.cjs → chunk-XOXA3QZR.cjs} +21 -15
- package/dist/chunk-XOXA3QZR.cjs.map +1 -0
- package/dist/{chunk-Y6LL3B5P.js → chunk-ZFU4FY3Q.js} +3 -3
- package/dist/{chunk-Y6LL3B5P.js.map → chunk-ZFU4FY3Q.js.map} +1 -1
- package/dist/icon.cjs +7 -7
- package/dist/icon.js +1 -1
- package/dist/{index-AesVUjQE.d.cts → index-Bd4br4sF.d.cts} +1 -1
- package/dist/{index-D3wJ8hrZ.d.ts → index-Bwrc9ktU.d.ts} +1 -1
- package/dist/index.cjs +45 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/inputs.cjs +5 -4
- package/dist/inputs.js +3 -2
- package/dist/json-editor.cjs +15 -15
- package/dist/json-editor.js +4 -4
- package/dist/magic-wand.cjs +4 -4
- package/dist/magic-wand.js +3 -3
- package/dist/media-viewer.cjs +3 -3
- package/dist/media-viewer.d.cts +2 -2
- package/dist/media-viewer.d.ts +2 -2
- package/dist/media-viewer.js +2 -2
- package/dist/multi-switch.cjs +3 -2
- package/dist/multi-switch.js +2 -1
- package/dist/pdf-viewer.cjs +2 -2
- package/dist/pdf-viewer.d.cts +13 -1
- package/dist/pdf-viewer.d.ts +13 -1
- package/dist/pdf-viewer.js +1 -1
- package/dist/prompt-input.cjs +6 -5
- package/dist/prompt-input.js +5 -4
- package/dist/reason-tag.cjs +4 -4
- package/dist/reason-tag.js +3 -3
- package/dist/switch.cjs +2 -2
- package/dist/switch.js +1 -1
- package/dist/tooltip.cjs +3 -2
- package/dist/tooltip.js +2 -1
- package/docs/PdfViewer.md +106 -4
- package/package.json +1 -1
- package/dist/PdfViewer.types-Bgn9EmZT.d.cts +0 -22
- package/dist/PdfViewer.types-xnPpdjJa.d.ts +0 -22
- package/dist/chunk-26JZ47BJ.js.map +0 -1
- package/dist/chunk-CAMQ5B3V.cjs.map +0 -1
- package/dist/chunk-CF5KRDN4.js.map +0 -1
- package/dist/chunk-EEFWVFKO.js.map +0 -1
- package/dist/chunk-HRH5BIYG.js +0 -56
- package/dist/chunk-HRH5BIYG.js.map +0 -1
- package/dist/chunk-IVRYSSM7.js.map +0 -1
- package/dist/chunk-QKFOJKVE.cjs.map +0 -1
- package/dist/chunk-RVBTDXPD.cjs +0 -169
- package/dist/chunk-RVBTDXPD.cjs.map +0 -1
- package/dist/chunk-VQXXX6DK.js +0 -167
- package/dist/chunk-VQXXX6DK.js.map +0 -1
- package/dist/chunk-X7H75WVP.cjs.map +0 -1
- package/dist/chunk-XM3W5ETT.cjs +0 -58
- package/dist/chunk-XM3W5ETT.cjs.map +0 -1
- package/dist/chunk-YVTFODCJ.cjs.map +0 -1
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkM5SEYDSS_cjs = require('./chunk-M5SEYDSS.cjs');
|
|
4
|
+
var chunkSNHU2AI4_cjs = require('./chunk-SNHU2AI4.cjs');
|
|
5
|
+
var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
var ZOOM_STEP = 1.25;
|
|
10
|
+
var MIN_ZOOM = 0.25;
|
|
11
|
+
var MAX_ZOOM = 4;
|
|
12
|
+
var SCALE_BUCKETS = [1, 1.5, 2, 3, 4];
|
|
13
|
+
var PRINT_SCREEN_MS = 1500;
|
|
14
|
+
var GAP = 16;
|
|
15
|
+
var clamp = (n, min, max) => Math.min(max, Math.max(min, n));
|
|
16
|
+
function scaleBucket(zoom) {
|
|
17
|
+
const dpr = typeof window !== "undefined" && window.devicePixelRatio > 0 ? window.devicePixelRatio : 1;
|
|
18
|
+
const want = zoom * dpr;
|
|
19
|
+
return SCALE_BUCKETS.find((b) => b >= want - 1e-9) ?? SCALE_BUCKETS[SCALE_BUCKETS.length - 1];
|
|
20
|
+
}
|
|
21
|
+
var PRINT_BLOCK_CSS = '@media print{[data-react-fancy-pdf-viewer][data-print-blocked="true"],[data-react-fancy-pdf-viewer][data-print-blocked="true"] *{visibility:hidden!important}}';
|
|
22
|
+
var PdfPages = react.forwardRef(
|
|
23
|
+
({
|
|
24
|
+
pages,
|
|
25
|
+
page: controlledPage,
|
|
26
|
+
defaultPage = 1,
|
|
27
|
+
onPageChange,
|
|
28
|
+
zoom: controlledZoom,
|
|
29
|
+
defaultZoom = 1,
|
|
30
|
+
onZoomChange,
|
|
31
|
+
policy,
|
|
32
|
+
watermark,
|
|
33
|
+
title,
|
|
34
|
+
className,
|
|
35
|
+
style
|
|
36
|
+
}, ref) => {
|
|
37
|
+
const count = Math.max(0, Math.floor(pages.count));
|
|
38
|
+
const download = policy?.download !== false;
|
|
39
|
+
const print = policy?.print !== false;
|
|
40
|
+
const copy = policy?.copy !== false;
|
|
41
|
+
const deter = policy?.screenshot === "deter";
|
|
42
|
+
const [rawPage, setPage] = chunkSNHU2AI4_cjs.useControllableState(controlledPage, defaultPage, onPageChange);
|
|
43
|
+
const page = clamp(rawPage, 1, Math.max(1, count));
|
|
44
|
+
const [zoom, setZoom] = chunkSNHU2AI4_cjs.useControllableState(controlledZoom, defaultZoom, onZoomChange);
|
|
45
|
+
const scale = scaleBucket(zoom);
|
|
46
|
+
const scrollerRef = react.useRef(null);
|
|
47
|
+
const [ratios, setRatios] = react.useState({});
|
|
48
|
+
const ratioOf = (n) => ratios[n] ?? pages.aspectRatio ?? 1 / Math.SQRT2;
|
|
49
|
+
const observable = typeof IntersectionObserver !== "undefined";
|
|
50
|
+
const [near, setNear] = react.useState(() => /* @__PURE__ */ new Set([page, page + 1]));
|
|
51
|
+
const isNear = (n) => !observable || n === page || near.has(n);
|
|
52
|
+
react.useEffect(() => {
|
|
53
|
+
const scroller = scrollerRef.current;
|
|
54
|
+
if (!observable || !scroller) return;
|
|
55
|
+
const io = new IntersectionObserver(
|
|
56
|
+
(entries) => {
|
|
57
|
+
setNear((prev) => {
|
|
58
|
+
const next = new Set(prev);
|
|
59
|
+
for (const e of entries) {
|
|
60
|
+
const n = Number(e.target.dataset.page);
|
|
61
|
+
if (e.isIntersecting) next.add(n);
|
|
62
|
+
else next.delete(n);
|
|
63
|
+
}
|
|
64
|
+
return next;
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
// A viewport's worth above and below, so a page is there before it scrolls in.
|
|
68
|
+
{ root: scroller, rootMargin: "100% 0px" }
|
|
69
|
+
);
|
|
70
|
+
scroller.querySelectorAll("[data-react-fancy-pdf-viewer-page]").forEach((el) => io.observe(el));
|
|
71
|
+
return () => io.disconnect();
|
|
72
|
+
}, [observable, count]);
|
|
73
|
+
const fromScroll = react.useRef(null);
|
|
74
|
+
const scrollToPage = react.useCallback((n) => {
|
|
75
|
+
const scroller = scrollerRef.current;
|
|
76
|
+
const slot = scroller?.querySelector(`[data-react-fancy-pdf-viewer-page][data-page="${n}"]`);
|
|
77
|
+
if (scroller && slot) scroller.scrollTop = Math.max(0, slot.offsetTop - GAP);
|
|
78
|
+
}, []);
|
|
79
|
+
react.useEffect(() => {
|
|
80
|
+
if (fromScroll.current === page) {
|
|
81
|
+
fromScroll.current = null;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
scrollToPage(page);
|
|
85
|
+
}, [page, scrollToPage]);
|
|
86
|
+
const firstZoom = react.useRef(true);
|
|
87
|
+
react.useLayoutEffect(() => {
|
|
88
|
+
if (firstZoom.current) {
|
|
89
|
+
firstZoom.current = false;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
scrollToPage(page);
|
|
93
|
+
}, [zoom]);
|
|
94
|
+
const pageRef = react.useRef(page);
|
|
95
|
+
pageRef.current = page;
|
|
96
|
+
react.useEffect(() => {
|
|
97
|
+
const scroller = scrollerRef.current;
|
|
98
|
+
if (!scroller || typeof ResizeObserver === "undefined") return;
|
|
99
|
+
let width = null;
|
|
100
|
+
const ro = new ResizeObserver(() => {
|
|
101
|
+
const w = scroller.clientWidth;
|
|
102
|
+
if (width !== null && w !== width) scrollToPage(pageRef.current);
|
|
103
|
+
width = w;
|
|
104
|
+
});
|
|
105
|
+
ro.observe(scroller);
|
|
106
|
+
return () => ro.disconnect();
|
|
107
|
+
}, [scrollToPage]);
|
|
108
|
+
const frame = react.useRef(0);
|
|
109
|
+
const onScroll = () => {
|
|
110
|
+
if (frame.current || typeof requestAnimationFrame === "undefined") return;
|
|
111
|
+
frame.current = requestAnimationFrame(() => {
|
|
112
|
+
frame.current = 0;
|
|
113
|
+
const scroller = scrollerRef.current;
|
|
114
|
+
if (!scroller) return;
|
|
115
|
+
const line = scroller.getBoundingClientRect().top + scroller.clientHeight / 3;
|
|
116
|
+
let current = 1;
|
|
117
|
+
scroller.querySelectorAll("[data-react-fancy-pdf-viewer-page]").forEach((el) => {
|
|
118
|
+
if (el.getBoundingClientRect().top <= line) current = Number(el.dataset.page);
|
|
119
|
+
});
|
|
120
|
+
if (current !== page) {
|
|
121
|
+
fromScroll.current = current;
|
|
122
|
+
setPage(current);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
react.useEffect(() => () => {
|
|
127
|
+
if (frame.current) cancelAnimationFrame(frame.current);
|
|
128
|
+
}, []);
|
|
129
|
+
const zoomTo = (z) => setZoom(clamp(Math.round(z * 100) / 100, MIN_ZOOM, MAX_ZOOM));
|
|
130
|
+
const fitPage = () => {
|
|
131
|
+
const scroller = scrollerRef.current;
|
|
132
|
+
if (!scroller || scroller.clientWidth <= GAP * 2) return;
|
|
133
|
+
const pageHeightAtFit = (scroller.clientWidth - GAP * 2) / ratioOf(page);
|
|
134
|
+
zoomTo((scroller.clientHeight - GAP * 2) / pageHeightAtFit);
|
|
135
|
+
};
|
|
136
|
+
const [hidden, setHidden] = react.useState(false);
|
|
137
|
+
const [blurred, setBlurred] = react.useState(false);
|
|
138
|
+
const [snapped, setSnapped] = react.useState(false);
|
|
139
|
+
react.useEffect(() => {
|
|
140
|
+
if (!deter || typeof window === "undefined") return;
|
|
141
|
+
let timer;
|
|
142
|
+
const onVisibility = () => setHidden(document.visibilityState === "hidden");
|
|
143
|
+
const onBlur = () => setBlurred(true);
|
|
144
|
+
const onFocus = () => setBlurred(false);
|
|
145
|
+
const onKeyUp = (e) => {
|
|
146
|
+
if (e.key !== "PrintScreen") return;
|
|
147
|
+
setSnapped(true);
|
|
148
|
+
clearTimeout(timer);
|
|
149
|
+
timer = setTimeout(() => setSnapped(false), PRINT_SCREEN_MS);
|
|
150
|
+
void navigator.clipboard?.writeText?.("").catch(() => {
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
154
|
+
window.addEventListener("blur", onBlur);
|
|
155
|
+
window.addEventListener("focus", onFocus);
|
|
156
|
+
window.addEventListener("keyup", onKeyUp);
|
|
157
|
+
return () => {
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
160
|
+
window.removeEventListener("blur", onBlur);
|
|
161
|
+
window.removeEventListener("focus", onFocus);
|
|
162
|
+
window.removeEventListener("keyup", onKeyUp);
|
|
163
|
+
};
|
|
164
|
+
}, [deter]);
|
|
165
|
+
const obscured = deter && (hidden || blurred || snapped);
|
|
166
|
+
const onKeyDown = (e) => {
|
|
167
|
+
if (!print && (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "p") e.preventDefault();
|
|
168
|
+
};
|
|
169
|
+
const block = (e) => e.preventDefault();
|
|
170
|
+
const markId = react.useId().replace(/[^a-zA-Z0-9_-]/g, "");
|
|
171
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
172
|
+
"div",
|
|
173
|
+
{
|
|
174
|
+
ref,
|
|
175
|
+
"data-react-fancy-pdf-viewer": "",
|
|
176
|
+
"data-mode": "pages",
|
|
177
|
+
"data-print-blocked": print ? void 0 : "true",
|
|
178
|
+
"data-obscured": String(obscured),
|
|
179
|
+
"aria-label": title,
|
|
180
|
+
role: "document",
|
|
181
|
+
onKeyDown,
|
|
182
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
183
|
+
"relative flex h-full min-h-[20rem] w-full flex-col overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-900",
|
|
184
|
+
className
|
|
185
|
+
),
|
|
186
|
+
style: copy ? style : { ...style, userSelect: "none", WebkitUserSelect: "none" },
|
|
187
|
+
children: [
|
|
188
|
+
!print && /* @__PURE__ */ jsxRuntime.jsx("style", { children: PRINT_BLOCK_CSS }),
|
|
189
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
190
|
+
"div",
|
|
191
|
+
{
|
|
192
|
+
"data-react-fancy-pdf-viewer-toolbar": "",
|
|
193
|
+
className: "flex shrink-0 items-center gap-1 border-b border-zinc-200 bg-[color:var(--fancy-surface,var(--color-white))] px-2 py-1 text-xs text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:border-zinc-800 dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]",
|
|
194
|
+
children: [
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolButton, { attr: "prev", label: "Previous page", disabled: page <= 1, onClick: () => setPage(page - 1), children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "up" }) }),
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { "data-react-fancy-pdf-viewer-page-label": "", className: "min-w-[3.5rem] text-center tabular-nums", "aria-live": "polite", children: [
|
|
197
|
+
page,
|
|
198
|
+
" / ",
|
|
199
|
+
count
|
|
200
|
+
] }),
|
|
201
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolButton, { attr: "next", label: "Next page", disabled: page >= count, onClick: () => setPage(page + 1), children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "down" }) }),
|
|
202
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-1 h-4 w-px bg-zinc-200 dark:bg-zinc-700", "aria-hidden": "true" }),
|
|
203
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolButton, { attr: "zoom-out", label: "Zoom out", disabled: zoom <= MIN_ZOOM, onClick: () => zoomTo(zoom / ZOOM_STEP), children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2212" }) }),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ToolButton, { attr: "zoom-reset", label: "Reset zoom", wide: true, onClick: () => zoomTo(1), children: [
|
|
205
|
+
Math.round(zoom * 100),
|
|
206
|
+
"%"
|
|
207
|
+
] }),
|
|
208
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolButton, { attr: "zoom-in", label: "Zoom in", disabled: zoom >= MAX_ZOOM, onClick: () => zoomTo(zoom * ZOOM_STEP), children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "+" }) }),
|
|
209
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolButton, { attr: "fit-width", label: "Fit width", wide: true, onClick: () => zoomTo(1), children: "Width" }),
|
|
210
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolButton, { attr: "fit-page", label: "Fit page", wide: true, onClick: fitPage, children: "Page" })
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
),
|
|
214
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
215
|
+
"div",
|
|
216
|
+
{
|
|
217
|
+
ref: scrollerRef,
|
|
218
|
+
"data-react-fancy-pdf-viewer-pages": "",
|
|
219
|
+
tabIndex: 0,
|
|
220
|
+
onScroll,
|
|
221
|
+
onContextMenu: download ? void 0 : block,
|
|
222
|
+
onDragStart: download ? void 0 : block,
|
|
223
|
+
className: "relative min-h-0 flex-1 overflow-auto outline-none transition-[filter] duration-150",
|
|
224
|
+
style: { padding: GAP, filter: obscured ? "blur(24px)" : void 0 },
|
|
225
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto flex flex-col", style: { width: `${zoom * 100}%`, gap: GAP }, children: Array.from({ length: count }, (_, i) => {
|
|
226
|
+
const n = i + 1;
|
|
227
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
228
|
+
"div",
|
|
229
|
+
{
|
|
230
|
+
"data-react-fancy-pdf-viewer-page": "",
|
|
231
|
+
"data-page": n,
|
|
232
|
+
className: "relative w-full overflow-hidden bg-white shadow-sm",
|
|
233
|
+
style: { aspectRatio: String(ratioOf(n)) },
|
|
234
|
+
children: [
|
|
235
|
+
isNear(n) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
236
|
+
"img",
|
|
237
|
+
{
|
|
238
|
+
"data-react-fancy-pdf-viewer-image": "",
|
|
239
|
+
src: pages.url(n, scale),
|
|
240
|
+
alt: `Page ${n}`,
|
|
241
|
+
decoding: "async",
|
|
242
|
+
draggable: download ? void 0 : false,
|
|
243
|
+
className: "block h-full w-full",
|
|
244
|
+
onLoad: (e) => {
|
|
245
|
+
const img = e.currentTarget;
|
|
246
|
+
if (img.naturalWidth > 0 && img.naturalHeight > 0) {
|
|
247
|
+
const r = img.naturalWidth / img.naturalHeight;
|
|
248
|
+
setRatios((prev) => prev[n] === r ? prev : { ...prev, [n]: r });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
),
|
|
253
|
+
watermark?.text && /* @__PURE__ */ jsxRuntime.jsx(Watermark, { id: `${markId}-${n}`, ...watermark })
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
n
|
|
257
|
+
);
|
|
258
|
+
}) })
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
PdfPages.displayName = "PdfPages";
|
|
267
|
+
function Watermark({ id, text, opacity = 0.15, angle = -30, density = 1 }) {
|
|
268
|
+
const fontSize = 14;
|
|
269
|
+
const gap = 80 / Math.max(0.1, density);
|
|
270
|
+
const w = text.length * fontSize * 0.55 + gap;
|
|
271
|
+
const h = fontSize + gap;
|
|
272
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
273
|
+
"svg",
|
|
274
|
+
{
|
|
275
|
+
"data-react-fancy-pdf-viewer-watermark": "",
|
|
276
|
+
"aria-hidden": "true",
|
|
277
|
+
className: "absolute inset-0 h-full w-full select-none",
|
|
278
|
+
style: { pointerEvents: "none" },
|
|
279
|
+
children: [
|
|
280
|
+
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("pattern", { id, width: w, height: h, patternUnits: "userSpaceOnUse", patternTransform: `rotate(${angle})`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
281
|
+
"text",
|
|
282
|
+
{
|
|
283
|
+
x: gap / 2,
|
|
284
|
+
y: h / 2,
|
|
285
|
+
fontSize,
|
|
286
|
+
fontFamily: "ui-sans-serif, system-ui, sans-serif",
|
|
287
|
+
fillOpacity: clamp(opacity, 0, 1),
|
|
288
|
+
style: { fill: "var(--fancy-text, var(--color-zinc-700))" },
|
|
289
|
+
children: text
|
|
290
|
+
}
|
|
291
|
+
) }) }),
|
|
292
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
function ToolButton({
|
|
298
|
+
attr,
|
|
299
|
+
label,
|
|
300
|
+
disabled,
|
|
301
|
+
wide,
|
|
302
|
+
onClick,
|
|
303
|
+
children
|
|
304
|
+
}) {
|
|
305
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
306
|
+
"button",
|
|
307
|
+
{
|
|
308
|
+
type: "button",
|
|
309
|
+
...{ [`data-react-fancy-pdf-viewer-${attr}`]: "" },
|
|
310
|
+
"aria-label": label,
|
|
311
|
+
title: label,
|
|
312
|
+
disabled,
|
|
313
|
+
onClick,
|
|
314
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
315
|
+
"flex h-6 items-center justify-center rounded-full tabular-nums transition-colors disabled:pointer-events-none disabled:opacity-30",
|
|
316
|
+
"hover:bg-zinc-900/5 hover:text-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 dark:hover:bg-white/10 dark:hover:text-zinc-200",
|
|
317
|
+
wide ? "min-w-[2.25rem] px-1.5" : "w-6"
|
|
318
|
+
),
|
|
319
|
+
children
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
function Chevron({ dir }) {
|
|
324
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: dir === "up" ? "m18 15-6-6-6 6" : "m6 9 6 6 6-6" }) });
|
|
325
|
+
}
|
|
326
|
+
var PdfViewer = react.forwardRef(
|
|
327
|
+
({
|
|
328
|
+
src,
|
|
329
|
+
pages,
|
|
330
|
+
page,
|
|
331
|
+
defaultPage,
|
|
332
|
+
onPageChange,
|
|
333
|
+
zoom,
|
|
334
|
+
defaultZoom,
|
|
335
|
+
onZoomChange,
|
|
336
|
+
policy,
|
|
337
|
+
watermark,
|
|
338
|
+
title = "PDF document",
|
|
339
|
+
className,
|
|
340
|
+
style,
|
|
341
|
+
frame = false,
|
|
342
|
+
frameProps
|
|
343
|
+
}, ref) => {
|
|
344
|
+
if (pages) {
|
|
345
|
+
const pageViewer = /* @__PURE__ */ jsxRuntime.jsx(
|
|
346
|
+
PdfPages,
|
|
347
|
+
{
|
|
348
|
+
ref,
|
|
349
|
+
pages,
|
|
350
|
+
page,
|
|
351
|
+
defaultPage,
|
|
352
|
+
onPageChange,
|
|
353
|
+
zoom,
|
|
354
|
+
defaultZoom,
|
|
355
|
+
onZoomChange,
|
|
356
|
+
policy,
|
|
357
|
+
watermark,
|
|
358
|
+
title,
|
|
359
|
+
className: chunkZU5Q77OT_cjs.cn(frame && "rounded-none", className),
|
|
360
|
+
style
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
if (!frame) return pageViewer;
|
|
364
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkM5SEYDSS_cjs.FauxClient, { variant: "browser", url: title, controls: { zoom: false }, fill: true, ...frameProps, children: pageViewer });
|
|
365
|
+
}
|
|
366
|
+
const viewer = /* @__PURE__ */ jsxRuntime.jsx(
|
|
367
|
+
"div",
|
|
368
|
+
{
|
|
369
|
+
ref,
|
|
370
|
+
"data-react-fancy-pdf-viewer": "",
|
|
371
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
372
|
+
"relative h-full min-h-[20rem] w-full overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-900",
|
|
373
|
+
className
|
|
374
|
+
),
|
|
375
|
+
style,
|
|
376
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("object", { data: src, type: "application/pdf", className: "h-full w-full", children: [
|
|
377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
378
|
+
"iframe",
|
|
379
|
+
{
|
|
380
|
+
src,
|
|
381
|
+
title,
|
|
382
|
+
className: "h-full w-full border-0"
|
|
383
|
+
}
|
|
384
|
+
),
|
|
385
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-2 p-4 text-center text-sm text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]", children: [
|
|
386
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "This browser can't display the PDF inline." }),
|
|
387
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
388
|
+
"a",
|
|
389
|
+
{
|
|
390
|
+
href: src,
|
|
391
|
+
download: true,
|
|
392
|
+
className: "font-medium text-blue-600 hover:underline dark:text-blue-400",
|
|
393
|
+
children: "Download PDF"
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
] })
|
|
397
|
+
] })
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
if (!frame) return viewer;
|
|
401
|
+
return (
|
|
402
|
+
// The browser variant, because the plugin swallows the pointer: hover over
|
|
403
|
+
// the PDF never reaches the frame, so controls over it could not be
|
|
404
|
+
// revealed, and its top-right corner is the PDF toolbar's. In the address
|
|
405
|
+
// bar they are reachable and collide with nothing.
|
|
406
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkM5SEYDSS_cjs.FauxClient, { variant: "browser", url: title, controls: { zoom: false }, fill: true, ...frameProps, children: viewer })
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
);
|
|
410
|
+
PdfViewer.displayName = "PdfViewer";
|
|
411
|
+
|
|
412
|
+
exports.PdfViewer = PdfViewer;
|
|
413
|
+
//# sourceMappingURL=chunk-7MDHCYEB.cjs.map
|
|
414
|
+
//# sourceMappingURL=chunk-7MDHCYEB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/PdfViewer/PdfPages.tsx","../src/components/PdfViewer/PdfViewer.tsx"],"names":["forwardRef","useControllableState","useRef","useState","useEffect","useCallback","useLayoutEffect","useId","jsxs","cn","jsx","FauxClient"],"mappings":"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","file":"chunk-7MDHCYEB.cjs","sourcesContent":["import { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport type { CSSProperties, KeyboardEvent, ReactNode, SyntheticEvent } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { PdfPageSource, PdfViewerPolicy, PdfViewerWatermark } from \"./PdfViewer.types\";\n\n/** One click of the zoom bar. Matches `FauxClient` and `ImageViewer`. */\nconst ZOOM_STEP = 1.25;\nconst MIN_ZOOM = 0.25;\nconst MAX_ZOOM = 4;\n/** The resolutions a page is requested at, so zooming refetches rarely. */\nconst SCALE_BUCKETS = [1, 1.5, 2, 3, 4];\n/** How long PrintScreen keeps the pages obscured. */\nconst PRINT_SCREEN_MS = 1500;\n/** Gap around and between pages, px. */\nconst GAP = 16;\n\nconst clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n));\n\nfunction scaleBucket(zoom: number): number {\n const dpr = typeof window !== \"undefined\" && window.devicePixelRatio > 0 ? window.devicePixelRatio : 1;\n const want = zoom * dpr;\n return SCALE_BUCKETS.find((b) => b >= want - 1e-9) ?? SCALE_BUCKETS[SCALE_BUCKETS.length - 1];\n}\n\n/*\n * Print is blanked from CSS, because a page can print without our key handler\n * ever seeing it (the browser menu, window.print()). `*` as well as the root, so\n * no descendant can set itself visible again.\n */\nconst PRINT_BLOCK_CSS =\n '@media print{[data-react-fancy-pdf-viewer][data-print-blocked=\"true\"],[data-react-fancy-pdf-viewer][data-print-blocked=\"true\"] *{visibility:hidden!important}}';\n\nexport interface PdfPagesProps {\n pages: PdfPageSource;\n page?: number;\n defaultPage?: number;\n onPageChange?: (page: number) => void;\n zoom?: number;\n defaultZoom?: number;\n onZoomChange?: (zoom: number) => void;\n policy?: PdfViewerPolicy;\n watermark?: PdfViewerWatermark;\n title: string;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Page-image mode of `PdfViewer`: images the app rendered, shown under a policy.\n * It never sees the PDF, so it has nothing to search and nothing to download.\n */\nexport const PdfPages = forwardRef<HTMLDivElement, PdfPagesProps>(\n (\n {\n pages,\n page: controlledPage,\n defaultPage = 1,\n onPageChange,\n zoom: controlledZoom,\n defaultZoom = 1,\n onZoomChange,\n policy,\n watermark,\n title,\n className,\n style,\n },\n ref,\n ) => {\n const count = Math.max(0, Math.floor(pages.count));\n const download = policy?.download !== false;\n const print = policy?.print !== false;\n const copy = policy?.copy !== false;\n const deter = policy?.screenshot === \"deter\";\n\n const [rawPage, setPage] = useControllableState(controlledPage, defaultPage, onPageChange);\n const page = clamp(rawPage, 1, Math.max(1, count));\n const [zoom, setZoom] = useControllableState(controlledZoom, defaultZoom, onZoomChange);\n const scale = scaleBucket(zoom);\n\n const scrollerRef = useRef<HTMLDivElement>(null);\n const [ratios, setRatios] = useState<Record<number, number>>({});\n const ratioOf = (n: number) => ratios[n] ?? pages.aspectRatio ?? 1 / Math.SQRT2;\n\n // ---- Which pages have an image: those near the viewport ---------------\n // Without IntersectionObserver there is no way to know what is near, so\n // every page renders (SSR markup, very old browsers).\n const observable = typeof IntersectionObserver !== \"undefined\";\n const [near, setNear] = useState<Set<number>>(() => new Set([page, page + 1]));\n const isNear = (n: number) => !observable || n === page || near.has(n);\n\n useEffect(() => {\n const scroller = scrollerRef.current;\n if (!observable || !scroller) return;\n const io = new IntersectionObserver(\n (entries) => {\n setNear((prev) => {\n const next = new Set(prev);\n for (const e of entries) {\n const n = Number((e.target as HTMLElement).dataset.page);\n if (e.isIntersecting) next.add(n);\n else next.delete(n);\n }\n return next;\n });\n },\n // A viewport's worth above and below, so a page is there before it scrolls in.\n { root: scroller, rootMargin: \"100% 0px\" },\n );\n scroller.querySelectorAll(\"[data-react-fancy-pdf-viewer-page]\").forEach((el) => io.observe(el));\n return () => io.disconnect();\n }, [observable, count]);\n\n // ---- The current page follows scrolling; a set page scrolls to it ------\n const fromScroll = useRef<number | null>(null);\n const scrollToPage = useCallback((n: number) => {\n const scroller = scrollerRef.current;\n const slot = scroller?.querySelector<HTMLElement>(`[data-react-fancy-pdf-viewer-page][data-page=\"${n}\"]`);\n if (scroller && slot) scroller.scrollTop = Math.max(0, slot.offsetTop - GAP);\n }, []);\n\n useEffect(() => {\n if (fromScroll.current === page) {\n fromScroll.current = null;\n return;\n }\n scrollToPage(page);\n }, [page, scrollToPage]);\n\n // Zooming changes every page's height: keep the current page in place.\n const firstZoom = useRef(true);\n useLayoutEffect(() => {\n if (firstZoom.current) {\n firstZoom.current = false;\n return;\n }\n scrollToPage(page);\n // Only on zoom; the page effect handles page changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zoom]);\n\n // A width change (full screen, a resized panel) re-flows every page's\n // height, so the scroll offset no longer points at the same page: put the\n // current one back.\n const pageRef = useRef(page);\n pageRef.current = page;\n useEffect(() => {\n const scroller = scrollerRef.current;\n if (!scroller || typeof ResizeObserver === \"undefined\") return;\n let width: number | null = null;\n const ro = new ResizeObserver(() => {\n const w = scroller.clientWidth;\n if (width !== null && w !== width) scrollToPage(pageRef.current);\n width = w;\n });\n ro.observe(scroller);\n return () => ro.disconnect();\n }, [scrollToPage]);\n\n const frame = useRef(0);\n const onScroll = () => {\n if (frame.current || typeof requestAnimationFrame === \"undefined\") return;\n frame.current = requestAnimationFrame(() => {\n frame.current = 0;\n const scroller = scrollerRef.current;\n if (!scroller) return;\n // The page under a line a third of the way down the viewport.\n const line = scroller.getBoundingClientRect().top + scroller.clientHeight / 3;\n let current = 1;\n scroller.querySelectorAll<HTMLElement>(\"[data-react-fancy-pdf-viewer-page]\").forEach((el) => {\n if (el.getBoundingClientRect().top <= line) current = Number(el.dataset.page);\n });\n if (current !== page) {\n fromScroll.current = current;\n setPage(current);\n }\n });\n };\n useEffect(() => () => {\n if (frame.current) cancelAnimationFrame(frame.current);\n }, []);\n\n const zoomTo = (z: number) => setZoom(clamp(Math.round(z * 100) / 100, MIN_ZOOM, MAX_ZOOM));\n const fitPage = () => {\n const scroller = scrollerRef.current;\n if (!scroller || scroller.clientWidth <= GAP * 2) return;\n const pageHeightAtFit = (scroller.clientWidth - GAP * 2) / ratioOf(page);\n zoomTo((scroller.clientHeight - GAP * 2) / pageHeightAtFit);\n };\n\n // ---- screenshot: \"deter\" ---------------------------------------------\n const [hidden, setHidden] = useState(false);\n const [blurred, setBlurred] = useState(false);\n const [snapped, setSnapped] = useState(false);\n useEffect(() => {\n if (!deter || typeof window === \"undefined\") return;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const onVisibility = () => setHidden(document.visibilityState === \"hidden\");\n const onBlur = () => setBlurred(true);\n const onFocus = () => setBlurred(false);\n const onKeyUp = (e: globalThis.KeyboardEvent) => {\n if (e.key !== \"PrintScreen\") return;\n // Best effort. The OS has usually taken the shot before this fires;\n // what is left is to obscure, and to clear a capture that went to the\n // clipboard (which fails quietly where the page may not write it).\n setSnapped(true);\n clearTimeout(timer);\n timer = setTimeout(() => setSnapped(false), PRINT_SCREEN_MS);\n void navigator.clipboard?.writeText?.(\"\").catch(() => {});\n };\n document.addEventListener(\"visibilitychange\", onVisibility);\n window.addEventListener(\"blur\", onBlur);\n window.addEventListener(\"focus\", onFocus);\n window.addEventListener(\"keyup\", onKeyUp);\n return () => {\n clearTimeout(timer);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n window.removeEventListener(\"blur\", onBlur);\n window.removeEventListener(\"focus\", onFocus);\n window.removeEventListener(\"keyup\", onKeyUp);\n };\n }, [deter]);\n const obscured = deter && (hidden || blurred || snapped);\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (!print && (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === \"p\") e.preventDefault();\n };\n const block = (e: SyntheticEvent) => e.preventDefault();\n\n const markId = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n\n return (\n <div\n ref={ref}\n data-react-fancy-pdf-viewer=\"\"\n data-mode=\"pages\"\n data-print-blocked={print ? undefined : \"true\"}\n data-obscured={String(obscured)}\n aria-label={title}\n role=\"document\"\n onKeyDown={onKeyDown}\n className={cn(\n \"relative flex h-full min-h-[20rem] w-full flex-col overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-900\",\n className,\n )}\n style={copy ? style : { ...style, userSelect: \"none\", WebkitUserSelect: \"none\" }}\n >\n {!print && <style>{PRINT_BLOCK_CSS}</style>}\n\n <div\n data-react-fancy-pdf-viewer-toolbar=\"\"\n className=\"flex shrink-0 items-center gap-1 border-b border-zinc-200 bg-[color:var(--fancy-surface,var(--color-white))] px-2 py-1 text-xs text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:border-zinc-800 dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]\"\n >\n <ToolButton attr=\"prev\" label=\"Previous page\" disabled={page <= 1} onClick={() => setPage(page - 1)}>\n <Chevron dir=\"up\" />\n </ToolButton>\n <span data-react-fancy-pdf-viewer-page-label=\"\" className=\"min-w-[3.5rem] text-center tabular-nums\" aria-live=\"polite\">\n {page} / {count}\n </span>\n <ToolButton attr=\"next\" label=\"Next page\" disabled={page >= count} onClick={() => setPage(page + 1)}>\n <Chevron dir=\"down\" />\n </ToolButton>\n <span className=\"mx-1 h-4 w-px bg-zinc-200 dark:bg-zinc-700\" aria-hidden=\"true\" />\n <ToolButton attr=\"zoom-out\" label=\"Zoom out\" disabled={zoom <= MIN_ZOOM} onClick={() => zoomTo(zoom / ZOOM_STEP)}>\n <span aria-hidden=\"true\">−</span>\n </ToolButton>\n <ToolButton attr=\"zoom-reset\" label=\"Reset zoom\" wide onClick={() => zoomTo(1)}>\n {Math.round(zoom * 100)}%\n </ToolButton>\n <ToolButton attr=\"zoom-in\" label=\"Zoom in\" disabled={zoom >= MAX_ZOOM} onClick={() => zoomTo(zoom * ZOOM_STEP)}>\n <span aria-hidden=\"true\">+</span>\n </ToolButton>\n <ToolButton attr=\"fit-width\" label=\"Fit width\" wide onClick={() => zoomTo(1)}>\n Width\n </ToolButton>\n <ToolButton attr=\"fit-page\" label=\"Fit page\" wide onClick={fitPage}>\n Page\n </ToolButton>\n </div>\n\n <div\n ref={scrollerRef}\n data-react-fancy-pdf-viewer-pages=\"\"\n tabIndex={0}\n onScroll={onScroll}\n onContextMenu={download ? undefined : block}\n onDragStart={download ? undefined : block}\n className=\"relative min-h-0 flex-1 overflow-auto outline-none transition-[filter] duration-150\"\n style={{ padding: GAP, filter: obscured ? \"blur(24px)\" : undefined }}\n >\n <div className=\"mx-auto flex flex-col\" style={{ width: `${zoom * 100}%`, gap: GAP }}>\n {Array.from({ length: count }, (_, i) => {\n const n = i + 1;\n return (\n <div\n key={n}\n data-react-fancy-pdf-viewer-page=\"\"\n data-page={n}\n className=\"relative w-full overflow-hidden bg-white shadow-sm\"\n style={{ aspectRatio: String(ratioOf(n)) }}\n >\n {isNear(n) && (\n <img\n data-react-fancy-pdf-viewer-image=\"\"\n src={pages.url(n, scale)}\n alt={`Page ${n}`}\n decoding=\"async\"\n draggable={download ? undefined : false}\n className=\"block h-full w-full\"\n onLoad={(e) => {\n const img = e.currentTarget;\n if (img.naturalWidth > 0 && img.naturalHeight > 0) {\n const r = img.naturalWidth / img.naturalHeight;\n setRatios((prev) => (prev[n] === r ? prev : { ...prev, [n]: r }));\n }\n }}\n />\n )}\n {watermark?.text && <Watermark id={`${markId}-${n}`} {...watermark} />}\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n },\n);\n\nPdfPages.displayName = \"PdfPages\";\n\n/** A tiled SVG pattern, so the text repeats at a constant size whatever the zoom. */\nfunction Watermark({ id, text, opacity = 0.15, angle = -30, density = 1 }: PdfViewerWatermark & { id: string }) {\n const fontSize = 14;\n const gap = 80 / Math.max(0.1, density);\n const w = text.length * fontSize * 0.55 + gap;\n const h = fontSize + gap;\n return (\n <svg\n data-react-fancy-pdf-viewer-watermark=\"\"\n aria-hidden=\"true\"\n className=\"absolute inset-0 h-full w-full select-none\"\n style={{ pointerEvents: \"none\" }}\n >\n <defs>\n <pattern id={id} width={w} height={h} patternUnits=\"userSpaceOnUse\" patternTransform={`rotate(${angle})`}>\n <text x={gap / 2} y={h / 2} fontSize={fontSize} fontFamily=\"ui-sans-serif, system-ui, sans-serif\" fillOpacity={clamp(opacity, 0, 1)}\n // The light-mode text role in both modes: page images are paper.\n style={{ fill: \"var(--fancy-text, var(--color-zinc-700))\" }}\n >\n {text}\n </text>\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${id})`} />\n </svg>\n );\n}\n\nfunction ToolButton({\n attr,\n label,\n disabled,\n wide,\n onClick,\n children,\n}: {\n attr: string;\n label: string;\n disabled?: boolean;\n wide?: boolean;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n {...{ [`data-react-fancy-pdf-viewer-${attr}`]: \"\" }}\n aria-label={label}\n title={label}\n disabled={disabled}\n onClick={onClick}\n className={cn(\n \"flex h-6 items-center justify-center rounded-full tabular-nums transition-colors disabled:pointer-events-none disabled:opacity-30\",\n \"hover:bg-zinc-900/5 hover:text-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 dark:hover:bg-white/10 dark:hover:text-zinc-200\",\n wide ? \"min-w-[2.25rem] px-1.5\" : \"w-6\",\n )}\n >\n {children}\n </button>\n );\n}\n\nfunction Chevron({ dir }: { dir: \"up\" | \"down\" }) {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d={dir === \"up\" ? \"m18 15-6-6-6 6\" : \"m6 9 6 6 6-6\"} />\n </svg>\n );\n}\n","import { forwardRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FauxClient } from \"../FauxClient\";\nimport { PdfPages } from \"./PdfPages\";\nimport type { PdfViewerProps } from \"./PdfViewer.types\";\n\n/**\n * A standalone PDF viewer — embeds the document via the browser's native PDF\n * plugin (`<object>`), falling back to an `<iframe>`, then to a download link.\n * Fills its container, so give it a height (a `min-h` floor is built in).\n * Renders for PDF sources inside `<MediaViewer>`.\n *\n * ```tsx\n * <PdfViewer src=\"/report.pdf\" title=\"report.pdf\" style={{ height: 600 }} />\n * ```\n *\n * With `pages` it shows page images the app rendered instead, and never\n * fetches or references the PDF; `policy` and `watermark` apply there.\n *\n * ```tsx\n * <PdfViewer\n * pages={{ count: 12, url: (n, scale) => `/docs/7/pages/${n}.png?scale=${scale}` }}\n * policy={{ download: false, print: false, copy: false, screenshot: \"deter\" }}\n * watermark={{ text: \"jane@example.com\" }}\n * />\n * ```\n */\nexport const PdfViewer = forwardRef<HTMLDivElement, PdfViewerProps>(\n (\n {\n src,\n pages,\n page,\n defaultPage,\n onPageChange,\n zoom,\n defaultZoom,\n onZoomChange,\n policy,\n watermark,\n title = \"PDF document\",\n className,\n style,\n frame = false,\n frameProps,\n },\n ref,\n ) => {\n if (pages) {\n // `src` is deliberately not passed on: in this mode the PDF is never\n // referenced, so it cannot leak through an attribute or a fallback link.\n const pageViewer = (\n <PdfPages\n ref={ref}\n pages={pages}\n page={page}\n defaultPage={defaultPage}\n onPageChange={onPageChange}\n zoom={zoom}\n defaultZoom={defaultZoom}\n onZoomChange={onZoomChange}\n policy={policy}\n watermark={watermark}\n title={title}\n className={cn(frame && \"rounded-none\", className)}\n style={style}\n />\n );\n if (!frame) return pageViewer;\n // Zoom lives on the viewer's own toolbar, which knows the page size; the\n // frame adds full screen.\n return (\n <FauxClient variant=\"browser\" url={title} controls={{ zoom: false }} fill {...frameProps}>\n {pageViewer}\n </FauxClient>\n );\n }\n\n const viewer = (\n <div\n ref={ref}\n data-react-fancy-pdf-viewer=\"\"\n className={cn(\n \"relative h-full min-h-[20rem] w-full overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-900\",\n className,\n )}\n style={style}\n >\n <object data={src} type=\"application/pdf\" className=\"h-full w-full\">\n <iframe\n src={src}\n title={title}\n className=\"h-full w-full border-0\"\n />\n <div className=\"flex h-full flex-col items-center justify-center gap-2 p-4 text-center text-sm text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]\">\n <span>This browser can't display the PDF inline.</span>\n <a\n href={src}\n download\n className=\"font-medium text-blue-600 hover:underline dark:text-blue-400\"\n >\n Download PDF\n </a>\n </div>\n </object>\n </div>\n );\n\n if (!frame) return viewer;\n\n // Full screen from the frame; zoom stays on the browser's PDF toolbar. A\n // plugin fits the page to its box, so scaling the box only re-fits it, and\n // the `#zoom=` open parameter is relative to the page's real size, which a\n // frame cannot know -- its bar would jump by uneven steps.\n return (\n // The browser variant, because the plugin swallows the pointer: hover over\n // the PDF never reaches the frame, so controls over it could not be\n // revealed, and its top-right corner is the PDF toolbar's. In the address\n // bar they are reachable and collide with nothing.\n <FauxClient variant=\"browser\" url={title} controls={{ zoom: false }} fill {...frameProps}>\n {viewer}\n </FauxClient>\n );\n },\n);\n\nPdfViewer.displayName = \"PdfViewer\";\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkI27K6NLX_cjs = require('./chunk-I27K6NLX.cjs');
|
|
3
4
|
var chunkJ2DI6RMR_cjs = require('./chunk-J2DI6RMR.cjs');
|
|
4
5
|
var chunkNBZC6LOB_cjs = require('./chunk-NBZC6LOB.cjs');
|
|
5
6
|
var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
|
|
@@ -24,12 +25,20 @@ var Tooltip = react.forwardRef(
|
|
|
24
25
|
clearTimeout(timeoutRef.current);
|
|
25
26
|
setOpen(false);
|
|
26
27
|
}, []);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
const child = children;
|
|
29
|
+
const childProps = child.props;
|
|
30
|
+
const childRef = childProps.ref;
|
|
31
|
+
const triggerRef = react.useMemo(() => chunkI27K6NLX_cjs.composeRefs(childRef, anchorRef), [childRef]);
|
|
32
|
+
const chain = (own, ours) => (event) => {
|
|
33
|
+
if (typeof own === "function") own(event);
|
|
34
|
+
ours();
|
|
35
|
+
};
|
|
36
|
+
const trigger = react.cloneElement(child, {
|
|
37
|
+
ref: triggerRef,
|
|
38
|
+
onMouseEnter: chain(childProps.onMouseEnter, show),
|
|
39
|
+
onMouseLeave: chain(childProps.onMouseLeave, hide),
|
|
40
|
+
onFocus: chain(childProps.onFocus, show),
|
|
41
|
+
onBlur: chain(childProps.onBlur, hide)
|
|
33
42
|
});
|
|
34
43
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
35
44
|
trigger,
|
|
@@ -70,5 +79,5 @@ var Tooltip = react.forwardRef(
|
|
|
70
79
|
Tooltip.displayName = "Tooltip";
|
|
71
80
|
|
|
72
81
|
exports.Tooltip = Tooltip;
|
|
73
|
-
//# sourceMappingURL=chunk-
|
|
74
|
-
//# sourceMappingURL=chunk-
|
|
82
|
+
//# sourceMappingURL=chunk-BJKKW77L.cjs.map
|
|
83
|
+
//# sourceMappingURL=chunk-BJKKW77L.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Tooltip/Tooltip.tsx"],"names":["forwardRef","Tooltip","useState","useRef","useFloatingPosition","useCallback","useMemo","composeRefs","cloneElement","jsxs","Fragment","Portal","cn","jsx"],"mappings":"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","file":"chunk-BJKKW77L.cjs","sourcesContent":["import {\n cloneElement,\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useState,\n type ReactElement,\n type Ref,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { composeRefs } from \"../../utils/compose-refs\";\nimport { Portal } from \"../Portal\";\nimport { useFloatingPosition } from \"../../hooks/use-floating-position\";\nimport type { TooltipProps } from \"./Tooltip.types\";\n\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(\n function Tooltip(\n { children, content, placement = \"top\", delay = 200, offset = 8, className },\n _ref,\n ) {\n const [open, setOpen] = useState(false);\n const anchorRef = useRef<HTMLElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n const position = useFloatingPosition(anchorRef, floatingRef, {\n placement,\n offset,\n enabled: open,\n });\n\n const show = useCallback(() => {\n timeoutRef.current = setTimeout(() => setOpen(true), delay);\n }, [delay]);\n\n const hide = useCallback(() => {\n clearTimeout(timeoutRef.current);\n setOpen(false);\n }, []);\n\n // The trigger is the caller's element, so its own ref and handlers have to\n // survive the clone. Overwriting them broke any child that needs its ref:\n // a <MultiSwitch> measures its thumb from it, and rendered with none.\n // className and every other prop are untouched — cloneElement keeps them.\n const child = children as ReactElement<Record<string, unknown>>;\n const childProps = child.props;\n const childRef = childProps.ref as Ref<HTMLElement> | undefined;\n const triggerRef = useMemo(() => composeRefs(childRef, anchorRef), [childRef]);\n const chain =\n (own: unknown, ours: () => void) =>\n (event: unknown) => {\n if (typeof own === \"function\") own(event);\n ours();\n };\n const trigger = cloneElement(child, {\n ref: triggerRef,\n onMouseEnter: chain(childProps.onMouseEnter, show),\n onMouseLeave: chain(childProps.onMouseLeave, hide),\n onFocus: chain(childProps.onFocus, show),\n onBlur: chain(childProps.onBlur, hide),\n });\n\n return (\n <>\n {trigger}\n {open && (\n <Portal>\n <div\n ref={floatingRef}\n data-react-fancy-tooltip=\"\"\n role=\"tooltip\"\n className={cn(\n \"fancy-fade-in pointer-events-none fixed z-50 max-w-xs rounded-lg bg-zinc-900 px-3 py-1.5 text-sm text-white shadow-lg dark:bg-zinc-700 dark:text-zinc-100\",\n className,\n )}\n style={{ left: position.x, top: position.y }}\n >\n {content}\n <div\n className={cn(\n // `bg-inherit`, not a colour of its own: a `className` that\n // restyles the bubble would otherwise leave a dark arrow\n // pointing out of a light one.\n \"absolute h-2 w-2 rotate-45 bg-inherit\",\n position.placement.startsWith(\"top\") &&\n \"bottom-[-4px] left-1/2 -translate-x-1/2\",\n position.placement.startsWith(\"bottom\") &&\n \"top-[-4px] left-1/2 -translate-x-1/2\",\n position.placement.startsWith(\"left\") &&\n \"right-[-4px] top-1/2 -translate-y-1/2\",\n position.placement.startsWith(\"right\") &&\n \"left-[-4px] top-1/2 -translate-y-1/2\",\n )}\n />\n </div>\n </Portal>\n )}\n </>\n );\n },\n);\n\nTooltip.displayName = \"Tooltip\";\n"]}
|