@peergrade/react-pdf
Version:
Display PDFs in your React app as easily as if they were images.
147 lines (120 loc) • 3.17 kB
JSX
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import PageContext from '../PageContext';
import TextLayerItem from './TextLayerItem';
import {
callIfDefined,
cancelRunningTask,
errorOnDev,
makeCancellable,
} from '../shared/utils';
import { isPage, isRotate } from '../shared/propTypes';
export class TextLayerInternal extends PureComponent {
state = {
textItems: null,
}
componentDidMount() {
if (!this.props.page) {
throw new Error('Attempted to load page text content, but no page was specified.');
}
this.loadTextItems();
}
componentDidUpdate(prevProps) {
if (prevProps.page && (this.props.page !== prevProps.page)) {
this.loadTextItems();
}
}
componentWillUnmount() {
cancelRunningTask(this.runningTask);
}
loadTextItems = async () => {
const { page } = this.props;
try {
const cancellable = makeCancellable(page.getTextContent());
this.runningTask = cancellable;
const { items: textItems } = await cancellable.promise;
this.setState({ textItems }, this.onLoadSuccess);
} catch (error) {
this.setState({ textItems: false });
this.onLoadError(error);
}
}
onLoadSuccess = () => {
callIfDefined(
this.props.onGetTextSuccess,
this.state.textItems,
);
}
onLoadError = (error) => {
if (
error.name === 'RenderingCancelledException' ||
error.name === 'PromiseCancelledException'
) {
return;
}
errorOnDev(error);
callIfDefined(
this.props.onGetTextError,
error,
);
}
get unrotatedViewport() {
const { page, scale } = this.props;
return page.getViewport(scale);
}
/**
* It might happen that the page is rotated by default. In such cases, we shouldn't rotate
* text content.
*/
get rotate() {
const { page, rotate } = this.props;
return rotate - page.rotate;
}
renderTextItems() {
const { textItems } = this.state;
if (!textItems) {
return null;
}
return textItems.map((textItem, itemIndex) => (
<TextLayerItem
// eslint-disable-next-line react/no-array-index-key
key={itemIndex}
itemIndex={itemIndex}
{...textItem}
/>
));
}
render() {
const { unrotatedViewport: viewport, rotate } = this;
return (
<div
className="react-pdf__Page__textContent"
style={{
position: 'absolute',
top: '50%',
left: '50%',
width: `${viewport.width}px`,
height: `${viewport.height}px`,
color: 'transparent',
transform: `translate(-50%, -50%) rotate(${rotate}deg)`,
pointerEvents: 'none',
}}
>
{this.renderTextItems()}
</div>
);
}
}
TextLayerInternal.propTypes = {
onGetTextError: PropTypes.func,
onGetTextSuccess: PropTypes.func,
page: isPage.isRequired,
rotate: isRotate,
scale: PropTypes.number,
};
const TextLayer = props => (
<PageContext.Consumer>
{context => <TextLayerInternal {...context} {...props} />}
</PageContext.Consumer>
);
export default TextLayer;