@embedpdf/plugin-selection 1.0.6 → 1.0.8
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 +46 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +52 -2
- package/dist/index.js.map +1 -1
- package/dist/preact/index.cjs +63 -16
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.cts +4 -2
- package/dist/preact/index.d.ts +4 -2
- package/dist/preact/index.js +68 -18
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +63 -16
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +4 -2
- package/dist/react/index.d.ts +4 -2
- package/dist/react/index.js +68 -18
- package/dist/react/index.js.map +1 -1
- package/package.json +7 -7
package/dist/react/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/react/index.ts
|
|
21
21
|
var react_exports = {};
|
|
22
22
|
__export(react_exports, {
|
|
23
|
+
CopyToClipboard: () => CopyToClipboard,
|
|
23
24
|
SelectionLayer: () => SelectionLayer,
|
|
24
25
|
useSelectionCapability: () => useSelectionCapability,
|
|
25
26
|
useSelectionPlugin: () => useSelectionPlugin
|
|
@@ -40,13 +41,22 @@ var import_plugin_selection2 = require("@embedpdf/plugin-selection");
|
|
|
40
41
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
42
|
function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
42
43
|
const { provides: sel } = useSelectionCapability();
|
|
43
|
-
const {
|
|
44
|
+
const { provides: im } = (0, import_react3.useInteractionManagerCapability)();
|
|
45
|
+
const { register } = (0, import_react3.usePointerHandlers)({ pageIndex });
|
|
44
46
|
const [rects, setRects] = (0, import_react2.useState)([]);
|
|
47
|
+
const [boundingRect, setBoundingRect] = (0, import_react2.useState)(null);
|
|
45
48
|
const { setCursor, removeCursor } = (0, import_react3.useCursor)();
|
|
46
49
|
(0, import_react2.useEffect)(() => {
|
|
47
50
|
if (!sel) return;
|
|
48
51
|
return sel.onSelectionChange(() => {
|
|
49
|
-
|
|
52
|
+
const mode = im?.getActiveMode();
|
|
53
|
+
if (mode === "default") {
|
|
54
|
+
setRects(sel.getHighlightRectsForPage(pageIndex));
|
|
55
|
+
setBoundingRect(sel.getBoundingRectForPage(pageIndex));
|
|
56
|
+
} else {
|
|
57
|
+
setRects([]);
|
|
58
|
+
setBoundingRect(null);
|
|
59
|
+
}
|
|
50
60
|
});
|
|
51
61
|
}, [sel, pageIndex]);
|
|
52
62
|
let geoCache;
|
|
@@ -67,8 +77,9 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
67
77
|
}, [sel, pageIndex]);
|
|
68
78
|
const handlers = (0, import_react2.useMemo)(
|
|
69
79
|
() => ({
|
|
70
|
-
onPointerDown: (point) => {
|
|
80
|
+
onPointerDown: (point, _evt, modeId) => {
|
|
71
81
|
if (!sel) return;
|
|
82
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
72
83
|
sel.clear();
|
|
73
84
|
const task = sel.getGeometry(pageIndex);
|
|
74
85
|
task.wait((geo) => {
|
|
@@ -76,8 +87,9 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
76
87
|
if (g !== -1) sel.begin(pageIndex, g);
|
|
77
88
|
}, import_models.ignore);
|
|
78
89
|
},
|
|
79
|
-
onPointerMove: (point) => {
|
|
90
|
+
onPointerMove: (point, _evt, modeId) => {
|
|
80
91
|
if (!sel) return;
|
|
92
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
81
93
|
const g = cachedGlyphAt(point);
|
|
82
94
|
if (g !== -1) {
|
|
83
95
|
setCursor("selection-text", "text", 10);
|
|
@@ -86,9 +98,15 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
86
98
|
}
|
|
87
99
|
if (g !== -1) sel.update(pageIndex, g);
|
|
88
100
|
},
|
|
89
|
-
onPointerUp: () => {
|
|
101
|
+
onPointerUp: (_point, _evt, modeId) => {
|
|
90
102
|
if (!sel) return;
|
|
103
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
91
104
|
sel.end();
|
|
105
|
+
},
|
|
106
|
+
onHandlerActiveEnd(modeId) {
|
|
107
|
+
if (!sel) return;
|
|
108
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
109
|
+
sel.clear();
|
|
92
110
|
}
|
|
93
111
|
}),
|
|
94
112
|
[sel, pageIndex, cachedGlyphAt]
|
|
@@ -97,24 +115,53 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
97
115
|
if (!register) return;
|
|
98
116
|
return register(handlers);
|
|
99
117
|
}, [register, handlers]);
|
|
100
|
-
|
|
118
|
+
if (!boundingRect) return null;
|
|
119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
101
120
|
"div",
|
|
102
121
|
{
|
|
103
122
|
style: {
|
|
104
123
|
position: "absolute",
|
|
105
|
-
left:
|
|
106
|
-
top:
|
|
107
|
-
width:
|
|
108
|
-
height:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
left: boundingRect.origin.x * scale,
|
|
125
|
+
top: boundingRect.origin.y * scale,
|
|
126
|
+
width: boundingRect.size.width * scale,
|
|
127
|
+
height: boundingRect.size.height * scale,
|
|
128
|
+
mixBlendMode: "multiply",
|
|
129
|
+
isolation: "isolate"
|
|
130
|
+
},
|
|
131
|
+
children: rects.map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
132
|
+
"div",
|
|
133
|
+
{
|
|
134
|
+
style: {
|
|
135
|
+
position: "absolute",
|
|
136
|
+
left: (b.origin.x - boundingRect.origin.x) * scale,
|
|
137
|
+
top: (b.origin.y - boundingRect.origin.y) * scale,
|
|
138
|
+
width: b.size.width * scale,
|
|
139
|
+
height: b.size.height * scale,
|
|
140
|
+
background,
|
|
141
|
+
pointerEvents: "none"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
i
|
|
145
|
+
))
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/react/components/copy-to-clipboard.tsx
|
|
151
|
+
var import_react4 = require("react");
|
|
152
|
+
function CopyToClipboard() {
|
|
153
|
+
const { provides: sel } = useSelectionCapability();
|
|
154
|
+
(0, import_react4.useEffect)(() => {
|
|
155
|
+
if (!sel) return;
|
|
156
|
+
return sel.onCopyToClipboard((text) => {
|
|
157
|
+
navigator.clipboard.writeText(text);
|
|
158
|
+
});
|
|
159
|
+
}, [sel]);
|
|
160
|
+
return null;
|
|
115
161
|
}
|
|
116
162
|
// Annotate the CommonJS export names for ESM import in node:
|
|
117
163
|
0 && (module.exports = {
|
|
164
|
+
CopyToClipboard,
|
|
118
165
|
SelectionLayer,
|
|
119
166
|
useSelectionCapability,
|
|
120
167
|
useSelectionPlugin
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/index.ts","../../src/react/hooks/use-selection.ts","../../src/react/components/selection-layer.tsx"],"sourcesContent":["export * from './hooks';\nexport * from './components';\n","import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { ignore, PdfErrorCode, PdfPageGeometry, Rect } from '@embedpdf/models';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/hooks/use-selection.ts","../../src/react/components/selection-layer.tsx","../../src/react/components/copy-to-clipboard.tsx"],"sourcesContent":["export * from './hooks';\nexport * from './components';\n","import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { ignore, PdfErrorCode, PdfPageGeometry, Rect } from '@embedpdf/models';\nimport {\n useCursor,\n useInteractionManagerCapability,\n usePointerHandlers,\n} from '@embedpdf/plugin-interaction-manager/react';\nimport { PointerEventHandlersWithLifecycle } from '@embedpdf/plugin-interaction-manager';\nimport { glyphAt } from '@embedpdf/plugin-selection';\n\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 { provides: sel } = useSelectionCapability();\n const { provides: im } = useInteractionManagerCapability();\n const { register } = usePointerHandlers({ pageIndex });\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n const { setCursor, removeCursor } = useCursor();\n\n /* subscribe to rect updates */\n useEffect(() => {\n if (!sel) return;\n return sel.onSelectionChange(() => {\n const mode = im?.getActiveMode();\n if (mode === 'default') {\n setRects(sel.getHighlightRectsForPage(pageIndex));\n setBoundingRect(sel.getBoundingRectForPage(pageIndex));\n } else {\n setRects([]);\n setBoundingRect(null);\n }\n });\n }, [sel, pageIndex]);\n\n /* cheap glyphAt cache for the active page */\n let geoCache: PdfPageGeometry | undefined;\n const cachedGlyphAt = useCallback((pt: { x: number; y: number }) => {\n if (!geoCache) return -1;\n return glyphAt(geoCache, pt);\n }, []);\n\n // Initialize geometry cache\n useEffect(() => {\n if (!sel) return;\n const task = sel.getGeometry(pageIndex);\n task.wait((g) => (geoCache = g), ignore);\n\n return () => {\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'Cancelled',\n });\n };\n }, [sel, pageIndex]);\n\n const handlers = useMemo(\n (): PointerEventHandlersWithLifecycle<PointerEvent> => ({\n onPointerDown: (point, _evt, modeId) => {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n // clear the selection\n sel.clear();\n const task = sel.getGeometry(pageIndex);\n task.wait((geo) => {\n const g = glyphAt(geo, point);\n if (g !== -1) sel.begin(pageIndex, g);\n }, ignore);\n },\n onPointerMove: (point, _evt, modeId) => {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n const g = cachedGlyphAt(point);\n if (g !== -1) {\n setCursor('selection-text', 'text', 10);\n } else {\n removeCursor('selection-text');\n }\n if (g !== -1) sel.update(pageIndex, g);\n },\n onPointerUp: (_point, _evt, modeId) => {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n sel.end();\n },\n onHandlerActiveEnd(modeId) {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n\n sel.clear();\n },\n }),\n [sel, pageIndex, cachedGlyphAt],\n );\n\n useEffect(() => {\n if (!register) return;\n return register(handlers);\n }, [register, handlers]);\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 'react';\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"],"mappings":"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","names":["import_react","import_plugin_selection","import_react"]}
|
package/dist/react/index.d.cts
CHANGED
|
@@ -18,6 +18,8 @@ type Props = {
|
|
|
18
18
|
scale: number;
|
|
19
19
|
background?: string;
|
|
20
20
|
};
|
|
21
|
-
declare function SelectionLayer({ pageIndex, scale, background }: Props): react_jsx_runtime.JSX.Element;
|
|
21
|
+
declare function SelectionLayer({ pageIndex, scale, background }: Props): react_jsx_runtime.JSX.Element | null;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
declare function CopyToClipboard(): null;
|
|
24
|
+
|
|
25
|
+
export { CopyToClipboard, SelectionLayer, useSelectionCapability, useSelectionPlugin };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ type Props = {
|
|
|
18
18
|
scale: number;
|
|
19
19
|
background?: string;
|
|
20
20
|
};
|
|
21
|
-
declare function SelectionLayer({ pageIndex, scale, background }: Props): react_jsx_runtime.JSX.Element;
|
|
21
|
+
declare function SelectionLayer({ pageIndex, scale, background }: Props): react_jsx_runtime.JSX.Element | null;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
declare function CopyToClipboard(): null;
|
|
24
|
+
|
|
25
|
+
export { CopyToClipboard, SelectionLayer, useSelectionCapability, useSelectionPlugin };
|
package/dist/react/index.js
CHANGED
|
@@ -7,18 +7,31 @@ var useSelectionPlugin = () => usePlugin(SelectionPlugin.id);
|
|
|
7
7
|
// src/react/components/selection-layer.tsx
|
|
8
8
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
9
9
|
import { ignore, PdfErrorCode } from "@embedpdf/models";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
useCursor,
|
|
12
|
+
useInteractionManagerCapability,
|
|
13
|
+
usePointerHandlers
|
|
14
|
+
} from "@embedpdf/plugin-interaction-manager/react";
|
|
11
15
|
import { glyphAt } from "@embedpdf/plugin-selection";
|
|
12
|
-
import {
|
|
16
|
+
import { jsx } from "react/jsx-runtime";
|
|
13
17
|
function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
14
18
|
const { provides: sel } = useSelectionCapability();
|
|
15
|
-
const {
|
|
19
|
+
const { provides: im } = useInteractionManagerCapability();
|
|
20
|
+
const { register } = usePointerHandlers({ pageIndex });
|
|
16
21
|
const [rects, setRects] = useState([]);
|
|
22
|
+
const [boundingRect, setBoundingRect] = useState(null);
|
|
17
23
|
const { setCursor, removeCursor } = useCursor();
|
|
18
24
|
useEffect(() => {
|
|
19
25
|
if (!sel) return;
|
|
20
26
|
return sel.onSelectionChange(() => {
|
|
21
|
-
|
|
27
|
+
const mode = im?.getActiveMode();
|
|
28
|
+
if (mode === "default") {
|
|
29
|
+
setRects(sel.getHighlightRectsForPage(pageIndex));
|
|
30
|
+
setBoundingRect(sel.getBoundingRectForPage(pageIndex));
|
|
31
|
+
} else {
|
|
32
|
+
setRects([]);
|
|
33
|
+
setBoundingRect(null);
|
|
34
|
+
}
|
|
22
35
|
});
|
|
23
36
|
}, [sel, pageIndex]);
|
|
24
37
|
let geoCache;
|
|
@@ -39,8 +52,9 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
39
52
|
}, [sel, pageIndex]);
|
|
40
53
|
const handlers = useMemo(
|
|
41
54
|
() => ({
|
|
42
|
-
onPointerDown: (point) => {
|
|
55
|
+
onPointerDown: (point, _evt, modeId) => {
|
|
43
56
|
if (!sel) return;
|
|
57
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
44
58
|
sel.clear();
|
|
45
59
|
const task = sel.getGeometry(pageIndex);
|
|
46
60
|
task.wait((geo) => {
|
|
@@ -48,8 +62,9 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
48
62
|
if (g !== -1) sel.begin(pageIndex, g);
|
|
49
63
|
}, ignore);
|
|
50
64
|
},
|
|
51
|
-
onPointerMove: (point) => {
|
|
65
|
+
onPointerMove: (point, _evt, modeId) => {
|
|
52
66
|
if (!sel) return;
|
|
67
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
53
68
|
const g = cachedGlyphAt(point);
|
|
54
69
|
if (g !== -1) {
|
|
55
70
|
setCursor("selection-text", "text", 10);
|
|
@@ -58,9 +73,15 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
58
73
|
}
|
|
59
74
|
if (g !== -1) sel.update(pageIndex, g);
|
|
60
75
|
},
|
|
61
|
-
onPointerUp: () => {
|
|
76
|
+
onPointerUp: (_point, _evt, modeId) => {
|
|
62
77
|
if (!sel) return;
|
|
78
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
63
79
|
sel.end();
|
|
80
|
+
},
|
|
81
|
+
onHandlerActiveEnd(modeId) {
|
|
82
|
+
if (!sel) return;
|
|
83
|
+
if (!sel.isEnabledForMode(modeId)) return;
|
|
84
|
+
sel.clear();
|
|
64
85
|
}
|
|
65
86
|
}),
|
|
66
87
|
[sel, pageIndex, cachedGlyphAt]
|
|
@@ -69,23 +90,52 @@ function SelectionLayer({ pageIndex, scale, background = "rgba(33,150,243)" }) {
|
|
|
69
90
|
if (!register) return;
|
|
70
91
|
return register(handlers);
|
|
71
92
|
}, [register, handlers]);
|
|
72
|
-
|
|
93
|
+
if (!boundingRect) return null;
|
|
94
|
+
return /* @__PURE__ */ jsx(
|
|
73
95
|
"div",
|
|
74
96
|
{
|
|
75
97
|
style: {
|
|
76
98
|
position: "absolute",
|
|
77
|
-
left:
|
|
78
|
-
top:
|
|
79
|
-
width:
|
|
80
|
-
height:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
99
|
+
left: boundingRect.origin.x * scale,
|
|
100
|
+
top: boundingRect.origin.y * scale,
|
|
101
|
+
width: boundingRect.size.width * scale,
|
|
102
|
+
height: boundingRect.size.height * scale,
|
|
103
|
+
mixBlendMode: "multiply",
|
|
104
|
+
isolation: "isolate"
|
|
105
|
+
},
|
|
106
|
+
children: rects.map((b, i) => /* @__PURE__ */ jsx(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
style: {
|
|
110
|
+
position: "absolute",
|
|
111
|
+
left: (b.origin.x - boundingRect.origin.x) * scale,
|
|
112
|
+
top: (b.origin.y - boundingRect.origin.y) * scale,
|
|
113
|
+
width: b.size.width * scale,
|
|
114
|
+
height: b.size.height * scale,
|
|
115
|
+
background,
|
|
116
|
+
pointerEvents: "none"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
i
|
|
120
|
+
))
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/react/components/copy-to-clipboard.tsx
|
|
126
|
+
import { useEffect as useEffect2 } from "react";
|
|
127
|
+
function CopyToClipboard() {
|
|
128
|
+
const { provides: sel } = useSelectionCapability();
|
|
129
|
+
useEffect2(() => {
|
|
130
|
+
if (!sel) return;
|
|
131
|
+
return sel.onCopyToClipboard((text) => {
|
|
132
|
+
navigator.clipboard.writeText(text);
|
|
133
|
+
});
|
|
134
|
+
}, [sel]);
|
|
135
|
+
return null;
|
|
87
136
|
}
|
|
88
137
|
export {
|
|
138
|
+
CopyToClipboard,
|
|
89
139
|
SelectionLayer,
|
|
90
140
|
useSelectionCapability,
|
|
91
141
|
useSelectionPlugin
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/hooks/use-selection.ts","../../src/react/components/selection-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { ignore, PdfErrorCode, PdfPageGeometry, Rect } from '@embedpdf/models';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/react/hooks/use-selection.ts","../../src/react/components/selection-layer.tsx","../../src/react/components/copy-to-clipboard.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { ignore, PdfErrorCode, PdfPageGeometry, Rect } from '@embedpdf/models';\nimport {\n useCursor,\n useInteractionManagerCapability,\n usePointerHandlers,\n} from '@embedpdf/plugin-interaction-manager/react';\nimport { PointerEventHandlersWithLifecycle } from '@embedpdf/plugin-interaction-manager';\nimport { glyphAt } from '@embedpdf/plugin-selection';\n\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 { provides: sel } = useSelectionCapability();\n const { provides: im } = useInteractionManagerCapability();\n const { register } = usePointerHandlers({ pageIndex });\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n const { setCursor, removeCursor } = useCursor();\n\n /* subscribe to rect updates */\n useEffect(() => {\n if (!sel) return;\n return sel.onSelectionChange(() => {\n const mode = im?.getActiveMode();\n if (mode === 'default') {\n setRects(sel.getHighlightRectsForPage(pageIndex));\n setBoundingRect(sel.getBoundingRectForPage(pageIndex));\n } else {\n setRects([]);\n setBoundingRect(null);\n }\n });\n }, [sel, pageIndex]);\n\n /* cheap glyphAt cache for the active page */\n let geoCache: PdfPageGeometry | undefined;\n const cachedGlyphAt = useCallback((pt: { x: number; y: number }) => {\n if (!geoCache) return -1;\n return glyphAt(geoCache, pt);\n }, []);\n\n // Initialize geometry cache\n useEffect(() => {\n if (!sel) return;\n const task = sel.getGeometry(pageIndex);\n task.wait((g) => (geoCache = g), ignore);\n\n return () => {\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'Cancelled',\n });\n };\n }, [sel, pageIndex]);\n\n const handlers = useMemo(\n (): PointerEventHandlersWithLifecycle<PointerEvent> => ({\n onPointerDown: (point, _evt, modeId) => {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n // clear the selection\n sel.clear();\n const task = sel.getGeometry(pageIndex);\n task.wait((geo) => {\n const g = glyphAt(geo, point);\n if (g !== -1) sel.begin(pageIndex, g);\n }, ignore);\n },\n onPointerMove: (point, _evt, modeId) => {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n const g = cachedGlyphAt(point);\n if (g !== -1) {\n setCursor('selection-text', 'text', 10);\n } else {\n removeCursor('selection-text');\n }\n if (g !== -1) sel.update(pageIndex, g);\n },\n onPointerUp: (_point, _evt, modeId) => {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n sel.end();\n },\n onHandlerActiveEnd(modeId) {\n if (!sel) return;\n if (!sel.isEnabledForMode(modeId)) return;\n\n sel.clear();\n },\n }),\n [sel, pageIndex, cachedGlyphAt],\n );\n\n useEffect(() => {\n if (!register) return;\n return register(handlers);\n }, [register, handlers]);\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 'react';\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"],"mappings":"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","names":["useEffect","useEffect"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-selection",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -23,22 +23,22 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@embedpdf/models": "1.0.
|
|
26
|
+
"@embedpdf/models": "1.0.8"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/react": "^18.2.0",
|
|
30
30
|
"tsup": "^8.0.0",
|
|
31
31
|
"typescript": "^5.0.0",
|
|
32
|
-
"@embedpdf/plugin-viewport": "1.0.
|
|
33
|
-
"@embedpdf/plugin-interaction-manager": "1.0.
|
|
32
|
+
"@embedpdf/plugin-viewport": "1.0.8",
|
|
33
|
+
"@embedpdf/plugin-interaction-manager": "1.0.8"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=16.8.0",
|
|
37
37
|
"react-dom": ">=16.8.0",
|
|
38
38
|
"preact": "^10.26.4",
|
|
39
|
-
"@embedpdf/plugin-viewport": "1.0.
|
|
40
|
-
"@embedpdf/plugin-interaction-manager": "1.0.
|
|
41
|
-
"@embedpdf/core": "1.0.
|
|
39
|
+
"@embedpdf/plugin-viewport": "1.0.8",
|
|
40
|
+
"@embedpdf/plugin-interaction-manager": "1.0.8",
|
|
41
|
+
"@embedpdf/core": "1.0.8"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"dist",
|