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