kviewer 0.0.10 → 0.0.11
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/README.md +29 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +19 -0
- package/dist/runtime/annotation/checkbox-styles.d.ts +19 -0
- package/dist/runtime/annotation/checkbox-styles.js +27 -0
- package/dist/runtime/annotation/engine/config.js +44 -0
- package/dist/runtime/annotation/engine/painter.d.ts +4 -1
- package/dist/runtime/annotation/engine/painter.js +26 -1
- package/dist/runtime/annotation/engine/tools/form-field.d.ts +24 -0
- package/dist/runtime/annotation/engine/tools/form-field.js +117 -0
- package/dist/runtime/annotation/engine/types.d.ts +54 -1
- package/dist/runtime/annotation/engine/types.js +4 -0
- package/dist/runtime/annotation/font-style.d.ts +23 -0
- package/dist/runtime/annotation/font-style.js +57 -0
- package/dist/runtime/annotation/parsers/extractCheckboxStyles.d.ts +21 -0
- package/dist/runtime/annotation/parsers/extractCheckboxStyles.js +75 -0
- package/dist/runtime/annotation/parsers/parseFormFields.js +16 -3
- package/dist/runtime/annotation/pdf-export/export-form-fields.d.ts +8 -5
- package/dist/runtime/annotation/pdf-export/export-form-fields.js +245 -1
- package/dist/runtime/annotation/pdf-export/export.d.ts +3 -2
- package/dist/runtime/annotation/pdf-export/export.js +9 -2
- package/dist/runtime/assets/kviewer.css +1 -1
- package/dist/runtime/components/FormFieldLayer.d.vue.ts +5 -0
- package/dist/runtime/components/FormFieldLayer.vue +40 -3
- package/dist/runtime/components/FormFieldLayer.vue.d.ts +5 -0
- package/dist/runtime/components/PdfPage.vue +24 -0
- package/dist/runtime/components/Viewer.d.vue.ts +18 -3
- package/dist/runtime/components/Viewer.vue +66 -7
- package/dist/runtime/components/Viewer.vue.d.ts +18 -3
- package/dist/runtime/components/ViewerBar.vue +24 -2
- package/dist/runtime/components/form-fields/FormButton.vue +16 -4
- package/dist/runtime/components/form-fields/FormCheckbox.vue +31 -15
- package/dist/runtime/components/form-fields/FormDropdown.vue +3 -1
- package/dist/runtime/components/form-fields/FormFieldWrapper.d.vue.ts +12 -1
- package/dist/runtime/components/form-fields/FormFieldWrapper.vue +45 -9
- package/dist/runtime/components/form-fields/FormFieldWrapper.vue.d.ts +12 -1
- package/dist/runtime/components/form-fields/FormRadioButton.vue +3 -1
- package/dist/runtime/components/form-fields/FormSignatureField.vue +2 -1
- package/dist/runtime/components/form-fields/FormTextField.vue +47 -7
- package/dist/runtime/components/form-fields/PlacedFieldChrome.d.vue.ts +16 -0
- package/dist/runtime/components/form-fields/PlacedFieldChrome.vue +131 -0
- package/dist/runtime/components/form-fields/PlacedFieldChrome.vue.d.ts +16 -0
- package/dist/runtime/components/modals/SignatureDrawModal.vue +70 -15
- package/dist/runtime/components/panels/PlacedFieldSidebar.d.vue.ts +3 -0
- package/dist/runtime/components/panels/PlacedFieldSidebar.vue +505 -0
- package/dist/runtime/components/panels/PlacedFieldSidebar.vue.d.ts +3 -0
- package/dist/runtime/components/tools/FormFieldTools.d.vue.ts +3 -0
- package/dist/runtime/components/tools/FormFieldTools.vue +35 -0
- package/dist/runtime/components/tools/FormFieldTools.vue.d.ts +3 -0
- package/dist/runtime/composables/useAnnotationEngine.d.ts +1 -0
- package/dist/runtime/composables/useAnnotationEngine.js +2 -1
- package/dist/runtime/composables/useFormFields.d.ts +29 -2
- package/dist/runtime/composables/useFormFields.js +259 -5
- package/dist/runtime/composables/useInertiaPanzoom.js +3 -0
- package/dist/runtime/composables/usePageVirtualization.d.ts +6 -0
- package/dist/runtime/composables/usePageVirtualization.js +11 -3
- package/dist/runtime/composables/useViewerState.d.ts +3 -0
- package/dist/runtime/composables/useViewerState.js +22 -1
- package/package.json +2 -2
|
@@ -1,18 +1,92 @@
|
|
|
1
1
|
import {
|
|
2
2
|
shallowRef,
|
|
3
|
+
ref,
|
|
3
4
|
triggerRef,
|
|
4
5
|
provide,
|
|
5
6
|
inject
|
|
6
7
|
} from "vue";
|
|
7
8
|
import { parseFormFields } from "../annotation/parsers/parseFormFields.js";
|
|
9
|
+
import { generateUUID } from "../annotation/engine/utils.js";
|
|
8
10
|
const FORM_FIELDS_KEY = Symbol("kviewer-form-fields");
|
|
9
11
|
export function provideFormFields() {
|
|
10
12
|
const fieldDefinitions = shallowRef(/* @__PURE__ */ new Map());
|
|
11
13
|
const fieldValues = shallowRef(/* @__PURE__ */ new Map());
|
|
14
|
+
const selectedPlacedFieldId = ref(null);
|
|
15
|
+
function selectPlacedField(id) {
|
|
16
|
+
selectedPlacedFieldId.value = id;
|
|
17
|
+
}
|
|
18
|
+
function getFieldById(id) {
|
|
19
|
+
for (const defs of fieldDefinitions.value.values()) {
|
|
20
|
+
for (const d of defs) {
|
|
21
|
+
if (d.id === id) return d;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
let checkboxStyleMap = null;
|
|
27
|
+
let buttonCaptionMap = null;
|
|
28
|
+
function applyCheckboxStyles(styles) {
|
|
29
|
+
checkboxStyleMap = styles;
|
|
30
|
+
let changed = false;
|
|
31
|
+
for (const [page, defs] of fieldDefinitions.value.entries()) {
|
|
32
|
+
let pageChanged = false;
|
|
33
|
+
const next = defs.map((d) => {
|
|
34
|
+
if (d.fieldType !== "checkbox" || d.origin !== "parsed") return d;
|
|
35
|
+
const style = styles.get(d.fieldName);
|
|
36
|
+
if (!style) return d;
|
|
37
|
+
if (d.originalCheckboxStyle) return d;
|
|
38
|
+
pageChanged = true;
|
|
39
|
+
return { ...d, checkboxStyle: d.checkboxStyle ?? style, originalCheckboxStyle: style };
|
|
40
|
+
});
|
|
41
|
+
if (pageChanged) {
|
|
42
|
+
fieldDefinitions.value.set(page, next);
|
|
43
|
+
changed = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (changed) triggerRef(fieldDefinitions);
|
|
47
|
+
}
|
|
48
|
+
function applyButtonCaptions(captions) {
|
|
49
|
+
buttonCaptionMap = captions;
|
|
50
|
+
let changed = false;
|
|
51
|
+
for (const [page, defs] of fieldDefinitions.value.entries()) {
|
|
52
|
+
let pageChanged = false;
|
|
53
|
+
const next = defs.map((d) => {
|
|
54
|
+
if (d.fieldType !== "button" || d.origin !== "parsed") return d;
|
|
55
|
+
const caption = captions.get(d.fieldName);
|
|
56
|
+
if (!caption) return d;
|
|
57
|
+
if (d.buttonLabel === caption) return d;
|
|
58
|
+
pageChanged = true;
|
|
59
|
+
return { ...d, buttonLabel: caption };
|
|
60
|
+
});
|
|
61
|
+
if (pageChanged) {
|
|
62
|
+
fieldDefinitions.value.set(page, next);
|
|
63
|
+
changed = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (changed) triggerRef(fieldDefinitions);
|
|
67
|
+
}
|
|
12
68
|
function parsePageFields(pageNumber, rawAnnotations) {
|
|
13
69
|
if (fieldDefinitions.value.has(pageNumber)) return;
|
|
14
70
|
const defs = parseFormFields(rawAnnotations, pageNumber);
|
|
15
71
|
if (defs.length === 0) return;
|
|
72
|
+
if (checkboxStyleMap) {
|
|
73
|
+
for (const def of defs) {
|
|
74
|
+
if (def.fieldType === "checkbox" && !def.checkboxStyle) {
|
|
75
|
+
const style = checkboxStyleMap.get(def.fieldName);
|
|
76
|
+
if (style) {
|
|
77
|
+
def.checkboxStyle = style;
|
|
78
|
+
def.originalCheckboxStyle = style;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (buttonCaptionMap) {
|
|
84
|
+
for (const def of defs) {
|
|
85
|
+
if (def.fieldType !== "button") continue;
|
|
86
|
+
const caption = buttonCaptionMap.get(def.fieldName);
|
|
87
|
+
if (caption) def.buttonLabel = caption;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
16
90
|
fieldDefinitions.value.set(pageNumber, defs);
|
|
17
91
|
triggerRef(fieldDefinitions);
|
|
18
92
|
for (const def of defs) {
|
|
@@ -30,11 +104,19 @@ export function provideFormFields() {
|
|
|
30
104
|
const existing = fieldValues.value.get(fieldId);
|
|
31
105
|
if (!existing) return;
|
|
32
106
|
existing.value = value;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
fv.
|
|
107
|
+
const { fieldName, fieldType } = existing;
|
|
108
|
+
if (fieldName) {
|
|
109
|
+
if (fieldType === "radio" && typeof value === "string" && value !== "") {
|
|
110
|
+
for (const [id, fv] of fieldValues.value.entries()) {
|
|
111
|
+
if (id !== fieldId && fv.fieldName === fieldName && fv.fieldType === "radio") {
|
|
112
|
+
fv.value = "";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} else if (fieldType !== "radio") {
|
|
116
|
+
for (const [id, fv] of fieldValues.value.entries()) {
|
|
117
|
+
if (id !== fieldId && fv.fieldName === fieldName && fv.fieldType === fieldType) {
|
|
118
|
+
fv.value = value;
|
|
119
|
+
}
|
|
38
120
|
}
|
|
39
121
|
}
|
|
40
122
|
}
|
|
@@ -97,6 +179,7 @@ export function provideFormFields() {
|
|
|
97
179
|
rect: [pdfX1, pdfY1, pdfX2, pdfY2],
|
|
98
180
|
readOnly: false,
|
|
99
181
|
required: false,
|
|
182
|
+
origin: "detected",
|
|
100
183
|
exportValue: "Yes",
|
|
101
184
|
defaultValue: "Off",
|
|
102
185
|
shapeType: s.shapeType
|
|
@@ -115,6 +198,164 @@ export function provideFormFields() {
|
|
|
115
198
|
}
|
|
116
199
|
triggerRef(fieldValues);
|
|
117
200
|
}
|
|
201
|
+
function nextPlacedFieldName(fieldType) {
|
|
202
|
+
const base = fieldType === "text" ? "Text" : fieldType === "checkbox" ? "Checkbox" : fieldType === "signature" ? "Signature" : fieldType === "dropdown" ? "Dropdown" : fieldType === "radio" ? "Radio" : "Field";
|
|
203
|
+
const existing = /* @__PURE__ */ new Set();
|
|
204
|
+
for (const defs of fieldDefinitions.value.values()) {
|
|
205
|
+
for (const d of defs) existing.add(d.fieldName);
|
|
206
|
+
}
|
|
207
|
+
let n = 1;
|
|
208
|
+
while (existing.has(`${base}_${n}`)) n += 1;
|
|
209
|
+
return `${base}_${n}`;
|
|
210
|
+
}
|
|
211
|
+
function placedDefaultValue(fieldType) {
|
|
212
|
+
if (fieldType === "checkbox") return false;
|
|
213
|
+
return "";
|
|
214
|
+
}
|
|
215
|
+
function addPlacedField(payload) {
|
|
216
|
+
const id = `placed-${generateUUID()}`;
|
|
217
|
+
let fieldName;
|
|
218
|
+
if (payload.fieldType === "radio" && selectedPlacedFieldId.value) {
|
|
219
|
+
const sel = getFieldById(selectedPlacedFieldId.value);
|
|
220
|
+
fieldName = sel && sel.fieldType === "radio" ? sel.fieldName : nextPlacedFieldName(payload.fieldType);
|
|
221
|
+
} else {
|
|
222
|
+
fieldName = nextPlacedFieldName(payload.fieldType);
|
|
223
|
+
}
|
|
224
|
+
const def = {
|
|
225
|
+
id,
|
|
226
|
+
pageNumber: payload.pageNumber,
|
|
227
|
+
fieldType: payload.fieldType,
|
|
228
|
+
fieldName,
|
|
229
|
+
rect: [...payload.rectPdf],
|
|
230
|
+
readOnly: false,
|
|
231
|
+
required: false,
|
|
232
|
+
origin: "placed"
|
|
233
|
+
};
|
|
234
|
+
if (payload.fieldType === "radio") {
|
|
235
|
+
def.buttonValue = nextRadioOptionValue(fieldName);
|
|
236
|
+
}
|
|
237
|
+
if (payload.fieldType === "checkbox") {
|
|
238
|
+
def.checkboxStyle = "check";
|
|
239
|
+
}
|
|
240
|
+
if (payload.fieldType === "dropdown") {
|
|
241
|
+
def.combo = true;
|
|
242
|
+
def.options = [{ exportValue: "Option 1", displayValue: "Option 1" }];
|
|
243
|
+
}
|
|
244
|
+
const existingDefs = fieldDefinitions.value.get(payload.pageNumber) ?? [];
|
|
245
|
+
fieldDefinitions.value.set(payload.pageNumber, [...existingDefs, def]);
|
|
246
|
+
triggerRef(fieldDefinitions);
|
|
247
|
+
fieldValues.value.set(id, {
|
|
248
|
+
fieldId: id,
|
|
249
|
+
fieldName: def.fieldName,
|
|
250
|
+
fieldType: def.fieldType,
|
|
251
|
+
value: placedDefaultValue(def.fieldType)
|
|
252
|
+
});
|
|
253
|
+
triggerRef(fieldValues);
|
|
254
|
+
if (payload.fieldType === "radio") {
|
|
255
|
+
selectedPlacedFieldId.value = id;
|
|
256
|
+
}
|
|
257
|
+
return def;
|
|
258
|
+
}
|
|
259
|
+
function nextRadioOptionValue(groupName) {
|
|
260
|
+
const used = /* @__PURE__ */ new Set();
|
|
261
|
+
for (const defs of fieldDefinitions.value.values()) {
|
|
262
|
+
for (const d of defs) {
|
|
263
|
+
if (d.fieldType === "radio" && d.fieldName === groupName && d.buttonValue) {
|
|
264
|
+
used.add(d.buttonValue);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
let n = 1;
|
|
269
|
+
while (used.has(`Option_${n}`)) n += 1;
|
|
270
|
+
return `Option_${n}`;
|
|
271
|
+
}
|
|
272
|
+
function updatePlacedField(id, patch) {
|
|
273
|
+
let found;
|
|
274
|
+
for (const [page, defs] of fieldDefinitions.value.entries()) {
|
|
275
|
+
const idx = defs.findIndex((d) => d.id === id);
|
|
276
|
+
if (idx === -1) continue;
|
|
277
|
+
const existing = defs[idx];
|
|
278
|
+
const next = { ...existing, ...patch, id: existing.id };
|
|
279
|
+
const nextDefs = defs.slice();
|
|
280
|
+
nextDefs[idx] = next;
|
|
281
|
+
fieldDefinitions.value.set(page, nextDefs);
|
|
282
|
+
found = next;
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
if (!found) return;
|
|
286
|
+
triggerRef(fieldDefinitions);
|
|
287
|
+
const fv = fieldValues.value.get(id);
|
|
288
|
+
if (fv && (fv.fieldName !== found.fieldName || fv.fieldType !== found.fieldType)) {
|
|
289
|
+
fv.fieldName = found.fieldName;
|
|
290
|
+
fv.fieldType = found.fieldType;
|
|
291
|
+
triggerRef(fieldValues);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function removePlacedField(id) {
|
|
295
|
+
let removed = false;
|
|
296
|
+
for (const [page, defs] of fieldDefinitions.value.entries()) {
|
|
297
|
+
const idx = defs.findIndex((d) => d.id === id);
|
|
298
|
+
if (idx === -1) continue;
|
|
299
|
+
const nextDefs = defs.slice();
|
|
300
|
+
nextDefs.splice(idx, 1);
|
|
301
|
+
if (nextDefs.length === 0) {
|
|
302
|
+
fieldDefinitions.value.delete(page);
|
|
303
|
+
} else {
|
|
304
|
+
fieldDefinitions.value.set(page, nextDefs);
|
|
305
|
+
}
|
|
306
|
+
removed = true;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
if (!removed) return;
|
|
310
|
+
triggerRef(fieldDefinitions);
|
|
311
|
+
if (fieldValues.value.delete(id)) {
|
|
312
|
+
triggerRef(fieldValues);
|
|
313
|
+
}
|
|
314
|
+
if (selectedPlacedFieldId.value === id) {
|
|
315
|
+
selectedPlacedFieldId.value = null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function getPlacedFields() {
|
|
319
|
+
const out = [];
|
|
320
|
+
for (const defs of fieldDefinitions.value.values()) {
|
|
321
|
+
for (const d of defs) {
|
|
322
|
+
if (d.origin === "placed" || d.origin === "detected") {
|
|
323
|
+
out.push(d);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const rectMoved = d.originalRect && rectChanged(d.rect, d.originalRect);
|
|
327
|
+
const styleChanged = d.fieldType === "checkbox" && (d.checkboxStyle ?? "check") !== (d.originalCheckboxStyle ?? "check");
|
|
328
|
+
if (rectMoved || styleChanged) {
|
|
329
|
+
out.push(d);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return out;
|
|
334
|
+
}
|
|
335
|
+
function rectChanged(a, b) {
|
|
336
|
+
for (let i = 0; i < 4; i++) {
|
|
337
|
+
if (Math.abs((a[i] ?? 0) - (b[i] ?? 0)) > 0.01) return true;
|
|
338
|
+
}
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
function isFieldLocked(fieldId) {
|
|
342
|
+
const target = getFieldById(fieldId);
|
|
343
|
+
if (!target) return false;
|
|
344
|
+
for (const defs of fieldDefinitions.value.values()) {
|
|
345
|
+
for (const sig of defs) {
|
|
346
|
+
if (sig.fieldType !== "signature") continue;
|
|
347
|
+
if (!sig.lockAction) continue;
|
|
348
|
+
if (sig.id === fieldId) continue;
|
|
349
|
+
const fv = fieldValues.value.get(sig.id);
|
|
350
|
+
if (!fv || typeof fv.value !== "string" || fv.value === "") continue;
|
|
351
|
+
if (sig.lockAction === "all") return true;
|
|
352
|
+
const list = sig.lockFieldNames ?? [];
|
|
353
|
+
if (sig.lockAction === "include" && list.includes(target.fieldName)) return true;
|
|
354
|
+
if (sig.lockAction === "exclude" && !list.includes(target.fieldName)) return true;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
118
359
|
function resetValues() {
|
|
119
360
|
for (const [, defs] of fieldDefinitions.value.entries()) {
|
|
120
361
|
for (const def of defs) {
|
|
@@ -129,6 +370,9 @@ export function provideFormFields() {
|
|
|
129
370
|
function reset() {
|
|
130
371
|
fieldDefinitions.value = /* @__PURE__ */ new Map();
|
|
131
372
|
fieldValues.value = /* @__PURE__ */ new Map();
|
|
373
|
+
selectedPlacedFieldId.value = null;
|
|
374
|
+
checkboxStyleMap = null;
|
|
375
|
+
buttonCaptionMap = null;
|
|
132
376
|
triggerRef(fieldDefinitions);
|
|
133
377
|
triggerRef(fieldValues);
|
|
134
378
|
}
|
|
@@ -142,6 +386,16 @@ export function provideFormFields() {
|
|
|
142
386
|
getAllFieldValues,
|
|
143
387
|
setFieldValueByName,
|
|
144
388
|
registerDetectedCheckboxes,
|
|
389
|
+
addPlacedField,
|
|
390
|
+
updatePlacedField,
|
|
391
|
+
removePlacedField,
|
|
392
|
+
getPlacedFields,
|
|
393
|
+
getFieldById,
|
|
394
|
+
selectedPlacedFieldId,
|
|
395
|
+
selectPlacedField,
|
|
396
|
+
applyCheckboxStyles,
|
|
397
|
+
applyButtonCaptions,
|
|
398
|
+
isFieldLocked,
|
|
145
399
|
resetValues,
|
|
146
400
|
reset
|
|
147
401
|
};
|
|
@@ -425,6 +425,9 @@ export function useInertiaPanzoom(options = {}) {
|
|
|
425
425
|
pinchStart = null;
|
|
426
426
|
panStart = null;
|
|
427
427
|
setWillChangeActive(false);
|
|
428
|
+
const b = getBounds();
|
|
429
|
+
tx = Math.max(b.minX, Math.min(b.maxX, tx));
|
|
430
|
+
ty = Math.max(b.minY, Math.min(b.maxY, ty));
|
|
428
431
|
apply();
|
|
429
432
|
},
|
|
430
433
|
stop: () => {
|
|
@@ -4,6 +4,12 @@ export interface PageMeta {
|
|
|
4
4
|
pageNumber: number;
|
|
5
5
|
width: number;
|
|
6
6
|
height: number;
|
|
7
|
+
/** PDF user-space origin of the page's visible area (`view[0]`, `view[1]`).
|
|
8
|
+
* Almost always (0, 0); non-zero for PDFs whose MediaBox has been
|
|
9
|
+
* shifted. Annotations in `/Rect` are in default user space, so any
|
|
10
|
+
* layer drawn at the canvas top-left must subtract this origin. */
|
|
11
|
+
viewOffsetX: number;
|
|
12
|
+
viewOffsetY: number;
|
|
7
13
|
}
|
|
8
14
|
export interface PageVirtualization {
|
|
9
15
|
pageMetas: ShallowRef<PageMeta[]>;
|
|
@@ -120,10 +120,16 @@ export function createPageVirtualization() {
|
|
|
120
120
|
async function fetchPageDimensions(doc, pageNumber) {
|
|
121
121
|
const proxy = await doc.getPage(pageNumber);
|
|
122
122
|
const view = proxy.view;
|
|
123
|
+
const vx = view[0] ?? 0;
|
|
124
|
+
const vy = view[1] ?? 0;
|
|
125
|
+
const vw = view[2] ?? 0;
|
|
126
|
+
const vh = view[3] ?? 0;
|
|
123
127
|
return {
|
|
124
128
|
pageNumber,
|
|
125
|
-
width:
|
|
126
|
-
height:
|
|
129
|
+
width: vw - vx,
|
|
130
|
+
height: vh - vy,
|
|
131
|
+
viewOffsetX: vx,
|
|
132
|
+
viewOffsetY: vy
|
|
127
133
|
};
|
|
128
134
|
}
|
|
129
135
|
async function init(doc, root) {
|
|
@@ -139,7 +145,9 @@ export function createPageVirtualization() {
|
|
|
139
145
|
metas.push({
|
|
140
146
|
pageNumber: i,
|
|
141
147
|
width: firstMeta.width,
|
|
142
|
-
height: firstMeta.height
|
|
148
|
+
height: firstMeta.height,
|
|
149
|
+
viewOffsetX: firstMeta.viewOffsetX,
|
|
150
|
+
viewOffsetY: firstMeta.viewOffsetY
|
|
143
151
|
});
|
|
144
152
|
}
|
|
145
153
|
}
|
|
@@ -57,6 +57,9 @@ export interface ViewerState {
|
|
|
57
57
|
history: AnnotationHistory;
|
|
58
58
|
readonly: Ref<boolean>;
|
|
59
59
|
shapeDetection: Ref<boolean>;
|
|
60
|
+
visualZoom: Ref<number>;
|
|
61
|
+
formEditMode: Ref<boolean>;
|
|
62
|
+
setFormEditMode: (enabled: boolean) => void;
|
|
60
63
|
}
|
|
61
64
|
export interface ViewerStateProvider {
|
|
62
65
|
state: ViewerState;
|
|
@@ -65,7 +65,22 @@ export function provideViewerState() {
|
|
|
65
65
|
}
|
|
66
66
|
const readonly = ref(false);
|
|
67
67
|
const shapeDetectionEnabled = ref(false);
|
|
68
|
+
const visualZoom = ref(1);
|
|
68
69
|
const stylusMode = ref(false);
|
|
70
|
+
const formEditMode = ref(false);
|
|
71
|
+
function isFormFieldTool(t) {
|
|
72
|
+
return typeof t === "number" && (t === AnnotationType.FORM_TEXT || t === AnnotationType.FORM_CHECKBOX || t === AnnotationType.FORM_RADIO || t === AnnotationType.FORM_SIGNATURE);
|
|
73
|
+
}
|
|
74
|
+
function setFormEditMode(enabled) {
|
|
75
|
+
if (formEditMode.value === enabled) return;
|
|
76
|
+
formEditMode.value = enabled;
|
|
77
|
+
const t = activeTool.value;
|
|
78
|
+
if (enabled) {
|
|
79
|
+
if (typeof t === "number" && !isFormFieldTool(t)) selectTool("hand");
|
|
80
|
+
} else {
|
|
81
|
+
if (isFormFieldTool(t)) selectTool("hand");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
69
84
|
function setStylusMode(enabled) {
|
|
70
85
|
stylusMode.value = enabled;
|
|
71
86
|
if (painter.value) {
|
|
@@ -95,6 +110,9 @@ export function provideViewerState() {
|
|
|
95
110
|
}
|
|
96
111
|
function selectTool(tool, dataTransfer) {
|
|
97
112
|
if (readonly.value && tool !== "hand") return;
|
|
113
|
+
if (isFormFieldTool(tool) && !formEditMode.value) {
|
|
114
|
+
formEditMode.value = true;
|
|
115
|
+
}
|
|
98
116
|
activeTool.value = tool;
|
|
99
117
|
selectedAnnotation.value = null;
|
|
100
118
|
selectedAnnotations.value = [];
|
|
@@ -181,7 +199,10 @@ export function provideViewerState() {
|
|
|
181
199
|
downloadPdf,
|
|
182
200
|
history,
|
|
183
201
|
readonly,
|
|
184
|
-
shapeDetection: shapeDetectionEnabled
|
|
202
|
+
shapeDetection: shapeDetectionEnabled,
|
|
203
|
+
visualZoom,
|
|
204
|
+
formEditMode,
|
|
205
|
+
setFormEditMode
|
|
185
206
|
};
|
|
186
207
|
provide(VIEWER_STATE_KEY, state);
|
|
187
208
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kviewer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "Kabema PDF Editor",
|
|
5
5
|
"repository": "kabema/kviewer",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
30
|
"prepack": "nuxt-module-build build",
|
|
31
|
-
"dev": "npm run dev:prepare && nuxt dev playground",
|
|
31
|
+
"dev": "npm run dev:prepare && portless kviewer nuxt dev playground",
|
|
32
32
|
"dev:build": "nuxt build playground",
|
|
33
33
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
34
34
|
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|