{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/text-selection.tsx","../../src/shared/components/marquee-selection.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts","../../src/shared/components/selection-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype TextSelectionProps = {\n  documentId: string;\n  pageIndex: number;\n  scale?: number;\n  rotation?: Rotation;\n  /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */\n  background?: string;\n  selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * TextSelection renders text selection highlight rects and the selection menu.\n * It registers the text selection handler on the page and subscribes to menu\n * placement changes.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport function TextSelection({\n  documentId,\n  pageIndex,\n  scale: scaleOverride,\n  rotation: rotationOverride,\n  background = 'rgba(33,150,243)',\n  selectionMenu,\n}: TextSelectionProps) {\n  const { plugin: selPlugin } = useSelectionPlugin();\n  const documentState = useDocumentState(documentId);\n  const page = documentState?.document?.pages?.[pageIndex];\n  const [rects, setRects] = useState<Rect[]>([]);\n  const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n  // Store the placement object from the plugin\n  const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n  useEffect(() => {\n    if (!selPlugin || !documentId) return;\n\n    return selPlugin.registerSelectionOnPage({\n      documentId,\n      pageIndex,\n      onRectsChange: ({ rects, boundingRect }) => {\n        setRects(rects);\n        setBoundingRect(boundingRect);\n      },\n    });\n  }, [selPlugin, documentId, pageIndex]);\n\n  useEffect(() => {\n    if (!selPlugin || !documentId) return;\n\n    // Subscribe to menu placement changes for this specific document\n    return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n      setPlacement(newPlacement);\n    });\n  }, [selPlugin, documentId]);\n\n  const actualScale = useMemo(() => {\n    if (scaleOverride !== undefined) return scaleOverride;\n    return documentState?.scale ?? 1;\n  }, [scaleOverride, documentState?.scale]);\n\n  const actualRotation = useMemo(() => {\n    if (rotationOverride !== undefined) return rotationOverride;\n    // Combine page intrinsic rotation with document rotation\n    const pageRotation = page?.rotation ?? 0;\n    const docRotation = documentState?.rotation ?? 0;\n    return ((pageRotation + docRotation) % 4) as Rotation;\n  }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n  const shouldRenderMenu =\n    selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n  if (!boundingRect) return null;\n\n  return (\n    <>\n      <div\n        style={{\n          position: 'absolute',\n          left: boundingRect.origin.x * actualScale,\n          top: boundingRect.origin.y * actualScale,\n          width: boundingRect.size.width * actualScale,\n          height: boundingRect.size.height * actualScale,\n          mixBlendMode: 'multiply',\n          isolation: 'isolate',\n          pointerEvents: 'none',\n        }}\n      >\n        {rects.map((b, i) => (\n          <div\n            key={i}\n            style={{\n              position: 'absolute',\n              left: (b.origin.x - boundingRect.origin.x) * actualScale,\n              top: (b.origin.y - boundingRect.origin.y) * actualScale,\n              width: b.size.width * actualScale,\n              height: b.size.height * actualScale,\n              background,\n            }}\n          />\n        ))}\n      </div>\n      {shouldRenderMenu && (\n        <CounterRotate\n          rect={{\n            origin: {\n              x: placement.rect.origin.x * actualScale,\n              y: placement.rect.origin.y * actualScale,\n            },\n            size: {\n              width: placement.rect.size.width * actualScale,\n              height: placement.rect.size.height * actualScale,\n            },\n          }}\n          rotation={actualRotation}\n        >\n          {(props) =>\n            selectionMenu({\n              ...props,\n              context: {\n                type: 'selection',\n                pageIndex,\n              },\n              selected: true,\n              placement,\n            })\n          }\n        </CounterRotate>\n      )}\n    </>\n  );\n}\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n  /** Document ID */\n  documentId: string;\n  /** Index of the page this layer lives on */\n  pageIndex: number;\n  /** Scale of the page (optional, defaults to document scale) */\n  scale?: number;\n  /** Optional CSS class applied to the marquee rectangle */\n  className?: string;\n  /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */\n  background?: string;\n  /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */\n  borderColor?: string;\n  /** Border style. Default: 'dashed' */\n  borderStyle?: 'solid' | 'dashed' | 'dotted';\n  /**\n   * @deprecated Use `borderColor` instead.\n   */\n  stroke?: string;\n  /**\n   * @deprecated Use `background` instead.\n   */\n  fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * It registers the marquee handler on the page.\n *\n * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport const MarqueeSelection = ({\n  documentId,\n  pageIndex,\n  scale,\n  className,\n  background,\n  borderColor,\n  borderStyle = 'dashed',\n  stroke,\n  fill,\n}: MarqueeSelectionProps) => {\n  const { plugin: selPlugin } = useSelectionPlugin();\n  const documentState = useDocumentState(documentId);\n  const [rect, setRect] = useState<Rect | null>(null);\n\n  // Resolve deprecated props: new CSS-standard props take precedence\n  const resolvedBorderColor = borderColor ?? stroke ?? 'rgba(0,122,204,0.8)';\n  const resolvedBackground = background ?? fill ?? 'rgba(0,122,204,0.15)';\n\n  const actualScale = useMemo(() => {\n    if (scale !== undefined) return scale;\n    return documentState?.scale ?? 1;\n  }, [scale, documentState?.scale]);\n\n  useEffect(() => {\n    if (!selPlugin || !documentId) return;\n\n    return selPlugin.registerMarqueeOnPage({\n      documentId,\n      pageIndex,\n      scale: actualScale,\n      onRectChange: setRect,\n    });\n  }, [selPlugin, documentId, pageIndex, actualScale]);\n\n  if (!rect) return null;\n\n  return (\n    <div\n      style={{\n        position: 'absolute',\n        pointerEvents: 'none',\n        left: rect.origin.x * actualScale,\n        top: rect.origin.y * actualScale,\n        width: rect.size.width * actualScale,\n        height: rect.size.height * actualScale,\n        border: `1px ${borderStyle} ${resolvedBorderColor}`,\n        background: resolvedBackground,\n        boxSizing: 'border-box',\n        zIndex: 1000,\n      }}\n      className={className}\n    />\n  );\n};\n","import { useEffect } from '@framework';\n\nimport { useSelectionCapability } from '../hooks';\n\nexport function CopyToClipboard() {\n  const { provides: sel } = useSelectionCapability();\n\n  useEffect(() => {\n    if (!sel) return;\n    return sel.onCopyToClipboard(({ text }) => {\n      navigator.clipboard.writeText(text);\n    });\n  }, [sel]);\n\n  return null;\n}\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n  .addUtility(CopyToClipboard)\n  .build();\n","import { Fragment } from '@framework';\nimport { Rotation } from '@embedpdf/models';\nimport { TextSelectionStyle, MarqueeSelectionStyle } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { TextSelection } from './text-selection';\nimport { MarqueeSelection } from './marquee-selection';\n\ntype Props = {\n  documentId: string;\n  pageIndex: number;\n  scale?: number;\n  rotation?: Rotation;\n  /**\n   * @deprecated Use `textStyle.background` instead.\n   */\n  background?: string;\n  /** Styling options for text selection highlights */\n  textStyle?: TextSelectionStyle;\n  /** Styling options for the marquee selection rectangle */\n  marqueeStyle?: MarqueeSelectionStyle;\n  /** Optional CSS class applied to the marquee rectangle */\n  marqueeClassName?: string;\n  selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * SelectionLayer is a convenience component that composes both text selection\n * and marquee selection on a single page.\n *\n * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`\n * individually.\n */\nexport function SelectionLayer({\n  documentId,\n  pageIndex,\n  scale,\n  rotation,\n  background,\n  textStyle,\n  marqueeStyle,\n  marqueeClassName,\n  selectionMenu,\n}: Props) {\n  return (\n    <Fragment>\n      <TextSelection\n        documentId={documentId}\n        pageIndex={pageIndex}\n        scale={scale}\n        rotation={rotation}\n        background={textStyle?.background ?? background}\n        selectionMenu={selectionMenu}\n      />\n      <MarqueeSelection\n        documentId={documentId}\n        pageIndex={pageIndex}\n        scale={scale}\n        background={marqueeStyle?.background}\n        borderColor={marqueeStyle?.borderColor}\n        borderStyle={marqueeStyle?.borderStyle}\n        className={marqueeClassName}\n      />\n    </Fragment>\n  );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","TextSelection","documentId","pageIndex","scale","scaleOverride","rotation","rotationOverride","background","selectionMenu","plugin","selPlugin","documentState","useDocumentState","page","_b","_a","document","pages","rects","setRects","useState","boundingRect","setBoundingRect","placement","setPlacement","useEffect","registerSelectionOnPage","onRectsChange","onMenuPlacement","newPlacement","actualScale","useMemo","actualRotation","shouldRenderMenu","isVisible","jsxs","Fragment","children","jsx","style","position","left","origin","x","top","y","width","size","height","mixBlendMode","isolation","pointerEvents","map","b","i","CounterRotate","rect","props","context","type","selected","MarqueeSelection","className","borderColor","borderStyle","stroke","fill","setRect","resolvedBorderColor","resolvedBackground","registerMarqueeOnPage","onRectChange","border","boxSizing","zIndex","CopyToClipboard","provides","sel","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","textStyle","marqueeStyle","marqueeClassName"],"mappings":"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"}