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
|
@@ -59,6 +59,9 @@
|
|
|
59
59
|
:zoom="activeTab.zoom ?? zoom"
|
|
60
60
|
:readonly="readonly"
|
|
61
61
|
:shape-detection="activeTab.shapeDetection ?? shapeDetection"
|
|
62
|
+
:role-colors="roleColors"
|
|
63
|
+
:active-role-id="activeRoleId"
|
|
64
|
+
@update:active-role-id="(v) => emit('update:activeRoleId', v)"
|
|
62
65
|
>
|
|
63
66
|
<template v-if="$slots.header" #header>
|
|
64
67
|
<slot name="header" :tab="activeTab" />
|
|
@@ -91,9 +94,11 @@ const props = defineProps({
|
|
|
91
94
|
shapeDetection: { type: Boolean, required: false },
|
|
92
95
|
viewMode: { type: String, required: false, default: "fit-width" },
|
|
93
96
|
zoom: { type: Number, required: false, default: 1 },
|
|
94
|
-
minTabs: { type: Number, required: false, default: 0 }
|
|
97
|
+
minTabs: { type: Number, required: false, default: 0 },
|
|
98
|
+
roleColors: { type: Object, required: false, default: void 0 },
|
|
99
|
+
activeRoleId: { type: [String, null], required: false, default: void 0 }
|
|
95
100
|
});
|
|
96
|
-
const emit = defineEmits(["update:activeTab", "tab-added", "tab-close", "tab-removed"]);
|
|
101
|
+
const emit = defineEmits(["update:activeTab", "tab-added", "tab-close", "tab-removed", "update:activeRoleId"]);
|
|
97
102
|
let idCounter = 0;
|
|
98
103
|
function generateId() {
|
|
99
104
|
return `tab-${Date.now()}-${++idCounter}`;
|
|
@@ -48,6 +48,11 @@ type __VLS_Props = {
|
|
|
48
48
|
zoom?: number;
|
|
49
49
|
/** Minimum number of tabs -- prevents closing below this count. */
|
|
50
50
|
minTabs?: number;
|
|
51
|
+
/** Forwarded to every Viewer instance — see KViewer's `roleColors`. */
|
|
52
|
+
roleColors?: Record<string, string>;
|
|
53
|
+
/** Forwarded to every Viewer instance — see KViewer's `activeRoleId`.
|
|
54
|
+
* Supports v-model via `v-model:active-role-id`. */
|
|
55
|
+
activeRoleId?: string | null;
|
|
51
56
|
};
|
|
52
57
|
declare function addTab(item: Omit<ViewerTabItem, 'id'> & {
|
|
53
58
|
id?: string;
|
|
@@ -55,7 +60,7 @@ declare function addTab(item: Omit<ViewerTabItem, 'id'> & {
|
|
|
55
60
|
declare function removeTab(id: string): boolean;
|
|
56
61
|
declare function activateTab(id: string): void;
|
|
57
62
|
declare function getViewer(id: string): ComponentPublicInstance | null;
|
|
58
|
-
declare var __VLS_7: {}, __VLS_21: {},
|
|
63
|
+
declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
|
|
59
64
|
tab: {
|
|
60
65
|
id: string;
|
|
61
66
|
label: string;
|
|
@@ -154,7 +159,7 @@ declare var __VLS_7: {}, __VLS_21: {}, __VLS_30: {
|
|
|
154
159
|
zoom?: number | undefined;
|
|
155
160
|
shapeDetection?: boolean | undefined;
|
|
156
161
|
};
|
|
157
|
-
},
|
|
162
|
+
}, __VLS_35: {
|
|
158
163
|
tab: {
|
|
159
164
|
id: string;
|
|
160
165
|
label: string;
|
|
@@ -253,17 +258,17 @@ declare var __VLS_7: {}, __VLS_21: {}, __VLS_30: {
|
|
|
253
258
|
zoom?: number | undefined;
|
|
254
259
|
shapeDetection?: boolean | undefined;
|
|
255
260
|
};
|
|
256
|
-
},
|
|
261
|
+
}, __VLS_37: {};
|
|
257
262
|
type __VLS_Slots = {} & {
|
|
258
263
|
'tabs-leading'?: (props: typeof __VLS_7) => any;
|
|
259
264
|
} & {
|
|
260
265
|
'tabs-trailing'?: (props: typeof __VLS_21) => any;
|
|
261
266
|
} & {
|
|
262
|
-
header?: (props: typeof
|
|
267
|
+
header?: (props: typeof __VLS_32) => any;
|
|
263
268
|
} & {
|
|
264
|
-
footer?: (props: typeof
|
|
269
|
+
footer?: (props: typeof __VLS_35) => any;
|
|
265
270
|
} & {
|
|
266
|
-
empty?: (props: typeof
|
|
271
|
+
empty?: (props: typeof __VLS_37) => any;
|
|
267
272
|
};
|
|
268
273
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
269
274
|
addTab: typeof addTab;
|
|
@@ -370,11 +375,13 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
|
370
375
|
shapeDetection?: boolean | undefined;
|
|
371
376
|
}[];
|
|
372
377
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
378
|
+
"update:activeRoleId": (value: string | null) => any;
|
|
373
379
|
"update:activeTab": (id: string) => any;
|
|
374
380
|
"tab-added": (tab: ViewerTabItem) => any;
|
|
375
381
|
"tab-close": (id: string) => any;
|
|
376
382
|
"tab-removed": (id: string) => any;
|
|
377
383
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
384
|
+
"onUpdate:activeRoleId"?: ((value: string | null) => any) | undefined;
|
|
378
385
|
"onUpdate:activeTab"?: ((id: string) => any) | undefined;
|
|
379
386
|
"onTab-added"?: ((tab: ViewerTabItem) => any) | undefined;
|
|
380
387
|
"onTab-close"?: ((id: string) => any) | undefined;
|
|
@@ -385,6 +392,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
|
385
392
|
stamps: StampDefinition[];
|
|
386
393
|
signatureHandlers: SignatureHandlers;
|
|
387
394
|
viewMode: ViewMode;
|
|
395
|
+
roleColors: Record<string, string>;
|
|
396
|
+
activeRoleId: string | null;
|
|
388
397
|
defaultActiveTab: string;
|
|
389
398
|
minTabs: number;
|
|
390
399
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
<script setup>
|
|
14
14
|
import { computed } from "vue";
|
|
15
|
+
import { decodeFontName } from "../../annotation/font-style";
|
|
15
16
|
import { useFormFields } from "../../composables/useFormFields";
|
|
16
17
|
import { useViewerState } from "../../composables/useViewerState";
|
|
17
18
|
const props = defineProps({
|
|
@@ -19,12 +20,23 @@ const props = defineProps({
|
|
|
19
20
|
});
|
|
20
21
|
const formFields = useFormFields();
|
|
21
22
|
const state = useViewerState();
|
|
22
|
-
const isReadOnly = computed(
|
|
23
|
+
const isReadOnly = computed(
|
|
24
|
+
() => state.readonly.value || props.field.readOnly || formFields.isFieldLocked(props.field.id)
|
|
25
|
+
);
|
|
26
|
+
const FONT_BORDER_SIZE = 2;
|
|
27
|
+
const LINE_HEIGHT_FACTOR = 1.35;
|
|
28
|
+
const DEFAULT_FIELD_FONT_SIZE = 9;
|
|
23
29
|
const buttonStyle = computed(() => {
|
|
24
30
|
const style = {};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
const declared = props.field.fontSize && props.field.fontSize > 0 ? props.field.fontSize : DEFAULT_FIELD_FONT_SIZE;
|
|
32
|
+
const rect = props.field.rect;
|
|
33
|
+
const rectHeight = Math.abs(rect[3] - rect[1] - FONT_BORDER_SIZE);
|
|
34
|
+
const computed2 = Math.min(declared, rectHeight / LINE_HEIGHT_FACTOR);
|
|
35
|
+
style.fontSize = `${Math.round(10 * computed2) / 10}px`;
|
|
36
|
+
const fontStyle = decodeFontName(props.field.fontName);
|
|
37
|
+
style.fontFamily = fontStyle.fontFamily;
|
|
38
|
+
if (fontStyle.fontWeight !== "normal") style.fontWeight = fontStyle.fontWeight;
|
|
39
|
+
if (fontStyle.fontStyle !== "normal") style.fontStyle = fontStyle.fontStyle;
|
|
28
40
|
if (props.field.color && props.field.color.length >= 3) {
|
|
29
41
|
style.color = `rgb(${props.field.color[0]}, ${props.field.color[1]}, ${props.field.color[2]})`;
|
|
30
42
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<!-- Detected shape:
|
|
2
|
+
<!-- Detected shape: lightweight × icon on transparent background -->
|
|
3
3
|
<div
|
|
4
4
|
v-if="isDetected"
|
|
5
5
|
class="kviewer-form-checkbox kviewer-form-checkbox--detected"
|
|
@@ -29,20 +29,30 @@
|
|
|
29
29
|
</svg>
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
|
-
<!-- Real PDF form field:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
<!-- Real PDF form field: render a custom box that draws the matching
|
|
33
|
+
Unicode glyph for whichever `/MK /CA` style is set (default 'check'
|
|
34
|
+
included). Native HTML checkboxes can't render cross/diamond/star/etc,
|
|
35
|
+
and rendering the default check via the same path keeps the look
|
|
36
|
+
consistent across all styles. -->
|
|
37
|
+
<div
|
|
38
|
+
v-else
|
|
39
|
+
class="kviewer-form-checkbox kviewer-form-checkbox--styled"
|
|
40
|
+
:class="{ 'kviewer-form-checkbox--checked': isChecked }"
|
|
41
|
+
role="checkbox"
|
|
42
|
+
:aria-checked="isChecked"
|
|
43
|
+
:aria-disabled="isReadOnly"
|
|
44
|
+
tabindex="0"
|
|
45
|
+
@click="toggle"
|
|
46
|
+
@keydown.space.prevent="toggle"
|
|
47
|
+
@keydown.enter.prevent="toggle"
|
|
48
|
+
>
|
|
49
|
+
<span v-if="isChecked" class="kviewer-form-checkbox__glyph">{{ styledGlyph }}</span>
|
|
41
50
|
</div>
|
|
42
51
|
</template>
|
|
43
52
|
|
|
44
53
|
<script setup>
|
|
45
54
|
import { computed } from "vue";
|
|
55
|
+
import { CHECKBOX_STYLE_TABLE } from "../../annotation/checkbox-styles";
|
|
46
56
|
import { useFormFields } from "../../composables/useFormFields";
|
|
47
57
|
import { useViewerState } from "../../composables/useViewerState";
|
|
48
58
|
const props = defineProps({
|
|
@@ -51,17 +61,23 @@ const props = defineProps({
|
|
|
51
61
|
const formFields = useFormFields();
|
|
52
62
|
const state = useViewerState();
|
|
53
63
|
const isDetected = computed(() => props.field.shapeType != null);
|
|
54
|
-
const isReadOnly = computed(
|
|
64
|
+
const isReadOnly = computed(
|
|
65
|
+
() => state.readonly.value || props.field.readOnly || formFields.isFieldLocked(props.field.id)
|
|
66
|
+
);
|
|
55
67
|
const isChecked = computed(() => {
|
|
56
68
|
const fv = formFields.getFieldValue(props.field.id);
|
|
57
69
|
return fv?.value === true;
|
|
58
70
|
});
|
|
71
|
+
const styledGlyph = computed(() => {
|
|
72
|
+
const style = props.field.checkboxStyle ?? "check";
|
|
73
|
+
return CHECKBOX_STYLE_TABLE[style]?.glyph ?? CHECKBOX_STYLE_TABLE.check.glyph;
|
|
74
|
+
});
|
|
59
75
|
function toggle() {
|
|
60
76
|
if (isReadOnly.value) return;
|
|
61
77
|
formFields.setFieldValue(props.field.id, !isChecked.value);
|
|
62
78
|
}
|
|
63
|
-
function onChange(event) {
|
|
64
|
-
const target = event.target;
|
|
65
|
-
formFields.setFieldValue(props.field.id, target.checked);
|
|
66
|
-
}
|
|
67
79
|
</script>
|
|
80
|
+
|
|
81
|
+
<style>
|
|
82
|
+
.kviewer-form-checkbox--styled{align-items:center;background:#fff;border:1px solid #444;cursor:pointer;display:flex;height:100%;justify-content:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.kviewer-form-checkbox--styled[aria-disabled=true]{cursor:not-allowed;opacity:.6}.kviewer-form-checkbox__glyph{color:#000;font-size:clamp(8px,88cqh,64px);font-variant-emoji:text;line-height:1;pointer-events:none}.kviewer-form-checkbox--styled{container-type:size}
|
|
83
|
+
</style>
|
|
@@ -74,7 +74,9 @@ const props = defineProps({
|
|
|
74
74
|
});
|
|
75
75
|
const formFields = useFormFields();
|
|
76
76
|
const state = useViewerState();
|
|
77
|
-
const isReadOnly = computed(
|
|
77
|
+
const isReadOnly = computed(
|
|
78
|
+
() => state.readonly.value || props.field.readOnly || formFields.isFieldLocked(props.field.id)
|
|
79
|
+
);
|
|
78
80
|
const datalistId = computed(() => `kviewer-datalist-${props.field.id}`);
|
|
79
81
|
const listBoxSize = computed(() => {
|
|
80
82
|
const optCount = props.field.options?.length ?? 0;
|
|
@@ -2,7 +2,18 @@ import type { FormFieldDefinition } from '../../annotation/engine/types.js';
|
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
field: FormFieldDefinition;
|
|
4
4
|
pageHeight: number;
|
|
5
|
+
scale: number;
|
|
6
|
+
/** PDF user-space origin (view[0], view[1]). /Rect coords are in
|
|
7
|
+
* default user space; the canvas top-left corresponds to PDF
|
|
8
|
+
* (viewOffsetX, viewOffsetY + pageHeight), so we have to subtract. */
|
|
9
|
+
viewOffsetX?: number;
|
|
10
|
+
viewOffsetY?: number;
|
|
11
|
+
selected: boolean;
|
|
5
12
|
};
|
|
6
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}
|
|
13
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
|
+
select: () => any;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
|
+
onSelect?: (() => any) | undefined;
|
|
17
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
18
|
declare const _default: typeof __VLS_export;
|
|
8
19
|
export default _default;
|
|
@@ -1,33 +1,72 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="kviewer-form-field"
|
|
4
|
-
:
|
|
4
|
+
:class="{
|
|
5
|
+
'kviewer-form-field--editable': showChrome,
|
|
6
|
+
'kviewer-form-field--placed': isPlaced,
|
|
7
|
+
'kviewer-form-field--selected': props.selected
|
|
8
|
+
}"
|
|
9
|
+
:style="[positionStyle, { '--kvw-field-color': chromeColor }]"
|
|
5
10
|
>
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
<div
|
|
12
|
+
class="kviewer-form-field__body"
|
|
13
|
+
:class="{ 'kviewer-form-field__body--locked': isFormEditMode }"
|
|
14
|
+
>
|
|
15
|
+
<FormTextField v-if="props.field.fieldType === 'text'" :field="props.field" />
|
|
16
|
+
<FormCheckbox v-else-if="props.field.fieldType === 'checkbox'" :field="props.field" />
|
|
17
|
+
<FormRadioButton v-else-if="props.field.fieldType === 'radio'" :field="props.field" />
|
|
18
|
+
<FormDropdown v-else-if="props.field.fieldType === 'dropdown'" :field="props.field" />
|
|
19
|
+
<FormSignatureField v-else-if="props.field.fieldType === 'signature'" :field="props.field" />
|
|
20
|
+
<FormButton v-else-if="props.field.fieldType === 'button'" :field="props.field" />
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<PlacedFieldChrome
|
|
24
|
+
v-if="showChrome"
|
|
25
|
+
:field="props.field"
|
|
26
|
+
:selected="props.selected"
|
|
27
|
+
:scale="props.scale"
|
|
28
|
+
:page-height="props.pageHeight"
|
|
29
|
+
@select="emit('select')"
|
|
30
|
+
/>
|
|
12
31
|
</div>
|
|
13
32
|
</template>
|
|
14
33
|
|
|
15
34
|
<script setup>
|
|
16
35
|
import { computed } from "vue";
|
|
36
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
37
|
+
import { useFormFields } from "../../composables/useFormFields";
|
|
17
38
|
import FormTextField from "./FormTextField.vue";
|
|
18
39
|
import FormCheckbox from "./FormCheckbox.vue";
|
|
19
40
|
import FormRadioButton from "./FormRadioButton.vue";
|
|
20
41
|
import FormDropdown from "./FormDropdown.vue";
|
|
21
42
|
import FormSignatureField from "./FormSignatureField.vue";
|
|
22
43
|
import FormButton from "./FormButton.vue";
|
|
44
|
+
import PlacedFieldChrome from "./PlacedFieldChrome.vue";
|
|
23
45
|
const props = defineProps({
|
|
24
46
|
field: { type: Object, required: true },
|
|
25
|
-
pageHeight: { type: Number, required: true }
|
|
47
|
+
pageHeight: { type: Number, required: true },
|
|
48
|
+
scale: { type: Number, required: true },
|
|
49
|
+
viewOffsetX: { type: Number, required: false },
|
|
50
|
+
viewOffsetY: { type: Number, required: false },
|
|
51
|
+
selected: { type: Boolean, required: true }
|
|
52
|
+
});
|
|
53
|
+
const emit = defineEmits(["select"]);
|
|
54
|
+
const state = useViewerState();
|
|
55
|
+
const formFields = useFormFields();
|
|
56
|
+
const isPlaced = computed(() => props.field.origin === "placed");
|
|
57
|
+
const isFormEditMode = computed(() => state.formEditMode.value);
|
|
58
|
+
const showChrome = computed(() => isFormEditMode.value);
|
|
59
|
+
const chromeColor = computed(() => {
|
|
60
|
+
const id = props.field.roleId;
|
|
61
|
+
if (!id) return "#1677ff";
|
|
62
|
+
return formFields.roleColors.value[id] ?? "#1677ff";
|
|
26
63
|
});
|
|
27
64
|
const positionStyle = computed(() => {
|
|
28
65
|
const rect = props.field.rect;
|
|
29
|
-
const
|
|
30
|
-
const
|
|
66
|
+
const vx = props.viewOffsetX ?? 0;
|
|
67
|
+
const vy = props.viewOffsetY ?? 0;
|
|
68
|
+
const left = rect[0] - vx;
|
|
69
|
+
const top = props.pageHeight + vy - rect[3];
|
|
31
70
|
const width = rect[2] - rect[0];
|
|
32
71
|
const height = rect[3] - rect[1];
|
|
33
72
|
return {
|
|
@@ -39,3 +78,7 @@ const positionStyle = computed(() => {
|
|
|
39
78
|
};
|
|
40
79
|
});
|
|
41
80
|
</script>
|
|
81
|
+
|
|
82
|
+
<style>
|
|
83
|
+
.kviewer-form-field__body{height:100%;width:100%}.kviewer-form-field__body--locked{pointer-events:none}.kviewer-form-field--editable{outline:1px dashed color-mix(in srgb,var(--kvw-field-color,#1677ff) 45%,transparent);outline-offset:0}.kviewer-form-field--editable.kviewer-form-field--placed{outline-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 75%,transparent)}.kviewer-form-field--editable.kviewer-form-field--selected{outline:none}
|
|
84
|
+
</style>
|
|
@@ -2,7 +2,18 @@ import type { FormFieldDefinition } from '../../annotation/engine/types.js';
|
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
field: FormFieldDefinition;
|
|
4
4
|
pageHeight: number;
|
|
5
|
+
scale: number;
|
|
6
|
+
/** PDF user-space origin (view[0], view[1]). /Rect coords are in
|
|
7
|
+
* default user space; the canvas top-left corresponds to PDF
|
|
8
|
+
* (viewOffsetX, viewOffsetY + pageHeight), so we have to subtract. */
|
|
9
|
+
viewOffsetX?: number;
|
|
10
|
+
viewOffsetY?: number;
|
|
11
|
+
selected: boolean;
|
|
5
12
|
};
|
|
6
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}
|
|
13
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
|
+
select: () => any;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
|
+
onSelect?: (() => any) | undefined;
|
|
17
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
18
|
declare const _default: typeof __VLS_export;
|
|
8
19
|
export default _default;
|
|
@@ -21,7 +21,9 @@ const props = defineProps({
|
|
|
21
21
|
});
|
|
22
22
|
const formFields = useFormFields();
|
|
23
23
|
const state = useViewerState();
|
|
24
|
-
const isReadOnly = computed(
|
|
24
|
+
const isReadOnly = computed(
|
|
25
|
+
() => state.readonly.value || props.field.readOnly || formFields.isFieldLocked(props.field.id)
|
|
26
|
+
);
|
|
25
27
|
const isSelected = computed(() => {
|
|
26
28
|
const fv = formFields.getFieldValue(props.field.id);
|
|
27
29
|
if (!fv) return false;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
alt="Signature"
|
|
12
12
|
>
|
|
13
13
|
<span v-else class="kviewer-form-signature__placeholder">
|
|
14
|
-
Click to sign
|
|
14
|
+
{{ props.field.promptText || "Click to sign" }}
|
|
15
15
|
</span>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
@@ -43,6 +43,7 @@ const signatureUrl = computed(() => {
|
|
|
43
43
|
const hasSigned = computed(() => !!signatureUrl.value);
|
|
44
44
|
async function onClickSign() {
|
|
45
45
|
if (props.field.readOnly || state.readonly.value) return;
|
|
46
|
+
if (formFields.isFieldLocked(props.field.id)) return;
|
|
46
47
|
if (state.signatures.value.length > 0) {
|
|
47
48
|
const sig = state.signatures.value[0];
|
|
48
49
|
if (sig) {
|
|
@@ -19,11 +19,13 @@
|
|
|
19
19
|
:style="fieldStyle"
|
|
20
20
|
class="kviewer-form-input"
|
|
21
21
|
@input="onInput"
|
|
22
|
+
@scroll="onScroll"
|
|
22
23
|
>
|
|
23
24
|
</template>
|
|
24
25
|
|
|
25
26
|
<script setup>
|
|
26
27
|
import { computed } from "vue";
|
|
28
|
+
import { decodeFontName } from "../../annotation/font-style";
|
|
27
29
|
import { useFormFields } from "../../composables/useFormFields";
|
|
28
30
|
import { useViewerState } from "../../composables/useViewerState";
|
|
29
31
|
const props = defineProps({
|
|
@@ -31,18 +33,37 @@ const props = defineProps({
|
|
|
31
33
|
});
|
|
32
34
|
const formFields = useFormFields();
|
|
33
35
|
const state = useViewerState();
|
|
34
|
-
const isReadOnly = computed(
|
|
36
|
+
const isReadOnly = computed(
|
|
37
|
+
() => state.readonly.value || props.field.readOnly || formFields.isFieldLocked(props.field.id)
|
|
38
|
+
);
|
|
35
39
|
const currentValue = computed(() => {
|
|
36
40
|
const fv = formFields.getFieldValue(props.field.id);
|
|
37
41
|
return typeof fv?.value === "string" ? fv.value : "";
|
|
38
42
|
});
|
|
43
|
+
const FONT_BORDER_SIZE = 2;
|
|
44
|
+
const LINE_HEIGHT_FACTOR = 1.35;
|
|
45
|
+
const DEFAULT_FIELD_FONT_SIZE = 9;
|
|
39
46
|
const fieldStyle = computed(() => {
|
|
40
47
|
const style = {};
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
const declared = props.field.fontSize && props.field.fontSize > 0 ? props.field.fontSize : DEFAULT_FIELD_FONT_SIZE;
|
|
49
|
+
const rect = props.field.rect;
|
|
50
|
+
const rectHeight = Math.abs(rect[3] - rect[1] - FONT_BORDER_SIZE);
|
|
51
|
+
let computed2;
|
|
52
|
+
if (props.field.multiLine) {
|
|
53
|
+
const numberOfLines = Math.max(
|
|
54
|
+
1,
|
|
55
|
+
Math.round(rectHeight / (LINE_HEIGHT_FACTOR * declared))
|
|
56
|
+
);
|
|
57
|
+
const lineHeight = rectHeight / numberOfLines;
|
|
58
|
+
computed2 = Math.min(declared, lineHeight / LINE_HEIGHT_FACTOR);
|
|
43
59
|
} else {
|
|
44
|
-
|
|
60
|
+
computed2 = Math.min(declared, rectHeight / LINE_HEIGHT_FACTOR);
|
|
45
61
|
}
|
|
62
|
+
style.fontSize = `${Math.round(10 * computed2) / 10}px`;
|
|
63
|
+
const fontStyle = decodeFontName(props.field.fontName);
|
|
64
|
+
style.fontFamily = fontStyle.fontFamily;
|
|
65
|
+
if (fontStyle.fontWeight !== "normal") style.fontWeight = fontStyle.fontWeight;
|
|
66
|
+
if (fontStyle.fontStyle !== "normal") style.fontStyle = fontStyle.fontStyle;
|
|
46
67
|
if (props.field.color && props.field.color.length >= 3) {
|
|
47
68
|
style.color = `rgb(${props.field.color[0]}, ${props.field.color[1]}, ${props.field.color[2]})`;
|
|
48
69
|
}
|
|
@@ -54,16 +75,35 @@ const fieldStyle = computed(() => {
|
|
|
54
75
|
style.textAlign = alignMap[props.field.textAlignment] ?? "left";
|
|
55
76
|
}
|
|
56
77
|
if (props.field.comb && props.field.maxLen && props.field.maxLen > 0) {
|
|
57
|
-
const rect = props.field.rect;
|
|
58
78
|
const fieldWidth = rect[2] - rect[0];
|
|
59
79
|
const cellWidth = fieldWidth / props.field.maxLen;
|
|
60
|
-
|
|
61
|
-
style.fontFamily = "monospace
|
|
80
|
+
const charWidth = computed2 * 0.6;
|
|
81
|
+
style.fontFamily = '"Courier New", Courier, monospace';
|
|
82
|
+
style.fontWeight = "700";
|
|
83
|
+
style.textAlign = "left";
|
|
84
|
+
style.letterSpacing = `${cellWidth - charWidth}px`;
|
|
85
|
+
style.paddingLeft = `${Math.max(0, (cellWidth - charWidth) / 2)}px`;
|
|
86
|
+
style.paddingRight = "0";
|
|
87
|
+
style.paddingTop = "0";
|
|
88
|
+
style.paddingBottom = "0";
|
|
89
|
+
style.borderLeftWidth = "0";
|
|
90
|
+
style.backgroundImage = "linear-gradient(to right, rgba(0, 0, 0, 0.55) 1px, transparent 1px)";
|
|
91
|
+
style.backgroundSize = `${100 / props.field.maxLen}% 100%`;
|
|
92
|
+
style.backgroundRepeat = "repeat-x";
|
|
93
|
+
style.borderTop = "1px solid rgba(0, 0, 0, 0.55)";
|
|
94
|
+
style.borderBottom = "1px solid rgba(0, 0, 0, 0.55)";
|
|
95
|
+
style.borderRight = "1px solid rgba(0, 0, 0, 0.55)";
|
|
62
96
|
}
|
|
63
97
|
return style;
|
|
64
98
|
});
|
|
65
99
|
function onInput(event) {
|
|
66
100
|
const target = event.target;
|
|
67
101
|
formFields.setFieldValue(props.field.id, target.value);
|
|
102
|
+
if (props.field.comb) target.scrollLeft = 0;
|
|
103
|
+
}
|
|
104
|
+
function onScroll(event) {
|
|
105
|
+
if (!props.field.comb) return;
|
|
106
|
+
const target = event.target;
|
|
107
|
+
if (target.scrollLeft !== 0) target.scrollLeft = 0;
|
|
68
108
|
}
|
|
69
109
|
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FormFieldDefinition } from '../../annotation/engine/types.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
field: FormFieldDefinition;
|
|
4
|
+
selected: boolean;
|
|
5
|
+
/** CSS pixels per PDF unit for the current page. */
|
|
6
|
+
scale: number;
|
|
7
|
+
/** PDF-space page height (kept for parity; unused here). */
|
|
8
|
+
pageHeight: number;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
11
|
+
select: () => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
onSelect?: (() => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- The whole chrome is the interactive surface in form-edit mode:
|
|
3
|
+
click to select, drag anywhere to move, plus a label bar above and
|
|
4
|
+
eight resize handles when selected. -->
|
|
5
|
+
<div
|
|
6
|
+
ref="rootEl"
|
|
7
|
+
class="kviewer-placed-chrome"
|
|
8
|
+
:class="{ 'kviewer-placed-chrome--selected': selected }"
|
|
9
|
+
:style="{ '--kvw-handle-zoom': handleZoom }"
|
|
10
|
+
@pointerdown.stop="onChromePointerDown"
|
|
11
|
+
@click.stop
|
|
12
|
+
>
|
|
13
|
+
<div
|
|
14
|
+
v-if="selected"
|
|
15
|
+
class="kviewer-placed-chrome__grip"
|
|
16
|
+
:title="field.fieldName"
|
|
17
|
+
>
|
|
18
|
+
<UIcon name="i-lucide-grip-vertical" class="kviewer-placed-chrome__grip-dots" />
|
|
19
|
+
<span class="kviewer-placed-chrome__grip-label">{{ field.fieldName }}</span>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<template v-if="selected">
|
|
23
|
+
<div
|
|
24
|
+
v-for="h in handles"
|
|
25
|
+
:key="h.name"
|
|
26
|
+
class="kviewer-placed-chrome__handle"
|
|
27
|
+
:class="`kviewer-placed-chrome__handle--${h.name}`"
|
|
28
|
+
:style="{ cursor: h.cursor }"
|
|
29
|
+
@pointerdown.stop="(e) => onHandlePointerDown(e, h.name)"
|
|
30
|
+
/>
|
|
31
|
+
</template>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script setup>
|
|
36
|
+
import { computed, ref } from "vue";
|
|
37
|
+
import { useFormFields } from "../../composables/useFormFields";
|
|
38
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
39
|
+
const rootEl = ref(null);
|
|
40
|
+
const viewerState = useViewerState();
|
|
41
|
+
const handleZoom = computed(() => {
|
|
42
|
+
const totalZoom = (props.scale || 1) * (viewerState.visualZoom.value || 1);
|
|
43
|
+
return Math.max(0.4, 1 / totalZoom).toFixed(3);
|
|
44
|
+
});
|
|
45
|
+
const props = defineProps({
|
|
46
|
+
field: { type: Object, required: true },
|
|
47
|
+
selected: { type: Boolean, required: true },
|
|
48
|
+
scale: { type: Number, required: true },
|
|
49
|
+
pageHeight: { type: Number, required: true }
|
|
50
|
+
});
|
|
51
|
+
const emit = defineEmits(["select"]);
|
|
52
|
+
const formFields = useFormFields();
|
|
53
|
+
const handles = [
|
|
54
|
+
{ name: "n", cursor: "ns-resize" },
|
|
55
|
+
{ name: "s", cursor: "ns-resize" },
|
|
56
|
+
{ name: "e", cursor: "ew-resize" },
|
|
57
|
+
{ name: "w", cursor: "ew-resize" },
|
|
58
|
+
{ name: "ne", cursor: "nesw-resize" },
|
|
59
|
+
{ name: "nw", cursor: "nwse-resize" },
|
|
60
|
+
{ name: "se", cursor: "nwse-resize" },
|
|
61
|
+
{ name: "sw", cursor: "nesw-resize" }
|
|
62
|
+
];
|
|
63
|
+
function effectiveScale() {
|
|
64
|
+
const el = rootEl.value;
|
|
65
|
+
if (!el) return props.scale;
|
|
66
|
+
const rect = el.getBoundingClientRect();
|
|
67
|
+
const pdfWidth = props.field.rect[2] - props.field.rect[0];
|
|
68
|
+
if (pdfWidth <= 0 || rect.width <= 0) return props.scale;
|
|
69
|
+
return rect.width / pdfWidth;
|
|
70
|
+
}
|
|
71
|
+
const DRAG_THRESHOLD_PX = 3;
|
|
72
|
+
function onChromePointerDown(e) {
|
|
73
|
+
const startX = e.clientX;
|
|
74
|
+
const startY = e.clientY;
|
|
75
|
+
const startRect = [...props.field.rect];
|
|
76
|
+
const s = effectiveScale();
|
|
77
|
+
let dragging = false;
|
|
78
|
+
const onMove = (ev) => {
|
|
79
|
+
if (!dragging) {
|
|
80
|
+
const adx = Math.abs(ev.clientX - startX);
|
|
81
|
+
const ady = Math.abs(ev.clientY - startY);
|
|
82
|
+
if (adx < DRAG_THRESHOLD_PX && ady < DRAG_THRESHOLD_PX) return;
|
|
83
|
+
dragging = true;
|
|
84
|
+
}
|
|
85
|
+
const dx = (ev.clientX - startX) / s;
|
|
86
|
+
const dy = (ev.clientY - startY) / s;
|
|
87
|
+
const pdfDy = -dy;
|
|
88
|
+
const next = [
|
|
89
|
+
startRect[0] + dx,
|
|
90
|
+
startRect[1] + pdfDy,
|
|
91
|
+
startRect[2] + dx,
|
|
92
|
+
startRect[3] + pdfDy
|
|
93
|
+
];
|
|
94
|
+
formFields.updatePlacedField(props.field.id, { rect: next });
|
|
95
|
+
};
|
|
96
|
+
const onUp = () => {
|
|
97
|
+
window.removeEventListener("pointermove", onMove);
|
|
98
|
+
window.removeEventListener("pointerup", onUp);
|
|
99
|
+
if (!dragging) emit("select");
|
|
100
|
+
};
|
|
101
|
+
window.addEventListener("pointermove", onMove);
|
|
102
|
+
window.addEventListener("pointerup", onUp);
|
|
103
|
+
}
|
|
104
|
+
function onHandlePointerDown(e, name) {
|
|
105
|
+
const startX = e.clientX;
|
|
106
|
+
const startY = e.clientY;
|
|
107
|
+
const [sx1, sy1, sx2, sy2] = props.field.rect;
|
|
108
|
+
const s = effectiveScale();
|
|
109
|
+
const onMove = (ev) => {
|
|
110
|
+
const dx = (ev.clientX - startX) / s;
|
|
111
|
+
const dy = (ev.clientY - startY) / s;
|
|
112
|
+
const pdfDy = -dy;
|
|
113
|
+
let x1 = sx1, y1 = sy1, x2 = sx2, y2 = sy2;
|
|
114
|
+
if (name.includes("n")) y2 = Math.max(y1 + 4, sy2 + pdfDy);
|
|
115
|
+
if (name.includes("s")) y1 = Math.min(y2 - 4, sy1 + pdfDy);
|
|
116
|
+
if (name.includes("e")) x2 = Math.max(x1 + 4, sx2 + dx);
|
|
117
|
+
if (name.includes("w")) x1 = Math.min(x2 - 4, sx1 + dx);
|
|
118
|
+
formFields.updatePlacedField(props.field.id, { rect: [x1, y1, x2, y2] });
|
|
119
|
+
};
|
|
120
|
+
const onUp = () => {
|
|
121
|
+
window.removeEventListener("pointermove", onMove);
|
|
122
|
+
window.removeEventListener("pointerup", onUp);
|
|
123
|
+
};
|
|
124
|
+
window.addEventListener("pointermove", onMove);
|
|
125
|
+
window.addEventListener("pointerup", onUp);
|
|
126
|
+
}
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
<style>
|
|
130
|
+
.kviewer-placed-chrome{cursor:move;inset:0;pointer-events:auto;position:absolute;touch-action:none}.kviewer-placed-chrome--selected{outline:1.5px dashed var(--kvw-field-color,#1677ff);outline-offset:0}.kviewer-placed-chrome__grip{align-items:center;background:color-mix(in srgb,var(--kvw-field-color,#1677ff) 15%,transparent);border:1px solid color-mix(in srgb,var(--kvw-field-color,#1677ff) 40%,transparent);border-radius:calc(3px*var(--kvw-handle-zoom, 1));bottom:calc(100% + 3px*var(--kvw-handle-zoom, 1));color:var(--kvw-field-color,#1677ff);cursor:move;display:flex;font-size:calc(9px*var(--kvw-handle-zoom, 1));gap:calc(3px*var(--kvw-handle-zoom, 1));height:calc(16px*var(--kvw-handle-zoom, 1));left:0;line-height:1;overflow:hidden;padding:0 calc(6px*var(--kvw-handle-zoom, 1)) 0 calc(2px*var(--kvw-handle-zoom, 1));pointer-events:auto;position:absolute;right:0;touch-action:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.kviewer-placed-chrome__grip-dots{color:var(--kvw-field-color,#1677ff);flex:0 0 auto;height:calc(10px*var(--kvw-handle-zoom, 1));width:calc(10px*var(--kvw-handle-zoom, 1))}.kviewer-placed-chrome__grip-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kviewer-placed-chrome__handle{background:#fff;border:1px solid var(--kvw-field-color,#1677ff);border-radius:2px;height:calc(8px*var(--kvw-handle-zoom, 1));pointer-events:auto;position:absolute;touch-action:none;width:calc(8px*var(--kvw-handle-zoom, 1))}.kviewer-placed-chrome__handle:before{content:"";inset:calc(-8px*var(--kvw-handle-zoom, 1));position:absolute}.kviewer-placed-chrome__handle--n{left:50%;top:calc(-4px*var(--kvw-handle-zoom, 1));transform:translateX(-50%)}.kviewer-placed-chrome__handle--s{bottom:calc(-4px*var(--kvw-handle-zoom, 1));left:50%;transform:translateX(-50%)}.kviewer-placed-chrome__handle--e{right:calc(-4px*var(--kvw-handle-zoom, 1));top:50%;transform:translateY(-50%)}.kviewer-placed-chrome__handle--w{left:calc(-4px*var(--kvw-handle-zoom, 1));top:50%;transform:translateY(-50%)}.kviewer-placed-chrome__handle--ne{right:calc(-4px*var(--kvw-handle-zoom, 1));top:calc(-4px*var(--kvw-handle-zoom, 1))}.kviewer-placed-chrome__handle--nw{left:calc(-4px*var(--kvw-handle-zoom, 1));top:calc(-4px*var(--kvw-handle-zoom, 1))}.kviewer-placed-chrome__handle--se{bottom:calc(-4px*var(--kvw-handle-zoom, 1));right:calc(-4px*var(--kvw-handle-zoom, 1))}.kviewer-placed-chrome__handle--sw{bottom:calc(-4px*var(--kvw-handle-zoom, 1));left:calc(-4px*var(--kvw-handle-zoom, 1))}
|
|
131
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FormFieldDefinition } from '../../annotation/engine/types.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
field: FormFieldDefinition;
|
|
4
|
+
selected: boolean;
|
|
5
|
+
/** CSS pixels per PDF unit for the current page. */
|
|
6
|
+
scale: number;
|
|
7
|
+
/** PDF-space page height (kept for parity; unused here). */
|
|
8
|
+
pageHeight: number;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
11
|
+
select: () => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
onSelect?: (() => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|