@embedpdf/react 3.0.0-next.14 → 3.0.0-next.16
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/dist/AnnotationList-DcyhF2kU-CiBFOq1z.d.cts +878 -0
- package/dist/AnnotationList-DcyhF2kU-CiBFOq1z.d.ts +878 -0
- package/dist/actions.cjs +25 -5
- package/dist/actions.cjs.map +1 -1
- package/dist/actions.d.cts +18 -5
- package/dist/actions.d.ts +18 -5
- package/dist/actions.js +22 -6
- package/dist/actions.js.map +1 -1
- package/dist/anchored-DeX95xSd.d.ts +85 -0
- package/dist/anchored-DzN3JywS.d.cts +85 -0
- package/dist/anchored.cjs +71 -28
- package/dist/anchored.cjs.map +1 -1
- package/dist/anchored.d.cts +2 -45
- package/dist/anchored.d.ts +2 -45
- package/dist/anchored.js +56 -19
- package/dist/anchored.js.map +1 -1
- package/dist/annotation-3UvABfJm.d.cts +305 -0
- package/dist/annotation-BNHQpMKv.cjs +806 -0
- package/dist/annotation-BNHQpMKv.cjs.map +1 -0
- package/dist/annotation-CDI8CFb3.js +684 -0
- package/dist/annotation-CDI8CFb3.js.map +1 -0
- package/dist/annotation-DhEfs0pH.d.ts +305 -0
- package/dist/annotation.cjs +20 -784
- package/dist/annotation.d.cts +2 -2
- package/dist/annotation.d.ts +2 -2
- package/dist/annotation.js +2 -769
- package/dist/attachment.cjs +39 -0
- package/dist/attachment.cjs.map +1 -0
- package/dist/attachment.d.cts +29 -0
- package/dist/attachment.d.ts +29 -0
- package/dist/attachment.js +28 -0
- package/dist/attachment.js.map +1 -0
- package/dist/commands.cjs +68 -28
- package/dist/commands.cjs.map +1 -1
- package/dist/commands.d.cts +37 -10
- package/dist/commands.d.ts +37 -10
- package/dist/commands.js +68 -31
- package/dist/commands.js.map +1 -1
- package/dist/form-BSGvjA5D.js +511 -0
- package/dist/form-BSGvjA5D.js.map +1 -0
- package/dist/form-BgztZyOK.cjs +548 -0
- package/dist/form-BgztZyOK.cjs.map +1 -0
- package/dist/form.cjs +5 -5
- package/dist/form.d.cts +41 -2
- package/dist/form.d.ts +41 -2
- package/dist/form.js +2 -3
- package/dist/history.cjs +38 -0
- package/dist/history.cjs.map +1 -0
- package/dist/history.d.cts +27 -0
- package/dist/history.d.ts +27 -0
- package/dist/history.js +27 -0
- package/dist/history.js.map +1 -0
- package/dist/i18n.cjs +26 -30
- package/dist/i18n.cjs.map +1 -1
- package/dist/i18n.d.cts +24 -21
- package/dist/i18n.d.ts +24 -21
- package/dist/i18n.js +24 -31
- package/dist/i18n.js.map +1 -1
- package/dist/index.cjs +227 -57
- package/dist/index.d.cts +35 -32
- package/dist/index.d.ts +35 -32
- package/dist/index.js +36 -30
- package/dist/inert-CmBEbKCn.cjs +19 -0
- package/dist/inert-CmBEbKCn.cjs.map +1 -0
- package/dist/inert-D8fkennb.js +14 -0
- package/dist/inert-D8fkennb.js.map +1 -0
- package/dist/interaction.cjs +48 -102
- package/dist/interaction.cjs.map +1 -1
- package/dist/interaction.d.cts +23 -32
- package/dist/interaction.d.ts +23 -32
- package/dist/interaction.js +33 -102
- package/dist/interaction.js.map +1 -1
- package/dist/link.cjs +65 -104
- package/dist/link.cjs.map +1 -1
- package/dist/link.d.cts +21 -16
- package/dist/link.d.ts +22 -17
- package/dist/link.js +67 -107
- package/dist/link.js.map +1 -1
- package/dist/measurement.cjs +36 -11
- package/dist/measurement.cjs.map +1 -1
- package/dist/measurement.d.cts +33 -7
- package/dist/measurement.d.ts +33 -7
- package/dist/measurement.js +35 -14
- package/dist/measurement.js.map +1 -1
- package/dist/metadata.cjs +20 -7
- package/dist/metadata.cjs.map +1 -1
- package/dist/metadata.d.cts +22 -7
- package/dist/metadata.d.ts +22 -7
- package/dist/metadata.js +20 -10
- package/dist/metadata.js.map +1 -1
- package/dist/outline.cjs +39 -0
- package/dist/outline.cjs.map +1 -0
- package/dist/outline.d.cts +31 -0
- package/dist/outline.d.ts +31 -0
- package/dist/outline.js +28 -0
- package/dist/outline.js.map +1 -0
- package/dist/page-edit.cjs +15 -3
- package/dist/page-edit.cjs.map +1 -1
- package/dist/page-edit.d.cts +17 -2
- package/dist/page-edit.d.ts +17 -2
- package/dist/page-edit.js +15 -5
- package/dist/page-edit.js.map +1 -1
- package/dist/page-layers-Bkaaz8Zf.js +26 -0
- package/dist/page-layers-Bkaaz8Zf.js.map +1 -0
- package/dist/page-layers-BloZDoOV.cjs +37 -0
- package/dist/page-layers-BloZDoOV.cjs.map +1 -0
- package/dist/page-view.cjs +89 -82
- package/dist/page-view.cjs.map +1 -1
- package/dist/page-view.d.cts +14 -7
- package/dist/page-view.d.ts +18 -11
- package/dist/page-view.js +86 -81
- package/dist/page-view.js.map +1 -1
- package/dist/redaction.cjs +30 -15
- package/dist/redaction.cjs.map +1 -1
- package/dist/redaction.d.cts +27 -9
- package/dist/redaction.d.ts +27 -9
- package/dist/redaction.js +29 -18
- package/dist/redaction.js.map +1 -1
- package/dist/render.cjs +71 -46
- package/dist/render.cjs.map +1 -1
- package/dist/render.d.cts +17 -5
- package/dist/render.d.ts +17 -5
- package/dist/render.js +70 -49
- package/dist/render.js.map +1 -1
- package/dist/runtime-BfnpyfY0.cjs +556 -0
- package/dist/runtime-BfnpyfY0.cjs.map +1 -0
- package/dist/runtime-DBEBlpQV.d.cts +237 -0
- package/dist/runtime-V3MVMb91.d.ts +237 -0
- package/dist/runtime-tD5iJU83.js +399 -0
- package/dist/runtime-tD5iJU83.js.map +1 -0
- package/dist/runtime.cjs +45 -324
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +2 -306
- package/dist/search.cjs +81 -50
- package/dist/search.cjs.map +1 -1
- package/dist/search.d.cts +37 -24
- package/dist/search.d.ts +37 -24
- package/dist/search.js +81 -53
- package/dist/search.js.map +1 -1
- package/dist/selection.cjs +105 -108
- package/dist/selection.cjs.map +1 -1
- package/dist/selection.d.cts +54 -26
- package/dist/selection.d.ts +56 -28
- package/dist/selection.js +103 -110
- package/dist/selection.js.map +1 -1
- package/dist/shell.cjs +36 -21
- package/dist/shell.cjs.map +1 -1
- package/dist/shell.d.cts +32 -17
- package/dist/shell.d.ts +32 -17
- package/dist/shell.js +36 -24
- package/dist/shell.js.map +1 -1
- package/dist/signature.cjs +29 -48
- package/dist/signature.cjs.map +1 -1
- package/dist/signature.d.cts +26 -26
- package/dist/signature.d.ts +26 -26
- package/dist/signature.js +30 -48
- package/dist/signature.js.map +1 -1
- package/dist/stage-B7BG2e8Q.cjs +369 -0
- package/dist/stage-B7BG2e8Q.cjs.map +1 -0
- package/dist/stage-BqfBjDu6.js +302 -0
- package/dist/stage-BqfBjDu6.js.map +1 -0
- package/dist/stage-ByFPD-Fv.d.cts +117 -0
- package/dist/stage-DaboaheR.d.ts +117 -0
- package/dist/stage-scope-CQgCuf1w.cjs +46 -0
- package/dist/stage-scope-CQgCuf1w.cjs.map +1 -0
- package/dist/stage-scope-D7ZeNduT.js +23 -0
- package/dist/stage-scope-D7ZeNduT.js.map +1 -0
- package/dist/stage.cjs +12 -235
- package/dist/stage.d.cts +2 -116
- package/dist/stage.d.ts +2 -116
- package/dist/stage.js +3 -228
- package/dist/stamp.cjs +41 -35
- package/dist/stamp.cjs.map +1 -1
- package/dist/stamp.d.cts +25 -18
- package/dist/stamp.d.ts +25 -18
- package/dist/stamp.js +40 -37
- package/dist/stamp.js.map +1 -1
- package/dist/state-0K1I5cM4.d.cts +29 -0
- package/dist/state-0K1I5cM4.d.ts +29 -0
- package/dist/state-CzI2KlZb.js +62 -0
- package/dist/state-CzI2KlZb.js.map +1 -0
- package/dist/state-Dtf8HAue.cjs +73 -0
- package/dist/state-Dtf8HAue.cjs.map +1 -0
- package/dist/svg-shapes-Dm1yTR1b.js +40 -0
- package/dist/svg-shapes-Dm1yTR1b.js.map +1 -0
- package/dist/svg-shapes-zo0GNkc9.cjs +53 -0
- package/dist/svg-shapes-zo0GNkc9.cjs.map +1 -0
- package/dist/toolbar.cjs +297 -295
- package/dist/toolbar.cjs.map +1 -1
- package/dist/toolbar.d.cts +58 -68
- package/dist/toolbar.d.ts +67 -77
- package/dist/toolbar.js +271 -293
- package/dist/toolbar.js.map +1 -1
- package/dist/view-manager.cjs +34 -0
- package/dist/view-manager.cjs.map +1 -0
- package/dist/view-manager.d.cts +21 -0
- package/dist/view-manager.d.ts +21 -0
- package/dist/view-manager.js +23 -0
- package/dist/view-manager.js.map +1 -0
- package/package.json +47 -39
- package/dist/annotation-BCED_p9H.d.cts +0 -160
- package/dist/annotation-anchors-CetwM1g7.js +0 -15
- package/dist/annotation-anchors-CetwM1g7.js.map +0 -1
- package/dist/annotation-anchors-DuYRBJLl.cjs +0 -26
- package/dist/annotation-anchors-DuYRBJLl.cjs.map +0 -1
- package/dist/annotation-hooks-BB5ZhPpf.cjs +0 -16
- package/dist/annotation-hooks-BB5ZhPpf.cjs.map +0 -1
- package/dist/annotation-hooks-Df8EmzDO.js +0 -11
- package/dist/annotation-hooks-Df8EmzDO.js.map +0 -1
- package/dist/annotation-k38KDlIZ.d.ts +0 -160
- package/dist/annotation-menu.cjs +0 -64
- package/dist/annotation-menu.cjs.map +0 -1
- package/dist/annotation-menu.d.cts +0 -33
- package/dist/annotation-menu.d.ts +0 -33
- package/dist/annotation-menu.js +0 -48
- package/dist/annotation-menu.js.map +0 -1
- package/dist/annotation.cjs.map +0 -1
- package/dist/annotation.js.map +0 -1
- package/dist/form-BVumS7up.cjs +0 -926
- package/dist/form-BVumS7up.cjs.map +0 -1
- package/dist/form-Bdjk0Z3T.d.cts +0 -537
- package/dist/form-CK3mp99m.js +0 -895
- package/dist/form-CK3mp99m.js.map +0 -1
- package/dist/form-CYRYgthn.d.ts +0 -537
- package/dist/rolldown-runtime-BBjsoOtd.js +0 -27
- package/dist/runtime-DE76hlnl.d.ts +0 -216
- package/dist/runtime-umHA_xHt.d.cts +0 -216
- package/dist/runtime.cjs.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/scrollbar.cjs +0 -241
- package/dist/scrollbar.cjs.map +0 -1
- package/dist/scrollbar.d.cts +0 -42
- package/dist/scrollbar.d.ts +0 -42
- package/dist/scrollbar.js +0 -213
- package/dist/scrollbar.js.map +0 -1
- package/dist/stage.cjs.map +0 -1
- package/dist/stage.js.map +0 -1
- package/dist/views.cjs +0 -35
- package/dist/views.cjs.map +0 -1
- package/dist/views.d.cts +0 -21
- package/dist/views.d.ts +0 -21
- package/dist/views.js +0 -27
- package/dist/views.js.map +0 -1
package/dist/scrollbar.cjs
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_rolldown_runtime = require("./rolldown-runtime-DDXJien1.cjs");
|
|
3
|
-
const require_runtime = require("./runtime.cjs");
|
|
4
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
-
let react = require("react");
|
|
6
|
-
react = require_rolldown_runtime.__toESM(react, 1);
|
|
7
|
-
let _embedpdf_plugin_stage_contract = require("@embedpdf/plugin-stage/contract");
|
|
8
|
-
//#region src/scrollbar.tsx
|
|
9
|
-
/**
|
|
10
|
-
* Headless scrollbar for a Stage lens — a pure view of `stage.scrollMetrics()`.
|
|
11
|
-
*
|
|
12
|
-
* The Stage exposes the native scroller contract (scrollTop/scrollHeight/
|
|
13
|
-
* clientHeight, in screen px — see plugin-stage's README); this component turns
|
|
14
|
-
* it into a native-feeling bar: thumb drag with pointer capture and a preserved
|
|
15
|
-
* grab point, track paging with press-and-hold repeat that stops at the
|
|
16
|
-
* pointer, a minimum thumb length on long documents, and macOS-style overlay
|
|
17
|
-
* auto-hide. On an UNBOUNDED stage the metrics already carry the Figma
|
|
18
|
-
* semantics (the range is the union of content and view), so the same bar
|
|
19
|
-
* shrinks toward the edge as you pan away and rides you back — the mapping is
|
|
20
|
-
* FROZEN for the duration of a thumb drag so the thumb never chases itself
|
|
21
|
-
* while the union re-collapses.
|
|
22
|
-
*
|
|
23
|
-
* Headless styling contract: geometry and behavior live here; looks live in
|
|
24
|
-
* your CSS. Style via `className`/`thumbClassName` (or the style props) against
|
|
25
|
-
* [data-embedpdf-scrollbar][data-axis="y"][data-state="visible|hidden"]
|
|
26
|
-
* [data-embedpdf-scrollbar][data-dragging]
|
|
27
|
-
* [data-embedpdf-scrollbar-thumb]
|
|
28
|
-
* The defaults are deliberately minimal: a transparent track pinned to the
|
|
29
|
-
* viewport edge and a `var(--epdf-scrollbar-thumb, …)` pill, so the bar works
|
|
30
|
-
* unstyled and disappears into any theme. Build something else entirely
|
|
31
|
-
* (minimap, progress ring) from `useScrollMetrics()` + `stage.scrollTo()`.
|
|
32
|
-
*/
|
|
33
|
-
/** Live scroll metrics for a stage lens (reference-stable; see
|
|
34
|
-
* `StageCapability.scrollMetrics`). The raw material for custom scroll UI. */
|
|
35
|
-
function useScrollMetrics(token = _embedpdf_plugin_stage_contract.StageToken) {
|
|
36
|
-
return require_runtime.useSelector(token, (c) => c.scrollMetrics());
|
|
37
|
-
}
|
|
38
|
-
const clamp01 = (v) => Math.min(1, Math.max(0, v));
|
|
39
|
-
/** Best-effort pointer capture: an already-released pointer (pen/touch races,
|
|
40
|
-
* synthetic events in tests) throws NotFoundError — the press must still work,
|
|
41
|
-
* just without capture (moves keep arriving while the pointer stays on us). */
|
|
42
|
-
const capturePointer = (el, pointerId) => {
|
|
43
|
-
try {
|
|
44
|
-
el.setPointerCapture(pointerId);
|
|
45
|
-
} catch {}
|
|
46
|
-
};
|
|
47
|
-
/** Thumb geometry from metrics + a measured track. One formula for render,
|
|
48
|
-
* drag capture, and paging — they can never disagree. */
|
|
49
|
-
const geometry = (m, vertical, trackPx, minThumbSize) => {
|
|
50
|
-
const client = vertical ? m.clientHeight : m.clientWidth;
|
|
51
|
-
const total = vertical ? m.scrollHeight : m.scrollWidth;
|
|
52
|
-
const offset = vertical ? m.scrollTop : m.scrollLeft;
|
|
53
|
-
const maxOffset = Math.max(0, total - client);
|
|
54
|
-
const thumbLen = Math.min(trackPx, Math.max(minThumbSize, total > 0 ? client / total * trackPx : 0));
|
|
55
|
-
const travel = Math.max(0, trackPx - thumbLen);
|
|
56
|
-
return {
|
|
57
|
-
client,
|
|
58
|
-
offset,
|
|
59
|
-
maxOffset,
|
|
60
|
-
thumbLen,
|
|
61
|
-
travel,
|
|
62
|
-
thumbPos: maxOffset > 0 ? offset / maxOffset * travel : 0
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
function Scrollbar({ axis, token = _embedpdf_plugin_stage_contract.StageToken, autoHide = 1200, minThumbSize = 24, trackPress = "page", className, style, thumbClassName, thumbStyle }) {
|
|
66
|
-
const stage = require_runtime.useCapability(token);
|
|
67
|
-
const m = useScrollMetrics(token);
|
|
68
|
-
const vertical = axis === "y";
|
|
69
|
-
const scrollable = vertical ? m.scrollableY : m.scrollableX;
|
|
70
|
-
const trackRef = (0, react.useRef)(null);
|
|
71
|
-
const [trackPx, setTrackPx] = (0, react.useState)(0);
|
|
72
|
-
const [dragging, setDragging] = (0, react.useState)(false);
|
|
73
|
-
const [hovered, setHovered] = (0, react.useState)(false);
|
|
74
|
-
const [active, setActive] = (0, react.useState)(true);
|
|
75
|
-
const g = geometry(m, vertical, trackPx, minThumbSize);
|
|
76
|
-
const hideAfter = autoHide === false ? 0 : autoHide;
|
|
77
|
-
(0, react.useEffect)(() => {
|
|
78
|
-
if (!hideAfter) return;
|
|
79
|
-
setActive(true);
|
|
80
|
-
const t = setTimeout(() => setActive(false), hideAfter);
|
|
81
|
-
return () => clearTimeout(t);
|
|
82
|
-
}, [m, hideAfter]);
|
|
83
|
-
const shown = !hideAfter || active || hovered || dragging;
|
|
84
|
-
(0, react.useEffect)(() => {
|
|
85
|
-
const el = trackRef.current;
|
|
86
|
-
if (!el) return;
|
|
87
|
-
const measure = () => setTrackPx(vertical ? el.clientHeight : el.clientWidth);
|
|
88
|
-
const ro = new ResizeObserver(measure);
|
|
89
|
-
ro.observe(el);
|
|
90
|
-
measure();
|
|
91
|
-
return () => ro.disconnect();
|
|
92
|
-
}, [vertical, scrollable]);
|
|
93
|
-
const dragRef = (0, react.useRef)(null);
|
|
94
|
-
const pageRef = (0, react.useRef)(null);
|
|
95
|
-
const lastPtr = (0, react.useRef)(0);
|
|
96
|
-
const ptrPos = (e) => {
|
|
97
|
-
const r = trackRef.current.getBoundingClientRect();
|
|
98
|
-
return vertical ? e.clientY - r.top : e.clientX - r.left;
|
|
99
|
-
};
|
|
100
|
-
/** Fresh geometry for paging steps — read from the capability, never a stale render. */
|
|
101
|
-
const liveGeometry = () => geometry(stage.scrollMetrics(), vertical, trackPx, minThumbSize);
|
|
102
|
-
const stopPaging = () => {
|
|
103
|
-
if (pageRef.current) {
|
|
104
|
-
clearTimeout(pageRef.current.timer);
|
|
105
|
-
clearInterval(pageRef.current.timer);
|
|
106
|
-
pageRef.current = null;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const endDrag = () => {
|
|
110
|
-
dragRef.current = null;
|
|
111
|
-
stopPaging();
|
|
112
|
-
setDragging(false);
|
|
113
|
-
};
|
|
114
|
-
const beginDrag = (grab, applied) => {
|
|
115
|
-
dragRef.current = {
|
|
116
|
-
grab,
|
|
117
|
-
applied,
|
|
118
|
-
max: g.maxOffset,
|
|
119
|
-
travel: g.travel
|
|
120
|
-
};
|
|
121
|
-
setDragging(true);
|
|
122
|
-
};
|
|
123
|
-
const onThumbDown = (e) => {
|
|
124
|
-
if (e.button !== 0) return;
|
|
125
|
-
e.preventDefault();
|
|
126
|
-
e.stopPropagation();
|
|
127
|
-
capturePointer(e.target, e.pointerId);
|
|
128
|
-
beginDrag(ptrPos(e) - g.thumbPos, g.offset);
|
|
129
|
-
};
|
|
130
|
-
const onTrackDown = (e) => {
|
|
131
|
-
if (e.button !== 0 || e.target !== e.currentTarget) return;
|
|
132
|
-
e.preventDefault();
|
|
133
|
-
capturePointer(e.currentTarget, e.pointerId);
|
|
134
|
-
const p = lastPtr.current = ptrPos(e);
|
|
135
|
-
if (trackPress === "jump") {
|
|
136
|
-
const want = g.travel > 0 ? clamp01((p - g.thumbLen / 2) / g.travel) * g.maxOffset : 0;
|
|
137
|
-
stage.scrollTo(vertical ? { top: want } : { left: want });
|
|
138
|
-
beginDrag(g.thumbLen / 2, want);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const dir = p < g.thumbPos ? -1 : 1;
|
|
142
|
-
const step = () => {
|
|
143
|
-
const live = liveGeometry();
|
|
144
|
-
if (dir === 1 ? lastPtr.current <= live.thumbPos + live.thumbLen : lastPtr.current >= live.thumbPos) return stopPaging();
|
|
145
|
-
stage.scrollBy(vertical ? { top: dir * live.client * .9 } : { left: dir * live.client * .9 });
|
|
146
|
-
};
|
|
147
|
-
step();
|
|
148
|
-
const timer = window.setTimeout(() => {
|
|
149
|
-
if (!pageRef.current) return;
|
|
150
|
-
pageRef.current.timer = window.setInterval(step, 80);
|
|
151
|
-
}, 350);
|
|
152
|
-
pageRef.current = {
|
|
153
|
-
dir,
|
|
154
|
-
timer
|
|
155
|
-
};
|
|
156
|
-
};
|
|
157
|
-
const onMove = (e) => {
|
|
158
|
-
const d = dragRef.current;
|
|
159
|
-
if (d) {
|
|
160
|
-
if (d.travel <= 0) return;
|
|
161
|
-
const want = clamp01((ptrPos(e) - d.grab) / d.travel) * d.max;
|
|
162
|
-
const delta = want - d.applied;
|
|
163
|
-
if (delta) {
|
|
164
|
-
stage.panBy(vertical ? 0 : -delta, vertical ? -delta : 0);
|
|
165
|
-
d.applied = want;
|
|
166
|
-
}
|
|
167
|
-
} else if (pageRef.current) lastPtr.current = ptrPos(e);
|
|
168
|
-
};
|
|
169
|
-
(0, react.useEffect)(() => endDrag, []);
|
|
170
|
-
if (!scrollable) return null;
|
|
171
|
-
const trackDefaults = vertical ? {
|
|
172
|
-
position: "absolute",
|
|
173
|
-
top: 0,
|
|
174
|
-
right: 0,
|
|
175
|
-
bottom: 0,
|
|
176
|
-
width: 12
|
|
177
|
-
} : {
|
|
178
|
-
position: "absolute",
|
|
179
|
-
left: 0,
|
|
180
|
-
right: 0,
|
|
181
|
-
bottom: 0,
|
|
182
|
-
height: 12
|
|
183
|
-
};
|
|
184
|
-
const thumbDefaults = vertical ? {
|
|
185
|
-
position: "absolute",
|
|
186
|
-
left: 2,
|
|
187
|
-
right: 2,
|
|
188
|
-
top: g.thumbPos,
|
|
189
|
-
height: g.thumbLen
|
|
190
|
-
} : {
|
|
191
|
-
position: "absolute",
|
|
192
|
-
top: 2,
|
|
193
|
-
bottom: 2,
|
|
194
|
-
left: g.thumbPos,
|
|
195
|
-
width: g.thumbLen
|
|
196
|
-
};
|
|
197
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
198
|
-
ref: trackRef,
|
|
199
|
-
role: "scrollbar",
|
|
200
|
-
"aria-orientation": vertical ? "vertical" : "horizontal",
|
|
201
|
-
"aria-valuemin": 0,
|
|
202
|
-
"aria-valuemax": Math.round(g.maxOffset),
|
|
203
|
-
"aria-valuenow": Math.round(g.offset),
|
|
204
|
-
"data-embedpdf-scrollbar": "",
|
|
205
|
-
"data-axis": axis,
|
|
206
|
-
"data-state": shown ? "visible" : "hidden",
|
|
207
|
-
"data-dragging": dragging ? "" : void 0,
|
|
208
|
-
className,
|
|
209
|
-
style: {
|
|
210
|
-
...trackDefaults,
|
|
211
|
-
touchAction: "none",
|
|
212
|
-
userSelect: "none",
|
|
213
|
-
opacity: shown ? 1 : 0,
|
|
214
|
-
transition: "opacity 200ms",
|
|
215
|
-
pointerEvents: shown ? "auto" : "none",
|
|
216
|
-
...style
|
|
217
|
-
},
|
|
218
|
-
onPointerDown: onTrackDown,
|
|
219
|
-
onPointerMove: onMove,
|
|
220
|
-
onPointerUp: endDrag,
|
|
221
|
-
onPointerCancel: endDrag,
|
|
222
|
-
onPointerEnter: () => setHovered(true),
|
|
223
|
-
onPointerLeave: () => setHovered(false),
|
|
224
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
225
|
-
"data-embedpdf-scrollbar-thumb": "",
|
|
226
|
-
className: thumbClassName,
|
|
227
|
-
style: {
|
|
228
|
-
...thumbDefaults,
|
|
229
|
-
borderRadius: 6,
|
|
230
|
-
background: "var(--epdf-scrollbar-thumb, rgba(0, 0, 0, 0.4))",
|
|
231
|
-
...thumbStyle
|
|
232
|
-
},
|
|
233
|
-
onPointerDown: onThumbDown
|
|
234
|
-
})
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
//#endregion
|
|
238
|
-
exports.Scrollbar = Scrollbar;
|
|
239
|
-
exports.useScrollMetrics = useScrollMetrics;
|
|
240
|
-
|
|
241
|
-
//# sourceMappingURL=scrollbar.cjs.map
|
package/dist/scrollbar.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scrollbar.cjs","names":["StageToken","useSelector","useCapability"],"sources":["../src/scrollbar.tsx"],"sourcesContent":["/**\n * Headless scrollbar for a Stage lens — a pure view of `stage.scrollMetrics()`.\n *\n * The Stage exposes the native scroller contract (scrollTop/scrollHeight/\n * clientHeight, in screen px — see plugin-stage's README); this component turns\n * it into a native-feeling bar: thumb drag with pointer capture and a preserved\n * grab point, track paging with press-and-hold repeat that stops at the\n * pointer, a minimum thumb length on long documents, and macOS-style overlay\n * auto-hide. On an UNBOUNDED stage the metrics already carry the Figma\n * semantics (the range is the union of content and view), so the same bar\n * shrinks toward the edge as you pan away and rides you back — the mapping is\n * FROZEN for the duration of a thumb drag so the thumb never chases itself\n * while the union re-collapses.\n *\n * Headless styling contract: geometry and behavior live here; looks live in\n * your CSS. Style via `className`/`thumbClassName` (or the style props) against\n * [data-embedpdf-scrollbar][data-axis=\"y\"][data-state=\"visible|hidden\"]\n * [data-embedpdf-scrollbar][data-dragging]\n * [data-embedpdf-scrollbar-thumb]\n * The defaults are deliberately minimal: a transparent track pinned to the\n * viewport edge and a `var(--epdf-scrollbar-thumb, …)` pill, so the bar works\n * unstyled and disappears into any theme. Build something else entirely\n * (minimap, progress ring) from `useScrollMetrics()` + `stage.scrollTo()`.\n */\n\nimport * as React from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\nimport type { ScrollMetrics, StageCapability } from '@embedpdf/plugin-stage/contract';\nimport type { CapabilityToken } from '@embedpdf/core';\nimport { useCapability, useSelector } from './runtime';\n\nexport type ScrollbarAxis = 'x' | 'y';\n\n/** Live scroll metrics for a stage lens (reference-stable; see\n * `StageCapability.scrollMetrics`). The raw material for custom scroll UI. */\nexport function useScrollMetrics(\n token: CapabilityToken<StageCapability> = StageToken,\n): ScrollMetrics {\n return useSelector(token, (c) => c.scrollMetrics());\n}\n\nexport interface ScrollbarProps {\n axis: ScrollbarAxis;\n /** The stage lens to scroll (default: the main StageToken). */\n token?: CapabilityToken<StageCapability>;\n /**\n * Overlay auto-hide: fade `autoHide` ms after the camera stops moving\n * (drags and hover pin it visible; a hidden bar ignores the pointer, like\n * macOS). `false` = always visible. Visibility is published as\n * `data-state=\"visible|hidden\"` — the default style fades opacity; replace\n * it in CSS for any other treatment. Default 1200.\n */\n autoHide?: number | false;\n /** Minimum thumb length in px — native bars never vanish on long documents.\n * Position stays proportional via the standard travel remap. Default 24. */\n minThumbSize?: number;\n /**\n * Pressing the track: 'page' steps by 90% of a viewport toward the pointer,\n * repeats while held, and stops when the thumb reaches the pointer (the\n * native default); 'jump' centers the thumb at the pointer and hands off to\n * a drag (the macOS option-click / Figma feel). Default 'page'.\n */\n trackPress?: 'page' | 'jump';\n /** Track class/style. The default style pins the bar to the right (y) or\n * bottom (x) edge of the nearest positioned ancestor — the Stage container\n * when rendered in its `overlay`; override to place it anywhere else. */\n className?: string;\n style?: React.CSSProperties;\n thumbClassName?: string;\n thumbStyle?: React.CSSProperties;\n}\n\nconst clamp01 = (v: number) => Math.min(1, Math.max(0, v));\n\n/** Best-effort pointer capture: an already-released pointer (pen/touch races,\n * synthetic events in tests) throws NotFoundError — the press must still work,\n * just without capture (moves keep arriving while the pointer stays on us). */\nconst capturePointer = (el: Element, pointerId: number) => {\n try {\n el.setPointerCapture(pointerId);\n } catch {\n /* uncaptured is fine */\n }\n};\n\n/** Thumb geometry from metrics + a measured track. One formula for render,\n * drag capture, and paging — they can never disagree. */\nconst geometry = (m: ScrollMetrics, vertical: boolean, trackPx: number, minThumbSize: number) => {\n const client = vertical ? m.clientHeight : m.clientWidth;\n const total = vertical ? m.scrollHeight : m.scrollWidth;\n const offset = vertical ? m.scrollTop : m.scrollLeft;\n const maxOffset = Math.max(0, total - client);\n const thumbLen = Math.min(\n trackPx,\n Math.max(minThumbSize, total > 0 ? (client / total) * trackPx : 0),\n );\n const travel = Math.max(0, trackPx - thumbLen);\n const thumbPos = maxOffset > 0 ? (offset / maxOffset) * travel : 0;\n return { client, offset, maxOffset, thumbLen, travel, thumbPos };\n};\n\nexport function Scrollbar({\n axis,\n token = StageToken,\n autoHide = 1200,\n minThumbSize = 24,\n trackPress = 'page',\n className,\n style,\n thumbClassName,\n thumbStyle,\n}: ScrollbarProps) {\n const stage = useCapability(token);\n const m = useScrollMetrics(token);\n const vertical = axis === 'y';\n const scrollable = vertical ? m.scrollableY : m.scrollableX;\n\n const trackRef = useRef<HTMLDivElement>(null);\n const [trackPx, setTrackPx] = useState(0);\n const [dragging, setDragging] = useState(false);\n const [hovered, setHovered] = useState(false);\n const [active, setActive] = useState(true); // camera moved recently\n\n const g = geometry(m, vertical, trackPx, minThumbSize);\n\n // ── overlay auto-hide: any metrics change re-arms the fade timer ──────────\n const hideAfter = autoHide === false ? 0 : autoHide;\n useEffect(() => {\n if (!hideAfter) return;\n setActive(true);\n const t = setTimeout(() => setActive(false), hideAfter);\n return () => clearTimeout(t);\n }, [m, hideAfter]);\n const shown = !hideAfter || active || hovered || dragging;\n\n // ── track measurement (px mapping needs real geometry) ────────────────────\n useEffect(() => {\n const el = trackRef.current;\n if (!el) return;\n const measure = () => setTrackPx(vertical ? el.clientHeight : el.clientWidth);\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n measure();\n return () => ro.disconnect();\n }, [vertical, scrollable]);\n\n // ── interactions. Drag state is FROZEN at pointer-down (grab point, travel,\n // max offset) and applied as relative pans — absolute-feeling in bounded\n // mode (the range is static there) and stable in unbounded mode, where\n // the live union would otherwise shift under the pointer mid-drag. ──────\n const dragRef = useRef<{ grab: number; applied: number; max: number; travel: number } | null>(\n null,\n );\n const pageRef = useRef<{ dir: 1 | -1; timer: number } | null>(null);\n const lastPtr = useRef(0);\n\n const ptrPos = (e: React.PointerEvent) => {\n const r = trackRef.current!.getBoundingClientRect();\n return vertical ? e.clientY - r.top : e.clientX - r.left;\n };\n /** Fresh geometry for paging steps — read from the capability, never a stale render. */\n const liveGeometry = () => geometry(stage.scrollMetrics(), vertical, trackPx, minThumbSize);\n\n const stopPaging = () => {\n if (pageRef.current) {\n clearTimeout(pageRef.current.timer);\n clearInterval(pageRef.current.timer);\n pageRef.current = null;\n }\n };\n const endDrag = () => {\n dragRef.current = null;\n stopPaging();\n setDragging(false);\n };\n\n const beginDrag = (grab: number, applied: number) => {\n dragRef.current = { grab, applied, max: g.maxOffset, travel: g.travel };\n setDragging(true);\n };\n\n const onThumbDown = (e: React.PointerEvent) => {\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n capturePointer(e.target as Element, e.pointerId);\n beginDrag(ptrPos(e) - g.thumbPos, g.offset);\n };\n\n const onTrackDown = (e: React.PointerEvent) => {\n if (e.button !== 0 || e.target !== e.currentTarget) return; // thumb handles its own\n e.preventDefault();\n capturePointer(e.currentTarget as Element, e.pointerId);\n const p = (lastPtr.current = ptrPos(e));\n\n if (trackPress === 'jump') {\n // land the thumb centered at the pointer, then it's an ordinary drag\n const want = g.travel > 0 ? clamp01((p - g.thumbLen / 2) / g.travel) * g.maxOffset : 0;\n stage.scrollTo(vertical ? { top: want } : { left: want });\n beginDrag(g.thumbLen / 2, want);\n return;\n }\n\n // 'page': step toward the pointer, repeat while held, stop at the pointer\n const dir: 1 | -1 = p < g.thumbPos ? -1 : 1;\n const step = () => {\n const live = liveGeometry();\n const reached =\n dir === 1\n ? lastPtr.current <= live.thumbPos + live.thumbLen\n : lastPtr.current >= live.thumbPos;\n if (reached) return stopPaging();\n stage.scrollBy(\n vertical ? { top: dir * live.client * 0.9 } : { left: dir * live.client * 0.9 },\n );\n };\n step();\n // native cadence: a beat before the repeat kicks in, then a steady march\n const timer = window.setTimeout(() => {\n if (!pageRef.current) return;\n pageRef.current.timer = window.setInterval(step, 80);\n }, 350);\n pageRef.current = { dir, timer };\n };\n\n // Pointer capture retargets to the pressed element and bubbles here — one\n // move/up pair serves thumb drags, jump-drags, and paging alike.\n const onMove = (e: React.PointerEvent) => {\n const d = dragRef.current;\n if (d) {\n if (d.travel <= 0) return;\n const want = clamp01((ptrPos(e) - d.grab) / d.travel) * d.max;\n const delta = want - d.applied;\n if (delta) {\n stage.panBy(vertical ? 0 : -delta, vertical ? -delta : 0);\n d.applied = want;\n }\n } else if (pageRef.current) {\n lastPtr.current = ptrPos(e);\n }\n };\n\n useEffect(() => endDrag, []); // unmount: no orphaned repeat timers\n\n if (!scrollable) return null;\n\n const trackDefaults: React.CSSProperties = vertical\n ? { position: 'absolute', top: 0, right: 0, bottom: 0, width: 12 }\n : { position: 'absolute', left: 0, right: 0, bottom: 0, height: 12 };\n const thumbDefaults: React.CSSProperties = vertical\n ? { position: 'absolute', left: 2, right: 2, top: g.thumbPos, height: g.thumbLen }\n : { position: 'absolute', top: 2, bottom: 2, left: g.thumbPos, width: g.thumbLen };\n\n return (\n <div\n ref={trackRef}\n role=\"scrollbar\"\n aria-orientation={vertical ? 'vertical' : 'horizontal'}\n aria-valuemin={0}\n aria-valuemax={Math.round(g.maxOffset)}\n aria-valuenow={Math.round(g.offset)}\n data-embedpdf-scrollbar=\"\"\n data-axis={axis}\n data-state={shown ? 'visible' : 'hidden'}\n data-dragging={dragging ? '' : undefined}\n className={className}\n style={{\n ...trackDefaults,\n touchAction: 'none',\n userSelect: 'none',\n opacity: shown ? 1 : 0,\n transition: 'opacity 200ms',\n // a hidden overlay bar must not eat the clicks under it\n pointerEvents: shown ? 'auto' : 'none',\n ...style,\n }}\n onPointerDown={onTrackDown}\n onPointerMove={onMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onPointerEnter={() => setHovered(true)}\n onPointerLeave={() => setHovered(false)}\n >\n <div\n data-embedpdf-scrollbar-thumb=\"\"\n className={thumbClassName}\n style={{\n ...thumbDefaults,\n borderRadius: 6,\n background: 'var(--epdf-scrollbar-thumb, rgba(0, 0, 0, 0.4))',\n ...thumbStyle,\n }}\n onPointerDown={onThumbDown}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
package/dist/scrollbar.d.cts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { CapabilityToken } from "@embedpdf/core";
|
|
3
|
-
import { ScrollMetrics, StageCapability } from "@embedpdf/plugin-stage/contract";
|
|
4
|
-
//#region src/scrollbar.d.ts
|
|
5
|
-
type ScrollbarAxis = 'x' | 'y';
|
|
6
|
-
/** Live scroll metrics for a stage lens (reference-stable; see
|
|
7
|
-
* `StageCapability.scrollMetrics`). The raw material for custom scroll UI. */
|
|
8
|
-
declare function useScrollMetrics(token?: CapabilityToken<StageCapability>): ScrollMetrics;
|
|
9
|
-
interface ScrollbarProps {
|
|
10
|
-
axis: ScrollbarAxis;
|
|
11
|
-
/** The stage lens to scroll (default: the main StageToken). */
|
|
12
|
-
token?: CapabilityToken<StageCapability>;
|
|
13
|
-
/**
|
|
14
|
-
* Overlay auto-hide: fade `autoHide` ms after the camera stops moving
|
|
15
|
-
* (drags and hover pin it visible; a hidden bar ignores the pointer, like
|
|
16
|
-
* macOS). `false` = always visible. Visibility is published as
|
|
17
|
-
* `data-state="visible|hidden"` — the default style fades opacity; replace
|
|
18
|
-
* it in CSS for any other treatment. Default 1200.
|
|
19
|
-
*/
|
|
20
|
-
autoHide?: number | false;
|
|
21
|
-
/** Minimum thumb length in px — native bars never vanish on long documents.
|
|
22
|
-
* Position stays proportional via the standard travel remap. Default 24. */
|
|
23
|
-
minThumbSize?: number;
|
|
24
|
-
/**
|
|
25
|
-
* Pressing the track: 'page' steps by 90% of a viewport toward the pointer,
|
|
26
|
-
* repeats while held, and stops when the thumb reaches the pointer (the
|
|
27
|
-
* native default); 'jump' centers the thumb at the pointer and hands off to
|
|
28
|
-
* a drag (the macOS option-click / Figma feel). Default 'page'.
|
|
29
|
-
*/
|
|
30
|
-
trackPress?: 'page' | 'jump';
|
|
31
|
-
/** Track class/style. The default style pins the bar to the right (y) or
|
|
32
|
-
* bottom (x) edge of the nearest positioned ancestor — the Stage container
|
|
33
|
-
* when rendered in its `overlay`; override to place it anywhere else. */
|
|
34
|
-
className?: string;
|
|
35
|
-
style?: React.CSSProperties;
|
|
36
|
-
thumbClassName?: string;
|
|
37
|
-
thumbStyle?: React.CSSProperties;
|
|
38
|
-
}
|
|
39
|
-
declare function Scrollbar({ axis, token, autoHide, minThumbSize, trackPress, className, style, thumbClassName, thumbStyle }: ScrollbarProps): import("react/jsx-runtime").JSX.Element | null;
|
|
40
|
-
//#endregion
|
|
41
|
-
export { Scrollbar, ScrollbarAxis, ScrollbarProps, useScrollMetrics };
|
|
42
|
-
//# sourceMappingURL=scrollbar.d.cts.map
|
package/dist/scrollbar.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { CapabilityToken } from "@embedpdf/core";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { ScrollMetrics, StageCapability } from "@embedpdf/plugin-stage/contract";
|
|
4
|
-
//#region src/scrollbar.d.ts
|
|
5
|
-
type ScrollbarAxis = 'x' | 'y';
|
|
6
|
-
/** Live scroll metrics for a stage lens (reference-stable; see
|
|
7
|
-
* `StageCapability.scrollMetrics`). The raw material for custom scroll UI. */
|
|
8
|
-
declare function useScrollMetrics(token?: CapabilityToken<StageCapability>): ScrollMetrics;
|
|
9
|
-
interface ScrollbarProps {
|
|
10
|
-
axis: ScrollbarAxis;
|
|
11
|
-
/** The stage lens to scroll (default: the main StageToken). */
|
|
12
|
-
token?: CapabilityToken<StageCapability>;
|
|
13
|
-
/**
|
|
14
|
-
* Overlay auto-hide: fade `autoHide` ms after the camera stops moving
|
|
15
|
-
* (drags and hover pin it visible; a hidden bar ignores the pointer, like
|
|
16
|
-
* macOS). `false` = always visible. Visibility is published as
|
|
17
|
-
* `data-state="visible|hidden"` — the default style fades opacity; replace
|
|
18
|
-
* it in CSS for any other treatment. Default 1200.
|
|
19
|
-
*/
|
|
20
|
-
autoHide?: number | false;
|
|
21
|
-
/** Minimum thumb length in px — native bars never vanish on long documents.
|
|
22
|
-
* Position stays proportional via the standard travel remap. Default 24. */
|
|
23
|
-
minThumbSize?: number;
|
|
24
|
-
/**
|
|
25
|
-
* Pressing the track: 'page' steps by 90% of a viewport toward the pointer,
|
|
26
|
-
* repeats while held, and stops when the thumb reaches the pointer (the
|
|
27
|
-
* native default); 'jump' centers the thumb at the pointer and hands off to
|
|
28
|
-
* a drag (the macOS option-click / Figma feel). Default 'page'.
|
|
29
|
-
*/
|
|
30
|
-
trackPress?: 'page' | 'jump';
|
|
31
|
-
/** Track class/style. The default style pins the bar to the right (y) or
|
|
32
|
-
* bottom (x) edge of the nearest positioned ancestor — the Stage container
|
|
33
|
-
* when rendered in its `overlay`; override to place it anywhere else. */
|
|
34
|
-
className?: string;
|
|
35
|
-
style?: React.CSSProperties;
|
|
36
|
-
thumbClassName?: string;
|
|
37
|
-
thumbStyle?: React.CSSProperties;
|
|
38
|
-
}
|
|
39
|
-
declare function Scrollbar({ axis, token, autoHide, minThumbSize, trackPress, className, style, thumbClassName, thumbStyle }: ScrollbarProps): import("react/jsx-runtime").JSX.Element | null;
|
|
40
|
-
//#endregion
|
|
41
|
-
export { Scrollbar, ScrollbarAxis, ScrollbarProps, useScrollMetrics };
|
|
42
|
-
//# sourceMappingURL=scrollbar.d.ts.map
|
package/dist/scrollbar.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import { useCapability, useSelector } from "./runtime.js";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
4
|
-
import { StageToken } from "@embedpdf/plugin-stage/contract";
|
|
5
|
-
//#region src/scrollbar.tsx
|
|
6
|
-
/** Live scroll metrics for a stage lens (reference-stable; see
|
|
7
|
-
* `StageCapability.scrollMetrics`). The raw material for custom scroll UI. */
|
|
8
|
-
function useScrollMetrics(token = StageToken) {
|
|
9
|
-
return useSelector(token, (c) => c.scrollMetrics());
|
|
10
|
-
}
|
|
11
|
-
const clamp01 = (v) => Math.min(1, Math.max(0, v));
|
|
12
|
-
/** Best-effort pointer capture: an already-released pointer (pen/touch races,
|
|
13
|
-
* synthetic events in tests) throws NotFoundError — the press must still work,
|
|
14
|
-
* just without capture (moves keep arriving while the pointer stays on us). */
|
|
15
|
-
const capturePointer = (el, pointerId) => {
|
|
16
|
-
try {
|
|
17
|
-
el.setPointerCapture(pointerId);
|
|
18
|
-
} catch {}
|
|
19
|
-
};
|
|
20
|
-
/** Thumb geometry from metrics + a measured track. One formula for render,
|
|
21
|
-
* drag capture, and paging — they can never disagree. */
|
|
22
|
-
const geometry = (m, vertical, trackPx, minThumbSize) => {
|
|
23
|
-
const client = vertical ? m.clientHeight : m.clientWidth;
|
|
24
|
-
const total = vertical ? m.scrollHeight : m.scrollWidth;
|
|
25
|
-
const offset = vertical ? m.scrollTop : m.scrollLeft;
|
|
26
|
-
const maxOffset = Math.max(0, total - client);
|
|
27
|
-
const thumbLen = Math.min(trackPx, Math.max(minThumbSize, total > 0 ? client / total * trackPx : 0));
|
|
28
|
-
const travel = Math.max(0, trackPx - thumbLen);
|
|
29
|
-
return {
|
|
30
|
-
client,
|
|
31
|
-
offset,
|
|
32
|
-
maxOffset,
|
|
33
|
-
thumbLen,
|
|
34
|
-
travel,
|
|
35
|
-
thumbPos: maxOffset > 0 ? offset / maxOffset * travel : 0
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
function Scrollbar({ axis, token = StageToken, autoHide = 1200, minThumbSize = 24, trackPress = "page", className, style, thumbClassName, thumbStyle }) {
|
|
39
|
-
const stage = useCapability(token);
|
|
40
|
-
const m = useScrollMetrics(token);
|
|
41
|
-
const vertical = axis === "y";
|
|
42
|
-
const scrollable = vertical ? m.scrollableY : m.scrollableX;
|
|
43
|
-
const trackRef = useRef(null);
|
|
44
|
-
const [trackPx, setTrackPx] = useState(0);
|
|
45
|
-
const [dragging, setDragging] = useState(false);
|
|
46
|
-
const [hovered, setHovered] = useState(false);
|
|
47
|
-
const [active, setActive] = useState(true);
|
|
48
|
-
const g = geometry(m, vertical, trackPx, minThumbSize);
|
|
49
|
-
const hideAfter = autoHide === false ? 0 : autoHide;
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (!hideAfter) return;
|
|
52
|
-
setActive(true);
|
|
53
|
-
const t = setTimeout(() => setActive(false), hideAfter);
|
|
54
|
-
return () => clearTimeout(t);
|
|
55
|
-
}, [m, hideAfter]);
|
|
56
|
-
const shown = !hideAfter || active || hovered || dragging;
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
const el = trackRef.current;
|
|
59
|
-
if (!el) return;
|
|
60
|
-
const measure = () => setTrackPx(vertical ? el.clientHeight : el.clientWidth);
|
|
61
|
-
const ro = new ResizeObserver(measure);
|
|
62
|
-
ro.observe(el);
|
|
63
|
-
measure();
|
|
64
|
-
return () => ro.disconnect();
|
|
65
|
-
}, [vertical, scrollable]);
|
|
66
|
-
const dragRef = useRef(null);
|
|
67
|
-
const pageRef = useRef(null);
|
|
68
|
-
const lastPtr = useRef(0);
|
|
69
|
-
const ptrPos = (e) => {
|
|
70
|
-
const r = trackRef.current.getBoundingClientRect();
|
|
71
|
-
return vertical ? e.clientY - r.top : e.clientX - r.left;
|
|
72
|
-
};
|
|
73
|
-
/** Fresh geometry for paging steps — read from the capability, never a stale render. */
|
|
74
|
-
const liveGeometry = () => geometry(stage.scrollMetrics(), vertical, trackPx, minThumbSize);
|
|
75
|
-
const stopPaging = () => {
|
|
76
|
-
if (pageRef.current) {
|
|
77
|
-
clearTimeout(pageRef.current.timer);
|
|
78
|
-
clearInterval(pageRef.current.timer);
|
|
79
|
-
pageRef.current = null;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
const endDrag = () => {
|
|
83
|
-
dragRef.current = null;
|
|
84
|
-
stopPaging();
|
|
85
|
-
setDragging(false);
|
|
86
|
-
};
|
|
87
|
-
const beginDrag = (grab, applied) => {
|
|
88
|
-
dragRef.current = {
|
|
89
|
-
grab,
|
|
90
|
-
applied,
|
|
91
|
-
max: g.maxOffset,
|
|
92
|
-
travel: g.travel
|
|
93
|
-
};
|
|
94
|
-
setDragging(true);
|
|
95
|
-
};
|
|
96
|
-
const onThumbDown = (e) => {
|
|
97
|
-
if (e.button !== 0) return;
|
|
98
|
-
e.preventDefault();
|
|
99
|
-
e.stopPropagation();
|
|
100
|
-
capturePointer(e.target, e.pointerId);
|
|
101
|
-
beginDrag(ptrPos(e) - g.thumbPos, g.offset);
|
|
102
|
-
};
|
|
103
|
-
const onTrackDown = (e) => {
|
|
104
|
-
if (e.button !== 0 || e.target !== e.currentTarget) return;
|
|
105
|
-
e.preventDefault();
|
|
106
|
-
capturePointer(e.currentTarget, e.pointerId);
|
|
107
|
-
const p = lastPtr.current = ptrPos(e);
|
|
108
|
-
if (trackPress === "jump") {
|
|
109
|
-
const want = g.travel > 0 ? clamp01((p - g.thumbLen / 2) / g.travel) * g.maxOffset : 0;
|
|
110
|
-
stage.scrollTo(vertical ? { top: want } : { left: want });
|
|
111
|
-
beginDrag(g.thumbLen / 2, want);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const dir = p < g.thumbPos ? -1 : 1;
|
|
115
|
-
const step = () => {
|
|
116
|
-
const live = liveGeometry();
|
|
117
|
-
if (dir === 1 ? lastPtr.current <= live.thumbPos + live.thumbLen : lastPtr.current >= live.thumbPos) return stopPaging();
|
|
118
|
-
stage.scrollBy(vertical ? { top: dir * live.client * .9 } : { left: dir * live.client * .9 });
|
|
119
|
-
};
|
|
120
|
-
step();
|
|
121
|
-
const timer = window.setTimeout(() => {
|
|
122
|
-
if (!pageRef.current) return;
|
|
123
|
-
pageRef.current.timer = window.setInterval(step, 80);
|
|
124
|
-
}, 350);
|
|
125
|
-
pageRef.current = {
|
|
126
|
-
dir,
|
|
127
|
-
timer
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
const onMove = (e) => {
|
|
131
|
-
const d = dragRef.current;
|
|
132
|
-
if (d) {
|
|
133
|
-
if (d.travel <= 0) return;
|
|
134
|
-
const want = clamp01((ptrPos(e) - d.grab) / d.travel) * d.max;
|
|
135
|
-
const delta = want - d.applied;
|
|
136
|
-
if (delta) {
|
|
137
|
-
stage.panBy(vertical ? 0 : -delta, vertical ? -delta : 0);
|
|
138
|
-
d.applied = want;
|
|
139
|
-
}
|
|
140
|
-
} else if (pageRef.current) lastPtr.current = ptrPos(e);
|
|
141
|
-
};
|
|
142
|
-
useEffect(() => endDrag, []);
|
|
143
|
-
if (!scrollable) return null;
|
|
144
|
-
const trackDefaults = vertical ? {
|
|
145
|
-
position: "absolute",
|
|
146
|
-
top: 0,
|
|
147
|
-
right: 0,
|
|
148
|
-
bottom: 0,
|
|
149
|
-
width: 12
|
|
150
|
-
} : {
|
|
151
|
-
position: "absolute",
|
|
152
|
-
left: 0,
|
|
153
|
-
right: 0,
|
|
154
|
-
bottom: 0,
|
|
155
|
-
height: 12
|
|
156
|
-
};
|
|
157
|
-
const thumbDefaults = vertical ? {
|
|
158
|
-
position: "absolute",
|
|
159
|
-
left: 2,
|
|
160
|
-
right: 2,
|
|
161
|
-
top: g.thumbPos,
|
|
162
|
-
height: g.thumbLen
|
|
163
|
-
} : {
|
|
164
|
-
position: "absolute",
|
|
165
|
-
top: 2,
|
|
166
|
-
bottom: 2,
|
|
167
|
-
left: g.thumbPos,
|
|
168
|
-
width: g.thumbLen
|
|
169
|
-
};
|
|
170
|
-
return /* @__PURE__ */ jsx("div", {
|
|
171
|
-
ref: trackRef,
|
|
172
|
-
role: "scrollbar",
|
|
173
|
-
"aria-orientation": vertical ? "vertical" : "horizontal",
|
|
174
|
-
"aria-valuemin": 0,
|
|
175
|
-
"aria-valuemax": Math.round(g.maxOffset),
|
|
176
|
-
"aria-valuenow": Math.round(g.offset),
|
|
177
|
-
"data-embedpdf-scrollbar": "",
|
|
178
|
-
"data-axis": axis,
|
|
179
|
-
"data-state": shown ? "visible" : "hidden",
|
|
180
|
-
"data-dragging": dragging ? "" : void 0,
|
|
181
|
-
className,
|
|
182
|
-
style: {
|
|
183
|
-
...trackDefaults,
|
|
184
|
-
touchAction: "none",
|
|
185
|
-
userSelect: "none",
|
|
186
|
-
opacity: shown ? 1 : 0,
|
|
187
|
-
transition: "opacity 200ms",
|
|
188
|
-
pointerEvents: shown ? "auto" : "none",
|
|
189
|
-
...style
|
|
190
|
-
},
|
|
191
|
-
onPointerDown: onTrackDown,
|
|
192
|
-
onPointerMove: onMove,
|
|
193
|
-
onPointerUp: endDrag,
|
|
194
|
-
onPointerCancel: endDrag,
|
|
195
|
-
onPointerEnter: () => setHovered(true),
|
|
196
|
-
onPointerLeave: () => setHovered(false),
|
|
197
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
198
|
-
"data-embedpdf-scrollbar-thumb": "",
|
|
199
|
-
className: thumbClassName,
|
|
200
|
-
style: {
|
|
201
|
-
...thumbDefaults,
|
|
202
|
-
borderRadius: 6,
|
|
203
|
-
background: "var(--epdf-scrollbar-thumb, rgba(0, 0, 0, 0.4))",
|
|
204
|
-
...thumbStyle
|
|
205
|
-
},
|
|
206
|
-
onPointerDown: onThumbDown
|
|
207
|
-
})
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
//#endregion
|
|
211
|
-
export { Scrollbar, useScrollMetrics };
|
|
212
|
-
|
|
213
|
-
//# sourceMappingURL=scrollbar.js.map
|
package/dist/scrollbar.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scrollbar.js","names":[],"sources":["../src/scrollbar.tsx"],"sourcesContent":["/**\n * Headless scrollbar for a Stage lens — a pure view of `stage.scrollMetrics()`.\n *\n * The Stage exposes the native scroller contract (scrollTop/scrollHeight/\n * clientHeight, in screen px — see plugin-stage's README); this component turns\n * it into a native-feeling bar: thumb drag with pointer capture and a preserved\n * grab point, track paging with press-and-hold repeat that stops at the\n * pointer, a minimum thumb length on long documents, and macOS-style overlay\n * auto-hide. On an UNBOUNDED stage the metrics already carry the Figma\n * semantics (the range is the union of content and view), so the same bar\n * shrinks toward the edge as you pan away and rides you back — the mapping is\n * FROZEN for the duration of a thumb drag so the thumb never chases itself\n * while the union re-collapses.\n *\n * Headless styling contract: geometry and behavior live here; looks live in\n * your CSS. Style via `className`/`thumbClassName` (or the style props) against\n * [data-embedpdf-scrollbar][data-axis=\"y\"][data-state=\"visible|hidden\"]\n * [data-embedpdf-scrollbar][data-dragging]\n * [data-embedpdf-scrollbar-thumb]\n * The defaults are deliberately minimal: a transparent track pinned to the\n * viewport edge and a `var(--epdf-scrollbar-thumb, …)` pill, so the bar works\n * unstyled and disappears into any theme. Build something else entirely\n * (minimap, progress ring) from `useScrollMetrics()` + `stage.scrollTo()`.\n */\n\nimport * as React from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\nimport type { ScrollMetrics, StageCapability } from '@embedpdf/plugin-stage/contract';\nimport type { CapabilityToken } from '@embedpdf/core';\nimport { useCapability, useSelector } from './runtime';\n\nexport type ScrollbarAxis = 'x' | 'y';\n\n/** Live scroll metrics for a stage lens (reference-stable; see\n * `StageCapability.scrollMetrics`). The raw material for custom scroll UI. */\nexport function useScrollMetrics(\n token: CapabilityToken<StageCapability> = StageToken,\n): ScrollMetrics {\n return useSelector(token, (c) => c.scrollMetrics());\n}\n\nexport interface ScrollbarProps {\n axis: ScrollbarAxis;\n /** The stage lens to scroll (default: the main StageToken). */\n token?: CapabilityToken<StageCapability>;\n /**\n * Overlay auto-hide: fade `autoHide` ms after the camera stops moving\n * (drags and hover pin it visible; a hidden bar ignores the pointer, like\n * macOS). `false` = always visible. Visibility is published as\n * `data-state=\"visible|hidden\"` — the default style fades opacity; replace\n * it in CSS for any other treatment. Default 1200.\n */\n autoHide?: number | false;\n /** Minimum thumb length in px — native bars never vanish on long documents.\n * Position stays proportional via the standard travel remap. Default 24. */\n minThumbSize?: number;\n /**\n * Pressing the track: 'page' steps by 90% of a viewport toward the pointer,\n * repeats while held, and stops when the thumb reaches the pointer (the\n * native default); 'jump' centers the thumb at the pointer and hands off to\n * a drag (the macOS option-click / Figma feel). Default 'page'.\n */\n trackPress?: 'page' | 'jump';\n /** Track class/style. The default style pins the bar to the right (y) or\n * bottom (x) edge of the nearest positioned ancestor — the Stage container\n * when rendered in its `overlay`; override to place it anywhere else. */\n className?: string;\n style?: React.CSSProperties;\n thumbClassName?: string;\n thumbStyle?: React.CSSProperties;\n}\n\nconst clamp01 = (v: number) => Math.min(1, Math.max(0, v));\n\n/** Best-effort pointer capture: an already-released pointer (pen/touch races,\n * synthetic events in tests) throws NotFoundError — the press must still work,\n * just without capture (moves keep arriving while the pointer stays on us). */\nconst capturePointer = (el: Element, pointerId: number) => {\n try {\n el.setPointerCapture(pointerId);\n } catch {\n /* uncaptured is fine */\n }\n};\n\n/** Thumb geometry from metrics + a measured track. One formula for render,\n * drag capture, and paging — they can never disagree. */\nconst geometry = (m: ScrollMetrics, vertical: boolean, trackPx: number, minThumbSize: number) => {\n const client = vertical ? m.clientHeight : m.clientWidth;\n const total = vertical ? m.scrollHeight : m.scrollWidth;\n const offset = vertical ? m.scrollTop : m.scrollLeft;\n const maxOffset = Math.max(0, total - client);\n const thumbLen = Math.min(\n trackPx,\n Math.max(minThumbSize, total > 0 ? (client / total) * trackPx : 0),\n );\n const travel = Math.max(0, trackPx - thumbLen);\n const thumbPos = maxOffset > 0 ? (offset / maxOffset) * travel : 0;\n return { client, offset, maxOffset, thumbLen, travel, thumbPos };\n};\n\nexport function Scrollbar({\n axis,\n token = StageToken,\n autoHide = 1200,\n minThumbSize = 24,\n trackPress = 'page',\n className,\n style,\n thumbClassName,\n thumbStyle,\n}: ScrollbarProps) {\n const stage = useCapability(token);\n const m = useScrollMetrics(token);\n const vertical = axis === 'y';\n const scrollable = vertical ? m.scrollableY : m.scrollableX;\n\n const trackRef = useRef<HTMLDivElement>(null);\n const [trackPx, setTrackPx] = useState(0);\n const [dragging, setDragging] = useState(false);\n const [hovered, setHovered] = useState(false);\n const [active, setActive] = useState(true); // camera moved recently\n\n const g = geometry(m, vertical, trackPx, minThumbSize);\n\n // ── overlay auto-hide: any metrics change re-arms the fade timer ──────────\n const hideAfter = autoHide === false ? 0 : autoHide;\n useEffect(() => {\n if (!hideAfter) return;\n setActive(true);\n const t = setTimeout(() => setActive(false), hideAfter);\n return () => clearTimeout(t);\n }, [m, hideAfter]);\n const shown = !hideAfter || active || hovered || dragging;\n\n // ── track measurement (px mapping needs real geometry) ────────────────────\n useEffect(() => {\n const el = trackRef.current;\n if (!el) return;\n const measure = () => setTrackPx(vertical ? el.clientHeight : el.clientWidth);\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n measure();\n return () => ro.disconnect();\n }, [vertical, scrollable]);\n\n // ── interactions. Drag state is FROZEN at pointer-down (grab point, travel,\n // max offset) and applied as relative pans — absolute-feeling in bounded\n // mode (the range is static there) and stable in unbounded mode, where\n // the live union would otherwise shift under the pointer mid-drag. ──────\n const dragRef = useRef<{ grab: number; applied: number; max: number; travel: number } | null>(\n null,\n );\n const pageRef = useRef<{ dir: 1 | -1; timer: number } | null>(null);\n const lastPtr = useRef(0);\n\n const ptrPos = (e: React.PointerEvent) => {\n const r = trackRef.current!.getBoundingClientRect();\n return vertical ? e.clientY - r.top : e.clientX - r.left;\n };\n /** Fresh geometry for paging steps — read from the capability, never a stale render. */\n const liveGeometry = () => geometry(stage.scrollMetrics(), vertical, trackPx, minThumbSize);\n\n const stopPaging = () => {\n if (pageRef.current) {\n clearTimeout(pageRef.current.timer);\n clearInterval(pageRef.current.timer);\n pageRef.current = null;\n }\n };\n const endDrag = () => {\n dragRef.current = null;\n stopPaging();\n setDragging(false);\n };\n\n const beginDrag = (grab: number, applied: number) => {\n dragRef.current = { grab, applied, max: g.maxOffset, travel: g.travel };\n setDragging(true);\n };\n\n const onThumbDown = (e: React.PointerEvent) => {\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n capturePointer(e.target as Element, e.pointerId);\n beginDrag(ptrPos(e) - g.thumbPos, g.offset);\n };\n\n const onTrackDown = (e: React.PointerEvent) => {\n if (e.button !== 0 || e.target !== e.currentTarget) return; // thumb handles its own\n e.preventDefault();\n capturePointer(e.currentTarget as Element, e.pointerId);\n const p = (lastPtr.current = ptrPos(e));\n\n if (trackPress === 'jump') {\n // land the thumb centered at the pointer, then it's an ordinary drag\n const want = g.travel > 0 ? clamp01((p - g.thumbLen / 2) / g.travel) * g.maxOffset : 0;\n stage.scrollTo(vertical ? { top: want } : { left: want });\n beginDrag(g.thumbLen / 2, want);\n return;\n }\n\n // 'page': step toward the pointer, repeat while held, stop at the pointer\n const dir: 1 | -1 = p < g.thumbPos ? -1 : 1;\n const step = () => {\n const live = liveGeometry();\n const reached =\n dir === 1\n ? lastPtr.current <= live.thumbPos + live.thumbLen\n : lastPtr.current >= live.thumbPos;\n if (reached) return stopPaging();\n stage.scrollBy(\n vertical ? { top: dir * live.client * 0.9 } : { left: dir * live.client * 0.9 },\n );\n };\n step();\n // native cadence: a beat before the repeat kicks in, then a steady march\n const timer = window.setTimeout(() => {\n if (!pageRef.current) return;\n pageRef.current.timer = window.setInterval(step, 80);\n }, 350);\n pageRef.current = { dir, timer };\n };\n\n // Pointer capture retargets to the pressed element and bubbles here — one\n // move/up pair serves thumb drags, jump-drags, and paging alike.\n const onMove = (e: React.PointerEvent) => {\n const d = dragRef.current;\n if (d) {\n if (d.travel <= 0) return;\n const want = clamp01((ptrPos(e) - d.grab) / d.travel) * d.max;\n const delta = want - d.applied;\n if (delta) {\n stage.panBy(vertical ? 0 : -delta, vertical ? -delta : 0);\n d.applied = want;\n }\n } else if (pageRef.current) {\n lastPtr.current = ptrPos(e);\n }\n };\n\n useEffect(() => endDrag, []); // unmount: no orphaned repeat timers\n\n if (!scrollable) return null;\n\n const trackDefaults: React.CSSProperties = vertical\n ? { position: 'absolute', top: 0, right: 0, bottom: 0, width: 12 }\n : { position: 'absolute', left: 0, right: 0, bottom: 0, height: 12 };\n const thumbDefaults: React.CSSProperties = vertical\n ? { position: 'absolute', left: 2, right: 2, top: g.thumbPos, height: g.thumbLen }\n : { position: 'absolute', top: 2, bottom: 2, left: g.thumbPos, width: g.thumbLen };\n\n return (\n <div\n ref={trackRef}\n role=\"scrollbar\"\n aria-orientation={vertical ? 'vertical' : 'horizontal'}\n aria-valuemin={0}\n aria-valuemax={Math.round(g.maxOffset)}\n aria-valuenow={Math.round(g.offset)}\n data-embedpdf-scrollbar=\"\"\n data-axis={axis}\n data-state={shown ? 'visible' : 'hidden'}\n data-dragging={dragging ? '' : undefined}\n className={className}\n style={{\n ...trackDefaults,\n touchAction: 'none',\n userSelect: 'none',\n opacity: shown ? 1 : 0,\n transition: 'opacity 200ms',\n // a hidden overlay bar must not eat the clicks under it\n pointerEvents: shown ? 'auto' : 'none',\n ...style,\n }}\n onPointerDown={onTrackDown}\n onPointerMove={onMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onPointerEnter={() => setHovered(true)}\n onPointerLeave={() => setHovered(false)}\n >\n <div\n data-embedpdf-scrollbar-thumb=\"\"\n className={thumbClassName}\n style={{\n ...thumbDefaults,\n borderRadius: 6,\n background: 'var(--epdf-scrollbar-thumb, rgba(0, 0, 0, 0.4))',\n ...thumbStyle,\n }}\n onPointerDown={onThumbDown}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|