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

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.
@@ -1,8 +1,9 @@
1
1
  import * as React from 'react';
2
- import { Toolbar } from '@progress/kendo-react-buttons';
2
+ import { ToolbarProps } from '@progress/kendo-react-buttons';
3
3
  import { SaveOptions } from '@progress/kendo-file-saver';
4
4
  import { TypedArray } from 'pdfjs-dist/types/src/display/api';
5
5
  import 'pdfjs-dist/build/pdf.worker.entry';
6
+ export declare type PDFViewerTool = 'pager' | 'spacer' | 'zoomInOut' | 'zoom' | 'selection' | 'search' | 'open' | 'download' | 'print';
6
7
  interface PDFViewerEvent {
7
8
  /**
8
9
  * The event target object.
@@ -42,6 +43,32 @@ export interface DownloadEvent extends PDFViewerEvent {
42
43
  */
43
44
  export interface LoadEvent extends PDFViewerEvent {
44
45
  }
46
+ /**
47
+ * The KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) ZoomEvent object.
48
+ */
49
+ export interface ZoomEvent extends PDFViewerEvent {
50
+ /**
51
+ * The zoom value.
52
+ */
53
+ zoom: number;
54
+ /**
55
+ * A React `SyntheticEvent`.
56
+ */
57
+ syntheticEvent: React.SyntheticEvent<any>;
58
+ }
59
+ /**
60
+ * The KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) PageEvent object.
61
+ */
62
+ export interface PageEvent extends PDFViewerEvent {
63
+ /**
64
+ * The page number.
65
+ */
66
+ page: number;
67
+ /**
68
+ * A React `SyntheticEvent`.
69
+ */
70
+ syntheticEvent: React.SyntheticEvent<any>;
71
+ }
45
72
  /**
46
73
  * The props of the KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) component.
47
74
  */
@@ -74,6 +101,12 @@ export interface PDFViewerProps {
74
101
  * Represents the options for saving the file when the user clicks the download tool.
75
102
  */
76
103
  saveOptions?: SaveOptions;
104
+ /**
105
+ * Represents the tools collection rendered in the toolbar.
106
+ *
107
+ * @default - ['pager', 'spacer', 'zoomInOut', 'zoom', 'selection', 'spacer', 'search', 'open', 'download', 'print']
108
+ */
109
+ tools?: PDFViewerTool[];
77
110
  /**
78
111
  * Represents the zoom levels populated in the ComboBox component.
79
112
  */
@@ -84,6 +117,26 @@ export interface PDFViewerProps {
84
117
  type: string;
85
118
  locationString?: string;
86
119
  }[];
120
+ /**
121
+ * Represents the zoom value of the document.
122
+ */
123
+ zoom?: number;
124
+ /**
125
+ * Represents the default zoom value.
126
+ */
127
+ defaultZoom?: number;
128
+ /**
129
+ * Represents the minimum zoom value.
130
+ */
131
+ minZoom?: number;
132
+ /**
133
+ * Represents the maximum zoom value.
134
+ */
135
+ maxZoom?: number;
136
+ /**
137
+ * Represents the zoom rate value.
138
+ */
139
+ zoomRate?: number;
87
140
  /**
88
141
  * Fires when an error occurs.
89
142
  */
@@ -95,11 +148,19 @@ export interface PDFViewerProps {
95
148
  /**
96
149
  * Fires when the download tool has been clicked. To prevent the download, return `false`.
97
150
  */
98
- onDownload?: (event: DownloadEvent) => boolean;
151
+ onDownload?: (event: DownloadEvent) => boolean | void;
152
+ /**
153
+ * Fires when the zoom has changed.
154
+ */
155
+ onZoom?: (event: ZoomEvent) => void;
156
+ /**
157
+ * Fires when the page has changed.
158
+ */
159
+ onPageChange?: (event: PageEvent) => void;
99
160
  /**
100
161
  * Fires when the toolbar component is about to be rendered. Use it to override the default appearance of the toolbar.
101
162
  */
102
- onRenderToolbar?: (defaultRendering: React.ReactElement<Toolbar>) => React.ReactNode;
163
+ onRenderToolbar?: (defaultRendering: React.ReactElement<ToolbarProps>) => React.ReactNode;
103
164
  /**
104
165
  * Fires when the content component is about to be rendered. Use it to override the default appearance of the content.
105
166
  */
@@ -12,24 +12,34 @@ import 'pdfjs-dist/build/pdf.worker.entry';
12
12
  import { packageMetadata } from './package-metadata';
13
13
  import { Scroller } from './scroller';
14
14
  import { SearchService } from './search';
15
- import { DEFAULT_ZOOM_LEVEL, loadPDF, print, download, goToNextSearchMatch, goToPreviousSearchMatch, reloadDocument, calculateZoomLevel, removeChildren } from './utils';
15
+ import { DEFAULT_ZOOM_LEVEL, loadPDF, print, download, goToNextSearchMatch, goToPreviousSearchMatch, reloadDocument, calculateZoomLevel, removeChildren, scrollToPage, currentPage } from './utils';
16
16
  import { messages, close, download as downloadM, enablePanning, enableSelection, matchCase as matchCaseM, nextMatch, open, prevMatch, print as printM, search, zoomIn, zoomOut, popupBlocked, actualWidth, fitToWidth, fitToPage } from './messages';
17
- const zoomMin = 0.5;
18
- const zoomMax = 4;
19
- const zoomStep = 0.25;
20
- const zoomLevels = [
21
- { id: 1, value: 1, text: 'ActualWidth', type: 'ActualWidth', locationString: actualWidth },
22
- { id: 2, value: 1, text: 'FitToWidth', type: 'FitToWidth', locationString: fitToWidth },
23
- { id: 3, value: 1, text: 'FitToPage', type: 'FitToPage', locationString: fitToPage },
24
- { id: 4, value: 0.5, text: '50%', type: '' },
25
- { id: 5, value: 0.75, text: '75%', type: '' },
26
- { id: 6, value: 1, text: '100%', type: '' },
27
- { id: 7, value: 1.25, text: '125%', type: '' },
28
- { id: 8, value: 1.5, text: '150%', type: '' },
29
- { id: 9, value: 2, text: '200%', type: '' },
30
- { id: 10, value: 3, text: '300%', type: '' },
31
- { id: 11, value: 4, text: '400%', type: '' }
17
+ const toolNames = [
18
+ 'pager', 'spacer', 'zoomInOut', 'zoom', 'selection', 'spacer', 'search', 'open', 'download', 'print'
32
19
  ];
20
+ // Correct declaration but typedoc does not recognize it.
21
+ // export type PDFViewerTool = typeof toolNames[number];
22
+ const defaultProps = {
23
+ minZoom: 0.5,
24
+ maxZoom: 4,
25
+ tools: [...toolNames],
26
+ zoomRate: 0.25,
27
+ zoomLevels: [
28
+ { id: 1, value: 1, text: 'ActualWidth', type: 'ActualWidth', locationString: actualWidth },
29
+ { id: 2, value: 1, text: 'FitToWidth', type: 'FitToWidth', locationString: fitToWidth },
30
+ { id: 3, value: 1, text: 'FitToPage', type: 'FitToPage', locationString: fitToPage },
31
+ { id: 4, value: 0.5, text: '50%', type: '' },
32
+ { id: 5, value: 0.75, text: '75%', type: '' },
33
+ { id: 6, value: 1, text: '100%', type: '' },
34
+ { id: 7, value: 1.25, text: '125%', type: '' },
35
+ { id: 8, value: 1.5, text: '150%', type: '' },
36
+ { id: 9, value: 2, text: '200%', type: '' },
37
+ { id: 10, value: 3, text: '300%', type: '' },
38
+ { id: 11, value: 4, text: '400%', type: '' }
39
+ ],
40
+ defaultZoom: 1.25,
41
+ defaultPage: 1
42
+ };
33
43
  const navigation = [
34
44
  '.k-toolbar > button',
35
45
  '.k-toolbar .k-combobox > input',
@@ -42,14 +52,19 @@ const navigation = [
42
52
  */
43
53
  export const PDFViewer = React.forwardRef((props, ref) => {
44
54
  validatePackage(packageMetadata);
55
+ const { zoom, zoomLevels = defaultProps.zoomLevels, defaultZoom = defaultProps.defaultZoom, minZoom = defaultProps.minZoom, maxZoom = defaultProps.maxZoom, zoomRate = defaultProps.zoomRate } = props;
45
56
  const loc = useLocalization();
46
57
  const pagesRef = React.useRef(null);
47
- const [zoom, setZoom] = React.useState(DEFAULT_ZOOM_LEVEL);
48
- const [zoomLevel, setZoomLevel] = React.useState(zoomLevels.find(z => z.value === DEFAULT_ZOOM_LEVEL));
58
+ const [stateZoom, setStateZoom] = React.useState(defaultZoom);
59
+ const currentZoom = zoom !== undefined ? zoom : stateZoom;
60
+ const currentZoomLevel = zoomLevels.find(z => z.value === currentZoom) ||
61
+ { text: (currentZoom * 100) + '%', value: currentZoom, id: currentZoom, locationString: '' };
62
+ if (currentZoomLevel.locationString) {
63
+ currentZoomLevel.text = loc.toLanguageString(currentZoomLevel.locationString, messages[currentZoomLevel.locationString]);
64
+ }
65
+ const [hasDocument, setHasDocument] = React.useState(false);
49
66
  const [loading, setLoading] = React.useState(true);
50
67
  const [skip, setSkip] = React.useState(0);
51
- const [pages, setPages] = React.useState([]);
52
- const [doc, setDoc] = React.useState(null);
53
68
  const [enabledSelection, setEnabledSelection] = React.useState(false);
54
69
  const [showSearch, setShowSearch] = React.useState(false);
55
70
  const [matches, setMatches] = React.useState(0);
@@ -57,14 +72,15 @@ export const PDFViewer = React.forwardRef((props, ref) => {
57
72
  const [matchCase, setMatchCase] = React.useState(false);
58
73
  const [searchText, setSearchText] = React.useState('');
59
74
  const refObj = React.useMemo(() => ({}), []);
75
+ refObj.currentZoom = currentZoom;
60
76
  const target = React.useRef(null);
61
77
  const pdfViewerRef = React.useRef(null);
62
78
  React.useImperativeHandle(target, () => ({
63
79
  element: pdfViewerRef.current,
64
80
  props,
65
- pages,
66
- document: doc
67
- }), [pages, doc]);
81
+ pages: refObj.pages,
82
+ document: refObj.document
83
+ }), []);
68
84
  React.useImperativeHandle(ref, () => target.current);
69
85
  const triggerOnLoad = React.useCallback(() => {
70
86
  if (props.onLoad) {
@@ -73,7 +89,6 @@ export const PDFViewer = React.forwardRef((props, ref) => {
73
89
  }
74
90
  }, [props.onLoad]);
75
91
  const triggerOnDownload = React.useCallback((blob, fileName, saveOptions) => {
76
- let handled = false;
77
92
  if (props.onDownload) {
78
93
  const downloadEvent = {
79
94
  target: target.current,
@@ -81,9 +96,10 @@ export const PDFViewer = React.forwardRef((props, ref) => {
81
96
  fileName,
82
97
  saveOptions
83
98
  };
84
- handled = props.onDownload.call(undefined, downloadEvent) || false;
99
+ const result = props.onDownload.call(undefined, downloadEvent);
100
+ return result === false ? true : false;
85
101
  }
86
- return handled;
102
+ return false;
87
103
  }, [props.onDownload]);
88
104
  const initScroller = React.useCallback(() => {
89
105
  var _a;
@@ -105,17 +121,20 @@ export const PDFViewer = React.forwardRef((props, ref) => {
105
121
  charClass: 'k-text-char'
106
122
  });
107
123
  }, []);
108
- const done = React.useCallback(({ pdfPages, pdfDoc }) => {
109
- setDoc(pdfDoc);
110
- setPages(pdfPages);
124
+ const done = React.useCallback(({ pdfPages, pdfDoc, zoom: documentZoom }) => {
125
+ refObj.document = pdfDoc;
126
+ refObj.pages = pdfPages;
127
+ refObj.zoom = documentZoom;
111
128
  initScroller();
112
129
  setLoading(false);
130
+ setHasDocument(true);
113
131
  triggerOnLoad();
114
132
  }, []);
115
133
  const error = React.useCallback((reason) => {
134
+ refObj.document = null;
135
+ refObj.pages = [];
116
136
  setLoading(false);
117
- setDoc(null);
118
- setPages([]);
137
+ setHasDocument(false);
119
138
  if (props.onError) {
120
139
  const errorEvent = {
121
140
  error: typeof reason === 'string' ? { message: reason } : reason,
@@ -124,6 +143,7 @@ export const PDFViewer = React.forwardRef((props, ref) => {
124
143
  props.onError.call(undefined, errorEvent);
125
144
  }
126
145
  }, [props.onError]);
146
+ refObj.onError = error;
127
147
  React.useEffect(() => {
128
148
  if (pagesRef.current) {
129
149
  if (props.url || props.data || props.arrayBuffer) {
@@ -134,20 +154,21 @@ export const PDFViewer = React.forwardRef((props, ref) => {
134
154
  data: props.data,
135
155
  arrayBuffer: props.arrayBuffer,
136
156
  dom: pagesRef.current,
137
- zoom: DEFAULT_ZOOM_LEVEL,
157
+ zoom: refObj.currentZoom,
138
158
  done,
139
- error
159
+ error: refObj.onError
140
160
  });
141
161
  }
142
162
  else {
163
+ refObj.document = null;
164
+ refObj.pages = [];
165
+ setHasDocument(false);
143
166
  setLoading(false);
144
167
  removeChildren(pagesRef.current);
145
- setDoc(null);
146
- setPages([]);
147
168
  }
148
169
  }
149
- }, [props.url, props.data, props.arrayBuffer, error]);
150
- const reload = React.useCallback((pdfDoc, zoomLev = DEFAULT_ZOOM_LEVEL) => {
170
+ }, [props.url, props.data, props.arrayBuffer]);
171
+ const reload = React.useCallback((pdfDoc, zoomLev) => {
151
172
  if (pagesRef.current) {
152
173
  setLoading(true);
153
174
  removeChildren(pagesRef.current);
@@ -156,13 +177,19 @@ export const PDFViewer = React.forwardRef((props, ref) => {
156
177
  zoom: zoomLev,
157
178
  dom: pagesRef.current,
158
179
  done: (pdfPages) => {
159
- setPages(pdfPages);
180
+ refObj.pages = pdfPages;
181
+ refObj.zoom = zoomLev;
160
182
  setLoading(false);
161
183
  },
162
184
  error
163
185
  });
164
186
  }
165
187
  }, [error]);
188
+ React.useEffect(() => {
189
+ if (pagesRef.current && refObj.document && currentZoom !== refObj.zoom) {
190
+ reload(refObj.document, currentZoom);
191
+ }
192
+ }, [currentZoom, reload]);
166
193
  const onSearch = React.useCallback(() => {
167
194
  setShowSearch(true);
168
195
  initSearch(pagesRef.current);
@@ -207,45 +234,97 @@ export const PDFViewer = React.forwardRef((props, ref) => {
207
234
  }
208
235
  }, [currentMatch, matches]);
209
236
  const onPageChange = React.useCallback((e) => {
210
- if (pagesRef.current && pagesRef.current.parentNode instanceof HTMLDivElement) {
211
- const page = pagesRef.current.querySelector('.k-page');
212
- if (page instanceof HTMLDivElement) {
213
- const top = (page.offsetHeight + page.offsetTop) * e.skip;
214
- pagesRef.current.parentNode.scrollTo({ top, behavior: 'auto' });
237
+ if (pagesRef.current) {
238
+ const nextPage = e.skip;
239
+ scrollToPage(pagesRef.current, nextPage);
240
+ const pageEvent = {
241
+ page: nextPage + 1,
242
+ target: target.current,
243
+ syntheticEvent: e.syntheticEvent
244
+ };
245
+ if (props.onPageChange) {
246
+ props.onPageChange.call(undefined, pageEvent);
215
247
  }
216
248
  }
217
249
  setSkip(e.skip);
218
- }, [skip]);
250
+ }, [skip, props.onPageChange]);
219
251
  const onScroll = React.useCallback((e) => {
220
- const targetEl = e.target;
221
- const page = targetEl.querySelector('.k-page');
222
- if (page) {
223
- setSkip(Math.floor(targetEl.scrollTop / (page.offsetHeight + page.offsetTop)));
252
+ if (pdfViewerRef.current) {
253
+ const nextPage = currentPage(pdfViewerRef.current);
254
+ if (nextPage !== skip) {
255
+ setSkip(nextPage);
256
+ const pageEvent = {
257
+ page: nextPage + 1,
258
+ target: target.current,
259
+ syntheticEvent: e
260
+ };
261
+ if (props.onPageChange) {
262
+ props.onPageChange.call(undefined, pageEvent);
263
+ }
264
+ }
224
265
  }
225
- }, []);
226
- const onZoomIn = React.useCallback(() => {
227
- const newZoom = Math.min(zoom + zoomStep, zoomMax);
228
- if (newZoom !== zoom && doc) {
229
- setZoom(newZoom);
230
- reload(doc, newZoom);
266
+ }, [skip, props.onPageChange]);
267
+ const onZoomIn = React.useCallback((e) => {
268
+ const newZoom = Math.min(currentZoom + zoomRate, maxZoom);
269
+ if (newZoom !== currentZoom && refObj.document) {
270
+ setStateZoom(newZoom);
271
+ if (zoom === undefined) {
272
+ reload(refObj.document, newZoom);
273
+ }
274
+ if (props.onZoom) {
275
+ const zoomEvent = {
276
+ zoom: newZoom,
277
+ target: target.current,
278
+ syntheticEvent: e
279
+ };
280
+ props.onZoom.call(undefined, zoomEvent);
281
+ }
231
282
  }
232
- }, [zoom, doc]);
233
- const onZoomOut = React.useCallback(() => {
234
- const newZoom = Math.max(zoom - zoomStep, zoomMin);
235
- if (newZoom !== zoom && doc) {
236
- setZoom(newZoom);
237
- reload(doc, newZoom);
283
+ }, [currentZoom, zoomRate, maxZoom, zoom, props.onZoom, reload]);
284
+ const onZoomOut = React.useCallback((e) => {
285
+ const newZoom = Math.max(stateZoom - zoomRate, minZoom);
286
+ if (newZoom !== stateZoom && refObj.document) {
287
+ setStateZoom(newZoom);
288
+ if (zoom === undefined) {
289
+ reload(refObj.document, newZoom);
290
+ }
291
+ if (props.onZoom) {
292
+ const zoomEvent = {
293
+ zoom: newZoom,
294
+ target: target.current,
295
+ syntheticEvent: e
296
+ };
297
+ props.onZoom.call(undefined, zoomEvent);
298
+ }
238
299
  }
239
- }, [zoom, doc]);
300
+ }, [currentZoom, zoomRate, minZoom, zoom, props.onZoom, reload]);
240
301
  const onZoomLevelChange = React.useCallback((e) => {
241
- const item = e.value;
242
- const newZoom = item ? calculateZoomLevel(item.value, item.type, zoom, pagesRef.current) : 1;
243
- if (zoom !== newZoom && doc) {
244
- setZoom(newZoom);
245
- reload(doc, newZoom);
302
+ const item = e.value === null ? { text: '100%', value: 1, id: 100 } : Object.assign({}, e.value);
303
+ if (item.value === undefined) {
304
+ const parsedText = parseFloat(item.text);
305
+ if (typeof parsedText === 'number' && !Number.isNaN(parsedText)) {
306
+ item.value = parsedText / 100;
307
+ }
308
+ else {
309
+ item.value = 1;
310
+ }
246
311
  }
247
- setZoomLevel(item);
248
- }, [zoom, doc]);
312
+ const newZoom = item ? calculateZoomLevel(item.value, item.type, currentZoom, pagesRef.current) : 1;
313
+ if (currentZoom !== newZoom && refObj.document) {
314
+ setStateZoom(newZoom);
315
+ if (zoom === undefined) {
316
+ reload(refObj.document, newZoom);
317
+ }
318
+ if (props.onZoom) {
319
+ const zoomEvent = {
320
+ zoom: newZoom,
321
+ target: target.current,
322
+ syntheticEvent: e.syntheticEvent
323
+ };
324
+ props.onZoom.call(undefined, zoomEvent);
325
+ }
326
+ }
327
+ }, [currentZoom, zoom, props.onZoom, reload]);
249
328
  const onTextSelection = React.useCallback(() => {
250
329
  refObj.scroller.disablePanEventsTracking();
251
330
  setEnabledSelection(true);
@@ -270,8 +349,8 @@ export const PDFViewer = React.forwardRef((props, ref) => {
270
349
  const onDone = () => {
271
350
  setLoading(false);
272
351
  };
273
- print(pages, onDone, onError);
274
- }, [pages, error]);
352
+ print(refObj.pages, onDone, onError);
353
+ }, [error]);
275
354
  const onAdd = React.useCallback((e) => {
276
355
  const st = e.newState;
277
356
  if (st[0] && st[0].getRawFile) {
@@ -287,7 +366,7 @@ export const PDFViewer = React.forwardRef((props, ref) => {
287
366
  done,
288
367
  error
289
368
  });
290
- setZoom(DEFAULT_ZOOM_LEVEL);
369
+ setStateZoom(DEFAULT_ZOOM_LEVEL);
291
370
  }
292
371
  });
293
372
  }
@@ -302,30 +381,41 @@ export const PDFViewer = React.forwardRef((props, ref) => {
302
381
  }
303
382
  }
304
383
  }, []);
305
- const noDocument = !doc;
306
384
  const loader = (loading && React.createElement("div", { className: "k-loader-container k-loader-container-md k-loader-top" },
307
385
  React.createElement("div", { className: "k-loader-container-overlay k-overlay-light" }),
308
386
  React.createElement("div", { className: "k-loader-container-inner " },
309
387
  React.createElement(Loader, { size: 'large' }))));
310
- const toolbar = (React.createElement(Toolbar, { buttons: navigation },
311
- React.createElement(Pager, { previousNext: true, type: 'input', skip: skip, take: 1, total: pages.length, info: false, onPageChange: onPageChange }),
312
- React.createElement(ToolbarSpacer, null),
313
- React.createElement(ButtonGroup, null,
314
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(zoomIn, messages[zoomIn]), disabled: zoom === zoomMax || noDocument, onClick: onZoomIn, icon: 'zoom-in' }),
315
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(zoomOut, messages[zoomOut]), disabled: zoom === zoomMin || noDocument, onClick: onZoomOut, icon: 'zoom-out' })),
316
- React.createElement(ComboBox, { disabled: noDocument, data: (props.zoomLevels || zoomLevels).map(level => (Object.assign(Object.assign({}, level), { text: level.locationString
317
- ? loc.toLanguageString(level.locationString, messages[level.locationString])
318
- : level.text }))), dataItemKey: 'id', textField: 'text', value: noDocument ? null : zoomLevel, onChange: onZoomLevelChange }),
319
- React.createElement(ButtonGroup, null,
320
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(enableSelection, messages[enableSelection]), icon: 'cursor', disabled: noDocument, togglable: true, selected: enabledSelection && !noDocument, onClick: onTextSelection }),
321
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(enablePanning, messages[enablePanning]), icon: 'hand', disabled: noDocument, togglable: true, selected: !enabledSelection && !noDocument, onClick: onPinning })),
322
- React.createElement(ToolbarSpacer, null),
323
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(search, messages[search]), icon: 'search', disabled: noDocument, onClick: onSearch }),
388
+ const zoomInOut = (React.createElement(ButtonGroup, null,
389
+ React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(zoomOut, messages[zoomOut]), disabled: currentZoom <= minZoom || !hasDocument, onClick: onZoomOut, icon: 'zoom-out' }),
390
+ React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(zoomIn, messages[zoomIn]), disabled: currentZoom >= maxZoom || !hasDocument, onClick: onZoomIn, icon: 'zoom-in' })));
391
+ const zoomComboBoxTool = (React.createElement(ComboBox, { disabled: !hasDocument, data: (zoomLevels).map(level => (Object.assign(Object.assign({}, level), { text: level.locationString
392
+ ? loc.toLanguageString(level.locationString, messages[level.locationString])
393
+ : level.text }))), dataItemKey: 'id', textField: 'text', value: hasDocument ? currentZoomLevel : null, allowCustom: true, onChange: onZoomLevelChange }));
394
+ const pagerTool = (React.createElement(Pager, { previousNext: true, type: 'input', skip: skip, take: 1, total: refObj.pages ? refObj.pages.length : 0, info: false, onPageChange: onPageChange }));
395
+ const spacer = React.createElement(ToolbarSpacer, null);
396
+ const selectionTool = (React.createElement(ButtonGroup, null,
397
+ React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(enableSelection, messages[enableSelection]), icon: 'cursor', disabled: !hasDocument, togglable: true, selected: enabledSelection && hasDocument, onClick: onTextSelection }),
398
+ React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(enablePanning, messages[enablePanning]), icon: 'hand', disabled: !hasDocument, togglable: true, selected: !enabledSelection && hasDocument, onClick: onPinning })));
399
+ const searchTool = (React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(search, messages[search]), icon: 'search', disabled: !hasDocument, onClick: onSearch }));
400
+ const openTool = (React.createElement(React.Fragment, null,
324
401
  React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(open, messages[open]), icon: 'folder-open', onClick: onFileOpen }),
325
402
  React.createElement("div", { style: { display: 'none' } },
326
- React.createElement(Upload, { restrictions: { allowedExtensions: ['.pdf'] }, onAdd: onAdd, autoUpload: false, defaultFiles: [], multiple: false, accept: ".pdf,.PDF", withCredentials: false })),
327
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(downloadM, messages[downloadM]), icon: 'download', disabled: noDocument, onClick: onDownload }),
328
- React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(printM, messages[printM]), icon: 'print', disabled: noDocument, onClick: onPrint })));
403
+ React.createElement(Upload, { restrictions: { allowedExtensions: ['.pdf'] }, onAdd: onAdd, autoUpload: false, defaultFiles: [], multiple: false, accept: ".pdf,.PDF", withCredentials: false }))));
404
+ const downloadTool = (React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(downloadM, messages[downloadM]), icon: 'download', disabled: !hasDocument, onClick: onDownload }));
405
+ const printTool = (React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(printM, messages[printM]), icon: 'print', disabled: !hasDocument, onClick: onPrint }));
406
+ const tools = {
407
+ pager: pagerTool,
408
+ spacer,
409
+ zoomInOut,
410
+ zoom: zoomComboBoxTool,
411
+ selection: selectionTool,
412
+ search: searchTool,
413
+ open: openTool,
414
+ download: downloadTool,
415
+ print: printTool
416
+ };
417
+ const buttons = (props.tools || defaultProps.tools).map((tool) => tools[tool]);
418
+ const toolbar = (React.createElement(Toolbar, { buttons: navigation }, ...buttons));
329
419
  const content = (React.createElement("div", { className: classNames('k-canvas k-pdf-viewer-canvas k-pos-relative k-overflow-auto', {
330
420
  'k-enable-text-select': enabledSelection,
331
421
  'k-enable-panning': !enabledSelection
@@ -355,11 +445,19 @@ PDFViewer.propTypes = {
355
445
  style: PropTypes.object,
356
446
  saveFileName: PropTypes.string,
357
447
  saveOptions: PropTypes.object,
448
+ tools: PropTypes.arrayOf(PropTypes.oneOf(toolNames).isRequired),
358
449
  zoomLevels: PropTypes.arrayOf(PropTypes.any),
450
+ zoom: PropTypes.number,
451
+ defaultZoom: PropTypes.number,
452
+ minZoom: PropTypes.number,
453
+ maxZoom: PropTypes.number,
454
+ zoomRate: PropTypes.number,
359
455
  onError: PropTypes.func,
360
456
  onLoad: PropTypes.func,
361
457
  onDownload: PropTypes.func,
362
458
  onRenderToolbar: PropTypes.func,
363
459
  onRenderContent: PropTypes.func,
364
- onRenderLoader: PropTypes.func
460
+ onRenderLoader: PropTypes.func,
461
+ onZoom: PropTypes.func
365
462
  };
463
+ PDFViewer.defaultProps = defaultProps;
package/dist/es/main.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { PDFViewer, PDFViewerProps, PDFViewerHandle, LoadEvent, ErrorEvent, DownloadEvent } from './PDFViewer';
1
+ export { PDFViewer, PDFViewerProps, PDFViewerHandle, PDFViewerTool, LoadEvent, ErrorEvent, DownloadEvent, ZoomEvent, PageEvent } from './PDFViewer';
2
+ export { scrollToPage, currentPage } from './utils';
package/dist/es/main.js CHANGED
@@ -1 +1,2 @@
1
1
  export { PDFViewer } from './PDFViewer';
2
+ export { scrollToPage, currentPage } from './utils';
@@ -5,7 +5,7 @@ export const packageMetadata = {
5
5
  name: '@progress/kendo-react-pdf-viewer',
6
6
  productName: 'KendoReact',
7
7
  productCodes: ['KENDOUIREACT', 'KENDOUICOMPLETE'],
8
- publishDate: 1669290352,
8
+ publishDate: 1669981622,
9
9
  version: '',
10
10
  licensingDocsUrl: 'https://www.telerik.com/kendo-react-ui/my-license/?utm_medium=product&utm_source=kendoreact&utm_campaign=kendo-ui-react-purchase-license-keys-warning'
11
11
  };
@@ -7,6 +7,7 @@ import { TypedArray } from 'pdfjs-dist/types/src/display/api';
7
7
  export declare type DoneFn = (result: {
8
8
  pdfPages: PDFPageProxy[];
9
9
  pdfDoc: PDFDocumentProxy;
10
+ zoom: number;
10
11
  }) => void;
11
12
  /**
12
13
  * @hidden
@@ -76,3 +77,17 @@ export declare const calculateZoomLevel: (zoomLevel: number, zoomLevelType: stri
76
77
  * @hidden
77
78
  */
78
79
  export declare const removeChildren: (dom: HTMLElement) => void;
80
+ /**
81
+ * Scrolls the PDFViewer document to the passed page number.
82
+ *
83
+ * @param rootElement The root HTML element of the PDFViewer component.
84
+ * @param pageNumber The page number.
85
+ */
86
+ export declare const scrollToPage: (rootElement: HTMLElement, pageNumber: number) => void;
87
+ /**
88
+ * A function which gives you the page number of the document according to the scroll position.
89
+ *
90
+ * @param rootElement The root HTML element of the PDFViewer component.
91
+ * @returns The page number.
92
+ */
93
+ export declare const currentPage: (rootElement: HTMLElement) => number;
package/dist/es/utils.js CHANGED
@@ -57,7 +57,7 @@ export const loadPDF = (options) => {
57
57
  return page;
58
58
  }))
59
59
  .then((pdfPages) => {
60
- done({ pdfPages, pdfDoc });
60
+ done({ pdfPages, pdfDoc, zoom });
61
61
  }).catch((reason) => { options.error(reason); });
62
62
  }).catch((reason) => { options.error(reason); });
63
63
  };
@@ -238,3 +238,31 @@ export const removeChildren = (dom) => {
238
238
  dom.removeChild(dom.firstChild);
239
239
  }
240
240
  };
241
+ /**
242
+ * Scrolls the PDFViewer document to the passed page number.
243
+ *
244
+ * @param rootElement The root HTML element of the PDFViewer component.
245
+ * @param pageNumber The page number.
246
+ */
247
+ export const scrollToPage = (rootElement, pageNumber) => {
248
+ const pages = rootElement.querySelectorAll('.k-page');
249
+ const page = pages[0];
250
+ if (page instanceof HTMLDivElement) {
251
+ const top = (page.offsetHeight + page.offsetTop) * Math.max(0, Math.min(pageNumber, pages.length - 1));
252
+ const scrollElement = page.closest('.k-pdf-viewer-canvas');
253
+ if (scrollElement) {
254
+ scrollElement.scrollTo({ top, behavior: 'auto' });
255
+ }
256
+ }
257
+ };
258
+ /**
259
+ * A function which gives you the page number of the document according to the scroll position.
260
+ *
261
+ * @param rootElement The root HTML element of the PDFViewer component.
262
+ * @returns The page number.
263
+ */
264
+ export const currentPage = (rootElement) => {
265
+ const scrollElement = rootElement.querySelector('.k-pdf-viewer-canvas');
266
+ const page = rootElement.querySelector('.k-page');
267
+ return (scrollElement && page) ? Math.floor(scrollElement.scrollTop / (page.offsetHeight + page.offsetTop)) : 0;
268
+ };