UNPKG

es-grid-template

Version:

es-grid-template

157 lines (151 loc) 4.82 kB
import { asyncScheduler, BehaviorSubject, defer, fromEvent, Subscription } from 'rxjs'; import { map, throttleTime } from 'rxjs/operators'; import * as styledComponents from 'styled-components'; /** Version of the `styled-components` library. ali-react-table supports both v3 and v5. */ export const STYLED_VERSION = styledComponents.createGlobalStyle != null ? 'v5' : 'v3'; export const STYLED_REF_PROP = STYLED_VERSION === 'v3' ? 'innerRef' : 'ref'; export const OVERSCAN_SIZE = 300; export const AUTO_VIRTUAL_THRESHOLD = 300; export function sum(arr) { let result = 0; arr.forEach(x => { result += x; }); return result; } // Use defer to avoid referencing window too early, which can cause errors in SSR export const throttledWindowResize$ = defer(() => fromEvent(window, 'resize', { passive: true }).pipe(throttleTime(150, asyncScheduler, { leading: true, trailing: true }))); /** Get the default scrollbar size */ function getScrollbarSizeImpl() { const scrollDiv = document.createElement('div'); scrollDiv.style.position = 'absolute'; scrollDiv.style.width = '100px'; scrollDiv.style.height = '100px'; scrollDiv.style.overflow = 'scroll'; scrollDiv.style.top = '-9999px'; document.body.appendChild(scrollDiv); const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; const scrollbarHeight = scrollDiv.offsetHeight - scrollDiv.clientHeight; document.body.removeChild(scrollDiv); return { width: scrollbarWidth, height: scrollbarHeight }; } let scrollBarSize$; export function getScrollbarSize() { if (scrollBarSize$ == null) { scrollBarSize$ = new BehaviorSubject(getScrollbarSizeImpl()); throttledWindowResize$.pipe(map(() => getScrollbarSizeImpl())).subscribe(scrollBarSize$); } return scrollBarSize$.value; } /** * Synchronize the `scrollLeft` value among multiple elements. * The callback will be invoked whenever `scrollLeft` changes. */ export function syncScrollLeft(elements, callback) { const bypassSet = new Set(); function publishScrollLeft(origin, scrollLeft) { bypassSet.clear(); for (const elem of elements) { if (elem === origin) { continue; } elem.scrollLeft = scrollLeft; bypassSet.add(elem); } } const subscription = new Subscription(); for (const ele of elements) { const listener = () => { if (bypassSet.has(ele)) { bypassSet.delete(ele); return; } const scrollLeft = ele.scrollLeft; publishScrollLeft(ele, scrollLeft); callback(scrollLeft); }; ele.addEventListener('scroll', listener, { passive: true }); subscription.add(() => ele.removeEventListener('scroll', listener)); } return subscription; } /** * Performs equality by iterating through keys on an object and returning false * when any key has values which are not strictly equal between the arguments. * Returns true when the values of all keys are strictly equal. */ export function shallowEqual(objA, objB) { const hasOwnProperty = Object.prototype.hasOwnProperty; if (Object.is(objA, objB)) { return true; } if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { return false; } const keysA = Object.keys(objA); const keysB = Object.keys(objB); if (keysA.length !== keysB.length) { return false; } // Test for A's keys different from B. for (let i = 0; i < keysA.length; i++) { if (!hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) { return false; } } return true; } export function getParentElement(element, selector) { function isMatched(el, str = "") { // eslint-disable-next-line no-param-reassign str = str.toLowerCase(); let matched = false; const firstChar = str.split("")[0]; if (firstChar === ".") { const selectorClass = str.split(".")[1] || ""; const elCls = el.className || ""; if (typeof elCls === "string") { const cls = elCls.toLowerCase().split(" "); matched = cls.indexOf(selectorClass) > -1; } } else if (firstChar === "#") { const selectorID = str.split("#")[1] || ""; const elID = el.id || ""; if (typeof elID === "string") { matched = elID.toLowerCase() === selectorID; } } else { matched = el.tagName.toLowerCase() === str; } return matched; } function getParent(el, tagName) { if (!el) { return null; } if (isMatched(el, tagName)) { // return el; } const p = el.parentElement || el.parentNode; if (p) { if (isMatched(p, tagName)) { return p; } else { return getParent(p, tagName); } } else { return null; } } return getParent(element, selector); }