@embedpdf/plugin-selection 1.0.25 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/types.d.ts +0 -7
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +4 -4
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +4 -4
- package/dist/react/index.js.map +1 -1
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.js +1 -1
- package/dist/vue/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models"),i="selection",n={id:i,name:"Selection Plugin",version:"1.0.0",provides:["selection"],requires:["interaction-manager"],optional:[],defaultConfig:{enabled:!0}},s="CACHE_PAGE_GEOMETRY",o="SET_SELECTION",r="START_SELECTION",a="END_SELECTION",c="CLEAR_SELECTION",h="SET_RECTS",l="SET_SLICES",g="RESET";function d(e,t){return e.rects[t]??[]}function u(e,i){return t.boundingRect(d(e,i))}function p(e,t){for(const i of e.runs){if(!(t.y>=i.rect.y&&t.y<=i.rect.y+i.rect.height&&t.x>=i.rect.x&&t.x<=i.rect.x+i.rect.width))continue;const e=i.glyphs.findIndex((e=>t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height));if(-1!==e)return i.charStart+e}return-1}function y(e,t,i){if(!e||!t)return null;if(i<e.start.page||i>e.end.page)return null;const n=i===e.start.page?e.start.index:0,s=t.runs[t.runs.length-1],o=s.charStart+s.glyphs.length-1;return{from:n,to:i===e.end.page?e.end.index:o}}function f(e,t,i,n=!0){const s=[];for(const o of e.runs){const e=o.charStart,n=e+o.glyphs.length-1;if(n<t||e>i)continue;const r=Math.max(t,e)-e,a=Math.min(i,n)-e;let c=1/0,h=-1/0,l=1/0,g=-1/0,d=0;for(let t=r;t<=a;t++){const e=o.glyphs[t];2!==e.flags&&(c=Math.min(c,e.x),h=Math.max(h,e.x+e.width),l=Math.min(l,e.y),g=Math.max(g,e.y+e.height),d++)}c!==1/0&&d>0&&s.push({rect:{origin:{x:c,y:l},size:{width:h-c,height:g-l}},charCount:d})}return n?E(s):s.map((e=>e.rect))}function x(e,t){const i=Math.min(e.origin.x,t.origin.x),n=Math.min(e.origin.y,t.origin.y);return{origin:{x:i,y:n},size:{width:Math.max(e.origin.x+e.size.width,t.origin.x+t.size.width)-i,height:Math.max(e.origin.y+e.size.height,t.origin.y+t.size.height)-n}}}function m(e,t){const i=Math.max(e.origin.x,t.origin.x),n=Math.max(e.origin.y,t.origin.y),s=Math.min(e.origin.x+e.size.width,t.origin.x+t.size.width),o=Math.min(e.origin.y+e.size.height,t.origin.y+t.size.height);return{origin:{x:i,y:n},size:{width:Math.max(0,s-i),height:Math.max(0,o-n)}}}function S(e){return e.size.width<=0||e.size.height<=0}function C(e,t){if(S(e)||S(t))return 0;const i=x(e,t);if(i.size.height===e.size.height||i.size.height===t.size.height)return 1;return m(e,t).size.height/i.size.height}function b(e,t){const i=e.rect,n=t.rect;if(C(i,n)<.8)return!1;const s=1*i.size.width/e.charCount,o=1*n.size.width/t.charCount,r=i.origin.x-s,a=i.origin.x+i.size.width+s,c=n.origin.x-o;return r<n.origin.x+n.size.width+o&&a>c}function E(e){const t=[];let i=null,n=null;for(const s of e)i&&n?b(i,s)?n=x(n,s.rect):(t.push(n),n=s.rect):n=s.rect,i=s;return n&&!S(n)&&t.push(n),t}const M=class extends e.BasePlugin{constructor(i,n){var s;super(i,n),this.enabledModes=new Set(["pointerMode"]),this.selecting=!1,this.pageCallbacks=new Map,this.selChange$=e.createBehaviorEmitter(),this.textRetrieved$=e.createBehaviorEmitter(),this.copyToClipboard$=e.createEmitter(),this.beginSelection$=e.createEmitter(),this.endSelection$=e.createEmitter(),this.interactionManagerCapability=null==(s=this.registry.getPlugin("interaction-manager"))?void 0:s.provides(),this.coreStore.onAction(e.SET_DOCUMENT,(e=>{this.dispatch({type:g}),this.notifyAllPages()})),this.coreStore.onAction(e.REFRESH_PAGES,(e=>{const i=e.payload.map((e=>this.getNewPageGeometryAndCache(e)));t.Task.all(i).wait((()=>{e.payload.forEach((e=>{this.notifyPage(e)}))}),t.ignore)}))}async initialize(){}async destroy(){this.selChange$.clear()}buildCapability(){return{
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models"),i="selection",n={id:i,name:"Selection Plugin",version:"1.0.0",provides:["selection"],requires:["interaction-manager"],optional:[],defaultConfig:{enabled:!0}},s="CACHE_PAGE_GEOMETRY",o="SET_SELECTION",r="START_SELECTION",a="END_SELECTION",c="CLEAR_SELECTION",h="SET_RECTS",l="SET_SLICES",g="RESET";function d(e,t){return e.rects[t]??[]}function u(e,i){return t.boundingRect(d(e,i))}function p(e,t){for(const i of e.runs){if(!(t.y>=i.rect.y&&t.y<=i.rect.y+i.rect.height&&t.x>=i.rect.x&&t.x<=i.rect.x+i.rect.width))continue;const e=i.glyphs.findIndex((e=>t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height));if(-1!==e)return i.charStart+e}return-1}function y(e,t,i){if(!e||!t)return null;if(i<e.start.page||i>e.end.page)return null;const n=i===e.start.page?e.start.index:0,s=t.runs[t.runs.length-1],o=s.charStart+s.glyphs.length-1;return{from:n,to:i===e.end.page?e.end.index:o}}function f(e,t,i,n=!0){const s=[];for(const o of e.runs){const e=o.charStart,n=e+o.glyphs.length-1;if(n<t||e>i)continue;const r=Math.max(t,e)-e,a=Math.min(i,n)-e;let c=1/0,h=-1/0,l=1/0,g=-1/0,d=0;for(let t=r;t<=a;t++){const e=o.glyphs[t];2!==e.flags&&(c=Math.min(c,e.x),h=Math.max(h,e.x+e.width),l=Math.min(l,e.y),g=Math.max(g,e.y+e.height),d++)}c!==1/0&&d>0&&s.push({rect:{origin:{x:c,y:l},size:{width:h-c,height:g-l}},charCount:d})}return n?E(s):s.map((e=>e.rect))}function x(e,t){const i=Math.min(e.origin.x,t.origin.x),n=Math.min(e.origin.y,t.origin.y);return{origin:{x:i,y:n},size:{width:Math.max(e.origin.x+e.size.width,t.origin.x+t.size.width)-i,height:Math.max(e.origin.y+e.size.height,t.origin.y+t.size.height)-n}}}function m(e,t){const i=Math.max(e.origin.x,t.origin.x),n=Math.max(e.origin.y,t.origin.y),s=Math.min(e.origin.x+e.size.width,t.origin.x+t.size.width),o=Math.min(e.origin.y+e.size.height,t.origin.y+t.size.height);return{origin:{x:i,y:n},size:{width:Math.max(0,s-i),height:Math.max(0,o-n)}}}function S(e){return e.size.width<=0||e.size.height<=0}function C(e,t){if(S(e)||S(t))return 0;const i=x(e,t);if(i.size.height===e.size.height||i.size.height===t.size.height)return 1;return m(e,t).size.height/i.size.height}function b(e,t){const i=e.rect,n=t.rect;if(C(i,n)<.8)return!1;const s=1*i.size.width/e.charCount,o=1*n.size.width/t.charCount,r=i.origin.x-s,a=i.origin.x+i.size.width+s,c=n.origin.x-o;return r<n.origin.x+n.size.width+o&&a>c}function E(e){const t=[];let i=null,n=null;for(const s of e)i&&n?b(i,s)?n=x(n,s.rect):(t.push(n),n=s.rect):n=s.rect,i=s;return n&&!S(n)&&t.push(n),t}const M=class extends e.BasePlugin{constructor(i,n){var s;super(i,n),this.enabledModes=new Set(["pointerMode"]),this.selecting=!1,this.pageCallbacks=new Map,this.selChange$=e.createBehaviorEmitter(),this.textRetrieved$=e.createBehaviorEmitter(),this.copyToClipboard$=e.createEmitter(),this.beginSelection$=e.createEmitter(),this.endSelection$=e.createEmitter(),this.interactionManagerCapability=null==(s=this.registry.getPlugin("interaction-manager"))?void 0:s.provides(),this.coreStore.onAction(e.SET_DOCUMENT,(e=>{this.dispatch({type:g}),this.notifyAllPages()})),this.coreStore.onAction(e.REFRESH_PAGES,(e=>{const i=e.payload.map((e=>this.getNewPageGeometryAndCache(e)));t.Task.all(i).wait((()=>{e.payload.forEach((e=>{this.notifyPage(e)}))}),t.ignore)}))}async initialize(){}async destroy(){this.selChange$.clear()}buildCapability(){return{getFormattedSelection:()=>function(e){const t=[],i=Object.keys(e.rects).map(Number);for(const n of i){const i=e.rects[n]||[];if(0===i.length)continue;const s=u(e,n);s&&t.push({pageIndex:n,rect:s,segmentRects:i})}return t}(this.state),getFormattedSelectionForPage:e=>function(e,t){const i=e.rects[t]||[];if(0===i.length)return null;const n=u(e,t);return n?{pageIndex:t,rect:n,segmentRects:i}:null}(this.state,e),getHighlightRectsForPage:e=>d(this.state,e),getHighlightRects:()=>this.state.rects,getBoundingRectForPage:e=>u(this.state,e),getBoundingRects:()=>function(e){const i=[],n=e.rects;for(const s in n){const e=Number(s),o=t.boundingRect(n[e]);o&&i.push({page:e,rect:o})}return i}(this.state),onCopyToClipboard:this.copyToClipboard$.on,onSelectionChange:this.selChange$.on,onTextRetrieved:this.textRetrieved$.on,onBeginSelection:this.beginSelection$.on,onEndSelection:this.endSelection$.on,getSelectedText:()=>this.getSelectedText(),copyToClipboard:()=>this.copyToClipboard(),enableForMode:e=>this.enabledModes.add(e),isEnabledForMode:e=>this.enabledModes.has(e),getState:()=>this.state}}registerSelectionOnPage(e){if(!this.interactionManagerCapability)return this.logger.warn("SelectionPlugin","MissingDependency","Interaction manager plugin not loaded, text selection disabled"),()=>{};const{pageIndex:i,onRectsChange:n}=e;this.pageCallbacks.set(i,n);const s=this.getOrLoadGeometry(i);n({rects:d(this.state,i),boundingRect:u(this.state,i)});const o={onPointerDown:(e,t,n)=>{if(!this.enabledModes.has(n))return;this.clearSelection();const s=this.state.geometry[i];if(s){const t=p(s,e);-1!==t&&this.beginSelection(i,t)}},onPointerMove:(e,t,n)=>{var s,o;if(!this.enabledModes.has(n))return;const r=this.state.geometry[i];if(r){const t=p(r,e);-1!==t?null==(s=this.interactionManagerCapability)||s.setCursor("selection-text","text",10):null==(o=this.interactionManagerCapability)||o.removeCursor("selection-text"),this.selecting&&-1!==t&&this.updateSelection(i,t)}},onPointerUp:(e,t,i)=>{this.enabledModes.has(i)&&this.endSelection()},onHandlerActiveEnd:e=>{this.enabledModes.has(e)&&this.clearSelection()}},r=this.interactionManagerCapability.registerAlways({scope:{type:"page",pageIndex:i},handlers:o});return()=>{r(),this.pageCallbacks.delete(i),s.abort({code:t.PdfErrorCode.Cancelled,message:"Cleanup"})}}notifyPage(e){var t;const i=this.pageCallbacks.get(e);if(i){i("pointerMode"===(null==(t=this.interactionManagerCapability)?void 0:t.getActiveMode())?{rects:d(this.state,e),boundingRect:u(this.state,e)}:{rects:[],boundingRect:null})}}notifyAllPages(){this.pageCallbacks.forEach(((e,t)=>{this.notifyPage(t)}))}getNewPageGeometryAndCache(e){if(!this.coreState.core.document)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Doc Not Found"});const i=this.coreState.core.document.pages.find((t=>t.index===e)),n=this.engine.getPageGeometry(this.coreState.core.document,i);return n.wait((t=>{this.dispatch(((e,t)=>({type:s,payload:{page:e,geo:t}}))(e,t))}),t.ignore),n}getOrLoadGeometry(e){const i=this.state.geometry[e];return i?t.PdfTaskHelper.resolve(i):this.getNewPageGeometryAndCache(e)}beginSelection(e,t){this.selecting=!0,this.anchor={page:e,index:t},this.dispatch({type:r}),this.beginSelection$.emit({page:e,index:t})}endSelection(){this.selecting=!1,this.anchor=void 0,this.dispatch({type:a}),this.endSelection$.emit()}clearSelection(){this.selecting=!1,this.anchor=void 0,this.dispatch({type:c}),this.selChange$.emit(null),this.notifyAllPages()}updateSelection(e,t){if(!this.selecting||!this.anchor)return;const i=this.anchor,n=e>i.page||e===i.page&&t>=i.index,s={start:n?i:{page:e,index:t},end:n?{page:e,index:t}:i};this.dispatch({type:o,payload:s}),this.updateRectsAndSlices(s),this.selChange$.emit(s);for(let o=s.start.page;o<=s.end.page;o++)this.notifyPage(o)}updateRectsAndSlices(e){const t={},i={};for(let n=e.start.page;n<=e.end.page;n++){const s=this.state.geometry[n],o=y(e,s,n);o&&(t[n]=f(s,o.from,o.to),i[n]={start:o.from,count:o.to-o.from+1})}this.dispatch((e=>({type:h,payload:e}))(t)),this.dispatch({type:l,payload:i})}getSelectedText(){if(!this.coreState.core.document||!this.state.selection)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Doc Not Found or No Selection"});const e=this.state.selection,i=[];for(let t=e.start.page;t<=e.end.page;t++){const e=this.state.slices[t];e&&i.push({pageIndex:t,charIndex:e.start,charCount:e.count})}if(0===i.length)return t.PdfTaskHelper.resolve([]);const n=this.engine.getTextSlices(this.coreState.core.document,i);return n.wait((e=>{this.textRetrieved$.emit(e)}),t.ignore),n}copyToClipboard(){this.getSelectedText().wait((e=>{this.copyToClipboard$.emit(e.join("\n"))}),t.ignore)}};M.id="selection";let P=M;const T={geometry:{},rects:{},slices:{},selection:null,active:!1,selecting:!1},w={manifest:n,create:e=>new P(i,e),reducer:(e=T,t)=>{switch(t.type){case s:{const{page:i,geo:n}=t.payload;return{...e,geometry:{...e.geometry,[i]:n}}}case o:return{...e,selection:t.payload,active:!0};case r:return{...e,selecting:!0,selection:null,rects:{}};case a:return{...e,selecting:!1};case c:return{...e,selecting:!1,selection:null,rects:{},active:!1};case h:return{...e,rects:t.payload};case l:return{...e,slices:t.payload};case g:return T;default:return e}},initialState:T};exports.SELECTION_PLUGIN_ID=i,exports.SelectionPlugin=P,exports.SelectionPluginPackage=w,exports.getVerticalOverlap=C,exports.glyphAt=p,exports.manifest=n,exports.mergeAdjacentRects=E,exports.rectIntersect=m,exports.rectIsEmpty=S,exports.rectUnion=x,exports.rectsWithinSlice=f,exports.shouldMergeHorizontalRects=b,exports.sliceBounds=y;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/utils.ts","../src/lib/selection-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { SelectionPluginConfig } from './types';\n\nexport const SELECTION_PLUGIN_ID = 'selection';\n\nexport const manifest: PluginManifest<SelectionPluginConfig> = {\n id: SELECTION_PLUGIN_ID,\n name: 'Selection Plugin',\n version: '1.0.0',\n provides: ['selection'],\n requires: ['interaction-manager'],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { PdfPageGeometry, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\nexport const CACHE_PAGE_GEOMETRY = 'CACHE_PAGE_GEOMETRY';\nexport const SET_SELECTION = 'SET_SELECTION';\nexport const START_SELECTION = 'START_SELECTION';\nexport const END_SELECTION = 'END_SELECTION';\nexport const CLEAR_SELECTION = 'CLEAR_SELECTION';\nexport const SET_RECTS = 'SET_RECTS';\nexport const SET_SLICES = 'SET_SLICES';\nexport const RESET = 'RESET';\n\nexport interface CachePageGeometryAction extends Action {\n type: typeof CACHE_PAGE_GEOMETRY;\n payload: { page: number; geo: PdfPageGeometry };\n}\nexport interface SetSelectionAction extends Action {\n type: typeof SET_SELECTION;\n payload: SelectionRangeX | null;\n}\n\nexport interface StartSelectionAction extends Action {\n type: typeof START_SELECTION;\n}\n\nexport interface EndSelectionAction extends Action {\n type: typeof END_SELECTION;\n}\n\nexport interface ClearSelectionAction extends Action {\n type: typeof CLEAR_SELECTION;\n}\n\nexport interface SetRectsAction extends Action {\n type: typeof SET_RECTS;\n payload: Record<number, Rect[]>;\n}\n\nexport interface SetSlicesAction extends Action {\n type: typeof SET_SLICES;\n payload: Record<number, { start: number; count: number }>;\n}\n\nexport interface ResetAction extends Action {\n type: typeof RESET;\n}\n\nexport type SelectionAction =\n | CachePageGeometryAction\n | SetSelectionAction\n | StartSelectionAction\n | EndSelectionAction\n | ClearSelectionAction\n | SetRectsAction\n | SetSlicesAction\n | ResetAction;\n\nexport const cachePageGeometry = (page: number, geo: PdfPageGeometry): CachePageGeometryAction => ({\n type: CACHE_PAGE_GEOMETRY,\n payload: { page, geo },\n});\n\nexport const setSelection = (sel: SelectionRangeX): SetSelectionAction => ({\n type: SET_SELECTION,\n payload: sel,\n});\n\nexport const startSelection = (): StartSelectionAction => ({ type: START_SELECTION });\n\nexport const endSelection = (): EndSelectionAction => ({ type: END_SELECTION });\n\nexport const clearSelection = (): ClearSelectionAction => ({ type: CLEAR_SELECTION });\n\nexport const setRects = (allRects: Record<number, Rect[]>): SetRectsAction => ({\n type: SET_RECTS,\n payload: allRects,\n});\n\nexport const setSlices = (\n slices: Record<number, { start: number; count: number }>,\n): SetSlicesAction => ({ type: SET_SLICES, payload: slices });\n\nexport const reset = (): ResetAction => ({ type: RESET });\n","import { Rect, boundingRect } from '@embedpdf/models';\nimport { FormattedSelection, SelectionState } from './types';\n\nexport function selectRectsForPage(state: SelectionState, page: number) {\n return state.rects[page] ?? [];\n}\n\nexport function selectBoundingRectForPage(state: SelectionState, page: number) {\n return boundingRect(selectRectsForPage(state, page));\n}\n\nexport function selectRectsAndBoundingRectForPage(state: SelectionState, page: number) {\n return {\n rects: selectRectsForPage(state, page),\n boundingRect: selectBoundingRectForPage(state, page),\n };\n}\n\nexport function selectBoundingRectsForAllPages(state: SelectionState) {\n const out: { page: number; rect: Rect }[] = [];\n const rectMap = state.rects;\n\n for (const key in rectMap) {\n const page = Number(key);\n const bRect = boundingRect(rectMap[page]);\n if (bRect) out.push({ page, rect: bRect });\n }\n return out;\n}\n\nexport function getFormattedSelectionForPage(\n state: SelectionState,\n page: number,\n): FormattedSelection | null {\n const segmentRects = state.rects[page] || [];\n if (segmentRects.length === 0) return null;\n const boundingRect = selectBoundingRectForPage(state, page);\n if (!boundingRect) return null;\n return { pageIndex: page, rect: boundingRect, segmentRects };\n}\n\nexport function getFormattedSelection(state: SelectionState) {\n const result: FormattedSelection[] = [];\n\n // Get all pages that have rects\n const pages = Object.keys(state.rects).map(Number);\n\n for (const pageIndex of pages) {\n const segmentRects = state.rects[pageIndex] || [];\n\n if (segmentRects.length === 0) continue;\n\n // Calculate bounding rect for this page\n const boundingRect = selectBoundingRectForPage(state, pageIndex);\n\n if (boundingRect) {\n result.push({\n pageIndex,\n rect: boundingRect,\n segmentRects,\n });\n }\n }\n\n return result;\n}\n","import { PdfPageGeometry, Position, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\n/**\n * Hit-test helper using runs\n * @param geo - page geometry\n * @param pt - point\n * @returns glyph index\n */\nexport function glyphAt(geo: PdfPageGeometry, pt: Position) {\n for (const run of geo.runs) {\n const inRun =\n pt.y >= run.rect.y &&\n pt.y <= run.rect.y + run.rect.height &&\n pt.x >= run.rect.x &&\n pt.x <= run.rect.x + run.rect.width;\n\n if (!inRun) continue;\n\n // Simply check if the point is within any glyph's bounding box\n const rel = run.glyphs.findIndex(\n (g) => pt.x >= g.x && pt.x <= g.x + g.width && pt.y >= g.y && pt.y <= g.y + g.height,\n );\n\n if (rel !== -1) {\n return run.charStart + rel;\n }\n }\n return -1;\n}\n\n/**\n * Helper: min/max glyph indices on `page` for current sel\n * @param sel - selection range\n * @param geo - page geometry\n * @param page - page index\n * @returns { from: number; to: number } | null\n */\nexport function sliceBounds(\n sel: SelectionRangeX | null,\n geo: PdfPageGeometry | undefined,\n page: number,\n): { from: number; to: number } | null {\n if (!sel || !geo) return null;\n if (page < sel.start.page || page > sel.end.page) return null;\n\n const from = page === sel.start.page ? sel.start.index : 0;\n\n const lastRun = geo.runs[geo.runs.length - 1];\n const lastCharOnPage = lastRun.charStart + lastRun.glyphs.length - 1;\n\n const to = page === sel.end.page ? sel.end.index : lastCharOnPage;\n\n return { from, to };\n}\n\n/**\n * Helper: build rects for a slice of the page\n * @param geo - page geometry\n * @param from - from index\n * @param to - to index\n * @param merge - whether to merge adjacent rects (default: true)\n * @returns rects\n */\nexport function rectsWithinSlice(\n geo: PdfPageGeometry,\n from: number,\n to: number,\n merge: boolean = true,\n): Rect[] {\n const textRuns: TextRunInfo[] = [];\n\n for (const run of geo.runs) {\n const runStart = run.charStart;\n const runEnd = runStart + run.glyphs.length - 1;\n if (runEnd < from || runStart > to) continue;\n\n const sIdx = Math.max(from, runStart) - runStart;\n const eIdx = Math.min(to, runEnd) - runStart;\n\n let minX = Infinity,\n maxX = -Infinity;\n let minY = Infinity,\n maxY = -Infinity;\n let charCount = 0;\n\n for (let i = sIdx; i <= eIdx; i++) {\n const g = run.glyphs[i];\n if (g.flags === 2) continue; // empty glyph\n\n minX = Math.min(minX, g.x);\n maxX = Math.max(maxX, g.x + g.width);\n minY = Math.min(minY, g.y);\n maxY = Math.max(maxY, g.y + g.height);\n charCount++;\n }\n\n if (minX !== Infinity && charCount > 0) {\n textRuns.push({\n rect: {\n origin: { x: minX, y: minY },\n size: { width: maxX - minX, height: maxY - minY },\n },\n charCount,\n });\n }\n }\n\n // If merge is false, just return the individual rects\n if (!merge) {\n return textRuns.map((run) => run.rect);\n }\n\n // Otherwise merge adjacent rects\n return mergeAdjacentRects(textRuns);\n}\n\n/**\n * ============================================================================\n * Rectangle Merging Algorithm\n * ============================================================================\n *\n * The following code is adapted from Chromium's PDF text selection implementation.\n *\n * Copyright 2010 The Chromium Authors\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file: https://source.chromium.org/chromium/chromium/src/+/main:LICENSE\n *\n * Original source:\n * https://source.chromium.org/chromium/chromium/src/+/main:pdf/pdfium/pdfium_range.cc\n *\n * Adapted for TypeScript and this project's Rect/geometry types.\n */\n\n/**\n * Text run info for rect merging (similar to Chromium's ScreenRectTextRunInfo)\n */\nexport interface TextRunInfo {\n rect: Rect;\n charCount: number;\n}\n\n/**\n * Helper functions for Rect operations\n */\nexport function rectUnion(rect1: Rect, rect2: Rect): Rect {\n const left = Math.min(rect1.origin.x, rect2.origin.x);\n const top = Math.min(rect1.origin.y, rect2.origin.y);\n const right = Math.max(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.max(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n return {\n origin: { x: left, y: top },\n size: { width: right - left, height: bottom - top },\n };\n}\n\nexport function rectIntersect(rect1: Rect, rect2: Rect): Rect {\n const left = Math.max(rect1.origin.x, rect2.origin.x);\n const top = Math.max(rect1.origin.y, rect2.origin.y);\n const right = Math.min(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.min(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n const width = Math.max(0, right - left);\n const height = Math.max(0, bottom - top);\n\n return {\n origin: { x: left, y: top },\n size: { width, height },\n };\n}\n\nexport function rectIsEmpty(rect: Rect): boolean {\n return rect.size.width <= 0 || rect.size.height <= 0;\n}\n\n/**\n * Returns a ratio between [0, 1] representing vertical overlap\n */\nexport function getVerticalOverlap(rect1: Rect, rect2: Rect): number {\n if (rectIsEmpty(rect1) || rectIsEmpty(rect2)) return 0;\n\n const unionRect = rectUnion(rect1, rect2);\n\n if (unionRect.size.height === rect1.size.height || unionRect.size.height === rect2.size.height) {\n return 1.0;\n }\n\n const intersectRect = rectIntersect(rect1, rect2);\n return intersectRect.size.height / unionRect.size.height;\n}\n\n/**\n * Returns true if there is sufficient horizontal and vertical overlap\n */\nexport function shouldMergeHorizontalRects(textRun1: TextRunInfo, textRun2: TextRunInfo): boolean {\n const VERTICAL_OVERLAP_THRESHOLD = 0.8;\n const rect1 = textRun1.rect;\n const rect2 = textRun2.rect;\n\n if (getVerticalOverlap(rect1, rect2) < VERTICAL_OVERLAP_THRESHOLD) {\n return false;\n }\n\n const HORIZONTAL_WIDTH_FACTOR = 1.0;\n const averageWidth1 = (HORIZONTAL_WIDTH_FACTOR * rect1.size.width) / textRun1.charCount;\n const averageWidth2 = (HORIZONTAL_WIDTH_FACTOR * rect2.size.width) / textRun2.charCount;\n\n const rect1Left = rect1.origin.x - averageWidth1;\n const rect1Right = rect1.origin.x + rect1.size.width + averageWidth1;\n const rect2Left = rect2.origin.x - averageWidth2;\n const rect2Right = rect2.origin.x + rect2.size.width + averageWidth2;\n\n return rect1Left < rect2Right && rect1Right > rect2Left;\n}\n\n/**\n * Merge adjacent rectangles based on proximity and overlap (similar to Chromium's algorithm)\n */\nexport function mergeAdjacentRects(textRuns: TextRunInfo[]): Rect[] {\n const results: Rect[] = [];\n let previousTextRun: TextRunInfo | null = null;\n let currentRect: Rect | null = null;\n\n for (const textRun of textRuns) {\n if (previousTextRun && currentRect) {\n if (shouldMergeHorizontalRects(previousTextRun, textRun)) {\n currentRect = rectUnion(currentRect, textRun.rect);\n } else {\n results.push(currentRect);\n currentRect = textRun.rect;\n }\n } else {\n currentRect = textRun.rect;\n }\n previousTextRun = textRun;\n }\n\n if (currentRect && !rectIsEmpty(currentRect)) {\n results.push(currentRect);\n }\n\n return results;\n}\n","import {\n BasePlugin,\n PluginRegistry,\n REFRESH_PAGES,\n SET_DOCUMENT,\n createBehaviorEmitter,\n createEmitter,\n} from '@embedpdf/core';\nimport {\n PdfPageGeometry,\n Rect,\n PdfTask,\n PdfTaskHelper,\n PdfErrorCode,\n ignore,\n PageTextSlice,\n Task,\n Position,\n} from '@embedpdf/models';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nimport {\n cachePageGeometry,\n setSelection,\n SelectionAction,\n endSelection,\n startSelection,\n clearSelection,\n reset,\n setRects,\n setSlices,\n} from './actions';\nimport * as selector from './selectors';\nimport {\n SelectionCapability,\n SelectionPluginConfig,\n SelectionRangeX,\n SelectionState,\n RegisterSelectionOnPageOptions,\n SelectionRectsCallback,\n} from './types';\nimport { sliceBounds, rectsWithinSlice, glyphAt } from './utils';\n\nexport class SelectionPlugin extends BasePlugin<\n SelectionPluginConfig,\n SelectionCapability,\n SelectionState,\n SelectionAction\n> {\n static readonly id = 'selection' as const;\n\n /** Modes that should trigger text-selection logic */\n private enabledModes = new Set<string>(['pointerMode']);\n\n /* interactive state */\n private selecting = false;\n private anchor?: { page: number; index: number };\n\n /** Page callbacks for rect updates */\n private pageCallbacks = new Map<number, (data: SelectionRectsCallback) => void>();\n\n private readonly selChange$ = createBehaviorEmitter<SelectionState['selection']>();\n private readonly textRetrieved$ = createBehaviorEmitter<string[]>();\n private readonly copyToClipboard$ = createEmitter<string>();\n private readonly beginSelection$ = createEmitter<{ page: number; index: number }>();\n private readonly endSelection$ = createEmitter<void>();\n\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action) => {\n this.dispatch(reset());\n this.notifyAllPages();\n });\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => {\n const tasks = action.payload.map((pageIdx) => this.getNewPageGeometryAndCache(pageIdx));\n Task.all(tasks).wait(() => {\n // Notify affected pages about geometry updates\n action.payload.forEach((pageIdx) => {\n this.notifyPage(pageIdx);\n });\n }, ignore);\n });\n }\n\n /* ── life-cycle ────────────────────────────────────────── */\n async initialize() {}\n async destroy() {\n this.selChange$.clear();\n }\n\n /* ── capability exposed to UI / other plugins ─────────── */\n buildCapability(): SelectionCapability {\n return {\n getGeometry: (p) => this.getOrLoadGeometry(p),\n getFormattedSelection: () => selector.getFormattedSelection(this.state),\n getFormattedSelectionForPage: (p) => selector.getFormattedSelectionForPage(this.state, p),\n getHighlightRectsForPage: (p) => selector.selectRectsForPage(this.state, p),\n getHighlightRects: () => this.state.rects,\n getBoundingRectForPage: (p) => selector.selectBoundingRectForPage(this.state, p),\n getBoundingRects: () => selector.selectBoundingRectsForAllPages(this.state),\n begin: (p, i) => this.beginSelection(p, i),\n update: (p, i) => this.updateSelection(p, i),\n end: () => this.endSelection(),\n clear: () => this.clearSelection(),\n onCopyToClipboard: this.copyToClipboard$.on,\n onSelectionChange: this.selChange$.on,\n onTextRetrieved: this.textRetrieved$.on,\n onBeginSelection: this.beginSelection$.on,\n onEndSelection: this.endSelection$.on,\n getSelectedText: () => this.getSelectedText(),\n copyToClipboard: () => this.copyToClipboard(),\n enableForMode: (id: string) => this.enabledModes.add(id),\n isEnabledForMode: (id: string) => this.enabledModes.has(id),\n getState: () => this.state,\n registerSelectionOnPage: (opts) => this.registerSelectionOnPage(opts),\n };\n }\n\n public registerSelectionOnPage(opts: RegisterSelectionOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'SelectionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, text selection disabled',\n );\n return () => {};\n }\n\n const { pageIndex, onRectsChange } = opts;\n\n // Track this callback for the page\n this.pageCallbacks.set(pageIndex, onRectsChange);\n\n const geoTask = this.getOrLoadGeometry(pageIndex);\n\n // Send initial state\n onRectsChange({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n\n const handlers: PointerEventHandlersWithLifecycle<PointerEvent> = {\n onPointerDown: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Clear the selection\n this.clearSelection();\n\n // Get geometry from cache (or load if needed)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n if (g !== -1) {\n this.beginSelection(pageIndex, g);\n }\n }\n },\n onPointerMove: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Get cached geometry (should be instant if already loaded)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n\n // Update cursor\n if (g !== -1) {\n this.interactionManagerCapability?.setCursor('selection-text', 'text', 10);\n } else {\n this.interactionManagerCapability?.removeCursor('selection-text');\n }\n\n // Update selection if we're selecting\n if (this.selecting && g !== -1) {\n this.updateSelection(pageIndex, g);\n }\n }\n },\n onPointerUp: (_point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.endSelection();\n },\n onHandlerActiveEnd: (modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.clearSelection();\n },\n };\n\n // Register the handlers with interaction manager\n const unregisterHandlers = this.interactionManagerCapability.registerAlways({\n scope: { type: 'page', pageIndex },\n handlers,\n });\n\n // Return cleanup function\n return () => {\n unregisterHandlers();\n this.pageCallbacks.delete(pageIndex);\n geoTask.abort({ code: PdfErrorCode.Cancelled, message: 'Cleanup' });\n };\n }\n\n private notifyPage(pageIndex: number) {\n const callback = this.pageCallbacks.get(pageIndex);\n if (callback) {\n const mode = this.interactionManagerCapability?.getActiveMode();\n if (mode === 'pointerMode') {\n callback({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n } else {\n callback({ rects: [], boundingRect: null });\n }\n }\n }\n\n private notifyAllPages() {\n this.pageCallbacks.forEach((_, pageIndex) => {\n this.notifyPage(pageIndex);\n });\n }\n\n private getNewPageGeometryAndCache(pageIdx: number): PdfTask<PdfPageGeometry> {\n if (!this.coreState.core.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Doc Not Found' });\n const page = this.coreState.core.document.pages.find((p) => p.index === pageIdx)!;\n const task = this.engine.getPageGeometry(this.coreState.core.document, page);\n task.wait((geo) => {\n this.dispatch(cachePageGeometry(pageIdx, geo));\n }, ignore);\n return task;\n }\n\n /* ── geometry cache ───────────────────────────────────── */\n private getOrLoadGeometry(pageIdx: number): PdfTask<PdfPageGeometry> {\n const cached = this.state.geometry[pageIdx];\n if (cached) return PdfTaskHelper.resolve(cached);\n\n return this.getNewPageGeometryAndCache(pageIdx);\n }\n\n /* ── selection state updates ───────────────────────────── */\n private beginSelection(page: number, index: number) {\n this.selecting = true;\n this.anchor = { page, index };\n this.dispatch(startSelection());\n this.beginSelection$.emit({ page, index });\n }\n\n private endSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(endSelection());\n this.endSelection$.emit();\n }\n\n private clearSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(clearSelection());\n this.selChange$.emit(null);\n this.notifyAllPages();\n }\n\n private updateSelection(page: number, index: number) {\n if (!this.selecting || !this.anchor) return;\n\n const a = this.anchor;\n const forward = page > a.page || (page === a.page && index >= a.index);\n\n const start = forward ? a : { page, index };\n const end = forward ? { page, index } : a;\n\n const range = { start, end };\n this.dispatch(setSelection(range));\n this.updateRectsAndSlices(range);\n this.selChange$.emit(range);\n\n // Notify affected pages\n for (let p = range.start.page; p <= range.end.page; p++) {\n this.notifyPage(p);\n }\n }\n\n private updateRectsAndSlices(range: SelectionRangeX) {\n const allRects: Record<number, Rect[]> = {};\n const allSlices: Record<number, { start: number; count: number }> = {};\n\n for (let p = range.start.page; p <= range.end.page; p++) {\n const geo = this.state.geometry[p];\n const sb = sliceBounds(range, geo, p);\n if (!sb) continue;\n\n allRects[p] = rectsWithinSlice(geo!, sb.from, sb.to);\n allSlices[p] = { start: sb.from, count: sb.to - sb.from + 1 };\n }\n\n this.dispatch(setRects(allRects));\n this.dispatch(setSlices(allSlices));\n }\n\n private getSelectedText(): PdfTask<string[]> {\n if (!this.coreState.core.document || !this.state.selection) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Doc Not Found or No Selection',\n });\n }\n\n const sel = this.state.selection;\n const req: PageTextSlice[] = [];\n\n for (let p = sel.start.page; p <= sel.end.page; p++) {\n const s = this.state.slices[p];\n if (s) req.push({ pageIndex: p, charIndex: s.start, charCount: s.count });\n }\n\n if (req.length === 0) return PdfTaskHelper.resolve([] as string[]);\n\n const task = this.engine.getTextSlices(this.coreState.core.document, req);\n\n // Emit the text when it's retrieved\n task.wait((text) => {\n this.textRetrieved$.emit(text);\n }, ignore);\n\n return task;\n }\n\n private copyToClipboard() {\n const text = this.getSelectedText();\n text.wait((text) => {\n this.copyToClipboard$.emit(text.join('\\n'));\n }, ignore);\n }\n}\n","import { SelectionState } from './types';\nimport {\n SelectionAction,\n CACHE_PAGE_GEOMETRY,\n SET_SELECTION,\n START_SELECTION,\n END_SELECTION,\n CLEAR_SELECTION,\n RESET,\n SET_SLICES,\n SET_RECTS,\n} from './actions';\n\nexport const initialState: SelectionState = {\n geometry: {},\n rects: {},\n slices: {},\n selection: null,\n active: false,\n selecting: false,\n};\n\nexport const selectionReducer = (state = initialState, action: SelectionAction): SelectionState => {\n switch (action.type) {\n case CACHE_PAGE_GEOMETRY: {\n const { page, geo } = action.payload;\n return { ...state, geometry: { ...state.geometry, [page]: geo } };\n }\n case SET_SELECTION:\n return { ...state, selection: action.payload, active: true };\n case START_SELECTION:\n return { ...state, selecting: true, selection: null, rects: {} };\n case END_SELECTION:\n return { ...state, selecting: false };\n case CLEAR_SELECTION:\n return { ...state, selecting: false, selection: null, rects: {}, active: false };\n case SET_RECTS:\n return { ...state, rects: action.payload };\n case SET_SLICES:\n return { ...state, slices: action.payload };\n case RESET:\n return initialState;\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, SELECTION_PLUGIN_ID } from './manifest';\nimport { SelectionPluginConfig, SelectionState } from './types';\n\nimport { SelectionPlugin } from './selection-plugin';\nimport { SelectionAction } from './actions';\nimport { selectionReducer, initialState } from './reducer';\n\nexport const SelectionPluginPackage: PluginPackage<\n SelectionPlugin,\n SelectionPluginConfig,\n SelectionState,\n SelectionAction\n> = {\n manifest,\n create: (registry) => new SelectionPlugin(SELECTION_PLUGIN_ID, registry),\n reducer: selectionReducer,\n initialState,\n};\n\nexport * from './selection-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './utils';\n"],"names":["SELECTION_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","enabled","CACHE_PAGE_GEOMETRY","SET_SELECTION","START_SELECTION","END_SELECTION","CLEAR_SELECTION","SET_RECTS","SET_SLICES","RESET","selectRectsForPage","state","page","rects","selectBoundingRectForPage","boundingRect","glyphAt","geo","pt","run","runs","y","rect","height","x","width","rel","glyphs","findIndex","g","charStart","sliceBounds","sel","start","end","from","index","lastRun","length","lastCharOnPage","to","rectsWithinSlice","merge","textRuns","runStart","runEnd","sIdx","Math","max","eIdx","min","minX","Infinity","maxX","minY","maxY","charCount","i","flags","push","origin","size","mergeAdjacentRects","map","rectUnion","rect1","rect2","left","top","rectIntersect","right","bottom","rectIsEmpty","getVerticalOverlap","unionRect","shouldMergeHorizontalRects","textRun1","textRun2","averageWidth1","averageWidth2","rect1Left","rect1Right","rect2Left","results","previousTextRun","currentRect","textRun","_SelectionPlugin","BasePlugin","constructor","registry","super","this","enabledModes","Set","selecting","pageCallbacks","Map","selChange$","createBehaviorEmitter","textRetrieved$","copyToClipboard$","createEmitter","beginSelection$","endSelection$","interactionManagerCapability","_a","getPlugin","coreStore","onAction","SET_DOCUMENT","_action","dispatch","type","notifyAllPages","REFRESH_PAGES","action","tasks","payload","pageIdx","getNewPageGeometryAndCache","Task","all","wait","forEach","notifyPage","ignore","initialize","destroy","clear","buildCapability","getGeometry","p","getOrLoadGeometry","getFormattedSelection","result","pages","Object","keys","Number","pageIndex","segmentRects","selector.getFormattedSelection","getFormattedSelectionForPage","selector.getFormattedSelectionForPage","getHighlightRectsForPage","selector.selectRectsForPage","getHighlightRects","getBoundingRectForPage","selector.selectBoundingRectForPage","getBoundingRects","out","rectMap","key","bRect","selector.selectBoundingRectsForAllPages","begin","beginSelection","update","updateSelection","endSelection","clearSelection","onCopyToClipboard","on","onSelectionChange","onTextRetrieved","onBeginSelection","onEndSelection","getSelectedText","copyToClipboard","enableForMode","add","isEnabledForMode","has","getState","registerSelectionOnPage","opts","logger","warn","onRectsChange","set","geoTask","handlers","onPointerDown","point","_evt","modeId","cached","geometry","onPointerMove","setCursor","_b","removeCursor","onPointerUp","_point","onHandlerActiveEnd","unregisterHandlers","registerAlways","scope","delete","abort","code","PdfErrorCode","Cancelled","message","callback","get","getActiveMode","_","coreState","core","document","PdfTaskHelper","reject","NotFound","find","task","engine","getPageGeometry","cachePageGeometry","resolve","anchor","emit","a","forward","range","updateRectsAndSlices","allRects","allSlices","sb","count","setRects","selection","req","s","slices","charIndex","getTextSlices","text","join","SelectionPlugin","initialState","active","SelectionPluginPackage","create","reducer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/utils.ts","../src/lib/selection-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { SelectionPluginConfig } from './types';\n\nexport const SELECTION_PLUGIN_ID = 'selection';\n\nexport const manifest: PluginManifest<SelectionPluginConfig> = {\n id: SELECTION_PLUGIN_ID,\n name: 'Selection Plugin',\n version: '1.0.0',\n provides: ['selection'],\n requires: ['interaction-manager'],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { PdfPageGeometry, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\nexport const CACHE_PAGE_GEOMETRY = 'CACHE_PAGE_GEOMETRY';\nexport const SET_SELECTION = 'SET_SELECTION';\nexport const START_SELECTION = 'START_SELECTION';\nexport const END_SELECTION = 'END_SELECTION';\nexport const CLEAR_SELECTION = 'CLEAR_SELECTION';\nexport const SET_RECTS = 'SET_RECTS';\nexport const SET_SLICES = 'SET_SLICES';\nexport const RESET = 'RESET';\n\nexport interface CachePageGeometryAction extends Action {\n type: typeof CACHE_PAGE_GEOMETRY;\n payload: { page: number; geo: PdfPageGeometry };\n}\nexport interface SetSelectionAction extends Action {\n type: typeof SET_SELECTION;\n payload: SelectionRangeX | null;\n}\n\nexport interface StartSelectionAction extends Action {\n type: typeof START_SELECTION;\n}\n\nexport interface EndSelectionAction extends Action {\n type: typeof END_SELECTION;\n}\n\nexport interface ClearSelectionAction extends Action {\n type: typeof CLEAR_SELECTION;\n}\n\nexport interface SetRectsAction extends Action {\n type: typeof SET_RECTS;\n payload: Record<number, Rect[]>;\n}\n\nexport interface SetSlicesAction extends Action {\n type: typeof SET_SLICES;\n payload: Record<number, { start: number; count: number }>;\n}\n\nexport interface ResetAction extends Action {\n type: typeof RESET;\n}\n\nexport type SelectionAction =\n | CachePageGeometryAction\n | SetSelectionAction\n | StartSelectionAction\n | EndSelectionAction\n | ClearSelectionAction\n | SetRectsAction\n | SetSlicesAction\n | ResetAction;\n\nexport const cachePageGeometry = (page: number, geo: PdfPageGeometry): CachePageGeometryAction => ({\n type: CACHE_PAGE_GEOMETRY,\n payload: { page, geo },\n});\n\nexport const setSelection = (sel: SelectionRangeX): SetSelectionAction => ({\n type: SET_SELECTION,\n payload: sel,\n});\n\nexport const startSelection = (): StartSelectionAction => ({ type: START_SELECTION });\n\nexport const endSelection = (): EndSelectionAction => ({ type: END_SELECTION });\n\nexport const clearSelection = (): ClearSelectionAction => ({ type: CLEAR_SELECTION });\n\nexport const setRects = (allRects: Record<number, Rect[]>): SetRectsAction => ({\n type: SET_RECTS,\n payload: allRects,\n});\n\nexport const setSlices = (\n slices: Record<number, { start: number; count: number }>,\n): SetSlicesAction => ({ type: SET_SLICES, payload: slices });\n\nexport const reset = (): ResetAction => ({ type: RESET });\n","import { Rect, boundingRect } from '@embedpdf/models';\nimport { FormattedSelection, SelectionState } from './types';\n\nexport function selectRectsForPage(state: SelectionState, page: number) {\n return state.rects[page] ?? [];\n}\n\nexport function selectBoundingRectForPage(state: SelectionState, page: number) {\n return boundingRect(selectRectsForPage(state, page));\n}\n\nexport function selectRectsAndBoundingRectForPage(state: SelectionState, page: number) {\n return {\n rects: selectRectsForPage(state, page),\n boundingRect: selectBoundingRectForPage(state, page),\n };\n}\n\nexport function selectBoundingRectsForAllPages(state: SelectionState) {\n const out: { page: number; rect: Rect }[] = [];\n const rectMap = state.rects;\n\n for (const key in rectMap) {\n const page = Number(key);\n const bRect = boundingRect(rectMap[page]);\n if (bRect) out.push({ page, rect: bRect });\n }\n return out;\n}\n\nexport function getFormattedSelectionForPage(\n state: SelectionState,\n page: number,\n): FormattedSelection | null {\n const segmentRects = state.rects[page] || [];\n if (segmentRects.length === 0) return null;\n const boundingRect = selectBoundingRectForPage(state, page);\n if (!boundingRect) return null;\n return { pageIndex: page, rect: boundingRect, segmentRects };\n}\n\nexport function getFormattedSelection(state: SelectionState) {\n const result: FormattedSelection[] = [];\n\n // Get all pages that have rects\n const pages = Object.keys(state.rects).map(Number);\n\n for (const pageIndex of pages) {\n const segmentRects = state.rects[pageIndex] || [];\n\n if (segmentRects.length === 0) continue;\n\n // Calculate bounding rect for this page\n const boundingRect = selectBoundingRectForPage(state, pageIndex);\n\n if (boundingRect) {\n result.push({\n pageIndex,\n rect: boundingRect,\n segmentRects,\n });\n }\n }\n\n return result;\n}\n","import { PdfPageGeometry, Position, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\n/**\n * Hit-test helper using runs\n * @param geo - page geometry\n * @param pt - point\n * @returns glyph index\n */\nexport function glyphAt(geo: PdfPageGeometry, pt: Position) {\n for (const run of geo.runs) {\n const inRun =\n pt.y >= run.rect.y &&\n pt.y <= run.rect.y + run.rect.height &&\n pt.x >= run.rect.x &&\n pt.x <= run.rect.x + run.rect.width;\n\n if (!inRun) continue;\n\n // Simply check if the point is within any glyph's bounding box\n const rel = run.glyphs.findIndex(\n (g) => pt.x >= g.x && pt.x <= g.x + g.width && pt.y >= g.y && pt.y <= g.y + g.height,\n );\n\n if (rel !== -1) {\n return run.charStart + rel;\n }\n }\n return -1;\n}\n\n/**\n * Helper: min/max glyph indices on `page` for current sel\n * @param sel - selection range\n * @param geo - page geometry\n * @param page - page index\n * @returns { from: number; to: number } | null\n */\nexport function sliceBounds(\n sel: SelectionRangeX | null,\n geo: PdfPageGeometry | undefined,\n page: number,\n): { from: number; to: number } | null {\n if (!sel || !geo) return null;\n if (page < sel.start.page || page > sel.end.page) return null;\n\n const from = page === sel.start.page ? sel.start.index : 0;\n\n const lastRun = geo.runs[geo.runs.length - 1];\n const lastCharOnPage = lastRun.charStart + lastRun.glyphs.length - 1;\n\n const to = page === sel.end.page ? sel.end.index : lastCharOnPage;\n\n return { from, to };\n}\n\n/**\n * Helper: build rects for a slice of the page\n * @param geo - page geometry\n * @param from - from index\n * @param to - to index\n * @param merge - whether to merge adjacent rects (default: true)\n * @returns rects\n */\nexport function rectsWithinSlice(\n geo: PdfPageGeometry,\n from: number,\n to: number,\n merge: boolean = true,\n): Rect[] {\n const textRuns: TextRunInfo[] = [];\n\n for (const run of geo.runs) {\n const runStart = run.charStart;\n const runEnd = runStart + run.glyphs.length - 1;\n if (runEnd < from || runStart > to) continue;\n\n const sIdx = Math.max(from, runStart) - runStart;\n const eIdx = Math.min(to, runEnd) - runStart;\n\n let minX = Infinity,\n maxX = -Infinity;\n let minY = Infinity,\n maxY = -Infinity;\n let charCount = 0;\n\n for (let i = sIdx; i <= eIdx; i++) {\n const g = run.glyphs[i];\n if (g.flags === 2) continue; // empty glyph\n\n minX = Math.min(minX, g.x);\n maxX = Math.max(maxX, g.x + g.width);\n minY = Math.min(minY, g.y);\n maxY = Math.max(maxY, g.y + g.height);\n charCount++;\n }\n\n if (minX !== Infinity && charCount > 0) {\n textRuns.push({\n rect: {\n origin: { x: minX, y: minY },\n size: { width: maxX - minX, height: maxY - minY },\n },\n charCount,\n });\n }\n }\n\n // If merge is false, just return the individual rects\n if (!merge) {\n return textRuns.map((run) => run.rect);\n }\n\n // Otherwise merge adjacent rects\n return mergeAdjacentRects(textRuns);\n}\n\n/**\n * ============================================================================\n * Rectangle Merging Algorithm\n * ============================================================================\n *\n * The following code is adapted from Chromium's PDF text selection implementation.\n *\n * Copyright 2010 The Chromium Authors\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file: https://source.chromium.org/chromium/chromium/src/+/main:LICENSE\n *\n * Original source:\n * https://source.chromium.org/chromium/chromium/src/+/main:pdf/pdfium/pdfium_range.cc\n *\n * Adapted for TypeScript and this project's Rect/geometry types.\n */\n\n/**\n * Text run info for rect merging (similar to Chromium's ScreenRectTextRunInfo)\n */\nexport interface TextRunInfo {\n rect: Rect;\n charCount: number;\n}\n\n/**\n * Helper functions for Rect operations\n */\nexport function rectUnion(rect1: Rect, rect2: Rect): Rect {\n const left = Math.min(rect1.origin.x, rect2.origin.x);\n const top = Math.min(rect1.origin.y, rect2.origin.y);\n const right = Math.max(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.max(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n return {\n origin: { x: left, y: top },\n size: { width: right - left, height: bottom - top },\n };\n}\n\nexport function rectIntersect(rect1: Rect, rect2: Rect): Rect {\n const left = Math.max(rect1.origin.x, rect2.origin.x);\n const top = Math.max(rect1.origin.y, rect2.origin.y);\n const right = Math.min(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.min(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n const width = Math.max(0, right - left);\n const height = Math.max(0, bottom - top);\n\n return {\n origin: { x: left, y: top },\n size: { width, height },\n };\n}\n\nexport function rectIsEmpty(rect: Rect): boolean {\n return rect.size.width <= 0 || rect.size.height <= 0;\n}\n\n/**\n * Returns a ratio between [0, 1] representing vertical overlap\n */\nexport function getVerticalOverlap(rect1: Rect, rect2: Rect): number {\n if (rectIsEmpty(rect1) || rectIsEmpty(rect2)) return 0;\n\n const unionRect = rectUnion(rect1, rect2);\n\n if (unionRect.size.height === rect1.size.height || unionRect.size.height === rect2.size.height) {\n return 1.0;\n }\n\n const intersectRect = rectIntersect(rect1, rect2);\n return intersectRect.size.height / unionRect.size.height;\n}\n\n/**\n * Returns true if there is sufficient horizontal and vertical overlap\n */\nexport function shouldMergeHorizontalRects(textRun1: TextRunInfo, textRun2: TextRunInfo): boolean {\n const VERTICAL_OVERLAP_THRESHOLD = 0.8;\n const rect1 = textRun1.rect;\n const rect2 = textRun2.rect;\n\n if (getVerticalOverlap(rect1, rect2) < VERTICAL_OVERLAP_THRESHOLD) {\n return false;\n }\n\n const HORIZONTAL_WIDTH_FACTOR = 1.0;\n const averageWidth1 = (HORIZONTAL_WIDTH_FACTOR * rect1.size.width) / textRun1.charCount;\n const averageWidth2 = (HORIZONTAL_WIDTH_FACTOR * rect2.size.width) / textRun2.charCount;\n\n const rect1Left = rect1.origin.x - averageWidth1;\n const rect1Right = rect1.origin.x + rect1.size.width + averageWidth1;\n const rect2Left = rect2.origin.x - averageWidth2;\n const rect2Right = rect2.origin.x + rect2.size.width + averageWidth2;\n\n return rect1Left < rect2Right && rect1Right > rect2Left;\n}\n\n/**\n * Merge adjacent rectangles based on proximity and overlap (similar to Chromium's algorithm)\n */\nexport function mergeAdjacentRects(textRuns: TextRunInfo[]): Rect[] {\n const results: Rect[] = [];\n let previousTextRun: TextRunInfo | null = null;\n let currentRect: Rect | null = null;\n\n for (const textRun of textRuns) {\n if (previousTextRun && currentRect) {\n if (shouldMergeHorizontalRects(previousTextRun, textRun)) {\n currentRect = rectUnion(currentRect, textRun.rect);\n } else {\n results.push(currentRect);\n currentRect = textRun.rect;\n }\n } else {\n currentRect = textRun.rect;\n }\n previousTextRun = textRun;\n }\n\n if (currentRect && !rectIsEmpty(currentRect)) {\n results.push(currentRect);\n }\n\n return results;\n}\n","import {\n BasePlugin,\n PluginRegistry,\n REFRESH_PAGES,\n SET_DOCUMENT,\n createBehaviorEmitter,\n createEmitter,\n} from '@embedpdf/core';\nimport {\n PdfPageGeometry,\n Rect,\n PdfTask,\n PdfTaskHelper,\n PdfErrorCode,\n ignore,\n PageTextSlice,\n Task,\n Position,\n} from '@embedpdf/models';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nimport {\n cachePageGeometry,\n setSelection,\n SelectionAction,\n endSelection,\n startSelection,\n clearSelection,\n reset,\n setRects,\n setSlices,\n} from './actions';\nimport * as selector from './selectors';\nimport {\n SelectionCapability,\n SelectionPluginConfig,\n SelectionRangeX,\n SelectionState,\n RegisterSelectionOnPageOptions,\n SelectionRectsCallback,\n} from './types';\nimport { sliceBounds, rectsWithinSlice, glyphAt } from './utils';\n\nexport class SelectionPlugin extends BasePlugin<\n SelectionPluginConfig,\n SelectionCapability,\n SelectionState,\n SelectionAction\n> {\n static readonly id = 'selection' as const;\n\n /** Modes that should trigger text-selection logic */\n private enabledModes = new Set<string>(['pointerMode']);\n\n /* interactive state */\n private selecting = false;\n private anchor?: { page: number; index: number };\n\n /** Page callbacks for rect updates */\n private pageCallbacks = new Map<number, (data: SelectionRectsCallback) => void>();\n\n private readonly selChange$ = createBehaviorEmitter<SelectionState['selection']>();\n private readonly textRetrieved$ = createBehaviorEmitter<string[]>();\n private readonly copyToClipboard$ = createEmitter<string>();\n private readonly beginSelection$ = createEmitter<{ page: number; index: number }>();\n private readonly endSelection$ = createEmitter<void>();\n\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action) => {\n this.dispatch(reset());\n this.notifyAllPages();\n });\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => {\n const tasks = action.payload.map((pageIdx) => this.getNewPageGeometryAndCache(pageIdx));\n Task.all(tasks).wait(() => {\n // Notify affected pages about geometry updates\n action.payload.forEach((pageIdx) => {\n this.notifyPage(pageIdx);\n });\n }, ignore);\n });\n }\n\n /* ── life-cycle ────────────────────────────────────────── */\n async initialize() {}\n async destroy() {\n this.selChange$.clear();\n }\n\n /* ── capability exposed to UI / other plugins ─────────── */\n buildCapability(): SelectionCapability {\n return {\n getFormattedSelection: () => selector.getFormattedSelection(this.state),\n getFormattedSelectionForPage: (p) => selector.getFormattedSelectionForPage(this.state, p),\n getHighlightRectsForPage: (p) => selector.selectRectsForPage(this.state, p),\n getHighlightRects: () => this.state.rects,\n getBoundingRectForPage: (p) => selector.selectBoundingRectForPage(this.state, p),\n getBoundingRects: () => selector.selectBoundingRectsForAllPages(this.state),\n onCopyToClipboard: this.copyToClipboard$.on,\n onSelectionChange: this.selChange$.on,\n onTextRetrieved: this.textRetrieved$.on,\n onBeginSelection: this.beginSelection$.on,\n onEndSelection: this.endSelection$.on,\n getSelectedText: () => this.getSelectedText(),\n copyToClipboard: () => this.copyToClipboard(),\n enableForMode: (id: string) => this.enabledModes.add(id),\n isEnabledForMode: (id: string) => this.enabledModes.has(id),\n getState: () => this.state,\n };\n }\n\n public registerSelectionOnPage(opts: RegisterSelectionOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'SelectionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, text selection disabled',\n );\n return () => {};\n }\n\n const { pageIndex, onRectsChange } = opts;\n\n // Track this callback for the page\n this.pageCallbacks.set(pageIndex, onRectsChange);\n\n const geoTask = this.getOrLoadGeometry(pageIndex);\n\n // Send initial state\n onRectsChange({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n\n const handlers: PointerEventHandlersWithLifecycle<PointerEvent> = {\n onPointerDown: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Clear the selection\n this.clearSelection();\n\n // Get geometry from cache (or load if needed)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n if (g !== -1) {\n this.beginSelection(pageIndex, g);\n }\n }\n },\n onPointerMove: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Get cached geometry (should be instant if already loaded)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n\n // Update cursor\n if (g !== -1) {\n this.interactionManagerCapability?.setCursor('selection-text', 'text', 10);\n } else {\n this.interactionManagerCapability?.removeCursor('selection-text');\n }\n\n // Update selection if we're selecting\n if (this.selecting && g !== -1) {\n this.updateSelection(pageIndex, g);\n }\n }\n },\n onPointerUp: (_point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.endSelection();\n },\n onHandlerActiveEnd: (modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.clearSelection();\n },\n };\n\n // Register the handlers with interaction manager\n const unregisterHandlers = this.interactionManagerCapability.registerAlways({\n scope: { type: 'page', pageIndex },\n handlers,\n });\n\n // Return cleanup function\n return () => {\n unregisterHandlers();\n this.pageCallbacks.delete(pageIndex);\n geoTask.abort({ code: PdfErrorCode.Cancelled, message: 'Cleanup' });\n };\n }\n\n private notifyPage(pageIndex: number) {\n const callback = this.pageCallbacks.get(pageIndex);\n if (callback) {\n const mode = this.interactionManagerCapability?.getActiveMode();\n if (mode === 'pointerMode') {\n callback({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n } else {\n callback({ rects: [], boundingRect: null });\n }\n }\n }\n\n private notifyAllPages() {\n this.pageCallbacks.forEach((_, pageIndex) => {\n this.notifyPage(pageIndex);\n });\n }\n\n private getNewPageGeometryAndCache(pageIdx: number): PdfTask<PdfPageGeometry> {\n if (!this.coreState.core.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Doc Not Found' });\n const page = this.coreState.core.document.pages.find((p) => p.index === pageIdx)!;\n const task = this.engine.getPageGeometry(this.coreState.core.document, page);\n task.wait((geo) => {\n this.dispatch(cachePageGeometry(pageIdx, geo));\n }, ignore);\n return task;\n }\n\n /* ── geometry cache ───────────────────────────────────── */\n private getOrLoadGeometry(pageIdx: number): PdfTask<PdfPageGeometry> {\n const cached = this.state.geometry[pageIdx];\n if (cached) return PdfTaskHelper.resolve(cached);\n\n return this.getNewPageGeometryAndCache(pageIdx);\n }\n\n /* ── selection state updates ───────────────────────────── */\n private beginSelection(page: number, index: number) {\n this.selecting = true;\n this.anchor = { page, index };\n this.dispatch(startSelection());\n this.beginSelection$.emit({ page, index });\n }\n\n private endSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(endSelection());\n this.endSelection$.emit();\n }\n\n private clearSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(clearSelection());\n this.selChange$.emit(null);\n this.notifyAllPages();\n }\n\n private updateSelection(page: number, index: number) {\n if (!this.selecting || !this.anchor) return;\n\n const a = this.anchor;\n const forward = page > a.page || (page === a.page && index >= a.index);\n\n const start = forward ? a : { page, index };\n const end = forward ? { page, index } : a;\n\n const range = { start, end };\n this.dispatch(setSelection(range));\n this.updateRectsAndSlices(range);\n this.selChange$.emit(range);\n\n // Notify affected pages\n for (let p = range.start.page; p <= range.end.page; p++) {\n this.notifyPage(p);\n }\n }\n\n private updateRectsAndSlices(range: SelectionRangeX) {\n const allRects: Record<number, Rect[]> = {};\n const allSlices: Record<number, { start: number; count: number }> = {};\n\n for (let p = range.start.page; p <= range.end.page; p++) {\n const geo = this.state.geometry[p];\n const sb = sliceBounds(range, geo, p);\n if (!sb) continue;\n\n allRects[p] = rectsWithinSlice(geo!, sb.from, sb.to);\n allSlices[p] = { start: sb.from, count: sb.to - sb.from + 1 };\n }\n\n this.dispatch(setRects(allRects));\n this.dispatch(setSlices(allSlices));\n }\n\n private getSelectedText(): PdfTask<string[]> {\n if (!this.coreState.core.document || !this.state.selection) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Doc Not Found or No Selection',\n });\n }\n\n const sel = this.state.selection;\n const req: PageTextSlice[] = [];\n\n for (let p = sel.start.page; p <= sel.end.page; p++) {\n const s = this.state.slices[p];\n if (s) req.push({ pageIndex: p, charIndex: s.start, charCount: s.count });\n }\n\n if (req.length === 0) return PdfTaskHelper.resolve([] as string[]);\n\n const task = this.engine.getTextSlices(this.coreState.core.document, req);\n\n // Emit the text when it's retrieved\n task.wait((text) => {\n this.textRetrieved$.emit(text);\n }, ignore);\n\n return task;\n }\n\n private copyToClipboard() {\n const text = this.getSelectedText();\n text.wait((text) => {\n this.copyToClipboard$.emit(text.join('\\n'));\n }, ignore);\n }\n}\n","import { SelectionState } from './types';\nimport {\n SelectionAction,\n CACHE_PAGE_GEOMETRY,\n SET_SELECTION,\n START_SELECTION,\n END_SELECTION,\n CLEAR_SELECTION,\n RESET,\n SET_SLICES,\n SET_RECTS,\n} from './actions';\n\nexport const initialState: SelectionState = {\n geometry: {},\n rects: {},\n slices: {},\n selection: null,\n active: false,\n selecting: false,\n};\n\nexport const selectionReducer = (state = initialState, action: SelectionAction): SelectionState => {\n switch (action.type) {\n case CACHE_PAGE_GEOMETRY: {\n const { page, geo } = action.payload;\n return { ...state, geometry: { ...state.geometry, [page]: geo } };\n }\n case SET_SELECTION:\n return { ...state, selection: action.payload, active: true };\n case START_SELECTION:\n return { ...state, selecting: true, selection: null, rects: {} };\n case END_SELECTION:\n return { ...state, selecting: false };\n case CLEAR_SELECTION:\n return { ...state, selecting: false, selection: null, rects: {}, active: false };\n case SET_RECTS:\n return { ...state, rects: action.payload };\n case SET_SLICES:\n return { ...state, slices: action.payload };\n case RESET:\n return initialState;\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, SELECTION_PLUGIN_ID } from './manifest';\nimport { SelectionPluginConfig, SelectionState } from './types';\n\nimport { SelectionPlugin } from './selection-plugin';\nimport { SelectionAction } from './actions';\nimport { selectionReducer, initialState } from './reducer';\n\nexport const SelectionPluginPackage: PluginPackage<\n SelectionPlugin,\n SelectionPluginConfig,\n SelectionState,\n SelectionAction\n> = {\n manifest,\n create: (registry) => new SelectionPlugin(SELECTION_PLUGIN_ID, registry),\n reducer: selectionReducer,\n initialState,\n};\n\nexport * from './selection-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './utils';\n"],"names":["SELECTION_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","enabled","CACHE_PAGE_GEOMETRY","SET_SELECTION","START_SELECTION","END_SELECTION","CLEAR_SELECTION","SET_RECTS","SET_SLICES","RESET","selectRectsForPage","state","page","rects","selectBoundingRectForPage","boundingRect","glyphAt","geo","pt","run","runs","y","rect","height","x","width","rel","glyphs","findIndex","g","charStart","sliceBounds","sel","start","end","from","index","lastRun","length","lastCharOnPage","to","rectsWithinSlice","merge","textRuns","runStart","runEnd","sIdx","Math","max","eIdx","min","minX","Infinity","maxX","minY","maxY","charCount","i","flags","push","origin","size","mergeAdjacentRects","map","rectUnion","rect1","rect2","left","top","rectIntersect","right","bottom","rectIsEmpty","getVerticalOverlap","unionRect","shouldMergeHorizontalRects","textRun1","textRun2","averageWidth1","averageWidth2","rect1Left","rect1Right","rect2Left","results","previousTextRun","currentRect","textRun","_SelectionPlugin","BasePlugin","constructor","registry","super","this","enabledModes","Set","selecting","pageCallbacks","Map","selChange$","createBehaviorEmitter","textRetrieved$","copyToClipboard$","createEmitter","beginSelection$","endSelection$","interactionManagerCapability","_a","getPlugin","coreStore","onAction","SET_DOCUMENT","_action","dispatch","type","notifyAllPages","REFRESH_PAGES","action","tasks","payload","pageIdx","getNewPageGeometryAndCache","Task","all","wait","forEach","notifyPage","ignore","initialize","destroy","clear","buildCapability","getFormattedSelection","result","pages","Object","keys","Number","pageIndex","segmentRects","selector.getFormattedSelection","getFormattedSelectionForPage","p","selector.getFormattedSelectionForPage","getHighlightRectsForPage","selector.selectRectsForPage","getHighlightRects","getBoundingRectForPage","selector.selectBoundingRectForPage","getBoundingRects","out","rectMap","key","bRect","selector.selectBoundingRectsForAllPages","onCopyToClipboard","on","onSelectionChange","onTextRetrieved","onBeginSelection","onEndSelection","getSelectedText","copyToClipboard","enableForMode","add","isEnabledForMode","has","getState","registerSelectionOnPage","opts","logger","warn","onRectsChange","set","geoTask","getOrLoadGeometry","handlers","onPointerDown","point","_evt","modeId","clearSelection","cached","geometry","beginSelection","onPointerMove","setCursor","_b","removeCursor","updateSelection","onPointerUp","_point","endSelection","onHandlerActiveEnd","unregisterHandlers","registerAlways","scope","delete","abort","code","PdfErrorCode","Cancelled","message","callback","get","getActiveMode","_","coreState","core","document","PdfTaskHelper","reject","NotFound","find","task","engine","getPageGeometry","cachePageGeometry","resolve","anchor","emit","a","forward","range","updateRectsAndSlices","allRects","allSlices","sb","count","setRects","selection","req","s","slices","charIndex","getTextSlices","text","join","SelectionPlugin","initialState","active","SelectionPluginPackage","create","reducer"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -241,17 +241,12 @@ const _SelectionPlugin = class _SelectionPlugin extends BasePlugin {
|
|
|
241
241
|
/* ── capability exposed to UI / other plugins ─────────── */
|
|
242
242
|
buildCapability() {
|
|
243
243
|
return {
|
|
244
|
-
getGeometry: (p) => this.getOrLoadGeometry(p),
|
|
245
244
|
getFormattedSelection: () => getFormattedSelection(this.state),
|
|
246
245
|
getFormattedSelectionForPage: (p) => getFormattedSelectionForPage(this.state, p),
|
|
247
246
|
getHighlightRectsForPage: (p) => selectRectsForPage(this.state, p),
|
|
248
247
|
getHighlightRects: () => this.state.rects,
|
|
249
248
|
getBoundingRectForPage: (p) => selectBoundingRectForPage(this.state, p),
|
|
250
249
|
getBoundingRects: () => selectBoundingRectsForAllPages(this.state),
|
|
251
|
-
begin: (p, i) => this.beginSelection(p, i),
|
|
252
|
-
update: (p, i) => this.updateSelection(p, i),
|
|
253
|
-
end: () => this.endSelection(),
|
|
254
|
-
clear: () => this.clearSelection(),
|
|
255
250
|
onCopyToClipboard: this.copyToClipboard$.on,
|
|
256
251
|
onSelectionChange: this.selChange$.on,
|
|
257
252
|
onTextRetrieved: this.textRetrieved$.on,
|
|
@@ -261,8 +256,7 @@ const _SelectionPlugin = class _SelectionPlugin extends BasePlugin {
|
|
|
261
256
|
copyToClipboard: () => this.copyToClipboard(),
|
|
262
257
|
enableForMode: (id) => this.enabledModes.add(id),
|
|
263
258
|
isEnabledForMode: (id) => this.enabledModes.has(id),
|
|
264
|
-
getState: () => this.state
|
|
265
|
-
registerSelectionOnPage: (opts) => this.registerSelectionOnPage(opts)
|
|
259
|
+
getState: () => this.state
|
|
266
260
|
};
|
|
267
261
|
}
|
|
268
262
|
registerSelectionOnPage(opts) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/utils.ts","../src/lib/selection-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { SelectionPluginConfig } from './types';\n\nexport const SELECTION_PLUGIN_ID = 'selection';\n\nexport const manifest: PluginManifest<SelectionPluginConfig> = {\n id: SELECTION_PLUGIN_ID,\n name: 'Selection Plugin',\n version: '1.0.0',\n provides: ['selection'],\n requires: ['interaction-manager'],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { PdfPageGeometry, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\nexport const CACHE_PAGE_GEOMETRY = 'CACHE_PAGE_GEOMETRY';\nexport const SET_SELECTION = 'SET_SELECTION';\nexport const START_SELECTION = 'START_SELECTION';\nexport const END_SELECTION = 'END_SELECTION';\nexport const CLEAR_SELECTION = 'CLEAR_SELECTION';\nexport const SET_RECTS = 'SET_RECTS';\nexport const SET_SLICES = 'SET_SLICES';\nexport const RESET = 'RESET';\n\nexport interface CachePageGeometryAction extends Action {\n type: typeof CACHE_PAGE_GEOMETRY;\n payload: { page: number; geo: PdfPageGeometry };\n}\nexport interface SetSelectionAction extends Action {\n type: typeof SET_SELECTION;\n payload: SelectionRangeX | null;\n}\n\nexport interface StartSelectionAction extends Action {\n type: typeof START_SELECTION;\n}\n\nexport interface EndSelectionAction extends Action {\n type: typeof END_SELECTION;\n}\n\nexport interface ClearSelectionAction extends Action {\n type: typeof CLEAR_SELECTION;\n}\n\nexport interface SetRectsAction extends Action {\n type: typeof SET_RECTS;\n payload: Record<number, Rect[]>;\n}\n\nexport interface SetSlicesAction extends Action {\n type: typeof SET_SLICES;\n payload: Record<number, { start: number; count: number }>;\n}\n\nexport interface ResetAction extends Action {\n type: typeof RESET;\n}\n\nexport type SelectionAction =\n | CachePageGeometryAction\n | SetSelectionAction\n | StartSelectionAction\n | EndSelectionAction\n | ClearSelectionAction\n | SetRectsAction\n | SetSlicesAction\n | ResetAction;\n\nexport const cachePageGeometry = (page: number, geo: PdfPageGeometry): CachePageGeometryAction => ({\n type: CACHE_PAGE_GEOMETRY,\n payload: { page, geo },\n});\n\nexport const setSelection = (sel: SelectionRangeX): SetSelectionAction => ({\n type: SET_SELECTION,\n payload: sel,\n});\n\nexport const startSelection = (): StartSelectionAction => ({ type: START_SELECTION });\n\nexport const endSelection = (): EndSelectionAction => ({ type: END_SELECTION });\n\nexport const clearSelection = (): ClearSelectionAction => ({ type: CLEAR_SELECTION });\n\nexport const setRects = (allRects: Record<number, Rect[]>): SetRectsAction => ({\n type: SET_RECTS,\n payload: allRects,\n});\n\nexport const setSlices = (\n slices: Record<number, { start: number; count: number }>,\n): SetSlicesAction => ({ type: SET_SLICES, payload: slices });\n\nexport const reset = (): ResetAction => ({ type: RESET });\n","import { Rect, boundingRect } from '@embedpdf/models';\nimport { FormattedSelection, SelectionState } from './types';\n\nexport function selectRectsForPage(state: SelectionState, page: number) {\n return state.rects[page] ?? [];\n}\n\nexport function selectBoundingRectForPage(state: SelectionState, page: number) {\n return boundingRect(selectRectsForPage(state, page));\n}\n\nexport function selectRectsAndBoundingRectForPage(state: SelectionState, page: number) {\n return {\n rects: selectRectsForPage(state, page),\n boundingRect: selectBoundingRectForPage(state, page),\n };\n}\n\nexport function selectBoundingRectsForAllPages(state: SelectionState) {\n const out: { page: number; rect: Rect }[] = [];\n const rectMap = state.rects;\n\n for (const key in rectMap) {\n const page = Number(key);\n const bRect = boundingRect(rectMap[page]);\n if (bRect) out.push({ page, rect: bRect });\n }\n return out;\n}\n\nexport function getFormattedSelectionForPage(\n state: SelectionState,\n page: number,\n): FormattedSelection | null {\n const segmentRects = state.rects[page] || [];\n if (segmentRects.length === 0) return null;\n const boundingRect = selectBoundingRectForPage(state, page);\n if (!boundingRect) return null;\n return { pageIndex: page, rect: boundingRect, segmentRects };\n}\n\nexport function getFormattedSelection(state: SelectionState) {\n const result: FormattedSelection[] = [];\n\n // Get all pages that have rects\n const pages = Object.keys(state.rects).map(Number);\n\n for (const pageIndex of pages) {\n const segmentRects = state.rects[pageIndex] || [];\n\n if (segmentRects.length === 0) continue;\n\n // Calculate bounding rect for this page\n const boundingRect = selectBoundingRectForPage(state, pageIndex);\n\n if (boundingRect) {\n result.push({\n pageIndex,\n rect: boundingRect,\n segmentRects,\n });\n }\n }\n\n return result;\n}\n","import { PdfPageGeometry, Position, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\n/**\n * Hit-test helper using runs\n * @param geo - page geometry\n * @param pt - point\n * @returns glyph index\n */\nexport function glyphAt(geo: PdfPageGeometry, pt: Position) {\n for (const run of geo.runs) {\n const inRun =\n pt.y >= run.rect.y &&\n pt.y <= run.rect.y + run.rect.height &&\n pt.x >= run.rect.x &&\n pt.x <= run.rect.x + run.rect.width;\n\n if (!inRun) continue;\n\n // Simply check if the point is within any glyph's bounding box\n const rel = run.glyphs.findIndex(\n (g) => pt.x >= g.x && pt.x <= g.x + g.width && pt.y >= g.y && pt.y <= g.y + g.height,\n );\n\n if (rel !== -1) {\n return run.charStart + rel;\n }\n }\n return -1;\n}\n\n/**\n * Helper: min/max glyph indices on `page` for current sel\n * @param sel - selection range\n * @param geo - page geometry\n * @param page - page index\n * @returns { from: number; to: number } | null\n */\nexport function sliceBounds(\n sel: SelectionRangeX | null,\n geo: PdfPageGeometry | undefined,\n page: number,\n): { from: number; to: number } | null {\n if (!sel || !geo) return null;\n if (page < sel.start.page || page > sel.end.page) return null;\n\n const from = page === sel.start.page ? sel.start.index : 0;\n\n const lastRun = geo.runs[geo.runs.length - 1];\n const lastCharOnPage = lastRun.charStart + lastRun.glyphs.length - 1;\n\n const to = page === sel.end.page ? sel.end.index : lastCharOnPage;\n\n return { from, to };\n}\n\n/**\n * Helper: build rects for a slice of the page\n * @param geo - page geometry\n * @param from - from index\n * @param to - to index\n * @param merge - whether to merge adjacent rects (default: true)\n * @returns rects\n */\nexport function rectsWithinSlice(\n geo: PdfPageGeometry,\n from: number,\n to: number,\n merge: boolean = true,\n): Rect[] {\n const textRuns: TextRunInfo[] = [];\n\n for (const run of geo.runs) {\n const runStart = run.charStart;\n const runEnd = runStart + run.glyphs.length - 1;\n if (runEnd < from || runStart > to) continue;\n\n const sIdx = Math.max(from, runStart) - runStart;\n const eIdx = Math.min(to, runEnd) - runStart;\n\n let minX = Infinity,\n maxX = -Infinity;\n let minY = Infinity,\n maxY = -Infinity;\n let charCount = 0;\n\n for (let i = sIdx; i <= eIdx; i++) {\n const g = run.glyphs[i];\n if (g.flags === 2) continue; // empty glyph\n\n minX = Math.min(minX, g.x);\n maxX = Math.max(maxX, g.x + g.width);\n minY = Math.min(minY, g.y);\n maxY = Math.max(maxY, g.y + g.height);\n charCount++;\n }\n\n if (minX !== Infinity && charCount > 0) {\n textRuns.push({\n rect: {\n origin: { x: minX, y: minY },\n size: { width: maxX - minX, height: maxY - minY },\n },\n charCount,\n });\n }\n }\n\n // If merge is false, just return the individual rects\n if (!merge) {\n return textRuns.map((run) => run.rect);\n }\n\n // Otherwise merge adjacent rects\n return mergeAdjacentRects(textRuns);\n}\n\n/**\n * ============================================================================\n * Rectangle Merging Algorithm\n * ============================================================================\n *\n * The following code is adapted from Chromium's PDF text selection implementation.\n *\n * Copyright 2010 The Chromium Authors\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file: https://source.chromium.org/chromium/chromium/src/+/main:LICENSE\n *\n * Original source:\n * https://source.chromium.org/chromium/chromium/src/+/main:pdf/pdfium/pdfium_range.cc\n *\n * Adapted for TypeScript and this project's Rect/geometry types.\n */\n\n/**\n * Text run info for rect merging (similar to Chromium's ScreenRectTextRunInfo)\n */\nexport interface TextRunInfo {\n rect: Rect;\n charCount: number;\n}\n\n/**\n * Helper functions for Rect operations\n */\nexport function rectUnion(rect1: Rect, rect2: Rect): Rect {\n const left = Math.min(rect1.origin.x, rect2.origin.x);\n const top = Math.min(rect1.origin.y, rect2.origin.y);\n const right = Math.max(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.max(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n return {\n origin: { x: left, y: top },\n size: { width: right - left, height: bottom - top },\n };\n}\n\nexport function rectIntersect(rect1: Rect, rect2: Rect): Rect {\n const left = Math.max(rect1.origin.x, rect2.origin.x);\n const top = Math.max(rect1.origin.y, rect2.origin.y);\n const right = Math.min(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.min(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n const width = Math.max(0, right - left);\n const height = Math.max(0, bottom - top);\n\n return {\n origin: { x: left, y: top },\n size: { width, height },\n };\n}\n\nexport function rectIsEmpty(rect: Rect): boolean {\n return rect.size.width <= 0 || rect.size.height <= 0;\n}\n\n/**\n * Returns a ratio between [0, 1] representing vertical overlap\n */\nexport function getVerticalOverlap(rect1: Rect, rect2: Rect): number {\n if (rectIsEmpty(rect1) || rectIsEmpty(rect2)) return 0;\n\n const unionRect = rectUnion(rect1, rect2);\n\n if (unionRect.size.height === rect1.size.height || unionRect.size.height === rect2.size.height) {\n return 1.0;\n }\n\n const intersectRect = rectIntersect(rect1, rect2);\n return intersectRect.size.height / unionRect.size.height;\n}\n\n/**\n * Returns true if there is sufficient horizontal and vertical overlap\n */\nexport function shouldMergeHorizontalRects(textRun1: TextRunInfo, textRun2: TextRunInfo): boolean {\n const VERTICAL_OVERLAP_THRESHOLD = 0.8;\n const rect1 = textRun1.rect;\n const rect2 = textRun2.rect;\n\n if (getVerticalOverlap(rect1, rect2) < VERTICAL_OVERLAP_THRESHOLD) {\n return false;\n }\n\n const HORIZONTAL_WIDTH_FACTOR = 1.0;\n const averageWidth1 = (HORIZONTAL_WIDTH_FACTOR * rect1.size.width) / textRun1.charCount;\n const averageWidth2 = (HORIZONTAL_WIDTH_FACTOR * rect2.size.width) / textRun2.charCount;\n\n const rect1Left = rect1.origin.x - averageWidth1;\n const rect1Right = rect1.origin.x + rect1.size.width + averageWidth1;\n const rect2Left = rect2.origin.x - averageWidth2;\n const rect2Right = rect2.origin.x + rect2.size.width + averageWidth2;\n\n return rect1Left < rect2Right && rect1Right > rect2Left;\n}\n\n/**\n * Merge adjacent rectangles based on proximity and overlap (similar to Chromium's algorithm)\n */\nexport function mergeAdjacentRects(textRuns: TextRunInfo[]): Rect[] {\n const results: Rect[] = [];\n let previousTextRun: TextRunInfo | null = null;\n let currentRect: Rect | null = null;\n\n for (const textRun of textRuns) {\n if (previousTextRun && currentRect) {\n if (shouldMergeHorizontalRects(previousTextRun, textRun)) {\n currentRect = rectUnion(currentRect, textRun.rect);\n } else {\n results.push(currentRect);\n currentRect = textRun.rect;\n }\n } else {\n currentRect = textRun.rect;\n }\n previousTextRun = textRun;\n }\n\n if (currentRect && !rectIsEmpty(currentRect)) {\n results.push(currentRect);\n }\n\n return results;\n}\n","import {\n BasePlugin,\n PluginRegistry,\n REFRESH_PAGES,\n SET_DOCUMENT,\n createBehaviorEmitter,\n createEmitter,\n} from '@embedpdf/core';\nimport {\n PdfPageGeometry,\n Rect,\n PdfTask,\n PdfTaskHelper,\n PdfErrorCode,\n ignore,\n PageTextSlice,\n Task,\n Position,\n} from '@embedpdf/models';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nimport {\n cachePageGeometry,\n setSelection,\n SelectionAction,\n endSelection,\n startSelection,\n clearSelection,\n reset,\n setRects,\n setSlices,\n} from './actions';\nimport * as selector from './selectors';\nimport {\n SelectionCapability,\n SelectionPluginConfig,\n SelectionRangeX,\n SelectionState,\n RegisterSelectionOnPageOptions,\n SelectionRectsCallback,\n} from './types';\nimport { sliceBounds, rectsWithinSlice, glyphAt } from './utils';\n\nexport class SelectionPlugin extends BasePlugin<\n SelectionPluginConfig,\n SelectionCapability,\n SelectionState,\n SelectionAction\n> {\n static readonly id = 'selection' as const;\n\n /** Modes that should trigger text-selection logic */\n private enabledModes = new Set<string>(['pointerMode']);\n\n /* interactive state */\n private selecting = false;\n private anchor?: { page: number; index: number };\n\n /** Page callbacks for rect updates */\n private pageCallbacks = new Map<number, (data: SelectionRectsCallback) => void>();\n\n private readonly selChange$ = createBehaviorEmitter<SelectionState['selection']>();\n private readonly textRetrieved$ = createBehaviorEmitter<string[]>();\n private readonly copyToClipboard$ = createEmitter<string>();\n private readonly beginSelection$ = createEmitter<{ page: number; index: number }>();\n private readonly endSelection$ = createEmitter<void>();\n\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action) => {\n this.dispatch(reset());\n this.notifyAllPages();\n });\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => {\n const tasks = action.payload.map((pageIdx) => this.getNewPageGeometryAndCache(pageIdx));\n Task.all(tasks).wait(() => {\n // Notify affected pages about geometry updates\n action.payload.forEach((pageIdx) => {\n this.notifyPage(pageIdx);\n });\n }, ignore);\n });\n }\n\n /* ── life-cycle ────────────────────────────────────────── */\n async initialize() {}\n async destroy() {\n this.selChange$.clear();\n }\n\n /* ── capability exposed to UI / other plugins ─────────── */\n buildCapability(): SelectionCapability {\n return {\n getGeometry: (p) => this.getOrLoadGeometry(p),\n getFormattedSelection: () => selector.getFormattedSelection(this.state),\n getFormattedSelectionForPage: (p) => selector.getFormattedSelectionForPage(this.state, p),\n getHighlightRectsForPage: (p) => selector.selectRectsForPage(this.state, p),\n getHighlightRects: () => this.state.rects,\n getBoundingRectForPage: (p) => selector.selectBoundingRectForPage(this.state, p),\n getBoundingRects: () => selector.selectBoundingRectsForAllPages(this.state),\n begin: (p, i) => this.beginSelection(p, i),\n update: (p, i) => this.updateSelection(p, i),\n end: () => this.endSelection(),\n clear: () => this.clearSelection(),\n onCopyToClipboard: this.copyToClipboard$.on,\n onSelectionChange: this.selChange$.on,\n onTextRetrieved: this.textRetrieved$.on,\n onBeginSelection: this.beginSelection$.on,\n onEndSelection: this.endSelection$.on,\n getSelectedText: () => this.getSelectedText(),\n copyToClipboard: () => this.copyToClipboard(),\n enableForMode: (id: string) => this.enabledModes.add(id),\n isEnabledForMode: (id: string) => this.enabledModes.has(id),\n getState: () => this.state,\n registerSelectionOnPage: (opts) => this.registerSelectionOnPage(opts),\n };\n }\n\n public registerSelectionOnPage(opts: RegisterSelectionOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'SelectionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, text selection disabled',\n );\n return () => {};\n }\n\n const { pageIndex, onRectsChange } = opts;\n\n // Track this callback for the page\n this.pageCallbacks.set(pageIndex, onRectsChange);\n\n const geoTask = this.getOrLoadGeometry(pageIndex);\n\n // Send initial state\n onRectsChange({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n\n const handlers: PointerEventHandlersWithLifecycle<PointerEvent> = {\n onPointerDown: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Clear the selection\n this.clearSelection();\n\n // Get geometry from cache (or load if needed)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n if (g !== -1) {\n this.beginSelection(pageIndex, g);\n }\n }\n },\n onPointerMove: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Get cached geometry (should be instant if already loaded)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n\n // Update cursor\n if (g !== -1) {\n this.interactionManagerCapability?.setCursor('selection-text', 'text', 10);\n } else {\n this.interactionManagerCapability?.removeCursor('selection-text');\n }\n\n // Update selection if we're selecting\n if (this.selecting && g !== -1) {\n this.updateSelection(pageIndex, g);\n }\n }\n },\n onPointerUp: (_point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.endSelection();\n },\n onHandlerActiveEnd: (modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.clearSelection();\n },\n };\n\n // Register the handlers with interaction manager\n const unregisterHandlers = this.interactionManagerCapability.registerAlways({\n scope: { type: 'page', pageIndex },\n handlers,\n });\n\n // Return cleanup function\n return () => {\n unregisterHandlers();\n this.pageCallbacks.delete(pageIndex);\n geoTask.abort({ code: PdfErrorCode.Cancelled, message: 'Cleanup' });\n };\n }\n\n private notifyPage(pageIndex: number) {\n const callback = this.pageCallbacks.get(pageIndex);\n if (callback) {\n const mode = this.interactionManagerCapability?.getActiveMode();\n if (mode === 'pointerMode') {\n callback({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n } else {\n callback({ rects: [], boundingRect: null });\n }\n }\n }\n\n private notifyAllPages() {\n this.pageCallbacks.forEach((_, pageIndex) => {\n this.notifyPage(pageIndex);\n });\n }\n\n private getNewPageGeometryAndCache(pageIdx: number): PdfTask<PdfPageGeometry> {\n if (!this.coreState.core.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Doc Not Found' });\n const page = this.coreState.core.document.pages.find((p) => p.index === pageIdx)!;\n const task = this.engine.getPageGeometry(this.coreState.core.document, page);\n task.wait((geo) => {\n this.dispatch(cachePageGeometry(pageIdx, geo));\n }, ignore);\n return task;\n }\n\n /* ── geometry cache ───────────────────────────────────── */\n private getOrLoadGeometry(pageIdx: number): PdfTask<PdfPageGeometry> {\n const cached = this.state.geometry[pageIdx];\n if (cached) return PdfTaskHelper.resolve(cached);\n\n return this.getNewPageGeometryAndCache(pageIdx);\n }\n\n /* ── selection state updates ───────────────────────────── */\n private beginSelection(page: number, index: number) {\n this.selecting = true;\n this.anchor = { page, index };\n this.dispatch(startSelection());\n this.beginSelection$.emit({ page, index });\n }\n\n private endSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(endSelection());\n this.endSelection$.emit();\n }\n\n private clearSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(clearSelection());\n this.selChange$.emit(null);\n this.notifyAllPages();\n }\n\n private updateSelection(page: number, index: number) {\n if (!this.selecting || !this.anchor) return;\n\n const a = this.anchor;\n const forward = page > a.page || (page === a.page && index >= a.index);\n\n const start = forward ? a : { page, index };\n const end = forward ? { page, index } : a;\n\n const range = { start, end };\n this.dispatch(setSelection(range));\n this.updateRectsAndSlices(range);\n this.selChange$.emit(range);\n\n // Notify affected pages\n for (let p = range.start.page; p <= range.end.page; p++) {\n this.notifyPage(p);\n }\n }\n\n private updateRectsAndSlices(range: SelectionRangeX) {\n const allRects: Record<number, Rect[]> = {};\n const allSlices: Record<number, { start: number; count: number }> = {};\n\n for (let p = range.start.page; p <= range.end.page; p++) {\n const geo = this.state.geometry[p];\n const sb = sliceBounds(range, geo, p);\n if (!sb) continue;\n\n allRects[p] = rectsWithinSlice(geo!, sb.from, sb.to);\n allSlices[p] = { start: sb.from, count: sb.to - sb.from + 1 };\n }\n\n this.dispatch(setRects(allRects));\n this.dispatch(setSlices(allSlices));\n }\n\n private getSelectedText(): PdfTask<string[]> {\n if (!this.coreState.core.document || !this.state.selection) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Doc Not Found or No Selection',\n });\n }\n\n const sel = this.state.selection;\n const req: PageTextSlice[] = [];\n\n for (let p = sel.start.page; p <= sel.end.page; p++) {\n const s = this.state.slices[p];\n if (s) req.push({ pageIndex: p, charIndex: s.start, charCount: s.count });\n }\n\n if (req.length === 0) return PdfTaskHelper.resolve([] as string[]);\n\n const task = this.engine.getTextSlices(this.coreState.core.document, req);\n\n // Emit the text when it's retrieved\n task.wait((text) => {\n this.textRetrieved$.emit(text);\n }, ignore);\n\n return task;\n }\n\n private copyToClipboard() {\n const text = this.getSelectedText();\n text.wait((text) => {\n this.copyToClipboard$.emit(text.join('\\n'));\n }, ignore);\n }\n}\n","import { SelectionState } from './types';\nimport {\n SelectionAction,\n CACHE_PAGE_GEOMETRY,\n SET_SELECTION,\n START_SELECTION,\n END_SELECTION,\n CLEAR_SELECTION,\n RESET,\n SET_SLICES,\n SET_RECTS,\n} from './actions';\n\nexport const initialState: SelectionState = {\n geometry: {},\n rects: {},\n slices: {},\n selection: null,\n active: false,\n selecting: false,\n};\n\nexport const selectionReducer = (state = initialState, action: SelectionAction): SelectionState => {\n switch (action.type) {\n case CACHE_PAGE_GEOMETRY: {\n const { page, geo } = action.payload;\n return { ...state, geometry: { ...state.geometry, [page]: geo } };\n }\n case SET_SELECTION:\n return { ...state, selection: action.payload, active: true };\n case START_SELECTION:\n return { ...state, selecting: true, selection: null, rects: {} };\n case END_SELECTION:\n return { ...state, selecting: false };\n case CLEAR_SELECTION:\n return { ...state, selecting: false, selection: null, rects: {}, active: false };\n case SET_RECTS:\n return { ...state, rects: action.payload };\n case SET_SLICES:\n return { ...state, slices: action.payload };\n case RESET:\n return initialState;\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, SELECTION_PLUGIN_ID } from './manifest';\nimport { SelectionPluginConfig, SelectionState } from './types';\n\nimport { SelectionPlugin } from './selection-plugin';\nimport { SelectionAction } from './actions';\nimport { selectionReducer, initialState } from './reducer';\n\nexport const SelectionPluginPackage: PluginPackage<\n SelectionPlugin,\n SelectionPluginConfig,\n SelectionState,\n SelectionAction\n> = {\n manifest,\n create: (registry) => new SelectionPlugin(SELECTION_PLUGIN_ID, registry),\n reducer: selectionReducer,\n initialState,\n};\n\nexport * from './selection-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './utils';\n"],"names":["boundingRect","selector.getFormattedSelection","selector.getFormattedSelectionForPage","selector.selectRectsForPage","selector.selectBoundingRectForPage","selector.selectBoundingRectsForAllPages","text"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/utils.ts","../src/lib/selection-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { SelectionPluginConfig } from './types';\n\nexport const SELECTION_PLUGIN_ID = 'selection';\n\nexport const manifest: PluginManifest<SelectionPluginConfig> = {\n id: SELECTION_PLUGIN_ID,\n name: 'Selection Plugin',\n version: '1.0.0',\n provides: ['selection'],\n requires: ['interaction-manager'],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { PdfPageGeometry, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\nexport const CACHE_PAGE_GEOMETRY = 'CACHE_PAGE_GEOMETRY';\nexport const SET_SELECTION = 'SET_SELECTION';\nexport const START_SELECTION = 'START_SELECTION';\nexport const END_SELECTION = 'END_SELECTION';\nexport const CLEAR_SELECTION = 'CLEAR_SELECTION';\nexport const SET_RECTS = 'SET_RECTS';\nexport const SET_SLICES = 'SET_SLICES';\nexport const RESET = 'RESET';\n\nexport interface CachePageGeometryAction extends Action {\n type: typeof CACHE_PAGE_GEOMETRY;\n payload: { page: number; geo: PdfPageGeometry };\n}\nexport interface SetSelectionAction extends Action {\n type: typeof SET_SELECTION;\n payload: SelectionRangeX | null;\n}\n\nexport interface StartSelectionAction extends Action {\n type: typeof START_SELECTION;\n}\n\nexport interface EndSelectionAction extends Action {\n type: typeof END_SELECTION;\n}\n\nexport interface ClearSelectionAction extends Action {\n type: typeof CLEAR_SELECTION;\n}\n\nexport interface SetRectsAction extends Action {\n type: typeof SET_RECTS;\n payload: Record<number, Rect[]>;\n}\n\nexport interface SetSlicesAction extends Action {\n type: typeof SET_SLICES;\n payload: Record<number, { start: number; count: number }>;\n}\n\nexport interface ResetAction extends Action {\n type: typeof RESET;\n}\n\nexport type SelectionAction =\n | CachePageGeometryAction\n | SetSelectionAction\n | StartSelectionAction\n | EndSelectionAction\n | ClearSelectionAction\n | SetRectsAction\n | SetSlicesAction\n | ResetAction;\n\nexport const cachePageGeometry = (page: number, geo: PdfPageGeometry): CachePageGeometryAction => ({\n type: CACHE_PAGE_GEOMETRY,\n payload: { page, geo },\n});\n\nexport const setSelection = (sel: SelectionRangeX): SetSelectionAction => ({\n type: SET_SELECTION,\n payload: sel,\n});\n\nexport const startSelection = (): StartSelectionAction => ({ type: START_SELECTION });\n\nexport const endSelection = (): EndSelectionAction => ({ type: END_SELECTION });\n\nexport const clearSelection = (): ClearSelectionAction => ({ type: CLEAR_SELECTION });\n\nexport const setRects = (allRects: Record<number, Rect[]>): SetRectsAction => ({\n type: SET_RECTS,\n payload: allRects,\n});\n\nexport const setSlices = (\n slices: Record<number, { start: number; count: number }>,\n): SetSlicesAction => ({ type: SET_SLICES, payload: slices });\n\nexport const reset = (): ResetAction => ({ type: RESET });\n","import { Rect, boundingRect } from '@embedpdf/models';\nimport { FormattedSelection, SelectionState } from './types';\n\nexport function selectRectsForPage(state: SelectionState, page: number) {\n return state.rects[page] ?? [];\n}\n\nexport function selectBoundingRectForPage(state: SelectionState, page: number) {\n return boundingRect(selectRectsForPage(state, page));\n}\n\nexport function selectRectsAndBoundingRectForPage(state: SelectionState, page: number) {\n return {\n rects: selectRectsForPage(state, page),\n boundingRect: selectBoundingRectForPage(state, page),\n };\n}\n\nexport function selectBoundingRectsForAllPages(state: SelectionState) {\n const out: { page: number; rect: Rect }[] = [];\n const rectMap = state.rects;\n\n for (const key in rectMap) {\n const page = Number(key);\n const bRect = boundingRect(rectMap[page]);\n if (bRect) out.push({ page, rect: bRect });\n }\n return out;\n}\n\nexport function getFormattedSelectionForPage(\n state: SelectionState,\n page: number,\n): FormattedSelection | null {\n const segmentRects = state.rects[page] || [];\n if (segmentRects.length === 0) return null;\n const boundingRect = selectBoundingRectForPage(state, page);\n if (!boundingRect) return null;\n return { pageIndex: page, rect: boundingRect, segmentRects };\n}\n\nexport function getFormattedSelection(state: SelectionState) {\n const result: FormattedSelection[] = [];\n\n // Get all pages that have rects\n const pages = Object.keys(state.rects).map(Number);\n\n for (const pageIndex of pages) {\n const segmentRects = state.rects[pageIndex] || [];\n\n if (segmentRects.length === 0) continue;\n\n // Calculate bounding rect for this page\n const boundingRect = selectBoundingRectForPage(state, pageIndex);\n\n if (boundingRect) {\n result.push({\n pageIndex,\n rect: boundingRect,\n segmentRects,\n });\n }\n }\n\n return result;\n}\n","import { PdfPageGeometry, Position, Rect } from '@embedpdf/models';\nimport { SelectionRangeX } from './types';\n\n/**\n * Hit-test helper using runs\n * @param geo - page geometry\n * @param pt - point\n * @returns glyph index\n */\nexport function glyphAt(geo: PdfPageGeometry, pt: Position) {\n for (const run of geo.runs) {\n const inRun =\n pt.y >= run.rect.y &&\n pt.y <= run.rect.y + run.rect.height &&\n pt.x >= run.rect.x &&\n pt.x <= run.rect.x + run.rect.width;\n\n if (!inRun) continue;\n\n // Simply check if the point is within any glyph's bounding box\n const rel = run.glyphs.findIndex(\n (g) => pt.x >= g.x && pt.x <= g.x + g.width && pt.y >= g.y && pt.y <= g.y + g.height,\n );\n\n if (rel !== -1) {\n return run.charStart + rel;\n }\n }\n return -1;\n}\n\n/**\n * Helper: min/max glyph indices on `page` for current sel\n * @param sel - selection range\n * @param geo - page geometry\n * @param page - page index\n * @returns { from: number; to: number } | null\n */\nexport function sliceBounds(\n sel: SelectionRangeX | null,\n geo: PdfPageGeometry | undefined,\n page: number,\n): { from: number; to: number } | null {\n if (!sel || !geo) return null;\n if (page < sel.start.page || page > sel.end.page) return null;\n\n const from = page === sel.start.page ? sel.start.index : 0;\n\n const lastRun = geo.runs[geo.runs.length - 1];\n const lastCharOnPage = lastRun.charStart + lastRun.glyphs.length - 1;\n\n const to = page === sel.end.page ? sel.end.index : lastCharOnPage;\n\n return { from, to };\n}\n\n/**\n * Helper: build rects for a slice of the page\n * @param geo - page geometry\n * @param from - from index\n * @param to - to index\n * @param merge - whether to merge adjacent rects (default: true)\n * @returns rects\n */\nexport function rectsWithinSlice(\n geo: PdfPageGeometry,\n from: number,\n to: number,\n merge: boolean = true,\n): Rect[] {\n const textRuns: TextRunInfo[] = [];\n\n for (const run of geo.runs) {\n const runStart = run.charStart;\n const runEnd = runStart + run.glyphs.length - 1;\n if (runEnd < from || runStart > to) continue;\n\n const sIdx = Math.max(from, runStart) - runStart;\n const eIdx = Math.min(to, runEnd) - runStart;\n\n let minX = Infinity,\n maxX = -Infinity;\n let minY = Infinity,\n maxY = -Infinity;\n let charCount = 0;\n\n for (let i = sIdx; i <= eIdx; i++) {\n const g = run.glyphs[i];\n if (g.flags === 2) continue; // empty glyph\n\n minX = Math.min(minX, g.x);\n maxX = Math.max(maxX, g.x + g.width);\n minY = Math.min(minY, g.y);\n maxY = Math.max(maxY, g.y + g.height);\n charCount++;\n }\n\n if (minX !== Infinity && charCount > 0) {\n textRuns.push({\n rect: {\n origin: { x: minX, y: minY },\n size: { width: maxX - minX, height: maxY - minY },\n },\n charCount,\n });\n }\n }\n\n // If merge is false, just return the individual rects\n if (!merge) {\n return textRuns.map((run) => run.rect);\n }\n\n // Otherwise merge adjacent rects\n return mergeAdjacentRects(textRuns);\n}\n\n/**\n * ============================================================================\n * Rectangle Merging Algorithm\n * ============================================================================\n *\n * The following code is adapted from Chromium's PDF text selection implementation.\n *\n * Copyright 2010 The Chromium Authors\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file: https://source.chromium.org/chromium/chromium/src/+/main:LICENSE\n *\n * Original source:\n * https://source.chromium.org/chromium/chromium/src/+/main:pdf/pdfium/pdfium_range.cc\n *\n * Adapted for TypeScript and this project's Rect/geometry types.\n */\n\n/**\n * Text run info for rect merging (similar to Chromium's ScreenRectTextRunInfo)\n */\nexport interface TextRunInfo {\n rect: Rect;\n charCount: number;\n}\n\n/**\n * Helper functions for Rect operations\n */\nexport function rectUnion(rect1: Rect, rect2: Rect): Rect {\n const left = Math.min(rect1.origin.x, rect2.origin.x);\n const top = Math.min(rect1.origin.y, rect2.origin.y);\n const right = Math.max(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.max(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n return {\n origin: { x: left, y: top },\n size: { width: right - left, height: bottom - top },\n };\n}\n\nexport function rectIntersect(rect1: Rect, rect2: Rect): Rect {\n const left = Math.max(rect1.origin.x, rect2.origin.x);\n const top = Math.max(rect1.origin.y, rect2.origin.y);\n const right = Math.min(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);\n const bottom = Math.min(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);\n\n const width = Math.max(0, right - left);\n const height = Math.max(0, bottom - top);\n\n return {\n origin: { x: left, y: top },\n size: { width, height },\n };\n}\n\nexport function rectIsEmpty(rect: Rect): boolean {\n return rect.size.width <= 0 || rect.size.height <= 0;\n}\n\n/**\n * Returns a ratio between [0, 1] representing vertical overlap\n */\nexport function getVerticalOverlap(rect1: Rect, rect2: Rect): number {\n if (rectIsEmpty(rect1) || rectIsEmpty(rect2)) return 0;\n\n const unionRect = rectUnion(rect1, rect2);\n\n if (unionRect.size.height === rect1.size.height || unionRect.size.height === rect2.size.height) {\n return 1.0;\n }\n\n const intersectRect = rectIntersect(rect1, rect2);\n return intersectRect.size.height / unionRect.size.height;\n}\n\n/**\n * Returns true if there is sufficient horizontal and vertical overlap\n */\nexport function shouldMergeHorizontalRects(textRun1: TextRunInfo, textRun2: TextRunInfo): boolean {\n const VERTICAL_OVERLAP_THRESHOLD = 0.8;\n const rect1 = textRun1.rect;\n const rect2 = textRun2.rect;\n\n if (getVerticalOverlap(rect1, rect2) < VERTICAL_OVERLAP_THRESHOLD) {\n return false;\n }\n\n const HORIZONTAL_WIDTH_FACTOR = 1.0;\n const averageWidth1 = (HORIZONTAL_WIDTH_FACTOR * rect1.size.width) / textRun1.charCount;\n const averageWidth2 = (HORIZONTAL_WIDTH_FACTOR * rect2.size.width) / textRun2.charCount;\n\n const rect1Left = rect1.origin.x - averageWidth1;\n const rect1Right = rect1.origin.x + rect1.size.width + averageWidth1;\n const rect2Left = rect2.origin.x - averageWidth2;\n const rect2Right = rect2.origin.x + rect2.size.width + averageWidth2;\n\n return rect1Left < rect2Right && rect1Right > rect2Left;\n}\n\n/**\n * Merge adjacent rectangles based on proximity and overlap (similar to Chromium's algorithm)\n */\nexport function mergeAdjacentRects(textRuns: TextRunInfo[]): Rect[] {\n const results: Rect[] = [];\n let previousTextRun: TextRunInfo | null = null;\n let currentRect: Rect | null = null;\n\n for (const textRun of textRuns) {\n if (previousTextRun && currentRect) {\n if (shouldMergeHorizontalRects(previousTextRun, textRun)) {\n currentRect = rectUnion(currentRect, textRun.rect);\n } else {\n results.push(currentRect);\n currentRect = textRun.rect;\n }\n } else {\n currentRect = textRun.rect;\n }\n previousTextRun = textRun;\n }\n\n if (currentRect && !rectIsEmpty(currentRect)) {\n results.push(currentRect);\n }\n\n return results;\n}\n","import {\n BasePlugin,\n PluginRegistry,\n REFRESH_PAGES,\n SET_DOCUMENT,\n createBehaviorEmitter,\n createEmitter,\n} from '@embedpdf/core';\nimport {\n PdfPageGeometry,\n Rect,\n PdfTask,\n PdfTaskHelper,\n PdfErrorCode,\n ignore,\n PageTextSlice,\n Task,\n Position,\n} from '@embedpdf/models';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nimport {\n cachePageGeometry,\n setSelection,\n SelectionAction,\n endSelection,\n startSelection,\n clearSelection,\n reset,\n setRects,\n setSlices,\n} from './actions';\nimport * as selector from './selectors';\nimport {\n SelectionCapability,\n SelectionPluginConfig,\n SelectionRangeX,\n SelectionState,\n RegisterSelectionOnPageOptions,\n SelectionRectsCallback,\n} from './types';\nimport { sliceBounds, rectsWithinSlice, glyphAt } from './utils';\n\nexport class SelectionPlugin extends BasePlugin<\n SelectionPluginConfig,\n SelectionCapability,\n SelectionState,\n SelectionAction\n> {\n static readonly id = 'selection' as const;\n\n /** Modes that should trigger text-selection logic */\n private enabledModes = new Set<string>(['pointerMode']);\n\n /* interactive state */\n private selecting = false;\n private anchor?: { page: number; index: number };\n\n /** Page callbacks for rect updates */\n private pageCallbacks = new Map<number, (data: SelectionRectsCallback) => void>();\n\n private readonly selChange$ = createBehaviorEmitter<SelectionState['selection']>();\n private readonly textRetrieved$ = createBehaviorEmitter<string[]>();\n private readonly copyToClipboard$ = createEmitter<string>();\n private readonly beginSelection$ = createEmitter<{ page: number; index: number }>();\n private readonly endSelection$ = createEmitter<void>();\n\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action) => {\n this.dispatch(reset());\n this.notifyAllPages();\n });\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => {\n const tasks = action.payload.map((pageIdx) => this.getNewPageGeometryAndCache(pageIdx));\n Task.all(tasks).wait(() => {\n // Notify affected pages about geometry updates\n action.payload.forEach((pageIdx) => {\n this.notifyPage(pageIdx);\n });\n }, ignore);\n });\n }\n\n /* ── life-cycle ────────────────────────────────────────── */\n async initialize() {}\n async destroy() {\n this.selChange$.clear();\n }\n\n /* ── capability exposed to UI / other plugins ─────────── */\n buildCapability(): SelectionCapability {\n return {\n getFormattedSelection: () => selector.getFormattedSelection(this.state),\n getFormattedSelectionForPage: (p) => selector.getFormattedSelectionForPage(this.state, p),\n getHighlightRectsForPage: (p) => selector.selectRectsForPage(this.state, p),\n getHighlightRects: () => this.state.rects,\n getBoundingRectForPage: (p) => selector.selectBoundingRectForPage(this.state, p),\n getBoundingRects: () => selector.selectBoundingRectsForAllPages(this.state),\n onCopyToClipboard: this.copyToClipboard$.on,\n onSelectionChange: this.selChange$.on,\n onTextRetrieved: this.textRetrieved$.on,\n onBeginSelection: this.beginSelection$.on,\n onEndSelection: this.endSelection$.on,\n getSelectedText: () => this.getSelectedText(),\n copyToClipboard: () => this.copyToClipboard(),\n enableForMode: (id: string) => this.enabledModes.add(id),\n isEnabledForMode: (id: string) => this.enabledModes.has(id),\n getState: () => this.state,\n };\n }\n\n public registerSelectionOnPage(opts: RegisterSelectionOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'SelectionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, text selection disabled',\n );\n return () => {};\n }\n\n const { pageIndex, onRectsChange } = opts;\n\n // Track this callback for the page\n this.pageCallbacks.set(pageIndex, onRectsChange);\n\n const geoTask = this.getOrLoadGeometry(pageIndex);\n\n // Send initial state\n onRectsChange({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n\n const handlers: PointerEventHandlersWithLifecycle<PointerEvent> = {\n onPointerDown: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Clear the selection\n this.clearSelection();\n\n // Get geometry from cache (or load if needed)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n if (g !== -1) {\n this.beginSelection(pageIndex, g);\n }\n }\n },\n onPointerMove: (point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n\n // Get cached geometry (should be instant if already loaded)\n const cached = this.state.geometry[pageIndex];\n if (cached) {\n const g = glyphAt(cached, point);\n\n // Update cursor\n if (g !== -1) {\n this.interactionManagerCapability?.setCursor('selection-text', 'text', 10);\n } else {\n this.interactionManagerCapability?.removeCursor('selection-text');\n }\n\n // Update selection if we're selecting\n if (this.selecting && g !== -1) {\n this.updateSelection(pageIndex, g);\n }\n }\n },\n onPointerUp: (_point: Position, _evt, modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.endSelection();\n },\n onHandlerActiveEnd: (modeId) => {\n if (!this.enabledModes.has(modeId)) return;\n this.clearSelection();\n },\n };\n\n // Register the handlers with interaction manager\n const unregisterHandlers = this.interactionManagerCapability.registerAlways({\n scope: { type: 'page', pageIndex },\n handlers,\n });\n\n // Return cleanup function\n return () => {\n unregisterHandlers();\n this.pageCallbacks.delete(pageIndex);\n geoTask.abort({ code: PdfErrorCode.Cancelled, message: 'Cleanup' });\n };\n }\n\n private notifyPage(pageIndex: number) {\n const callback = this.pageCallbacks.get(pageIndex);\n if (callback) {\n const mode = this.interactionManagerCapability?.getActiveMode();\n if (mode === 'pointerMode') {\n callback({\n rects: selector.selectRectsForPage(this.state, pageIndex),\n boundingRect: selector.selectBoundingRectForPage(this.state, pageIndex),\n });\n } else {\n callback({ rects: [], boundingRect: null });\n }\n }\n }\n\n private notifyAllPages() {\n this.pageCallbacks.forEach((_, pageIndex) => {\n this.notifyPage(pageIndex);\n });\n }\n\n private getNewPageGeometryAndCache(pageIdx: number): PdfTask<PdfPageGeometry> {\n if (!this.coreState.core.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Doc Not Found' });\n const page = this.coreState.core.document.pages.find((p) => p.index === pageIdx)!;\n const task = this.engine.getPageGeometry(this.coreState.core.document, page);\n task.wait((geo) => {\n this.dispatch(cachePageGeometry(pageIdx, geo));\n }, ignore);\n return task;\n }\n\n /* ── geometry cache ───────────────────────────────────── */\n private getOrLoadGeometry(pageIdx: number): PdfTask<PdfPageGeometry> {\n const cached = this.state.geometry[pageIdx];\n if (cached) return PdfTaskHelper.resolve(cached);\n\n return this.getNewPageGeometryAndCache(pageIdx);\n }\n\n /* ── selection state updates ───────────────────────────── */\n private beginSelection(page: number, index: number) {\n this.selecting = true;\n this.anchor = { page, index };\n this.dispatch(startSelection());\n this.beginSelection$.emit({ page, index });\n }\n\n private endSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(endSelection());\n this.endSelection$.emit();\n }\n\n private clearSelection() {\n this.selecting = false;\n this.anchor = undefined;\n this.dispatch(clearSelection());\n this.selChange$.emit(null);\n this.notifyAllPages();\n }\n\n private updateSelection(page: number, index: number) {\n if (!this.selecting || !this.anchor) return;\n\n const a = this.anchor;\n const forward = page > a.page || (page === a.page && index >= a.index);\n\n const start = forward ? a : { page, index };\n const end = forward ? { page, index } : a;\n\n const range = { start, end };\n this.dispatch(setSelection(range));\n this.updateRectsAndSlices(range);\n this.selChange$.emit(range);\n\n // Notify affected pages\n for (let p = range.start.page; p <= range.end.page; p++) {\n this.notifyPage(p);\n }\n }\n\n private updateRectsAndSlices(range: SelectionRangeX) {\n const allRects: Record<number, Rect[]> = {};\n const allSlices: Record<number, { start: number; count: number }> = {};\n\n for (let p = range.start.page; p <= range.end.page; p++) {\n const geo = this.state.geometry[p];\n const sb = sliceBounds(range, geo, p);\n if (!sb) continue;\n\n allRects[p] = rectsWithinSlice(geo!, sb.from, sb.to);\n allSlices[p] = { start: sb.from, count: sb.to - sb.from + 1 };\n }\n\n this.dispatch(setRects(allRects));\n this.dispatch(setSlices(allSlices));\n }\n\n private getSelectedText(): PdfTask<string[]> {\n if (!this.coreState.core.document || !this.state.selection) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Doc Not Found or No Selection',\n });\n }\n\n const sel = this.state.selection;\n const req: PageTextSlice[] = [];\n\n for (let p = sel.start.page; p <= sel.end.page; p++) {\n const s = this.state.slices[p];\n if (s) req.push({ pageIndex: p, charIndex: s.start, charCount: s.count });\n }\n\n if (req.length === 0) return PdfTaskHelper.resolve([] as string[]);\n\n const task = this.engine.getTextSlices(this.coreState.core.document, req);\n\n // Emit the text when it's retrieved\n task.wait((text) => {\n this.textRetrieved$.emit(text);\n }, ignore);\n\n return task;\n }\n\n private copyToClipboard() {\n const text = this.getSelectedText();\n text.wait((text) => {\n this.copyToClipboard$.emit(text.join('\\n'));\n }, ignore);\n }\n}\n","import { SelectionState } from './types';\nimport {\n SelectionAction,\n CACHE_PAGE_GEOMETRY,\n SET_SELECTION,\n START_SELECTION,\n END_SELECTION,\n CLEAR_SELECTION,\n RESET,\n SET_SLICES,\n SET_RECTS,\n} from './actions';\n\nexport const initialState: SelectionState = {\n geometry: {},\n rects: {},\n slices: {},\n selection: null,\n active: false,\n selecting: false,\n};\n\nexport const selectionReducer = (state = initialState, action: SelectionAction): SelectionState => {\n switch (action.type) {\n case CACHE_PAGE_GEOMETRY: {\n const { page, geo } = action.payload;\n return { ...state, geometry: { ...state.geometry, [page]: geo } };\n }\n case SET_SELECTION:\n return { ...state, selection: action.payload, active: true };\n case START_SELECTION:\n return { ...state, selecting: true, selection: null, rects: {} };\n case END_SELECTION:\n return { ...state, selecting: false };\n case CLEAR_SELECTION:\n return { ...state, selecting: false, selection: null, rects: {}, active: false };\n case SET_RECTS:\n return { ...state, rects: action.payload };\n case SET_SLICES:\n return { ...state, slices: action.payload };\n case RESET:\n return initialState;\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, SELECTION_PLUGIN_ID } from './manifest';\nimport { SelectionPluginConfig, SelectionState } from './types';\n\nimport { SelectionPlugin } from './selection-plugin';\nimport { SelectionAction } from './actions';\nimport { selectionReducer, initialState } from './reducer';\n\nexport const SelectionPluginPackage: PluginPackage<\n SelectionPlugin,\n SelectionPluginConfig,\n SelectionState,\n SelectionAction\n> = {\n manifest,\n create: (registry) => new SelectionPlugin(SELECTION_PLUGIN_ID, registry),\n reducer: selectionReducer,\n initialState,\n};\n\nexport * from './selection-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './utils';\n"],"names":["boundingRect","selector.getFormattedSelection","selector.getFormattedSelectionForPage","selector.selectRectsForPage","selector.selectBoundingRectForPage","selector.selectBoundingRectsForAllPages","text"],"mappings":"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"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -37,7 +37,6 @@ export interface RegisterSelectionOnPageOptions {
|
|
|
37
37
|
onRectsChange: (data: SelectionRectsCallback) => void;
|
|
38
38
|
}
|
|
39
39
|
export interface SelectionCapability {
|
|
40
|
-
getGeometry(page: number): PdfTask<PdfPageGeometry>;
|
|
41
40
|
getFormattedSelection(): FormattedSelection[];
|
|
42
41
|
getFormattedSelectionForPage(page: number): FormattedSelection | null;
|
|
43
42
|
getHighlightRectsForPage(page: number): Rect[];
|
|
@@ -49,10 +48,6 @@ export interface SelectionCapability {
|
|
|
49
48
|
}[];
|
|
50
49
|
getSelectedText(): PdfTask<string[]>;
|
|
51
50
|
copyToClipboard(): void;
|
|
52
|
-
begin(page: number, glyphIdx: number): void;
|
|
53
|
-
update(page: number, glyphIdx: number): void;
|
|
54
|
-
end(): void;
|
|
55
|
-
clear(): void;
|
|
56
51
|
onSelectionChange: EventHook<SelectionRangeX | null>;
|
|
57
52
|
onTextRetrieved: EventHook<string[]>;
|
|
58
53
|
onCopyToClipboard: EventHook<string>;
|
|
@@ -68,6 +63,4 @@ export interface SelectionCapability {
|
|
|
68
63
|
isEnabledForMode(modeId: string): boolean;
|
|
69
64
|
/** Get the current state of the selection plugin. */
|
|
70
65
|
getState(): SelectionState;
|
|
71
|
-
/** Register selection handlers for a specific page */
|
|
72
|
-
registerSelectionOnPage: (opts: RegisterSelectionOnPageOptions) => () => void;
|
|
73
66
|
}
|
package/dist/preact/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),i=require("preact/jsx-runtime");require("preact");const o=require("preact/hooks"),r=require("@embedpdf/core/preact"),n=()=>r.useCapability(t.SelectionPlugin.id);function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),i=require("preact/jsx-runtime");require("preact");const o=require("preact/hooks"),r=require("@embedpdf/core/preact"),n=()=>r.useCapability(t.SelectionPlugin.id),l=()=>r.usePlugin(t.SelectionPlugin.id);function s(){const{provides:e}=n();return o.useEffect((()=>{if(e)return e.onCopyToClipboard((e=>{navigator.clipboard.writeText(e)}))}),[e]),null}const u=e.createPluginPackage(t.SelectionPluginPackage).addUtility(s).build();exports.CopyToClipboard=s,exports.SelectionLayer=function({pageIndex:e,scale:t,background:r="rgba(33,150,243)"}){const{plugin:n}=l(),[s,u]=o.useState([]),[a,c]=o.useState(null);return o.useEffect((()=>{if(n)return n.registerSelectionOnPage({pageIndex:e,onRectsChange:({rects:e,boundingRect:t})=>{u(e),c(t)}})}),[n,e]),a?i.jsx("div",{style:{position:"absolute",left:a.origin.x*t,top:a.origin.y*t,width:a.size.width*t,height:a.size.height*t,mixBlendMode:"multiply",isolation:"isolate"},children:s.map(((e,o)=>i.jsx("div",{style:{position:"absolute",left:(e.origin.x-a.origin.x)*t,top:(e.origin.y-a.origin.y)*t,width:e.size.width*t,height:e.size.height*t,background:r,pointerEvents:"none"}},o)))}):null},exports.SelectionPluginPackage=u,exports.useSelectionCapability=n,exports.useSelectionPlugin=l,Object.keys(t).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})}));
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../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 } 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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const {
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../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 } 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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability, useSelectionPlugin } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!selPlugin) return;\n\n return selPlugin.registerSelectionOnPage({\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * scale,\n top: boundingRect.origin.y * scale,\n width: boundingRect.size.width * scale,\n height: boundingRect.size.height * scale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\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) * scale,\n top: (b.origin.y - boundingRect.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background,\n pointerEvents: 'none',\n }}\n />\n ))}\n </div>\n );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","CopyToClipboard","provides","sel","useEffect","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","pageIndex","scale","background","plugin","selPlugin","rects","setRects","useState","boundingRect","setBoundingRect","registerSelectionOnPage","onRectsChange","jsxRuntime","jsx","style","position","left","origin","x","top","y","width","size","height","mixBlendMode","isolation","children","map","b","i","pointerEvents"],"mappings":"+QAGaA,EAAyB,IAAMC,gBAA+BC,EAAAA,gBAAgBC,IAC9EC,EAAqB,IAAMC,YAA2BH,EAAAA,gBAAgBC,ICA5E,SAASG,IACd,MAAQC,SAAUC,GAAQR,IASnB,OAPPS,EAAAA,WAAU,KACR,GAAKD,EACE,OAAAA,EAAIE,mBAAmBC,IAClBC,UAAAC,UAAUC,UAAUH,EAAI,GACnC,GACA,CAACH,IAEG,IACT,CCNO,MAAMO,EAAyBC,EAAoBA,oBAAAC,EAA0BF,wBACjFG,WAAWZ,GACXa,yDCDI,UAAwBC,UAAEA,EAAAC,MAAWA,EAAOC,WAAAA,EAAa,qBAC9D,MAAQC,OAAQC,GAAcpB,KACvBqB,EAAOC,GAAYC,EAAAA,SAAiB,KACpCC,EAAcC,GAAmBF,EAAAA,SAAsB,MAc1D,OAZJlB,EAAAA,WAAU,KACR,GAAKe,EAEL,OAAOA,EAAUM,wBAAwB,CACvCV,YACAW,cAAe,EAAGN,MAAAA,EAAOG,aAAAA,MACvBF,EAASD,GACTI,EAAgBD,EAAY,GAE/B,GACA,CAACJ,EAAWJ,IAEVQ,EAGHI,EAAAC,IAAC,MAAA,CACCC,MAAO,CACLC,SAAU,WACVC,KAAMR,EAAaS,OAAOC,EAAIjB,EAC9BkB,IAAKX,EAAaS,OAAOG,EAAInB,EAC7BoB,MAAOb,EAAac,KAAKD,MAAQpB,EACjCsB,OAAQf,EAAac,KAAKC,OAAStB,EACnCuB,aAAc,WACdC,UAAW,WAGZC,SAAMrB,EAAAsB,KAAI,CAACC,EAAGC,IACbjB,EAAAC,IAAC,MAAA,CAECC,MAAO,CACLC,SAAU,WACVC,MAAOY,EAAEX,OAAOC,EAAIV,EAAaS,OAAOC,GAAKjB,EAC7CkB,KAAMS,EAAEX,OAAOG,EAAIZ,EAAaS,OAAOG,GAAKnB,EAC5CoB,MAAOO,EAAEN,KAAKD,MAAQpB,EACtBsB,OAAQK,EAAEN,KAAKC,OAAStB,EACxBC,aACA4B,cAAe,SARZD,OAhBa,IA8B5B"}
|
package/dist/preact/index.js
CHANGED
|
@@ -8,19 +8,19 @@ import { useCapability, usePlugin } from "@embedpdf/core/preact";
|
|
|
8
8
|
const useSelectionCapability = () => useCapability(SelectionPlugin.id);
|
|
9
9
|
const useSelectionPlugin = () => usePlugin(SelectionPlugin.id);
|
|
10
10
|
function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
11
|
-
const {
|
|
11
|
+
const { plugin: selPlugin } = useSelectionPlugin();
|
|
12
12
|
const [rects, setRects] = useState([]);
|
|
13
13
|
const [boundingRect, setBoundingRect] = useState(null);
|
|
14
14
|
useEffect(() => {
|
|
15
|
-
if (!
|
|
16
|
-
return
|
|
15
|
+
if (!selPlugin) return;
|
|
16
|
+
return selPlugin.registerSelectionOnPage({
|
|
17
17
|
pageIndex,
|
|
18
18
|
onRectsChange: ({ rects: rects2, boundingRect: boundingRect2 }) => {
|
|
19
19
|
setRects(rects2);
|
|
20
20
|
setBoundingRect(boundingRect2);
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
|
-
}, [
|
|
23
|
+
}, [selPlugin, pageIndex]);
|
|
24
24
|
if (!boundingRect) return null;
|
|
25
25
|
return /* @__PURE__ */ jsx(
|
|
26
26
|
"div",
|
package/dist/preact/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/selection-layer.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts"],"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, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const {
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/selection-layer.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts"],"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, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability, useSelectionPlugin } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!selPlugin) return;\n\n return selPlugin.registerSelectionOnPage({\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * scale,\n top: boundingRect.origin.y * scale,\n width: boundingRect.size.width * scale,\n height: boundingRect.size.height * scale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\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) * scale,\n top: (b.origin.y - boundingRect.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background,\n pointerEvents: 'none',\n }}\n />\n ))}\n </div>\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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["rects","boundingRect","BaseSelectionPluginPackage"],"mappings":";;;;;;;AAGO,MAAM,yBAAyB,MAAM,cAA+B,gBAAgB,EAAE;AACtF,MAAM,qBAAqB,MAAM,UAA2B,gBAAgB,EAAE;ACM9E,SAAS,eAAe,EAAE,WAAW,OAAO,aAAa,sBAA6B;AAC3F,QAAM,EAAE,QAAQ,UAAU,IAAI,mBAAmB;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB,CAAA,CAAE;AAC7C,QAAM,CAAC,cAAc,eAAe,IAAI,SAAsB,IAAI;AAElE,YAAU,MAAM;AACd,QAAI,CAAC,UAAW;AAEhB,WAAO,UAAU,wBAAwB;AAAA,MACvC;AAAA,MACA,eAAe,CAAC,EAAE,OAAAA,QAAO,cAAAC,oBAAmB;AAC1C,iBAASD,MAAK;AACd,wBAAgBC,aAAY;AAAA,MAAA;AAAA,IAC9B,CACD;AAAA,EAAA,GACA,CAAC,WAAW,SAAS,CAAC;AAErB,MAAA,CAAC,aAAqB,QAAA;AAGxB,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM,aAAa,OAAO,IAAI;AAAA,QAC9B,KAAK,aAAa,OAAO,IAAI;AAAA,QAC7B,OAAO,aAAa,KAAK,QAAQ;AAAA,QACjC,QAAQ,aAAa,KAAK,SAAS;AAAA,QACnC,cAAc;AAAA,QACd,WAAW;AAAA,MACb;AAAA,MAEC,UAAM,MAAA,IAAI,CAAC,GAAG,MACb;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO,EAAE,OAAO,IAAI,aAAa,OAAO,KAAK;AAAA,YAC7C,MAAM,EAAE,OAAO,IAAI,aAAa,OAAO,KAAK;AAAA,YAC5C,OAAO,EAAE,KAAK,QAAQ;AAAA,YACtB,QAAQ,EAAE,KAAK,SAAS;AAAA,YACxB;AAAA,YACA,eAAe;AAAA,UAAA;AAAA,QACjB;AAAA,QATK;AAAA,MAWR,CAAA;AAAA,IAAA;AAAA,EACH;AAEJ;ACrDO,SAAS,kBAAkB;AAChC,QAAM,EAAE,UAAU,IAAI,IAAI,uBAAuB;AAEjD,YAAU,MAAM;AACd,QAAI,CAAC,IAAK;AACH,WAAA,IAAI,kBAAkB,CAAC,SAAS;AAC3B,gBAAA,UAAU,UAAU,IAAI;AAAA,IAAA,CACnC;AAAA,EAAA,GACA,CAAC,GAAG,CAAC;AAED,SAAA;AACT;ACNO,MAAM,yBAAyB,oBAAoBC,wBAA0B,EACjF,WAAW,eAAe,EAC1B,MAAM;"}
|
package/dist/react/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),i=require("react/jsx-runtime"),o=require("react"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),i=require("react/jsx-runtime"),o=require("react"),n=require("@embedpdf/core/react"),r=()=>n.useCapability(t.SelectionPlugin.id),l=()=>n.usePlugin(t.SelectionPlugin.id);function s(){const{provides:e}=r();return o.useEffect((()=>{if(e)return e.onCopyToClipboard((e=>{navigator.clipboard.writeText(e)}))}),[e]),null}const u=e.createPluginPackage(t.SelectionPluginPackage).addUtility(s).build();exports.CopyToClipboard=s,exports.SelectionLayer=function({pageIndex:e,scale:t,background:n="rgba(33,150,243)"}){const{plugin:r}=l(),[s,u]=o.useState([]),[a,c]=o.useState(null);return o.useEffect((()=>{if(r)return r.registerSelectionOnPage({pageIndex:e,onRectsChange:({rects:e,boundingRect:t})=>{u(e),c(t)}})}),[r,e]),a?i.jsx("div",{style:{position:"absolute",left:a.origin.x*t,top:a.origin.y*t,width:a.size.width*t,height:a.size.height*t,mixBlendMode:"multiply",isolation:"isolate"},children:s.map(((e,o)=>i.jsx("div",{style:{position:"absolute",left:(e.origin.x-a.origin.x)*t,top:(e.origin.y-a.origin.y)*t,width:e.size.width*t,height:e.size.height*t,background:n,pointerEvents:"none"}},o)))}):null},exports.SelectionPluginPackage=u,exports.useSelectionCapability=r,exports.useSelectionPlugin=l,Object.keys(t).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})}));
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../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 } 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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const {
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../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 } 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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability, useSelectionPlugin } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!selPlugin) return;\n\n return selPlugin.registerSelectionOnPage({\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * scale,\n top: boundingRect.origin.y * scale,\n width: boundingRect.size.width * scale,\n height: boundingRect.size.height * scale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\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) * scale,\n top: (b.origin.y - boundingRect.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background,\n pointerEvents: 'none',\n }}\n />\n ))}\n </div>\n );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","CopyToClipboard","provides","sel","useEffect","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","pageIndex","scale","background","plugin","selPlugin","rects","setRects","useState","boundingRect","setBoundingRect","registerSelectionOnPage","onRectsChange","jsxRuntime","jsx","style","position","left","origin","x","top","y","width","size","height","mixBlendMode","isolation","children","map","b","i","pointerEvents"],"mappings":"8OAGaA,EAAyB,IAAMC,gBAA+BC,EAAAA,gBAAgBC,IAC9EC,EAAqB,IAAMC,YAA2BH,EAAAA,gBAAgBC,ICA5E,SAASG,IACd,MAAQC,SAAUC,GAAQR,IASnB,OAPPS,EAAAA,WAAU,KACR,GAAKD,EACE,OAAAA,EAAIE,mBAAmBC,IAClBC,UAAAC,UAAUC,UAAUH,EAAI,GACnC,GACA,CAACH,IAEG,IACT,CCNO,MAAMO,EAAyBC,EAAoBA,oBAAAC,EAA0BF,wBACjFG,WAAWZ,GACXa,yDCDI,UAAwBC,UAAEA,EAAAC,MAAWA,EAAOC,WAAAA,EAAa,qBAC9D,MAAQC,OAAQC,GAAcpB,KACvBqB,EAAOC,GAAYC,EAAAA,SAAiB,KACpCC,EAAcC,GAAmBF,EAAAA,SAAsB,MAc1D,OAZJlB,EAAAA,WAAU,KACR,GAAKe,EAEL,OAAOA,EAAUM,wBAAwB,CACvCV,YACAW,cAAe,EAAGN,MAAAA,EAAOG,aAAAA,MACvBF,EAASD,GACTI,EAAgBD,EAAY,GAE/B,GACA,CAACJ,EAAWJ,IAEVQ,EAGHI,EAAAC,IAAC,MAAA,CACCC,MAAO,CACLC,SAAU,WACVC,KAAMR,EAAaS,OAAOC,EAAIjB,EAC9BkB,IAAKX,EAAaS,OAAOG,EAAInB,EAC7BoB,MAAOb,EAAac,KAAKD,MAAQpB,EACjCsB,OAAQf,EAAac,KAAKC,OAAStB,EACnCuB,aAAc,WACdC,UAAW,WAGZC,SAAMrB,EAAAsB,KAAI,CAACC,EAAGC,IACbjB,EAAAC,IAAC,MAAA,CAECC,MAAO,CACLC,SAAU,WACVC,MAAOY,EAAEX,OAAOC,EAAIV,EAAaS,OAAOC,GAAKjB,EAC7CkB,KAAMS,EAAEX,OAAOG,EAAIZ,EAAaS,OAAOG,GAAKnB,EAC5CoB,MAAOO,EAAEN,KAAKD,MAAQpB,EACtBsB,OAAQK,EAAEN,KAAKC,OAAStB,EACxBC,aACA4B,cAAe,SARZD,OAhBa,IA8B5B"}
|
package/dist/react/index.js
CHANGED
|
@@ -7,19 +7,19 @@ import { useCapability, usePlugin } from "@embedpdf/core/react";
|
|
|
7
7
|
const useSelectionCapability = () => useCapability(SelectionPlugin.id);
|
|
8
8
|
const useSelectionPlugin = () => usePlugin(SelectionPlugin.id);
|
|
9
9
|
function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
10
|
-
const {
|
|
10
|
+
const { plugin: selPlugin } = useSelectionPlugin();
|
|
11
11
|
const [rects, setRects] = useState([]);
|
|
12
12
|
const [boundingRect, setBoundingRect] = useState(null);
|
|
13
13
|
useEffect(() => {
|
|
14
|
-
if (!
|
|
15
|
-
return
|
|
14
|
+
if (!selPlugin) return;
|
|
15
|
+
return selPlugin.registerSelectionOnPage({
|
|
16
16
|
pageIndex,
|
|
17
17
|
onRectsChange: ({ rects: rects2, boundingRect: boundingRect2 }) => {
|
|
18
18
|
setRects(rects2);
|
|
19
19
|
setBoundingRect(boundingRect2);
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
-
}, [
|
|
22
|
+
}, [selPlugin, pageIndex]);
|
|
23
23
|
if (!boundingRect) return null;
|
|
24
24
|
return /* @__PURE__ */ jsx(
|
|
25
25
|
"div",
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/selection-layer.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts"],"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, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const {
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/selection-layer.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts"],"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, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\nimport { useSelectionCapability, useSelectionPlugin } from '../hooks';\n\ntype Props = {\n pageIndex: number;\n scale: number;\n background?: string;\n};\n\nexport function SelectionLayer({ pageIndex, scale, background = 'rgba(33,150,243)' }: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!selPlugin) return;\n\n return selPlugin.registerSelectionOnPage({\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * scale,\n top: boundingRect.origin.y * scale,\n width: boundingRect.size.width * scale,\n height: boundingRect.size.height * scale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\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) * scale,\n top: (b.origin.y - boundingRect.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background,\n pointerEvents: 'none',\n }}\n />\n ))}\n </div>\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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["rects","boundingRect","BaseSelectionPluginPackage"],"mappings":";;;;;;AAGO,MAAM,yBAAyB,MAAM,cAA+B,gBAAgB,EAAE;AACtF,MAAM,qBAAqB,MAAM,UAA2B,gBAAgB,EAAE;ACM9E,SAAS,eAAe,EAAE,WAAW,OAAO,aAAa,sBAA6B;AAC3F,QAAM,EAAE,QAAQ,UAAU,IAAI,mBAAmB;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB,CAAA,CAAE;AAC7C,QAAM,CAAC,cAAc,eAAe,IAAI,SAAsB,IAAI;AAElE,YAAU,MAAM;AACd,QAAI,CAAC,UAAW;AAEhB,WAAO,UAAU,wBAAwB;AAAA,MACvC;AAAA,MACA,eAAe,CAAC,EAAE,OAAAA,QAAO,cAAAC,oBAAmB;AAC1C,iBAASD,MAAK;AACd,wBAAgBC,aAAY;AAAA,MAAA;AAAA,IAC9B,CACD;AAAA,EAAA,GACA,CAAC,WAAW,SAAS,CAAC;AAErB,MAAA,CAAC,aAAqB,QAAA;AAGxB,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM,aAAa,OAAO,IAAI;AAAA,QAC9B,KAAK,aAAa,OAAO,IAAI;AAAA,QAC7B,OAAO,aAAa,KAAK,QAAQ;AAAA,QACjC,QAAQ,aAAa,KAAK,SAAS;AAAA,QACnC,cAAc;AAAA,QACd,WAAW;AAAA,MACb;AAAA,MAEC,UAAM,MAAA,IAAI,CAAC,GAAG,MACb;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO,EAAE,OAAO,IAAI,aAAa,OAAO,KAAK;AAAA,YAC7C,MAAM,EAAE,OAAO,IAAI,aAAa,OAAO,KAAK;AAAA,YAC5C,OAAO,EAAE,KAAK,QAAQ;AAAA,YACtB,QAAQ,EAAE,KAAK,SAAS;AAAA,YACxB;AAAA,YACA,eAAe;AAAA,UAAA;AAAA,QACjB;AAAA,QATK;AAAA,MAWR,CAAA;AAAA,IAAA;AAAA,EACH;AAEJ;ACrDO,SAAS,kBAAkB;AAChC,QAAM,EAAE,UAAU,IAAI,IAAI,uBAAuB;AAEjD,YAAU,MAAM;AACd,QAAI,CAAC,IAAK;AACH,WAAA,IAAI,kBAAkB,CAAC,SAAS;AAC3B,gBAAA,UAAU,UAAU,IAAI;AAAA,IAAA,CACnC;AAAA,EAAA,GACA,CAAC,GAAG,CAAC;AAED,SAAA;AACT;ACNO,MAAM,yBAAyB,oBAAoBC,wBAA0B,EACjF,WAAW,eAAe,EAC1B,MAAM;"}
|
package/dist/vue/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),o=require("vue"),l=require("@embedpdf/core/vue"),i=()=>l.useCapability(t.SelectionPlugin.id),n=o.defineComponent({__name:"selection-layer",props:{pageIndex:{},scale:{},background:{default:"rgba(33, 150, 243)"}},setup(e){const t=e,{
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),o=require("vue"),l=require("@embedpdf/core/vue"),i=()=>l.useCapability(t.SelectionPlugin.id),n=()=>l.usePlugin(t.SelectionPlugin.id),a=o.defineComponent({__name:"selection-layer",props:{pageIndex:{},scale:{},background:{default:"rgba(33, 150, 243)"}},setup(e){const t=e,{plugin:l}=n(),i=o.ref([]),a=o.ref(null);let r;return o.onMounted((()=>{l.value&&(r=l.value.registerSelectionOnPage({pageIndex:t.pageIndex,onRectsChange:({rects:e,boundingRect:t})=>{i.value=e,a.value=t}}))})),o.onUnmounted((()=>{null==r||r()})),(e,t)=>a.value?(o.openBlock(),o.createElementBlock("div",{key:0,style:o.normalizeStyle({position:"absolute",left:a.value.origin.x*e.scale+"px",top:a.value.origin.y*e.scale+"px",width:a.value.size.width*e.scale+"px",height:a.value.size.height*e.scale+"px",mixBlendMode:"multiply",isolation:"isolate",pointerEvents:"none"})},[(o.openBlock(!0),o.createElementBlock(o.Fragment,null,o.renderList(i.value,((t,l)=>(o.openBlock(),o.createElementBlock("div",{key:l,style:o.normalizeStyle({position:"absolute",left:(t.origin.x-a.value.origin.x)*e.scale+"px",top:(t.origin.y-a.value.origin.y)*e.scale+"px",width:t.size.width*e.scale+"px",height:t.size.height*e.scale+"px",background:e.background})},null,4)))),128))],4)):o.createCommentVNode("",!0)}}),r=o.defineComponent({__name:"copy-to-clipboard",setup(e){const{provides:t}=i();return o.watchEffect((e=>{if(t.value){e(t.value.onCopyToClipboard((e=>{navigator.clipboard.writeText(e).catch((e=>{console.error("Failed to copy text to clipboard:",e)}))})))}})),(e,t)=>null}}),c=e.createPluginPackage(t.SelectionPluginPackage).addUtility(r).build();exports.CopyToClipboard=r,exports.SelectionLayer=a,exports.SelectionPluginPackage=c,exports.useSelectionCapability=i,exports.useSelectionPlugin=n,Object.keys(t).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})}));
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/vue/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-selection.ts","../../src/vue/components/selection-layer.vue","../../src/vue/components/copy-to-clipboard.vue","../../src/vue/index.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\n/**\n * Hook to get the selection plugin's capability API.\n * This provides methods for controlling and listening to selection events.\n */\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\n\n/**\n * Hook to get the raw selection plugin instance.\n * Useful for accessing plugin-specific properties or methods not exposed in the capability.\n */\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","<template>\n <div\n v-if=\"boundingRect\"\n :style=\"{\n position: 'absolute',\n left: `${boundingRect.origin.x * scale}px`,\n top: `${boundingRect.origin.y * scale}px`,\n width: `${boundingRect.size.width * scale}px`,\n height: `${boundingRect.size.height * scale}px`,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }\"\n >\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n :style=\"{\n position: 'absolute',\n left: `${(rect.origin.x - boundingRect.origin.x) * scale}px`,\n top: `${(rect.origin.y - boundingRect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: background,\n }\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport {
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-selection.ts","../../src/vue/components/selection-layer.vue","../../src/vue/components/copy-to-clipboard.vue","../../src/vue/index.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\n/**\n * Hook to get the selection plugin's capability API.\n * This provides methods for controlling and listening to selection events.\n */\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\n\n/**\n * Hook to get the raw selection plugin instance.\n * Useful for accessing plugin-specific properties or methods not exposed in the capability.\n */\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","<template>\n <div\n v-if=\"boundingRect\"\n :style=\"{\n position: 'absolute',\n left: `${boundingRect.origin.x * scale}px`,\n top: `${boundingRect.origin.y * scale}px`,\n width: `${boundingRect.size.width * scale}px`,\n height: `${boundingRect.size.height * scale}px`,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }\"\n >\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n :style=\"{\n position: 'absolute',\n left: `${(rect.origin.x - boundingRect.origin.x) * scale}px`,\n top: `${(rect.origin.y - boundingRect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: background,\n }\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks/use-selection';\n\ninterface Props {\n pageIndex: number;\n scale: number;\n background?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n background: 'rgba(33, 150, 243)',\n});\n\nconst { plugin: sel } = useSelectionPlugin();\nconst rects = ref<Rect[]>([]);\nconst boundingRect = ref<Rect | null>(null);\n\nlet unregister: (() => void) | undefined;\n\nonMounted(() => {\n if (!sel.value) return;\n\n unregister = sel.value.registerSelectionOnPage({\n pageIndex: props.pageIndex,\n onRectsChange: ({ rects: newRects, boundingRect: newBoundingRect }) => {\n rects.value = newRects;\n boundingRect.value = newBoundingRect;\n },\n });\n});\n\nonUnmounted(() => {\n unregister?.();\n});\n</script>\n","<script setup lang=\"ts\">\nimport { watchEffect } from 'vue';\nimport { useSelectionCapability } from '../hooks';\n\nconst { provides: sel } = useSelectionCapability();\n\n// This effect runs when the component is mounted and the capability is available.\n// It automatically handles unsubscribing when the component is unmounted.\nwatchEffect((onCleanup) => {\n if (sel.value) {\n const unsubscribe = sel.value.onCopyToClipboard((text) => {\n // Use the Clipboard API to write the text\n navigator.clipboard.writeText(text).catch((err) => {\n console.error('Failed to copy text to clipboard:', err);\n });\n });\n\n // Register the cleanup function to run on unmount or re-run\n onCleanup(unsubscribe);\n }\n});\n</script>\n\n<template>\n <!-- This component renders nothing to the DOM -->\n</template>\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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","props","__props","plugin","sel","rects","ref","boundingRect","unregister","onMounted","value","registerSelectionOnPage","pageIndex","onRectsChange","newRects","newBoundingRect","onUnmounted","_createElementBlock","style","_normalizeStyle","left","origin","x","scale","top","y","width","size","height","_openBlock","createElementBlock","_Fragment","_renderList","renderList","rect","i","key","background","provides","vue$1","watchEffect","onCleanup","onCopyToClipboard","text","navigator","clipboard","writeText","catch","err","console","error","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","CopyToClipboard","build"],"mappings":"2MAOaA,EAAyB,IAAMC,gBAA+BC,EAAAA,gBAAgBC,IAM9EC,EAAqB,IAAMC,YAA2BH,EAAAA,gBAAgBC,mIC2BnF,MAAMG,EAAQC,GAINC,OAAQC,GAAQL,IAClBM,EAAQC,EAAYA,IAAA,IACpBC,EAAeD,MAAiB,MAElC,IAAAE,SAEJC,EAAAA,WAAU,KACHL,EAAIM,QAEIF,EAAAJ,EAAIM,MAAMC,wBAAwB,CAC7CC,UAAWX,EAAMW,UACjBC,cAAe,EAAGR,MAAOS,EAAUP,aAAcQ,MAC/CV,EAAMK,MAAQI,EACdP,EAAaG,MAAQK,CAAA,IAExB,IAGHC,EAAAA,aAAY,KACG,MAAAR,GAAAA,GAAA,WA7DLD,EAAYG,qBADpBO,EAAAA,mBAyBM,MAAA,OAvBHC,MAAKC,EAAAA,eAAA,qBAA+CC,KAAAb,EAAAG,MAAaW,OAAOC,EAAIC,EAAKA,MAA7B,KAAiDC,IAAAjB,EAAAG,MAAaW,OAAOI,EAAIF,EAAKA,MAA7B,KAAmDG,MAAAnB,EAAAG,MAAaiB,KAAKD,MAAQH,EAAKA,MAA/B,KAAsDK,OAAArB,EAAAG,MAAaiB,KAAKC,OAASL,EAAKA,MAAhC,2EAW/MM,EAAAA,WAAA,GAAAZ,EAWEa,mBAAAC,WAVoB,KAAAC,EAAAC,WAAA5B,EAAAK,OAAZ,CAAAwB,EAAMC,mBADhBlB,EAAAa,mBAWE,MAAA,CATCM,IAAKD,EACLjB,MAAKC,EAAAA,eAAA,2BAAoDe,EAAKb,OAAOC,EAAIf,EAAYG,MAACW,OAAOC,GAAKC,EAAKA,gBAAuBW,EAAKb,OAAOI,EAAIlB,EAAYG,MAACW,OAAOI,GAAKF,EAAKA,WAAwBG,MAAAQ,EAAKP,KAAKD,MAAQH,EAAKA,MAAvB,KAAgDK,OAAAM,EAAKP,KAAKC,OAASL,EAAKA,MAAxB,gBAAkDc,EAAUA,4HCbvT,MAAQC,SAAUlC,GAAQT,WAI1B4C,EAAAC,aAAaC,IACX,GAAIrC,EAAIM,MAAO,CASb+B,EARoBrC,EAAIM,MAAMgC,mBAAmBC,IAE/CC,UAAUC,UAAUC,UAAUH,GAAMI,OAAOC,IACjCC,QAAAC,MAAM,oCAAqCF,EAAG,GACvD,IAIkB,oBCTZG,EAAyBC,EAAoBA,oBAAAC,EAA0BF,wBACjFG,WAAWC,GACXC"}
|
package/dist/vue/index.js
CHANGED
|
@@ -14,7 +14,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
14
14
|
},
|
|
15
15
|
setup(__props) {
|
|
16
16
|
const props = __props;
|
|
17
|
-
const {
|
|
17
|
+
const { plugin: sel } = useSelectionPlugin();
|
|
18
18
|
const rects = ref([]);
|
|
19
19
|
const boundingRect = ref(null);
|
|
20
20
|
let unregister;
|
package/dist/vue/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-selection.ts","../../src/vue/components/selection-layer.vue","../../src/vue/components/copy-to-clipboard.vue","../../src/vue/index.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\n/**\n * Hook to get the selection plugin's capability API.\n * This provides methods for controlling and listening to selection events.\n */\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\n\n/**\n * Hook to get the raw selection plugin instance.\n * Useful for accessing plugin-specific properties or methods not exposed in the capability.\n */\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","<template>\n <div\n v-if=\"boundingRect\"\n :style=\"{\n position: 'absolute',\n left: `${boundingRect.origin.x * scale}px`,\n top: `${boundingRect.origin.y * scale}px`,\n width: `${boundingRect.size.width * scale}px`,\n height: `${boundingRect.size.height * scale}px`,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }\"\n >\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n :style=\"{\n position: 'absolute',\n left: `${(rect.origin.x - boundingRect.origin.x) * scale}px`,\n top: `${(rect.origin.y - boundingRect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: background,\n }\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-selection.ts","../../src/vue/components/selection-layer.vue","../../src/vue/components/copy-to-clipboard.vue","../../src/vue/index.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\n/**\n * Hook to get the selection plugin's capability API.\n * This provides methods for controlling and listening to selection events.\n */\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\n\n/**\n * Hook to get the raw selection plugin instance.\n * Useful for accessing plugin-specific properties or methods not exposed in the capability.\n */\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","<template>\n <div\n v-if=\"boundingRect\"\n :style=\"{\n position: 'absolute',\n left: `${boundingRect.origin.x * scale}px`,\n top: `${boundingRect.origin.y * scale}px`,\n width: `${boundingRect.size.width * scale}px`,\n height: `${boundingRect.size.height * scale}px`,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }\"\n >\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n :style=\"{\n position: 'absolute',\n left: `${(rect.origin.x - boundingRect.origin.x) * scale}px`,\n top: `${(rect.origin.y - boundingRect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: background,\n }\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks/use-selection';\n\ninterface Props {\n pageIndex: number;\n scale: number;\n background?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n background: 'rgba(33, 150, 243)',\n});\n\nconst { plugin: sel } = useSelectionPlugin();\nconst rects = ref<Rect[]>([]);\nconst boundingRect = ref<Rect | null>(null);\n\nlet unregister: (() => void) | undefined;\n\nonMounted(() => {\n if (!sel.value) return;\n\n unregister = sel.value.registerSelectionOnPage({\n pageIndex: props.pageIndex,\n onRectsChange: ({ rects: newRects, boundingRect: newBoundingRect }) => {\n rects.value = newRects;\n boundingRect.value = newBoundingRect;\n },\n });\n});\n\nonUnmounted(() => {\n unregister?.();\n});\n</script>\n","<script setup lang=\"ts\">\nimport { watchEffect } from 'vue';\nimport { useSelectionCapability } from '../hooks';\n\nconst { provides: sel } = useSelectionCapability();\n\n// This effect runs when the component is mounted and the capability is available.\n// It automatically handles unsubscribing when the component is unmounted.\nwatchEffect((onCleanup) => {\n if (sel.value) {\n const unsubscribe = sel.value.onCopyToClipboard((text) => {\n // Use the Clipboard API to write the text\n navigator.clipboard.writeText(text).catch((err) => {\n console.error('Failed to copy text to clipboard:', err);\n });\n });\n\n // Register the cleanup function to run on unmount or re-run\n onCleanup(unsubscribe);\n }\n});\n</script>\n\n<template>\n <!-- This component renders nothing to the DOM -->\n</template>\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 '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["_createElementBlock","_normalizeStyle","scale","_openBlock","_Fragment","_renderList","background","BaseSelectionPluginPackage","CopyToClipboard"],"mappings":";;;;;AAOO,MAAM,yBAAyB,MAAM,cAA+B,gBAAgB,EAAE;AAMtF,MAAM,qBAAqB,MAAM,UAA2B,gBAAgB,EAAE;;;;;;;;;AC2BrF,UAAM,QAAQ;AAId,UAAM,EAAE,QAAQ,IAAI,IAAI,mBAAmB;AACrC,UAAA,QAAQ,IAAY,EAAE;AACtB,UAAA,eAAe,IAAiB,IAAI;AAEtC,QAAA;AAEJ,cAAU,MAAM;AACV,UAAA,CAAC,IAAI,MAAO;AAEH,mBAAA,IAAI,MAAM,wBAAwB;AAAA,QAC7C,WAAW,MAAM;AAAA,QACjB,eAAe,CAAC,EAAE,OAAO,UAAU,cAAc,sBAAsB;AACrE,gBAAM,QAAQ;AACd,uBAAa,QAAQ;AAAA,QAAA;AAAA,MACvB,CACD;AAAA,IAAA,CACF;AAED,gBAAY,MAAM;AACH;AAAA,IAAA,CACd;;aA9DS,aAAY,sBADpBA,mBAyBM,OAAA;AAAA;QAvBH,OAAKC,eAAA;AAAA;UAA+C,MAAA,GAAA,aAAA,MAAa,OAAO,IAAIC,KAAK,KAAA;AAAA,UAAoB,KAAA,GAAA,aAAA,MAAa,OAAO,IAAIA,KAAK,KAAA;AAAA,UAAsB,OAAA,GAAA,aAAA,MAAa,KAAK,QAAQA,KAAK,KAAA;AAAA,UAAuB,QAAA,GAAA,aAAA,MAAa,KAAK,SAASA,KAAK,KAAA;AAAA;;;;;SAW/OC,UAAA,IAAA,GAAAH,mBAWEI,UAVoB,MAAAC,WAAA,MAAA,OAAZ,CAAA,MAAM,MAAC;8BADjBL,mBAWE,OAAA;AAAA,YATC,KAAK;AAAA,YACL,OAAKC,eAAA;AAAA;wBAAoD,KAAK,OAAO,IAAI,aAAY,MAAC,OAAO,KAAKC,KAAK,KAAA;AAAA,uBAAuB,KAAK,OAAO,IAAI,aAAY,MAAC,OAAO,KAAKA,KAAK,KAAA;AAAA,cAAwB,OAAA,GAAA,KAAK,KAAK,QAAQA,KAAK,KAAA;AAAA,cAAyB,QAAA,GAAA,KAAK,KAAK,SAASA,KAAK,KAAA;AAAA,0BAA0BI,KAAU;AAAA;;;;;;;;;;ACbvT,UAAM,EAAE,UAAU,IAAI,IAAI,uBAAuB;AAIjD,gBAAY,CAAC,cAAc;AACzB,UAAI,IAAI,OAAO;AACb,cAAM,cAAc,IAAI,MAAM,kBAAkB,CAAC,SAAS;AAExD,oBAAU,UAAU,UAAU,IAAI,EAAE,MAAM,CAAC,QAAQ;AACzC,oBAAA,MAAM,qCAAqC,GAAG;AAAA,UAAA,CACvD;AAAA,QAAA,CACF;AAGD,kBAAU,WAAW;AAAA,MAAA;AAAA,IACvB,CACD;;;;;;ACXM,MAAM,yBAAyB,oBAAoBC,wBAA0B,EACjF,WAAWC,SAAe,EAC1B,MAAM;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-selection",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,24 +28,24 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@embedpdf/models": "1.0
|
|
31
|
+
"@embedpdf/models": "1.1.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/react": "^18.2.0",
|
|
35
35
|
"typescript": "^5.0.0",
|
|
36
36
|
"@embedpdf/build": "1.0.0",
|
|
37
|
-
"@embedpdf/core": "1.0
|
|
38
|
-
"@embedpdf/plugin-
|
|
39
|
-
"@embedpdf/plugin-
|
|
37
|
+
"@embedpdf/core": "1.1.0",
|
|
38
|
+
"@embedpdf/plugin-viewport": "1.1.0",
|
|
39
|
+
"@embedpdf/plugin-interaction-manager": "1.1.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": ">=16.8.0",
|
|
43
43
|
"react-dom": ">=16.8.0",
|
|
44
44
|
"preact": "^10.26.4",
|
|
45
45
|
"vue": ">=3.2.0",
|
|
46
|
-
"@embedpdf/
|
|
47
|
-
"@embedpdf/
|
|
48
|
-
"@embedpdf/plugin-
|
|
46
|
+
"@embedpdf/plugin-viewport": "1.1.0",
|
|
47
|
+
"@embedpdf/core": "1.1.0",
|
|
48
|
+
"@embedpdf/plugin-interaction-manager": "1.1.0"
|
|
49
49
|
},
|
|
50
50
|
"files": [
|
|
51
51
|
"dist",
|