@embedpdf/plugin-annotation 1.1.1 → 1.2.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 +1924 -396
- package/dist/index.js.map +1 -1
- package/dist/lib/actions.d.ts +21 -15
- package/dist/lib/annotation-plugin.d.ts +30 -7
- package/dist/lib/handlers/circle.handler.d.ts +3 -0
- package/dist/lib/handlers/click-detector.d.ts +27 -0
- package/dist/lib/handlers/free-text.handler.d.ts +3 -0
- package/dist/lib/handlers/index.d.ts +8 -0
- package/dist/lib/handlers/ink.handler.d.ts +3 -0
- package/dist/lib/handlers/line.handler.d.ts +3 -0
- package/dist/lib/handlers/polygon.handler.d.ts +3 -0
- package/dist/lib/handlers/polyline.handler.d.ts +3 -0
- package/dist/lib/handlers/square.handler.d.ts +3 -0
- package/dist/lib/handlers/stamp.handler.d.ts +3 -0
- package/dist/lib/handlers/types.d.ts +139 -0
- package/dist/lib/helpers.d.ts +1 -6
- package/dist/lib/index.d.ts +3 -1
- package/dist/lib/patching/index.d.ts +1 -1
- package/dist/lib/patching/patch-registry.d.ts +27 -0
- package/dist/lib/patching/patches/index.d.ts +4 -0
- package/dist/lib/patching/patches/ink.patch.d.ts +3 -0
- package/dist/lib/patching/patches/line.patch.d.ts +3 -0
- package/dist/lib/patching/patches/polygon.patch.d.ts +3 -0
- package/dist/lib/patching/patches/polyline.patch.d.ts +3 -0
- package/dist/lib/selectors.d.ts +8 -12
- package/dist/lib/tools/default-tools.d.ts +436 -0
- package/dist/lib/tools/tools-utils.d.ts +25 -0
- package/dist/lib/tools/types.d.ts +96 -0
- package/dist/lib/types.d.ts +78 -161
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/use-state.d.ts +12 -0
- package/dist/preact/adapter.d.ts +1 -5
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +392 -1796
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +2 -4
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +393 -1795
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/annotation-container.d.ts +18 -16
- package/dist/shared-preact/components/annotation-layer.d.ts +9 -2
- package/dist/shared-preact/components/annotation-paint-layer.d.ts +6 -0
- package/dist/shared-preact/components/annotations/free-text.d.ts +1 -0
- package/dist/shared-preact/components/annotations/polygon.d.ts +4 -1
- package/dist/shared-preact/components/annotations.d.ts +4 -1
- package/dist/shared-preact/components/preview-renderer.d.ts +7 -0
- package/dist/shared-preact/components/text-markup/highlight.d.ts +2 -2
- package/dist/shared-preact/components/text-markup/squiggly.d.ts +2 -2
- package/dist/shared-preact/components/text-markup/strikeout.d.ts +2 -2
- package/dist/shared-preact/components/text-markup/underline.d.ts +2 -2
- package/dist/shared-preact/types.d.ts +32 -2
- package/dist/shared-react/components/annotation-container.d.ts +18 -16
- package/dist/shared-react/components/annotation-layer.d.ts +9 -2
- package/dist/shared-react/components/annotation-paint-layer.d.ts +6 -0
- package/dist/shared-react/components/annotations/free-text.d.ts +1 -0
- package/dist/shared-react/components/annotations/polygon.d.ts +4 -1
- package/dist/shared-react/components/annotations.d.ts +4 -1
- package/dist/shared-react/components/preview-renderer.d.ts +7 -0
- package/dist/shared-react/components/text-markup/highlight.d.ts +2 -2
- package/dist/shared-react/components/text-markup/squiggly.d.ts +2 -2
- package/dist/shared-react/components/text-markup/strikeout.d.ts +2 -2
- package/dist/shared-react/components/text-markup/underline.d.ts +2 -2
- package/dist/shared-react/types.d.ts +32 -2
- package/dist/vue/hooks/index.d.ts +1 -0
- package/dist/vue/hooks/use-annotation.d.ts +3 -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 +10 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +19 -12
- package/dist/lib/patching/derived-rect.d.ts +0 -2
- package/dist/lib/variant-key.d.ts +0 -8
- package/dist/shared-preact/components/annotations/circle-paint.d.ts +0 -10
- package/dist/shared-preact/components/annotations/free-text-paint.d.ts +0 -10
- package/dist/shared-preact/components/annotations/ink-highlight-paint.d.ts +0 -0
- package/dist/shared-preact/components/annotations/ink-paint.d.ts +0 -18
- package/dist/shared-preact/components/annotations/line-paint.d.ts +0 -10
- package/dist/shared-preact/components/annotations/polygon-paint.d.ts +0 -9
- package/dist/shared-preact/components/annotations/polyline-paint.d.ts +0 -10
- package/dist/shared-preact/components/annotations/square-paint.d.ts +0 -10
- package/dist/shared-preact/components/annotations/stamp-paint.d.ts +0 -8
- package/dist/shared-preact/components/resize-handles.d.ts +0 -9
- package/dist/shared-preact/components/vertex-editor.d.ts +0 -19
- package/dist/shared-preact/hooks/use-drag-resize.d.ts +0 -38
- package/dist/shared-preact/patch-ink.d.ts +0 -16
- package/dist/shared-preact/patchers.d.ts +0 -9
- package/dist/shared-preact/vertex-patchers.d.ts +0 -10
- package/dist/shared-react/components/annotations/circle-paint.d.ts +0 -10
- package/dist/shared-react/components/annotations/free-text-paint.d.ts +0 -10
- package/dist/shared-react/components/annotations/ink-highlight-paint.d.ts +0 -0
- package/dist/shared-react/components/annotations/ink-paint.d.ts +0 -17
- package/dist/shared-react/components/annotations/line-paint.d.ts +0 -10
- package/dist/shared-react/components/annotations/polygon-paint.d.ts +0 -9
- package/dist/shared-react/components/annotations/polyline-paint.d.ts +0 -10
- package/dist/shared-react/components/annotations/square-paint.d.ts +0 -10
- package/dist/shared-react/components/annotations/stamp-paint.d.ts +0 -8
- package/dist/shared-react/components/resize-handles.d.ts +0 -9
- package/dist/shared-react/components/vertex-editor.d.ts +0 -19
- package/dist/shared-react/hooks/use-drag-resize.d.ts +0 -38
- package/dist/shared-react/patch-ink.d.ts +0 -16
- package/dist/shared-react/patchers.d.ts +0 -9
- package/dist/shared-react/vertex-patchers.d.ts +0 -10
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BasePlugin, createBehaviorEmitter, SET_DOCUMENT } from "@embedpdf/core";
|
|
2
|
-
import { PdfAnnotationSubtype,
|
|
1
|
+
import { clamp, BasePlugin, createBehaviorEmitter, SET_DOCUMENT } from "@embedpdf/core";
|
|
2
|
+
import { PdfAnnotationSubtype, expandRect, rectFromPoints, uuidV4, PdfVerticalAlignment, PdfTextAlignment, PdfStandardFont, PdfAnnotationLineEnding, rotateAndTranslatePoint, PdfAnnotationBorderStyle, PdfAnnotationIcon, ignore, PdfTaskHelper, PdfErrorCode, Task, PdfBlendMode } from "@embedpdf/models";
|
|
3
3
|
const ANNOTATION_PLUGIN_ID = "annotation";
|
|
4
4
|
const manifest = {
|
|
5
5
|
id: ANNOTATION_PLUGIN_ID,
|
|
@@ -11,20 +11,23 @@ const manifest = {
|
|
|
11
11
|
defaultConfig: {
|
|
12
12
|
enabled: true,
|
|
13
13
|
autoCommit: true,
|
|
14
|
-
annotationAuthor: "Guest"
|
|
14
|
+
annotationAuthor: "Guest",
|
|
15
|
+
deactivateToolAfterCreate: false,
|
|
16
|
+
selectAfterCreate: true
|
|
15
17
|
}
|
|
16
18
|
};
|
|
17
19
|
const SET_ANNOTATIONS = "ANNOTATION/SET_ANNOTATIONS";
|
|
18
20
|
const SELECT_ANNOTATION = "ANNOTATION/SELECT_ANNOTATION";
|
|
19
21
|
const DESELECT_ANNOTATION = "ANNOTATION/DESELECT_ANNOTATION";
|
|
20
|
-
const UPDATE_TOOL_DEFAULTS = "ANNOTATION/UPDATE_TOOL_DEFAULTS";
|
|
21
22
|
const ADD_COLOR_PRESET = "ANNOTATION/ADD_COLOR_PRESET";
|
|
22
23
|
const CREATE_ANNOTATION = "ANNOTATION/CREATE_ANNOTATION";
|
|
23
24
|
const PATCH_ANNOTATION = "ANNOTATION/PATCH_ANNOTATION";
|
|
24
25
|
const DELETE_ANNOTATION = "ANNOTATION/DELETE_ANNOTATION";
|
|
25
26
|
const COMMIT_PENDING_CHANGES = "ANNOTATION/COMMIT";
|
|
26
27
|
const PURGE_ANNOTATION = "ANNOTATION/PURGE_ANNOTATION";
|
|
27
|
-
const
|
|
28
|
+
const SET_ACTIVE_TOOL_ID = "ANNOTATION/SET_ACTIVE_TOOL_ID";
|
|
29
|
+
const SET_TOOL_DEFAULTS = "ANNOTATION/SET_TOOL_DEFAULTS";
|
|
30
|
+
const ADD_TOOL = "ANNOTATION/ADD_TOOL";
|
|
28
31
|
const setAnnotations = (p) => ({
|
|
29
32
|
type: SET_ANNOTATIONS,
|
|
30
33
|
payload: p
|
|
@@ -34,19 +37,12 @@ const selectAnnotation = (pageIndex, id) => ({
|
|
|
34
37
|
payload: { pageIndex, id }
|
|
35
38
|
});
|
|
36
39
|
const deselectAnnotation = () => ({ type: DESELECT_ANNOTATION });
|
|
37
|
-
const updateToolDefaults = (variantKey, patch) => ({ type: UPDATE_TOOL_DEFAULTS, payload: { variantKey, patch } });
|
|
38
40
|
const addColorPreset = (c) => ({
|
|
39
41
|
type: ADD_COLOR_PRESET,
|
|
40
42
|
payload: c
|
|
41
43
|
});
|
|
42
|
-
const createAnnotation = (pageIndex, annotation) => ({
|
|
43
|
-
|
|
44
|
-
payload: { pageIndex, annotation }
|
|
45
|
-
});
|
|
46
|
-
const patchAnnotation = (pageIndex, id, patch) => ({
|
|
47
|
-
type: PATCH_ANNOTATION,
|
|
48
|
-
payload: { pageIndex, id, patch }
|
|
49
|
-
});
|
|
44
|
+
const createAnnotation = (pageIndex, annotation) => ({ type: CREATE_ANNOTATION, payload: { pageIndex, annotation } });
|
|
45
|
+
const patchAnnotation = (pageIndex, id, patch) => ({ type: PATCH_ANNOTATION, payload: { pageIndex, id, patch } });
|
|
50
46
|
const deleteAnnotation = (pageIndex, id) => ({
|
|
51
47
|
type: DELETE_ANNOTATION,
|
|
52
48
|
payload: { pageIndex, id }
|
|
@@ -56,16 +52,15 @@ const purgeAnnotation = (uid) => ({
|
|
|
56
52
|
type: PURGE_ANNOTATION,
|
|
57
53
|
payload: { uid }
|
|
58
54
|
});
|
|
59
|
-
const
|
|
60
|
-
type:
|
|
61
|
-
payload:
|
|
55
|
+
const setActiveToolId = (id) => ({
|
|
56
|
+
type: SET_ACTIVE_TOOL_ID,
|
|
57
|
+
payload: id
|
|
62
58
|
});
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
};
|
|
68
|
-
const variantKeyFromAnnotation = (a) => makeVariantKey(a.type, a.intent);
|
|
59
|
+
const setToolDefaults = (toolId, patch) => ({
|
|
60
|
+
type: SET_TOOL_DEFAULTS,
|
|
61
|
+
payload: { toolId, patch }
|
|
62
|
+
});
|
|
63
|
+
const addTool = (tool) => ({ type: ADD_TOOL, payload: tool });
|
|
69
64
|
function isInk(a) {
|
|
70
65
|
return a.object.type === PdfAnnotationSubtype.INK;
|
|
71
66
|
}
|
|
@@ -111,21 +106,6 @@ function isText(a) {
|
|
|
111
106
|
function isSidebarAnnotation(a) {
|
|
112
107
|
return isTextMarkup(a) || isInk(a) || isSquare(a) || isCircle(a) || isPolygon(a) || isLine(a) || isPolyline(a) || isFreeText(a) || isStamp(a);
|
|
113
108
|
}
|
|
114
|
-
function isHighlightDefaults(defaults) {
|
|
115
|
-
return defaults.subtype === PdfAnnotationSubtype.HIGHLIGHT;
|
|
116
|
-
}
|
|
117
|
-
function isUnderlineDefaults(defaults) {
|
|
118
|
-
return defaults.subtype === PdfAnnotationSubtype.UNDERLINE;
|
|
119
|
-
}
|
|
120
|
-
function isStrikeoutDefaults(defaults) {
|
|
121
|
-
return defaults.subtype === PdfAnnotationSubtype.STRIKEOUT;
|
|
122
|
-
}
|
|
123
|
-
function isSquigglyDefaults(defaults) {
|
|
124
|
-
return defaults.subtype === PdfAnnotationSubtype.SQUIGGLY;
|
|
125
|
-
}
|
|
126
|
-
function isTextMarkupDefaults(defaults) {
|
|
127
|
-
return isHighlightDefaults(defaults) || isUnderlineDefaults(defaults) || isStrikeoutDefaults(defaults) || isSquigglyDefaults(defaults);
|
|
128
|
-
}
|
|
129
109
|
const getAnnotationsByPageIndex = (s, page) => (s.pages[page] ?? []).map((uid) => s.byUid[uid]);
|
|
130
110
|
const getAnnotations = (s) => {
|
|
131
111
|
const out = {};
|
|
@@ -141,26 +121,17 @@ const getSelectedAnnotationByPageIndex = (s, pageIndex) => {
|
|
|
141
121
|
}
|
|
142
122
|
return null;
|
|
143
123
|
};
|
|
144
|
-
const isInAnnotationVariant = (s) => s.activeVariant !== null;
|
|
145
|
-
const getSelectedAnnotationVariant = (s) => s.activeVariant;
|
|
146
124
|
const isAnnotationSelected = (s, id) => s.selectedUid === id;
|
|
147
|
-
function
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
const defaults = state.toolDefaults[variantKey] ?? state.toolDefaults[fallbackKey];
|
|
151
|
-
if (!defaults) {
|
|
152
|
-
throw new Error(
|
|
153
|
-
`No tool defaults found for subtype ${subtype}${intent ? ` and intent ${intent}` : ""}`
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
return defaults;
|
|
125
|
+
function getToolDefaultsById(state, toolId) {
|
|
126
|
+
const tool = state.tools.find((t) => t.id === toolId);
|
|
127
|
+
return tool == null ? void 0 : tool.defaults;
|
|
157
128
|
}
|
|
158
129
|
const getSidebarAnnotationsWithRepliesGroupedByPage = (s) => {
|
|
159
130
|
const repliesByParent = {};
|
|
160
131
|
for (const uidList of Object.values(s.pages)) {
|
|
161
132
|
for (const uid of uidList) {
|
|
162
133
|
const ta = s.byUid[uid];
|
|
163
|
-
if (isText(ta)) {
|
|
134
|
+
if (ta && isText(ta)) {
|
|
164
135
|
const parentId = ta.object.inReplyToId;
|
|
165
136
|
if (parentId) (repliesByParent[parentId] || (repliesByParent[parentId] = [])).push(ta);
|
|
166
137
|
}
|
|
@@ -172,7 +143,7 @@ const getSidebarAnnotationsWithRepliesGroupedByPage = (s) => {
|
|
|
172
143
|
const pageAnnotations = [];
|
|
173
144
|
for (const uid of uidList) {
|
|
174
145
|
const ta = s.byUid[uid];
|
|
175
|
-
if (isSidebarAnnotation(ta)) {
|
|
146
|
+
if (ta && isSidebarAnnotation(ta)) {
|
|
176
147
|
pageAnnotations.push({
|
|
177
148
|
page,
|
|
178
149
|
annotation: ta,
|
|
@@ -195,6 +166,292 @@ const getSidebarAnnotationsWithReplies = (s) => {
|
|
|
195
166
|
}
|
|
196
167
|
return out;
|
|
197
168
|
};
|
|
169
|
+
function useState(initialValue) {
|
|
170
|
+
let value = initialValue;
|
|
171
|
+
const getValue = () => value;
|
|
172
|
+
const setValue = (newValue) => {
|
|
173
|
+
value = newValue;
|
|
174
|
+
};
|
|
175
|
+
return [getValue, setValue];
|
|
176
|
+
}
|
|
177
|
+
const inkHandlerFactory = {
|
|
178
|
+
annotationType: PdfAnnotationSubtype.INK,
|
|
179
|
+
create(context) {
|
|
180
|
+
const { onCommit, onPreview, getTool, pageSize } = context;
|
|
181
|
+
const [getStrokes, setStrokes] = useState([]);
|
|
182
|
+
const [getIsDrawing, setIsDrawing] = useState(false);
|
|
183
|
+
const timerRef = { current: null };
|
|
184
|
+
const clampToPage = (pos) => ({
|
|
185
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
186
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
187
|
+
});
|
|
188
|
+
const getDefaults = () => {
|
|
189
|
+
const tool = getTool();
|
|
190
|
+
if (!tool) return null;
|
|
191
|
+
return {
|
|
192
|
+
...tool.defaults,
|
|
193
|
+
strokeWidth: tool.defaults.strokeWidth ?? 1,
|
|
194
|
+
color: tool.defaults.color ?? "#000000",
|
|
195
|
+
opacity: tool.defaults.opacity ?? 1,
|
|
196
|
+
flags: tool.defaults.flags ?? ["print"]
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
const getPreview = () => {
|
|
200
|
+
const strokes = getStrokes();
|
|
201
|
+
if (strokes.length === 0 || strokes[0].points.length === 0) return null;
|
|
202
|
+
const defaults = getDefaults();
|
|
203
|
+
if (!defaults) return null;
|
|
204
|
+
const allPoints = strokes.flatMap((s) => s.points);
|
|
205
|
+
const bounds = expandRect(rectFromPoints(allPoints), defaults.strokeWidth / 2);
|
|
206
|
+
return {
|
|
207
|
+
type: PdfAnnotationSubtype.INK,
|
|
208
|
+
bounds,
|
|
209
|
+
data: {
|
|
210
|
+
...defaults,
|
|
211
|
+
rect: bounds,
|
|
212
|
+
inkList: strokes
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
return {
|
|
217
|
+
onPointerDown: (pos, evt) => {
|
|
218
|
+
var _a;
|
|
219
|
+
const clampedPos = clampToPage(pos);
|
|
220
|
+
setIsDrawing(true);
|
|
221
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
222
|
+
const newStrokes = [...getStrokes(), { points: [clampedPos] }];
|
|
223
|
+
setStrokes(newStrokes);
|
|
224
|
+
onPreview(getPreview());
|
|
225
|
+
(_a = evt.setPointerCapture) == null ? void 0 : _a.call(evt);
|
|
226
|
+
},
|
|
227
|
+
onPointerMove: (pos) => {
|
|
228
|
+
if (!getIsDrawing()) return;
|
|
229
|
+
const strokes = getStrokes();
|
|
230
|
+
if (strokes.length === 0) return;
|
|
231
|
+
const clampedPos = clampToPage(pos);
|
|
232
|
+
strokes[strokes.length - 1].points.push(clampedPos);
|
|
233
|
+
setStrokes(strokes);
|
|
234
|
+
onPreview(getPreview());
|
|
235
|
+
},
|
|
236
|
+
onPointerUp: (_, evt) => {
|
|
237
|
+
var _a;
|
|
238
|
+
setIsDrawing(false);
|
|
239
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
240
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
241
|
+
timerRef.current = setTimeout(() => {
|
|
242
|
+
const strokes = getStrokes();
|
|
243
|
+
if (strokes.length > 0 && strokes[0].points.length > 1) {
|
|
244
|
+
const defaults = getDefaults();
|
|
245
|
+
if (!defaults) return;
|
|
246
|
+
const allPoints = strokes.flatMap((s) => s.points);
|
|
247
|
+
const rect = expandRect(rectFromPoints(allPoints), defaults.strokeWidth / 2);
|
|
248
|
+
onCommit({
|
|
249
|
+
...defaults,
|
|
250
|
+
inkList: strokes,
|
|
251
|
+
rect,
|
|
252
|
+
type: PdfAnnotationSubtype.INK,
|
|
253
|
+
pageIndex: context.pageIndex,
|
|
254
|
+
id: uuidV4(),
|
|
255
|
+
created: /* @__PURE__ */ new Date()
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
setStrokes([]);
|
|
259
|
+
onPreview(null);
|
|
260
|
+
}, 800);
|
|
261
|
+
},
|
|
262
|
+
onPointerCancel: (_, evt) => {
|
|
263
|
+
var _a;
|
|
264
|
+
setStrokes([]);
|
|
265
|
+
setIsDrawing(false);
|
|
266
|
+
onPreview(null);
|
|
267
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
268
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
function useClickDetector({
|
|
274
|
+
threshold = 5,
|
|
275
|
+
getTool,
|
|
276
|
+
onClickDetected
|
|
277
|
+
}) {
|
|
278
|
+
const [getStartPos, setStartPos] = useState(null);
|
|
279
|
+
const [getHasMoved, setHasMoved] = useState(false);
|
|
280
|
+
return {
|
|
281
|
+
onStart: (pos) => {
|
|
282
|
+
setStartPos(pos);
|
|
283
|
+
setHasMoved(false);
|
|
284
|
+
},
|
|
285
|
+
onMove: (pos) => {
|
|
286
|
+
const start = getStartPos();
|
|
287
|
+
if (!start || getHasMoved()) return;
|
|
288
|
+
const distance = Math.sqrt(Math.pow(pos.x - start.x, 2) + Math.pow(pos.y - start.y, 2));
|
|
289
|
+
if (distance > threshold) {
|
|
290
|
+
setHasMoved(true);
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
onEnd: (pos) => {
|
|
294
|
+
var _a;
|
|
295
|
+
const start = getStartPos();
|
|
296
|
+
if (start && !getHasMoved()) {
|
|
297
|
+
const tool = getTool();
|
|
298
|
+
if (tool && "clickBehavior" in tool && ((_a = tool.clickBehavior) == null ? void 0 : _a.enabled)) {
|
|
299
|
+
onClickDetected(pos, tool);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
setStartPos(null);
|
|
303
|
+
setHasMoved(false);
|
|
304
|
+
},
|
|
305
|
+
hasMoved: getHasMoved,
|
|
306
|
+
reset: () => {
|
|
307
|
+
setStartPos(null);
|
|
308
|
+
setHasMoved(false);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
const freeTextHandlerFactory = {
|
|
313
|
+
annotationType: PdfAnnotationSubtype.FREETEXT,
|
|
314
|
+
create(context) {
|
|
315
|
+
const { onCommit, onPreview, getTool, pageSize, pageIndex } = context;
|
|
316
|
+
const [getStart, setStart] = useState(null);
|
|
317
|
+
const clampToPage = (pos) => ({
|
|
318
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
319
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
320
|
+
});
|
|
321
|
+
const getDefaults = () => {
|
|
322
|
+
const tool = getTool();
|
|
323
|
+
if (!tool) return null;
|
|
324
|
+
return {
|
|
325
|
+
...tool.defaults,
|
|
326
|
+
fontColor: tool.defaults.fontColor ?? "#000000",
|
|
327
|
+
opacity: tool.defaults.opacity ?? 1,
|
|
328
|
+
fontSize: tool.defaults.fontSize ?? 12,
|
|
329
|
+
fontFamily: tool.defaults.fontFamily ?? PdfStandardFont.Helvetica,
|
|
330
|
+
backgroundColor: tool.defaults.backgroundColor ?? "transparent",
|
|
331
|
+
textAlign: tool.defaults.textAlign ?? PdfTextAlignment.Left,
|
|
332
|
+
verticalAlign: tool.defaults.verticalAlign ?? PdfVerticalAlignment.Top,
|
|
333
|
+
contents: tool.defaults.contents ?? "Insert text here",
|
|
334
|
+
flags: tool.defaults.flags ?? ["print"]
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
const clickDetector = useClickDetector({
|
|
338
|
+
threshold: 5,
|
|
339
|
+
getTool,
|
|
340
|
+
onClickDetected: (pos, tool) => {
|
|
341
|
+
const defaults = getDefaults();
|
|
342
|
+
if (!defaults) return;
|
|
343
|
+
const clickConfig = tool.clickBehavior;
|
|
344
|
+
if (!(clickConfig == null ? void 0 : clickConfig.enabled)) return;
|
|
345
|
+
const { width, height } = clickConfig.defaultSize;
|
|
346
|
+
const halfWidth = width / 2;
|
|
347
|
+
const halfHeight = height / 2;
|
|
348
|
+
const x = clamp(pos.x - halfWidth, 0, pageSize.width - width);
|
|
349
|
+
const y = clamp(pos.y - halfHeight, 0, pageSize.height - height);
|
|
350
|
+
const rect = {
|
|
351
|
+
origin: { x, y },
|
|
352
|
+
size: { width, height }
|
|
353
|
+
};
|
|
354
|
+
const contents = clickConfig.defaultContent ?? defaults.contents;
|
|
355
|
+
const anno = {
|
|
356
|
+
...defaults,
|
|
357
|
+
contents,
|
|
358
|
+
type: PdfAnnotationSubtype.FREETEXT,
|
|
359
|
+
rect,
|
|
360
|
+
pageIndex,
|
|
361
|
+
id: uuidV4(),
|
|
362
|
+
created: /* @__PURE__ */ new Date()
|
|
363
|
+
};
|
|
364
|
+
onCommit(anno);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
const getPreview = (current) => {
|
|
368
|
+
const start = getStart();
|
|
369
|
+
if (!start) return null;
|
|
370
|
+
const defaults = getDefaults();
|
|
371
|
+
if (!defaults) return null;
|
|
372
|
+
const minX = Math.min(start.x, current.x);
|
|
373
|
+
const minY = Math.min(start.y, current.y);
|
|
374
|
+
const width = Math.abs(start.x - current.x);
|
|
375
|
+
const height = Math.abs(start.y - current.y);
|
|
376
|
+
const rect = {
|
|
377
|
+
origin: { x: minX, y: minY },
|
|
378
|
+
size: { width, height }
|
|
379
|
+
};
|
|
380
|
+
return {
|
|
381
|
+
type: PdfAnnotationSubtype.FREETEXT,
|
|
382
|
+
bounds: rect,
|
|
383
|
+
data: {
|
|
384
|
+
...defaults,
|
|
385
|
+
rect
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
return {
|
|
390
|
+
onPointerDown: (pos, evt) => {
|
|
391
|
+
var _a;
|
|
392
|
+
const clampedPos = clampToPage(pos);
|
|
393
|
+
setStart(clampedPos);
|
|
394
|
+
clickDetector.onStart(clampedPos);
|
|
395
|
+
onPreview(getPreview(clampedPos));
|
|
396
|
+
(_a = evt.setPointerCapture) == null ? void 0 : _a.call(evt);
|
|
397
|
+
},
|
|
398
|
+
onPointerMove: (pos) => {
|
|
399
|
+
const clampedPos = clampToPage(pos);
|
|
400
|
+
clickDetector.onMove(clampedPos);
|
|
401
|
+
if (getStart() && clickDetector.hasMoved()) {
|
|
402
|
+
onPreview(getPreview(clampedPos));
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
onPointerUp: (pos, evt) => {
|
|
406
|
+
var _a;
|
|
407
|
+
const start = getStart();
|
|
408
|
+
if (!start) return;
|
|
409
|
+
const defaults = getDefaults();
|
|
410
|
+
if (!defaults) return;
|
|
411
|
+
const clampedPos = clampToPage(pos);
|
|
412
|
+
if (!clickDetector.hasMoved()) {
|
|
413
|
+
clickDetector.onEnd(clampedPos);
|
|
414
|
+
} else {
|
|
415
|
+
const minX = Math.min(start.x, clampedPos.x);
|
|
416
|
+
const minY = Math.min(start.y, clampedPos.y);
|
|
417
|
+
const width = Math.abs(start.x - clampedPos.x);
|
|
418
|
+
const height = Math.abs(start.y - clampedPos.y);
|
|
419
|
+
const rect = {
|
|
420
|
+
origin: { x: minX, y: minY },
|
|
421
|
+
size: { width, height }
|
|
422
|
+
};
|
|
423
|
+
const anno = {
|
|
424
|
+
...defaults,
|
|
425
|
+
type: PdfAnnotationSubtype.FREETEXT,
|
|
426
|
+
rect,
|
|
427
|
+
pageIndex: context.pageIndex,
|
|
428
|
+
id: uuidV4(),
|
|
429
|
+
created: /* @__PURE__ */ new Date()
|
|
430
|
+
};
|
|
431
|
+
onCommit(anno);
|
|
432
|
+
}
|
|
433
|
+
setStart(null);
|
|
434
|
+
onPreview(null);
|
|
435
|
+
clickDetector.reset();
|
|
436
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
437
|
+
},
|
|
438
|
+
onPointerLeave: (_, evt) => {
|
|
439
|
+
var _a;
|
|
440
|
+
setStart(null);
|
|
441
|
+
onPreview(null);
|
|
442
|
+
clickDetector.reset();
|
|
443
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
444
|
+
},
|
|
445
|
+
onPointerCancel: (_, evt) => {
|
|
446
|
+
var _a;
|
|
447
|
+
setStart(null);
|
|
448
|
+
onPreview(null);
|
|
449
|
+
clickDetector.reset();
|
|
450
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
};
|
|
198
455
|
function createArrowHandler(isClosed) {
|
|
199
456
|
const calculateGeometry = (sw) => {
|
|
200
457
|
const len = sw * 9;
|
|
@@ -344,38 +601,6 @@ function lineRectWithEndings(vertices, strokeWidth, endings) {
|
|
|
344
601
|
const pad = strokeWidth / 2 + EXTRA_PADDING * strokeWidth;
|
|
345
602
|
return expandRect(baseRect, pad);
|
|
346
603
|
}
|
|
347
|
-
const vertsRect = (verts, sw) => expandRect(rectFromPoints(verts), sw / 2);
|
|
348
|
-
function deriveRect(a) {
|
|
349
|
-
switch (a.type) {
|
|
350
|
-
/* mark‑ups already carry their real rect */
|
|
351
|
-
case PdfAnnotationSubtype.HIGHLIGHT:
|
|
352
|
-
case PdfAnnotationSubtype.UNDERLINE:
|
|
353
|
-
case PdfAnnotationSubtype.STRIKEOUT:
|
|
354
|
-
case PdfAnnotationSubtype.SQUIGGLY:
|
|
355
|
-
case PdfAnnotationSubtype.SQUARE:
|
|
356
|
-
case PdfAnnotationSubtype.CIRCLE:
|
|
357
|
-
return a.rect;
|
|
358
|
-
/* ink */
|
|
359
|
-
case PdfAnnotationSubtype.INK: {
|
|
360
|
-
const pts = a.inkList.flatMap((s) => s.points);
|
|
361
|
-
return vertsRect(pts, a.strokeWidth);
|
|
362
|
-
}
|
|
363
|
-
/* one‑segment */
|
|
364
|
-
case PdfAnnotationSubtype.LINE:
|
|
365
|
-
return lineRectWithEndings(
|
|
366
|
-
[a.linePoints.start, a.linePoints.end],
|
|
367
|
-
a.strokeWidth,
|
|
368
|
-
a.lineEndings
|
|
369
|
-
);
|
|
370
|
-
/* multi‑segment */
|
|
371
|
-
case PdfAnnotationSubtype.POLYLINE:
|
|
372
|
-
return lineRectWithEndings(a.vertices, a.strokeWidth, a.lineEndings);
|
|
373
|
-
case PdfAnnotationSubtype.POLYGON:
|
|
374
|
-
return vertsRect(a.vertices, a.strokeWidth);
|
|
375
|
-
default:
|
|
376
|
-
return a.rect;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
604
|
function createEnding(ending, strokeWidth, rad, px, py) {
|
|
380
605
|
if (!ending) return null;
|
|
381
606
|
const handler = LINE_ENDING_HANDLERS[ending];
|
|
@@ -388,187 +613,1249 @@ function createEnding(ending, strokeWidth, rad, px, py) {
|
|
|
388
613
|
filled: handler.filled
|
|
389
614
|
};
|
|
390
615
|
}
|
|
616
|
+
class PatchRegistry {
|
|
617
|
+
constructor() {
|
|
618
|
+
this.patches = /* @__PURE__ */ new Map();
|
|
619
|
+
}
|
|
620
|
+
register(type, patchFn) {
|
|
621
|
+
this.patches.set(type, patchFn);
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Transform an annotation based on the context.
|
|
625
|
+
* Returns the transformed properties or just the changes if no patch function exists.
|
|
626
|
+
*/
|
|
627
|
+
transform(annotation, context) {
|
|
628
|
+
const patchFn = this.patches.get(annotation.type);
|
|
629
|
+
if (patchFn) {
|
|
630
|
+
return patchFn(annotation, context);
|
|
631
|
+
}
|
|
632
|
+
return context.changes;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
const patchRegistry = new PatchRegistry();
|
|
391
636
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
392
637
|
__proto__: null,
|
|
393
638
|
LINE_ENDING_HANDLERS,
|
|
639
|
+
PatchRegistry,
|
|
394
640
|
createEnding,
|
|
395
|
-
|
|
396
|
-
|
|
641
|
+
lineRectWithEndings,
|
|
642
|
+
patchRegistry
|
|
397
643
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
644
|
+
const lineHandlerFactory = {
|
|
645
|
+
annotationType: PdfAnnotationSubtype.LINE,
|
|
646
|
+
create(context) {
|
|
647
|
+
const { pageIndex, onCommit, onPreview, getTool, pageSize } = context;
|
|
648
|
+
const [getStart, setStart] = useState(null);
|
|
649
|
+
const clampToPage = (pos) => ({
|
|
650
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
651
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
652
|
+
});
|
|
653
|
+
const getDefaults = () => {
|
|
654
|
+
const tool = getTool();
|
|
655
|
+
if (!tool) return null;
|
|
656
|
+
return {
|
|
657
|
+
...tool.defaults,
|
|
658
|
+
strokeWidth: tool.defaults.strokeWidth ?? 1,
|
|
659
|
+
lineEndings: tool.defaults.lineEndings ?? {
|
|
660
|
+
start: PdfAnnotationLineEnding.None,
|
|
661
|
+
end: PdfAnnotationLineEnding.None
|
|
662
|
+
},
|
|
663
|
+
color: tool.defaults.color ?? "#000000",
|
|
664
|
+
opacity: tool.defaults.opacity ?? 1,
|
|
665
|
+
strokeStyle: tool.defaults.strokeStyle ?? PdfAnnotationBorderStyle.SOLID,
|
|
666
|
+
strokeDashArray: tool.defaults.strokeDashArray ?? [],
|
|
667
|
+
strokeColor: tool.defaults.strokeColor ?? "#000000",
|
|
668
|
+
flags: tool.defaults.flags ?? ["print"]
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
const clickDetector = useClickDetector({
|
|
672
|
+
threshold: 5,
|
|
673
|
+
getTool,
|
|
674
|
+
onClickDetected: (pos, tool) => {
|
|
675
|
+
const defaults = getDefaults();
|
|
676
|
+
if (!defaults) return;
|
|
677
|
+
const clickConfig = tool.clickBehavior;
|
|
678
|
+
if (!(clickConfig == null ? void 0 : clickConfig.enabled)) return;
|
|
679
|
+
const angle = clickConfig.defaultAngle ?? 0;
|
|
680
|
+
const length = clickConfig.defaultLength;
|
|
681
|
+
const halfLength = length / 2;
|
|
682
|
+
const startX = pos.x - halfLength * Math.cos(angle);
|
|
683
|
+
const startY = pos.y - halfLength * Math.sin(angle);
|
|
684
|
+
const endX = pos.x + halfLength * Math.cos(angle);
|
|
685
|
+
const endY = pos.y + halfLength * Math.sin(angle);
|
|
686
|
+
const start = clampToPage({ x: startX, y: startY });
|
|
687
|
+
const end = clampToPage({ x: endX, y: endY });
|
|
688
|
+
const rect = lineRectWithEndings(
|
|
689
|
+
[start, end],
|
|
690
|
+
defaults.strokeWidth,
|
|
691
|
+
defaults.lineEndings
|
|
692
|
+
);
|
|
693
|
+
onCommit({
|
|
694
|
+
...defaults,
|
|
695
|
+
rect,
|
|
696
|
+
linePoints: { start, end },
|
|
697
|
+
pageIndex,
|
|
698
|
+
id: uuidV4(),
|
|
699
|
+
created: /* @__PURE__ */ new Date(),
|
|
700
|
+
type: PdfAnnotationSubtype.LINE
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
const getPreview = (current) => {
|
|
705
|
+
const start = getStart();
|
|
706
|
+
if (!start) return null;
|
|
707
|
+
const defaults = getDefaults();
|
|
708
|
+
if (!defaults) return null;
|
|
709
|
+
const bounds = lineRectWithEndings(
|
|
710
|
+
[start, current],
|
|
711
|
+
defaults.strokeWidth,
|
|
712
|
+
defaults.lineEndings
|
|
713
|
+
);
|
|
714
|
+
return {
|
|
715
|
+
type: PdfAnnotationSubtype.LINE,
|
|
716
|
+
bounds,
|
|
717
|
+
data: {
|
|
718
|
+
...defaults,
|
|
719
|
+
rect: bounds,
|
|
720
|
+
linePoints: { start, end: current }
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
};
|
|
724
|
+
return {
|
|
725
|
+
onPointerDown: (pos, evt) => {
|
|
726
|
+
var _a;
|
|
727
|
+
const clampedPos = clampToPage(pos);
|
|
728
|
+
setStart(clampedPos);
|
|
729
|
+
clickDetector.onStart(clampedPos);
|
|
730
|
+
onPreview(getPreview(clampedPos));
|
|
731
|
+
(_a = evt.setPointerCapture) == null ? void 0 : _a.call(evt);
|
|
732
|
+
},
|
|
733
|
+
onPointerMove: (pos) => {
|
|
734
|
+
const clampedPos = clampToPage(pos);
|
|
735
|
+
clickDetector.onMove(clampedPos);
|
|
736
|
+
if (getStart() && clickDetector.hasMoved()) {
|
|
737
|
+
onPreview(getPreview(clampedPos));
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
onPointerUp: (pos, evt) => {
|
|
741
|
+
var _a;
|
|
742
|
+
const start = getStart();
|
|
743
|
+
if (!start) return;
|
|
744
|
+
const clampedPos = clampToPage(pos);
|
|
745
|
+
if (!clickDetector.hasMoved()) {
|
|
746
|
+
clickDetector.onEnd(clampedPos);
|
|
747
|
+
} else {
|
|
748
|
+
const defaults = getDefaults();
|
|
749
|
+
if (!defaults) return;
|
|
750
|
+
if (Math.abs(clampedPos.x - start.x) > 2 || Math.abs(clampedPos.y - start.y) > 2) {
|
|
751
|
+
const rect = lineRectWithEndings(
|
|
752
|
+
[start, clampedPos],
|
|
753
|
+
defaults.strokeWidth,
|
|
754
|
+
defaults.lineEndings
|
|
755
|
+
);
|
|
756
|
+
onCommit({
|
|
757
|
+
...defaults,
|
|
758
|
+
rect,
|
|
759
|
+
linePoints: { start, end: clampedPos },
|
|
760
|
+
pageIndex,
|
|
761
|
+
id: uuidV4(),
|
|
762
|
+
flags: ["print"],
|
|
763
|
+
created: /* @__PURE__ */ new Date(),
|
|
764
|
+
type: PdfAnnotationSubtype.LINE
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
setStart(null);
|
|
769
|
+
onPreview(null);
|
|
770
|
+
clickDetector.reset();
|
|
771
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
772
|
+
},
|
|
773
|
+
onPointerLeave: (_, evt) => {
|
|
774
|
+
var _a;
|
|
775
|
+
setStart(null);
|
|
776
|
+
onPreview(null);
|
|
777
|
+
clickDetector.reset();
|
|
778
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
779
|
+
},
|
|
780
|
+
onPointerCancel: (_, evt) => {
|
|
781
|
+
var _a;
|
|
782
|
+
setStart(null);
|
|
783
|
+
onPreview(null);
|
|
784
|
+
clickDetector.reset();
|
|
785
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
const polylineHandlerFactory = {
|
|
791
|
+
annotationType: PdfAnnotationSubtype.POLYLINE,
|
|
792
|
+
create(context) {
|
|
793
|
+
const { onCommit, onPreview, getTool, pageSize } = context;
|
|
794
|
+
const [getVertices, setVertices] = useState([]);
|
|
795
|
+
const [getCurrent, setCurrent] = useState(null);
|
|
796
|
+
const clampToPage = (pos) => ({
|
|
797
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
798
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
799
|
+
});
|
|
800
|
+
const getDefaults = () => {
|
|
801
|
+
const tool = getTool();
|
|
802
|
+
if (!tool) return null;
|
|
803
|
+
return {
|
|
804
|
+
...tool.defaults,
|
|
805
|
+
strokeWidth: tool.defaults.strokeWidth ?? 1,
|
|
806
|
+
lineEndings: tool.defaults.lineEndings ?? {
|
|
807
|
+
start: PdfAnnotationLineEnding.None,
|
|
808
|
+
end: PdfAnnotationLineEnding.None
|
|
809
|
+
},
|
|
810
|
+
color: tool.defaults.color ?? "#000000",
|
|
811
|
+
opacity: tool.defaults.opacity ?? 1,
|
|
812
|
+
strokeColor: tool.defaults.strokeColor ?? "#000000",
|
|
813
|
+
strokeStyle: tool.defaults.strokeStyle ?? PdfAnnotationBorderStyle.SOLID,
|
|
814
|
+
strokeDashArray: tool.defaults.strokeDashArray ?? [],
|
|
815
|
+
flags: tool.defaults.flags ?? ["print"]
|
|
816
|
+
};
|
|
817
|
+
};
|
|
818
|
+
const commitPolyline = () => {
|
|
819
|
+
const vertices = getVertices();
|
|
820
|
+
if (vertices.length < 2) return;
|
|
821
|
+
const defaults = getDefaults();
|
|
822
|
+
if (!defaults) return;
|
|
823
|
+
const rect = lineRectWithEndings(
|
|
824
|
+
vertices,
|
|
825
|
+
defaults.strokeWidth,
|
|
826
|
+
defaults.lineEndings
|
|
827
|
+
);
|
|
828
|
+
const anno = {
|
|
829
|
+
...defaults,
|
|
830
|
+
vertices,
|
|
831
|
+
rect,
|
|
832
|
+
type: PdfAnnotationSubtype.POLYLINE,
|
|
833
|
+
pageIndex: context.pageIndex,
|
|
834
|
+
id: uuidV4(),
|
|
835
|
+
created: /* @__PURE__ */ new Date()
|
|
836
|
+
};
|
|
837
|
+
onCommit(anno);
|
|
838
|
+
setVertices([]);
|
|
839
|
+
setCurrent(null);
|
|
840
|
+
onPreview(null);
|
|
841
|
+
};
|
|
842
|
+
const getPreview = () => {
|
|
843
|
+
const vertices = getVertices();
|
|
844
|
+
const currentPos = getCurrent();
|
|
845
|
+
if (vertices.length === 0 || !currentPos) return null;
|
|
846
|
+
const defaults = getDefaults();
|
|
847
|
+
if (!defaults) return null;
|
|
848
|
+
const allPoints = [...vertices, currentPos];
|
|
849
|
+
const bounds = lineRectWithEndings(
|
|
850
|
+
allPoints,
|
|
851
|
+
defaults.strokeWidth,
|
|
852
|
+
defaults.lineEndings
|
|
853
|
+
);
|
|
854
|
+
return {
|
|
855
|
+
type: PdfAnnotationSubtype.POLYLINE,
|
|
856
|
+
bounds,
|
|
857
|
+
data: {
|
|
858
|
+
...defaults,
|
|
859
|
+
rect: bounds,
|
|
860
|
+
vertices: allPoints,
|
|
861
|
+
currentVertex: currentPos
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
};
|
|
865
|
+
return {
|
|
866
|
+
onClick: (pos) => {
|
|
867
|
+
const clampedPos = clampToPage(pos);
|
|
868
|
+
const vertices = getVertices();
|
|
869
|
+
const lastVertex = vertices[vertices.length - 1];
|
|
870
|
+
if (lastVertex && Math.abs(lastVertex.x - clampedPos.x) < 1 && Math.abs(lastVertex.y - clampedPos.y) < 1) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
setVertices([...vertices, clampedPos]);
|
|
874
|
+
setCurrent(clampedPos);
|
|
875
|
+
onPreview(getPreview());
|
|
876
|
+
},
|
|
877
|
+
onDoubleClick: () => {
|
|
878
|
+
commitPolyline();
|
|
879
|
+
},
|
|
880
|
+
onPointerMove: (pos) => {
|
|
881
|
+
if (getVertices().length > 0) {
|
|
882
|
+
const clampedPos = clampToPage(pos);
|
|
883
|
+
setCurrent(clampedPos);
|
|
884
|
+
onPreview(getPreview());
|
|
885
|
+
}
|
|
886
|
+
},
|
|
887
|
+
onPointerCancel: () => {
|
|
888
|
+
setVertices([]);
|
|
889
|
+
setCurrent(null);
|
|
890
|
+
onPreview(null);
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
const HANDLE_SIZE_PX = 14;
|
|
896
|
+
const polygonHandlerFactory = {
|
|
897
|
+
annotationType: PdfAnnotationSubtype.POLYGON,
|
|
898
|
+
create(context) {
|
|
899
|
+
const { onCommit, onPreview, getTool, scale, pageSize } = context;
|
|
900
|
+
const [getVertices, setVertices] = useState([]);
|
|
901
|
+
const [getCurrent, setCurrent] = useState(null);
|
|
902
|
+
const clampToPage = (pos) => ({
|
|
903
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
904
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
905
|
+
});
|
|
906
|
+
const isInsideStartHandle = (pos) => {
|
|
907
|
+
const vertices = getVertices();
|
|
908
|
+
if (vertices.length < 2) return false;
|
|
909
|
+
const sizePDF = HANDLE_SIZE_PX / scale;
|
|
910
|
+
const half = sizePDF / 2;
|
|
911
|
+
const v0 = vertices[0];
|
|
912
|
+
return pos.x >= v0.x - half && pos.x <= v0.x + half && pos.y >= v0.y - half && pos.y <= v0.y + half;
|
|
913
|
+
};
|
|
914
|
+
const getDefaults = () => {
|
|
915
|
+
const tool = getTool();
|
|
916
|
+
if (!tool) return null;
|
|
917
|
+
return {
|
|
918
|
+
...tool.defaults,
|
|
919
|
+
color: tool.defaults.color ?? "#000000",
|
|
920
|
+
opacity: tool.defaults.opacity ?? 1,
|
|
921
|
+
strokeWidth: tool.defaults.strokeWidth ?? 1,
|
|
922
|
+
strokeColor: tool.defaults.strokeColor ?? "#000000",
|
|
923
|
+
strokeStyle: tool.defaults.strokeStyle ?? PdfAnnotationBorderStyle.SOLID,
|
|
924
|
+
strokeDashArray: tool.defaults.strokeDashArray ?? [],
|
|
925
|
+
flags: tool.defaults.flags ?? ["print"]
|
|
926
|
+
};
|
|
927
|
+
};
|
|
928
|
+
const commitPolygon = () => {
|
|
929
|
+
const vertices = getVertices();
|
|
930
|
+
if (vertices.length < 3) return;
|
|
931
|
+
const defaults = getDefaults();
|
|
932
|
+
if (!defaults) return;
|
|
933
|
+
const rect = expandRect(rectFromPoints(vertices), defaults.strokeWidth / 2);
|
|
934
|
+
const anno = {
|
|
935
|
+
...defaults,
|
|
936
|
+
vertices,
|
|
937
|
+
rect,
|
|
938
|
+
type: PdfAnnotationSubtype.POLYGON,
|
|
939
|
+
pageIndex: context.pageIndex,
|
|
940
|
+
id: uuidV4(),
|
|
941
|
+
created: /* @__PURE__ */ new Date()
|
|
942
|
+
};
|
|
943
|
+
onCommit(anno);
|
|
944
|
+
setVertices([]);
|
|
945
|
+
setCurrent(null);
|
|
946
|
+
onPreview(null);
|
|
947
|
+
};
|
|
948
|
+
const getPreview = () => {
|
|
949
|
+
const vertices = getVertices();
|
|
950
|
+
const currentPos = getCurrent();
|
|
951
|
+
if (vertices.length === 0 || !currentPos) return null;
|
|
952
|
+
const defaults = getDefaults();
|
|
953
|
+
if (!defaults) return null;
|
|
954
|
+
const allPoints = [...vertices, currentPos];
|
|
955
|
+
const bounds = expandRect(rectFromPoints(allPoints), defaults.strokeWidth / 2);
|
|
956
|
+
return {
|
|
957
|
+
type: PdfAnnotationSubtype.POLYGON,
|
|
958
|
+
bounds,
|
|
959
|
+
data: {
|
|
960
|
+
...defaults,
|
|
961
|
+
rect: bounds,
|
|
962
|
+
vertices,
|
|
963
|
+
currentVertex: currentPos
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
};
|
|
967
|
+
return {
|
|
968
|
+
onClick: (pos) => {
|
|
969
|
+
const clampedPos = clampToPage(pos);
|
|
970
|
+
if (isInsideStartHandle(clampedPos) && getVertices().length >= 3) {
|
|
971
|
+
commitPolygon();
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const vertices = getVertices();
|
|
975
|
+
const lastVertex = vertices[vertices.length - 1];
|
|
976
|
+
if (lastVertex && Math.abs(lastVertex.x - clampedPos.x) < 1 && Math.abs(lastVertex.y - clampedPos.y) < 1) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
setVertices([...vertices, clampedPos]);
|
|
980
|
+
setCurrent(clampedPos);
|
|
981
|
+
onPreview(getPreview());
|
|
982
|
+
},
|
|
983
|
+
onDoubleClick: (_) => {
|
|
984
|
+
commitPolygon();
|
|
985
|
+
},
|
|
986
|
+
onPointerMove: (pos) => {
|
|
987
|
+
if (getVertices().length > 0) {
|
|
988
|
+
const clampedPos = clampToPage(pos);
|
|
989
|
+
setCurrent(clampedPos);
|
|
990
|
+
onPreview(getPreview());
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
onPointerCancel: (_) => {
|
|
994
|
+
setVertices([]);
|
|
995
|
+
setCurrent(null);
|
|
996
|
+
onPreview(null);
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
const squareHandlerFactory = {
|
|
1002
|
+
annotationType: PdfAnnotationSubtype.SQUARE,
|
|
1003
|
+
create(context) {
|
|
1004
|
+
const { pageIndex, onCommit, onPreview, getTool, pageSize } = context;
|
|
1005
|
+
const [getStart, setStart] = useState(null);
|
|
1006
|
+
const clampToPage = (pos) => ({
|
|
1007
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
1008
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
1009
|
+
});
|
|
1010
|
+
const getDefaults = () => {
|
|
1011
|
+
const tool = getTool();
|
|
1012
|
+
if (!tool) return null;
|
|
1013
|
+
return {
|
|
1014
|
+
...tool.defaults,
|
|
1015
|
+
flags: tool.defaults.flags ?? ["print"],
|
|
1016
|
+
strokeWidth: tool.defaults.strokeWidth ?? 2,
|
|
1017
|
+
strokeColor: tool.defaults.strokeColor ?? "#000000",
|
|
1018
|
+
strokeStyle: tool.defaults.strokeStyle ?? PdfAnnotationBorderStyle.SOLID,
|
|
1019
|
+
strokeDashArray: tool.defaults.strokeDashArray ?? [],
|
|
1020
|
+
color: tool.defaults.color ?? "#000000",
|
|
1021
|
+
opacity: tool.defaults.opacity ?? 1
|
|
1022
|
+
};
|
|
1023
|
+
};
|
|
1024
|
+
const clickDetector = useClickDetector({
|
|
1025
|
+
threshold: 5,
|
|
1026
|
+
getTool,
|
|
1027
|
+
onClickDetected: (pos, tool) => {
|
|
1028
|
+
const defaults = getDefaults();
|
|
1029
|
+
if (!defaults) return;
|
|
1030
|
+
const clickConfig = tool.clickBehavior;
|
|
1031
|
+
if (!(clickConfig == null ? void 0 : clickConfig.enabled)) return;
|
|
1032
|
+
const { width, height } = clickConfig.defaultSize;
|
|
1033
|
+
const halfWidth = width / 2;
|
|
1034
|
+
const halfHeight = height / 2;
|
|
1035
|
+
const x = clamp(pos.x - halfWidth, 0, pageSize.width - width);
|
|
1036
|
+
const y = clamp(pos.y - halfHeight, 0, pageSize.height - height);
|
|
1037
|
+
const strokeWidth = defaults.strokeWidth;
|
|
1038
|
+
const halfStroke = strokeWidth / 2;
|
|
1039
|
+
const rect = {
|
|
1040
|
+
origin: { x: x - halfStroke, y: y - halfStroke },
|
|
1041
|
+
size: { width: width + strokeWidth, height: height + strokeWidth }
|
|
1042
|
+
};
|
|
1043
|
+
const anno = {
|
|
1044
|
+
...defaults,
|
|
1045
|
+
type: PdfAnnotationSubtype.SQUARE,
|
|
1046
|
+
created: /* @__PURE__ */ new Date(),
|
|
1047
|
+
id: uuidV4(),
|
|
1048
|
+
pageIndex,
|
|
1049
|
+
rect
|
|
1050
|
+
};
|
|
1051
|
+
onCommit(anno);
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
const getPreview = (current) => {
|
|
1055
|
+
const p1 = getStart();
|
|
1056
|
+
if (!p1) return null;
|
|
1057
|
+
const minX = Math.min(p1.x, current.x);
|
|
1058
|
+
const minY = Math.min(p1.y, current.y);
|
|
1059
|
+
const width = Math.abs(p1.x - current.x);
|
|
1060
|
+
const height = Math.abs(p1.y - current.y);
|
|
1061
|
+
const defaults = getDefaults();
|
|
1062
|
+
if (!defaults) return null;
|
|
1063
|
+
const strokeWidth = defaults.strokeWidth;
|
|
1064
|
+
const halfStroke = strokeWidth / 2;
|
|
1065
|
+
const rect = {
|
|
1066
|
+
origin: { x: minX - halfStroke, y: minY - halfStroke },
|
|
1067
|
+
size: { width: width + strokeWidth, height: height + strokeWidth }
|
|
1068
|
+
};
|
|
1069
|
+
return {
|
|
1070
|
+
type: PdfAnnotationSubtype.SQUARE,
|
|
1071
|
+
bounds: rect,
|
|
1072
|
+
data: {
|
|
1073
|
+
rect,
|
|
1074
|
+
...defaults
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
};
|
|
1078
|
+
return {
|
|
1079
|
+
onPointerDown: (pos, evt) => {
|
|
1080
|
+
var _a;
|
|
1081
|
+
const clampedPos = clampToPage(pos);
|
|
1082
|
+
setStart(clampedPos);
|
|
1083
|
+
clickDetector.onStart(clampedPos);
|
|
1084
|
+
onPreview(getPreview(clampedPos));
|
|
1085
|
+
(_a = evt.setPointerCapture) == null ? void 0 : _a.call(evt);
|
|
1086
|
+
},
|
|
1087
|
+
onPointerMove: (pos) => {
|
|
1088
|
+
const clampedPos = clampToPage(pos);
|
|
1089
|
+
clickDetector.onMove(clampedPos);
|
|
1090
|
+
if (getStart() && clickDetector.hasMoved()) {
|
|
1091
|
+
onPreview(getPreview(clampedPos));
|
|
1092
|
+
}
|
|
1093
|
+
},
|
|
1094
|
+
onPointerUp: (pos, evt) => {
|
|
1095
|
+
var _a;
|
|
1096
|
+
const p1 = getStart();
|
|
1097
|
+
if (!p1) return;
|
|
1098
|
+
const defaults = getDefaults();
|
|
1099
|
+
if (!defaults) return;
|
|
1100
|
+
const clampedPos = clampToPage(pos);
|
|
1101
|
+
if (!clickDetector.hasMoved()) {
|
|
1102
|
+
clickDetector.onEnd(clampedPos);
|
|
1103
|
+
} else {
|
|
1104
|
+
const defaults2 = getDefaults();
|
|
1105
|
+
if (!defaults2) return;
|
|
1106
|
+
const preview = getPreview(clampedPos);
|
|
1107
|
+
if (preview) {
|
|
1108
|
+
const anno = {
|
|
1109
|
+
...defaults2,
|
|
1110
|
+
type: PdfAnnotationSubtype.SQUARE,
|
|
1111
|
+
created: /* @__PURE__ */ new Date(),
|
|
1112
|
+
id: uuidV4(),
|
|
1113
|
+
pageIndex,
|
|
1114
|
+
rect: preview.data.rect
|
|
1115
|
+
};
|
|
1116
|
+
onCommit(anno);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
setStart(null);
|
|
1120
|
+
onPreview(null);
|
|
1121
|
+
clickDetector.reset();
|
|
1122
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
1123
|
+
},
|
|
1124
|
+
onPointerLeave: (_, evt) => {
|
|
1125
|
+
var _a;
|
|
1126
|
+
setStart(null);
|
|
1127
|
+
onPreview(null);
|
|
1128
|
+
clickDetector.reset();
|
|
1129
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
1130
|
+
},
|
|
1131
|
+
onPointerCancel: (_, evt) => {
|
|
1132
|
+
var _a;
|
|
1133
|
+
setStart(null);
|
|
1134
|
+
onPreview(null);
|
|
1135
|
+
clickDetector.reset();
|
|
1136
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
1137
|
+
}
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
const stampHandlerFactory = {
|
|
1142
|
+
annotationType: PdfAnnotationSubtype.STAMP,
|
|
1143
|
+
create(context) {
|
|
1144
|
+
const { services, onCommit, getTool, pageSize } = context;
|
|
1145
|
+
return {
|
|
1146
|
+
onPointerDown: (pos) => {
|
|
1147
|
+
const tool = getTool();
|
|
1148
|
+
if (!tool) return;
|
|
1149
|
+
const { imageSrc, imageSize } = tool.defaults;
|
|
1150
|
+
const placeStamp = (imageData, width, height) => {
|
|
1151
|
+
const originX = pos.x - width / 2;
|
|
1152
|
+
const originY = pos.y - height / 2;
|
|
1153
|
+
const finalX = clamp(originX, 0, pageSize.width - width);
|
|
1154
|
+
const finalY = clamp(originY, 0, pageSize.height - height);
|
|
1155
|
+
const rect = {
|
|
1156
|
+
origin: { x: finalX, y: finalY },
|
|
1157
|
+
size: { width, height }
|
|
1158
|
+
};
|
|
1159
|
+
const anno = {
|
|
1160
|
+
...tool.defaults,
|
|
1161
|
+
rect,
|
|
1162
|
+
type: PdfAnnotationSubtype.STAMP,
|
|
1163
|
+
icon: tool.defaults.icon ?? PdfAnnotationIcon.Draft,
|
|
1164
|
+
subject: tool.defaults.subject ?? "Stamp",
|
|
1165
|
+
flags: tool.defaults.flags ?? ["print"],
|
|
1166
|
+
pageIndex: context.pageIndex,
|
|
1167
|
+
id: uuidV4(),
|
|
1168
|
+
created: /* @__PURE__ */ new Date()
|
|
1169
|
+
};
|
|
1170
|
+
onCommit(anno, { imageData });
|
|
1171
|
+
};
|
|
1172
|
+
if (imageSrc) {
|
|
1173
|
+
services.processImage({
|
|
1174
|
+
source: imageSrc,
|
|
1175
|
+
maxWidth: pageSize.width,
|
|
1176
|
+
maxHeight: pageSize.height,
|
|
1177
|
+
onComplete: (result) => placeStamp(
|
|
1178
|
+
result.imageData,
|
|
1179
|
+
(imageSize == null ? void 0 : imageSize.width) ?? result.width,
|
|
1180
|
+
(imageSize == null ? void 0 : imageSize.height) ?? result.height
|
|
1181
|
+
)
|
|
1182
|
+
});
|
|
1183
|
+
} else {
|
|
1184
|
+
services.requestFile({
|
|
1185
|
+
accept: "image/png,image/jpeg",
|
|
1186
|
+
onFile: (file) => {
|
|
1187
|
+
services.processImage({
|
|
1188
|
+
source: file,
|
|
1189
|
+
maxWidth: pageSize.width,
|
|
1190
|
+
maxHeight: pageSize.height,
|
|
1191
|
+
onComplete: (result) => placeStamp(result.imageData, result.width, result.height)
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
const circleHandlerFactory = {
|
|
1201
|
+
annotationType: PdfAnnotationSubtype.CIRCLE,
|
|
1202
|
+
create(context) {
|
|
1203
|
+
const { pageIndex, onCommit, onPreview, getTool, pageSize } = context;
|
|
1204
|
+
const [getStart, setStart] = useState(null);
|
|
1205
|
+
const clampToPage = (pos) => ({
|
|
1206
|
+
x: clamp(pos.x, 0, pageSize.width),
|
|
1207
|
+
y: clamp(pos.y, 0, pageSize.height)
|
|
1208
|
+
});
|
|
1209
|
+
const getDefaults = () => {
|
|
1210
|
+
const tool = getTool();
|
|
1211
|
+
if (!tool) return null;
|
|
1212
|
+
return {
|
|
1213
|
+
...tool.defaults,
|
|
1214
|
+
strokeWidth: tool.defaults.strokeWidth ?? 2,
|
|
1215
|
+
strokeColor: tool.defaults.strokeColor ?? "#000000",
|
|
1216
|
+
strokeStyle: tool.defaults.strokeStyle ?? PdfAnnotationBorderStyle.SOLID,
|
|
1217
|
+
strokeDashArray: tool.defaults.strokeDashArray ?? [],
|
|
1218
|
+
color: tool.defaults.color ?? "#000000",
|
|
1219
|
+
opacity: tool.defaults.opacity ?? 1,
|
|
1220
|
+
flags: tool.defaults.flags ?? ["print"]
|
|
1221
|
+
};
|
|
1222
|
+
};
|
|
1223
|
+
const clickDetector = useClickDetector({
|
|
1224
|
+
threshold: 5,
|
|
1225
|
+
getTool,
|
|
1226
|
+
onClickDetected: (pos, tool) => {
|
|
1227
|
+
const defaults = getDefaults();
|
|
1228
|
+
if (!defaults) return;
|
|
1229
|
+
const clickConfig = tool.clickBehavior;
|
|
1230
|
+
if (!(clickConfig == null ? void 0 : clickConfig.enabled)) return;
|
|
1231
|
+
const { width, height } = clickConfig.defaultSize;
|
|
1232
|
+
const halfWidth = width / 2;
|
|
1233
|
+
const halfHeight = height / 2;
|
|
1234
|
+
const x = clamp(pos.x - halfWidth, 0, pageSize.width - width);
|
|
1235
|
+
const y = clamp(pos.y - halfHeight, 0, pageSize.height - height);
|
|
1236
|
+
const strokeWidth = defaults.strokeWidth;
|
|
1237
|
+
const halfStroke = strokeWidth / 2;
|
|
1238
|
+
const rect = {
|
|
1239
|
+
origin: { x: x - halfStroke, y: y - halfStroke },
|
|
1240
|
+
size: { width: width + strokeWidth, height: height + strokeWidth }
|
|
1241
|
+
};
|
|
1242
|
+
const anno = {
|
|
1243
|
+
...defaults,
|
|
1244
|
+
type: PdfAnnotationSubtype.CIRCLE,
|
|
1245
|
+
created: /* @__PURE__ */ new Date(),
|
|
1246
|
+
id: uuidV4(),
|
|
1247
|
+
pageIndex,
|
|
1248
|
+
rect
|
|
1249
|
+
};
|
|
1250
|
+
onCommit(anno);
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
const getPreview = (current) => {
|
|
1254
|
+
const p1 = getStart();
|
|
1255
|
+
if (!p1) return null;
|
|
1256
|
+
const minX = Math.min(p1.x, current.x);
|
|
1257
|
+
const minY = Math.min(p1.y, current.y);
|
|
1258
|
+
const width = Math.abs(p1.x - current.x);
|
|
1259
|
+
const height = Math.abs(p1.y - current.y);
|
|
1260
|
+
const defaults = getDefaults();
|
|
1261
|
+
if (!defaults) return null;
|
|
1262
|
+
const strokeWidth = defaults.strokeWidth;
|
|
1263
|
+
const halfStroke = strokeWidth / 2;
|
|
1264
|
+
const rect = {
|
|
1265
|
+
origin: { x: minX - halfStroke, y: minY - halfStroke },
|
|
1266
|
+
size: { width: width + strokeWidth, height: height + strokeWidth }
|
|
1267
|
+
};
|
|
1268
|
+
return {
|
|
1269
|
+
type: PdfAnnotationSubtype.CIRCLE,
|
|
1270
|
+
bounds: rect,
|
|
1271
|
+
data: {
|
|
1272
|
+
rect,
|
|
1273
|
+
...defaults
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
};
|
|
1277
|
+
return {
|
|
1278
|
+
onPointerDown: (pos, evt) => {
|
|
1279
|
+
var _a;
|
|
1280
|
+
const clampedPos = clampToPage(pos);
|
|
1281
|
+
setStart(clampedPos);
|
|
1282
|
+
clickDetector.onStart(clampedPos);
|
|
1283
|
+
onPreview(getPreview(clampedPos));
|
|
1284
|
+
(_a = evt.setPointerCapture) == null ? void 0 : _a.call(evt);
|
|
1285
|
+
},
|
|
1286
|
+
onPointerMove: (pos) => {
|
|
1287
|
+
const clampedPos = clampToPage(pos);
|
|
1288
|
+
clickDetector.onMove(clampedPos);
|
|
1289
|
+
if (getStart() && clickDetector.hasMoved()) {
|
|
1290
|
+
onPreview(getPreview(clampedPos));
|
|
1291
|
+
}
|
|
1292
|
+
},
|
|
1293
|
+
onPointerUp: (pos, evt) => {
|
|
1294
|
+
var _a;
|
|
1295
|
+
const p1 = getStart();
|
|
1296
|
+
if (!p1) return;
|
|
1297
|
+
const defaults = getDefaults();
|
|
1298
|
+
if (!defaults) return;
|
|
1299
|
+
const clampedPos = clampToPage(pos);
|
|
1300
|
+
if (!clickDetector.hasMoved()) {
|
|
1301
|
+
clickDetector.onEnd(clampedPos);
|
|
1302
|
+
} else {
|
|
1303
|
+
const defaults2 = getDefaults();
|
|
1304
|
+
if (!defaults2) return;
|
|
1305
|
+
const preview = getPreview(clampedPos);
|
|
1306
|
+
if (preview) {
|
|
1307
|
+
const anno = {
|
|
1308
|
+
...defaults2,
|
|
1309
|
+
type: PdfAnnotationSubtype.CIRCLE,
|
|
1310
|
+
flags: ["print"],
|
|
1311
|
+
created: /* @__PURE__ */ new Date(),
|
|
1312
|
+
id: uuidV4(),
|
|
1313
|
+
pageIndex,
|
|
1314
|
+
rect: preview.data.rect
|
|
1315
|
+
};
|
|
1316
|
+
onCommit(anno);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
setStart(null);
|
|
1320
|
+
onPreview(null);
|
|
1321
|
+
clickDetector.reset();
|
|
1322
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
1323
|
+
},
|
|
1324
|
+
onPointerLeave: (_, evt) => {
|
|
1325
|
+
var _a;
|
|
1326
|
+
setStart(null);
|
|
1327
|
+
onPreview(null);
|
|
1328
|
+
clickDetector.reset();
|
|
1329
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
1330
|
+
},
|
|
1331
|
+
onPointerCancel: (_, evt) => {
|
|
1332
|
+
var _a;
|
|
1333
|
+
setStart(null);
|
|
1334
|
+
onPreview(null);
|
|
1335
|
+
clickDetector.reset();
|
|
1336
|
+
(_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
};
|
|
1341
|
+
const patchInk = (original, ctx) => {
|
|
1342
|
+
var _a;
|
|
1343
|
+
switch (ctx.type) {
|
|
1344
|
+
case "vertex-edit":
|
|
1345
|
+
return ctx.changes;
|
|
1346
|
+
case "move":
|
|
1347
|
+
if (ctx.changes.rect) {
|
|
1348
|
+
const dx = ctx.changes.rect.origin.x - original.rect.origin.x;
|
|
1349
|
+
const dy = ctx.changes.rect.origin.y - original.rect.origin.y;
|
|
1350
|
+
const movedInkList = original.inkList.map((stroke) => ({
|
|
1351
|
+
points: stroke.points.map((p) => ({
|
|
1352
|
+
x: p.x + dx,
|
|
1353
|
+
y: p.y + dy
|
|
1354
|
+
}))
|
|
1355
|
+
}));
|
|
1356
|
+
return {
|
|
1357
|
+
rect: ctx.changes.rect,
|
|
1358
|
+
inkList: movedInkList
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
return ctx.changes;
|
|
1362
|
+
case "resize":
|
|
1363
|
+
if (ctx.changes.rect) {
|
|
1364
|
+
const oldRect = original.rect;
|
|
1365
|
+
const newRect = ctx.changes.rect;
|
|
1366
|
+
let scaleX = newRect.size.width / oldRect.size.width;
|
|
1367
|
+
let scaleY = newRect.size.height / oldRect.size.height;
|
|
1368
|
+
const minSize = 10;
|
|
1369
|
+
if (newRect.size.width < minSize || newRect.size.height < minSize) {
|
|
1370
|
+
scaleX = Math.max(scaleX, minSize / oldRect.size.width);
|
|
1371
|
+
scaleY = Math.max(scaleY, minSize / oldRect.size.height);
|
|
1372
|
+
ctx.changes.rect = {
|
|
1373
|
+
origin: newRect.origin,
|
|
1374
|
+
size: {
|
|
1375
|
+
width: oldRect.size.width * scaleX,
|
|
1376
|
+
height: oldRect.size.height * scaleY
|
|
1377
|
+
}
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
if ((_a = ctx.metadata) == null ? void 0 : _a.maintainAspectRatio) {
|
|
1381
|
+
const minScale = Math.min(scaleX, scaleY);
|
|
1382
|
+
scaleX = minScale;
|
|
1383
|
+
scaleY = minScale;
|
|
1384
|
+
ctx.changes.rect.size = {
|
|
1385
|
+
width: oldRect.size.width * minScale,
|
|
1386
|
+
height: oldRect.size.height * minScale
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
const inset = (r, pad) => ({
|
|
1390
|
+
origin: { x: r.origin.x + pad, y: r.origin.y + pad },
|
|
1391
|
+
size: {
|
|
1392
|
+
width: Math.max(1, r.size.width - pad * 2),
|
|
1393
|
+
height: Math.max(1, r.size.height - pad * 2)
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
const strokeScale = Math.min(
|
|
1397
|
+
ctx.changes.rect.size.width / oldRect.size.width,
|
|
1398
|
+
ctx.changes.rect.size.height / oldRect.size.height
|
|
1399
|
+
);
|
|
1400
|
+
const newStrokeWidth = Math.max(1, Math.round(original.strokeWidth * strokeScale));
|
|
1401
|
+
const innerOld = inset(oldRect, original.strokeWidth / 2);
|
|
1402
|
+
const innerNew = inset(ctx.changes.rect, newStrokeWidth / 2);
|
|
1403
|
+
const sx = innerNew.size.width / Math.max(innerOld.size.width, 1e-6);
|
|
1404
|
+
const sy = innerNew.size.height / Math.max(innerOld.size.height, 1e-6);
|
|
1405
|
+
const newInkList = original.inkList.map((stroke) => ({
|
|
1406
|
+
points: stroke.points.map((p) => ({
|
|
1407
|
+
x: innerNew.origin.x + (p.x - innerOld.origin.x) * sx,
|
|
1408
|
+
y: innerNew.origin.y + (p.y - innerOld.origin.y) * sy
|
|
1409
|
+
}))
|
|
1410
|
+
}));
|
|
1411
|
+
return {
|
|
1412
|
+
rect: ctx.changes.rect,
|
|
1413
|
+
inkList: newInkList,
|
|
1414
|
+
strokeWidth: newStrokeWidth
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
return ctx.changes;
|
|
1418
|
+
case "property-update":
|
|
1419
|
+
if (ctx.changes.strokeWidth !== void 0) {
|
|
1420
|
+
const merged = { ...original, ...ctx.changes };
|
|
1421
|
+
const pts = merged.inkList.flatMap((s) => s.points);
|
|
1422
|
+
const rect = expandRect(rectFromPoints(pts), merged.strokeWidth / 2);
|
|
1423
|
+
return { ...ctx.changes, rect };
|
|
1424
|
+
}
|
|
1425
|
+
return ctx.changes;
|
|
1426
|
+
default:
|
|
1427
|
+
return ctx.changes;
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
const patchLine = (orig, ctx) => {
|
|
1431
|
+
var _a;
|
|
1432
|
+
switch (ctx.type) {
|
|
1433
|
+
case "vertex-edit":
|
|
1434
|
+
if (ctx.changes.linePoints) {
|
|
1435
|
+
const { start, end } = ctx.changes.linePoints;
|
|
1436
|
+
const rect = lineRectWithEndings([start, end], orig.strokeWidth, orig.lineEndings);
|
|
1437
|
+
return {
|
|
1438
|
+
rect,
|
|
1439
|
+
linePoints: { start, end }
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
return ctx.changes;
|
|
1443
|
+
case "move":
|
|
1444
|
+
if (ctx.changes.rect) {
|
|
1445
|
+
const dx = ctx.changes.rect.origin.x - orig.rect.origin.x;
|
|
1446
|
+
const dy = ctx.changes.rect.origin.y - orig.rect.origin.y;
|
|
1447
|
+
return {
|
|
1448
|
+
rect: ctx.changes.rect,
|
|
1449
|
+
linePoints: {
|
|
1450
|
+
start: { x: orig.linePoints.start.x + dx, y: orig.linePoints.start.y + dy },
|
|
1451
|
+
end: { x: orig.linePoints.end.x + dx, y: orig.linePoints.end.y + dy }
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
return ctx.changes;
|
|
1456
|
+
case "resize":
|
|
1457
|
+
if (ctx.changes.rect) {
|
|
1458
|
+
const oldRect = orig.rect;
|
|
1459
|
+
const newRect = ctx.changes.rect;
|
|
1460
|
+
let scaleX = newRect.size.width / oldRect.size.width;
|
|
1461
|
+
let scaleY = newRect.size.height / oldRect.size.height;
|
|
1462
|
+
const minSize = 10;
|
|
1463
|
+
if (newRect.size.width < minSize || newRect.size.height < minSize) {
|
|
1464
|
+
scaleX = Math.max(scaleX, minSize / oldRect.size.width);
|
|
1465
|
+
scaleY = Math.max(scaleY, minSize / oldRect.size.height);
|
|
1466
|
+
ctx.changes.rect = {
|
|
1467
|
+
origin: newRect.origin,
|
|
1468
|
+
size: {
|
|
1469
|
+
width: oldRect.size.width * scaleX,
|
|
1470
|
+
height: oldRect.size.height * scaleY
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
if ((_a = ctx.metadata) == null ? void 0 : _a.maintainAspectRatio) {
|
|
1475
|
+
const minScale = Math.min(scaleX, scaleY);
|
|
1476
|
+
scaleX = minScale;
|
|
1477
|
+
scaleY = minScale;
|
|
1478
|
+
ctx.changes.rect.size = {
|
|
1479
|
+
width: oldRect.size.width * minScale,
|
|
1480
|
+
height: oldRect.size.height * minScale
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
const newLinePoints = {
|
|
1484
|
+
start: {
|
|
1485
|
+
x: ctx.changes.rect.origin.x + (orig.linePoints.start.x - oldRect.origin.x) * scaleX,
|
|
1486
|
+
y: ctx.changes.rect.origin.y + (orig.linePoints.start.y - oldRect.origin.y) * scaleY
|
|
1487
|
+
},
|
|
1488
|
+
end: {
|
|
1489
|
+
x: ctx.changes.rect.origin.x + (orig.linePoints.end.x - oldRect.origin.x) * scaleX,
|
|
1490
|
+
y: ctx.changes.rect.origin.y + (orig.linePoints.end.y - oldRect.origin.y) * scaleY
|
|
1491
|
+
}
|
|
1492
|
+
};
|
|
1493
|
+
return {
|
|
1494
|
+
rect: ctx.changes.rect,
|
|
1495
|
+
linePoints: newLinePoints
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
return ctx.changes;
|
|
1499
|
+
case "property-update":
|
|
1500
|
+
if (ctx.changes.strokeWidth || ctx.changes.lineEndings) {
|
|
1501
|
+
const merged = { ...orig, ...ctx.changes };
|
|
1502
|
+
const rect = lineRectWithEndings(
|
|
1503
|
+
[merged.linePoints.start, merged.linePoints.end],
|
|
1504
|
+
merged.strokeWidth,
|
|
1505
|
+
merged.lineEndings
|
|
1506
|
+
);
|
|
1507
|
+
return { ...ctx.changes, rect };
|
|
1508
|
+
}
|
|
1509
|
+
return ctx.changes;
|
|
1510
|
+
default:
|
|
1511
|
+
return ctx.changes;
|
|
1512
|
+
}
|
|
1513
|
+
};
|
|
1514
|
+
const patchPolyline = (orig, ctx) => {
|
|
1515
|
+
var _a;
|
|
1516
|
+
switch (ctx.type) {
|
|
1517
|
+
case "vertex-edit":
|
|
1518
|
+
if (ctx.changes.vertices && ctx.changes.vertices.length) {
|
|
1519
|
+
return {
|
|
1520
|
+
rect: lineRectWithEndings(ctx.changes.vertices, orig.strokeWidth, orig.lineEndings),
|
|
1521
|
+
vertices: ctx.changes.vertices
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
return ctx.changes;
|
|
1525
|
+
case "move":
|
|
1526
|
+
if (ctx.changes.rect) {
|
|
1527
|
+
const dx = ctx.changes.rect.origin.x - orig.rect.origin.x;
|
|
1528
|
+
const dy = ctx.changes.rect.origin.y - orig.rect.origin.y;
|
|
1529
|
+
const moved = orig.vertices.map((p) => ({ x: p.x + dx, y: p.y + dy }));
|
|
1530
|
+
return {
|
|
1531
|
+
rect: ctx.changes.rect,
|
|
1532
|
+
vertices: moved
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
return ctx.changes;
|
|
1536
|
+
case "resize":
|
|
1537
|
+
if (ctx.changes.rect) {
|
|
1538
|
+
const oldRect = orig.rect;
|
|
1539
|
+
const newRect = ctx.changes.rect;
|
|
1540
|
+
let scaleX = newRect.size.width / oldRect.size.width;
|
|
1541
|
+
let scaleY = newRect.size.height / oldRect.size.height;
|
|
1542
|
+
const minSize = 10;
|
|
1543
|
+
if (newRect.size.width < minSize || newRect.size.height < minSize) {
|
|
1544
|
+
scaleX = Math.max(scaleX, minSize / oldRect.size.width);
|
|
1545
|
+
scaleY = Math.max(scaleY, minSize / oldRect.size.height);
|
|
1546
|
+
ctx.changes.rect = {
|
|
1547
|
+
origin: newRect.origin,
|
|
1548
|
+
size: {
|
|
1549
|
+
width: oldRect.size.width * scaleX,
|
|
1550
|
+
height: oldRect.size.height * scaleY
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
if ((_a = ctx.metadata) == null ? void 0 : _a.maintainAspectRatio) {
|
|
1555
|
+
const minScale = Math.min(scaleX, scaleY);
|
|
1556
|
+
scaleX = minScale;
|
|
1557
|
+
scaleY = minScale;
|
|
1558
|
+
ctx.changes.rect.size = {
|
|
1559
|
+
width: oldRect.size.width * minScale,
|
|
1560
|
+
height: oldRect.size.height * minScale
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
const scaledVertices = orig.vertices.map((vertex) => ({
|
|
1564
|
+
x: ctx.changes.rect.origin.x + (vertex.x - oldRect.origin.x) * scaleX,
|
|
1565
|
+
y: ctx.changes.rect.origin.y + (vertex.y - oldRect.origin.y) * scaleY
|
|
1566
|
+
}));
|
|
1567
|
+
return {
|
|
1568
|
+
rect: ctx.changes.rect,
|
|
1569
|
+
vertices: scaledVertices
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
return ctx.changes;
|
|
1573
|
+
case "property-update":
|
|
1574
|
+
if (ctx.changes.strokeWidth !== void 0 || ctx.changes.lineEndings !== void 0) {
|
|
1575
|
+
const merged = { ...orig, ...ctx.changes };
|
|
1576
|
+
const rect = lineRectWithEndings(merged.vertices, merged.strokeWidth, merged.lineEndings);
|
|
1577
|
+
return { ...ctx.changes, rect };
|
|
1578
|
+
}
|
|
1579
|
+
return ctx.changes;
|
|
1580
|
+
default:
|
|
1581
|
+
return ctx.changes;
|
|
1582
|
+
}
|
|
1583
|
+
};
|
|
1584
|
+
const patchPolygon = (orig, ctx) => {
|
|
1585
|
+
var _a;
|
|
1586
|
+
switch (ctx.type) {
|
|
1587
|
+
case "vertex-edit":
|
|
1588
|
+
if (ctx.changes.vertices && ctx.changes.vertices.length) {
|
|
1589
|
+
const pad = orig.strokeWidth / 2;
|
|
1590
|
+
return {
|
|
1591
|
+
rect: expandRect(rectFromPoints(ctx.changes.vertices), pad),
|
|
1592
|
+
vertices: ctx.changes.vertices
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
return ctx.changes;
|
|
1596
|
+
case "move":
|
|
1597
|
+
if (ctx.changes.rect) {
|
|
1598
|
+
const dx = ctx.changes.rect.origin.x - orig.rect.origin.x;
|
|
1599
|
+
const dy = ctx.changes.rect.origin.y - orig.rect.origin.y;
|
|
1600
|
+
const moved = orig.vertices.map((p) => ({ x: p.x + dx, y: p.y + dy }));
|
|
1601
|
+
return {
|
|
1602
|
+
rect: ctx.changes.rect,
|
|
1603
|
+
vertices: moved
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
return ctx.changes;
|
|
1607
|
+
case "resize":
|
|
1608
|
+
if (ctx.changes.rect) {
|
|
1609
|
+
const oldRect = orig.rect;
|
|
1610
|
+
const newRect = ctx.changes.rect;
|
|
1611
|
+
let scaleX = newRect.size.width / oldRect.size.width;
|
|
1612
|
+
let scaleY = newRect.size.height / oldRect.size.height;
|
|
1613
|
+
const minSize = 10;
|
|
1614
|
+
if (newRect.size.width < minSize || newRect.size.height < minSize) {
|
|
1615
|
+
scaleX = Math.max(scaleX, minSize / oldRect.size.width);
|
|
1616
|
+
scaleY = Math.max(scaleY, minSize / oldRect.size.height);
|
|
1617
|
+
ctx.changes.rect = {
|
|
1618
|
+
origin: newRect.origin,
|
|
1619
|
+
size: {
|
|
1620
|
+
width: oldRect.size.width * scaleX,
|
|
1621
|
+
height: oldRect.size.height * scaleY
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
if ((_a = ctx.metadata) == null ? void 0 : _a.maintainAspectRatio) {
|
|
1626
|
+
const minScale = Math.min(scaleX, scaleY);
|
|
1627
|
+
scaleX = minScale;
|
|
1628
|
+
scaleY = minScale;
|
|
1629
|
+
ctx.changes.rect.size = {
|
|
1630
|
+
width: oldRect.size.width * minScale,
|
|
1631
|
+
height: oldRect.size.height * minScale
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
const scaledVertices = orig.vertices.map((vertex) => ({
|
|
1635
|
+
x: ctx.changes.rect.origin.x + (vertex.x - oldRect.origin.x) * scaleX,
|
|
1636
|
+
y: ctx.changes.rect.origin.y + (vertex.y - oldRect.origin.y) * scaleY
|
|
1637
|
+
}));
|
|
1638
|
+
return {
|
|
1639
|
+
rect: ctx.changes.rect,
|
|
1640
|
+
vertices: scaledVertices
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
return ctx.changes;
|
|
1644
|
+
case "property-update":
|
|
1645
|
+
if (ctx.changes.strokeWidth !== void 0) {
|
|
1646
|
+
const merged = { ...orig, ...ctx.changes };
|
|
1647
|
+
const pad = merged.strokeWidth / 2;
|
|
1648
|
+
const rect = expandRect(rectFromPoints(merged.vertices), pad);
|
|
1649
|
+
return { ...ctx.changes, rect };
|
|
1650
|
+
}
|
|
1651
|
+
return ctx.changes;
|
|
1652
|
+
default:
|
|
1653
|
+
return ctx.changes;
|
|
1654
|
+
}
|
|
1655
|
+
};
|
|
398
1656
|
const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
399
1657
|
constructor(id, registry, config) {
|
|
1658
|
+
var _a, _b, _c;
|
|
400
1659
|
super(id, registry);
|
|
401
1660
|
this.ANNOTATION_HISTORY_TOPIC = "annotations";
|
|
402
1661
|
this.state$ = createBehaviorEmitter();
|
|
403
|
-
this.modeByVariant = /* @__PURE__ */ new Map();
|
|
404
|
-
this.variantByMode = /* @__PURE__ */ new Map();
|
|
405
1662
|
this.pendingContexts = /* @__PURE__ */ new Map();
|
|
406
|
-
this.
|
|
407
|
-
this.activeTool$ = createBehaviorEmitter(
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
1663
|
+
this.handlerFactories = /* @__PURE__ */ new Map();
|
|
1664
|
+
this.activeTool$ = createBehaviorEmitter(null);
|
|
1665
|
+
this.events$ = createBehaviorEmitter();
|
|
1666
|
+
this.patchRegistry = new PatchRegistry();
|
|
1667
|
+
this.isInitialLoadComplete = false;
|
|
1668
|
+
this.importQueue = [];
|
|
411
1669
|
this.config = config;
|
|
412
|
-
|
|
413
|
-
this.
|
|
414
|
-
|
|
415
|
-
this.
|
|
416
|
-
const interactionManager = registry.getPlugin("interaction-manager");
|
|
417
|
-
this.interactionManager = (interactionManager == null ? void 0 : interactionManager.provides()) ?? null;
|
|
418
|
-
this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {
|
|
1670
|
+
this.selection = ((_a = registry.getPlugin("selection")) == null ? void 0 : _a.provides()) ?? null;
|
|
1671
|
+
this.history = ((_b = registry.getPlugin("history")) == null ? void 0 : _b.provides()) ?? null;
|
|
1672
|
+
this.interactionManager = ((_c = registry.getPlugin("interaction-manager")) == null ? void 0 : _c.provides()) ?? null;
|
|
1673
|
+
this.coreStore.onAction(SET_DOCUMENT, (_, state) => {
|
|
419
1674
|
const doc = state.core.document;
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
}
|
|
1675
|
+
this.isInitialLoadComplete = false;
|
|
1676
|
+
if (doc) this.getAllAnnotations(doc);
|
|
423
1677
|
});
|
|
1678
|
+
this.registerHandlerFactories();
|
|
1679
|
+
this.registerBuiltInPatches();
|
|
1680
|
+
}
|
|
1681
|
+
registerHandlerFactories() {
|
|
1682
|
+
this.handlerFactories.set(PdfAnnotationSubtype.CIRCLE, circleHandlerFactory);
|
|
1683
|
+
this.handlerFactories.set(PdfAnnotationSubtype.SQUARE, squareHandlerFactory);
|
|
1684
|
+
this.handlerFactories.set(PdfAnnotationSubtype.STAMP, stampHandlerFactory);
|
|
1685
|
+
this.handlerFactories.set(PdfAnnotationSubtype.POLYGON, polygonHandlerFactory);
|
|
1686
|
+
this.handlerFactories.set(PdfAnnotationSubtype.POLYLINE, polylineHandlerFactory);
|
|
1687
|
+
this.handlerFactories.set(PdfAnnotationSubtype.LINE, lineHandlerFactory);
|
|
1688
|
+
this.handlerFactories.set(PdfAnnotationSubtype.INK, inkHandlerFactory);
|
|
1689
|
+
this.handlerFactories.set(PdfAnnotationSubtype.FREETEXT, freeTextHandlerFactory);
|
|
1690
|
+
}
|
|
1691
|
+
registerBuiltInPatches() {
|
|
1692
|
+
this.patchRegistry.register(PdfAnnotationSubtype.INK, patchInk);
|
|
1693
|
+
this.patchRegistry.register(PdfAnnotationSubtype.LINE, patchLine);
|
|
1694
|
+
this.patchRegistry.register(PdfAnnotationSubtype.POLYLINE, patchPolyline);
|
|
1695
|
+
this.patchRegistry.register(PdfAnnotationSubtype.POLYGON, patchPolygon);
|
|
424
1696
|
}
|
|
425
1697
|
async initialize() {
|
|
426
1698
|
var _a, _b, _c;
|
|
427
|
-
|
|
428
|
-
this.registerTool(variantKey, defaults);
|
|
429
|
-
}
|
|
1699
|
+
this.state.tools.forEach((tool) => this.registerInteractionForTool(tool));
|
|
430
1700
|
(_a = this.history) == null ? void 0 : _a.onHistoryChange((topic) => {
|
|
431
1701
|
if (topic === this.ANNOTATION_HISTORY_TOPIC && this.config.autoCommit !== false) {
|
|
432
1702
|
this.commit();
|
|
433
1703
|
}
|
|
434
1704
|
});
|
|
435
1705
|
(_b = this.interactionManager) == null ? void 0 : _b.onModeChange((s) => {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
this.
|
|
1706
|
+
var _a2;
|
|
1707
|
+
const newToolId = ((_a2 = this.state.tools.find((t) => (t.interaction.mode ?? t.id) === s.activeMode)) == null ? void 0 : _a2.id) ?? null;
|
|
1708
|
+
if (newToolId !== this.state.activeToolId) {
|
|
1709
|
+
this.dispatch(setActiveToolId(newToolId));
|
|
440
1710
|
}
|
|
441
1711
|
});
|
|
442
1712
|
(_c = this.selection) == null ? void 0 : _c.onEndSelection(() => {
|
|
443
1713
|
var _a2, _b2, _c2;
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if (!defaults || !isTextMarkupDefaults(defaults)) return;
|
|
1714
|
+
const activeTool = this.getActiveTool();
|
|
1715
|
+
if (!activeTool || !activeTool.interaction.textSelection) return;
|
|
447
1716
|
const formattedSelection = (_a2 = this.selection) == null ? void 0 : _a2.getFormattedSelection();
|
|
448
1717
|
const selectionText = (_b2 = this.selection) == null ? void 0 : _b2.getSelectedText();
|
|
449
1718
|
if (!formattedSelection || !selectionText) return;
|
|
450
1719
|
for (const selection of formattedSelection) {
|
|
451
|
-
const rect = selection.rect;
|
|
452
|
-
const segmentRects = selection.segmentRects;
|
|
453
|
-
const subtype = defaults.subtype;
|
|
454
|
-
const color = defaults.color;
|
|
455
|
-
const opacity = defaults.opacity;
|
|
456
|
-
const blendMode = defaults.blendMode ?? PdfBlendMode.Normal;
|
|
457
1720
|
selectionText.wait((text) => {
|
|
1721
|
+
const annotationId = uuidV4();
|
|
458
1722
|
this.createAnnotation(selection.pageIndex, {
|
|
459
|
-
|
|
460
|
-
rect,
|
|
461
|
-
segmentRects,
|
|
462
|
-
color,
|
|
463
|
-
opacity,
|
|
464
|
-
flags: ["print"],
|
|
465
|
-
blendMode,
|
|
1723
|
+
...activeTool.defaults,
|
|
1724
|
+
rect: selection.rect,
|
|
1725
|
+
segmentRects: selection.segmentRects,
|
|
466
1726
|
pageIndex: selection.pageIndex,
|
|
467
|
-
|
|
468
|
-
|
|
1727
|
+
created: /* @__PURE__ */ new Date(),
|
|
1728
|
+
id: annotationId,
|
|
469
1729
|
custom: {
|
|
470
1730
|
text: text.join("\n")
|
|
471
1731
|
}
|
|
472
1732
|
});
|
|
1733
|
+
if (this.getToolBehavior(activeTool, "deactivateToolAfterCreate")) {
|
|
1734
|
+
this.setActiveTool(null);
|
|
1735
|
+
}
|
|
1736
|
+
if (this.getToolBehavior(activeTool, "selectAfterCreate")) {
|
|
1737
|
+
this.selectAnnotation(selection.pageIndex, annotationId);
|
|
1738
|
+
}
|
|
473
1739
|
}, ignore);
|
|
474
1740
|
}
|
|
475
1741
|
(_c2 = this.selection) == null ? void 0 : _c2.clear();
|
|
476
1742
|
});
|
|
477
1743
|
}
|
|
478
|
-
|
|
1744
|
+
registerInteractionForTool(tool) {
|
|
479
1745
|
var _a, _b;
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
id: modeId,
|
|
1746
|
+
(_a = this.interactionManager) == null ? void 0 : _a.registerMode({
|
|
1747
|
+
id: tool.interaction.mode ?? tool.id,
|
|
483
1748
|
scope: "page",
|
|
484
|
-
exclusive:
|
|
485
|
-
cursor:
|
|
486
|
-
};
|
|
487
|
-
(
|
|
488
|
-
|
|
489
|
-
(_b = this.selection) == null ? void 0 : _b.enableForMode(modeId);
|
|
1749
|
+
exclusive: tool.interaction.exclusive,
|
|
1750
|
+
cursor: tool.interaction.cursor
|
|
1751
|
+
});
|
|
1752
|
+
if (tool.interaction.textSelection) {
|
|
1753
|
+
(_b = this.selection) == null ? void 0 : _b.enableForMode(tool.interaction.mode ?? tool.id);
|
|
490
1754
|
}
|
|
491
|
-
this.modeByVariant.set(variantKey, modeId);
|
|
492
|
-
this.variantByMode.set(modeId, variantKey);
|
|
493
1755
|
}
|
|
494
1756
|
buildCapability() {
|
|
495
1757
|
return {
|
|
496
|
-
getPageAnnotations: (options) =>
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
this.
|
|
507
|
-
},
|
|
508
|
-
getActiveVariant: () => {
|
|
509
|
-
return this.state.activeVariant;
|
|
510
|
-
},
|
|
511
|
-
setActiveVariant: (variantKey) => {
|
|
512
|
-
var _a, _b;
|
|
513
|
-
if (variantKey === this.state.activeVariant) return;
|
|
514
|
-
if (variantKey) {
|
|
515
|
-
const mode = this.modeByVariant.get(variantKey);
|
|
516
|
-
if (!mode) throw new Error(`Mode missing for variant ${variantKey}`);
|
|
517
|
-
(_a = this.interactionManager) == null ? void 0 : _a.activate(mode);
|
|
518
|
-
} else {
|
|
519
|
-
(_b = this.interactionManager) == null ? void 0 : _b.activateDefaultMode();
|
|
520
|
-
}
|
|
521
|
-
},
|
|
522
|
-
getSubtypeAndIntentByVariant: (variantKey) => {
|
|
523
|
-
return parseVariantKey(variantKey);
|
|
524
|
-
},
|
|
525
|
-
getToolDefaults: (variantKey) => {
|
|
526
|
-
const defaults = this.state.toolDefaults[variantKey];
|
|
527
|
-
if (!defaults) {
|
|
528
|
-
throw new Error(`No defaults found for variant: ${variantKey}`);
|
|
529
|
-
}
|
|
530
|
-
return defaults;
|
|
531
|
-
},
|
|
532
|
-
getToolDefaultsBySubtypeAndIntent: (subtype, intent) => {
|
|
533
|
-
return getToolDefaultsBySubtypeAndIntent(this.state, subtype, intent);
|
|
534
|
-
},
|
|
535
|
-
getToolDefaultsBySubtype: (subtype) => {
|
|
536
|
-
return getToolDefaultsBySubtypeAndIntent(this.state, subtype);
|
|
537
|
-
},
|
|
538
|
-
setToolDefaults: (variantKey, patch) => {
|
|
539
|
-
this.dispatch(updateToolDefaults(variantKey, patch));
|
|
1758
|
+
getPageAnnotations: (options) => this.getPageAnnotations(options),
|
|
1759
|
+
getSelectedAnnotation: () => getSelectedAnnotation(this.state),
|
|
1760
|
+
selectAnnotation: (pageIndex, id) => this.selectAnnotation(pageIndex, id),
|
|
1761
|
+
deselectAnnotation: () => this.dispatch(deselectAnnotation()),
|
|
1762
|
+
getActiveTool: () => this.getActiveTool(),
|
|
1763
|
+
setActiveTool: (toolId) => this.setActiveTool(toolId),
|
|
1764
|
+
getTools: () => this.state.tools,
|
|
1765
|
+
getTool: (toolId) => this.getTool(toolId),
|
|
1766
|
+
addTool: (tool) => {
|
|
1767
|
+
this.dispatch(addTool(tool));
|
|
1768
|
+
this.registerInteractionForTool(tool);
|
|
540
1769
|
},
|
|
1770
|
+
transformAnnotation: (annotation, options) => this.transformAnnotation(annotation, options),
|
|
1771
|
+
registerPatchFunction: (type, patchFn) => this.registerPatchFunction(type, patchFn),
|
|
1772
|
+
findToolForAnnotation: (anno) => this.findToolForAnnotation(anno),
|
|
1773
|
+
setToolDefaults: (toolId, patch) => this.dispatch(setToolDefaults(toolId, patch)),
|
|
541
1774
|
getColorPresets: () => [...this.state.colorPresets],
|
|
542
1775
|
addColorPreset: (color) => this.dispatch(addColorPreset(color)),
|
|
543
|
-
|
|
1776
|
+
importAnnotations: (items) => this.importAnnotations(items),
|
|
1777
|
+
createAnnotation: (pageIndex, anno, ctx) => this.createAnnotation(pageIndex, anno, ctx),
|
|
544
1778
|
updateAnnotation: (pageIndex, id, patch) => this.updateAnnotation(pageIndex, id, patch),
|
|
545
1779
|
deleteAnnotation: (pageIndex, id) => this.deleteAnnotation(pageIndex, id),
|
|
546
1780
|
renderAnnotation: (options) => this.renderAnnotation(options),
|
|
547
1781
|
onStateChange: this.state$.on,
|
|
548
|
-
onActiveVariantChange: this.activeVariantChange$.on,
|
|
549
1782
|
onActiveToolChange: this.activeTool$.on,
|
|
1783
|
+
onAnnotationEvent: this.events$.on,
|
|
550
1784
|
commit: () => this.commit()
|
|
551
1785
|
};
|
|
552
1786
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
1787
|
+
onStoreUpdated(prev, next) {
|
|
1788
|
+
this.state$.emit(next);
|
|
1789
|
+
if (prev.activeToolId !== next.activeToolId || prev.tools !== next.tools) {
|
|
1790
|
+
this.activeTool$.emit(this.getActiveTool());
|
|
556
1791
|
}
|
|
557
|
-
return { variantKey: mode, defaults: toolDefaults[mode] };
|
|
558
1792
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
this.activeTool$.emit(activeTool);
|
|
1793
|
+
registerPatchFunction(type, patchFn) {
|
|
1794
|
+
this.patchRegistry.register(type, patchFn);
|
|
562
1795
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
1796
|
+
transformAnnotation(annotation, options) {
|
|
1797
|
+
const context = {
|
|
1798
|
+
type: options.type,
|
|
1799
|
+
changes: options.changes,
|
|
1800
|
+
metadata: options.metadata
|
|
1801
|
+
};
|
|
1802
|
+
return this.patchRegistry.transform(annotation, context);
|
|
1803
|
+
}
|
|
1804
|
+
registerPageHandlers(pageIndex, scale, callbacks) {
|
|
1805
|
+
var _a;
|
|
1806
|
+
const page = (_a = this.coreState.core.document) == null ? void 0 : _a.pages[pageIndex];
|
|
1807
|
+
if (!page) return () => {
|
|
1808
|
+
};
|
|
1809
|
+
if (!this.interactionManager) return () => {
|
|
1810
|
+
};
|
|
1811
|
+
const unregisterFns = [];
|
|
1812
|
+
for (const tool of this.state.tools) {
|
|
1813
|
+
if (!tool.defaults.type) continue;
|
|
1814
|
+
const factory = this.handlerFactories.get(tool.defaults.type);
|
|
1815
|
+
if (!factory) continue;
|
|
1816
|
+
const context = {
|
|
1817
|
+
pageIndex,
|
|
1818
|
+
pageSize: page.size,
|
|
1819
|
+
scale,
|
|
1820
|
+
services: callbacks.services,
|
|
1821
|
+
// Pass through services
|
|
1822
|
+
onPreview: (state) => callbacks.onPreview(tool.id, state),
|
|
1823
|
+
onCommit: (annotation, ctx) => {
|
|
1824
|
+
this.createAnnotation(pageIndex, annotation, ctx);
|
|
1825
|
+
if (this.getToolBehavior(tool, "deactivateToolAfterCreate")) {
|
|
1826
|
+
this.setActiveTool(null);
|
|
1827
|
+
}
|
|
1828
|
+
if (this.getToolBehavior(tool, "selectAfterCreate")) {
|
|
1829
|
+
this.selectAnnotation(pageIndex, annotation.id);
|
|
1830
|
+
}
|
|
1831
|
+
},
|
|
1832
|
+
getTool: () => this.state.tools.find((t) => t.id === tool.id)
|
|
1833
|
+
};
|
|
1834
|
+
const unregister = this.interactionManager.registerHandlers({
|
|
1835
|
+
modeId: tool.interaction.mode ?? tool.id,
|
|
1836
|
+
handlers: factory.create(context),
|
|
1837
|
+
pageIndex
|
|
1838
|
+
});
|
|
1839
|
+
unregisterFns.push(unregister);
|
|
567
1840
|
}
|
|
1841
|
+
return () => unregisterFns.forEach((fn) => fn());
|
|
568
1842
|
}
|
|
569
1843
|
getAllAnnotations(doc) {
|
|
570
1844
|
const task = this.engine.getAllAnnotations(doc);
|
|
571
|
-
task.wait((annotations) =>
|
|
1845
|
+
task.wait((annotations) => {
|
|
1846
|
+
this.dispatch(setAnnotations(annotations));
|
|
1847
|
+
this.isInitialLoadComplete = true;
|
|
1848
|
+
if (this.importQueue.length > 0) {
|
|
1849
|
+
this.processImportQueue();
|
|
1850
|
+
}
|
|
1851
|
+
this.events$.emit({
|
|
1852
|
+
type: "loaded",
|
|
1853
|
+
total: Object.values(annotations).reduce(
|
|
1854
|
+
(sum, pageAnnotations) => sum + pageAnnotations.length,
|
|
1855
|
+
0
|
|
1856
|
+
)
|
|
1857
|
+
});
|
|
1858
|
+
}, ignore);
|
|
572
1859
|
}
|
|
573
1860
|
getPageAnnotations(options) {
|
|
574
1861
|
const { pageIndex } = options;
|
|
@@ -585,28 +1872,53 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
585
1872
|
renderAnnotation({ pageIndex, annotation, options }) {
|
|
586
1873
|
const coreState = this.coreState.core;
|
|
587
1874
|
if (!coreState.document) {
|
|
588
|
-
|
|
1875
|
+
return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: "Document not found" });
|
|
589
1876
|
}
|
|
590
1877
|
const page = coreState.document.pages.find((page2) => page2.index === pageIndex);
|
|
591
1878
|
if (!page) {
|
|
592
|
-
|
|
1879
|
+
return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: "Page not found" });
|
|
593
1880
|
}
|
|
594
1881
|
return this.engine.renderPageAnnotation(coreState.document, page, annotation, options);
|
|
595
1882
|
}
|
|
596
|
-
|
|
597
|
-
this.
|
|
1883
|
+
importAnnotations(items) {
|
|
1884
|
+
if (!this.isInitialLoadComplete) {
|
|
1885
|
+
this.importQueue.push(...items);
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
this.processImportItems(items);
|
|
1889
|
+
}
|
|
1890
|
+
processImportQueue() {
|
|
1891
|
+
if (this.importQueue.length === 0) return;
|
|
1892
|
+
const items = [...this.importQueue];
|
|
1893
|
+
this.importQueue = [];
|
|
1894
|
+
this.processImportItems(items);
|
|
1895
|
+
}
|
|
1896
|
+
processImportItems(items) {
|
|
1897
|
+
for (const item of items) {
|
|
1898
|
+
const { annotation, ctx } = item;
|
|
1899
|
+
const pageIndex = annotation.pageIndex;
|
|
1900
|
+
const id = annotation.id;
|
|
1901
|
+
this.dispatch(createAnnotation(pageIndex, annotation));
|
|
1902
|
+
if (ctx) this.pendingContexts.set(id, ctx);
|
|
1903
|
+
}
|
|
1904
|
+
if (this.config.autoCommit !== false) this.commit();
|
|
598
1905
|
}
|
|
599
1906
|
createAnnotation(pageIndex, annotation, ctx) {
|
|
600
1907
|
const id = annotation.id;
|
|
1908
|
+
const newAnnotation = {
|
|
1909
|
+
...annotation,
|
|
1910
|
+
author: annotation.author ?? this.config.annotationAuthor
|
|
1911
|
+
};
|
|
601
1912
|
const execute = () => {
|
|
602
|
-
this.dispatch(
|
|
603
|
-
createAnnotation(pageIndex, {
|
|
604
|
-
...annotation,
|
|
605
|
-
author: annotation.author ?? this.config.annotationAuthor,
|
|
606
|
-
flags: ["print"]
|
|
607
|
-
})
|
|
608
|
-
);
|
|
1913
|
+
this.dispatch(createAnnotation(pageIndex, newAnnotation));
|
|
609
1914
|
if (ctx) this.pendingContexts.set(id, ctx);
|
|
1915
|
+
this.events$.emit({
|
|
1916
|
+
type: "create",
|
|
1917
|
+
annotation: newAnnotation,
|
|
1918
|
+
pageIndex,
|
|
1919
|
+
ctx,
|
|
1920
|
+
committed: false
|
|
1921
|
+
});
|
|
610
1922
|
};
|
|
611
1923
|
if (!this.history) {
|
|
612
1924
|
execute();
|
|
@@ -619,14 +1931,22 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
619
1931
|
this.pendingContexts.delete(id);
|
|
620
1932
|
this.dispatch(deselectAnnotation());
|
|
621
1933
|
this.dispatch(deleteAnnotation(pageIndex, id));
|
|
1934
|
+
this.events$.emit({
|
|
1935
|
+
type: "delete",
|
|
1936
|
+
annotation: newAnnotation,
|
|
1937
|
+
pageIndex,
|
|
1938
|
+
committed: false
|
|
1939
|
+
});
|
|
622
1940
|
}
|
|
623
1941
|
};
|
|
624
1942
|
this.history.register(command, this.ANNOTATION_HISTORY_TOPIC);
|
|
625
1943
|
}
|
|
626
1944
|
buildPatch(original, patch) {
|
|
627
1945
|
if ("rect" in patch) return patch;
|
|
628
|
-
|
|
629
|
-
|
|
1946
|
+
return this.transformAnnotation(original, {
|
|
1947
|
+
type: "property-update",
|
|
1948
|
+
changes: patch
|
|
1949
|
+
});
|
|
630
1950
|
}
|
|
631
1951
|
updateAnnotation(pageIndex, id, patch) {
|
|
632
1952
|
const originalObject = this.state.byUid[id].object;
|
|
@@ -634,8 +1954,18 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
634
1954
|
...patch,
|
|
635
1955
|
author: patch.author ?? this.config.annotationAuthor
|
|
636
1956
|
});
|
|
637
|
-
|
|
1957
|
+
const execute = () => {
|
|
638
1958
|
this.dispatch(patchAnnotation(pageIndex, id, finalPatch));
|
|
1959
|
+
this.events$.emit({
|
|
1960
|
+
type: "update",
|
|
1961
|
+
annotation: originalObject,
|
|
1962
|
+
pageIndex,
|
|
1963
|
+
patch: finalPatch,
|
|
1964
|
+
committed: false
|
|
1965
|
+
});
|
|
1966
|
+
};
|
|
1967
|
+
if (!this.history) {
|
|
1968
|
+
execute();
|
|
639
1969
|
if (this.config.autoCommit !== false) {
|
|
640
1970
|
this.commit();
|
|
641
1971
|
}
|
|
@@ -645,30 +1975,85 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
645
1975
|
Object.keys(patch).map((key) => [key, originalObject[key]])
|
|
646
1976
|
);
|
|
647
1977
|
const command = {
|
|
648
|
-
execute
|
|
649
|
-
undo: () =>
|
|
1978
|
+
execute,
|
|
1979
|
+
undo: () => {
|
|
1980
|
+
this.dispatch(patchAnnotation(pageIndex, id, originalPatch));
|
|
1981
|
+
this.events$.emit({
|
|
1982
|
+
type: "update",
|
|
1983
|
+
annotation: originalObject,
|
|
1984
|
+
pageIndex,
|
|
1985
|
+
patch: originalPatch,
|
|
1986
|
+
committed: false
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
650
1989
|
};
|
|
651
1990
|
this.history.register(command, this.ANNOTATION_HISTORY_TOPIC);
|
|
652
1991
|
}
|
|
653
1992
|
deleteAnnotation(pageIndex, id) {
|
|
654
|
-
|
|
1993
|
+
var _a;
|
|
1994
|
+
const originalAnnotation = (_a = this.state.byUid[id]) == null ? void 0 : _a.object;
|
|
1995
|
+
if (!originalAnnotation) return;
|
|
1996
|
+
const execute = () => {
|
|
655
1997
|
this.dispatch(deselectAnnotation());
|
|
656
1998
|
this.dispatch(deleteAnnotation(pageIndex, id));
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
1999
|
+
this.events$.emit({
|
|
2000
|
+
type: "delete",
|
|
2001
|
+
annotation: originalAnnotation,
|
|
2002
|
+
pageIndex,
|
|
2003
|
+
committed: false
|
|
2004
|
+
});
|
|
2005
|
+
};
|
|
2006
|
+
if (!this.history) {
|
|
2007
|
+
execute();
|
|
2008
|
+
if (this.config.autoCommit !== false) this.commit();
|
|
660
2009
|
return;
|
|
661
2010
|
}
|
|
662
|
-
const originalAnnotation = this.state.byUid[id].object;
|
|
663
2011
|
const command = {
|
|
664
|
-
execute
|
|
665
|
-
|
|
666
|
-
this.dispatch(
|
|
667
|
-
|
|
668
|
-
|
|
2012
|
+
execute,
|
|
2013
|
+
undo: () => {
|
|
2014
|
+
this.dispatch(createAnnotation(pageIndex, originalAnnotation));
|
|
2015
|
+
this.events$.emit({
|
|
2016
|
+
type: "create",
|
|
2017
|
+
annotation: originalAnnotation,
|
|
2018
|
+
pageIndex,
|
|
2019
|
+
committed: false
|
|
2020
|
+
});
|
|
2021
|
+
}
|
|
669
2022
|
};
|
|
670
2023
|
this.history.register(command, this.ANNOTATION_HISTORY_TOPIC);
|
|
671
2024
|
}
|
|
2025
|
+
selectAnnotation(pageIndex, id) {
|
|
2026
|
+
this.dispatch(selectAnnotation(pageIndex, id));
|
|
2027
|
+
}
|
|
2028
|
+
getActiveTool() {
|
|
2029
|
+
if (!this.state.activeToolId) return null;
|
|
2030
|
+
return this.state.tools.find((t) => t.id === this.state.activeToolId) ?? null;
|
|
2031
|
+
}
|
|
2032
|
+
setActiveTool(toolId) {
|
|
2033
|
+
var _a, _b;
|
|
2034
|
+
if (toolId === this.state.activeToolId) return;
|
|
2035
|
+
const tool = this.state.tools.find((t) => t.id === toolId);
|
|
2036
|
+
if (tool) {
|
|
2037
|
+
(_a = this.interactionManager) == null ? void 0 : _a.activate(tool.interaction.mode ?? tool.id);
|
|
2038
|
+
} else {
|
|
2039
|
+
(_b = this.interactionManager) == null ? void 0 : _b.activateDefaultMode();
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
getTool(toolId) {
|
|
2043
|
+
return this.state.tools.find((t) => t.id === toolId);
|
|
2044
|
+
}
|
|
2045
|
+
findToolForAnnotation(annotation) {
|
|
2046
|
+
let bestTool = null;
|
|
2047
|
+
let bestScore = 0;
|
|
2048
|
+
for (const tool of this.state.tools) {
|
|
2049
|
+
const score = tool.matchScore(annotation);
|
|
2050
|
+
if (score > bestScore) {
|
|
2051
|
+
bestScore = score;
|
|
2052
|
+
bestTool = tool;
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
return bestTool;
|
|
2056
|
+
}
|
|
672
2057
|
commit() {
|
|
673
2058
|
const task = new Task();
|
|
674
2059
|
if (!this.state.hasPendingChanges) return PdfTaskHelper.resolve(true);
|
|
@@ -687,12 +2072,29 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
687
2072
|
const ctx = this.pendingContexts.get(ta.object.id);
|
|
688
2073
|
const task2 = this.engine.createPageAnnotation(doc, page, ta.object, ctx);
|
|
689
2074
|
task2.wait(() => {
|
|
2075
|
+
this.events$.emit({
|
|
2076
|
+
type: "create",
|
|
2077
|
+
annotation: ta.object,
|
|
2078
|
+
pageIndex: ta.object.pageIndex,
|
|
2079
|
+
ctx,
|
|
2080
|
+
committed: true
|
|
2081
|
+
});
|
|
690
2082
|
this.pendingContexts.delete(ta.object.id);
|
|
691
2083
|
}, ignore);
|
|
692
2084
|
creations.push(task2);
|
|
693
2085
|
break;
|
|
694
2086
|
case "dirty":
|
|
695
|
-
|
|
2087
|
+
const updateTask = this.engine.updatePageAnnotation(doc, page, ta.object);
|
|
2088
|
+
updateTask.wait(() => {
|
|
2089
|
+
this.events$.emit({
|
|
2090
|
+
type: "update",
|
|
2091
|
+
annotation: ta.object,
|
|
2092
|
+
pageIndex: ta.object.pageIndex,
|
|
2093
|
+
patch: ta.object,
|
|
2094
|
+
committed: true
|
|
2095
|
+
});
|
|
2096
|
+
}, ignore);
|
|
2097
|
+
updates.push(updateTask);
|
|
696
2098
|
break;
|
|
697
2099
|
case "deleted":
|
|
698
2100
|
deletions.push({ ta, uid });
|
|
@@ -707,6 +2109,12 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
707
2109
|
const removeTask = this.engine.removePageAnnotation(doc, page, ta.object);
|
|
708
2110
|
removeTask.wait(() => {
|
|
709
2111
|
this.dispatch(purgeAnnotation(uid));
|
|
2112
|
+
this.events$.emit({
|
|
2113
|
+
type: "delete",
|
|
2114
|
+
annotation: ta.object,
|
|
2115
|
+
pageIndex: ta.object.pageIndex,
|
|
2116
|
+
committed: true
|
|
2117
|
+
});
|
|
710
2118
|
task2.resolve(true);
|
|
711
2119
|
}, task2.fail);
|
|
712
2120
|
deletionTasks.push(task2);
|
|
@@ -721,189 +2129,295 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
|
|
|
721
2129
|
}, task.fail);
|
|
722
2130
|
return task;
|
|
723
2131
|
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Gets the effective behavior setting for a tool, checking tool-specific config first,
|
|
2134
|
+
* then falling back to plugin config.
|
|
2135
|
+
*/
|
|
2136
|
+
getToolBehavior(tool, setting) {
|
|
2137
|
+
var _a;
|
|
2138
|
+
if (((_a = tool.behavior) == null ? void 0 : _a[setting]) !== void 0) {
|
|
2139
|
+
return tool.behavior[setting];
|
|
2140
|
+
}
|
|
2141
|
+
return this.config[setting] !== false;
|
|
2142
|
+
}
|
|
724
2143
|
};
|
|
725
2144
|
_AnnotationPlugin.id = "annotation";
|
|
726
2145
|
let AnnotationPlugin = _AnnotationPlugin;
|
|
727
|
-
const
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
"#000000",
|
|
737
|
-
"#FFFFFF"
|
|
738
|
-
];
|
|
739
|
-
const patchAnno = (state, uid, patch) => {
|
|
740
|
-
const prev = state.byUid[uid];
|
|
741
|
-
if (!prev) return state;
|
|
742
|
-
return {
|
|
743
|
-
...state,
|
|
744
|
-
byUid: {
|
|
745
|
-
...state.byUid,
|
|
746
|
-
[uid]: {
|
|
747
|
-
...prev,
|
|
748
|
-
commitState: prev.commitState === "synced" ? "dirty" : prev.commitState,
|
|
749
|
-
object: { ...prev.object, ...patch }
|
|
750
|
-
}
|
|
2146
|
+
const defaultTools = [
|
|
2147
|
+
// Text Markup Tools
|
|
2148
|
+
{
|
|
2149
|
+
id: "highlight",
|
|
2150
|
+
name: "Highlight",
|
|
2151
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.HIGHLIGHT ? 1 : 0,
|
|
2152
|
+
interaction: {
|
|
2153
|
+
exclusive: false,
|
|
2154
|
+
textSelection: true
|
|
751
2155
|
},
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
};
|
|
755
|
-
const initialState = (cfg) => ({
|
|
756
|
-
pages: {},
|
|
757
|
-
byUid: {},
|
|
758
|
-
selectedUid: null,
|
|
759
|
-
activeVariant: null,
|
|
760
|
-
toolDefaults: {
|
|
761
|
-
[makeVariantKey(PdfAnnotationSubtype.HIGHLIGHT)]: {
|
|
762
|
-
name: "Highlight",
|
|
763
|
-
subtype: PdfAnnotationSubtype.HIGHLIGHT,
|
|
764
|
-
interaction: { mode: "highlight", exclusive: false },
|
|
765
|
-
textSelection: true,
|
|
2156
|
+
defaults: {
|
|
2157
|
+
type: PdfAnnotationSubtype.HIGHLIGHT,
|
|
766
2158
|
color: "#FFCD45",
|
|
767
2159
|
opacity: 1,
|
|
768
2160
|
blendMode: PdfBlendMode.Multiply
|
|
2161
|
+
}
|
|
2162
|
+
},
|
|
2163
|
+
{
|
|
2164
|
+
id: "underline",
|
|
2165
|
+
name: "Underline",
|
|
2166
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.UNDERLINE ? 1 : 0,
|
|
2167
|
+
interaction: {
|
|
2168
|
+
exclusive: false,
|
|
2169
|
+
textSelection: true
|
|
769
2170
|
},
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
subtype: PdfAnnotationSubtype.UNDERLINE,
|
|
773
|
-
interaction: { mode: "underline", exclusive: false },
|
|
774
|
-
textSelection: true,
|
|
2171
|
+
defaults: {
|
|
2172
|
+
type: PdfAnnotationSubtype.UNDERLINE,
|
|
775
2173
|
color: "#E44234",
|
|
776
|
-
opacity: 1
|
|
777
|
-
|
|
2174
|
+
opacity: 1
|
|
2175
|
+
}
|
|
2176
|
+
},
|
|
2177
|
+
{
|
|
2178
|
+
id: "strikeout",
|
|
2179
|
+
name: "Strikeout",
|
|
2180
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.STRIKEOUT ? 1 : 0,
|
|
2181
|
+
interaction: {
|
|
2182
|
+
exclusive: false,
|
|
2183
|
+
textSelection: true
|
|
778
2184
|
},
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
subtype: PdfAnnotationSubtype.STRIKEOUT,
|
|
782
|
-
interaction: { mode: "strikeout", exclusive: false },
|
|
783
|
-
textSelection: true,
|
|
2185
|
+
defaults: {
|
|
2186
|
+
type: PdfAnnotationSubtype.STRIKEOUT,
|
|
784
2187
|
color: "#E44234",
|
|
785
|
-
opacity: 1
|
|
786
|
-
|
|
2188
|
+
opacity: 1
|
|
2189
|
+
}
|
|
2190
|
+
},
|
|
2191
|
+
{
|
|
2192
|
+
id: "squiggly",
|
|
2193
|
+
name: "Squiggly",
|
|
2194
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.SQUIGGLY ? 1 : 0,
|
|
2195
|
+
interaction: {
|
|
2196
|
+
exclusive: false,
|
|
2197
|
+
textSelection: true
|
|
787
2198
|
},
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
subtype: PdfAnnotationSubtype.SQUIGGLY,
|
|
791
|
-
interaction: { mode: "squiggly", exclusive: false },
|
|
792
|
-
textSelection: true,
|
|
2199
|
+
defaults: {
|
|
2200
|
+
type: PdfAnnotationSubtype.SQUIGGLY,
|
|
793
2201
|
color: "#E44234",
|
|
794
|
-
opacity: 1
|
|
795
|
-
|
|
2202
|
+
opacity: 1
|
|
2203
|
+
}
|
|
2204
|
+
},
|
|
2205
|
+
// Drawing Tools
|
|
2206
|
+
{
|
|
2207
|
+
id: "ink",
|
|
2208
|
+
name: "Pen",
|
|
2209
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.INK && a.intent !== "InkHighlight" ? 5 : 0,
|
|
2210
|
+
interaction: {
|
|
2211
|
+
exclusive: false,
|
|
2212
|
+
cursor: "crosshair"
|
|
796
2213
|
},
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
subtype: PdfAnnotationSubtype.INK,
|
|
800
|
-
interaction: { mode: "ink", exclusive: true, cursor: "crosshair" },
|
|
2214
|
+
defaults: {
|
|
2215
|
+
type: PdfAnnotationSubtype.INK,
|
|
801
2216
|
color: "#E44234",
|
|
802
2217
|
opacity: 1,
|
|
803
|
-
strokeWidth:
|
|
804
|
-
|
|
2218
|
+
strokeWidth: 6
|
|
2219
|
+
}
|
|
2220
|
+
},
|
|
2221
|
+
{
|
|
2222
|
+
id: "inkHighlighter",
|
|
2223
|
+
name: "Ink Highlighter",
|
|
2224
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.INK && a.intent === "InkHighlight" ? 10 : 0,
|
|
2225
|
+
interaction: {
|
|
2226
|
+
exclusive: false,
|
|
2227
|
+
cursor: "crosshair"
|
|
805
2228
|
},
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
subtype: PdfAnnotationSubtype.INK,
|
|
2229
|
+
defaults: {
|
|
2230
|
+
type: PdfAnnotationSubtype.INK,
|
|
809
2231
|
intent: "InkHighlight",
|
|
810
|
-
|
|
811
|
-
color: "#E44234",
|
|
2232
|
+
color: "#FFCD45",
|
|
812
2233
|
opacity: 1,
|
|
813
|
-
strokeWidth:
|
|
2234
|
+
strokeWidth: 14,
|
|
814
2235
|
blendMode: PdfBlendMode.Multiply
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
2236
|
+
}
|
|
2237
|
+
},
|
|
2238
|
+
// Shape Tools
|
|
2239
|
+
{
|
|
2240
|
+
id: "circle",
|
|
2241
|
+
name: "Circle",
|
|
2242
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.CIRCLE ? 1 : 0,
|
|
2243
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2244
|
+
defaults: {
|
|
2245
|
+
type: PdfAnnotationSubtype.CIRCLE,
|
|
820
2246
|
color: "transparent",
|
|
821
2247
|
opacity: 1,
|
|
822
|
-
strokeWidth:
|
|
2248
|
+
strokeWidth: 6,
|
|
823
2249
|
strokeColor: "#E44234",
|
|
824
2250
|
strokeStyle: PdfAnnotationBorderStyle.SOLID
|
|
825
2251
|
},
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
2252
|
+
clickBehavior: {
|
|
2253
|
+
enabled: true,
|
|
2254
|
+
defaultSize: { width: 100, height: 100 }
|
|
2255
|
+
}
|
|
2256
|
+
},
|
|
2257
|
+
{
|
|
2258
|
+
id: "square",
|
|
2259
|
+
name: "Square",
|
|
2260
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.SQUARE ? 1 : 0,
|
|
2261
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2262
|
+
defaults: {
|
|
2263
|
+
type: PdfAnnotationSubtype.SQUARE,
|
|
830
2264
|
color: "transparent",
|
|
831
2265
|
opacity: 1,
|
|
832
|
-
strokeWidth:
|
|
2266
|
+
strokeWidth: 6,
|
|
833
2267
|
strokeColor: "#E44234",
|
|
834
2268
|
strokeStyle: PdfAnnotationBorderStyle.SOLID
|
|
835
2269
|
},
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
2270
|
+
clickBehavior: {
|
|
2271
|
+
enabled: true,
|
|
2272
|
+
defaultSize: { width: 100, height: 100 }
|
|
2273
|
+
}
|
|
2274
|
+
},
|
|
2275
|
+
{
|
|
2276
|
+
id: "line",
|
|
2277
|
+
name: "Line",
|
|
2278
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.LINE && a.intent !== "LineArrow" ? 5 : 0,
|
|
2279
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2280
|
+
defaults: {
|
|
2281
|
+
type: PdfAnnotationSubtype.LINE,
|
|
840
2282
|
color: "transparent",
|
|
841
2283
|
opacity: 1,
|
|
842
|
-
strokeWidth:
|
|
843
|
-
strokeColor: "#E44234"
|
|
844
|
-
strokeStyle: PdfAnnotationBorderStyle.SOLID
|
|
2284
|
+
strokeWidth: 6,
|
|
2285
|
+
strokeColor: "#E44234"
|
|
845
2286
|
},
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
2287
|
+
clickBehavior: {
|
|
2288
|
+
enabled: true,
|
|
2289
|
+
defaultLength: 100,
|
|
2290
|
+
defaultAngle: 0
|
|
2291
|
+
}
|
|
2292
|
+
},
|
|
2293
|
+
{
|
|
2294
|
+
id: "lineArrow",
|
|
2295
|
+
name: "Arrow",
|
|
2296
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.LINE && a.intent === "LineArrow" ? 10 : 0,
|
|
2297
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2298
|
+
defaults: {
|
|
2299
|
+
type: PdfAnnotationSubtype.LINE,
|
|
851
2300
|
intent: "LineArrow",
|
|
2301
|
+
color: "transparent",
|
|
852
2302
|
opacity: 1,
|
|
853
|
-
strokeWidth:
|
|
2303
|
+
strokeWidth: 6,
|
|
854
2304
|
strokeColor: "#E44234",
|
|
855
|
-
strokeStyle: PdfAnnotationBorderStyle.SOLID,
|
|
856
2305
|
lineEndings: {
|
|
857
2306
|
start: PdfAnnotationLineEnding.None,
|
|
858
2307
|
end: PdfAnnotationLineEnding.OpenArrow
|
|
859
2308
|
}
|
|
860
2309
|
},
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
2310
|
+
clickBehavior: {
|
|
2311
|
+
enabled: true,
|
|
2312
|
+
defaultLength: 100,
|
|
2313
|
+
defaultAngle: 0
|
|
2314
|
+
}
|
|
2315
|
+
},
|
|
2316
|
+
{
|
|
2317
|
+
id: "polyline",
|
|
2318
|
+
name: "Polyline",
|
|
2319
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.POLYLINE ? 1 : 0,
|
|
2320
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2321
|
+
defaults: {
|
|
2322
|
+
type: PdfAnnotationSubtype.POLYLINE,
|
|
865
2323
|
color: "transparent",
|
|
866
2324
|
opacity: 1,
|
|
867
|
-
strokeWidth:
|
|
868
|
-
strokeColor: "#E44234"
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
2325
|
+
strokeWidth: 6,
|
|
2326
|
+
strokeColor: "#E44234"
|
|
2327
|
+
}
|
|
2328
|
+
},
|
|
2329
|
+
{
|
|
2330
|
+
id: "polygon",
|
|
2331
|
+
name: "Polygon",
|
|
2332
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.POLYGON ? 1 : 0,
|
|
2333
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2334
|
+
defaults: {
|
|
2335
|
+
type: PdfAnnotationSubtype.POLYGON,
|
|
875
2336
|
color: "transparent",
|
|
876
2337
|
opacity: 1,
|
|
877
|
-
strokeWidth:
|
|
878
|
-
strokeColor: "#E44234"
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
2338
|
+
strokeWidth: 6,
|
|
2339
|
+
strokeColor: "#E44234"
|
|
2340
|
+
}
|
|
2341
|
+
},
|
|
2342
|
+
// Text & Stamp
|
|
2343
|
+
{
|
|
2344
|
+
id: "freeText",
|
|
2345
|
+
name: "Free Text",
|
|
2346
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.FREETEXT ? 1 : 0,
|
|
2347
|
+
interaction: { exclusive: false, cursor: "crosshair" },
|
|
2348
|
+
defaults: {
|
|
2349
|
+
type: PdfAnnotationSubtype.FREETEXT,
|
|
2350
|
+
contents: "Insert text",
|
|
887
2351
|
fontSize: 14,
|
|
888
2352
|
fontColor: "#E44234",
|
|
889
|
-
content: "Insert text here",
|
|
890
2353
|
fontFamily: PdfStandardFont.Helvetica,
|
|
891
2354
|
textAlign: PdfTextAlignment.Left,
|
|
892
|
-
verticalAlign: PdfVerticalAlignment.Top
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
name: "Photo",
|
|
896
|
-
subtype: PdfAnnotationSubtype.STAMP,
|
|
897
|
-
interaction: { mode: "stamp", exclusive: true, cursor: "crosshair" }
|
|
2355
|
+
verticalAlign: PdfVerticalAlignment.Top,
|
|
2356
|
+
backgroundColor: "transparent",
|
|
2357
|
+
opacity: 1
|
|
898
2358
|
},
|
|
899
|
-
|
|
2359
|
+
clickBehavior: {
|
|
2360
|
+
enabled: true,
|
|
2361
|
+
defaultSize: { width: 100, height: 20 },
|
|
2362
|
+
defaultContent: "Insert text"
|
|
2363
|
+
}
|
|
900
2364
|
},
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
2365
|
+
{
|
|
2366
|
+
id: "stamp",
|
|
2367
|
+
name: "Image",
|
|
2368
|
+
matchScore: (a) => a.type === PdfAnnotationSubtype.STAMP ? 1 : 0,
|
|
2369
|
+
interaction: { exclusive: false, cursor: "copy" },
|
|
2370
|
+
defaults: {
|
|
2371
|
+
type: PdfAnnotationSubtype.STAMP
|
|
2372
|
+
// No imageSrc by default, which tells the UI to open a file picker
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
];
|
|
2376
|
+
const DEFAULT_COLORS = [
|
|
2377
|
+
"#E44234",
|
|
2378
|
+
"#FF8D00",
|
|
2379
|
+
"#FFCD45",
|
|
2380
|
+
"#5CC96E",
|
|
2381
|
+
"#25D2D1",
|
|
2382
|
+
"#597CE2",
|
|
2383
|
+
"#C544CE",
|
|
2384
|
+
"#7D2E25",
|
|
2385
|
+
"#000000",
|
|
2386
|
+
"#FFFFFF"
|
|
2387
|
+
];
|
|
2388
|
+
const patchAnno = (state, uid, patch) => {
|
|
2389
|
+
const prev = state.byUid[uid];
|
|
2390
|
+
if (!prev) return state;
|
|
2391
|
+
return {
|
|
2392
|
+
...state,
|
|
2393
|
+
byUid: {
|
|
2394
|
+
...state.byUid,
|
|
2395
|
+
[uid]: {
|
|
2396
|
+
...prev,
|
|
2397
|
+
commitState: prev.commitState === "synced" ? "dirty" : prev.commitState,
|
|
2398
|
+
object: { ...prev.object, ...patch }
|
|
2399
|
+
}
|
|
2400
|
+
},
|
|
2401
|
+
hasPendingChanges: true
|
|
2402
|
+
};
|
|
2403
|
+
};
|
|
2404
|
+
const initialState = (cfg) => {
|
|
2405
|
+
const toolMap = /* @__PURE__ */ new Map();
|
|
2406
|
+
defaultTools.forEach((t) => toolMap.set(t.id, t));
|
|
2407
|
+
(cfg.tools || []).forEach((t) => toolMap.set(t.id, t));
|
|
2408
|
+
return {
|
|
2409
|
+
pages: {},
|
|
2410
|
+
byUid: {},
|
|
2411
|
+
selectedUid: null,
|
|
2412
|
+
activeToolId: null,
|
|
2413
|
+
// `Array.from(toolMap.values())` now correctly returns `AnnotationTool[]`, which matches the state's type.
|
|
2414
|
+
tools: Array.from(toolMap.values()),
|
|
2415
|
+
colorPresets: cfg.colorPresets ?? DEFAULT_COLORS,
|
|
2416
|
+
hasPendingChanges: false
|
|
2417
|
+
};
|
|
2418
|
+
};
|
|
904
2419
|
const reducer = (state, action) => {
|
|
905
2420
|
switch (action.type) {
|
|
906
|
-
/* ───── bulk load from engine ───── */
|
|
907
2421
|
case SET_ANNOTATIONS: {
|
|
908
2422
|
const newPages = { ...state.pages };
|
|
909
2423
|
const newByUid = { ...state.byUid };
|
|
@@ -922,45 +2436,41 @@ const reducer = (state, action) => {
|
|
|
922
2436
|
}
|
|
923
2437
|
return { ...state, pages: newPages, byUid: newByUid };
|
|
924
2438
|
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
2439
|
+
case SET_ACTIVE_TOOL_ID:
|
|
2440
|
+
return { ...state, activeToolId: action.payload };
|
|
2441
|
+
case ADD_TOOL: {
|
|
2442
|
+
const toolMap = new Map(state.tools.map((t) => [t.id, t]));
|
|
2443
|
+
toolMap.set(action.payload.id, action.payload);
|
|
2444
|
+
return { ...state, tools: Array.from(toolMap.values()) };
|
|
2445
|
+
}
|
|
2446
|
+
case SET_TOOL_DEFAULTS: {
|
|
2447
|
+
const { toolId, patch } = action.payload;
|
|
929
2448
|
return {
|
|
930
2449
|
...state,
|
|
931
|
-
|
|
2450
|
+
tools: state.tools.map((tool) => {
|
|
2451
|
+
if (tool.id === toolId) {
|
|
2452
|
+
return { ...tool, defaults: { ...tool.defaults, ...patch } };
|
|
2453
|
+
}
|
|
2454
|
+
return tool;
|
|
2455
|
+
})
|
|
932
2456
|
};
|
|
2457
|
+
}
|
|
2458
|
+
case SELECT_ANNOTATION:
|
|
2459
|
+
return { ...state, selectedUid: action.payload.id };
|
|
933
2460
|
case DESELECT_ANNOTATION:
|
|
934
2461
|
return { ...state, selectedUid: null };
|
|
935
2462
|
case ADD_COLOR_PRESET:
|
|
936
2463
|
return state.colorPresets.includes(action.payload) ? state : { ...state, colorPresets: [...state.colorPresets, action.payload] };
|
|
937
|
-
case UPDATE_TOOL_DEFAULTS: {
|
|
938
|
-
const { variantKey, patch } = action.payload;
|
|
939
|
-
const prev = state.toolDefaults[variantKey];
|
|
940
|
-
if (!prev) return state;
|
|
941
|
-
return {
|
|
942
|
-
...state,
|
|
943
|
-
toolDefaults: {
|
|
944
|
-
...state.toolDefaults,
|
|
945
|
-
[variantKey]: { ...prev, ...patch }
|
|
946
|
-
}
|
|
947
|
-
};
|
|
948
|
-
}
|
|
949
|
-
/* ───── create ───── */
|
|
950
2464
|
case CREATE_ANNOTATION: {
|
|
951
2465
|
const { pageIndex, annotation } = action.payload;
|
|
952
2466
|
const uid = annotation.id;
|
|
953
2467
|
return {
|
|
954
2468
|
...state,
|
|
955
2469
|
pages: { ...state.pages, [pageIndex]: [...state.pages[pageIndex] ?? [], uid] },
|
|
956
|
-
byUid: {
|
|
957
|
-
...state.byUid,
|
|
958
|
-
[uid]: { commitState: "new", object: annotation }
|
|
959
|
-
},
|
|
2470
|
+
byUid: { ...state.byUid, [uid]: { commitState: "new", object: annotation } },
|
|
960
2471
|
hasPendingChanges: true
|
|
961
2472
|
};
|
|
962
2473
|
}
|
|
963
|
-
/* ───── delete ───── */
|
|
964
2474
|
case DELETE_ANNOTATION: {
|
|
965
2475
|
const { pageIndex, id: uid } = action.payload;
|
|
966
2476
|
if (!state.byUid[uid]) return state;
|
|
@@ -977,12 +2487,8 @@ const reducer = (state, action) => {
|
|
|
977
2487
|
hasPendingChanges: true
|
|
978
2488
|
};
|
|
979
2489
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
const uid = action.payload.id;
|
|
983
|
-
return patchAnno(state, uid, action.payload.patch);
|
|
984
|
-
}
|
|
985
|
-
/* ───── commit bookkeeping ───── */
|
|
2490
|
+
case PATCH_ANNOTATION:
|
|
2491
|
+
return patchAnno(state, action.payload.id, action.payload.patch);
|
|
986
2492
|
case COMMIT_PENDING_CHANGES: {
|
|
987
2493
|
const cleaned = {};
|
|
988
2494
|
for (const [uid, ta] of Object.entries(state.byUid)) {
|
|
@@ -1002,6 +2508,24 @@ const reducer = (state, action) => {
|
|
|
1002
2508
|
return state;
|
|
1003
2509
|
}
|
|
1004
2510
|
};
|
|
2511
|
+
function createToolPredicate(id) {
|
|
2512
|
+
return (tool) => {
|
|
2513
|
+
return (tool == null ? void 0 : tool.id) === id;
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
const isHighlightTool = createToolPredicate("highlight");
|
|
2517
|
+
const isSquigglyTool = createToolPredicate("squiggly");
|
|
2518
|
+
const isUnderlineTool = createToolPredicate("underline");
|
|
2519
|
+
const isStrikeoutTool = createToolPredicate("strikeout");
|
|
2520
|
+
const isInkTool = createToolPredicate("ink");
|
|
2521
|
+
const isInkHighlighterTool = createToolPredicate("inkHighlighter");
|
|
2522
|
+
const isSquareTool = createToolPredicate("square");
|
|
2523
|
+
const isCircleTool = createToolPredicate("circle");
|
|
2524
|
+
const isLineTool = createToolPredicate("line");
|
|
2525
|
+
const isPolylineTool = createToolPredicate("polyline");
|
|
2526
|
+
const isPolygonTool = createToolPredicate("polygon");
|
|
2527
|
+
const isFreeTextTool = createToolPredicate("freeText");
|
|
2528
|
+
const isStampTool = createToolPredicate("stamp");
|
|
1005
2529
|
const AnnotationPluginPackage = {
|
|
1006
2530
|
manifest,
|
|
1007
2531
|
create: (registry, config) => new AnnotationPlugin(ANNOTATION_PLUGIN_ID, registry, config),
|
|
@@ -1012,40 +2536,44 @@ export {
|
|
|
1012
2536
|
ANNOTATION_PLUGIN_ID,
|
|
1013
2537
|
AnnotationPlugin,
|
|
1014
2538
|
AnnotationPluginPackage,
|
|
2539
|
+
createToolPredicate,
|
|
1015
2540
|
getAnnotations,
|
|
1016
2541
|
getAnnotationsByPageIndex,
|
|
1017
2542
|
getSelectedAnnotation,
|
|
1018
2543
|
getSelectedAnnotationByPageIndex,
|
|
1019
|
-
getSelectedAnnotationVariant,
|
|
1020
2544
|
getSidebarAnnotationsWithReplies,
|
|
1021
2545
|
getSidebarAnnotationsWithRepliesGroupedByPage,
|
|
1022
|
-
|
|
2546
|
+
getToolDefaultsById,
|
|
1023
2547
|
isAnnotationSelected,
|
|
1024
2548
|
isCircle,
|
|
2549
|
+
isCircleTool,
|
|
1025
2550
|
isFreeText,
|
|
2551
|
+
isFreeTextTool,
|
|
1026
2552
|
isHighlight,
|
|
1027
|
-
|
|
1028
|
-
isInAnnotationVariant,
|
|
2553
|
+
isHighlightTool,
|
|
1029
2554
|
isInk,
|
|
2555
|
+
isInkHighlighterTool,
|
|
2556
|
+
isInkTool,
|
|
1030
2557
|
isLine,
|
|
2558
|
+
isLineTool,
|
|
1031
2559
|
isPolygon,
|
|
2560
|
+
isPolygonTool,
|
|
1032
2561
|
isPolyline,
|
|
2562
|
+
isPolylineTool,
|
|
1033
2563
|
isSidebarAnnotation,
|
|
1034
2564
|
isSquare,
|
|
2565
|
+
isSquareTool,
|
|
1035
2566
|
isSquiggly,
|
|
1036
|
-
|
|
2567
|
+
isSquigglyTool,
|
|
1037
2568
|
isStamp,
|
|
2569
|
+
isStampTool,
|
|
1038
2570
|
isStrikeout,
|
|
1039
|
-
|
|
2571
|
+
isStrikeoutTool,
|
|
1040
2572
|
isText,
|
|
1041
2573
|
isTextMarkup,
|
|
1042
|
-
isTextMarkupDefaults,
|
|
1043
2574
|
isUnderline,
|
|
1044
|
-
|
|
1045
|
-
makeVariantKey,
|
|
2575
|
+
isUnderlineTool,
|
|
1046
2576
|
manifest,
|
|
1047
|
-
|
|
1048
|
-
index as patching,
|
|
1049
|
-
variantKeyFromAnnotation
|
|
2577
|
+
index as patching
|
|
1050
2578
|
};
|
|
1051
2579
|
//# sourceMappingURL=index.js.map
|