@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.
- package/LICENSE.md +11 -0
- package/NOTICE.txt +111 -0
- package/README.md +54 -0
- package/about.md +3 -0
- package/dist/cdn/js/kendo-react-pdf-viewer.js +2 -0
- package/dist/cdn/js/kendo-react-pdf-viewer.js.LICENSE.txt +21 -0
- package/dist/es/PDFViewer.d.ts +138 -0
- package/dist/es/PDFViewer.js +365 -0
- package/dist/es/main.d.ts +1 -0
- package/dist/es/main.js +1 -0
- package/dist/es/messages.d.ts +85 -0
- package/dist/es/messages.js +85 -0
- package/dist/es/package-metadata.d.ts +5 -0
- package/dist/es/package-metadata.js +11 -0
- package/dist/es/scroller.d.ts +34 -0
- package/dist/es/scroller.js +226 -0
- package/dist/es/search.d.ts +42 -0
- package/dist/es/search.js +249 -0
- package/dist/es/utils.d.ts +78 -0
- package/dist/es/utils.js +240 -0
- package/dist/npm/PDFViewer.d.ts +138 -0
- package/dist/npm/PDFViewer.js +368 -0
- package/dist/npm/main.d.ts +1 -0
- package/dist/npm/main.js +5 -0
- package/dist/npm/messages.d.ts +85 -0
- package/dist/npm/messages.js +88 -0
- package/dist/npm/package-metadata.d.ts +5 -0
- package/dist/npm/package-metadata.js +14 -0
- package/dist/npm/scroller.d.ts +34 -0
- package/dist/npm/scroller.js +230 -0
- package/dist/npm/search.d.ts +42 -0
- package/dist/npm/search.js +253 -0
- package/dist/npm/utils.d.ts +78 -0
- package/dist/npm/utils.js +251 -0
- package/dist/systemjs/kendo-react-pdf-viewer.js +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @licstart The following is the entire license notice for the
|
|
3
|
+
* JavaScript code in this page
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2022 Mozilla Foundation
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*
|
|
19
|
+
* @licend The above is the entire license notice for the
|
|
20
|
+
* JavaScript code in this page
|
|
21
|
+
*/
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Toolbar } from '@progress/kendo-react-buttons';
|
|
3
|
+
import { SaveOptions } from '@progress/kendo-file-saver';
|
|
4
|
+
import { TypedArray } from 'pdfjs-dist/types/src/display/api';
|
|
5
|
+
import 'pdfjs-dist/build/pdf.worker.entry';
|
|
6
|
+
interface PDFViewerEvent {
|
|
7
|
+
/**
|
|
8
|
+
* The event target object.
|
|
9
|
+
*/
|
|
10
|
+
target: PDFViewerHandle;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) ErrorEvent object.
|
|
14
|
+
*/
|
|
15
|
+
export interface ErrorEvent extends PDFViewerEvent {
|
|
16
|
+
/**
|
|
17
|
+
* The raised error.
|
|
18
|
+
*/
|
|
19
|
+
error: Error | {
|
|
20
|
+
message: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) DownloadEvent object.
|
|
25
|
+
*/
|
|
26
|
+
export interface DownloadEvent extends PDFViewerEvent {
|
|
27
|
+
/**
|
|
28
|
+
* The Blob object.
|
|
29
|
+
*/
|
|
30
|
+
blob: Blob;
|
|
31
|
+
/**
|
|
32
|
+
* The name which will be used for saving the file.
|
|
33
|
+
*/
|
|
34
|
+
fileName: string;
|
|
35
|
+
/**
|
|
36
|
+
* The options which will be used for saving the file.
|
|
37
|
+
*/
|
|
38
|
+
saveOptions: SaveOptions;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) LoadEvent object.
|
|
42
|
+
*/
|
|
43
|
+
export interface LoadEvent extends PDFViewerEvent {
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The props of the KendoReact [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) component.
|
|
47
|
+
*/
|
|
48
|
+
export interface PDFViewerProps {
|
|
49
|
+
/**
|
|
50
|
+
* Represents the url of the PDF file.
|
|
51
|
+
*/
|
|
52
|
+
url?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Represents the data of the PDF file in Base64 format.
|
|
55
|
+
*/
|
|
56
|
+
data?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Represents the raw binary data buffer of the PDF file.
|
|
59
|
+
*/
|
|
60
|
+
arrayBuffer?: ArrayBuffer;
|
|
61
|
+
/**
|
|
62
|
+
* Represents the data of the PDF file in typed array format.
|
|
63
|
+
*/
|
|
64
|
+
typedArray?: TypedArray;
|
|
65
|
+
/**
|
|
66
|
+
* Represents the additional styles which will be added to the PDFViewer component.
|
|
67
|
+
*/
|
|
68
|
+
style?: React.CSSProperties;
|
|
69
|
+
/**
|
|
70
|
+
* Represents the file name used to save the file when the user clicks the download tool.
|
|
71
|
+
*/
|
|
72
|
+
saveFileName?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Represents the options for saving the file when the user clicks the download tool.
|
|
75
|
+
*/
|
|
76
|
+
saveOptions?: SaveOptions;
|
|
77
|
+
/**
|
|
78
|
+
* Represents the zoom levels populated in the ComboBox component.
|
|
79
|
+
*/
|
|
80
|
+
zoomLevels?: {
|
|
81
|
+
id: number;
|
|
82
|
+
value: number;
|
|
83
|
+
text: string;
|
|
84
|
+
type: string;
|
|
85
|
+
locationString?: string;
|
|
86
|
+
}[];
|
|
87
|
+
/**
|
|
88
|
+
* Fires when an error occurs.
|
|
89
|
+
*/
|
|
90
|
+
onError?: (event: ErrorEvent) => void;
|
|
91
|
+
/**
|
|
92
|
+
* Fires when a PDF document has been loaded.
|
|
93
|
+
*/
|
|
94
|
+
onLoad?: (event: LoadEvent) => void;
|
|
95
|
+
/**
|
|
96
|
+
* Fires when the download tool has been clicked. To prevent the download, return `false`.
|
|
97
|
+
*/
|
|
98
|
+
onDownload?: (event: DownloadEvent) => boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Fires when the toolbar component is about to be rendered. Use it to override the default appearance of the toolbar.
|
|
101
|
+
*/
|
|
102
|
+
onRenderToolbar?: (defaultRendering: React.ReactElement<Toolbar>) => React.ReactNode;
|
|
103
|
+
/**
|
|
104
|
+
* Fires when the content component is about to be rendered. Use it to override the default appearance of the content.
|
|
105
|
+
*/
|
|
106
|
+
onRenderContent?: (defaultRendering: React.ReactElement<HTMLDivElement>) => React.ReactNode;
|
|
107
|
+
/**
|
|
108
|
+
* Fires when the loading indication component is about to be rendered. Use it to override the default appearance of the loading.
|
|
109
|
+
*/
|
|
110
|
+
onRenderLoader?: (defaultRendering: React.ReactElement<HTMLDivElement> | null) => React.ReactNode;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Represents the object which is passed to the [`ref`](https://reactjs.org/docs/refs-and-the-dom.html)
|
|
114
|
+
* callback of the [PDFViewer]({% slug api_pdf-viewer_pdfviewer %}) component.
|
|
115
|
+
*/
|
|
116
|
+
export interface PDFViewerHandle {
|
|
117
|
+
/**
|
|
118
|
+
* The root DOM element of the PDFViewer component.
|
|
119
|
+
*/
|
|
120
|
+
element: HTMLDivElement | null;
|
|
121
|
+
/**
|
|
122
|
+
* The props of the PDFViewer component.
|
|
123
|
+
*/
|
|
124
|
+
props: PDFViewerProps;
|
|
125
|
+
/**
|
|
126
|
+
* The `PDF.js` document loaded in the PDFViewer component.
|
|
127
|
+
*/
|
|
128
|
+
document: any;
|
|
129
|
+
/**
|
|
130
|
+
* The `PDF.js` pages loaded in the PDFViewer component.
|
|
131
|
+
*/
|
|
132
|
+
pages: any[];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Represents the [KendoReact PDFViewer component]({% slug api_pdf-viewer_pdfviewerprops %}).
|
|
136
|
+
*/
|
|
137
|
+
export declare const PDFViewer: React.ForwardRefExoticComponent<PDFViewerProps & React.RefAttributes<PDFViewerHandle | null>>;
|
|
138
|
+
export {};
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as PropTypes from 'prop-types';
|
|
3
|
+
import { Button, ButtonGroup, Toolbar, ToolbarSpacer } from '@progress/kendo-react-buttons';
|
|
4
|
+
import { TextBox, InputSuffix } from '@progress/kendo-react-inputs';
|
|
5
|
+
import { Pager } from '@progress/kendo-react-data-tools';
|
|
6
|
+
import { Upload } from '@progress/kendo-react-upload';
|
|
7
|
+
import { ComboBox } from '@progress/kendo-react-dropdowns';
|
|
8
|
+
import { Loader } from '@progress/kendo-react-indicators';
|
|
9
|
+
import { classNames, validatePackage } from '@progress/kendo-react-common';
|
|
10
|
+
import { useLocalization } from '@progress/kendo-react-intl';
|
|
11
|
+
import 'pdfjs-dist/build/pdf.worker.entry';
|
|
12
|
+
import { packageMetadata } from './package-metadata';
|
|
13
|
+
import { Scroller } from './scroller';
|
|
14
|
+
import { SearchService } from './search';
|
|
15
|
+
import { DEFAULT_ZOOM_LEVEL, loadPDF, print, download, goToNextSearchMatch, goToPreviousSearchMatch, reloadDocument, calculateZoomLevel, removeChildren } from './utils';
|
|
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: '' }
|
|
32
|
+
];
|
|
33
|
+
const navigation = [
|
|
34
|
+
'.k-toolbar > button',
|
|
35
|
+
'.k-toolbar .k-combobox > input',
|
|
36
|
+
'.k-toolbar .k-button-group > button',
|
|
37
|
+
'.k-toolbar .k-pager > a',
|
|
38
|
+
'.k-toolbar .k-pager input'
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Represents the [KendoReact PDFViewer component]({% slug api_pdf-viewer_pdfviewerprops %}).
|
|
42
|
+
*/
|
|
43
|
+
export const PDFViewer = React.forwardRef((props, ref) => {
|
|
44
|
+
validatePackage(packageMetadata);
|
|
45
|
+
const loc = useLocalization();
|
|
46
|
+
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));
|
|
49
|
+
const [loading, setLoading] = React.useState(true);
|
|
50
|
+
const [skip, setSkip] = React.useState(0);
|
|
51
|
+
const [pages, setPages] = React.useState([]);
|
|
52
|
+
const [doc, setDoc] = React.useState(null);
|
|
53
|
+
const [enabledSelection, setEnabledSelection] = React.useState(false);
|
|
54
|
+
const [showSearch, setShowSearch] = React.useState(false);
|
|
55
|
+
const [matches, setMatches] = React.useState(0);
|
|
56
|
+
const [currentMatch, setCurrentMatch] = React.useState(0);
|
|
57
|
+
const [matchCase, setMatchCase] = React.useState(false);
|
|
58
|
+
const [searchText, setSearchText] = React.useState('');
|
|
59
|
+
const refObj = React.useMemo(() => ({}), []);
|
|
60
|
+
const target = React.useRef(null);
|
|
61
|
+
const pdfViewerRef = React.useRef(null);
|
|
62
|
+
React.useImperativeHandle(target, () => ({
|
|
63
|
+
element: pdfViewerRef.current,
|
|
64
|
+
props,
|
|
65
|
+
pages,
|
|
66
|
+
document: doc
|
|
67
|
+
}), [pages, doc]);
|
|
68
|
+
React.useImperativeHandle(ref, () => target.current);
|
|
69
|
+
const triggerOnLoad = React.useCallback(() => {
|
|
70
|
+
if (props.onLoad) {
|
|
71
|
+
const loadEvent = { target: target.current };
|
|
72
|
+
props.onLoad.call(undefined, loadEvent);
|
|
73
|
+
}
|
|
74
|
+
}, [props.onLoad]);
|
|
75
|
+
const triggerOnDownload = React.useCallback((blob, fileName, saveOptions) => {
|
|
76
|
+
let handled = false;
|
|
77
|
+
if (props.onDownload) {
|
|
78
|
+
const downloadEvent = {
|
|
79
|
+
target: target.current,
|
|
80
|
+
blob,
|
|
81
|
+
fileName,
|
|
82
|
+
saveOptions
|
|
83
|
+
};
|
|
84
|
+
handled = props.onDownload.call(undefined, downloadEvent) || false;
|
|
85
|
+
}
|
|
86
|
+
return handled;
|
|
87
|
+
}, [props.onDownload]);
|
|
88
|
+
const initScroller = React.useCallback(() => {
|
|
89
|
+
var _a;
|
|
90
|
+
if (refObj.scroller) {
|
|
91
|
+
refObj.scroller.destroy();
|
|
92
|
+
}
|
|
93
|
+
refObj.scroller = new Scroller((_a = pagesRef.current) === null || _a === void 0 ? void 0 : _a.parentNode, {
|
|
94
|
+
filter: '.k-page',
|
|
95
|
+
events: {}
|
|
96
|
+
});
|
|
97
|
+
refObj.scroller.enablePanEventsTracking();
|
|
98
|
+
}, []);
|
|
99
|
+
const initSearch = React.useCallback((wrapper) => {
|
|
100
|
+
const pagesTextLayers = Array.from(wrapper.querySelectorAll('.k-text-layer'));
|
|
101
|
+
refObj.search = new SearchService({
|
|
102
|
+
textContainers: pagesTextLayers || [],
|
|
103
|
+
highlightClass: 'k-search-highlight',
|
|
104
|
+
highlightMarkClass: 'k-search-highlight-mark',
|
|
105
|
+
charClass: 'k-text-char'
|
|
106
|
+
});
|
|
107
|
+
}, []);
|
|
108
|
+
const done = React.useCallback(({ pdfPages, pdfDoc }) => {
|
|
109
|
+
setDoc(pdfDoc);
|
|
110
|
+
setPages(pdfPages);
|
|
111
|
+
initScroller();
|
|
112
|
+
setLoading(false);
|
|
113
|
+
triggerOnLoad();
|
|
114
|
+
}, []);
|
|
115
|
+
const error = React.useCallback((reason) => {
|
|
116
|
+
setLoading(false);
|
|
117
|
+
setDoc(null);
|
|
118
|
+
setPages([]);
|
|
119
|
+
if (props.onError) {
|
|
120
|
+
const errorEvent = {
|
|
121
|
+
error: typeof reason === 'string' ? { message: reason } : reason,
|
|
122
|
+
target: target.current
|
|
123
|
+
};
|
|
124
|
+
props.onError.call(undefined, errorEvent);
|
|
125
|
+
}
|
|
126
|
+
}, [props.onError]);
|
|
127
|
+
React.useEffect(() => {
|
|
128
|
+
if (pagesRef.current) {
|
|
129
|
+
if (props.url || props.data || props.arrayBuffer) {
|
|
130
|
+
setLoading(true);
|
|
131
|
+
removeChildren(pagesRef.current);
|
|
132
|
+
loadPDF({
|
|
133
|
+
url: props.url,
|
|
134
|
+
data: props.data,
|
|
135
|
+
arrayBuffer: props.arrayBuffer,
|
|
136
|
+
dom: pagesRef.current,
|
|
137
|
+
zoom: DEFAULT_ZOOM_LEVEL,
|
|
138
|
+
done,
|
|
139
|
+
error
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
setLoading(false);
|
|
144
|
+
removeChildren(pagesRef.current);
|
|
145
|
+
setDoc(null);
|
|
146
|
+
setPages([]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}, [props.url, props.data, props.arrayBuffer, error]);
|
|
150
|
+
const reload = React.useCallback((pdfDoc, zoomLev = DEFAULT_ZOOM_LEVEL) => {
|
|
151
|
+
if (pagesRef.current) {
|
|
152
|
+
setLoading(true);
|
|
153
|
+
removeChildren(pagesRef.current);
|
|
154
|
+
reloadDocument({
|
|
155
|
+
pdfDoc,
|
|
156
|
+
zoom: zoomLev,
|
|
157
|
+
dom: pagesRef.current,
|
|
158
|
+
done: (pdfPages) => {
|
|
159
|
+
setPages(pdfPages);
|
|
160
|
+
setLoading(false);
|
|
161
|
+
},
|
|
162
|
+
error
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}, [error]);
|
|
166
|
+
const onSearch = React.useCallback(() => {
|
|
167
|
+
setShowSearch(true);
|
|
168
|
+
initSearch(pagesRef.current);
|
|
169
|
+
}, []);
|
|
170
|
+
const onSearchTextChange = React.useCallback((e) => {
|
|
171
|
+
const text = e.value;
|
|
172
|
+
const currentMatches = refObj.search.search({ text, matchCase });
|
|
173
|
+
setCurrentMatch(currentMatches.length ? 1 : 0);
|
|
174
|
+
setMatches(currentMatches.length);
|
|
175
|
+
setSearchText(text);
|
|
176
|
+
}, [matchCase]);
|
|
177
|
+
const onMatchCaseClick = React.useCallback(() => {
|
|
178
|
+
const currentMatches = refObj.search.search({ text: searchText, matchCase: !matchCase });
|
|
179
|
+
setCurrentMatch(currentMatches.length ? 1 : 0);
|
|
180
|
+
setMatches(currentMatches.length);
|
|
181
|
+
setMatchCase(!matchCase);
|
|
182
|
+
}, [matchCase, searchText]);
|
|
183
|
+
const onNextMatch = React.useCallback(() => {
|
|
184
|
+
goToNextSearchMatch(refObj);
|
|
185
|
+
setCurrentMatch((currentMatch + 1) > matches ? 1 : (currentMatch + 1));
|
|
186
|
+
}, [currentMatch, matches]);
|
|
187
|
+
const onPrevMatch = React.useCallback(() => {
|
|
188
|
+
goToPreviousSearchMatch(refObj);
|
|
189
|
+
setCurrentMatch((currentMatch - 1) < 1 ? matches : (currentMatch - 1));
|
|
190
|
+
}, [currentMatch, matches]);
|
|
191
|
+
const onClose = React.useCallback(() => {
|
|
192
|
+
refObj.search.destroy();
|
|
193
|
+
setCurrentMatch(0);
|
|
194
|
+
setMatches(0);
|
|
195
|
+
setMatchCase(false);
|
|
196
|
+
setSearchText('');
|
|
197
|
+
setShowSearch(false);
|
|
198
|
+
}, []);
|
|
199
|
+
const onTextBoxKeyDown = React.useCallback((e) => {
|
|
200
|
+
if (e.key === 'Enter') {
|
|
201
|
+
e.preventDefault();
|
|
202
|
+
goToNextSearchMatch(refObj);
|
|
203
|
+
setCurrentMatch((currentMatch + 1) > matches ? 1 : (currentMatch + 1));
|
|
204
|
+
}
|
|
205
|
+
else if (e.key === 'Escape') {
|
|
206
|
+
onClose();
|
|
207
|
+
}
|
|
208
|
+
}, [currentMatch, matches]);
|
|
209
|
+
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' });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
setSkip(e.skip);
|
|
218
|
+
}, [skip]);
|
|
219
|
+
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)));
|
|
224
|
+
}
|
|
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);
|
|
231
|
+
}
|
|
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);
|
|
238
|
+
}
|
|
239
|
+
}, [zoom, doc]);
|
|
240
|
+
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);
|
|
246
|
+
}
|
|
247
|
+
setZoomLevel(item);
|
|
248
|
+
}, [zoom, doc]);
|
|
249
|
+
const onTextSelection = React.useCallback(() => {
|
|
250
|
+
refObj.scroller.disablePanEventsTracking();
|
|
251
|
+
setEnabledSelection(true);
|
|
252
|
+
}, []);
|
|
253
|
+
const onPinning = React.useCallback(() => {
|
|
254
|
+
refObj.scroller.enablePanEventsTracking();
|
|
255
|
+
setEnabledSelection(false);
|
|
256
|
+
}, []);
|
|
257
|
+
const onDownload = React.useCallback(() => {
|
|
258
|
+
download({
|
|
259
|
+
url: props.url,
|
|
260
|
+
data: props.data,
|
|
261
|
+
arrayBuffer: props.arrayBuffer,
|
|
262
|
+
error
|
|
263
|
+
}, props.saveFileName, props.saveOptions, triggerOnDownload);
|
|
264
|
+
}, [props.url, props.data, props.arrayBuffer, error, props.saveFileName, props.saveOptions, triggerOnDownload]);
|
|
265
|
+
const onPrint = React.useCallback(() => {
|
|
266
|
+
setLoading(true);
|
|
267
|
+
const onError = (e) => {
|
|
268
|
+
error(typeof (e ? e.message || e : null) === 'string' ? e.message || e : loc.toLanguageString(popupBlocked, messages[popupBlocked]));
|
|
269
|
+
};
|
|
270
|
+
const onDone = () => {
|
|
271
|
+
setLoading(false);
|
|
272
|
+
};
|
|
273
|
+
print(pages, onDone, onError);
|
|
274
|
+
}, [pages, error]);
|
|
275
|
+
const onAdd = React.useCallback((e) => {
|
|
276
|
+
const st = e.newState;
|
|
277
|
+
if (st[0] && st[0].getRawFile) {
|
|
278
|
+
const file = st[0].getRawFile();
|
|
279
|
+
file.arrayBuffer().then((arrayBuffer) => {
|
|
280
|
+
if (pagesRef.current) {
|
|
281
|
+
setLoading(true);
|
|
282
|
+
removeChildren(pagesRef.current);
|
|
283
|
+
loadPDF({
|
|
284
|
+
arrayBuffer,
|
|
285
|
+
dom: pagesRef.current,
|
|
286
|
+
zoom: DEFAULT_ZOOM_LEVEL,
|
|
287
|
+
done,
|
|
288
|
+
error
|
|
289
|
+
});
|
|
290
|
+
setZoom(DEFAULT_ZOOM_LEVEL);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}, [error]);
|
|
295
|
+
const onFileOpen = React.useCallback((e) => {
|
|
296
|
+
const targetEl = e.target;
|
|
297
|
+
if (targetEl instanceof HTMLElement && targetEl.parentNode) {
|
|
298
|
+
const toolbarEl = targetEl.closest('.k-toolbar');
|
|
299
|
+
const input = toolbarEl && toolbarEl.querySelector('.k-upload input');
|
|
300
|
+
if (input) {
|
|
301
|
+
input.click();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}, []);
|
|
305
|
+
const noDocument = !doc;
|
|
306
|
+
const loader = (loading && React.createElement("div", { className: "k-loader-container k-loader-container-md k-loader-top" },
|
|
307
|
+
React.createElement("div", { className: "k-loader-container-overlay k-overlay-light" }),
|
|
308
|
+
React.createElement("div", { className: "k-loader-container-inner " },
|
|
309
|
+
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 }),
|
|
324
|
+
React.createElement(Button, { className: 'k-toolbar-button', title: loc.toLanguageString(open, messages[open]), icon: 'folder-open', onClick: onFileOpen }),
|
|
325
|
+
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 })));
|
|
329
|
+
const content = (React.createElement("div", { className: classNames('k-canvas k-pdf-viewer-canvas k-pos-relative k-overflow-auto', {
|
|
330
|
+
'k-enable-text-select': enabledSelection,
|
|
331
|
+
'k-enable-panning': !enabledSelection
|
|
332
|
+
}), onScroll: onScroll },
|
|
333
|
+
showSearch && (React.createElement("div", { className: 'k-search-panel k-pos-sticky k-top-center' },
|
|
334
|
+
React.createElement(TextBox, { value: searchText, onChange: onSearchTextChange, placeholder: loc.toLanguageString(search, messages[search]), autoFocus: true, onKeyDown: onTextBoxKeyDown, suffix: () => (React.createElement(InputSuffix, null,
|
|
335
|
+
React.createElement(Button, { icon: "convert-lowercase", title: loc.toLanguageString(matchCaseM, messages[matchCaseM]), fillMode: "flat", togglable: true, selected: matchCase, onClick: onMatchCaseClick }))) }),
|
|
336
|
+
React.createElement("span", { className: "k-search-matches" },
|
|
337
|
+
React.createElement("span", null, currentMatch),
|
|
338
|
+
" of ",
|
|
339
|
+
React.createElement("span", null, matches)),
|
|
340
|
+
React.createElement(Button, { title: loc.toLanguageString(prevMatch, messages[prevMatch]), fillMode: 'flat', icon: 'arrow-up', disabled: matches === 0, onClick: onPrevMatch }),
|
|
341
|
+
React.createElement(Button, { title: loc.toLanguageString(nextMatch, messages[nextMatch]), fillMode: 'flat', icon: 'arrow-down', disabled: matches === 0, onClick: onNextMatch }),
|
|
342
|
+
React.createElement(Button, { title: loc.toLanguageString(close, messages[close]), fillMode: 'flat', icon: 'close', onClick: onClose }))),
|
|
343
|
+
React.createElement("div", { ref: pagesRef, className: 'k-pdf-viewer-pages' })));
|
|
344
|
+
return (React.createElement("div", { className: 'k-pdf-viewer', style: props.style, ref: pdfViewerRef },
|
|
345
|
+
props.onRenderLoader ? props.onRenderLoader.call(undefined, loader || null) : loader,
|
|
346
|
+
props.onRenderToolbar ? props.onRenderToolbar.call(undefined, toolbar) : toolbar,
|
|
347
|
+
props.onRenderContent ? props.onRenderContent.call(undefined, content) : content));
|
|
348
|
+
});
|
|
349
|
+
PDFViewer.displayName = 'KendoReactPDFViewer';
|
|
350
|
+
PDFViewer.propTypes = {
|
|
351
|
+
url: PropTypes.string,
|
|
352
|
+
data: PropTypes.string,
|
|
353
|
+
arrayBuffer: PropTypes.any,
|
|
354
|
+
typedArray: PropTypes.any,
|
|
355
|
+
style: PropTypes.object,
|
|
356
|
+
saveFileName: PropTypes.string,
|
|
357
|
+
saveOptions: PropTypes.object,
|
|
358
|
+
zoomLevels: PropTypes.arrayOf(PropTypes.any),
|
|
359
|
+
onError: PropTypes.func,
|
|
360
|
+
onLoad: PropTypes.func,
|
|
361
|
+
onDownload: PropTypes.func,
|
|
362
|
+
onRenderToolbar: PropTypes.func,
|
|
363
|
+
onRenderContent: PropTypes.func,
|
|
364
|
+
onRenderLoader: PropTypes.func
|
|
365
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PDFViewer, PDFViewerProps, PDFViewerHandle, LoadEvent, ErrorEvent, DownloadEvent } from './PDFViewer';
|
package/dist/es/main.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PDFViewer } from './PDFViewer';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hidden
|
|
3
|
+
*/
|
|
4
|
+
export declare const zoomIn = "pdfviewer.zoomIn";
|
|
5
|
+
/**
|
|
6
|
+
* @hidden
|
|
7
|
+
*/
|
|
8
|
+
export declare const zoomOut = "pdfviewer.zoomOut";
|
|
9
|
+
/**
|
|
10
|
+
* @hidden
|
|
11
|
+
*/
|
|
12
|
+
export declare const enableSelection = "pdfviewer.enableSelection";
|
|
13
|
+
/**
|
|
14
|
+
* @hidden
|
|
15
|
+
*/
|
|
16
|
+
export declare const enablePanning = "pdfviewer.enablePanning";
|
|
17
|
+
/**
|
|
18
|
+
* @hidden
|
|
19
|
+
*/
|
|
20
|
+
export declare const search = "pdfviewer.search";
|
|
21
|
+
/**
|
|
22
|
+
* @hidden
|
|
23
|
+
*/
|
|
24
|
+
export declare const open = "pdfviewer.open";
|
|
25
|
+
/**
|
|
26
|
+
* @hidden
|
|
27
|
+
*/
|
|
28
|
+
export declare const download = "pdfviewer.download";
|
|
29
|
+
/**
|
|
30
|
+
* @hidden
|
|
31
|
+
*/
|
|
32
|
+
export declare const print = "pdfviewer.print";
|
|
33
|
+
/**
|
|
34
|
+
* @hidden
|
|
35
|
+
*/
|
|
36
|
+
export declare const close = "pdfviewer.close";
|
|
37
|
+
/**
|
|
38
|
+
* @hidden
|
|
39
|
+
*/
|
|
40
|
+
export declare const matchCase = "pdfviewer.matchCase";
|
|
41
|
+
/**
|
|
42
|
+
* @hidden
|
|
43
|
+
*/
|
|
44
|
+
export declare const prevMatch = "pdfviewer.prevMatch";
|
|
45
|
+
/**
|
|
46
|
+
* @hidden
|
|
47
|
+
*/
|
|
48
|
+
export declare const nextMatch = "pdfviewer.nextMatch";
|
|
49
|
+
/**
|
|
50
|
+
* @hidden
|
|
51
|
+
*/
|
|
52
|
+
export declare const actualWidth = "pdfviewer.actualWidth";
|
|
53
|
+
/**
|
|
54
|
+
* @hidden
|
|
55
|
+
*/
|
|
56
|
+
export declare const fitToWidth = "pdfviewer.fitToWidth";
|
|
57
|
+
/**
|
|
58
|
+
* @hidden
|
|
59
|
+
*/
|
|
60
|
+
export declare const fitToPage = "pdfviewer.fitToPage";
|
|
61
|
+
/**
|
|
62
|
+
* @hidden
|
|
63
|
+
*/
|
|
64
|
+
export declare const popupBlocked = "pdfviewer.popupBlocked";
|
|
65
|
+
/**
|
|
66
|
+
* @hidden
|
|
67
|
+
*/
|
|
68
|
+
export declare const messages: {
|
|
69
|
+
"pdfviewer.zoomIn": string;
|
|
70
|
+
"pdfviewer.zoomOut": string;
|
|
71
|
+
"pdfviewer.enableSelection": string;
|
|
72
|
+
"pdfviewer.enablePanning": string;
|
|
73
|
+
"pdfviewer.search": string;
|
|
74
|
+
"pdfviewer.open": string;
|
|
75
|
+
"pdfviewer.download": string;
|
|
76
|
+
"pdfviewer.print": string;
|
|
77
|
+
"pdfviewer.close": string;
|
|
78
|
+
"pdfviewer.matchCase": string;
|
|
79
|
+
"pdfviewer.prevMatch": string;
|
|
80
|
+
"pdfviewer.nextMatch": string;
|
|
81
|
+
"pdfviewer.actualWidth": string;
|
|
82
|
+
"pdfviewer.fitToWidth": string;
|
|
83
|
+
"pdfviewer.fitToPage": string;
|
|
84
|
+
"pdfviewer.popupBlocked": string;
|
|
85
|
+
};
|