UNPKG

@eccenca/gui-elements

Version:

Collection of low-level GUI elements like Buttons, Icons or Alerts. Also includes core styles for those elements.

110 lines (101 loc) 3.99 kB
import ReactDOM from 'react-dom'; import scrollIntoViewExternal from 'scroll-into-view'; import _ from 'lodash'; const ScrollingMixin = { scrollIntoView(options = {}) { /* options { animationTime: 500, // (optional) integer, time in milliseconds topOffset: 0, // (optional) integer, pixels to offset top alignment callbackFinished: function(result) {}, // (optional) function, result parameter is currently 'cancelled' or 'completed' } */ this.scrollElementIntoView(ReactDOM.findDOMNode(this), options); }, scrollElementIntoView(element, options = {}) { let domElement = false; if (_.isElement(element)) { // is already a DOM element domElement = element; if (__DEBUG__) { console.log( `scrolling DOM element with a height of ${ domElement.scrollHeight }` ); } } else if (_.get(element, 'props', false) !== false) { // await a mounted react element or component // TODO: improve test, 'props' is only a weak check, findDOMNode still can fail domElement = ReactDOM.findDOMNode(element); if (__DEBUG__) { console.log( `scrolling react element with a height of ${ domElement.scrollHeight }` ); } } if (!domElement) { if (__DEBUG__) { console.warn( 'Cannot scroll element that is not part of the DOM.' ); } return false; } return scrollIntoViewExternal( domElement, { time: _.get(options, 'animationTime', 500), align: { top: 0, // align it to the top, or user cannot see top part if element is higher than the viewport topOffset: _.get(options, 'topOffset', 0), }, /* We replace the standard isScrollable with a function which also checks overflowX and overflowY, as only checking overflow is not enough in IE/Edge, because if the following is set: .foo { overflow-x: hidden; overflow-y: auto; } `getComputedStyle(element).overflow` will yield `'hidden'` */ isScrollable(el) { if (el === window) { return true; } if ( el.scrollHeight !== el.clientHeight || el.scrollWidth !== el.clientWidth ) { const css = getComputedStyle(el); return ( css && (css.overflow !== 'hidden' || (_.get(options, 'scrollY', true) && css.overflowY !== 'hidden') || (_.get(options, 'scrollX', true) && css.overflowX !== 'hidden')) ); } return false; }, }, result => { if (__DEBUG__) { console.log( `element scrolling ${result}, now at ${ domElement.getBoundingClientRect().top }` ); } if (_.isFunction(options.callbackFinished)) { options.callbackFinished(result); } } ); }, }; export default ScrollingMixin;