@alauda-fe/common
Version:
Alauda frontend team common codes.
209 lines • 30.1 kB
JavaScript
import { animationFrameScheduler, fromEvent, interval, NEVER, distinctUntilChanged, filter, map, switchMap, tap, } from 'rxjs';
import { getClientRectSnapshot } from './client-rect.utils';
/**
* Proximity, as a ratio to width/height at which to start auto-scrolling.
* The value comes from trying it out manually until it feels right.
*/
const SCROLL_PROXIMITY_THRESHOLD = 0.05;
/**
* Increments the vertical scroll position of a node.
* @param node Node whose scroll position should change.
* @param amount Amount of pixels that the `node` should be scrolled.
*/
function incrementVerticalScroll(node, amount) {
if (node === window) {
node.scrollBy(0, amount);
}
else {
// Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it.
node.scrollTop += amount;
}
}
/**
* Increments the horizontal scroll position of a node.
* @param node Node whose scroll position should change.
* @param amount Amount of pixels that the `node` should be scrolled.
*/
function incrementHorizontalScroll(node, amount) {
if (node === window) {
node.scrollBy(amount, 0);
}
else {
// Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it.
node.scrollLeft += amount;
}
}
/**
* Gets whether the vertical auto-scroll direction of a node.
* @param clientRect Dimensions of the node.
* @param pointerY Position of the user's pointer along the y axis.
*/
function getVerticalScrollDirection(clientRect, pointerY) {
const { top, bottom, height } = clientRect;
const yThreshold = height * SCROLL_PROXIMITY_THRESHOLD;
if (pointerY >= top - yThreshold && pointerY <= top + yThreshold) {
return 1 /* AutoScrollVerticalDirection.UP */;
}
if (pointerY >= bottom - yThreshold && pointerY <= bottom + yThreshold) {
return 2 /* AutoScrollVerticalDirection.DOWN */;
}
return 0 /* AutoScrollVerticalDirection.NONE */;
}
/**
* Gets whether the horizontal auto-scroll direction of a node.
* @param clientRect Dimensions of the node.
* @param pointerX Position of the user's pointer along the x axis.
*/
function getHorizontalScrollDirection(clientRect, pointerX) {
const { left, right, width } = clientRect;
const xThreshold = width * SCROLL_PROXIMITY_THRESHOLD;
if (pointerX >= left - xThreshold && pointerX <= left + xThreshold) {
return 1 /* AutoScrollHorizontalDirection.LEFT */;
}
if (pointerX >= right - xThreshold && pointerX <= right + xThreshold) {
return 2 /* AutoScrollHorizontalDirection.RIGHT */;
}
return 0 /* AutoScrollHorizontalDirection.NONE */;
}
/**
* Returns an observable that schedules a loop and apply scroll on the scrollNode into the specified direction/s.
* This observable doesn't emit, it just performs the 'scroll' side effect.
* @param scrollNode, node where the scroll would be applied.
* @param verticalScrollDirection, vertical direction of the scroll.
* @param horizontalScrollDirection, horizontal direction of the scroll.
* @param scrollStep, scroll step in CSS pixels that would be applied in every loop.
*/
function scrollToDirectionInterval$(scrollNode, verticalScrollDirection, horizontalScrollDirection, scrollStep = 2) {
return interval(0, animationFrameScheduler).pipe(tap(() => {
if (verticalScrollDirection === 1 /* AutoScrollVerticalDirection.UP */) {
incrementVerticalScroll(scrollNode, -scrollStep);
}
else if (verticalScrollDirection === 2 /* AutoScrollVerticalDirection.DOWN */) {
incrementVerticalScroll(scrollNode, scrollStep);
}
if (horizontalScrollDirection === 1 /* AutoScrollHorizontalDirection.LEFT */) {
incrementHorizontalScroll(scrollNode, -scrollStep);
}
else if (horizontalScrollDirection === 2 /* AutoScrollHorizontalDirection.RIGHT */) {
incrementHorizontalScroll(scrollNode, scrollStep);
}
}), filter(() => false));
}
/**
* Given a source$ observable with pointer location, scroll the scrollNode if the pointer is near to it.
* This observable doesn't emit, it just performs a 'scroll' side effect.
* @param scrollableParent, parent node in which the scroll would be performed.
* @param options, configuration options.
*/
// eslint-disable-next-line sonarjs/cognitive-complexity
export function scrollIfNearElementClientRect$(scrollableParent, options) {
let scrollNode;
let scrollableParentClientRect;
let scrollableParentScrollWidth;
if (scrollableParent === document) {
scrollNode = document.defaultView;
const { width, height } = getViewportSize();
scrollableParentClientRect = {
width,
height,
top: 0,
right: width,
bottom: height,
left: 0,
};
scrollableParentScrollWidth = getDocumentScrollWidth();
}
else {
scrollNode = scrollableParent;
scrollableParentClientRect = getClientRectSnapshot(scrollableParent);
scrollableParentScrollWidth = scrollableParent.scrollWidth;
}
/**
* IMPORTANT: By design, only let scroll horizontal if the scrollable parent has explicitly an scroll horizontal.
* This layout solution is not designed in mind to have any scroll horizontal, but exceptionally we allow it in this
* specific use case.
*/
options = options || {};
if (options.disableHorizontal == null &&
scrollableParentScrollWidth <= scrollableParentClientRect.width) {
options.disableHorizontal = true;
}
return source$ => source$.pipe(map(({ pointerX, pointerY }) => {
let verticalScrollDirection = getVerticalScrollDirection(scrollableParentClientRect, pointerY);
let horizontalScrollDirection = getHorizontalScrollDirection(scrollableParentClientRect, pointerX);
// Check if scroll directions are disabled.
if (options?.disableVertical) {
verticalScrollDirection = 0 /* AutoScrollVerticalDirection.NONE */;
}
if (options?.disableHorizontal) {
horizontalScrollDirection = 0 /* AutoScrollHorizontalDirection.NONE */;
}
return { verticalScrollDirection, horizontalScrollDirection };
}), distinctUntilChanged((prev, actual) => prev.verticalScrollDirection === actual.verticalScrollDirection &&
prev.horizontalScrollDirection === actual.horizontalScrollDirection), switchMap(({ verticalScrollDirection, horizontalScrollDirection }) => {
if (verticalScrollDirection || horizontalScrollDirection) {
return scrollToDirectionInterval$(scrollNode, verticalScrollDirection, horizontalScrollDirection, options?.scrollStep);
}
return NEVER;
}));
}
/**
* Emits on EVERY scroll event and returns the accumulated scroll offset relative to the initial scroll position.
* @param scrollableParent, node in which scroll events would be listened.
*/
export function getScrollTotalRelativeDifference$(scrollableParent) {
const scrollInitialPosition = scrollableParent === document
? getViewportScrollPosition()
: {
top: scrollableParent.scrollTop,
left: scrollableParent.scrollLeft,
};
return fromEvent(scrollableParent, 'scroll', {
capture: true,
}).pipe(map(() => {
let newTop;
let newLeft;
if (scrollableParent === document) {
const viewportScrollPosition = getViewportScrollPosition();
newTop = viewportScrollPosition.top;
newLeft = viewportScrollPosition.left;
}
else {
newTop = scrollableParent.scrollTop;
newLeft = scrollableParent.scrollLeft;
}
const topDifference = scrollInitialPosition.top - newTop;
const leftDifference = scrollInitialPosition.left - newLeft;
return { top: topDifference, left: leftDifference };
}));
}
/** Returns the viewport's width and height. */
function getViewportSize() {
const _window = document.defaultView || window;
return {
width: _window.innerWidth,
height: _window.innerHeight,
};
}
/** Gets the (top, left) scroll position of the viewport. */
function getViewportScrollPosition() {
const windowRef = document.defaultView || window;
const documentElement = document.documentElement;
const documentRect = documentElement.getBoundingClientRect();
const top = -documentRect.top ||
document.body.scrollTop ||
windowRef.scrollY ||
documentElement.scrollTop ||
0;
const left = -documentRect.left ||
document.body.scrollLeft ||
windowRef.scrollX ||
documentElement.scrollLeft ||
0;
return { top, left };
}
/** Returns the document scroll width */
function getDocumentScrollWidth() {
return Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsLnV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9jb21tb24vc3JjL2dyaWQtbGF5b3V0L3V0aWxzL3Njcm9sbC51dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxRQUFRLEVBQ1IsS0FBSyxFQUVMLG9CQUFvQixFQUNwQixNQUFNLEVBQ04sR0FBRyxFQUNILFNBQVMsRUFDVCxHQUFHLEdBQ0osTUFBTSxNQUFNLENBQUM7QUFJZCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU1RDs7O0dBR0c7QUFDSCxNQUFNLDBCQUEwQixHQUFHLElBQUksQ0FBQztBQXFCeEM7Ozs7R0FJRztBQUNILFNBQVMsdUJBQXVCLENBQUMsSUFBMEIsRUFBRSxNQUFjO0lBQ3pFLElBQUksSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzNCLENBQUM7U0FBTSxDQUFDO1FBQ04sMEZBQTBGO1FBQ3pGLElBQW9CLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQztJQUM1QyxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLHlCQUF5QixDQUFDLElBQTBCLEVBQUUsTUFBYztJQUMzRSxJQUFJLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzQixDQUFDO1NBQU0sQ0FBQztRQUNOLDBGQUEwRjtRQUN6RixJQUFvQixDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUM7SUFDN0MsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUywwQkFBMEIsQ0FDakMsVUFBOEIsRUFDOUIsUUFBZ0I7SUFFaEIsTUFBTSxF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QztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBhbmltYXRpb25GcmFtZVNjaGVkdWxlcixcbiAgZnJvbUV2ZW50LFxuICBpbnRlcnZhbCxcbiAgTkVWRVIsXG4gIE9ic2VydmFibGUsXG4gIGRpc3RpbmN0VW50aWxDaGFuZ2VkLFxuICBmaWx0ZXIsXG4gIG1hcCxcbiAgc3dpdGNoTWFwLFxuICB0YXAsXG59IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBHcmlkSXRlbUNsaWVudFJlY3QgfSBmcm9tICcuLi9wdWJsaWMtYXBpJztcblxuaW1wb3J0IHsgZ2V0Q2xpZW50UmVjdFNuYXBzaG90IH0gZnJvbSAnLi9jbGllbnQtcmVjdC51dGlscyc7XG5cbi8qKlxuICogUHJveGltaXR5LCBhcyBhIHJhdGlvIHRvIHdpZHRoL2hlaWdodCBhdCB3aGljaCB0byBzdGFydCBhdXRvLXNjcm9sbGluZy5cbiAqIFRoZSB2YWx1ZSBjb21lcyBmcm9tIHRyeWluZyBpdCBvdXQgbWFudWFsbHkgdW50aWwgaXQgZmVlbHMgcmlnaHQuXG4gKi9cbmNvbnN0IFNDUk9MTF9QUk9YSU1JVFlfVEhSRVNIT0xEID0gMC4wNTtcblxuLyoqIFZlcnRpY2FsIGRpcmVjdGlvbiBpbiB3aGljaCB3ZSBjYW4gYXV0by1zY3JvbGwuICovXG5jb25zdCBlbnVtIEF1dG9TY3JvbGxWZXJ0aWNhbERpcmVjdGlvbiB7XG4gIE5PTkUsXG4gIFVQLFxuICBET1dOLFxufVxuXG4vKiogSG9yaXpvbnRhbCBkaXJlY3Rpb24gaW4gd2hpY2ggd2UgY2FuIGF1dG8tc2Nyb2xsLiAqL1xuY29uc3QgZW51bSBBdXRvU2Nyb2xsSG9yaXpvbnRhbERpcmVjdGlvbiB7XG4gIE5PTkUsXG4gIExFRlQsXG4gIFJJR0hULFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEt0ZFNjcm9sbFBvc2l0aW9uIHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBJbmNyZW1lbnRzIHRoZSB2ZXJ0aWNhbCBzY3JvbGwgcG9zaXRpb24gb2YgYSBub2RlLlxuICogQHBhcmFtIG5vZGUgTm9kZSB3aG9zZSBzY3JvbGwgcG9zaXRpb24gc2hvdWxkIGNoYW5nZS5cbiAqIEBwYXJhbSBhbW91bnQgQW1vdW50IG9mIHBpeGVscyB0aGF0IHRoZSBgbm9kZWAgc2hvdWxkIGJlIHNjcm9sbGVkLlxuICovXG5mdW5jdGlvbiBpbmNyZW1lbnRWZXJ0aWNhbFNjcm9sbChub2RlOiBIVE1MRWxlbWVudCB8IFdpbmRvdywgYW1vdW50OiBudW1iZXIpIHtcbiAgaWYgKG5vZGUgPT09IHdpbmRvdykge1xuICAgIG5vZGUuc2Nyb2xsQnkoMCwgYW1vdW50KTtcbiAgfSBlbHNlIHtcbiAgICAvLyBJZGVhbGx5IHdlIGNvdWxkIHVzZSBgRWxlbWVudC5zY3JvbGxCeWAgaGVyZSBhcyB3ZWxsLCBidXQgSUUgYW5kIEVkZ2UgZG9uJ3Qgc3VwcG9ydCBpdC5cbiAgICAobm9kZSBhcyBIVE1MRWxlbWVudCkuc2Nyb2xsVG9wICs9IGFtb3VudDtcbiAgfVxufVxuXG4vKipcbiAqIEluY3JlbWVudHMgdGhlIGhvcml6b250YWwgc2Nyb2xsIHBvc2l0aW9uIG9mIGEgbm9kZS5cbiAqIEBwYXJhbSBub2RlIE5vZGUgd2hvc2Ugc2Nyb2xsIHBvc2l0aW9uIHNob3VsZCBjaGFuZ2UuXG4gKiBAcGFyYW0gYW1vdW50IEFtb3VudCBvZiBwaXhlbHMgdGhhdCB0aGUgYG5vZGVgIHNob3VsZCBiZSBzY3JvbGxlZC5cbiAqL1xuZnVuY3Rpb24gaW5jcmVtZW50SG9yaXpvbnRhbFNjcm9sbChub2RlOiBIVE1MRWxlbWVudCB8IFdpbmRvdywgYW1vdW50OiBudW1iZXIpIHtcbiAgaWYgKG5vZGUgPT09IHdpbmRvdykge1xuICAgIG5vZGUuc2Nyb2xsQnkoYW1vdW50LCAwKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBJZGVhbGx5IHdlIGNvdWxkIHVzZSBgRWxlbWVudC5zY3JvbGxCeWAgaGVyZSBhcyB3ZWxsLCBidXQgSUUgYW5kIEVkZ2UgZG9uJ3Qgc3VwcG9ydCBpdC5cbiAgICAobm9kZSBhcyBIVE1MRWxlbWVudCkuc2Nyb2xsTGVmdCArPSBhbW91bnQ7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIHdoZXRoZXIgdGhlIHZlcnRpY2FsIGF1dG8tc2Nyb2xsIGRpcmVjdGlvbiBvZiBhIG5vZGUuXG4gKiBAcGFyYW0gY2xpZW50UmVjdCBEaW1lbnNpb25zIG9mIHRoZSBub2RlLlxuICogQHBhcmFtIHBvaW50ZXJZIFBvc2l0aW9uIG9mIHRoZSB1c2VyJ3MgcG9pbnRlciBhbG9uZyB0aGUgeSBheGlzLlxuICovXG5mdW5jdGlvbiBnZXRWZXJ0aWNhbFNjcm9sbERpcmVjdGlvbihcbiAgY2xpZW50UmVjdDogR3JpZEl0ZW1DbGllbnRSZWN0LFxuICBwb2ludGVyWTogbnVtYmVyLFxuKSB7XG4gIGNvbnN0IHsgdG9wLCBib3R0b20sIGhlaWdodCB9ID0gY2xpZW50UmVjdDtcbiAgY29uc3QgeVRocmVzaG9sZCA9IGhlaWdodCAqIFNDUk9MTF9QUk9YSU1JVFlfVEhSRVNIT0xEO1xuXG4gIGlmIChwb2ludGVyWSA+PSB0b3AgLSB5VGhyZXNob2xkICYmIHBvaW50ZXJZIDw9IHRvcCArIHlUaHJlc2hvbGQpIHtcbiAgICByZXR1cm4gQXV0b1Njcm9sbFZlcnRpY2FsRGlyZWN0aW9uLlVQO1xuICB9XG4gIGlmIChwb2ludGVyWSA+PSBib3R0b20gLSB5VGhyZXNob2xkICYmIHBvaW50ZXJZIDw9IGJvdHRvbSArIHlUaHJlc2hvbGQpIHtcbiAgICByZXR1cm4gQXV0b1Njcm9sbFZlcnRpY2FsRGlyZWN0aW9uLkRPV047XG4gIH1cblxuICByZXR1cm4gQXV0b1Njcm9sbFZlcnRpY2FsRGlyZWN0aW9uLk5PTkU7XG59XG5cbi8qKlxuICogR2V0cyB3aGV0aGVyIHRoZSBob3Jpem9udGFsIGF1dG8tc2Nyb2xsIGRpcmVjdGlvbiBvZiBhIG5vZGUuXG4gKiBAcGFyYW0gY2xpZW50UmVjdCBEaW1lbnNpb25zIG9mIHRoZSBub2RlLlxuICogQHBhcmFtIHBvaW50ZXJYIFBvc2l0aW9uIG9mIHRoZSB1c2VyJ3MgcG9pbnRlciBhbG9uZyB0aGUgeCBheGlzLlxuICovXG5mdW5jdGlvbiBnZXRIb3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uKFxuICBjbGllbnRSZWN0OiBHcmlkSXRlbUNsaWVudFJlY3QsXG4gIHBvaW50ZXJYOiBudW1iZXIsXG4pIHtcbiAgY29uc3QgeyBsZWZ0LCByaWdodCwgd2lkdGggfSA9IGNsaWVudFJlY3Q7XG4gIGNvbnN0IHhUaHJlc2hvbGQgPSB3aWR0aCAqIFNDUk9MTF9QUk9YSU1JVFlfVEhSRVNIT0xEO1xuXG4gIGlmIChwb2ludGVyWCA+PSBsZWZ0IC0geFRocmVzaG9sZCAmJiBwb2ludGVyWCA8PSBsZWZ0ICsgeFRocmVzaG9sZCkge1xuICAgIHJldHVybiBBdXRvU2Nyb2xsSG9yaXpvbnRhbERpcmVjdGlvbi5MRUZUO1xuICB9XG4gIGlmIChwb2ludGVyWCA+PSByaWdodCAtIHhUaHJlc2hvbGQgJiYgcG9pbnRlclggPD0gcmlnaHQgKyB4VGhyZXNob2xkKSB7XG4gICAgcmV0dXJuIEF1dG9TY3JvbGxIb3Jpem9udGFsRGlyZWN0aW9uLlJJR0hUO1xuICB9XG5cbiAgcmV0dXJuIEF1dG9TY3JvbGxIb3Jpem9udGFsRGlyZWN0aW9uLk5PTkU7XG59XG5cbi8qKlxuICogUmV0dXJucyBhbiBvYnNlcnZhYmxlIHRoYXQgc2NoZWR1bGVzIGEgbG9vcCBhbmQgYXBwbHkgc2Nyb2xsIG9uIHRoZSBzY3JvbGxOb2RlIGludG8gdGhlIHNwZWNpZmllZCBkaXJlY3Rpb24vcy5cbiAqIFRoaXMgb2JzZXJ2YWJsZSBkb2Vzbid0IGVtaXQsIGl0IGp1c3QgcGVyZm9ybXMgdGhlICdzY3JvbGwnIHNpZGUgZWZmZWN0LlxuICogQHBhcmFtIHNjcm9sbE5vZGUsIG5vZGUgd2hlcmUgdGhlIHNjcm9sbCB3b3VsZCBiZSBhcHBsaWVkLlxuICogQHBhcmFtIHZlcnRpY2FsU2Nyb2xsRGlyZWN0aW9uLCB2ZXJ0aWNhbCBkaXJlY3Rpb24gb2YgdGhlIHNjcm9sbC5cbiAqIEBwYXJhbSBob3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uLCBob3Jpem9udGFsIGRpcmVjdGlvbiBvZiB0aGUgc2Nyb2xsLlxuICogQHBhcmFtIHNjcm9sbFN0ZXAsIHNjcm9sbCBzdGVwIGluIENTUyBwaXhlbHMgdGhhdCB3b3VsZCBiZSBhcHBsaWVkIGluIGV2ZXJ5IGxvb3AuXG4gKi9cbmZ1bmN0aW9uIHNjcm9sbFRvRGlyZWN0aW9uSW50ZXJ2YWwkKFxuICBzY3JvbGxOb2RlOiBIVE1MRWxlbWVudCB8IFdpbmRvdyxcbiAgdmVydGljYWxTY3JvbGxEaXJlY3Rpb246IEF1dG9TY3JvbGxWZXJ0aWNhbERpcmVjdGlvbixcbiAgaG9yaXpvbnRhbFNjcm9sbERpcmVjdGlvbjogQXV0b1Njcm9sbEhvcml6b250YWxEaXJlY3Rpb24sXG4gIHNjcm9sbFN0ZXAgPSAyLFxuKSB7XG4gIHJldHVybiBpbnRlcnZhbCgwLCBhbmltYXRpb25GcmFtZVNjaGVkdWxlcikucGlwZShcbiAgICB0YXAoKCkgPT4ge1xuICAgICAgaWYgKHZlcnRpY2FsU2Nyb2xsRGlyZWN0aW9uID09PSBBdXRvU2Nyb2xsVmVydGljYWxEaXJlY3Rpb24uVVApIHtcbiAgICAgICAgaW5jcmVtZW50VmVydGljYWxTY3JvbGwoc2Nyb2xsTm9kZSwgLXNjcm9sbFN0ZXApO1xuICAgICAgfSBlbHNlIGlmICh2ZXJ0aWNhbFNjcm9sbERpcmVjdGlvbiA9PT0gQXV0b1Njcm9sbFZlcnRpY2FsRGlyZWN0aW9uLkRPV04pIHtcbiAgICAgICAgaW5jcmVtZW50VmVydGljYWxTY3JvbGwoc2Nyb2xsTm9kZSwgc2Nyb2xsU3RlcCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChob3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uID09PSBBdXRvU2Nyb2xsSG9yaXpvbnRhbERpcmVjdGlvbi5MRUZUKSB7XG4gICAgICAgIGluY3JlbWVudEhvcml6b250YWxTY3JvbGwoc2Nyb2xsTm9kZSwgLXNjcm9sbFN0ZXApO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgaG9yaXpvbnRhbFNjcm9sbERpcmVjdGlvbiA9PT0gQXV0b1Njcm9sbEhvcml6b250YWxEaXJlY3Rpb24uUklHSFRcbiAgICAgICkge1xuICAgICAgICBpbmNyZW1lbnRIb3Jpem9udGFsU2Nyb2xsKHNjcm9sbE5vZGUsIHNjcm9sbFN0ZXApO1xuICAgICAgfVxuICAgIH0pLFxuICAgIGZpbHRlcigoKSA9PiBmYWxzZSksXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Nyb2xsSWZOZWFyRWxlbWVudE9wdGlvbnMge1xuICBzY3JvbGxTdGVwPzogbnVtYmVyO1xuICBkaXNhYmxlVmVydGljYWw/OiBib29sZWFuO1xuICBkaXNhYmxlSG9yaXpvbnRhbD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogR2l2ZW4gYSBzb3VyY2UkIG9ic2VydmFibGUgd2l0aCBwb2ludGVyIGxvY2F0aW9uLCBzY3JvbGwgdGhlIHNjcm9sbE5vZGUgaWYgdGhlIHBvaW50ZXIgaXMgbmVhciB0byBpdC5cbiAqIFRoaXMgb2JzZXJ2YWJsZSBkb2Vzbid0IGVtaXQsIGl0IGp1c3QgcGVyZm9ybXMgYSAnc2Nyb2xsJyBzaWRlIGVmZmVjdC5cbiAqIEBwYXJhbSBzY3JvbGxhYmxlUGFyZW50LCBwYXJlbnQgbm9kZSBpbiB3aGljaCB0aGUgc2Nyb2xsIHdvdWxkIGJlIHBlcmZvcm1lZC5cbiAqIEBwYXJhbSBvcHRpb25zLCBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gKi9cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzb25hcmpzL2NvZ25pdGl2ZS1jb21wbGV4aXR5XG5leHBvcnQgZnVuY3Rpb24gc2Nyb2xsSWZOZWFyRWxlbWVudENsaWVudFJlY3QkKFxuICBzY3JvbGxhYmxlUGFyZW50OiBFbGVtZW50IHwgRG9jdW1lbnQsXG4gIG9wdGlvbnM/OiBTY3JvbGxJZk5lYXJFbGVtZW50T3B0aW9ucyxcbik6IChcbiAgc291cmNlJDogT2JzZXJ2YWJsZTx7IHBvaW50ZXJYOiBudW1iZXI7IHBvaW50ZXJZOiBudW1iZXIgfT4sXG4pID0+IE9ic2VydmFibGU8YW55PiB7XG4gIGxldCBzY3JvbGxOb2RlOiBXaW5kb3cgfCBIVE1MRWxlbWVudDtcbiAgbGV0IHNjcm9sbGFibGVQYXJlbnRDbGllbnRSZWN0OiBHcmlkSXRlbUNsaWVudFJlY3Q7XG4gIGxldCBzY3JvbGxhYmxlUGFyZW50U2Nyb2xsV2lkdGg6IG51bWJlcjtcblxuICBpZiAoc2Nyb2xsYWJsZVBhcmVudCA9PT0gZG9jdW1lbnQpIHtcbiAgICBzY3JvbGxOb2RlID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcgYXMgV2luZG93O1xuICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gZ2V0Vmlld3BvcnRTaXplKCk7XG4gICAgc2Nyb2xsYWJsZVBhcmVudENsaWVudFJlY3QgPSB7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRvcDogMCxcbiAgICAgIHJpZ2h0OiB3aWR0aCxcbiAgICAgIGJvdHRvbTogaGVpZ2h0LFxuICAgICAgbGVmdDogMCxcbiAgICB9O1xuICAgIHNjcm9sbGFibGVQYXJlbnRTY3JvbGxXaWR0aCA9IGdldERvY3VtZW50U2Nyb2xsV2lkdGgoKTtcbiAgfSBlbHNlIHtcbiAgICBzY3JvbGxOb2RlID0gc2Nyb2xsYWJsZVBhcmVudCBhcyBIVE1MRWxlbWVudDtcbiAgICBzY3JvbGxhYmxlUGFyZW50Q2xpZW50UmVjdCA9IGdldENsaWVudFJlY3RTbmFwc2hvdChcbiAgICAgIHNjcm9sbGFibGVQYXJlbnQgYXMgSFRNTEVsZW1lbnQsXG4gICAgKTtcbiAgICBzY3JvbGxhYmxlUGFyZW50U2Nyb2xsV2lkdGggPSAoc2Nyb2xsYWJsZVBhcmVudCBhcyBIVE1MRWxlbWVudCkuc2Nyb2xsV2lkdGg7XG4gIH1cblxuICAvKipcbiAgICogSU1QT1JUQU5UOiBCeSBkZXNpZ24sIG9ubHkgbGV0IHNjcm9sbCBob3Jpem9udGFsIGlmIHRoZSBzY3JvbGxhYmxlIHBhcmVudCBoYXMgZXhwbGljaXRseSBhbiBzY3JvbGwgaG9yaXpvbnRhbC5cbiAgICogVGhpcyBsYXlvdXQgc29sdXRpb24gaXMgbm90IGRlc2lnbmVkIGluIG1pbmQgdG8gaGF2ZSBhbnkgc2Nyb2xsIGhvcml6b250YWwsIGJ1dCBleGNlcHRpb25hbGx5IHdlIGFsbG93IGl0IGluIHRoaXNcbiAgICogc3BlY2lmaWMgdXNlIGNhc2UuXG4gICAqL1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgaWYgKFxuICAgIG9wdGlvbnMuZGlzYWJsZUhvcml6b250YWwgPT0gbnVsbCAmJlxuICAgIHNjcm9sbGFibGVQYXJlbnRTY3JvbGxXaWR0aCA8PSBzY3JvbGxhYmxlUGFyZW50Q2xpZW50UmVjdC53aWR0aFxuICApIHtcbiAgICBvcHRpb25zLmRpc2FibGVIb3Jpem9udGFsID0gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBzb3VyY2UkID0+XG4gICAgc291cmNlJC5waXBlKFxuICAgICAgbWFwKCh7IHBvaW50ZXJYLCBwb2ludGVyWSB9KSA9PiB7XG4gICAgICAgIGxldCB2ZXJ0aWNhbFNjcm9sbERpcmVjdGlvbiA9IGdldFZlcnRpY2FsU2Nyb2xsRGlyZWN0aW9uKFxuICAgICAgICAgIHNjcm9sbGFibGVQYXJlbnRDbGllbnRSZWN0LFxuICAgICAgICAgIHBvaW50ZXJZLFxuICAgICAgICApO1xuICAgICAgICBsZXQgaG9yaXpvbnRhbFNjcm9sbERpcmVjdGlvbiA9IGdldEhvcml6b250YWxTY3JvbGxEaXJlY3Rpb24oXG4gICAgICAgICAgc2Nyb2xsYWJsZVBhcmVudENsaWVudFJlY3QsXG4gICAgICAgICAgcG9pbnRlclgsXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgc2Nyb2xsIGRpcmVjdGlvbnMgYXJlIGRpc2FibGVkLlxuICAgICAgICBpZiAob3B0aW9ucz8uZGlzYWJsZVZlcnRpY2FsKSB7XG4gICAgICAgICAgdmVydGljYWxTY3JvbGxEaXJlY3Rpb24gPSBBdXRvU2Nyb2xsVmVydGljYWxEaXJlY3Rpb24uTk9ORTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucz8uZGlzYWJsZUhvcml6b250YWwpIHtcbiAgICAgICAgICBob3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uID0gQXV0b1Njcm9sbEhvcml6b250YWxEaXJlY3Rpb24uTk9ORTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IHZlcnRpY2FsU2Nyb2xsRGlyZWN0aW9uLCBob3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uIH07XG4gICAgICB9KSxcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKFxuICAgICAgICAocHJldiwgYWN0dWFsKSA9PlxuICAgICAgICAgIHByZXYudmVydGljYWxTY3JvbGxEaXJlY3Rpb24gPT09IGFjdHVhbC52ZXJ0aWNhbFNjcm9sbERpcmVjdGlvbiAmJlxuICAgICAgICAgIHByZXYuaG9yaXpvbnRhbFNjcm9sbERpcmVjdGlvbiA9PT0gYWN0dWFsLmhvcml6b250YWxTY3JvbGxEaXJlY3Rpb24sXG4gICAgICApLFxuICAgICAgc3dpdGNoTWFwKCh7IHZlcnRpY2FsU2Nyb2xsRGlyZWN0aW9uLCBob3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uIH0pID0+IHtcbiAgICAgICAgaWYgKHZlcnRpY2FsU2Nyb2xsRGlyZWN0aW9uIHx8IGhvcml6b250YWxTY3JvbGxEaXJlY3Rpb24pIHtcbiAgICAgICAgICByZXR1cm4gc2Nyb2xsVG9EaXJlY3Rpb25JbnRlcnZhbCQoXG4gICAgICAgICAgICBzY3JvbGxOb2RlLFxuICAgICAgICAgICAgdmVydGljYWxTY3JvbGxEaXJlY3Rpb24sXG4gICAgICAgICAgICBob3Jpem9udGFsU2Nyb2xsRGlyZWN0aW9uLFxuICAgICAgICAgICAgb3B0aW9ucz8uc2Nyb2xsU3RlcCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBORVZFUjtcbiAgICAgIH0pLFxuICAgICk7XG59XG5cbi8qKlxuICogRW1pdHMgb24gRVZFUlkgc2Nyb2xsIGV2ZW50IGFuZCByZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCBzY3JvbGwgb2Zmc2V0IHJlbGF0aXZlIHRvIHRoZSBpbml0aWFsIHNjcm9sbCBwb3NpdGlvbi5cbiAqIEBwYXJhbSBzY3JvbGxhYmxlUGFyZW50LCBub2RlIGluIHdoaWNoIHNjcm9sbCBldmVudHMgd291bGQgYmUgbGlzdGVuZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTY3JvbGxUb3RhbFJlbGF0aXZlRGlmZmVyZW5jZSQoXG4gIHNjcm9sbGFibGVQYXJlbnQ6IEVsZW1lbnQgfCBEb2N1bWVudCxcbik6IE9ic2VydmFibGU8eyB0b3A6IG51bWJlcjsgbGVmdDogbnVtYmVyIH0+IHtcbiAgY29uc3Qgc2Nyb2xsSW5pdGlhbFBvc2l0aW9uID1cbiAgICBzY3JvbGxhYmxlUGFyZW50ID09PSBkb2N1bWVudFxuICAgICAgPyBnZXRWaWV3cG9ydFNjcm9sbFBvc2l0aW9uKClcbiAgICAgIDoge1xuICAgICAgICAgIHRvcDogKHNjcm9sbGFibGVQYXJlbnQgYXMgSFRNTEVsZW1lbnQpLnNjcm9sbFRvcCxcbiAgICAgICAgICBsZWZ0OiAoc2Nyb2xsYWJsZVBhcmVudCBhcyBIVE1MRWxlbWVudCkuc2Nyb2xsTGVmdCxcbiAgICAgICAgfTtcbiAgcmV0dXJuIGZyb21FdmVudChzY3JvbGxhYmxlUGFyZW50LCAnc2Nyb2xsJywge1xuICAgIGNhcHR1cmU6IHRydWUsXG4gIH0pLnBpcGUoXG4gICAgbWFwKCgpID0+IHtcbiAgICAgIGxldCBuZXdUb3A6IG51bWJlcjtcbiAgICAgIGxldCBuZXdMZWZ0OiBudW1iZXI7XG5cbiAgICAgIGlmIChzY3JvbGxhYmxlUGFyZW50ID09PSBkb2N1bWVudCkge1xuICAgICAgICBjb25zdCB2aWV3cG9ydFNjcm9sbFBvc2l0aW9uID0gZ2V0Vmlld3BvcnRTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICBuZXdUb3AgPSB2aWV3cG9ydFNjcm9sbFBvc2l0aW9uLnRvcDtcbiAgICAgICAgbmV3TGVmdCA9IHZpZXdwb3J0U2Nyb2xsUG9zaXRpb24ubGVmdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld1RvcCA9IChzY3JvbGxhYmxlUGFyZW50IGFzIEhUTUxFbGVtZW50KS5zY3JvbGxUb3A7XG4gICAgICAgIG5ld0xlZnQgPSAoc2Nyb2xsYWJsZVBhcmVudCBhcyBIVE1MRWxlbWVudCkuc2Nyb2xsTGVmdDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdG9wRGlmZmVyZW5jZSA9IHNjcm9sbEluaXRpYWxQb3NpdGlvbi50b3AgLSBuZXdUb3A7XG4gICAgICBjb25zdCBsZWZ0RGlmZmVyZW5jZSA9IHNjcm9sbEluaXRpYWxQb3NpdGlvbi5sZWZ0IC0gbmV3TGVmdDtcblxuICAgICAgcmV0dXJuIHsgdG9wOiB0b3BEaWZmZXJlbmNlLCBsZWZ0OiBsZWZ0RGlmZmVyZW5jZSB9O1xuICAgIH0pLFxuICApO1xufVxuXG4vKiogUmV0dXJucyB0aGUgdmlld3BvcnQncyB3aWR0aCBhbmQgaGVpZ2h0LiAqL1xuZnVuY3Rpb24gZ2V0Vmlld3BvcnRTaXplKCk6IHsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSB7XG4gIGNvbnN0IF93aW5kb3cgPSBkb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3c7XG4gIHJldHVybiB7XG4gICAgd2lkdGg6IF93aW5kb3cuaW5uZXJXaWR0aCxcbiAgICBoZWlnaHQ6IF93aW5kb3cuaW5uZXJIZWlnaHQsXG4gIH07XG59XG5cbi8qKiBHZXRzIHRoZSAodG9wLCBsZWZ0KSBzY3JvbGwgcG9zaXRpb24gb2YgdGhlIHZpZXdwb3J0LiAqL1xuZnVuY3Rpb24gZ2V0Vmlld3BvcnRTY3JvbGxQb3NpdGlvbigpOiB7IHRvcDogbnVtYmVyOyBsZWZ0OiBudW1iZXIgfSB7XG4gIGNvbnN0IHdpbmRvd1JlZiA9IGRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdztcbiAgY29uc3QgZG9jdW1lbnRFbGVtZW50ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICBjb25zdCBkb2N1bWVudFJlY3QgPSBkb2N1bWVudEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgY29uc3QgdG9wID1cbiAgICAtZG9jdW1lbnRSZWN0LnRvcCB8fFxuICAgIGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIHx8XG4gICAgd2luZG93UmVmLnNjcm9sbFkgfHxcbiAgICBkb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8XG4gICAgMDtcblxuICBjb25zdCBsZWZ0ID1cbiAgICAtZG9jdW1lbnRSZWN0LmxlZnQgfHxcbiAgICBkb2N1bWVudC5ib2R5LnNjcm9sbExlZnQgfHxcbiAgICB3aW5kb3dSZWYuc2Nyb2xsWCB8fFxuICAgIGRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8XG4gICAgMDtcblxuICByZXR1cm4geyB0b3AsIGxlZnQgfTtcbn1cblxuLyoqIFJldHVybnMgdGhlIGRvY3VtZW50IHNjcm9sbCB3aWR0aCAqL1xuZnVuY3Rpb24gZ2V0RG9jdW1lbnRTY3JvbGxXaWR0aCgpIHtcbiAgcmV0dXJuIE1hdGgubWF4KFxuICAgIGRvY3VtZW50LmJvZHkuc2Nyb2xsV2lkdGgsXG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFdpZHRoLFxuICApO1xufVxuIl19