UNPKG

es-grid-template

Version:

es-grid-template

194 lines (188 loc) 7.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getRichVisibleRectsStream = getRichVisibleRectsStream; var _getNodeName = _interopRequireDefault(require("@popperjs/core/lib/dom-utils/getNodeName")); var _getOffsetParent = _interopRequireDefault(require("@popperjs/core/lib/dom-utils/getOffsetParent")); var _getParentNode = _interopRequireDefault(require("@popperjs/core/lib/dom-utils/getParentNode")); var _getWindow = _interopRequireDefault(require("@popperjs/core/lib/dom-utils/getWindow")); var _getWindowScroll = _interopRequireDefault(require("@popperjs/core/lib/dom-utils/getWindowScroll")); var _instanceOf = require("@popperjs/core/lib/dom-utils/instanceOf"); var _isScrollParent = _interopRequireDefault(require("@popperjs/core/lib/dom-utils/isScrollParent")); var _resizeObserverPolyfill = _interopRequireDefault(require("resize-observer-polyfill")); var _rxjs = require("rxjs"); var op = _interopRequireWildcard(require("rxjs/operators")); var _utils = require("../utils"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function isWindow(arg) { return arg.toString() === '[object Window]'; } function isBody(arg) { return (0, _getNodeName.default)(arg) === 'body'; } function isHtml(arg) { return (0, _getNodeName.default)(arg) === 'html'; } function isHtmlOrBody(arg) { return isHtml(arg) || isBody(arg); } // Accumulate the sum of scrollTop or scrollLeft for all elements from start (child) to stop (ancestor) // Note: start and stop are INCLUSIVE; both their scroll offsets are included function accumulateScrollOffset(start, stop, scrollOffsetKey) { let result = 0; let elem = start; while (elem != null) { result += elem[scrollOffsetKey]; if (elem === stop || isWindow(stop) && isHtmlOrBody(elem)) { break; } elem = elem.parentElement; } if (isWindow(stop)) { result += (0, _getWindowScroll.default)(elem)[scrollOffsetKey]; } return result; } /** * Get the layout size and relative position of `target` relative to `base`. * Note: this function accounts for scroll offsets. */ function getRelativeLayoutRect(base, target) { if (isWindow(target) || isHtmlOrBody(target)) { return { left: 0, right: window.innerWidth, top: 0, bottom: window.innerHeight }; } let deltaX = 0; let deltaY = 0; let elem = target; while (elem != null && elem != base) { deltaY += elem.offsetTop; deltaX += elem.offsetLeft; const offsetParent = (0, _getOffsetParent.default)(elem); deltaY -= accumulateScrollOffset(elem.parentElement, offsetParent, 'scrollTop'); deltaX -= accumulateScrollOffset(elem.parentElement, offsetParent, 'scrollLeft'); if (isWindow(offsetParent)) { break; } deltaY += offsetParent.clientTop; deltaX += offsetParent.clientLeft; elem = offsetParent; } return { top: deltaY, bottom: deltaY + target.offsetHeight, left: deltaX, right: deltaX + target.offsetWidth }; } function findCommonOffsetAncestor(target, scrollParent) { if (isWindow(scrollParent)) { return scrollParent; } const offsetParents = listOffsetParents(target); if (offsetParents.includes(scrollParent)) { return scrollParent; } return (0, _getOffsetParent.default)(scrollParent); } // List all offset parents above the target element function listOffsetParents(target) { const result = []; let elem = target; while (true) { if (isWindow(elem)) { break; } elem = (0, _getOffsetParent.default)(elem); result.push(elem); } return result; } function fromScrollEvent(element) { return (0, _rxjs.fromEvent)(element, 'scroll', { passive: true }); } function fromResizeEvent(element) { if (isWindow(element)) { return (0, _rxjs.fromEvent)(element, 'resize', { passive: true }); } return new _rxjs.Observable(subscriber => { const resizeObserver = new _resizeObserverPolyfill.default(entries => { subscriber.next(entries); }); resizeObserver.observe(element); return () => { resizeObserver.disconnect(); }; }); } function getScrollParent(elem) { // @ts-ignore if (['html', 'body', '#document'].includes((0, _getNodeName.default)(elem))) { return (0, _getWindow.default)(elem); } if ((0, _instanceOf.isHTMLElement)(elem) && (0, _isScrollParent.default)(elem)) { return elem; } return getScrollParent((0, _getParentNode.default)(elem)); } // Get the size and position of the visible area of the target // relative to its scroll parent function getRichVisibleRectsStream(target, structureMayChange$, virtualDebugLabel) { return structureMayChange$.pipe(op.startWith('init'), op.map(() => { // The first scroll parent of `target`; we consider this where virtual scrolling occurs. // Virtual scrolling ignores scrolls from ancestors above this element. const scrollParent = getScrollParent(target); // Common offset ancestor of `target` and `scrollParent`, used as reference for layout calculations const commonOffsetAncestor = findCommonOffsetAncestor(target, scrollParent); return { scrollParent, commonOffsetAncestor }; }), op.distinctUntilChanged(_utils.shallowEqual), op.tap(structure => { if (virtualDebugLabel) { console.log(`%c[ali-react-table STRUCTURE ${virtualDebugLabel}]`, 'color: #4f9052; font-weight: bold', '\ntarget:', target, '\nscrollParent:', structure.scrollParent, '\ncommonOffsetAncestor:', structure.commonOffsetAncestor); } }), op.switchMap(({ scrollParent, commonOffsetAncestor }) => { const events$ = (0, _rxjs.merge)(fromScrollEvent(scrollParent), fromResizeEvent(scrollParent), fromResizeEvent(target)); return events$.pipe(op.map(event => ({ targetRect: getRelativeLayoutRect(commonOffsetAncestor, target), scrollParentRect: getRelativeLayoutRect(commonOffsetAncestor, scrollParent), event })), op.map(({ event, scrollParentRect, targetRect }) => ({ event, targetRect, scrollParentRect, offsetY: Math.max(0, scrollParentRect.top - targetRect.top), // Table horizontal scrolling always occurs within the table, so offsetX does not need to be computed here // offsetX: Math.max(0, scrollParentRect.left - targetRect.left), clipRect: { left: Math.max(targetRect.left, scrollParentRect.left), top: Math.max(targetRect.top, scrollParentRect.top), right: Math.min(targetRect.right, scrollParentRect.right), bottom: Math.min(targetRect.bottom, scrollParentRect.bottom) } }))); }), op.tap(rects => { if (virtualDebugLabel) { console.log(`%c[ali-react-table RECTS ${virtualDebugLabel}]`, 'color: #4f9052; font-weight: bold', '\noffsetY:', rects.offsetY, '\ntargetRect:', rects.targetRect, '\nscrollParentRect:', rects.scrollParentRect, '\nclipRect:', rects.clipRect, '\nevent:', rects.event); } })); }