@embedpdf/plugin-selection 1.0.11 → 1.0.12
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 +2 -450
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -210
- package/dist/index.js +27 -53
- package/dist/index.js.map +1 -1
- package/dist/lib/actions.d.ts +57 -0
- package/dist/lib/index.d.ts +9 -0
- package/dist/lib/manifest.d.ts +4 -0
- package/dist/lib/reducer.d.ts +4 -0
- package/dist/lib/selection-plugin.d.ts +29 -0
- package/dist/lib/selectors.d.ts +14 -0
- package/dist/lib/types.d.ts +63 -0
- package/dist/lib/utils.d.ts +70 -0
- package/dist/preact/adapter.d.ts +4 -0
- package/dist/preact/core.d.ts +1 -0
- package/dist/preact/index.cjs +2 -170
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.ts +1 -25
- package/dist/preact/index.js +10 -20
- package/dist/preact/index.js.map +1 -1
- package/dist/preact/interaction-manager.d.ts +1 -0
- package/dist/react/adapter.d.ts +2 -0
- package/dist/react/core.d.ts +1 -0
- package/dist/react/index.cjs +2 -170
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +1 -25
- package/dist/react/index.js +9 -20
- package/dist/react/index.js.map +1 -1
- package/dist/react/interaction-manager.d.ts +1 -0
- package/dist/shared-preact/components/copy-to-clipboard.d.ts +1 -0
- package/dist/shared-preact/components/index.d.ts +2 -0
- package/dist/shared-preact/components/selection-layer.d.ts +7 -0
- package/dist/shared-preact/hooks/index.d.ts +1 -0
- package/dist/shared-preact/hooks/use-selection.d.ts +11 -0
- package/dist/shared-preact/index.d.ts +2 -0
- package/dist/shared-react/components/copy-to-clipboard.d.ts +1 -0
- package/dist/shared-react/components/index.d.ts +2 -0
- package/dist/shared-react/components/selection-layer.d.ts +7 -0
- package/dist/shared-react/hooks/index.d.ts +1 -0
- package/dist/shared-react/hooks/use-selection.d.ts +11 -0
- package/dist/shared-react/index.d.ts +2 -0
- package/dist/vue/components/copy-to-clipboard.vue.d.ts +2 -0
- package/dist/vue/components/index.d.ts +2 -0
- package/dist/vue/components/selection-layer.vue.d.ts +9 -0
- package/dist/vue/hooks/index.d.ts +1 -0
- package/dist/vue/hooks/use-selection.d.ts +11 -0
- package/dist/vue/index.cjs +2 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +145 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +23 -14
- package/dist/index.d.cts +0 -210
- package/dist/preact/index.d.cts +0 -25
- package/dist/react/index.d.cts +0 -25
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { useCapability, usePlugin } from "@embedpdf/core/vue";
|
|
2
|
+
import { SelectionPlugin, glyphAt } from "@embedpdf/plugin-selection";
|
|
3
|
+
import { defineComponent, ref, watchEffect, computed, createElementBlock, createCommentVNode, openBlock, normalizeStyle, Fragment, renderList } from "vue";
|
|
4
|
+
import { ignore, PdfErrorCode } from "@embedpdf/models";
|
|
5
|
+
import { useInteractionManagerCapability, usePointerHandlers, useCursor } from "@embedpdf/plugin-interaction-manager/vue";
|
|
6
|
+
const useSelectionCapability = () => useCapability(SelectionPlugin.id);
|
|
7
|
+
const useSelectionPlugin = () => usePlugin(SelectionPlugin.id);
|
|
8
|
+
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
9
|
+
__name: "selection-layer",
|
|
10
|
+
props: {
|
|
11
|
+
pageIndex: {},
|
|
12
|
+
scale: {},
|
|
13
|
+
background: { default: "rgba(33, 150, 243)" }
|
|
14
|
+
},
|
|
15
|
+
setup(__props) {
|
|
16
|
+
const props = __props;
|
|
17
|
+
const { provides: sel } = useSelectionCapability();
|
|
18
|
+
const { provides: im } = useInteractionManagerCapability();
|
|
19
|
+
const { register } = usePointerHandlers({ pageIndex: props.pageIndex });
|
|
20
|
+
const { setCursor, removeCursor } = useCursor();
|
|
21
|
+
const rects = ref([]);
|
|
22
|
+
const boundingRect = ref(null);
|
|
23
|
+
watchEffect((onCleanup) => {
|
|
24
|
+
if (sel.value) {
|
|
25
|
+
const unsubscribe = sel.value.onSelectionChange(() => {
|
|
26
|
+
var _a;
|
|
27
|
+
const mode = (_a = im.value) == null ? void 0 : _a.getActiveMode();
|
|
28
|
+
if (mode === "default") {
|
|
29
|
+
rects.value = sel.value.getHighlightRectsForPage(props.pageIndex);
|
|
30
|
+
boundingRect.value = sel.value.getBoundingRectForPage(props.pageIndex);
|
|
31
|
+
} else {
|
|
32
|
+
rects.value = [];
|
|
33
|
+
boundingRect.value = null;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
onCleanup(unsubscribe);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
let geoCache;
|
|
40
|
+
watchEffect((onCleanup) => {
|
|
41
|
+
if (sel.value) {
|
|
42
|
+
const task = sel.value.getGeometry(props.pageIndex);
|
|
43
|
+
task.wait((g) => geoCache = g, ignore);
|
|
44
|
+
onCleanup(() => {
|
|
45
|
+
task.abort({
|
|
46
|
+
code: PdfErrorCode.Cancelled,
|
|
47
|
+
message: "SelectionLayer unmounted"
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const handlers = computed(
|
|
53
|
+
() => ({
|
|
54
|
+
onPointerDown: (point, _evt, modeId) => {
|
|
55
|
+
if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;
|
|
56
|
+
sel.value.clear();
|
|
57
|
+
const task = sel.value.getGeometry(props.pageIndex);
|
|
58
|
+
task.wait((geo) => {
|
|
59
|
+
const g = glyphAt(geo, point);
|
|
60
|
+
if (g !== -1) sel.value.begin(props.pageIndex, g);
|
|
61
|
+
}, ignore);
|
|
62
|
+
},
|
|
63
|
+
onPointerMove: (point, _evt, modeId) => {
|
|
64
|
+
if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;
|
|
65
|
+
const g = geoCache ? glyphAt(geoCache, point) : -1;
|
|
66
|
+
if (g !== -1) {
|
|
67
|
+
setCursor("selection-text", "text", 10);
|
|
68
|
+
sel.value.update(props.pageIndex, g);
|
|
69
|
+
} else {
|
|
70
|
+
removeCursor("selection-text");
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
onPointerUp: (_point, _evt, modeId) => {
|
|
74
|
+
if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;
|
|
75
|
+
sel.value.end();
|
|
76
|
+
},
|
|
77
|
+
onHandlerActiveEnd: (modeId) => {
|
|
78
|
+
if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;
|
|
79
|
+
sel.value.clear();
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
watchEffect((onCleanup) => {
|
|
84
|
+
if (register) {
|
|
85
|
+
const cleanup = register(handlers.value);
|
|
86
|
+
if (cleanup) onCleanup(cleanup);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return (_ctx, _cache) => {
|
|
90
|
+
return boundingRect.value ? (openBlock(), createElementBlock("div", {
|
|
91
|
+
key: 0,
|
|
92
|
+
style: normalizeStyle({
|
|
93
|
+
position: "absolute",
|
|
94
|
+
left: `${boundingRect.value.origin.x * _ctx.scale}px`,
|
|
95
|
+
top: `${boundingRect.value.origin.y * _ctx.scale}px`,
|
|
96
|
+
width: `${boundingRect.value.size.width * _ctx.scale}px`,
|
|
97
|
+
height: `${boundingRect.value.size.height * _ctx.scale}px`,
|
|
98
|
+
mixBlendMode: "multiply",
|
|
99
|
+
isolation: "isolate",
|
|
100
|
+
pointerEvents: "none"
|
|
101
|
+
})
|
|
102
|
+
}, [
|
|
103
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(rects.value, (rect, i) => {
|
|
104
|
+
return openBlock(), createElementBlock("div", {
|
|
105
|
+
key: i,
|
|
106
|
+
style: normalizeStyle({
|
|
107
|
+
position: "absolute",
|
|
108
|
+
left: `${(rect.origin.x - boundingRect.value.origin.x) * _ctx.scale}px`,
|
|
109
|
+
top: `${(rect.origin.y - boundingRect.value.origin.y) * _ctx.scale}px`,
|
|
110
|
+
width: `${rect.size.width * _ctx.scale}px`,
|
|
111
|
+
height: `${rect.size.height * _ctx.scale}px`,
|
|
112
|
+
background: _ctx.background
|
|
113
|
+
})
|
|
114
|
+
}, null, 4);
|
|
115
|
+
}), 128))
|
|
116
|
+
], 4)) : createCommentVNode("", true);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
121
|
+
__name: "copy-to-clipboard",
|
|
122
|
+
setup(__props) {
|
|
123
|
+
const { provides: sel } = useSelectionCapability();
|
|
124
|
+
watchEffect((onCleanup) => {
|
|
125
|
+
if (sel.value) {
|
|
126
|
+
const unsubscribe = sel.value.onCopyToClipboard((text) => {
|
|
127
|
+
navigator.clipboard.writeText(text).catch((err) => {
|
|
128
|
+
console.error("Failed to copy text to clipboard:", err);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
onCleanup(unsubscribe);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
return (_ctx, _cache) => {
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
export {
|
|
140
|
+
_sfc_main as CopyToClipboard,
|
|
141
|
+
_sfc_main$1 as SelectionLayer,
|
|
142
|
+
useSelectionCapability,
|
|
143
|
+
useSelectionPlugin
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-selection.ts","../../src/vue/components/selection-layer.vue","../../src/vue/components/copy-to-clipboard.vue"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\n/**\n * Hook to get the selection plugin's capability API.\n * This provides methods for controlling and listening to selection events.\n */\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\n\n/**\n * Hook to get the raw selection plugin instance.\n * Useful for accessing plugin-specific properties or methods not exposed in the capability.\n */\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","<script setup lang=\"ts\">\nimport { ref, watchEffect, computed } from 'vue';\nimport { ignore, PdfErrorCode, PdfPageGeometry, Rect } from '@embedpdf/models';\nimport {\n useCursor,\n useInteractionManagerCapability,\n usePointerHandlers,\n} from '@embedpdf/plugin-interaction-manager/vue';\nimport { PointerEventHandlersWithLifecycle } from '@embedpdf/plugin-interaction-manager';\nimport { glyphAt } from '@embedpdf/plugin-selection';\nimport { useSelectionCapability } from '../hooks';\n\ninterface Props {\n pageIndex: number;\n scale: number;\n background?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n background: 'rgba(33, 150, 243)', // Default selection color\n});\n\nconst { provides: sel } = useSelectionCapability();\nconst { provides: im } = useInteractionManagerCapability();\nconst { register } = usePointerHandlers({ pageIndex: props.pageIndex });\nconst { setCursor, removeCursor } = useCursor();\n\nconst rects = ref<Rect[]>([]);\nconst boundingRect = ref<Rect | null>(null);\n\n// Subscribe to selection changes and update the rendered rectangles\nwatchEffect((onCleanup) => {\n if (sel.value) {\n const unsubscribe = sel.value.onSelectionChange(() => {\n const mode = im.value?.getActiveMode();\n if (mode === 'default') {\n rects.value = sel.value!.getHighlightRectsForPage(props.pageIndex);\n boundingRect.value = sel.value!.getBoundingRectForPage(props.pageIndex);\n } else {\n rects.value = [];\n boundingRect.value = null;\n }\n });\n onCleanup(unsubscribe);\n }\n});\n\n// Cache page geometry for faster hit-testing during pointer moves\nlet geoCache: PdfPageGeometry | undefined;\nwatchEffect((onCleanup) => {\n if (sel.value) {\n const task = sel.value.getGeometry(props.pageIndex);\n task.wait((g) => (geoCache = g), ignore);\n\n onCleanup(() => {\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'SelectionLayer unmounted',\n });\n });\n }\n});\n\nconst handlers = computed(\n (): PointerEventHandlersWithLifecycle<PointerEvent> => ({\n onPointerDown: (point, _evt, modeId) => {\n if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;\n sel.value.clear();\n const task = sel.value.getGeometry(props.pageIndex);\n task.wait((geo) => {\n const g = glyphAt(geo, point);\n if (g !== -1) sel.value!.begin(props.pageIndex, g);\n }, ignore);\n },\n onPointerMove: (point, _evt, modeId) => {\n if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;\n const g = geoCache ? glyphAt(geoCache, point) : -1;\n if (g !== -1) {\n setCursor('selection-text', 'text', 10);\n sel.value.update(props.pageIndex, g);\n } else {\n removeCursor('selection-text');\n }\n },\n onPointerUp: (_point, _evt, modeId) => {\n if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;\n sel.value.end();\n },\n onHandlerActiveEnd: (modeId) => {\n if (!sel.value || !sel.value.isEnabledForMode(modeId)) return;\n sel.value.clear();\n },\n }),\n);\n\n// Register the pointer handlers with the interaction manager\nwatchEffect((onCleanup) => {\n if (register) {\n const cleanup = register(handlers.value);\n if (cleanup) onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div\n v-if=\"boundingRect\"\n :style=\"{\n position: 'absolute',\n left: `${boundingRect.origin.x * scale}px`,\n top: `${boundingRect.origin.y * scale}px`,\n width: `${boundingRect.size.width * scale}px`,\n height: `${boundingRect.size.height * scale}px`,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }\"\n >\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n :style=\"{\n position: 'absolute',\n left: `${(rect.origin.x - boundingRect.origin.x) * scale}px`,\n top: `${(rect.origin.y - boundingRect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: background,\n }\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { watchEffect } from 'vue';\nimport { useSelectionCapability } from '../hooks';\n\nconst { provides: sel } = useSelectionCapability();\n\n// This effect runs when the component is mounted and the capability is available.\n// It automatically handles unsubscribing when the component is unmounted.\nwatchEffect((onCleanup) => {\n if (sel.value) {\n const unsubscribe = sel.value.onCopyToClipboard((text) => {\n // Use the Clipboard API to write the text\n navigator.clipboard.writeText(text).catch((err) => {\n console.error('Failed to copy text to clipboard:', err);\n });\n });\n\n // Register the cleanup function to run on unmount or re-run\n onCleanup(unsubscribe);\n }\n});\n</script>\n\n<template>\n <!-- This component renders nothing to the DOM -->\n</template>\n"],"names":["_createElementBlock","_normalizeStyle","scale","_openBlock","_Fragment","_renderList","background"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-selection",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -20,25 +20,32 @@
|
|
|
20
20
|
"types": "./dist/react/index.d.ts",
|
|
21
21
|
"import": "./dist/react/index.js",
|
|
22
22
|
"require": "./dist/react/index.cjs"
|
|
23
|
+
},
|
|
24
|
+
"./vue": {
|
|
25
|
+
"types": "./dist/vue/index.d.ts",
|
|
26
|
+
"import": "./dist/vue/index.js",
|
|
27
|
+
"require": "./dist/vue/index.cjs"
|
|
23
28
|
}
|
|
24
29
|
},
|
|
25
30
|
"dependencies": {
|
|
26
|
-
"@embedpdf/models": "1.0.
|
|
31
|
+
"@embedpdf/models": "1.0.12"
|
|
27
32
|
},
|
|
28
33
|
"devDependencies": {
|
|
29
34
|
"@types/react": "^18.2.0",
|
|
30
|
-
"tsup": "^8.0.0",
|
|
31
35
|
"typescript": "^5.0.0",
|
|
32
|
-
"@embedpdf/
|
|
33
|
-
"@embedpdf/
|
|
36
|
+
"@embedpdf/build": "1.0.0",
|
|
37
|
+
"@embedpdf/core": "1.0.12",
|
|
38
|
+
"@embedpdf/plugin-viewport": "1.0.12",
|
|
39
|
+
"@embedpdf/plugin-interaction-manager": "1.0.12"
|
|
34
40
|
},
|
|
35
41
|
"peerDependencies": {
|
|
36
42
|
"react": ">=16.8.0",
|
|
37
43
|
"react-dom": ">=16.8.0",
|
|
38
44
|
"preact": "^10.26.4",
|
|
39
|
-
"
|
|
40
|
-
"@embedpdf/
|
|
41
|
-
"@embedpdf/plugin-
|
|
45
|
+
"vue": ">=3.2.0",
|
|
46
|
+
"@embedpdf/core": "1.0.12",
|
|
47
|
+
"@embedpdf/plugin-viewport": "1.0.12",
|
|
48
|
+
"@embedpdf/plugin-interaction-manager": "1.0.12"
|
|
42
49
|
},
|
|
43
50
|
"files": [
|
|
44
51
|
"dist",
|
|
@@ -57,11 +64,13 @@
|
|
|
57
64
|
"access": "public"
|
|
58
65
|
},
|
|
59
66
|
"scripts": {
|
|
60
|
-
"build": "
|
|
61
|
-
"build:
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
67
|
+
"build:base": "vite build --mode base",
|
|
68
|
+
"build:react": "vite build --mode react",
|
|
69
|
+
"build:preact": "vite build --mode preact",
|
|
70
|
+
"build:vue": "vite build --mode vue",
|
|
71
|
+
"build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\"",
|
|
72
|
+
"clean": "rimraf dist",
|
|
73
|
+
"lint": "eslint src --color",
|
|
74
|
+
"lint:fix": "eslint src --color --fix"
|
|
66
75
|
}
|
|
67
76
|
}
|
package/dist/index.d.cts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { BasePluginConfig, EventHook, Action, BasePlugin, PluginRegistry, PluginManifest, PluginPackage } from '@embedpdf/core';
|
|
2
|
-
import { PdfTask, PdfPageGeometry, Rect, PdfEngine, Position } from '@embedpdf/models';
|
|
3
|
-
|
|
4
|
-
interface SelectionPluginConfig extends BasePluginConfig {
|
|
5
|
-
}
|
|
6
|
-
interface GlyphPointer {
|
|
7
|
-
page: number;
|
|
8
|
-
index: number;
|
|
9
|
-
}
|
|
10
|
-
interface SelectionRangeX {
|
|
11
|
-
start: GlyphPointer;
|
|
12
|
-
end: GlyphPointer;
|
|
13
|
-
}
|
|
14
|
-
interface SelectionState {
|
|
15
|
-
/** page → geometry cache */
|
|
16
|
-
geometry: Record<number, PdfPageGeometry>;
|
|
17
|
-
/** current selection or null */
|
|
18
|
-
rects: Record<number, Rect[]>;
|
|
19
|
-
selection: SelectionRangeX | null;
|
|
20
|
-
slices: Record<number, {
|
|
21
|
-
start: number;
|
|
22
|
-
count: number;
|
|
23
|
-
}>;
|
|
24
|
-
active: boolean;
|
|
25
|
-
selecting: boolean;
|
|
26
|
-
}
|
|
27
|
-
interface FormattedSelection {
|
|
28
|
-
pageIndex: number;
|
|
29
|
-
rect: Rect;
|
|
30
|
-
segmentRects: Rect[];
|
|
31
|
-
}
|
|
32
|
-
interface SelectionCapability {
|
|
33
|
-
getGeometry(page: number): PdfTask<PdfPageGeometry>;
|
|
34
|
-
getFormattedSelection(): FormattedSelection[];
|
|
35
|
-
getFormattedSelectionForPage(page: number): FormattedSelection | null;
|
|
36
|
-
getHighlightRectsForPage(page: number): Rect[];
|
|
37
|
-
getHighlightRects(): Record<number, Rect[]>;
|
|
38
|
-
getBoundingRectForPage(page: number): Rect | null;
|
|
39
|
-
getBoundingRects(): {
|
|
40
|
-
page: number;
|
|
41
|
-
rect: Rect;
|
|
42
|
-
}[];
|
|
43
|
-
getSelectedText(): PdfTask<string[]>;
|
|
44
|
-
copyToClipboard(): void;
|
|
45
|
-
begin(page: number, glyphIdx: number): void;
|
|
46
|
-
update(page: number, glyphIdx: number): void;
|
|
47
|
-
end(): void;
|
|
48
|
-
clear(): void;
|
|
49
|
-
onSelectionChange: EventHook<SelectionRangeX | null>;
|
|
50
|
-
onTextRetrieved: EventHook<string[]>;
|
|
51
|
-
onCopyToClipboard: EventHook<string>;
|
|
52
|
-
onBeginSelection: EventHook<{
|
|
53
|
-
page: number;
|
|
54
|
-
index: number;
|
|
55
|
-
}>;
|
|
56
|
-
onEndSelection: EventHook<void>;
|
|
57
|
-
/** Tell the selection plugin that text selection should stay
|
|
58
|
-
enabled while <modeId> is active. */
|
|
59
|
-
enableForMode(modeId: string): void;
|
|
60
|
-
/** Quick check used by SelectionLayer during pointer events. */
|
|
61
|
-
isEnabledForMode(modeId: string): boolean;
|
|
62
|
-
/** Get the current state of the selection plugin. */
|
|
63
|
-
getState(): SelectionState;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
declare const CACHE_PAGE_GEOMETRY = "CACHE_PAGE_GEOMETRY";
|
|
67
|
-
declare const SET_SELECTION = "SET_SELECTION";
|
|
68
|
-
declare const START_SELECTION = "START_SELECTION";
|
|
69
|
-
declare const END_SELECTION = "END_SELECTION";
|
|
70
|
-
declare const CLEAR_SELECTION = "CLEAR_SELECTION";
|
|
71
|
-
declare const SET_RECTS = "SET_RECTS";
|
|
72
|
-
declare const SET_SLICES = "SET_SLICES";
|
|
73
|
-
declare const RESET = "RESET";
|
|
74
|
-
interface CachePageGeometryAction extends Action {
|
|
75
|
-
type: typeof CACHE_PAGE_GEOMETRY;
|
|
76
|
-
payload: {
|
|
77
|
-
page: number;
|
|
78
|
-
geo: PdfPageGeometry;
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
interface SetSelectionAction extends Action {
|
|
82
|
-
type: typeof SET_SELECTION;
|
|
83
|
-
payload: SelectionRangeX | null;
|
|
84
|
-
}
|
|
85
|
-
interface StartSelectionAction extends Action {
|
|
86
|
-
type: typeof START_SELECTION;
|
|
87
|
-
}
|
|
88
|
-
interface EndSelectionAction extends Action {
|
|
89
|
-
type: typeof END_SELECTION;
|
|
90
|
-
}
|
|
91
|
-
interface ClearSelectionAction extends Action {
|
|
92
|
-
type: typeof CLEAR_SELECTION;
|
|
93
|
-
}
|
|
94
|
-
interface SetRectsAction extends Action {
|
|
95
|
-
type: typeof SET_RECTS;
|
|
96
|
-
payload: Record<number, Rect[]>;
|
|
97
|
-
}
|
|
98
|
-
interface SetSlicesAction extends Action {
|
|
99
|
-
type: typeof SET_SLICES;
|
|
100
|
-
payload: Record<number, {
|
|
101
|
-
start: number;
|
|
102
|
-
count: number;
|
|
103
|
-
}>;
|
|
104
|
-
}
|
|
105
|
-
interface ResetAction extends Action {
|
|
106
|
-
type: typeof RESET;
|
|
107
|
-
}
|
|
108
|
-
type SelectionAction = CachePageGeometryAction | SetSelectionAction | StartSelectionAction | EndSelectionAction | ClearSelectionAction | SetRectsAction | SetSlicesAction | ResetAction;
|
|
109
|
-
|
|
110
|
-
declare class SelectionPlugin extends BasePlugin<SelectionPluginConfig, SelectionCapability, SelectionState, SelectionAction> {
|
|
111
|
-
private engine;
|
|
112
|
-
static readonly id: "selection";
|
|
113
|
-
/** Modes that should trigger text-selection logic */
|
|
114
|
-
private enabledModes;
|
|
115
|
-
private selecting;
|
|
116
|
-
private anchor?;
|
|
117
|
-
private readonly selChange$;
|
|
118
|
-
private readonly textRetrieved$;
|
|
119
|
-
private readonly copyToClipboard$;
|
|
120
|
-
private readonly beginSelection$;
|
|
121
|
-
private readonly endSelection$;
|
|
122
|
-
constructor(id: string, registry: PluginRegistry, engine: PdfEngine);
|
|
123
|
-
initialize(): Promise<void>;
|
|
124
|
-
destroy(): Promise<void>;
|
|
125
|
-
buildCapability(): SelectionCapability;
|
|
126
|
-
private getOrLoadGeometry;
|
|
127
|
-
private beginSelection;
|
|
128
|
-
private endSelection;
|
|
129
|
-
private clearSelection;
|
|
130
|
-
private updateSelection;
|
|
131
|
-
private updateRectsAndSlices;
|
|
132
|
-
private getSelectedText;
|
|
133
|
-
private copyToClipboard;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
declare const SELECTION_PLUGIN_ID = "selection";
|
|
137
|
-
declare const manifest: PluginManifest<SelectionPluginConfig>;
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Hit-test helper using runs
|
|
141
|
-
* @param geo - page geometry
|
|
142
|
-
* @param pt - point
|
|
143
|
-
* @returns glyph index
|
|
144
|
-
*/
|
|
145
|
-
declare function glyphAt(geo: PdfPageGeometry, pt: Position): number;
|
|
146
|
-
/**
|
|
147
|
-
* Helper: min/max glyph indices on `page` for current sel
|
|
148
|
-
* @param sel - selection range
|
|
149
|
-
* @param geo - page geometry
|
|
150
|
-
* @param page - page index
|
|
151
|
-
* @returns { from: number; to: number } | null
|
|
152
|
-
*/
|
|
153
|
-
declare function sliceBounds(sel: SelectionRangeX | null, geo: PdfPageGeometry | undefined, page: number): {
|
|
154
|
-
from: number;
|
|
155
|
-
to: number;
|
|
156
|
-
} | null;
|
|
157
|
-
/**
|
|
158
|
-
* Helper: build rects for a slice of the page
|
|
159
|
-
* @param geo - page geometry
|
|
160
|
-
* @param from - from index
|
|
161
|
-
* @param to - to index
|
|
162
|
-
* @param merge - whether to merge adjacent rects (default: true)
|
|
163
|
-
* @returns rects
|
|
164
|
-
*/
|
|
165
|
-
declare function rectsWithinSlice(geo: PdfPageGeometry, from: number, to: number, merge?: boolean): Rect[];
|
|
166
|
-
/**
|
|
167
|
-
* ============================================================================
|
|
168
|
-
* Rectangle Merging Algorithm
|
|
169
|
-
* ============================================================================
|
|
170
|
-
*
|
|
171
|
-
* The following code is adapted from Chromium's PDF text selection implementation.
|
|
172
|
-
*
|
|
173
|
-
* Copyright 2010 The Chromium Authors
|
|
174
|
-
* Use of this source code is governed by a BSD-style license that can be
|
|
175
|
-
* found in the LICENSE file: https://source.chromium.org/chromium/chromium/src/+/main:LICENSE
|
|
176
|
-
*
|
|
177
|
-
* Original source:
|
|
178
|
-
* https://source.chromium.org/chromium/chromium/src/+/main:pdf/pdfium/pdfium_range.cc
|
|
179
|
-
*
|
|
180
|
-
* Adapted for TypeScript and this project's Rect/geometry types.
|
|
181
|
-
*/
|
|
182
|
-
/**
|
|
183
|
-
* Text run info for rect merging (similar to Chromium's ScreenRectTextRunInfo)
|
|
184
|
-
*/
|
|
185
|
-
interface TextRunInfo {
|
|
186
|
-
rect: Rect;
|
|
187
|
-
charCount: number;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Helper functions for Rect operations
|
|
191
|
-
*/
|
|
192
|
-
declare function rectUnion(rect1: Rect, rect2: Rect): Rect;
|
|
193
|
-
declare function rectIntersect(rect1: Rect, rect2: Rect): Rect;
|
|
194
|
-
declare function rectIsEmpty(rect: Rect): boolean;
|
|
195
|
-
/**
|
|
196
|
-
* Returns a ratio between [0, 1] representing vertical overlap
|
|
197
|
-
*/
|
|
198
|
-
declare function getVerticalOverlap(rect1: Rect, rect2: Rect): number;
|
|
199
|
-
/**
|
|
200
|
-
* Returns true if there is sufficient horizontal and vertical overlap
|
|
201
|
-
*/
|
|
202
|
-
declare function shouldMergeHorizontalRects(textRun1: TextRunInfo, textRun2: TextRunInfo): boolean;
|
|
203
|
-
/**
|
|
204
|
-
* Merge adjacent rectangles based on proximity and overlap (similar to Chromium's algorithm)
|
|
205
|
-
*/
|
|
206
|
-
declare function mergeAdjacentRects(textRuns: TextRunInfo[]): Rect[];
|
|
207
|
-
|
|
208
|
-
declare const SelectionPluginPackage: PluginPackage<SelectionPlugin, SelectionPluginConfig, SelectionState, SelectionAction>;
|
|
209
|
-
|
|
210
|
-
export { type FormattedSelection, type GlyphPointer, SELECTION_PLUGIN_ID, type SelectionCapability, SelectionPlugin, type SelectionPluginConfig, SelectionPluginPackage, type SelectionRangeX, type SelectionState, type TextRunInfo, getVerticalOverlap, glyphAt, manifest, mergeAdjacentRects, rectIntersect, rectIsEmpty, rectUnion, rectsWithinSlice, shouldMergeHorizontalRects, sliceBounds };
|
package/dist/preact/index.d.cts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as _embedpdf_plugin_selection from '@embedpdf/plugin-selection';
|
|
2
|
-
import { SelectionPlugin } from '@embedpdf/plugin-selection';
|
|
3
|
-
import * as preact from 'preact';
|
|
4
|
-
|
|
5
|
-
declare const useSelectionCapability: () => {
|
|
6
|
-
provides: Readonly<_embedpdf_plugin_selection.SelectionCapability> | null;
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
ready: Promise<void>;
|
|
9
|
-
};
|
|
10
|
-
declare const useSelectionPlugin: () => {
|
|
11
|
-
plugin: SelectionPlugin | null;
|
|
12
|
-
isLoading: boolean;
|
|
13
|
-
ready: Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
type Props = {
|
|
17
|
-
pageIndex: number;
|
|
18
|
-
scale: number;
|
|
19
|
-
background?: string;
|
|
20
|
-
};
|
|
21
|
-
declare function SelectionLayer({ pageIndex, scale, background }: Props): preact.JSX.Element | null;
|
|
22
|
-
|
|
23
|
-
declare function CopyToClipboard(): null;
|
|
24
|
-
|
|
25
|
-
export { CopyToClipboard, SelectionLayer, useSelectionCapability, useSelectionPlugin };
|
package/dist/react/index.d.cts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as _embedpdf_plugin_selection from '@embedpdf/plugin-selection';
|
|
2
|
-
import { SelectionPlugin } from '@embedpdf/plugin-selection';
|
|
3
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
-
|
|
5
|
-
declare const useSelectionCapability: () => {
|
|
6
|
-
provides: Readonly<_embedpdf_plugin_selection.SelectionCapability> | null;
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
ready: Promise<void>;
|
|
9
|
-
};
|
|
10
|
-
declare const useSelectionPlugin: () => {
|
|
11
|
-
plugin: SelectionPlugin | null;
|
|
12
|
-
isLoading: boolean;
|
|
13
|
-
ready: Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
type Props = {
|
|
17
|
-
pageIndex: number;
|
|
18
|
-
scale: number;
|
|
19
|
-
background?: string;
|
|
20
|
-
};
|
|
21
|
-
declare function SelectionLayer({ pageIndex, scale, background }: Props): react_jsx_runtime.JSX.Element | null;
|
|
22
|
-
|
|
23
|
-
declare function CopyToClipboard(): null;
|
|
24
|
-
|
|
25
|
-
export { CopyToClipboard, SelectionLayer, useSelectionCapability, useSelectionPlugin };
|