UNPKG

react-resize-reporter

Version:

Lightweight React Component that reports width and height changes when its parent resizes.

145 lines 6.06 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ResizeReporter = void 0; const react_1 = __importStar(require("react")); const check_parent_1 = require("./check-parent"); const scrollerStyles = { overflow: 'hidden', position: 'absolute', zIndex: -1000, top: 0, right: 0, width: '100%', height: '100%', opacity: 0, pointerEvents: 'none' }; const expandDetectorStyles = { transition: '0s', animation: 'none' }; const shrinkDetectorStyles = { transition: '0s', animation: 'none', width: '250%', height: '250%' }; /** * Scroll event based resize detector */ class ResizeReporter extends react_1.PureComponent { constructor() { super(...arguments); this.containerRef = react_1.default.createRef(); this.lastWidth = -1; this.lastHeight = -1; this.resetPosition = (container, newWidth, newHeight) => { const $expand = container.firstChild; const $shrink = $expand.nextSibling; // ensure expand detector can scroll // shrink detector uses percentage so it will always be able to scroll const $expandDetector = $expand.firstChild; $expandDetector.style.width = newWidth + 1000 + 'px'; $expandDetector.style.height = newHeight + 1000 + 'px'; // after styles are applied this._setScrollPositionTicket = window.setTimeout(() => { $expand.scrollLeft = newWidth + 1000; $expand.scrollTop = newHeight + 1000; $shrink.scrollLeft = newWidth * 2.5; $shrink.scrollTop = newHeight * 2.5; }, 0); }; this.checkSize = () => { if (this.containerRef.current) { const parent = this.containerRef.current.parentElement; if (parent) { const newRect = parent.getBoundingClientRect(); const { width: newWidth, height: newHeight } = newRect; if (this.props.onSizeChanged) { if (newWidth !== this.lastWidth || newHeight !== this.lastHeight) { this.props.onSizeChanged(newWidth, newHeight, newRect); } } if (this.props.onWidthChanged && newWidth !== this.lastWidth) { this.props.onWidthChanged(newWidth, newRect); } if (this.props.onHeightChanged && newHeight !== this.lastHeight) { this.props.onHeightChanged(newHeight, newRect); } this.resetPosition(this.containerRef.current, newWidth, newHeight); this.lastWidth = newWidth; this.lastHeight = newHeight; } } }; this.onScroll = () => { if (this._debounceTicket) { window.clearTimeout(this._debounceTicket); this._debounceTicket = null; } // height and width scrolling happens on next loop // add timeout even for 0 this._debounceTicket = window.setTimeout(this.checkSize, this.props.debounce || 0); }; } componentDidMount() { if (this.containerRef.current) { const parent = this.containerRef.current.parentElement; if (process.env.NODE_ENV !== 'production') { check_parent_1.checkParent(parent); } if (parent) { if (this.props.reportInit) { this.checkSize(); } else { const rect = parent.getBoundingClientRect(); this.lastWidth = rect.width; this.lastHeight = rect.height; this.resetPosition(this.containerRef.current, this.lastWidth, this.lastHeight); } } } } componentWillUnmount() { if (this._debounceTicket) { window.clearTimeout(this._debounceTicket); this._debounceTicket = null; } if (this._setScrollPositionTicket) { window.clearTimeout(this._setScrollPositionTicket); this._setScrollPositionTicket = null; } } render() { const { reportInit, debounce, onSizeChanged, onWidthChanged, onHeightChanged, children, ...restProps } = this.props; return (react_1.default.createElement("div", Object.assign({ "aria-hidden": true, "aria-label": "react-resize-reporter", tabIndex: -1 }, restProps, { ref: this.containerRef }), react_1.default.createElement("div", { style: scrollerStyles, onScroll: this.onScroll }, react_1.default.createElement("div", { style: expandDetectorStyles })), react_1.default.createElement("div", { style: scrollerStyles, onScroll: this.onScroll }, react_1.default.createElement("div", { style: shrinkDetectorStyles })), children)); } } exports.ResizeReporter = ResizeReporter; exports.default = ResizeReporter; //# sourceMappingURL=scroll.js.map