kviewer 0.0.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 (197) hide show
  1. package/README.md +134 -0
  2. package/dist/module.d.mts +15 -0
  3. package/dist/module.json +9 -0
  4. package/dist/module.mjs +26 -0
  5. package/dist/runtime/annotation/engine/config.d.ts +52 -0
  6. package/dist/runtime/annotation/engine/config.js +283 -0
  7. package/dist/runtime/annotation/engine/const.d.ts +6 -0
  8. package/dist/runtime/annotation/engine/const.js +7 -0
  9. package/dist/runtime/annotation/engine/cursor-preview.d.ts +2 -0
  10. package/dist/runtime/annotation/engine/cursor-preview.js +88 -0
  11. package/dist/runtime/annotation/engine/editor/editor.d.ts +69 -0
  12. package/dist/runtime/annotation/engine/editor/editor.js +233 -0
  13. package/dist/runtime/annotation/engine/editor/selector.d.ts +74 -0
  14. package/dist/runtime/annotation/engine/editor/selector.js +594 -0
  15. package/dist/runtime/annotation/engine/import-normalize.d.ts +5 -0
  16. package/dist/runtime/annotation/engine/import-normalize.js +99 -0
  17. package/dist/runtime/annotation/engine/input-device.d.ts +53 -0
  18. package/dist/runtime/annotation/engine/input-device.js +64 -0
  19. package/dist/runtime/annotation/engine/painter.d.ts +97 -0
  20. package/dist/runtime/annotation/engine/painter.js +591 -0
  21. package/dist/runtime/annotation/engine/store.d.ts +11 -0
  22. package/dist/runtime/annotation/engine/store.js +47 -0
  23. package/dist/runtime/annotation/engine/tools/arrow.d.ts +22 -0
  24. package/dist/runtime/annotation/engine/tools/arrow.js +126 -0
  25. package/dist/runtime/annotation/engine/tools/circle.d.ts +45 -0
  26. package/dist/runtime/annotation/engine/tools/circle.js +148 -0
  27. package/dist/runtime/annotation/engine/tools/cloud.d.ts +50 -0
  28. package/dist/runtime/annotation/engine/tools/cloud.js +244 -0
  29. package/dist/runtime/annotation/engine/tools/free-highlight.d.ts +43 -0
  30. package/dist/runtime/annotation/engine/tools/free-highlight.js +165 -0
  31. package/dist/runtime/annotation/engine/tools/free-text.d.ts +27 -0
  32. package/dist/runtime/annotation/engine/tools/free-text.js +114 -0
  33. package/dist/runtime/annotation/engine/tools/freehand.d.ts +44 -0
  34. package/dist/runtime/annotation/engine/tools/freehand.js +151 -0
  35. package/dist/runtime/annotation/engine/tools/highlight.d.ts +87 -0
  36. package/dist/runtime/annotation/engine/tools/highlight.js +215 -0
  37. package/dist/runtime/annotation/engine/tools/note.d.ts +9 -0
  38. package/dist/runtime/annotation/engine/tools/note.js +34 -0
  39. package/dist/runtime/annotation/engine/tools/rectangle.d.ts +45 -0
  40. package/dist/runtime/annotation/engine/tools/rectangle.js +142 -0
  41. package/dist/runtime/annotation/engine/tools/signature.d.ts +16 -0
  42. package/dist/runtime/annotation/engine/tools/signature.js +74 -0
  43. package/dist/runtime/annotation/engine/tools/stamp.d.ts +18 -0
  44. package/dist/runtime/annotation/engine/tools/stamp.js +94 -0
  45. package/dist/runtime/annotation/engine/types.d.ts +170 -0
  46. package/dist/runtime/annotation/engine/types.js +67 -0
  47. package/dist/runtime/annotation/engine/utils.d.ts +40 -0
  48. package/dist/runtime/annotation/engine/utils.js +257 -0
  49. package/dist/runtime/annotation/parsers/parseFormFields.d.ts +9 -0
  50. package/dist/runtime/annotation/parsers/parseFormFields.js +101 -0
  51. package/dist/runtime/annotation/pdf-export/download.d.ts +1 -0
  52. package/dist/runtime/annotation/pdf-export/download.js +10 -0
  53. package/dist/runtime/annotation/pdf-export/export-form-fields.d.ts +9 -0
  54. package/dist/runtime/annotation/pdf-export/export-form-fields.js +90 -0
  55. package/dist/runtime/annotation/pdf-export/export.d.ts +15 -0
  56. package/dist/runtime/annotation/pdf-export/export.js +145 -0
  57. package/dist/runtime/annotation/pdf-export/parse.d.ts +10 -0
  58. package/dist/runtime/annotation/pdf-export/parse.js +19 -0
  59. package/dist/runtime/annotation/pdf-export/parse_circle.d.ts +4 -0
  60. package/dist/runtime/annotation/pdf-export/parse_circle.js +41 -0
  61. package/dist/runtime/annotation/pdf-export/parse_freetext.d.ts +4 -0
  62. package/dist/runtime/annotation/pdf-export/parse_freetext.js +54 -0
  63. package/dist/runtime/annotation/pdf-export/parse_highlight.d.ts +4 -0
  64. package/dist/runtime/annotation/pdf-export/parse_highlight.js +134 -0
  65. package/dist/runtime/annotation/pdf-export/parse_ink.d.ts +4 -0
  66. package/dist/runtime/annotation/pdf-export/parse_ink.js +124 -0
  67. package/dist/runtime/annotation/pdf-export/parse_line.d.ts +4 -0
  68. package/dist/runtime/annotation/pdf-export/parse_line.js +71 -0
  69. package/dist/runtime/annotation/pdf-export/parse_polyline.d.ts +4 -0
  70. package/dist/runtime/annotation/pdf-export/parse_polyline.js +93 -0
  71. package/dist/runtime/annotation/pdf-export/parse_square.d.ts +4 -0
  72. package/dist/runtime/annotation/pdf-export/parse_square.js +41 -0
  73. package/dist/runtime/annotation/pdf-export/parse_stamp.d.ts +4 -0
  74. package/dist/runtime/annotation/pdf-export/parse_stamp.js +195 -0
  75. package/dist/runtime/annotation/pdf-export/parse_strikeout.d.ts +4 -0
  76. package/dist/runtime/annotation/pdf-export/parse_strikeout.js +59 -0
  77. package/dist/runtime/annotation/pdf-export/parse_text.d.ts +4 -0
  78. package/dist/runtime/annotation/pdf-export/parse_text.js +42 -0
  79. package/dist/runtime/annotation/pdf-export/parse_underline.d.ts +4 -0
  80. package/dist/runtime/annotation/pdf-export/parse_underline.js +59 -0
  81. package/dist/runtime/assets/kviewer.css +1 -0
  82. package/dist/runtime/components/AnnotationToolbar.d.vue.ts +3 -0
  83. package/dist/runtime/components/AnnotationToolbar.vue +125 -0
  84. package/dist/runtime/components/AnnotationToolbar.vue.d.ts +3 -0
  85. package/dist/runtime/components/FloatingPageIndicator.d.vue.ts +6 -0
  86. package/dist/runtime/components/FloatingPageIndicator.vue +93 -0
  87. package/dist/runtime/components/FloatingPageIndicator.vue.d.ts +6 -0
  88. package/dist/runtime/components/FormFieldLayer.d.vue.ts +11 -0
  89. package/dist/runtime/components/FormFieldLayer.vue +40 -0
  90. package/dist/runtime/components/FormFieldLayer.vue.d.ts +11 -0
  91. package/dist/runtime/components/PdfPage.d.vue.ts +9 -0
  92. package/dist/runtime/components/PdfPage.vue +199 -0
  93. package/dist/runtime/components/PdfPage.vue.d.ts +9 -0
  94. package/dist/runtime/components/ToolButton.d.vue.ts +13 -0
  95. package/dist/runtime/components/ToolButton.vue +26 -0
  96. package/dist/runtime/components/ToolButton.vue.d.ts +13 -0
  97. package/dist/runtime/components/Toolbar.d.vue.ts +3 -0
  98. package/dist/runtime/components/Toolbar.vue +11 -0
  99. package/dist/runtime/components/Toolbar.vue.d.ts +3 -0
  100. package/dist/runtime/components/Viewer.d.vue.ts +45 -0
  101. package/dist/runtime/components/Viewer.vue +617 -0
  102. package/dist/runtime/components/Viewer.vue.d.ts +45 -0
  103. package/dist/runtime/components/ViewerBar.d.vue.ts +3 -0
  104. package/dist/runtime/components/ViewerBar.vue +91 -0
  105. package/dist/runtime/components/ViewerBar.vue.d.ts +3 -0
  106. package/dist/runtime/components/ViewerTabs.d.vue.ts +381 -0
  107. package/dist/runtime/components/ViewerTabs.vue +171 -0
  108. package/dist/runtime/components/ViewerTabs.vue.d.ts +381 -0
  109. package/dist/runtime/components/form-fields/FormButton.d.vue.ts +7 -0
  110. package/dist/runtime/components/form-fields/FormButton.vue +39 -0
  111. package/dist/runtime/components/form-fields/FormButton.vue.d.ts +7 -0
  112. package/dist/runtime/components/form-fields/FormCheckbox.d.vue.ts +7 -0
  113. package/dist/runtime/components/form-fields/FormCheckbox.vue +28 -0
  114. package/dist/runtime/components/form-fields/FormCheckbox.vue.d.ts +7 -0
  115. package/dist/runtime/components/form-fields/FormDropdown.d.vue.ts +7 -0
  116. package/dist/runtime/components/form-fields/FormDropdown.vue +112 -0
  117. package/dist/runtime/components/form-fields/FormDropdown.vue.d.ts +7 -0
  118. package/dist/runtime/components/form-fields/FormFieldWrapper.d.vue.ts +8 -0
  119. package/dist/runtime/components/form-fields/FormFieldWrapper.vue +41 -0
  120. package/dist/runtime/components/form-fields/FormFieldWrapper.vue.d.ts +8 -0
  121. package/dist/runtime/components/form-fields/FormRadioButton.d.vue.ts +7 -0
  122. package/dist/runtime/components/form-fields/FormRadioButton.vue +30 -0
  123. package/dist/runtime/components/form-fields/FormRadioButton.vue.d.ts +7 -0
  124. package/dist/runtime/components/form-fields/FormSignatureField.d.vue.ts +7 -0
  125. package/dist/runtime/components/form-fields/FormSignatureField.vue +54 -0
  126. package/dist/runtime/components/form-fields/FormSignatureField.vue.d.ts +7 -0
  127. package/dist/runtime/components/form-fields/FormTextField.d.vue.ts +7 -0
  128. package/dist/runtime/components/form-fields/FormTextField.vue +66 -0
  129. package/dist/runtime/components/form-fields/FormTextField.vue.d.ts +7 -0
  130. package/dist/runtime/components/modals/FreeTextModal.d.vue.ts +25 -0
  131. package/dist/runtime/components/modals/FreeTextModal.vue +89 -0
  132. package/dist/runtime/components/modals/FreeTextModal.vue.d.ts +25 -0
  133. package/dist/runtime/components/modals/SignatureDrawModal.d.vue.ts +14 -0
  134. package/dist/runtime/components/modals/SignatureDrawModal.vue +120 -0
  135. package/dist/runtime/components/modals/SignatureDrawModal.vue.d.ts +14 -0
  136. package/dist/runtime/components/panels/SignaturePicker.d.vue.ts +3 -0
  137. package/dist/runtime/components/panels/SignaturePicker.vue +85 -0
  138. package/dist/runtime/components/panels/SignaturePicker.vue.d.ts +3 -0
  139. package/dist/runtime/components/panels/StampPicker.d.vue.ts +3 -0
  140. package/dist/runtime/components/panels/StampPicker.vue +46 -0
  141. package/dist/runtime/components/panels/StampPicker.vue.d.ts +3 -0
  142. package/dist/runtime/components/tools/ActionTools.d.vue.ts +3 -0
  143. package/dist/runtime/components/tools/ActionTools.vue +32 -0
  144. package/dist/runtime/components/tools/ActionTools.vue.d.ts +3 -0
  145. package/dist/runtime/components/tools/DrawingTools.d.vue.ts +6 -0
  146. package/dist/runtime/components/tools/DrawingTools.vue +57 -0
  147. package/dist/runtime/components/tools/DrawingTools.vue.d.ts +6 -0
  148. package/dist/runtime/components/tools/HandTool.d.vue.ts +3 -0
  149. package/dist/runtime/components/tools/HandTool.vue +14 -0
  150. package/dist/runtime/components/tools/HandTool.vue.d.ts +3 -0
  151. package/dist/runtime/components/tools/MarqueeTool.d.vue.ts +3 -0
  152. package/dist/runtime/components/tools/MarqueeTool.vue +15 -0
  153. package/dist/runtime/components/tools/MarqueeTool.vue.d.ts +3 -0
  154. package/dist/runtime/components/tools/PageInfo.d.vue.ts +3 -0
  155. package/dist/runtime/components/tools/PageInfo.vue +10 -0
  156. package/dist/runtime/components/tools/PageInfo.vue.d.ts +3 -0
  157. package/dist/runtime/components/tools/PageSettings.d.vue.ts +3 -0
  158. package/dist/runtime/components/tools/PageSettings.vue +92 -0
  159. package/dist/runtime/components/tools/PageSettings.vue.d.ts +3 -0
  160. package/dist/runtime/components/tools/SearchTool.d.vue.ts +3 -0
  161. package/dist/runtime/components/tools/SearchTool.vue +149 -0
  162. package/dist/runtime/components/tools/SearchTool.vue.d.ts +3 -0
  163. package/dist/runtime/components/tools/ToolProperties.d.vue.ts +7 -0
  164. package/dist/runtime/components/tools/ToolProperties.vue +174 -0
  165. package/dist/runtime/components/tools/ToolProperties.vue.d.ts +7 -0
  166. package/dist/runtime/components/tools/ZoomControls.d.vue.ts +3 -0
  167. package/dist/runtime/components/tools/ZoomControls.vue +59 -0
  168. package/dist/runtime/components/tools/ZoomControls.vue.d.ts +3 -0
  169. package/dist/runtime/composables/search-utils.d.ts +20 -0
  170. package/dist/runtime/composables/search-utils.js +55 -0
  171. package/dist/runtime/composables/useAnnotationEngine.d.ts +7 -0
  172. package/dist/runtime/composables/useAnnotationEngine.js +70 -0
  173. package/dist/runtime/composables/useAnnotationHistory.d.ts +12 -0
  174. package/dist/runtime/composables/useAnnotationHistory.js +69 -0
  175. package/dist/runtime/composables/useFormFields.d.ts +26 -0
  176. package/dist/runtime/composables/useFormFields.js +112 -0
  177. package/dist/runtime/composables/usePageProxyCache.d.ts +8 -0
  178. package/dist/runtime/composables/usePageProxyCache.js +73 -0
  179. package/dist/runtime/composables/usePageSettings.d.ts +16 -0
  180. package/dist/runtime/composables/usePageSettings.js +66 -0
  181. package/dist/runtime/composables/usePageVirtualization.d.ts +19 -0
  182. package/dist/runtime/composables/usePageVirtualization.js +203 -0
  183. package/dist/runtime/composables/useSearchIndex.d.ts +11 -0
  184. package/dist/runtime/composables/useSearchIndex.js +71 -0
  185. package/dist/runtime/composables/useViewerSearch.d.ts +32 -0
  186. package/dist/runtime/composables/useViewerSearch.js +418 -0
  187. package/dist/runtime/composables/useViewerState.d.ts +62 -0
  188. package/dist/runtime/composables/useViewerState.js +189 -0
  189. package/dist/runtime/composables/viewMode.d.ts +11 -0
  190. package/dist/runtime/composables/viewMode.js +19 -0
  191. package/dist/runtime/plugin.d.ts +2 -0
  192. package/dist/runtime/plugin.js +3 -0
  193. package/dist/runtime/public-types.d.ts +2 -0
  194. package/dist/runtime/public-types.js +0 -0
  195. package/dist/runtime/server/tsconfig.json +3 -0
  196. package/dist/types.d.mts +5 -0
  197. package/package.json +64 -0
@@ -0,0 +1,418 @@
1
+ import {
2
+ inject,
3
+ provide,
4
+ ref
5
+ } from "vue";
6
+ import {
7
+ findMatchesInText,
8
+ flattenMatchesByPage,
9
+ getRenderRange,
10
+ stepMatchIndex
11
+ } from "./search-utils.js";
12
+ const VIEWER_SEARCH_KEY = Symbol("kviewer-search");
13
+ export function provideViewerSearch() {
14
+ const isOpen = ref(false);
15
+ const query = ref("");
16
+ const matchCase = ref(false);
17
+ const wholeWord = ref(false);
18
+ const highlightAll = ref(true);
19
+ const currentMatch = ref(0);
20
+ const totalMatches = ref(0);
21
+ const notFound = ref(false);
22
+ const pageLayers = /* @__PURE__ */ new Map();
23
+ const matchesByPage = /* @__PURE__ */ new Map();
24
+ let flattenedMatches = [];
25
+ let selectedGlobalIndex = -1;
26
+ let inputElement = null;
27
+ let _searchIndex = null;
28
+ let _scrollToPage = null;
29
+ function setSearchIndex(index) {
30
+ _searchIndex = index;
31
+ }
32
+ function setScrollToPage(fn) {
33
+ _scrollToPage = fn;
34
+ }
35
+ function getSortedPageNumbers() {
36
+ return [...pageLayers.keys()].sort((a, b) => a - b);
37
+ }
38
+ function ensureDivElement(binding, divIdx) {
39
+ const current = binding.textDivs[divIdx];
40
+ if (!current) return null;
41
+ if (typeof Node !== "undefined" && current.nodeType === Node.TEXT_NODE) {
42
+ const span = document.createElement("span");
43
+ const parent = current.parentNode;
44
+ if (!parent) return null;
45
+ parent.replaceChild(span, current);
46
+ binding.textDivs[divIdx] = span;
47
+ return span;
48
+ }
49
+ return current;
50
+ }
51
+ function clearPageHighlights(binding) {
52
+ for (let i = 0; i < binding.textDivs.length; i++) {
53
+ const div = ensureDivElement(binding, i);
54
+ if (!div) continue;
55
+ div.textContent = binding.sourceTextByDiv[i] ?? "";
56
+ div.className = "";
57
+ }
58
+ }
59
+ function convertPageMatches(pageMatches, sourceTextByDiv) {
60
+ if (pageMatches.length === 0 || sourceTextByDiv.length === 0) return [];
61
+ let i = 0;
62
+ let iIndex = 0;
63
+ const end = sourceTextByDiv.length - 1;
64
+ const converted = [];
65
+ for (const pageMatch of pageMatches) {
66
+ let matchIdx = pageMatch.index;
67
+ while (i !== end && matchIdx >= iIndex + sourceTextByDiv[i].length) {
68
+ iIndex += sourceTextByDiv[i].length;
69
+ i++;
70
+ }
71
+ const begin = {
72
+ divIdx: i,
73
+ offset: matchIdx - iIndex
74
+ };
75
+ matchIdx += pageMatch.length;
76
+ while (i !== end && matchIdx > iIndex + sourceTextByDiv[i].length) {
77
+ iIndex += sourceTextByDiv[i].length;
78
+ i++;
79
+ }
80
+ const endMatch = {
81
+ divIdx: i,
82
+ offset: matchIdx - iIndex
83
+ };
84
+ converted.push({ begin, end: endMatch });
85
+ }
86
+ return converted;
87
+ }
88
+ function appendTextToDiv(binding, divIdx, fromOffset, toOffset, className) {
89
+ const div = ensureDivElement(binding, divIdx);
90
+ if (!div) return null;
91
+ const sourceText = binding.sourceTextByDiv[divIdx] ?? "";
92
+ const content = toOffset === void 0 ? sourceText.slice(fromOffset) : sourceText.slice(fromOffset, toOffset);
93
+ const node = document.createTextNode(content);
94
+ if (!className) {
95
+ div.append(node);
96
+ return null;
97
+ }
98
+ const span = document.createElement("span");
99
+ span.className = `${className} appended`;
100
+ span.append(node);
101
+ div.append(span);
102
+ return className.includes("selected") ? span : null;
103
+ }
104
+ function beginText(binding, begin, className) {
105
+ const div = ensureDivElement(binding, begin.divIdx);
106
+ if (!div) return null;
107
+ div.textContent = "";
108
+ return appendTextToDiv(binding, begin.divIdx, 0, begin.offset, className);
109
+ }
110
+ function getSelectedLocation() {
111
+ if (selectedGlobalIndex < 0 || selectedGlobalIndex >= flattenedMatches.length) {
112
+ return null;
113
+ }
114
+ const selected = flattenedMatches[selectedGlobalIndex];
115
+ if (!selected) return null;
116
+ return {
117
+ pageNumber: selected.pageNumber,
118
+ matchIndex: selected.matchIndex
119
+ };
120
+ }
121
+ function renderHighlightsForPage(pageNumber, shouldScrollSelected) {
122
+ const binding = pageLayers.get(pageNumber);
123
+ if (!binding) return;
124
+ clearPageHighlights(binding);
125
+ if (!isOpen.value) return;
126
+ const pageMatches = matchesByPage.get(pageNumber) ?? [];
127
+ if (pageMatches.length === 0) return;
128
+ const selectedLocation = getSelectedLocation();
129
+ const isSelectedPage = selectedLocation?.pageNumber === pageNumber;
130
+ const selectedMatchIndex = isSelectedPage ? selectedLocation?.matchIndex ?? -1 : -1;
131
+ const range = getRenderRange(
132
+ pageMatches.length,
133
+ highlightAll.value,
134
+ isSelectedPage,
135
+ selectedMatchIndex
136
+ );
137
+ if (!range) return;
138
+ const convertedMatches = convertPageMatches(pageMatches, binding.sourceTextByDiv);
139
+ if (convertedMatches.length === 0) return;
140
+ let prevEnd = null;
141
+ let lastDivIdx = -1;
142
+ let lastOffset = -1;
143
+ for (let i = range.start; i < range.end; i++) {
144
+ const match = convertedMatches[i];
145
+ if (!match) continue;
146
+ const begin = match.begin;
147
+ if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) {
148
+ continue;
149
+ }
150
+ lastDivIdx = begin.divIdx;
151
+ lastOffset = begin.offset;
152
+ const end = match.end;
153
+ const isSelected = isSelectedPage && i === selectedMatchIndex;
154
+ const highlightSuffix = isSelected ? " selected" : "";
155
+ let selectedSpan = null;
156
+ if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
157
+ if (prevEnd) {
158
+ appendTextToDiv(binding, prevEnd.divIdx, prevEnd.offset, void 0);
159
+ }
160
+ beginText(binding, begin);
161
+ } else {
162
+ appendTextToDiv(binding, prevEnd.divIdx, prevEnd.offset, begin.offset);
163
+ }
164
+ if (begin.divIdx === end.divIdx) {
165
+ selectedSpan = appendTextToDiv(
166
+ binding,
167
+ begin.divIdx,
168
+ begin.offset,
169
+ end.offset,
170
+ `highlight${highlightSuffix}`
171
+ );
172
+ } else {
173
+ selectedSpan = appendTextToDiv(
174
+ binding,
175
+ begin.divIdx,
176
+ begin.offset,
177
+ void 0,
178
+ `highlight begin${highlightSuffix}`
179
+ );
180
+ for (let mid = begin.divIdx + 1; mid < end.divIdx; mid++) {
181
+ const middleDiv = ensureDivElement(binding, mid);
182
+ if (!middleDiv) continue;
183
+ middleDiv.className = `highlight middle${highlightSuffix}`;
184
+ }
185
+ beginText(binding, end, `highlight end${highlightSuffix}`);
186
+ }
187
+ prevEnd = end;
188
+ if (isSelected && shouldScrollSelected && selectedSpan) {
189
+ selectedSpan.scrollIntoView({
190
+ block: "start",
191
+ inline: "center"
192
+ });
193
+ }
194
+ }
195
+ if (prevEnd) {
196
+ appendTextToDiv(binding, prevEnd.divIdx, prevEnd.offset, void 0);
197
+ }
198
+ }
199
+ function renderAllHighlights(shouldScrollSelected = false) {
200
+ for (const pageNumber of getSortedPageNumbers()) {
201
+ renderHighlightsForPage(pageNumber, shouldScrollSelected);
202
+ }
203
+ }
204
+ function clearAllHighlights() {
205
+ for (const binding of pageLayers.values()) {
206
+ clearPageHighlights(binding);
207
+ }
208
+ }
209
+ function updateCounters() {
210
+ totalMatches.value = flattenedMatches.length;
211
+ currentMatch.value = selectedGlobalIndex >= 0 ? selectedGlobalIndex + 1 : 0;
212
+ notFound.value = query.value.length > 0 && totalMatches.value === 0;
213
+ }
214
+ function recomputeMatches({ preferFirst = false, shouldScrollSelected = false } = {}) {
215
+ const selectedLocation = getSelectedLocation();
216
+ matchesByPage.clear();
217
+ flattenedMatches = [];
218
+ if (!query.value) {
219
+ selectedGlobalIndex = -1;
220
+ updateCounters();
221
+ if (isOpen.value) {
222
+ clearAllHighlights();
223
+ }
224
+ return;
225
+ }
226
+ if (_searchIndex) {
227
+ const allPageNumbers = [];
228
+ for (let i = 1; i <= _searchIndex.totalPages; i++) {
229
+ allPageNumbers.push(i);
230
+ }
231
+ for (const pageNumber of allPageNumbers) {
232
+ const text = _searchIndex.getPageText(pageNumber);
233
+ if (text === null) continue;
234
+ const pageMatches = findMatchesInText(text, query.value, {
235
+ matchCase: matchCase.value,
236
+ wholeWord: wholeWord.value
237
+ });
238
+ if (pageMatches.length > 0) {
239
+ matchesByPage.set(pageNumber, pageMatches);
240
+ }
241
+ }
242
+ flattenedMatches = flattenMatchesByPage(allPageNumbers, matchesByPage);
243
+ } else {
244
+ const pageNumbers = getSortedPageNumbers();
245
+ for (const pageNumber of pageNumbers) {
246
+ const binding = pageLayers.get(pageNumber);
247
+ if (!binding) continue;
248
+ const pageMatches = findMatchesInText(binding.fullText, query.value, {
249
+ matchCase: matchCase.value,
250
+ wholeWord: wholeWord.value
251
+ });
252
+ matchesByPage.set(pageNumber, pageMatches);
253
+ }
254
+ flattenedMatches = flattenMatchesByPage(pageNumbers, matchesByPage);
255
+ }
256
+ if (flattenedMatches.length === 0) {
257
+ selectedGlobalIndex = -1;
258
+ } else if (preferFirst) {
259
+ selectedGlobalIndex = 0;
260
+ } else if (selectedLocation) {
261
+ const preservedIndex = flattenedMatches.findIndex(
262
+ (entry) => entry.pageNumber === selectedLocation.pageNumber && entry.matchIndex === selectedLocation.matchIndex
263
+ );
264
+ selectedGlobalIndex = preservedIndex >= 0 ? preservedIndex : 0;
265
+ } else {
266
+ selectedGlobalIndex = 0;
267
+ }
268
+ updateCounters();
269
+ if (isOpen.value) {
270
+ renderAllHighlights(shouldScrollSelected);
271
+ }
272
+ }
273
+ function setPageBinding(pageNumber, textDivs, textContentItemsStr) {
274
+ const sourceTextByDiv = textDivs.map((div, index) => div.textContent ?? textContentItemsStr[index] ?? "");
275
+ pageLayers.set(pageNumber, {
276
+ textDivs,
277
+ sourceTextByDiv,
278
+ fullText: sourceTextByDiv.join("")
279
+ });
280
+ if (query.value) {
281
+ recomputeMatches();
282
+ } else if (isOpen.value) {
283
+ renderHighlightsForPage(pageNumber, false);
284
+ }
285
+ }
286
+ function open() {
287
+ if (isOpen.value) return;
288
+ isOpen.value = true;
289
+ renderAllHighlights();
290
+ }
291
+ function close() {
292
+ if (!isOpen.value) return;
293
+ isOpen.value = false;
294
+ clearAllHighlights();
295
+ }
296
+ function reset() {
297
+ close();
298
+ query.value = "";
299
+ matchCase.value = false;
300
+ wholeWord.value = false;
301
+ highlightAll.value = true;
302
+ currentMatch.value = 0;
303
+ totalMatches.value = 0;
304
+ notFound.value = false;
305
+ matchesByPage.clear();
306
+ flattenedMatches = [];
307
+ selectedGlobalIndex = -1;
308
+ pageLayers.clear();
309
+ inputElement = null;
310
+ _searchIndex = null;
311
+ _scrollToPage = null;
312
+ }
313
+ function setQuery(value) {
314
+ query.value = value;
315
+ recomputeMatches({ preferFirst: true, shouldScrollSelected: true });
316
+ }
317
+ function toggleMatchCase() {
318
+ matchCase.value = !matchCase.value;
319
+ recomputeMatches();
320
+ }
321
+ function toggleWholeWord() {
322
+ wholeWord.value = !wholeWord.value;
323
+ recomputeMatches();
324
+ }
325
+ function toggleHighlightAll() {
326
+ highlightAll.value = !highlightAll.value;
327
+ if (isOpen.value) {
328
+ renderAllHighlights();
329
+ }
330
+ }
331
+ function scrollToSelectedMatch() {
332
+ if (!_scrollToPage) return;
333
+ const location = getSelectedLocation();
334
+ if (!location) return;
335
+ if (!pageLayers.has(location.pageNumber)) {
336
+ _scrollToPage(location.pageNumber);
337
+ }
338
+ }
339
+ function findNext() {
340
+ selectedGlobalIndex = stepMatchIndex(selectedGlobalIndex, flattenedMatches.length, false);
341
+ updateCounters();
342
+ scrollToSelectedMatch();
343
+ if (isOpen.value) {
344
+ renderAllHighlights(true);
345
+ }
346
+ }
347
+ function findPrevious() {
348
+ selectedGlobalIndex = stepMatchIndex(selectedGlobalIndex, flattenedMatches.length, true);
349
+ updateCounters();
350
+ scrollToSelectedMatch();
351
+ if (isOpen.value) {
352
+ renderAllHighlights(true);
353
+ }
354
+ }
355
+ function registerPageLayer(pageNumber, textDivs, textContentItemsStr) {
356
+ setPageBinding(pageNumber, textDivs, textContentItemsStr);
357
+ }
358
+ function updatePageLayer(pageNumber, textDivs, textContentItemsStr) {
359
+ setPageBinding(pageNumber, textDivs, textContentItemsStr);
360
+ }
361
+ function unregisterPageLayer(pageNumber) {
362
+ const binding = pageLayers.get(pageNumber);
363
+ if (binding) {
364
+ clearPageHighlights(binding);
365
+ }
366
+ pageLayers.delete(pageNumber);
367
+ matchesByPage.delete(pageNumber);
368
+ if (query.value) {
369
+ recomputeMatches();
370
+ } else {
371
+ flattenedMatches = [];
372
+ selectedGlobalIndex = -1;
373
+ updateCounters();
374
+ }
375
+ }
376
+ function setInputElement(input) {
377
+ inputElement = input;
378
+ }
379
+ function focusInput() {
380
+ inputElement?.focus();
381
+ inputElement?.select();
382
+ }
383
+ const state = {
384
+ isOpen,
385
+ query,
386
+ matchCase,
387
+ wholeWord,
388
+ highlightAll,
389
+ currentMatch,
390
+ totalMatches,
391
+ notFound,
392
+ open,
393
+ close,
394
+ reset,
395
+ setQuery,
396
+ toggleMatchCase,
397
+ toggleWholeWord,
398
+ toggleHighlightAll,
399
+ findNext,
400
+ findPrevious,
401
+ registerPageLayer,
402
+ updatePageLayer,
403
+ unregisterPageLayer,
404
+ setInputElement,
405
+ focusInput,
406
+ setSearchIndex,
407
+ setScrollToPage
408
+ };
409
+ provide(VIEWER_SEARCH_KEY, state);
410
+ return state;
411
+ }
412
+ export function useViewerSearch() {
413
+ const state = inject(VIEWER_SEARCH_KEY);
414
+ if (!state) {
415
+ throw new Error("useViewerSearch() must be used inside a <KViewer> component");
416
+ }
417
+ return state;
418
+ }
@@ -0,0 +1,62 @@
1
+ import { type Ref, type ShallowRef } from 'vue';
2
+ import type { PDFDocumentProxy } from 'pdfjs-dist';
3
+ import type { Painter } from '../annotation/engine/painter.js';
4
+ import { AnnotationType, type IAnnotationStore, type StampDefinition, type SignatureData, type SignatureHandlers } from '../annotation/engine/types.js';
5
+ import { type AnnotationHistory } from './useAnnotationHistory.js';
6
+ import { type FitMode } from './viewMode.js';
7
+ export type { FitMode, ViewMode } from './viewMode.js';
8
+ export { mapViewModeToFitMode, normalizeZoom } from './viewMode.js';
9
+ export type ActiveTool = 'hand' | 'marquee' | 'eraser' | AnnotationType;
10
+ export interface ViewerState {
11
+ scale: Ref<number>;
12
+ scaleOptions: number[];
13
+ fitMode: Ref<FitMode>;
14
+ containerDimensions: Ref<{
15
+ width: number;
16
+ height: number;
17
+ }>;
18
+ pageDimensions: Ref<{
19
+ width: number;
20
+ height: number;
21
+ } | null>;
22
+ setFitMode: (mode: FitMode) => void;
23
+ zoomIn: () => void;
24
+ zoomOut: () => void;
25
+ setScale: (value: number) => void;
26
+ currentPage: Ref<number>;
27
+ totalPages: Ref<number>;
28
+ isLoading: Ref<boolean>;
29
+ activeTool: Ref<ActiveTool>;
30
+ doc: ShallowRef<PDFDocumentProxy | null>;
31
+ annotations: ShallowRef<Map<string, IAnnotationStore>>;
32
+ selectedAnnotation: Ref<IAnnotationStore | null>;
33
+ selectedAnnotations: Ref<IAnnotationStore[]>;
34
+ selectionRect: Ref<{
35
+ x: number;
36
+ y: number;
37
+ width: number;
38
+ height: number;
39
+ } | null>;
40
+ painter: ShallowRef<Painter | null>;
41
+ stamps: Ref<StampDefinition[]>;
42
+ activeStamp: Ref<StampDefinition | null>;
43
+ signatures: Ref<SignatureData[]>;
44
+ activeSignature: Ref<SignatureData | null>;
45
+ signatureHandlers: SignatureHandlers | null;
46
+ loadSignatures: () => Promise<void>;
47
+ saveSignature: (imageUrl: string) => Promise<SignatureData | null>;
48
+ deleteSignature: (id: string) => Promise<void>;
49
+ selectTool: (tool: ActiveTool, dataTransfer?: string | null) => void;
50
+ deleteAnnotation: (id: string) => void;
51
+ getAnnotations: () => IAnnotationStore[];
52
+ stylusMode: Ref<boolean>;
53
+ setStylusMode: (enabled: boolean) => void;
54
+ scrollToPage: (pageNumber: number) => void;
55
+ history: AnnotationHistory;
56
+ }
57
+ export interface ViewerStateProvider {
58
+ state: ViewerState;
59
+ setScrollToPageFn: (fn: (pageNumber: number) => void) => void;
60
+ }
61
+ export declare function provideViewerState(): ViewerStateProvider;
62
+ export declare function useViewerState(): ViewerState;
@@ -0,0 +1,189 @@
1
+ import {
2
+ ref,
3
+ shallowRef,
4
+ provide,
5
+ inject,
6
+ triggerRef,
7
+ watch
8
+ } from "vue";
9
+ import {
10
+ AnnotationType
11
+ } from "../annotation/engine/types.js";
12
+ import { annotationDefinitions } from "../annotation/engine/config.js";
13
+ import { createAnnotationHistory } from "./useAnnotationHistory.js";
14
+ import { computeScaleForFitMode } from "./viewMode.js";
15
+ export { mapViewModeToFitMode, normalizeZoom } from "./viewMode.js";
16
+ const VIEWER_STATE_KEY = Symbol("kviewer-state");
17
+ const SCALE_OPTIONS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2];
18
+ export function provideViewerState() {
19
+ const scale = ref(1);
20
+ const currentPage = ref(1);
21
+ const totalPages = ref(0);
22
+ const isLoading = ref(false);
23
+ const activeTool = ref("hand");
24
+ const doc = shallowRef(null);
25
+ const annotations = shallowRef(/* @__PURE__ */ new Map());
26
+ const selectedAnnotation = ref(null);
27
+ const selectedAnnotations = ref([]);
28
+ const selectionRect = ref(null);
29
+ const painter = shallowRef(null);
30
+ const fitMode = ref("fit-width");
31
+ const containerDimensions = ref({ width: 0, height: 0 });
32
+ const pageDimensions = ref(null);
33
+ watch(
34
+ [fitMode, containerDimensions, pageDimensions],
35
+ ([mode, container, page]) => {
36
+ if (mode === "custom" || !page || !container.width || !container.height) return;
37
+ scale.value = computeScaleForFitMode(mode, container, page, scale.value);
38
+ }
39
+ );
40
+ function setFitMode(mode) {
41
+ fitMode.value = mode;
42
+ }
43
+ function setScale(value) {
44
+ fitMode.value = "custom";
45
+ scale.value = value;
46
+ }
47
+ function zoomIn() {
48
+ const currentIndex = SCALE_OPTIONS.indexOf(scale.value);
49
+ if (currentIndex >= 0 && currentIndex < SCALE_OPTIONS.length - 1) {
50
+ setScale(SCALE_OPTIONS[currentIndex + 1]);
51
+ } else if (currentIndex === -1) {
52
+ const next = SCALE_OPTIONS.find((s) => s > scale.value);
53
+ if (next !== void 0) setScale(next);
54
+ }
55
+ }
56
+ function zoomOut() {
57
+ const currentIndex = SCALE_OPTIONS.indexOf(scale.value);
58
+ if (currentIndex > 0) {
59
+ setScale(SCALE_OPTIONS[currentIndex - 1]);
60
+ } else if (currentIndex === -1) {
61
+ const prev = [...SCALE_OPTIONS].reverse().find((s) => s < scale.value);
62
+ if (prev !== void 0) setScale(prev);
63
+ }
64
+ }
65
+ const stylusMode = ref(false);
66
+ function setStylusMode(enabled) {
67
+ stylusMode.value = enabled;
68
+ if (painter.value) {
69
+ painter.value.refreshStylusMode();
70
+ }
71
+ }
72
+ const stamps = ref([]);
73
+ const activeStamp = ref(null);
74
+ const signatures = ref([]);
75
+ const activeSignature = ref(null);
76
+ let _signatureHandlers = null;
77
+ async function loadSignatures() {
78
+ if (!_signatureHandlers) return;
79
+ signatures.value = await _signatureHandlers.onLoad();
80
+ }
81
+ async function saveSignature(imageUrl) {
82
+ if (!_signatureHandlers) return null;
83
+ const sig = await _signatureHandlers.onSave(imageUrl);
84
+ signatures.value = [...signatures.value, sig];
85
+ return sig;
86
+ }
87
+ async function deleteSignature(id) {
88
+ if (!_signatureHandlers) return;
89
+ await _signatureHandlers.onDelete(id);
90
+ signatures.value = signatures.value.filter((s) => s.id !== id);
91
+ if (activeSignature.value?.id === id) activeSignature.value = null;
92
+ }
93
+ function selectTool(tool, dataTransfer) {
94
+ activeTool.value = tool;
95
+ selectedAnnotation.value = null;
96
+ selectedAnnotations.value = [];
97
+ selectionRect.value = null;
98
+ if (!painter.value) return;
99
+ if (typeof tool === "number") {
100
+ const annotationDef = annotationDefinitions.find(
101
+ (d) => d.type === tool
102
+ );
103
+ painter.value.activate(annotationDef ?? null, dataTransfer ?? null);
104
+ } else if (tool === "marquee") {
105
+ painter.value.activateMarquee();
106
+ } else if (tool === "eraser") {
107
+ painter.value.activateEraser();
108
+ } else {
109
+ const selectDef = annotationDefinitions.find(
110
+ (d) => d.type === AnnotationType.SELECT
111
+ );
112
+ painter.value.activate(selectDef ?? null, null);
113
+ }
114
+ }
115
+ function deleteAnnotation(id) {
116
+ if (painter.value) {
117
+ painter.value.delete(id, true);
118
+ annotations.value.delete(id);
119
+ triggerRef(annotations);
120
+ selectedAnnotation.value = null;
121
+ selectionRect.value = null;
122
+ }
123
+ }
124
+ function getAnnotations() {
125
+ return painter.value?.getData() ?? [];
126
+ }
127
+ let _scrollToPageFn = null;
128
+ function scrollToPage(pageNumber) {
129
+ _scrollToPageFn?.(pageNumber);
130
+ }
131
+ const history = createAnnotationHistory(annotations, painter);
132
+ const state = {
133
+ scale,
134
+ scaleOptions: SCALE_OPTIONS,
135
+ fitMode,
136
+ containerDimensions,
137
+ pageDimensions,
138
+ setFitMode,
139
+ zoomIn,
140
+ zoomOut,
141
+ setScale,
142
+ currentPage,
143
+ totalPages,
144
+ isLoading,
145
+ activeTool,
146
+ doc,
147
+ annotations,
148
+ selectedAnnotation,
149
+ selectedAnnotations,
150
+ selectionRect,
151
+ painter,
152
+ stamps,
153
+ activeStamp,
154
+ signatures,
155
+ activeSignature,
156
+ get signatureHandlers() {
157
+ return _signatureHandlers;
158
+ },
159
+ set signatureHandlers(v) {
160
+ _signatureHandlers = v;
161
+ },
162
+ loadSignatures,
163
+ saveSignature,
164
+ deleteSignature,
165
+ selectTool,
166
+ deleteAnnotation,
167
+ getAnnotations,
168
+ stylusMode,
169
+ setStylusMode,
170
+ scrollToPage,
171
+ history
172
+ };
173
+ provide(VIEWER_STATE_KEY, state);
174
+ return {
175
+ state,
176
+ setScrollToPageFn(fn) {
177
+ _scrollToPageFn = fn;
178
+ }
179
+ };
180
+ }
181
+ export function useViewerState() {
182
+ const state = inject(VIEWER_STATE_KEY);
183
+ if (!state) {
184
+ throw new Error(
185
+ "useViewerState() must be used inside a <KViewer> component"
186
+ );
187
+ }
188
+ return state;
189
+ }
@@ -0,0 +1,11 @@
1
+ export type ViewMode = 'fit-width' | 'fit-page' | 'zoom';
2
+ export type FitMode = 'fit-width' | 'fit-page' | 'custom';
3
+ export declare function mapViewModeToFitMode(mode: ViewMode): FitMode;
4
+ export declare function normalizeZoom(zoom: number): number;
5
+ export declare function computeScaleForFitMode(mode: FitMode, container: {
6
+ width: number;
7
+ height: number;
8
+ }, page: {
9
+ width: number;
10
+ height: number;
11
+ }, currentScale: number): number;
@@ -0,0 +1,19 @@
1
+ export function mapViewModeToFitMode(mode) {
2
+ return mode === "zoom" ? "custom" : mode;
3
+ }
4
+ export function normalizeZoom(zoom) {
5
+ if (!Number.isFinite(zoom) || zoom <= 0) {
6
+ return 1;
7
+ }
8
+ return zoom;
9
+ }
10
+ export function computeScaleForFitMode(mode, container, page, currentScale) {
11
+ switch (mode) {
12
+ case "fit-width":
13
+ return container.width / page.width;
14
+ case "fit-page":
15
+ return Math.min(container.width / page.width, container.height / page.height);
16
+ default:
17
+ return currentScale;
18
+ }
19
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import { defineNuxtPlugin } from "#app";
2
+ export default defineNuxtPlugin((_nuxtApp) => {
3
+ });