@embedpdf/plugin-selection 2.5.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +159 -81
- package/dist/index.js.map +1 -1
- package/dist/lib/handlers/marquee-selection.handler.d.ts +9 -7
- package/dist/lib/handlers/text-selection.handler.d.ts +8 -6
- package/dist/lib/selection-plugin.d.ts +7 -4
- package/dist/lib/types.d.ts +71 -2
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +59 -16
- 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 +59 -16
- package/dist/react/index.js.map +1 -1
- package/dist/shared/components/index.d.ts +1 -0
- package/dist/shared/components/marquee-selection.d.ts +18 -5
- package/dist/shared/components/selection-layer.d.ts +18 -1
- package/dist/shared/components/text-selection.d.ts +21 -0
- package/dist/shared-preact/components/index.d.ts +1 -0
- package/dist/shared-preact/components/marquee-selection.d.ts +18 -5
- package/dist/shared-preact/components/selection-layer.d.ts +18 -1
- package/dist/shared-preact/components/text-selection.d.ts +21 -0
- package/dist/shared-react/components/index.d.ts +1 -0
- package/dist/shared-react/components/marquee-selection.d.ts +18 -5
- package/dist/shared-react/components/selection-layer.d.ts +18 -1
- package/dist/shared-react/components/text-selection.d.ts +21 -0
- package/dist/svelte/components/MarqueeSelection.svelte.d.ts +12 -2
- package/dist/svelte/components/SelectionLayer.svelte.d.ts +11 -1
- package/dist/svelte/components/TextSelection.svelte.d.ts +22 -0
- package/dist/svelte/components/index.d.ts +1 -0
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.cjs.map +1 -1
- package/dist/svelte/index.js +93 -17
- package/dist/svelte/index.js.map +1 -1
- package/dist/vue/components/index.d.ts +1 -0
- package/dist/vue/components/marquee-selection.vue.d.ts +13 -4
- package/dist/vue/components/selection-layer.vue.d.ts +15 -5
- package/dist/vue/components/text-selection.vue.d.ts +51 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.js +89 -32
- package/dist/vue/index.js.map +1 -1
- package/package.json +9 -9
package/dist/lib/types.d.ts
CHANGED
|
@@ -72,6 +72,18 @@ export interface RegisterMarqueeOnPageOptions {
|
|
|
72
72
|
/** Called when the marquee rect changes during drag, or null when cancelled/ended */
|
|
73
73
|
onRectChange: (rect: Rect | null) => void;
|
|
74
74
|
}
|
|
75
|
+
export interface TextSelectionStyle {
|
|
76
|
+
/** Background color for text selection highlights. Default: 'rgba(33,150,243)' */
|
|
77
|
+
background?: string;
|
|
78
|
+
}
|
|
79
|
+
export interface MarqueeSelectionStyle {
|
|
80
|
+
/** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */
|
|
81
|
+
background?: string;
|
|
82
|
+
/** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */
|
|
83
|
+
borderColor?: string;
|
|
84
|
+
/** Border style. Default: 'dashed' */
|
|
85
|
+
borderStyle?: 'solid' | 'dashed' | 'dotted';
|
|
86
|
+
}
|
|
75
87
|
export interface SelectionMenuPlacementEvent {
|
|
76
88
|
documentId: string;
|
|
77
89
|
placement: SelectionMenuPlacement | null;
|
|
@@ -79,6 +91,7 @@ export interface SelectionMenuPlacementEvent {
|
|
|
79
91
|
export interface SelectionChangeEvent {
|
|
80
92
|
documentId: string;
|
|
81
93
|
selection: SelectionRangeX | null;
|
|
94
|
+
modeId: string;
|
|
82
95
|
}
|
|
83
96
|
export interface TextRetrievedEvent {
|
|
84
97
|
documentId: string;
|
|
@@ -92,36 +105,75 @@ export interface BeginSelectionEvent {
|
|
|
92
105
|
documentId: string;
|
|
93
106
|
page: number;
|
|
94
107
|
index: number;
|
|
108
|
+
modeId: string;
|
|
95
109
|
}
|
|
96
110
|
export interface EndSelectionEvent {
|
|
97
111
|
documentId: string;
|
|
112
|
+
modeId: string;
|
|
98
113
|
}
|
|
99
114
|
export interface MarqueeChangeEvent {
|
|
100
115
|
documentId: string;
|
|
101
116
|
pageIndex: number;
|
|
102
117
|
rect: Rect | null;
|
|
118
|
+
modeId: string;
|
|
103
119
|
}
|
|
104
120
|
export interface MarqueeEndEvent {
|
|
105
121
|
documentId: string;
|
|
106
122
|
pageIndex: number;
|
|
107
123
|
rect: Rect;
|
|
124
|
+
modeId: string;
|
|
125
|
+
}
|
|
126
|
+
export interface EmptySpaceClickEvent {
|
|
127
|
+
documentId: string;
|
|
128
|
+
pageIndex: number;
|
|
129
|
+
modeId: string;
|
|
108
130
|
}
|
|
109
131
|
export interface EnableForModeOptions {
|
|
110
132
|
/**
|
|
111
133
|
* Whether to show selection rects in the SelectionLayer.
|
|
134
|
+
* @deprecated Use `showSelectionRects` instead.
|
|
135
|
+
* @default true
|
|
136
|
+
*/
|
|
137
|
+
showRects?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Enable text selection for this mode.
|
|
140
|
+
* @default true
|
|
141
|
+
*/
|
|
142
|
+
enableSelection?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Whether to show text selection rects in the SelectionLayer.
|
|
112
145
|
* When false, the selection logic is enabled but the rects are not
|
|
113
146
|
* rendered (useful when a consuming plugin handles its own rendering).
|
|
147
|
+
* Takes precedence over `showRects`.
|
|
114
148
|
* @default true
|
|
115
149
|
*/
|
|
116
|
-
|
|
150
|
+
showSelectionRects?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Enable marquee selection for this mode.
|
|
153
|
+
* @default false
|
|
154
|
+
*/
|
|
155
|
+
enableMarquee?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Whether to show the marquee rect in the MarqueeSelection component.
|
|
158
|
+
* When false, the marquee logic runs but the rect is not rendered
|
|
159
|
+
* (useful when a consuming plugin handles its own rendering).
|
|
160
|
+
* @default true
|
|
161
|
+
*/
|
|
162
|
+
showMarqueeRects?: boolean;
|
|
117
163
|
}
|
|
118
164
|
export interface MarqueeScopeEvent {
|
|
119
165
|
pageIndex: number;
|
|
120
166
|
rect: Rect | null;
|
|
167
|
+
modeId: string;
|
|
121
168
|
}
|
|
122
169
|
export interface MarqueeEndScopeEvent {
|
|
123
170
|
pageIndex: number;
|
|
124
171
|
rect: Rect;
|
|
172
|
+
modeId: string;
|
|
173
|
+
}
|
|
174
|
+
export interface EmptySpaceClickScopeEvent {
|
|
175
|
+
pageIndex: number;
|
|
176
|
+
modeId: string;
|
|
125
177
|
}
|
|
126
178
|
export interface SelectionScope {
|
|
127
179
|
getFormattedSelection(): FormattedSelection[];
|
|
@@ -137,7 +189,13 @@ export interface SelectionScope {
|
|
|
137
189
|
clear(): void;
|
|
138
190
|
copyToClipboard(): void;
|
|
139
191
|
getState(): SelectionDocumentState;
|
|
192
|
+
/**
|
|
193
|
+
* @deprecated Use `enableForMode` with `enableMarquee` option on the capability instead.
|
|
194
|
+
*/
|
|
140
195
|
setMarqueeEnabled(enabled: boolean): void;
|
|
196
|
+
/**
|
|
197
|
+
* @deprecated Use `enableForMode` / `isEnabledForMode` on the capability instead.
|
|
198
|
+
*/
|
|
141
199
|
isMarqueeEnabled(): boolean;
|
|
142
200
|
onSelectionChange: EventHook<SelectionRangeX | null>;
|
|
143
201
|
onTextRetrieved: EventHook<string[]>;
|
|
@@ -145,10 +203,14 @@ export interface SelectionScope {
|
|
|
145
203
|
onBeginSelection: EventHook<{
|
|
146
204
|
page: number;
|
|
147
205
|
index: number;
|
|
206
|
+
modeId: string;
|
|
207
|
+
}>;
|
|
208
|
+
onEndSelection: EventHook<{
|
|
209
|
+
modeId: string;
|
|
148
210
|
}>;
|
|
149
|
-
onEndSelection: EventHook<void>;
|
|
150
211
|
onMarqueeChange: EventHook<MarqueeScopeEvent>;
|
|
151
212
|
onMarqueeEnd: EventHook<MarqueeEndScopeEvent>;
|
|
213
|
+
onEmptySpaceClick: EventHook<EmptySpaceClickScopeEvent>;
|
|
152
214
|
}
|
|
153
215
|
export interface SelectionCapability {
|
|
154
216
|
getFormattedSelection(documentId?: string): FormattedSelection[];
|
|
@@ -166,7 +228,13 @@ export interface SelectionCapability {
|
|
|
166
228
|
getState(documentId?: string): SelectionDocumentState;
|
|
167
229
|
enableForMode(modeId: string, options?: EnableForModeOptions, documentId?: string): void;
|
|
168
230
|
isEnabledForMode(modeId: string, documentId?: string): boolean;
|
|
231
|
+
/**
|
|
232
|
+
* @deprecated Use `enableForMode` with `enableMarquee` option instead.
|
|
233
|
+
*/
|
|
169
234
|
setMarqueeEnabled(enabled: boolean, documentId?: string): void;
|
|
235
|
+
/**
|
|
236
|
+
* @deprecated Use `enableForMode` / `isEnabledForMode` instead.
|
|
237
|
+
*/
|
|
170
238
|
isMarqueeEnabled(documentId?: string): boolean;
|
|
171
239
|
forDocument(documentId: string): SelectionScope;
|
|
172
240
|
onSelectionChange: EventHook<SelectionChangeEvent>;
|
|
@@ -176,4 +244,5 @@ export interface SelectionCapability {
|
|
|
176
244
|
onEndSelection: EventHook<EndSelectionEvent>;
|
|
177
245
|
onMarqueeChange: EventHook<MarqueeChangeEvent>;
|
|
178
246
|
onMarqueeEnd: EventHook<MarqueeEndEvent>;
|
|
247
|
+
onEmptySpaceClick: EventHook<EmptySpaceClickEvent>;
|
|
179
248
|
}
|
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"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),o=require("preact/jsx-runtime"),i=require("preact"),n=require("preact/hooks"),r=require("@embedpdf/core/preact"),l=require("@embedpdf/utils/preact"),u=()=>r.useCapability(t.SelectionPlugin.id),s=()=>r.usePlugin(t.SelectionPlugin.id);function a({documentId:e,pageIndex:t,scale:i,rotation:u,background:a="rgba(33,150,243)",selectionMenu:d}){var c,g;const{plugin:p}=s(),x=r.useDocumentState(e),b=null==(g=null==(c=null==x?void 0:x.document)?void 0:c.pages)?void 0:g[t],[h,m]=n.useState([]),[f,y]=n.useState(null),[v,S]=n.useState(null);n.useEffect(()=>{if(p&&e)return p.registerSelectionOnPage({documentId:e,pageIndex:t,onRectsChange:({rects:e,boundingRect:t})=>{m(e),y(t)}})},[p,e,t]),n.useEffect(()=>{if(p&&e)return p.onMenuPlacement(e,e=>{S(e)})},[p,e]);const I=n.useMemo(()=>void 0!==i?i:(null==x?void 0:x.scale)??1,[i,null==x?void 0:x.scale]),P=n.useMemo(()=>{if(void 0!==u)return u;return(((null==b?void 0:b.rotation)??0)+((null==x?void 0:x.rotation)??0))%4},[u,null==b?void 0:b.rotation,null==x?void 0:x.rotation]),k=d&&v&&v.pageIndex===t&&v.isVisible;return f?o.jsxs(o.Fragment,{children:[o.jsx("div",{style:{position:"absolute",left:f.origin.x*I,top:f.origin.y*I,width:f.size.width*I,height:f.size.height*I,mixBlendMode:"multiply",isolation:"isolate",pointerEvents:"none"},children:h.map((e,t)=>o.jsx("div",{style:{position:"absolute",left:(e.origin.x-f.origin.x)*I,top:(e.origin.y-f.origin.y)*I,width:e.size.width*I,height:e.size.height*I,background:a}},t))}),k&&o.jsx(l.CounterRotate,{rect:{origin:{x:v.rect.origin.x*I,y:v.rect.origin.y*I},size:{width:v.rect.size.width*I,height:v.rect.size.height*I}},rotation:P,children:e=>d({...e,context:{type:"selection",pageIndex:t},selected:!0,placement:v})})]}):null}const d=({documentId:e,pageIndex:t,scale:i,className:l,background:u,borderColor:a,borderStyle:d="dashed",stroke:c,fill:g})=>{const{plugin:p}=s(),x=r.useDocumentState(e),[b,h]=n.useState(null),m=a??c??"rgba(0,122,204,0.8)",f=u??g??"rgba(0,122,204,0.15)",y=n.useMemo(()=>void 0!==i?i:(null==x?void 0:x.scale)??1,[i,null==x?void 0:x.scale]);return n.useEffect(()=>{if(p&&e)return p.registerMarqueeOnPage({documentId:e,pageIndex:t,scale:y,onRectChange:h})},[p,e,t,y]),b?o.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:b.origin.x*y,top:b.origin.y*y,width:b.size.width*y,height:b.size.height*y,border:`1px ${d} ${m}`,background:f,boxSizing:"border-box",zIndex:1e3},className:l}):null};function c(){const{provides:e}=u();return n.useEffect(()=>{if(e)return e.onCopyToClipboard(({text:e})=>{navigator.clipboard.writeText(e)})},[e]),null}const g=e.createPluginPackage(t.SelectionPluginPackage).addUtility(c).build();exports.CopyToClipboard=c,exports.MarqueeSelection=d,exports.SelectionLayer=function({documentId:e,pageIndex:t,scale:n,rotation:r,background:l,textStyle:u,marqueeStyle:s,marqueeClassName:c,selectionMenu:g}){return o.jsxs(i.Fragment,{children:[o.jsx(a,{documentId:e,pageIndex:t,scale:n,rotation:r,background:(null==u?void 0:u.background)??l,selectionMenu:g}),o.jsx(d,{documentId:e,pageIndex:t,scale:n,background:null==s?void 0:s.background,borderColor:null==s?void 0:s.borderColor,borderStyle:null==s?void 0:s.borderStyle,className:c})]})},exports.SelectionPluginPackage=g,exports.TextSelection=a,exports.useSelectionCapability=u,exports.useSelectionPlugin=s,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/components/marquee-selection.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 { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke colour (default: 'rgba(0,122,204,0.8)') */\n stroke?: string;\n /** Fill colour (default: 'rgba(0,122,204,0.15)') */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * Place this component on each page where you want marquee selection to work.\n *\n * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n stroke = 'rgba(0,122,204,0.8)',\n fill = 'rgba(0,122,204,0.15)',\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px dashed ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n // Optimization: We could filter here, but React state updates are cheap enough usually.\n // Ideally, check: if (newPlacement?.pageIndex === pageIndex)\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","CopyToClipboard","provides","sel","useEffect","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","documentId","pageIndex","scale","className","stroke","fill","plugin","selPlugin","documentState","useDocumentState","rect","setRect","useState","actualScale","useMemo","registerMarqueeOnPage","onRectChange","jsx","style","position","pointerEvents","left","origin","x","top","y","width","size","height","border","background","boxSizing","zIndex","scaleOverride","rotation","rotationOverride","selectionMenu","page","_b","_a","document","pages","rects","setRects","boundingRect","setBoundingRect","placement","setPlacement","registerSelectionOnPage","onRectsChange","onMenuPlacement","newPlacement","actualRotation","shouldRenderMenu","isVisible","jsxs","Fragment","children","mixBlendMode","isolation","map","b","i","CounterRotate","props","context","type","selected"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/text-selection.tsx","../../src/shared/components/marquee-selection.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts","../../src/shared/components/selection-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype TextSelectionProps = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * TextSelection renders text selection highlight rects and the selection menu.\n * It registers the text selection handler on the page and subscribes to menu\n * placement changes.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport function TextSelection({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: TextSelectionProps) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */\n background?: string;\n /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */\n borderColor?: string;\n /** Border style. Default: 'dashed' */\n borderStyle?: 'solid' | 'dashed' | 'dotted';\n /**\n * @deprecated Use `borderColor` instead.\n */\n stroke?: string;\n /**\n * @deprecated Use `background` instead.\n */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * It registers the marquee handler on the page.\n *\n * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n background,\n borderColor,\n borderStyle = 'dashed',\n stroke,\n fill,\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n // Resolve deprecated props: new CSS-standard props take precedence\n const resolvedBorderColor = borderColor ?? stroke ?? 'rgba(0,122,204,0.8)';\n const resolvedBackground = background ?? fill ?? 'rgba(0,122,204,0.15)';\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px ${borderStyle} ${resolvedBorderColor}`,\n background: resolvedBackground,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { useEffect } from '@framework';\n\nimport { useSelectionCapability } from '../hooks';\n\nexport function CopyToClipboard() {\n const { provides: sel } = useSelectionCapability();\n\n useEffect(() => {\n if (!sel) return;\n return sel.onCopyToClipboard(({ text }) => {\n navigator.clipboard.writeText(text);\n });\n }, [sel]);\n\n return null;\n}\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { Fragment } from '@framework';\nimport { Rotation } from '@embedpdf/models';\nimport { TextSelectionStyle, MarqueeSelectionStyle } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { TextSelection } from './text-selection';\nimport { MarqueeSelection } from './marquee-selection';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /**\n * @deprecated Use `textStyle.background` instead.\n */\n background?: string;\n /** Styling options for text selection highlights */\n textStyle?: TextSelectionStyle;\n /** Styling options for the marquee selection rectangle */\n marqueeStyle?: MarqueeSelectionStyle;\n /** Optional CSS class applied to the marquee rectangle */\n marqueeClassName?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * SelectionLayer is a convenience component that composes both text selection\n * and marquee selection on a single page.\n *\n * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`\n * individually.\n */\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale,\n rotation,\n background,\n textStyle,\n marqueeStyle,\n marqueeClassName,\n selectionMenu,\n}: Props) {\n return (\n <Fragment>\n <TextSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n background={textStyle?.background ?? background}\n selectionMenu={selectionMenu}\n />\n <MarqueeSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n background={marqueeStyle?.background}\n borderColor={marqueeStyle?.borderColor}\n borderStyle={marqueeStyle?.borderStyle}\n className={marqueeClassName}\n />\n </Fragment>\n );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","TextSelection","documentId","pageIndex","scale","scaleOverride","rotation","rotationOverride","background","selectionMenu","plugin","selPlugin","documentState","useDocumentState","page","_b","_a","document","pages","rects","setRects","useState","boundingRect","setBoundingRect","placement","setPlacement","useEffect","registerSelectionOnPage","onRectsChange","onMenuPlacement","newPlacement","actualScale","useMemo","actualRotation","shouldRenderMenu","isVisible","jsxs","Fragment","children","jsx","style","position","left","origin","x","top","y","width","size","height","mixBlendMode","isolation","pointerEvents","map","b","i","CounterRotate","rect","props","context","type","selected","MarqueeSelection","className","borderColor","borderStyle","stroke","fill","setRect","resolvedBorderColor","resolvedBackground","registerMarqueeOnPage","onRectChange","border","boxSizing","zIndex","CopyToClipboard","provides","sel","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","textStyle","marqueeStyle","marqueeClassName"],"mappings":"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"}
|
package/dist/preact/index.js
CHANGED
|
@@ -2,13 +2,13 @@ import { createPluginPackage } from "@embedpdf/core";
|
|
|
2
2
|
import { SelectionPlugin, SelectionPluginPackage as SelectionPluginPackage$1 } from "@embedpdf/plugin-selection";
|
|
3
3
|
export * from "@embedpdf/plugin-selection";
|
|
4
4
|
import { jsxs, Fragment, jsx } from "preact/jsx-runtime";
|
|
5
|
-
import "preact";
|
|
5
|
+
import { Fragment as Fragment$1 } from "preact";
|
|
6
6
|
import { useState, useEffect, useMemo } from "preact/hooks";
|
|
7
7
|
import { useCapability, usePlugin, useDocumentState } from "@embedpdf/core/preact";
|
|
8
8
|
import { CounterRotate } from "@embedpdf/utils/preact";
|
|
9
9
|
const useSelectionCapability = () => useCapability(SelectionPlugin.id);
|
|
10
10
|
const useSelectionPlugin = () => usePlugin(SelectionPlugin.id);
|
|
11
|
-
function
|
|
11
|
+
function TextSelection({
|
|
12
12
|
documentId,
|
|
13
13
|
pageIndex,
|
|
14
14
|
scale: scaleOverride,
|
|
@@ -109,27 +109,22 @@ function SelectionLayer({
|
|
|
109
109
|
)
|
|
110
110
|
] });
|
|
111
111
|
}
|
|
112
|
-
function CopyToClipboard() {
|
|
113
|
-
const { provides: sel } = useSelectionCapability();
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (!sel) return;
|
|
116
|
-
return sel.onCopyToClipboard(({ text }) => {
|
|
117
|
-
navigator.clipboard.writeText(text);
|
|
118
|
-
});
|
|
119
|
-
}, [sel]);
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
112
|
const MarqueeSelection = ({
|
|
123
113
|
documentId,
|
|
124
114
|
pageIndex,
|
|
125
115
|
scale,
|
|
126
116
|
className,
|
|
127
|
-
|
|
128
|
-
|
|
117
|
+
background,
|
|
118
|
+
borderColor,
|
|
119
|
+
borderStyle = "dashed",
|
|
120
|
+
stroke,
|
|
121
|
+
fill
|
|
129
122
|
}) => {
|
|
130
123
|
const { plugin: selPlugin } = useSelectionPlugin();
|
|
131
124
|
const documentState = useDocumentState(documentId);
|
|
132
125
|
const [rect, setRect] = useState(null);
|
|
126
|
+
const resolvedBorderColor = borderColor ?? stroke ?? "rgba(0,122,204,0.8)";
|
|
127
|
+
const resolvedBackground = background ?? fill ?? "rgba(0,122,204,0.15)";
|
|
133
128
|
const actualScale = useMemo(() => {
|
|
134
129
|
if (scale !== void 0) return scale;
|
|
135
130
|
return (documentState == null ? void 0 : documentState.scale) ?? 1;
|
|
@@ -154,8 +149,8 @@ const MarqueeSelection = ({
|
|
|
154
149
|
top: rect.origin.y * actualScale,
|
|
155
150
|
width: rect.size.width * actualScale,
|
|
156
151
|
height: rect.size.height * actualScale,
|
|
157
|
-
border: `1px
|
|
158
|
-
background:
|
|
152
|
+
border: `1px ${borderStyle} ${resolvedBorderColor}`,
|
|
153
|
+
background: resolvedBackground,
|
|
159
154
|
boxSizing: "border-box",
|
|
160
155
|
zIndex: 1e3
|
|
161
156
|
},
|
|
@@ -163,12 +158,60 @@ const MarqueeSelection = ({
|
|
|
163
158
|
}
|
|
164
159
|
);
|
|
165
160
|
};
|
|
161
|
+
function SelectionLayer({
|
|
162
|
+
documentId,
|
|
163
|
+
pageIndex,
|
|
164
|
+
scale,
|
|
165
|
+
rotation,
|
|
166
|
+
background,
|
|
167
|
+
textStyle,
|
|
168
|
+
marqueeStyle,
|
|
169
|
+
marqueeClassName,
|
|
170
|
+
selectionMenu
|
|
171
|
+
}) {
|
|
172
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
173
|
+
/* @__PURE__ */ jsx(
|
|
174
|
+
TextSelection,
|
|
175
|
+
{
|
|
176
|
+
documentId,
|
|
177
|
+
pageIndex,
|
|
178
|
+
scale,
|
|
179
|
+
rotation,
|
|
180
|
+
background: (textStyle == null ? void 0 : textStyle.background) ?? background,
|
|
181
|
+
selectionMenu
|
|
182
|
+
}
|
|
183
|
+
),
|
|
184
|
+
/* @__PURE__ */ jsx(
|
|
185
|
+
MarqueeSelection,
|
|
186
|
+
{
|
|
187
|
+
documentId,
|
|
188
|
+
pageIndex,
|
|
189
|
+
scale,
|
|
190
|
+
background: marqueeStyle == null ? void 0 : marqueeStyle.background,
|
|
191
|
+
borderColor: marqueeStyle == null ? void 0 : marqueeStyle.borderColor,
|
|
192
|
+
borderStyle: marqueeStyle == null ? void 0 : marqueeStyle.borderStyle,
|
|
193
|
+
className: marqueeClassName
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
] });
|
|
197
|
+
}
|
|
198
|
+
function CopyToClipboard() {
|
|
199
|
+
const { provides: sel } = useSelectionCapability();
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
if (!sel) return;
|
|
202
|
+
return sel.onCopyToClipboard(({ text }) => {
|
|
203
|
+
navigator.clipboard.writeText(text);
|
|
204
|
+
});
|
|
205
|
+
}, [sel]);
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
166
208
|
const SelectionPluginPackage = createPluginPackage(SelectionPluginPackage$1).addUtility(CopyToClipboard).build();
|
|
167
209
|
export {
|
|
168
210
|
CopyToClipboard,
|
|
169
211
|
MarqueeSelection,
|
|
170
212
|
SelectionLayer,
|
|
171
213
|
SelectionPluginPackage,
|
|
214
|
+
TextSelection,
|
|
172
215
|
useSelectionCapability,
|
|
173
216
|
useSelectionPlugin
|
|
174
217
|
};
|
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/components/marquee-selection.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, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n // Optimization: We could filter here, but React state updates are cheap enough usually.\n // Ideally, check: if (newPlacement?.pageIndex === pageIndex)\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n","import { useEffect } 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 { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke colour (default: 'rgba(0,122,204,0.8)') */\n stroke?: string;\n /** Fill colour (default: 'rgba(0,122,204,0.15)') */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * Place this component on each page where you want marquee selection to work.\n *\n * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n stroke = 'rgba(0,122,204,0.8)',\n fill = 'rgba(0,122,204,0.15)',\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px dashed ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["rects","boundingRect","BaseSelectionPluginPackage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/text-selection.tsx","../../src/shared/components/marquee-selection.tsx","../../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, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype TextSelectionProps = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * TextSelection renders text selection highlight rects and the selection menu.\n * It registers the text selection handler on the page and subscribes to menu\n * placement changes.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport function TextSelection({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: TextSelectionProps) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */\n background?: string;\n /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */\n borderColor?: string;\n /** Border style. Default: 'dashed' */\n borderStyle?: 'solid' | 'dashed' | 'dotted';\n /**\n * @deprecated Use `borderColor` instead.\n */\n stroke?: string;\n /**\n * @deprecated Use `background` instead.\n */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * It registers the marquee handler on the page.\n *\n * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n background,\n borderColor,\n borderStyle = 'dashed',\n stroke,\n fill,\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n // Resolve deprecated props: new CSS-standard props take precedence\n const resolvedBorderColor = borderColor ?? stroke ?? 'rgba(0,122,204,0.8)';\n const resolvedBackground = background ?? fill ?? 'rgba(0,122,204,0.15)';\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px ${borderStyle} ${resolvedBorderColor}`,\n background: resolvedBackground,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { Fragment } from '@framework';\nimport { Rotation } from '@embedpdf/models';\nimport { TextSelectionStyle, MarqueeSelectionStyle } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { TextSelection } from './text-selection';\nimport { MarqueeSelection } from './marquee-selection';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /**\n * @deprecated Use `textStyle.background` instead.\n */\n background?: string;\n /** Styling options for text selection highlights */\n textStyle?: TextSelectionStyle;\n /** Styling options for the marquee selection rectangle */\n marqueeStyle?: MarqueeSelectionStyle;\n /** Optional CSS class applied to the marquee rectangle */\n marqueeClassName?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * SelectionLayer is a convenience component that composes both text selection\n * and marquee selection on a single page.\n *\n * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`\n * individually.\n */\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale,\n rotation,\n background,\n textStyle,\n marqueeStyle,\n marqueeClassName,\n selectionMenu,\n}: Props) {\n return (\n <Fragment>\n <TextSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n background={textStyle?.background ?? background}\n selectionMenu={selectionMenu}\n />\n <MarqueeSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n background={marqueeStyle?.background}\n borderColor={marqueeStyle?.borderColor}\n borderStyle={marqueeStyle?.borderStyle}\n className={marqueeClassName}\n />\n </Fragment>\n );\n}\n","import { useEffect } from '@framework';\n\nimport { useSelectionCapability } from '../hooks';\n\nexport function CopyToClipboard() {\n const { provides: sel } = useSelectionCapability();\n\n useEffect(() => {\n if (!sel) return;\n return sel.onCopyToClipboard(({ text }) => {\n navigator.clipboard.writeText(text);\n });\n }, [sel]);\n\n return null;\n}\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["rects","boundingRect","Fragment","BaseSelectionPluginPackage"],"mappings":"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"}
|
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"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection"),o=require("react/jsx-runtime"),i=require("react"),n=require("@embedpdf/core/react"),r=require("@embedpdf/utils/react"),l=()=>n.useCapability(t.SelectionPlugin.id),u=()=>n.usePlugin(t.SelectionPlugin.id);function s({documentId:e,pageIndex:t,scale:l,rotation:s,background:a="rgba(33,150,243)",selectionMenu:d}){var c,g;const{plugin:p}=u(),x=n.useDocumentState(e),b=null==(g=null==(c=null==x?void 0:x.document)?void 0:c.pages)?void 0:g[t],[h,m]=i.useState([]),[f,y]=i.useState(null),[v,S]=i.useState(null);i.useEffect(()=>{if(p&&e)return p.registerSelectionOnPage({documentId:e,pageIndex:t,onRectsChange:({rects:e,boundingRect:t})=>{m(e),y(t)}})},[p,e,t]),i.useEffect(()=>{if(p&&e)return p.onMenuPlacement(e,e=>{S(e)})},[p,e]);const I=i.useMemo(()=>void 0!==l?l:(null==x?void 0:x.scale)??1,[l,null==x?void 0:x.scale]),P=i.useMemo(()=>{if(void 0!==s)return s;return(((null==b?void 0:b.rotation)??0)+((null==x?void 0:x.rotation)??0))%4},[s,null==b?void 0:b.rotation,null==x?void 0:x.rotation]),k=d&&v&&v.pageIndex===t&&v.isVisible;return f?o.jsxs(o.Fragment,{children:[o.jsx("div",{style:{position:"absolute",left:f.origin.x*I,top:f.origin.y*I,width:f.size.width*I,height:f.size.height*I,mixBlendMode:"multiply",isolation:"isolate",pointerEvents:"none"},children:h.map((e,t)=>o.jsx("div",{style:{position:"absolute",left:(e.origin.x-f.origin.x)*I,top:(e.origin.y-f.origin.y)*I,width:e.size.width*I,height:e.size.height*I,background:a}},t))}),k&&o.jsx(r.CounterRotate,{rect:{origin:{x:v.rect.origin.x*I,y:v.rect.origin.y*I},size:{width:v.rect.size.width*I,height:v.rect.size.height*I}},rotation:P,children:e=>d({...e,context:{type:"selection",pageIndex:t},selected:!0,placement:v})})]}):null}const a=({documentId:e,pageIndex:t,scale:r,className:l,background:s,borderColor:a,borderStyle:d="dashed",stroke:c,fill:g})=>{const{plugin:p}=u(),x=n.useDocumentState(e),[b,h]=i.useState(null),m=a??c??"rgba(0,122,204,0.8)",f=s??g??"rgba(0,122,204,0.15)",y=i.useMemo(()=>void 0!==r?r:(null==x?void 0:x.scale)??1,[r,null==x?void 0:x.scale]);return i.useEffect(()=>{if(p&&e)return p.registerMarqueeOnPage({documentId:e,pageIndex:t,scale:y,onRectChange:h})},[p,e,t,y]),b?o.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:b.origin.x*y,top:b.origin.y*y,width:b.size.width*y,height:b.size.height*y,border:`1px ${d} ${m}`,background:f,boxSizing:"border-box",zIndex:1e3},className:l}):null};function d(){const{provides:e}=l();return i.useEffect(()=>{if(e)return e.onCopyToClipboard(({text:e})=>{navigator.clipboard.writeText(e)})},[e]),null}const c=e.createPluginPackage(t.SelectionPluginPackage).addUtility(d).build();exports.CopyToClipboard=d,exports.MarqueeSelection=a,exports.SelectionLayer=function({documentId:e,pageIndex:t,scale:n,rotation:r,background:l,textStyle:u,marqueeStyle:d,marqueeClassName:c,selectionMenu:g}){return o.jsxs(i.Fragment,{children:[o.jsx(s,{documentId:e,pageIndex:t,scale:n,rotation:r,background:(null==u?void 0:u.background)??l,selectionMenu:g}),o.jsx(a,{documentId:e,pageIndex:t,scale:n,background:null==d?void 0:d.background,borderColor:null==d?void 0:d.borderColor,borderStyle:null==d?void 0:d.borderStyle,className:c})]})},exports.SelectionPluginPackage=c,exports.TextSelection=s,exports.useSelectionCapability=l,exports.useSelectionPlugin=u,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/components/marquee-selection.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 { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke colour (default: 'rgba(0,122,204,0.8)') */\n stroke?: string;\n /** Fill colour (default: 'rgba(0,122,204,0.15)') */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * Place this component on each page where you want marquee selection to work.\n *\n * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n stroke = 'rgba(0,122,204,0.8)',\n fill = 'rgba(0,122,204,0.15)',\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px dashed ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n // Optimization: We could filter here, but React state updates are cheap enough usually.\n // Ideally, check: if (newPlacement?.pageIndex === pageIndex)\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","CopyToClipboard","provides","sel","useEffect","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","documentId","pageIndex","scale","className","stroke","fill","plugin","selPlugin","documentState","useDocumentState","rect","setRect","useState","actualScale","useMemo","registerMarqueeOnPage","onRectChange","jsx","style","position","pointerEvents","left","origin","x","top","y","width","size","height","border","background","boxSizing","zIndex","scaleOverride","rotation","rotationOverride","selectionMenu","page","_b","_a","document","pages","rects","setRects","boundingRect","setBoundingRect","placement","setPlacement","registerSelectionOnPage","onRectsChange","onMenuPlacement","newPlacement","actualRotation","shouldRenderMenu","isVisible","jsxs","Fragment","children","mixBlendMode","isolation","map","b","i","CounterRotate","props","context","type","selected"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/text-selection.tsx","../../src/shared/components/marquee-selection.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts","../../src/shared/components/selection-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype TextSelectionProps = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * TextSelection renders text selection highlight rects and the selection menu.\n * It registers the text selection handler on the page and subscribes to menu\n * placement changes.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport function TextSelection({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: TextSelectionProps) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */\n background?: string;\n /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */\n borderColor?: string;\n /** Border style. Default: 'dashed' */\n borderStyle?: 'solid' | 'dashed' | 'dotted';\n /**\n * @deprecated Use `borderColor` instead.\n */\n stroke?: string;\n /**\n * @deprecated Use `background` instead.\n */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * It registers the marquee handler on the page.\n *\n * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n background,\n borderColor,\n borderStyle = 'dashed',\n stroke,\n fill,\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n // Resolve deprecated props: new CSS-standard props take precedence\n const resolvedBorderColor = borderColor ?? stroke ?? 'rgba(0,122,204,0.8)';\n const resolvedBackground = background ?? fill ?? 'rgba(0,122,204,0.15)';\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px ${borderStyle} ${resolvedBorderColor}`,\n background: resolvedBackground,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { useEffect } from '@framework';\n\nimport { useSelectionCapability } from '../hooks';\n\nexport function CopyToClipboard() {\n const { provides: sel } = useSelectionCapability();\n\n useEffect(() => {\n if (!sel) return;\n return sel.onCopyToClipboard(({ text }) => {\n navigator.clipboard.writeText(text);\n });\n }, [sel]);\n\n return null;\n}\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n","import { Fragment } from '@framework';\nimport { Rotation } from '@embedpdf/models';\nimport { TextSelectionStyle, MarqueeSelectionStyle } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { TextSelection } from './text-selection';\nimport { MarqueeSelection } from './marquee-selection';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /**\n * @deprecated Use `textStyle.background` instead.\n */\n background?: string;\n /** Styling options for text selection highlights */\n textStyle?: TextSelectionStyle;\n /** Styling options for the marquee selection rectangle */\n marqueeStyle?: MarqueeSelectionStyle;\n /** Optional CSS class applied to the marquee rectangle */\n marqueeClassName?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * SelectionLayer is a convenience component that composes both text selection\n * and marquee selection on a single page.\n *\n * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`\n * individually.\n */\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale,\n rotation,\n background,\n textStyle,\n marqueeStyle,\n marqueeClassName,\n selectionMenu,\n}: Props) {\n return (\n <Fragment>\n <TextSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n background={textStyle?.background ?? background}\n selectionMenu={selectionMenu}\n />\n <MarqueeSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n background={marqueeStyle?.background}\n borderColor={marqueeStyle?.borderColor}\n borderStyle={marqueeStyle?.borderStyle}\n className={marqueeClassName}\n />\n </Fragment>\n );\n}\n"],"names":["useSelectionCapability","useCapability","SelectionPlugin","id","useSelectionPlugin","usePlugin","TextSelection","documentId","pageIndex","scale","scaleOverride","rotation","rotationOverride","background","selectionMenu","plugin","selPlugin","documentState","useDocumentState","page","_b","_a","document","pages","rects","setRects","useState","boundingRect","setBoundingRect","placement","setPlacement","useEffect","registerSelectionOnPage","onRectsChange","onMenuPlacement","newPlacement","actualScale","useMemo","actualRotation","shouldRenderMenu","isVisible","jsxs","Fragment","children","jsx","style","position","left","origin","x","top","y","width","size","height","mixBlendMode","isolation","pointerEvents","map","b","i","CounterRotate","rect","props","context","type","selected","MarqueeSelection","className","borderColor","borderStyle","stroke","fill","setRect","resolvedBorderColor","resolvedBackground","registerMarqueeOnPage","onRectChange","border","boxSizing","zIndex","CopyToClipboard","provides","sel","onCopyToClipboard","text","navigator","clipboard","writeText","SelectionPluginPackage","createPluginPackage","BaseSelectionPluginPackage","addUtility","build","textStyle","marqueeStyle","marqueeClassName"],"mappings":"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"}
|