pdfjs-reader-core 0.5.6 → 0.5.8

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 CHANGED
@@ -13268,7 +13268,7 @@ function withErrorBoundary({ component, ...props }) {
13268
13268
  init_PDFLoadingScreen2();
13269
13269
 
13270
13270
  // src/components/TutorMode/TutorModeContainer.tsx
13271
- var import_react58 = require("react");
13271
+ var import_react57 = require("react");
13272
13272
  var import_zustand2 = require("zustand");
13273
13273
  init_PDFPage2();
13274
13274
  init_hooks();
@@ -13559,12 +13559,23 @@ 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 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;
13562
13569
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
13563
13570
  "svg",
13564
13571
  {
13572
+ width: svgW,
13573
+ height: svgH,
13574
+ viewBox: `${svgX} ${svgY} ${svgW} ${svgH}`,
13565
13575
  style: {
13566
13576
  position: "absolute",
13567
- inset: 0,
13577
+ left: svgX,
13578
+ top: svgY,
13568
13579
  pointerEvents: "none",
13569
13580
  overflow: "visible"
13570
13581
  },
@@ -13627,10 +13638,14 @@ function AnimatedUnderline({ bbox, action }) {
13627
13638
  }
13628
13639
 
13629
13640
  // src/components/TutorMode/AnimatedHighlight.tsx
13630
- var import_react56 = require("react");
13631
13641
  var import_framer_motion4 = require("framer-motion");
13632
13642
  var import_jsx_runtime44 = require("react/jsx-runtime");
13633
- var WASH = "rgba(230, 180, 34, 0.22)";
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
+ }
13634
13649
  function AnimatedHighlight({ bbox, action }) {
13635
13650
  const [x1, y1, x2, y2] = bbox;
13636
13651
  const h = Math.max(1, y2 - y1);
@@ -13638,9 +13653,8 @@ function AnimatedHighlight({ bbox, action }) {
13638
13653
  const yTop = y1 - bleed;
13639
13654
  const yBot = y2 + bleed;
13640
13655
  const duration = action.draw_duration_ms / 1e3;
13641
- const filterId = (0, import_react56.useId)();
13642
13656
  const isDefaultColour = !action.color || action.color === "rgba(250, 204, 21, 0.35)" || action.color === "rgba(250,204,21,0.35)";
13643
- const fill = isDefaultColour ? WASH : action.color;
13657
+ const fill = stripAlpha(isDefaultColour ? DEFAULT_HUE : action.color);
13644
13658
  const taper = Math.min(6, h * 0.2);
13645
13659
  const pathD = `
13646
13660
  M ${x1 - 2} ${yTop + taper}
@@ -13653,44 +13667,37 @@ function AnimatedHighlight({ bbox, action }) {
13653
13667
  L ${x1 - 2} ${yBot - taper}
13654
13668
  Z
13655
13669
  `;
13656
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
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;
13675
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13657
13676
  "svg",
13658
13677
  {
13678
+ width: svgW,
13679
+ height: svgH,
13680
+ viewBox: `${svgX} ${svgY} ${svgW} ${svgH}`,
13659
13681
  style: {
13660
13682
  position: "absolute",
13661
- inset: 0,
13683
+ left: svgX,
13684
+ top: svgY,
13662
13685
  pointerEvents: "none",
13663
- overflow: "visible",
13664
- mixBlendMode: "multiply"
13686
+ overflow: "visible"
13665
13687
  },
13666
13688
  "data-role": "highlight",
13667
- children: [
13668
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("filter", { id: filterId, children: [
13669
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13670
- "feTurbulence",
13671
- {
13672
- type: "fractalNoise",
13673
- baseFrequency: "1.8",
13674
- numOctaves: "1",
13675
- seed: 3,
13676
- result: "noise"
13677
- }
13678
- ),
13679
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("feDisplacementMap", { in: "SourceGraphic", in2: "noise", scale: 1 })
13680
- ] }) }),
13681
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13682
- import_framer_motion4.motion.path,
13683
- {
13684
- d: pathD,
13685
- fill,
13686
- initial: { clipPath: `inset(0 100% 0 0)` },
13687
- animate: { clipPath: `inset(0 0% 0 0)` },
13688
- exit: { opacity: 0 },
13689
- filter: `url(#${filterId})`,
13690
- transition: { duration, ease: EASE_OUT_EXPO }
13691
- }
13692
- )
13693
- ]
13689
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
13690
+ import_framer_motion4.motion.path,
13691
+ {
13692
+ d: pathD,
13693
+ fill,
13694
+ fillOpacity: WASH_OPACITY,
13695
+ initial: { clipPath: `inset(0 100% 0 0)` },
13696
+ animate: { clipPath: `inset(0 0% 0 0)` },
13697
+ exit: { opacity: 0 },
13698
+ transition: { duration, ease: EASE_OUT_EXPO }
13699
+ }
13700
+ )
13694
13701
  }
13695
13702
  );
13696
13703
  }
@@ -13712,12 +13719,27 @@ function PulseOverlay({ bbox, action }) {
13712
13719
  const spec = INTENSITY[action.intensity] ?? INTENSITY.normal;
13713
13720
  const L = Math.min(spec.bracketLen, Math.min(w, h) / 2.5);
13714
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;
13726
+ const bracketExtent = PAD + L + 8;
13727
+ const svgPadX = Math.ceil(Math.max(40, ringExtentX, glowExtentX, bracketExtent));
13728
+ const svgPadY = Math.ceil(Math.max(40, ringExtentY, glowExtentY, bracketExtent));
13729
+ const svgX = x1 - svgPadX;
13730
+ const svgY = y1 - svgPadY;
13731
+ const svgW = w + 2 * svgPadX;
13732
+ const svgH = h + 2 * svgPadY;
13715
13733
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
13716
13734
  "svg",
13717
13735
  {
13736
+ width: svgW,
13737
+ height: svgH,
13738
+ viewBox: `${svgX} ${svgY} ${svgW} ${svgH}`,
13718
13739
  style: {
13719
13740
  position: "absolute",
13720
- inset: 0,
13741
+ left: svgX,
13742
+ top: svgY,
13721
13743
  pointerEvents: "none",
13722
13744
  overflow: "visible"
13723
13745
  },
@@ -13865,7 +13887,7 @@ function Bracket({
13865
13887
  }
13866
13888
 
13867
13889
  // src/components/TutorMode/CalloutArrow.tsx
13868
- var import_react57 = require("react");
13890
+ var import_react56 = require("react");
13869
13891
  var import_framer_motion6 = require("framer-motion");
13870
13892
  var import_jsx_runtime46 = require("react/jsx-runtime");
13871
13893
  function centerOf(b) {
@@ -13903,16 +13925,31 @@ function arrowPath(from, to, curve) {
13903
13925
  return `M ${from.x} ${from.y} Q ${cx} ${cy} ${to.x} ${to.y}`;
13904
13926
  }
13905
13927
  function CalloutArrow({ fromBbox, toBbox, action }) {
13906
- const markerId = (0, import_react57.useId)();
13928
+ const markerId = (0, import_react56.useId)();
13907
13929
  const glowId = `${markerId}-glow`;
13908
13930
  const { from, to } = edgePoints(fromBbox, toBbox);
13909
13931
  const d = arrowPath(from, to, action.curve);
13932
+ const rawMinX = Math.min(from.x, to.x);
13933
+ const rawMinY = Math.min(from.y, to.y);
13934
+ const rawMaxX = Math.max(from.x, to.x);
13935
+ const rawMaxY = Math.max(from.y, to.y);
13936
+ const dist = Math.hypot(to.x - from.x, to.y - from.y);
13937
+ const arcDev = action.curve === "curved" ? dist * 0.12 : 0;
13938
+ const basePad = 16;
13939
+ const svgX = rawMinX - basePad - arcDev;
13940
+ const svgY = rawMinY - basePad - arcDev;
13941
+ const svgW = rawMaxX - rawMinX + 2 * (basePad + arcDev);
13942
+ const svgH = rawMaxY - rawMinY + 2 * (basePad + arcDev);
13910
13943
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
13911
13944
  "svg",
13912
13945
  {
13946
+ width: svgW,
13947
+ height: svgH,
13948
+ viewBox: `${svgX} ${svgY} ${svgW} ${svgH}`,
13913
13949
  style: {
13914
13950
  position: "absolute",
13915
- inset: 0,
13951
+ left: svgX,
13952
+ top: svgY,
13916
13953
  pointerEvents: "none",
13917
13954
  overflow: "visible"
13918
13955
  },
@@ -15036,11 +15073,36 @@ var StoryboardEngine = class {
15036
15073
  this.pendingStepTimers.clear();
15037
15074
  this.deps.narrationStore.getState().setEngineStatus("idle");
15038
15075
  }
15039
- /** Cancel every removal timer (used by resetVisuals only). */
15076
+ /** Cancel every removal timer (used by resetVisuals and destroy). */
15040
15077
  cancelAllRemovalTimers() {
15041
15078
  for (const t of this.overlayRemovalTimers.values()) clearTimeout(t);
15042
15079
  this.overlayRemovalTimers.clear();
15043
15080
  }
15081
+ /**
15082
+ * Full destructor — cancels BOTH pending step timers AND overlay
15083
+ * removal timers. Use this in component unmount / cleanup.
15084
+ *
15085
+ * The per-storyboard `cancelPending()` deliberately leaves overlay
15086
+ * removal timers alone so a mid-flight overlay doesn't get stranded
15087
+ * when a new storyboard arrives (see `overlayRemovalTimers` doc).
15088
+ * That invariant is correct inside a session, but at teardown we
15089
+ * must release every timer — otherwise their setTimeout closures
15090
+ * keep `deps` (narrationStore, the full bboxIndex) alive beyond the
15091
+ * lifetime of this engine. Over many component recreations on iOS
15092
+ * Safari (viewport state churns during address-bar scroll
15093
+ * animation), that cumulative retention contributes to tab reloads.
15094
+ */
15095
+ destroy() {
15096
+ this.cancelPending();
15097
+ this.cancelAllRemovalTimers();
15098
+ }
15099
+ /** Test-only — exposes internal queue sizes for regression tests. */
15100
+ _queueSizesForTest() {
15101
+ return {
15102
+ pending: this.pendingStepTimers.size,
15103
+ removals: this.overlayRemovalTimers.size
15104
+ };
15105
+ }
15044
15106
  /** Reset visuals: clear overlays, cancel every removal timer, fit camera. */
15045
15107
  resetVisuals() {
15046
15108
  this.cancelPending();
@@ -16183,31 +16245,31 @@ function TutorModeContainer({
16183
16245
  storyboardProvider,
16184
16246
  className
16185
16247
  }) {
16186
- const containerRef = (0, import_react58.useRef)(null);
16187
- const index = (0, import_react58.useMemo)(() => buildBBoxIndex(bboxData), [bboxData]);
16248
+ const containerRef = (0, import_react57.useRef)(null);
16249
+ const index = (0, import_react57.useMemo)(() => buildBBoxIndex(bboxData), [bboxData]);
16188
16250
  const {
16189
16251
  document: document2,
16190
16252
  currentPage: viewerCurrentPage,
16191
16253
  numPages,
16192
16254
  goToPage: viewerGoToPage
16193
16255
  } = usePDFViewer();
16194
- const [pageProxy, setPageProxy] = (0, import_react58.useState)(null);
16195
- const [viewport, setViewport] = (0, import_react58.useState)({ width: 800, height: 1e3 });
16256
+ const [pageProxy, setPageProxy] = (0, import_react57.useState)(null);
16257
+ const [viewport, setViewport] = (0, import_react57.useState)({ width: 800, height: 1e3 });
16196
16258
  const camera = (0, import_zustand2.useStore)(narrationStore, (s) => s.camera);
16197
16259
  const activeOverlays = (0, import_zustand2.useStore)(narrationStore, (s) => s.activeOverlays);
16198
- (0, import_react58.useEffect)(() => {
16260
+ (0, import_react57.useEffect)(() => {
16199
16261
  if (numPages <= 0) return;
16200
16262
  if (pageNumber < 1 || pageNumber > numPages) return;
16201
16263
  if (viewerCurrentPage === pageNumber) return;
16202
16264
  viewerGoToPage(pageNumber);
16203
16265
  }, [pageNumber, numPages, viewerCurrentPage, viewerGoToPage]);
16204
- (0, import_react58.useEffect)(() => {
16266
+ (0, import_react57.useEffect)(() => {
16205
16267
  if (!onPageChange) return;
16206
16268
  if (viewerCurrentPage === pageNumber) return;
16207
16269
  if (viewerCurrentPage < 1) return;
16208
16270
  onPageChange(viewerCurrentPage);
16209
16271
  }, [viewerCurrentPage, pageNumber, onPageChange]);
16210
- (0, import_react58.useEffect)(() => {
16272
+ (0, import_react57.useEffect)(() => {
16211
16273
  if (!containerRef.current) return;
16212
16274
  const el = containerRef.current;
16213
16275
  const update = () => setViewport({ width: el.clientWidth, height: el.clientHeight });
@@ -16216,7 +16278,7 @@ function TutorModeContainer({
16216
16278
  ro.observe(el);
16217
16279
  return () => ro.disconnect();
16218
16280
  }, []);
16219
- (0, import_react58.useEffect)(() => {
16281
+ (0, import_react57.useEffect)(() => {
16220
16282
  if (!document2) {
16221
16283
  setPageProxy(null);
16222
16284
  return;
@@ -16231,10 +16293,10 @@ function TutorModeContainer({
16231
16293
  cancelled = true;
16232
16294
  };
16233
16295
  }, [document2, pageNumber]);
16234
- (0, import_react58.useEffect)(() => {
16296
+ (0, import_react57.useEffect)(() => {
16235
16297
  narrationStore.getState().setCurrentPage(pageNumber);
16236
16298
  }, [pageNumber, narrationStore]);
16237
- (0, import_react58.useEffect)(() => {
16299
+ (0, import_react57.useEffect)(() => {
16238
16300
  const page2 = index.byPage.get(pageNumber);
16239
16301
  if (!page2) return;
16240
16302
  if (viewport.width === 0 || viewport.height === 0) return;
@@ -16245,20 +16307,20 @@ function TutorModeContainer({
16245
16307
  ) * 0.95;
16246
16308
  narrationStore.getState().setCamera({ scale: fit, x: 0, y: 0 });
16247
16309
  }, [pageNumber, viewport, index, narrationStore]);
16248
- const engineRef = (0, import_react58.useRef)(null);
16249
- (0, import_react58.useEffect)(() => {
16310
+ const engineRef = (0, import_react57.useRef)(null);
16311
+ (0, import_react57.useEffect)(() => {
16250
16312
  engineRef.current = new StoryboardEngine({
16251
16313
  narrationStore,
16252
16314
  bboxIndex: index,
16253
16315
  getViewport: () => viewport,
16254
16316
  minOverlayDurationMs
16255
16317
  });
16256
- return () => engineRef.current?.cancelPending();
16318
+ return () => engineRef.current?.destroy();
16257
16319
  }, [narrationStore, index, viewport, minOverlayDurationMs]);
16258
- const abortRef = (0, import_react58.useRef)(null);
16259
- const debounceRef = (0, import_react58.useRef)(null);
16260
- const lastChunkRef = (0, import_react58.useRef)(null);
16261
- (0, import_react58.useEffect)(() => {
16320
+ const abortRef = (0, import_react57.useRef)(null);
16321
+ const debounceRef = (0, import_react57.useRef)(null);
16322
+ const lastChunkRef = (0, import_react57.useRef)(null);
16323
+ (0, import_react57.useEffect)(() => {
16262
16324
  if (!storyboardProvider && !llm) return;
16263
16325
  if (!currentChunk || currentChunk === lastChunkRef.current) return;
16264
16326
  if (debounceRef.current) clearTimeout(debounceRef.current);
@@ -16423,7 +16485,7 @@ function TutorModeContainer({
16423
16485
  embeddingProvider,
16424
16486
  llmTimeoutMs
16425
16487
  ]);
16426
- (0, import_react58.useEffect)(() => {
16488
+ (0, import_react57.useEffect)(() => {
16427
16489
  if (!currentChunk) return;
16428
16490
  const t = setTimeout(() => {
16429
16491
  if (!engineRef.current) return;