UNPKG

ng-terminal

Version:

NgTerminal is a terminal component on Angular 16 or higher.

1 lines 78.9 kB
{"version":3,"file":"ng-terminal.mjs","sources":["../../../projects/ng-terminal/src/lib/linear-render.service.ts","../../../projects/ng-terminal/src/lib/module-options.ts","../../../projects/ng-terminal/src/lib/logging.service.ts","../../../projects/ng-terminal/src/lib/global-style/global-style.component.ts","../../../projects/ng-terminal/src/lib/global-style/global-style.component.html","../../../projects/ng-terminal/src/lib/ng-terminal.component.ts","../../../projects/ng-terminal/src/lib/ng-terminal.component.html","../../../projects/ng-terminal/src/lib/ng-terminal.module.ts","../../../projects/ng-terminal/src/lib/functions-using-csi.ts","../../../projects/ng-terminal/src/public-api.ts","../../../projects/ng-terminal/src/ng-terminal.ts"],"sourcesContent":["import { Injectable, ElementRef, OnDestroy } from '@angular/core';\nimport { Subject, Observable } from 'rxjs';\n\n/**\n *\n * In the past, indivisual property changes caused very unexpected behavior on NgTerminal.\n * To solve issues related to property changes, Queue is applied.\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class LinearRenderService implements OnDestroy {\n constructor(private hostRef: ElementRef) {}\n\n private handlerToCheckElementConnection?: ReturnType<typeof setInterval> =\n undefined;\n\n /**\n * This queue has items to have a influence on the view and items are handled in order.\n */\n private propertyChangeQueue: PropertyChangeSet[] = [];\n private itemsToBeHandled = new Subject<PropertyChangeSet>();\n\n get renderObservable(): Observable<PropertyChangeSet> {\n return this.itemsToBeHandled;\n }\n\n /**\n * {@link handleNextOne()} calls {@link handleImmediate()} if an element is connected.\n * Otherwise, {@link pollAndHandle()} is called.\n */\n public handleNextOne(lazy = false) {\n if (!this.hostRef.nativeElement.isConnected || lazy) {\n this.pollAndHandle(\n !this.hostRef.nativeElement.isConnected\n ? 'NOT_CONNECTED_ELEMENT'\n : 'LAZY'\n );\n } else {\n this.handleImmediate();\n }\n }\n\n /**\n * This method pushes item into {@link propertyChangeQueue}.\n * @param item\n */\n public pushAndHandle(item: PropertyChangeSet, lazy = false) {\n let changeWithDefault = {\n ...item,\n };\n this.propertyChangeQueue.push(changeWithDefault);\n this.handleNextOne(lazy);\n }\n\n /**\n * {@link pollAndHandle()} continues checking whether new item is put on a queue to call {@link handleImmediate()}.\n */\n private pollAndHandle(mode: 'NOT_CONNECTED_ELEMENT' | 'LAZY') {\n const pollFunction = () => {\n if (this.handlerToCheckElementConnection) return;\n const interval = setInterval(\n () => {\n if (this.hostRef.nativeElement.isConnected) {\n clearInterval(interval);\n this.handlerToCheckElementConnection = undefined;\n this.handleImmediate();\n }\n },\n mode === 'NOT_CONNECTED_ELEMENT' ? 500 : 30\n );\n this.handlerToCheckElementConnection = interval;\n };\n // Start polling\n pollFunction();\n }\n\n /**\n * Handle a next set of changes if it exists.\n */\n private handleImmediate = () => {\n if (!this.handlerToCheckElementConnection) {\n let list = this.propertyChangeQueue.splice(0, 1);\n if (list.length == 1) {\n this.itemsToBeHandled.next(list[0]);\n }\n }\n };\n\n ngOnDestroy(): void {\n if (this.handlerToCheckElementConnection)\n clearInterval(this.handlerToCheckElementConnection);\n }\n}\n\nexport type PropertyChangeSet =\n | { time: Date; type: 'rowChanged'}\n | { time: Date; type: 'columnChanged'}\n | {\n time: Date; type: 'dragged';\n dragged: { draggedWidth: string; draggedHeight: string };\n }\n | { time: Date; type: 'hostResized'; hostResized: { width: string; height: string } }\n | { time: Date; type: 'detectBoxResized'; detectBoxResized: { width: string } }\n | {\n time: Date; type: 'xtermViewportExceedingOuterDiv';\n xtermViewportExceedingOuterDiv: {\n width: string;\n height: string;\n outerDivWidth: string;\n outerDivHeight: string;\n };\n }\n | { time: Date; type: 'none' };\n","\nexport class ModuleOptions {\n enableLog: boolean = true;\n }","import { Injectable, Optional } from '@angular/core';\nimport { ModuleOptions } from './module-options';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class LoggingService {\n private enableLog: boolean = false;\n constructor(@Optional() _options?: ModuleOptions) {\n if (_options) this.enableLog = _options.enableLog;\n }\n\n log(loggingFunc: () => void) {\n if (this.enableLog) loggingFunc();\n }\n}\n","import { Component, OnInit, ViewEncapsulation } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'global-style',\r\n templateUrl: './global-style.component.html',\r\n styleUrls: ['../../../../../node_modules/xterm/css/xterm.css'], //global styles\r\n encapsulation: ViewEncapsulation.None\r\n})\r\nexport class GlobalStyleComponent implements OnInit {\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n}\r\n","","import {\n Component,\n OnInit,\n ViewChild,\n ElementRef,\n Input,\n Output,\n EventEmitter,\n OnDestroy,\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n OnChanges,\n Renderer2,\n SimpleChanges,\n isDevMode,\n Optional,\n} from '@angular/core';\nimport { ITerminalOptions, Terminal } from '@xterm/xterm';\nimport { FitAddon } from '@xterm/addon-fit';\nimport { NgTerminal } from './ng-terminal';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { ResizeEvent } from 'angular-resizable-element';\nimport {\n LinearRenderService,\n PropertyChangeSet,\n} from './linear-render.service';\nimport { LoggingService } from './logging.service';\n\n@Component({\n selector: 'ng-terminal',\n templateUrl: './ng-terminal.component.html',\n styleUrls: ['./ng-terminal.component.css'],\n providers: [LinearRenderService],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class NgTerminalComponent\n implements OnInit, OnChanges, AfterViewInit, NgTerminal, OnDestroy\n{\n private linearRender: LinearRenderService;\n private xterm?: Terminal;\n private fitAddon?: FitAddon;\n private dataSubject: Subject<string> = new Subject<string>();\n private keySubject = new Subject<{ key: string; domEvent: KeyboardEvent }>();\n\n private keyInputSubjectSubscription?: Subscription = undefined;\n private keyEventSubjectSubscription?: Subscription = undefined;\n private allLogsSubjectSubscription?: Subscription = undefined;\n private dataSourceSubscription?: Subscription = undefined;\n private resizableObservers: ResizeObserver[] = [];\n private dataSource?: Observable<string> = undefined;\n private readonly paddingSize = 5;\n stylesForResizeBox: Partial<CSSStyleDeclaration> = { display: 'block' };\n\n /**\n * @deprecated use (data)='' instead.\n * An emitter emits printable characters pushed from xterm's onData() when a user typed on the terminal.\n */\n @Output('keyInput')\n keyInputEmitter = new EventEmitter<string>();\n\n /**\n * @deprecated use (key)='' instead.\n * An emitter emits key and keybaord event pushed from xterm's onKey() when a user typed on the terminal.\n */\n @Output('keyEvent')\n keyEventEmitter = new EventEmitter<{\n key: string;\n domEvent: KeyboardEvent;\n }>();\n\n /**\n * An emitter emits printable characters pushed from xterm's onData() when a user typed on the terminal.\n */\n @Output('data')\n dataEmitter = this.keyInputEmitter;\n\n /**\n * An emitter emits key and keybaord event pushed from xterm's onKey() when a user typed on the terminal.\n */\n @Output('key')\n keyEmitter = this.keyEventEmitter;\n\n /**\n * A datsource is an observable where NgTerminal reads charactors.\n */\n @Input('dataSource')\n set _dataSource(dataSource: Observable<string> | undefined) {\n if (!dataSource) return;\n if (this.dataSourceSubscription != undefined)\n this.dataSourceSubscription.unsubscribe();\n this.dataSource = dataSource;\n this.dataSourceSubscription = this.dataSource.subscribe((data) =>\n this.write(data)\n );\n }\n\n /**\n * Change the row count of a terminal immediately.\n */\n @Input('rows')\n _rowsInput?: number;\n\n /**\n * Change the column count of a terminal immediately.\n */\n @Input('cols')\n _colsInput?: number;\n\n /**\n * Set the minimum width to limit dragging.\n */\n @Input('minWidth')\n _minWidthInput?: number;\n\n /**\n * Set the minimum height to limit dragging.\n */\n @Input('minHeight')\n _minHeightInput?: number;\n\n /**\n * Toggle draggable.\n */\n @Input('draggable')\n set draggable(draggable: boolean) {\n this._draggable = draggable;\n }\n\n /**\n * An wrapper of {@link ITerminalOptions} for Xterm.\n */\n @Input('xtermOptions')\n _xtermOptions: ITerminalOptions & { theme?: { border?: string } } = {};\n\n @ViewChild('terminal', { static: true })\n terminalOuter!: ElementRef<HTMLDivElement>;\n\n @ViewChild('resizeBox', { static: true })\n resizeBox!: ElementRef<HTMLDivElement>;\n\n @ViewChild('detectBox', { static: true })\n detectBox!: ElementRef<HTMLDivElement>;\n\n get draggable() {\n return this._draggable;\n }\n\n lastDraggedPosition?: { width: string; height: string } = undefined;\n\n _draggable: boolean = false;\n\n _stylesInput: any = {};\n\n setMinWidth(width: number): void {\n this._minWidthInput = width;\n }\n\n setMinHeight(height: number): void {\n this._minHeightInput = height;\n }\n\n setDraggable(draggable: boolean): void {\n this._draggable = draggable;\n this.lastDraggedPosition = undefined; // Reset position values\n }\n\n setXtermOptions(\n options: ITerminalOptions & { theme?: { border?: string } }\n ): void {\n this._xtermOptions = options;\n this.linearRender.pushAndHandle({ time: new Date(), type: 'none' });\n }\n\n setRows(rows: number): void {\n if (this._rowsInput != rows) {\n this._rowsInput = rows;\n this.linearRender.pushAndHandle({\n time: new Date(),\n type: 'rowChanged',\n });\n }\n }\n\n setCols(cols: number): void {\n if (this._colsInput != cols) {\n this._colsInput = cols;\n this.linearRender.pushAndHandle({\n time: new Date(),\n type: 'columnChanged',\n });\n }\n }\n\n setStyle(styleObject: any): void {\n if (\n JSON.stringify(this._stylesInput ?? {}) !=\n JSON.stringify(styleObject ?? {})\n ) {\n this._stylesInput = styleObject;\n this.linearRender.pushAndHandle({\n time: new Date(),\n type: 'none',\n });\n }\n }\n\n handleToCheckLazyContainer?: ReturnType<typeof setInterval> = undefined;\n\n constructor(\n private renderer: Renderer2, //Render is being used for fast rendering without markForCheck().\n private hostRef: ElementRef<HTMLElement>,\n private loggingService: LoggingService,\n ) {\n this.linearRender = new LinearRenderService(hostRef);\n }\n\n private setup() {\n if (this.xterm) {\n this.xterm.onData((input) => {\n this.dataSubject.next(input);\n });\n this.xterm.onKey((e) => {\n this.keySubject.next(e);\n });\n }\n this.keyInputSubjectSubscription = this.dataSubject.subscribe((data) => {\n this.keyInputEmitter.emit(data);\n });\n this.keyEventSubjectSubscription = this.keySubject.subscribe((e) => {\n this.keyEventEmitter.emit(e);\n });\n this.setupResizeObservers();\n // if (ob3) this.resizableObservers.push(ob3);\n this.allLogsSubjectSubscription =\n this.linearRender.renderObservable.subscribe((change) => {\n if (change) this.coordinateOuterAndTerminal(change);\n else this.coordinateOuterAndTerminal(change);\n this.linearRender.handleNextOne();\n });\n this.linearRender.handleNextOne();\n }\n\n /**\n * set dimensions\n */\n private setOuterDimensions(\n left: number,\n top: number,\n width: number,\n height: number\n ) {\n this.linearRender.pushAndHandle({\n time: new Date(),\n type: 'dragged',\n dragged: { draggedWidth: `${width}px`, draggedHeight: `${height}px` },\n });\n }\n\n private applyStylesToResizeBox() {\n Object.keys(this.stylesForResizeBox)\n .map((key) => {\n return { key, value: (this.stylesForResizeBox as StringToString)[key] };\n })\n .forEach(({ key, value }) => {\n if (this.resizeBox) {\n if (value)\n this.renderer.setStyle(this.resizeBox.nativeElement, key, value);\n else {\n this.renderer.removeStyle(this.resizeBox.nativeElement, key);\n }\n }\n });\n this.stylesForResizeBox = this.stylesForResizeBox; //invalidate\n }\n\n ngOnInit() {}\n\n /**\n * It creates new terminal in #terminal.\n */\n ngAfterViewInit() {\n this.fitAddon = new FitAddon();\n this.xterm = new Terminal({\n allowProposedApi: true,\n });\n if (!(this.terminalOuter.nativeElement as HTMLElement).isConnected) {\n this.handleToCheckLazyContainer = setInterval(() => {\n if ((this.terminalOuter.nativeElement as HTMLElement).isConnected) {\n try {\n this.loggingService.log(() => console.debug(\"The container's been connected.\"));\n this.xterm!.open(this.terminalOuter.nativeElement);\n this.xterm!.loadAddon(this.fitAddon!!);\n this.setup();\n this.linearRender.pushAndHandle({ time: new Date(), type: 'none' });\n } finally {\n if (this.handleToCheckLazyContainer)\n clearInterval(this.handleToCheckLazyContainer);\n }\n }\n }, 500);\n } else {\n this.xterm.open(this.terminalOuter.nativeElement);\n this.xterm.loadAddon(this.fitAddon);\n this.setup();\n this.linearRender.pushAndHandle({ time: new Date(), type: 'none' });\n }\n }\n\n ngOnChanges(changes?: SimpleChanges) {\n this.loggingService.log(() => console.group('onChanges'));\n this.loggingService.log(() => console.debug('prop: ', changes));\n this.loggingService.log(() => console.groupEnd());\n if (changes?.['_rowsInput']) {\n if (\n changes?.['_rowsInput']?.previousValue !=\n changes?.['_rowsInput']?.currentValue\n ) {\n this.linearRender.pushAndHandle({\n time: new Date(),\n type: 'rowChanged',\n });\n }\n }\n if (changes?.['_colsInput']) {\n if (\n changes?.['_colsInput']?.previousValue !=\n changes?.['_colsInput']?.currentValue\n ) {\n this.linearRender.pushAndHandle({\n time: new Date(),\n type: 'columnChanged',\n });\n }\n }\n if (changes?.['draggable'])\n this.linearRender.pushAndHandle({ time: new Date(), type: 'none' });\n }\n\n resizeHandleStyleRule?: CSSStyleRule;\n resizeHandleActiveStyleRule?: CSSStyleRule;\n\n /**\n * It serves a callback function to adjust the dimensions of the xterm-screen, xterm-view, and resize box\n * after making any changes to the outer box, rows, or columns, or when the resize box is being dragged.\n *\n * There several factors that affect dimensions, as I mentioned earlier.\n * Regardless of whether the draggable feature is on, if new row or column value is input, this value will be applied.\n * - Draggable = New specified Row/Column value > Full (Default)\n * @param change This argument represents a single change that occured.\n * @returns\n */\n private coordinateOuterAndTerminal(change: PropertyChangeSet) {\n this.loggingService.log(() => console.debug(`changeList: ${JSON.stringify(change)}`))\n if (!this.xterm) return;\n const isHostElementVisible =\n this.hostRef.nativeElement?.offsetParent !== null;\n if (!isHostElementVisible) {\n // Do nothing if the host element is invisible.\n this.loggingService.log(() => console.debug('`display` of host element was set to `none`'));\n return;\n }\n this.doUpdateXtermStyles();\n this.doAdjustDimensionOfResizeBox(change);\n this.doAdjustSizeOfXtermScreen(change);\n this.doUpdateViewportAndResizeBoxWithPixcelUnit();\n }\n\n /**\n * apply options to the xterm terminal\n * @returns\n */\n private doUpdateXtermStyles() {\n if (!this.xterm) return;\n this.xterm.options = { ...this._xtermOptions };\n // apply the theme to the background of the handle\n if (this._xtermOptions.theme?.background) {\n if (!this.resizeHandleStyleRule)\n this.resizeHandleStyleRule = this.findCssStyleRule('.resize-handle[');\n if (this.resizeHandleStyleRule)\n this.resizeHandleStyleRule.style.backgroundColor =\n this._xtermOptions.theme.background;\n }\n if (this._xtermOptions.theme?.border) {\n if (!this.resizeHandleActiveStyleRule)\n this.resizeHandleActiveStyleRule =\n this.findCssStyleRule('.handle-active');\n if (this.resizeHandleActiveStyleRule)\n this.resizeHandleActiveStyleRule.style.backgroundColor =\n this._xtermOptions.theme.border;\n }\n }\n\n /**\n * If the resize handles are moved, the resize box adjusts to the new dimensions;\n * otherwise, it defaults to a maximized size.\n * @param change\n */\n private doAdjustDimensionOfResizeBox(change: PropertyChangeSet) {\n this.stylesForResizeBox = {\n ...this.stylesForResizeBox,\n ...this._stylesInput,\n width: this.stylesForResizeBox.width,\n height: this.stylesForResizeBox.height,\n };\n\n // Reset styles of the resize element\n if (change.type === 'dragged') {\n const minWidth = this._minWidthInput ?? 24;\n const minHeight = this._minHeightInput ?? 24;\n const width =\n parseInt(change.dragged.draggedWidth) > minWidth\n ? change.dragged.draggedWidth\n : `${minWidth}px`;\n const height =\n parseInt(change.dragged.draggedHeight) > minHeight\n ? change.dragged.draggedHeight\n : `${minHeight}px`;\n this.stylesForResizeBox.width = width;\n this.stylesForResizeBox.height = height;\n this.lastDraggedPosition = {\n width,\n height,\n };\n this.applyStylesToResizeBox();\n } else if (!(this.draggable && this.lastDraggedPosition)) {\n // When `_colsInput` and `draggable` is not enabled,\n // it fits the size to the host element.\n const currentHostWidth = getComputedStyle(\n this.hostRef.nativeElement\n ).width;\n const detectBoxWidth = getComputedStyle(\n this.detectBox.nativeElement\n ).width;\n let smallParent = false;\n if (parseFloat(detectBoxWidth) < parseFloat(currentHostWidth)) {\n // the width of the parent is smaller than that of resize-box element\n smallParent = true;\n }\n if (smallParent) {\n // It's been written to solve https://github.com/qwefgh90/ng-terminal/issues/79\n // 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\n // host element: 1000px, resize-box(child): 985px -> host element: 985px, resize-box(child): 970px -> ... -> stop\n\n // This code check if the parent element (that is the parent of `<ng-terminal>), is smaller than `.resize-box`\n // 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.\n this.stylesForResizeBox.width = `${parseFloat(detectBoxWidth)}px`;\n this.applyStylesToResizeBox();\n } else {\n // but if the dimension of host element is resized, update width and height\n // If `_rowsInput` is specified, NgTerminal keep the current height; otherwise, the height is set to 100%\n if (!this._rowsInput) this.stylesForResizeBox.height = '100%';\n if (!this._colsInput) this.stylesForResizeBox.width = '100%';\n this.applyStylesToResizeBox();\n }\n }\n }\n\n /**\n * This function uses fitAddon() to adjust the dimension of xterm-screen to character unit\n * If the draggable value is true or there are no fixed values for the row or column,\n * it fits the xterm terminal boxes into the resize box;\n * otherwise, it resizes the xterm terminal with specified row and column values.\n */\n private doAdjustSizeOfXtermScreen(change: PropertyChangeSet) {\n if (!this.xterm) return;\n if (\n (change.type == 'rowChanged' && this._rowsInput) ||\n (change.type == 'columnChanged' && this._colsInput)\n ) {\n this.xterm.resize(\n this._colsInput ?? this.xterm.cols,\n this._rowsInput ?? this.xterm.rows\n );\n }\n else {\n if (this.xterm.element) {\n // The fitAddon.fit() operation doesn't recognize the padding values of terminalOuter.\n // It seems to be using the padding values of xterm element instead.\n // Therefore, we establish a brief time frame to adjust the padding values before and after executing fitAddon.fit().\n // If this line is removed, when dragging resize-box vertically, the width is decreased.\n this.xterm.element.style.paddingLeft = `${this.paddingSize}px`;\n this.printDimension('Before fitAddon.fit() of Xterm');\n this.fitAddon?.fit();\n this.printDimension('After fitAddon.fit() of Xterm');\n this.xterm.element.style.paddingLeft = `${0}px`;\n }\n }\n }\n\n /**\n * This functions sets width of the resize box, xterm-viewport and xterm-screen with specific pixel values.\n */\n private doUpdateViewportAndResizeBoxWithPixcelUnit() {\n if (this.xterm?.element) {\n let xtermScreen =\n this.xterm.element.getElementsByClassName('xterm-screen')[0];\n let xtermViewport =\n this.xterm.element.getElementsByClassName('xterm-viewport')[0];\n const screenWidth = xtermScreen.clientWidth;\n const screenHeight = xtermScreen.clientHeight;\n const core = (this.underlying as any)._core;\n const scrollBarWidth: number = core.viewport.scrollBarWidth as number;\n const hostWidth = parseInt(\n getComputedStyle(this.hostRef.nativeElement).width\n );\n\n // It fixes a bug where the viewport's width isn't updated by fitAddon.fit()\n this.renderer.setStyle(\n xtermViewport,\n 'width',\n `${screenWidth + scrollBarWidth}px`\n );\n\n // It adjusts the dimension of the resize box to the xterm-screen element.\n const calulatedBoxWidth =\n screenWidth + scrollBarWidth + this.paddingSize * 2;\n const componentElement = this.hostRef.nativeElement as HTMLElement;\n const componentWith = parseInt(getComputedStyle(componentElement).width);\n const restrictedWidth =\n calulatedBoxWidth > componentWith ? componentWith : calulatedBoxWidth;\n\n this.stylesForResizeBox = {\n ...this.stylesForResizeBox,\n width: `${restrictedWidth}px`,\n height: `${screenHeight + this.paddingSize * 2}px`,\n };\n this.applyStylesToResizeBox();\n this.printDimension(\n 'After update the dimensions for all boxes with pixel values'\n );\n }\n }\n\n private printDimension(title: string) {\n if (this.xterm?.element) {\n let resizeBox = this.resizeBox.nativeElement as HTMLDivElement;\n let xtermScreen =\n this.xterm.element.getElementsByClassName('xterm-screen')[0];\n let xtermViewport =\n this.xterm.element.getElementsByClassName('xterm-viewport')[0];\n const screenWidth = xtermScreen.clientWidth;\n const screenHeight = xtermScreen.clientHeight;\n\n this.loggingService.log(() => console.group(`${title}`));\n this.loggingService.log(() => console.debug(`width(resizeBox): ${getComputedStyle(resizeBox).width},\nwidth(viewport): ${getComputedStyle(xtermViewport).width},\nwidth(screen): ${screenWidth}\nscrollBarWidth: ${this.scrollBarWidth}`));\n this.loggingService.log(() => console.debug(`height(resizeBox): ${getComputedStyle(resizeBox).height},\nheight(viewport) ${getComputedStyle(xtermViewport).height},\nheight(screen): ${screenHeight}`));\n this.loggingService.log(() => console.groupEnd());\n }\n }\n\n /**\n * If pushAndHandle() were used, there could be an issue\n * because it can adjust the size of elements during a loop of ResizeObserver.\n */\n private setupResizeObservers() {\n this.resizableObservers = [];\n let ob1 = this.observeXtermViewportDimension();\n let ob2 = this.observeHostDimension();\n if (ob1) this.resizableObservers.push(ob1);\n if (ob2) this.resizableObservers.push(ob2);\n }\n\n private observeXtermViewportDimension() {\n let xtermViewport = this.terminalOuter.nativeElement.querySelector(\n '.xterm-viewport'\n ) as HTMLDivElement | undefined;\n if (xtermViewport) {\n const resizeObserver = new ResizeObserver((entries) => {\n const outerDivWidth = (\n this.terminalOuter.nativeElement as HTMLDivElement | undefined\n )?.clientWidth;\n const outerDivHeight = (\n this.terminalOuter.nativeElement as HTMLDivElement | undefined\n )?.clientHeight;\n for (let entry of entries) {\n if (entry.contentBoxSize.length > 0) {\n let width: number = entry.target.clientWidth;\n let height: number = entry.target.clientHeight;\n if (\n (outerDivWidth && width > outerDivWidth) ||\n (outerDivHeight && height > outerDivHeight)\n ) {\n this.loggingService.log(() => console.debug(\n 'Changes on a xterm viewport element will be handled.'\n ));\n this.linearRender.pushAndHandle(\n {\n time: new Date(),\n type: 'xtermViewportExceedingOuterDiv',\n xtermViewportExceedingOuterDiv: {\n width: `${width}`,\n height: `${height}`,\n outerDivWidth: `${outerDivWidth}`,\n outerDivHeight: `${outerDivHeight}`,\n },\n },\n true\n );\n }\n }\n }\n });\n resizeObserver.observe(xtermViewport);\n return resizeObserver;\n } else {\n this.loggingService.log(() => console.error(\n 'Invalid state is detected. xterm element should exist below .terminal-outer.'\n ));\n }\n return undefined;\n }\n\n lastDetectedWidth = 0;\n private observeHostDimension() {\n let hostElement = this.hostRef.nativeElement;\n let detectBox = this.detectBox.nativeElement;\n if (hostElement && detectBox) {\n const resizeObserver = new ResizeObserver((entries) => {\n for (let entry of entries) {\n if (entry.target === hostElement) {\n if (entry.contentBoxSize.length > 0) {\n let width = getComputedStyle(entry.target).width;\n let height = getComputedStyle(entry.target).height;\n if (parseInt(width) >= 0 && parseInt(height) >= 0) {\n this.loggingService.log(() => console.debug('Changes on a host element will be handled.'));\n this.linearRender.pushAndHandle(\n {\n time: new Date(),\n type: 'hostResized',\n hostResized: { width: `${width}`, height: `${height}` },\n },\n true\n );\n }\n }\n }\n if (entry.target === detectBox) {\n if (entry.contentBoxSize.length > 0) {\n let width = getComputedStyle(entry.target).width;\n if (\n parseInt(width) >= 0 &&\n parseInt(width) <= this.lastDetectedWidth\n ) {\n this.loggingService.log(() => console.debug(\n 'Changes on a detect-box element will be handled.'\n ));\n this.linearRender.pushAndHandle(\n {\n time: new Date(),\n type: 'detectBoxResized',\n detectBoxResized: { width: `${width}` },\n },\n true\n );\n }\n this.lastDetectedWidth = parseInt(width);\n }\n }\n }\n });\n resizeObserver.observe(hostElement);\n resizeObserver.observe(detectBox);\n return resizeObserver;\n } else {\n this.loggingService.log(() => console.error(\n 'Invalid state is detected. xterm element should exist below .terminal-outer.'\n ));\n }\n return undefined;\n }\n /**\n * clean all resources\n */\n ngOnDestroy(): void {\n this.resizableObservers.forEach((ob) => ob.disconnect());\n if (this.keyInputSubjectSubscription)\n this.keyInputSubjectSubscription.unsubscribe();\n if (this.dataSourceSubscription) this.dataSourceSubscription.unsubscribe();\n if (this.keyEventSubjectSubscription)\n this.keyEventSubjectSubscription.unsubscribe();\n if (this.allLogsSubjectSubscription)\n this.allLogsSubjectSubscription.unsubscribe();\n if (this.handleToCheckLazyContainer)\n clearInterval(this.handleToCheckLazyContainer);\n if (this.xterm) this.xterm.dispose();\n this.loggingService.log(() => console.debug('All resources has been cleaned up.'));\n }\n\n write(chars: string) {\n this.xterm?.write(chars);\n }\n\n get keyInput(): Observable<string> {\n return this.dataSubject;\n }\n\n onData(): Observable<string> {\n return this.dataSubject;\n }\n\n get keyEventInput(): Observable<{ key: string; domEvent: KeyboardEvent }> {\n return this.keySubject;\n }\n\n onKey(): Observable<{ key: string; domEvent: KeyboardEvent }> {\n return this.keySubject;\n }\n\n get underlying(): Terminal | undefined {\n return this.xterm;\n }\n\n get isDraggableOnEdgeActivated() {\n // return this.displayOption.activateDraggableOnEdge != undefined && this.displayOption.fixedGrid == undefined;\n return this._draggable;\n }\n\n private get scrollBarWidth() {\n const core = (this.underlying as any)._core;\n return core.viewport.scrollBarWidth as number;\n }\n\n /**\n * After user coordinate dimensions of terminal, it's called.\n * @param left\n * @param top\n * @param width\n * @param height\n */\n onResizeEnd(left: number, top: number, width: number, height: number): void {\n this.setOuterDimensions(left, top, width, height);\n }\n\n /**\n * Before onResizeEnd is called, it valiates dimensions to change.\n * @param re dimension to be submitted from resizable stuff\n */\n validatorFactory(): (re: ResizeEvent) => boolean {\n const comp = this;\n return (re: ResizeEvent) => {\n if (this._draggable) {\n return true;\n } else return false;\n };\n }\n\n private findCssStyleRule(containingSelector: string) {\n for (let i = 0; i < document.styleSheets.length; i++) {\n let sheet = document.styleSheets.item(i);\n if (sheet) {\n for (let i = 0; i < sheet.cssRules.length; i++) {\n let rule = sheet.cssRules.item(i) as CSSStyleRule;\n if ('selectorText' in rule)\n if (rule.selectorText.includes(containingSelector)) return rule;\n }\n }\n }\n return undefined;\n }\n}\n\ninterface StringToString {\n [index: string]: string;\n}\n","<!-- 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>","import { ModuleWithProviders, NgModule } from '@angular/core';\nimport { NgTerminalComponent } from './ng-terminal.component';\nimport { ResizableModule } from 'angular-resizable-element';\nimport { GlobalStyleComponent } from './global-style/global-style.component';\nimport { CommonModule } from '@angular/common';\nimport { ModuleOptions } from './module-options';\n\n@NgModule({\n declarations: [NgTerminalComponent, GlobalStyleComponent],\n imports: [ResizableModule, CommonModule],\n exports: [NgTerminalComponent],\n})\nexport class NgTerminalModule {\n static forRoot(\n config?: ModuleOptions\n ): ModuleWithProviders<NgTerminalModule> {\n return {\n ngModule: NgTerminalModule,\n providers: [\n {provide: ModuleOptions, useValue: config }\n ]\n };\n }\n}","/**\n *\n * It is a CSI sequences generator\n * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Functions-using-CSI-_-ordered-by-the-final-character_s_\n */\nlet CSI = '\\x9b';\n\nexport class FunctionsUsingCSI {\n static get CSI() {\n return CSI;\n }\n\n /**\n * CSI Ps @ Insert Ps (Blank) Character(s) (default = 1) (ICH).\n *\n * */\n static insertBlank(count: number) {\n return `${CSI}${count}@`;\n }\n /**\n * CSI Ps SP @ */\n /**\n * CSI Ps A Cursor Up Ps Times (default = 1) (CUU).\n * \\x9b3A */\n static cursorUp(count: number) {\n return `${CSI}${count}A`;\n }\n /**\n * CSI Ps SP A */\n /**\n * CSI Ps B Cursor Down Ps Times (default = 1) (CUD).\n * \\x9b3B */\n static cursorDown(count: number) {\n return `${CSI}${count}B`;\n }\n /**\n * CSI Ps C Cursor Forward Ps Times (default = 1) (CUF).\n * \\x9b3C */\n static cursorForward(count: number) {\n return `${CSI}${count}C`;\n }\n /**\n * CSI Ps D Cursor Backward Ps Times (default = 1) (CUB).\n * \\x9b3D */\n static cursorBackward(count: number) {\n return `${CSI}${count}D`;\n }\n /**\n * CSI Ps E Cursor Next Line Ps Times (default = 1) (CNL).\n * \\x9b3E\n * */\n static cursorNextLine(count: number) {\n return `${CSI}${count}E`;\n }\n /**\n * CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL).\n * \\x9b3F\n * */\n static cursorPrecedingLine(count: number) {\n return `${CSI}${count}F`;\n }\n /**\n * CSI Ps G Cursor Character Absolute [column] (default = [row,1]) (CHA).\n * \\x9b9G\n * */\n static cursorColumn(count: number) {\n return `${CSI}${count}G`;\n }\n /**\n * CSI Ps ; Ps H Cursor Position [row;column] (default = [1,1]) (CUP).\n * \\x9b2;2H\n * */\n static cursorPosition(row: number, col: number) {\n return `${CSI}${row};${col}H`;\n }\n /**\n * CSI Ps I Cursor Forward Tabulation Ps tab stops (default = 1) (CHT). */\n /**\n * CSI Ps J Erase in Display (ED), VT100.\n * Ps = 0 -> Erase Below (default).\n * Ps = 1 -> Erase Above.\n * Ps = 2 -> Erase All.\n * Ps = 3 -> Erase Saved Lines (xterm).\n * \\x9b2J\n * */\n static eraseInDisplay(category: KindOfEraseInDisplay) {\n return `${CSI}${category}J`;\n }\n\n /**\n * CSI ? Ps J\n * Erase in Display (DECSED), VT220.\n * Ps = 0 -> Selective Erase Below (default).\n * Ps = 1 -> Selective Erase Above.\n * Ps = 2 -> Selective Erase All.\n * Ps = 3 -> Selective Erase Saved Lines (xterm).\n * \\x9b?2J\n * */\n static eraseSelectiveThingsInDisplay(category: KindOfEraseInDisplay) {\n return `${CSI}?${category}J`;\n }\n /**\n * CSI Ps K\n * Erase in Line (EL), VT100.\n * Ps = 0 -> Erase to Right (default).\n * Ps = 1 -> Erase to Left.\n * Ps = 2 -> Erase All.\n * \\x9b?1K\n * */\n static eraseInLine(category: KindOfEraseInLine) {\n return `${CSI}${category}K`;\n }\n /**\n * CSI ? Ps K\n * Erase in Line (DECSEL), VT220.\n * Ps = 0 -> Selective Erase to Right (default).\n * Ps = 1 -> Selective Erase to Left.\n * Ps = 2 -> Selective Erase All.\n * \\x9b?1K\n * */\n static eraseSelectiveThingsInLine(category: KindOfEraseInLine) {\n return `${CSI}?${category}K`;\n }\n /**\n * CSI Ps L Insert Ps Line(s) (default = 1) (IL).\n * \\x9b2L\n * */\n static insertLines(count: number) {\n return `${CSI}${count}L`;\n }\n /**\n * CSI Ps M Delete Ps Line(s) (default = 1) (DL).\n * \\x9b2M\n * */\n static deleteLines(count: number) {\n return `${CSI}${count}M`;\n }\n /**\n * CSI Ps P Delete Ps Character(s) (default = 1) (DCH).\n * \\x9b2P\n * */\n static deleteCharacter(count: number) {\n return `${CSI}${count}P`;\n }\n /**\n * CSI Ps S Scroll up Ps lines (default = 1) (SU), VT420, ECMA-48.\n * \\x9b2S\n * */\n static scrollUpLines(count: number) {\n return `${CSI}${count}S`;\n }\n /**\n * CSI ? Pi ; Pa ; Pv S */\n /**\n * CSI Ps T Scroll down Ps lines (default = 1) (SD), VT420.\n * \\x9b2T\n * */\n static scrollDownLines(count: number) {\n return `${CSI}${count}T`;\n }\n /**\n * CSI Ps ; Ps ; Ps ; Ps ; Ps T */\n /**\n * CSI > Ps ; Ps T */\n /**\n * CSI Ps X Erase Ps Character(s) (default = 1) (ECH).\n * \\x9b2X\n * */\n static eraseCharacters(count: number) {\n return `${CSI}${count}X`;\n }\n /**\n * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n * \\x9b2Z\n * */\n static cursorBackwardTabulationPstabstops(count: number) {\n return `${CSI}${count}Z`;\n }\n /**\n * CSI Ps ^ Scroll down Ps lines (default = 1) (SD), ECMA-48.\n * \\x9b2^\n * */\n static scrolldownPslines(count: number) {\n return `${CSI}${count}^`;\n }\n /**\n * CSI Ps ` Character Position Absolute [column] (default = [row,1])\n * \\x9b1` */\n static characterPositionAbsolute(count: number) {\n return `${CSI}${count}\\``;\n }\n /**\n * CSI Ps a Character Position Relative [columns] (default = [row,col+1])\n * \\x9b1a */\n static characterPositionRelative(count: number) {\n return `${CSI}${count}a`;\n }\n /**\n * CSI Ps b Repeat the preceding graphic character Ps times (REP).\n * \\x9b1b\n * */\n static repeatThePrecedingGraphicCharacter(count: number) {\n return `${CSI}${count}b`;\n }\n /**\n * CSI Pm d Line Position Absolute [row] (default = [1,column]) (VPA). \n * \\x9b4d\n * */\n static linePositionAbsolute(count: number) {\n return `${CSI}${count}d`;\n }\n /**\n * CSI Pm e Line Position Relative [rows] (default = [row+1,column]) \n * \\x9b1e\n * */\n static linePositionRelative(count: number) {\n return `${CSI}${count}e`;\n }\n /**\n * CSI Ps ; Ps f Horizontal and Vertical Position [row;column] (default =\n * [1,1]) \n * \\x9b3;5f\n * */\n static horizontalandVerticalPosition(row: number, column: number) {\n return `${CSI}${row};${column}f`;\n }\n\n /**\n * CSI Ps g Tab Clear (TBC). \n * \\x9b3g\n * */\n /**\n * CSI Pm h Set Mode (SM).\n * \\x9b4h\n * */\n static setMode(mode: KindOfSetMode, ...additionalModes: KindOfSetMode[]) {\n const modes = [mode, ...(additionalModes ?? [])];\n return `${CSI}${modes.join(\";\")}h`;\n }\n /**\n * CSI ? Pm h DEC Private Mode Set (DECSET).\n * */\n /**\n * CSI Pm i Media Copy (MC). */\n /**\n * CSI ? Pm i */\n /**\n * CSI Pm l Reset Mode (RM). \n * \\x9b4l\n * */\n static resetMode(mode: KindOfResetMode, ...additionalModes: KindOfResetMode[]) {\n const modes = [mode, ...(additionalModes ?? [])];\n return `${CSI}${modes.join(\";\")}l`;\n }\n /**\n * CSI ? Pm l */\n /**\n * CSI Pm m Character Attributes (SGR).\n * \\x9b31m\n * */\n static characterAttributes(\n firstAttribute: KindOfCharacterAttributes,\n ...additionalAttributes: KindOfCharacterAttributes[]\n ) {\n const chars: KindOfCharacterAttributes[] = [\n firstAttribute,\n ...(additionalAttributes ?? []),\n ];\n return `${CSI}${chars.join(';')}m`;\n }\n /**\n * CSI > Ps ; Ps m */\n /**\n * CSI Ps n Device Status Report (DSR). */\n /**\n * CSI > Ps n */\n /**\n * CSI ? Ps n */\n /**\n * CSI > Ps p */\n /**\n * CSI ! p Soft terminal reset (DECSTR), VT220 and up. */\n /**\n * CSI Ps ; Ps \" p */\n /**\n * CSI Ps $ p */\n /**\n * CSI ? Ps $ p */\n /**\n * CSI # p */\n /**\n * CSI Ps ; Ps # p */\n /**\n * CSI Ps q Load LEDs (DECLL), VT100. */\n /**\n * CSI Ps SP q */\n /**\n * CSI Ps \" q */\n /**\n * CSI # q Pop video attributes from stack (XTPOPSGR), xterm. This is an */\n /**\n * CSI Ps ; Ps r */\n /**\n * CSI ? Pm r */\n /**\n * CSI Pt ; Pl ; Pb ; Pr ; Ps $ r */\n /**\n * CSI s Save cursor, available only when DECLRMM is disabled (SCOSC, */\n /**\n * CSI Pl ; Pr s */\n /**\n * CSI ? Pm s */\n /**\n * CSI Ps ; Ps ; Ps t */\n /**\n * CSI > Ps ; Ps t */\n /**\n * CSI Ps SP t */\n /**\n * CSI Pt ; Pl ; Pb ; Pr ; Ps $ t */\n /**\n * CSI u Restore cursor (SCORC, also ANSI.SYS). */\n /**\n * CSI Ps SP u */\n /**\n * CSI Pt ; Pl ; Pb ; Pr ; Pp ; Pt ; Pl ; Pp $ v */\n /**\n * CSI Ps $ w */\n /**\n * CSI Pt ; Pl ; Pb ; Pr ' w */\n /**\n * CSI Ps x Request Terminal Parameters (DECREQTPARM). */\n /**\n * CSI Ps * x */\n /**\n * CSI Pc ; Pt ; Pl ; Pb ; Pr $ x */\n /**\n * CSI Ps # y */\n /**\n * CSI Pi ; Pg ; Pt ; Pl ; Pb ; Pr * y */\n /**\n * CSI Ps ; Pu ' z */\n /**\n * CSI Pt ; Pl ; Pb ; Pr $ z */\n /**\n * CSI Pm ' { */\n /**\n * CSI # { */\n /**\n * CSI Ps ; Ps # { */\n /**\n * CSI Pt ; Pl ; Pb ; Pr $ { */\n /**\n * CSI Pt ; Pl ; Pb ; Pr # | */\n /**\n * CSI Ps $ | */\n /**\n * CSI Ps ' | */\n /**\n * CSI Ps * | */\n /**\n * CSI # } Pop video attributes from stack (XTPOPSGR), xterm. Popping */\n /**\n * CSI Pm ' } */\n /**\n * CSI Pm ' ~ */\n}\nexport enum KindOfEraseInDisplay {\n Below = 0,\n Above = 1,\n All = 2,\n SavedLines = 3,\n}\nexport enum KindOfEraseInLine {\n Right = 0,\n Left = 1,\n All = 2,\n}\n\nexport enum KindOfTabClear{\n ClearCurrentColumn = 0,\n ClearAll = 3\n}\n\n\nexport enum KindOfSetMode{\n KeyboardActionMode = 2,\n InsertMode = 4,\n SendReceive = 12,\n AutomaticNewline = 20\n}\nexport enum KindOfResetMode{\n KeyboardActionMode = 2,\n ReplaceMode = 4,\n SendReceive = 12,\n NormalNewline = 20\n}\nexport enum KindOfCharacterAttributes {\n Normal = 0,\n Bold = 1,\n Faint = 2,\n Italicized = 3,\n Underlined = 4,\n Blink = 5,\n Inverse = 7,\n Invisible = 8,\n CrossedOutcharacters = 9,\n DoublyUnderlined = 21,\n NormalNeitherBoldNorFaint = 22,\n Notitalicized = 23,\n Notunderlined = 24,\n Steady = 25,\n Positive = 27,\n Visible = 28,\n NotcrossedOut = 29,\n SetforegroundcolortoBlack = 30,\n SetforegroundcolortoRed = 31,\n SetforegroundcolortoGreen = 32,\n SetforegroundcolortoYellow = 33,\n SetforegroundcolortoBlue = 34,\n SetforegroundcolortoMagenta = 35,\n SetforegroundcolortoCyan = 36,\n SetforegroundcolortoWhite = 37,\n Setforegroundcolortodefault = 39,\n SetbackgroundcolortoBlack = 40,\n SetbackgroundcolortoRed = 41,\n SetbackgroundcolortoGreen = 42,\n SetbackgroundcolortoYellow = 43,\n SetbackgroundcolortoBlue = 44,\n SetbackgroundcolortoMagenta = 45,\n SetbackgroundcolortoCyan = 46,\n SetbackgroundcolortoWhite = 47,\n SetbackgroundcolortoDefault = 49,\n}\n","/*\n * Public API Surface of ng-terminal\n */\n\nexport * from './lib/ng-terminal.component';\nexport * from './lib/ng-terminal.module';\nexport * from './lib/functions-using-csi';\nexport * from './lib/ng-terminal';\nexport * from './lib/module-options';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.ModuleOptions","i1.LoggingService","i4.GlobalStyleComponent"],"mappings":"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