{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/strategies/base-strategy.ts","../src/lib/strategies/vertical-strategy.ts","../src/lib/strategies/horizontal-strategy.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/selectors.ts","../src/lib/scroll-plugin.ts","../src/lib/manifest.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { PdfPageObject, PdfPageObjectWithRotatedSize, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from './types/virtual-item';\n\nexport type ScrollBehavior = 'instant' | 'smooth' | 'auto';\n\nexport interface PageChangeState {\n  isChanging: boolean;\n  targetPage: number;\n  fromPage: number;\n  startTime: number;\n}\n\n// Per-document scroll state\nexport interface ScrollDocumentState {\n  virtualItems: VirtualItem[];\n  totalPages: number;\n  currentPage: number;\n  totalContentSize: { width: number; height: number };\n  strategy: ScrollStrategy;\n  pageGap: number;\n\n  // Scroll metrics\n  visiblePages: number[];\n  pageVisibilityMetrics: PageVisibilityMetrics[];\n  renderedPageIndexes: number[];\n  scrollOffset: { x: number; y: number };\n  startSpacing: number;\n  endSpacing: number;\n  pageChangeState: PageChangeState;\n}\n\n// Plugin state\nexport interface ScrollState {\n  // Global defaults (applied to new documents)\n  defaultStrategy: ScrollStrategy;\n  defaultPageGap: number;\n  defaultBufferSize: number;\n\n  // Per-document states\n  documents: Record<string, ScrollDocumentState>;\n}\n\nexport interface ScrollerLayout {\n  startSpacing: number;\n  endSpacing: number;\n  totalWidth: number;\n  totalHeight: number;\n  pageGap: number;\n  strategy: ScrollStrategy;\n  items: VirtualItem[];\n}\n\nexport enum ScrollStrategy {\n  Vertical = 'vertical',\n  Horizontal = 'horizontal',\n}\n\nexport interface PageVisibilityMetrics {\n  pageNumber: number;\n  viewportX: number;\n  viewportY: number;\n  visiblePercentage: number;\n  original: {\n    pageX: number;\n    pageY: number;\n    visibleWidth: number;\n    visibleHeight: number;\n    scale: number;\n  };\n  scaled: {\n    pageX: number;\n    pageY: number;\n    visibleWidth: number;\n    visibleHeight: number;\n    scale: number;\n  };\n}\n\nexport interface ScrollMetrics {\n  currentPage: number;\n  visiblePages: number[];\n  pageVisibilityMetrics: PageVisibilityMetrics[];\n  renderedPageIndexes: number[];\n  scrollOffset: { x: number; y: number };\n  startSpacing: number;\n  endSpacing: number;\n}\n\nexport interface ScrollPluginConfig extends BasePluginConfig {\n  defaultStrategy?: ScrollStrategy;\n  defaultPageGap?: number;\n  defaultBufferSize?: number;\n}\n\nexport type LayoutChangePayload = Pick<ScrollDocumentState, 'virtualItems' | 'totalContentSize'>;\n\nexport interface ScrollToPageOptions {\n  pageNumber: number;\n  pageCoordinates?: { x: number; y: number };\n  behavior?: ScrollBehavior;\n  /**\n   * Horizontal alignment as a percentage (0-100).\n   * 0 = target at left edge, 50 = centered, 100 = target at right edge.\n   */\n  alignX?: number;\n  /**\n   * Vertical alignment as a percentage (0-100).\n   * 0 = target at top edge, 50 = centered, 100 = target at bottom edge.\n   * Useful for mobile where UI overlays may cover part of the screen (e.g., alignY: 25 for top quarter).\n   */\n  alignY?: number;\n}\n\n// Events include documentId\nexport interface PageChangeEvent {\n  documentId: string;\n  pageNumber: number;\n  totalPages: number;\n}\n\nexport interface ScrollEvent {\n  documentId: string;\n  metrics: ScrollMetrics;\n}\n\nexport interface LayoutChangeEvent {\n  documentId: string;\n  layout: LayoutChangePayload;\n}\n\nexport interface PageChangeStateEvent {\n  documentId: string;\n  state: PageChangeState;\n}\n\nexport interface LayoutReadyEvent {\n  documentId: string;\n  /** True only on the first layout ready after document load, false on subsequent (e.g., tab switches) */\n  isInitial: boolean;\n  pageNumber: number;\n  totalPages: number;\n}\n\n// Scoped scroll capability\nexport interface ScrollScope {\n  getCurrentPage(): number;\n  getTotalPages(): number;\n  getPageChangeState(): PageChangeState;\n  scrollToPage(options: ScrollToPageOptions): void;\n  scrollToNextPage(behavior?: ScrollBehavior): void;\n  scrollToPreviousPage(behavior?: ScrollBehavior): void;\n  getSpreadPagesWithRotatedSize(): PdfPageObjectWithRotatedSize[][];\n  getMetrics(viewport?: ViewportMetrics): ScrollMetrics;\n  getLayout(): LayoutChangePayload;\n  getRectPositionForPage(\n    page: number,\n    rect: Rect,\n    scale?: number,\n    rotation?: Rotation,\n  ): Rect | null;\n  setScrollStrategy(strategy: ScrollStrategy): void;\n  onPageChange: EventHook<PageChangeEvent>;\n  onScroll: EventHook<ScrollMetrics>;\n  onLayoutChange: EventHook<LayoutChangePayload>;\n}\n\nexport interface ScrollCapability {\n  // Active document operations (defaults to active document)\n  getCurrentPage(): number;\n  getTotalPages(): number;\n  getPageChangeState(): PageChangeState;\n  scrollToPage(options: ScrollToPageOptions): void;\n  scrollToNextPage(behavior?: ScrollBehavior): void;\n  scrollToPreviousPage(behavior?: ScrollBehavior): void;\n  getMetrics(viewport?: ViewportMetrics): ScrollMetrics;\n  getLayout(): LayoutChangePayload;\n  getRectPositionForPage(\n    page: number,\n    rect: Rect,\n    scale?: number,\n    rotation?: Rotation,\n  ): Rect | null;\n\n  // Document-scoped operations\n  forDocument(documentId: string): ScrollScope;\n\n  // Global settings\n  setScrollStrategy(strategy: ScrollStrategy, documentId?: string): void;\n  getPageGap(): number;\n\n  // Events (all include documentId)\n  onPageChange: EventHook<PageChangeEvent>;\n  onScroll: EventHook<ScrollEvent>;\n  onLayoutChange: EventHook<LayoutChangeEvent>;\n  onLayoutReady: EventHook<LayoutReadyEvent>;\n  onPageChangeState: EventHook<PageChangeStateEvent>;\n  onStateChange: EventHook<ScrollDocumentState>;\n}\n","import {\n  PdfPageObjectWithRotatedSize,\n  Position,\n  Rect,\n  Rotation,\n  scalePosition,\n  Size,\n  transformPosition,\n  transformRect,\n} from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport interface ScrollStrategyConfig {\n  pageGap?: number;\n  viewportGap?: number;\n  bufferSize?: number;\n}\n\nexport abstract class BaseScrollStrategy {\n  protected pageGap: number;\n  protected viewportGap: number;\n  protected bufferSize: number;\n\n  constructor(config: ScrollStrategyConfig) {\n    this.pageGap = config.pageGap ?? 20;\n    this.viewportGap = config.viewportGap ?? 20;\n    this.bufferSize = config.bufferSize ?? 2;\n  }\n\n  abstract createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[];\n  abstract getTotalContentSize(virtualItems: VirtualItem[]): Size;\n  protected abstract getScrollOffset(viewport: ViewportMetrics): number;\n  protected abstract getClientSize(viewport: ViewportMetrics): number;\n\n  /**\n   * Returns the item's extent along the scroll axis. Vertical layout uses height;\n   * horizontal layout uses width. Used for visible range and end spacing calculations.\n   */\n  protected abstract getItemSizeAlongScrollAxis(item: VirtualItem): number;\n\n  /**\n   * Horizontal centering offset for items narrower than the content max width.\n   * Vertical layout centers spreads within the row; horizontal layout overrides to 0\n   * since items stay in a simple row without centering.\n   */\n  protected getCenteringOffsetX(_item: VirtualItem, totalContentSize: Size | undefined): number {\n    if (!totalContentSize || _item.width >= totalContentSize.width) return 0;\n    return (totalContentSize.width - _item.width) / 2;\n  }\n\n  /**\n   * Vertical centering offset for items shorter than the content max height.\n   * Horizontal layout centers items within the row height; vertical layout keeps\n   * items top-aligned and uses the default of 0.\n   */\n  protected getCenteringOffsetY(_item: VirtualItem, _totalContentSize: Size | undefined): number {\n    return 0;\n  }\n\n  protected getVisibleRange(\n    viewport: ViewportMetrics,\n    virtualItems: VirtualItem[],\n    scale: number,\n  ): { start: number; end: number } {\n    const scrollOffset = this.getScrollOffset(viewport);\n    const clientSize = this.getClientSize(viewport);\n    const viewportStart = scrollOffset;\n    const viewportEnd = scrollOffset + clientSize;\n\n    // Use extent along scroll axis (height for vertical, width for horizontal)\n    let startIndex = 0;\n    while (\n      startIndex < virtualItems.length &&\n      (virtualItems[startIndex].offset +\n        this.getItemSizeAlongScrollAxis(virtualItems[startIndex])) *\n        scale <=\n        viewportStart\n    ) {\n      startIndex++;\n    }\n\n    let endIndex = startIndex;\n    while (endIndex < virtualItems.length && virtualItems[endIndex].offset * scale <= viewportEnd) {\n      endIndex++;\n    }\n\n    return {\n      start: Math.max(0, startIndex - this.bufferSize),\n      end: Math.min(virtualItems.length - 1, endIndex + this.bufferSize - 1),\n    };\n  }\n\n  handleScroll(\n    viewport: ViewportMetrics,\n    virtualItems: VirtualItem[],\n    scale: number,\n  ): ScrollMetrics {\n    const range = this.getVisibleRange(viewport, virtualItems, scale);\n    const visibleItems = virtualItems.slice(range.start, range.end + 1);\n    const totalContentSize = this.getTotalContentSize(virtualItems);\n    const pageVisibilityMetrics = this.calculatePageVisibility(\n      visibleItems,\n      viewport,\n      scale,\n      totalContentSize,\n    );\n    const visiblePages = pageVisibilityMetrics.map((m) => m.pageNumber);\n    const renderedPageIndexes = virtualItems\n      .slice(range.start, range.end + 1)\n      .flatMap((item) => item.index);\n    const currentPage = this.determineCurrentPage(pageVisibilityMetrics);\n    const first = virtualItems[range.start];\n    const last = virtualItems[range.end];\n    const startSpacing = first ? first.offset * scale : 0;\n    const lastItem = virtualItems[virtualItems.length - 1];\n    // End spacing = distance from last rendered item to end of content (uses extent along scroll axis)\n    const endSpacing = last\n      ? (lastItem.offset + this.getItemSizeAlongScrollAxis(lastItem)) * scale -\n        (last.offset + this.getItemSizeAlongScrollAxis(last)) * scale\n      : 0;\n\n    return {\n      currentPage,\n      visiblePages,\n      pageVisibilityMetrics,\n      renderedPageIndexes,\n      scrollOffset: { x: viewport.scrollLeft, y: viewport.scrollTop },\n      startSpacing,\n      endSpacing,\n    };\n  }\n\n  protected calculatePageVisibility(\n    virtualItems: VirtualItem[],\n    viewport: ViewportMetrics,\n    scale: number,\n    totalContentSize?: Size,\n  ): ScrollMetrics['pageVisibilityMetrics'] {\n    const visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'] = [];\n\n    virtualItems.forEach((item) => {\n      const centeringOffsetX = this.getCenteringOffsetX(item, totalContentSize);\n      const centeringOffsetY = this.getCenteringOffsetY(item, totalContentSize);\n\n      item.pageLayouts.forEach((page) => {\n        const itemX = (item.x + centeringOffsetX) * scale;\n        const itemY = (item.y + centeringOffsetY) * scale;\n        const pageX = itemX + page.x * scale;\n        const pageY = itemY + page.y * scale;\n        const pageWidth = page.rotatedWidth * scale;\n        const pageHeight = page.rotatedHeight * scale;\n\n        const viewportLeft = viewport.scrollLeft;\n        const viewportTop = viewport.scrollTop;\n        const viewportRight = viewportLeft + viewport.clientWidth;\n        const viewportBottom = viewportTop + viewport.clientHeight;\n\n        const intersectionLeft = Math.max(pageX, viewportLeft);\n        const intersectionTop = Math.max(pageY, viewportTop);\n        const intersectionRight = Math.min(pageX + pageWidth, viewportRight);\n        const intersectionBottom = Math.min(pageY + pageHeight, viewportBottom);\n\n        if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) {\n          const visibleWidth = intersectionRight - intersectionLeft;\n          const visibleHeight = intersectionBottom - intersectionTop;\n          const totalArea = pageWidth * pageHeight;\n          const visibleArea = visibleWidth * visibleHeight;\n\n          visibilityMetrics.push({\n            pageNumber: page.pageNumber,\n            viewportX: intersectionLeft - viewportLeft,\n            viewportY: intersectionTop - viewportTop,\n            visiblePercentage: (visibleArea / totalArea) * 100,\n            original: {\n              pageX: (intersectionLeft - pageX) / scale,\n              pageY: (intersectionTop - pageY) / scale,\n              visibleWidth: visibleWidth / scale,\n              visibleHeight: visibleHeight / scale,\n              scale: 1,\n            },\n            scaled: {\n              pageX: intersectionLeft - pageX,\n              pageY: intersectionTop - pageY,\n              visibleWidth,\n              visibleHeight,\n              scale,\n            },\n          });\n        }\n      });\n    });\n\n    return visibilityMetrics;\n  }\n\n  protected determineCurrentPage(\n    visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'],\n  ): number {\n    if (visibilityMetrics.length === 0) return 1;\n\n    const maxVisibility = Math.max(...visibilityMetrics.map((m) => m.visiblePercentage));\n    const mostVisiblePages = visibilityMetrics.filter((m) => m.visiblePercentage === maxVisibility);\n\n    return mostVisiblePages.length === 1\n      ? mostVisiblePages[0].pageNumber\n      : mostVisiblePages.sort((a, b) => a.pageNumber - b.pageNumber)[0].pageNumber;\n  }\n\n  private getRectLocationForPage(\n    pageNumber: number,\n    virtualItems: VirtualItem[],\n    totalContentSize?: Size,\n  ): Rect | null {\n    // Find the virtual item containing the page\n    const item = virtualItems.find((item) => item.pageNumbers.includes(pageNumber));\n    if (!item) return null;\n\n    // Find the specific page layout for the requested page number\n    const pageLayout = item.pageLayouts.find((layout) => layout.pageNumber === pageNumber);\n    if (!pageLayout) return null;\n\n    const centeringOffsetX = this.getCenteringOffsetX(item, totalContentSize);\n    const centeringOffsetY = this.getCenteringOffsetY(item, totalContentSize);\n\n    return {\n      origin: {\n        x: item.x + pageLayout.x + centeringOffsetX,\n        y: item.y + pageLayout.y + centeringOffsetY,\n      },\n      size: {\n        width: pageLayout.width,\n        height: pageLayout.height,\n      },\n    };\n  }\n\n  getScrollPositionForPage(\n    pageNumber: number,\n    virtualItems: VirtualItem[],\n    scale: number,\n    rotation: Rotation,\n    pageCoordinates?: { x: number; y: number },\n  ): Position | null {\n    const totalContentSize = this.getTotalContentSize(virtualItems);\n    const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n    if (!pageRect) return null;\n\n    const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n    // If specific page coordinates are provided, add them to the base position\n    if (pageCoordinates) {\n      const rotatedSize = transformPosition(\n        {\n          width: pageRect.size.width,\n          height: pageRect.size.height,\n        },\n        {\n          x: pageCoordinates.x,\n          y: pageCoordinates.y,\n        },\n        rotation,\n        scale,\n      );\n\n      return {\n        x: scaledBasePosition.x + rotatedSize.x + this.viewportGap,\n        y: scaledBasePosition.y + rotatedSize.y + this.viewportGap,\n      };\n    }\n\n    return {\n      x: scaledBasePosition.x + this.viewportGap,\n      y: scaledBasePosition.y + this.viewportGap,\n    };\n  }\n\n  getRectPositionForPage(\n    pageNumber: number,\n    virtualItems: VirtualItem[],\n    scale: number,\n    rotation: Rotation,\n    rect: Rect,\n  ): Rect | null {\n    const totalContentSize = this.getTotalContentSize(virtualItems);\n    const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n    if (!pageRect) return null;\n\n    const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n    const rotatedSize = transformRect(\n      {\n        width: pageRect.size.width,\n        height: pageRect.size.height,\n      },\n      rect,\n      rotation,\n      scale,\n    );\n\n    return {\n      origin: {\n        x: scaledBasePosition.x + rotatedSize.origin.x,\n        y: scaledBasePosition.y + rotatedSize.origin.y,\n      },\n      size: rotatedSize.size,\n    };\n  }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\n\nexport class VerticalScrollStrategy extends BaseScrollStrategy {\n  constructor(config: ScrollStrategyConfig) {\n    super(config);\n  }\n\n  createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n    let yOffset = 0;\n    return pdfPageObject.map((pagesInSpread, index) => {\n      let pageX = 0;\n      const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n        const layout: PageLayout = {\n          pageNumber: page.index + 1,\n          pageIndex: page.index,\n          x: pageX,\n          y: 0,\n          width: page.size.width,\n          height: page.size.height,\n          rotatedWidth: page.rotatedSize.width,\n          rotatedHeight: page.rotatedSize.height,\n          elevated: false,\n        };\n        pageX += page.rotatedSize.width + this.pageGap;\n        return layout;\n      });\n      const width = pagesInSpread.reduce(\n        (sum, page, i) =>\n          sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n        0,\n      );\n      const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n      const item: VirtualItem = {\n        id: `item-${index}`,\n        x: 0,\n        y: yOffset,\n        offset: yOffset,\n        width,\n        height,\n        pageLayouts,\n        pageNumbers: pagesInSpread.map((p) => p.index + 1),\n        index,\n      };\n      yOffset += height + this.pageGap;\n      return item;\n    });\n  }\n\n  getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n    if (virtualItems.length === 0) return { width: 0, height: 0 };\n    const maxWidth = Math.max(...virtualItems.map((item) => item.width));\n    const totalHeight =\n      virtualItems[virtualItems.length - 1].y + virtualItems[virtualItems.length - 1].height;\n    return {\n      width: maxWidth,\n      height: totalHeight,\n    };\n  }\n\n  protected getScrollOffset(viewport: ViewportMetrics): number {\n    return viewport.scrollTop;\n  }\n\n  protected getClientSize(viewport: ViewportMetrics): number {\n    return viewport.clientHeight;\n  }\n\n  /** Vertical scroll: extent along scroll axis is height. */\n  protected getItemSizeAlongScrollAxis(item: VirtualItem): number {\n    return item.height;\n  }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { Size } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\n\nexport class HorizontalScrollStrategy extends BaseScrollStrategy {\n  constructor(config: ScrollStrategyConfig) {\n    super(config);\n  }\n\n  createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n    let xOffset = 0;\n    return pdfPageObject.map((pagesInSpread, index) => {\n      let pageX = 0;\n      const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n        const layout: PageLayout = {\n          pageNumber: page.index + 1,\n          pageIndex: page.index,\n          x: pageX,\n          y: 0,\n          width: page.size.width,\n          height: page.size.height,\n          rotatedWidth: page.rotatedSize.width,\n          rotatedHeight: page.rotatedSize.height,\n          elevated: false,\n        };\n        pageX += page.rotatedSize.width + this.pageGap;\n        return layout;\n      });\n      const width = pagesInSpread.reduce(\n        (sum, page, i) =>\n          sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n        0,\n      );\n      const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n      const item: VirtualItem = {\n        id: `item-${index}`,\n        x: xOffset,\n        y: 0,\n        offset: xOffset,\n        width,\n        height,\n        pageLayouts,\n        pageNumbers: pagesInSpread.map((p) => p.index + 1),\n        index,\n      };\n      xOffset += width + this.pageGap;\n      return item;\n    });\n  }\n\n  getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n    if (virtualItems.length === 0) return { width: 0, height: 0 };\n    const totalWidth =\n      virtualItems[virtualItems.length - 1].x + virtualItems[virtualItems.length - 1].width;\n    const maxHeight = Math.max(...virtualItems.map((item) => item.height));\n    return {\n      width: totalWidth,\n      height: maxHeight,\n    };\n  }\n\n  protected getScrollOffset(viewport: ViewportMetrics): number {\n    return viewport.scrollLeft;\n  }\n\n  protected getClientSize(viewport: ViewportMetrics): number {\n    return viewport.clientWidth;\n  }\n\n  /** Horizontal scroll: extent along scroll axis is width. */\n  protected getItemSizeAlongScrollAxis(item: VirtualItem): number {\n    return item.width;\n  }\n\n  /**\n   * No centering for horizontal layout. Items are laid out in a simple row;\n   * using total content width would produce incorrect offsets and shift pages.\n   */\n  /* eslint-disable no-unused-vars -- override intentionally ignores params */\n  protected getCenteringOffsetX(_item: VirtualItem, _totalContentSize: Size | undefined): number {\n    return 0;\n  }\n\n  /**\n   * Horizontal rows visually center shorter items within the tallest row height.\n   * Match that DOM layout so page-coordinate targeting lands on the rendered page.\n   */\n  protected getCenteringOffsetY(item: VirtualItem, totalContentSize: Size | undefined): number {\n    if (!totalContentSize || item.height >= totalContentSize.height) return 0;\n    return (totalContentSize.height - item.height) / 2;\n  }\n}\n","import { Action } from '@embedpdf/core';\nimport { ScrollDocumentState, ScrollStrategy } from './types';\n\n// Document lifecycle\nexport const INIT_SCROLL_STATE = 'INIT_SCROLL_STATE';\nexport const CLEANUP_SCROLL_STATE = 'CLEANUP_SCROLL_STATE';\nexport const UPDATE_DOCUMENT_SCROLL_STATE = 'UPDATE_DOCUMENT_SCROLL_STATE';\nexport const SET_SCROLL_STRATEGY = 'SET_SCROLL_STRATEGY';\n\nexport interface InitScrollStateAction extends Action {\n  type: typeof INIT_SCROLL_STATE;\n  payload: {\n    documentId: string;\n    state: ScrollDocumentState;\n  };\n}\n\nexport interface CleanupScrollStateAction extends Action {\n  type: typeof CLEANUP_SCROLL_STATE;\n  payload: string; // documentId\n}\n\nexport interface UpdateDocumentScrollStateAction extends Action {\n  type: typeof UPDATE_DOCUMENT_SCROLL_STATE;\n  payload: {\n    documentId: string;\n    state: Partial<ScrollDocumentState>;\n  };\n}\n\nexport interface SetScrollStrategyAction extends Action {\n  type: typeof SET_SCROLL_STRATEGY;\n  payload: {\n    documentId: string;\n    strategy: ScrollStrategy;\n  };\n}\n\nexport type ScrollAction =\n  | InitScrollStateAction\n  | CleanupScrollStateAction\n  | UpdateDocumentScrollStateAction\n  | SetScrollStrategyAction;\n\nexport function initScrollState(\n  documentId: string,\n  state: ScrollDocumentState,\n): InitScrollStateAction {\n  return { type: INIT_SCROLL_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupScrollState(documentId: string): CleanupScrollStateAction {\n  return { type: CLEANUP_SCROLL_STATE, payload: documentId };\n}\n\nexport function updateDocumentScrollState(\n  documentId: string,\n  state: Partial<ScrollDocumentState>,\n): UpdateDocumentScrollStateAction {\n  return { type: UPDATE_DOCUMENT_SCROLL_STATE, payload: { documentId, state } };\n}\n\nexport function setScrollStrategy(\n  documentId: string,\n  strategy: ScrollStrategy,\n): SetScrollStrategyAction {\n  return { type: SET_SCROLL_STRATEGY, payload: { documentId, strategy } };\n}\n","import { Reducer, CoreState } from '@embedpdf/core';\nimport { ScrollState, ScrollStrategy, ScrollPluginConfig, PageChangeState } from './types';\nimport {\n  ScrollAction,\n  INIT_SCROLL_STATE,\n  CLEANUP_SCROLL_STATE,\n  UPDATE_DOCUMENT_SCROLL_STATE,\n  SET_SCROLL_STRATEGY,\n} from './actions';\n\nexport const defaultPageChangeState: PageChangeState = {\n  isChanging: false,\n  targetPage: 1,\n  fromPage: 1,\n  startTime: 0,\n};\n\nexport const initialState: (coreState: CoreState, config: ScrollPluginConfig) => ScrollState = (\n  _coreState,\n  config,\n) => ({\n  defaultStrategy: config.defaultStrategy ?? ScrollStrategy.Vertical,\n  defaultPageGap: config.defaultPageGap ?? 10,\n  defaultBufferSize: config.defaultBufferSize ?? 2,\n  documents: {},\n});\n\nexport const scrollReducer: Reducer<ScrollState, ScrollAction> = (state, action) => {\n  switch (action.type) {\n    case INIT_SCROLL_STATE: {\n      const { documentId, state: docState } = action.payload;\n      return {\n        ...state,\n        documents: {\n          ...state.documents,\n          [documentId]: docState,\n        },\n      };\n    }\n\n    case CLEANUP_SCROLL_STATE: {\n      const { [action.payload]: removed, ...remaining } = state.documents;\n      return {\n        ...state,\n        documents: remaining,\n      };\n    }\n\n    case UPDATE_DOCUMENT_SCROLL_STATE: {\n      const { documentId, state: updates } = action.payload;\n      const docState = state.documents[documentId];\n      if (!docState) return state;\n\n      return {\n        ...state,\n        documents: {\n          ...state.documents,\n          [documentId]: {\n            ...docState,\n            ...updates,\n          },\n        },\n      };\n    }\n\n    case SET_SCROLL_STRATEGY: {\n      const { documentId, strategy } = action.payload;\n      const docState = state.documents[documentId];\n      if (!docState) return state;\n\n      return {\n        ...state,\n        documents: {\n          ...state.documents,\n          [documentId]: {\n            ...docState,\n            strategy,\n          },\n        },\n      };\n    }\n\n    default:\n      return state;\n  }\n};\n","import { ScrollerLayout, ScrollDocumentState } from './types';\n\nexport const getScrollerLayout = (\n  documentState: ScrollDocumentState,\n  scale: number,\n  elevatedPages?: Set<number>,\n): ScrollerLayout => {\n  return {\n    startSpacing: documentState.startSpacing,\n    endSpacing: documentState.endSpacing,\n    totalWidth: documentState.totalContentSize.width * scale,\n    totalHeight: documentState.totalContentSize.height * scale,\n    pageGap: documentState.pageGap * scale,\n    strategy: documentState.strategy,\n    items: documentState.renderedPageIndexes.map((idx) => {\n      return {\n        ...documentState.virtualItems[idx],\n        pageLayouts: documentState.virtualItems[idx].pageLayouts.map((layout) => {\n          return {\n            ...layout,\n            rotatedWidth: layout.rotatedWidth * scale,\n            rotatedHeight: layout.rotatedHeight * scale,\n            width: layout.width * scale,\n            height: layout.height * scale,\n            elevated: elevatedPages?.has(layout.pageIndex) ?? false,\n          };\n        }),\n      };\n    }),\n  };\n};\n","import {\n  BasePlugin,\n  PluginRegistry,\n  createBehaviorEmitter,\n  DocumentState,\n  Unsubscribe,\n  Listener,\n  SET_PAGES,\n} from '@embedpdf/core';\nimport { PdfPageObjectWithRotatedSize, Rect, Rotation, transformSize } from '@embedpdf/models';\nimport { ViewportCapability, ViewportMetrics, ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { SpreadCapability, SpreadPlugin } from '@embedpdf/plugin-spread';\nimport { InteractionManagerPlugin } from '@embedpdf/plugin-interaction-manager';\n\nimport {\n  ScrollCapability,\n  ScrollScope,\n  ScrollPluginConfig,\n  ScrollStrategy,\n  ScrollMetrics,\n  ScrollState,\n  ScrollDocumentState,\n  LayoutChangePayload,\n  ScrollerLayout,\n  ScrollToPageOptions,\n  PageChangeEvent,\n  ScrollEvent,\n  LayoutChangeEvent,\n  PageChangeStateEvent,\n  LayoutReadyEvent,\n  ScrollBehavior,\n  PageChangeState,\n} from './types';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './strategies/base-strategy';\nimport { VerticalScrollStrategy } from './strategies/vertical-strategy';\nimport { HorizontalScrollStrategy } from './strategies/horizontal-strategy';\nimport {\n  ScrollAction,\n  initScrollState,\n  cleanupScrollState,\n  updateDocumentScrollState,\n  setScrollStrategy,\n} from './actions';\nimport { VirtualItem } from './types/virtual-item';\nimport { defaultPageChangeState } from './reducer';\nimport { getScrollerLayout } from './selectors';\n\nexport class ScrollPlugin extends BasePlugin<\n  ScrollPluginConfig,\n  ScrollCapability,\n  ScrollState,\n  ScrollAction\n> {\n  static readonly id = 'scroll' as const;\n\n  private viewport: ViewportCapability;\n  private spread: SpreadCapability | null;\n\n  // Elevated pages per document (derived from InteractionManager page activity)\n  private elevatedPages = new Map<string, Set<number>>();\n\n  // Strategies per document\n  private strategies = new Map<string, BaseScrollStrategy>();\n\n  // Layout ready tracking per document\n  private layoutReady = new Set<string>();\n\n  // Tracks documents that have had their initial layout ready (cleared only on document close)\n  private initialLayoutFired = new Set<string>();\n\n  // Per-document scroller layout emitters (for real-time scroll updates)\n  private scrollerLayoutEmitters = new Map<\n    string,\n    ReturnType<typeof createBehaviorEmitter<ScrollerLayout>>\n  >();\n\n  // Event emitters (include documentId)\n  private readonly pageChange$ = createBehaviorEmitter<PageChangeEvent>();\n  private readonly scroll$ = createBehaviorEmitter<ScrollEvent>();\n  private readonly layoutChange$ = createBehaviorEmitter<LayoutChangeEvent>();\n  private readonly pageChangeState$ = createBehaviorEmitter<PageChangeStateEvent>();\n  private readonly layoutReady$ = createBehaviorEmitter<LayoutReadyEvent>();\n  private readonly state$ = createBehaviorEmitter<ScrollDocumentState>();\n\n  constructor(\n    public readonly id: string,\n    registry: PluginRegistry,\n    private config?: ScrollPluginConfig,\n  ) {\n    super(id, registry);\n\n    this.viewport = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n    this.spread = this.registry.getPlugin<SpreadPlugin>('spread')?.provides() ?? null;\n\n    // Subscribe to viewport scroll activity (per document)\n    this.viewport.onScrollActivity((event) => {\n      const docState = this.getDocumentState(event.documentId);\n      if (docState?.pageChangeState.isChanging && !event.activity.isSmoothScrolling) {\n        this.completePageChange(event.documentId);\n      }\n    });\n\n    this.spread?.onSpreadChange((event) => {\n      this.refreshDocumentLayout(event.documentId);\n    });\n\n    // Subscribe to page activity changes from the interaction manager (optional)\n    const im = this.registry.getPlugin<InteractionManagerPlugin>('interaction-manager')?.provides();\n    if (im) {\n      im.onPageActivityChange((event) => {\n        let pages = this.elevatedPages.get(event.documentId);\n        if (event.hasActivity) {\n          if (!pages) {\n            pages = new Set();\n            this.elevatedPages.set(event.documentId, pages);\n          }\n          pages.add(event.pageIndex);\n        } else {\n          pages?.delete(event.pageIndex);\n        }\n        this.pushScrollerLayout(event.documentId);\n      });\n    }\n\n    // Subscribe to viewport changes (per document) with throttling\n    this.viewport.onViewportChange((event) => {\n      const docState = this.getDocumentState(event.documentId);\n      if (!docState) return;\n\n      // Compute the metrics based on the incoming event\n      const computedMetrics = this.computeMetrics(event.documentId, event.metrics);\n\n      // THE GUARD: Only update the scrollOffset if the layout is already \"ready\".\n      if (this.layoutReady.has(event.documentId)) {\n        // Layout is ready, so this is a real scroll event from the user.\n        // Commit all metrics, including the new scrollOffset.\n        this.commitMetrics(event.documentId, computedMetrics);\n      } else {\n        // Layout is NOT ready. This is the initial, premature event.\n        // We must commit the other metrics (like visible pages for rendering)\n        // but EXCLUDE the incorrect scrollOffset to protect our persisted state.\n        this.commitMetrics(event.documentId, {\n          ...computedMetrics,\n          scrollOffset: docState.scrollOffset,\n        });\n      }\n    });\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Document Lifecycle Hooks (from BasePlugin)\n  // ─────────────────────────────────────────────────────────\n  protected override onDocumentLoadingStarted(documentId: string): void {\n    const coreDoc = this.getCoreDocument(documentId);\n    if (!coreDoc) return;\n    // Initialize scroll state for this document\n    const docState = this.createDocumentState(coreDoc);\n    this.dispatch(initScrollState(documentId, docState));\n\n    // Create strategy for this document\n    const strategy = this.createStrategy(docState.strategy);\n    this.strategies.set(documentId, strategy);\n\n    // Create scroller layout emitter for this document\n    this.scrollerLayoutEmitters.set(documentId, createBehaviorEmitter<ScrollerLayout>());\n  }\n\n  protected override onDocumentLoaded(documentId: string): void {\n    const coreDoc = this.getCoreDocument(documentId);\n    if (!coreDoc) return;\n\n    this.dispatch(\n      updateDocumentScrollState(documentId, { totalPages: coreDoc.document?.pageCount ?? 0 }),\n    );\n    // Initial layout computation\n    this.refreshDocumentLayout(documentId);\n\n    this.logger.debug(\n      'ScrollPlugin',\n      'DocumentOpened',\n      `Initialized scroll state for document: ${documentId}`,\n    );\n  }\n\n  protected override onDocumentClosed(documentId: string): void {\n    // Cleanup strategy\n    this.strategies.delete(documentId);\n\n    // Cleanup layout ready tracking\n    this.layoutReady.delete(documentId);\n    this.initialLayoutFired.delete(documentId);\n\n    // Cleanup elevated pages\n    this.elevatedPages.delete(documentId);\n\n    // Cleanup scroller layout emitter\n    const emitter = this.scrollerLayoutEmitters.get(documentId);\n    if (emitter) {\n      emitter.clear();\n      this.scrollerLayoutEmitters.delete(documentId);\n    }\n\n    // Cleanup state\n    this.dispatch(cleanupScrollState(documentId));\n\n    this.logger.debug(\n      'ScrollPlugin',\n      'DocumentClosed',\n      `Cleaned up scroll state for document: ${documentId}`,\n    );\n  }\n\n  protected override onScaleChanged(documentId: string): void {\n    const coreDoc = this.coreState.core.documents[documentId];\n    if (!coreDoc || coreDoc.status !== 'loaded') return;\n\n    const viewportScope = this.viewport.forDocument(documentId);\n    const metrics = this.computeMetrics(documentId, viewportScope.getMetrics());\n\n    // Use the canonical path so scroll/pageChange events and scroller layout\n    // updates all flow through the same place.\n    this.commitMetrics(documentId, metrics);\n  }\n\n  protected override onRotationChanged(documentId: string): void {\n    this.refreshDocumentLayout(documentId);\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Public API for Components (Scroller Layout)\n  // ─────────────────────────────────────────────────────────\n\n  /**\n   * Subscribe to scroller layout updates for a specific document\n   * This is the key method for the Scroller component to stay reactive\n   */\n  public onScrollerData(\n    documentId: string,\n    callback: (layout: ScrollerLayout) => void,\n  ): Unsubscribe {\n    const emitter = this.scrollerLayoutEmitters.get(documentId);\n    if (!emitter) {\n      throw new Error(`No scroller layout emitter found for document: ${documentId}`);\n    }\n    return emitter.on(callback);\n  }\n\n  /**\n   * Get current scroller layout for a document\n   */\n  public getScrollerLayout(documentId: string): ScrollerLayout {\n    const docState = this.getDocumentState(documentId);\n    const coreDoc = this.getCoreDocumentOrThrow(documentId);\n\n    if (!docState || !coreDoc) {\n      throw new Error(`Cannot get scroller layout for document: ${documentId}`);\n    }\n\n    return getScrollerLayout(docState, coreDoc.scale, this.elevatedPages.get(documentId));\n  }\n\n  public setLayoutReady(documentId: string): void {\n    // This guard logic is now reliable because the flag gets reset correctly.\n    if (this.layoutReady.has(documentId)) {\n      return;\n    }\n\n    const docState = this.getDocumentState(documentId);\n    if (!docState) return;\n\n    this.layoutReady.add(documentId);\n\n    // Determine if this is the initial layout for this document\n    const isInitial = !this.initialLayoutFired.has(documentId);\n    if (isInitial) {\n      this.initialLayoutFired.add(documentId);\n    }\n\n    // Restore the persisted scroll position\n    const viewport = this.viewport.forDocument(documentId);\n    viewport.scrollTo({ ...docState.scrollOffset, behavior: 'instant' });\n\n    this.layoutReady$.emit({\n      documentId,\n      isInitial,\n      pageNumber: docState.currentPage,\n      totalPages: docState.totalPages,\n    });\n  }\n\n  public clearLayoutReady(documentId: string): void {\n    this.layoutReady.delete(documentId);\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Capability\n  // ─────────────────────────────────────────────────────────\n\n  protected buildCapability(): ScrollCapability {\n    return {\n      // Active document operations\n      getCurrentPage: () => this.getCurrentPage(),\n      getTotalPages: () => this.getTotalPages(),\n      getPageChangeState: () => this.getPageChangeState(),\n      scrollToPage: (options) => this.scrollToPage(options),\n      scrollToNextPage: (behavior) => this.scrollToNextPage(behavior),\n      scrollToPreviousPage: (behavior) => this.scrollToPreviousPage(behavior),\n      getMetrics: (viewport) => this.getMetrics(viewport),\n      getLayout: () => this.getLayout(),\n      getRectPositionForPage: (page, rect, scale, rotation) =>\n        this.getRectPositionForPage(page, rect, scale, rotation),\n\n      // Document-scoped operations\n      forDocument: (documentId) => this.createScrollScope(documentId),\n\n      // Global settings\n      setScrollStrategy: (strategy, documentId) =>\n        this.setScrollStrategyForDocument(strategy, documentId),\n      getPageGap: () => this.state.defaultPageGap,\n\n      // Events\n      onPageChange: this.pageChange$.on,\n      onScroll: this.scroll$.on,\n      onLayoutChange: this.layoutChange$.on,\n      onLayoutReady: this.layoutReady$.on,\n      onPageChangeState: this.pageChangeState$.on,\n      onStateChange: this.state$.on,\n    };\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Document Scoping\n  // ─────────────────────────────────────────────────────────\n\n  private createScrollScope(documentId: string): ScrollScope {\n    return {\n      getCurrentPage: () => this.getCurrentPage(documentId),\n      getTotalPages: () => this.getTotalPages(documentId),\n      getPageChangeState: () => this.getPageChangeState(documentId),\n      scrollToPage: (options) => this.scrollToPage(options, documentId),\n      scrollToNextPage: (behavior) => this.scrollToNextPage(behavior, documentId),\n      scrollToPreviousPage: (behavior) => this.scrollToPreviousPage(behavior, documentId),\n      getSpreadPagesWithRotatedSize: () => this.getSpreadPagesWithRotatedSize(documentId),\n      getMetrics: (viewport) => this.getMetrics(viewport, documentId),\n      getLayout: () => this.getLayout(documentId),\n      getRectPositionForPage: (page, rect, scale, rotation) =>\n        this.getRectPositionForPage(page, rect, scale, rotation, documentId),\n      setScrollStrategy: (strategy) => this.setScrollStrategyForDocument(strategy, documentId),\n      onPageChange: (listener: Listener<PageChangeEvent>) =>\n        this.pageChange$.on((event) => {\n          if (event.documentId === documentId) listener(event);\n        }),\n      onScroll: (listener: Listener<ScrollMetrics>) =>\n        this.scroll$.on((event) => {\n          if (event.documentId === documentId) listener(event.metrics);\n        }),\n      onLayoutChange: (listener: Listener<LayoutChangePayload>) =>\n        this.layoutChange$.on((event) => {\n          if (event.documentId === documentId) listener(event.layout);\n        }),\n    };\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // State Helpers\n  // ─────────────────────────────────────────────────────────\n  private getDocumentState(documentId?: string): ScrollDocumentState | null {\n    const id = documentId ?? this.getActiveDocumentId();\n    return this.state.documents[id] ?? null;\n  }\n\n  private getDocumentStateOrThrow(documentId?: string): ScrollDocumentState {\n    const state = this.getDocumentState(documentId);\n    if (!state) {\n      throw new Error(`Scroll state not found for document: ${documentId ?? 'active'}`);\n    }\n    return state;\n  }\n\n  private getStrategy(documentId?: string): BaseScrollStrategy {\n    const id = documentId ?? this.getActiveDocumentId();\n    const strategy = this.strategies.get(id);\n    if (!strategy) {\n      throw new Error(`Strategy not found for document: ${id}`);\n    }\n    return strategy;\n  }\n\n  private createStrategy(strategyType: ScrollStrategy): BaseScrollStrategy {\n    const config: ScrollStrategyConfig = {\n      pageGap: this.state.defaultPageGap,\n      viewportGap: this.viewport.getViewportGap(),\n      bufferSize: this.state.defaultBufferSize,\n    };\n\n    return strategyType === ScrollStrategy.Horizontal\n      ? new HorizontalScrollStrategy(config)\n      : new VerticalScrollStrategy(config);\n  }\n\n  private createDocumentState(coreDoc: DocumentState): ScrollDocumentState {\n    return {\n      virtualItems: [],\n      totalPages: coreDoc.document?.pageCount ?? 0,\n      currentPage: 1,\n      totalContentSize: { width: 0, height: 0 },\n      strategy: this.state.defaultStrategy,\n      pageGap: this.state.defaultPageGap,\n      visiblePages: [],\n      pageVisibilityMetrics: [],\n      renderedPageIndexes: [],\n      scrollOffset: { x: 0, y: 0 },\n      startSpacing: 0,\n      endSpacing: 0,\n      pageChangeState: defaultPageChangeState,\n    };\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Page Change Management\n  // ─────────────────────────────────────────────────────────\n\n  private startPageChange(\n    documentId: string,\n    targetPage: number,\n    behavior: ScrollBehavior = 'smooth',\n  ): void {\n    const docState = this.getDocumentState(documentId);\n    if (!docState) return;\n\n    const pageChangeState: PageChangeState = {\n      isChanging: true,\n      targetPage,\n      fromPage: docState.currentPage,\n      startTime: Date.now(),\n    };\n\n    // Optimistic update: set currentPage immediately so UI reflects target during smooth scroll\n    this.dispatch(\n      updateDocumentScrollState(documentId, {\n        pageChangeState,\n        currentPage: targetPage,\n      }),\n    );\n    this.pageChange$.emit({\n      documentId,\n      pageNumber: targetPage,\n      totalPages: docState.totalPages,\n    });\n\n    if (behavior === 'instant') {\n      this.completePageChange(documentId);\n    }\n  }\n\n  private completePageChange(documentId: string): void {\n    const docState = this.getDocumentState(documentId);\n    if (!docState || !docState.pageChangeState.isChanging) return;\n\n    const pageChangeState: PageChangeState = {\n      isChanging: false,\n      targetPage: docState.pageChangeState.targetPage,\n      fromPage: docState.pageChangeState.fromPage,\n      startTime: docState.pageChangeState.startTime,\n    };\n\n    this.dispatch(updateDocumentScrollState(documentId, { pageChangeState }));\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Layout & Metrics Computation\n  // ─────────────────────────────────────────────────────────\n\n  private computeLayout(\n    documentId: string,\n    pages: PdfPageObjectWithRotatedSize[][],\n  ): {\n    virtualItems: VirtualItem[];\n    totalContentSize: { width: number; height: number };\n  } {\n    const strategy = this.getStrategy(documentId);\n    const virtualItems = strategy.createVirtualItems(pages);\n    const totalContentSize = strategy.getTotalContentSize(virtualItems);\n    return { virtualItems, totalContentSize };\n  }\n\n  private computeMetrics(\n    documentId: string,\n    vp: ViewportMetrics,\n    items?: VirtualItem[],\n  ): ScrollMetrics {\n    const coreDocState = this.getCoreDocumentOrThrow(documentId);\n    const docState = this.getDocumentState(documentId);\n    const strategy = this.getStrategy(documentId);\n    if (!docState) throw new Error(`Document state not found: ${documentId}`);\n\n    return strategy.handleScroll(vp, items ?? docState.virtualItems, coreDocState.scale);\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Commit (Single Source of Truth)\n  // ─────────────────────────────────────────────────────────\n\n  private commitMetrics(documentId: string, metrics: ScrollMetrics): void {\n    const docState = this.getDocumentState(documentId);\n    if (!docState) return;\n\n    // During smooth scroll (Next/Previous), viewport fires before scroll completes.\n    // Metrics would derive currentPage from old viewport position and revert the optimistic update.\n    const isProgrammaticScroll = docState.pageChangeState.isChanging;\n    // Preserve optimistic currentPage during programmatic scroll; use viewport-derived value otherwise\n    const metricsToCommit =\n      isProgrammaticScroll && metrics.currentPage !== docState.currentPage\n        ? { ...metrics, currentPage: docState.currentPage }\n        : metrics;\n\n    // Update state before emitting scroll event,\n    // so any scroll$ listener that reads state sees metricsToCommit; then notify\n    this.dispatch(updateDocumentScrollState(documentId, metricsToCommit));\n    this.scroll$.emit({ documentId, metrics: metricsToCommit });\n\n    // Only emit pageChange$ for user-driven scroll; programmatic scroll already emitted in startPageChange\n    if (!isProgrammaticScroll && metrics.currentPage !== docState.currentPage) {\n      this.pageChange$.emit({\n        documentId,\n        pageNumber: metrics.currentPage,\n        totalPages: docState.totalPages,\n      });\n    }\n\n    // CRITICAL: Push updated scroller layout (for spacing/visible items reactivity)\n    this.pushScrollerLayout(documentId);\n  }\n\n  private pushScrollerLayout(documentId: string): void {\n    const emitter = this.scrollerLayoutEmitters.get(documentId);\n    if (!emitter) return;\n\n    try {\n      const layout = this.getScrollerLayout(documentId);\n      emitter.emit(layout);\n    } catch (error) {\n      // Document might be closing, ignore\n    }\n  }\n\n  private refreshDocumentLayout(documentId: string): void {\n    const coreDoc = this.coreState.core.documents[documentId];\n    const docState = this.getDocumentState(documentId);\n\n    if (!coreDoc || !docState || coreDoc.status !== 'loaded') return;\n\n    const pages = this.getSpreadPagesWithRotatedSize(documentId);\n    const layout = this.computeLayout(documentId, pages);\n    // Get viewport metrics for this document\n    const viewport = this.viewport.forDocument(documentId);\n    const metrics = this.computeMetrics(documentId, viewport.getMetrics(), layout.virtualItems);\n\n    // Update state with layout + metrics\n    this.dispatch(\n      updateDocumentScrollState(documentId, {\n        ...layout,\n        ...metrics,\n      }),\n    );\n    // Emit layout change event\n    this.layoutChange$.emit({ documentId, layout });\n\n    // Push updated scroller layout\n    this.pushScrollerLayout(documentId);\n  }\n\n  private getSpreadPagesWithRotatedSize(documentId?: string): PdfPageObjectWithRotatedSize[][] {\n    const id = documentId ?? this.getActiveDocumentId();\n    const coreDoc = this.coreState.core.documents[id];\n    if (!coreDoc) throw new Error(`Document ${id} not loaded`);\n\n    const spreadPages =\n      this.spread?.forDocument(id).getSpreadPages() ||\n      coreDoc.document?.pages.map((page) => [page]) ||\n      [];\n\n    return spreadPages.map((spread) =>\n      spread.map((page) => {\n        // Combine page intrinsic rotation with document rotation\n        const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;\n        return {\n          ...page,\n          rotatedSize: transformSize(page.size, effectiveRotation, 1),\n        };\n      }),\n    );\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Core Operations\n  // ─────────────────────────────────────────────────────────\n\n  private getCurrentPage(documentId?: string): number {\n    return this.getDocumentStateOrThrow(documentId).currentPage;\n  }\n\n  private getTotalPages(documentId?: string): number {\n    return this.getDocumentStateOrThrow(documentId).totalPages;\n  }\n\n  private getPageChangeState(documentId?: string): PageChangeState {\n    return this.getDocumentStateOrThrow(documentId).pageChangeState;\n  }\n\n  private scrollToPage(options: ScrollToPageOptions, documentId?: string): void {\n    const id = documentId ?? this.getActiveDocumentId();\n    const docState = this.getDocumentStateOrThrow(id);\n    const strategy = this.getStrategy(id);\n    const coreDoc = this.getCoreDocumentOrThrow(id);\n\n    const { pageNumber, behavior = 'smooth', pageCoordinates, alignX, alignY } = options;\n\n    this.startPageChange(id, pageNumber, behavior);\n\n    // Calculate effective rotation for this page (page intrinsic + document rotation)\n    const pageObj = coreDoc.document?.pages[pageNumber - 1];\n    const effectiveRotation = ((pageObj?.rotation ?? 0) + coreDoc.rotation) % 4;\n\n    const position = strategy.getScrollPositionForPage(\n      pageNumber,\n      docState.virtualItems,\n      coreDoc.scale,\n      effectiveRotation as Rotation,\n      pageCoordinates,\n    );\n\n    if (position) {\n      const viewport = this.viewport.forDocument(id);\n      viewport.scrollTo({ ...position, behavior, alignX, alignY });\n    } else {\n      this.completePageChange(id);\n    }\n  }\n\n  private scrollToNextPage(behavior: ScrollBehavior = 'smooth', documentId?: string): void {\n    const id = documentId ?? this.getActiveDocumentId();\n    const docState = this.getDocumentStateOrThrow(id);\n    const strategy = this.getStrategy(id);\n    const coreDoc = this.getCoreDocumentOrThrow(id);\n\n    const currentItemIndex = docState.virtualItems.findIndex((item) =>\n      item.pageNumbers.includes(docState.currentPage),\n    );\n\n    if (currentItemIndex >= 0 && currentItemIndex < docState.virtualItems.length - 1) {\n      const nextItem = docState.virtualItems[currentItemIndex + 1];\n      const targetPage = nextItem.pageNumbers[0];\n\n      this.startPageChange(id, targetPage, behavior);\n\n      const position = strategy.getScrollPositionForPage(\n        targetPage,\n        docState.virtualItems,\n        coreDoc.scale,\n        coreDoc.rotation,\n      );\n\n      if (position) {\n        const viewport = this.viewport.forDocument(id);\n        viewport.scrollTo({ ...position, behavior });\n      } else {\n        this.completePageChange(id);\n      }\n    }\n  }\n\n  private scrollToPreviousPage(behavior: ScrollBehavior = 'smooth', documentId?: string): void {\n    const id = documentId ?? this.getActiveDocumentId();\n    const docState = this.getDocumentStateOrThrow(id);\n    const strategy = this.getStrategy(id);\n    const coreDoc = this.coreState.core.documents[id];\n\n    const currentItemIndex = docState.virtualItems.findIndex((item) =>\n      item.pageNumbers.includes(docState.currentPage),\n    );\n\n    if (currentItemIndex > 0) {\n      const prevItem = docState.virtualItems[currentItemIndex - 1];\n      const targetPage = prevItem.pageNumbers[0];\n\n      this.startPageChange(id, targetPage, behavior);\n\n      const position = strategy.getScrollPositionForPage(\n        targetPage,\n        docState.virtualItems,\n        coreDoc.scale,\n        coreDoc.rotation,\n      );\n\n      if (position) {\n        const viewport = this.viewport.forDocument(id);\n        viewport.scrollTo({ ...position, behavior });\n      } else {\n        this.completePageChange(id);\n      }\n    }\n  }\n\n  private getMetrics(viewport?: ViewportMetrics, documentId?: string): ScrollMetrics {\n    const id = documentId ?? this.getActiveDocumentId();\n\n    if (viewport) {\n      return this.computeMetrics(id, viewport);\n    }\n\n    const viewportScope = this.viewport.forDocument(id);\n    return this.computeMetrics(id, viewportScope.getMetrics());\n  }\n\n  private getLayout(documentId?: string): LayoutChangePayload {\n    const docState = this.getDocumentStateOrThrow(documentId);\n    return {\n      virtualItems: docState.virtualItems,\n      totalContentSize: docState.totalContentSize,\n    };\n  }\n\n  private getRectPositionForPage(\n    pageIndex: number,\n    rect: Rect,\n    scale?: number,\n    rotation?: Rotation,\n    documentId?: string,\n  ): Rect | null {\n    const id = documentId ?? this.getActiveDocumentId();\n    const docState = this.getDocumentStateOrThrow(id);\n    const strategy = this.getStrategy(id);\n    const coreDoc = this.getCoreDocumentOrThrow(id);\n\n    // Calculate effective rotation if not provided (page intrinsic + document rotation)\n    let effectiveRotation = rotation;\n    if (effectiveRotation === undefined) {\n      const pageObj = coreDoc.document?.pages[pageIndex];\n      effectiveRotation = (((pageObj?.rotation ?? 0) + coreDoc.rotation) % 4) as Rotation;\n    }\n\n    return strategy.getRectPositionForPage(\n      pageIndex + 1,\n      docState.virtualItems,\n      scale ?? coreDoc.scale,\n      effectiveRotation,\n      rect,\n    );\n  }\n\n  private setScrollStrategyForDocument(newStrategy: ScrollStrategy, documentId?: string): void {\n    const id = documentId ?? this.getActiveDocumentId();\n    const docState = this.getDocumentState(id);\n\n    if (!docState || docState.strategy === newStrategy) return;\n\n    // Create new strategy\n    const strategy = this.createStrategy(newStrategy);\n    this.strategies.set(id, strategy);\n\n    // Update state\n    this.dispatch(setScrollStrategy(id, newStrategy));\n\n    // Recalculate layout\n    this.refreshDocumentLayout(id);\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Store Update Handlers\n  // ─────────────────────────────────────────────────────────\n\n  override onStoreUpdated(prevState: ScrollState, newState: ScrollState): void {\n    // Emit state changes and push scroller layout for each changed document\n    for (const documentId in newState.documents) {\n      const prevDoc = prevState.documents[documentId];\n      const newDoc = newState.documents[documentId];\n\n      if (prevDoc !== newDoc) {\n        this.state$.emit(newDoc);\n\n        if (prevDoc?.pageChangeState !== newDoc.pageChangeState) {\n          this.pageChangeState$.emit({\n            documentId,\n            state: newDoc.pageChangeState,\n          });\n        }\n\n        // Push scroller layout on any state change\n        this.pushScrollerLayout(documentId);\n      }\n    }\n  }\n\n  // ─────────────────────────────────────────────────────────\n  // Lifecycle\n  // ─────────────────────────────────────────────────────────\n\n  async initialize(): Promise<void> {\n    this.logger.info('ScrollPlugin', 'Initialize', 'Scroll plugin initialized');\n  }\n\n  async destroy(): Promise<void> {\n    this.strategies.clear();\n    this.layoutReady.clear();\n    this.initialLayoutFired.clear();\n    this.elevatedPages.clear();\n\n    // Clear all scroller layout emitters\n    for (const emitter of this.scrollerLayoutEmitters.values()) {\n      emitter.clear();\n    }\n    this.scrollerLayoutEmitters.clear();\n\n    this.pageChange$.clear();\n    this.scroll$.clear();\n    this.layoutChange$.clear();\n    this.pageChangeState$.clear();\n    this.layoutReady$.clear();\n    this.state$.clear();\n\n    super.destroy();\n  }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { ScrollPluginConfig, ScrollStrategy } from './types';\n\nexport const SCROLL_PLUGIN_ID = 'scroll';\n\nexport const manifest: PluginManifest<ScrollPluginConfig> = {\n  id: SCROLL_PLUGIN_ID,\n  name: 'Scroll Plugin',\n  version: '1.0.0',\n  provides: ['scroll'],\n  requires: ['viewport'],\n  optional: ['spread', 'interaction-manager'],\n  defaultConfig: {\n    defaultPageGap: 10,\n    defaultBufferSize: 4,\n    defaultStrategy: ScrollStrategy.Vertical,\n  },\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { ScrollPlugin } from './scroll-plugin';\nimport { manifest, SCROLL_PLUGIN_ID } from './manifest';\nimport { ScrollPluginConfig, ScrollState } from './types';\nimport { scrollReducer, initialState } from './reducer';\nimport { ScrollAction } from './actions';\n\nexport const ScrollPluginPackage: PluginPackage<\n  ScrollPlugin,\n  ScrollPluginConfig,\n  ScrollState,\n  ScrollAction\n> = {\n  manifest,\n  create: (registry, config) => new ScrollPlugin(SCROLL_PLUGIN_ID, registry, config),\n  reducer: scrollReducer,\n  initialState: (coreState, config) => initialState(coreState, config),\n};\n\nexport * from './scroll-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './types/virtual-item';\nexport * from './selectors';\n"],"names":["ScrollStrategy","BaseScrollStrategy","constructor","config","this","pageGap","viewportGap","bufferSize","getCenteringOffsetX","_item","totalContentSize","width","getCenteringOffsetY","_totalContentSize","getVisibleRange","viewport","virtualItems","scale","scrollOffset","getScrollOffset","viewportStart","viewportEnd","getClientSize","startIndex","length","offset","getItemSizeAlongScrollAxis","endIndex","start","Math","max","end","min","handleScroll","range","visibleItems","slice","getTotalContentSize","pageVisibilityMetrics","calculatePageVisibility","visiblePages","map","m","pageNumber","renderedPageIndexes","flatMap","item","index","currentPage","determineCurrentPage","first","last","startSpacing","lastItem","endSpacing","x","scrollLeft","y","scrollTop","visibilityMetrics","forEach","centeringOffsetX","centeringOffsetY","pageLayouts","page","itemX","itemY","pageX","pageY","pageWidth","rotatedWidth","pageHeight","rotatedHeight","viewportLeft","viewportTop","viewportRight","clientWidth","viewportBottom","clientHeight","intersectionLeft","intersectionTop","intersectionRight","intersectionBottom","visibleWidth","visibleHeight","totalArea","visibleArea","push","viewportX","viewportY","visiblePercentage","original","scaled","maxVisibility","mostVisiblePages","filter","sort","a","b","getRectLocationForPage","find","pageNumbers","includes","pageLayout","layout","origin","size","height","getScrollPositionForPage","rotation","pageCoordinates","pageRect","scaledBasePosition","scalePosition","rotatedSize","transformPosition","getRectPositionForPage","rect","transformRect","VerticalScrollStrategy","super","createVirtualItems","pdfPageObject","yOffset","pagesInSpread","pageIndex","elevated","reduce","sum","i","p","id","HorizontalScrollStrategy","xOffset","INIT_SCROLL_STATE","CLEANUP_SCROLL_STATE","UPDATE_DOCUMENT_SCROLL_STATE","SET_SCROLL_STRATEGY","updateDocumentScrollState","documentId","state","type","payload","defaultPageChangeState","isChanging","targetPage","fromPage","startTime","getScrollerLayout","documentState","elevatedPages","totalWidth","totalHeight","strategy","items","idx","has","_ScrollPlugin","BasePlugin","registry","Map","strategies","layoutReady","Set","initialLayoutFired","scrollerLayoutEmitters","pageChange$","createBehaviorEmitter","scroll$","layoutChange$","pageChangeState$","layoutReady$","state$","getPlugin","provides","spread","_a","onScrollActivity","event","docState","getDocumentState","pageChangeState","activity","isSmoothScrolling","completePageChange","_b","onSpreadChange","refreshDocumentLayout","im","_c","onPageActivityChange","pages","get","hasActivity","set","add","delete","pushScrollerLayout","onViewportChange","computedMetrics","computeMetrics","metrics","commitMetrics","onDocumentLoadingStarted","coreDoc","getCoreDocument","createDocumentState","dispatch","initScrollState","createStrategy","onDocumentLoaded","totalPages","document","pageCount","logger","debug","onDocumentClosed","emitter","clear","cleanupScrollState","onScaleChanged","coreState","core","documents","status","viewportScope","forDocument","getMetrics","onRotationChanged","onScrollerData","callback","Error","on","getCoreDocumentOrThrow","setLayoutReady","isInitial","scrollTo","behavior","emit","clearLayoutReady","buildCapability","getCurrentPage","getTotalPages","getPageChangeState","scrollToPage","options","scrollToNextPage","scrollToPreviousPage","getLayout","createScrollScope","setScrollStrategy","setScrollStrategyForDocument","getPageGap","defaultPageGap","onPageChange","onScroll","onLayoutChange","onLayoutReady","onPageChangeState","onStateChange","getSpreadPagesWithRotatedSize","listener","getActiveDocumentId","getDocumentStateOrThrow","getStrategy","strategyType","getViewportGap","defaultBufferSize","Horizontal","defaultStrategy","startPageChange","Date","now","computeLayout","vp","coreDocState","isProgrammaticScroll","metricsToCommit","error","getSpreadPages","effectiveRotation","transformSize","alignX","alignY","pageObj","position","currentItemIndex","findIndex","newStrategy","onStoreUpdated","prevState","newState","prevDoc","newDoc","initialize","info","destroy","values","ScrollPlugin","SCROLL_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","Vertical","ScrollPluginPackage","create","reducer","action","removed","remaining","updates","initialState","_coreState"],"mappings":"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"}