kviewer 0.2.4 → 0.3.1

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.
Files changed (49) hide show
  1. package/README.md +13 -1
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +9 -0
  4. package/dist/runtime/annotation/engine/config.d.ts +1 -0
  5. package/dist/runtime/annotation/engine/config.js +4 -0
  6. package/dist/runtime/annotation/engine/cursor-preview.d.ts +14 -1
  7. package/dist/runtime/annotation/engine/cursor-preview.js +32 -6
  8. package/dist/runtime/annotation/engine/editor/editor.d.ts +17 -0
  9. package/dist/runtime/annotation/engine/editor/editor.js +44 -15
  10. package/dist/runtime/annotation/engine/tools/signature.js +30 -5
  11. package/dist/runtime/annotation/engine/tools/stamp.d.ts +9 -0
  12. package/dist/runtime/annotation/engine/tools/stamp.js +67 -15
  13. package/dist/runtime/annotation/engine/types.d.ts +25 -0
  14. package/dist/runtime/annotation/engine/utils.d.ts +1 -4
  15. package/dist/runtime/annotation/engine/utils.js +1 -10
  16. package/dist/runtime/annotation/pdf-export/export.js +0 -3
  17. package/dist/runtime/annotation/utils/placement_size.d.ts +27 -0
  18. package/dist/runtime/annotation/utils/placement_size.js +26 -0
  19. package/dist/runtime/annotation/utils/signature_image.d.ts +26 -0
  20. package/dist/runtime/annotation/utils/signature_image.js +20 -0
  21. package/dist/runtime/assets/kviewer.css +1 -1
  22. package/dist/runtime/components/FormFieldLayer.vue +6 -1
  23. package/dist/runtime/components/Viewer.d.vue.ts +56 -2
  24. package/dist/runtime/components/Viewer.vue +68 -2
  25. package/dist/runtime/components/Viewer.vue.d.ts +56 -2
  26. package/dist/runtime/components/ViewerTabs.d.vue.ts +29 -9
  27. package/dist/runtime/components/ViewerTabs.vue +10 -2
  28. package/dist/runtime/components/ViewerTabs.vue.d.ts +29 -9
  29. package/dist/runtime/components/form-fields/FormFieldWrapper.vue +4 -2
  30. package/dist/runtime/components/form-fields/FormSignatureField.vue +15 -2
  31. package/dist/runtime/components/modals/FreeTextModal.vue +1 -1
  32. package/dist/runtime/components/modals/SignatureDrawModal.vue +170 -4
  33. package/dist/runtime/components/tools/ToolProperties.vue +98 -101
  34. package/dist/runtime/composables/useFormFields.d.ts +17 -1
  35. package/dist/runtime/composables/useFormFields.js +48 -9
  36. package/dist/runtime/composables/useViewerSearch.js +1 -1
  37. package/dist/runtime/composables/useViewerState.d.ts +1 -0
  38. package/dist/runtime/composables/useViewerState.js +12 -13
  39. package/dist/runtime/embed/bridge-client.d.ts +19 -3
  40. package/dist/runtime/embed/bridge-client.js +24 -0
  41. package/dist/runtime/embed/bridge-host.d.ts +10 -1
  42. package/dist/runtime/embed/bridge-host.js +20 -0
  43. package/dist/runtime/embed/protocol.d.ts +28 -1
  44. package/dist/runtime/i18n/messages.d.ts +16 -2
  45. package/dist/runtime/i18n/messages.js +16 -2
  46. package/dist/runtime/public-types.d.ts +1 -1
  47. package/dist/runtime/toolbar-tools.d.ts +1 -1
  48. package/dist/runtime/toolbar-tools.js +8 -0
  49. package/package.json +18 -18
@@ -0,0 +1,20 @@
1
+ export const WHITE_CUTOFF = 240;
2
+ export const WHITE_SOFT_EDGE = 180;
3
+ export function knockOutWhite(data, cutoff = WHITE_CUTOFF, softEdge = WHITE_SOFT_EDGE) {
4
+ for (let i = 0; i < data.length; i += 4) {
5
+ const luminance = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];
6
+ if (luminance >= cutoff) {
7
+ data[i + 3] = 0;
8
+ } else if (luminance > softEdge) {
9
+ const ratio = (cutoff - luminance) / (cutoff - softEdge);
10
+ data[i + 3] = Math.round(data[i + 3] * ratio);
11
+ }
12
+ }
13
+ }
14
+ export function fitWithin(width, height, maxWidth, maxHeight) {
15
+ const scale = Math.min(maxWidth / width, maxHeight / height, 1);
16
+ return {
17
+ width: Math.max(1, Math.round(width * scale)),
18
+ height: Math.max(1, Math.round(height * scale))
19
+ };
20
+ }
@@ -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: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-uselect{align-items:center;background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 14%,transparent);border:1px solid transparent;border-radius:0;box-sizing:border-box;color:#000;cursor:pointer;display:flex;height:100%;line-height:1;padding:0 11px 0 2px;width:100%}.kviewer-form-uselect:hover{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 22%,transparent);border-color:rgba(0,0,0,.2)}.kviewer-form-uselect:focus-visible{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 28%,transparent);outline:2px solid var(--kvw-field-color,var(--color-primary,#3b82f6));outline-offset:-2px}.kviewer-form-uselect:disabled{cursor:default}.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}
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-uselect{align-items:center;background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 14%,transparent);border:1px solid transparent;border-radius:0;box-sizing:border-box;color:#000;cursor:pointer;display:flex;height:100%;line-height:1;padding:0 11px 0 2px;width:100%}.kviewer-form-uselect:hover{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 22%,transparent);border-color:rgba(0,0,0,.2)}.kviewer-form-uselect:focus-visible{background-color:color-mix(in srgb,var(--kvw-field-color,#1677ff) 28%,transparent);outline:2px solid var(--kvw-field-color,var(--color-primary,#3b82f6));outline-offset:-2px}.kviewer-form-uselect:disabled{cursor:default}.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}.kviewer-form-signature--static{cursor:default}.kviewer-form-signature--static:hover{background:rgba(255,255,200,.15);border-color:rgba(0,0,0,.2)}.kviewer-form-signature__marker{align-items:center;display:inline-flex;gap:4px}.kviewer-form-signature__marker-icon{flex:0 0 auto;height:12px;width:12px}
@@ -48,7 +48,12 @@ const state = useViewerState();
48
48
  const fields = computed(() => formFields.getFieldsForPage(props.pageNumber));
49
49
  const selectedFieldId = formFields.selectedPlacedFieldId;
50
50
  watch(() => state.formEditMode.value, (enabled) => {
51
- if (!enabled) formFields.selectPlacedField(null);
51
+ if (enabled) return;
52
+ const id = formFields.selectedPlacedFieldId.value;
53
+ if (!id) return;
54
+ const def = formFields.getFieldById(id);
55
+ const keepsChrome = formFields.editablePlacedFields.value && def?.origin === "placed";
56
+ if (!keepsChrome) formFields.selectPlacedField(null);
52
57
  });
53
58
  watch(() => state.activeTool.value, (tool) => {
54
59
  const isFormFieldTool = typeof tool === "number" && (tool === AnnotationType.FORM_TEXT || tool === AnnotationType.FORM_CHECKBOX || tool === AnnotationType.FORM_RADIO || tool === AnnotationType.FORM_SIGNATURE);
@@ -1,5 +1,5 @@
1
1
  import { type ViewMode } from '../composables/useViewerState.js';
2
- import type { AddFormFieldPayload, FormFieldDefinition, IAnnotationStore, StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
2
+ import type { AddFormFieldPayload, FormFieldDefinition, IAnnotationStore, PlacedFieldDefaults, SignatureFieldStatus, StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
3
3
  import { type ExportPdfOptions } from '../annotation/pdf-export/export.js';
4
4
  import type { ViewerMenuItem } from '../menu-items.js';
5
5
  import type { ViewerToolEntry } from '../toolbar-tools.js';
@@ -35,6 +35,21 @@ type __VLS_Props = {
35
35
  * drives this — typically by binding it to a role picker in its own
36
36
  * UI. Supports v-model via `v-model:active-role-id`. */
37
37
  activeRoleId?: string | null;
38
+ /** When true, clicking an unsigned signature field opens kviewer's own
39
+ * signing flow (saved signature or draw modal). Off by default so hosts
40
+ * that own the signing process (e.g. an embedding e-sign app) don't get
41
+ * a competing canvas — fields then render as passive markers. */
42
+ clickToSign?: boolean;
43
+ /** When true, user-placed form fields show selection chrome and can be
44
+ * moved/resized/deleted in hand mode even outside form-edit mode.
45
+ * Fields parsed from the source PDF are unaffected. */
46
+ editablePlacedFields?: boolean;
47
+ /** Per-field-type presets merged into every field the user places via
48
+ * the placement tools (e.g. a signature `promptText` or `lockAction`).
49
+ * `fieldName` stays auto-generated — rename via the `field-placed`
50
+ * event and `updateFormField()`. Programmatic `addFormField()` calls
51
+ * are not affected. */
52
+ fieldDefaults?: PlacedFieldDefaults;
38
53
  /** Execute embedded JavaScript inside the PDF — field-level AA scripts
39
54
  * (Mouse Up, Calculate, Format, Validate, Keystroke), document-level
40
55
  * open actions, and page-level scripts. Powered by pdf.js's QuickJS
@@ -98,6 +113,32 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
98
113
  removeFormField: (id: string) => void;
99
114
  /** All form-field definitions (parsed, detected, and placed), flat. */
100
115
  getFormFields: () => FormFieldDefinition[];
116
+ /** Replace the per-field-type presets applied to tool placements.
117
+ * Programmatic counterpart to the `fieldDefaults` prop. */
118
+ setFieldDefaults: (defaults: PlacedFieldDefaults) => void;
119
+ /** Enable/disable kviewer's built-in click-to-sign flow at runtime.
120
+ * Programmatic counterpart to the `clickToSign` prop. */
121
+ setClickToSign: (enabled: boolean) => void;
122
+ /** Subscribe to tool placements (imperative mirror of the
123
+ * `field-placed` event, used by the embed bridge). Returns an
124
+ * unsubscribe function. */
125
+ onFieldPlaced: (cb: (field: FormFieldDefinition) => void) => (() => void);
126
+ /** True once every signature field in the document is signed — via a
127
+ * value applied in this session or a digital signature already in the
128
+ * source PDF. Vacuously true when the document has no signature
129
+ * fields, so combine with `getSignatureFieldStatus().length` if you
130
+ * need "at least one". Use to gate e.g. envelope finalization. */
131
+ getSignedStatus: () => boolean;
132
+ /** Per-widget signed-state snapshot (id, fieldName, pageNumber,
133
+ * signed, roleId). */
134
+ getSignatureFieldStatus: () => SignatureFieldStatus[];
135
+ /** Subscribe to signed-status changes (imperative mirror of the
136
+ * `signed-status-changed` event, used by the embed bridge). Returns
137
+ * an unsubscribe function. */
138
+ onSignedStatusChanged: (cb: (payload: {
139
+ allSigned: boolean;
140
+ fields: SignatureFieldStatus[];
141
+ }) => void) => (() => void);
101
142
  /** Reactive form-edit-mode flag — read with `.value`. */
102
143
  formEditMode: import("vue").Ref<boolean, boolean>;
103
144
  /** Programmatically enter or leave form-edit mode. */
@@ -114,20 +155,32 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
114
155
  resetViewedPages: () => void;
115
156
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
116
157
  "all-pages-read": () => any;
158
+ "field-placed": (field: FormFieldDefinition) => any;
117
159
  "update:formEditMode": (value: boolean) => any;
118
160
  "update:activeRoleId": (value: string | null) => any;
119
161
  "update:viewedPages": (pages: number[]) => any;
162
+ "signed-status-changed": (payload: {
163
+ allSigned: boolean;
164
+ fields: SignatureFieldStatus[];
165
+ }) => any;
120
166
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
121
167
  "onAll-pages-read"?: (() => any) | undefined;
168
+ "onField-placed"?: ((field: FormFieldDefinition) => any) | undefined;
122
169
  "onUpdate:formEditMode"?: ((value: boolean) => any) | undefined;
123
170
  "onUpdate:activeRoleId"?: ((value: string | null) => any) | undefined;
124
171
  "onUpdate:viewedPages"?: ((pages: number[]) => any) | undefined;
172
+ "onSigned-status-changed"?: ((payload: {
173
+ allSigned: boolean;
174
+ fields: SignatureFieldStatus[];
175
+ }) => any) | undefined;
125
176
  }>, {
126
177
  userName: string;
127
178
  freehandGroupingDelay: number;
128
179
  zoom: number;
180
+ clickToSign: boolean;
129
181
  readonly: boolean;
130
182
  active: boolean;
183
+ locale: KviewerLocale;
131
184
  menuItems: ViewerMenuItem[];
132
185
  tools: ViewerToolEntry[];
133
186
  scripting: boolean;
@@ -138,7 +191,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
138
191
  formEditMode: boolean;
139
192
  roleColors: Record<string, string>;
140
193
  activeRoleId: string | null;
141
- locale: KviewerLocale;
194
+ editablePlacedFields: boolean;
195
+ fieldDefaults: PlacedFieldDefaults;
142
196
  messages: KviewerMessageOverrides;
143
197
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
144
198
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -242,6 +242,9 @@ const props = defineProps({
242
242
  formEditMode: { type: Boolean, required: false, default: void 0 },
243
243
  roleColors: { type: Object, required: false, default: void 0 },
244
244
  activeRoleId: { type: [String, null], required: false, default: void 0 },
245
+ clickToSign: { type: Boolean, required: false, default: false },
246
+ editablePlacedFields: { type: Boolean, required: false, default: false },
247
+ fieldDefaults: { type: Object, required: false, default: void 0 },
245
248
  scripting: { type: Boolean, required: false, default: false },
246
249
  menuItems: { type: Array, required: false, default: void 0 },
247
250
  tools: { type: Array, required: false, default: void 0 },
@@ -252,7 +255,9 @@ const slots = useSlots();
252
255
  const toolSlotNames = computed(
253
256
  () => Object.keys(slots).filter((name) => name.startsWith("tool-"))
254
257
  );
255
- const emit = defineEmits(["update:formEditMode", "update:activeRoleId", "update:viewedPages", "all-pages-read"]);
258
+ const emit = defineEmits(["update:formEditMode", "update:activeRoleId", "update:viewedPages", "all-pages-read", "field-placed", "signed-status-changed"]);
259
+ const fieldPlacedCallbacks = /* @__PURE__ */ new Set();
260
+ const signedStatusCallbacks = /* @__PURE__ */ new Set();
256
261
  const viewerRoot = ref(null);
257
262
  const scrollContainer = ref(null);
258
263
  const { state: viewerState, setScrollToPageFn, setDownloadPdfFn, setApplyScaleFn } = provideViewerState();
@@ -262,6 +267,9 @@ watchEffect(() => {
262
267
  watchEffect(() => {
263
268
  viewerState.shapeDetection.value = props.shapeDetection ?? false;
264
269
  });
270
+ watchEffect(() => {
271
+ viewerState.clickToSign.value = props.clickToSign ?? false;
272
+ });
265
273
  watch(
266
274
  () => props.formEditMode,
267
275
  (v) => {
@@ -293,6 +301,28 @@ watch(
293
301
  },
294
302
  { immediate: true }
295
303
  );
304
+ watch(
305
+ () => props.fieldDefaults,
306
+ (v) => {
307
+ formFieldsState.setPlacedFieldDefaults(v ?? {});
308
+ },
309
+ { immediate: true }
310
+ );
311
+ watch(
312
+ () => props.editablePlacedFields,
313
+ (v) => {
314
+ formFieldsState.setEditablePlacedFields(v ?? false);
315
+ },
316
+ { immediate: true }
317
+ );
318
+ const signatureStatus = computed(() => formFieldsState.getSignatureFieldStatus());
319
+ const signatureStatusKey = (fields) => fields.map((s) => `${s.id}|${s.fieldName}|${s.signed ? 1 : 0}`).join(";");
320
+ watch(signatureStatus, (next, prev) => {
321
+ if (prev && signatureStatusKey(next) === signatureStatusKey(prev)) return;
322
+ const payload = { allSigned: next.every((s) => s.signed), fields: next };
323
+ emit("signed-status-changed", payload);
324
+ for (const cb of signedStatusCallbacks) cb(payload);
325
+ });
296
326
  watch(
297
327
  () => props.activeRoleId,
298
328
  (v) => {
@@ -918,7 +948,12 @@ onMounted(() => {
918
948
  userName: props.userName,
919
949
  onRequestTextInput,
920
950
  onPlaceField: (payload) => {
921
- formFieldsState.addPlacedField(payload);
951
+ const def = formFieldsState.addPlacedField(payload);
952
+ if (!viewerState.formEditMode.value && formFieldsState.editablePlacedFields.value) {
953
+ formFieldsState.selectPlacedField(def.id);
954
+ }
955
+ emit("field-placed", def);
956
+ for (const cb of fieldPlacedCallbacks) cb(def);
922
957
  viewerState.selectTool("hand");
923
958
  },
924
959
  getFormFieldPreviewColor: () => {
@@ -1070,6 +1105,37 @@ defineExpose({
1070
1105
  removeFormField: (id) => formFieldsState.removePlacedField(id),
1071
1106
  /** All form-field definitions (parsed, detected, and placed), flat. */
1072
1107
  getFormFields: () => formFieldsState.getAllFields(),
1108
+ /** Replace the per-field-type presets applied to tool placements.
1109
+ * Programmatic counterpart to the `fieldDefaults` prop. */
1110
+ setFieldDefaults: (defaults) => formFieldsState.setPlacedFieldDefaults(defaults),
1111
+ /** Enable/disable kviewer's built-in click-to-sign flow at runtime.
1112
+ * Programmatic counterpart to the `clickToSign` prop. */
1113
+ setClickToSign: (enabled) => {
1114
+ viewerState.clickToSign.value = enabled;
1115
+ },
1116
+ /** Subscribe to tool placements (imperative mirror of the
1117
+ * `field-placed` event, used by the embed bridge). Returns an
1118
+ * unsubscribe function. */
1119
+ onFieldPlaced: (cb) => {
1120
+ fieldPlacedCallbacks.add(cb);
1121
+ return () => fieldPlacedCallbacks.delete(cb);
1122
+ },
1123
+ /** True once every signature field in the document is signed — via a
1124
+ * value applied in this session or a digital signature already in the
1125
+ * source PDF. Vacuously true when the document has no signature
1126
+ * fields, so combine with `getSignatureFieldStatus().length` if you
1127
+ * need "at least one". Use to gate e.g. envelope finalization. */
1128
+ getSignedStatus: () => formFieldsState.getSignatureFieldStatus().every((s) => s.signed),
1129
+ /** Per-widget signed-state snapshot (id, fieldName, pageNumber,
1130
+ * signed, roleId). */
1131
+ getSignatureFieldStatus: () => formFieldsState.getSignatureFieldStatus(),
1132
+ /** Subscribe to signed-status changes (imperative mirror of the
1133
+ * `signed-status-changed` event, used by the embed bridge). Returns
1134
+ * an unsubscribe function. */
1135
+ onSignedStatusChanged: (cb) => {
1136
+ signedStatusCallbacks.add(cb);
1137
+ return () => signedStatusCallbacks.delete(cb);
1138
+ },
1073
1139
  /** Reactive form-edit-mode flag — read with `.value`. */
1074
1140
  formEditMode: viewerState.formEditMode,
1075
1141
  /** Programmatically enter or leave form-edit mode. */
@@ -1,5 +1,5 @@
1
1
  import { type ViewMode } from '../composables/useViewerState.js';
2
- import type { AddFormFieldPayload, FormFieldDefinition, IAnnotationStore, StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
2
+ import type { AddFormFieldPayload, FormFieldDefinition, IAnnotationStore, PlacedFieldDefaults, SignatureFieldStatus, StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
3
3
  import { type ExportPdfOptions } from '../annotation/pdf-export/export.js';
4
4
  import type { ViewerMenuItem } from '../menu-items.js';
5
5
  import type { ViewerToolEntry } from '../toolbar-tools.js';
@@ -35,6 +35,21 @@ type __VLS_Props = {
35
35
  * drives this — typically by binding it to a role picker in its own
36
36
  * UI. Supports v-model via `v-model:active-role-id`. */
37
37
  activeRoleId?: string | null;
38
+ /** When true, clicking an unsigned signature field opens kviewer's own
39
+ * signing flow (saved signature or draw modal). Off by default so hosts
40
+ * that own the signing process (e.g. an embedding e-sign app) don't get
41
+ * a competing canvas — fields then render as passive markers. */
42
+ clickToSign?: boolean;
43
+ /** When true, user-placed form fields show selection chrome and can be
44
+ * moved/resized/deleted in hand mode even outside form-edit mode.
45
+ * Fields parsed from the source PDF are unaffected. */
46
+ editablePlacedFields?: boolean;
47
+ /** Per-field-type presets merged into every field the user places via
48
+ * the placement tools (e.g. a signature `promptText` or `lockAction`).
49
+ * `fieldName` stays auto-generated — rename via the `field-placed`
50
+ * event and `updateFormField()`. Programmatic `addFormField()` calls
51
+ * are not affected. */
52
+ fieldDefaults?: PlacedFieldDefaults;
38
53
  /** Execute embedded JavaScript inside the PDF — field-level AA scripts
39
54
  * (Mouse Up, Calculate, Format, Validate, Keystroke), document-level
40
55
  * open actions, and page-level scripts. Powered by pdf.js's QuickJS
@@ -98,6 +113,32 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
98
113
  removeFormField: (id: string) => void;
99
114
  /** All form-field definitions (parsed, detected, and placed), flat. */
100
115
  getFormFields: () => FormFieldDefinition[];
116
+ /** Replace the per-field-type presets applied to tool placements.
117
+ * Programmatic counterpart to the `fieldDefaults` prop. */
118
+ setFieldDefaults: (defaults: PlacedFieldDefaults) => void;
119
+ /** Enable/disable kviewer's built-in click-to-sign flow at runtime.
120
+ * Programmatic counterpart to the `clickToSign` prop. */
121
+ setClickToSign: (enabled: boolean) => void;
122
+ /** Subscribe to tool placements (imperative mirror of the
123
+ * `field-placed` event, used by the embed bridge). Returns an
124
+ * unsubscribe function. */
125
+ onFieldPlaced: (cb: (field: FormFieldDefinition) => void) => (() => void);
126
+ /** True once every signature field in the document is signed — via a
127
+ * value applied in this session or a digital signature already in the
128
+ * source PDF. Vacuously true when the document has no signature
129
+ * fields, so combine with `getSignatureFieldStatus().length` if you
130
+ * need "at least one". Use to gate e.g. envelope finalization. */
131
+ getSignedStatus: () => boolean;
132
+ /** Per-widget signed-state snapshot (id, fieldName, pageNumber,
133
+ * signed, roleId). */
134
+ getSignatureFieldStatus: () => SignatureFieldStatus[];
135
+ /** Subscribe to signed-status changes (imperative mirror of the
136
+ * `signed-status-changed` event, used by the embed bridge). Returns
137
+ * an unsubscribe function. */
138
+ onSignedStatusChanged: (cb: (payload: {
139
+ allSigned: boolean;
140
+ fields: SignatureFieldStatus[];
141
+ }) => void) => (() => void);
101
142
  /** Reactive form-edit-mode flag — read with `.value`. */
102
143
  formEditMode: import("vue").Ref<boolean, boolean>;
103
144
  /** Programmatically enter or leave form-edit mode. */
@@ -114,20 +155,32 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
114
155
  resetViewedPages: () => void;
115
156
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
116
157
  "all-pages-read": () => any;
158
+ "field-placed": (field: FormFieldDefinition) => any;
117
159
  "update:formEditMode": (value: boolean) => any;
118
160
  "update:activeRoleId": (value: string | null) => any;
119
161
  "update:viewedPages": (pages: number[]) => any;
162
+ "signed-status-changed": (payload: {
163
+ allSigned: boolean;
164
+ fields: SignatureFieldStatus[];
165
+ }) => any;
120
166
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
121
167
  "onAll-pages-read"?: (() => any) | undefined;
168
+ "onField-placed"?: ((field: FormFieldDefinition) => any) | undefined;
122
169
  "onUpdate:formEditMode"?: ((value: boolean) => any) | undefined;
123
170
  "onUpdate:activeRoleId"?: ((value: string | null) => any) | undefined;
124
171
  "onUpdate:viewedPages"?: ((pages: number[]) => any) | undefined;
172
+ "onSigned-status-changed"?: ((payload: {
173
+ allSigned: boolean;
174
+ fields: SignatureFieldStatus[];
175
+ }) => any) | undefined;
125
176
  }>, {
126
177
  userName: string;
127
178
  freehandGroupingDelay: number;
128
179
  zoom: number;
180
+ clickToSign: boolean;
129
181
  readonly: boolean;
130
182
  active: boolean;
183
+ locale: KviewerLocale;
131
184
  menuItems: ViewerMenuItem[];
132
185
  tools: ViewerToolEntry[];
133
186
  scripting: boolean;
@@ -138,7 +191,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
138
191
  formEditMode: boolean;
139
192
  roleColors: Record<string, string>;
140
193
  activeRoleId: string | null;
141
- locale: KviewerLocale;
194
+ editablePlacedFields: boolean;
195
+ fieldDefaults: PlacedFieldDefaults;
142
196
  messages: KviewerMessageOverrides;
143
197
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
144
198
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,6 +1,6 @@
1
1
  import { type ComponentPublicInstance } from 'vue';
2
2
  import type { ViewMode } from '../composables/useViewerState.js';
3
- import type { StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
3
+ import type { FormFieldDefinition, PlacedFieldDefaults, SignatureFieldStatus, StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
4
4
  import type { ViewerMenuItem } from '../menu-items.js';
5
5
  import type { ViewerToolEntry } from '../toolbar-tools.js';
6
6
  export interface ViewerTabItem {
@@ -65,6 +65,13 @@ type __VLS_Props = {
65
65
  menuItems?: ViewerMenuItem[];
66
66
  /** Forwarded to every Viewer instance — see KViewer's `tools`. */
67
67
  tools?: ViewerToolEntry[];
68
+ /** Forwarded to every Viewer instance — see KViewer's `clickToSign`. */
69
+ clickToSign?: boolean;
70
+ /** Forwarded to every Viewer instance — see KViewer's
71
+ * `editablePlacedFields`. */
72
+ editablePlacedFields?: boolean;
73
+ /** Forwarded to every Viewer instance — see KViewer's `fieldDefaults`. */
74
+ fieldDefaults?: PlacedFieldDefaults;
68
75
  };
69
76
  declare function addTab(item: Omit<ViewerTabItem, 'id'> & {
70
77
  id?: string;
@@ -72,7 +79,7 @@ declare function addTab(item: Omit<ViewerTabItem, 'id'> & {
72
79
  declare function removeTab(id: string): boolean;
73
80
  declare function activateTab(id: string): void;
74
81
  declare function getViewer(id: string): ComponentPublicInstance | null;
75
- declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
82
+ declare var __VLS_7: {}, __VLS_21: {}, __VLS_34: {
76
83
  tab: {
77
84
  id: string;
78
85
  label: string;
@@ -172,7 +179,7 @@ declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
172
179
  shapeDetection?: boolean | undefined;
173
180
  scripting?: boolean | undefined;
174
181
  };
175
- }, __VLS_35: {
182
+ }, __VLS_37: {
176
183
  tab: {
177
184
  id: string;
178
185
  label: string;
@@ -272,21 +279,21 @@ declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
272
279
  shapeDetection?: boolean | undefined;
273
280
  scripting?: boolean | undefined;
274
281
  };
275
- }, __VLS_39: string, __VLS_40: {
282
+ }, __VLS_41: string, __VLS_42: {
276
283
  state: import("../composables/useViewerState.js").ViewerState;
277
- }, __VLS_42: {};
284
+ }, __VLS_44: {};
278
285
  type __VLS_Slots = {} & {
279
- [K in NonNullable<typeof __VLS_39>]?: (props: typeof __VLS_40) => any;
286
+ [K in NonNullable<typeof __VLS_41>]?: (props: typeof __VLS_42) => any;
280
287
  } & {
281
288
  'tabs-leading'?: (props: typeof __VLS_7) => any;
282
289
  } & {
283
290
  'tabs-trailing'?: (props: typeof __VLS_21) => any;
284
291
  } & {
285
- header?: (props: typeof __VLS_32) => any;
292
+ header?: (props: typeof __VLS_34) => any;
286
293
  } & {
287
- footer?: (props: typeof __VLS_35) => any;
294
+ footer?: (props: typeof __VLS_37) => any;
288
295
  } & {
289
- empty?: (props: typeof __VLS_42) => any;
296
+ empty?: (props: typeof __VLS_44) => any;
290
297
  };
291
298
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
292
299
  addTab: typeof addTab;
@@ -394,13 +401,23 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
394
401
  scripting?: boolean | undefined;
395
402
  }[];
396
403
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
404
+ "field-placed": (field: FormFieldDefinition) => any;
397
405
  "update:activeRoleId": (value: string | null) => any;
406
+ "signed-status-changed": (payload: {
407
+ allSigned: boolean;
408
+ fields: SignatureFieldStatus[];
409
+ }) => any;
398
410
  "update:activeTab": (id: string) => any;
399
411
  "tab-added": (tab: ViewerTabItem) => any;
400
412
  "tab-close": (id: string) => any;
401
413
  "tab-removed": (id: string) => any;
402
414
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
415
+ "onField-placed"?: ((field: FormFieldDefinition) => any) | undefined;
403
416
  "onUpdate:activeRoleId"?: ((value: string | null) => any) | undefined;
417
+ "onSigned-status-changed"?: ((payload: {
418
+ allSigned: boolean;
419
+ fields: SignatureFieldStatus[];
420
+ }) => any) | undefined;
404
421
  "onUpdate:activeTab"?: ((id: string) => any) | undefined;
405
422
  "onTab-added"?: ((tab: ViewerTabItem) => any) | undefined;
406
423
  "onTab-close"?: ((id: string) => any) | undefined;
@@ -408,6 +425,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
408
425
  }>, {
409
426
  userName: string;
410
427
  zoom: number;
428
+ clickToSign: boolean;
411
429
  menuItems: ViewerMenuItem[];
412
430
  tools: ViewerToolEntry[];
413
431
  scripting: boolean;
@@ -416,6 +434,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
416
434
  viewMode: ViewMode;
417
435
  roleColors: Record<string, string>;
418
436
  activeRoleId: string | null;
437
+ editablePlacedFields: boolean;
438
+ fieldDefaults: PlacedFieldDefaults;
419
439
  defaultActiveTab: string;
420
440
  minTabs: number;
421
441
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -64,7 +64,12 @@
64
64
  :tools="tools"
65
65
  :role-colors="roleColors"
66
66
  :active-role-id="activeRoleId"
67
+ :click-to-sign="clickToSign"
68
+ :editable-placed-fields="editablePlacedFields"
69
+ :field-defaults="fieldDefaults"
67
70
  @update:active-role-id="(v) => emit('update:activeRoleId', v)"
71
+ @field-placed="(f) => emit('field-placed', f)"
72
+ @signed-status-changed="(p) => emit('signed-status-changed', p)"
68
73
  >
69
74
  <template v-if="$slots.header" #header>
70
75
  <slot name="header" :tab="activeTab" />
@@ -107,13 +112,16 @@ const props = defineProps({
107
112
  activeRoleId: { type: [String, null], required: false, default: void 0 },
108
113
  scripting: { type: Boolean, required: false, default: false },
109
114
  menuItems: { type: Array, required: false, default: void 0 },
110
- tools: { type: Array, required: false, default: void 0 }
115
+ tools: { type: Array, required: false, default: void 0 },
116
+ clickToSign: { type: Boolean, required: false, default: false },
117
+ editablePlacedFields: { type: Boolean, required: false, default: false },
118
+ fieldDefaults: { type: Object, required: false, default: void 0 }
111
119
  });
112
120
  const slots = useSlots();
113
121
  const toolSlotNames = computed(
114
122
  () => Object.keys(slots).filter((name) => name.startsWith("tool-"))
115
123
  );
116
- const emit = defineEmits(["update:activeTab", "tab-added", "tab-close", "tab-removed", "update:activeRoleId"]);
124
+ const emit = defineEmits(["update:activeTab", "tab-added", "tab-close", "tab-removed", "update:activeRoleId", "field-placed", "signed-status-changed"]);
117
125
  let idCounter = 0;
118
126
  function generateId() {
119
127
  return `tab-${Date.now()}-${++idCounter}`;
@@ -1,6 +1,6 @@
1
1
  import { type ComponentPublicInstance } from 'vue';
2
2
  import type { ViewMode } from '../composables/useViewerState.js';
3
- import type { StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
3
+ import type { FormFieldDefinition, PlacedFieldDefaults, SignatureFieldStatus, StampDefinition, SignatureHandlers } from '../annotation/engine/types.js';
4
4
  import type { ViewerMenuItem } from '../menu-items.js';
5
5
  import type { ViewerToolEntry } from '../toolbar-tools.js';
6
6
  export interface ViewerTabItem {
@@ -65,6 +65,13 @@ type __VLS_Props = {
65
65
  menuItems?: ViewerMenuItem[];
66
66
  /** Forwarded to every Viewer instance — see KViewer's `tools`. */
67
67
  tools?: ViewerToolEntry[];
68
+ /** Forwarded to every Viewer instance — see KViewer's `clickToSign`. */
69
+ clickToSign?: boolean;
70
+ /** Forwarded to every Viewer instance — see KViewer's
71
+ * `editablePlacedFields`. */
72
+ editablePlacedFields?: boolean;
73
+ /** Forwarded to every Viewer instance — see KViewer's `fieldDefaults`. */
74
+ fieldDefaults?: PlacedFieldDefaults;
68
75
  };
69
76
  declare function addTab(item: Omit<ViewerTabItem, 'id'> & {
70
77
  id?: string;
@@ -72,7 +79,7 @@ declare function addTab(item: Omit<ViewerTabItem, 'id'> & {
72
79
  declare function removeTab(id: string): boolean;
73
80
  declare function activateTab(id: string): void;
74
81
  declare function getViewer(id: string): ComponentPublicInstance | null;
75
- declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
82
+ declare var __VLS_7: {}, __VLS_21: {}, __VLS_34: {
76
83
  tab: {
77
84
  id: string;
78
85
  label: string;
@@ -172,7 +179,7 @@ declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
172
179
  shapeDetection?: boolean | undefined;
173
180
  scripting?: boolean | undefined;
174
181
  };
175
- }, __VLS_35: {
182
+ }, __VLS_37: {
176
183
  tab: {
177
184
  id: string;
178
185
  label: string;
@@ -272,21 +279,21 @@ declare var __VLS_7: {}, __VLS_21: {}, __VLS_32: {
272
279
  shapeDetection?: boolean | undefined;
273
280
  scripting?: boolean | undefined;
274
281
  };
275
- }, __VLS_39: string, __VLS_40: {
282
+ }, __VLS_41: string, __VLS_42: {
276
283
  state: import("../composables/useViewerState.js").ViewerState;
277
- }, __VLS_42: {};
284
+ }, __VLS_44: {};
278
285
  type __VLS_Slots = {} & {
279
- [K in NonNullable<typeof __VLS_39>]?: (props: typeof __VLS_40) => any;
286
+ [K in NonNullable<typeof __VLS_41>]?: (props: typeof __VLS_42) => any;
280
287
  } & {
281
288
  'tabs-leading'?: (props: typeof __VLS_7) => any;
282
289
  } & {
283
290
  'tabs-trailing'?: (props: typeof __VLS_21) => any;
284
291
  } & {
285
- header?: (props: typeof __VLS_32) => any;
292
+ header?: (props: typeof __VLS_34) => any;
286
293
  } & {
287
- footer?: (props: typeof __VLS_35) => any;
294
+ footer?: (props: typeof __VLS_37) => any;
288
295
  } & {
289
- empty?: (props: typeof __VLS_42) => any;
296
+ empty?: (props: typeof __VLS_44) => any;
290
297
  };
291
298
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
292
299
  addTab: typeof addTab;
@@ -394,13 +401,23 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
394
401
  scripting?: boolean | undefined;
395
402
  }[];
396
403
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
404
+ "field-placed": (field: FormFieldDefinition) => any;
397
405
  "update:activeRoleId": (value: string | null) => any;
406
+ "signed-status-changed": (payload: {
407
+ allSigned: boolean;
408
+ fields: SignatureFieldStatus[];
409
+ }) => any;
398
410
  "update:activeTab": (id: string) => any;
399
411
  "tab-added": (tab: ViewerTabItem) => any;
400
412
  "tab-close": (id: string) => any;
401
413
  "tab-removed": (id: string) => any;
402
414
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
415
+ "onField-placed"?: ((field: FormFieldDefinition) => any) | undefined;
403
416
  "onUpdate:activeRoleId"?: ((value: string | null) => any) | undefined;
417
+ "onSigned-status-changed"?: ((payload: {
418
+ allSigned: boolean;
419
+ fields: SignatureFieldStatus[];
420
+ }) => any) | undefined;
404
421
  "onUpdate:activeTab"?: ((id: string) => any) | undefined;
405
422
  "onTab-added"?: ((tab: ViewerTabItem) => any) | undefined;
406
423
  "onTab-close"?: ((id: string) => any) | undefined;
@@ -408,6 +425,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
408
425
  }>, {
409
426
  userName: string;
410
427
  zoom: number;
428
+ clickToSign: boolean;
411
429
  menuItems: ViewerMenuItem[];
412
430
  tools: ViewerToolEntry[];
413
431
  scripting: boolean;
@@ -416,6 +434,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
416
434
  viewMode: ViewMode;
417
435
  roleColors: Record<string, string>;
418
436
  activeRoleId: string | null;
437
+ editablePlacedFields: boolean;
438
+ fieldDefaults: PlacedFieldDefaults;
419
439
  defaultActiveTab: string;
420
440
  minTabs: number;
421
441
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -11,7 +11,7 @@
11
11
  >
12
12
  <div
13
13
  class="kviewer-form-field__body"
14
- :class="{ 'kviewer-form-field__body--locked': isFormEditMode }"
14
+ :class="{ 'kviewer-form-field__body--locked': showChrome }"
15
15
  >
16
16
  <FormTextField v-if="props.field.fieldType === 'text'" :field="props.field" />
17
17
  <FormCheckbox v-else-if="props.field.fieldType === 'checkbox'" :field="props.field" />
@@ -55,7 +55,9 @@ const state = useViewerState();
55
55
  const formFields = useFormFields();
56
56
  const isPlaced = computed(() => props.field.origin === "placed");
57
57
  const isFormEditMode = computed(() => state.formEditMode.value);
58
- const showChrome = computed(() => isFormEditMode.value);
58
+ const showChrome = computed(
59
+ () => isFormEditMode.value || formFields.editablePlacedFields.value && isPlaced.value
60
+ );
59
61
  const chromeColor = computed(() => {
60
62
  const id = props.field.roleId;
61
63
  if (!id) return "#1677ff";