@firestitch/html-editor 14.0.0 → 15.0.0

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.
Files changed (57) hide show
  1. package/app/modules/html-editor/classes/plugin.d.ts +7 -7
  2. package/app/modules/html-editor/components/html-editor/html-editor.component.d.ts +60 -60
  3. package/app/modules/html-editor/consts/paragraph-buttons.const.d.ts +1 -1
  4. package/app/modules/html-editor/consts/rich-buttons.const.d.ts +1 -1
  5. package/app/modules/html-editor/consts/text-buttons.const.d.ts +1 -1
  6. package/app/modules/html-editor/directives/html-editor-container.directive.d.ts +9 -9
  7. package/app/modules/html-editor/directives/index.d.ts +1 -1
  8. package/app/modules/html-editor/enums/default-plugin.enum.d.ts +16 -16
  9. package/app/modules/html-editor/fs-html-editor.module.d.ts +37 -37
  10. package/app/modules/html-editor/injects/config.inject.d.ts +3 -3
  11. package/app/modules/html-editor/interfaces/html-editor-config.d.ts +34 -34
  12. package/app/modules/html-editor/interfaces/index.d.ts +3 -3
  13. package/app/modules/html-editor/interfaces/plugin-config.d.ts +5 -5
  14. package/app/modules/html-editor/interfaces/toolbar-button.d.ts +14 -14
  15. package/app/modules/html-editor/plugins/checklist.plugin.d.ts +7 -7
  16. package/app/modules/html-editor/plugins/code.plugin.d.ts +9 -9
  17. package/app/modules/html-editor/plugins/configs/mention-plugin.config.d.ts +13 -13
  18. package/app/modules/html-editor/plugins/configs/screen-record-plugin.config.d.ts +7 -7
  19. package/app/modules/html-editor/plugins/mention.plugin.d.ts +15 -15
  20. package/app/modules/html-editor/plugins/realtime.plugin.d.ts +7 -7
  21. package/app/modules/html-editor/plugins/screen-record.plugin.d.ts +11 -11
  22. package/app/modules/html-editor/services/froala-loader.service.d.ts +21 -21
  23. package/app/modules/html-renderer/components/html-renderer/html-renderer.component.d.ts +12 -12
  24. package/app/modules/html-renderer/fs-html-renderer.module.d.ts +8 -8
  25. package/esm2020/app/modules/html-editor/classes/plugin.mjs +4 -4
  26. package/esm2020/app/modules/html-editor/components/html-editor/html-editor.component.mjs +509 -509
  27. package/esm2020/app/modules/html-editor/consts/paragraph-buttons.const.mjs +9 -9
  28. package/esm2020/app/modules/html-editor/consts/rich-buttons.const.mjs +6 -6
  29. package/esm2020/app/modules/html-editor/consts/text-buttons.const.mjs +18 -18
  30. package/esm2020/app/modules/html-editor/directives/html-editor-container.directive.mjs +14 -14
  31. package/esm2020/app/modules/html-editor/directives/index.mjs +1 -1
  32. package/esm2020/app/modules/html-editor/enums/default-plugin.enum.mjs +1 -1
  33. package/esm2020/app/modules/html-editor/fs-html-editor.module.mjs +75 -75
  34. package/esm2020/app/modules/html-editor/injects/config.inject.mjs +3 -3
  35. package/esm2020/app/modules/html-editor/interfaces/html-editor-config.mjs +1 -1
  36. package/esm2020/app/modules/html-editor/interfaces/index.mjs +3 -3
  37. package/esm2020/app/modules/html-editor/interfaces/plugin-config.mjs +1 -1
  38. package/esm2020/app/modules/html-editor/interfaces/toolbar-button.mjs +1 -1
  39. package/esm2020/app/modules/html-editor/plugins/checklist.plugin.mjs +38 -38
  40. package/esm2020/app/modules/html-editor/plugins/code.plugin.mjs +66 -66
  41. package/esm2020/app/modules/html-editor/plugins/configs/mention-plugin.config.mjs +1 -1
  42. package/esm2020/app/modules/html-editor/plugins/configs/screen-record-plugin.config.mjs +1 -1
  43. package/esm2020/app/modules/html-editor/plugins/mention.plugin.mjs +89 -89
  44. package/esm2020/app/modules/html-editor/plugins/realtime.plugin.mjs +15 -15
  45. package/esm2020/app/modules/html-editor/plugins/screen-record.plugin.mjs +89 -89
  46. package/esm2020/app/modules/html-editor/services/froala-loader.service.mjs +90 -90
  47. package/esm2020/app/modules/html-renderer/components/html-renderer/html-renderer.component.mjs +24 -24
  48. package/esm2020/app/modules/html-renderer/fs-html-renderer.module.mjs +24 -24
  49. package/esm2020/firestitch-html-editor.mjs +4 -4
  50. package/esm2020/public_api.mjs +14 -14
  51. package/fesm2015/firestitch-html-editor.mjs +987 -987
  52. package/fesm2015/firestitch-html-editor.mjs.map +1 -1
  53. package/fesm2020/firestitch-html-editor.mjs +1000 -1000
  54. package/fesm2020/firestitch-html-editor.mjs.map +1 -1
  55. package/index.d.ts +5 -5
  56. package/package.json +1 -1
  57. package/public_api.d.ts +19 -19
@@ -16,1027 +16,1027 @@ import { merge, debounce } from 'lodash-es';
16
16
  import Tribute from 'tributejs';
17
17
  import { __awaiter } from 'tslib';
18
18
 
19
- class FsHtmlRendererComponent {
20
- constructor(sanitized, _cdRef) {
21
- this.sanitized = sanitized;
22
- this._cdRef = _cdRef;
23
- }
24
- set setHtml(html) {
25
- this.trustedHtml = this.sanitized.bypassSecurityTrustHtml(html || '');
26
- this._cdRef.markForCheck();
27
- }
28
- }
29
- FsHtmlRendererComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlRendererComponent, deps: [{ token: i1.DomSanitizer }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
30
- FsHtmlRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FsHtmlRendererComponent, selector: "fs-html-renderer", inputs: { setHtml: ["html", "setHtml"] }, ngImport: i0, template: "<span class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></span>\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
31
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlRendererComponent, decorators: [{
32
- type: Component,
33
- args: [{ selector: 'fs-html-renderer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></span>\n" }]
34
- }], ctorParameters: function () { return [{ type: i1.DomSanitizer }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { setHtml: [{
35
- type: Input,
36
- args: ['html']
19
+ class FsHtmlRendererComponent {
20
+ set setHtml(html) {
21
+ this.trustedHtml = this.sanitized.bypassSecurityTrustHtml(html || '');
22
+ this._cdRef.markForCheck();
23
+ }
24
+ constructor(sanitized, _cdRef) {
25
+ this.sanitized = sanitized;
26
+ this._cdRef = _cdRef;
27
+ }
28
+ }
29
+ FsHtmlRendererComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlRendererComponent, deps: [{ token: i1.DomSanitizer }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
30
+ FsHtmlRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: FsHtmlRendererComponent, selector: "fs-html-renderer", inputs: { setHtml: ["html", "setHtml"] }, ngImport: i0, template: "<span class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></span>\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlRendererComponent, decorators: [{
32
+ type: Component,
33
+ args: [{ selector: 'fs-html-renderer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></span>\n" }]
34
+ }], ctorParameters: function () { return [{ type: i1.DomSanitizer }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { setHtml: [{
35
+ type: Input,
36
+ args: ['html']
37
37
  }] } });
38
38
 
39
- class FsHtmlRendererModule {
40
- }
41
- FsHtmlRendererModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlRendererModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
42
- FsHtmlRendererModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlRendererModule, declarations: [FsHtmlRendererComponent], imports: [CommonModule], exports: [FsHtmlRendererComponent] });
43
- FsHtmlRendererModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlRendererModule, imports: [CommonModule] });
44
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlRendererModule, decorators: [{
45
- type: NgModule,
46
- args: [{
47
- imports: [
48
- CommonModule,
49
- ],
50
- exports: [
51
- FsHtmlRendererComponent,
52
- ],
53
- declarations: [
54
- FsHtmlRendererComponent,
55
- ],
56
- }]
39
+ class FsHtmlRendererModule {
40
+ }
41
+ FsHtmlRendererModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlRendererModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
42
+ FsHtmlRendererModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlRendererModule, declarations: [FsHtmlRendererComponent], imports: [CommonModule], exports: [FsHtmlRendererComponent] });
43
+ FsHtmlRendererModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlRendererModule, imports: [CommonModule] });
44
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlRendererModule, decorators: [{
45
+ type: NgModule,
46
+ args: [{
47
+ imports: [
48
+ CommonModule,
49
+ ],
50
+ exports: [
51
+ FsHtmlRendererComponent,
52
+ ],
53
+ declarations: [
54
+ FsHtmlRendererComponent,
55
+ ],
56
+ }]
57
57
  }] });
58
58
 
59
- class FsHtmlEditorContainerDirective {
60
- static ngTemplateContextGuard(dir, ctx) {
61
- return true;
62
- }
63
- }
64
- FsHtmlEditorContainerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
65
- FsHtmlEditorContainerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: FsHtmlEditorContainerDirective, selector: "[fsHtmlEditorContainer]", ngImport: i0 });
66
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorContainerDirective, decorators: [{
67
- type: Directive,
68
- args: [{ selector: '[fsHtmlEditorContainer]' }]
59
+ class FsHtmlEditorContainerDirective {
60
+ static ngTemplateContextGuard(dir, ctx) {
61
+ return true;
62
+ }
63
+ }
64
+ FsHtmlEditorContainerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
65
+ FsHtmlEditorContainerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: FsHtmlEditorContainerDirective, selector: "[fsHtmlEditorContainer]", ngImport: i0 });
66
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorContainerDirective, decorators: [{
67
+ type: Directive,
68
+ args: [{ selector: '[fsHtmlEditorContainer]' }]
69
69
  }] });
70
70
 
71
- const FS_HTML_EDITOR_DEFAULT_CONFIG = new InjectionToken('fs-html-editor.default-config');
71
+ const FS_HTML_EDITOR_DEFAULT_CONFIG = new InjectionToken('fs-html-editor.default-config');
72
72
  const FS_HTML_EDITOR_CONFIG = new InjectionToken('fs-html-editor.config');
73
73
 
74
- const ParagraphButtons = [
75
- 'align',
76
- 'formatOL',
77
- 'formatUL',
78
- 'checklist',
79
- 'indent',
80
- 'outdent',
81
- 'lineHeight'
74
+ const ParagraphButtons = [
75
+ 'align',
76
+ 'formatOL',
77
+ 'formatUL',
78
+ 'checklist',
79
+ 'indent',
80
+ 'outdent',
81
+ 'lineHeight'
82
82
  ];
83
83
 
84
- const RichButtons = [
85
- 'insertTable',
86
- 'insertImage',
87
- 'insertLink',
88
- 'insertVideo',
84
+ const RichButtons = [
85
+ 'insertTable',
86
+ 'insertImage',
87
+ 'insertLink',
88
+ 'insertVideo',
89
89
  ];
90
90
 
91
- const TextButtons = [
92
- 'paragraphFormat',
93
- 'bold',
94
- 'italic',
95
- 'underline',
96
- 'strikeThrough',
97
- 'subscript',
98
- 'superscript',
99
- 'fontFamily',
100
- 'fontSize',
101
- 'textColor',
102
- 'backgroundColor',
103
- 'inlineClass',
104
- 'inlineStyle',
105
- 'clearFormatting',
106
- 'quote',
107
- 'code',
91
+ const TextButtons = [
92
+ 'paragraphFormat',
93
+ 'bold',
94
+ 'italic',
95
+ 'underline',
96
+ 'strikeThrough',
97
+ 'subscript',
98
+ 'superscript',
99
+ 'fontFamily',
100
+ 'fontSize',
101
+ 'textColor',
102
+ 'backgroundColor',
103
+ 'inlineClass',
104
+ 'inlineStyle',
105
+ 'clearFormatting',
106
+ 'quote',
107
+ 'code',
108
108
  ];
109
109
 
110
- class FsFroalaLoaderService {
111
- constructor(_defaultConfig, _document) {
112
- this._defaultConfig = _defaultConfig;
113
- this._document = _document;
114
- this._froalaLoaded = new BehaviorSubject(false);
115
- this._froalaPluginsLoaded = new BehaviorSubject(false);
116
- this._sourceLoader = fsSourceLoader;
117
- this._loaded$ = combineLatest([this._froalaLoaded, this._froalaPluginsLoaded])
118
- .pipe(map(([FroalaReady, pluginsRead]) => {
119
- return pluginsRead && FroalaReady;
120
- }), shareReplay(1));
121
- this._sourceLoader.setDocument(this._document);
122
- this._load();
123
- }
124
- get loaded$() {
125
- return this._loaded$;
126
- }
127
- get FroalaEditor() {
128
- return this._froalaEditor;
129
- }
130
- _load() {
131
- const baseDir = '/assets/froala/';
132
- this._sourceLoader.registerResources({
133
- froala: [
134
- `${baseDir}js/froala_editor.min.js`,
135
- `${baseDir}css/froala_editor.pkgd.min.css`,
136
- ],
137
- froala_align: `${baseDir}js/plugins/align.min.js`,
138
- froala_colors: `${baseDir}js/plugins/colors.min.js`,
139
- froala_image: `${baseDir}js/plugins/image.min.js`,
140
- froala_link: `${baseDir}js/plugins/link.min.js`,
141
- froala_lists: `${baseDir}js/plugins/lists.min.js`,
142
- froala_paragraph_format: `${baseDir}js/plugins/paragraph_format.min.js`,
143
- froala_table: `${baseDir}js/plugins/table.min.js`,
144
- froala_url: `${baseDir}js/plugins/url.min.js`,
145
- froala_video: `${baseDir}js/plugins/video.min.js`,
146
- froala_quote: `${baseDir}js/plugins/quote.min.js`,
147
- froala_draggable: `${baseDir}js/plugins/draggable.min.js`,
148
- froala_font_size: `${baseDir}js/plugins/font_size.min.js`,
149
- froala_quick_insert: `${baseDir}js/plugins/quick_insert.min.js`,
150
- froala_line_height: `${baseDir}js/plugins/line_height.min.js`,
151
- });
152
- this._sourceLoader.loadResource('froala')
153
- .pipe(tap(() => {
154
- this._froalaEditor = window.FroalaEditor;
155
- this._froalaDone();
156
- }), concatMap(() => {
157
- return this._loadPlugins();
158
- }), tap(() => {
159
- this._froalaPluginsDone();
160
- }))
161
- .subscribe();
162
- }
163
- _loadPlugins() {
164
- const resources = this._defaultConfig
165
- .froalaPlugins
166
- .map((pluginName) => `froala_${pluginName}`);
167
- return this._sourceLoader.loadResources(resources);
168
- }
169
- _froalaDone() {
170
- this._froalaLoaded.next(true);
171
- }
172
- _froalaPluginsDone() {
173
- this._froalaPluginsLoaded.next(true);
174
- }
175
- }
176
- FsFroalaLoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFroalaLoaderService, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
177
- FsFroalaLoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFroalaLoaderService, providedIn: 'root' });
178
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFroalaLoaderService, decorators: [{
179
- type: Injectable,
180
- args: [{
181
- providedIn: 'root',
182
- }]
183
- }], ctorParameters: function () {
184
- return [{ type: undefined, decorators: [{
185
- type: Optional
186
- }, {
187
- type: Inject,
188
- args: [FS_HTML_EDITOR_CONFIG]
189
- }] }, { type: Document, decorators: [{
190
- type: Inject,
191
- args: [DOCUMENT]
192
- }] }];
110
+ class FsFroalaLoaderService {
111
+ constructor(_defaultConfig, _document) {
112
+ this._defaultConfig = _defaultConfig;
113
+ this._document = _document;
114
+ this._froalaLoaded = new BehaviorSubject(false);
115
+ this._froalaPluginsLoaded = new BehaviorSubject(false);
116
+ this._sourceLoader = fsSourceLoader;
117
+ this._loaded$ = combineLatest([this._froalaLoaded, this._froalaPluginsLoaded])
118
+ .pipe(map(([FroalaReady, pluginsRead]) => {
119
+ return pluginsRead && FroalaReady;
120
+ }), shareReplay(1));
121
+ this._sourceLoader.setDocument(this._document);
122
+ this._load();
123
+ }
124
+ get loaded$() {
125
+ return this._loaded$;
126
+ }
127
+ get FroalaEditor() {
128
+ return this._froalaEditor;
129
+ }
130
+ _load() {
131
+ const baseDir = '/assets/froala/';
132
+ this._sourceLoader.registerResources({
133
+ froala: [
134
+ `${baseDir}js/froala_editor.min.js`,
135
+ `${baseDir}css/froala_editor.pkgd.min.css`,
136
+ ],
137
+ froala_align: `${baseDir}js/plugins/align.min.js`,
138
+ froala_colors: `${baseDir}js/plugins/colors.min.js`,
139
+ froala_image: `${baseDir}js/plugins/image.min.js`,
140
+ froala_link: `${baseDir}js/plugins/link.min.js`,
141
+ froala_lists: `${baseDir}js/plugins/lists.min.js`,
142
+ froala_paragraph_format: `${baseDir}js/plugins/paragraph_format.min.js`,
143
+ froala_table: `${baseDir}js/plugins/table.min.js`,
144
+ froala_url: `${baseDir}js/plugins/url.min.js`,
145
+ froala_video: `${baseDir}js/plugins/video.min.js`,
146
+ froala_quote: `${baseDir}js/plugins/quote.min.js`,
147
+ froala_draggable: `${baseDir}js/plugins/draggable.min.js`,
148
+ froala_font_size: `${baseDir}js/plugins/font_size.min.js`,
149
+ froala_quick_insert: `${baseDir}js/plugins/quick_insert.min.js`,
150
+ froala_line_height: `${baseDir}js/plugins/line_height.min.js`,
151
+ });
152
+ this._sourceLoader.loadResource('froala')
153
+ .pipe(tap(() => {
154
+ this._froalaEditor = window.FroalaEditor;
155
+ this._froalaDone();
156
+ }), concatMap(() => {
157
+ return this._loadPlugins();
158
+ }), tap(() => {
159
+ this._froalaPluginsDone();
160
+ }))
161
+ .subscribe();
162
+ }
163
+ _loadPlugins() {
164
+ const resources = this._defaultConfig
165
+ .froalaPlugins
166
+ .map((pluginName) => `froala_${pluginName}`);
167
+ return this._sourceLoader.loadResources(resources);
168
+ }
169
+ _froalaDone() {
170
+ this._froalaLoaded.next(true);
171
+ }
172
+ _froalaPluginsDone() {
173
+ this._froalaPluginsLoaded.next(true);
174
+ }
175
+ }
176
+ FsFroalaLoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsFroalaLoaderService, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
177
+ FsFroalaLoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsFroalaLoaderService, providedIn: 'root' });
178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsFroalaLoaderService, decorators: [{
179
+ type: Injectable,
180
+ args: [{
181
+ providedIn: 'root',
182
+ }]
183
+ }], ctorParameters: function () {
184
+ return [{ type: undefined, decorators: [{
185
+ type: Optional
186
+ }, {
187
+ type: Inject,
188
+ args: [FS_HTML_EDITOR_CONFIG]
189
+ }] }, { type: Document, decorators: [{
190
+ type: Inject,
191
+ args: [DOCUMENT]
192
+ }] }];
193
193
  } });
194
194
 
195
- class FsHtmlEditorComponent {
196
- constructor(_defaultConfig, _cdRef, _fr) {
197
- this._defaultConfig = _defaultConfig;
198
- this._cdRef = _cdRef;
199
- this._fr = _fr;
200
- this.classFocused = false;
201
- this.config = {};
202
- this.disabled = false;
203
- this.initialized = false;
204
- this.containerID = `fs-html-editor-${guid('xxx')}`;
205
- this._initialize$ = new ReplaySubject();
206
- this._froalaReady$ = new BehaviorSubject(null);
207
- this._destroy$ = new Subject();
208
- }
209
- get el() {
210
- return this.elRef.nativeElement;
211
- }
212
- get html() {
213
- return this._html;
214
- }
215
- get editor() {
216
- return this._editor;
217
- }
218
- get froalaLoaded$() {
219
- return this._fr.loaded$;
220
- }
221
- ngOnInit() {
222
- this.config = this.config || {};
223
- this.config.autofocus = this.config.autofocus && (!this.config.disabled || !this.disabled);
224
- this.initialized = !this.config.initOnClick;
225
- }
226
- ngAfterViewInit() {
227
- this._listenLazyInit();
228
- this._initialize$.next();
229
- }
230
- hasContent() {
231
- const el = document.createElement('div');
232
- if (el.querySelector('img')) {
233
- return true;
234
- }
235
- el.innerHTML = this._html;
236
- return !!el.innerText.length;
237
- }
238
- uninitialize() {
239
- this.initialized = false;
240
- }
241
- initialize(options = {}) {
242
- const config = this._createConfig();
243
- this._initPlugins(config);
244
- this._initButtons(config);
245
- this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
246
- this._froalaReady$.next({ config, options });
247
- });
248
- }
249
- updateSize() {
250
- // Hack: To trigger the toolbar button size modes
251
- window.dispatchEvent(new Event('resize'));
252
- }
253
- validate(control) {
254
- const err = {};
255
- if (this.config.maxLength && this._html) {
256
- const maxLength = this.config.maxLength;
257
- const length = this._html.length;
258
- if (length > maxLength) {
259
- err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
260
- }
261
- }
262
- return Object.keys(err).length ? err : null;
263
- }
264
- focus(options) {
265
- options = options ? options : {};
266
- if (options.cursorPosition === 'end') {
267
- this.editor.selection.setAtEnd(this.editor.$el.get(0));
268
- }
269
- else {
270
- this.editor.selection.setAtStart(this.editor.$el.get(0));
271
- }
272
- this.editor.selection.restore();
273
- const elSelection = this.editor.selection.element();
274
- if (elSelection) {
275
- elSelection.scrollIntoView({ block: 'center' });
276
- }
277
- }
278
- clear() {
279
- this.writeValue('');
280
- }
281
- disable() {
282
- this.disabled = true;
283
- }
284
- setHtml(html) {
285
- this.writeValue(html);
286
- }
287
- writeValue(html) {
288
- this._html = html || '';
289
- if (Array.isArray(this._html)) {
290
- this._html = this._html.pop();
291
- }
292
- this._html = this._html
293
- .replace(/<(li)>\s?<(div)>/g, '<li>')
294
- .replace(/<\/(div)><\/(li)>/g, '</li>');
295
- if (this.editor && this.editor.html) {
296
- try {
297
- this.editor.html.set(this._html);
298
- }
299
- catch (e) {
300
- //
301
- }
302
- }
303
- this._cdRef.markForCheck();
304
- }
305
- registerOnChange(fn) {
306
- this.onChange = fn;
307
- }
308
- registerOnTouched(fn) {
309
- this.onTouched = fn;
310
- }
311
- ngOnDestroy() {
312
- this._initialize$.complete();
313
- this._destroy$.next();
314
- this._destroy$.complete();
315
- this.destroy();
316
- }
317
- destroy() {
318
- if (this.editor) {
319
- this.editor.destroy();
320
- }
321
- this.initialized = false;
322
- this._cdRef.markForCheck();
323
- }
324
- _processImageUpload(blob) {
325
- const processor = new FileProcessor();
326
- const file = new FsFile(blob);
327
- const config = {
328
- orientate: true,
329
- quality: this.config.image.quality,
330
- format: this.config.image.format,
331
- maxWidth: this.config.image.width,
332
- maxHeight: this.config.image.height,
333
- minWidth: this.config.image.minWidth,
334
- minHeight: this.config.image.minHeight,
335
- };
336
- return processor.processFile(file, config)
337
- .pipe(switchMap((fsFile) => {
338
- return this.config.image.upload(fsFile.file);
339
- }));
340
- }
341
- _createConfig() {
342
- return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
343
- }
344
- _change(html) {
345
- this._html = html;
346
- this.onChange(html);
347
- }
348
- _initButtons(config) {
349
- (config.buttons || [])
350
- .forEach((button) => {
351
- var _a, _b, _c;
352
- /*
353
- Svg Keys:
354
- ["add", "advancedImageEditor", "alignCenter", "alignJustify", "alignLeft", "alignRight",
355
- "anchors", "back", "backgroundColor", "blockquote", "bold", "cellBackground",
356
- "cellBorderColor", "cellOptions", "cellStyle", "clearFormatting", "close", "codeView",
357
- "cogs", "columns", "editLink", "exitFullscreen", "fontAwesome", "fontFamily",
358
- "fontSize", "fullscreen", "help", "horizontalLine", "imageAltText", "imageCaption",
359
- "imageClass", "imageDisplay", "imageManager", "imageSize", "indent", "inlineClass",
360
- "inlineStyle", "insertEmbed", "insertFile", "insertImage", "insertLink", "insertMore",
361
- "insertTable", "insertVideo", "upload", "italic", "search", "lineHeight", "linkStyles",
362
- "mention", "more", "openLink", "orderedList", "outdent", "pageBreaker",
363
- "paragraphFormat", "paragraphMore", "paragraphStyle", "pdfExport", "print",
364
- "redo", "removeTable", "remove", "replaceImage", "row", "selectAll", "smile",
365
- "spellcheck", "star", "strikeThrough", "subscript", "superscript", "symbols", "tags",
366
- "tableHeader", "tableStyle", "textColor", "textMore", "underline", "undo", "unlink",
367
- "unorderedList", "verticalAlignBottom", "verticalAlignMiddle", "verticalAlignTop"]
368
- */
369
- if (button.svgKey) {
370
- this._fr.FroalaEditor.DefineIcon(button.name, { SVG_KEY: button.svgKey });
371
- }
372
- this._fr.FroalaEditor.RegisterCommand(button.name, {
373
- title: button.title,
374
- focus: (_a = button.focus) !== null && _a !== void 0 ? _a : true,
375
- undo: (_b = button.undo) !== null && _b !== void 0 ? _b : true,
376
- refreshAfterCallback: (_c = button.refreshAfterCallback) !== null && _c !== void 0 ? _c : true,
377
- callback() {
378
- button.click(this);
379
- },
380
- });
381
- });
382
- }
383
- _initPlugins(config) {
384
- (config.prependToolbarTextButtons || [])
385
- .forEach((button) => {
386
- this._defineButton(button);
387
- });
388
- (config.plugins || []).forEach((plugin) => {
389
- this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
390
- plugin.editor = editor;
391
- plugin.initialize();
392
- return plugin;
393
- };
394
- (plugin.config.buttons || [])
395
- .forEach((button) => {
396
- this._defineButton(button);
397
- });
398
- });
399
- }
400
- _defineButton(button) {
401
- if (button.html) {
402
- this._fr.FroalaEditor
403
- .DefineIconTemplate(`${button.name}-template`, button.html);
404
- this._fr.FroalaEditor
405
- .DefineIcon(button.name, {
406
- NAME: `${button.name}-icon`,
407
- template: `${button.name}-template`,
408
- });
409
- }
410
- else {
411
- this._fr.FroalaEditor.DefineIcon(button.name, {
412
- NAME: button.name,
413
- PATH: button.svgPath,
414
- });
415
- }
416
- this._fr.FroalaEditor.RegisterCommand(button.name, {
417
- icon: button.name,
418
- title: button.tooltip,
419
- undo: button.undo,
420
- focus: button.focus,
421
- showOnMobile: button.showOnMobile,
422
- refreshAfterCallback: button.refreshAfterCallback,
423
- callback() {
424
- if (button.click) {
425
- button.click(this);
426
- }
427
- },
428
- refresh(event) {
429
- if (event.refresh) {
430
- event.refresh(this, event);
431
- }
432
- },
433
- });
434
- }
435
- _createOptions() {
436
- var _a, _b;
437
- const config = this._createConfig();
438
- const textButtons = [
439
- ...(config.prependToolbarTextButtons || [])
440
- .map((item) => item.name),
441
- ...TextButtons,
442
- ];
443
- return merge(
444
- // For some reason editor store somewhere pointer on default config object and dublicate options each time on init
445
- // Extra merge level fixed this problem and allow to init config properly without legacy data
446
- {}, {
447
- shortcutsEnabled: ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo', 'insertImage', 'createLink'],
448
- key: config.activationKey,
449
- placeholderText: config.placeholder,
450
- linkAlwaysBlank: true,
451
- tabSpaces: 2,
452
- typingTimer: 250,
453
- tooltips: false,
454
- wordPasteModal: false,
455
- imageDefaultWidth: 0,
456
- paragraphStyles: {
457
- class1: 'Class 1',
458
- class2: 'Class 2',
459
- },
460
- imageDefaultAlign: 'left',
461
- fontFamilyDefaultSelection: 'Font Family',
462
- quickInsertEnabled: false,
463
- scrollableContainer: `#${this.containerID}`,
464
- paragraphDefaultSelection: 'Format',
465
- videoUpload: false,
466
- imagePaste: !!((_a = config.image) === null || _a === void 0 ? void 0 : _a.upload),
467
- imageUpload: !!((_b = config.image) === null || _b === void 0 ? void 0 : _b.upload),
468
- paragraphFormat: {
469
- N: 'Normal',
470
- H1: 'Heading 1',
471
- H2: 'Heading 2',
472
- H3: 'Heading 3',
473
- H4: 'Heading 4',
474
- BLOCKQUOTE: 'Quote',
475
- },
476
- lineHeights: {
477
- Default: '',
478
- 0.5: '0.5',
479
- Single: '1',
480
- 1.15: '1.15',
481
- 1.5: '1.5',
482
- Double: '2',
483
- },
484
- paragraphFormatSelection: true,
485
- toolbarButtonsXS: {
486
- moreText: {
487
- buttons: textButtons,
488
- buttonsVisible: 1,
489
- },
490
- moreParagraph: {
491
- buttons: ParagraphButtons,
492
- buttonsVisible: 2,
493
- },
494
- moreRich: {
495
- buttons: RichButtons,
496
- buttonsVisible: 0,
497
- },
498
- },
499
- toolbarButtons: {
500
- moreText: {
501
- buttons: textButtons,
502
- buttonsVisible: 3,
503
- },
504
- moreParagraph: {
505
- buttons: ParagraphButtons,
506
- buttonsVisible: 5,
507
- },
508
- moreRich: {
509
- buttons: RichButtons,
510
- buttonsVisible: 3,
511
- },
512
- },
513
- }, config.froalaConfig);
514
- }
515
- _listenLazyInit() {
516
- this.froalaLoaded$
517
- .pipe(filter((ready) => ready), switchMap(() => this._initialize$), tap(() => {
518
- const selection = window.getSelection();
519
- const options = {};
520
- if (selection.baseNode) {
521
- options.selection = {
522
- node: selection.baseNode.nodeValue,
523
- offset: selection.baseOffset,
524
- };
525
- }
526
- this.initialize(options);
527
- }), switchMap(() => this._froalaReady$), filter((data) => !!data), tap(({ config, options }) => {
528
- this._setupFroala(config, options);
529
- }))
530
- .subscribe();
531
- }
532
- _contentChanged() {
533
- const editorHTML = this._editor.html.get();
534
- if (this.html !== editorHTML) {
535
- this._change(editorHTML);
536
- }
537
- }
538
- _setupFroala(config, options) {
539
- this._cdRef.markForCheck();
540
- this.setHtml(this._html);
541
- if (config.disabled) {
542
- this.disable();
543
- }
544
- if (config.froalaConfig.events) {
545
- if (config.froalaConfig.events.initialized) {
546
- config.froalaConfig.events.initialized();
547
- }
548
- }
549
- this._editor.events.on('focus', () => {
550
- this.classFocused = true;
551
- this._cdRef.markForCheck();
552
- });
553
- this._editor.events.on('blur', () => {
554
- this.classFocused = false;
555
- this._cdRef.markForCheck();
556
- });
557
- this._editor.events.on('click', () => {
558
- if (this.config.initOnClick && !this.initialized) {
559
- this.initialized = true;
560
- this._cdRef.markForCheck();
561
- }
562
- });
563
- fromEventPattern((handler) => {
564
- this._editor.events.on('contentChanged', handler);
565
- }, () => {
566
- //
567
- })
568
- .pipe(startWith(this._html), map(() => this.editor.html.get()), distinctUntilChanged(), skip(1))
569
- .subscribe(() => {
570
- this._contentChanged();
571
- });
572
- this._editor.events.on('paste.afterCleanup', (html) => {
573
- const div = document.createElement('div');
574
- div.innerHTML = html;
575
- div.querySelectorAll('*')
576
- .forEach((el) => {
577
- for (let i = 0; i < el.attributes.length; i++) {
578
- const name = el.attributes[0].name;
579
- if (name !== 'href') {
580
- el.removeAttribute(name);
581
- }
582
- }
583
- });
584
- return div.innerHTML;
585
- });
586
- this._editor.events.on('keydown', () => {
587
- this.onTouched();
588
- });
589
- if (this.config.image && this.config.image.upload) {
590
- this._editor.events.on('image.beforePasteUpload', (image) => {
591
- fetch(image.getAttribute('src'))
592
- .then((res) => {
593
- res.blob()
594
- .then((blob) => {
595
- this._processImageUpload(blob)
596
- .pipe(takeUntil(this._destroy$))
597
- .subscribe((url) => {
598
- image.setAttribute('src', url);
599
- image.removeAttribute('data-fr-image-pasted');
600
- this._contentChanged();
601
- });
602
- });
603
- });
604
- return false;
605
- });
606
- this._editor.events.on('image.beforeUpload', (blobs) => {
607
- this._processImageUpload(blobs[0])
608
- .pipe(takeUntil(this._destroy$))
609
- .subscribe((url) => {
610
- this.editor.image.insert(url, null, null, this.editor.image.get());
611
- });
612
- return false;
613
- });
614
- }
615
- if (this.el.querySelector('.fr-second-toolbar')) {
616
- this.el.querySelector('.fr-second-toolbar').remove();
617
- }
618
- if (this.config.autofocus && !this.config.initOnClick) {
619
- this.focus();
620
- }
621
- }
622
- }
623
- FsHtmlEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorComponent, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: FsFroalaLoaderService }], target: i0.ɵɵFactoryTarget.Component });
624
- FsHtmlEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: { config: "config", disabled: "disabled" }, host: { properties: { "class.focused": "this.classFocused", "class.disabled": "this.disabled", "class.initialized": "this.initialized" } }, providers: [
625
- {
626
- provide: NG_VALUE_ACCESSOR,
627
- useExisting: forwardRef(() => FsHtmlEditorComponent),
628
- multi: true,
629
- },
630
- {
631
- provide: NG_VALIDATORS,
632
- useExisting: forwardRef(() => FsHtmlEditorComponent),
633
- multi: true,
634
- },
635
- ], queries: [{ propertyName: "htmlEditorContainer", first: true, predicate: FsHtmlEditorContainerDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["elRef"], descendants: true }], ngImport: i0, template: "<fs-label-field>\n <div class=\"outline\">\n <div class=\"outline-overlay\"></div>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <ng-container *ngIf=\"htmlEditorContainer; else htmlEditorContainerTmpl\">\n <ng-container \n [ngTemplateOutlet]=\"htmlEditorContainer\" \n [ngTemplateOutletContext]=\"{ template: htmlEditorContainerTmpl }\">\n </ng-container>\n </ng-container>\n <ng-template #htmlEditorContainerTmpl>\n <div\n class=\"html-editor-container fs-html-editor-default\"\n [id]=\"containerID\"\n [ngClass]=\"{\n 'init-on-click': config.initOnClick\n }\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\"></ng-container>\n <div #elRef></div>\n </div>\n </ng-template>\n </div>\n\n <fs-label-message>\n <div class=\"fs-form-message\">\n <div class=\"fs-form-hint\">{{config.hint}}</div>\n </div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host{position:relative;display:block}:host.initialized .outline-overlay{border:1px solid transparent;position:absolute;inset:-1px;border-width:2px}:host.initialized .outline,:host.initialized .outline-overlay{border-radius:5px}:host.initialized .outline{border:1px solid #E0E0E0;position:relative;padding:0 .75em}:host.initialized .outline fs-label{background:#fff;top:-5px;position:absolute;left:11px;padding:0 3px;z-index:5}:host.initialized:not(.focused):not(.disabled):hover .outline-overlay{border-color:#212121}:host:not(.initialized) ::ng-deep .fr-toolbar{display:none}:host ::ng-deep fs-label-field{margin:.25em 0}:host ::ng-deep .fr-wrapper{border:none!important}:host ::ng-deep .fr-toolbar.fr-top{margin-top:2px}:host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto;display:flex;justify-content:center;padding-left:0!important}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }, { kind: "component", type: i4.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i4.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { kind: "component", type: i4.FsLabelMessageComponent, selector: "fs-label-message" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], viewProviders: [
636
- {
637
- provide: ControlContainer,
638
- deps: [[Optional, NgForm]],
639
- useFactory: (ngForm) => ngForm,
640
- },
641
- ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
642
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorComponent, decorators: [{
643
- type: Component,
644
- args: [{ selector: 'fs-html-editor', providers: [
645
- {
646
- provide: NG_VALUE_ACCESSOR,
647
- useExisting: forwardRef(() => FsHtmlEditorComponent),
648
- multi: true,
649
- },
650
- {
651
- provide: NG_VALIDATORS,
652
- useExisting: forwardRef(() => FsHtmlEditorComponent),
653
- multi: true,
654
- },
655
- ], changeDetection: ChangeDetectionStrategy.OnPush, viewProviders: [
656
- {
657
- provide: ControlContainer,
658
- deps: [[Optional, NgForm]],
659
- useFactory: (ngForm) => ngForm,
660
- },
661
- ], template: "<fs-label-field>\n <div class=\"outline\">\n <div class=\"outline-overlay\"></div>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <ng-container *ngIf=\"htmlEditorContainer; else htmlEditorContainerTmpl\">\n <ng-container \n [ngTemplateOutlet]=\"htmlEditorContainer\" \n [ngTemplateOutletContext]=\"{ template: htmlEditorContainerTmpl }\">\n </ng-container>\n </ng-container>\n <ng-template #htmlEditorContainerTmpl>\n <div\n class=\"html-editor-container fs-html-editor-default\"\n [id]=\"containerID\"\n [ngClass]=\"{\n 'init-on-click': config.initOnClick\n }\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\"></ng-container>\n <div #elRef></div>\n </div>\n </ng-template>\n </div>\n\n <fs-label-message>\n <div class=\"fs-form-message\">\n <div class=\"fs-form-hint\">{{config.hint}}</div>\n </div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host{position:relative;display:block}:host.initialized .outline-overlay{border:1px solid transparent;position:absolute;inset:-1px;border-width:2px}:host.initialized .outline,:host.initialized .outline-overlay{border-radius:5px}:host.initialized .outline{border:1px solid #E0E0E0;position:relative;padding:0 .75em}:host.initialized .outline fs-label{background:#fff;top:-5px;position:absolute;left:11px;padding:0 3px;z-index:5}:host.initialized:not(.focused):not(.disabled):hover .outline-overlay{border-color:#212121}:host:not(.initialized) ::ng-deep .fr-toolbar{display:none}:host ::ng-deep fs-label-field{margin:.25em 0}:host ::ng-deep .fr-wrapper{border:none!important}:host ::ng-deep .fr-toolbar.fr-top{margin-top:2px}:host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto;display:flex;justify-content:center;padding-left:0!important}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"] }]
662
- }], ctorParameters: function () {
663
- return [{ type: undefined, decorators: [{
664
- type: Optional
665
- }, {
666
- type: Inject,
667
- args: [FS_HTML_EDITOR_CONFIG]
668
- }] }, { type: i0.ChangeDetectorRef }, { type: FsFroalaLoaderService }];
669
- }, propDecorators: { htmlEditorContainer: [{
670
- type: ContentChild,
671
- args: [FsHtmlEditorContainerDirective, { read: TemplateRef }]
672
- }], classFocused: [{
673
- type: HostBinding,
674
- args: ['class.focused']
675
- }], elRef: [{
676
- type: ViewChild,
677
- args: ['elRef']
678
- }], config: [{
679
- type: Input
680
- }], disabled: [{
681
- type: Input
682
- }, {
683
- type: HostBinding,
684
- args: ['class.disabled']
685
- }], initialized: [{
686
- type: HostBinding,
687
- args: ['class.initialized']
195
+ class FsHtmlEditorComponent {
196
+ constructor(_defaultConfig, _cdRef, _fr) {
197
+ this._defaultConfig = _defaultConfig;
198
+ this._cdRef = _cdRef;
199
+ this._fr = _fr;
200
+ this.classFocused = false;
201
+ this.config = {};
202
+ this.disabled = false;
203
+ this.initialized = false;
204
+ this.containerID = `fs-html-editor-${guid('xxx')}`;
205
+ this._initialize$ = new ReplaySubject();
206
+ this._froalaReady$ = new BehaviorSubject(null);
207
+ this._destroy$ = new Subject();
208
+ }
209
+ get el() {
210
+ return this.elRef.nativeElement;
211
+ }
212
+ get html() {
213
+ return this._html;
214
+ }
215
+ get editor() {
216
+ return this._editor;
217
+ }
218
+ get froalaLoaded$() {
219
+ return this._fr.loaded$;
220
+ }
221
+ ngOnInit() {
222
+ this.config = this.config || {};
223
+ this.config.autofocus = this.config.autofocus && (!this.config.disabled || !this.disabled);
224
+ this.initialized = !this.config.initOnClick;
225
+ }
226
+ ngAfterViewInit() {
227
+ this._listenLazyInit();
228
+ this._initialize$.next();
229
+ }
230
+ hasContent() {
231
+ const el = document.createElement('div');
232
+ if (el.querySelector('img')) {
233
+ return true;
234
+ }
235
+ el.innerHTML = this._html;
236
+ return !!el.innerText.length;
237
+ }
238
+ uninitialize() {
239
+ this.initialized = false;
240
+ }
241
+ initialize(options = {}) {
242
+ const config = this._createConfig();
243
+ this._initPlugins(config);
244
+ this._initButtons(config);
245
+ this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
246
+ this._froalaReady$.next({ config, options });
247
+ });
248
+ }
249
+ updateSize() {
250
+ // Hack: To trigger the toolbar button size modes
251
+ window.dispatchEvent(new Event('resize'));
252
+ }
253
+ validate(control) {
254
+ const err = {};
255
+ if (this.config.maxLength && this._html) {
256
+ const maxLength = this.config.maxLength;
257
+ const length = this._html.length;
258
+ if (length > maxLength) {
259
+ err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
260
+ }
261
+ }
262
+ return Object.keys(err).length ? err : null;
263
+ }
264
+ focus(options) {
265
+ options = options ? options : {};
266
+ if (options.cursorPosition === 'end') {
267
+ this.editor.selection.setAtEnd(this.editor.$el.get(0));
268
+ }
269
+ else {
270
+ this.editor.selection.setAtStart(this.editor.$el.get(0));
271
+ }
272
+ this.editor.selection.restore();
273
+ const elSelection = this.editor.selection.element();
274
+ if (elSelection) {
275
+ elSelection.scrollIntoView({ block: 'center' });
276
+ }
277
+ }
278
+ clear() {
279
+ this.writeValue('');
280
+ }
281
+ disable() {
282
+ this.disabled = true;
283
+ }
284
+ setHtml(html) {
285
+ this.writeValue(html);
286
+ }
287
+ writeValue(html) {
288
+ this._html = html || '';
289
+ if (Array.isArray(this._html)) {
290
+ this._html = this._html.pop();
291
+ }
292
+ this._html = this._html
293
+ .replace(/<(li)>\s?<(div)>/g, '<li>')
294
+ .replace(/<\/(div)><\/(li)>/g, '</li>');
295
+ if (this.editor && this.editor.html) {
296
+ try {
297
+ this.editor.html.set(this._html);
298
+ }
299
+ catch (e) {
300
+ //
301
+ }
302
+ }
303
+ this._cdRef.markForCheck();
304
+ }
305
+ registerOnChange(fn) {
306
+ this.onChange = fn;
307
+ }
308
+ registerOnTouched(fn) {
309
+ this.onTouched = fn;
310
+ }
311
+ ngOnDestroy() {
312
+ this._initialize$.complete();
313
+ this._destroy$.next();
314
+ this._destroy$.complete();
315
+ this.destroy();
316
+ }
317
+ destroy() {
318
+ if (this.editor) {
319
+ this.editor.destroy();
320
+ }
321
+ this.initialized = false;
322
+ this._cdRef.markForCheck();
323
+ }
324
+ _processImageUpload(blob) {
325
+ const processor = new FileProcessor();
326
+ const file = new FsFile(blob);
327
+ const config = {
328
+ orientate: true,
329
+ quality: this.config.image.quality,
330
+ format: this.config.image.format,
331
+ maxWidth: this.config.image.width,
332
+ maxHeight: this.config.image.height,
333
+ minWidth: this.config.image.minWidth,
334
+ minHeight: this.config.image.minHeight,
335
+ };
336
+ return processor.processFile(file, config)
337
+ .pipe(switchMap((fsFile) => {
338
+ return this.config.image.upload(fsFile.file);
339
+ }));
340
+ }
341
+ _createConfig() {
342
+ return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
343
+ }
344
+ _change(html) {
345
+ this._html = html;
346
+ this.onChange(html);
347
+ }
348
+ _initButtons(config) {
349
+ (config.buttons || [])
350
+ .forEach((button) => {
351
+ var _a, _b, _c;
352
+ /*
353
+ Svg Keys:
354
+ ["add", "advancedImageEditor", "alignCenter", "alignJustify", "alignLeft", "alignRight",
355
+ "anchors", "back", "backgroundColor", "blockquote", "bold", "cellBackground",
356
+ "cellBorderColor", "cellOptions", "cellStyle", "clearFormatting", "close", "codeView",
357
+ "cogs", "columns", "editLink", "exitFullscreen", "fontAwesome", "fontFamily",
358
+ "fontSize", "fullscreen", "help", "horizontalLine", "imageAltText", "imageCaption",
359
+ "imageClass", "imageDisplay", "imageManager", "imageSize", "indent", "inlineClass",
360
+ "inlineStyle", "insertEmbed", "insertFile", "insertImage", "insertLink", "insertMore",
361
+ "insertTable", "insertVideo", "upload", "italic", "search", "lineHeight", "linkStyles",
362
+ "mention", "more", "openLink", "orderedList", "outdent", "pageBreaker",
363
+ "paragraphFormat", "paragraphMore", "paragraphStyle", "pdfExport", "print",
364
+ "redo", "removeTable", "remove", "replaceImage", "row", "selectAll", "smile",
365
+ "spellcheck", "star", "strikeThrough", "subscript", "superscript", "symbols", "tags",
366
+ "tableHeader", "tableStyle", "textColor", "textMore", "underline", "undo", "unlink",
367
+ "unorderedList", "verticalAlignBottom", "verticalAlignMiddle", "verticalAlignTop"]
368
+ */
369
+ if (button.svgKey) {
370
+ this._fr.FroalaEditor.DefineIcon(button.name, { SVG_KEY: button.svgKey });
371
+ }
372
+ this._fr.FroalaEditor.RegisterCommand(button.name, {
373
+ title: button.title,
374
+ focus: (_a = button.focus) !== null && _a !== void 0 ? _a : true,
375
+ undo: (_b = button.undo) !== null && _b !== void 0 ? _b : true,
376
+ refreshAfterCallback: (_c = button.refreshAfterCallback) !== null && _c !== void 0 ? _c : true,
377
+ callback() {
378
+ button.click(this);
379
+ },
380
+ });
381
+ });
382
+ }
383
+ _initPlugins(config) {
384
+ (config.prependToolbarTextButtons || [])
385
+ .forEach((button) => {
386
+ this._defineButton(button);
387
+ });
388
+ (config.plugins || []).forEach((plugin) => {
389
+ this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
390
+ plugin.editor = editor;
391
+ plugin.initialize();
392
+ return plugin;
393
+ };
394
+ (plugin.config.buttons || [])
395
+ .forEach((button) => {
396
+ this._defineButton(button);
397
+ });
398
+ });
399
+ }
400
+ _defineButton(button) {
401
+ if (button.html) {
402
+ this._fr.FroalaEditor
403
+ .DefineIconTemplate(`${button.name}-template`, button.html);
404
+ this._fr.FroalaEditor
405
+ .DefineIcon(button.name, {
406
+ NAME: `${button.name}-icon`,
407
+ template: `${button.name}-template`,
408
+ });
409
+ }
410
+ else {
411
+ this._fr.FroalaEditor.DefineIcon(button.name, {
412
+ NAME: button.name,
413
+ PATH: button.svgPath,
414
+ });
415
+ }
416
+ this._fr.FroalaEditor.RegisterCommand(button.name, {
417
+ icon: button.name,
418
+ title: button.tooltip,
419
+ undo: button.undo,
420
+ focus: button.focus,
421
+ showOnMobile: button.showOnMobile,
422
+ refreshAfterCallback: button.refreshAfterCallback,
423
+ callback() {
424
+ if (button.click) {
425
+ button.click(this);
426
+ }
427
+ },
428
+ refresh(event) {
429
+ if (event.refresh) {
430
+ event.refresh(this, event);
431
+ }
432
+ },
433
+ });
434
+ }
435
+ _createOptions() {
436
+ var _a, _b;
437
+ const config = this._createConfig();
438
+ const textButtons = [
439
+ ...(config.prependToolbarTextButtons || [])
440
+ .map((item) => item.name),
441
+ ...TextButtons,
442
+ ];
443
+ return merge(
444
+ // For some reason editor store somewhere pointer on default config object and dublicate options each time on init
445
+ // Extra merge level fixed this problem and allow to init config properly without legacy data
446
+ {}, {
447
+ shortcutsEnabled: ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo', 'insertImage', 'createLink'],
448
+ key: config.activationKey,
449
+ placeholderText: config.placeholder,
450
+ linkAlwaysBlank: true,
451
+ tabSpaces: 2,
452
+ typingTimer: 250,
453
+ tooltips: false,
454
+ wordPasteModal: false,
455
+ imageDefaultWidth: 0,
456
+ paragraphStyles: {
457
+ class1: 'Class 1',
458
+ class2: 'Class 2',
459
+ },
460
+ imageDefaultAlign: 'left',
461
+ fontFamilyDefaultSelection: 'Font Family',
462
+ quickInsertEnabled: false,
463
+ scrollableContainer: `#${this.containerID}`,
464
+ paragraphDefaultSelection: 'Format',
465
+ videoUpload: false,
466
+ imagePaste: !!((_a = config.image) === null || _a === void 0 ? void 0 : _a.upload),
467
+ imageUpload: !!((_b = config.image) === null || _b === void 0 ? void 0 : _b.upload),
468
+ paragraphFormat: {
469
+ N: 'Normal',
470
+ H1: 'Heading 1',
471
+ H2: 'Heading 2',
472
+ H3: 'Heading 3',
473
+ H4: 'Heading 4',
474
+ BLOCKQUOTE: 'Quote',
475
+ },
476
+ lineHeights: {
477
+ Default: '',
478
+ 0.5: '0.5',
479
+ Single: '1',
480
+ 1.15: '1.15',
481
+ 1.5: '1.5',
482
+ Double: '2',
483
+ },
484
+ paragraphFormatSelection: true,
485
+ toolbarButtonsXS: {
486
+ moreText: {
487
+ buttons: textButtons,
488
+ buttonsVisible: 1,
489
+ },
490
+ moreParagraph: {
491
+ buttons: ParagraphButtons,
492
+ buttonsVisible: 2,
493
+ },
494
+ moreRich: {
495
+ buttons: RichButtons,
496
+ buttonsVisible: 0,
497
+ },
498
+ },
499
+ toolbarButtons: {
500
+ moreText: {
501
+ buttons: textButtons,
502
+ buttonsVisible: 3,
503
+ },
504
+ moreParagraph: {
505
+ buttons: ParagraphButtons,
506
+ buttonsVisible: 5,
507
+ },
508
+ moreRich: {
509
+ buttons: RichButtons,
510
+ buttonsVisible: 3,
511
+ },
512
+ },
513
+ }, config.froalaConfig);
514
+ }
515
+ _listenLazyInit() {
516
+ this.froalaLoaded$
517
+ .pipe(filter((ready) => ready), switchMap(() => this._initialize$), tap(() => {
518
+ const selection = window.getSelection();
519
+ const options = {};
520
+ if (selection.baseNode) {
521
+ options.selection = {
522
+ node: selection.baseNode.nodeValue,
523
+ offset: selection.baseOffset,
524
+ };
525
+ }
526
+ this.initialize(options);
527
+ }), switchMap(() => this._froalaReady$), filter((data) => !!data), tap(({ config, options }) => {
528
+ this._setupFroala(config, options);
529
+ }))
530
+ .subscribe();
531
+ }
532
+ _contentChanged() {
533
+ const editorHTML = this._editor.html.get();
534
+ if (this.html !== editorHTML) {
535
+ this._change(editorHTML);
536
+ }
537
+ }
538
+ _setupFroala(config, options) {
539
+ this._cdRef.markForCheck();
540
+ this.setHtml(this._html);
541
+ if (config.disabled) {
542
+ this.disable();
543
+ }
544
+ if (config.froalaConfig.events) {
545
+ if (config.froalaConfig.events.initialized) {
546
+ config.froalaConfig.events.initialized();
547
+ }
548
+ }
549
+ this._editor.events.on('focus', () => {
550
+ this.classFocused = true;
551
+ this._cdRef.markForCheck();
552
+ });
553
+ this._editor.events.on('blur', () => {
554
+ this.classFocused = false;
555
+ this._cdRef.markForCheck();
556
+ });
557
+ this._editor.events.on('click', () => {
558
+ if (this.config.initOnClick && !this.initialized) {
559
+ this.initialized = true;
560
+ this._cdRef.markForCheck();
561
+ }
562
+ });
563
+ fromEventPattern((handler) => {
564
+ this._editor.events.on('contentChanged', handler);
565
+ }, () => {
566
+ //
567
+ })
568
+ .pipe(startWith(this._html), map(() => this.editor.html.get()), distinctUntilChanged(), skip(1))
569
+ .subscribe(() => {
570
+ this._contentChanged();
571
+ });
572
+ this._editor.events.on('paste.afterCleanup', (html) => {
573
+ const div = document.createElement('div');
574
+ div.innerHTML = html;
575
+ div.querySelectorAll('*')
576
+ .forEach((el) => {
577
+ for (let i = 0; i < el.attributes.length; i++) {
578
+ const name = el.attributes[0].name;
579
+ if (name !== 'href') {
580
+ el.removeAttribute(name);
581
+ }
582
+ }
583
+ });
584
+ return div.innerHTML;
585
+ });
586
+ this._editor.events.on('keydown', () => {
587
+ this.onTouched();
588
+ });
589
+ if (this.config.image && this.config.image.upload) {
590
+ this._editor.events.on('image.beforePasteUpload', (image) => {
591
+ fetch(image.getAttribute('src'))
592
+ .then((res) => {
593
+ res.blob()
594
+ .then((blob) => {
595
+ this._processImageUpload(blob)
596
+ .pipe(takeUntil(this._destroy$))
597
+ .subscribe((url) => {
598
+ image.setAttribute('src', url);
599
+ image.removeAttribute('data-fr-image-pasted');
600
+ this._contentChanged();
601
+ });
602
+ });
603
+ });
604
+ return false;
605
+ });
606
+ this._editor.events.on('image.beforeUpload', (blobs) => {
607
+ this._processImageUpload(blobs[0])
608
+ .pipe(takeUntil(this._destroy$))
609
+ .subscribe((url) => {
610
+ this.editor.image.insert(url, null, null, this.editor.image.get());
611
+ });
612
+ return false;
613
+ });
614
+ }
615
+ if (this.el.querySelector('.fr-second-toolbar')) {
616
+ this.el.querySelector('.fr-second-toolbar').remove();
617
+ }
618
+ if (this.config.autofocus && !this.config.initOnClick) {
619
+ this.focus();
620
+ }
621
+ }
622
+ }
623
+ FsHtmlEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorComponent, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: FsFroalaLoaderService }], target: i0.ɵɵFactoryTarget.Component });
624
+ FsHtmlEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: { config: "config", disabled: "disabled" }, host: { properties: { "class.focused": "this.classFocused", "class.disabled": "this.disabled", "class.initialized": "this.initialized" } }, providers: [
625
+ {
626
+ provide: NG_VALUE_ACCESSOR,
627
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
628
+ multi: true,
629
+ },
630
+ {
631
+ provide: NG_VALIDATORS,
632
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
633
+ multi: true,
634
+ },
635
+ ], queries: [{ propertyName: "htmlEditorContainer", first: true, predicate: FsHtmlEditorContainerDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["elRef"], descendants: true }], ngImport: i0, template: "<fs-label-field>\n <div class=\"outline\">\n <div class=\"outline-overlay\"></div>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <ng-container *ngIf=\"htmlEditorContainer; else htmlEditorContainerTmpl\">\n <ng-container \n [ngTemplateOutlet]=\"htmlEditorContainer\" \n [ngTemplateOutletContext]=\"{ template: htmlEditorContainerTmpl }\">\n </ng-container>\n </ng-container>\n <ng-template #htmlEditorContainerTmpl>\n <div\n class=\"html-editor-container fs-html-editor-default\"\n [id]=\"containerID\"\n [ngClass]=\"{\n 'init-on-click': config.initOnClick\n }\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\"></ng-container>\n <div #elRef></div>\n </div>\n </ng-template>\n </div>\n\n <fs-label-message>\n <div class=\"fs-form-message\">\n <div class=\"fs-form-hint\">{{config.hint}}</div>\n </div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host{position:relative;display:block}:host.initialized .outline-overlay{border:1px solid transparent;position:absolute;inset:-1px;border-width:2px}:host.initialized .outline,:host.initialized .outline-overlay{border-radius:5px}:host.initialized .outline{border:1px solid #E0E0E0;position:relative;padding:0 .75em}:host.initialized .outline fs-label{background:#fff;top:-5px;position:absolute;left:11px;padding:0 3px;z-index:5}:host.initialized:not(.focused):not(.disabled):hover .outline-overlay{border-color:#212121}:host:not(.initialized) ::ng-deep .fr-toolbar{display:none}:host ::ng-deep fs-label-field{margin:.25em 0}:host ::ng-deep .fr-wrapper{border:none!important}:host ::ng-deep .fr-toolbar.fr-top{margin-top:2px}:host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto;display:flex;justify-content:center;padding-left:0!important}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }, { kind: "component", type: i4.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i4.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { kind: "component", type: i4.FsLabelMessageComponent, selector: "fs-label-message" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], viewProviders: [
636
+ {
637
+ provide: ControlContainer,
638
+ deps: [[Optional, NgForm]],
639
+ useFactory: (ngForm) => ngForm,
640
+ },
641
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
642
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorComponent, decorators: [{
643
+ type: Component,
644
+ args: [{ selector: 'fs-html-editor', providers: [
645
+ {
646
+ provide: NG_VALUE_ACCESSOR,
647
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
648
+ multi: true,
649
+ },
650
+ {
651
+ provide: NG_VALIDATORS,
652
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
653
+ multi: true,
654
+ },
655
+ ], changeDetection: ChangeDetectionStrategy.OnPush, viewProviders: [
656
+ {
657
+ provide: ControlContainer,
658
+ deps: [[Optional, NgForm]],
659
+ useFactory: (ngForm) => ngForm,
660
+ },
661
+ ], template: "<fs-label-field>\n <div class=\"outline\">\n <div class=\"outline-overlay\"></div>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <ng-container *ngIf=\"htmlEditorContainer; else htmlEditorContainerTmpl\">\n <ng-container \n [ngTemplateOutlet]=\"htmlEditorContainer\" \n [ngTemplateOutletContext]=\"{ template: htmlEditorContainerTmpl }\">\n </ng-container>\n </ng-container>\n <ng-template #htmlEditorContainerTmpl>\n <div\n class=\"html-editor-container fs-html-editor-default\"\n [id]=\"containerID\"\n [ngClass]=\"{\n 'init-on-click': config.initOnClick\n }\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\"></ng-container>\n <div #elRef></div>\n </div>\n </ng-template>\n </div>\n\n <fs-label-message>\n <div class=\"fs-form-message\">\n <div class=\"fs-form-hint\">{{config.hint}}</div>\n </div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host{position:relative;display:block}:host.initialized .outline-overlay{border:1px solid transparent;position:absolute;inset:-1px;border-width:2px}:host.initialized .outline,:host.initialized .outline-overlay{border-radius:5px}:host.initialized .outline{border:1px solid #E0E0E0;position:relative;padding:0 .75em}:host.initialized .outline fs-label{background:#fff;top:-5px;position:absolute;left:11px;padding:0 3px;z-index:5}:host.initialized:not(.focused):not(.disabled):hover .outline-overlay{border-color:#212121}:host:not(.initialized) ::ng-deep .fr-toolbar{display:none}:host ::ng-deep fs-label-field{margin:.25em 0}:host ::ng-deep .fr-wrapper{border:none!important}:host ::ng-deep .fr-toolbar.fr-top{margin-top:2px}:host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto;display:flex;justify-content:center;padding-left:0!important}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"] }]
662
+ }], ctorParameters: function () {
663
+ return [{ type: undefined, decorators: [{
664
+ type: Optional
665
+ }, {
666
+ type: Inject,
667
+ args: [FS_HTML_EDITOR_CONFIG]
668
+ }] }, { type: i0.ChangeDetectorRef }, { type: FsFroalaLoaderService }];
669
+ }, propDecorators: { htmlEditorContainer: [{
670
+ type: ContentChild,
671
+ args: [FsHtmlEditorContainerDirective, { read: TemplateRef }]
672
+ }], classFocused: [{
673
+ type: HostBinding,
674
+ args: ['class.focused']
675
+ }], elRef: [{
676
+ type: ViewChild,
677
+ args: ['elRef']
678
+ }], config: [{
679
+ type: Input
680
+ }], disabled: [{
681
+ type: Input
682
+ }, {
683
+ type: HostBinding,
684
+ args: ['class.disabled']
685
+ }], initialized: [{
686
+ type: HostBinding,
687
+ args: ['class.initialized']
688
688
  }] } });
689
689
 
690
- class FsHtmlEditorModule {
691
- static forRoot(config = {}) {
692
- return {
693
- ngModule: FsHtmlEditorModule,
694
- providers: [
695
- { provide: FS_HTML_EDITOR_DEFAULT_CONFIG, useValue: config },
696
- {
697
- provide: FS_HTML_EDITOR_CONFIG,
698
- useFactory: FsHtmlEditorConfigFactory,
699
- deps: [FS_HTML_EDITOR_DEFAULT_CONFIG],
700
- },
701
- ],
702
- };
703
- }
704
- }
705
- FsHtmlEditorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
706
- FsHtmlEditorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorModule, declarations: [FsHtmlEditorComponent,
707
- FsHtmlEditorContainerDirective], imports: [CommonModule,
708
- FsSkeletonModule,
709
- FsLabelModule,
710
- FsHtmlRendererModule], exports: [FsHtmlEditorComponent,
711
- FsHtmlEditorContainerDirective] });
712
- FsHtmlEditorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorModule, imports: [CommonModule,
713
- FsSkeletonModule,
714
- FsLabelModule,
715
- FsHtmlRendererModule] });
716
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsHtmlEditorModule, decorators: [{
717
- type: NgModule,
718
- args: [{
719
- imports: [
720
- CommonModule,
721
- FsSkeletonModule,
722
- FsLabelModule,
723
- FsHtmlRendererModule,
724
- ],
725
- exports: [
726
- FsHtmlEditorComponent,
727
- FsHtmlEditorContainerDirective,
728
- ],
729
- declarations: [
730
- FsHtmlEditorComponent,
731
- FsHtmlEditorContainerDirective,
732
- ],
733
- }]
734
- }] });
735
- function FsHtmlEditorConfigFactory(config) {
736
- return Object.assign({ froalaPlugins: [
737
- "align" /* Align */,
738
- "colors" /* Colors */,
739
- "image" /* Image */,
740
- "link" /* Link */,
741
- "lists" /* Lists */,
742
- "paragraph_format" /* ParagraphFormat */,
743
- "quote" /* Quote */,
744
- "table" /* Table */,
745
- "url" /* Url */,
746
- "video" /* Video */,
747
- "draggable" /* Draggable */,
748
- "font_size" /* FontSize */,
749
- "line_height" /* LineHeight */,
750
- ] }, config);
690
+ class FsHtmlEditorModule {
691
+ static forRoot(config = {}) {
692
+ return {
693
+ ngModule: FsHtmlEditorModule,
694
+ providers: [
695
+ { provide: FS_HTML_EDITOR_DEFAULT_CONFIG, useValue: config },
696
+ {
697
+ provide: FS_HTML_EDITOR_CONFIG,
698
+ useFactory: FsHtmlEditorConfigFactory,
699
+ deps: [FS_HTML_EDITOR_DEFAULT_CONFIG],
700
+ },
701
+ ],
702
+ };
703
+ }
704
+ }
705
+ FsHtmlEditorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
706
+ FsHtmlEditorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorModule, declarations: [FsHtmlEditorComponent,
707
+ FsHtmlEditorContainerDirective], imports: [CommonModule,
708
+ FsSkeletonModule,
709
+ FsLabelModule,
710
+ FsHtmlRendererModule], exports: [FsHtmlEditorComponent,
711
+ FsHtmlEditorContainerDirective] });
712
+ FsHtmlEditorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorModule, imports: [CommonModule,
713
+ FsSkeletonModule,
714
+ FsLabelModule,
715
+ FsHtmlRendererModule] });
716
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsHtmlEditorModule, decorators: [{
717
+ type: NgModule,
718
+ args: [{
719
+ imports: [
720
+ CommonModule,
721
+ FsSkeletonModule,
722
+ FsLabelModule,
723
+ FsHtmlRendererModule,
724
+ ],
725
+ exports: [
726
+ FsHtmlEditorComponent,
727
+ FsHtmlEditorContainerDirective,
728
+ ],
729
+ declarations: [
730
+ FsHtmlEditorComponent,
731
+ FsHtmlEditorContainerDirective,
732
+ ],
733
+ }]
734
+ }] });
735
+ function FsHtmlEditorConfigFactory(config) {
736
+ return Object.assign({ froalaPlugins: [
737
+ "align" /* FroalaPlugin.Align */,
738
+ "colors" /* FroalaPlugin.Colors */,
739
+ "image" /* FroalaPlugin.Image */,
740
+ "link" /* FroalaPlugin.Link */,
741
+ "lists" /* FroalaPlugin.Lists */,
742
+ "paragraph_format" /* FroalaPlugin.ParagraphFormat */,
743
+ "quote" /* FroalaPlugin.Quote */,
744
+ "table" /* FroalaPlugin.Table */,
745
+ "url" /* FroalaPlugin.Url */,
746
+ "video" /* FroalaPlugin.Video */,
747
+ "draggable" /* FroalaPlugin.Draggable */,
748
+ "font_size" /* FroalaPlugin.FontSize */,
749
+ "line_height" /* FroalaPlugin.LineHeight */,
750
+ ] }, config);
751
751
  }
752
752
 
753
- class Plugin {
754
- initialize() { }
755
- destroy() { }
753
+ class Plugin {
754
+ initialize() { }
755
+ destroy() { }
756
756
  }
757
757
 
758
- class ChecklistPlugin extends Plugin {
759
- constructor(config = { name: 'checklist' }) {
760
- super();
761
- this.config = config;
762
- this.config = Object.assign(Object.assign({}, config), { name: 'checklist', buttons: [
763
- {
764
- name: 'checklist',
765
- svgPath: 'M8.4,10.3l-1.2,1.2l4,4L20,6.7l-1.2-1.2l-7.6,7.6L8.4,10.3z M18.2,18.2H5.8V5.8h8.9V4H5.8C4.8,4,4,4.8,4,5.8v12.4c0,1,0.8,1.8,1.8,1.8h12.4c1,0,1.8-0.8,1.8-1.8v-7.1h-1.8V18.2z',
766
- click: (editor) => {
767
- editor.html.insert('<ul class="checklist"><li></li></ul>');
768
- }
769
- }
770
- ] });
771
- }
772
- initialize() {
773
- this.editor.events.on('click', (e) => {
774
- const li = e.target;
775
- if (li.nodeName === 'LI' && e.offsetX < 0) {
776
- const items = [li, ...li.querySelectorAll('li')];
777
- if (li.classList.contains('checked')) {
778
- items.forEach((item) => {
779
- item.classList.remove('checked');
780
- });
781
- }
782
- else {
783
- items.forEach((item) => {
784
- item.classList.add('checked');
785
- });
786
- }
787
- }
788
- }, false);
789
- }
758
+ class ChecklistPlugin extends Plugin {
759
+ constructor(config = { name: 'checklist' }) {
760
+ super();
761
+ this.config = config;
762
+ this.config = Object.assign(Object.assign({}, config), { name: 'checklist', buttons: [
763
+ {
764
+ name: 'checklist',
765
+ svgPath: 'M8.4,10.3l-1.2,1.2l4,4L20,6.7l-1.2-1.2l-7.6,7.6L8.4,10.3z M18.2,18.2H5.8V5.8h8.9V4H5.8C4.8,4,4,4.8,4,5.8v12.4c0,1,0.8,1.8,1.8,1.8h12.4c1,0,1.8-0.8,1.8-1.8v-7.1h-1.8V18.2z',
766
+ click: (editor) => {
767
+ editor.html.insert('<ul class="checklist"><li></li></ul>');
768
+ }
769
+ }
770
+ ] });
771
+ }
772
+ initialize() {
773
+ this.editor.events.on('click', (e) => {
774
+ const li = e.target;
775
+ if (li.nodeName === 'LI' && e.offsetX < 0) {
776
+ const items = [li, ...li.querySelectorAll('li')];
777
+ if (li.classList.contains('checked')) {
778
+ items.forEach((item) => {
779
+ item.classList.remove('checked');
780
+ });
781
+ }
782
+ else {
783
+ items.forEach((item) => {
784
+ item.classList.add('checked');
785
+ });
786
+ }
787
+ }
788
+ }, false);
789
+ }
790
790
  }
791
791
 
792
- class CodePlugin extends Plugin {
793
- constructor(config = { name: 'code' }) {
794
- super();
795
- this.config = config;
796
- this.config = Object.assign(Object.assign({}, config), { name: 'code', buttons: [
797
- {
798
- name: 'code',
799
- svgPath: 'M8.9,7.3L4.2,12l4.7,4.7l1.1-1.1L6.4,12L10,8.4L8.9,7.3z M15.1,7.3L14,8.4l3.6,3.6L14,15.6l1.1,1.1l4.7-4.7L15.1,7.3z',
800
- click: (editor) => {
801
- const node = editor.selection.get();
802
- const codeEl = this._getCodeEl(node.baseNode);
803
- if (codeEl) {
804
- codeEl.classList.remove('code');
805
- }
806
- else {
807
- editor.html.insert('<p class="code">' + editor.selection.get().toString().replace(/\n{1,}/g, '<br>') + '</p>');
808
- }
809
- }
810
- }
811
- ] });
812
- }
813
- initialize() {
814
- this.editor.events.on('keydown', (e) => {
815
- if (e.keyCode === 13) {
816
- const selection = this.editor.selection.get();
817
- if (selection && this._getCodeEl(selection.baseNode)) {
818
- e.preventDefault();
819
- e.stopPropagation();
820
- e.stopImmediatePropagation();
821
- let br = '<br>';
822
- const base = selection.baseNode;
823
- if (base.nodeName === '#text' && selection.baseOffset === base.length) {
824
- if (!(base.nextSibling && base.nextSibling.nodeName === 'BR')) {
825
- br += '<br>';
826
- }
827
- }
828
- else {
829
- const el = Array.from(base.childNodes).splice(selection.baseOffset - 1, 1).pop();
830
- if (el && el.nodeName !== 'BR') {
831
- br += '<br>';
832
- }
833
- }
834
- this.editor.html.insert(br);
835
- return false;
836
- }
837
- }
838
- }, true);
839
- }
840
- destroy() { }
841
- _getCodeEl(el) {
842
- if (el) {
843
- if (el.classList && el.classList.contains('code')) {
844
- return el;
845
- }
846
- if (el.parentElement) {
847
- return this._getCodeEl(el.parentElement);
848
- }
849
- }
850
- return null;
851
- }
792
+ class CodePlugin extends Plugin {
793
+ constructor(config = { name: 'code' }) {
794
+ super();
795
+ this.config = config;
796
+ this.config = Object.assign(Object.assign({}, config), { name: 'code', buttons: [
797
+ {
798
+ name: 'code',
799
+ svgPath: 'M8.9,7.3L4.2,12l4.7,4.7l1.1-1.1L6.4,12L10,8.4L8.9,7.3z M15.1,7.3L14,8.4l3.6,3.6L14,15.6l1.1,1.1l4.7-4.7L15.1,7.3z',
800
+ click: (editor) => {
801
+ const node = editor.selection.get();
802
+ const codeEl = this._getCodeEl(node.baseNode);
803
+ if (codeEl) {
804
+ codeEl.classList.remove('code');
805
+ }
806
+ else {
807
+ editor.html.insert('<p class="code">' + editor.selection.get().toString().replace(/\n{1,}/g, '<br>') + '</p>');
808
+ }
809
+ }
810
+ }
811
+ ] });
812
+ }
813
+ initialize() {
814
+ this.editor.events.on('keydown', (e) => {
815
+ if (e.keyCode === 13) {
816
+ const selection = this.editor.selection.get();
817
+ if (selection && this._getCodeEl(selection.baseNode)) {
818
+ e.preventDefault();
819
+ e.stopPropagation();
820
+ e.stopImmediatePropagation();
821
+ let br = '<br>';
822
+ const base = selection.baseNode;
823
+ if (base.nodeName === '#text' && selection.baseOffset === base.length) {
824
+ if (!(base.nextSibling && base.nextSibling.nodeName === 'BR')) {
825
+ br += '<br>';
826
+ }
827
+ }
828
+ else {
829
+ const el = Array.from(base.childNodes).splice(selection.baseOffset - 1, 1).pop();
830
+ if (el && el.nodeName !== 'BR') {
831
+ br += '<br>';
832
+ }
833
+ }
834
+ this.editor.html.insert(br);
835
+ return false;
836
+ }
837
+ }
838
+ }, true);
839
+ }
840
+ destroy() { }
841
+ _getCodeEl(el) {
842
+ if (el) {
843
+ if (el.classList && el.classList.contains('code')) {
844
+ return el;
845
+ }
846
+ if (el.parentElement) {
847
+ return this._getCodeEl(el.parentElement);
848
+ }
849
+ }
850
+ return null;
851
+ }
852
852
  }
853
853
 
854
- class MentionPlugin extends Plugin {
855
- constructor(config) {
856
- super();
857
- this.config = config;
858
- this._guid = guid();
859
- this.selected = (event) => {
860
- if (this.config.selected) {
861
- if (MentionPlugin._currentGuid === this._guid) {
862
- this.config.selected(event.detail.item.original);
863
- }
864
- }
865
- };
866
- this.config = Object.assign(Object.assign({}, config), { buttons: [
867
- {
868
- name: config.name,
869
- tooltip: config.tooltip,
870
- svgPath: config.iconPath,
871
- click: (editor) => {
872
- this._closeAll();
873
- this._tribute.showMenuForCollection(editor.el);
874
- }
875
- }
876
- ] });
877
- this._tribute = new Tribute({
878
- values: debounce(this._loadValues.bind(this), 200),
879
- searchOpts: {
880
- pre: '',
881
- post: '',
882
- skip: true
883
- },
884
- containerClass: `fs-html-editor-mention-container ${this.config.containerClass || ''}`,
885
- itemClass: `fs-html-editor-mention-menu-item ${this.config.menuItemClass || ''}`,
886
- trigger: this.config.trigger,
887
- allowSpaces: true,
888
- menuItemTemplate: (item) => {
889
- return this.config.menuItemTemplate(item.original);
890
- },
891
- selectTemplate: (item) => {
892
- const template = this.config.selectedTemplate(item.original);
893
- let p = document.createElement('p');
894
- p.innerHTML = template;
895
- let node = p.firstElementChild;
896
- if (!node) {
897
- node = document.createElement('span');
898
- node.innerHTML = template;
899
- }
900
- node.setAttribute('contenteditable', 'false');
901
- node.classList.add('fr-deletable');
902
- return node.outerHTML;
903
- },
904
- });
905
- MentionPlugin._tributes.push(this._tribute);
906
- }
907
- initialize() {
908
- this._tribute.attach(this.editor.el);
909
- this.editor.events.on('keydown', (e) => {
910
- if (e.key === 'Enter' && this._tribute.isActive) {
911
- return false;
912
- }
913
- }, true);
914
- this.editor.el.addEventListener("tribute-replaced", this.selected);
915
- }
916
- destroy() {
917
- this.editor.el.removeEventListener("tribute-replaced", this.selected);
918
- }
919
- _closeAll() {
920
- MentionPlugin._tributes.forEach((tribute) => {
921
- if (tribute.menu) {
922
- tribute.hideMenu();
923
- }
924
- });
925
- }
926
- _loadValues(keyword, cb) {
927
- MentionPlugin._currentGuid = this._guid;
928
- return this.config.fetch(keyword)
929
- .subscribe((data) => {
930
- cb(data);
931
- });
932
- }
933
- }
934
- MentionPlugin._currentGuid = null;
854
+ class MentionPlugin extends Plugin {
855
+ constructor(config) {
856
+ super();
857
+ this.config = config;
858
+ this._guid = guid();
859
+ this.selected = (event) => {
860
+ if (this.config.selected) {
861
+ if (MentionPlugin._currentGuid === this._guid) {
862
+ this.config.selected(event.detail.item.original);
863
+ }
864
+ }
865
+ };
866
+ this.config = Object.assign(Object.assign({}, config), { buttons: [
867
+ {
868
+ name: config.name,
869
+ tooltip: config.tooltip,
870
+ svgPath: config.iconPath,
871
+ click: (editor) => {
872
+ this._closeAll();
873
+ this._tribute.showMenuForCollection(editor.el);
874
+ }
875
+ }
876
+ ] });
877
+ this._tribute = new Tribute({
878
+ values: debounce(this._loadValues.bind(this), 200),
879
+ searchOpts: {
880
+ pre: '',
881
+ post: '',
882
+ skip: true
883
+ },
884
+ containerClass: `fs-html-editor-mention-container ${this.config.containerClass || ''}`,
885
+ itemClass: `fs-html-editor-mention-menu-item ${this.config.menuItemClass || ''}`,
886
+ trigger: this.config.trigger,
887
+ allowSpaces: true,
888
+ menuItemTemplate: (item) => {
889
+ return this.config.menuItemTemplate(item.original);
890
+ },
891
+ selectTemplate: (item) => {
892
+ const template = this.config.selectedTemplate(item.original);
893
+ let p = document.createElement('p');
894
+ p.innerHTML = template;
895
+ let node = p.firstElementChild;
896
+ if (!node) {
897
+ node = document.createElement('span');
898
+ node.innerHTML = template;
899
+ }
900
+ node.setAttribute('contenteditable', 'false');
901
+ node.classList.add('fr-deletable');
902
+ return node.outerHTML;
903
+ },
904
+ });
905
+ MentionPlugin._tributes.push(this._tribute);
906
+ }
907
+ initialize() {
908
+ this._tribute.attach(this.editor.el);
909
+ this.editor.events.on('keydown', (e) => {
910
+ if (e.key === 'Enter' && this._tribute.isActive) {
911
+ return false;
912
+ }
913
+ }, true);
914
+ this.editor.el.addEventListener("tribute-replaced", this.selected);
915
+ }
916
+ destroy() {
917
+ this.editor.el.removeEventListener("tribute-replaced", this.selected);
918
+ }
919
+ _closeAll() {
920
+ MentionPlugin._tributes.forEach((tribute) => {
921
+ if (tribute.menu) {
922
+ tribute.hideMenu();
923
+ }
924
+ });
925
+ }
926
+ _loadValues(keyword, cb) {
927
+ MentionPlugin._currentGuid = this._guid;
928
+ return this.config.fetch(keyword)
929
+ .subscribe((data) => {
930
+ cb(data);
931
+ });
932
+ }
933
+ }
934
+ MentionPlugin._currentGuid = null;
935
935
  MentionPlugin._tributes = [];
936
936
 
937
- class RealtimePlugin extends Plugin {
938
- constructor(config = { name: 'realtime' }) {
939
- super();
940
- this.config = config;
941
- this.config = Object.assign(Object.assign({}, config), { name: 'realtime' });
942
- }
943
- initialize() {
944
- this.editor.events.on('click', (e) => {
945
- }, false);
946
- }
937
+ class RealtimePlugin extends Plugin {
938
+ constructor(config = { name: 'realtime' }) {
939
+ super();
940
+ this.config = config;
941
+ this.config = Object.assign(Object.assign({}, config), { name: 'realtime' });
942
+ }
943
+ initialize() {
944
+ this.editor.events.on('click', (e) => {
945
+ }, false);
946
+ }
947
947
  }
948
948
 
949
- class ScreenRecordPlugin extends Plugin {
950
- constructor(config = {}) {
951
- super();
952
- this.config = config;
953
- this.config = Object.assign(Object.assign({}, config), { name: config.name || 'screenRecord', buttons: [
954
- {
955
- name: 'screenRecord',
949
+ class ScreenRecordPlugin extends Plugin {
950
+ constructor(config = {}) {
951
+ super();
952
+ this.config = config;
953
+ this.config = Object.assign(Object.assign({}, config), { name: config.name || 'screenRecord', buttons: [
954
+ {
955
+ name: 'screenRecord',
956
956
  svgPath: `M14.7,7.7v6.1H7.1V7.7H14.7 M16.3,9.6V6.9c0-0.4-0.3-0.8-0.8-0.8H6.4c-0.4,0-0.8,0.3-0.8,0.8v7.6c0,0.4,0.3,0.8,0.8,0.8h9.1c0.4,0,0.8-0.3,0.8-0.8v-2.7l1.7,1.7c0.3,0.3,0.8,0.3,1.1,0c0.1-0.1,0.2-0.3,0.2-0.5V8.4c0-0.4-0.3-0.8-0.8-0.8
957
957
  c-0.2,0-0.4,0.1-0.5,0.2L16.3,9.6z M21.5,1.6H2.9c-0.7,0-1.3,0.7-1.3,1.6v14.6c0,0.9,0.6,1.6,1.3,1.6h7.6v1.1l-5,1c-0.2,0-0.4,0.3-0.4,0.6c0,0.3,0.2,0.4,0.4,0.4c0,0,0,0,0.1,0l5.3-1h2.6l5.3,1c0,0,0,0,0.1,0c0.2,0,0.4-0.2,0.4-0.4
958
- c0-0.3-0.1-0.6-0.4-0.6l-5-1v-1.1h7.6c0.7,0,1.3-0.7,1.3-1.6V3.2C22.9,2.3,22.3,1.6,21.5,1.6z M21.1,17.3H3.3V3.7h17.8L21.1,17.3L21.1,17.3z`,
959
- tooltip: 'Screen Record',
960
- click: (editor) => {
961
- navigator.mediaDevices.getDisplayMedia({ video: true })
962
- .then((stream) => {
963
- const chunks = [];
964
- const options = { mimeType: 'video/webm; codecs=vp9' };
965
- let mediaRecorder = new MediaRecorder(stream, options);
966
- stream.addEventListener('inactive', (e) => {
967
- mediaRecorder.stop();
968
- mediaRecorder = null;
969
- stream.getTracks().forEach((track) => track.stop());
970
- stream = null;
971
- const blob = new Blob(chunks, { type: 'video/webm' });
972
- config.upload(blob)
973
- .subscribe((url) => {
974
- editor.html.insert(`<span class="fr-screen-record fr-deletable fr-draggable"><video controls style="max-width:${config.maxWidth}"><source src="${url}" type="video/webm"></video></span>`);
975
- });
976
- });
977
- mediaRecorder.addEventListener('dataavailable', (event) => {
978
- if (event.data && event.data.size > 0) {
979
- chunks.push(event.data);
980
- }
981
- });
982
- mediaRecorder.start(10);
983
- })
984
- .catch((e) => { });
985
- }
986
- }
987
- ] });
988
- }
989
- initialize() {
990
- return __awaiter(this, void 0, void 0, function* () {
991
- const FroalaEditor = window.FroalaEditor;
992
- this.editor.events.on('mouseup', (e) => {
993
- const el = this._getEl(e.target);
994
- if (el) {
995
- this.editor.popups.hideAll();
996
- this._activeEl = el;
997
- this._showPopup(el);
998
- }
999
- });
1000
- FroalaEditor.POPUP_TEMPLATES["screenRecordPlugin.popup"] = '[_BUTTONS_]';
1001
- FroalaEditor.DefineIcon('popupClose', { NAME: 'trash', SVG_KEY: 'remove' });
1002
- FroalaEditor.RegisterCommand('popupClose', {
1003
- title: 'Remove',
1004
- undo: false,
1005
- focus: false,
1006
- callback: () => {
1007
- if (this._activeEl) {
1008
- this._activeEl.remove();
1009
- }
1010
- }
1011
- });
1012
- });
1013
- }
1014
- _createPopup() {
1015
- const template = {
1016
- buttons: `<div class="fr-buttons">${this.editor.button.buildList(['popupClose'])}</div>`,
1017
- };
1018
- return this.editor.popups.create('screenRecordPlugin.popup', template);
1019
- }
1020
- _showPopup(el) {
1021
- var $popup = this.editor.popups.get('screenRecordPlugin.popup');
1022
- if (!$popup) {
1023
- $popup = this._createPopup();
1024
- }
1025
- this.editor.popups.setContainer('screenRecordPlugin.popup', this.editor.$(el));
1026
- const left = el.offsetLeft + el.offsetWidth / 2;
1027
- this.editor.popups.show('screenRecordPlugin.popup', left, null);
1028
- }
1029
- _getEl(el) {
1030
- if (el && el.classList) {
1031
- if (el.classList.contains('fr-screen-record'))
1032
- return el;
1033
- return this._getEl(el.parentNode);
1034
- }
1035
- }
958
+ c0-0.3-0.1-0.6-0.4-0.6l-5-1v-1.1h7.6c0.7,0,1.3-0.7,1.3-1.6V3.2C22.9,2.3,22.3,1.6,21.5,1.6z M21.1,17.3H3.3V3.7h17.8L21.1,17.3L21.1,17.3z`,
959
+ tooltip: 'Screen Record',
960
+ click: (editor) => {
961
+ navigator.mediaDevices.getDisplayMedia({ video: true })
962
+ .then((stream) => {
963
+ const chunks = [];
964
+ const options = { mimeType: 'video/webm; codecs=vp9' };
965
+ let mediaRecorder = new MediaRecorder(stream, options);
966
+ stream.addEventListener('inactive', (e) => {
967
+ mediaRecorder.stop();
968
+ mediaRecorder = null;
969
+ stream.getTracks().forEach((track) => track.stop());
970
+ stream = null;
971
+ const blob = new Blob(chunks, { type: 'video/webm' });
972
+ config.upload(blob)
973
+ .subscribe((url) => {
974
+ editor.html.insert(`<span class="fr-screen-record fr-deletable fr-draggable"><video controls style="max-width:${config.maxWidth}"><source src="${url}" type="video/webm"></video></span>`);
975
+ });
976
+ });
977
+ mediaRecorder.addEventListener('dataavailable', (event) => {
978
+ if (event.data && event.data.size > 0) {
979
+ chunks.push(event.data);
980
+ }
981
+ });
982
+ mediaRecorder.start(10);
983
+ })
984
+ .catch((e) => { });
985
+ }
986
+ }
987
+ ] });
988
+ }
989
+ initialize() {
990
+ return __awaiter(this, void 0, void 0, function* () {
991
+ const FroalaEditor = window.FroalaEditor;
992
+ this.editor.events.on('mouseup', (e) => {
993
+ const el = this._getEl(e.target);
994
+ if (el) {
995
+ this.editor.popups.hideAll();
996
+ this._activeEl = el;
997
+ this._showPopup(el);
998
+ }
999
+ });
1000
+ FroalaEditor.POPUP_TEMPLATES["screenRecordPlugin.popup"] = '[_BUTTONS_]';
1001
+ FroalaEditor.DefineIcon('popupClose', { NAME: 'trash', SVG_KEY: 'remove' });
1002
+ FroalaEditor.RegisterCommand('popupClose', {
1003
+ title: 'Remove',
1004
+ undo: false,
1005
+ focus: false,
1006
+ callback: () => {
1007
+ if (this._activeEl) {
1008
+ this._activeEl.remove();
1009
+ }
1010
+ }
1011
+ });
1012
+ });
1013
+ }
1014
+ _createPopup() {
1015
+ const template = {
1016
+ buttons: `<div class="fr-buttons">${this.editor.button.buildList(['popupClose'])}</div>`,
1017
+ };
1018
+ return this.editor.popups.create('screenRecordPlugin.popup', template);
1019
+ }
1020
+ _showPopup(el) {
1021
+ var $popup = this.editor.popups.get('screenRecordPlugin.popup');
1022
+ if (!$popup) {
1023
+ $popup = this._createPopup();
1024
+ }
1025
+ this.editor.popups.setContainer('screenRecordPlugin.popup', this.editor.$(el));
1026
+ const left = el.offsetLeft + el.offsetWidth / 2;
1027
+ this.editor.popups.show('screenRecordPlugin.popup', left, null);
1028
+ }
1029
+ _getEl(el) {
1030
+ if (el && el.classList) {
1031
+ if (el.classList.contains('fr-screen-record'))
1032
+ return el;
1033
+ return this._getEl(el.parentNode);
1034
+ }
1035
+ }
1036
1036
  }
1037
1037
 
1038
- /**
1039
- * Generated bundle index. Do not edit.
1038
+ /**
1039
+ * Generated bundle index. Do not edit.
1040
1040
  */
1041
1041
 
1042
1042
  export { ChecklistPlugin, CodePlugin, FS_HTML_EDITOR_CONFIG, FsHtmlEditorComponent, FsHtmlEditorContainerDirective, FsHtmlEditorModule, FsHtmlRendererComponent, FsHtmlRendererModule, MentionPlugin, ParagraphButtons, RealtimePlugin, RichButtons, ScreenRecordPlugin, TextButtons };