@notectl/angular 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -0
- package/dist/README.md +141 -0
- package/dist/esm2022/index.mjs +6 -0
- package/dist/esm2022/lib/notectl-editor.component.mjs +244 -0
- package/dist/esm2022/lib/notectl-editor.directive.mjs +164 -0
- package/dist/esm2022/lib/notectl-editor.module.mjs +21 -0
- package/dist/esm2022/notectl-angular.mjs +5 -0
- package/dist/esm2022/public-api.mjs +7 -0
- package/dist/fesm2022/notectl-angular.mjs +439 -0
- package/dist/fesm2022/notectl-angular.mjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/notectl-editor.component.d.ts +92 -0
- package/dist/lib/notectl-editor.directive.d.ts +42 -0
- package/dist/lib/notectl-editor.module.d.ts +8 -0
- package/dist/public-api.d.ts +6 -0
- package/package.json +58 -0
- package/src/index.ts +6 -0
- package/src/lib/notectl-editor.component.ts +261 -0
- package/src/lib/notectl-editor.directive.ts +156 -0
- package/src/lib/notectl-editor.module.ts +14 -0
- package/src/public-api.ts +7 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Angular directive for NotectlEditor (optional alternative to component)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Directive,
|
|
7
|
+
ElementRef,
|
|
8
|
+
EventEmitter,
|
|
9
|
+
Input,
|
|
10
|
+
OnDestroy,
|
|
11
|
+
OnInit,
|
|
12
|
+
Output,
|
|
13
|
+
forwardRef,
|
|
14
|
+
} from '@angular/core';
|
|
15
|
+
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
16
|
+
import { NotectlEditor as NotectlEditorCore } from '@notectl/core';
|
|
17
|
+
import type { EditorConfig, EditorAPI } from '@notectl/core';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Directive to use NotectlEditor on any element
|
|
21
|
+
* Usage: <div notectl-editor [content]="content"></div>
|
|
22
|
+
*/
|
|
23
|
+
@Directive({
|
|
24
|
+
selector: '[notectl-editor]',
|
|
25
|
+
providers: [
|
|
26
|
+
{
|
|
27
|
+
provide: NG_VALUE_ACCESSOR,
|
|
28
|
+
useExisting: forwardRef(() => NotectlEditorDirective),
|
|
29
|
+
multi: true,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
export class NotectlEditorDirective implements OnInit, OnDestroy, ControlValueAccessor {
|
|
34
|
+
@Input() debug?: boolean;
|
|
35
|
+
@Input() content?: string | object;
|
|
36
|
+
@Input() placeholder?: string;
|
|
37
|
+
@Input() readOnly?: boolean;
|
|
38
|
+
@Input() accessibility?: EditorConfig['accessibility'];
|
|
39
|
+
@Input() i18n?: EditorConfig['i18n'];
|
|
40
|
+
@Input() theme?: EditorConfig['theme'];
|
|
41
|
+
|
|
42
|
+
@Output() contentChange = new EventEmitter<unknown>();
|
|
43
|
+
@Output() selectionChange = new EventEmitter<unknown>();
|
|
44
|
+
@Output() editorFocus = new EventEmitter<void>();
|
|
45
|
+
@Output() editorBlur = new EventEmitter<void>();
|
|
46
|
+
@Output() ready = new EventEmitter<EditorAPI>();
|
|
47
|
+
@Output() error = new EventEmitter<Error>();
|
|
48
|
+
|
|
49
|
+
private editor: NotectlEditorCore | null = null;
|
|
50
|
+
private onChange: (value: unknown) => void = () => {};
|
|
51
|
+
private onTouched: () => void = () => {};
|
|
52
|
+
|
|
53
|
+
constructor(private elementRef: ElementRef<HTMLElement>) {}
|
|
54
|
+
|
|
55
|
+
ngOnInit(): void {
|
|
56
|
+
this.initEditor();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ngOnDestroy(): void {
|
|
60
|
+
this.destroyEditor();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private initEditor(): void {
|
|
64
|
+
const hostElement = this.elementRef.nativeElement;
|
|
65
|
+
|
|
66
|
+
// Create editor instance
|
|
67
|
+
this.editor = document.createElement('notectl-editor') as NotectlEditorCore;
|
|
68
|
+
|
|
69
|
+
// Configure editor
|
|
70
|
+
const config: EditorConfig = {
|
|
71
|
+
debug: this.debug,
|
|
72
|
+
content: this.content,
|
|
73
|
+
placeholder: this.placeholder,
|
|
74
|
+
readOnly: this.readOnly,
|
|
75
|
+
accessibility: this.accessibility,
|
|
76
|
+
i18n: this.i18n,
|
|
77
|
+
theme: this.theme,
|
|
78
|
+
};
|
|
79
|
+
this.editor.configure(config);
|
|
80
|
+
|
|
81
|
+
// Attach event listeners
|
|
82
|
+
this.editor.on('content-change', (data) => {
|
|
83
|
+
const eventData = data as { content?: unknown };
|
|
84
|
+
const content = eventData.content;
|
|
85
|
+
this.contentChange.emit(content);
|
|
86
|
+
this.onChange(content);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this.editor.on('selection-change', (data) => {
|
|
90
|
+
const eventData = data as { selection?: unknown };
|
|
91
|
+
this.selectionChange.emit(eventData.selection);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
this.editor.on('focus', () => {
|
|
95
|
+
this.editorFocus.emit();
|
|
96
|
+
this.onTouched();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
this.editor.on('blur', () => {
|
|
100
|
+
this.editorBlur.emit();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
this.editor.on('ready', () => {
|
|
104
|
+
this.ready.emit(this.getEditorAPI());
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
this.editor.on('error', (data) => {
|
|
108
|
+
const eventData = data as { error?: Error };
|
|
109
|
+
if (eventData.error) {
|
|
110
|
+
this.error.emit(eventData.error);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Mount editor
|
|
115
|
+
hostElement.appendChild(this.editor);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private destroyEditor(): void {
|
|
119
|
+
if (this.editor) {
|
|
120
|
+
this.editor.destroy();
|
|
121
|
+
const hostElement = this.elementRef.nativeElement;
|
|
122
|
+
if (hostElement.contains(this.editor)) {
|
|
123
|
+
hostElement.removeChild(this.editor);
|
|
124
|
+
}
|
|
125
|
+
this.editor = null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private getEditorAPI(): EditorAPI {
|
|
130
|
+
if (!this.editor) {
|
|
131
|
+
throw new Error('Editor not initialized');
|
|
132
|
+
}
|
|
133
|
+
return this.editor as EditorAPI;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ControlValueAccessor implementation
|
|
137
|
+
writeValue(value: unknown): void {
|
|
138
|
+
if (this.editor && typeof value === 'string') {
|
|
139
|
+
this.editor.setContent(value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
registerOnChange(fn: (value: unknown) => void): void {
|
|
144
|
+
this.onChange = fn;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
registerOnTouched(fn: () => void): void {
|
|
148
|
+
this.onTouched = fn;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
setDisabledState(isDisabled: boolean): void {
|
|
152
|
+
if (this.editor) {
|
|
153
|
+
this.editor.configure({ readOnly: isDisabled });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Angular module for NotectlEditor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { NgModule } from '@angular/core';
|
|
6
|
+
import { CommonModule } from '@angular/common';
|
|
7
|
+
import { NotectlEditorComponent } from './notectl-editor.component';
|
|
8
|
+
|
|
9
|
+
@NgModule({
|
|
10
|
+
declarations: [NotectlEditorComponent],
|
|
11
|
+
imports: [CommonModule],
|
|
12
|
+
exports: [NotectlEditorComponent],
|
|
13
|
+
})
|
|
14
|
+
export class NotectlEditorModule {}
|