Files
PLSmartPivot/src/linked-scroll/linked-scroll-wrapper.jsx

83 lines
2.1 KiB
JavaScript

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
export const LinkedScrollContext = React.createContext();
class LinkedScrollWrapper extends React.PureComponent {
constructor (props) {
super(props);
this.linkComponent = this.linkComponent.bind(this);
this.unlinkComponent = this.unlinkComponent.bind(this);
this.handleScroll = this.handleScroll.bind(this);
this.scrollElements = [];
this.linkActions = {
link: this.linkComponent,
unlink: this.unlinkComponent
};
}
linkComponent (component) {
// eslint-disable-next-line react/no-find-dom-node
const node = ReactDOM.findDOMNode(component);
const element = {
component,
node
};
this.scrollElements.push(element);
node.onscroll = this.handleScroll.bind(this, element);
}
unlinkComponent (component) {
const componentIndex = this.scrollElements.map(element => element.component).indexOf(component);
if (componentIndex !== -1) {
this.scrollElements.removeAt(componentIndex);
// eslint-disable-next-line react/no-find-dom-node
const node = ReactDOM.findDOMNode(component);
node.onscroll = null;
}
}
handleScroll (element) {
window.requestAnimationFrame(() => {
this.sync(element);
});
}
sync (scrollElement) {
this.scrollElements.forEach(element => {
if (scrollElement === element) {
return;
}
element.node.onscroll = null;
if (element.component.props.linkHorizontal) {
element.node.scrollLeft = scrollElement.node.scrollLeft;
}
if (element.component.props.linkVertical) {
element.node.scrollTop = scrollElement.node.scrollTop;
}
window.requestAnimationFrame(() => {
element.node.onscroll = this.handleScroll.bind(this, element);
});
});
}
render () {
const { children } = this.props;
return (
<LinkedScrollContext.Provider value={this.linkActions}>
{children}
</LinkedScrollContext.Provider>
);
}
}
LinkedScrollWrapper.propTypes = {
children: PropTypes.any
};
export default LinkedScrollWrapper;