pdfjs-reader-core 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1782,11 +1782,24 @@ interface TutorModeContainerProps {
1782
1782
  * Default: 3500ms.
1783
1783
  */
1784
1784
  minOverlayDurationMs?: number;
1785
+ /**
1786
+ * Background colour of the container surround (visible around the PDF when
1787
+ * the viewport is larger than the page fit). Default: `#ffffff`. Pass a
1788
+ * dark value for dark-themed hosts.
1789
+ */
1790
+ backgroundColor?: string;
1791
+ /**
1792
+ * Optional content to render while the PDF document/page is still loading.
1793
+ * Receives the loading stage so the host can show a spinner, a skeleton,
1794
+ * or a custom brand. If omitted, a minimal default spinner is rendered on
1795
+ * the `backgroundColor` surround.
1796
+ */
1797
+ loadingComponent?: react__default.ReactNode;
1785
1798
  className?: string;
1786
1799
  }
1787
1800
  /** Build a cross-page/block index from the raw bbox list. */
1788
1801
  declare function buildBBoxIndex(bboxData: PageBBoxData[]): BBoxIndex;
1789
- declare function TutorModeContainer({ pageNumber, bboxData, narrationStore, scale, rotation, currentChunk, llm, idleTimeoutMs, llmTimeoutMs, embeddingProvider, showSubtitles, showExitButton, onExitTutorMode, minOverlayDurationMs, className, }: TutorModeContainerProps): react_jsx_runtime.JSX.Element;
1802
+ declare function TutorModeContainer({ pageNumber, bboxData, narrationStore, scale, rotation, currentChunk, llm, idleTimeoutMs, llmTimeoutMs, embeddingProvider, showSubtitles, showExitButton, onExitTutorMode, minOverlayDurationMs, backgroundColor, loadingComponent, className, }: TutorModeContainerProps): react_jsx_runtime.JSX.Element;
1790
1803
 
1791
1804
  interface CinemaLayerProps {
1792
1805
  page: PageBBoxData;
@@ -1902,7 +1915,20 @@ interface EngineDeps {
1902
1915
  }
1903
1916
  declare class StoryboardEngine {
1904
1917
  private deps;
1905
- private pendingTimers;
1918
+ /**
1919
+ * Timers that schedule the START of a step (via `setTimeout(runStep, at_ms)`).
1920
+ * These are storyboard-scoped: when a new storyboard arrives, anything still
1921
+ * pending should be abandoned.
1922
+ */
1923
+ private pendingStepTimers;
1924
+ /**
1925
+ * Timers that auto-REMOVE an already-placed overlay after its visible
1926
+ * duration. Keyed by overlay id so we can cancel one specifically. These are
1927
+ * NOT cancelled when a new storyboard starts — otherwise the still-visible
1928
+ * overlay from the previous beat would get stranded in the store forever
1929
+ * (the "stuck spotlight" bug).
1930
+ */
1931
+ private overlayRemovalTimers;
1906
1932
  private currentStoryboardId;
1907
1933
  constructor(deps: EngineDeps);
1908
1934
  /**
@@ -1910,9 +1936,16 @@ declare class StoryboardEngine {
1910
1936
  * and smoothly transitions the camera/overlays from the current state.
1911
1937
  */
1912
1938
  execute(storyboard: Storyboard): void;
1913
- /** Abort all pending steps and set engine status to idle. */
1939
+ /**
1940
+ * Abort pending STEP dispatches from the current storyboard. Overlay
1941
+ * removal timers are left alone so already-visible overlays still auto-
1942
+ * expire on their own schedule. To force-clear every overlay, call
1943
+ * `resetVisuals()` instead.
1944
+ */
1914
1945
  cancelPending(): void;
1915
- /** Reset visuals: clear overlays, fit camera back to page. */
1946
+ /** Cancel every removal timer (used by resetVisuals only). */
1947
+ private cancelAllRemovalTimers;
1948
+ /** Reset visuals: clear overlays, cancel every removal timer, fit camera. */
1916
1949
  resetVisuals(): void;
1917
1950
  /** Execute one step — dispatch to narrationStore. Returns true if applied. */
1918
1951
  private runStep;
package/dist/index.d.ts CHANGED
@@ -1782,11 +1782,24 @@ interface TutorModeContainerProps {
1782
1782
  * Default: 3500ms.
1783
1783
  */
1784
1784
  minOverlayDurationMs?: number;
1785
+ /**
1786
+ * Background colour of the container surround (visible around the PDF when
1787
+ * the viewport is larger than the page fit). Default: `#ffffff`. Pass a
1788
+ * dark value for dark-themed hosts.
1789
+ */
1790
+ backgroundColor?: string;
1791
+ /**
1792
+ * Optional content to render while the PDF document/page is still loading.
1793
+ * Receives the loading stage so the host can show a spinner, a skeleton,
1794
+ * or a custom brand. If omitted, a minimal default spinner is rendered on
1795
+ * the `backgroundColor` surround.
1796
+ */
1797
+ loadingComponent?: react__default.ReactNode;
1785
1798
  className?: string;
1786
1799
  }
1787
1800
  /** Build a cross-page/block index from the raw bbox list. */
1788
1801
  declare function buildBBoxIndex(bboxData: PageBBoxData[]): BBoxIndex;
1789
- declare function TutorModeContainer({ pageNumber, bboxData, narrationStore, scale, rotation, currentChunk, llm, idleTimeoutMs, llmTimeoutMs, embeddingProvider, showSubtitles, showExitButton, onExitTutorMode, minOverlayDurationMs, className, }: TutorModeContainerProps): react_jsx_runtime.JSX.Element;
1802
+ declare function TutorModeContainer({ pageNumber, bboxData, narrationStore, scale, rotation, currentChunk, llm, idleTimeoutMs, llmTimeoutMs, embeddingProvider, showSubtitles, showExitButton, onExitTutorMode, minOverlayDurationMs, backgroundColor, loadingComponent, className, }: TutorModeContainerProps): react_jsx_runtime.JSX.Element;
1790
1803
 
1791
1804
  interface CinemaLayerProps {
1792
1805
  page: PageBBoxData;
@@ -1902,7 +1915,20 @@ interface EngineDeps {
1902
1915
  }
1903
1916
  declare class StoryboardEngine {
1904
1917
  private deps;
1905
- private pendingTimers;
1918
+ /**
1919
+ * Timers that schedule the START of a step (via `setTimeout(runStep, at_ms)`).
1920
+ * These are storyboard-scoped: when a new storyboard arrives, anything still
1921
+ * pending should be abandoned.
1922
+ */
1923
+ private pendingStepTimers;
1924
+ /**
1925
+ * Timers that auto-REMOVE an already-placed overlay after its visible
1926
+ * duration. Keyed by overlay id so we can cancel one specifically. These are
1927
+ * NOT cancelled when a new storyboard starts — otherwise the still-visible
1928
+ * overlay from the previous beat would get stranded in the store forever
1929
+ * (the "stuck spotlight" bug).
1930
+ */
1931
+ private overlayRemovalTimers;
1906
1932
  private currentStoryboardId;
1907
1933
  constructor(deps: EngineDeps);
1908
1934
  /**
@@ -1910,9 +1936,16 @@ declare class StoryboardEngine {
1910
1936
  * and smoothly transitions the camera/overlays from the current state.
1911
1937
  */
1912
1938
  execute(storyboard: Storyboard): void;
1913
- /** Abort all pending steps and set engine status to idle. */
1939
+ /**
1940
+ * Abort pending STEP dispatches from the current storyboard. Overlay
1941
+ * removal timers are left alone so already-visible overlays still auto-
1942
+ * expire on their own schedule. To force-clear every overlay, call
1943
+ * `resetVisuals()` instead.
1944
+ */
1914
1945
  cancelPending(): void;
1915
- /** Reset visuals: clear overlays, fit camera back to page. */
1946
+ /** Cancel every removal timer (used by resetVisuals only). */
1947
+ private cancelAllRemovalTimers;
1948
+ /** Reset visuals: clear overlays, cancel every removal timer, fit camera. */
1916
1949
  resetVisuals(): void;
1917
1950
  /** Execute one step — dispatch to narrationStore. Returns true if applied. */
1918
1951
  private runStep;
package/dist/index.js CHANGED
@@ -13621,7 +13621,20 @@ init_camera_math();
13621
13621
  var DEFAULT_MIN_OVERLAY_MS = 3500;
13622
13622
  var StoryboardEngine = class {
13623
13623
  constructor(deps) {
13624
- this.pendingTimers = /* @__PURE__ */ new Set();
13624
+ /**
13625
+ * Timers that schedule the START of a step (via `setTimeout(runStep, at_ms)`).
13626
+ * These are storyboard-scoped: when a new storyboard arrives, anything still
13627
+ * pending should be abandoned.
13628
+ */
13629
+ this.pendingStepTimers = /* @__PURE__ */ new Set();
13630
+ /**
13631
+ * Timers that auto-REMOVE an already-placed overlay after its visible
13632
+ * duration. Keyed by overlay id so we can cancel one specifically. These are
13633
+ * NOT cancelled when a new storyboard starts — otherwise the still-visible
13634
+ * overlay from the previous beat would get stranded in the store forever
13635
+ * (the "stuck spotlight" bug).
13636
+ */
13637
+ this.overlayRemovalTimers = /* @__PURE__ */ new Map();
13625
13638
  this.currentStoryboardId = 0;
13626
13639
  this.deps = deps;
13627
13640
  }
@@ -13664,13 +13677,13 @@ var StoryboardEngine = class {
13664
13677
  if (storyboardId !== this.currentStoryboardId) return;
13665
13678
  this.runStep(step);
13666
13679
  }, step.at_ms);
13667
- this.pendingTimers.add(timer);
13680
+ this.pendingStepTimers.add(timer);
13668
13681
  }
13669
13682
  const markExecuting = setTimeout(() => {
13670
13683
  if (storyboardId !== this.currentStoryboardId) return;
13671
13684
  narrationStore.getState().setEngineStatus("executing");
13672
13685
  }, 0);
13673
- this.pendingTimers.add(markExecuting);
13686
+ this.pendingStepTimers.add(markExecuting);
13674
13687
  const last = steps[steps.length - 1];
13675
13688
  if (last) {
13676
13689
  const totalMs = last.at_ms + last.duration_ms;
@@ -13678,18 +13691,29 @@ var StoryboardEngine = class {
13678
13691
  if (storyboardId !== this.currentStoryboardId) return;
13679
13692
  narrationStore.getState().setEngineStatus("idle");
13680
13693
  }, totalMs + 50);
13681
- this.pendingTimers.add(markIdle);
13694
+ this.pendingStepTimers.add(markIdle);
13682
13695
  }
13683
13696
  }
13684
- /** Abort all pending steps and set engine status to idle. */
13697
+ /**
13698
+ * Abort pending STEP dispatches from the current storyboard. Overlay
13699
+ * removal timers are left alone so already-visible overlays still auto-
13700
+ * expire on their own schedule. To force-clear every overlay, call
13701
+ * `resetVisuals()` instead.
13702
+ */
13685
13703
  cancelPending() {
13686
- for (const t of this.pendingTimers) clearTimeout(t);
13687
- this.pendingTimers.clear();
13704
+ for (const t of this.pendingStepTimers) clearTimeout(t);
13705
+ this.pendingStepTimers.clear();
13688
13706
  this.deps.narrationStore.getState().setEngineStatus("idle");
13689
13707
  }
13690
- /** Reset visuals: clear overlays, fit camera back to page. */
13708
+ /** Cancel every removal timer (used by resetVisuals only). */
13709
+ cancelAllRemovalTimers() {
13710
+ for (const t of this.overlayRemovalTimers.values()) clearTimeout(t);
13711
+ this.overlayRemovalTimers.clear();
13712
+ }
13713
+ /** Reset visuals: clear overlays, cancel every removal timer, fit camera. */
13691
13714
  resetVisuals() {
13692
13715
  this.cancelPending();
13716
+ this.cancelAllRemovalTimers();
13693
13717
  const { narrationStore, bboxIndex, getViewport } = this.deps;
13694
13718
  narrationStore.getState().clearOverlays();
13695
13719
  const viewport = getViewport();
@@ -13760,8 +13784,9 @@ var StoryboardEngine = class {
13760
13784
  narrationStore.getState().addOverlay(overlay);
13761
13785
  const timer = setTimeout(() => {
13762
13786
  narrationStore.getState().removeOverlay(overlay.id);
13787
+ this.overlayRemovalTimers.delete(overlay.id);
13763
13788
  }, visibleMs);
13764
- this.pendingTimers.add(timer);
13789
+ this.overlayRemovalTimers.set(overlay.id, timer);
13765
13790
  return true;
13766
13791
  }
13767
13792
  applyCamera(action, durationMs) {
@@ -14812,6 +14837,8 @@ function TutorModeContainer({
14812
14837
  showExitButton = true,
14813
14838
  onExitTutorMode,
14814
14839
  minOverlayDurationMs,
14840
+ backgroundColor = "#ffffff",
14841
+ loadingComponent,
14815
14842
  className
14816
14843
  }) {
14817
14844
  const containerRef = useRef27(null);
@@ -14976,6 +15003,7 @@ function TutorModeContainer({
14976
15003
  const rasterScale = dpiScale * (scale || 1);
14977
15004
  const baseW = page ? page.page_dimensions.width * (scale || 1) : 0;
14978
15005
  const baseH = page ? page.page_dimensions.height * (scale || 1) : 0;
15006
+ const isReady = !!page && !!pageProxy;
14979
15007
  return /* @__PURE__ */ jsxs38(
14980
15008
  "div",
14981
15009
  {
@@ -14986,12 +15014,12 @@ function TutorModeContainer({
14986
15014
  width: "100%",
14987
15015
  height: "100%",
14988
15016
  overflow: "hidden",
14989
- background: "#111"
15017
+ background: backgroundColor
14990
15018
  },
14991
15019
  "data-role": "tutor-mode-container",
14992
- "data-page-loaded": page ? "true" : "false",
15020
+ "data-page-loaded": isReady ? "true" : "false",
14993
15021
  children: [
14994
- showExitButton ? /* @__PURE__ */ jsx52(
15022
+ showExitButton && isReady ? /* @__PURE__ */ jsx52(
14995
15023
  "button",
14996
15024
  {
14997
15025
  onClick: () => {
@@ -15008,7 +15036,9 @@ function TutorModeContainer({
15008
15036
  padding: "8px 14px",
15009
15037
  border: "none",
15010
15038
  borderRadius: 8,
15011
- background: "rgba(255,255,255,0.12)",
15039
+ // Dark translucent pill with white text reads cleanly on both
15040
+ // light and dark container backgrounds.
15041
+ background: "rgba(17,24,39,0.72)",
15012
15042
  color: "white",
15013
15043
  cursor: "pointer",
15014
15044
  fontFamily: "system-ui, sans-serif",
@@ -15020,7 +15050,7 @@ function TutorModeContainer({
15020
15050
  children: "Reset view"
15021
15051
  }
15022
15052
  ) : null,
15023
- page ? /* @__PURE__ */ jsx52(CameraView, { camera, children: /* @__PURE__ */ jsxs38(
15053
+ isReady ? /* @__PURE__ */ jsx52(CameraView, { camera, children: /* @__PURE__ */ jsxs38(
15024
15054
  "div",
15025
15055
  {
15026
15056
  style: {
@@ -15055,12 +15085,73 @@ function TutorModeContainer({
15055
15085
  )
15056
15086
  ]
15057
15087
  }
15058
- ) }) : null,
15088
+ ) }) : /* @__PURE__ */ jsx52(TutorLoadingState, { custom: loadingComponent }),
15059
15089
  showSubtitles ? /* @__PURE__ */ jsx52(SubtitleBar, { text: currentChunk ?? null }) : null
15060
15090
  ]
15061
15091
  }
15062
15092
  );
15063
15093
  }
15094
+ function TutorLoadingState({
15095
+ custom
15096
+ }) {
15097
+ if (custom) {
15098
+ return /* @__PURE__ */ jsx52(
15099
+ "div",
15100
+ {
15101
+ style: {
15102
+ position: "absolute",
15103
+ inset: 0,
15104
+ display: "flex",
15105
+ alignItems: "center",
15106
+ justifyContent: "center"
15107
+ },
15108
+ "data-role": "tutor-loading",
15109
+ children: custom
15110
+ }
15111
+ );
15112
+ }
15113
+ return /* @__PURE__ */ jsxs38(
15114
+ "div",
15115
+ {
15116
+ style: {
15117
+ position: "absolute",
15118
+ inset: 0,
15119
+ display: "flex",
15120
+ flexDirection: "column",
15121
+ alignItems: "center",
15122
+ justifyContent: "center",
15123
+ gap: 12,
15124
+ color: "rgba(0,0,0,0.55)",
15125
+ fontFamily: "system-ui, sans-serif",
15126
+ fontSize: 13
15127
+ },
15128
+ "data-role": "tutor-loading",
15129
+ children: [
15130
+ /* @__PURE__ */ jsx52(
15131
+ "div",
15132
+ {
15133
+ "aria-hidden": true,
15134
+ style: {
15135
+ width: 36,
15136
+ height: 36,
15137
+ borderRadius: "50%",
15138
+ border: "3px solid rgba(0,0,0,0.1)",
15139
+ borderTopColor: "rgba(0,0,0,0.45)",
15140
+ animation: "pdf-tutor-spin 0.9s linear infinite"
15141
+ }
15142
+ }
15143
+ ),
15144
+ /* @__PURE__ */ jsx52("span", { children: "Loading document\u2026" }),
15145
+ /* @__PURE__ */ jsx52("style", { children: `
15146
+ @keyframes pdf-tutor-spin {
15147
+ from { transform: rotate(0deg); }
15148
+ to { transform: rotate(360deg); }
15149
+ }
15150
+ ` })
15151
+ ]
15152
+ }
15153
+ );
15154
+ }
15064
15155
 
15065
15156
  // src/director/transformers-embedding.ts
15066
15157
  var loaded = null;