kviewer 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/annotation/engine/painter.d.ts +3 -1
- package/dist/runtime/annotation/engine/painter.js +5 -1
- package/dist/runtime/components/AnnotationToolbar.vue +1 -1
- package/dist/runtime/components/PdfPage.vue +8 -2
- package/dist/runtime/components/Viewer.d.vue.ts +2 -0
- package/dist/runtime/components/Viewer.vue +7 -2
- package/dist/runtime/components/Viewer.vue.d.ts +2 -0
- package/dist/runtime/components/ViewerBar.vue +6 -4
- package/dist/runtime/components/ViewerTabs.d.vue.ts +2 -0
- package/dist/runtime/components/ViewerTabs.vue +2 -0
- package/dist/runtime/components/ViewerTabs.vue.d.ts +2 -0
- package/dist/runtime/components/form-fields/FormButton.vue +4 -1
- package/dist/runtime/components/form-fields/FormCheckbox.vue +4 -1
- package/dist/runtime/components/form-fields/FormDropdown.vue +6 -3
- package/dist/runtime/components/form-fields/FormRadioButton.vue +4 -1
- package/dist/runtime/components/form-fields/FormSignatureField.vue +1 -1
- package/dist/runtime/components/form-fields/FormTextField.vue +5 -2
- package/dist/runtime/composables/useAnnotationEngine.js +2 -1
- package/dist/runtime/composables/useViewerState.d.ts +1 -0
- package/dist/runtime/composables/useViewerState.js +5 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -31,10 +31,12 @@ export declare class Painter {
|
|
|
31
31
|
private tempDataTransfer;
|
|
32
32
|
private callbacks;
|
|
33
33
|
private getStylusModeEnabled?;
|
|
34
|
-
|
|
34
|
+
private getReadonly?;
|
|
35
|
+
constructor({ userName, callbacks, getStylusModeEnabled, getReadonly, }: {
|
|
35
36
|
userName: string;
|
|
36
37
|
callbacks: PainterCallbacks;
|
|
37
38
|
getStylusModeEnabled?: () => boolean;
|
|
39
|
+
getReadonly?: () => boolean;
|
|
38
40
|
});
|
|
39
41
|
private editFreeText;
|
|
40
42
|
private bindGlobalEvents;
|
|
@@ -33,14 +33,17 @@ export class Painter {
|
|
|
33
33
|
tempDataTransfer = null;
|
|
34
34
|
callbacks;
|
|
35
35
|
getStylusModeEnabled;
|
|
36
|
+
getReadonly;
|
|
36
37
|
constructor({
|
|
37
38
|
userName,
|
|
38
39
|
callbacks,
|
|
39
|
-
getStylusModeEnabled
|
|
40
|
+
getStylusModeEnabled,
|
|
41
|
+
getReadonly
|
|
40
42
|
}) {
|
|
41
43
|
this.userName = userName;
|
|
42
44
|
this.callbacks = callbacks;
|
|
43
45
|
this.getStylusModeEnabled = getStylusModeEnabled;
|
|
46
|
+
this.getReadonly = getReadonly;
|
|
44
47
|
this.store = new Store();
|
|
45
48
|
this.selector = new Selector({
|
|
46
49
|
konvaCanvasStore: this.konvaCanvasStore,
|
|
@@ -110,6 +113,7 @@ export class Painter {
|
|
|
110
113
|
window.addEventListener("keyup", this.globalKeyUpHandler);
|
|
111
114
|
}
|
|
112
115
|
globalKeyUpHandler = (e) => {
|
|
116
|
+
if (this.getReadonly?.()) return;
|
|
113
117
|
if (e.code === "Escape" && this.currentAnnotation && (this.currentAnnotation.type === AnnotationType.SIGNATURE || this.currentAnnotation.type === AnnotationType.STAMP)) {
|
|
114
118
|
hideCursorPreview();
|
|
115
119
|
this.callbacks.forceReset();
|
|
@@ -65,7 +65,7 @@ const state = useViewerState();
|
|
|
65
65
|
const colors = defaultOptions.colors;
|
|
66
66
|
const isMultiSelect = computed(() => state.selectedAnnotations.value.length > 1);
|
|
67
67
|
const hasSelection = computed(
|
|
68
|
-
() => state.selectedAnnotation.value !== null || state.selectedAnnotations.value.length > 0
|
|
68
|
+
() => !state.readonly.value && (state.selectedAnnotation.value !== null || state.selectedAnnotations.value.length > 0)
|
|
69
69
|
);
|
|
70
70
|
const selectedDef = computed(() => {
|
|
71
71
|
const ann = state.selectedAnnotation.value;
|
|
@@ -82,12 +82,18 @@ const isAnnotating = computed(() => {
|
|
|
82
82
|
return tool === "hand" || tool === "marquee" || tool === "eraser" || typeof tool === "number" && tool !== AnnotationType.NONE;
|
|
83
83
|
});
|
|
84
84
|
const isSearchTextInteractive = computed(() => search.isOpen.value && state.activeTool.value === "hand");
|
|
85
|
-
const annotationPointerEvents = computed(() =>
|
|
85
|
+
const annotationPointerEvents = computed(() => {
|
|
86
|
+
if (state.readonly.value) return "none";
|
|
87
|
+
return isSearchTextInteractive.value ? "none" : isAnnotating.value ? "auto" : "none";
|
|
88
|
+
});
|
|
86
89
|
const isUsingAnnotationTool = computed(() => {
|
|
87
90
|
const tool = state.activeTool.value;
|
|
88
91
|
return tool === "marquee" || tool === "eraser" || typeof tool === "number" && tool !== AnnotationType.NONE;
|
|
89
92
|
});
|
|
90
|
-
const formFieldPointerEvents = computed(() =>
|
|
93
|
+
const formFieldPointerEvents = computed(() => {
|
|
94
|
+
if (state.readonly.value) return "none";
|
|
95
|
+
return isUsingAnnotationTool.value ? "none" : "auto";
|
|
96
|
+
});
|
|
91
97
|
const formFieldZIndex = computed(() => isUsingAnnotationTool.value ? 2 : 4);
|
|
92
98
|
onMounted(async () => {
|
|
93
99
|
pageProxy.value = await proxyCache.getPage(props.pageNumber);
|
|
@@ -9,6 +9,8 @@ type __VLS_Props = {
|
|
|
9
9
|
signatureHandlers?: SignatureHandlers;
|
|
10
10
|
viewMode?: ViewMode;
|
|
11
11
|
zoom?: number;
|
|
12
|
+
/** When true, the viewer is in view-only mode: annotations, drawing tools, and form editing are disabled. */
|
|
13
|
+
readonly?: boolean;
|
|
12
14
|
/** When false, global keyboard shortcuts (e.g. Cmd+F) are suppressed. Used by ViewerTabs to prevent hidden viewers from capturing input. */
|
|
13
15
|
active?: boolean;
|
|
14
16
|
};
|
|
@@ -96,11 +96,11 @@
|
|
|
96
96
|
<!-- Footer slot: empty by default -->
|
|
97
97
|
<slot name="footer" />
|
|
98
98
|
|
|
99
|
-
<ClientOnly>
|
|
99
|
+
<ClientOnly v-if="!viewerState.readonly.value">
|
|
100
100
|
<AnnotationToolbar />
|
|
101
101
|
</ClientOnly>
|
|
102
102
|
|
|
103
|
-
<ClientOnly>
|
|
103
|
+
<ClientOnly v-if="!viewerState.readonly.value">
|
|
104
104
|
<FreeTextModal
|
|
105
105
|
v-model:open="freeTextModalOpen"
|
|
106
106
|
:default-color="freeTextDefaults.color"
|
|
@@ -119,6 +119,7 @@ import {
|
|
|
119
119
|
shallowRef,
|
|
120
120
|
computed,
|
|
121
121
|
watch,
|
|
122
|
+
watchEffect,
|
|
122
123
|
nextTick,
|
|
123
124
|
triggerRef,
|
|
124
125
|
onMounted,
|
|
@@ -150,11 +151,15 @@ const props = defineProps({
|
|
|
150
151
|
signatureHandlers: { type: Object, required: false, default: void 0 },
|
|
151
152
|
viewMode: { type: String, required: false, default: "fit-width" },
|
|
152
153
|
zoom: { type: Number, required: false, default: 1 },
|
|
154
|
+
readonly: { type: Boolean, required: false, default: false },
|
|
153
155
|
active: { type: Boolean, required: false, default: true }
|
|
154
156
|
});
|
|
155
157
|
const viewerRoot = ref(null);
|
|
156
158
|
const scrollContainer = ref(null);
|
|
157
159
|
const { state: viewerState, setScrollToPageFn } = provideViewerState();
|
|
160
|
+
watchEffect(() => {
|
|
161
|
+
viewerState.readonly.value = props.readonly ?? false;
|
|
162
|
+
});
|
|
158
163
|
const viewerSearch = provideViewerSearch();
|
|
159
164
|
const formFieldsState = provideFormFields();
|
|
160
165
|
const pageSettings = providePageSettings(viewerRoot);
|
|
@@ -9,6 +9,8 @@ type __VLS_Props = {
|
|
|
9
9
|
signatureHandlers?: SignatureHandlers;
|
|
10
10
|
viewMode?: ViewMode;
|
|
11
11
|
zoom?: number;
|
|
12
|
+
/** When true, the viewer is in view-only mode: annotations, drawing tools, and form editing are disabled. */
|
|
13
|
+
readonly?: boolean;
|
|
12
14
|
/** When false, global keyboard shortcuts (e.g. Cmd+F) are suppressed. Used by ViewerTabs to prevent hidden viewers from capturing input. */
|
|
13
15
|
active?: boolean;
|
|
14
16
|
};
|
|
@@ -24,10 +24,12 @@
|
|
|
24
24
|
|
|
25
25
|
<ZoomControls />
|
|
26
26
|
|
|
27
|
-
<
|
|
27
|
+
<template v-if="!state.readonly.value">
|
|
28
|
+
<USeparator orientation="vertical" class="h-5" color="neutral" />
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
<HandTool />
|
|
31
|
+
<MarqueeTool />
|
|
32
|
+
</template>
|
|
31
33
|
|
|
32
34
|
<div class="ml-auto flex items-center gap-2">
|
|
33
35
|
<PageInfo />
|
|
@@ -36,7 +38,7 @@
|
|
|
36
38
|
</div>
|
|
37
39
|
|
|
38
40
|
<!-- Tool bar -->
|
|
39
|
-
<div class="grid grid-cols-3 items-center h-11 px-3 gap-2 bg-elevated">
|
|
41
|
+
<div v-if="!state.readonly.value" class="grid grid-cols-3 items-center h-11 px-3 gap-2 bg-elevated">
|
|
40
42
|
<div class="justify-self-start">
|
|
41
43
|
<ToolProperties @style-updated="bumpStyleVersion" />
|
|
42
44
|
</div>
|
|
@@ -36,6 +36,8 @@ type __VLS_Props = {
|
|
|
36
36
|
signatureHandlers?: SignatureHandlers;
|
|
37
37
|
/** Enable text layer on all Viewer instances. */
|
|
38
38
|
textLayer?: boolean;
|
|
39
|
+
/** When true, all viewers are in view-only mode. */
|
|
40
|
+
readonly?: boolean;
|
|
39
41
|
/** Default view mode for tabs without a per-tab override. */
|
|
40
42
|
viewMode?: ViewMode;
|
|
41
43
|
/** Default zoom for tabs without a per-tab override. */
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
:signature-handlers="signatureHandlers"
|
|
57
57
|
:view-mode="tab.viewMode ?? viewMode"
|
|
58
58
|
:zoom="tab.zoom ?? zoom"
|
|
59
|
+
:readonly="readonly"
|
|
59
60
|
>
|
|
60
61
|
<template v-if="$slots.header" #header>
|
|
61
62
|
<slot name="header" :tab="tab" />
|
|
@@ -84,6 +85,7 @@ const props = defineProps({
|
|
|
84
85
|
userName: { type: String, required: false, default: void 0 },
|
|
85
86
|
signatureHandlers: { type: Object, required: false, default: void 0 },
|
|
86
87
|
textLayer: { type: Boolean, required: false },
|
|
88
|
+
readonly: { type: Boolean, required: false },
|
|
87
89
|
viewMode: { type: String, required: false, default: "fit-width" },
|
|
88
90
|
zoom: { type: Number, required: false, default: 1 },
|
|
89
91
|
minTabs: { type: Number, required: false, default: 0 }
|
|
@@ -36,6 +36,8 @@ type __VLS_Props = {
|
|
|
36
36
|
signatureHandlers?: SignatureHandlers;
|
|
37
37
|
/** Enable text layer on all Viewer instances. */
|
|
38
38
|
textLayer?: boolean;
|
|
39
|
+
/** When true, all viewers are in view-only mode. */
|
|
40
|
+
readonly?: boolean;
|
|
39
41
|
/** Default view mode for tabs without a per-tab override. */
|
|
40
42
|
viewMode?: ViewMode;
|
|
41
43
|
/** Default zoom for tabs without a per-tab override. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
3
|
type="button"
|
|
4
|
-
:disabled="
|
|
4
|
+
:disabled="isReadOnly"
|
|
5
5
|
:style="buttonStyle"
|
|
6
6
|
class="kviewer-form-button"
|
|
7
7
|
@click="onClick"
|
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
<script setup>
|
|
14
14
|
import { computed } from "vue";
|
|
15
15
|
import { useFormFields } from "../../composables/useFormFields";
|
|
16
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
16
17
|
const props = defineProps({
|
|
17
18
|
field: { type: Object, required: true }
|
|
18
19
|
});
|
|
19
20
|
const formFields = useFormFields();
|
|
21
|
+
const state = useViewerState();
|
|
22
|
+
const isReadOnly = computed(() => state.readonly.value || props.field.readOnly);
|
|
20
23
|
const buttonStyle = computed(() => {
|
|
21
24
|
const style = {};
|
|
22
25
|
if (props.field.fontSize && props.field.fontSize > 0) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<input
|
|
4
4
|
type="checkbox"
|
|
5
5
|
:checked="isChecked"
|
|
6
|
-
:disabled="
|
|
6
|
+
:disabled="isReadOnly"
|
|
7
7
|
:required="props.field.required"
|
|
8
8
|
@change="onChange"
|
|
9
9
|
>
|
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
<script setup>
|
|
14
14
|
import { computed } from "vue";
|
|
15
15
|
import { useFormFields } from "../../composables/useFormFields";
|
|
16
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
16
17
|
const props = defineProps({
|
|
17
18
|
field: { type: Object, required: true }
|
|
18
19
|
});
|
|
19
20
|
const formFields = useFormFields();
|
|
21
|
+
const state = useViewerState();
|
|
22
|
+
const isReadOnly = computed(() => state.readonly.value || props.field.readOnly);
|
|
20
23
|
const isChecked = computed(() => {
|
|
21
24
|
const fv = formFields.getFieldValue(props.field.id);
|
|
22
25
|
return fv?.value === true;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<input
|
|
5
5
|
:value="currentValue"
|
|
6
6
|
:list="datalistId"
|
|
7
|
-
:disabled="
|
|
7
|
+
:disabled="isReadOnly"
|
|
8
8
|
:required="props.field.required"
|
|
9
9
|
:style="fieldStyle"
|
|
10
10
|
class="kviewer-form-input"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<select
|
|
26
26
|
v-else-if="!props.field.combo"
|
|
27
27
|
:value="currentValue"
|
|
28
|
-
:disabled="
|
|
28
|
+
:disabled="isReadOnly"
|
|
29
29
|
:required="props.field.required"
|
|
30
30
|
:multiple="props.field.multiSelect"
|
|
31
31
|
:size="listBoxSize"
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
<select
|
|
47
47
|
v-else
|
|
48
48
|
:value="currentValue"
|
|
49
|
-
:disabled="
|
|
49
|
+
:disabled="isReadOnly"
|
|
50
50
|
:required="props.field.required"
|
|
51
51
|
:style="fieldStyle"
|
|
52
52
|
class="kviewer-form-input kviewer-form-select"
|
|
@@ -68,10 +68,13 @@
|
|
|
68
68
|
<script setup>
|
|
69
69
|
import { computed } from "vue";
|
|
70
70
|
import { useFormFields } from "../../composables/useFormFields";
|
|
71
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
71
72
|
const props = defineProps({
|
|
72
73
|
field: { type: Object, required: true }
|
|
73
74
|
});
|
|
74
75
|
const formFields = useFormFields();
|
|
76
|
+
const state = useViewerState();
|
|
77
|
+
const isReadOnly = computed(() => state.readonly.value || props.field.readOnly);
|
|
75
78
|
const datalistId = computed(() => `kviewer-datalist-${props.field.id}`);
|
|
76
79
|
const listBoxSize = computed(() => {
|
|
77
80
|
const optCount = props.field.options?.length ?? 0;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
:name="props.field.fieldName"
|
|
6
6
|
:value="props.field.buttonValue"
|
|
7
7
|
:checked="isSelected"
|
|
8
|
-
:disabled="
|
|
8
|
+
:disabled="isReadOnly"
|
|
9
9
|
:required="props.field.required"
|
|
10
10
|
@change="onChange"
|
|
11
11
|
>
|
|
@@ -15,10 +15,13 @@
|
|
|
15
15
|
<script setup>
|
|
16
16
|
import { computed } from "vue";
|
|
17
17
|
import { useFormFields } from "../../composables/useFormFields";
|
|
18
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
18
19
|
const props = defineProps({
|
|
19
20
|
field: { type: Object, required: true }
|
|
20
21
|
});
|
|
21
22
|
const formFields = useFormFields();
|
|
23
|
+
const state = useViewerState();
|
|
24
|
+
const isReadOnly = computed(() => state.readonly.value || props.field.readOnly);
|
|
22
25
|
const isSelected = computed(() => {
|
|
23
26
|
const fv = formFields.getFieldValue(props.field.id);
|
|
24
27
|
if (!fv) return false;
|
|
@@ -32,7 +32,7 @@ const signatureUrl = computed(() => {
|
|
|
32
32
|
});
|
|
33
33
|
const hasSigned = computed(() => !!signatureUrl.value);
|
|
34
34
|
async function onClickSign() {
|
|
35
|
-
if (props.field.readOnly) return;
|
|
35
|
+
if (props.field.readOnly || state.readonly.value) return;
|
|
36
36
|
if (state.signatures.value.length > 0) {
|
|
37
37
|
const sig = state.signatures.value[0];
|
|
38
38
|
if (sig) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
v-if="props.field.multiLine"
|
|
4
4
|
:value="currentValue"
|
|
5
5
|
:maxlength="props.field.maxLen || void 0"
|
|
6
|
-
:readonly="
|
|
6
|
+
:readonly="isReadOnly"
|
|
7
7
|
:required="props.field.required"
|
|
8
8
|
:style="fieldStyle"
|
|
9
9
|
class="kviewer-form-input"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
:type="props.field.password ? 'password' : 'text'"
|
|
15
15
|
:value="currentValue"
|
|
16
16
|
:maxlength="props.field.maxLen || void 0"
|
|
17
|
-
:readonly="
|
|
17
|
+
:readonly="isReadOnly"
|
|
18
18
|
:required="props.field.required"
|
|
19
19
|
:style="fieldStyle"
|
|
20
20
|
class="kviewer-form-input"
|
|
@@ -25,10 +25,13 @@
|
|
|
25
25
|
<script setup>
|
|
26
26
|
import { computed } from "vue";
|
|
27
27
|
import { useFormFields } from "../../composables/useFormFields";
|
|
28
|
+
import { useViewerState } from "../../composables/useViewerState";
|
|
28
29
|
const props = defineProps({
|
|
29
30
|
field: { type: Object, required: true }
|
|
30
31
|
});
|
|
31
32
|
const formFields = useFormFields();
|
|
33
|
+
const state = useViewerState();
|
|
34
|
+
const isReadOnly = computed(() => state.readonly.value || props.field.readOnly);
|
|
32
35
|
const currentValue = computed(() => {
|
|
33
36
|
const fv = formFields.getFieldValue(props.field.id);
|
|
34
37
|
return typeof fv?.value === "string" ? fv.value : "";
|
|
@@ -63,7 +63,8 @@ export function createAnnotationEngine(viewerState, options) {
|
|
|
63
63
|
const painter = new Painter({
|
|
64
64
|
userName: options.userName ?? "User",
|
|
65
65
|
callbacks,
|
|
66
|
-
getStylusModeEnabled: () => viewerState.stylusMode.value
|
|
66
|
+
getStylusModeEnabled: () => viewerState.stylusMode.value,
|
|
67
|
+
getReadonly: () => viewerState.readonly.value
|
|
67
68
|
});
|
|
68
69
|
viewerState.painter.value = painter;
|
|
69
70
|
return painter;
|
|
@@ -62,6 +62,7 @@ export function provideViewerState() {
|
|
|
62
62
|
if (prev !== void 0) setScale(prev);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
const readonly = ref(false);
|
|
65
66
|
const stylusMode = ref(false);
|
|
66
67
|
function setStylusMode(enabled) {
|
|
67
68
|
stylusMode.value = enabled;
|
|
@@ -91,6 +92,7 @@ export function provideViewerState() {
|
|
|
91
92
|
if (activeSignature.value?.id === id) activeSignature.value = null;
|
|
92
93
|
}
|
|
93
94
|
function selectTool(tool, dataTransfer) {
|
|
95
|
+
if (readonly.value && tool !== "hand") return;
|
|
94
96
|
activeTool.value = tool;
|
|
95
97
|
selectedAnnotation.value = null;
|
|
96
98
|
selectedAnnotations.value = [];
|
|
@@ -113,6 +115,7 @@ export function provideViewerState() {
|
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
function deleteAnnotation(id) {
|
|
118
|
+
if (readonly.value) return;
|
|
116
119
|
if (painter.value) {
|
|
117
120
|
painter.value.delete(id, true);
|
|
118
121
|
annotations.value.delete(id);
|
|
@@ -168,7 +171,8 @@ export function provideViewerState() {
|
|
|
168
171
|
stylusMode,
|
|
169
172
|
setStylusMode,
|
|
170
173
|
scrollToPage,
|
|
171
|
-
history
|
|
174
|
+
history,
|
|
175
|
+
readonly
|
|
172
176
|
};
|
|
173
177
|
provide(VIEWER_STATE_KEY, state);
|
|
174
178
|
return {
|