@progress/kendo-react-pdf-viewer 5.10.0-dev.202211241147

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.
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Scroller = void 0;
4
+ const kendo_draggable_1 = require("@telerik/kendo-draggable");
5
+ const throttle = function (func, wait, options = {}) {
6
+ let timeout, context, args, result;
7
+ let previous = 0;
8
+ options = options || {};
9
+ const later = function () {
10
+ previous = options.leading === false ? 0 : new Date().getTime();
11
+ timeout = undefined;
12
+ result = func.apply(context, args);
13
+ if (!timeout) {
14
+ context = args = null;
15
+ }
16
+ };
17
+ const throttled = function () {
18
+ const now = new Date().getTime();
19
+ if (!previous && options.leading === false) {
20
+ previous = now;
21
+ }
22
+ const remaining = wait - (now - previous);
23
+ context = undefined; // this
24
+ args = arguments;
25
+ if (remaining <= 0 || remaining > wait) {
26
+ if (timeout) {
27
+ clearTimeout(timeout);
28
+ timeout = undefined;
29
+ }
30
+ previous = now;
31
+ result = func.apply(context, args);
32
+ if (!timeout) {
33
+ context = args = null;
34
+ }
35
+ }
36
+ else if (!timeout && options.trailing !== false) {
37
+ timeout = window.setTimeout(later, remaining);
38
+ }
39
+ return result;
40
+ };
41
+ return throttled;
42
+ };
43
+ const preventDefault = (e) => {
44
+ if (e.preventDefault) {
45
+ e.preventDefault();
46
+ }
47
+ if (e.originalEvent) {
48
+ e.originalEvent.preventDefault();
49
+ }
50
+ };
51
+ const matchesElementSelector = (element, selector) => {
52
+ if (!element || !selector) {
53
+ return false;
54
+ }
55
+ return element.closest(selector);
56
+ };
57
+ const FRAMES_PER_SECOND = 1000 / 60;
58
+ const SCROLL = 'scroll';
59
+ /**
60
+ * @hidden
61
+ */
62
+ class Scroller {
63
+ constructor(element, options) {
64
+ this.options = {
65
+ // the drag directions are actually reversed, e.g.
66
+ // dragging to the right actually moves the document to the left
67
+ scrollDirectionModifier: -1,
68
+ // throttle the scroll events to get a more similar experience
69
+ // to the scrolling behavior in Adobe Acrobat Reader
70
+ // as well as allow a way to improve the scrolling performance for large files
71
+ panScrollThrottleDelay: FRAMES_PER_SECOND,
72
+ scrollThrottleDelay: FRAMES_PER_SECOND,
73
+ filter: '',
74
+ events: {
75
+ [SCROLL]: () => { }
76
+ }
77
+ };
78
+ this.onElementScroll = () => {
79
+ const element = this.element;
80
+ if (this.state.trackNextElementScroll) {
81
+ this.scrollTo(element.scrollLeft, element.scrollTop);
82
+ }
83
+ else {
84
+ // reset the state, so that consecutive scroll events can be handled
85
+ this.state.trackNextElementScroll = true;
86
+ }
87
+ };
88
+ this.OnDragStart = (e) => {
89
+ this.state.dragStarted = false;
90
+ if (!this.shouldTrackPanEvents()) {
91
+ return;
92
+ }
93
+ const target = e.target || (e.originalEvent || {}).target;
94
+ if (this.options.filter && !matchesElementSelector(target, this.options.filter)) {
95
+ return;
96
+ }
97
+ preventDefault(e);
98
+ this.setState({
99
+ dragStarted: true,
100
+ location: {
101
+ pageX: e.pageX,
102
+ pageY: e.pageY
103
+ },
104
+ locationDelta: {
105
+ x: 0,
106
+ y: 0
107
+ }
108
+ });
109
+ };
110
+ this.onDrag = (e) => {
111
+ if (!this.shouldTrackPanEvents() || !this.state.dragStarted) {
112
+ return;
113
+ }
114
+ this.calculateEventLocationDelta(e);
115
+ this.setState({
116
+ location: {
117
+ pageX: e.pageX,
118
+ pageY: e.pageY
119
+ }
120
+ });
121
+ const directionModifier = this.options.scrollDirectionModifier;
122
+ const scrollLeft = this.element.scrollLeft + (directionModifier * this.state.locationDelta.x);
123
+ const scrollTop = this.element.scrollTop + (directionModifier * this.state.locationDelta.y);
124
+ this.scrollTo(scrollLeft, scrollTop);
125
+ };
126
+ this.onDragEnd = () => {
127
+ if (!this.shouldTrackPanEvents()) {
128
+ return;
129
+ }
130
+ };
131
+ this.element = element;
132
+ this.options = Object.assign({}, this.options, options);
133
+ this.resetState();
134
+ this.bindEvents();
135
+ }
136
+ destroy() {
137
+ this.unbindEvents();
138
+ }
139
+ initDraggable() {
140
+ this.destroyDraggable();
141
+ if (this.options.panScrollThrottleDelay > 0) {
142
+ this.throttledOnDrag = throttle(this.onDrag, this.options.panScrollThrottleDelay);
143
+ }
144
+ else {
145
+ this.throttledOnDrag = this.onDrag;
146
+ }
147
+ this.draggable = new kendo_draggable_1.default({
148
+ mouseOnly: false,
149
+ press: this.OnDragStart,
150
+ drag: this.throttledOnDrag,
151
+ release: this.onDragEnd
152
+ });
153
+ this.draggable.bindTo(this.element);
154
+ }
155
+ destroyDraggable() {
156
+ if (this.draggable && this.draggable.destroy) {
157
+ this.draggable.destroy();
158
+ if (this.throttledOnDrag && this.throttledOnDrag.cancel) {
159
+ this.throttledOnDrag.cancel();
160
+ this.throttledOnDrag = null;
161
+ }
162
+ }
163
+ }
164
+ bindEvents() {
165
+ this.bindDraggableEvents();
166
+ this.bindElementScroll();
167
+ }
168
+ bindDraggableEvents() {
169
+ this.initDraggable();
170
+ }
171
+ bindElementScroll() {
172
+ if (this.options.scrollThrottleDelay > 0) {
173
+ this.throttledOnElementScroll = throttle(this.onElementScroll, this.options.scrollThrottleDelay);
174
+ }
175
+ else {
176
+ this.throttledOnElementScroll = this.onElementScroll;
177
+ }
178
+ this.element.addEventListener(SCROLL, this.throttledOnElementScroll);
179
+ }
180
+ unbindEvents() {
181
+ this.unbindElementScroll();
182
+ this.unbindDraggableEvents();
183
+ }
184
+ unbindDraggableEvents() {
185
+ this.destroyDraggable();
186
+ }
187
+ unbindElementScroll() {
188
+ if (this.throttledOnElementScroll && this.throttledOnElementScroll.cancel) {
189
+ this.throttledOnElementScroll.cancel();
190
+ this.throttledOnElementScroll = null;
191
+ }
192
+ this.element.removeEventListener(SCROLL, this.throttledOnElementScroll);
193
+ }
194
+ setState(newState) {
195
+ this.state = Object.assign({}, this.state || {}, newState);
196
+ }
197
+ resetState() {
198
+ this.setState({
199
+ trackPanEvents: false,
200
+ trackNextElementScroll: false,
201
+ location: { pageX: 0, pageY: 0 },
202
+ locationDelta: { x: 0, y: 0 }
203
+ });
204
+ }
205
+ enablePanEventsTracking() {
206
+ this.state.trackPanEvents = true;
207
+ this.bindDraggableEvents();
208
+ }
209
+ disablePanEventsTracking() {
210
+ this.unbindDraggableEvents();
211
+ this.state.trackPanEvents = false;
212
+ }
213
+ shouldTrackPanEvents() {
214
+ return this.state.trackPanEvents;
215
+ }
216
+ calculateEventLocationDelta(e) {
217
+ this.state.locationDelta = {
218
+ x: e.pageX - this.state.location.pageX,
219
+ y: e.pageY - this.state.location.pageY
220
+ };
221
+ }
222
+ scrollTo(x, y, options = { trackScrollEvent: true }) {
223
+ if (!options.trackScrollEvent) {
224
+ this.state.trackNextElementScroll = false;
225
+ }
226
+ this.element.scrollLeft = x;
227
+ this.element.scrollTop = y;
228
+ }
229
+ }
230
+ exports.Scroller = Scroller;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @hidden
3
+ */
4
+ export declare class SearchService {
5
+ options: {
6
+ highlightClass: string;
7
+ highlightMarkClass: string;
8
+ charClass: string;
9
+ textContainers: never[];
10
+ };
11
+ state: any;
12
+ constructor(options: any);
13
+ destroy(): void;
14
+ extendOptions(options: any): void;
15
+ setState(newState: any): void;
16
+ resetState(): void;
17
+ search({ text, matchCase }: any): {
18
+ startOffset: number;
19
+ endOffset: number;
20
+ }[];
21
+ clearSearch(): void;
22
+ restoreOriginalText(): void;
23
+ shouldTransformText(): boolean;
24
+ transformTextForSearch(): void;
25
+ extractTextNodes(node: any): void;
26
+ transformTextNodesForSearch(textNodes: any): void;
27
+ transformTextNodeForSearch(node: any): void;
28
+ splitTextByChars(text: any): string;
29
+ forEachTextContainer(callback: any): void;
30
+ highlightAllMatches(): void;
31
+ addMatchHighlight(matchStartOffset: number, matchEndOffset: number, matchIndex: number): void;
32
+ removeMatchHighlights(): void;
33
+ addActiveMatchMark(): void;
34
+ removeActiveMatchMark(): void;
35
+ removeIndicators(): void;
36
+ markNextMatch(): void;
37
+ markPreviousMatch(): void;
38
+ markNextMatchIndex(): void;
39
+ markPreviousMatchIndex(): void;
40
+ moveActiveMatchIndex(delta: any): void;
41
+ getActiveMatchElement(): undefined;
42
+ }
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SearchService = void 0;
4
+ const unwrapElement = (element) => {
5
+ const parentElement = element.parentElement;
6
+ if (!element || !parentElement) {
7
+ return;
8
+ }
9
+ parentElement.replaceWith(...Array.from(parentElement.childNodes));
10
+ };
11
+ const unwrapElements = (elements) => {
12
+ if (!elements || !elements.length || elements.length <= 0) {
13
+ return;
14
+ }
15
+ for (let i = 0; i < elements.length; i++) {
16
+ unwrapElement(elements[i]);
17
+ }
18
+ };
19
+ const wrapElement = (element, wrapper) => {
20
+ if (element.parentNode) {
21
+ element.parentNode.insertBefore(wrapper, element);
22
+ wrapper.appendChild(element);
23
+ }
24
+ };
25
+ const wrapInnerElement = (element, wrapper) => {
26
+ if (!element || !element.parentNode || !wrapper) {
27
+ return;
28
+ }
29
+ element.appendChild(wrapper);
30
+ while (element.firstChild && element.firstChild !== wrapper) {
31
+ wrapper.appendChild(element.firstChild);
32
+ }
33
+ };
34
+ const addClass = (className, element) => { element.classList.add(className); };
35
+ const removeClass = (className, element) => { element.classList.remove(className); };
36
+ const toClassSelector = (className) => `.${className}`;
37
+ const CHAR_INDEX_DATA_ATTR = 'data-char-index';
38
+ const MATCH_INDEX_DATA_ATTR = 'data-match-index';
39
+ /**
40
+ * @hidden
41
+ */
42
+ class SearchService {
43
+ constructor(options) {
44
+ this.options = {
45
+ highlightClass: 'k-search-highlight',
46
+ highlightMarkClass: 'k-search-highlight-mark',
47
+ charClass: 'k-text-char',
48
+ textContainers: []
49
+ };
50
+ this.extendOptions(options);
51
+ this.resetState();
52
+ }
53
+ destroy() {
54
+ this.clearSearch();
55
+ }
56
+ extendOptions(options) {
57
+ this.options = Object.assign({}, this.options, options);
58
+ }
59
+ setState(newState) {
60
+ this.state = Object.assign({}, this.state || {}, newState);
61
+ }
62
+ resetState() {
63
+ this.setState({
64
+ text: '',
65
+ textNodes: [],
66
+ charIndex: 0,
67
+ activeMatchIndex: 0,
68
+ matches: []
69
+ });
70
+ }
71
+ search({ text, matchCase }) {
72
+ let searchRegex = new RegExp(text, matchCase ? 'g' : 'ig');
73
+ let match;
74
+ if (this.shouldTransformText()) {
75
+ this.transformTextForSearch();
76
+ }
77
+ this.state.matches = [];
78
+ this.state.activeMatchIndex = 0;
79
+ this.removeIndicators();
80
+ if (text === '') {
81
+ return [];
82
+ }
83
+ match = searchRegex.exec(this.state.text);
84
+ while (match) {
85
+ this.state.matches.push({
86
+ startOffset: match.index,
87
+ endOffset: match.index + match[0].length
88
+ });
89
+ match = searchRegex.exec(this.state.text);
90
+ }
91
+ this.highlightAllMatches();
92
+ this.addActiveMatchMark();
93
+ return this.state.matches;
94
+ }
95
+ clearSearch() {
96
+ this.removeIndicators();
97
+ this.restoreOriginalText();
98
+ }
99
+ restoreOriginalText() {
100
+ this.forEachTextContainer((textContainer) => {
101
+ const nodes = Array.from(textContainer.querySelectorAll('span:not(.' + this.options.charClass + ')'));
102
+ nodes.forEach((node) => {
103
+ node.innerHTML = node.textContent;
104
+ });
105
+ });
106
+ }
107
+ shouldTransformText() {
108
+ return !this.state.text;
109
+ }
110
+ transformTextForSearch() {
111
+ this.state.textNodes = [];
112
+ this.state.charIndex = 0;
113
+ this.state.text = '';
114
+ this.forEachTextContainer((textContainer) => {
115
+ this.extractTextNodes(textContainer);
116
+ });
117
+ this.transformTextNodesForSearch(this.state.textNodes);
118
+ }
119
+ extractTextNodes(node) {
120
+ if (node.nodeType === Node.TEXT_NODE) {
121
+ this.state.textNodes.push(node);
122
+ }
123
+ else {
124
+ for (let i = 0; i < node.childNodes.length; i++) {
125
+ this.extractTextNodes(node.childNodes[i]);
126
+ }
127
+ }
128
+ }
129
+ transformTextNodesForSearch(textNodes) {
130
+ for (let i = 0; i < textNodes.length; i++) {
131
+ this.transformTextNodeForSearch(textNodes[i]);
132
+ }
133
+ }
134
+ transformTextNodeForSearch(node) {
135
+ const text = node.textContent;
136
+ if (text.length <= 0) {
137
+ return;
138
+ }
139
+ this.state.text = this.state.text + text;
140
+ const span = document.createElement('span');
141
+ wrapElement(node, span);
142
+ const splittedHtml = this.splitTextByChars(text);
143
+ span.innerHTML = splittedHtml;
144
+ unwrapElement(span.childNodes[0]);
145
+ }
146
+ splitTextByChars(text) {
147
+ let splittedTextHtml = '';
148
+ for (let i = 0; i < text.length; i++) {
149
+ splittedTextHtml +=
150
+ '<span class=\'' + this.options.charClass + '\' ' + CHAR_INDEX_DATA_ATTR + '=' + this.state.charIndex + '>' +
151
+ text[i] +
152
+ '</span>';
153
+ this.state.charIndex++;
154
+ }
155
+ return splittedTextHtml;
156
+ }
157
+ forEachTextContainer(callback) {
158
+ for (let i = 0; i < this.options.textContainers.length; i++) {
159
+ const textContainer = this.options.textContainers[i];
160
+ callback(textContainer, i);
161
+ }
162
+ }
163
+ highlightAllMatches() {
164
+ this.state.matches.forEach((match, matchIndex) => {
165
+ this.addMatchHighlight(match.startOffset, match.endOffset, matchIndex);
166
+ });
167
+ }
168
+ addMatchHighlight(matchStartOffset, matchEndOffset, matchIndex) {
169
+ for (let i = matchStartOffset; i < matchEndOffset; i++) {
170
+ this.forEachTextContainer((textContainer) => {
171
+ const highlights = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.charClass + '[' + CHAR_INDEX_DATA_ATTR + '=\'' + i + '\'' + ']')));
172
+ highlights.forEach((highlight) => {
173
+ addClass(this.options.highlightClass, highlight);
174
+ highlight.setAttribute(MATCH_INDEX_DATA_ATTR, matchIndex);
175
+ });
176
+ });
177
+ }
178
+ }
179
+ removeMatchHighlights() {
180
+ this.forEachTextContainer((textContainer) => {
181
+ const highlights = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.highlightClass)));
182
+ highlights.forEach((highlight) => {
183
+ removeClass(this.options.highlightClass, highlight);
184
+ highlight.removeAttribute(MATCH_INDEX_DATA_ATTR);
185
+ });
186
+ });
187
+ }
188
+ addActiveMatchMark() {
189
+ if (!this.state.activeMatchIndex && this.state.activeMatchIndex !== 0) {
190
+ this.state.activeMatchIndex = 0;
191
+ }
192
+ else if (this.state.activeMatchIndex > this.state.matches.length) {
193
+ this.state.activeMatchIndex = this.state.matches.length;
194
+ }
195
+ else {
196
+ this.removeActiveMatchMark();
197
+ }
198
+ const mark = document.createElement('span');
199
+ mark.classList.add(this.options.highlightMarkClass);
200
+ this.forEachTextContainer((textContainer) => {
201
+ const matches = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.charClass + '[' + MATCH_INDEX_DATA_ATTR + '=\'' + this.state.activeMatchIndex + '\']')));
202
+ matches.forEach((match) => {
203
+ wrapInnerElement(match, mark.cloneNode(true));
204
+ });
205
+ });
206
+ }
207
+ removeActiveMatchMark() {
208
+ this.forEachTextContainer((textContainer) => {
209
+ const marks = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.highlightMarkClass)));
210
+ const childNodes = marks.flatMap((x) => Array.from(x.childNodes));
211
+ unwrapElements(childNodes);
212
+ });
213
+ }
214
+ removeIndicators() {
215
+ this.removeActiveMatchMark();
216
+ this.removeMatchHighlights();
217
+ }
218
+ markNextMatch() {
219
+ this.markNextMatchIndex();
220
+ this.addActiveMatchMark();
221
+ }
222
+ markPreviousMatch() {
223
+ this.markPreviousMatchIndex();
224
+ this.addActiveMatchMark();
225
+ }
226
+ markNextMatchIndex() {
227
+ this.moveActiveMatchIndex(1);
228
+ }
229
+ markPreviousMatchIndex() {
230
+ this.moveActiveMatchIndex(-1);
231
+ }
232
+ moveActiveMatchIndex(delta) {
233
+ this.state.activeMatchIndex += delta;
234
+ if (this.state.activeMatchIndex < 0) {
235
+ this.state.activeMatchIndex = Math.max(this.state.matches.length - 1, 0);
236
+ }
237
+ else if (this.state.activeMatchIndex > this.state.matches.length - 1) {
238
+ this.state.activeMatchIndex = 0;
239
+ }
240
+ }
241
+ getActiveMatchElement() {
242
+ let markedMatch;
243
+ this.forEachTextContainer((textContainer) => {
244
+ const mark = textContainer.querySelector(toClassSelector(this.options.highlightMarkClass));
245
+ if (mark) {
246
+ markedMatch = mark;
247
+ return;
248
+ }
249
+ });
250
+ return markedMatch;
251
+ }
252
+ }
253
+ exports.SearchService = SearchService;
@@ -0,0 +1,78 @@
1
+ import { SaveOptions } from '@progress/kendo-file-saver';
2
+ import { PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist';
3
+ import { TypedArray } from 'pdfjs-dist/types/src/display/api';
4
+ /**
5
+ * @hidden
6
+ */
7
+ export declare type DoneFn = (result: {
8
+ pdfPages: PDFPageProxy[];
9
+ pdfDoc: PDFDocumentProxy;
10
+ }) => void;
11
+ /**
12
+ * @hidden
13
+ */
14
+ export declare type ErrorFn = (e?: any) => void;
15
+ /**
16
+ * @hidden
17
+ */
18
+ export interface PDFReadParameters {
19
+ url?: string;
20
+ data?: string;
21
+ arrayBuffer?: ArrayBuffer;
22
+ typedArray?: TypedArray;
23
+ error: ErrorFn;
24
+ }
25
+ /**
26
+ * @hidden
27
+ */
28
+ export interface PDFReadOptions extends PDFReadParameters {
29
+ dom: HTMLDivElement;
30
+ zoom: number;
31
+ done: DoneFn;
32
+ }
33
+ /**
34
+ * @hidden
35
+ */
36
+ export interface PDFReloadParameters {
37
+ pdfDoc: PDFDocumentProxy;
38
+ zoom: number;
39
+ dom: HTMLElement;
40
+ done: (pdfPages: PDFPageProxy[]) => void;
41
+ error: ErrorFn;
42
+ }
43
+ /**
44
+ * @hidden
45
+ */
46
+ export declare const DEFAULT_ZOOM_LEVEL = 1.25;
47
+ /**
48
+ * @hidden
49
+ */
50
+ export declare const download: (options: PDFReadParameters, fileName: string | undefined, saveOptions: SaveOptions | undefined, onDownload: (blob: Blob, fileName: string, saveOptions: SaveOptions) => boolean) => void;
51
+ /**
52
+ * @hidden
53
+ */
54
+ export declare const loadPDF: (options: PDFReadOptions) => void;
55
+ /**
56
+ * @hidden
57
+ */
58
+ export declare const reloadDocument: (params: PDFReloadParameters) => void;
59
+ /**
60
+ * @hidden
61
+ */
62
+ export declare const print: (pages: PDFPageProxy[], done: () => void, error: ErrorFn) => void;
63
+ /**
64
+ * @hidden
65
+ */
66
+ export declare const goToNextSearchMatch: (ref: any) => void;
67
+ /**
68
+ * @hidden
69
+ */
70
+ export declare const goToPreviousSearchMatch: (ref: any) => void;
71
+ /**
72
+ * @hidden
73
+ */
74
+ export declare const calculateZoomLevel: (zoomLevel: number, zoomLevelType: string, currentZoom: number, dom: HTMLDivElement) => number;
75
+ /**
76
+ * @hidden
77
+ */
78
+ export declare const removeChildren: (dom: HTMLElement) => void;