es-grid-template
Version:
es-grid-template
194 lines (188 loc) • 7.8 kB
JavaScript
;
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);
}
}));
}