@firestitch/html-editor 13.0.2 → 13.1.1

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