UNPKG

@letter-ai/lector

Version:
3,913 lines 122 kB
'use client';

import { AnnotationLayer, TextLayer, getDocument } from 'pdfjs-dist';
import React, { createContext, forwardRef, useContext, useCallback, cloneElement, useState, useRef, useEffect, createRef, useLayoutEffect } from 'react';
import { useVirtualizer, elementScroll, debounce } from '@tanstack/react-virtual';
import { useStore, createStore } from 'zustand';
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
import { useDebounce } from 'use-debounce';
import { Slot } from '@radix-ui/react-slot';
import { useFloating, autoUpdate, offset, shift, useDismiss, useInteractions } from '@floating-ui/react';

// ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
function r(e) {
  var t, f, n = "";
  if ("string" == typeof e || "number" == typeof e) n += e;
  else if ("object" == typeof e) if (Array.isArray(e)) {
    var o = e.length;
    for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
  } else for (f in e) e[f] && (n && (n += " "), n += f);
  return n;
}
function clsx() {
  for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
  return n;
}
var clsx_default = clsx;

// src/lib/clamp.ts
var clamp = (value, min, max) => {
  return Math.min(Math.max(value, min), max);
};

// src/lib/zoom.ts
var getFitWidthZoom = (containerWidth, viewports, zoomOptions) => {
  const { minZoom, maxZoom } = zoomOptions;
  const maxPageWidth = Math.max(...viewports.map((viewport) => viewport.width));
  const targetZoom = containerWidth / maxPageWidth;
  const clampedZoom = Math.min(Math.max(targetZoom, minZoom), maxZoom);
  return clampedZoom;
};
var createZustandContext = (getStore) => {
  const Context = React.createContext(null);
  const Provider = (props) => {
    const [store] = React.useState(() => getStore(props.initialValue));
    return /* @__PURE__ */ jsx(Context.Provider, { value: store, children: props.children });
  };
  return {
    useContext: () => React.useContext(Context),
    Context,
    Provider
  };
};

// src/internal.ts
var PDFStore = createZustandContext(
  (initialState) => {
    return createStore((set, get) => ({
      pdfDocumentProxy: initialState.pdfDocumentProxy,
      zoom: initialState.zoom,
      isZoomFitWidth: initialState.isZoomFitWidth ?? false,
      zoomOptions: {
        minZoom: initialState.zoomOptions?.minZoom ?? 0.5,
        maxZoom: initialState.zoomOptions?.maxZoom ?? 10
      },
      viewportRef: createRef(),
      viewports: initialState.viewports,
      updateZoom: (zoom, isZoomFitWidth = false) => {
        const { minZoom, maxZoom } = get().zoomOptions;
        set((state) => {
          if (typeof zoom === "function") {
            const newZoom2 = clamp(zoom(state.zoom), minZoom, maxZoom);
            return { zoom: newZoom2, isZoomFitWidth };
          }
          const newZoom = clamp(zoom, minZoom, maxZoom);
          return { zoom: newZoom, isZoomFitWidth };
        });
      },
      zoomFitWidth: () => {
        const { viewportRef, zoomOptions, viewports } = get();
        if (!viewportRef.current) return;
        const clampedZoom = getFitWidthZoom(
          viewportRef.current.clientWidth,
          viewports,
          zoomOptions
        );
        set({
          zoom: clampedZoom,
          isZoomFitWidth: true
        });
        return clampedZoom;
      },
      currentPage: 1,
      setCurrentPage: (val) => {
        set({
          currentPage: val
        });
      },
      isPinching: false,
      setIsPinching: (val) => {
        set({
          isPinching: val
        });
      },
      virtualizer: null,
      setVirtualizer: (val) => {
        set({
          virtualizer: val
        });
      },
      pageProxies: initialState.pageProxies,
      getPdfPageProxy: (pageNumber) => {
        const proxy = get().pageProxies[pageNumber - 1];
        if (!proxy) throw new Error(`Page ${pageNumber} does not exist`);
        return proxy;
      },
      textContent: [],
      setTextContent: (val) => {
        set({
          textContent: val
        });
      },
      highlights: [],
      setHighlight: (val) => {
        set({
          highlights: val
        });
      },
      customSelectionRects: [],
      setCustomSelectionRects: (val) => {
        set({
          customSelectionRects: val
        });
      }
    }));
  }
);
var usePdf = (selector) => useStore(PDFStore.useContext(), selector);

// src/lib/cancellable.ts
var cancellable = (promise) => {
  let isCancelled = false;
  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then(
      (value) => {
        if (!isCancelled) {
          resolve(value);
        }
      },
      (error) => {
        if (!isCancelled) {
          reject(error);
        }
      }
    );
  });
  return {
    promise: wrappedPromise,
    cancel() {
      isCancelled = true;
    }
  };
};
var LinkService = class {
  _pdfDocumentProxy;
  externalLinkEnabled = true;
  isInPresentationMode = false;
  _currentPageNumber = 0;
  _pageNavigationCallback;
  get pdfDocumentProxy() {
    if (!this._pdfDocumentProxy) {
      throw new Error("pdfDocumentProxy is not set");
    }
    return this._pdfDocumentProxy;
  }
  constructor() {
  }
  get pagesCount() {
    return this._pdfDocumentProxy?.numPages || 0;
  }
  get page() {
    return this._currentPageNumber;
  }
  set page(value) {
    this._currentPageNumber = value;
    if (this._pageNavigationCallback) {
      this._pageNavigationCallback(value);
    }
  }
  // Required for link annotations to work
  setDocument(pdfDocument) {
    this._pdfDocumentProxy = pdfDocument;
  }
  setViewer() {
  }
  getDestinationHash(dest) {
    if (!dest) return "";
    const destRef = dest[0];
    if (dest.length > 1 && typeof dest[1] === "object" && dest[1] !== null && "url" in dest[1]) {
      const urlDest = dest[1];
      return urlDest.url;
    }
    if (destRef && typeof destRef === "object") {
      if ("num" in destRef) {
        const numRef = destRef;
        return `#page=${numRef.num + 1}`;
      }
      if ("gen" in destRef) {
        const genRef = destRef;
        const refNum = genRef.num ?? 0;
        return `#page=${refNum + 1}`;
      }
    }
    if (typeof destRef === "number") {
      return `#page=${destRef + 1}`;
    }
    return `#dest-${String(dest)}`;
  }
  getAnchorUrl(hash) {
    if (hash.startsWith("http://") || hash.startsWith("https://")) {
      return hash;
    }
    return `#${hash}`;
  }
  addLinkAttributes(link, url, newWindow) {
    if (!link) return;
    const isExternalLink = url.startsWith("http://") || url.startsWith("https://");
    if (isExternalLink && this.externalLinkEnabled) {
      link.href = url;
      link.target = newWindow === false ? "" : "_blank";
      link.rel = "noopener noreferrer";
    } else if (!isExternalLink) {
      link.href = url;
      link.target = "";
    } else {
      link.href = "#";
      link.target = "";
    }
  }
  async goToDestination(dest) {
    let explicitDest;
    if (typeof dest === "string") {
      explicitDest = await this.pdfDocumentProxy.getDestination(dest);
    } else if (Array.isArray(dest)) {
      explicitDest = dest;
    } else {
      explicitDest = await dest;
    }
    if (!explicitDest) {
      return;
    }
    if (explicitDest.length > 1 && typeof explicitDest[1] === "object" && explicitDest[1] !== null && "url" in explicitDest[1]) {
      return;
    }
    const destRef = explicitDest[0];
    let pageIndex;
    if (destRef && typeof destRef === "object") {
      if ("num" in destRef) {
        try {
          const refProxy = destRef;
          pageIndex = await this.pdfDocumentProxy.getPageIndex(refProxy);
        } catch (error) {
          return;
        }
      } else {
        return;
      }
    } else if (typeof destRef === "number") {
      pageIndex = destRef;
    } else {
      return;
    }
    const pageNumber = pageIndex + 1;
    if (this._pageNavigationCallback) {
      this._pageNavigationCallback(pageNumber);
    }
  }
  executeNamedAction() {
  }
  navigateTo(dest) {
    this.goToDestination(dest);
  }
  get rotation() {
    return 0;
  }
  set rotation(value) {
  }
  goToPage(pageNumber) {
    if (pageNumber >= 1 && pageNumber <= this.pagesCount) {
      if (this._pageNavigationCallback) {
        this._pageNavigationCallback(pageNumber);
      }
    }
  }
  setHash(hash) {
    if (hash.startsWith("#page=")) {
      const pageNumber = parseInt(hash.substring(6), 10);
      if (!isNaN(pageNumber)) {
        this.goToPage(pageNumber);
      }
    }
  }
  executeSetOCGState() {
  }
  // Method to register navigation callback
  registerPageNavigationCallback(callback) {
    this._pageNavigationCallback = callback;
  }
  // Method to unregister navigation callback
  unregisterPageNavigationCallback() {
    this._pageNavigationCallback = void 0;
  }
};
var defaultLinkService = new LinkService();
var PDFLinkServiceContext = createContext(defaultLinkService);
var usePDFLinkService = () => {
  return useContext(PDFLinkServiceContext);
};
var PDFPageNumberContext = createContext(0);
var usePDFPageNumber = () => {
  return useContext(PDFPageNumberContext);
};
var useVisibility = ({
  elementRef
}) => {
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    if (!elementRef.current) {
      return;
    }
    const observer = new IntersectionObserver(([entry]) => {
      setVisible(entry?.isIntersecting ?? false);
    });
    observer.observe(elementRef.current);
    return () => {
      observer.disconnect();
    };
  }, [elementRef]);
  return { visible };
};

// src/hooks/pages/usePdfJump.tsx
var usePdfJump = () => {
  const virtualizer = usePdf((state) => state.virtualizer);
  const setHighlight = usePdf((state) => state.setHighlight);
  const jumpToPage = (pageIndex, options) => {
    if (!virtualizer) return;
    const defaultOptions = {
      align: "start",
      behavior: "smooth"
    };
    const finalOptions = { ...defaultOptions, ...options };
    virtualizer.scrollToIndex(pageIndex - 1, finalOptions);
  };
  const jumpToOffset = (offset2) => {
    if (!virtualizer) return;
    virtualizer.scrollToOffset(offset2, {
      align: "start",
      behavior: "smooth"
    });
  };
  const jumpToHighlightRects = (rects, type, align = "start", additionalOffset = 0) => {
    if (!virtualizer) return;
    setHighlight(rects);
    const firstPage = Math.min(...rects.map((rect) => rect.pageNumber));
    const pageOffset = virtualizer.getOffsetForIndex(firstPage - 1, "start");
    if (pageOffset === null) return;
    const targetRect = rects.find((rect) => rect.pageNumber === firstPage);
    if (!targetRect) return;
    const isNumber = pageOffset?.[0] != null;
    if (!isNumber) return;
    const pageStart = pageOffset[0] ?? 0;
    let rectTop;
    let rectHeight;
    if (type === "percent") {
      const estimatePageHeight = virtualizer.options.estimateSize(
        firstPage - 1
      );
      rectTop = targetRect.top / 100 * estimatePageHeight;
      rectHeight = targetRect.height / 100 * estimatePageHeight;
    } else {
      rectTop = targetRect.top;
      rectHeight = targetRect.height;
    }
    let scrollOffset;
    if (align === "center") {
      const viewportHeight = virtualizer.scrollElement?.clientHeight || 0;
      const rectCenter = pageStart + rectTop + rectHeight / 2;
      scrollOffset = rectCenter - viewportHeight / 2;
    } else {
      scrollOffset = pageStart + rectTop;
    }
    scrollOffset += additionalOffset;
    const adjustedOffset = Math.max(0, scrollOffset);
    virtualizer.scrollToOffset(adjustedOffset, {
      align: "start",
      // Always use start when we've calculated our own centering
      behavior: "smooth"
    });
  };
  return { jumpToPage, jumpToOffset, jumpToHighlightRects };
};

// src/hooks/layers/useAnnotationLayer.tsx
var defaultAnnotationLayerParams = {
  renderForms: true,
  externalLinksEnabled: true,
  jumpOptions: { behavior: "smooth", align: "start" }
};
var useAnnotationLayer = (params) => {
  const mergedParams = { ...defaultAnnotationLayerParams, ...params };
  const annotationLayerRef = useRef(null);
  const annotationLayerObjectRef = useRef(null);
  const linkService = usePDFLinkService();
  const { visible } = useVisibility({
    elementRef: annotationLayerRef
  });
  const pageNumber = usePDFPageNumber();
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
  const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
  useEffect(() => {
    linkService.externalLinkEnabled = mergedParams.externalLinksEnabled;
  }, [linkService, mergedParams.externalLinksEnabled]);
  const { jumpToPage } = usePdfJump();
  useEffect(() => {
    if (!jumpToPage) return;
    const handlePageNavigation = (pageNumber2) => {
      jumpToPage(pageNumber2, mergedParams.jumpOptions);
    };
    linkService.registerPageNavigationCallback(handlePageNavigation);
    return () => {
      linkService.unregisterPageNavigationCallback();
    };
  }, [jumpToPage, linkService, mergedParams.jumpOptions]);
  useEffect(() => {
    const style = document.createElement("style");
    style.textContent = `
      .annotationLayer {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        overflow: hidden;
        opacity: 1;
        z-index: 3;
      }
      
      .annotationLayer section {
        position: absolute;
      }
      
      .annotationLayer .linkAnnotation > a,
      .annotationLayer .buttonWidgetAnnotation.pushButton > a {
        position: absolute;
        font-size: 1em;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat;
        cursor: pointer;
      }
      
      .annotationLayer .linkAnnotation > a:hover,
      .annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
        opacity: 0.2;
        background: rgba(255, 255, 0, 1);
        box-shadow: 0 2px 10px rgba(255, 255, 0, 1);
      }
    `;
    document.head.appendChild(style);
    return () => {
      document.head.removeChild(style);
    };
  }, []);
  useEffect(() => {
    if (!annotationLayerRef.current) return;
    const element = annotationLayerRef.current;
    const handleLinkClick = (e) => {
      if (!e.target || !(e.target instanceof HTMLAnchorElement)) return;
      const target = e.target;
      const href = target.getAttribute("href") || "";
      if (href.startsWith("#page=")) {
        e.preventDefault();
        const pageNumber2 = parseInt(href.substring(6), 10);
        if (!isNaN(pageNumber2)) {
          linkService.goToPage(pageNumber2);
        }
      }
    };
    element.addEventListener("click", handleLinkClick);
    return () => {
      element.removeEventListener("click", handleLinkClick);
    };
  }, [linkService]);
  useEffect(() => {
    if (!annotationLayerRef.current) {
      return;
    }
    if (visible) {
      annotationLayerRef.current.style.contentVisibility = "visible";
    } else {
      annotationLayerRef.current.style.contentVisibility = "hidden";
    }
  }, [visible]);
  useEffect(() => {
    if (!annotationLayerRef.current || !pdfPageProxy || !pdfDocumentProxy) {
      return;
    }
    if (linkService._pdfDocumentProxy !== pdfDocumentProxy) {
      linkService.setDocument(pdfDocumentProxy);
    }
    annotationLayerRef.current.innerHTML = "";
    annotationLayerRef.current.className = "annotationLayer";
    const viewport = pdfPageProxy.getViewport({ scale: 1 });
    const annotationLayerConfig = {
      div: annotationLayerRef.current,
      viewport,
      page: pdfPageProxy,
      linkService,
      accessibilityManager: void 0,
      annotationCanvasMap: void 0,
      annotationEditorUIManager: void 0,
      structTreeLayer: void 0
    };
    const annotationLayer = new AnnotationLayer(annotationLayerConfig);
    annotationLayerObjectRef.current = annotationLayer;
    const { cancel } = cancellable(
      (async () => {
        try {
          const annotations = await pdfPageProxy.getAnnotations();
          await annotationLayer.render({
            ...annotationLayerConfig,
            ...mergedParams,
            annotations,
            linkService
          });
        } catch (error) {
        }
      })()
    );
    return () => {
      cancel();
    };
  }, [pdfPageProxy, pdfDocumentProxy, mergedParams, linkService]);
  return {
    annotationLayerRef
  };
};
var AnnotationLayer2 = ({
  renderForms = true,
  externalLinksEnabled = true,
  jumpOptions = { behavior: "smooth", align: "start" },
  className,
  style,
  ...props
}) => {
  const { annotationLayerRef } = useAnnotationLayer({
    renderForms,
    externalLinksEnabled,
    jumpOptions
  });
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: clsx_default("annotationLayer", className),
      style: {
        ...style,
        position: "absolute",
        top: 0,
        left: 0
      },
      ...props,
      ref: annotationLayerRef
    }
  );
};
var useDpr = () => {
  const [dpr, setDPR] = useState(
    !window ? 1 : Math.min(window.devicePixelRatio, 2)
  );
  useEffect(() => {
    if (!window) {
      return;
    }
    const handleDPRChange = () => {
      setDPR(window.devicePixelRatio);
    };
    const windowMatch = window.matchMedia(
      `screen and (min-resolution: ${dpr}dppx)`
    );
    windowMatch.addEventListener("change", handleDPRChange);
    return () => {
      windowMatch.removeEventListener("change", handleDPRChange);
    };
  }, []);
  return dpr;
};

// src/hooks/layers/useCanvasLayer.tsx
var useCanvasLayer = () => {
  const canvasRef = useRef(null);
  const pageNumber = usePDFPageNumber();
  const dpr = useDpr();
  const bouncyZoom = usePdf((state) => state.zoom);
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
  const [zoom] = useDebounce(bouncyZoom, 100);
  useLayoutEffect(() => {
    if (!canvasRef.current) {
      return;
    }
    const viewport = pdfPageProxy.getViewport({ scale: 1 });
    const canvas = canvasRef.current;
    const scale = dpr * zoom;
    canvas.height = viewport.height * scale;
    canvas.width = viewport.width * scale;
    canvas.style.height = `${viewport.height}px`;
    canvas.style.width = `${viewport.width}px`;
    const canvasContext = canvas.getContext("2d");
    canvasContext.scale(scale, scale);
    const renderingTask = pdfPageProxy.render({
      canvasContext,
      viewport
    });
    renderingTask.promise.catch((error) => {
      if (error.name === "RenderingCancelledException") {
        return;
      }
      throw error;
    });
    return () => {
      void renderingTask.cancel();
    };
  }, [pdfPageProxy, dpr, zoom]);
  return {
    canvasRef
  };
};
var CanvasLayer = ({
  style,
  ...props
}) => {
  const { canvasRef } = useCanvasLayer();
  return /* @__PURE__ */ jsx(
    "canvas",
    {
      style: {
        ...style,
        position: "absolute",
        top: 0,
        left: 0,
        width: "100%",
        height: "100%"
      },
      ...props,
      ref: canvasRef
    }
  );
};

// src/components/layers/custom-layer.tsx
var CustomLayer = ({
  children
}) => {
  const pageNumber = usePDFPageNumber();
  return children(pageNumber);
};
var convertToPercentString = (rect) => {
  return {
    top: `${rect.top}%`,
    left: `${rect.left}%`,
    height: `${rect.height}%`,
    width: `${rect.width}%`
  };
};
var HighlightLayer = forwardRef(({ asChild, className, style, ...props }, ref) => {
  const pageNumber = usePDFPageNumber();
  const highlights = usePdf((state) => state.highlights);
  const Comp = asChild ? Slot : "div";
  const rects = highlights.filter((area) => area.pageNumber === pageNumber);
  if (!rects?.length) return null;
  return /* @__PURE__ */ jsx(Fragment, { children: rects.map((rect, index) => {
    const { pageNumber: pageNumber2, type, ...coordinates } = rect;
    let dimensions = coordinates;
    if (type === "percent") {
      dimensions = convertToPercentString(rect);
    }
    return /* @__PURE__ */ jsx(
      Comp,
      {
        ref,
        className,
        style: {
          position: "absolute",
          ...dimensions,
          pointerEvents: "none",
          zIndex: 30,
          ...style
        },
        ...props,
        children: props.children
      },
      `highlight-${pageNumber2}-${index}`
    );
  }) });
});
HighlightLayer.displayName = "HighlightLayer";
var useTextLayer = () => {
  const textContainerRef = useRef(null);
  const pageNumber = usePDFPageNumber();
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
  useEffect(() => {
    if (!textContainerRef.current) {
      return;
    }
    const textLayer = new TextLayer({
      textContentSource: pdfPageProxy.streamTextContent(),
      container: textContainerRef.current,
      viewport: pdfPageProxy.getViewport({ scale: 1 })
    });
    void textLayer.render();
    return () => {
      textLayer.cancel();
    };
  }, [pdfPageProxy]);
  return {
    textContainerRef,
    pageNumber: pdfPageProxy.pageNumber
  };
};
var TextLayer2 = ({
  className,
  style,
  ...props
}) => {
  const { textContainerRef, pageNumber } = useTextLayer();
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: clsx_default("textLayer", className),
      style: {
        ...style,
        position: "absolute",
        top: 0,
        left: 0
      },
      ...props,
      ...{
        ["data-page-number"]: pageNumber
      },
      ref: textContainerRef
    }
  );
};
var usePDFOutline = () => {
  const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
  const [outline, setOutline] = useState();
  useEffect(() => {
    const { promise: outline2, cancel } = cancellable(
      pdfDocumentProxy.getOutline()
    );
    outline2.then(
      (result) => {
        setOutline(result);
      },
      () => {
      }
    );
    return () => {
      cancel();
    };
  }, [pdfDocumentProxy]);
  return outline;
};
var HTMLTags = [
  "a",
  "button",
  "div",
  "aside",
  "section",
  "main",
  "ul",
  "li",
  "input",
  "canvas"
];
var makePrimitive = (htmlTag) => {
  const primitive = forwardRef(
    (props, ref) => {
      const Renderer = htmlTag;
      return /* @__PURE__ */ jsx(Renderer, { ...props, ref });
    }
  );
  primitive.displayName = `PDFReader.${htmlTag}`;
  return primitive;
};
var Primitive = HTMLTags.reduce((acc, tag) => {
  acc[tag] = makePrimitive(tag);
  return acc;
}, {});
var OutlineChildItems = ({
  ...props
}) => {
  return /* @__PURE__ */ jsx(Primitive.ul, { ...props });
};
var OutlineItem = ({
  level = 0,
  item,
  children,
  outlineItem,
  ...props
}) => {
  if (!item || !outlineItem || !children) {
    throw new Error("Outline item is required");
  }
  const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
  const { jumpToPage } = usePdfJump();
  const getDestinationPage = useCallback(
    async (dest) => {
      let explicitDest;
      if (typeof dest === "string") {
        explicitDest = await pdfDocumentProxy.getDestination(dest);
      } else if (Array.isArray(dest)) {
        explicitDest = dest;
      } else {
        explicitDest = await dest;
      }
      if (!explicitDest) {
        return;
      }
      const explicitRef = explicitDest[0];
      const page = await pdfDocumentProxy.getPageIndex(explicitRef);
      return page;
    },
    [pdfDocumentProxy]
  );
  const navigate = useCallback(() => {
    if (!item.dest) {
      return;
    }
    getDestinationPage(item.dest).then((page) => {
      if (!page) {
        return;
      }
      jumpToPage(page, { behavior: "smooth" });
    });
  }, [item.dest, jumpToPage, getDestinationPage]);
  return /* @__PURE__ */ jsxs(Primitive.li, { ...props, children: [
    /* @__PURE__ */ jsx(
      "a",
      {
        role: "button",
        tabIndex: 0,
        onClick: navigate,
        onKeyUp: (e) => {
          if (e.key === "Enter") {
            navigate();
          }
        },
        "data-level": level,
        children: item.title
      }
    ),
    item.items && item.items.length > 0 && cloneElement(children, {
      // @ts-expect-error we are missing the corect props types
      children: item.items.map(
        (item2, index) => cloneElement(outlineItem, {
          // @ts-expect-error we are missing the corect props types
          level: level + 1,
          item: item2,
          outlineItem,
          key: index
        })
      )
    })
  ] });
};
var Outline = ({
  children,
  ...props
}) => {
  const outline = usePDFOutline();
  return /* @__PURE__ */ jsx(Primitive.ul, { ...props, children: outline && outline.map((item, idx) => {
    return cloneElement(children, {
      key: idx,
      item,
      outlineItem: children
    });
  }) });
};
var Page = ({
  children,
  pageNumber = 1,
  style,
  ...props
}) => {
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
  const width = (pdfPageProxy.view[2] ?? 0) - (pdfPageProxy.view[0] ?? 0);
  const height = (pdfPageProxy.view[3] ?? 0) - (pdfPageProxy.view[1] ?? 0);
  return /* @__PURE__ */ jsx(PDFPageNumberContext.Provider, { value: pdfPageProxy.pageNumber, children: /* @__PURE__ */ jsx(
    Primitive.div,
    {
      style: {
        display: "block"
      },
      children: /* @__PURE__ */ jsx(
        "div",
        {
          style: {
            ...style,
            "--scale-factor": 1,
            position: "relative",
            width,
            height
          },
          ...props,
          children
        }
      )
    }
  ) });
};
var NextPage = () => {
};
var PreviousPage = () => {
};
var CurrentPage = ({ ...props }) => {
  const currentPage = usePdf((state) => state.currentPage);
  const pages = usePdf((state) => state.pdfDocumentProxy.numPages);
  const [pageNumber, setPageNumber] = useState(currentPage);
  const isSelected = useRef(false);
  const { jumpToPage } = usePdfJump();
  useEffect(() => {
    if (isSelected.current) {
      return;
    }
    setPageNumber(currentPage);
  }, [currentPage]);
  return /* @__PURE__ */ jsx(
    "input",
    {
      type: "number",
      ...props,
      style: {
        ...props.style,
        appearance: "textfield",
        MozAppearance: "textfield",
        WebkitAppearance: "none"
      },
      value: pageNumber,
      onChange: (e) => {
        setPageNumber(e.target.value);
      },
      onClick: () => isSelected.current = true,
      onBlur: (e) => {
        if (currentPage !== Number(e.target.value)) {
          jumpToPage(Number(e.target.value), {
            behavior: "auto"
          });
        }
        isSelected.current = false;
      },
      onKeyDown: (e) => {
        e.key === "Enter" && e.currentTarget.blur();
      },
      min: 1,
      max: pages
    }
  );
};
var TotalPages = ({ ...props }) => {
  const pages = usePdf((state) => state.pdfDocumentProxy.numPages);
  return /* @__PURE__ */ jsx("div", { ...props, children: pages });
};
var useFitWidth = ({ viewportRef }) => {
  const viewports = usePdf((state) => state.viewports);
  const zoomOptions = usePdf((state) => state.zoomOptions);
  const updateZoom = usePdf((state) => state.updateZoom);
  const store = PDFStore.useContext();
  useLayoutEffect(() => {
    if (viewportRef.current === null) return;
    const resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        const isFitWidth = store.getState().isZoomFitWidth;
        if (entry.target === viewportRef.current && isFitWidth) {
          const containerWidth = entry.contentRect.width;
          const newZoom = getFitWidthZoom(
            containerWidth,
            viewports,
            zoomOptions
          );
          updateZoom(newZoom, true);
        }
      }
    });
    resizeObserver.observe(viewportRef.current);
    return () => {
      resizeObserver.disconnect();
    };
  }, [store, updateZoom, viewportRef, viewports, zoomOptions]);
  return null;
};
var supportsScrollend = typeof window == "undefined" ? true : "onscrollend" in window;
var addEventListenerOptions = {
  passive: true
};
var useObserveElement = () => {
  const store = PDFStore.useContext();
  const observeElementOffset = (instance, cb) => {
    const element = instance.scrollElement;
    if (!element) {
      return;
    }
    const targetWindow = instance.targetWindow;
    if (!targetWindow) {
      return;
    }
    let offset2 = 0;
    const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce(
      targetWindow,
      () => {
        cb(offset2, false);
      },
      instance.options.isScrollingResetDelay
    );
    const createHandler = (isScrolling) => () => {
      const { horizontal, isRtl } = instance.options;
      offset2 = horizontal ? element["scrollLeft"] * (isRtl && -1 || 1) : element["scrollTop"];
      const zoom = store.getState().zoom;
      offset2 = offset2 / zoom;
      fallback();
      cb(offset2, isScrolling);
    };
    const handler = createHandler(true);
    const endHandler = createHandler(false);
    endHandler();
    element.addEventListener("scroll", handler, addEventListenerOptions);
    element.addEventListener("scrollend", endHandler, addEventListenerOptions);
    return () => {
      element.removeEventListener("scroll", handler);
      element.removeEventListener("scrollend", endHandler);
    };
  };
  return {
    observeElementOffset
  };
};
var useScrollFn = () => {
  const store = PDFStore.useContext();
  const scrollToFn = useCallback(
    (_offset, canSmooth, instance) => {
      const zoom = store.getState().zoom;
      const offset2 = _offset * zoom;
      elementScroll(offset2, canSmooth, instance);
    },
    [store]
  );
  return { scrollToFn };
};
var useVisiblePage = ({ items }) => {
  const zoomLevel = usePdf((state) => state.zoom);
  const isPinching = usePdf((state) => state.isPinching);
  const setCurrentPage = usePdf((state) => state.setCurrentPage);
  const scrollElement = usePdf((state) => state.viewportRef?.current);
  const calculateVisiblePageIndex = useCallback(
    (virtualItems) => {
      if (!scrollElement || virtualItems.length === 0) return 0;
      const scrollTop = scrollElement.scrollTop / zoomLevel;
      const viewportHeight = scrollElement.clientHeight / zoomLevel;
      const viewportCenter = scrollTop + viewportHeight / 2;
      let closestIndex = 0;
      let smallestDistance = Infinity;
      for (const item of virtualItems) {
        const itemCenter = item.start + item.size / 2;
        const distance = Math.abs(itemCenter - viewportCenter);
        if (distance < smallestDistance * 0.8) {
          smallestDistance = distance;
          closestIndex = item.index;
        }
      }
      return closestIndex;
    },
    [scrollElement, zoomLevel]
  );
  useEffect(() => {
    if (!isPinching && items.length > 0) {
      const mostVisibleIndex = calculateVisiblePageIndex(items);
      setCurrentPage?.(mostVisibleIndex + 1);
    }
  }, [items, isPinching, calculateVisiblePageIndex, setCurrentPage]);
  return null;
};

// ../../node_modules/.pnpm/@use-gesture+core@10.3.1/node_modules/@use-gesture/core/dist/maths-0ab39ae9.esm.js
function clamp2(v, min, max) {
  return Math.max(min, Math.min(v, max));
}
var V = {
  toVector(v, fallback) {
    if (v === void 0) v = fallback;
    return Array.isArray(v) ? v : [v, v];
  },
  add(v1, v2) {
    return [v1[0] + v2[0], v1[1] + v2[1]];
  },
  sub(v1, v2) {
    return [v1[0] - v2[0], v1[1] - v2[1]];
  },
  addTo(v1, v2) {
    v1[0] += v2[0];
    v1[1] += v2[1];
  },
  subTo(v1, v2) {
    v1[0] -= v2[0];
    v1[1] -= v2[1];
  }
};
function rubberband(distance, dimension, constant) {
  if (dimension === 0 || Math.abs(dimension) === Infinity) return Math.pow(distance, constant * 5);
  return distance * dimension * constant / (dimension + constant * distance);
}
function rubberbandIfOutOfBounds(position, min, max, constant = 0.15) {
  if (constant === 0) return clamp2(position, min, max);
  if (position < min) return -rubberband(min - position, max - min, constant) + min;
  if (position > max) return +rubberband(position - max, max - min, constant) + max;
  return position;
}
function computeRubberband(bounds, [Vx, Vy], [Rx, Ry]) {
  const [[X0, X1], [Y0, Y1]] = bounds;
  return [rubberbandIfOutOfBounds(Vx, X0, X1, Rx), rubberbandIfOutOfBounds(Vy, Y0, Y1, Ry)];
}

// ../../node_modules/.pnpm/@use-gesture+core@10.3.1/node_modules/@use-gesture/core/dist/actions-fe213e88.esm.js
function _toPrimitive(input, hint) {
  if (typeof input !== "object" || input === null) return input;
  var prim = input[Symbol.toPrimitive];
  if (prim !== void 0) {
    var res = prim.call(input, hint || "default");
    if (typeof res !== "object") return res;
    throw new TypeError("@@toPrimitive must return a primitive value.");
  }
  return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey(arg) {
  var key = _toPrimitive(arg, "string");
  return typeof key === "symbol" ? key : String(key);
}
function _defineProperty(obj, key, value) {
  key = _toPropertyKey(key);
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }
  return obj;
}
function ownKeys(e, r2) {
  var t = Object.keys(e);
  if (Object.getOwnPropertySymbols) {
    var o = Object.getOwnPropertySymbols(e);
    r2 && (o = o.filter(function(r3) {
      return Object.getOwnPropertyDescriptor(e, r3).enumerable;
    })), t.push.apply(t, o);
  }
  return t;
}
function _objectSpread2(e) {
  for (var r2 = 1; r2 < arguments.length; r2++) {
    var t = null != arguments[r2] ? arguments[r2] : {};
    r2 % 2 ? ownKeys(Object(t), true).forEach(function(r3) {
      _defineProperty(e, r3, t[r3]);
    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r3) {
      Object.defineProperty(e, r3, Object.getOwnPropertyDescriptor(t, r3));
    });
  }
  return e;
}
var EVENT_TYPE_MAP = {
  pointer: {
    start: "down",
    change: "move",
    end: "up"
  },
  mouse: {
    start: "down",
    change: "move",
    end: "up"
  },
  touch: {
    start: "start",
    change: "move",
    end: "end"
  },
  gesture: {
    start: "start",
    change: "change",
    end: "end"
  }
};
function capitalize(string) {
  if (!string) return "";
  return string[0].toUpperCase() + string.slice(1);
}
var actionsWithoutCaptureSupported = ["enter", "leave"];
function hasCapture(capture = false, actionKey) {
  return capture && !actionsWithoutCaptureSupported.includes(actionKey);
}
function toHandlerProp(device, action = "", capture = false) {
  const deviceProps = EVENT_TYPE_MAP[device];
  const actionKey = deviceProps ? deviceProps[action] || action : action;
  return "on" + capitalize(device) + capitalize(actionKey) + (hasCapture(capture, actionKey) ? "Capture" : "");
}
var pointerCaptureEvents = ["gotpointercapture", "lostpointercapture"];
function parseProp(prop) {
  let eventKey = prop.substring(2).toLowerCase();
  const passive = !!~eventKey.indexOf("passive");
  if (passive) eventKey = eventKey.replace("passive", "");
  const captureKey = pointerCaptureEvents.includes(eventKey) ? "capturecapture" : "capture";
  const capture = !!~eventKey.indexOf(captureKey);
  if (capture) eventKey = eventKey.replace("capture", "");
  return {
    device: eventKey,
    capture,
    passive
  };
}
function toDomEventType(device, action = "") {
  const deviceProps = EVENT_TYPE_MAP[device];
  const actionKey = deviceProps ? deviceProps[action] || action : action;
  return device + actionKey;
}
function isTouch(event) {
  return "touches" in event;
}
function getPointerType(event) {
  if (isTouch(event)) return "touch";
  if ("pointerType" in event) return event.pointerType;
  return "mouse";
}
function getCurrentTargetTouchList(event) {
  return Array.from(event.touches).filter((e) => {
    var _event$currentTarget, _event$currentTarget$;
    return e.target === event.currentTarget || ((_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 || (_event$currentTarget$ = _event$currentTarget.contains) === null || _event$currentTarget$ === void 0 ? void 0 : _event$currentTarget$.call(_event$currentTarget, e.target));
  });
}
function getTouchList(event) {
  return event.type === "touchend" || event.type === "touchcancel" ? event.changedTouches : event.targetTouches;
}
function getValueEvent(event) {
  return isTouch(event) ? getTouchList(event)[0] : event;
}
function distanceAngle(P1, P2) {
  try {
    const dx = P2.clientX - P1.clientX;
    const dy = P2.clientY - P1.clientY;
    const cx = (P2.clientX + P1.clientX) / 2;
    const cy = (P2.clientY + P1.clientY) / 2;
    const distance = Math.hypot(dx, dy);
    const angle = -(Math.atan2(dx, dy) * 180) / Math.PI;
    const origin = [cx, cy];
    return {
      angle,
      distance,
      origin
    };
  } catch (_unused) {
  }
  return null;
}
function touchIds(event) {
  return getCurrentTargetTouchList(event).map((touch) => touch.identifier);
}
function touchDistanceAngle(event, ids) {
  const [P1, P2] = Array.from(event.touches).filter((touch) => ids.includes(touch.identifier));
  return distanceAngle(P1, P2);
}
function pointerId(event) {
  const valueEvent = getValueEvent(event);
  return isTouch(event) ? valueEvent.identifier : valueEvent.pointerId;
}
function pointerValues(event) {
  const valueEvent = getValueEvent(event);
  return [valueEvent.clientX, valueEvent.clientY];
}
var LINE_HEIGHT = 40;
var PAGE_HEIGHT = 800;
function wheelValues(event) {
  let {
    deltaX,
    deltaY,
    deltaMode
  } = event;
  if (deltaMode === 1) {
    deltaX *= LINE_HEIGHT;
    deltaY *= LINE_HEIGHT;
  } else if (deltaMode === 2) {
    deltaX *= PAGE_HEIGHT;
    deltaY *= PAGE_HEIGHT;
  }
  return [deltaX, deltaY];
}
function scrollValues(event) {
  var _ref, _ref2;
  const {
    scrollX,
    scrollY,
    scrollLeft,
    scrollTop
  } = event.currentTarget;
  return [(_ref = scrollX !== null && scrollX !== void 0 ? scrollX : scrollLeft) !== null && _ref !== void 0 ? _ref : 0, (_ref2 = scrollY !== null && scrollY !== void 0 ? scrollY : scrollTop) !== null && _ref2 !== void 0 ? _ref2 : 0];
}
function getEventDetails(event) {
  const payload = {};
  if ("buttons" in event) payload.buttons = event.buttons;
  if ("shiftKey" in event) {
    const {
      shiftKey,
      altKey,
      metaKey,
      ctrlKey
    } = event;
    Object.assign(payload, {
      shiftKey,
      altKey,
      metaKey,
      ctrlKey
    });
  }
  return payload;
}
function call(v, ...args) {
  if (typeof v === "function") {
    return v(...args);
  } else {
    return v;
  }
}
function noop() {
}
function chain(...fns) {
  if (fns.length === 0) return noop;
  if (fns.length === 1) return fns[0];
  return function() {
    let result;
    for (const fn of fns) {
      result = fn.apply(this, arguments) || result;
    }
    return result;
  };
}
function assignDefault(value, fallback) {
  return Object.assign({}, fallback, value || {});
}
var BEFORE_LAST_KINEMATICS_DELAY = 32;
var Engine = class {
  constructor(ctrl, args, key) {
    this.ctrl = ctrl;
    this.args = args;
    this.key = key;
    if (!this.state) {
      this.state = {};
      this.computeValues([0, 0]);
      this.computeInitial();
      if (this.init) this.init();
      this.reset();
    }
  }
  get state() {
    return this.ctrl.state[this.key];
  }
  set state(state) {
    this.ctrl.state[this.key] = state;
  }
  get shared() {
    return this.ctrl.state.shared;
  }
  get eventStore() {
    return this.ctrl.gestureEventStores[this.key];
  }
  get timeoutStore() {
    return this.ctrl.gestureTimeoutStores[this.key];
  }
  get config() {
    return this.ctrl.config[this.key];
  }
  get sharedConfig() {
    return this.ctrl.config.shared;
  }
  get handler() {
    return this.ctrl.handlers[this.key];
  }
  reset() {
    const {
      state,
      shared,
      ingKey,
      args
    } = this;
    shared[ingKey] = state._active = state.active = state._blocked = state._force = false;
    state._step = [false, false];
    state.intentional = false;
    state._movement = [0, 0];
    state._distance = [0, 0];
    state._direction = [0, 0];
    state._delta = [0, 0];
    state._bounds = [[-Infinity, Infinity], [-Infinity, Infinity]];
    state.args = args;
    state.axis = void 0;
    state.memo = void 0;
    state.elapsedTime = state.timeDelta = 0;
    state.direction = [0, 0];
    state.distance = [0, 0];
    state.overflow = [0, 0];
    state._movementBound = [false, false];
    state.velocity = [0, 0];
    state.movement = [0, 0];
    state.delta = [0, 0];
    state.timeStamp = 0;
  }
  start(event) {
    const state = this.state;
    const config = this.config;
    if (!state._active) {
      this.reset();
      this.computeInitial();
      state._active = true;
      state.target = event.target;
      state.currentTarget = event.currentTarget;
      state.lastOffset = config.from ? call(config.from, state) : state.offset;
      state.offset = state.lastOffset;
      state.startTime = state.timeStamp = event.timeStamp;
    }
  }
  computeValues(values) {
    const state = this.state;
    state._values = values;
    state.values = this.config.transform(values);
  }
  computeInitial() {
    const state = this.state;
    state._initial = state._values;
    state.initial = state.values;
  }
  compute(event) {
    const {
      state,
      config,
      shared
    } = this;
    state.args = this.args;
    let dt = 0;
    if (event) {
      state.event = event;
      if (config.preventDefault && event.cancelable) state.event.preventDefault();
      state.type = event.type;
      shared.touches = this.ctrl.pointerIds.size || this.ctrl.touchIds.size;
      shared.locked = !!document.pointerLockElement;
      Object.assign(shared, getEventDetails(event));
      shared.down = shared.pressed = shared.buttons % 2 === 1 || shared.touches > 0;
      dt = event.timeStamp - state.timeStamp;
      state.timeStamp = event.timeStamp;
      state.elapsedTime = state.timeStamp - state.startTime;
    }
    if (state._active) {
      const _absoluteDelta = state._delta.map(Math.abs);
      V.addTo(state._distance, _absoluteDelta);
    }
    if (this.axisIntent) this.axisIntent(event);
    const [_m0, _m1] = state._movement;
    const [t0, t1] = config.threshold;
    const {
      _step,
      values
    } = state;
    if (config.hasCustomTransform) {
      if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && values[0];
      if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && values[1];
    } else {
      if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && Math.sign(_m0) * t0;
      if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && Math.sign(_m1) * t1;
    }
    state.intentional = _step[0] !== false || _step[1] !== false;
    if (!state.intentional) return;
    const movement = [0, 0];
    if (config.hasCustomTransform) {
      const [v0, v1] = values;
      movement[0] = _step[0] !== false ? v0 - _step[0] : 0;
      movement[1] = _step[1] !== false ? v1 - _step[1] : 0;
    } else {
      movement[0] = _step[0] !== false ? _m0 - _step[0] : 0;
      movement[1] = _step[1] !== false ? _m1 - _step[1] : 0;
    }
    if (this.restrictToAxis && !state._blocked) this.restrictToAxis(movement);
    const previousOffset = state.offset;
    const gestureIsActive = state._active && !state._blocked || state.active;
    if (gestureIsActive) {
      state.first = state._active && !state.active;
      state.last = !state._active && state.active;
      state.active = shared[this.ingKey] = state._active;
      if (event) {
        if (state.first) {
          if ("bounds" in config) state._bounds = call(config.bounds, state);
          if (this.setup) this.setup();
        }
        state.movement = movement;
        this.computeOffset();
      }
    }
    const [ox, oy] = state.offset;
    const [[x0, x1], [y0, y1]] = state._bounds;
    state.overflow = [ox < x0 ? -1 : ox > x1 ? 1 : 0, oy < y0 ? -1 : oy > y1 ? 1 : 0];
    state._movementBound[0] = state.overflow[0] ? state._movementBound[0] === false ? state._movement[0] : state._movementBound[0] : false;
    state._movementBound[1] = state.overflow[1] ? state._movementBound[1] === false ? state._movement[1] : state._movementBound[1] : false;
    const rubberband2 = state._active ? config.rubberband || [0, 0] : [0, 0];
    state.offset = computeRubberband(state._bounds, state.offset, rubberband2);
    state.delta = V.sub(state.offset, previousOffset);
    this.computeMovement();
    if (gestureIsActive && (!state.last || dt > BEFORE_LAST_KINEMATICS_DELAY)) {
      state.delta = V.sub(state.offset, previousOffset);
      const absoluteDelta = state.delta.map(Math.abs);
      V.addTo(state.distance, absoluteDelta);
      state.direction = state.delta.map(Math.sign);
      state._direction = state._delta.map(Math.sign);
      if (!state.first && dt > 0) {
        state.velocity = [absoluteDelta[0] / dt, absoluteDelta[1] / dt];
        state.timeDelta = dt;
      }
    }
  }
  emit() {
    const state = this.state;
    const shared = this.shared;
    const config = this.config;
    if (!state._active) this.clean();
    if ((state._blocked || !state.intentional) && !state._force && !config.triggerAllEvents) return;
    const memo = this.handler(_objectSpread2(_objectSpread2(_objectSpread2({}, shared), state), {}, {
      [this.aliasKey]: state.values
    }));
    if (memo !== void 0) state.memo = memo;
  }
  clean() {
    this.eventStore.clean();
    this.timeoutStore.clean();
  }
};
function selectAxis([dx, dy], threshold) {
  const absDx = Math.abs(dx);
  const absDy = Math.abs(dy);
  if (absDx > absDy && absDx > threshold) {
    return "x";
  }
  if (absDy > absDx && absDy > threshold) {
    return "y";
  }
  return void 0;
}
var CoordinatesEngine = class extends Engine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "aliasKey", "xy");
  }
  reset() {
    super.reset();
    this.state.axis = void 0;
  }
  init() {
    this.state.offset = [0, 0];
    this.state.lastOffset = [0, 0];
  }
  computeOffset() {
    this.state.offset = V.add(this.state.lastOffset, this.state.movement);
  }
  computeMovement() {
    this.state.movement = V.sub(this.state.offset, this.state.lastOffset);
  }
  axisIntent(event) {
    const state = this.state;
    const config = this.config;
    if (!state.axis && event) {
      const threshold = typeof config.axisThreshold === "object" ? config.axisThreshold[getPointerType(event)] : config.axisThreshold;
      state.axis = selectAxis(state._movement, threshold);
    }
    state._blocked = (config.lockDirection || !!config.axis) && !state.axis || !!config.axis && config.axis !== state.axis;
  }
  restrictToAxis(v) {
    if (this.config.axis || this.config.lockDirection) {
      switch (this.state.axis) {
        case "x":
          v[1] = 0;
          break;
        case "y":
          v[0] = 0;
          break;
      }
    }
  }
};
var identity = (v) => v;
var DEFAULT_RUBBERBAND = 0.15;
var commonConfigResolver = {
  enabled(value = true) {
    return value;
  },
  eventOptions(value, _k, config) {
    return _objectSpread2(_objectSpread2({}, config.shared.eventOptions), value);
  },
  preventDefault(value = false) {
    return value;
  },
  triggerAllEvents(value = false) {
    return value;
  },
  rubberband(value = 0) {
    switch (value) {
      case true:
        return [DEFAULT_RUBBERBAND, DEFAULT_RUBBERBAND];
      case false:
        return [0, 0];
      default:
        return V.toVector(value);
    }
  },
  from(value) {
    if (typeof value === "function") return value;
    if (value != null) return V.toVector(value);
  },
  transform(value, _k, config) {
    const transform = value || config.shared.transform;
    this.hasCustomTransform = !!transform;
    if (process.env.NODE_ENV === "development") {
      const originalTransform = transform || identity;
      return (v) => {
        const r2 = originalTransform(v);
        if (!isFinite(r2[0]) || !isFinite(r2[1])) {
          console.warn(`[@use-gesture]: config.transform() must produce a valid result, but it was: [${r2[0]},${[1]}]`);
        }
        return r2;
      };
    }
    return transform || identity;
  },
  threshold(value) {
    return V.toVector(value, 0);
  }
};
if (process.env.NODE_ENV === "development") {
  Object.assign(commonConfigResolver, {
    domTarget(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`);
      }
      return NaN;
    },
    lockDirection(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`lockDirection\` option has been merged with \`axis\`. Use it as in \`{ axis: 'lock' }\``);
      }
      return NaN;
    },
    initial(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`initial\` option has been renamed to \`from\`.`);
      }
      return NaN;
    }
  });
}
var DEFAULT_AXIS_THRESHOLD = 0;
var coordinatesConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, {
  axis(_v, _k, {
    axis
  }) {
    this.lockDirection = axis === "lock";
    if (!this.lockDirection) return axis;
  },
  axisThreshold(value = DEFAULT_AXIS_THRESHOLD) {
    return value;
  },
  bounds(value = {}) {
    if (typeof value === "function") {
      return (state) => coordinatesConfigResolver.bounds(value(state));
    }
    if ("current" in value) {
      return () => value.current;
    }
    if (typeof HTMLElement === "function" && value instanceof HTMLElement) {
      return value;
    }
    const {
      left = -Infinity,
      right = Infinity,
      top = -Infinity,
      bottom = Infinity
    } = value;
    return [[left, right], [top, bottom]];
  }
});
var KEYS_DELTA_MAP = {
  ArrowRight: (displacement, factor = 1) => [displacement * factor, 0],
  ArrowLeft: (displacement, factor = 1) => [-1 * displacement * factor, 0],
  ArrowUp: (displacement, factor = 1) => [0, -1 * displacement * factor],
  ArrowDown: (displacement, factor = 1) => [0, displacement * factor]
};
var DragEngine = class extends CoordinatesEngine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "ingKey", "dragging");
  }
  reset() {
    super.reset();
    const state = this.state;
    state._pointerId = void 0;
    state._pointerActive = false;
    state._keyboardActive = false;
    state._preventScroll = false;
    state._delayed = false;
    state.swipe = [0, 0];
    state.tap = false;
    state.canceled = false;
    state.cancel = this.cancel.bind(this);
  }
  setup() {
    const state = this.state;
    if (state._bounds instanceof HTMLElement) {
      const boundRect = state._bounds.getBoundingClientRect();
      const targetRect = state.currentTarget.getBoundingClientRect();
      const _bounds = {
        left: boundRect.left - targetRect.left + state.offset[0],
        right: boundRect.right - targetRect.right + state.offset[0],
        top: boundRect.top - targetRect.top + state.offset[1],
        bottom: boundRect.bottom - targetRect.bottom + state.offset[1]
      };
      state._bounds = coordinatesConfigResolver.bounds(_bounds);
    }
  }
  cancel() {
    const state = this.state;
    if (state.canceled) return;
    state.canceled = true;
    state._active = false;
    setTimeout(() => {
      this.compute();
      this.emit();
    }, 0);
  }
  setActive() {
    this.state._active = this.state._pointerActive || this.state._keyboardActive;
  }
  clean() {
    this.pointerClean();
    this.state._pointerActive = false;
    this.state._keyboardActive = false;
    super.clean();
  }
  pointerDown(event) {
    const config = this.config;
    const state = this.state;
    if (event.buttons != null && (Array.isArray(config.pointerButtons) ? !config.pointerButtons.includes(event.buttons) : config.pointerButtons !== -1 && config.pointerButtons !== event.buttons)) return;
    const ctrlIds = this.ctrl.setEventIds(event);
    if (config.pointerCapture) {
      event.target.setPointerCapture(event.pointerId);
    }
    if (ctrlIds && ctrlIds.size > 1 && state._pointerActive) return;
    this.start(event);
    this.setupPointer(event);
    state._pointerId = pointerId(event);
    state._pointerActive = true;
    this.computeValues(pointerValues(event));
    this.computeInitial();
    if (config.preventScrollAxis && getPointerType(event) !== "mouse") {
      state._active = false;
      this.setupScrollPrevention(event);
    } else if (config.delay > 0) {
      this.setupDelayTrigger(event);
      if (config.triggerAllEvents) {
        this.compute(event);
        this.emit();
      }
    } else {
      this.startPointerDrag(event);
    }
  }
  startPointerDrag(event) {
    const state = this.state;
    state._active = true;
    state._preventScroll = true;
    state._delayed = false;
    this.compute(event);
    this.emit();
  }
  pointerMove(event) {
    const state = this.state;
    const config = this.config;
    if (!state._pointerActive) return;
    const id = pointerId(event);
    if (state._pointerId !== void 0 && id !== state._pointerId) return;
    const _values = pointerValues(event);
    if (document.pointerLockElement === event.target) {
      state._delta = [event.movementX, event.movementY];
    } else {
      state._delta = V.sub(_values, state._values);
      this.computeValues(_values);
    }
    V.addTo(state._movement, state._delta);
    this.compute(event);
    if (state._delayed && state.intentional) {
      this.timeoutStore.remove("dragDelay");
      state.active = false;
      this.startPointerDrag(event);
      return;
    }
    if (config.preventScrollAxis && !state._preventScroll) {
      if (state.axis) {
        if (state.axis === config.preventScrollAxis || config.preventScrollAxis === "xy") {
          state._active = false;
          this.clean();
          return;
        } else {
          this.timeoutStore.remove("startPointerDrag");
          this.startPointerDrag(event);
          return;
        }
      } else {
        return;
      }
    }
    this.emit();
  }
  pointerUp(event) {
    this.ctrl.setEventIds(event);
    try {
      if (this.config.pointerCapture && event.target.hasPointerCapture(event.pointerId)) {
        ;
        event.target.releasePointerCapture(event.pointerId);
      }
    } catch (_unused) {
      if (process.env.NODE_ENV === "development") {
        console.warn(`[@use-gesture]: If you see this message, it's likely that you're using an outdated version of \`@react-three/fiber\`. 

Please upgrade to the latest version.`);
      }
    }
    const state = this.state;
    const config = this.config;
    if (!state._active || !state._pointerActive) return;
    const id = pointerId(event);
    if (state._pointerId !== void 0 && id !== state._pointerId) return;
    this.state._pointerActive = false;
    this.setActive();
    this.compute(event);
    const [dx, dy] = state._distance;
    state.tap = dx <= config.tapsThreshold && dy <= config.tapsThreshold;
    if (state.tap && config.filterTaps) {
      state._force = true;
    } else {
      const [_dx, _dy] = state._delta;
      const [_mx, _my] = state._movement;
      const [svx, svy] = config.swipe.velocity;
      const [sx, sy] = config.swipe.distance;
      const sdt = config.swipe.duration;
      if (state.elapsedTime < sdt) {
        const _vx = Math.abs(_dx / state.timeDelta);
        const _vy = Math.abs(_dy / state.timeDelta);
        if (_vx > svx && Math.abs(_mx) > sx) state.swipe[0] = Math.sign(_dx);
        if (_vy > svy && Math.abs(_my) > sy) state.swipe[1] = Math.sign(_dy);
      }
    }
    this.emit();
  }
  pointerClick(event) {
    if (!this.state.tap && event.detail > 0) {
      event.preventDefault();
      event.stopPropagation();
    }
  }
  setupPointer(event) {
    const config = this.config;
    const device = config.device;
    if (process.env.NODE_ENV === "development") {
      try {
        if (device === "pointer" && config.preventScrollDelay === void 0) {
          const currentTarget = "uv" in event ? event.sourceEvent.currentTarget : event.currentTarget;
          const style = window.getComputedStyle(currentTarget);
          if (style.touchAction === "auto") {
            console.warn(`[@use-gesture]: The drag target has its \`touch-action\` style property set to \`auto\`. It is recommended to add \`touch-action: 'none'\` so that the drag gesture behaves correctly on touch-enabled devices. For more information read this: https://use-gesture.netlify.app/docs/extras/#touch-action.

This message will only show in development mode. It won't appear in production. If this is intended, you can ignore it.`, currentTarget);
          }
        }
      } catch (_unused2) {
      }
    }
    if (config.pointerLock) {
      event.currentTarget.requestPointerLock();
    }
    if (!config.pointerCapture) {
      this.eventStore.add(this.sharedConfig.window, device, "change", this.pointerMove.bind(this));
      this.eventStore.add(this.sharedConfig.window, device, "end", this.pointerUp.bind(this));
      this.eventStore.add(this.sharedConfig.window, device, "cancel", this.pointerUp.bind(this));
    }
  }
  pointerClean() {
    if (this.config.pointerLock && document.pointerLockElement === this.state.currentTarget) {
      document.exitPointerLock();
    }
  }
  preventScroll(event) {
    if (this.state._preventScroll && event.cancelable) {
      event.preventDefault();
    }
  }
  setupScrollPrevention(event) {
    this.state._preventScroll = false;
    persistEvent(event);
    const remove = this.eventStore.add(this.sharedConfig.window, "touch", "change", this.preventScroll.bind(this), {
      passive: false
    });
    this.eventStore.add(this.sharedConfig.window, "touch", "end", remove);
    this.eventStore.add(this.sharedConfig.window, "touch", "cancel", remove);
    this.timeoutStore.add("startPointerDrag", this.startPointerDrag.bind(this), this.config.preventScrollDelay, event);
  }
  setupDelayTrigger(event) {
    this.state._delayed = true;
    this.timeoutStore.add("dragDelay", () => {
      this.state._step = [0, 0];
      this.startPointerDrag(event);
    }, this.config.delay);
  }
  keyDown(event) {
    const deltaFn = KEYS_DELTA_MAP[event.key];
    if (deltaFn) {
      const state = this.state;
      const factor = event.shiftKey ? 10 : event.altKey ? 0.1 : 1;
      this.start(event);
      state._delta = deltaFn(this.config.keyboardDisplacement, factor);
      state._keyboardActive = true;
      V.addTo(state._movement, state._delta);
      this.compute(event);
      this.emit();
    }
  }
  keyUp(event) {
    if (!(event.key in KEYS_DELTA_MAP)) return;
    this.state._keyboardActive = false;
    this.setActive();
    this.compute(event);
    this.emit();
  }
  bind(bindFunction) {
    const device = this.config.device;
    bindFunction(device, "start", this.pointerDown.bind(this));
    if (this.config.pointerCapture) {
      bindFunction(device, "change", this.pointerMove.bind(this));
      bindFunction(device, "end", this.pointerUp.bind(this));
      bindFunction(device, "cancel", this.pointerUp.bind(this));
      bindFunction("lostPointerCapture", "", this.pointerUp.bind(this));
    }
    if (this.config.keys) {
      bindFunction("key", "down", this.keyDown.bind(this));
      bindFunction("key", "up", this.keyUp.bind(this));
    }
    if (this.config.filterTaps) {
      bindFunction("click", "", this.pointerClick.bind(this), {
        capture: true,
        passive: false
      });
    }
  }
};
function persistEvent(event) {
  "persist" in event && typeof event.persist === "function" && event.persist();
}
var isBrowser = typeof window !== "undefined" && window.document && window.document.createElement;
function supportsTouchEvents() {
  return isBrowser && "ontouchstart" in window;
}
function isTouchScreen() {
  return supportsTouchEvents() || isBrowser && window.navigator.maxTouchPoints > 1;
}
function supportsPointerEvents() {
  return isBrowser && "onpointerdown" in window;
}
function supportsPointerLock() {
  return isBrowser && "exitPointerLock" in window.document;
}
function supportsGestureEvents() {
  try {
    return "constructor" in GestureEvent;
  } catch (e) {
    return false;
  }
}
var SUPPORT = {
  isBrowser,
  gesture: supportsGestureEvents(),
  touch: supportsTouchEvents(),
  touchscreen: isTouchScreen(),
  pointer: supportsPointerEvents(),
  pointerLock: supportsPointerLock()
};
var DEFAULT_PREVENT_SCROLL_DELAY = 250;
var DEFAULT_DRAG_DELAY = 180;
var DEFAULT_SWIPE_VELOCITY = 0.5;
var DEFAULT_SWIPE_DISTANCE = 50;
var DEFAULT_SWIPE_DURATION = 250;
var DEFAULT_KEYBOARD_DISPLACEMENT = 10;
var DEFAULT_DRAG_AXIS_THRESHOLD = {
  mouse: 0,
  touch: 0,
  pen: 8
};
var dragConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
  device(_v, _k, {
    pointer: {
      touch = false,
      lock = false,
      mouse = false
    } = {}
  }) {
    this.pointerLock = lock && SUPPORT.pointerLock;
    if (SUPPORT.touch && touch) return "touch";
    if (this.pointerLock) return "mouse";
    if (SUPPORT.pointer && !mouse) return "pointer";
    if (SUPPORT.touch) return "touch";
    return "mouse";
  },
  preventScrollAxis(value, _k, {
    preventScroll
  }) {
    this.preventScrollDelay = typeof preventScroll === "number" ? preventScroll : preventScroll || preventScroll === void 0 && value ? DEFAULT_PREVENT_SCROLL_DELAY : void 0;
    if (!SUPPORT.touchscreen || preventScroll === false) return void 0;
    return value ? value : preventScroll !== void 0 ? "y" : void 0;
  },
  pointerCapture(_v, _k, {
    pointer: {
      capture = true,
      buttons = 1,
      keys = true
    } = {}
  }) {
    this.pointerButtons = buttons;
    this.keys = keys;
    return !this.pointerLock && this.device === "pointer" && capture;
  },
  threshold(value, _k, {
    filterTaps = false,
    tapsThreshold = 3,
    axis = void 0
  }) {
    const threshold = V.toVector(value, filterTaps ? tapsThreshold : axis ? 1 : 0);
    this.filterTaps = filterTaps;
    this.tapsThreshold = tapsThreshold;
    return threshold;
  },
  swipe({
    velocity = DEFAULT_SWIPE_VELOCITY,
    distance = DEFAULT_SWIPE_DISTANCE,
    duration = DEFAULT_SWIPE_DURATION
  } = {}) {
    return {
      velocity: this.transform(V.toVector(velocity)),
      distance: this.transform(V.toVector(distance)),
      duration
    };
  },
  delay(value = 0) {
    switch (value) {
      case true:
        return DEFAULT_DRAG_DELAY;
      case false:
        return 0;
      default:
        return value;
    }
  },
  axisThreshold(value) {
    if (!value) return DEFAULT_DRAG_AXIS_THRESHOLD;
    return _objectSpread2(_objectSpread2({}, DEFAULT_DRAG_AXIS_THRESHOLD), value);
  },
  keyboardDisplacement(value = DEFAULT_KEYBOARD_DISPLACEMENT) {
    return value;
  }
});
if (process.env.NODE_ENV === "development") {
  Object.assign(dragConfigResolver, {
    useTouch(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`useTouch\` option has been renamed to \`pointer.touch\`. Use it as in \`{ pointer: { touch: true } }\`.`);
      }
      return NaN;
    },
    experimental_preventWindowScrollY(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`experimental_preventWindowScrollY\` option has been renamed to \`preventScroll\`.`);
      }
      return NaN;
    },
    swipeVelocity(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`swipeVelocity\` option has been renamed to \`swipe.velocity\`. Use it as in \`{ swipe: { velocity: 0.5 } }\`.`);
      }
      return NaN;
    },
    swipeDistance(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`swipeDistance\` option has been renamed to \`swipe.distance\`. Use it as in \`{ swipe: { distance: 50 } }\`.`);
      }
      return NaN;
    },
    swipeDuration(value) {
      if (value !== void 0) {
        throw Error(`[@use-gesture]: \`swipeDuration\` option has been renamed to \`swipe.duration\`. Use it as in \`{ swipe: { duration: 250 } }\`.`);
      }
      return NaN;
    }
  });
}
function clampStateInternalMovementToBounds(state) {
  const [ox, oy] = state.overflow;
  const [dx, dy] = state._delta;
  const [dirx, diry] = state._direction;
  if (ox < 0 && dx > 0 && dirx < 0 || ox > 0 && dx < 0 && dirx > 0) {
    state._movement[0] = state._movementBound[0];
  }
  if (oy < 0 && dy > 0 && diry < 0 || oy > 0 && dy < 0 && diry > 0) {
    state._movement[1] = state._movementBound[1];
  }
}
var SCALE_ANGLE_RATIO_INTENT_DEG = 30;
var PINCH_WHEEL_RATIO = 100;
var PinchEngine = class extends Engine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "ingKey", "pinching");
    _defineProperty(this, "aliasKey", "da");
  }
  init() {
    this.state.offset = [1, 0];
    this.state.lastOffset = [1, 0];
    this.state._pointerEvents = /* @__PURE__ */ new Map();
  }
  reset() {
    super.reset();
    const state = this.state;
    state._touchIds = [];
    state.canceled = false;
    state.cancel = this.cancel.bind(this);
    state.turns = 0;
  }
  computeOffset() {
    const {
      type,
      movement,
      lastOffset
    } = this.state;
    if (type === "wheel") {
      this.state.offset = V.add(movement, lastOffset);
    } else {
      this.state.offset = [(1 + movement[0]) * lastOffset[0], movement[1] + lastOffset[1]];
    }
  }
  computeMovement() {
    const {
      offset: offset2,
      lastOffset
    } = this.state;
    this.state.movement = [offset2[0] / lastOffset[0], offset2[1] - lastOffset[1]];
  }
  axisIntent() {
    const state = this.state;
    const [_m0, _m1] = state._movement;
    if (!state.axis) {
      const axisMovementDifference = Math.abs(_m0) * SCALE_ANGLE_RATIO_INTENT_DEG - Math.abs(_m1);
      if (axisMovementDifference < 0) state.axis = "angle";
      else if (axisMovementDifference > 0) state.axis = "scale";
    }
  }
  restrictToAxis(v) {
    if (this.config.lockDirection) {
      if (this.state.axis === "scale") v[1] = 0;
      else if (this.state.axis === "angle") v[0] = 0;
    }
  }
  cancel() {
    const state = this.state;
    if (state.canceled) return;
    setTimeout(() => {
      state.canceled = true;
      state._active = false;
      this.compute();
      this.emit();
    }, 0);
  }
  touchStart(event) {
    this.ctrl.setEventIds(event);
    const state = this.state;
    const ctrlTouchIds = this.ctrl.touchIds;
    if (state._active) {
      if (state._touchIds.every((id) => ctrlTouchIds.has(id))) return;
    }
    if (ctrlTouchIds.size < 2) return;
    this.start(event);
    state._touchIds = Array.from(ctrlTouchIds).slice(0, 2);
    const payload = touchDistanceAngle(event, state._touchIds);
    if (!payload) return;
    this.pinchStart(event, payload);
  }
  pointerStart(event) {
    if (event.buttons != null && event.buttons % 2 !== 1) return;
    this.ctrl.setEventIds(event);
    event.target.setPointerCapture(event.pointerId);
    const state = this.state;
    const _pointerEvents = state._pointerEvents;
    const ctrlPointerIds = this.ctrl.pointerIds;
    if (state._active) {
      if (Array.from(_pointerEvents.keys()).every((id) => ctrlPointerIds.has(id))) return;
    }
    if (_pointerEvents.size < 2) {
      _pointerEvents.set(event.pointerId, event);
    }
    if (state._pointerEvents.size < 2) return;
    this.start(event);
    const payload = distanceAngle(...Array.from(_pointerEvents.values()));
    if (!payload) return;
    this.pinchStart(event, payload);
  }
  pinchStart(event, payload) {
    const state = this.state;
    state.origin = payload.origin;
    this.computeValues([payload.distance, payload.angle]);
    this.computeInitial();
    this.compute(event);
    this.emit();
  }
  touchMove(event) {
    if (!this.state._active) return;
    const payload = touchDistanceAngle(event, this.state._touchIds);
    if (!payload) return;
    this.pinchMove(event, payload);
  }
  pointerMove(event) {
    const _pointerEvents = this.state._pointerEvents;
    if (_pointerEvents.has(event.pointerId)) {
      _pointerEvents.set(event.pointerId, event);
    }
    if (!this.state._active) return;
    const payload = distanceAngle(...Array.from(_pointerEvents.values()));
    if (!payload) return;
    this.pinchMove(event, payload);
  }
  pinchMove(event, payload) {
    const state = this.state;
    const prev_a = state._values[1];
    const delta_a = payload.angle - prev_a;
    let delta_turns = 0;
    if (Math.abs(delta_a) > 270) delta_turns += Math.sign(delta_a);
    this.computeValues([payload.distance, payload.angle - 360 * delta_turns]);
    state.origin = payload.origin;
    state.turns = delta_turns;
    state._movement = [state._values[0] / state._initial[0] - 1, state._values[1] - state._initial[1]];
    this.compute(event);
    this.emit();
  }
  touchEnd(event) {
    this.ctrl.setEventIds(event);
    if (!this.state._active) return;
    if (this.state._touchIds.some((id) => !this.ctrl.touchIds.has(id))) {
      this.state._active = false;
      this.compute(event);
      this.emit();
    }
  }
  pointerEnd(event) {
    const state = this.state;
    this.ctrl.setEventIds(event);
    try {
      event.target.releasePointerCapture(event.pointerId);
    } catch (_unused) {
    }
    if (state._pointerEvents.has(event.pointerId)) {
      state._pointerEvents.delete(event.pointerId);
    }
    if (!state._active) return;
    if (state._pointerEvents.size < 2) {
      state._active = false;
      this.compute(event);
      this.emit();
    }
  }
  gestureStart(event) {
    if (event.cancelable) event.preventDefault();
    const state = this.state;
    if (state._active) return;
    this.start(event);
    this.computeValues([event.scale, event.rotation]);
    state.origin = [event.clientX, event.clientY];
    this.compute(event);
    this.emit();
  }
  gestureMove(event) {
    if (event.cancelable) event.preventDefault();
    if (!this.state._active) return;
    const state = this.state;
    this.computeValues([event.scale, event.rotation]);
    state.origin = [event.clientX, event.clientY];
    const _previousMovement = state._movement;
    state._movement = [event.scale - 1, event.rotation];
    state._delta = V.sub(state._movement, _previousMovement);
    this.compute(event);
    this.emit();
  }
  gestureEnd(event) {
    if (!this.state._active) return;
    this.state._active = false;
    this.compute(event);
    this.emit();
  }
  wheel(event) {
    const modifierKey = this.config.modifierKey;
    if (modifierKey && (Array.isArray(modifierKey) ? !modifierKey.find((k) => event[k]) : !event[modifierKey])) return;
    if (!this.state._active) this.wheelStart(event);
    else this.wheelChange(event);
    this.timeoutStore.add("wheelEnd", this.wheelEnd.bind(this));
  }
  wheelStart(event) {
    this.start(event);
    this.wheelChange(event);
  }
  wheelChange(event) {
    const isR3f = "uv" in event;
    if (!isR3f) {
      if (event.cancelable) {
        event.preventDefault();
      }
      if (process.env.NODE_ENV === "development" && !event.defaultPrevented) {
        console.warn(`[@use-gesture]: To properly support zoom on trackpads, try using the \`target\` option.

This message will only appear in development mode.`);
      }
    }
    const state = this.state;
    state._delta = [-wheelValues(event)[1] / PINCH_WHEEL_RATIO * state.offset[0], 0];
    V.addTo(state._movement, state._delta);
    clampStateInternalMovementToBounds(state);
    this.state.origin = [event.clientX, event.clientY];
    this.compute(event);
    this.emit();
  }
  wheelEnd() {
    if (!this.state._active) return;
    this.state._active = false;
    this.compute();
    this.emit();
  }
  bind(bindFunction) {
    const device = this.config.device;
    if (!!device) {
      bindFunction(device, "start", this[device + "Start"].bind(this));
      bindFunction(device, "change", this[device + "Move"].bind(this));
      bindFunction(device, "end", this[device + "End"].bind(this));
      bindFunction(device, "cancel", this[device + "End"].bind(this));
      bindFunction("lostPointerCapture", "", this[device + "End"].bind(this));
    }
    if (this.config.pinchOnWheel) {
      bindFunction("wheel", "", this.wheel.bind(this), {
        passive: false
      });
    }
  }
};
var pinchConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, {
  device(_v, _k, {
    shared,
    pointer: {
      touch = false
    } = {}
  }) {
    const sharedConfig = shared;
    if (sharedConfig.target && !SUPPORT.touch && SUPPORT.gesture) return "gesture";
    if (SUPPORT.touch && touch) return "touch";
    if (SUPPORT.touchscreen) {
      if (SUPPORT.pointer) return "pointer";
      if (SUPPORT.touch) return "touch";
    }
  },
  bounds(_v, _k, {
    scaleBounds = {},
    angleBounds = {}
  }) {
    const _scaleBounds = (state) => {
      const D = assignDefault(call(scaleBounds, state), {
        min: -Infinity,
        max: Infinity
      });
      return [D.min, D.max];
    };
    const _angleBounds = (state) => {
      const A = assignDefault(call(angleBounds, state), {
        min: -Infinity,
        max: Infinity
      });
      return [A.min, A.max];
    };
    if (typeof scaleBounds !== "function" && typeof angleBounds !== "function") return [_scaleBounds(), _angleBounds()];
    return (state) => [_scaleBounds(state), _angleBounds(state)];
  },
  threshold(value, _k, config) {
    this.lockDirection = config.axis === "lock";
    const threshold = V.toVector(value, this.lockDirection ? [0.1, 3] : 0);
    return threshold;
  },
  modifierKey(value) {
    if (value === void 0) return "ctrlKey";
    return value;
  },
  pinchOnWheel(value = true) {
    return value;
  }
});
var MoveEngine = class extends CoordinatesEngine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "ingKey", "moving");
  }
  move(event) {
    if (this.config.mouseOnly && event.pointerType !== "mouse") return;
    if (!this.state._active) this.moveStart(event);
    else this.moveChange(event);
    this.timeoutStore.add("moveEnd", this.moveEnd.bind(this));
  }
  moveStart(event) {
    this.start(event);
    this.computeValues(pointerValues(event));
    this.compute(event);
    this.computeInitial();
    this.emit();
  }
  moveChange(event) {
    if (!this.state._active) return;
    const values = pointerValues(event);
    const state = this.state;
    state._delta = V.sub(values, state._values);
    V.addTo(state._movement, state._delta);
    this.computeValues(values);
    this.compute(event);
    this.emit();
  }
  moveEnd(event) {
    if (!this.state._active) return;
    this.state._active = false;
    this.compute(event);
    this.emit();
  }
  bind(bindFunction) {
    bindFunction("pointer", "change", this.move.bind(this));
    bindFunction("pointer", "leave", this.moveEnd.bind(this));
  }
};
var moveConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
  mouseOnly: (value = true) => value
});
var ScrollEngine = class extends CoordinatesEngine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "ingKey", "scrolling");
  }
  scroll(event) {
    if (!this.state._active) this.start(event);
    this.scrollChange(event);
    this.timeoutStore.add("scrollEnd", this.scrollEnd.bind(this));
  }
  scrollChange(event) {
    if (event.cancelable) event.preventDefault();
    const state = this.state;
    const values = scrollValues(event);
    state._delta = V.sub(values, state._values);
    V.addTo(state._movement, state._delta);
    this.computeValues(values);
    this.compute(event);
    this.emit();
  }
  scrollEnd() {
    if (!this.state._active) return;
    this.state._active = false;
    this.compute();
    this.emit();
  }
  bind(bindFunction) {
    bindFunction("scroll", "", this.scroll.bind(this));
  }
};
var scrollConfigResolver = coordinatesConfigResolver;
var WheelEngine = class extends CoordinatesEngine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "ingKey", "wheeling");
  }
  wheel(event) {
    if (!this.state._active) this.start(event);
    this.wheelChange(event);
    this.timeoutStore.add("wheelEnd", this.wheelEnd.bind(this));
  }
  wheelChange(event) {
    const state = this.state;
    state._delta = wheelValues(event);
    V.addTo(state._movement, state._delta);
    clampStateInternalMovementToBounds(state);
    this.compute(event);
    this.emit();
  }
  wheelEnd() {
    if (!this.state._active) return;
    this.state._active = false;
    this.compute();
    this.emit();
  }
  bind(bindFunction) {
    bindFunction("wheel", "", this.wheel.bind(this));
  }
};
var wheelConfigResolver = coordinatesConfigResolver;
var HoverEngine = class extends CoordinatesEngine {
  constructor(...args) {
    super(...args);
    _defineProperty(this, "ingKey", "hovering");
  }
  enter(event) {
    if (this.config.mouseOnly && event.pointerType !== "mouse") return;
    this.start(event);
    this.computeValues(pointerValues(event));
    this.compute(event);
    this.emit();
  }
  leave(event) {
    if (this.config.mouseOnly && event.pointerType !== "mouse") return;
    const state = this.state;
    if (!state._active) return;
    state._active = false;
    const values = pointerValues(event);
    state._movement = state._delta = V.sub(values, state._values);
    this.computeValues(values);
    this.compute(event);
    state.delta = state.movement;
    this.emit();
  }
  bind(bindFunction) {
    bindFunction("pointer", "enter", this.enter.bind(this));
    bindFunction("pointer", "leave", this.leave.bind(this));
  }
};
var hoverConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
  mouseOnly: (value = true) => value
});
var EngineMap = /* @__PURE__ */ new Map();
var ConfigResolverMap = /* @__PURE__ */ new Map();
function registerAction(action) {
  EngineMap.set(action.key, action.engine);
  ConfigResolverMap.set(action.key, action.resolver);
}
var dragAction = {
  key: "drag",
  engine: DragEngine,
  resolver: dragConfigResolver
};
var hoverAction = {
  key: "hover",
  engine: HoverEngine,
  resolver: hoverConfigResolver
};
var moveAction = {
  key: "move",
  engine: MoveEngine,
  resolver: moveConfigResolver
};
var pinchAction = {
  key: "pinch",
  engine: PinchEngine,
  resolver: pinchConfigResolver
};
var scrollAction = {
  key: "scroll",
  engine: ScrollEngine,
  resolver: scrollConfigResolver
};
var wheelAction = {
  key: "wheel",
  engine: WheelEngine,
  resolver: wheelConfigResolver
};

// ../../node_modules/.pnpm/@use-gesture+core@10.3.1/node_modules/@use-gesture/core/dist/use-gesture-core.esm.js
function _objectWithoutPropertiesLoose(source, excluded) {
  if (source == null) return {};
  var target = {};
  var sourceKeys = Object.keys(source);
  var key, i;
  for (i = 0; i < sourceKeys.length; i++) {
    key = sourceKeys[i];
    if (excluded.indexOf(key) >= 0) continue;
    target[key] = source[key];
  }
  return target;
}
function _objectWithoutProperties(source, excluded) {
  if (source == null) return {};
  var target = _objectWithoutPropertiesLoose(source, excluded);
  var key, i;
  if (Object.getOwnPropertySymbols) {
    var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
    for (i = 0; i < sourceSymbolKeys.length; i++) {
      key = sourceSymbolKeys[i];
      if (excluded.indexOf(key) >= 0) continue;
      if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
      target[key] = source[key];
    }
  }
  return target;
}
var sharedConfigResolver = {
  target(value) {
    if (value) {
      return () => "current" in value ? value.current : value;
    }
    return void 0;
  },
  enabled(value = true) {
    return value;
  },
  window(value = SUPPORT.isBrowser ? window : void 0) {
    return value;
  },
  eventOptions({
    passive = true,
    capture = false
  } = {}) {
    return {
      passive,
      capture
    };
  },
  transform(value) {
    return value;
  }
};
var _excluded = ["target", "eventOptions", "window", "enabled", "transform"];
function resolveWith(config = {}, resolvers) {
  const result = {};
  for (const [key, resolver] of Object.entries(resolvers)) {
    switch (typeof resolver) {
      case "function":
        if (process.env.NODE_ENV === "development") {
          const r2 = resolver.call(result, config[key], key, config);
          if (!Number.isNaN(r2)) result[key] = r2;
        } else {
          result[key] = resolver.call(result, config[key], key, config);
        }
        break;
      case "object":
        result[key] = resolveWith(config[key], resolver);
        break;
      case "boolean":
        if (resolver) result[key] = config[key];
        break;
    }
  }
  return result;
}
function parse(newConfig, gestureKey, _config = {}) {
  const _ref = newConfig, {
    target,
    eventOptions,
    window: window2,
    enabled,
    transform
  } = _ref, rest = _objectWithoutProperties(_ref, _excluded);
  _config.shared = resolveWith({
    target,
    eventOptions,
    window: window2,
    enabled,
    transform
  }, sharedConfigResolver);
  if (gestureKey) {
    const resolver = ConfigResolverMap.get(gestureKey);
    _config[gestureKey] = resolveWith(_objectSpread2({
      shared: _config.shared
    }, rest), resolver);
  } else {
    for (const key in rest) {
      const resolver = ConfigResolverMap.get(key);
      if (resolver) {
        _config[key] = resolveWith(_objectSpread2({
          shared: _config.shared
        }, rest[key]), resolver);
      } else if (process.env.NODE_ENV === "development") {
        if (!["drag", "pinch", "scroll", "wheel", "move", "hover"].includes(key)) {
          if (key === "domTarget") {
            throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`);
          }
          console.warn(`[@use-gesture]: Unknown config key \`${key}\` was used. Please read the documentation for further information.`);
        }
      }
    }
  }
  return _config;
}
var EventStore = class {
  constructor(ctrl, gestureKey) {
    _defineProperty(this, "_listeners", /* @__PURE__ */ new Set());
    this._ctrl = ctrl;
    this._gestureKey = gestureKey;
  }
  add(element, device, action, handler, options) {
    const listeners = this._listeners;
    const type = toDomEventType(device, action);
    const _options = this._gestureKey ? this._ctrl.config[this._gestureKey].eventOptions : {};
    const eventOptions = _objectSpread2(_objectSpread2({}, _options), options);
    element.addEventListener(type, handler, eventOptions);
    const remove = () => {
      element.removeEventListener(type, handler, eventOptions);
      listeners.delete(remove);
    };
    listeners.add(remove);
    return remove;
  }
  clean() {
    this._listeners.forEach((remove) => remove());
    this._listeners.clear();
  }
};
var TimeoutStore = class {
  constructor() {
    _defineProperty(this, "_timeouts", /* @__PURE__ */ new Map());
  }
  add(key, callback, ms = 140, ...args) {
    this.remove(key);
    this._timeouts.set(key, window.setTimeout(callback, ms, ...args));
  }
  remove(key) {
    const timeout = this._timeouts.get(key);
    if (timeout) window.clearTimeout(timeout);
  }
  clean() {
    this._timeouts.forEach((timeout) => void window.clearTimeout(timeout));
    this._timeouts.clear();
  }
};
var Controller = class {
  constructor(handlers) {
    _defineProperty(this, "gestures", /* @__PURE__ */ new Set());
    _defineProperty(this, "_targetEventStore", new EventStore(this));
    _defineProperty(this, "gestureEventStores", {});
    _defineProperty(this, "gestureTimeoutStores", {});
    _defineProperty(this, "handlers", {});
    _defineProperty(this, "config", {});
    _defineProperty(this, "pointerIds", /* @__PURE__ */ new Set());
    _defineProperty(this, "touchIds", /* @__PURE__ */ new Set());
    _defineProperty(this, "state", {
      shared: {
        shiftKey: false,
        metaKey: false,
        ctrlKey: false,
        altKey: false
      }
    });
    resolveGestures(this, handlers);
  }
  setEventIds(event) {
    if (isTouch(event)) {
      this.touchIds = new Set(touchIds(event));
      return this.touchIds;
    } else if ("pointerId" in event) {
      if (event.type === "pointerup" || event.type === "pointercancel") this.pointerIds.delete(event.pointerId);
      else if (event.type === "pointerdown") this.pointerIds.add(event.pointerId);
      return this.pointerIds;
    }
  }
  applyHandlers(handlers, nativeHandlers) {
    this.handlers = handlers;
    this.nativeHandlers = nativeHandlers;
  }
  applyConfig(config, gestureKey) {
    this.config = parse(config, gestureKey, this.config);
  }
  clean() {
    this._targetEventStore.clean();
    for (const key of this.gestures) {
      this.gestureEventStores[key].clean();
      this.gestureTimeoutStores[key].clean();
    }
  }
  effect() {
    if (this.config.shared.target) this.bind();
    return () => this._targetEventStore.clean();
  }
  bind(...args) {
    const sharedConfig = this.config.shared;
    const props = {};
    let target;
    if (sharedConfig.target) {
      target = sharedConfig.target();
      if (!target) return;
    }
    if (sharedConfig.enabled) {
      for (const gestureKey of this.gestures) {
        const gestureConfig = this.config[gestureKey];
        const bindFunction = bindToProps(props, gestureConfig.eventOptions, !!target);
        if (gestureConfig.enabled) {
          const Engine2 = EngineMap.get(gestureKey);
          new Engine2(this, args, gestureKey).bind(bindFunction);
        }
      }
      const nativeBindFunction = bindToProps(props, sharedConfig.eventOptions, !!target);
      for (const eventKey in this.nativeHandlers) {
        nativeBindFunction(eventKey, "", (event) => this.nativeHandlers[eventKey](_objectSpread2(_objectSpread2({}, this.state.shared), {}, {
          event,
          args
        })), void 0, true);
      }
    }
    for (const handlerProp in props) {
      props[handlerProp] = chain(...props[handlerProp]);
    }
    if (!target) return props;
    for (const handlerProp in props) {
      const {
        device,
        capture,
        passive
      } = parseProp(handlerProp);
      this._targetEventStore.add(target, device, "", props[handlerProp], {
        capture,
        passive
      });
    }
  }
};
function setupGesture(ctrl, gestureKey) {
  ctrl.gestures.add(gestureKey);
  ctrl.gestureEventStores[gestureKey] = new EventStore(ctrl, gestureKey);
  ctrl.gestureTimeoutStores[gestureKey] = new TimeoutStore();
}
function resolveGestures(ctrl, internalHandlers) {
  if (internalHandlers.drag) setupGesture(ctrl, "drag");
  if (internalHandlers.wheel) setupGesture(ctrl, "wheel");
  if (internalHandlers.scroll) setupGesture(ctrl, "scroll");
  if (internalHandlers.move) setupGesture(ctrl, "move");
  if (internalHandlers.pinch) setupGesture(ctrl, "pinch");
  if (internalHandlers.hover) setupGesture(ctrl, "hover");
}
var bindToProps = (props, eventOptions, withPassiveOption) => (device, action, handler, options = {}, isNative = false) => {
  var _options$capture, _options$passive;
  const capture = (_options$capture = options.capture) !== null && _options$capture !== void 0 ? _options$capture : eventOptions.capture;
  const passive = (_options$passive = options.passive) !== null && _options$passive !== void 0 ? _options$passive : eventOptions.passive;
  let handlerProp = isNative ? device : toHandlerProp(device, action, capture);
  if (withPassiveOption && passive) handlerProp += "Passive";
  props[handlerProp] = props[handlerProp] || [];
  props[handlerProp].push(handler);
};
var RE_NOT_NATIVE = /^on(Drag|Wheel|Scroll|Move|Pinch|Hover)/;
function sortHandlers(_handlers) {
  const native = {};
  const handlers = {};
  const actions = /* @__PURE__ */ new Set();
  for (let key in _handlers) {
    if (RE_NOT_NATIVE.test(key)) {
      actions.add(RegExp.lastMatch);
      handlers[key] = _handlers[key];
    } else {
      native[key] = _handlers[key];
    }
  }
  return [handlers, native, actions];
}
function registerGesture(actions, handlers, handlerKey, key, internalHandlers, config) {
  if (!actions.has(handlerKey)) return;
  if (!EngineMap.has(key)) {
    if (process.env.NODE_ENV === "development") {
      console.warn(`[@use-gesture]: You've created a custom handler that that uses the \`${key}\` gesture but isn't properly configured.

Please add \`${key}Action\` when creating your handler.`);
    }
    return;
  }
  const startKey = handlerKey + "Start";
  const endKey = handlerKey + "End";
  const fn = (state) => {
    let memo = void 0;
    if (state.first && startKey in handlers) handlers[startKey](state);
    if (handlerKey in handlers) memo = handlers[handlerKey](state);
    if (state.last && endKey in handlers) handlers[endKey](state);
    return memo;
  };
  internalHandlers[key] = fn;
  config[key] = config[key] || {};
}
function parseMergedHandlers(mergedHandlers, mergedConfig) {
  const [handlers, nativeHandlers, actions] = sortHandlers(mergedHandlers);
  const internalHandlers = {};
  registerGesture(actions, handlers, "onDrag", "drag", internalHandlers, mergedConfig);
  registerGesture(actions, handlers, "onWheel", "wheel", internalHandlers, mergedConfig);
  registerGesture(actions, handlers, "onScroll", "scroll", internalHandlers, mergedConfig);
  registerGesture(actions, handlers, "onPinch", "pinch", internalHandlers, mergedConfig);
  registerGesture(actions, handlers, "onMove", "move", internalHandlers, mergedConfig);
  registerGesture(actions, handlers, "onHover", "hover", internalHandlers, mergedConfig);
  return {
    handlers: internalHandlers,
    config: mergedConfig,
    nativeHandlers
  };
}

// ../../node_modules/.pnpm/@use-gesture+react@10.3.1_react@18.3.1/node_modules/@use-gesture/react/dist/use-gesture-react.esm.js
function useRecognizers(handlers, config = {}, gestureKey, nativeHandlers) {
  const ctrl = React.useMemo(() => new Controller(handlers), []);
  ctrl.applyHandlers(handlers, nativeHandlers);
  ctrl.applyConfig(config, gestureKey);
  React.useEffect(ctrl.effect.bind(ctrl));
  React.useEffect(() => {
    return ctrl.clean.bind(ctrl);
  }, []);
  if (config.target === void 0) {
    return ctrl.bind.bind(ctrl);
  }
  return void 0;
}
function createUseGesture(actions) {
  actions.forEach(registerAction);
  return function useGesture2(_handlers, _config) {
    const {
      handlers,
      nativeHandlers,
      config
    } = parseMergedHandlers(_handlers, _config || {});
    return useRecognizers(handlers, config, void 0, nativeHandlers);
  };
}
function useGesture(handlers, config) {
  const hook = createUseGesture([dragAction, pinchAction, scrollAction, wheelAction, moveAction, hoverAction]);
  return hook(handlers, config || {});
}

// src/lib/memo.ts
var firstMemo = (first, memo, initializer) => {
  if (!first && !memo) {
    throw new Error(
      "Missing memo initialization. You likely forgot to return the result of `firstMemo` in the event function"
    );
  }
  if (first) {
    return initializer();
  }
  return memo;
};

// src/hooks/viewport/useViewportContainer.tsx
var useViewportContainer = ({
  containerRef,
  elementWrapperRef,
  elementRef
}) => {
  const [origin, setOrigin] = useState([0, 0]);
  const { maxZoom, minZoom } = usePdf((state) => state.zoomOptions);
  const zoom = usePdf((state) => state.zoom);
  const viewportRef = usePdf((state) => state.viewportRef);
  const setIsPinching = usePdf((state) => state.setIsPinching);
  const updateZoom = usePdf((state) => state.updateZoom);
  useEffect(() => {
    viewportRef.current = containerRef.current;
  }, [containerRef, viewportRef]);
  const transformations = useRef({
    translateX: 0,
    translateY: 0,
    zoom
  });
  const updateTransform = useCallback(
    (zoomUpdate) => {
      if (!elementRef.current || !containerRef.current || !elementWrapperRef.current) {
        return;
      }
      const { zoom: zoom2, translateX, translateY } = transformations.current;
      elementRef.current.style.transform = `scale3d(${zoom2}, ${zoom2}, 1)`;
      const elementBoundingBox = elementRef.current.getBoundingClientRect();
      const width = elementBoundingBox.width;
      elementWrapperRef.current.style.width = `${width}px`;
      elementWrapperRef.current.style.height = `${elementBoundingBox.height}px`;
      containerRef.current.scrollTop = translateY;
      containerRef.current.scrollLeft = translateX;
      if (zoomUpdate) updateZoom(() => transformations.current.zoom);
    },
    [containerRef, elementRef, elementWrapperRef, updateZoom]
  );
  useEffect(() => {
    if (transformations.current.zoom === zoom || !containerRef.current) {
      return;
    }
    const dZoom = zoom / transformations.current.zoom;
    transformations.current = {
      translateX: containerRef.current.scrollLeft * dZoom,
      translateY: containerRef.current.scrollTop * dZoom,
      zoom
    };
    updateTransform();
  }, [containerRef, zoom]);
  useLayoutEffect(() => {
    updateTransform();
  }, []);
  useEffect(() => {
    const preventDefault = (e) => e.preventDefault();
    document.addEventListener("gesturestart", preventDefault);
    document.addEventListener("gesturechange", preventDefault);
    return () => {
      document.removeEventListener("gesturestart", preventDefault);
      document.removeEventListener("gesturechange", preventDefault);
    };
  });
  useGesture(
    {
      onPinch: ({ origin: origin2, first, movement: [ms], memo }) => {
        const newMemo = firstMemo(first, memo, () => {
          const elementRect = elementRef.current.getBoundingClientRect();
          const containerRect = containerRef.current.getBoundingClientRect();
          const contentPosition = [
            origin2[0] - elementRect.left,
            origin2[1] - elementRect.top
          ];
          const containerPosition = [
            origin2[0] - containerRect.left,
            origin2[1] - containerRect.top
          ];
          setOrigin([
            contentPosition[0] / transformations.current.zoom,
            contentPosition[1] / transformations.current.zoom
          ]);
          return {
            contentPosition,
            containerPosition,
            originZoom: transformations.current.zoom,
            originTranslate: transformations.current.translateY
          };
        });
        const newZoom = clamp(ms * newMemo.originZoom, minZoom, maxZoom);
        const realMs = newZoom / newMemo.originZoom;
        const newTranslateX = newMemo.contentPosition[0] * realMs - newMemo.containerPosition[0];
        const newTranslateY = newMemo.contentPosition[1] * realMs - newMemo.containerPosition[1];
        transformations.current = {
          zoom: newZoom,
          translateX: newTranslateX,
          translateY: newTranslateY
        };
        updateTransform(true);
        return newMemo;
      },
      onPinchStart: () => setIsPinching(true),
      onPinchEnd: () => setIsPinching(false)
    },
    {
      target: containerRef
    }
  );
  return {
    origin
  };
};
var DEFAULT_HEIGHT = 600;
var EXTRA_HEIGHT = 0;
var Pages = ({
  children,
  gap = 10,
  virtualizerOptions = { overscan: 3 },
  initialOffset,
  onOffsetChange,
  ...props
}) => {
  const [tempItems, setTempItems] = useState([]);
  const viewports = usePdf((state) => state.viewports);
  const numPages = usePdf((state) => state.pdfDocumentProxy.numPages);
  const isPinching = usePdf((state) => state.isPinching);
  const elementWrapperRef = useRef(null);
  const elementRef = useRef(null);
  const containerRef = useRef(null);
  useViewportContainer({
    elementRef,
    elementWrapperRef,
    containerRef
  });
  const setVirtualizer = usePdf((state) => state.setVirtualizer);
  const { scrollToFn } = useScrollFn();
  const { observeElementOffset } = useObserveElement();
  const estimateSize = useCallback(
    (index) => {
      if (!viewports || !viewports[index]) return DEFAULT_HEIGHT;
      return viewports[index].height + EXTRA_HEIGHT;
    },
    [viewports]
  );
  const virtualizer = useVirtualizer({
    count: numPages || 0,
    getScrollElement: () => containerRef.current,
    estimateSize,
    observeElementOffset,
    overscan: virtualizerOptions?.overscan ?? 0,
    scrollToFn,
    gap,
    initialOffset
  });
  useEffect(() => {
    if (onOffsetChange && virtualizer.scrollOffset)
      onOffsetChange(virtualizer.scrollOffset);
  }, [virtualizer.scrollOffset, onOffsetChange]);
  useEffect(() => {
    setVirtualizer(virtualizer);
  }, [setVirtualizer, virtualizer]);
  useEffect(() => {
    let timeout;
    const virtualized = virtualizer?.getVirtualItems();
    if (!isPinching) {
      virtualizer?.measure();
      timeout = setTimeout(() => {
        setTempItems([]);
      }, 200);
    } else if (virtualized && virtualized?.length > 0) {
      setTempItems(virtualized);
    }
    return () => {
      clearTimeout(timeout);
    };
  }, [isPinching]);
  const virtualizerItems = virtualizer?.getVirtualItems() ?? [];
  const items = tempItems.length ? tempItems : virtualizerItems;
  useVisiblePage({
    items
  });
  useFitWidth({ viewportRef: containerRef });
  const largestPageWidth = usePdf(
    (state) => Math.max(...state.viewports.map((v) => v.width))
  );
  const zoom = usePdf((state) => state.zoom);
  useEffect(() => {
    virtualizer.getOffsetForAlignment = (toOffset, align, itemSize = 0) => {
      const size = virtualizer.getSize();
      const scrollOffset = virtualizer.getScrollOffset();
      if (align === "auto") {
        align = toOffset >= scrollOffset + size ? "end" : "start";
      }
      if (align === "center") {
        toOffset += (itemSize - size) / 2;
      } else if (align === "end") {
        toOffset -= size;
      }
      const scrollSizeProp = virtualizer.options.horizontal ? "scrollWidth" : "scrollHeight";
      const scrollSize = virtualizer.scrollElement ? "document" in virtualizer.scrollElement ? (
        //@ts-expect-error this is a private stuff
        virtualizer.scrollElement.document.documentElement[scrollSizeProp]
      ) : virtualizer.scrollElement[scrollSizeProp] : 0;
      const maxOffset = scrollSize - size;
      console.log(scrollSize, maxOffset, toOffset);
      return Math.max(toOffset, 0);
    };
  }, [zoom, virtualizer]);
  return /* @__PURE__ */ jsx(
    Primitive.div,
    {
      ref: containerRef,
      ...props,
      style: {
        display: "flex",
        justifyContent: "center",
        height: "100%",
        position: "relative",
        overflow: "auto",
        ...props.style
      },
      children: /* @__PURE__ */ jsx(
        "div",
        {
          ref: elementWrapperRef,
          style: {
            width: "max-content"
          },
          children: /* @__PURE__ */ jsx(
            "div",
            {
              ref: elementRef,
              style: {
                height: `${virtualizer.getTotalSize()}px`,
                position: "absolute",
                display: "flex",
                alignItems: "center",
                flexDirection: "column",
                transformOrigin: "0 0",
                // width: "max-content",
                width: largestPageWidth,
                margin: "0 auto"
              },
              children: items.map((virtualItem) => {
                const innerBoxWidth = viewports && viewports[virtualItem.index] ? viewports[virtualItem.index]?.width : 0;
                if (!innerBoxWidth) return null;
                return /* @__PURE__ */ jsx(
                  "div",
                  {
                    style: {
                      width: innerBoxWidth,
                      height: `0px`
                    },
                    children: /* @__PURE__ */ jsx(
                      "div",
                      {
                        style: {
                          height: `${virtualItem.size}px`,
                          transform: `translateY(${virtualItem.start}px)`
                        },
                        children: cloneElement(children, {
                          key: virtualItem.key,
                          //@ts-expect-error pageNumber is not a valid react key
                          pageNumber: virtualItem.index + 1
                        })
                      }
                    )
                  },
                  virtualItem.key
                );
              })
            }
          )
        }
      )
    }
  );
};
var usePDFDocumentContext = ({
  onDocumentLoad,
  source,
  initialRotation = 0,
  isZoomFitWidth,
  zoom = 1,
  zoomOptions
}) => {
  const [_, setProgress] = useState(0);
  const [initialState, setInitialState] = useState();
  const [rotation] = useState(initialRotation);
  useEffect(() => {
    const generateViewports = async (pdf) => {
      const pageProxies = [];
      const rotations = [];
      const viewports = await Promise.all(
        Array.from({ length: pdf.numPages }, async (_2, index) => {
          const page = await pdf.getPage(index + 1);
          const deltaRotate = page.rotate || 0;
          const viewport = page.getViewport({
            scale: 1,
            rotation: rotation + deltaRotate
          });
          pageProxies.push(page);
          rotations.push(page.rotate);
          return viewport;
        })
      );
      const sortedPageProxies = pageProxies.sort((a, b) => {
        return a.pageNumber - b.pageNumber;
      });
      setInitialState((prev) => ({
        ...prev,
        isZoomFitWidth,
        viewports,
        pageProxies: sortedPageProxies,
        pdfDocumentProxy: pdf,
        zoom,
        zoomOptions
      }));
    };
    const loadDocument = () => {
      setInitialState(null);
      setProgress(0);
      const loadingTask = getDocument(source);
      loadingTask.onProgress = (progressEvent) => {
        if (progressEvent.loaded === progressEvent.total) {
          return;
        }
        setProgress(progressEvent.loaded / progressEvent.total);
      };
      const loadingPromise = loadingTask.promise.then((proxy) => {
        onDocumentLoad?.({ proxy, source });
        setProgress(1);
        generateViewports(proxy);
      }).catch((error) => {
        if (loadingTask.destroyed) {
          return;
        }
        console.error("Error loading PDF document", error);
      });
      return () => {
        loadingPromise.finally(() => loadingTask.destroy());
      };
    };
    loadDocument();
  }, [source]);
  return {
    initialState
  };
};
var Root = forwardRef(
  ({
    children,
    source,
    loader,
    onDocumentLoad,
    isZoomFitWidth,
    zoom,
    zoomOptions,
    ...props
  }, ref) => {
    const { initialState } = usePDFDocumentContext({
      source,
      onDocumentLoad,
      isZoomFitWidth,
      zoom,
      zoomOptions
    });
    return /* @__PURE__ */ jsx(Primitive.div, { ref, ...props, children: initialState ? /* @__PURE__ */ jsx(PDFStore.Provider, { initialValue: initialState, children }) : loader || "Loading..." });
  }
);
Root.displayName = "Root";
var Search = ({ children, loading = "Loading..." }) => {
  const [isLoading, setIsLoading] = useState(false);
  const proxies = usePdf((state) => state.pageProxies);
  const setTextContent = usePdf((state) => state.setTextContent);
  const getTextContent = useCallback(
    async (pages) => {
      setIsLoading(true);
      const promises = pages.map(async (proxy) => {
        const content = await proxy.getTextContent();
        const text2 = content.items.map((item) => item?.str || "").join("");
        return Promise.resolve({
          pageNumber: proxy.pageNumber,
          text: text2
        });
      });
      const text = await Promise.all(promises);
      setIsLoading(false);
      setTextContent(text);
    },
    [setTextContent]
  );
  useEffect(() => {
    getTextContent(proxies);
  }, [proxies, getTextContent]);
  return isLoading ? loading : children;
};
var SelectionTooltip = ({ children }) => {
  const [isOpen, setIsOpen] = useState(false);
  const lastSelectionRef = useRef(null);
  const viewportRef = usePdf((state) => state.viewportRef);
  const { refs, floatingStyles, context } = useFloating({
    placement: "bottom",
    open: isOpen,
    onOpenChange: setIsOpen,
    whileElementsMounted: autoUpdate,
    middleware: [offset(10), shift({ padding: 8 })]
  });
  const dismiss = useDismiss(context);
  const { getFloatingProps } = useInteractions([dismiss]);
  const updateTooltipPosition = useCallback(() => {
    const selection = document.getSelection();
    if (!selection || selection.isCollapsed) {
      setIsOpen(false);
      lastSelectionRef.current = null;
      return;
    }
    const range = selection.getRangeAt(0);
    if (!range) return;
    const rects = range.getClientRects();
    const lastRect = rects[rects.length - 1];
    lastSelectionRef.current = range;
    if (lastRect) {
      refs.setReference({
        getBoundingClientRect: () => ({
          width: lastRect.width,
          height: lastRect.height,
          x: lastRect.left,
          y: lastRect.bottom,
          // Position below the last line of selection
          top: lastRect.bottom,
          right: lastRect.right,
          bottom: lastRect.bottom + lastRect.height,
          left: lastRect.left
        }),
        getClientRects: () => [lastRect]
      });
      setIsOpen(true);
    } else {
      setIsOpen(false);
    }
  }, [refs]);
  useEffect(() => {
    const handleSelectionChange = () => {
      const selection = document.getSelection();
      if (selection && viewportRef.current?.contains(selection.anchorNode)) {
        requestAnimationFrame(updateTooltipPosition);
      } else {
        setIsOpen(false);
      }
    };
    const handleScroll = () => {
      if (!isOpen || !lastSelectionRef.current) return;
      requestAnimationFrame(updateTooltipPosition);
    };
    document.addEventListener("selectionchange", handleSelectionChange);
    if (viewportRef.current) {
      viewportRef.current.addEventListener("scroll", handleScroll, {
        passive: true
      });
    }
    return () => {
      document.removeEventListener("selectionchange", handleSelectionChange);
      if (viewportRef.current) {
        viewportRef.current.removeEventListener("scroll", handleScroll);
      }
    };
  }, [refs, isOpen, viewportRef, updateTooltipPosition]);
  useEffect(() => {
    const handleFloatingClick = (e) => {
      if (refs.floating.current?.contains(e.target)) {
        e.stopPropagation();
      }
    };
    document.addEventListener("click", handleFloatingClick);
    return () => document.removeEventListener("click", handleFloatingClick);
  }, [refs.floating]);
  return /* @__PURE__ */ jsx(Fragment, { children: isOpen && /* @__PURE__ */ jsx(
    "div",
    {
      ref: refs.setFloating,
      style: {
        ...floatingStyles
      },
      ...getFloatingProps(),
      children
    }
  ) });
};
var DEFAULT_CONFIG = {
  maxHeight: 800,
  maxWidth: 400
};
var useThumbnail = (pageNumber, config = {}) => {
  const {
    maxHeight = DEFAULT_CONFIG.maxHeight,
    maxWidth = DEFAULT_CONFIG.maxWidth,
    isFirstPage = false
  } = config;
  const containerRef = useRef(null);
  const canvasRef = useRef(null);
  const renderTaskRef = useRef(null);
  const pageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
  const { visible } = useVisibility({ elementRef: containerRef });
  const [debouncedVisible] = useDebounce(visible, 50);
  const dpr = useDpr();
  const isVisible = isFirstPage || debouncedVisible;
  useEffect(() => {
    const renderThumbnail = async () => {
      const canvas = canvasRef.current;
      if (!canvas || !pageProxy) return;
      try {
        if (renderTaskRef.current) {
          renderTaskRef.current.cancel();
        }
        const viewport = pageProxy.getViewport({ scale: 1 });
        const scale = Math.min(maxWidth / viewport.width, maxHeight / viewport.height) * (isVisible ? dpr : 0.5);
        const scaledViewport = pageProxy.getViewport({ scale });
        canvas.width = scaledViewport.width;
        canvas.height = scaledViewport.height;
        const context = canvas.getContext("2d");
        if (!context) return;
        const renderTask = pageProxy.render({
          canvasContext: context,
          viewport: scaledViewport
        });
        renderTaskRef.current = renderTask;
        await renderTask.promise;
      } catch (error) {
        if (error instanceof Error && error.name === "RenderingCancelledException") {
          console.log("Rendering cancelled");
        } else {
          console.error("Failed to render PDF page:", error);
        }
      }
    };
    renderThumbnail();
    return () => {
      renderTaskRef.current?.cancel();
    };
  }, [pageNumber, pageProxy, isVisible, dpr, maxHeight, maxWidth]);
  return {
    canvasRef,
    containerRef,
    isVisible
  };
};
var Thumbnail = ({
  pageNumber = 1,
  ...props
}) => {
  const { canvasRef, containerRef, isVisible } = useThumbnail(pageNumber, {
    isFirstPage: pageNumber < 5
  });
  const { jumpToPage } = usePdfJump();
  return /* @__PURE__ */ jsx("div", { ref: containerRef, style: { minHeight: "150px", minWidth: "10px" }, children: isVisible && /* @__PURE__ */ jsx(
    Primitive.canvas,
    {
      ...props,
      role: "button",
      tabIndex: 0,
      onClick: (e) => {
        if (props.onClick) {
          props.onClick(e);
        }
        jumpToPage(pageNumber, { behavior: "auto" });
      },
      onKeyDown: (e) => {
        if (props.onKeyDown) {
          props.onKeyDown(e);
        }
        if (e.key === "Enter") {
          jumpToPage(pageNumber, { behavior: "auto" });
        }
      },
      ref: canvasRef
    }
  ) });
};
var Thumbnails = ({
  children,
  ...props
}) => {
  const pageCount = usePdf((state) => state.pdfDocumentProxy.numPages);
  return /* @__PURE__ */ jsx(Primitive.div, { ...props, children: Array.from({
    length: pageCount
  }).map((_, index) => {
    return cloneElement(children, { key: index, pageNumber: index + 1 });
  }) });
};
var ZoomIn = ({ ...props }) => {
  const setZoom = usePdf((state) => state.updateZoom);
  return /* @__PURE__ */ jsx(
    Primitive.button,
    {
      ...props,
      onClick: (e) => {
        props.onClick && props.onClick(e);
        setZoom((zoom) => Number((zoom + 0.1).toFixed(1)));
      }
    }
  );
};
var ZoomOut = ({ ...props }) => {
  const setZoom = usePdf((state) => state.updateZoom);
  return /* @__PURE__ */ jsx(
    Primitive.button,
    {
      ...props,
      onClick: (e) => {
        props.onClick && props.onClick(e);
        setZoom((zoom) => Number((zoom - 0.1).toFixed(1)));
      }
    }
  );
};
var CurrentZoom = ({ ...props }) => {
  const setRealZoom = usePdf((state) => state.updateZoom);
  const realZoom = usePdf((state) => state.zoom);
  const [zoom, setZoom] = useState((realZoom * 100).toFixed(0));
  const isSelected = useRef(false);
  useEffect(() => {
    if (isSelected.current) {
      return;
    }
    setZoom((realZoom * 100).toFixed(0));
  }, [realZoom]);
  return /* @__PURE__ */ jsx(
    "input",
    {
      ...props,
      value: zoom,
      onClick: () => isSelected.current = true,
      onChange: (e) => {
        setRealZoom(Number(e.target.value) / 100);
        setZoom(e.target.value);
      },
      onBlur: () => {
        isSelected.current = false;
        setZoom((realZoom * 100).toFixed(0));
      }
    }
  );
};
function levenshteinDistance(a, b) {
  const matrix = [];
  for (let i = 0; i <= b.length; i++) {
    matrix[i] = [i];
  }
  for (let j = 0; j <= a.length; j++) {
    matrix[0][j] = j;
  }
  for (let i = 1; i <= b.length; i++) {
    for (let j = 1; j <= a.length; j++) {
      if (b.charAt(i - 1) === a.charAt(j - 1)) {
        matrix[i][j] = matrix[i - 1][j - 1];
      } else {
        matrix[i][j] = Math.min(
          matrix[i - 1][j - 1] + 1,
          matrix[i][j - 1] + 1,
          matrix[i - 1][j] + 1
        );
      }
    }
  }
  return matrix[b.length][a.length];
}
var useSearch = () => {
  const textContent = usePdf((state) => state.textContent);
  const [keywords] = useState([]);
  const [searchResults, setSearchResults] = useState({
    exactMatches: [],
    fuzzyMatches: [],
    hasMoreResults: false
  });
  const findExactMatches = (searchText, text, pageNumber, textSize) => {
    const results = [];
    const textLower = text.toLowerCase();
    const searchLower = searchText.toLowerCase();
    let index = 0;
    while (true) {
      const matchIndex = textLower.indexOf(searchLower, index);
      if (matchIndex === -1) break;
      results.push({
        pageNumber,
        text: text.substr(matchIndex, searchText.length + textSize),
        score: 1,
        matchIndex,
        isExactMatch: true
      });
      index = matchIndex + searchText.length;
    }
    return results;
  };
  const findFuzzyMatches = (searchText, text, pageNumber, threshold, excludeIndices, textSize) => {
    const results = [];
    const textLower = text.toLowerCase();
    const searchLower = searchText.toLowerCase();
    let index = 0;
    while (index < textLower.length) {
      if (excludeIndices.has(index)) {
        index++;
        continue;
      }
      const chunk = textLower.substr(index, searchLower.length + 10);
      const distance = levenshteinDistance(
        searchLower,
        chunk.substr(0, searchLower.length)
      );
      const maxDistance = Math.floor(searchLower.length * (1 - threshold));
      if (distance <= maxDistance && distance > 0) {
        const score = 1 - distance / searchLower.length;
        results.push({
          pageNumber,
          text: text.substr(index, searchLower.length + textSize),
          score,
          matchIndex: index,
          isExactMatch: false
        });
        index += searchLower.length;
      } else {
        index++;
      }
    }
    return results;
  };
  const search = useCallback(
    (searchText, options = {}) => {
      const { threshold = 0.7, limit = 10, textSize = 100 } = options;
      if (!searchText.trim()) {
        const emptyResults = {
          exactMatches: [],
          fuzzyMatches: [],
          hasMoreResults: false
        };
        setSearchResults(emptyResults);
        return emptyResults;
      }
      let exactMatches = [];
      let fuzzyMatches = [];
      const exactMatchIndices = /* @__PURE__ */ new Set();
      textContent.forEach(({ pageNumber, text }) => {
        const matches = findExactMatches(
          searchText,
          text,
          pageNumber,
          textSize
        );
        exactMatches = [...exactMatches, ...matches];
        matches.forEach((match) => {
          for (let i = 0; i < searchText.length; i++) {
            exactMatchIndices.add(match.matchIndex + i);
          }
        });
      });
      textContent.forEach(({ pageNumber, text }) => {
        const matches = findFuzzyMatches(
          searchText,
          text,
          pageNumber,
          threshold,
          exactMatchIndices,
          textSize
        );
        fuzzyMatches = [...fuzzyMatches, ...matches];
      });
      exactMatches.sort((a, b) => b.score - a.score);
      fuzzyMatches.sort((a, b) => b.score - a.score);
      const exactLimit = Math.min(exactMatches.length, Math.ceil(limit / 2));
      const fuzzyLimit = Math.min(fuzzyMatches.length, limit - exactLimit);
      const limitedResults = {
        exactMatches: exactMatches.slice(0, exactLimit),
        fuzzyMatches: fuzzyMatches.slice(0, fuzzyLimit),
        hasMoreResults: exactMatches.length + fuzzyMatches.length > limit
      };
      setSearchResults(limitedResults);
      return limitedResults;
    },
    [textContent]
  );
  return {
    textContent,
    keywords,
    searchResults,
    search
  };
};

// src/hooks/search/useSearchPosition.tsx
async function calculateHighlightRects(pageProxy, textMatch) {
  const textContent = await pageProxy.getTextContent();
  const items = textContent.items;
  const matchLength = textMatch.text.length;
  const matchRects = [];
  let currentIndex = 0;
  let remainingMatchLength = matchLength;
  let foundStart = false;
  const viewport = pageProxy.getViewport({ scale: 1 });
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (!item) continue;
    const itemLength = item.str.length;
    if (!foundStart && currentIndex <= textMatch.matchIndex && textMatch.matchIndex < currentIndex + itemLength) {
      foundStart = true;
      const matchStartInItem = textMatch.matchIndex - currentIndex;
      const matchLengthInItem = Math.min(
        itemLength - matchStartInItem,
        remainingMatchLength
      );
      const transform = item.transform;
      const y = viewport.height - (transform[5] + item.height);
      const rect = {
        pageNumber: textMatch.pageNumber,
        left: transform[4] + matchStartInItem * (item.width / itemLength),
        top: y,
        width: matchLengthInItem * (item.width / itemLength),
        height: item.height
      };
      matchRects.push(rect);
      remainingMatchLength -= matchLengthInItem;
    } else if (foundStart && remainingMatchLength > 0) {
      const matchLengthInItem = Math.min(itemLength, remainingMatchLength);
      const transform = item.transform;
      const y = viewport.height - (transform[5] + item.height);
      const rect = {
        pageNumber: textMatch.pageNumber,
        left: transform[4],
        top: y,
        width: matchLengthInItem * (item.width / itemLength),
        height: item.height
      };
      matchRects.push(rect);
      remainingMatchLength -= matchLengthInItem;
    }
    if (remainingMatchLength <= 0 && foundStart) {
      break;
    }
    currentIndex += itemLength;
  }
  return mergeAdjacentRects(matchRects);
}
function mergeAdjacentRects(rects) {
  if (rects.length <= 1) return rects;
  const merged = [];
  let current = rects[0];
  if (!current) return rects;
  for (let i = 1; i < rects.length; i++) {
    const next = rects[i];
    if (!next) continue;
    if (Math.abs(current.top - next.top) < 2 && Math.abs(current.height - next.height) < 2) {
      current = {
        ...current,
        width: next.left + next.width - current.left
      };
    } else {
      merged.push(current);
      current = next;
    }
  }
  merged.push(current);
  return merged;
}

// src/hooks/useSelectionDimensions.tsx
var MERGE_THRESHOLD = 5;
var shouldMergeRects = (rect1, rect2) => {
  const verticalOverlap = !(rect1.top > rect2.top + rect2.height || rect2.top > rect1.top + rect1.height);
  const horizontallyClose = Math.abs(rect1.left + rect1.width - rect2.left) < MERGE_THRESHOLD || Math.abs(rect2.left + rect2.width - rect1.left) < MERGE_THRESHOLD || rect1.left < rect2.left + rect2.width && rect2.left < rect1.left + rect1.width;
  return verticalOverlap && horizontallyClose;
};
var mergeRects = (rect1, rect2) => {
  return {
    left: Math.min(rect1.left, rect2.left),
    top: Math.min(rect1.top, rect2.top),
    width: Math.max(rect1.left + rect1.width, rect2.left + rect2.width) - Math.min(rect1.left, rect2.left),
    height: Math.max(rect1.top + rect1.height, rect2.top + rect2.height) - Math.min(rect1.top, rect2.top),
    pageNumber: rect1.pageNumber
  };
};
var consolidateRects = (rects) => {
  if (rects.length <= 1) return rects;
  const sortedRects = [...rects].sort((a, b) => a.top - b.top);
  let hasChanges;
  do {
    hasChanges = false;
    let currentRect = sortedRects[0];
    const tempResult = [];
    for (let i = 1; i < sortedRects.length; i++) {
      const sorted = sortedRects[i];
      if (!currentRect || !sorted) continue;
      if (shouldMergeRects(currentRect, sorted)) {
        currentRect = mergeRects(currentRect, sorted);
        hasChanges = true;
      } else {
        tempResult.push(currentRect);
        currentRect = sorted;
      }
    }
    if (currentRect) tempResult.push(currentRect);
    sortedRects.length = 0;
    sortedRects.push(...tempResult);
  } while (hasChanges);
  return sortedRects;
};
var useSelectionDimensions = () => {
  const store = PDFStore.useContext();
  const getDimension = () => {
    const selection = window.getSelection();
    if (!selection || selection.isCollapsed) return;
    const range = selection.getRangeAt(0);
    const highlights = [];
    const textLayerMap = /* @__PURE__ */ new Map();
    const clientRects = Array.from(range.getClientRects()).filter(
      (rect) => rect.width > 2 && rect.height > 2
    );
    clientRects.forEach((clientRect) => {
      const element = document.elementFromPoint(
        clientRect.left + 1,
        clientRect.top + clientRect.height / 2
      );
      const textLayer = element?.closest(".textLayer");
      if (!textLayer) return;
      const pageNumber = parseInt(
        textLayer.getAttribute("data-page-number") || "1",
        10
      );
      const textLayerRect = textLayer.getBoundingClientRect();
      const zoom = store.getState().zoom;
      const rect = {
        width: clientRect.width / zoom,
        height: clientRect.height / zoom,
        top: (clientRect.top - textLayerRect.top) / zoom,
        left: (clientRect.left - textLayerRect.left) / zoom,
        pageNumber
      };
      if (!textLayerMap.has(pageNumber)) {
        textLayerMap.set(pageNumber, []);
      }
      textLayerMap.get(pageNumber)?.push(rect);
    });
    textLayerMap.forEach((rects) => {
      if (rects.length > 0) {
        highlights.push(...consolidateRects(rects));
      }
    });
    return {
      highlights: highlights.sort((a, b) => a.pageNumber - b.pageNumber),
      text: range.toString().trim(),
      isCollapsed: false
    };
  };
  return { getDimension };
};

export { AnnotationLayer2 as AnnotationLayer, CanvasLayer, CurrentPage, CurrentZoom, CustomLayer, HighlightLayer, LinkService, NextPage, Outline, OutlineChildItems, OutlineItem, Page, Pages, PreviousPage, Root, Search, SelectionTooltip, TextLayer2 as TextLayer, Thumbnail, Thumbnails, TotalPages, ZoomIn, ZoomOut, calculateHighlightRects, usePdf, usePdfJump, useSearch, useSelectionDimensions };