|
|
|
@ -14,11 +14,23 @@ |
|
|
|
/// limitations under the License.
|
|
|
|
///
|
|
|
|
|
|
|
|
import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; |
|
|
|
import { |
|
|
|
ChangeDetectorRef, |
|
|
|
Component, |
|
|
|
ElementRef, |
|
|
|
forwardRef, |
|
|
|
Input, |
|
|
|
OnDestroy, |
|
|
|
OnInit, |
|
|
|
ViewChild, |
|
|
|
ViewEncapsulation |
|
|
|
} from '@angular/core'; |
|
|
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; |
|
|
|
import { Ace } from 'ace-builds'; |
|
|
|
import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
|
|
|
import { getAce } from '@shared/models/ace/ace.models'; |
|
|
|
import { ResizeObserver } from '@juggle/resize-observer'; |
|
|
|
import { coerceBoolean } from '@shared/decorators/coercion'; |
|
|
|
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; |
|
|
|
|
|
|
|
@Component({ |
|
|
|
selector: 'tb-markdown-editor', |
|
|
|
@ -30,7 +42,8 @@ import { getAce } from '@shared/models/ace/ace.models'; |
|
|
|
useExisting: forwardRef(() => MarkdownEditorComponent), |
|
|
|
multi: true |
|
|
|
} |
|
|
|
] |
|
|
|
], |
|
|
|
encapsulation: ViewEncapsulation.None |
|
|
|
}) |
|
|
|
export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, OnDestroy { |
|
|
|
|
|
|
|
@ -42,11 +55,13 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On |
|
|
|
|
|
|
|
@Input() helpId: string; |
|
|
|
|
|
|
|
@Input() |
|
|
|
@coerceBoolean() |
|
|
|
required: boolean; |
|
|
|
|
|
|
|
@ViewChild('markdownEditor', {static: true}) |
|
|
|
markdownEditorElmRef: ElementRef; |
|
|
|
|
|
|
|
private markdownEditor: Ace.Editor; |
|
|
|
|
|
|
|
editorMode = true; |
|
|
|
|
|
|
|
fullscreen = false; |
|
|
|
@ -54,22 +69,15 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On |
|
|
|
markdownValue: string; |
|
|
|
renderValue: string; |
|
|
|
|
|
|
|
ignoreChange = false; |
|
|
|
|
|
|
|
private propagateChange = null; |
|
|
|
|
|
|
|
private requiredValue: boolean; |
|
|
|
private markdownEditor: Ace.Editor; |
|
|
|
private ignoreChange = false; |
|
|
|
|
|
|
|
get required(): boolean { |
|
|
|
return this.requiredValue; |
|
|
|
} |
|
|
|
private editorResize$: ResizeObserver; |
|
|
|
private editorsResizeCaf: CancelAnimationFrame; |
|
|
|
private propagateChange: (value: any) => void = () => {}; |
|
|
|
|
|
|
|
@Input() |
|
|
|
set required(value: boolean) { |
|
|
|
this.requiredValue = coerceBooleanProperty(value); |
|
|
|
} |
|
|
|
|
|
|
|
constructor() { |
|
|
|
constructor(private cd: ChangeDetectorRef, |
|
|
|
private raf: RafService) { |
|
|
|
} |
|
|
|
|
|
|
|
ngOnInit(): void { |
|
|
|
@ -100,6 +108,10 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On |
|
|
|
this.updateView(); |
|
|
|
} |
|
|
|
}); |
|
|
|
this.editorResize$ = new ResizeObserver(() => { |
|
|
|
this.onAceEditorResize(); |
|
|
|
}); |
|
|
|
this.editorResize$.observe(editorElement); |
|
|
|
} |
|
|
|
); |
|
|
|
|
|
|
|
@ -107,6 +119,13 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On |
|
|
|
} |
|
|
|
|
|
|
|
ngOnDestroy(): void { |
|
|
|
if (this.editorResize$) { |
|
|
|
this.editorResize$.disconnect(); |
|
|
|
} |
|
|
|
if (this.editorsResizeCaf) { |
|
|
|
this.editorsResizeCaf(); |
|
|
|
this.editorsResizeCaf = null; |
|
|
|
} |
|
|
|
if (this.markdownEditor) { |
|
|
|
this.markdownEditor.destroy(); |
|
|
|
} |
|
|
|
@ -134,15 +153,6 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
updateView() { |
|
|
|
const editorValue = this.markdownEditor.getValue(); |
|
|
|
if (this.markdownValue !== editorValue) { |
|
|
|
this.markdownValue = editorValue; |
|
|
|
this.renderValue = this.markdownValue ? this.markdownValue : ' '; |
|
|
|
this.propagateChange(this.markdownValue); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
onFullscreen() { |
|
|
|
if (this.markdownEditor) { |
|
|
|
setTimeout(() => { |
|
|
|
@ -159,4 +169,25 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On |
|
|
|
}, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private updateView() { |
|
|
|
const editorValue = this.markdownEditor.getValue(); |
|
|
|
if (this.markdownValue !== editorValue) { |
|
|
|
this.markdownValue = editorValue; |
|
|
|
this.renderValue = this.markdownValue ? this.markdownValue : ' '; |
|
|
|
this.propagateChange(this.markdownValue); |
|
|
|
this.cd.markForCheck(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private onAceEditorResize() { |
|
|
|
if (this.editorsResizeCaf) { |
|
|
|
this.editorsResizeCaf(); |
|
|
|
this.editorsResizeCaf = null; |
|
|
|
} |
|
|
|
this.editorsResizeCaf = this.raf.raf(() => { |
|
|
|
this.markdownEditor.resize(); |
|
|
|
this.markdownEditor.renderer.updateFull(); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|