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