kviewer 0.0.10 → 0.1.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/README.md +29 -0
- package/dist/module.d.mts +9 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +25 -1
- 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 +12 -2
- package/dist/runtime/annotation/engine/painter.js +36 -6
- package/dist/runtime/annotation/engine/tools/form-field.d.ts +30 -0
- package/dist/runtime/annotation/engine/tools/form-field.js +119 -0
- package/dist/runtime/annotation/engine/types.d.ts +118 -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 +295 -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 +30 -1
- package/dist/runtime/components/Viewer.d.vue.ts +43 -4
- package/dist/runtime/components/Viewer.vue +106 -7
- package/dist/runtime/components/Viewer.vue.d.ts +43 -4
- package/dist/runtime/components/ViewerBar.vue +24 -2
- package/dist/runtime/components/ViewerTabs.d.vue.ts +15 -6
- package/dist/runtime/components/ViewerTabs.vue +7 -2
- package/dist/runtime/components/ViewerTabs.vue.d.ts +15 -6
- 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 +53 -10
- 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 +2 -0
- package/dist/runtime/composables/useAnnotationEngine.js +3 -1
- package/dist/runtime/composables/useFormFields.d.ts +48 -2
- package/dist/runtime/composables/useFormFields.js +338 -6
- package/dist/runtime/composables/useInertiaPanzoom.js +4 -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/dist/runtime/public-types.d.ts +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decode the font name parsed from a PDF widget's `/DA` (Default
|
|
3
|
+
* Appearance) string into CSS font properties.
|
|
4
|
+
*
|
|
5
|
+
* PDF /DA font names come in two flavours:
|
|
6
|
+
* - PDF "abbreviations" used by Acrobat for the standard 14 fonts
|
|
7
|
+
* (`Helv`, `HelvB`, `HelvO`, `HelvBO`, `TiRo`, `TiBo`, `TiIt`,
|
|
8
|
+
* `TiBI`, `Cour`, `CoBo`, `CoOb`, `CoBO`, `ZaDb`, `Symb`).
|
|
9
|
+
* - Full PostScript-style names (`Helvetica-Bold`, `Times-Italic`,
|
|
10
|
+
* `Courier-BoldOblique`, etc.) — common in PDFs produced by other
|
|
11
|
+
* tools.
|
|
12
|
+
*
|
|
13
|
+
* Anything we don't recognize falls back to sans-serif regular —
|
|
14
|
+
* exactly what pdf.js's annotation layer renders. Unrecognized names
|
|
15
|
+
* still keep weight/style detection via the `Bold`/`Italic`/`Oblique`
|
|
16
|
+
* substring check, so e.g. `MyFont-Bold` becomes `bold`.
|
|
17
|
+
*/
|
|
18
|
+
export interface DecodedFontStyle {
|
|
19
|
+
fontFamily: string;
|
|
20
|
+
fontWeight: 'normal' | 'bold';
|
|
21
|
+
fontStyle: 'normal' | 'italic';
|
|
22
|
+
}
|
|
23
|
+
export declare function decodeFontName(fontName: string | undefined): DecodedFontStyle;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const STANDARD_14 = {
|
|
2
|
+
// Helvetica family
|
|
3
|
+
Helv: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "normal", fontStyle: "normal" },
|
|
4
|
+
HelvB: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "bold", fontStyle: "normal" },
|
|
5
|
+
HelvO: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "normal", fontStyle: "italic" },
|
|
6
|
+
HelvBO: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "bold", fontStyle: "italic" },
|
|
7
|
+
Helvetica: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "normal", fontStyle: "normal" },
|
|
8
|
+
"Helvetica-Bold": { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "bold", fontStyle: "normal" },
|
|
9
|
+
"Helvetica-Oblique": { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "normal", fontStyle: "italic" },
|
|
10
|
+
"Helvetica-BoldOblique": { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', fontWeight: "bold", fontStyle: "italic" },
|
|
11
|
+
// Times family
|
|
12
|
+
TiRo: { fontFamily: '"Times New Roman", Times, serif', fontWeight: "normal", fontStyle: "normal" },
|
|
13
|
+
TiBo: { fontFamily: '"Times New Roman", Times, serif', fontWeight: "bold", fontStyle: "normal" },
|
|
14
|
+
TiIt: { fontFamily: '"Times New Roman", Times, serif', fontWeight: "normal", fontStyle: "italic" },
|
|
15
|
+
TiBI: { fontFamily: '"Times New Roman", Times, serif', fontWeight: "bold", fontStyle: "italic" },
|
|
16
|
+
"Times-Roman": { fontFamily: '"Times New Roman", Times, serif', fontWeight: "normal", fontStyle: "normal" },
|
|
17
|
+
"Times-Bold": { fontFamily: '"Times New Roman", Times, serif', fontWeight: "bold", fontStyle: "normal" },
|
|
18
|
+
"Times-Italic": { fontFamily: '"Times New Roman", Times, serif', fontWeight: "normal", fontStyle: "italic" },
|
|
19
|
+
"Times-BoldItalic": { fontFamily: '"Times New Roman", Times, serif', fontWeight: "bold", fontStyle: "italic" },
|
|
20
|
+
// Courier family
|
|
21
|
+
Cour: { fontFamily: '"Courier New", Courier, monospace', fontWeight: "normal", fontStyle: "normal" },
|
|
22
|
+
CoBo: { fontFamily: '"Courier New", Courier, monospace', fontWeight: "bold", fontStyle: "normal" },
|
|
23
|
+
CoOb: { fontFamily: '"Courier New", Courier, monospace', fontWeight: "normal", fontStyle: "italic" },
|
|
24
|
+
CoBO: { fontFamily: '"Courier New", Courier, monospace', fontWeight: "bold", fontStyle: "italic" },
|
|
25
|
+
Courier: { fontFamily: '"Courier New", Courier, monospace', fontWeight: "normal", fontStyle: "normal" },
|
|
26
|
+
"Courier-Bold": { fontFamily: '"Courier New", Courier, monospace', fontWeight: "bold", fontStyle: "normal" },
|
|
27
|
+
"Courier-Oblique": { fontFamily: '"Courier New", Courier, monospace', fontWeight: "normal", fontStyle: "italic" },
|
|
28
|
+
"Courier-BoldOblique": { fontFamily: '"Courier New", Courier, monospace', fontWeight: "bold", fontStyle: "italic" }
|
|
29
|
+
};
|
|
30
|
+
const DEFAULT_STYLE = {
|
|
31
|
+
fontFamily: "sans-serif",
|
|
32
|
+
fontWeight: "normal",
|
|
33
|
+
fontStyle: "normal"
|
|
34
|
+
};
|
|
35
|
+
export function decodeFontName(fontName) {
|
|
36
|
+
if (!fontName) return DEFAULT_STYLE;
|
|
37
|
+
const name = fontName.startsWith("/") ? fontName.slice(1) : fontName;
|
|
38
|
+
const standard = STANDARD_14[name];
|
|
39
|
+
if (standard) return standard;
|
|
40
|
+
const stripped = /^[A-Z]{6}\+/.test(name) ? name.slice(7) : name;
|
|
41
|
+
const lower = stripped.toLowerCase();
|
|
42
|
+
let fontFamily = "sans-serif";
|
|
43
|
+
if (/serif|times|roman|georgia|garamond|cambria/.test(lower)) {
|
|
44
|
+
fontFamily = '"Times New Roman", Times, serif';
|
|
45
|
+
} else if (/mono|courier|consolas|menlo|inconsolata/.test(lower)) {
|
|
46
|
+
fontFamily = '"Courier New", Courier, monospace';
|
|
47
|
+
} else if (/helvet|arial|verdana|tahoma|sans/.test(lower)) {
|
|
48
|
+
fontFamily = '"Helvetica Neue", Helvetica, Arial, sans-serif';
|
|
49
|
+
}
|
|
50
|
+
const isBold = /bold|black|heavy|semibold|demibold/i.test(stripped);
|
|
51
|
+
const isItalic = /italic|oblique/i.test(stripped);
|
|
52
|
+
return {
|
|
53
|
+
fontFamily,
|
|
54
|
+
fontWeight: isBold ? "bold" : "normal",
|
|
55
|
+
fontStyle: isItalic ? "italic" : "normal"
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CheckboxStyle } from '../engine/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walk the AcroForm of a source PDF and extract the checkbox style hint
|
|
4
|
+
* (`/MK /CA`) for every checkbox widget. pdf.js does not surface this
|
|
5
|
+
* field, so without a side-channel parse we cannot know whether an
|
|
6
|
+
* existing checkbox should render as a check, cross, diamond, etc.
|
|
7
|
+
*
|
|
8
|
+
* Returns a Map keyed by field name. If multiple widgets share a name
|
|
9
|
+
* (uncommon for checkboxes, normal for radio groups), the first hit
|
|
10
|
+
* wins.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractCheckboxStyles(pdfBytes: Uint8Array | ArrayBuffer): Promise<Map<string, CheckboxStyle>>;
|
|
13
|
+
/**
|
|
14
|
+
* Walk the AcroForm and extract push-button captions from `/MK /CA`.
|
|
15
|
+
* pdf.js exposes neither the caption nor a button label, so without this
|
|
16
|
+
* side-channel parse every push button would render with our generic
|
|
17
|
+
* "Button" fallback (e.g. a Reset button shows the wrong text).
|
|
18
|
+
*
|
|
19
|
+
* Returns a Map keyed by the button's fully qualified field name.
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractButtonCaptions(pdfBytes: Uint8Array | ArrayBuffer): Promise<Map<string, string>>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { PDFButton, PDFCheckBox, PDFDocument, PDFDict, PDFHexString, PDFName, PDFString } from "pdf-lib";
|
|
2
|
+
import { captionToStyle } from "../checkbox-styles.js";
|
|
3
|
+
export async function extractCheckboxStyles(pdfBytes) {
|
|
4
|
+
const out = /* @__PURE__ */ new Map();
|
|
5
|
+
let doc;
|
|
6
|
+
try {
|
|
7
|
+
doc = await PDFDocument.load(pdfBytes, { ignoreEncryption: true });
|
|
8
|
+
} catch {
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
let form;
|
|
12
|
+
try {
|
|
13
|
+
form = doc.getForm();
|
|
14
|
+
} catch {
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
for (const field of form.getFields()) {
|
|
18
|
+
if (!(field instanceof PDFCheckBox)) continue;
|
|
19
|
+
const acro = field.acroField;
|
|
20
|
+
const name = field.getName();
|
|
21
|
+
if (!name || out.has(name)) continue;
|
|
22
|
+
const widgets = acro.getWidgets();
|
|
23
|
+
for (const widget of widgets) {
|
|
24
|
+
const mk = widget.dict.get(PDFName.of("MK"));
|
|
25
|
+
if (!(mk instanceof PDFDict)) continue;
|
|
26
|
+
const ca = mk.get(PDFName.of("CA"));
|
|
27
|
+
let caption;
|
|
28
|
+
if (ca instanceof PDFString || ca instanceof PDFHexString) {
|
|
29
|
+
caption = ca.decodeText();
|
|
30
|
+
}
|
|
31
|
+
if (!caption) continue;
|
|
32
|
+
const style = captionToStyle(caption);
|
|
33
|
+
if (style) {
|
|
34
|
+
out.set(name, style);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
export async function extractButtonCaptions(pdfBytes) {
|
|
42
|
+
const out = /* @__PURE__ */ new Map();
|
|
43
|
+
let doc;
|
|
44
|
+
try {
|
|
45
|
+
doc = await PDFDocument.load(pdfBytes, { ignoreEncryption: true });
|
|
46
|
+
} catch {
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
let form;
|
|
50
|
+
try {
|
|
51
|
+
form = doc.getForm();
|
|
52
|
+
} catch {
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
for (const field of form.getFields()) {
|
|
56
|
+
if (!(field instanceof PDFButton)) continue;
|
|
57
|
+
const acro = field.acroField;
|
|
58
|
+
const name = field.getName();
|
|
59
|
+
if (!name || out.has(name)) continue;
|
|
60
|
+
const widgets = acro.getWidgets();
|
|
61
|
+
for (const widget of widgets) {
|
|
62
|
+
const mk = widget.dict.get(PDFName.of("MK"));
|
|
63
|
+
if (!(mk instanceof PDFDict)) continue;
|
|
64
|
+
const ca = mk.get(PDFName.of("CA"));
|
|
65
|
+
if (ca instanceof PDFString || ca instanceof PDFHexString) {
|
|
66
|
+
const caption = ca.decodeText();
|
|
67
|
+
if (caption) {
|
|
68
|
+
out.set(name, caption);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
@@ -19,8 +19,10 @@ export function parseFormFields(annotations, pageNumber) {
|
|
|
19
19
|
fieldType,
|
|
20
20
|
fieldName: ann.fieldName ?? "",
|
|
21
21
|
rect: normalizedRect,
|
|
22
|
+
originalRect: [...normalizedRect],
|
|
22
23
|
readOnly: Boolean(ann.readOnly),
|
|
23
|
-
required: Boolean(ann.required)
|
|
24
|
+
required: Boolean(ann.required),
|
|
25
|
+
origin: "parsed"
|
|
24
26
|
};
|
|
25
27
|
if (fieldType === "text") {
|
|
26
28
|
if (ann.fieldValue != null) def.defaultValue = String(ann.fieldValue);
|
|
@@ -68,8 +70,19 @@ export function parseFormFields(annotations, pageNumber) {
|
|
|
68
70
|
if (fieldType === "button") {
|
|
69
71
|
def.buttonLabel = ann.alternativeText ?? ann.fieldValue ?? ann.fieldName ?? "Button";
|
|
70
72
|
}
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
+
const da = ann.defaultAppearanceData ?? {};
|
|
74
|
+
if (typeof da.fontSize === "number" && da.fontSize > 0) {
|
|
75
|
+
def.fontSize = da.fontSize;
|
|
76
|
+
} else if (typeof ann.fontSize === "number" && ann.fontSize > 0) {
|
|
77
|
+
def.fontSize = ann.fontSize;
|
|
78
|
+
}
|
|
79
|
+
if (typeof da.fontName === "string" && da.fontName.length > 0) {
|
|
80
|
+
def.fontName = da.fontName;
|
|
81
|
+
}
|
|
82
|
+
if (da.fontColor && da.fontColor.length >= 3) {
|
|
83
|
+
const fc = da.fontColor;
|
|
84
|
+
def.color = [fc[0] ?? 0, fc[1] ?? 0, fc[2] ?? 0];
|
|
85
|
+
} else if (Array.isArray(ann.color)) {
|
|
73
86
|
def.color = ann.color.map(
|
|
74
87
|
(c) => (
|
|
75
88
|
// pdf.js colors may be 0-1 floats or 0-255 integers
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type { FormFieldValue } from '../engine/types.js';
|
|
1
|
+
import { type PDFDocument } from 'pdf-lib';
|
|
2
|
+
import type { FormFieldDefinition, FormFieldValue } from '../engine/types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Write form field values back to the PDF using pdf-lib's AcroForm API.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* - Placed/detected fields that originate from the viewer are created as new
|
|
7
|
+
* AcroForm widgets (text, checkbox, radio). Signature fields are drawn as
|
|
8
|
+
* flat images (pdf-lib does not support creating AcroForm signature widgets).
|
|
9
|
+
* - Parsed fields (already present in the source PDF) get their values
|
|
10
|
+
* updated in place.
|
|
8
11
|
*/
|
|
9
|
-
export declare function writeFormFieldsToPdf(pdfDoc: PDFDocument, fieldValues: FormFieldValue[]): Promise<void>;
|
|
12
|
+
export declare function writeFormFieldsToPdf(pdfDoc: PDFDocument, fieldValues: FormFieldValue[], placedDefinitions?: FormFieldDefinition[]): Promise<void>;
|
|
@@ -1,6 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
|
+
AcroFieldFlags,
|
|
3
|
+
AnnotationFlags,
|
|
4
|
+
PDFAcroSignature,
|
|
5
|
+
PDFBool,
|
|
6
|
+
PDFDict,
|
|
7
|
+
PDFName,
|
|
8
|
+
PDFRawStream,
|
|
9
|
+
PDFString,
|
|
10
|
+
StandardFonts
|
|
11
|
+
} from "pdf-lib";
|
|
12
|
+
import { CHECKBOX_STYLE_TABLE } from "../checkbox-styles.js";
|
|
13
|
+
export async function writeFormFieldsToPdf(pdfDoc, fieldValues, placedDefinitions = []) {
|
|
14
|
+
const valueByFieldId = new Map(fieldValues.map((v) => [v.fieldId, v]));
|
|
15
|
+
const createdFieldNames = /* @__PURE__ */ new Set();
|
|
16
|
+
const radioGroupCache = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const def of placedDefinitions) {
|
|
18
|
+
try {
|
|
19
|
+
if (def.origin === "parsed") {
|
|
20
|
+
updateParsedField(pdfDoc, def);
|
|
21
|
+
} else {
|
|
22
|
+
await createWidgetForDefinition(
|
|
23
|
+
pdfDoc,
|
|
24
|
+
def,
|
|
25
|
+
valueByFieldId.get(def.id),
|
|
26
|
+
radioGroupCache
|
|
27
|
+
);
|
|
28
|
+
createdFieldNames.add(def.fieldName);
|
|
29
|
+
}
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.warn(
|
|
32
|
+
`Failed to write form field "${def.fieldName}" (${def.fieldType}, origin=${def.origin ?? "parsed"}):`,
|
|
33
|
+
err
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
2
37
|
const form = pdfDoc.getForm();
|
|
3
38
|
for (const field of fieldValues) {
|
|
39
|
+
if (createdFieldNames.has(field.fieldName)) continue;
|
|
4
40
|
try {
|
|
5
41
|
switch (field.fieldType) {
|
|
6
42
|
case "text": {
|
|
@@ -50,6 +86,264 @@ export async function writeFormFieldsToPdf(pdfDoc, fieldValues) {
|
|
|
50
86
|
}
|
|
51
87
|
}
|
|
52
88
|
}
|
|
89
|
+
function applyCheckboxStyle(pdfDoc, cb, def) {
|
|
90
|
+
const style = def.checkboxStyle;
|
|
91
|
+
if (!style) return;
|
|
92
|
+
const caption = CHECKBOX_STYLE_TABLE[style]?.caption;
|
|
93
|
+
if (!caption) return;
|
|
94
|
+
const widgets = cb.acroField.getWidgets();
|
|
95
|
+
for (const widget of widgets) {
|
|
96
|
+
let mk = widget.dict.get(PDFName.of("MK"));
|
|
97
|
+
if (!(mk instanceof PDFDict)) {
|
|
98
|
+
mk = pdfDoc.context.obj({});
|
|
99
|
+
widget.dict.set(PDFName.of("MK"), mk);
|
|
100
|
+
}
|
|
101
|
+
mk.set(PDFName.of("CA"), PDFString.of(caption));
|
|
102
|
+
}
|
|
103
|
+
const form = pdfDoc.getForm();
|
|
104
|
+
form.acroForm.dict.set(PDFName.of("NeedAppearances"), PDFBool.True);
|
|
105
|
+
}
|
|
106
|
+
function updateParsedField(pdfDoc, def) {
|
|
107
|
+
const form = pdfDoc.getForm();
|
|
108
|
+
let field;
|
|
109
|
+
try {
|
|
110
|
+
field = form.getField(def.fieldName);
|
|
111
|
+
} catch {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const widgets = field.acroField.getWidgets();
|
|
115
|
+
if (widgets.length === 0) return;
|
|
116
|
+
const target = def.originalRect ? pickWidgetByRect(widgets, def.originalRect) : widgets[0];
|
|
117
|
+
if (!target) return;
|
|
118
|
+
if (def.originalRect && !rectsEqual(def.rect, def.originalRect)) {
|
|
119
|
+
const [x1, y1, x2, y2] = def.rect;
|
|
120
|
+
target.setRectangle({
|
|
121
|
+
x: x1,
|
|
122
|
+
y: y1,
|
|
123
|
+
width: Math.max(1, x2 - x1),
|
|
124
|
+
height: Math.max(1, y2 - y1)
|
|
125
|
+
});
|
|
126
|
+
if (def.fieldType === "text" && def.comb) {
|
|
127
|
+
form.acroForm.dict.set(PDFName.of("NeedAppearances"), PDFBool.True);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (def.fieldType === "checkbox" && (def.checkboxStyle ?? "check") !== (def.originalCheckboxStyle ?? "check")) {
|
|
131
|
+
const caption = CHECKBOX_STYLE_TABLE[def.checkboxStyle ?? "check"]?.caption;
|
|
132
|
+
if (caption) {
|
|
133
|
+
for (const widget of widgets) {
|
|
134
|
+
let mk = widget.dict.get(PDFName.of("MK"));
|
|
135
|
+
if (!(mk instanceof PDFDict)) {
|
|
136
|
+
mk = pdfDoc.context.obj({});
|
|
137
|
+
widget.dict.set(PDFName.of("MK"), mk);
|
|
138
|
+
}
|
|
139
|
+
mk.set(PDFName.of("CA"), PDFString.of(caption));
|
|
140
|
+
}
|
|
141
|
+
form.acroForm.dict.set(PDFName.of("NeedAppearances"), PDFBool.True);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function rectsEqual(a, b) {
|
|
146
|
+
for (let i = 0; i < 4; i++) {
|
|
147
|
+
if (Math.abs((a[i] ?? 0) - (b[i] ?? 0)) > 0.01) return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
function pickWidgetByRect(widgets, expected) {
|
|
152
|
+
const [ex1, ey1, ex2, ey2] = expected;
|
|
153
|
+
const ew = ex2 - ex1;
|
|
154
|
+
const eh = ey2 - ey1;
|
|
155
|
+
const tolerance = 0.5;
|
|
156
|
+
for (const w of widgets) {
|
|
157
|
+
const r = w.getRectangle();
|
|
158
|
+
if (Math.abs(r.x - ex1) <= tolerance && Math.abs(r.y - ey1) <= tolerance && Math.abs(r.width - ew) <= tolerance && Math.abs(r.height - eh) <= tolerance) return w;
|
|
159
|
+
}
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
async function createWidgetForDefinition(pdfDoc, def, fv, radioGroupCache) {
|
|
163
|
+
const form = pdfDoc.getForm();
|
|
164
|
+
const pageIndex = def.pageNumber - 1;
|
|
165
|
+
const pages = pdfDoc.getPages();
|
|
166
|
+
const page = pages[pageIndex];
|
|
167
|
+
if (!page) return;
|
|
168
|
+
const [x1, y1, x2, y2] = def.rect;
|
|
169
|
+
const box = {
|
|
170
|
+
x: x1,
|
|
171
|
+
y: y1,
|
|
172
|
+
width: Math.max(1, x2 - x1),
|
|
173
|
+
height: Math.max(1, y2 - y1)
|
|
174
|
+
};
|
|
175
|
+
switch (def.fieldType) {
|
|
176
|
+
case "text": {
|
|
177
|
+
const tf = form.createTextField(def.fieldName);
|
|
178
|
+
if (def.maxLen && def.maxLen > 0) tf.setMaxLength(def.maxLen);
|
|
179
|
+
if (def.multiLine) tf.enableMultiline();
|
|
180
|
+
const v = fv?.value;
|
|
181
|
+
if (typeof v === "string" && v !== "") tf.setText(v);
|
|
182
|
+
tf.addToPage(page, box);
|
|
183
|
+
applyFlags(tf, def);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case "checkbox": {
|
|
187
|
+
const cb = form.createCheckBox(def.fieldName);
|
|
188
|
+
cb.addToPage(page, box);
|
|
189
|
+
if (fv?.value === true) cb.check();
|
|
190
|
+
applyFlags(cb, def);
|
|
191
|
+
applyCheckboxStyle(pdfDoc, cb, def);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case "radio": {
|
|
195
|
+
let group = radioGroupCache.get(def.fieldName);
|
|
196
|
+
if (!group) {
|
|
197
|
+
try {
|
|
198
|
+
group = form.getRadioGroup(def.fieldName);
|
|
199
|
+
} catch {
|
|
200
|
+
group = form.createRadioGroup(def.fieldName);
|
|
201
|
+
}
|
|
202
|
+
radioGroupCache.set(def.fieldName, group);
|
|
203
|
+
}
|
|
204
|
+
const existingOptions = new Set(group.getOptions());
|
|
205
|
+
let optionValue = def.buttonValue || `Option_${existingOptions.size + 1}`;
|
|
206
|
+
if (existingOptions.has(optionValue)) {
|
|
207
|
+
let n = existingOptions.size + 1;
|
|
208
|
+
while (existingOptions.has(`Option_${n}`)) n += 1;
|
|
209
|
+
optionValue = `Option_${n}`;
|
|
210
|
+
}
|
|
211
|
+
group.addOptionToPage(optionValue, page, box);
|
|
212
|
+
if (typeof fv?.value === "string" && fv.value === optionValue) {
|
|
213
|
+
group.select(optionValue);
|
|
214
|
+
}
|
|
215
|
+
applyFlags(group, def);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case "signature": {
|
|
219
|
+
await createSignatureField(pdfDoc, page, def, fv);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case "dropdown": {
|
|
223
|
+
const labels = (def.options ?? []).map((o) => o.displayValue);
|
|
224
|
+
if (def.combo === false) {
|
|
225
|
+
const list = form.createOptionList(def.fieldName);
|
|
226
|
+
if (labels.length > 0) list.setOptions(labels);
|
|
227
|
+
list.addToPage(page, box);
|
|
228
|
+
if (def.multiSelect) list.enableMultiselect();
|
|
229
|
+
const v = fv?.value;
|
|
230
|
+
if (Array.isArray(v) && v.length > 0) list.select(v);
|
|
231
|
+
else if (typeof v === "string" && v) list.select(v);
|
|
232
|
+
applyFlags(list, def);
|
|
233
|
+
} else {
|
|
234
|
+
const dd = form.createDropdown(def.fieldName);
|
|
235
|
+
if (labels.length > 0) dd.setOptions(labels);
|
|
236
|
+
dd.addToPage(page, box);
|
|
237
|
+
if (def.editable) dd.enableEditing();
|
|
238
|
+
const v = fv?.value;
|
|
239
|
+
if (typeof v === "string" && v) dd.select(v);
|
|
240
|
+
else if (Array.isArray(v) && v[0]) dd.select(v[0]);
|
|
241
|
+
applyFlags(dd, def);
|
|
242
|
+
}
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function applyFlags(field, def) {
|
|
248
|
+
if (def.readOnly) field.enableReadOnly();
|
|
249
|
+
if (def.required) field.enableRequired();
|
|
250
|
+
}
|
|
251
|
+
async function createSignatureField(pdfDoc, page, def, fv) {
|
|
252
|
+
const { context } = pdfDoc;
|
|
253
|
+
const form = pdfDoc.getForm();
|
|
254
|
+
const [x1, y1, x2, y2] = def.rect;
|
|
255
|
+
const width = Math.max(1, x2 - x1);
|
|
256
|
+
const height = Math.max(1, y2 - y1);
|
|
257
|
+
const fieldDict = context.obj({
|
|
258
|
+
FT: "Sig",
|
|
259
|
+
Kids: []
|
|
260
|
+
});
|
|
261
|
+
const fieldRef = context.register(fieldDict);
|
|
262
|
+
const sig = PDFAcroSignature.fromDict(fieldDict, fieldRef);
|
|
263
|
+
sig.setPartialName(def.fieldName);
|
|
264
|
+
if (def.readOnly) sig.setFlagTo(AcroFieldFlags.ReadOnly, true);
|
|
265
|
+
if (def.required) sig.setFlagTo(AcroFieldFlags.Required, true);
|
|
266
|
+
const v = fv?.value;
|
|
267
|
+
const signed = typeof v === "string" && v.startsWith("data:image");
|
|
268
|
+
const appearanceRef = signed ? await buildSignedSignatureAppearance(pdfDoc, v, width, height) : await buildSignaturePlaceholderAppearance(pdfDoc, width, height);
|
|
269
|
+
const widgetDict = context.obj({
|
|
270
|
+
Type: "Annot",
|
|
271
|
+
Subtype: "Widget",
|
|
272
|
+
Rect: [x1, y1, x2, y2],
|
|
273
|
+
P: page.ref,
|
|
274
|
+
Parent: fieldRef,
|
|
275
|
+
F: 1 << AnnotationFlags.Print,
|
|
276
|
+
AP: { N: appearanceRef }
|
|
277
|
+
});
|
|
278
|
+
const widgetRef = context.register(widgetDict);
|
|
279
|
+
sig.addWidget(widgetRef);
|
|
280
|
+
form.acroForm.addField(fieldRef);
|
|
281
|
+
page.node.addAnnot(widgetRef);
|
|
282
|
+
}
|
|
283
|
+
async function buildSignaturePlaceholderAppearance(pdfDoc, width, height) {
|
|
284
|
+
const { context } = pdfDoc;
|
|
285
|
+
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
286
|
+
const label = "Sign here";
|
|
287
|
+
const fontSize = Math.max(6, Math.min(12, height * 0.4));
|
|
288
|
+
const textWidth = font.widthOfTextAtSize(label, fontSize);
|
|
289
|
+
const textHeight = font.heightAtSize(fontSize);
|
|
290
|
+
const textX = (width - textWidth) / 2;
|
|
291
|
+
const textY = (height - textHeight) / 2;
|
|
292
|
+
const ops = [
|
|
293
|
+
"q",
|
|
294
|
+
"0.55 0.55 0.55 RG",
|
|
295
|
+
"0.75 w",
|
|
296
|
+
"[3 2] 0 d",
|
|
297
|
+
`0.5 0.5 ${(width - 1).toFixed(3)} ${(height - 1).toFixed(3)} re`,
|
|
298
|
+
"S",
|
|
299
|
+
"0.55 0.55 0.55 rg",
|
|
300
|
+
"BT",
|
|
301
|
+
`/F1 ${fontSize.toFixed(3)} Tf`,
|
|
302
|
+
`${textX.toFixed(3)} ${textY.toFixed(3)} Td`,
|
|
303
|
+
`(${label}) Tj`,
|
|
304
|
+
"ET",
|
|
305
|
+
"Q"
|
|
306
|
+
].join("\n");
|
|
307
|
+
const dict = context.obj({
|
|
308
|
+
Type: "XObject",
|
|
309
|
+
Subtype: "Form",
|
|
310
|
+
BBox: [0, 0, width, height],
|
|
311
|
+
Matrix: [1, 0, 0, 1, 0, 0],
|
|
312
|
+
Resources: { Font: { F1: font.ref } }
|
|
313
|
+
});
|
|
314
|
+
const stream = PDFRawStream.of(dict, new TextEncoder().encode(ops));
|
|
315
|
+
return context.register(stream);
|
|
316
|
+
}
|
|
317
|
+
async function buildSignedSignatureAppearance(pdfDoc, dataUrl, width, height) {
|
|
318
|
+
const match = dataUrl.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$/);
|
|
319
|
+
if (!match) return buildSignaturePlaceholderAppearance(pdfDoc, width, height);
|
|
320
|
+
const mimeType = match[1] ?? "";
|
|
321
|
+
const base64 = match[2] ?? "";
|
|
322
|
+
const image = mimeType.includes("jpeg") || mimeType.includes("jpg") ? await pdfDoc.embedJpg(base64) : await pdfDoc.embedPng(base64);
|
|
323
|
+
const imgAspect = image.width / image.height;
|
|
324
|
+
const boxAspect = width / height;
|
|
325
|
+
let drawW = width;
|
|
326
|
+
let drawH = height;
|
|
327
|
+
if (imgAspect > boxAspect) drawH = width / imgAspect;
|
|
328
|
+
else drawW = height * imgAspect;
|
|
329
|
+
const drawX = (width - drawW) / 2;
|
|
330
|
+
const drawY = (height - drawH) / 2;
|
|
331
|
+
const ops = [
|
|
332
|
+
"q",
|
|
333
|
+
`${drawW.toFixed(3)} 0 0 ${drawH.toFixed(3)} ${drawX.toFixed(3)} ${drawY.toFixed(3)} cm`,
|
|
334
|
+
"/Img Do",
|
|
335
|
+
"Q"
|
|
336
|
+
].join("\n");
|
|
337
|
+
const dict = pdfDoc.context.obj({
|
|
338
|
+
Type: "XObject",
|
|
339
|
+
Subtype: "Form",
|
|
340
|
+
BBox: [0, 0, width, height],
|
|
341
|
+
Matrix: [1, 0, 0, 1, 0, 0],
|
|
342
|
+
Resources: { XObject: { Img: image.ref } }
|
|
343
|
+
});
|
|
344
|
+
const stream = PDFRawStream.of(dict, new TextEncoder().encode(ops));
|
|
345
|
+
return pdfDoc.context.register(stream);
|
|
346
|
+
}
|
|
53
347
|
async function embedSignatureImage(pdfDoc, field) {
|
|
54
348
|
const dataUrl = field.value;
|
|
55
349
|
const match = dataUrl.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$/);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IAnnotationStore, type FormFieldValue } from '../engine/types.js';
|
|
1
|
+
import { type IAnnotationStore, type FormFieldDefinition, type FormFieldValue } from '../engine/types.js';
|
|
2
2
|
export interface ExportPdfOptions {
|
|
3
3
|
flatten?: boolean;
|
|
4
4
|
download?: boolean;
|
|
@@ -10,9 +10,10 @@ interface ExportPdfParams {
|
|
|
10
10
|
annotations: IAnnotationStore[];
|
|
11
11
|
options?: ExportPdfOptions;
|
|
12
12
|
formFieldValues?: FormFieldValue[];
|
|
13
|
+
placedFormFieldDefinitions?: FormFieldDefinition[];
|
|
13
14
|
originalAnnotationIds?: Set<string>;
|
|
14
15
|
modifiedAnnotationIds?: Set<string>;
|
|
15
16
|
deletedAnnotationIds?: Set<string>;
|
|
16
17
|
}
|
|
17
|
-
export declare function exportAnnotationsToPdf({ pdfData, annotations, options, formFieldValues, originalAnnotationIds, modifiedAnnotationIds, deletedAnnotationIds, }: ExportPdfParams): Promise<Uint8Array>;
|
|
18
|
+
export declare function exportAnnotationsToPdf({ pdfData, annotations, options, formFieldValues, placedFormFieldDefinitions, originalAnnotationIds, modifiedAnnotationIds, deletedAnnotationIds, }: ExportPdfParams): Promise<Uint8Array>;
|
|
18
19
|
export {};
|
|
@@ -198,6 +198,7 @@ export async function exportAnnotationsToPdf({
|
|
|
198
198
|
annotations,
|
|
199
199
|
options,
|
|
200
200
|
formFieldValues,
|
|
201
|
+
placedFormFieldDefinitions,
|
|
201
202
|
originalAnnotationIds,
|
|
202
203
|
modifiedAnnotationIds,
|
|
203
204
|
deletedAnnotationIds
|
|
@@ -205,8 +206,14 @@ export async function exportAnnotationsToPdf({
|
|
|
205
206
|
const flatten = options?.flatten ?? false;
|
|
206
207
|
const preserveOriginalAnnotations = options?.preserveOriginalAnnotations ?? false;
|
|
207
208
|
const pdfDoc = await PDFDocument.load(toUint8Array(pdfData));
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
const hasValues = formFieldValues && formFieldValues.length > 0;
|
|
210
|
+
const hasPlaced = placedFormFieldDefinitions && placedFormFieldDefinitions.length > 0;
|
|
211
|
+
if (hasValues || hasPlaced) {
|
|
212
|
+
await writeFormFieldsToPdf(
|
|
213
|
+
pdfDoc,
|
|
214
|
+
formFieldValues ?? [],
|
|
215
|
+
placedFormFieldDefinitions ?? []
|
|
216
|
+
);
|
|
210
217
|
}
|
|
211
218
|
let annotationsToWrite = annotations;
|
|
212
219
|
if (!preserveOriginalAnnotations) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.kviewer-text-layer{left:0;line-height:1;overflow:hidden;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:1}.kviewer-text-layer--interactive{cursor:text;-webkit-user-select:text;-moz-user-select:text;user-select:text}.KViewer_is_painting.KViewer_painting_type_12 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_12 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_13 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_13 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_5 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_5 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_6 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_6 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_7 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_7 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_8 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_8 .kviewer-annotation-layer *{cursor:crosshair!important}.KViewer_is_painting.KViewer_painting_type_4 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_4 .kviewer-annotation-layer *{cursor:text!important}.KViewer_is_painting.KViewer_painting_type_11 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_11 .kviewer-annotation-layer *{cursor:crosshair!important}.KViewer_selector_hover{cursor:pointer!important}.kviewer-form-layer{left:0;overflow:hidden;position:absolute;top:0}.kviewer-form-field{box-sizing:border-box;position:absolute}.kviewer-form-input{background-color:
|
|
1
|
+
.kviewer-text-layer{left:0;line-height:1;overflow:hidden;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:1}.kviewer-text-layer--interactive{cursor:text;-webkit-user-select:text;-moz-user-select:text;user-select:text}.KViewer_is_painting.KViewer_painting_type_12 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_12 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_13 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_13 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_5 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_5 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_6 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_6 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_7 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_7 .kviewer-annotation-layer *,.KViewer_is_painting.KViewer_painting_type_8 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_8 .kviewer-annotation-layer *{cursor:crosshair!important}.KViewer_is_painting.KViewer_painting_type_4 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_4 .kviewer-annotation-layer *{cursor:text!important}.KViewer_is_painting.KViewer_painting_type_11 .kviewer-annotation-layer,.KViewer_is_painting.KViewer_painting_type_11 .kviewer-annotation-layer *{cursor:crosshair!important}.KViewer_selector_hover{cursor:pointer!important}.kviewer-form-layer{left:0;overflow:hidden;position:absolute;top:0}.kviewer-form-field{box-sizing:border-box;position:absolute}.kviewer-form-input{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 14%,transparent);border:1px solid transparent;box-sizing:border-box;color:#000;display:block;font-family:-apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,Arial,sans-serif;font-weight:500;height:100%;line-height:normal;margin:0;outline:none;padding:1px 2px;resize:none;width:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;vertical-align:top}.kviewer-form-input:hover{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 22%,transparent);border-color:rgba(0,0,0,.2)}.kviewer-form-input:focus{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 28%,transparent);border-color:var(--kvw-field-color,var(--color-primary,#3b82f6));outline:2px solid var(--kvw-field-color,var(--color-primary,#3b82f6))}.kviewer-form-select{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto;cursor:pointer}.kviewer-form-listbox{overflow-y:auto;padding:0}.kviewer-form-listbox option{padding:1px 3px}.kviewer-form-editable-combo{height:100%;position:relative;width:100%}.kviewer-form-editable-combo input{height:100%;width:100%}.kviewer-form-checkbox,.kviewer-form-radio{align-items:center;background:#fff;box-sizing:border-box;cursor:pointer;display:flex;height:100%;justify-content:center;width:100%}.kviewer-form-checkbox input,.kviewer-form-radio input{accent-color:var(--kvw-field-color,var(--color-primary,#3b82f6));cursor:pointer;height:80%;margin:0;max-height:18px;max-width:18px;width:80%}.kviewer-form-checkbox--detected{background:transparent}.kviewer-form-checkbox--circle{border-radius:50%}.kviewer-form-checkbox__icon{color:#1a1a1a;height:65%;width:65%}.kviewer-form-checkbox--circle .kviewer-form-checkbox__icon{height:50%;width:50%}.kviewer-form-radio input{accent-color:var(--kvw-field-color,var(--color-primary,#3b82f6));cursor:pointer;height:80%;margin:0;max-height:18px;max-width:18px;width:80%}.kviewer-form-button{align-items:center;background:#c8c8c8;border:1px solid rgba(0,0,0,.35);box-sizing:border-box;color:#000;cursor:pointer;display:flex;font-family:inherit;font-weight:700;height:100%;justify-content:center;line-height:1;padding:0 6px;text-align:center;width:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.kviewer-form-button:hover{background:#bdbdbd}.kviewer-form-button:active{background:#b0b0b0}.kviewer-form-signature{align-items:center;background:rgba(255,255,200,.15);border:1px dashed rgba(0,0,0,.2);cursor:pointer;display:flex;height:100%;justify-content:center;width:100%}.kviewer-form-signature:hover{background:color-mix(in srgb,var(--kvw-field-color,#3b82f6) 8%,transparent);border-color:var(--kvw-field-color,var(--color-primary,#3b82f6))}.kviewer-form-signature--filled{background:transparent;border-color:transparent;border-style:solid}.kviewer-form-signature__preview{max-height:100%;max-width:100%;-o-object-fit:contain;object-fit:contain}.kviewer-form-signature__placeholder{color:rgba(0,0,0,.4);font-size:10px;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}
|
|
@@ -5,6 +5,11 @@ type __VLS_Props = {
|
|
|
5
5
|
pageHeight: number;
|
|
6
6
|
pointerEvents: string;
|
|
7
7
|
zIndex: number;
|
|
8
|
+
/** PDF user-space origin offsets (`view[0]`, `view[1]`). Forwarded to
|
|
9
|
+
* FormFieldWrapper so /Rect coordinates can be mapped to canvas space
|
|
10
|
+
* when the page's MediaBox is not at (0, 0). */
|
|
11
|
+
viewOffsetX?: number;
|
|
12
|
+
viewOffsetY?: number;
|
|
8
13
|
};
|
|
9
14
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
15
|
declare const _default: typeof __VLS_export;
|