@firestitch/html-editor 12.1.1 → 12.1.2

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