UNPKG

ng-terminal

Version:

NgTerminal is a terminal component on Angular 17 or higher.

638 lines 96.4 kB
import { Component, ViewChild, Input, Output, EventEmitter, ChangeDetectionStrategy, } from '@angular/core'; import { Terminal } from '@xterm/xterm'; import { FitAddon } from '@xterm/addon-fit'; import { Subject } from 'rxjs'; import { LinearRenderService, } from './linear-render.service'; import * as i0 from "@angular/core"; import * as i1 from "./logging.service"; import * as i2 from "angular-resizable-element"; import * as i3 from "@angular/common"; import * as i4 from "./global-style/global-style.component"; export class NgTerminalComponent { /** * A datsource is an observable where NgTerminal reads charactors. */ set _dataSource(dataSource) { if (!dataSource) return; if (this.dataSourceSubscription != undefined) this.dataSourceSubscription.unsubscribe(); this.dataSource = dataSource; this.dataSourceSubscription = this.dataSource.subscribe((data) => this.write(data)); } /** * Toggle draggable. */ set draggable(draggable) { this._draggable = draggable; } get draggable() { return this._draggable; } setMinWidth(width) { this._minWidthInput = width; } setMinHeight(height) { this._minHeightInput = height; } setDraggable(draggable) { this._draggable = draggable; this.lastDraggedPosition = undefined; // Reset position values } setXtermOptions(options) { this._xtermOptions = options; this.linearRender.pushAndHandle({ time: new Date(), type: 'none' }); } setRows(rows) { if (this._rowsInput != rows) { this._rowsInput = rows; this.linearRender.pushAndHandle({ time: new Date(), type: 'rowChanged', }); } } setCols(cols) { if (this._colsInput != cols) { this._colsInput = cols; this.linearRender.pushAndHandle({ time: new Date(), type: 'columnChanged', }); } } setStyle(styleObject) { if (JSON.stringify(this._stylesInput ?? {}) != JSON.stringify(styleObject ?? {})) { this._stylesInput = styleObject; this.linearRender.pushAndHandle({ time: new Date(), type: 'none', }); } } constructor(renderer, //Render is being used for fast rendering without markForCheck(). hostRef, loggingService) { this.renderer = renderer; this.hostRef = hostRef; this.loggingService = loggingService; this.dataSubject = new Subject(); this.keySubject = new Subject(); this.keyInputSubjectSubscription = undefined; this.keyEventSubjectSubscription = undefined; this.allLogsSubjectSubscription = undefined; this.dataSourceSubscription = undefined; this.resizableObservers = []; this.dataSource = undefined; this.paddingSize = 5; this.stylesForResizeBox = { display: 'block' }; /** * @deprecated use (data)='' instead. * An emitter emits printable characters pushed from xterm's onData() when a user typed on the terminal. */ this.keyInputEmitter = new EventEmitter(); /** * @deprecated use (key)='' instead. * An emitter emits key and keybaord event pushed from xterm's onKey() when a user typed on the terminal. */ this.keyEventEmitter = new EventEmitter(); /** * An emitter emits printable characters pushed from xterm's onData() when a user typed on the terminal. */ this.dataEmitter = this.keyInputEmitter; /** * An emitter emits key and keybaord event pushed from xterm's onKey() when a user typed on the terminal. */ this.keyEmitter = this.keyEventEmitter; /** * An wrapper of {@link ITerminalOptions} for Xterm. */ this._xtermOptions = {}; this.lastDraggedPosition = undefined; this._draggable = false; this._stylesInput = {}; this.handleToCheckLazyContainer = undefined; this.lastDetectedWidth = 0; this.linearRender = new LinearRenderService(hostRef); } setup() { if (this.xterm) { this.xterm.onData((input) => { this.dataSubject.next(input); }); this.xterm.onKey((e) => { this.keySubject.next(e); }); } this.keyInputSubjectSubscription = this.dataSubject.subscribe((data) => { this.keyInputEmitter.emit(data); }); this.keyEventSubjectSubscription = this.keySubject.subscribe((e) => { this.keyEventEmitter.emit(e); }); this.setupResizeObservers(); // if (ob3) this.resizableObservers.push(ob3); this.allLogsSubjectSubscription = this.linearRender.renderObservable.subscribe((change) => { if (change) this.coordinateOuterAndTerminal(change); else this.coordinateOuterAndTerminal(change); this.linearRender.handleNextOne(); }); this.linearRender.handleNextOne(); } /** * set dimensions */ setOuterDimensions(left, top, width, height) { this.linearRender.pushAndHandle({ time: new Date(), type: 'dragged', dragged: { draggedWidth: `${width}px`, draggedHeight: `${height}px` }, }); } applyStylesToResizeBox() { Object.keys(this.stylesForResizeBox) .map((key) => { return { key, value: this.stylesForResizeBox[key] }; }) .forEach(({ key, value }) => { if (this.resizeBox) { if (value) this.renderer.setStyle(this.resizeBox.nativeElement, key, value); else { this.renderer.removeStyle(this.resizeBox.nativeElement, key); } } }); this.stylesForResizeBox = this.stylesForResizeBox; //invalidate } ngOnInit() { } /** * It creates new terminal in #terminal. */ ngAfterViewInit() { this.fitAddon = new FitAddon(); this.xterm = new Terminal({ allowProposedApi: true, }); if (!this.terminalOuter.nativeElement.isConnected) { this.handleToCheckLazyContainer = setInterval(() => { if (this.terminalOuter.nativeElement.isConnected) { try { this.loggingService.log(() => console.debug("The container's been connected.")); this.xterm.open(this.terminalOuter.nativeElement); this.xterm.loadAddon(this.fitAddon); this.setup(); this.linearRender.pushAndHandle({ time: new Date(), type: 'none' }); } finally { if (this.handleToCheckLazyContainer) clearInterval(this.handleToCheckLazyContainer); } } }, 500); } else { this.xterm.open(this.terminalOuter.nativeElement); this.xterm.loadAddon(this.fitAddon); this.setup(); this.linearRender.pushAndHandle({ time: new Date(), type: 'none' }); } } ngOnChanges(changes) { this.loggingService.log(() => console.group('onChanges')); this.loggingService.log(() => console.debug('prop: ', changes)); this.loggingService.log(() => console.groupEnd()); if (changes?.['_rowsInput']) { if (changes?.['_rowsInput']?.previousValue != changes?.['_rowsInput']?.currentValue) { this.linearRender.pushAndHandle({ time: new Date(), type: 'rowChanged', }); } } if (changes?.['_colsInput']) { if (changes?.['_colsInput']?.previousValue != changes?.['_colsInput']?.currentValue) { this.linearRender.pushAndHandle({ time: new Date(), type: 'columnChanged', }); } } if (changes?.['draggable']) this.linearRender.pushAndHandle({ time: new Date(), type: 'none' }); } /** * It serves a callback function to adjust the dimensions of the xterm-screen, xterm-view, and resize box * after making any changes to the outer box, rows, or columns, or when the resize box is being dragged. * * There several factors that affect dimensions, as I mentioned earlier. * Regardless of whether the draggable feature is on, if new row or column value is input, this value will be applied. * - Draggable = New specified Row/Column value > Full (Default) * @param change This argument represents a single change that occured. * @returns */ coordinateOuterAndTerminal(change) { this.loggingService.log(() => console.debug(`changeList: ${JSON.stringify(change)}`)); if (!this.xterm) return; const isHostElementVisible = this.hostRef.nativeElement?.offsetParent !== null; if (!isHostElementVisible) { // Do nothing if the host element is invisible. this.loggingService.log(() => console.debug('`display` of host element was set to `none`')); return; } this.doUpdateXtermStyles(); this.doAdjustDimensionOfResizeBox(change); this.doAdjustSizeOfXtermScreen(change); this.doUpdateViewportAndResizeBoxWithPixcelUnit(); } /** * apply options to the xterm terminal * @returns */ doUpdateXtermStyles() { if (!this.xterm) return; this.xterm.options = { ...this._xtermOptions }; // apply the theme to the background of the handle if (this._xtermOptions.theme?.background) { if (!this.resizeHandleStyleRule) this.resizeHandleStyleRule = this.findCssStyleRule('.resize-handle['); if (this.resizeHandleStyleRule) this.resizeHandleStyleRule.style.backgroundColor = this._xtermOptions.theme.background; } if (this._xtermOptions.theme?.border) { if (!this.resizeHandleActiveStyleRule) this.resizeHandleActiveStyleRule = this.findCssStyleRule('.handle-active'); if (this.resizeHandleActiveStyleRule) this.resizeHandleActiveStyleRule.style.backgroundColor = this._xtermOptions.theme.border; } } /** * If the resize handles are moved, the resize box adjusts to the new dimensions; * otherwise, it defaults to a maximized size. * @param change */ doAdjustDimensionOfResizeBox(change) { this.stylesForResizeBox = { ...this.stylesForResizeBox, ...this._stylesInput, width: this.stylesForResizeBox.width, height: this.stylesForResizeBox.height, }; // Reset styles of the resize element if (change.type === 'dragged') { const minWidth = this._minWidthInput ?? 24; const minHeight = this._minHeightInput ?? 24; const width = parseInt(change.dragged.draggedWidth) > minWidth ? change.dragged.draggedWidth : `${minWidth}px`; const height = parseInt(change.dragged.draggedHeight) > minHeight ? change.dragged.draggedHeight : `${minHeight}px`; this.stylesForResizeBox.width = width; this.stylesForResizeBox.height = height; this.lastDraggedPosition = { width, height, }; this.applyStylesToResizeBox(); } else if (!(this.draggable && this.lastDraggedPosition)) { // When `_colsInput` and `draggable` is not enabled, // it fits the size to the host element. const currentHostWidth = getComputedStyle(this.hostRef.nativeElement).width; const detectBoxWidth = getComputedStyle(this.detectBox.nativeElement).width; let smallParent = false; if (parseFloat(detectBoxWidth) < parseFloat(currentHostWidth)) { // the width of the parent is smaller than that of resize-box element smallParent = true; } if (smallParent) { // It's been written to solve https://github.com/qwefgh90/ng-terminal/issues/79 // If the width of the flex-box (that is the parent of the host element) is smaller than that of child element, the host element is adjusted to the width of child element // host element: 1000px, resize-box(child): 985px -> host element: 985px, resize-box(child): 970px -> ... -> stop // This code check if the parent element (that is the parent of `<ng-terminal>), is smaller than `.resize-box` // and ensures that the width of the `<ng-terminal>` adjusts to match that of the parent element rather than the child elements, in the subsequent events. this.stylesForResizeBox.width = `${parseFloat(detectBoxWidth)}px`; this.applyStylesToResizeBox(); } else { // but if the dimension of host element is resized, update width and height // If `_rowsInput` is specified, NgTerminal keep the current height; otherwise, the height is set to 100% if (!this._rowsInput) this.stylesForResizeBox.height = '100%'; if (!this._colsInput) this.stylesForResizeBox.width = '100%'; this.applyStylesToResizeBox(); } } } /** * This function uses fitAddon() to adjust the dimension of xterm-screen to character unit * If the draggable value is true or there are no fixed values for the row or column, * it fits the xterm terminal boxes into the resize box; * otherwise, it resizes the xterm terminal with specified row and column values. */ doAdjustSizeOfXtermScreen(change) { if (!this.xterm) return; if ((change.type == 'rowChanged' && this._rowsInput) || (change.type == 'columnChanged' && this._colsInput)) { this.xterm.resize(this._colsInput ?? this.xterm.cols, this._rowsInput ?? this.xterm.rows); } else { if (this.xterm.element) { // The fitAddon.fit() operation doesn't recognize the padding values of terminalOuter. // It seems to be using the padding values of xterm element instead. // Therefore, we establish a brief time frame to adjust the padding values before and after executing fitAddon.fit(). // If this line is removed, when dragging resize-box vertically, the width is decreased. this.xterm.element.style.paddingLeft = `${this.paddingSize}px`; this.printDimension('Before fitAddon.fit() of Xterm'); this.fitAddon?.fit(); this.printDimension('After fitAddon.fit() of Xterm'); this.xterm.element.style.paddingLeft = `${0}px`; } } } /** * This functions sets width of the resize box, xterm-viewport and xterm-screen with specific pixel values. */ doUpdateViewportAndResizeBoxWithPixcelUnit() { if (this.xterm?.element) { let xtermScreen = this.xterm.element.getElementsByClassName('xterm-screen')[0]; let xtermViewport = this.xterm.element.getElementsByClassName('xterm-viewport')[0]; const screenWidth = xtermScreen.clientWidth; const screenHeight = xtermScreen.clientHeight; const core = this.underlying._core; const scrollBarWidth = core.viewport.scrollBarWidth; const hostWidth = parseInt(getComputedStyle(this.hostRef.nativeElement).width); // It fixes a bug where the viewport's width isn't updated by fitAddon.fit() this.renderer.setStyle(xtermViewport, 'width', `${screenWidth + scrollBarWidth}px`); // It adjusts the dimension of the resize box to the xterm-screen element. const calulatedBoxWidth = screenWidth + scrollBarWidth + this.paddingSize * 2; const componentElement = this.hostRef.nativeElement; const componentWith = parseInt(getComputedStyle(componentElement).width); const restrictedWidth = calulatedBoxWidth > componentWith ? componentWith : calulatedBoxWidth; this.stylesForResizeBox = { ...this.stylesForResizeBox, width: `${restrictedWidth}px`, height: `${screenHeight + this.paddingSize * 2}px`, }; this.applyStylesToResizeBox(); this.printDimension('After update the dimensions for all boxes with pixel values'); } } printDimension(title) { if (this.xterm?.element) { let resizeBox = this.resizeBox.nativeElement; let xtermScreen = this.xterm.element.getElementsByClassName('xterm-screen')[0]; let xtermViewport = this.xterm.element.getElementsByClassName('xterm-viewport')[0]; const screenWidth = xtermScreen.clientWidth; const screenHeight = xtermScreen.clientHeight; this.loggingService.log(() => console.group(`${title}`)); this.loggingService.log(() => console.debug(`width(resizeBox): ${getComputedStyle(resizeBox).width}, width(viewport): ${getComputedStyle(xtermViewport).width}, width(screen): ${screenWidth} scrollBarWidth: ${this.scrollBarWidth}`)); this.loggingService.log(() => console.debug(`height(resizeBox): ${getComputedStyle(resizeBox).height}, height(viewport) ${getComputedStyle(xtermViewport).height}, height(screen): ${screenHeight}`)); this.loggingService.log(() => console.groupEnd()); } } /** * If pushAndHandle() were used, there could be an issue * because it can adjust the size of elements during a loop of ResizeObserver. */ setupResizeObservers() { this.resizableObservers = []; let ob1 = this.observeXtermViewportDimension(); let ob2 = this.observeHostDimension(); if (ob1) this.resizableObservers.push(ob1); if (ob2) this.resizableObservers.push(ob2); } observeXtermViewportDimension() { let xtermViewport = this.terminalOuter.nativeElement.querySelector('.xterm-viewport'); if (xtermViewport) { const resizeObserver = new ResizeObserver((entries) => { const outerDivWidth = this.terminalOuter.nativeElement?.clientWidth; const outerDivHeight = this.terminalOuter.nativeElement?.clientHeight; for (let entry of entries) { if (entry.contentBoxSize.length > 0) { let width = entry.target.clientWidth; let height = entry.target.clientHeight; if ((outerDivWidth && width > outerDivWidth) || (outerDivHeight && height > outerDivHeight)) { this.loggingService.log(() => console.debug('Changes on a xterm viewport element will be handled.')); this.linearRender.pushAndHandle({ time: new Date(), type: 'xtermViewportExceedingOuterDiv', xtermViewportExceedingOuterDiv: { width: `${width}`, height: `${height}`, outerDivWidth: `${outerDivWidth}`, outerDivHeight: `${outerDivHeight}`, }, }, true); } } } }); resizeObserver.observe(xtermViewport); return resizeObserver; } else { this.loggingService.log(() => console.error('Invalid state is detected. xterm element should exist below .terminal-outer.')); } return undefined; } observeHostDimension() { let hostElement = this.hostRef.nativeElement; let detectBox = this.detectBox.nativeElement; if (hostElement && detectBox) { const resizeObserver = new ResizeObserver((entries) => { for (let entry of entries) { if (entry.target === hostElement) { if (entry.contentBoxSize.length > 0) { let width = getComputedStyle(entry.target).width; let height = getComputedStyle(entry.target).height; if (parseInt(width) >= 0 && parseInt(height) >= 0) { this.loggingService.log(() => console.debug('Changes on a host element will be handled.')); this.linearRender.pushAndHandle({ time: new Date(), type: 'hostResized', hostResized: { width: `${width}`, height: `${height}` }, }, true); } } } if (entry.target === detectBox) { if (entry.contentBoxSize.length > 0) { let width = getComputedStyle(entry.target).width; if (parseInt(width) >= 0 && parseInt(width) <= this.lastDetectedWidth) { this.loggingService.log(() => console.debug('Changes on a detect-box element will be handled.')); this.linearRender.pushAndHandle({ time: new Date(), type: 'detectBoxResized', detectBoxResized: { width: `${width}` }, }, true); } this.lastDetectedWidth = parseInt(width); } } } }); resizeObserver.observe(hostElement); resizeObserver.observe(detectBox); return resizeObserver; } else { this.loggingService.log(() => console.error('Invalid state is detected. xterm element should exist below .terminal-outer.')); } return undefined; } /** * clean all resources */ ngOnDestroy() { this.resizableObservers.forEach((ob) => ob.disconnect()); if (this.keyInputSubjectSubscription) this.keyInputSubjectSubscription.unsubscribe(); if (this.dataSourceSubscription) this.dataSourceSubscription.unsubscribe(); if (this.keyEventSubjectSubscription) this.keyEventSubjectSubscription.unsubscribe(); if (this.allLogsSubjectSubscription) this.allLogsSubjectSubscription.unsubscribe(); if (this.handleToCheckLazyContainer) clearInterval(this.handleToCheckLazyContainer); if (this.xterm) this.xterm.dispose(); this.loggingService.log(() => console.debug('All resources has been cleaned up.')); } write(chars) { this.xterm?.write(chars); } get keyInput() { return this.dataSubject; } onData() { return this.dataSubject; } get keyEventInput() { return this.keySubject; } onKey() { return this.keySubject; } get underlying() { return this.xterm; } get isDraggableOnEdgeActivated() { // return this.displayOption.activateDraggableOnEdge != undefined && this.displayOption.fixedGrid == undefined; return this._draggable; } get scrollBarWidth() { const core = this.underlying._core; return core.viewport.scrollBarWidth; } /** * After user coordinate dimensions of terminal, it's called. * @param left * @param top * @param width * @param height */ onResizeEnd(left, top, width, height) { this.setOuterDimensions(left, top, width, height); } /** * Before onResizeEnd is called, it valiates dimensions to change. * @param re dimension to be submitted from resizable stuff */ validatorFactory() { const comp = this; return (re) => { if (this._draggable) { return true; } else return false; }; } findCssStyleRule(containingSelector) { for (let i = 0; i < document.styleSheets.length; i++) { let sheet = document.styleSheets.item(i); if (sheet) { for (let i = 0; i < sheet.cssRules.length; i++) { let rule = sheet.cssRules.item(i); if ('selectorText' in rule) if (rule.selectorText.includes(containingSelector)) return rule; } } } return undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgTerminalComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.LoggingService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NgTerminalComponent, selector: "ng-terminal", inputs: { _dataSource: ["dataSource", "_dataSource"], _rowsInput: ["rows", "_rowsInput"], _colsInput: ["cols", "_colsInput"], _minWidthInput: ["minWidth", "_minWidthInput"], _minHeightInput: ["minHeight", "_minHeightInput"], draggable: "draggable", _xtermOptions: ["xtermOptions", "_xtermOptions"] }, outputs: { keyInputEmitter: "keyInput", keyEventEmitter: "keyEvent", dataEmitter: "data", keyEmitter: "key" }, providers: [LinearRenderService], viewQueries: [{ propertyName: "terminalOuter", first: true, predicate: ["terminal"], descendants: true, static: true }, { propertyName: "resizeBox", first: true, predicate: ["resizeBox"], descendants: true, static: true }, { propertyName: "detectBox", first: true, predicate: ["detectBox"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Hierarchy: parent element(user) > host element(ng-terminal) > resize-box element > outer element -->\n<global-style></global-style>\n<div mwlResizable #resizeBox class=\"resize-box\" [validateResize]=\"validatorFactory()\" [enableGhostResize]=\"true\"\n (resizeEnd)=\"onResizeEnd($event.rectangle.left, $event.rectangle.top, $event.rectangle.width??0, $event.rectangle.height??0)\">\n <div #terminal class=\"terminal-outer\">\n </div>\n <div class=\"resize-handle resize-handle-top\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"{ top: false }\"></div>\n <div class=\"resize-handle resize-handle-left\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"{ left: false }\"></div>\n <div class=\"resize-handle resize-handle-right\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"isDraggableOnEdgeActivated ? { right: true } : { right: false }\"></div>\n <div class=\"resize-handle resize-handle-bottom\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"isDraggableOnEdgeActivated ? { bottom: true } : { bottom: false }\"></div>\n</div>\n<div #detectBox style=\"width: 100%; height: 0px; position: absolute;\">\n</div>", styles: [".terminal-outer{box-sizing:border-box;height:100%;width:100%;padding:5px}:host{display:block;height:100%;width:100%}.resize-box{box-sizing:border-box;height:100%;width:100%;position:relative}div>.handle-active{z-index:100;background-color:#85858a!important}.resize-handle{background-color:#000}.resize-handle-top.handle-active,.resize-handle-bottom.handle-active{cursor:row-resize}.resize-handle-left.handle-active,.resize-handle-right.handle-active{cursor:col-resize}.resize-handle-top,.resize-handle-bottom{position:absolute;height:5px;width:100%}.resize-handle-top{top:0}.resize-handle-bottom{bottom:0}.resize-handle-left,.resize-handle-right{position:absolute;height:100%;width:5px}.resize-handle-left{left:0;top:0}.resize-handle-right{right:0;top:0}\n"], dependencies: [{ kind: "directive", type: i2.ResizableDirective, selector: "[mwlResizable]", inputs: ["validateResize", "enableGhostResize", "resizeSnapGrid", "resizeCursors", "ghostElementPositioning", "allowNegativeResizes", "mouseMoveThrottleMS"], outputs: ["resizeStart", "resizing", "resizeEnd"], exportAs: ["mwlResizable"] }, { kind: "directive", type: i2.ResizeHandleDirective, selector: "[mwlResizeHandle]", inputs: ["resizeEdges", "resizableContainer"] }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i4.GlobalStyleComponent, selector: "global-style" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgTerminalComponent, decorators: [{ type: Component, args: [{ selector: 'ng-terminal', providers: [LinearRenderService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Hierarchy: parent element(user) > host element(ng-terminal) > resize-box element > outer element -->\n<global-style></global-style>\n<div mwlResizable #resizeBox class=\"resize-box\" [validateResize]=\"validatorFactory()\" [enableGhostResize]=\"true\"\n (resizeEnd)=\"onResizeEnd($event.rectangle.left, $event.rectangle.top, $event.rectangle.width??0, $event.rectangle.height??0)\">\n <div #terminal class=\"terminal-outer\">\n </div>\n <div class=\"resize-handle resize-handle-top\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"{ top: false }\"></div>\n <div class=\"resize-handle resize-handle-left\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"{ left: false }\"></div>\n <div class=\"resize-handle resize-handle-right\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"isDraggableOnEdgeActivated ? { right: true } : { right: false }\"></div>\n <div class=\"resize-handle resize-handle-bottom\" mwlResizeHandle [ngClass]=\"{'handle-active' : isDraggableOnEdgeActivated}\"\n [resizeEdges]=\"isDraggableOnEdgeActivated ? { bottom: true } : { bottom: false }\"></div>\n</div>\n<div #detectBox style=\"width: 100%; height: 0px; position: absolute;\">\n</div>", styles: [".terminal-outer{box-sizing:border-box;height:100%;width:100%;padding:5px}:host{display:block;height:100%;width:100%}.resize-box{box-sizing:border-box;height:100%;width:100%;position:relative}div>.handle-active{z-index:100;background-color:#85858a!important}.resize-handle{background-color:#000}.resize-handle-top.handle-active,.resize-handle-bottom.handle-active{cursor:row-resize}.resize-handle-left.handle-active,.resize-handle-right.handle-active{cursor:col-resize}.resize-handle-top,.resize-handle-bottom{position:absolute;height:5px;width:100%}.resize-handle-top{top:0}.resize-handle-bottom{bottom:0}.resize-handle-left,.resize-handle-right{position:absolute;height:100%;width:5px}.resize-handle-left{left:0;top:0}.resize-handle-right{right:0;top:0}\n"] }] }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.LoggingService }], propDecorators: { keyInputEmitter: [{ type: Output, args: ['keyInput'] }], keyEventEmitter: [{ type: Output, args: ['keyEvent'] }], dataEmitter: [{ type: Output, args: ['data'] }], keyEmitter: [{ type: Output, args: ['key'] }], _dataSource: [{ type: Input, args: ['dataSource'] }], _rowsInput: [{ type: Input, args: ['rows'] }], _colsInput: [{ type: Input, args: ['cols'] }], _minWidthInput: [{ type: Input, args: ['minWidth'] }], _minHeightInput: [{ type: Input, args: ['minHeight'] }], draggable: [{ type: Input, args: ['draggable'] }], _xtermOptions: [{ type: Input, args: ['xtermOptions'] }], terminalOuter: [{ type: ViewChild, args: ['terminal', { static: true }] }], resizeBox: [{ type: ViewChild, args: ['resizeBox', { static: true }] }], detectBox: [{ type: ViewChild, args: ['detectBox', { static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctdGVybWluYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctdGVybWluYWwvc3JjL2xpYi9uZy10ZXJtaW5hbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy10ZXJtaW5hbC9zcmMvbGliL25nLXRlcm1pbmFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBRVQsU0FBUyxFQUVULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUdaLHVCQUF1QixHQU94QixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQW9CLFFBQVEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMxRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUFFLE9BQU8sRUFBNEIsTUFBTSxNQUFNLENBQUM7QUFFekQsT0FBTyxFQUNMLG1CQUFtQixHQUVwQixNQUFNLHlCQUF5QixDQUFDOzs7Ozs7QUFVakMsTUFBTSxPQUFPLG1CQUFtQjtJQStDOUI7O09BRUc7SUFDSCxJQUNJLFdBQVcsQ0FBQyxVQUEwQztRQUN4RCxJQUFJLENBQUMsVUFBVTtZQUFFLE9BQU87UUFDeEIsSUFBSSxJQUFJLENBQUMsc0JBQXNCLElBQUksU0FBUztZQUMxQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDNUMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDL0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FDakIsQ0FBQztJQUNKLENBQUM7SUEwQkQ7O09BRUc7SUFDSCxJQUNJLFNBQVMsQ0FBQyxTQUFrQjtRQUM5QixJQUFJ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