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