UNPKG

@tots/ngx-drag-scroll

Version:

Lightweight drag to scroll library for Angular

695 lines 94.3 kB
import { ElementRef, Component, Renderer2, Input, Output, EventEmitter, ViewChild, ContentChildren, QueryList, Inject, HostBinding, HostListener } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { DragScrollItemDirective } from './ngx-drag-scroll-item'; import * as i0 from "@angular/core"; export class DragScrollComponent { constructor(_elementRef, _renderer, _document) { this._elementRef = _elementRef; this._renderer = _renderer; this._document = _document; this._index = 0; this._scrollbarHidden = false; this._disabled = false; this._xDisabled = false; this._xWheelEnabled = false; this._yDisabled = false; this._dragDisabled = false; this._snapDisabled = false; this._snapOffset = 0; this._snapDuration = 500; this._isDragging = false; /** * Is the user currently pressing the element */ this.isPressed = false; /** * Is the user currently scrolling the element */ this.isScrolling = false; this.scrollTimer = -1; this.scrollToTimer = -1; /** * The x coordinates on the element */ this.downX = 0; /** * The y coordinates on the element */ this.downY = 0; this.displayType = 'block'; this.elWidth = null; this.elHeight = null; this._pointerEvents = 'auto'; this.scrollbarWidth = null; this.isAnimating = false; this.prevChildrenLength = 0; this.indexBound = 0; this.rtl = false; this.dsInitialized = new EventEmitter(); this.indexChanged = new EventEmitter(); this.reachesLeftBound = new EventEmitter(); this.reachesRightBound = new EventEmitter(); this.snapAnimationFinished = new EventEmitter(); this.dragStart = new EventEmitter(); this.dragEnd = new EventEmitter(); this.scrollbarWidth = `${this.getScrollbarWidth()}px`; } /** * Is the user currently dragging the element */ get isDragging() { return this._isDragging; } get currIndex() { return this._index; } set currIndex(value) { if (value !== this._index) { this._index = value; this.indexChanged.emit(value); } } /** * Whether the scrollbar is hidden */ get scrollbarHidden() { return this._scrollbarHidden; } set scrollbarHidden(value) { this._scrollbarHidden = value; } /** * Whether horizontally and vertically draging and scrolling is be disabled */ get disabled() { return this._disabled; } set disabled(value) { this._disabled = value; } /** * Whether horizontally dragging and scrolling is be disabled */ get xDisabled() { return this._xDisabled; } set xDisabled(value) { this._xDisabled = value; } /** * Whether vertically dragging and scrolling events is disabled */ get yDisabled() { return this._yDisabled; } set yDisabled(value) { this._yDisabled = value; } /** * Whether scrolling horizontally with mouse wheel is enabled */ get xWheelEnabled() { return this._xWheelEnabled; } set xWheelEnabled(value) { this._xWheelEnabled = value; } get dragDisabled() { return this._dragDisabled; } set dragDisabled(value) { this._dragDisabled = value; } get snapDisabled() { return this._snapDisabled; } set snapDisabled(value) { this._snapDisabled = value; } get snapOffset() { return this._snapOffset; } set snapOffset(value) { this._snapOffset = value; } get snapDuration() { return this._snapDuration; } set snapDuration(value) { this._snapDuration = value; } ngOnChanges() { this.setScrollBar(); if (this.xDisabled || this.disabled || this._scrollbarHidden) { this.disableScroll('x'); } else { this.enableScroll('x'); } if (this.yDisabled || this.disabled) { this.disableScroll('y'); } else { this.enableScroll('y'); } } ngAfterViewInit() { // auto assign computed css this._renderer.setAttribute(this._contentRef.nativeElement, 'drag-scroll', 'true'); this.displayType = typeof window !== 'undefined' ? window.getComputedStyle(this._elementRef.nativeElement).display : 'block'; this._renderer.setStyle(this._contentRef.nativeElement, 'display', this.displayType); this._renderer.setStyle(this._contentRef.nativeElement, 'whiteSpace', 'noWrap'); // store ele width height for later user this.markElDimension(); this._renderer.setStyle(this._contentRef.nativeElement, 'width', this.elWidth); this._renderer.setStyle(this._contentRef.nativeElement, 'height', this.elHeight); if (this.wrapper) { this.checkScrollbar(); } this._onMouseDownListener = this._renderer.listen(this._contentRef.nativeElement, 'mousedown', this.onMouseDownHandler.bind(this)); this._onScrollListener = this._renderer.listen(this._contentRef.nativeElement, 'scroll', this.onScrollHandler.bind(this)); // prevent Firefox from dragging images this._onDragStartListener = this._renderer.listen(this._contentRef.nativeElement, 'dragstart', (e) => { e.preventDefault(); }); this.checkNavStatus(); this.dsInitialized.emit(); this.adjustMarginToLastChild(); this.rtl = getComputedStyle(this._contentRef.nativeElement).getPropertyValue('direction') === 'rtl'; } ngAfterViewChecked() { // avoid extra checks if (this._children.length !== this.prevChildrenLength) { this.markElDimension(); this.checkScrollbar(); this.prevChildrenLength = this._children.length; this.checkNavStatus(); } } ngOnDestroy() { this._renderer.setAttribute(this._contentRef.nativeElement, 'drag-scroll', 'false'); if (this._onMouseDownListener) { this._onMouseDownListener = this._onMouseDownListener(); } if (this._onScrollListener) { this._onScrollListener = this._onScrollListener(); } if (this._onDragStartListener) { this._onDragStartListener = this._onDragStartListener(); } } onMouseMoveHandler(event) { this.onMouseMove(event); } onMouseMove(event) { if (event.clientX === this.downX && event.clientY === this.downY) { // Ignore 'mousemove" event triggered at the same coordinates that the last mousedown event (consequence of window resize) return; } if (this.isPressed && !this.disabled) { // Workaround for prevent scroll stuck if browser lost focus // MouseEvent.buttons not support by Safari // eslint-disable-next-line import/no-deprecated if (!event.buttons && !event.which) { return this.onMouseUpHandler(event); } this._pointerEvents = 'none'; this._setIsDragging(true); // Drag X if (!this.xDisabled && !this.dragDisabled) { const clientX = event.clientX; this._contentRef.nativeElement.scrollLeft = this._contentRef.nativeElement.scrollLeft - clientX + this.downX; this.downX = clientX; } // Drag Y if (!this.yDisabled && !this.dragDisabled) { const clientY = event.clientY; this._contentRef.nativeElement.scrollTop = this._contentRef.nativeElement.scrollTop - clientY + this.downY; this.downY = clientY; } } } onMouseDownHandler(event) { const dragScrollItem = this.locateDragScrollItem(event.target); if (dragScrollItem && dragScrollItem.dragDisabled) { return; } const isTouchEvent = event.type === 'touchstart'; this._startGlobalListening(isTouchEvent); this.isPressed = true; const mouseEvent = event; this.downX = mouseEvent.clientX; this.downY = mouseEvent.clientY; clearTimeout(this.scrollToTimer); } onScrollHandler() { this.checkNavStatus(); if (!this.isPressed && !this.isAnimating && !this.snapDisabled) { this.isScrolling = true; clearTimeout(this.scrollTimer); this.scrollTimer = setTimeout(() => { this.isScrolling = false; this.locateCurrentIndex(true); }, 500); } else { this.locateCurrentIndex(); } } onMouseUpHandler(event) { if (this.isPressed) { this.isPressed = false; this._pointerEvents = 'auto'; this._setIsDragging(false); if (!this.snapDisabled) { this.locateCurrentIndex(true); } else { this.locateCurrentIndex(); } this._stopGlobalListening(); } } /* * Nav button */ moveLeft() { if ((this.currIndex !== 0 || this.snapDisabled)) { this.currIndex--; clearTimeout(this.scrollToTimer); this.scrollTo(this._contentRef.nativeElement, this.toChildrenLocation(), this.snapDuration); } } moveRight() { const container = this.wrapper || this.parentNode; const containerWidth = container ? container.clientWidth : 0; if (!this.isScrollReachesRightEnd() && this.currIndex < this.maximumIndex(containerWidth, this._children.toArray())) { this.currIndex++; clearTimeout(this.scrollToTimer); this.scrollTo(this._contentRef.nativeElement, this.toChildrenLocation(), this.snapDuration); } } moveTo(index) { const container = this.wrapper || this.parentNode; const containerWidth = container ? container.clientWidth : 0; if (index >= 0 && index !== this.currIndex && this.currIndex <= this.maximumIndex(containerWidth, this._children.toArray())) { this.currIndex = Math.min(index, this.maximumIndex(containerWidth, this._children.toArray())); clearTimeout(this.scrollToTimer); this.scrollTo(this._contentRef.nativeElement, this.toChildrenLocation(), this.snapDuration); } } checkNavStatus() { setTimeout(() => { const onlyOneItem = Boolean(this._children.length <= 1); const containerIsLargerThanContent = Boolean(this._contentRef.nativeElement.scrollWidth <= this._contentRef.nativeElement.clientWidth); if (onlyOneItem || containerIsLargerThanContent) { // only one element this.reachesLeftBound.emit(true); this.reachesRightBound.emit(true); } else if (this.isScrollReachesRightEnd()) { // reached right end this.reachesLeftBound.emit(false); this.reachesRightBound.emit(true); } else if (this._contentRef.nativeElement.scrollLeft === 0 && this._contentRef.nativeElement.scrollWidth > this._contentRef.nativeElement.clientWidth) { // reached left end this.reachesLeftBound.emit(true); this.reachesRightBound.emit(false); } else { // in the middle this.reachesLeftBound.emit(false); this.reachesRightBound.emit(false); } }, 0); } onWheel(event) { if (this._xWheelEnabled) { event.preventDefault(); if (this._snapDisabled) { this._contentRef.nativeElement.scrollBy(event.deltaY, 0); } else { if (event.deltaY < 0) { this.moveLeft(); } else if (event.deltaY > 0) { this.moveRight(); } } } } onWindowResize() { this.refreshWrapperDimensions(); this.checkNavStatus(); } _setIsDragging(value) { if (this._isDragging === value) { return; } this._isDragging = value; value ? this.dragStart.emit() : this.dragEnd.emit(); } _startGlobalListening(isTouchEvent) { if (!this._onMouseMoveListener) { const eventName = isTouchEvent ? 'touchmove' : 'mousemove'; this._onMouseMoveListener = this._renderer.listen('document', eventName, this.onMouseMoveHandler.bind(this)); } if (!this._onMouseUpListener) { const eventName = isTouchEvent ? 'touchend' : 'mouseup'; this._onMouseUpListener = this._renderer.listen('document', eventName, this.onMouseUpHandler.bind(this)); } } _stopGlobalListening() { if (this._onMouseMoveListener) { this._onMouseMoveListener = this._onMouseMoveListener(); } if (this._onMouseUpListener) { this._onMouseUpListener = this._onMouseUpListener(); } } disableScroll(axis) { this._renderer.setStyle(this._contentRef.nativeElement, `overflow-${axis}`, 'hidden'); } enableScroll(axis) { this._renderer.setStyle(this._contentRef.nativeElement, `overflow-${axis}`, 'auto'); } hideScrollbar() { if (this._contentRef.nativeElement.style.display !== 'none' && !this.wrapper) { this.parentNode = this._contentRef.nativeElement.parentNode; // create container element this.wrapper = this._renderer.createElement('div'); this._renderer.setAttribute(this.wrapper, 'class', 'drag-scroll-wrapper'); this._renderer.addClass(this.wrapper, 'drag-scroll-container'); this.refreshWrapperDimensions(); this._renderer.setStyle(this.wrapper, 'overflow', 'hidden'); this._renderer.setStyle(this._contentRef.nativeElement, 'width', `calc(100% + ${this.scrollbarWidth})`); this._renderer.setStyle(this._contentRef.nativeElement, 'height', `calc(100% + ${this.scrollbarWidth})`); // Append container element to component element. this._renderer.appendChild(this._elementRef.nativeElement, this.wrapper); // Append content element to container element. this._renderer.appendChild(this.wrapper, this._contentRef.nativeElement); this.adjustMarginToLastChild(); } } showScrollbar() { if (this.wrapper) { this._renderer.setStyle(this._contentRef.nativeElement, 'width', '100%'); this._renderer.setStyle(this._contentRef.nativeElement, 'height', this.wrapper.style.height); if (this.parentNode !== null) { this.parentNode.removeChild(this.wrapper); this.parentNode.appendChild(this._contentRef.nativeElement); } this.wrapper = null; this.adjustMarginToLastChild(); } } checkScrollbar() { if (this._contentRef.nativeElement.scrollWidth <= this._contentRef.nativeElement.clientWidth) { this._renderer.setStyle(this._contentRef.nativeElement, 'height', '100%'); } else { this._renderer.setStyle(this._contentRef.nativeElement, 'height', `calc(100% + ${this.scrollbarWidth})`); } if (this._contentRef.nativeElement.scrollHeight <= this._contentRef.nativeElement.clientHeight) { this._renderer.setStyle(this._contentRef.nativeElement, 'width', '100%'); } else { this._renderer.setStyle(this._contentRef.nativeElement, 'width', `calc(100% + ${this.scrollbarWidth})`); } } setScrollBar() { if (this.scrollbarHidden) { this.hideScrollbar(); } else { this.showScrollbar(); } } getScrollbarWidth() { /** * Browser Scrollbar Widths (2016) * OSX (Chrome, Safari, Firefox) - 15px * Windows XP (IE7, Chrome, Firefox) - 17px * Windows 7 (IE10, IE11, Chrome, Firefox) - 17px * Windows 8.1 (IE11, Chrome, Firefox) - 17px * Windows 10 (IE11, Chrome, Firefox) - 17px * Windows 10 (Edge 12/13) - 12px */ const outer = this._renderer.createElement('div'); this._renderer.setStyle(outer, 'visibility', 'hidden'); this._renderer.setStyle(outer, 'width', '100px'); this._renderer.setStyle(outer, 'msOverflowStyle', 'scrollbar'); // needed for WinJS apps // document.body.appendChild(outer); this._renderer.appendChild(this._document.body, outer); // this._renderer.appendChild(this._renderer.selectRootElement('body'), outer); const widthNoScroll = outer.offsetWidth; // force scrollbars this._renderer.setStyle(outer, 'overflow', 'scroll'); // add innerdiv const inner = this._renderer.createElement('div'); this._renderer.setStyle(inner, 'width', '100%'); this._renderer.appendChild(outer, inner); const widthWithScroll = inner.offsetWidth; // remove divs this._renderer.removeChild(this._document.body, outer); /** * Scrollbar width will be 0 on Mac OS with the * default "Only show scrollbars when scrolling" setting (Yosemite and up). * setting default width to 20; */ return widthNoScroll - widthWithScroll || 20; } refreshWrapperDimensions() { if (this.wrapper) { this._renderer.setStyle(this.wrapper, 'width', '100%'); if (this._elementRef.nativeElement.style.height > 0 || this._elementRef.nativeElement.offsetHeight > 0) { this._renderer.setStyle(this.wrapper, 'height', this._elementRef.nativeElement.style.height || this._elementRef.nativeElement.offsetHeight + 'px'); } else { this._renderer.setStyle(this.wrapper, 'height', '100%'); } } } /* * The below solution is heavily inspired from * https://gist.github.com/andjosh/6764939 */ scrollTo(element, to, duration) { const self = this; self.isAnimating = true; const rtlFactor = this.rtl ? -1 : 1; const start = element.scrollLeft, change = (rtlFactor * to) - start - this.snapOffset, increment = 20; let currentTime = 0; // t = current time // b = start value // c = change in value // d = duration const easeInOutQuad = function (t, b, c, d) { t /= d / 2; if (t < 1) { return c / 2 * t * t + b; } t--; return -c / 2 * (t * (t - 2) - 1) + b; }; const animateScroll = function () { currentTime += increment; element.scrollLeft = easeInOutQuad(currentTime, start, change, duration); if (currentTime < duration) { self.scrollToTimer = setTimeout(animateScroll, increment); } else { // run one more frame to make sure the animation is fully finished setTimeout(() => { self.isAnimating = false; self.snapAnimationFinished.emit(self.currIndex); }, increment); } }; animateScroll(); } locateCurrentIndex(snap) { const scrollLeft = Math.abs(this._contentRef.nativeElement.scrollLeft); this.currentChildWidth((currentChildWidth, nextChildrenWidth, childrenWidth, idx, stop) => { if ((scrollLeft >= childrenWidth && scrollLeft <= nextChildrenWidth)) { if (nextChildrenWidth - scrollLeft > currentChildWidth / 2 && !this.isScrollReachesRightEnd()) { // roll back scrolling if (!this.isAnimating) { this.currIndex = idx; } if (snap) { this.scrollTo(this._contentRef.nativeElement, childrenWidth, this.snapDuration); } } else if (scrollLeft !== 0) { // forward scrolling if (!this.isAnimating) { this.currIndex = idx + 1; } if (snap) { this.scrollTo(this._contentRef.nativeElement, childrenWidth + currentChildWidth, this.snapDuration); } } stop(); } else if ((idx + 1) === (this._children.length - 1)) { // reaches last index if (!this.isAnimating) { this.currIndex = idx + 1; } stop(); } }); } currentChildWidth(cb) { let childrenWidth = 0; let shouldBreak = false; const breakFunc = function () { shouldBreak = true; }; const childrenArr = this._children.toArray(); for (let i = 0; i < childrenArr.length; i++) { if (i === childrenArr.length - 1) { break; } if (shouldBreak) { break; } const nextChildrenWidth = childrenWidth + childrenArr[i + 1]._elementRef.nativeElement.clientWidth; const currentClildWidth = childrenArr[i]._elementRef.nativeElement.clientWidth; cb(currentClildWidth, nextChildrenWidth, childrenWidth, i, breakFunc); childrenWidth += currentClildWidth; } } toChildrenLocation() { let to = 0; const childrenArr = this._children.toArray(); for (let i = 0; i < this.currIndex; i++) { to += childrenArr[i]._elementRef.nativeElement.clientWidth; } return to; } locateDragScrollItem(element) { let item = null; const childrenArr = this._children.toArray(); for (let i = 0; i < childrenArr.length; i++) { if (element === childrenArr[i]._elementRef.nativeElement) { item = childrenArr[i]; } } return item; } markElDimension() { if (this.wrapper) { this.elWidth = this.wrapper.style.width; this.elHeight = this.wrapper.style.height; } else { this.elWidth = this._elementRef.nativeElement.style.width || (this._elementRef.nativeElement.offsetWidth + 'px'); this.elHeight = this._elementRef.nativeElement.style.height || (this._elementRef.nativeElement.offsetHeight + 'px'); } const container = this.wrapper || this.parentNode; const containerWidth = container ? container.clientWidth : 0; if (this._children.length > 1) { this.indexBound = this.maximumIndex(containerWidth, this._children.toArray()); } } maximumIndex(containerWidth, childrenElements) { let count = 0; let childrenWidth = 0; for (let i = 0; i <= childrenElements.length; i++) { // last N element const dragScrollItemDirective = childrenElements[childrenElements.length - 1 - i]; if (!dragScrollItemDirective) { break; } else { const nativeElement = dragScrollItemDirective._elementRef.nativeElement; let itemWidth = nativeElement.clientWidth; if (itemWidth === 0 && nativeElement.firstElementChild) { itemWidth = dragScrollItemDirective._elementRef.nativeElement.firstElementChild.clientWidth; } childrenWidth += itemWidth; if (childrenWidth < containerWidth) { count++; } else { break; } } } return childrenElements.length - count; } isScrollReachesRightEnd() { const scrollLeftPos = Math.abs(this._contentRef.nativeElement.scrollLeft) + this._contentRef.nativeElement.offsetWidth; return scrollLeftPos >= this._contentRef.nativeElement.scrollWidth; } /** * adds a margin right style to the last child element which will resolve the issue * of last item gets cutoff. */ adjustMarginToLastChild() { if (this._children && this._children.length > 0 && this.hideScrollbar) { const childrenArr = this._children.toArray(); const lastItem = childrenArr[childrenArr.length - 1]._elementRef.nativeElement; if (this.wrapper && childrenArr.length > 1) { this._renderer.setStyle(lastItem, 'margin-right', this.scrollbarWidth); } else { this._renderer.setStyle(lastItem, 'margin-right', 0); } } } } DragScrollComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: DragScrollComponent, deps: [{ token: ElementRef }, { token: Renderer2 }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); DragScrollComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: DragScrollComponent, selector: "drag-scroll", inputs: { scrollbarHidden: ["scrollbar-hidden", "scrollbarHidden"], disabled: ["drag-scroll-disabled", "disabled"], xDisabled: ["drag-scroll-x-disabled", "xDisabled"], yDisabled: ["drag-scroll-y-disabled", "yDisabled"], xWheelEnabled: ["scroll-x-wheel-enabled", "xWheelEnabled"], dragDisabled: ["drag-disabled", "dragDisabled"], snapDisabled: ["snap-disabled", "snapDisabled"], snapOffset: ["snap-offset", "snapOffset"], snapDuration: ["snap-duration", "snapDuration"] }, outputs: { dsInitialized: "dsInitialized", indexChanged: "indexChanged", reachesLeftBound: "reachesLeftBound", reachesRightBound: "reachesRightBound", snapAnimationFinished: "snapAnimationFinished", dragStart: "dragStart", dragEnd: "dragEnd" }, host: { listeners: { "wheel": "onWheel($event)", "window:resize": "onWindowResize()" }, properties: { "style.pointer-events": "this._pointerEvents" } }, queries: [{ propertyName: "_children", predicate: DragScrollItemDirective, descendants: true }], viewQueries: [{ propertyName: "_contentRef", first: true, predicate: ["contentRef"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: ` <div class="drag-scroll-content" #contentRef> <ng-content></ng-content> </div> `, isInline: true, styles: [":host{overflow:hidden;display:block}.drag-scroll-content{height:100%;overflow:auto;white-space:nowrap}\n"] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: DragScrollComponent, decorators: [{ type: Component, args: [{ selector: 'drag-scroll', template: ` <div class="drag-scroll-content" #contentRef> <ng-content></ng-content> </div> `, styles: [":host{overflow:hidden;display:block}.drag-scroll-content{height:100%;overflow:auto;white-space:nowrap}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef, decorators: [{ type: Inject, args: [ElementRef] }] }, { type: i0.Renderer2, decorators: [{ type: Inject, args: [Renderer2] }] }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }]; }, propDecorators: { _contentRef: [{ type: ViewChild, args: ['contentRef', { static: true }] }], _children: [{ type: ContentChildren, args: [DragScrollItemDirective, { descendants: true }] }], _pointerEvents: [{ type: HostBinding, args: ['style.pointer-events'] }], dsInitialized: [{ type: Output }], indexChanged: [{ type: Output }], reachesLeftBound: [{ type: Output }], reachesRightBound: [{ type: Output }], snapAnimationFinished: [{ type: Output }], dragStart: [{ type: Output }], dragEnd: [{ type: Output }], scrollbarHidden: [{ type: Input, args: ['scrollbar-hidden'] }], disabled: [{ type: Input, args: ['drag-scroll-disabled'] }], xDisabled: [{ type: Input, args: ['drag-scroll-x-disabled'] }], yDisabled: [{ type: Input, args: ['drag-scroll-y-disabled'] }], xWheelEnabled: [{ type: Input, args: ['scroll-x-wheel-enabled'] }], dragDisabled: [{ type: Input, args: ['drag-disabled'] }], snapDisabled: [{ type: Input, args: ['snap-disabled'] }], snapOffset: [{ type: Input, args: ['snap-offset'] }], snapDuration: [{ type: Input, args: ['snap-duration'] }], onWheel: [{ type: HostListener, args: ['wheel', ['$event']] }], onWindowResize: [{ type: HostListener, args: ['window:resize'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWRyYWctc2Nyb2xsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kcmFnLXNjcm9sbC9zcmMvbGliL25neC1kcmFnLXNjcm9sbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFVBQVUsRUFDVixTQUFTLEVBQ1QsU0FBUyxFQUVULEtBQUssRUFDTCxNQUFNLEVBR04sWUFBWSxFQUNaLFNBQVMsRUFDVCxlQUFlLEVBRWYsU0FBUyxFQUNULE1BQU0sRUFDTixXQUFXLEVBQ1gsWUFBWSxFQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7QUFxQmpFLE1BQU0sT0FBTyxtQkFBbUI7SUEwSzlCLFlBQzhCLFdBQXVCLEVBQ3hCLFNBQW9CLEVBQ3JCLFNBQWM7UUFGWixnQkFBVyxHQUFYLFdBQVcsQ0FBWTtRQUN4QixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3JCLGNBQVMsR0FBVCxTQUFTLENBQUs7UUE1S2xDLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFFWCxxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFFekIsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUVsQixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBRW5CLG1CQUFjLEdBQUcsS0FBSyxDQUFDO1FBRXZCLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFFbkIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFFdEIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFFdEIsZ0JBQVcsR0FBRyxDQUFDLENBQUM7UUFFaEIsa0JBQWEsR0FBRyxHQUFHLENBQUM7UUFFcEIsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFZNUI7O1dBRUc7UUFDSCxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBRWxCOztX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