pdfjs-reader-core 0.5.7 → 0.5.9
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/index.cjs +111 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -31
- package/dist/index.d.ts +14 -31
- package/dist/index.js +93 -153
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9191,7 +9191,7 @@ var init_DocumentContainer = __esm({
|
|
|
9191
9191
|
const containerRef = (0, import_react37.useRef)(null);
|
|
9192
9192
|
const documentRef = (0, import_react37.useRef)(null);
|
|
9193
9193
|
const baseScaleRef = (0, import_react37.useRef)(scale);
|
|
9194
|
-
const
|
|
9194
|
+
const isTouchDevice = useIsTouchDevice();
|
|
9195
9195
|
const documentLoadingState = useViewerStore((s) => s.documentLoadingState);
|
|
9196
9196
|
const { selection, clearSelection, copySelection } = useTextSelection();
|
|
9197
9197
|
const handlePinchZoom = (0, import_react37.useCallback)(
|
|
@@ -9222,7 +9222,7 @@ var init_DocumentContainer = __esm({
|
|
|
9222
9222
|
onSwipeLeft: handleSwipeLeft,
|
|
9223
9223
|
onSwipeRight: handleSwipeRight,
|
|
9224
9224
|
onDoubleTap: handleDoubleTap,
|
|
9225
|
-
enabled: enableTouchGestures &&
|
|
9225
|
+
enabled: enableTouchGestures && isTouchDevice,
|
|
9226
9226
|
swipeThreshold: 50,
|
|
9227
9227
|
doubleTapInterval: 300
|
|
9228
9228
|
});
|
|
@@ -9466,7 +9466,7 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9466
9466
|
const pageCache = (0, import_react38.useRef)(/* @__PURE__ */ new Map());
|
|
9467
9467
|
const pageDimensionsCache = (0, import_react38.useRef)(/* @__PURE__ */ new Map());
|
|
9468
9468
|
const baseScaleRef = (0, import_react38.useRef)(scale);
|
|
9469
|
-
const
|
|
9469
|
+
const isTouchDevice = useIsTouchDevice();
|
|
9470
9470
|
const [visiblePages, setVisiblePages] = (0, import_react38.useState)([1]);
|
|
9471
9471
|
const [pageObjects, setPageObjects] = (0, import_react38.useState)(/* @__PURE__ */ new Map());
|
|
9472
9472
|
const [totalHeight, setTotalHeight] = (0, import_react38.useState)(0);
|
|
@@ -9669,7 +9669,7 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9669
9669
|
onPinchZoom: handlePinchZoom,
|
|
9670
9670
|
onSwipeLeft: nextPage,
|
|
9671
9671
|
onSwipeRight: previousPage,
|
|
9672
|
-
enabled: enableTouchGestures &&
|
|
9672
|
+
enabled: enableTouchGestures && isTouchDevice
|
|
9673
9673
|
});
|
|
9674
9674
|
const setContainerRef = (0, import_react38.useCallback)(
|
|
9675
9675
|
(element) => {
|
|
@@ -9877,7 +9877,7 @@ var init_DualPageContainer = __esm({
|
|
|
9877
9877
|
const containerRef = (0, import_react40.useRef)(null);
|
|
9878
9878
|
const documentRef = (0, import_react40.useRef)(null);
|
|
9879
9879
|
const baseScaleRef = (0, import_react40.useRef)(scale);
|
|
9880
|
-
const
|
|
9880
|
+
const isTouchDevice = useIsTouchDevice();
|
|
9881
9881
|
const [leftPage, setLeftPage] = (0, import_react40.useState)(null);
|
|
9882
9882
|
const [rightPage, setRightPage] = (0, import_react40.useState)(null);
|
|
9883
9883
|
const [isLoading, setIsLoading] = (0, import_react40.useState)(false);
|
|
@@ -10020,7 +10020,7 @@ var init_DualPageContainer = __esm({
|
|
|
10020
10020
|
onPinchZoom: handlePinchZoom,
|
|
10021
10021
|
onSwipeLeft: goToNextSpread,
|
|
10022
10022
|
onSwipeRight: goToPreviousSpread,
|
|
10023
|
-
enabled: enableTouchGestures &&
|
|
10023
|
+
enabled: enableTouchGestures && isTouchDevice
|
|
10024
10024
|
});
|
|
10025
10025
|
const setContainerRef = (0, import_react40.useCallback)(
|
|
10026
10026
|
(element) => {
|
|
@@ -13268,7 +13268,7 @@ function withErrorBoundary({ component, ...props }) {
|
|
|
13268
13268
|
init_PDFLoadingScreen2();
|
|
13269
13269
|
|
|
13270
13270
|
// src/components/TutorMode/TutorModeContainer.tsx
|
|
13271
|
-
var
|
|
13271
|
+
var import_react57 = require("react");
|
|
13272
13272
|
var import_zustand2 = require("zustand");
|
|
13273
13273
|
init_PDFPage2();
|
|
13274
13274
|
init_hooks();
|
|
@@ -13559,13 +13559,13 @@ function AnimatedUnderline({ bbox, action }) {
|
|
|
13559
13559
|
const blotX = x2 + 4;
|
|
13560
13560
|
const blotY = y;
|
|
13561
13561
|
const strokeWeight = action.style === "wavy" ? 3 : 4;
|
|
13562
|
-
const
|
|
13563
|
-
const
|
|
13564
|
-
const
|
|
13565
|
-
const svgX = x1 -
|
|
13566
|
-
const svgY = y -
|
|
13567
|
-
const svgW = x2 - x1 + 2 *
|
|
13568
|
-
const svgH =
|
|
13562
|
+
const uxPad = 8;
|
|
13563
|
+
const uAbove = 8;
|
|
13564
|
+
const uBelow = 24;
|
|
13565
|
+
const svgX = x1 - uxPad;
|
|
13566
|
+
const svgY = y - uAbove;
|
|
13567
|
+
const svgW = x2 - x1 + 2 * uxPad;
|
|
13568
|
+
const svgH = uAbove + uBelow;
|
|
13569
13569
|
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
13570
13570
|
"svg",
|
|
13571
13571
|
{
|
|
@@ -13640,7 +13640,12 @@ function AnimatedUnderline({ bbox, action }) {
|
|
|
13640
13640
|
// src/components/TutorMode/AnimatedHighlight.tsx
|
|
13641
13641
|
var import_framer_motion4 = require("framer-motion");
|
|
13642
13642
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
13643
|
-
var
|
|
13643
|
+
var DEFAULT_HUE = "rgb(230, 180, 34)";
|
|
13644
|
+
var WASH_OPACITY = 0.28;
|
|
13645
|
+
function stripAlpha(color) {
|
|
13646
|
+
const m = color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
|
|
13647
|
+
return m ? `rgb(${m[1]}, ${m[2]}, ${m[3]})` : color;
|
|
13648
|
+
}
|
|
13644
13649
|
function AnimatedHighlight({ bbox, action }) {
|
|
13645
13650
|
const [x1, y1, x2, y2] = bbox;
|
|
13646
13651
|
const h = Math.max(1, y2 - y1);
|
|
@@ -13649,7 +13654,7 @@ function AnimatedHighlight({ bbox, action }) {
|
|
|
13649
13654
|
const yBot = y2 + bleed;
|
|
13650
13655
|
const duration = action.draw_duration_ms / 1e3;
|
|
13651
13656
|
const isDefaultColour = !action.color || action.color === "rgba(250, 204, 21, 0.35)" || action.color === "rgba(250,204,21,0.35)";
|
|
13652
|
-
const fill = isDefaultColour ?
|
|
13657
|
+
const fill = stripAlpha(isDefaultColour ? DEFAULT_HUE : action.color);
|
|
13653
13658
|
const taper = Math.min(6, h * 0.2);
|
|
13654
13659
|
const pathD = `
|
|
13655
13660
|
M ${x1 - 2} ${yTop + taper}
|
|
@@ -13662,11 +13667,11 @@ function AnimatedHighlight({ bbox, action }) {
|
|
|
13662
13667
|
L ${x1 - 2} ${yBot - taper}
|
|
13663
13668
|
Z
|
|
13664
13669
|
`;
|
|
13665
|
-
const
|
|
13666
|
-
const svgX = x1 -
|
|
13667
|
-
const svgY = yTop -
|
|
13668
|
-
const svgW = x2 - x1 + 2 *
|
|
13669
|
-
const svgH = yBot - yTop + 2 *
|
|
13670
|
+
const svgPad = 8;
|
|
13671
|
+
const svgX = x1 - svgPad;
|
|
13672
|
+
const svgY = yTop - svgPad;
|
|
13673
|
+
const svgW = x2 - x1 + 2 * svgPad;
|
|
13674
|
+
const svgH = yBot - yTop + 2 * svgPad;
|
|
13670
13675
|
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
13671
13676
|
"svg",
|
|
13672
13677
|
{
|
|
@@ -13686,6 +13691,7 @@ function AnimatedHighlight({ bbox, action }) {
|
|
|
13686
13691
|
{
|
|
13687
13692
|
d: pathD,
|
|
13688
13693
|
fill,
|
|
13694
|
+
fillOpacity: WASH_OPACITY,
|
|
13689
13695
|
initial: { clipPath: `inset(0 100% 0 0)` },
|
|
13690
13696
|
animate: { clipPath: `inset(0 0% 0 0)` },
|
|
13691
13697
|
exit: { opacity: 0 },
|
|
@@ -13697,7 +13703,6 @@ function AnimatedHighlight({ bbox, action }) {
|
|
|
13697
13703
|
}
|
|
13698
13704
|
|
|
13699
13705
|
// src/components/TutorMode/PulseOverlay.tsx
|
|
13700
|
-
var import_react56 = require("react");
|
|
13701
13706
|
var import_framer_motion5 = require("framer-motion");
|
|
13702
13707
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
13703
13708
|
var INTENSITY = {
|
|
@@ -13706,7 +13711,6 @@ var INTENSITY = {
|
|
|
13706
13711
|
strong: { bracketLen: 26, strokeWeight: 3, coreOpacity: 1, ringScale: 1.22 }
|
|
13707
13712
|
};
|
|
13708
13713
|
function PulseOverlay({ bbox, action }) {
|
|
13709
|
-
const pulseId = (0, import_react56.useId)();
|
|
13710
13714
|
const [x1, y1, x2, y2] = bbox;
|
|
13711
13715
|
const w = Math.max(1, x2 - x1);
|
|
13712
13716
|
const h = Math.max(1, y2 - y1);
|
|
@@ -13715,13 +13719,13 @@ function PulseOverlay({ bbox, action }) {
|
|
|
13715
13719
|
const spec = INTENSITY[action.intensity] ?? INTENSITY.normal;
|
|
13716
13720
|
const L = Math.min(spec.bracketLen, Math.min(w, h) / 2.5);
|
|
13717
13721
|
const PAD = 6;
|
|
13722
|
+
const ringExtentX = (w / 2 + PAD) * spec.ringScale - w / 2;
|
|
13723
|
+
const ringExtentY = (h / 2 + PAD) * spec.ringScale - h / 2;
|
|
13724
|
+
const glowExtentX = (w / 2 + 10) * spec.ringScale - w / 2 + 24;
|
|
13725
|
+
const glowExtentY = (h / 2 + 10) * spec.ringScale - h / 2 + 24;
|
|
13718
13726
|
const bracketExtent = PAD + L + 8;
|
|
13719
|
-
const
|
|
13720
|
-
const
|
|
13721
|
-
const glowExtentV = (h / 2 + 24) * spec.ringScale - h / 2;
|
|
13722
|
-
const ringExtentV = (h / 2 + PAD) * spec.ringScale - h / 2;
|
|
13723
|
-
const svgPadX = Math.ceil(Math.max(bracketExtent, glowExtent, ringExtent) + 4);
|
|
13724
|
-
const svgPadY = Math.ceil(Math.max(bracketExtent, glowExtentV, ringExtentV) + 4);
|
|
13727
|
+
const svgPadX = Math.ceil(Math.max(40, ringExtentX, glowExtentX, bracketExtent));
|
|
13728
|
+
const svgPadY = Math.ceil(Math.max(40, ringExtentY, glowExtentY, bracketExtent));
|
|
13725
13729
|
const svgX = x1 - svgPadX;
|
|
13726
13730
|
const svgY = y1 - svgPadY;
|
|
13727
13731
|
const svgW = w + 2 * svgPadX;
|
|
@@ -13741,22 +13745,18 @@ function PulseOverlay({ bbox, action }) {
|
|
|
13741
13745
|
},
|
|
13742
13746
|
"data-role": "pulse",
|
|
13743
13747
|
children: [
|
|
13744
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("radialGradient", { id: `${pulseId}-glow`, cx: "50%", cy: "50%", r: "50%", children: [
|
|
13745
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("stop", { offset: "0%", stopColor: ACCENT_GLOW, stopOpacity: 1 }),
|
|
13746
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("stop", { offset: "60%", stopColor: ACCENT_GLOW, stopOpacity: 0.45 }),
|
|
13747
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("stop", { offset: "100%", stopColor: ACCENT_GLOW, stopOpacity: 0 })
|
|
13748
|
-
] }) }),
|
|
13749
13748
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
13750
13749
|
import_framer_motion5.motion.ellipse,
|
|
13751
13750
|
{
|
|
13752
13751
|
cx,
|
|
13753
13752
|
cy,
|
|
13754
|
-
rx: w / 2 +
|
|
13755
|
-
ry: h / 2 +
|
|
13756
|
-
fill:
|
|
13753
|
+
rx: w / 2 + 10,
|
|
13754
|
+
ry: h / 2 + 10,
|
|
13755
|
+
fill: ACCENT_GLOW,
|
|
13757
13756
|
style: {
|
|
13758
13757
|
transformOrigin: `${cx}px ${cy}px`,
|
|
13759
|
-
transformBox: "fill-box"
|
|
13758
|
+
transformBox: "fill-box",
|
|
13759
|
+
filter: "blur(16px)"
|
|
13760
13760
|
},
|
|
13761
13761
|
initial: { opacity: 0, scale: 0.95 },
|
|
13762
13762
|
animate: {
|
|
@@ -13887,7 +13887,7 @@ function Bracket({
|
|
|
13887
13887
|
}
|
|
13888
13888
|
|
|
13889
13889
|
// src/components/TutorMode/CalloutArrow.tsx
|
|
13890
|
-
var
|
|
13890
|
+
var import_react56 = require("react");
|
|
13891
13891
|
var import_framer_motion6 = require("framer-motion");
|
|
13892
13892
|
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
13893
13893
|
function centerOf(b) {
|
|
@@ -13925,7 +13925,7 @@ function arrowPath(from, to, curve) {
|
|
|
13925
13925
|
return `M ${from.x} ${from.y} Q ${cx} ${cy} ${to.x} ${to.y}`;
|
|
13926
13926
|
}
|
|
13927
13927
|
function CalloutArrow({ fromBbox, toBbox, action }) {
|
|
13928
|
-
const markerId = (0,
|
|
13928
|
+
const markerId = (0, import_react56.useId)();
|
|
13929
13929
|
const glowId = `${markerId}-glow`;
|
|
13930
13930
|
const { from, to } = edgePoints(fromBbox, toBbox);
|
|
13931
13931
|
const d = arrowPath(from, to, action.curve);
|
|
@@ -14098,9 +14098,8 @@ function CinemaLayer({
|
|
|
14098
14098
|
page,
|
|
14099
14099
|
index,
|
|
14100
14100
|
overlays,
|
|
14101
|
-
|
|
14101
|
+
scale
|
|
14102
14102
|
}) {
|
|
14103
|
-
if (overlays.length === 0) return null;
|
|
14104
14103
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
14105
14104
|
"div",
|
|
14106
14105
|
{
|
|
@@ -14109,7 +14108,7 @@ function CinemaLayer({
|
|
|
14109
14108
|
position: "absolute",
|
|
14110
14109
|
inset: 0,
|
|
14111
14110
|
transformOrigin: "0 0",
|
|
14112
|
-
transform: `scale(${
|
|
14111
|
+
transform: `scale(${scale})`,
|
|
14113
14112
|
width: page.page_dimensions.width,
|
|
14114
14113
|
height: page.page_dimensions.height,
|
|
14115
14114
|
pointerEvents: "none",
|
|
@@ -14594,10 +14593,14 @@ function StickyLabel({ screenAnchor, action }) {
|
|
|
14594
14593
|
letterSpacing: 0.6,
|
|
14595
14594
|
textTransform: "uppercase",
|
|
14596
14595
|
fontWeight: 500,
|
|
14597
|
-
|
|
14596
|
+
// Wrap instead of truncating with an ellipsis. Short labels stay
|
|
14597
|
+
// single-line naturally; longer ones grow in height rather than
|
|
14598
|
+
// losing their tail. `overflowWrap: 'anywhere'` keeps a stray
|
|
14599
|
+
// long word from pushing the pill past `maxWidth` (normal word
|
|
14600
|
+
// breaking stops at whitespace and can't break inside words).
|
|
14598
14601
|
maxWidth: PILL_MAX_W_BODY,
|
|
14599
|
-
|
|
14600
|
-
|
|
14602
|
+
whiteSpace: "normal",
|
|
14603
|
+
overflowWrap: "anywhere",
|
|
14601
14604
|
// Warm two-layer shadow (matches GhostReference's palette).
|
|
14602
14605
|
boxShadow: "0 1px 2px rgba(42, 36, 32, 0.12), 0 8px 18px -6px rgba(42, 36, 32, 0.22)",
|
|
14603
14606
|
// Internal left accent rule — a 2px terracotta stripe.
|
|
@@ -14699,8 +14702,7 @@ function LabelOverlay({
|
|
|
14699
14702
|
index,
|
|
14700
14703
|
currentPage,
|
|
14701
14704
|
camera,
|
|
14702
|
-
viewport
|
|
14703
|
-
coordScale
|
|
14705
|
+
viewport
|
|
14704
14706
|
}) {
|
|
14705
14707
|
const labels = overlays.filter((o) => o.kind === "label");
|
|
14706
14708
|
const page = index.byPage.get(currentPage);
|
|
@@ -14727,8 +14729,7 @@ function LabelOverlay({
|
|
|
14727
14729
|
a.position,
|
|
14728
14730
|
page,
|
|
14729
14731
|
camera,
|
|
14730
|
-
viewport
|
|
14731
|
-
coordScale
|
|
14732
|
+
viewport
|
|
14732
14733
|
);
|
|
14733
14734
|
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
14734
14735
|
StickyLabel,
|
|
@@ -14742,7 +14743,7 @@ function LabelOverlay({
|
|
|
14742
14743
|
}
|
|
14743
14744
|
);
|
|
14744
14745
|
}
|
|
14745
|
-
function computeScreenAnchor(bbox, where, page, camera, viewport
|
|
14746
|
+
function computeScreenAnchor(bbox, where, page, camera, viewport) {
|
|
14746
14747
|
const [x1, y1, x2, y2] = bbox;
|
|
14747
14748
|
const pageCX = page.page_dimensions.width / 2;
|
|
14748
14749
|
const pageCY = page.page_dimensions.height / 2;
|
|
@@ -14768,8 +14769,8 @@ function computeScreenAnchor(bbox, where, page, camera, viewport, coordScale) {
|
|
|
14768
14769
|
px = (x1 + x2) / 2;
|
|
14769
14770
|
py = y1;
|
|
14770
14771
|
}
|
|
14771
|
-
const screenX = viewport.width / 2 + camera.x + (px - pageCX) *
|
|
14772
|
-
const screenY = viewport.height / 2 + camera.y + (py - pageCY) *
|
|
14772
|
+
const screenX = viewport.width / 2 + camera.x + (px - pageCX) * camera.scale;
|
|
14773
|
+
const screenY = viewport.height / 2 + camera.y + (py - pageCY) * camera.scale;
|
|
14773
14774
|
return { x: screenX, y: screenY };
|
|
14774
14775
|
}
|
|
14775
14776
|
|
|
@@ -14781,8 +14782,7 @@ function CalloutLabelOverlay({
|
|
|
14781
14782
|
index,
|
|
14782
14783
|
currentPage,
|
|
14783
14784
|
camera,
|
|
14784
|
-
viewport
|
|
14785
|
-
coordScale
|
|
14785
|
+
viewport
|
|
14786
14786
|
}) {
|
|
14787
14787
|
const callouts = overlays.filter(
|
|
14788
14788
|
(o) => o.kind === "callout" && o.action.label
|
|
@@ -14811,8 +14811,7 @@ function CalloutLabelOverlay({
|
|
|
14811
14811
|
toHit.block.bbox,
|
|
14812
14812
|
page,
|
|
14813
14813
|
camera,
|
|
14814
|
-
viewport
|
|
14815
|
-
coordScale
|
|
14814
|
+
viewport
|
|
14816
14815
|
);
|
|
14817
14816
|
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
14818
14817
|
CalloutLabelPill,
|
|
@@ -14827,7 +14826,7 @@ function CalloutLabelOverlay({
|
|
|
14827
14826
|
}
|
|
14828
14827
|
);
|
|
14829
14828
|
}
|
|
14830
|
-
function computePillAnchor(fromBbox, toBbox, page, camera, viewport
|
|
14829
|
+
function computePillAnchor(fromBbox, toBbox, page, camera, viewport) {
|
|
14831
14830
|
const aCX = (fromBbox[0] + fromBbox[2]) / 2;
|
|
14832
14831
|
const aCY = (fromBbox[1] + fromBbox[3]) / 2;
|
|
14833
14832
|
const bCX = (toBbox[0] + toBbox[2]) / 2;
|
|
@@ -14844,8 +14843,8 @@ function computePillAnchor(fromBbox, toBbox, page, camera, viewport, coordScale)
|
|
|
14844
14843
|
const toY = bCY - uy * bOff;
|
|
14845
14844
|
const pageCX = page.page_dimensions.width / 2;
|
|
14846
14845
|
const pageCY = page.page_dimensions.height / 2;
|
|
14847
|
-
const tipScreenX = viewport.width / 2 + camera.x + (toX - pageCX) *
|
|
14848
|
-
const tipScreenY = viewport.height / 2 + camera.y + (toY - pageCY) *
|
|
14846
|
+
const tipScreenX = viewport.width / 2 + camera.x + (toX - pageCX) * camera.scale;
|
|
14847
|
+
const tipScreenY = viewport.height / 2 + camera.y + (toY - pageCY) * camera.scale;
|
|
14849
14848
|
const isVertical = Math.abs(dy) >= Math.abs(dx);
|
|
14850
14849
|
const OFFSET = resolvePillOffset(viewport.width);
|
|
14851
14850
|
const MAX_PILL_W = resolveMaxPillW(viewport.width);
|
|
@@ -14898,10 +14897,13 @@ function CalloutLabelPill({
|
|
|
14898
14897
|
letterSpacing: 0.6,
|
|
14899
14898
|
textTransform: "uppercase",
|
|
14900
14899
|
fontWeight: 500,
|
|
14901
|
-
|
|
14900
|
+
// Wrap instead of truncating. Short labels stay single-line;
|
|
14901
|
+
// longer ones grow taller rather than losing their tail to an
|
|
14902
|
+
// ellipsis. `overflowWrap: 'anywhere'` guards against a stray
|
|
14903
|
+
// long word pushing the pill past `maxWidth`.
|
|
14902
14904
|
maxWidth: PILL_MAX_W_CAPS,
|
|
14903
|
-
|
|
14904
|
-
|
|
14905
|
+
whiteSpace: "normal",
|
|
14906
|
+
overflowWrap: "anywhere",
|
|
14905
14907
|
boxShadow: "0 1px 2px rgba(42, 36, 32, 0.12), 0 8px 18px -6px rgba(42, 36, 32, 0.22)",
|
|
14906
14908
|
// Accent rule on the "inward" edge (the one closest to the arrow).
|
|
14907
14909
|
backgroundImage: spec.accentGradient,
|
|
@@ -14988,41 +14990,6 @@ function SubtitleBar({ text }) {
|
|
|
14988
14990
|
) : null });
|
|
14989
14991
|
}
|
|
14990
14992
|
|
|
14991
|
-
// src/utils/render-scale.ts
|
|
14992
|
-
function computeFitScale(input) {
|
|
14993
|
-
const { pageWidthPt, pageHeightPt, viewport, paddingFactor = 0.95 } = input;
|
|
14994
|
-
if (!Number.isFinite(pageWidthPt) || !Number.isFinite(pageHeightPt) || pageWidthPt <= 0 || pageHeightPt <= 0) {
|
|
14995
|
-
return 1;
|
|
14996
|
-
}
|
|
14997
|
-
const w = Math.max(1, viewport.width);
|
|
14998
|
-
const h = Math.max(1, viewport.height);
|
|
14999
|
-
const fit = Math.min(w / pageWidthPt, h / pageHeightPt) * paddingFactor;
|
|
15000
|
-
return Number.isFinite(fit) && fit > 0 ? fit : 1;
|
|
15001
|
-
}
|
|
15002
|
-
function computeCoordScale(input) {
|
|
15003
|
-
const { renderScale, dpi } = input;
|
|
15004
|
-
if (!Number.isFinite(renderScale) || renderScale <= 0) return 0;
|
|
15005
|
-
if (!Number.isFinite(dpi) || dpi <= 0) return 1;
|
|
15006
|
-
return renderScale * 72 / dpi;
|
|
15007
|
-
}
|
|
15008
|
-
function isTouchDevice() {
|
|
15009
|
-
if (typeof window === "undefined") return false;
|
|
15010
|
-
if (typeof window.matchMedia !== "function") return false;
|
|
15011
|
-
try {
|
|
15012
|
-
return window.matchMedia("(pointer: coarse)").matches;
|
|
15013
|
-
} catch {
|
|
15014
|
-
return false;
|
|
15015
|
-
}
|
|
15016
|
-
}
|
|
15017
|
-
function resolveRenderScale(input) {
|
|
15018
|
-
const { renderScaleProp, scaleProp, defaultRenderScale } = input;
|
|
15019
|
-
if (Number.isFinite(renderScaleProp) && renderScaleProp > 0) {
|
|
15020
|
-
return renderScaleProp;
|
|
15021
|
-
}
|
|
15022
|
-
const multiplier = Number.isFinite(scaleProp) && scaleProp > 0 ? scaleProp : 1;
|
|
15023
|
-
return defaultRenderScale * multiplier;
|
|
15024
|
-
}
|
|
15025
|
-
|
|
15026
14993
|
// src/director/storyboard-engine.ts
|
|
15027
14994
|
init_narration_store();
|
|
15028
14995
|
init_camera_math();
|
|
@@ -15119,14 +15086,18 @@ var StoryboardEngine = class {
|
|
|
15119
15086
|
this.overlayRemovalTimers.clear();
|
|
15120
15087
|
}
|
|
15121
15088
|
/**
|
|
15122
|
-
* Full destructor — cancels
|
|
15123
|
-
* timers. Use this in component unmount/cleanup.
|
|
15124
|
-
*
|
|
15125
|
-
*
|
|
15126
|
-
*
|
|
15089
|
+
* Full destructor — cancels BOTH pending step timers AND overlay
|
|
15090
|
+
* removal timers. Use this in component unmount / cleanup.
|
|
15091
|
+
*
|
|
15092
|
+
* The per-storyboard `cancelPending()` deliberately leaves overlay
|
|
15093
|
+
* removal timers alone so a mid-flight overlay doesn't get stranded
|
|
15094
|
+
* when a new storyboard arrives (see `overlayRemovalTimers` doc).
|
|
15095
|
+
* That invariant is correct inside a session, but at teardown we
|
|
15096
|
+
* must release every timer — otherwise their setTimeout closures
|
|
15127
15097
|
* keep `deps` (narrationStore, the full bboxIndex) alive beyond the
|
|
15128
|
-
* lifetime of this engine.
|
|
15129
|
-
*
|
|
15098
|
+
* lifetime of this engine. Over many component recreations on iOS
|
|
15099
|
+
* Safari (viewport state churns during address-bar scroll
|
|
15100
|
+
* animation), that cumulative retention contributes to tab reloads.
|
|
15130
15101
|
*/
|
|
15131
15102
|
destroy() {
|
|
15132
15103
|
this.cancelPending();
|
|
@@ -16279,70 +16250,42 @@ function TutorModeContainer({
|
|
|
16279
16250
|
loadingComponent,
|
|
16280
16251
|
onPageChange,
|
|
16281
16252
|
storyboardProvider,
|
|
16282
|
-
renderScale,
|
|
16283
16253
|
className
|
|
16284
16254
|
}) {
|
|
16285
|
-
const containerRef = (0,
|
|
16286
|
-
const index = (0,
|
|
16255
|
+
const containerRef = (0, import_react57.useRef)(null);
|
|
16256
|
+
const index = (0, import_react57.useMemo)(() => buildBBoxIndex(bboxData), [bboxData]);
|
|
16287
16257
|
const {
|
|
16288
16258
|
document: document2,
|
|
16289
16259
|
currentPage: viewerCurrentPage,
|
|
16290
16260
|
numPages,
|
|
16291
16261
|
goToPage: viewerGoToPage
|
|
16292
16262
|
} = usePDFViewer();
|
|
16293
|
-
const [pageProxy, setPageProxy] = (0,
|
|
16294
|
-
const [viewport, setViewport] = (0,
|
|
16263
|
+
const [pageProxy, setPageProxy] = (0, import_react57.useState)(null);
|
|
16264
|
+
const [viewport, setViewport] = (0, import_react57.useState)({ width: 800, height: 1e3 });
|
|
16295
16265
|
const camera = (0, import_zustand2.useStore)(narrationStore, (s) => s.camera);
|
|
16296
16266
|
const activeOverlays = (0, import_zustand2.useStore)(narrationStore, (s) => s.activeOverlays);
|
|
16297
|
-
|
|
16298
|
-
const pagePointsW = page ? page.page_dimensions.width * 72 / page.page_dimensions.dpi : 0;
|
|
16299
|
-
const pagePointsH = page ? page.page_dimensions.height * 72 / page.page_dimensions.dpi : 0;
|
|
16300
|
-
const touch = isTouchDevice();
|
|
16301
|
-
const defaultRenderScale = page ? touch ? computeFitScale({
|
|
16302
|
-
pageWidthPt: pagePointsW,
|
|
16303
|
-
pageHeightPt: pagePointsH,
|
|
16304
|
-
viewport
|
|
16305
|
-
}) : page.page_dimensions.dpi / 72 : 1;
|
|
16306
|
-
const effectiveRenderScale = resolveRenderScale({
|
|
16307
|
-
renderScaleProp: renderScale,
|
|
16308
|
-
scaleProp: scale,
|
|
16309
|
-
defaultRenderScale
|
|
16310
|
-
});
|
|
16311
|
-
const coordScale = page ? computeCoordScale({
|
|
16312
|
-
renderScale: effectiveRenderScale,
|
|
16313
|
-
dpi: page.page_dimensions.dpi
|
|
16314
|
-
}) : 1;
|
|
16315
|
-
const rasterScale = effectiveRenderScale;
|
|
16316
|
-
const baseW = pagePointsW * effectiveRenderScale;
|
|
16317
|
-
const baseH = pagePointsH * effectiveRenderScale;
|
|
16318
|
-
(0, import_react58.useEffect)(() => {
|
|
16267
|
+
(0, import_react57.useEffect)(() => {
|
|
16319
16268
|
if (numPages <= 0) return;
|
|
16320
16269
|
if (pageNumber < 1 || pageNumber > numPages) return;
|
|
16321
16270
|
if (viewerCurrentPage === pageNumber) return;
|
|
16322
16271
|
viewerGoToPage(pageNumber);
|
|
16323
16272
|
}, [pageNumber, numPages, viewerCurrentPage, viewerGoToPage]);
|
|
16324
|
-
(0,
|
|
16273
|
+
(0, import_react57.useEffect)(() => {
|
|
16325
16274
|
if (!onPageChange) return;
|
|
16326
16275
|
if (viewerCurrentPage === pageNumber) return;
|
|
16327
16276
|
if (viewerCurrentPage < 1) return;
|
|
16328
16277
|
onPageChange(viewerCurrentPage);
|
|
16329
16278
|
}, [viewerCurrentPage, pageNumber, onPageChange]);
|
|
16330
|
-
(0,
|
|
16279
|
+
(0, import_react57.useEffect)(() => {
|
|
16331
16280
|
if (!containerRef.current) return;
|
|
16332
16281
|
const el = containerRef.current;
|
|
16333
|
-
const update = () => {
|
|
16334
|
-
const w = el.clientWidth;
|
|
16335
|
-
const h = el.clientHeight;
|
|
16336
|
-
setViewport(
|
|
16337
|
-
(prev) => prev.width === w && prev.height === h ? prev : { width: w, height: h }
|
|
16338
|
-
);
|
|
16339
|
-
};
|
|
16282
|
+
const update = () => setViewport({ width: el.clientWidth, height: el.clientHeight });
|
|
16340
16283
|
update();
|
|
16341
16284
|
const ro = new ResizeObserver(update);
|
|
16342
16285
|
ro.observe(el);
|
|
16343
16286
|
return () => ro.disconnect();
|
|
16344
16287
|
}, []);
|
|
16345
|
-
(0,
|
|
16288
|
+
(0, import_react57.useEffect)(() => {
|
|
16346
16289
|
if (!document2) {
|
|
16347
16290
|
setPageProxy(null);
|
|
16348
16291
|
return;
|
|
@@ -16357,40 +16300,34 @@ function TutorModeContainer({
|
|
|
16357
16300
|
cancelled = true;
|
|
16358
16301
|
};
|
|
16359
16302
|
}, [document2, pageNumber]);
|
|
16360
|
-
(0,
|
|
16303
|
+
(0, import_react57.useEffect)(() => {
|
|
16361
16304
|
narrationStore.getState().setCurrentPage(pageNumber);
|
|
16362
16305
|
}, [pageNumber, narrationStore]);
|
|
16363
|
-
(0,
|
|
16306
|
+
(0, import_react57.useEffect)(() => {
|
|
16364
16307
|
const page2 = index.byPage.get(pageNumber);
|
|
16365
16308
|
if (!page2) return;
|
|
16366
16309
|
if (viewport.width === 0 || viewport.height === 0) return;
|
|
16367
|
-
if (baseW === 0 || baseH === 0) return;
|
|
16368
16310
|
if (narrationStore.getState().activeOverlays.length > 0) return;
|
|
16369
|
-
const fit = Math.min(
|
|
16311
|
+
const fit = Math.min(
|
|
16312
|
+
viewport.width / page2.page_dimensions.width,
|
|
16313
|
+
viewport.height / page2.page_dimensions.height
|
|
16314
|
+
) * 0.95;
|
|
16370
16315
|
narrationStore.getState().setCamera({ scale: fit, x: 0, y: 0 });
|
|
16371
|
-
}, [pageNumber, viewport, index, narrationStore
|
|
16372
|
-
const
|
|
16373
|
-
(0,
|
|
16374
|
-
|
|
16375
|
-
}, [viewport]);
|
|
16376
|
-
const engineRef = (0, import_react58.useRef)(null);
|
|
16377
|
-
(0, import_react58.useEffect)(() => {
|
|
16378
|
-
const engine = new StoryboardEngine({
|
|
16316
|
+
}, [pageNumber, viewport, index, narrationStore]);
|
|
16317
|
+
const engineRef = (0, import_react57.useRef)(null);
|
|
16318
|
+
(0, import_react57.useEffect)(() => {
|
|
16319
|
+
engineRef.current = new StoryboardEngine({
|
|
16379
16320
|
narrationStore,
|
|
16380
16321
|
bboxIndex: index,
|
|
16381
|
-
getViewport: () =>
|
|
16322
|
+
getViewport: () => viewport,
|
|
16382
16323
|
minOverlayDurationMs
|
|
16383
16324
|
});
|
|
16384
|
-
engineRef.current
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
const abortRef = (0, import_react58.useRef)(null);
|
|
16391
|
-
const debounceRef = (0, import_react58.useRef)(null);
|
|
16392
|
-
const lastChunkRef = (0, import_react58.useRef)(null);
|
|
16393
|
-
(0, import_react58.useEffect)(() => {
|
|
16325
|
+
return () => engineRef.current?.destroy();
|
|
16326
|
+
}, [narrationStore, index, viewport, minOverlayDurationMs]);
|
|
16327
|
+
const abortRef = (0, import_react57.useRef)(null);
|
|
16328
|
+
const debounceRef = (0, import_react57.useRef)(null);
|
|
16329
|
+
const lastChunkRef = (0, import_react57.useRef)(null);
|
|
16330
|
+
(0, import_react57.useEffect)(() => {
|
|
16394
16331
|
if (!storyboardProvider && !llm) return;
|
|
16395
16332
|
if (!currentChunk || currentChunk === lastChunkRef.current) return;
|
|
16396
16333
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
@@ -16555,7 +16492,7 @@ function TutorModeContainer({
|
|
|
16555
16492
|
embeddingProvider,
|
|
16556
16493
|
llmTimeoutMs
|
|
16557
16494
|
]);
|
|
16558
|
-
(0,
|
|
16495
|
+
(0, import_react57.useEffect)(() => {
|
|
16559
16496
|
if (!currentChunk) return;
|
|
16560
16497
|
const t = setTimeout(() => {
|
|
16561
16498
|
if (!engineRef.current) return;
|
|
@@ -16567,6 +16504,11 @@ function TutorModeContainer({
|
|
|
16567
16504
|
}, idleTimeoutMs + 100);
|
|
16568
16505
|
return () => clearTimeout(t);
|
|
16569
16506
|
}, [currentChunk, idleTimeoutMs, narrationStore]);
|
|
16507
|
+
const page = index.byPage.get(pageNumber);
|
|
16508
|
+
const dpiScale = page ? page.page_dimensions.dpi / 72 : 1;
|
|
16509
|
+
const rasterScale = dpiScale * (scale || 1);
|
|
16510
|
+
const baseW = page ? page.page_dimensions.width * (scale || 1) : 0;
|
|
16511
|
+
const baseH = page ? page.page_dimensions.height * (scale || 1) : 0;
|
|
16570
16512
|
const isReady = !!page && !!pageProxy;
|
|
16571
16513
|
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
16572
16514
|
"div",
|
|
@@ -16645,7 +16587,7 @@ function TutorModeContainer({
|
|
|
16645
16587
|
page,
|
|
16646
16588
|
index,
|
|
16647
16589
|
overlays: activeOverlays,
|
|
16648
|
-
|
|
16590
|
+
scale: scale || 1
|
|
16649
16591
|
}
|
|
16650
16592
|
)
|
|
16651
16593
|
]
|
|
@@ -16658,8 +16600,7 @@ function TutorModeContainer({
|
|
|
16658
16600
|
index,
|
|
16659
16601
|
currentPage: pageNumber,
|
|
16660
16602
|
camera,
|
|
16661
|
-
viewport
|
|
16662
|
-
coordScale
|
|
16603
|
+
viewport
|
|
16663
16604
|
}
|
|
16664
16605
|
),
|
|
16665
16606
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
@@ -16669,8 +16610,7 @@ function TutorModeContainer({
|
|
|
16669
16610
|
index,
|
|
16670
16611
|
currentPage: pageNumber,
|
|
16671
16612
|
camera,
|
|
16672
|
-
viewport
|
|
16673
|
-
coordScale
|
|
16613
|
+
viewport
|
|
16674
16614
|
}
|
|
16675
16615
|
),
|
|
16676
16616
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(GhostReferenceOverlay, { overlays: activeOverlays, index })
|