@revolist/revogrid
Version:
Virtual reactive data grid spreadsheet component - RevoGrid.
84 lines (83 loc) • 3.4 kB
JavaScript
/*!
* Built by Revolist OU ❤️
*/
const FALLBACK_MAX_SCROLL_SIZE = 16000000;
const SCROLL_SIZE_GUARD = 1000000;
let detectedMaxScrollSize;
export function getMaxScrollSize(doc = typeof document === 'undefined' ? undefined : document) {
if (typeof detectedMaxScrollSize === 'number') {
return detectedMaxScrollSize;
}
const body = doc === null || doc === void 0 ? void 0 : doc.body;
if (body) {
const ownerDocument = body.ownerDocument;
const element = ownerDocument.createElement('div');
element.style.cssText = [
'height:1px',
'left:-10000px',
'overflow:scroll',
'position:absolute',
'top:-10000px',
'visibility:hidden',
'width:1px',
].join(';');
const content = ownerDocument.createElement('div');
content.style.height = `${FALLBACK_MAX_SCROLL_SIZE * 4}px`;
element.appendChild(content);
body.appendChild(element);
detectedMaxScrollSize = Math.max(0, Math.min(element.scrollHeight, FALLBACK_MAX_SCROLL_SIZE * 4) - SCROLL_SIZE_GUARD);
element.remove();
if (detectedMaxScrollSize > SCROLL_SIZE_GUARD) {
return detectedMaxScrollSize;
}
detectedMaxScrollSize = FALLBACK_MAX_SCROLL_SIZE;
return detectedMaxScrollSize;
}
return FALLBACK_MAX_SCROLL_SIZE;
}
export function getScrollDimension({ contentSize, clientSize, virtualSize = 0, maxScrollSize = getMaxScrollSize(), }) {
const safeContentSize = Math.max(0, maxScrollSize - SCROLL_SIZE_GUARD);
const size = Math.max(0, contentSize);
const client = Math.max(0, clientSize);
const viewport = Math.max(0, virtualSize || client);
const logicalScrollSize = Math.max(0, size - viewport);
const maxPhysicalScrollSize = Math.max(0, safeContentSize - client);
const physicalScrollSize = Math.min(logicalScrollSize, maxPhysicalScrollSize);
const physicalContentSize = client + physicalScrollSize;
const isCompressed = logicalScrollSize > physicalScrollSize && physicalScrollSize > 0;
const clampLogical = (coordinate) => Math.min(Math.max(0, coordinate || 0), logicalScrollSize);
const clampPhysical = (coordinate) => Math.min(Math.max(0, coordinate || 0), physicalScrollSize);
const toLogicalCoordinate = (coordinate) => {
if (!logicalScrollSize || !physicalScrollSize) {
return 0;
}
if (!isCompressed) {
return clampLogical(coordinate);
}
return clampLogical((clampPhysical(coordinate) / physicalScrollSize) * logicalScrollSize);
};
const toPhysicalCoordinate = (coordinate) => {
if (!logicalScrollSize || !physicalScrollSize) {
return 0;
}
if (!isCompressed) {
return clampPhysical(coordinate);
}
return clampPhysical((clampLogical(coordinate) / logicalScrollSize) * physicalScrollSize);
};
return {
contentSize: size,
clientSize: client,
viewportSize: viewport,
physicalContentSize,
logicalScrollSize,
physicalScrollSize,
isCompressed,
toLogicalCoordinate,
toPhysicalCoordinate,
getRenderOffset(coordinate) {
const logical = clampLogical(coordinate);
return logical - toPhysicalCoordinate(logical);
},
};
}