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