@theseam/ui-common 0.4.25 → 0.4.26

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 (63) hide show
  1. package/esm2020/data-filters/filters/data-filter-search/data-filter-search.component.mjs +1 -1
  2. package/esm2020/data-filters/filters/data-filter-text/data-filter-text.component.mjs +1 -1
  3. package/esm2020/datatable/datatable-column-preferences/datatable-column-preferences.component.mjs +1 -1
  4. package/esm2020/form-field/input.directive.mjs +8 -4
  5. package/esm2020/framework/schema-form-controls/schema-form-input/schema-form-input.component.mjs +1 -1
  6. package/esm2020/framework/schema-form-controls/schema-form-number/schema-form-number.component.mjs +1 -1
  7. package/esm2020/framework/schema-form-controls/schema-form-select/schema-form-select.component.mjs +2 -2
  8. package/esm2020/framework/schema-form-controls/schema-form-tel/schema-form-tel.component.mjs +2 -2
  9. package/esm2020/google-maps/google-maps-places-autocomplete/google-maps-places-autocomplete.component.mjs +1 -1
  10. package/esm2020/rich-text/public-api.mjs +5 -0
  11. package/esm2020/rich-text/rich-text/rich-text.component.mjs +573 -0
  12. package/esm2020/rich-text/rich-text.module.mjs +32 -0
  13. package/esm2020/rich-text/theseam-ui-common-rich-text.mjs +5 -0
  14. package/esm2020/rich-text/utils/models.mjs +24 -0
  15. package/esm2020/rich-text/utils/utils.mjs +123 -0
  16. package/esm2020/tel-input/tel-input/tel-input.component.mjs +2 -2
  17. package/esm2020/utils/is-null-or-undefined-or-empty.mjs +4 -0
  18. package/esm2020/utils/not-null-or-undefined-or-empty.mjs +4 -0
  19. package/esm2020/utils/public-api.mjs +3 -1
  20. package/fesm2015/theseam-ui-common-data-filters.mjs +2 -2
  21. package/fesm2015/theseam-ui-common-data-filters.mjs.map +1 -1
  22. package/fesm2015/theseam-ui-common-datatable.mjs +1 -1
  23. package/fesm2015/theseam-ui-common-datatable.mjs.map +1 -1
  24. package/fesm2015/theseam-ui-common-form-field.mjs +7 -3
  25. package/fesm2015/theseam-ui-common-form-field.mjs.map +1 -1
  26. package/fesm2015/theseam-ui-common-framework.mjs +4 -4
  27. package/fesm2015/theseam-ui-common-framework.mjs.map +1 -1
  28. package/fesm2015/theseam-ui-common-google-maps.mjs +1 -1
  29. package/fesm2015/theseam-ui-common-google-maps.mjs.map +1 -1
  30. package/fesm2015/theseam-ui-common-rich-text.mjs +744 -0
  31. package/fesm2015/theseam-ui-common-rich-text.mjs.map +1 -0
  32. package/fesm2015/theseam-ui-common-tel-input.mjs +1 -1
  33. package/fesm2015/theseam-ui-common-tel-input.mjs.map +1 -1
  34. package/fesm2015/theseam-ui-common-utils.mjs +9 -1
  35. package/fesm2015/theseam-ui-common-utils.mjs.map +1 -1
  36. package/fesm2020/theseam-ui-common-data-filters.mjs +2 -2
  37. package/fesm2020/theseam-ui-common-data-filters.mjs.map +1 -1
  38. package/fesm2020/theseam-ui-common-datatable.mjs +1 -1
  39. package/fesm2020/theseam-ui-common-datatable.mjs.map +1 -1
  40. package/fesm2020/theseam-ui-common-form-field.mjs +7 -3
  41. package/fesm2020/theseam-ui-common-form-field.mjs.map +1 -1
  42. package/fesm2020/theseam-ui-common-framework.mjs +4 -4
  43. package/fesm2020/theseam-ui-common-framework.mjs.map +1 -1
  44. package/fesm2020/theseam-ui-common-google-maps.mjs +1 -1
  45. package/fesm2020/theseam-ui-common-google-maps.mjs.map +1 -1
  46. package/fesm2020/theseam-ui-common-rich-text.mjs +752 -0
  47. package/fesm2020/theseam-ui-common-rich-text.mjs.map +1 -0
  48. package/fesm2020/theseam-ui-common-tel-input.mjs +1 -1
  49. package/fesm2020/theseam-ui-common-tel-input.mjs.map +1 -1
  50. package/fesm2020/theseam-ui-common-utils.mjs +9 -1
  51. package/fesm2020/theseam-ui-common-utils.mjs.map +1 -1
  52. package/form-field/input.directive.d.ts +2 -1
  53. package/package.json +9 -1
  54. package/rich-text/index.d.ts +5 -0
  55. package/rich-text/public-api.d.ts +4 -0
  56. package/rich-text/rich-text/rich-text.component.d.ts +192 -0
  57. package/rich-text/rich-text.module.d.ts +10 -0
  58. package/rich-text/utils/models.d.ts +343 -0
  59. package/rich-text/utils/utils.d.ts +14 -0
  60. package/styles/vendor/quill/_quill.scss +162 -10
  61. package/utils/is-null-or-undefined-or-empty.d.ts +1 -0
  62. package/utils/not-null-or-undefined-or-empty.d.ts +1 -0
  63. package/utils/public-api.d.ts +2 -0
@@ -0,0 +1,744 @@
1
+ import { __awaiter } from 'tslib';
2
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
3
+ import * as i0 from '@angular/core';
4
+ import { InjectionToken, forwardRef, EventEmitter, Component, Optional, Inject, Input, Output, ViewChild, NgModule } from '@angular/core';
5
+ import * as i2 from '@angular/forms';
6
+ import { NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule } from '@angular/forms';
7
+ import 'quill-mention';
8
+ import { BehaviorSubject, filter, shareReplay, Subject, combineLatest, map, switchMap, startWith, of, tap, take, lastValueFrom } from 'rxjs';
9
+ import { isNullOrUndefined, notNullOrUndefined, notNullOrUndefinedOrEmpty } from '@theseam/ui-common/utils';
10
+ import * as i1 from '@angular/common';
11
+ import { CommonModule } from '@angular/common';
12
+ import * as i3 from 'ngx-quill';
13
+ import { QuillModule } from 'ngx-quill';
14
+
15
+ const HTML_ENTITY_REGEX = /<[^>]+>/gm;
16
+ const THESEAM_QUILL_TOOLBAR_OPTIONS_DEFAULT = [
17
+ ['bold', 'italic', 'underline', 'strike'],
18
+ [{ header: [0, 1, 2, 3, 4, 5] }],
19
+ [{ list: 'ordered' }, { list: 'bullet' }],
20
+ [{ align: [] }],
21
+ ['link'],
22
+ ['clean'],
23
+ ];
24
+ const THESEAM_QUILL_MENTION_OPTIONS_DEFAULT = {
25
+ spaceAfterInsert: false,
26
+ positioningStrategy: 'fixed',
27
+ dataAttributes: ['type']
28
+ };
29
+ const THESEAM_QUILL_MODULES_DEFAULT = {
30
+ toolbar: THESEAM_QUILL_TOOLBAR_OPTIONS_DEFAULT
31
+ };
32
+ const THESEAM_QUILL_FORMATS_DEFAULT = [
33
+ 'align',
34
+ 'bold',
35
+ 'header',
36
+ 'indent',
37
+ 'italic',
38
+ 'link',
39
+ 'list',
40
+ 'size',
41
+ 'strike',
42
+ 'underline',
43
+ 'mention'
44
+ ];
45
+ const THESEAM_QUILL_EDITOR_CONFIG_DEFAULT = {
46
+ format: 'html',
47
+ modules: THESEAM_QUILL_MODULES_DEFAULT,
48
+ formats: THESEAM_QUILL_FORMATS_DEFAULT,
49
+ linkPlaceholder: 'https://google.com',
50
+ customToolbarPosition: 'top',
51
+ sanitize: false,
52
+ strict: true,
53
+ customOptions: [],
54
+ customModules: [],
55
+ preserveWhitespace: false,
56
+ trimOnValidation: false,
57
+ compareValues: false,
58
+ filterNull: false
59
+ };
60
+ const THESEAM_QUILL_EDITOR_CONFIG = new InjectionToken('TheSeamQuillEditorConfig');
61
+ const defaultHtmlCharacterCounterFn = (value, format) => {
62
+ if (format === 'html') {
63
+ return value.replace(HTML_ENTITY_REGEX, ' ').replace(/\s\s+/g, ' ').trim().length;
64
+ }
65
+ else if (format === 'text') {
66
+ return value.replace(/\s\s+/g, ' ').trim().length;
67
+ }
68
+ else {
69
+ console.warn(`Format ${format} not supported!`);
70
+ return 0;
71
+ }
72
+ };
73
+ function isMentionMenuOption(value) {
74
+ if (isNullOrUndefined(value) || typeof value !== 'object') {
75
+ return false;
76
+ }
77
+ return Object.prototype.hasOwnProperty.call(value, 'id');
78
+ }
79
+ const defaultMentionSearchFn = (source, textAfter, mentionChar) => {
80
+ return source.filter(u => {
81
+ if (!isMentionMenuOption(u) || u.searchIgnore === true) {
82
+ return true;
83
+ }
84
+ return u.value.toLowerCase().includes(textAfter.toLowerCase());
85
+ });
86
+ };
87
+ const defaultMentionRenderListFn = (source, searchFn, emptyListItem, textAfter, renderList, mentionChar) => {
88
+ let list = searchFn(source, textAfter, mentionChar);
89
+ if (list.length === 0 && notNullOrUndefined(emptyListItem)) {
90
+ list.push(emptyListItem);
91
+ }
92
+ else {
93
+ let reduceIdx = 0;
94
+ list = list.reduce((acc, mention) => {
95
+ const previousMenuItem = acc[reduceIdx - 1];
96
+ const previousMenuItemGroupName = isMentionMenuOption(previousMenuItem) ? previousMenuItem.groupName : undefined;
97
+ if (isMentionMenuOption(mention)
98
+ && notNullOrUndefinedOrEmpty(mention.groupName)
99
+ && mention.groupName !== previousMenuItemGroupName) {
100
+ acc.push({
101
+ value: mention.groupName,
102
+ disabled: true,
103
+ type: 'groupName'
104
+ });
105
+ reduceIdx++;
106
+ }
107
+ if (!isMentionMenuOption(mention)) {
108
+ mention.disabled = true;
109
+ }
110
+ acc.push(mention);
111
+ reduceIdx++;
112
+ return acc;
113
+ }, []);
114
+ }
115
+ renderList(list, textAfter);
116
+ };
117
+ // Keeping this as an example for a custom menu item.
118
+ // There doesn't appear to be a better way of passing in a custom template.
119
+ // export const defaultMentionRenderItem = (item: TheSeamQuillMentionListItem) => {
120
+ // if (item.type === 'groupName') {
121
+ // const text = document.createElement('div')
122
+ // text.setAttribute('class', 'small text-black-50')
123
+ // text.innerText = item.value
124
+ // return text.outerHTML
125
+ // }
126
+ // else if (item.type === 'divider') {
127
+ // const div = document.createElement('hr')
128
+ // div.setAttribute('class', 'my-2')
129
+ // return div.outerHTML
130
+ // }
131
+ // else {
132
+ // return item.value
133
+ // }
134
+ // }
135
+
136
+ const RICH_TEXT_VALUE_ACCESSOR = {
137
+ provide: NG_VALUE_ACCESSOR,
138
+ useExisting: forwardRef(() => RichTextComponent),
139
+ multi: true
140
+ };
141
+ class RichTextComponent {
142
+ get required() {
143
+ return this._required;
144
+ }
145
+ set required(value) {
146
+ if (notNullOrUndefined(value)) {
147
+ this._required = coerceBooleanProperty(value);
148
+ }
149
+ }
150
+ /** @default '' (empty string) */
151
+ get placeholder() {
152
+ return this._placeholder;
153
+ }
154
+ set placeholder(value) {
155
+ if (notNullOrUndefined(value)) {
156
+ this._placeholder = value;
157
+ }
158
+ }
159
+ /**
160
+ * Initial rows visible in text area, set using `height` and `minHeight`.
161
+ *
162
+ * NOTE: Resizable editors will not be able to size below the height calculated from this value.
163
+ *
164
+ * @default 5
165
+ */
166
+ get rows() {
167
+ return this._rows;
168
+ }
169
+ set rows(value) {
170
+ if (notNullOrUndefined(value)) {
171
+ this._rows = value;
172
+ this._pollCalculatedRowHeight.next();
173
+ }
174
+ }
175
+ /**
176
+ * When `true`, text area can be resized vertically.
177
+ *
178
+ * @default true
179
+ */
180
+ get resizable() {
181
+ return this._resizable;
182
+ }
183
+ set resizable(value) {
184
+ if (notNullOrUndefined(value)) {
185
+ this._resizable = coerceBooleanProperty(value);
186
+ }
187
+ }
188
+ /** @default false */
189
+ get readOnly() {
190
+ return this._readOnly;
191
+ }
192
+ set readOnly(value) {
193
+ if (notNullOrUndefined(value)) {
194
+ this._readOnly = coerceBooleanProperty(value);
195
+ }
196
+ }
197
+ // TODO: fix bug where initial html value is rendered in plain text
198
+ /**
199
+ * When `true`, overrides all other provided settings to present the editor
200
+ * as a standard textbox.
201
+ *
202
+ * NOTE: For the moment, `<p></p>` tags are still allowed, triggered by the `Enter` key.
203
+ * https://github.com/slab/quill/issues/1432
204
+ *
205
+ * @default false
206
+ */
207
+ get disableRichText() {
208
+ return this._disableRichText;
209
+ }
210
+ set disableRichText(value) {
211
+ if (notNullOrUndefined(value)) {
212
+ this._disableRichText = coerceBooleanProperty(value);
213
+ this._updateQuillConfig();
214
+ }
215
+ }
216
+ /**
217
+ * When `true`, displays a character counter at the bottom of the editor.
218
+ * Character counter text is determined by values provided in `minLength`
219
+ * and `maxLength`.
220
+ *
221
+ * The default count algorithm strips out html entities and replaces them
222
+ * with spaces to get the string length. To override this behavior, pass
223
+ * a custom function to `characterCounterFn`.
224
+ *
225
+ * To override default character counter display, pass a custom template to `characterCountTpl`.
226
+ *
227
+ * @default false
228
+ */
229
+ get displayCharacterCounter() {
230
+ return this._displayCharacterCounter;
231
+ }
232
+ set displayCharacterCounter(value) {
233
+ if (notNullOrUndefined(value)) {
234
+ this._displayCharacterCounter = coerceBooleanProperty(value);
235
+ }
236
+ }
237
+ get minLength() {
238
+ return this._minLength;
239
+ }
240
+ set minLength(value) {
241
+ if (notNullOrUndefined(value)) {
242
+ this._minLength = value;
243
+ }
244
+ }
245
+ get maxLength() {
246
+ return this._maxLength;
247
+ }
248
+ set maxLength(value) {
249
+ if (notNullOrUndefined(value)) {
250
+ this._maxLength = value;
251
+ }
252
+ }
253
+ /**
254
+ * Set to override default character counter display.
255
+ *
256
+ * Template context includes variables `minLength`, `maxLength`, and `characterCount`.
257
+ */
258
+ get characterCounterTpl() {
259
+ return this._characterCounterTpl;
260
+ }
261
+ set characterCounterTpl(value) {
262
+ if (notNullOrUndefined(value)) {
263
+ this._characterCounterTpl = value;
264
+ }
265
+ }
266
+ /**
267
+ * Set to override default counter function, which strips html entities and
268
+ * replaces them with a space.
269
+ */
270
+ get characterCounterFn() {
271
+ return this._characterCounterFn;
272
+ }
273
+ set characterCounterFn(value) {
274
+ if (notNullOrUndefined(value)) {
275
+ this._characterCounterFn = value;
276
+ }
277
+ }
278
+ /**
279
+ * If `true`, component will configure the Quill editor with the quill-mentions extension
280
+ * and listen for values passed to `mentionItems` to populate the mentions menu.
281
+ *
282
+ * @default false
283
+ */
284
+ get useMentions() {
285
+ return this._useMentions;
286
+ }
287
+ set useMentions(value) {
288
+ if (notNullOrUndefined(value)) {
289
+ this._useMentions = coerceBooleanProperty(value);
290
+ this._updateQuillConfig();
291
+ }
292
+ }
293
+ /**
294
+ * List of users, user groups, or other entities to display in mentions menu.
295
+ * Minimum required properties are `id` (unique) and `value`, which acts as the label.
296
+ *
297
+ * By default, the menu is triggered by typing the `@` symbol into the text area.
298
+ */
299
+ get mentionItems() {
300
+ return this._mentionItems.value;
301
+ }
302
+ set mentionItems(value) {
303
+ if (notNullOrUndefined(value)) {
304
+ this._mentionItems.next(value);
305
+ }
306
+ }
307
+ /**
308
+ * Set to override default search function when user is typing a mention.
309
+ */
310
+ get mentionSearchFn() {
311
+ return this._mentionSearchFn;
312
+ }
313
+ set mentionSearchFn(value) {
314
+ if (notNullOrUndefined(value)) {
315
+ this._mentionSearchFn = value;
316
+ }
317
+ }
318
+ /**
319
+ * Set to override default render function for mentions list.
320
+ *
321
+ * Function should call `renderList`.
322
+ */
323
+ get mentionRenderListFn() {
324
+ return this._mentionRenderListFn;
325
+ }
326
+ set mentionRenderListFn(value) {
327
+ if (notNullOrUndefined(value)) {
328
+ this._mentionRenderListFn = value;
329
+ }
330
+ }
331
+ /**
332
+ * Set to override default text shown while mention items are loading.
333
+ *
334
+ * @default 'Loading...'
335
+ */
336
+ get mentionListLoadingText() {
337
+ return this._mentionListLoadingText;
338
+ }
339
+ set mentionListLoadingText(value) {
340
+ if (notNullOrUndefined(value)) {
341
+ this._mentionListLoadingText = value;
342
+ }
343
+ }
344
+ /**
345
+ * Set to override default text shown when a mention search returns no items.
346
+ *
347
+ * @default 'No matches found.'
348
+ */
349
+ get mentionListEmptyText() {
350
+ return this._mentionListEmptyText;
351
+ }
352
+ set mentionListEmptyText(value) {
353
+ if (notNullOrUndefined(value)) {
354
+ this._mentionListEmptyText = value;
355
+ }
356
+ }
357
+ get mentionListEmptyItem() {
358
+ return {
359
+ id: 'undefined',
360
+ value: this.mentionListEmptyText,
361
+ disabled: true,
362
+ emptyList: true
363
+ };
364
+ }
365
+ get quillEditor() {
366
+ return this._quillEditor;
367
+ }
368
+ set quillEditor(value) {
369
+ this._quillEditor = value;
370
+ // setTimeout because full html isn't available until the next tick
371
+ setTimeout(() => {
372
+ this._pollCalculatedRowHeight.next();
373
+ }, 0);
374
+ }
375
+ constructor(_renderer, _customConfig) {
376
+ this._renderer = _renderer;
377
+ this._customConfig = _customConfig;
378
+ this.formControl = new FormControl(null);
379
+ this._required = false;
380
+ this._placeholder = '';
381
+ this._rows = 5;
382
+ this._resizable = true;
383
+ this._readOnly = false;
384
+ this._disableRichText = false;
385
+ this._displayCharacterCounter = false;
386
+ this._characterCounterTpl = null;
387
+ this._characterCounterFn = defaultHtmlCharacterCounterFn;
388
+ this._useMentions = false;
389
+ this._mentionItems = new BehaviorSubject(undefined);
390
+ this.mentionItems$ = this._mentionItems.asObservable().pipe(filter(mentions => notNullOrUndefined(mentions) && mentions.length > 0), shareReplay({ bufferSize: 1, refCount: true }));
391
+ this._mentionSearchFn = defaultMentionSearchFn;
392
+ this._mentionRenderListFn = defaultMentionRenderListFn;
393
+ this._mentionListLoadingText = 'Loading...';
394
+ this._mentionListEmptyText = 'No matches found.';
395
+ this.quillEditorCreated = new EventEmitter();
396
+ this.quillEditorChanged = new EventEmitter();
397
+ this.quillContentChanged = new EventEmitter();
398
+ this.quillSelectionChanged = new EventEmitter();
399
+ this.quillFocus = new EventEmitter();
400
+ this.quillBlur = new EventEmitter();
401
+ this.mentionsUpdated = new EventEmitter();
402
+ this._isWritingValue = false;
403
+ this._pollCalculatedRowHeight = new Subject();
404
+ this._configSet = new BehaviorSubject(false);
405
+ this.configSet$ = this._configSet.asObservable();
406
+ this._stylesSet = new BehaviorSubject(false);
407
+ this._templateSet = new BehaviorSubject(false);
408
+ this._config = new BehaviorSubject(undefined);
409
+ this.config$ = this._config.asObservable();
410
+ this._selectedMentions = new BehaviorSubject([]);
411
+ this.selectedMentions$ = this._selectedMentions.asObservable();
412
+ this.initialized$ = combineLatest([
413
+ this._configSet.asObservable(),
414
+ this._stylesSet.asObservable(),
415
+ this._templateSet.asObservable(),
416
+ ]).pipe(map(sets => sets.findIndex(s => !s) === -1));
417
+ this.characterCount$ = this.initialized$.pipe(filter(i => i), switchMap(() => {
418
+ if (notNullOrUndefined(this.formControl)) {
419
+ return this.formControl.valueChanges.pipe(startWith(this.formControl.value), map(v => { var _a; return this.characterCounterFn(v || '', (_a = this._config.value) === null || _a === void 0 ? void 0 : _a.format); }));
420
+ }
421
+ return of(0);
422
+ }));
423
+ this.selectedMentions$.pipe(tap(mentions => this.mentionsUpdated.emit(mentions))).subscribe();
424
+ }
425
+ ngOnInit() {
426
+ // TODO: test this more
427
+ // ignore quill initial valueChange event, to keep functionality in line with other inputs
428
+ let initialEmitComplete = false;
429
+ this._configSet.pipe(filter(s => s), switchMap(() => this.formControl.valueChanges.pipe(
430
+ // skip(1),
431
+ take(1), tap(() => initialEmitComplete = true)))).subscribe();
432
+ this.formControl.valueChanges.pipe(filter(() => !this._isWritingValue && initialEmitComplete), tap(value => this.value = value)).subscribe();
433
+ this._pollCalculatedRowHeight.asObservable().pipe(tap(() => {
434
+ this._stylesSet.next(false);
435
+ const calculatedRowsHeight = `${this.rows * 1.5}rem`;
436
+ if (notNullOrUndefined(this.rows) && notNullOrUndefined(this._quillEditor)) {
437
+ const editorEl = this._quillEditor.elementRef.nativeElement.querySelector('.ql-editor');
438
+ if (notNullOrUndefined(editorEl)) {
439
+ this._renderer.setStyle(editorEl, 'height', calculatedRowsHeight);
440
+ this._renderer.setStyle(editorEl, 'min-height', calculatedRowsHeight);
441
+ }
442
+ }
443
+ this._stylesSet.next(true);
444
+ })).subscribe();
445
+ this._buildQuillConfig();
446
+ }
447
+ ngAfterViewInit() {
448
+ if (isNullOrUndefined(this.characterCounterTpl)) {
449
+ this.characterCounterTpl = this.defaultCharacterCounterTpl || null;
450
+ }
451
+ this._templateSet.next(true);
452
+ }
453
+ _buildQuillConfig() {
454
+ var _a;
455
+ this._configSet.next(false);
456
+ const config = Object.assign({}, THESEAM_QUILL_EDITOR_CONFIG_DEFAULT);
457
+ if (this.disableRichText) {
458
+ config.format = 'text';
459
+ config.formats = [];
460
+ config.modules = {
461
+ toolbar: false
462
+ };
463
+ }
464
+ else {
465
+ config.format = this._getConfigOrDefault('format');
466
+ config.formats = this._getConfigOrDefault('formats');
467
+ config.modules = Object.assign({}, this._getConfigOrDefault('modules'));
468
+ }
469
+ if (this.useMentions) {
470
+ const mentionModules = Object.assign(Object.assign({}, config.modules), { mention: Object.assign(Object.assign(Object.assign({}, THESEAM_QUILL_MENTION_OPTIONS_DEFAULT), { renderLoading: () => this.mentionListLoadingText, source: (searchTerm, renderList, mentionChar) => __awaiter(this, void 0, void 0, function* () {
471
+ // this function is called every time the menu is triggered,
472
+ // so it will always have the latest value from mentionItems$
473
+ const mentionsAsync = yield lastValueFrom(this.mentionItems$.pipe(take(1)));
474
+ if (notNullOrUndefined(mentionsAsync)) {
475
+ this.mentionRenderListFn(mentionsAsync, this.mentionSearchFn, this.mentionListEmptyItem, searchTerm, renderList, mentionChar);
476
+ }
477
+ }) }), (_a = config.modules) === null || _a === void 0 ? void 0 : _a.mention) });
478
+ config.modules = mentionModules;
479
+ }
480
+ config.theme = this._getConfigOrDefault('theme');
481
+ config.debug = this._getConfigOrDefault('debug');
482
+ config.customToolbarPosition = this._getConfigOrDefault('customToolbarPosition');
483
+ config.sanitize = this._getConfigOrDefault('sanitize');
484
+ config.styles = this._getConfigOrDefault('styles');
485
+ config.strict = this._getConfigOrDefault('strict');
486
+ config.scrollingContainer = this._getConfigOrDefault('scrollingContainer');
487
+ config.bounds = this._getConfigOrDefault('bounds');
488
+ config.customOptions = this._getConfigOrDefault('customOptions');
489
+ config.customModules = this._getConfigOrDefault('customModules');
490
+ config.trackChanges = this._getConfigOrDefault('trackChanges');
491
+ config.preserveWhitespace = this._getConfigOrDefault('preserveWhitespace');
492
+ config.classes = this._getConfigOrDefault('classes');
493
+ config.trimOnValidation = this._getConfigOrDefault('trimOnValidation');
494
+ config.linkPlaceholder = this._getConfigOrDefault('linkPlaceholder');
495
+ config.compareValues = this._getConfigOrDefault('compareValues');
496
+ config.filterNull = this._getConfigOrDefault('filterNull');
497
+ config.debounceTime = this._getConfigOrDefault('debounceTime');
498
+ this._config.next(config);
499
+ // setTimeout bc ngx-quill library doesn't listen for input changes,
500
+ // so we must destroy and create the component each time config is updated
501
+ setTimeout(() => {
502
+ this._configSet.next(true);
503
+ }, 0);
504
+ }
505
+ _getConfigOrDefault(prop) {
506
+ if (this._customConfig && Object.prototype.hasOwnProperty.call(this._customConfig, prop)) {
507
+ return this._customConfig[prop];
508
+ }
509
+ return THESEAM_QUILL_EDITOR_CONFIG_DEFAULT[prop];
510
+ }
511
+ _updateQuillConfig() {
512
+ if (this._configSet.value) {
513
+ this._buildQuillConfig();
514
+ }
515
+ }
516
+ // Not usable, bc config has to be set immediately, potentially before mentions populate.
517
+ // To set customDataAttributes, provide a custom config.
518
+ // private _getCustomDataAttributes(mentions: TheSeamQuillMentionMenuOption[]): string[] {
519
+ // return mentions.reduce((acc, mention) => {
520
+ // const keys = Object.keys(mention)
521
+ // keys.forEach(key => {
522
+ // if (acc.findIndex(a => a === key) === -1) {
523
+ // acc.push(key)
524
+ // }
525
+ // })
526
+ // return acc
527
+ // }, <string[]>[] satisfies string[])
528
+ // }
529
+ get value() {
530
+ return this._value;
531
+ }
532
+ set value(value) {
533
+ this._value = value;
534
+ if (this.onChange) {
535
+ this.onChange(value);
536
+ }
537
+ if (this.onTouched) {
538
+ this.onTouched();
539
+ }
540
+ }
541
+ writeValue(value) {
542
+ this._isWritingValue = true;
543
+ this.formControl.setValue(value);
544
+ this.value = value;
545
+ this._isWritingValue = false;
546
+ }
547
+ registerOnChange(fn) {
548
+ this.onChange = fn;
549
+ }
550
+ registerOnTouched(fn) {
551
+ this.onTouched = fn;
552
+ }
553
+ setDisabledState(isDisabled) {
554
+ this.readOnly = isDisabled;
555
+ }
556
+ _onEditorCreated(event) {
557
+ this.quillEditorCreated.emit(event);
558
+ }
559
+ _onEditorChanged(event) {
560
+ this.quillEditorChanged.emit(event);
561
+ }
562
+ _onContentChanged(event) {
563
+ this.quillContentChanged.emit(event);
564
+ this._updateMentionsFromDelta(event.content);
565
+ }
566
+ _onSelectionChanged(event) {
567
+ this.quillSelectionChanged.emit(event);
568
+ }
569
+ _onFocus(event) {
570
+ this.quillFocus.emit(event);
571
+ }
572
+ _onBlur(event) {
573
+ this.quillBlur.emit(event);
574
+ if (this.onTouched) {
575
+ this.onTouched();
576
+ }
577
+ }
578
+ /**
579
+ * Hacky way to track mention inserts/deletes
580
+ */
581
+ _updateMentionsFromDelta(content) {
582
+ if (notNullOrUndefined(content.ops)) {
583
+ const contentMentionIds = content.ops.map(o => { var _a, _b; return (_b = (_a = o.insert) === null || _a === void 0 ? void 0 : _a.mention) === null || _b === void 0 ? void 0 : _b.id; }).filter(notNullOrUndefined);
584
+ const selectedMentions = [...this._selectedMentions.value];
585
+ const mentionOptions = [...this._mentionItems.value || []];
586
+ const newMentions = contentMentionIds.reduce((acc, mentionId) => {
587
+ const insertMention = mentionOptions.find(m => isMentionMenuOption(m) && m.id === mentionId);
588
+ if (notNullOrUndefined(insertMention)) {
589
+ acc.push(insertMention);
590
+ }
591
+ else {
592
+ console.warn('Mention addition failed! Selected mention option not found:', mentionId);
593
+ }
594
+ return acc;
595
+ }, []);
596
+ let emitUpdate = false;
597
+ if (selectedMentions.length !== newMentions.length) {
598
+ // if the length has changed, we know an update occurred
599
+ emitUpdate = true;
600
+ }
601
+ else {
602
+ // otherwise, test ids for old and new items to see if we need to emit a change
603
+ const selectedMentionIds = this._selectedMentions.value.map(m => m.id);
604
+ const newMentionIds = newMentions.map(m => m.id);
605
+ if (selectedMentionIds.findIndex(m => !newMentionIds.includes(m)) !== -1 ||
606
+ newMentionIds.findIndex(m => !selectedMentionIds.includes(m)) !== -1) {
607
+ emitUpdate = true;
608
+ }
609
+ }
610
+ if (emitUpdate) {
611
+ this._selectedMentions.next(newMentions);
612
+ }
613
+ }
614
+ }
615
+ }
616
+ RichTextComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: RichTextComponent, deps: [{ token: i0.Renderer2 }, { token: THESEAM_QUILL_EDITOR_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
617
+ RichTextComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.7", type: RichTextComponent, selector: "seam-rich-text", inputs: { val: ["value", "val"], required: "required", placeholder: "placeholder", rows: "rows", resizable: "resizable", disableRichText: "disableRichText", displayCharacterCounter: "displayCharacterCounter", minLength: "minLength", maxLength: "maxLength", characterCounterTpl: "characterCounterTpl", characterCounterFn: "characterCounterFn", useMentions: "useMentions", mentionItems: "mentionItems", mentionSearchFn: "mentionSearchFn", mentionRenderListFn: "mentionRenderListFn", mentionListLoadingText: "mentionListLoadingText", mentionListEmptyText: "mentionListEmptyText" }, outputs: { quillEditorCreated: "quillEditorCreated", quillEditorChanged: "quillEditorChanged", quillContentChanged: "quillContentChanged", quillSelectionChanged: "quillSelectionChanged", quillFocus: "quillFocus", quillBlur: "quillBlur", mentionsUpdated: "mentionsUpdated" }, providers: [
618
+ RICH_TEXT_VALUE_ACCESSOR
619
+ ], viewQueries: [{ propertyName: "quillEditor", first: true, predicate: ["quillEditor"], descendants: true }, { propertyName: "defaultCharacterCounterTpl", first: true, predicate: ["characterCounter"], descendants: true }], ngImport: i0, template: "<div class=\"editor\" *ngIf=\"configSet$ | async\" [class.initializing]=\"!(initialized$ | async)\">\n <ng-container *ngIf=\"config$ | async as config\">\n <quill-editor\n #quillEditor\n seamInput\n [class.disabled]=\"readOnly\"\n [attr.disabled]=\"readOnly\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [readOnly]=\"readOnly\"\n [required]=\"required\"\n [minLength]=\"minLength\"\n [maxLength]=\"maxLength\"\n [format]=\"config.format\"\n [theme]=\"config.theme\"\n [modules]=\"config.modules\"\n [debug]=\"config.debug\"\n [formats]=\"config.formats\"\n [customToolbarPosition]=\"config.customToolbarPosition\"\n [sanitize]=\"config.sanitize\"\n [styles]=\"config.styles\"\n [strict]=\"config.strict\"\n [scrollingContainer]=\"config.scrollingContainer\"\n [bounds]=\"config.bounds\"\n [customOptions]=\"config.customOptions\"\n [customModules]=\"config.customModules\"\n [trackChanges]=\"config.trackChanges\"\n [preserveWhitespace]=\"config.preserveWhitespace\"\n [classes]=\"config.classes\"\n [trimOnValidation]=\"config.trimOnValidation\"\n [linkPlaceholder]=\"config.linkPlaceholder\"\n [compareValues]=\"config.compareValues\"\n [filterNull]=\"config.filterNull\"\n [debounceTime]=\"config.debounceTime\"\n [class.can-resize]=\"resizable\"\n (onEditorCreated)=\"_onEditorCreated($event)\"\n (onEditorChanged)=\"_onEditorChanged($event)\"\n (onContentChanged)=\"_onContentChanged($event)\"\n (onSelectionChanged)=\"_onSelectionChanged($event)\"\n (onFocus)=\"_onFocus($event)\"\n (onBlur)=\"_onBlur($event)\"></quill-editor>\n <ng-container *ngIf=\"displayCharacterCounter\">\n <ng-container\n [ngTemplateOutlet]=\"characterCounterTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: characterCount$ | async, minLength: minLength, maxLength: maxLength, characterCount: characterCount$ | async }\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #characterCounter let-implicit let-minLength=\"minLength\" let-maxLength=\"maxLength\" let-characterCount=\"characterCount\">\n <div class=\"small text-black-50 text-right\">\n <ng-container *ngIf=\"characterCount || characterCount === 0\">\n Character Count:\n <span [class.text-danger]=\"characterCount && ((maxLength && characterCount > maxLength) || (minLength && characterCount < minLength))\">\n {{ characterCount | number }}\n </span>\n <ng-container *ngIf=\"maxLength\">\n / {{ maxLength }}\n </ng-container>\n <span *ngIf=\"minLength\" class=\"font-italic\">\n (minimum {{ minLength }} expected)\n </span>\n </ng-container>\n </div>\n</ng-template>\n", styles: [":host .editor{position:relative}:host .editor.initializing:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:#f8f9fa;z-index:1}:host quill-editor.can-resize ::ng-deep .ql-editor{overflow:auto;resize:vertical}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i3.QuillEditorComponent, selector: "quill-editor" }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] });
620
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: RichTextComponent, decorators: [{
621
+ type: Component,
622
+ args: [{ selector: 'seam-rich-text', providers: [
623
+ RICH_TEXT_VALUE_ACCESSOR
624
+ ], template: "<div class=\"editor\" *ngIf=\"configSet$ | async\" [class.initializing]=\"!(initialized$ | async)\">\n <ng-container *ngIf=\"config$ | async as config\">\n <quill-editor\n #quillEditor\n seamInput\n [class.disabled]=\"readOnly\"\n [attr.disabled]=\"readOnly\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [readOnly]=\"readOnly\"\n [required]=\"required\"\n [minLength]=\"minLength\"\n [maxLength]=\"maxLength\"\n [format]=\"config.format\"\n [theme]=\"config.theme\"\n [modules]=\"config.modules\"\n [debug]=\"config.debug\"\n [formats]=\"config.formats\"\n [customToolbarPosition]=\"config.customToolbarPosition\"\n [sanitize]=\"config.sanitize\"\n [styles]=\"config.styles\"\n [strict]=\"config.strict\"\n [scrollingContainer]=\"config.scrollingContainer\"\n [bounds]=\"config.bounds\"\n [customOptions]=\"config.customOptions\"\n [customModules]=\"config.customModules\"\n [trackChanges]=\"config.trackChanges\"\n [preserveWhitespace]=\"config.preserveWhitespace\"\n [classes]=\"config.classes\"\n [trimOnValidation]=\"config.trimOnValidation\"\n [linkPlaceholder]=\"config.linkPlaceholder\"\n [compareValues]=\"config.compareValues\"\n [filterNull]=\"config.filterNull\"\n [debounceTime]=\"config.debounceTime\"\n [class.can-resize]=\"resizable\"\n (onEditorCreated)=\"_onEditorCreated($event)\"\n (onEditorChanged)=\"_onEditorChanged($event)\"\n (onContentChanged)=\"_onContentChanged($event)\"\n (onSelectionChanged)=\"_onSelectionChanged($event)\"\n (onFocus)=\"_onFocus($event)\"\n (onBlur)=\"_onBlur($event)\"></quill-editor>\n <ng-container *ngIf=\"displayCharacterCounter\">\n <ng-container\n [ngTemplateOutlet]=\"characterCounterTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: characterCount$ | async, minLength: minLength, maxLength: maxLength, characterCount: characterCount$ | async }\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #characterCounter let-implicit let-minLength=\"minLength\" let-maxLength=\"maxLength\" let-characterCount=\"characterCount\">\n <div class=\"small text-black-50 text-right\">\n <ng-container *ngIf=\"characterCount || characterCount === 0\">\n Character Count:\n <span [class.text-danger]=\"characterCount && ((maxLength && characterCount > maxLength) || (minLength && characterCount < minLength))\">\n {{ characterCount | number }}\n </span>\n <ng-container *ngIf=\"maxLength\">\n / {{ maxLength }}\n </ng-container>\n <span *ngIf=\"minLength\" class=\"font-italic\">\n (minimum {{ minLength }} expected)\n </span>\n </ng-container>\n </div>\n</ng-template>\n", styles: [":host .editor{position:relative}:host .editor.initializing:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:#f8f9fa;z-index:1}:host quill-editor.can-resize ::ng-deep .ql-editor{overflow:auto;resize:vertical}\n"] }]
625
+ }], ctorParameters: function () {
626
+ return [{ type: i0.Renderer2 }, { type: undefined, decorators: [{
627
+ type: Optional
628
+ }, {
629
+ type: Inject,
630
+ args: [THESEAM_QUILL_EDITOR_CONFIG]
631
+ }] }];
632
+ }, propDecorators: { val: [{
633
+ type: Input,
634
+ args: ['value']
635
+ }], required: [{
636
+ type: Input
637
+ }], placeholder: [{
638
+ type: Input
639
+ }], rows: [{
640
+ type: Input
641
+ }], resizable: [{
642
+ type: Input
643
+ }], disableRichText: [{
644
+ type: Input
645
+ }], displayCharacterCounter: [{
646
+ type: Input
647
+ }], minLength: [{
648
+ type: Input
649
+ }], maxLength: [{
650
+ type: Input
651
+ }], characterCounterTpl: [{
652
+ type: Input
653
+ }], characterCounterFn: [{
654
+ type: Input
655
+ }], useMentions: [{
656
+ type: Input
657
+ }], mentionItems: [{
658
+ type: Input
659
+ }], mentionSearchFn: [{
660
+ type: Input
661
+ }], mentionRenderListFn: [{
662
+ type: Input
663
+ }], mentionListLoadingText: [{
664
+ type: Input
665
+ }], mentionListEmptyText: [{
666
+ type: Input
667
+ }], quillEditorCreated: [{
668
+ type: Output
669
+ }], quillEditorChanged: [{
670
+ type: Output
671
+ }], quillContentChanged: [{
672
+ type: Output
673
+ }], quillSelectionChanged: [{
674
+ type: Output
675
+ }], quillFocus: [{
676
+ type: Output
677
+ }], quillBlur: [{
678
+ type: Output
679
+ }], mentionsUpdated: [{
680
+ type: Output
681
+ }], quillEditor: [{
682
+ type: ViewChild,
683
+ args: ['quillEditor']
684
+ }], defaultCharacterCounterTpl: [{
685
+ type: ViewChild,
686
+ args: ['characterCounter']
687
+ }] } });
688
+
689
+ const THESEAM_QUILL_FORMATS = [
690
+ 'align',
691
+ 'background',
692
+ 'blockquote',
693
+ 'bold',
694
+ 'code-block',
695
+ 'code',
696
+ 'color',
697
+ 'direction',
698
+ 'font',
699
+ 'header',
700
+ 'image',
701
+ 'indent',
702
+ 'italic',
703
+ 'link',
704
+ 'list',
705
+ 'script',
706
+ 'size',
707
+ 'strike',
708
+ 'underline',
709
+ 'video',
710
+ 'mention'
711
+ ];
712
+
713
+ class TheSeamRichTextModule {
714
+ }
715
+ TheSeamRichTextModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: TheSeamRichTextModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
716
+ TheSeamRichTextModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: TheSeamRichTextModule, declarations: [RichTextComponent], imports: [CommonModule,
717
+ ReactiveFormsModule,
718
+ QuillModule], exports: [RichTextComponent] });
719
+ TheSeamRichTextModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: TheSeamRichTextModule, imports: [CommonModule,
720
+ ReactiveFormsModule,
721
+ QuillModule] });
722
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: TheSeamRichTextModule, decorators: [{
723
+ type: NgModule,
724
+ args: [{
725
+ declarations: [
726
+ RichTextComponent,
727
+ ],
728
+ imports: [
729
+ CommonModule,
730
+ ReactiveFormsModule,
731
+ QuillModule
732
+ ],
733
+ exports: [
734
+ RichTextComponent,
735
+ ]
736
+ }]
737
+ }] });
738
+
739
+ /**
740
+ * Generated bundle index. Do not edit.
741
+ */
742
+
743
+ export { HTML_ENTITY_REGEX, RICH_TEXT_VALUE_ACCESSOR, RichTextComponent, THESEAM_QUILL_EDITOR_CONFIG, THESEAM_QUILL_EDITOR_CONFIG_DEFAULT, THESEAM_QUILL_FORMATS, THESEAM_QUILL_FORMATS_DEFAULT, THESEAM_QUILL_MENTION_OPTIONS_DEFAULT, THESEAM_QUILL_MODULES_DEFAULT, THESEAM_QUILL_TOOLBAR_OPTIONS_DEFAULT, TheSeamRichTextModule, defaultHtmlCharacterCounterFn, defaultMentionRenderListFn, defaultMentionSearchFn, isMentionMenuOption };
744
+ //# sourceMappingURL=theseam-ui-common-rich-text.mjs.map