angular2-draggable
Version:
<!-- Badges section here. --> [][npm-badge-url] [][npm-badge-url] [ {
this.el = el;
this.renderer = renderer;
this._resizable = true;
this._handles = {};
this._handleType = [];
this._handleResizing = null;
this._direction = null;
this._directionChanged = null;
this._aspectRatio = 0;
this._containment = null;
this._origMousePos = null;
/**
* Original Size and Position
*/
this._origSize = null;
this._origPos = null;
/**
* Current Size and Position
*/
this._currSize = null;
this._currPos = null;
/**
* Initial Size and Position
*/
this._initSize = null;
this._initPos = null;
/**
* Snap to gird
*/
this._gridSize = null;
this._bounding = null;
/**
* Bugfix: iFrames, and context unrelated elements block all events, and are unusable
* https://github.com/xieziyu/angular2-draggable/issues/84
*/
this._helperBlock = null;
this.draggingSub = null;
this._adjusted = false;
/**
* Which handles can be used for resizing.
* \@example
* [rzHandles] = "'n,e,s,w,se,ne,sw,nw'"
* equals to: [rzHandles] = "'all'"
*
*
*/
this.rzHandles = 'e,s,se';
/**
* Whether the element should be constrained to a specific aspect ratio.
* Multiple types supported:
* boolean: When set to true, the element will maintain its original aspect ratio.
* number: Force the element to maintain a specific aspect ratio during resizing.
*/
this.rzAspectRatio = false;
/**
* Constrains resizing to within the bounds of the specified element or region.
* Multiple types supported:
* Selector: The resizable element will be contained to the bounding box of the first element found by the selector.
* If no element is found, no containment will be set.
* Element: The resizable element will be contained to the bounding box of this element.
* String: Possible values: "parent".
*/
this.rzContainment = null;
/**
* Snaps the resizing element to a grid, every x and y pixels.
* A number for both width and height or an array values like [ x, y ]
*/
this.rzGrid = null;
/**
* The minimum width the resizable should be allowed to resize to.
*/
this.rzMinWidth = null;
/**
* The minimum height the resizable should be allowed to resize to.
*/
this.rzMinHeight = null;
/**
* The maximum width the resizable should be allowed to resize to.
*/
this.rzMaxWidth = null;
/**
* The maximum height the resizable should be allowed to resize to.
*/
this.rzMaxHeight = null;
/**
* Whether to prevent default event
*/
this.preventDefaultEvent = true;
/**
* emitted when start resizing
*/
this.rzStart = new EventEmitter();
/**
* emitted when start resizing
*/
this.rzResizing = new EventEmitter();
/**
* emitted when stop resizing
*/
this.rzStop = new EventEmitter();
this._helperBlock = new HelperBlock(el.nativeElement, renderer);
}
/**
* Disables the resizable if set to false.
* @param {?} v
* @return {?}
*/
set ngResizable(v) {
if (v !== undefined && v !== null && v !== '') {
this._resizable = !!v;
this.updateResizable();
}
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
if (changes['rzHandles'] && !changes['rzHandles'].isFirstChange()) {
this.updateResizable();
}
if (changes['rzAspectRatio'] && !changes['rzAspectRatio'].isFirstChange()) {
this.updateAspectRatio();
}
if (changes['rzContainment'] && !changes['rzContainment'].isFirstChange()) {
this.updateContainment();
}
}
/**
* @return {?}
*/
ngOnInit() {
this.updateResizable();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.removeHandles();
this._containment = null;
this._helperBlock.dispose();
this._helperBlock = null;
}
/**
* @return {?}
*/
ngAfterViewInit() {
/** @type {?} */
const elm = this.el.nativeElement;
this._initSize = Size.getCurrent(elm);
this._initPos = Position.getCurrent(elm);
this._currSize = Size.copy(this._initSize);
this._currPos = Position.copy(this._initPos);
this.updateAspectRatio();
this.updateContainment();
}
/**
* A method to reset size
* @return {?}
*/
resetSize() {
this._currSize = Size.copy(this._initSize);
this._currPos = Position.copy(this._initPos);
this.doResize();
}
/**
* A method to get current status
* @return {?}
*/
getStatus() {
if (!this._currPos || !this._currSize) {
return null;
}
return {
size: {
width: this._currSize.width,
height: this._currSize.height
},
position: {
top: this._currPos.y,
left: this._currPos.x
}
};
}
/**
* @private
* @return {?}
*/
updateResizable() {
/** @type {?} */
const element = this.el.nativeElement;
// clear handles:
this.renderer.removeClass(element, 'ng-resizable');
this.removeHandles();
// create new ones:
if (this._resizable) {
this.renderer.addClass(element, 'ng-resizable');
this.createHandles();
}
}
/**
* Use it to update aspect
* @private
* @return {?}
*/
updateAspectRatio() {
if (typeof this.rzAspectRatio === 'boolean') {
if (this.rzAspectRatio && this._currSize.height) {
this._aspectRatio = (this._currSize.width / this._currSize.height);
}
else {
this._aspectRatio = 0;
}
}
else {
/** @type {?} */
let r = Number(this.rzAspectRatio);
this._aspectRatio = isNaN(r) ? 0 : r;
}
}
/**
* Use it to update containment
* @private
* @return {?}
*/
updateContainment() {
if (!this.rzContainment) {
this._containment = null;
return;
}
if (typeof this.rzContainment === 'string') {
if (this.rzContainment === 'parent') {
this._containment = this.el.nativeElement.parentElement;
}
else {
this._containment = document.querySelector(this.rzContainment);
}
}
else {
this._containment = this.rzContainment;
}
}
/**
* Use it to create handle divs
* @private
* @return {?}
*/
createHandles() {
if (!this.rzHandles) {
return;
}
/** @type {?} */
let tmpHandleTypes;
if (typeof this.rzHandles === 'string') {
if (this.rzHandles === 'all') {
tmpHandleTypes = ['n', 'e', 's', 'w', 'ne', 'se', 'nw', 'sw'];
}
else {
tmpHandleTypes = this.rzHandles.replace(/ /g, '').toLowerCase().split(',');
}
for (let type of tmpHandleTypes) {
// default handle theme: ng-resizable-$type.
/** @type {?} */
let handle = this.createHandleByType(type, `ng-resizable-${type}`);
if (handle) {
this._handleType.push(type);
this._handles[type] = handle;
}
}
}
else {
tmpHandleTypes = Object.keys(this.rzHandles);
for (let type of tmpHandleTypes) {
// custom handle theme.
/** @type {?} */
let handle = this.createHandleByType(type, this.rzHandles[type]);
if (handle) {
this._handleType.push(type);
this._handles[type] = handle;
}
}
}
}
/**
* Use it to create a handle
* @private
* @param {?} type
* @param {?} css
* @return {?}
*/
createHandleByType(type, css) {
/** @type {?} */
const _el = this.el.nativeElement;
if (!type.match(/^(se|sw|ne|nw|n|e|s|w)$/)) {
console.error('Invalid handle type:', type);
return null;
}
return new ResizeHandle(_el, this.renderer, type, css, this.onMouseDown.bind(this));
}
/**
* @private
* @return {?}
*/
removeHandles() {
for (let type of this._handleType) {
this._handles[type].dispose();
}
this._handleType = [];
this._handles = {};
}
/**
* @param {?} event
* @param {?} handle
* @return {?}
*/
onMouseDown(event, handle) {
// skip right click;
if (event instanceof MouseEvent && event.button === 2) {
return;
}
if (this.preventDefaultEvent) {
// prevent default events
event.stopPropagation();
event.preventDefault();
}
if (!this._handleResizing) {
this._origMousePos = Position.fromEvent(event);
this.startResize(handle);
this.subscribeEvents();
}
}
/**
* @private
* @return {?}
*/
subscribeEvents() {
this.draggingSub = fromEvent(document, 'mousemove', { passive: false }).subscribe(event => this.onMouseMove((/** @type {?} */ (event))));
this.draggingSub.add(fromEvent(document, 'touchmove', { passive: false }).subscribe(event => this.onMouseMove((/** @type {?} */ (event)))));
this.draggingSub.add(fromEvent(document, 'mouseup', { passive: false }).subscribe(() => this.onMouseLeave()));
// fix for issue #164
/** @type {?} */
let isIEOrEdge = /msie\s|trident\//i.test(window.navigator.userAgent);
if (!isIEOrEdge) {
this.draggingSub.add(fromEvent(document, 'mouseleave', { passive: false }).subscribe(() => this.onMouseLeave()));
}
this.draggingSub.add(fromEvent(document, 'touchend', { passive: false }).subscribe(() => this.onMouseLeave()));
this.draggingSub.add(fromEvent(document, 'touchcancel', { passive: false }).subscribe(() => this.onMouseLeave()));
}
/**
* @private
* @return {?}
*/
unsubscribeEvents() {
this.draggingSub.unsubscribe();
this.draggingSub = null;
}
/**
* @return {?}
*/
onMouseLeave() {
if (this._handleResizing) {
this.stopResize();
this._origMousePos = null;
this.unsubscribeEvents();
}
}
/**
* @param {?} event
* @return {?}
*/
onMouseMove(event) {
if (this._handleResizing && this._resizable && this._origMousePos && this._origPos && this._origSize) {
this.resizeTo(Position.fromEvent(event));
this.onResizing();
}
}
/**
* @private
* @param {?} handle
* @return {?}
*/
startResize(handle) {
/** @type {?} */
const elm = this.el.nativeElement;
this._origSize = Size.getCurrent(elm);
this._origPos = Position.getCurrent(elm); // x: left, y: top
this._currSize = Size.copy(this._origSize);
this._currPos = Position.copy(this._origPos);
if (this._containment) {
this.getBounding();
}
this.getGridSize();
// Add a transparent helper div:
this._helperBlock.add();
this._handleResizing = handle;
this.updateDirection();
this.rzStart.emit(this.getResizingEvent());
}
/**
* @private
* @return {?}
*/
stopResize() {
// Remove the helper div:
this._helperBlock.remove();
this.rzStop.emit(this.getResizingEvent());
this._handleResizing = null;
this._direction = null;
this._origSize = null;
this._origPos = null;
if (this._containment) {
this.resetBounding();
}
}
/**
* @private
* @return {?}
*/
onResizing() {
this.rzResizing.emit(this.getResizingEvent());
}
/**
* @private
* @return {?}
*/
getResizingEvent() {
return {
host: this.el.nativeElement,
handle: this._handleResizing ? this._handleResizing.el : null,
size: {
width: this._currSize.width,
height: this._currSize.height
},
position: {
top: this._currPos.y,
left: this._currPos.x
},
direction: Object.assign({}, this._directionChanged),
};
}
/**
* @private
* @return {?}
*/
updateDirection() {
this._direction = {
n: !!this._handleResizing.type.match(/n/),
s: !!this._handleResizing.type.match(/s/),
w: !!this._handleResizing.type.match(/w/),
e: !!this._handleResizing.type.match(/e/)
};
this._directionChanged = Object.assign({}, this._direction);
// if aspect ration should be preserved:
if (this.rzAspectRatio) {
// if north then west (unless ne)
if (this._directionChanged.n && !this._directionChanged.e) {
this._directionChanged.w = true;
}
// if south then east (unless sw)
if (this._directionChanged.s && !this._directionChanged.w) {
this._directionChanged.e = true;
}
// if east then south (unless ne)
if (this._directionChanged.e && !this._directionChanged.n) {
this._directionChanged.s = true;
}
// if west then south (unless nw)
if (this._directionChanged.w && !this._directionChanged.n) {
this._directionChanged.s = true;
}
}
}
/**
* @private
* @param {?} p
* @return {?}
*/
resizeTo(p) {
p.subtract(this._origMousePos);
/** @type {?} */
const tmpX = Math.round(p.x / this._gridSize.x) * this._gridSize.x;
/** @type {?} */
const tmpY = Math.round(p.y / this._gridSize.y) * this._gridSize.y;
if (this._direction.n) {
// n, ne, nw
this._currPos.y = this._origPos.y + tmpY;
this._currSize.height = this._origSize.height - tmpY;
}
else if (this._direction.s) {
// s, se, sw
this._currSize.height = this._origSize.height + tmpY;
}
if (this._direction.e) {
// e, ne, se
this._currSize.width = this._origSize.width + tmpX;
}
else if (this._direction.w) {
// w, nw, sw
this._currSize.width = this._origSize.width - tmpX;
this._currPos.x = this._origPos.x + tmpX;
}
this.checkBounds();
this.checkSize();
this.adjustByRatio();
this.doResize();
}
/**
* @private
* @return {?}
*/
doResize() {
/** @type {?} */
const container = this.el.nativeElement;
if (!this._direction || this._direction.n || this._direction.s || this._aspectRatio) {
this.renderer.setStyle(container, 'height', this._currSize.height + 'px');
}
if (!this._direction || this._direction.w || this._direction.e || this._aspectRatio) {
this.renderer.setStyle(container, 'width', this._currSize.width + 'px');
}
this.renderer.setStyle(container, 'left', this._currPos.x + 'px');
this.renderer.setStyle(container, 'top', this._currPos.y + 'px');
}
/**
* @private
* @return {?}
*/
adjustByRatio() {
if (this._aspectRatio && !this._adjusted) {
if (this._direction.e || this._direction.w) {
/** @type {?} */
const newHeight = Math.floor(this._currSize.width / this._aspectRatio);
if (this._direction.n) {
this._currPos.y += this._currSize.height - newHeight;
}
this._currSize.height = newHeight;
}
else {
/** @type {?} */
const newWidth = Math.floor(this._aspectRatio * this._currSize.height);
if (this._direction.n) {
this._currPos.x += this._currSize.width - newWidth;
}
this._currSize.width = newWidth;
}
}
}
/**
* @private
* @return {?}
*/
checkBounds() {
if (this._containment) {
/** @type {?} */
const maxWidth = this._bounding.width - this._bounding.pr - this._bounding.deltaL - this._bounding.translateX - this._currPos.x;
/** @type {?} */
const maxHeight = this._bounding.height - this._bounding.pb - this._bounding.deltaT - this._bounding.translateY - this._currPos.y;
if (this._direction.n && (this._currPos.y + this._bounding.translateY < 0)) {
this._currPos.y = -this._bounding.translateY;
this._currSize.height = this._origSize.height + this._origPos.y + this._bounding.translateY;
}
if (this._direction.w && (this._currPos.x + this._bounding.translateX) < 0) {
this._currPos.x = -this._bounding.translateX;
this._currSize.width = this._origSize.width + this._origPos.x + this._bounding.translateX;
}
if (this._currSize.width > maxWidth) {
this._currSize.width = maxWidth;
}
if (this._currSize.height > maxHeight) {
this._currSize.height = maxHeight;
}
/**
* Fix Issue: Additional check for aspect ratio
* https://github.com/xieziyu/angular2-draggable/issues/132
*/
if (this._aspectRatio) {
this._adjusted = false;
if ((this._direction.w || this._direction.e) &&
(this._currSize.width / this._aspectRatio) >= maxHeight) {
/** @type {?} */
const newWidth = Math.floor(maxHeight * this._aspectRatio);
if (this._direction.w) {
this._currPos.x += this._currSize.width - newWidth;
}
this._currSize.width = newWidth;
this._currSize.height = maxHeight;
this._adjusted = true;
}
if ((this._direction.n || this._direction.s) &&
(this._currSize.height * this._aspectRatio) >= maxWidth) {
/** @type {?} */
const newHeight = Math.floor(maxWidth / this._aspectRatio);
if (this._direction.n) {
this._currPos.y += this._currSize.height - newHeight;
}
this._currSize.width = maxWidth;
this._currSize.height = newHeight;
this._adjusted = true;
}
}
}
}
/**
* @private
* @return {?}
*/
checkSize() {
/** @type {?} */
const minHeight = !this.rzMinHeight ? 1 : this.rzMinHeight;
/** @type {?} */
const minWidth = !this.rzMinWidth ? 1 : this.rzMinWidth;
if (this._currSize.height < minHeight) {
this._currSize.height = minHeight;
if (this._direction.n) {
this._currPos.y = this._origPos.y + (this._origSize.height - minHeight);
}
}
if (this._currSize.width < minWidth) {
this._currSize.width = minWidth;
if (this._direction.w) {
this._currPos.x = this._origPos.x + (this._origSize.width - minWidth);
}
}
if (this.rzMaxHeight && this._currSize.height > this.rzMaxHeight) {
this._currSize.height = this.rzMaxHeight;
if (this._direction.n) {
this._currPos.y = this._origPos.y + (this._origSize.height - this.rzMaxHeight);
}
}
if (this.rzMaxWidth && this._currSize.width > this.rzMaxWidth) {
this._currSize.width = this.rzMaxWidth;
if (this._direction.w) {
this._currPos.x = this._origPos.x + (this._origSize.width - this.rzMaxWidth);
}
}
}
/**
* @private
* @return {?}
*/
getBounding() {
/** @type {?} */
const el = this._containment;
/** @type {?} */
const computed = window.getComputedStyle(el);
if (computed) {
/** @type {?} */
let p = computed.getPropertyValue('position');
/** @type {?} */
const nativeEl = window.getComputedStyle(this.el.nativeElement);
/** @type {?} */
let transforms = nativeEl.getPropertyValue('transform').replace(/[^-\d,]/g, '').split(',');
this._bounding = {};
this._bounding.width = el.clientWidth;
this._bounding.height = el.clientHeight;
this._bounding.pr = parseInt(computed.getPropertyValue('padding-right'), 10);
this._bounding.pb = parseInt(computed.getPropertyValue('padding-bottom'), 10);
this._bounding.deltaL = this.el.nativeElement.offsetLeft - this._currPos.x;
this._bounding.deltaT = this.el.nativeElement.offsetTop - this._currPos.y;
if (transforms.length >= 6) {
this._bounding.translateX = parseInt(transforms[4], 10);
this._bounding.translateY = parseInt(transforms[5], 10);
}
else {
this._bounding.translateX = 0;
this._bounding.translateY = 0;
}
this._bounding.position = computed.getPropertyValue('position');
if (p === 'static') {
this.renderer.setStyle(el, 'position', 'relative');
}
}
}
/**
* @private
* @return {?}
*/
resetBounding() {
if (this._bounding && this._bounding.position === 'static') {
this.renderer.setStyle(this._containment, 'position', 'relative');
}
this._bounding = null;
}
/**
* @private
* @return {?}
*/
getGridSize() {
// set default value:
this._gridSize = { x: 1, y: 1 };
if (this.rzGrid) {
if (typeof this.rzGrid === 'number') {
this._gridSize = { x: this.rzGrid, y: this.rzGrid };
}
else if (Array.isArray(this.rzGrid)) {
this._gridSize = { x: this.rzGrid[0], y: this.rzGrid[1] };
}
}
}
}
AngularResizableDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngResizable]',
exportAs: 'ngResizable'
},] }
];
/** @nocollapse */
AngularResizableDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 }
];
AngularResizableDirective.propDecorators = {
ngResizable: [{ type: Input }],
rzHandles: [{ type: Input }],
rzAspectRatio: [{ type: Input }],
rzContainment: [{ type: Input }],
rzGrid: [{ type: Input }],
rzMinWidth: [{ type: Input }],
rzMinHeight: [{ type: Input }],
rzMaxWidth: [{ type: Input }],
rzMaxHeight: [{ type: Input }],
preventDefaultEvent: [{ type: Input }],
rzStart: [{ type: Output }],
rzResizing: [{ type: Output }],
rzStop: [{ type: Output }]
};
if (false) {
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._resizable;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._handles;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._handleType;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._handleResizing;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._direction;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._directionChanged;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._aspectRatio;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._containment;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._origMousePos;
/**
* Original Size and Position
* @type {?}
* @private
*/
AngularResizableDirective.prototype._origSize;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._origPos;
/**
* Current Size and Position
* @type {?}
* @private
*/
AngularResizableDirective.prototype._currSize;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._currPos;
/**
* Initial Size and Position
* @type {?}
* @private
*/
AngularResizableDirective.prototype._initSize;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._initPos;
/**
* Snap to gird
* @type {?}
* @private
*/
AngularResizableDirective.prototype._gridSize;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._bounding;
/**
* Bugfix: iFrames, and context unrelated elements block all events, and are unusable
* https://github.com/xieziyu/angular2-draggable/issues/84
* @type {?}
* @private
*/
AngularResizableDirective.prototype._helperBlock;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype.draggingSub;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype._adjusted;
/**
* Which handles can be used for resizing.
* \@example
* [rzHandles] = "'n,e,s,w,se,ne,sw,nw'"
* equals to: [rzHandles] = "'all'"
*
*
* @type {?}
*/
AngularResizableDirective.prototype.rzHandles;
/**
* Whether the element should be constrained to a specific aspect ratio.
* Multiple types supported:
* boolean: When set to true, the element will maintain its original aspect ratio.
* number: Force the element to maintain a specific aspect ratio during resizing.
* @type {?}
*/
AngularResizableDirective.prototype.rzAspectRatio;
/**
* Constrains resizing to within the bounds of the specified element or region.
* Multiple types supported:
* Selector: The resizable element will be contained to the bounding box of the first element found by the selector.
* If no element is found, no containment will be set.
* Element: The resizable element will be contained to the bounding box of this element.
* String: Possible values: "parent".
* @type {?}
*/
AngularResizableDirective.prototype.rzContainment;
/**
* Snaps the resizing element to a grid, every x and y pixels.
* A number for both width and height or an array values like [ x, y ]
* @type {?}
*/
AngularResizableDirective.prototype.rzGrid;
/**
* The minimum width the resizable should be allowed to resize to.
* @type {?}
*/
AngularResizableDirective.prototype.rzMinWidth;
/**
* The minimum height the resizable should be allowed to resize to.
* @type {?}
*/
AngularResizableDirective.prototype.rzMinHeight;
/**
* The maximum width the resizable should be allowed to resize to.
* @type {?}
*/
AngularResizableDirective.prototype.rzMaxWidth;
/**
* The maximum height the resizable should be allowed to resize to.
* @type {?}
*/
AngularResizableDirective.prototype.rzMaxHeight;
/**
* Whether to prevent default event
* @type {?}
*/
AngularResizableDirective.prototype.preventDefaultEvent;
/**
* emitted when start resizing
* @type {?}
*/
AngularResizableDirective.prototype.rzStart;
/**
* emitted when start resizing
* @type {?}
*/
AngularResizableDirective.prototype.rzResizing;
/**
* emitted when stop resizing
* @type {?}
*/
AngularResizableDirective.prototype.rzStop;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype.el;
/**
* @type {?}
* @private
*/
AngularResizableDirective.prototype.renderer;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1yZXNpemFibGUuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhcjItZHJhZ2dhYmxlLyIsInNvdXJjZXMiOlsibGliL2FuZ3VsYXItcmVzaXphYmxlLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUNoQyxLQUFLLEVBQUUsTUFBTSxFQUFVLFlBQVksRUFFcEMsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFnQixTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsUUFBUSxFQUFhLE1BQU0sbUJBQW1CLENBQUM7QUFDeEQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQU9yQyxNQUFNLE9BQU8seUJBQXlCOzs7OztJQXNHcEMsWUFBb0IsRUFBMkIsRUFBVSxRQUFtQjtRQUF4RCxPQUFFLEdBQUYsRUFBRSxDQUF5QjtRQUFVLGFBQVEsR0FBUixRQUFRLENBQVc7UUFyR3BFLGVBQVUsR0FBRyxJQUFJLENBQUM7UUFDbEIsYUFBUSxHQUFvQyxFQUFFLENBQUM7UUFDL0MsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDM0Isb0JBQWUsR0FBaUIsSUFBSSxDQUFDO1FBQ3JDLGVBQVUsR0FBK0QsSUFBSSxDQUFDO1FBQzlFLHNCQUFpQixHQUErRCxJQUFJLENBQUM7UUFDckYsaUJBQVksR0FBRyxDQUFDLENBQUM7UUFDakIsaUJBQVksR0FBZ0IsSUFBSSxDQUFDO1FBQ2pDLGtCQUFhLEdBQWEsSUFBSSxDQUFDOzs7O1FBRy9CLGNBQVMsR0FBUyxJQUFJLENBQUM7UUFDdkIsYUFBUSxHQUFhLElBQUksQ0FBQzs7OztRQUcxQixjQUFTLEdB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QUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRWpJLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsRUFBRTtnQkFDMUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQztnQkFDN0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUM7YUFDN0Y7WUFFRCxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQzFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUM7Z0JBQzdDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDO2FBQzNGO1lBRUQsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssR0FBRyxRQUFRLEVBQUU7Z0JBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQzthQUNqQztZQUVELElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsU0FBUyxFQUFFO2dCQUNyQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7YUFDbkM7WUFFRDs7O2VBR0c7WUFDSCxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ3JCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUV2QixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7b0JBQ3hDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLFNBQVMsRUFBRTs7MEJBQ3JELFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO29CQUUxRCxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFO3dCQUNyQixJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7cUJBQ3BEO29CQUVELElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQztvQkFDaEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO29CQUNsQyxJQUFJLENBQUMsU0FBUyxHQUFH