UNPKG

@angular/cdk

Version:

Angular Material Component Development Kit

493 lines 70 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { Directionality } from '@angular/cdk/bidi'; import { DOCUMENT } from '@angular/common'; import { ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, Inject, Input, NgZone, Optional, Output, QueryList, SkipSelf, ViewContainerRef, ChangeDetectorRef, Self, InjectionToken, } from '@angular/core'; import { coerceBooleanProperty, coerceNumberProperty, coerceElement, } from '@angular/cdk/coercion'; import { Observable, Subject, merge } from 'rxjs'; import { startWith, take, map, takeUntil, switchMap, tap } from 'rxjs/operators'; import { CDK_DRAG_HANDLE, CdkDragHandle } from './drag-handle'; import { CDK_DRAG_PLACEHOLDER, CdkDragPlaceholder } from './drag-placeholder'; import { CDK_DRAG_PREVIEW, CdkDragPreview } from './drag-preview'; import { CDK_DRAG_PARENT } from '../drag-parent'; import { DragDrop } from '../drag-drop'; import { CDK_DRAG_CONFIG } from './config'; import { assertElementNode } from './assertions'; import * as i0 from "@angular/core"; import * as i1 from "@angular/cdk/bidi"; import * as i2 from "../drag-drop"; import * as i3 from "./drag-handle"; const DRAG_HOST_CLASS = 'cdk-drag'; /** * Injection token that can be used to reference instances of `CdkDropList`. It serves as * alternative token to the actual `CdkDropList` class which could cause unnecessary * retention of the class and its directive metadata. */ export const CDK_DROP_LIST = new InjectionToken('CdkDropList'); /** Element that can be moved inside a CdkDropList container. */ export class CdkDrag { static { this._dragInstances = []; } /** Whether starting to drag this element is disabled. */ get disabled() { return this._disabled || (this.dropContainer && this.dropContainer.disabled); } set disabled(value) { this._disabled = coerceBooleanProperty(value); this._dragRef.disabled = this._disabled; } constructor( /** Element that the draggable is attached to. */ element, /** Droppable container that the draggable is a part of. */ dropContainer, /** * @deprecated `_document` parameter no longer being used and will be removed. * @breaking-change 12.0.0 */ _document, _ngZone, _viewContainerRef, config, _dir, dragDrop, _changeDetectorRef, _selfHandle, _parentDrag) { this.element = element; this.dropContainer = dropContainer; this._ngZone = _ngZone; this._viewContainerRef = _viewContainerRef; this._dir = _dir; this._changeDetectorRef = _changeDetectorRef; this._selfHandle = _selfHandle; this._parentDrag = _parentDrag; this._destroyed = new Subject(); /** Emits when the user starts dragging the item. */ this.started = new EventEmitter(); /** Emits when the user has released a drag item, before any animations have started. */ this.released = new EventEmitter(); /** Emits when the user stops dragging an item in the container. */ this.ended = new EventEmitter(); /** Emits when the user has moved the item into a new container. */ this.entered = new EventEmitter(); /** Emits when the user removes the item its container by dragging it into another container. */ this.exited = new EventEmitter(); /** Emits when the user drops the item inside a container. */ this.dropped = new EventEmitter(); /** * Emits as the user is dragging the item. Use with caution, * because this event will fire for every pixel that the user has dragged. */ this.moved = new Observable((observer) => { const subscription = this._dragRef.moved .pipe(map(movedEvent => ({ source: this, pointerPosition: movedEvent.pointerPosition, event: movedEvent.event, delta: movedEvent.delta, distance: movedEvent.distance, }))) .subscribe(observer); return () => { subscription.unsubscribe(); }; }); this._dragRef = dragDrop.createDrag(element, { dragStartThreshold: config && config.dragStartThreshold != null ? config.dragStartThreshold : 5, pointerDirectionChangeThreshold: config && config.pointerDirectionChangeThreshold != null ? config.pointerDirectionChangeThreshold : 5, zIndex: config?.zIndex, }); this._dragRef.data = this; // We have to keep track of the drag instances in order to be able to match an element to // a drag instance. We can't go through the global registry of `DragRef`, because the root // element could be different. CdkDrag._dragInstances.push(this); if (config) { this._assignDefaults(config); } // Note that usually the container is assigned when the drop list is picks up the item, but in // some cases (mainly transplanted views with OnPush, see #18341) we may end up in a situation // where there are no items on the first change detection pass, but the items get picked up as // soon as the user triggers another pass by dragging. This is a problem, because the item would // have to switch from standalone mode to drag mode in the middle of the dragging sequence which // is too late since the two modes save different kinds of information. We work around it by // assigning the drop container both from here and the list. if (dropContainer) { this._dragRef._withDropContainer(dropContainer._dropListRef); dropContainer.addItem(this); } this._syncInputs(this._dragRef); this._handleEvents(this._dragRef); } /** * Returns the element that is being used as a placeholder * while the current element is being dragged. */ getPlaceholderElement() { return this._dragRef.getPlaceholderElement(); } /** Returns the root draggable element. */ getRootElement() { return this._dragRef.getRootElement(); } /** Resets a standalone drag item to its initial position. */ reset() { this._dragRef.reset(); } /** * Gets the pixel coordinates of the draggable outside of a drop container. */ getFreeDragPosition() { return this._dragRef.getFreeDragPosition(); } /** * Sets the current position in pixels the draggable outside of a drop container. * @param value New position to be set. */ setFreeDragPosition(value) { this._dragRef.setFreeDragPosition(value); } ngAfterViewInit() { // Normally this isn't in the zone, but it can cause major performance regressions for apps // using `zone-patch-rxjs` because it'll trigger a change detection when it unsubscribes. this._ngZone.runOutsideAngular(() => { // We need to wait for the zone to stabilize, in order for the reference // element to be in the proper place in the DOM. This is mostly relevant // for draggable elements inside portals since they get stamped out in // their original DOM position and then they get transferred to the portal. this._ngZone.onStable.pipe(take(1), takeUntil(this._destroyed)).subscribe(() => { this._updateRootElement(); this._setupHandlesListener(); if (this.freeDragPosition) { this._dragRef.setFreeDragPosition(this.freeDragPosition); } }); }); } ngOnChanges(changes) { const rootSelectorChange = changes['rootElementSelector']; const positionChange = changes['freeDragPosition']; // We don't have to react to the first change since it's being // handled in `ngAfterViewInit` where it needs to be deferred. if (rootSelectorChange && !rootSelectorChange.firstChange) { this._updateRootElement(); } // Skip the first change since it's being handled in `ngAfterViewInit`. if (positionChange && !positionChange.firstChange && this.freeDragPosition) { this._dragRef.setFreeDragPosition(this.freeDragPosition); } } ngOnDestroy() { if (this.dropContainer) { this.dropContainer.removeItem(this); } const index = CdkDrag._dragInstances.indexOf(this); if (index > -1) { CdkDrag._dragInstances.splice(index, 1); } // Unnecessary in most cases, but used to avoid extra change detections with `zone-paths-rxjs`. this._ngZone.runOutsideAngular(() => { this._destroyed.next(); this._destroyed.complete(); this._dragRef.dispose(); }); } /** Syncs the root element with the `DragRef`. */ _updateRootElement() { const element = this.element.nativeElement; let rootElement = element; if (this.rootElementSelector) { rootElement = element.closest !== undefined ? element.closest(this.rootElementSelector) : // Comment tag doesn't have closest method, so use parent's one. element.parentElement?.closest(this.rootElementSelector); } if (rootElement && (typeof ngDevMode === 'undefined' || ngDevMode)) { assertElementNode(rootElement, 'cdkDrag'); } this._dragRef.withRootElement(rootElement || element); } /** Gets the boundary element, based on the `boundaryElement` value. */ _getBoundaryElement() { const boundary = this.boundaryElement; if (!boundary) { return null; } if (typeof boundary === 'string') { return this.element.nativeElement.closest(boundary); } return coerceElement(boundary); } /** Syncs the inputs of the CdkDrag with the options of the underlying DragRef. */ _syncInputs(ref) { ref.beforeStarted.subscribe(() => { if (!ref.isDragging()) { const dir = this._dir; const dragStartDelay = this.dragStartDelay; const placeholder = this._placeholderTemplate ? { template: this._placeholderTemplate.templateRef, context: this._placeholderTemplate.data, viewContainer: this._viewContainerRef, } : null; const preview = this._previewTemplate ? { template: this._previewTemplate.templateRef, context: this._previewTemplate.data, matchSize: this._previewTemplate.matchSize, viewContainer: this._viewContainerRef, } : null; ref.disabled = this.disabled; ref.lockAxis = this.lockAxis; ref.dragStartDelay = typeof dragStartDelay === 'object' && dragStartDelay ? dragStartDelay : coerceNumberProperty(dragStartDelay); ref.constrainPosition = this.constrainPosition; ref.previewClass = this.previewClass; ref .withBoundaryElement(this._getBoundaryElement()) .withPlaceholderTemplate(placeholder) .withPreviewTemplate(preview) .withPreviewContainer(this.previewContainer || 'global'); if (dir) { ref.withDirection(dir.value); } } }); // This only needs to be resolved once. ref.beforeStarted.pipe(take(1)).subscribe(() => { // If we managed to resolve a parent through DI, use it. if (this._parentDrag) { ref.withParent(this._parentDrag._dragRef); return; } // Otherwise fall back to resolving the parent by looking up the DOM. This can happen if // the item was projected into another item by something like `ngTemplateOutlet`. let parent = this.element.nativeElement.parentElement; while (parent) { if (parent.classList.contains(DRAG_HOST_CLASS)) { ref.withParent(CdkDrag._dragInstances.find(drag => { return drag.element.nativeElement === parent; })?._dragRef || null); break; } parent = parent.parentElement; } }); } /** Handles the events from the underlying `DragRef`. */ _handleEvents(ref) { ref.started.subscribe(startEvent => { this.started.emit({ source: this, event: startEvent.event }); // Since all of these events run outside of change detection, // we need to ensure that everything is marked correctly. this._changeDetectorRef.markForCheck(); }); ref.released.subscribe(releaseEvent => { this.released.emit({ source: this, event: releaseEvent.event }); }); ref.ended.subscribe(endEvent => { this.ended.emit({ source: this, distance: endEvent.distance, dropPoint: endEvent.dropPoint, event: endEvent.event, }); // Since all of these events run outside of change detection, // we need to ensure that everything is marked correctly. this._changeDetectorRef.markForCheck(); }); ref.entered.subscribe(enterEvent => { this.entered.emit({ container: enterEvent.container.data, item: this, currentIndex: enterEvent.currentIndex, }); }); ref.exited.subscribe(exitEvent => { this.exited.emit({ container: exitEvent.container.data, item: this, }); }); ref.dropped.subscribe(dropEvent => { this.dropped.emit({ previousIndex: dropEvent.previousIndex, currentIndex: dropEvent.currentIndex, previousContainer: dropEvent.previousContainer.data, container: dropEvent.container.data, isPointerOverContainer: dropEvent.isPointerOverContainer, item: this, distance: dropEvent.distance, dropPoint: dropEvent.dropPoint, event: dropEvent.event, }); }); } /** Assigns the default input values based on a provided config object. */ _assignDefaults(config) { const { lockAxis, dragStartDelay, constrainPosition, previewClass, boundaryElement, draggingDisabled, rootElementSelector, previewContainer, } = config; this.disabled = draggingDisabled == null ? false : draggingDisabled; this.dragStartDelay = dragStartDelay || 0; if (lockAxis) { this.lockAxis = lockAxis; } if (constrainPosition) { this.constrainPosition = constrainPosition; } if (previewClass) { this.previewClass = previewClass; } if (boundaryElement) { this.boundaryElement = boundaryElement; } if (rootElementSelector) { this.rootElementSelector = rootElementSelector; } if (previewContainer) { this.previewContainer = previewContainer; } } /** Sets up the listener that syncs the handles with the drag ref. */ _setupHandlesListener() { // Listen for any newly-added handles. this._handles.changes .pipe(startWith(this._handles), // Sync the new handles with the DragRef. tap((handles) => { const childHandleElements = handles .filter(handle => handle._parentDrag === this) .map(handle => handle.element); // Usually handles are only allowed to be a descendant of the drag element, but if // the consumer defined a different drag root, we should allow the drag element // itself to be a handle too. if (this._selfHandle && this.rootElementSelector) { childHandleElements.push(this.element); } this._dragRef.withHandles(childHandleElements); }), // Listen if the state of any of the handles changes. switchMap((handles) => { return merge(...handles.map(item => { return item._stateChanges.pipe(startWith(item)); })); }), takeUntil(this._destroyed)) .subscribe(handleInstance => { // Enabled/disable the handle that changed in the DragRef. const dragRef = this._dragRef; const handle = handleInstance.element.nativeElement; handleInstance.disabled ? dragRef.disableHandle(handle) : dragRef.enableHandle(handle); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: CdkDrag, deps: [{ token: i0.ElementRef }, { token: CDK_DROP_LIST, optional: true, skipSelf: true }, { token: DOCUMENT }, { token: i0.NgZone }, { token: i0.ViewContainerRef }, { token: CDK_DRAG_CONFIG, optional: true }, { token: i1.Directionality, optional: true }, { token: i2.DragDrop }, { token: i0.ChangeDetectorRef }, { token: CDK_DRAG_HANDLE, optional: true, self: true }, { token: CDK_DRAG_PARENT, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.1", type: CdkDrag, isStandalone: true, selector: "[cdkDrag]", inputs: { data: ["cdkDragData", "data"], lockAxis: ["cdkDragLockAxis", "lockAxis"], rootElementSelector: ["cdkDragRootElement", "rootElementSelector"], boundaryElement: ["cdkDragBoundary", "boundaryElement"], dragStartDelay: ["cdkDragStartDelay", "dragStartDelay"], freeDragPosition: ["cdkDragFreeDragPosition", "freeDragPosition"], disabled: ["cdkDragDisabled", "disabled"], constrainPosition: ["cdkDragConstrainPosition", "constrainPosition"], previewClass: ["cdkDragPreviewClass", "previewClass"], previewContainer: ["cdkDragPreviewContainer", "previewContainer"] }, outputs: { started: "cdkDragStarted", released: "cdkDragReleased", ended: "cdkDragEnded", entered: "cdkDragEntered", exited: "cdkDragExited", dropped: "cdkDragDropped", moved: "cdkDragMoved" }, host: { properties: { "class.cdk-drag-disabled": "disabled", "class.cdk-drag-dragging": "_dragRef.isDragging()" }, classAttribute: "cdk-drag" }, providers: [{ provide: CDK_DRAG_PARENT, useExisting: CdkDrag }], queries: [{ propertyName: "_previewTemplate", first: true, predicate: CDK_DRAG_PREVIEW, descendants: true }, { propertyName: "_placeholderTemplate", first: true, predicate: CDK_DRAG_PLACEHOLDER, descendants: true }, { propertyName: "_handles", predicate: CDK_DRAG_HANDLE, descendants: true }], exportAs: ["cdkDrag"], usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: CdkDrag, decorators: [{ type: Directive, args: [{ selector: '[cdkDrag]', exportAs: 'cdkDrag', standalone: true, host: { 'class': DRAG_HOST_CLASS, '[class.cdk-drag-disabled]': 'disabled', '[class.cdk-drag-dragging]': '_dragRef.isDragging()', }, providers: [{ provide: CDK_DRAG_PARENT, useExisting: CdkDrag }], }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: undefined, decorators: [{ type: Inject, args: [CDK_DROP_LIST] }, { type: Optional }, { type: SkipSelf }] }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: i0.NgZone }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [CDK_DRAG_CONFIG] }] }, { type: i1.Directionality, decorators: [{ type: Optional }] }, { type: i2.DragDrop }, { type: i0.ChangeDetectorRef }, { type: i3.CdkDragHandle, decorators: [{ type: Optional }, { type: Self }, { type: Inject, args: [CDK_DRAG_HANDLE] }] }, { type: CdkDrag, decorators: [{ type: Optional }, { type: SkipSelf }, { type: Inject, args: [CDK_DRAG_PARENT] }] }]; }, propDecorators: { _handles: [{ type: ContentChildren, args: [CDK_DRAG_HANDLE, { descendants: true }] }], _previewTemplate: [{ type: ContentChild, args: [CDK_DRAG_PREVIEW] }], _placeholderTemplate: [{ type: ContentChild, args: [CDK_DRAG_PLACEHOLDER] }], data: [{ type: Input, args: ['cdkDragData'] }], lockAxis: [{ type: Input, args: ['cdkDragLockAxis'] }], rootElementSelector: [{ type: Input, args: ['cdkDragRootElement'] }], boundaryElement: [{ type: Input, args: ['cdkDragBoundary'] }], dragStartDelay: [{ type: Input, args: ['cdkDragStartDelay'] }], freeDragPosition: [{ type: Input, args: ['cdkDragFreeDragPosition'] }], disabled: [{ type: Input, args: ['cdkDragDisabled'] }], constrainPosition: [{ type: Input, args: ['cdkDragConstrainPosition'] }], previewClass: [{ type: Input, args: ['cdkDragPreviewClass'] }], previewContainer: [{ type: Input, args: ['cdkDragPreviewContainer'] }], started: [{ type: Output, args: ['cdkDragStarted'] }], released: [{ type: Output, args: ['cdkDragReleased'] }], ended: [{ type: Output, args: ['cdkDragEnded'] }], entered: [{ type: Output, args: ['cdkDragEntered'] }], exited: [{ type: Output, args: ['cdkDragExited'] }], dropped: [{ type: Output, args: ['cdkDragDropped'] }], moved: [{ type: Output, args: ['cdkDragMoved'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jZGsvZHJhZy1kcm9wL2RpcmVjdGl2ZXMvZHJhZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDakQsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFFTCxZQUFZLEVBQ1osZUFBZSxFQUNmLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUVOLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULFFBQVEsRUFDUixnQkFBZ0IsRUFHaEIsaUJBQWlCLEVBQ2pCLElBQUksRUFDSixjQUFjLEdBQ2YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLHFCQUFxQixFQUNyQixvQkFBb0IsRUFDcEIsYUFBYSxHQUVkLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFDLFVBQVUsRUFBWSxPQUFPLEVBQUUsS0FBSyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzFELE9BQU8sRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBVS9FLE9BQU8sRUFBQyxlQUFlLEVBQUUsYUFBYSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQzdELE9BQU8sRUFBQyxvQkFBb0IsRUFBRSxrQkFBa0IsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQzVFLE9BQU8sRUFBQyxnQkFBZ0IsRUFBRSxjQUFjLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNoRSxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFHL0MsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGNB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QXJDLE1BQU07dUJBQUMsY0FBYztnQkFHYSxPQUFPO3NCQUF6QyxNQUFNO3VCQUFDLGdCQUFnQjtnQkFLVSxNQUFNO3NCQUF2QyxNQUFNO3VCQUFDLGVBQWU7Z0JBS1ksT0FBTztzQkFBekMsTUFBTTt1QkFBQyxnQkFBZ0I7Z0JBU2YsS0FBSztzQkFEYixNQUFNO3VCQUFDLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtEaXJlY3Rpb25hbGl0eX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2JpZGknO1xuaW1wb3J0IHtET0NVTUVOVH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbnRlbnRDaGlsZCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgU2tpcFNlbGYsXG4gIFZpZXdDb250YWluZXJSZWYsXG4gIE9uQ2hhbmdlcyxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIFNlbGYsXG4gIEluamVjdGlvblRva2VuLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSxcbiAgY29lcmNlTnVtYmVyUHJvcGVydHksXG4gIGNvZXJjZUVsZW1lbnQsXG4gIEJvb2xlYW5JbnB1dCxcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7T2JzZXJ2YWJsZSwgT2JzZXJ2ZXIsIFN1YmplY3QsIG1lcmdlfSBmcm9tICdyeGpzJztcbmltcG9ydCB7c3RhcnRXaXRoLCB0YWtlLCBtYXAsIHRha2VVbnRpbCwgc3dpdGNoTWFwLCB0YXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB0eXBlIHtcbiAgQ2RrRHJhZ0Ryb3AsXG4gIENka0RyYWdFbmQsXG4gIENka0RyYWdFbnRlcixcbiAgQ2RrRHJhZ0V4aXQsXG4gIENka0RyYWdNb3ZlLFxuICBDZGtEcmFnU3RhcnQsXG4gIENka0RyYWdSZWxlYXNlLFxufSBmcm9tICcuLi9kcmFnLWV2ZW50cyc7XG5pbXBvcnQge0NES19EUkFHX0hBTkRMRSwgQ2RrRHJhZ0hhbmRsZX0gZnJvbSAnLi9kcmFnLWhhbmRsZSc7XG5pbXBvcnQge0NES19EUkFHX1BMQUNFSE9MREVSLCBDZGtEcmFnUGxhY2Vob2xkZXJ9IGZyb20gJy4vZHJhZy1wbGFjZWhvbGRlcic7XG5pbXBvcnQge0NES19EUkFHX1BSRVZJRVcsIENka0RyYWdQcmV2aWV3fSBmcm9tICcuL2RyYWctcHJldmlldyc7XG5pbXBvcnQge0NES19EUkFHX1BBUkVOVH0gZnJvbSAnLi4vZHJhZy1wYXJlbnQnO1xuaW1wb3J0IHtEcmFnUmVmLCBQb2ludCwgUHJldmlld0NvbnRhaW5lcn0gZnJvbSAnLi4vZHJhZy1yZWYnO1xuaW1wb3J0IHR5cGUge0Nka0Ryb3BMaXN0fSBmcm9tICcuL2Ryb3AtbGlzdCc7XG5pbXBvcnQge0RyYWdEcm9wfSBmcm9tICcuLi9kcmFnLWRyb3AnO1xuaW1wb3J0IHtDREtfRFJBR19DT05GSUcsIERyYWdEcm9wQ29uZmlnLCBEcmFnU3RhcnREZWxheSwgRHJhZ0F4aXN9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7YXNzZXJ0RWxlbWVudE5vZGV9IGZyb20gJy4vYXNzZXJ0aW9ucyc7XG5cbmNvbnN0IERSQUdfSE9TVF9DTEFTUyA9ICdjZGstZHJhZyc7XG5cbi8qKlxuICogSW5qZWN0aW9uIHRva2VuIHRoYXQgY2FuIGJlIHVzZWQgdG8gcmVmZXJlbmNlIGluc3RhbmNlcyBvZiBgQ2RrRHJvcExpc3RgLiBJdCBzZXJ2ZXMgYXNcbiAqIGFsdGVybmF0aXZlIHRva2VuIHRvIHRoZSBhY3R1YWwgYENka0Ryb3BMaXN0YCBjbGFzcyB3aGljaCBjb3VsZCBjYXVzZSB1bm5lY2Vzc2FyeVxuICogcmV0ZW50aW9uIG9mIHRoZSBjbGFzcyBhbmQgaXRzIGRpcmVjdGl2ZSBtZXRhZGF0YS5cbiAqL1xuZXhwb3J0IGNvbnN0IENES19EUk9QX0xJU1QgPSBuZXcgSW5qZWN0aW9uVG9rZW48Q2RrRHJvcExpc3Q+KCdDZGtEcm9wTGlzdCcpO1xuXG4vKiogRWxlbWVudCB0aGF0IGNhbiBiZSBtb3ZlZCBpbnNpZGUgYSBDZGtEcm9wTGlzdCBjb250YWluZXIuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbY2RrRHJhZ10nLFxuICBleHBvcnRBczogJ2Nka0RyYWcnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBob3N0OiB7XG4gICAgJ2NsYXNzJzogRFJBR19IT1NUX0NMQVNTLFxuICAgICdbY2xhc3MuY2RrLWRyYWctZGlzYWJsZWRdJzogJ2Rpc2FibGVkJyxcbiAgICAnW2NsYXNzLmNkay1kcmFnLWRyYWdnaW5nXSc6ICdfZHJhZ1JlZi5pc0RyYWdnaW5nKCknLFxuICB9LFxuICBwcm92aWRlcnM6IFt7cHJvdmlkZTogQ0RLX0RSQUdfUEFSRU5ULCB1c2VFeGlzdGluZzogQ2RrRHJhZ31dLFxufSlcbmV4cG9ydCBjbGFzcyBDZGtEcmFnPFQgPSBhbnk+IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95ZWQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBwcml2YXRlIHN0YXRpYyBfZHJhZ0luc3RhbmNlczogQ2RrRHJhZ1tdID0gW107XG5cbiAgLyoqIFJlZmVyZW5jZSB0byB0aGUgdW5kZXJseWluZyBkcmFnIGluc3RhbmNlLiAqL1xuICBfZHJhZ1JlZjogRHJhZ1JlZjxDZGtEcmFnPFQ+PjtcblxuICAvKiogRWxlbWVudHMgdGhhdCBjYW4gYmUgdXNlZCB0byBkcmFnIHRoZSBkcmFnZ2FibGUgaXRlbS4gKi9cbiAgQENvbnRlbnRDaGlsZHJlbihDREtfRFJBR19IQU5ETEUsIHtkZXNjZW5kYW50czogdHJ1ZX0pIF9oYW5kbGVzOiBRdWVyeUxpc3Q8Q2RrRHJhZ0hhbmRsZT47XG5cbiAgLyoqIEVsZW1lbnQgdGhhdCB3aWxsIGJlIHVzZWQgYXMgYSB0ZW1wbGF0ZSB0byBjcmVhdGUgdGhlIGRyYWdnYWJsZSBpdGVtJ3MgcHJldmlldy4gKi9cbiAgQENvbnRlbnRDaGlsZChDREtfRFJBR19QUkVWSUVXKSBfcHJldmlld1RlbXBsYXRlOiBDZGtEcmFnUHJldmlldztcblxuICAvKiogVGVtcGxhdGUgZm9yIHBsYWNlaG9sZGVyIGVsZW1lbnQgcmVuZGVyZWQgdG8gc2hvdyB3aGVyZSBhIGRyYWdnYWJsZSB3b3VsZCBiZSBkcm9wcGVkLiAqL1xuICBAQ29udGVudENoaWxkKENES19EUkFHX1BMQUNFSE9MREVSKSBfcGxhY2Vob2xkZXJUZW1wbGF0ZTogQ2RrRHJhZ1BsYWNlaG9sZGVyO1xuXG4gIC8qKiBBcmJpdHJhcnkgZGF0YSB0byBhdHRhY2ggdG8gdGhpcyBkcmFnIGluc3RhbmNlLiAqL1xuICBASW5wdXQoJ2Nka0RyYWdEYXRhJykgZGF0YTogVDtcblxuICAvKiogTG9ja3MgdGhlIHBvc2l0aW9uIG9mIHRoZSBkcmFnZ2VkIGVsZW1lbnQgYWxvbmcgdGhlIHNwZWNpZmllZCBheGlzLiAqL1xuICBASW5wdXQoJ2Nka0RyYWdMb2NrQXhpcycpIGxvY2tBeGlzOiBEcmFnQXhpcztcblxuICAvKipcbiAgICogU2VsZWN0b3IgdGhhdCB3aWxsIGJlIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZSByb290IGRyYWdnYWJsZSBlbGVtZW50LCBzdGFydGluZyBmcm9tXG4gICAqIHRoZSBgY2RrRHJhZ2AgZWxlbWVudCBhbmQgZ29pbmcgdXAgdGhlIERPTS4gUGFzc2luZyBhbiBhbHRlcm5hdGUgcm9vdCBlbGVtZW50IGlzIHVzZWZ1bFxuICAgKiB3aGVuIHRyeWluZyB0byBlbmFibGUgZHJhZ2dpbmcgb24gYW4gZWxlbWVudCB0aGF0IHlvdSBtaWdodCBub3QgaGF2ZSBhY2Nlc3MgdG8uXG4gICAqL1xuICBASW5wdXQoJ2Nka0RyYWdSb290RWxlbWVudCcpIHJvb3RFbGVtZW50U2VsZWN0b3I6IHN0cmluZztcblxuICAvKipcbiAgICogTm9kZSBvciBzZWxlY3RvciB0aGF0IHdpbGwgYmUgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGVsZW1lbnQgdG8gd2hpY2ggdGhlIGRyYWdnYWJsZSdzXG4gICAqIHBvc2l0aW9uIHdpbGwgYmUgY29uc3RyYWluZWQuIElmIGEgc3RyaW5nIGlzIHBhc3NlZCBpbiwgaXQnbGwgYmUgdXNlZCBhcyBhIHNlbGVjdG9yIHRoYXRcbiAgICogd2lsbCBiZSBtYXRjaGVkIHN0YXJ0aW5nIGZyb20gdGhlIGVsZW1lbnQncyBwYXJlbnQgYW5kIGdvaW5nIHVwIHRoZSBET00gdW50aWwgYSBtYXRjaFxuICAgKiBoYXMgYmVlbiBmb3VuZC5cbiAgICovXG4gIEBJbnB1dCgnY2RrRHJhZ0JvdW5kYXJ5JykgYm91bmRhcnlFbGVtZW50OiBzdHJpbmcgfCBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiB8IEhUTUxFbGVtZW50O1xuXG4gIC8qKlxuICAgKiBBbW91bnQgb2YgbWlsbGlzZWNvbmRzIHRvIHdhaXQgYWZ0ZXIgdGhlIHVzZXIgaGFzIHB1dCB0aGVpclxuICAgKiBwb2ludGVyIGRvd24gYmVmb3JlIHN0YXJ0aW5nIHRvIGRyYWcgdGhlIGVsZW1lbnQuXG4gICAqL1xuICBASW5wdXQoJ2Nka0RyYWdTdGFydERlbGF5JykgZHJhZ1N0YXJ0RGVsYXk6IERyYWdTdGFydERlbGF5O1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBwb3NpdGlvbiBvZiBhIGBDZGtEcmFnYCB0aGF0IGlzIG91dHNpZGUgb2YgYSBkcm9wIGNvbnRhaW5lci5cbiAgICogQ2FuIGJlIHVzZWQgdG8gcmVzdG9yZSB0aGUgZWxlbWVudCdzIHBvc2l0aW9uIGZvciBhIHJldHVybmluZyB1c2VyLlxuICAgKi9cbiAgQElucHV0KCdjZGtEcmFnRnJlZURyYWdQb3NpdGlvbicpIGZyZWVEcmFnUG9zaXRpb246IFBvaW50O1xuXG4gIC8qKiBXaGV0aGVyIHN0YXJ0aW5nIHRvIGRyYWcgdGhpcyBlbGVtZW50IGlzIGRpc2FibGVkLiAqL1xuICBASW5wdXQoJ2Nka0RyYWdEaXNhYmxlZCcpXG4gIGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZGlzYWJsZWQgfHwgKHRoaXMuZHJvcENvbnRhaW5lciAmJiB0aGlzLmRyb3BDb250YWluZXIuZGlzYWJsZWQpO1xuICB9XG4gIHNldCBkaXNhYmxlZCh2YWx1ZTogQm9vbGVhbklucHV0KSB7XG4gICAgdGhpcy5fZGlzYWJsZWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICAgIHRoaXMuX2RyYWdSZWYuZGlzYWJsZWQgPSB0aGlzLl9kaXNhYmxlZDtcbiAgfVxuICBwcml2YXRlIF9kaXNhYmxlZDogYm9vbGVhbjtcblxuICAvKipcbiAgICogRnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCB0byBjdXN0b21pemUgdGhlIGxvZ2ljIG9mIGhvdyB0aGUgcG9zaXRpb24gb2YgdGhlIGRyYWcgaXRlbVxuICAgKiBpcyBsaW1pdGVkIHdoaWxlIGl0J3MgYmVpbmcgZHJhZ2dlZC4gR2V0cyBjYWxsZWQgd2l0aCBhIHBvaW50IGNvbnRhaW5pbmcgdGhlIGN1cnJlbnQgcG9zaXRpb25cbiAgICogb2YgdGhlIHVzZXIncyBwb2ludGVyIG9uIHRoZSBwYWdlLCBhIHJlZmVyZW5jZSB0byB0aGUgaXRlbSBiZWluZyBkcmFnZ2VkIGFuZCBpdHMgZGltZW5zaW9ucy5cbiAgICogU2hvdWxkIHJldHVybiBhIHBvaW50IGRlc2NyaWJpbmcgd2hlcmUgdGhlIGl0ZW0gc2hvdWxkIGJlIHJlbmRlcmVkLlxuICAgKi9cbiAgQElucHV0KCdjZGtEcmFnQ29uc3RyYWluUG9zaXRpb24nKSBjb25zdHJhaW5Qb3NpdGlvbj86IChcbiAgICB1c2VyUG9pbnRlclBvc2l0aW9uOiBQb2ludCxcbiAgICBkcmFnUmVmOiBEcmFnUmVmLFxuICAgIGRpbWVuc2lvbnM6IENsaWVudFJlY3QsXG4gICAgcGlja3VwUG9zaXRpb25JbkVsZW1lbnQ6IFBvaW50LFxuICApID0+IFBvaW50O1xuXG4gIC8qKiBDbGFzcyB0byBiZSBhZGRlZCB0byB0aGUgcHJldmlldyBlbGVtZW50LiAqL1xuICBASW5wdXQoJ2Nka0RyYWdQcmV2aWV3Q2xhc3MnKSBwcmV2aWV3Q2xhc3M6IHN0cmluZyB8IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBDb25maWd1cmVzIHRoZSBwbGFjZSBpbnRvIHdoaWNoIHRoZSBwcmV2aWV3IG9mIHRoZSBpdGVtIHdpbGwgYmUgaW5zZXJ0ZWQuIENhbiBiZSBjb25maWd1cmVkXG4gICAqIGdsb2JhbGx5IHRocm91Z2ggYENES19EUk9QX0xJU1RgLiBQb3NzaWJsZSB2YWx1ZXM6XG4gICAqIC0gYGdsb2JhbGAgLSBQcmV2aWV3IHdpbGwgYmUgaW5zZXJ0ZWQgYXQgdGhlIGJvdHRvbSBvZiB0aGUgYDxib2R5PmAuIFRoZSBhZHZhbnRhZ2UgaXMgdGhhdFxuICAgKiB5b3UgZG9uJ3QgaGF2ZSB0byB3b3JyeSBhYm91dCBgb3ZlcmZsb3c6IGhpZGRlbmAgb3IgYHotaW5kZXhgLCBidXQgdGhlIGl0ZW0gd29uJ3QgcmV0YWluXG4gICAqIGl0cyBpbmhlcml0ZWQgc3R5bGVzLlxuICAgKiAtIGBwYXJlbnRgIC0gUHJldmlldyB3aWxsIGJlIGluc2VydGVkIGludG8gdGhlIHBhcmVudCBvZiB0aGUgZHJhZyBpdGVtLiBUaGUgYWR2YW50YWdlIGlzIHRoYXRcbiAgICogaW5oZXJpdGVkIHN0eWxlcyB3aWxsIGJlIHByZXNlcnZlZCwgYnV0IGl0IG1heSBiZSBjbGlwcGVkIGJ5IGBvdmVyZmxvdzogaGlkZGVuYCBvciBub3QgYmVcbiAgICogdmlzaWJsZSBkdWUgdG8gYHotaW5kZXhgLiBGdXJ0aGVybW9yZSwgdGhlIHByZXZpZXcgaXMgZ29pbmcgdG8gaGF2ZSBhbiBlZmZlY3Qgb3ZlciBzZWxlY3RvcnNcbiAgICogbGlrZSBgOm50aC1jaGlsZGAgYW5kIHNvbWUgZmxleGJveCBjb25maWd1cmF0aW9ucy5cbiAgICogLSBgRWxlbWVudFJlZjxIVE1MRWxlbWVudD4gfCBIVE1MRWxlbWVudGAgLSBQcmV2aWV3IHdpbGwgYmUgaW5zZXJ0ZWQgaW50byBhIHNwZWNpZmljIGVsZW1lbnQuXG4gICAqIFNhbWUgYWR2YW50YWdlcyBhbmQgZGlzYWR2YW50YWdlcyBhcyBgcGFyZW50YC5cbiAgICovXG4gIEBJbnB1dCgnY2RrRHJhZ1ByZXZpZXdDb250YWluZXInKSBwcmV2aWV3Q29udGFpbmVyOiBQcmV2aWV3Q29udGFpbmVyO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHN0YXJ0cyBkcmFnZ2luZyB0aGUgaXRlbS4gKi9cbiAgQE91dHB1dCgnY2RrRHJhZ1N0YXJ0ZWQnKSByZWFkb25seSBzdGFydGVkOiBFdmVudEVtaXR0ZXI8Q2RrRHJhZ1N0YXJ0PiA9XG4gICAgbmV3IEV2ZW50RW1pdHRlcjxDZGtEcmFnU3RhcnQ+KCk7XG5cbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHVzZXIgaGFzIHJlbGVhc2VkIGEgZHJhZyBpdGVtLCBiZWZvcmUgYW55IGFuaW1hdGlvbnMgaGF2ZSBzdGFydGVkLiAqL1xuICBAT3V0cHV0KCdjZGtEcmFnUmVsZWFzZWQnKSByZWFkb25seSByZWxlYXNlZDogRXZlbnRFbWl0dGVyPENka0RyYWdSZWxlYXNlPiA9XG4gICAgbmV3IEV2ZW50RW1pdHRlc