rapid-text-editor 1.0.15 → 1.0.17

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.
@@ -23,11 +23,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
23
23
  }], ctorParameters: function () { return []; } });
24
24
 
25
25
  class RapidTextEditorComponent {
26
- constructor(dialog, el, renderer, elRef) {
26
+ constructor(dialog, el, renderer, elRef, _change) {
27
27
  this.dialog = dialog;
28
28
  this.el = el;
29
29
  this.renderer = renderer;
30
30
  this.elRef = elRef;
31
+ this._change = _change;
31
32
  this.contentCapture = false;
32
33
  this.height = "auto";
33
34
  this.width = "auto";
@@ -45,6 +46,7 @@ class RapidTextEditorComponent {
45
46
  this.selectedHead = 'P';
46
47
  this.selectedFont = '14';
47
48
  }
49
+ this._change.detectChanges();
48
50
  };
49
51
  this.onTouched = () => { };
50
52
  console.log('Build -1');
@@ -56,6 +58,8 @@ class RapidTextEditorComponent {
56
58
  else {
57
59
  console.log('Content capture is disabled.');
58
60
  }
61
+ // this.initializeEditorContent('');
62
+ // this.ensureParagraphAndFocus();
59
63
  }
60
64
  ngOnChanges(changes) {
61
65
  if (changes['height'] || changes['width']) {
@@ -88,6 +92,57 @@ class RapidTextEditorComponent {
88
92
  else {
89
93
  console.error('Editor element not found.');
90
94
  }
95
+ const observer = new MutationObserver(() => this.updateCurrentFormat());
96
+ observer.observe(this.editor.nativeElement, {
97
+ childList: true,
98
+ characterData: true,
99
+ subtree: true
100
+ });
101
+ // this.initializeEditorContent('');
102
+ // this.ensureParagraphAndFocus();
103
+ }
104
+ ensureParagraphAndFocus() {
105
+ const editor = document.getElementById('editor');
106
+ if (!editor)
107
+ return;
108
+ // If editor is empty or doesn't have a <p> as the last element
109
+ if (!editor.innerHTML.trim()) {
110
+ editor.innerHTML = '<p style="font-size:14px; font-weight:normal;">\u200B</p>';
111
+ }
112
+ else {
113
+ const firstChild = editor.firstChild;
114
+ if (!firstChild || firstChild.tagName !== 'P') {
115
+ const content = editor.innerHTML;
116
+ editor.innerHTML = `<p style="font-size:14px; font-weight:normal;">${content}</p>`;
117
+ }
118
+ }
119
+ const p = editor.querySelector('p');
120
+ if (p) {
121
+ const range = document.createRange();
122
+ range.selectNodeContents(p);
123
+ range.collapse(true);
124
+ const selection = window.getSelection();
125
+ if (selection) {
126
+ selection.removeAllRanges();
127
+ selection.addRange(range);
128
+ }
129
+ }
130
+ // Focus the editor
131
+ editor.focus();
132
+ }
133
+ initializeEditorContent(data) {
134
+ const editor = document.getElementById('editor');
135
+ if (!editor)
136
+ return;
137
+ // If content has no HTML tags, wrap with <p>
138
+ const hasHtmlTags = /<[^>]+>/.test(data);
139
+ if (!hasHtmlTags) {
140
+ editor.innerHTML = `<p style="font-size:14px; font-weight: normal;">${data}</p>`;
141
+ // this.ensureParagraphAndFocus();
142
+ }
143
+ else {
144
+ editor.innerHTML = data;
145
+ }
91
146
  }
92
147
  onContentChange() {
93
148
  if (this.contentCapture) {
@@ -119,6 +174,93 @@ class RapidTextEditorComponent {
119
174
  onBlur() {
120
175
  this.onTouched();
121
176
  }
177
+ // setFontSize(event: Event) {
178
+ // const select = event.target as HTMLSelectElement;
179
+ // const size = select.value;
180
+ // const selection = window.getSelection();
181
+ // if (!selection || selection.rangeCount === 0) return;
182
+ // const range = selection.getRangeAt(0);
183
+ // if (!range.collapsed) {
184
+ // const parent = selection.anchorNode?.parentElement;
185
+ // if (
186
+ // parent &&
187
+ // parent.classList &&
188
+ // Array.from(parent.classList).some((c: string) => c.startsWith('fs-'))
189
+ // ) {
190
+ // parent.style.fontSize = `${size}px`;
191
+ // parent.className = `fs-${size}`;
192
+ // } else {
193
+ // const span = document.createElement('span');
194
+ // span.style.fontSize = `${size}px`;
195
+ // span.classList.add(`fs-${size}`);
196
+ // range.surroundContents(span);
197
+ // }
198
+ // }
199
+ // else {
200
+ // const span = document.createElement('span');
201
+ // span.style.fontSize = `${size}px`;
202
+ // span.classList.add(`fs-${size}`);
203
+ // span.appendChild(document.createTextNode('\u200B')); // zero-width space
204
+ // range.insertNode(span);
205
+ // const newRange = document.createRange();
206
+ // newRange.setStart(span.firstChild as Node, 1);
207
+ // newRange.collapse(true);
208
+ // selection.removeAllRanges();
209
+ // selection.addRange(newRange);
210
+ // }
211
+ // }
212
+ onEditorKeyUp(event) {
213
+ // handle Enter or arrow keys
214
+ if (event.key === 'Enter' || event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'BackSpace') {
215
+ this.updateCurrentFormat();
216
+ }
217
+ }
218
+ updateCurrentFormat() {
219
+ const selection = window.getSelection();
220
+ if (!selection || selection.rangeCount === 0)
221
+ return;
222
+ const anchorNode = selection.anchorNode;
223
+ if (!anchorNode)
224
+ return;
225
+ let parentElem = anchorNode.nodeType === Node.ELEMENT_NODE
226
+ ? anchorNode
227
+ : anchorNode.parentElement;
228
+ if (!parentElem)
229
+ return;
230
+ let detectedHead = 'P';
231
+ let detectedFont = '14'; // default
232
+ // Traverse upward to detect formatting
233
+ while (parentElem && parentElem !== this.editor.nativeElement) {
234
+ const tag = parentElem.tagName.toUpperCase();
235
+ // Detect heading
236
+ if (['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'P'].includes(tag)) {
237
+ detectedHead = tag;
238
+ }
239
+ // Detect inline font-size from style or class
240
+ const fontSize = window.getComputedStyle(parentElem).fontSize;
241
+ if (fontSize) {
242
+ const px = parseInt(fontSize.replace('px', ''), 10);
243
+ if (!isNaN(px)) {
244
+ detectedFont = px.toString();
245
+ break; // found the closest valid font size
246
+ }
247
+ }
248
+ parentElem = parentElem.parentElement;
249
+ }
250
+ // Update bound properties if changed
251
+ let changed = false;
252
+ if (this.selectedHead !== detectedHead) {
253
+ this.selectedHead = detectedHead;
254
+ changed = true;
255
+ }
256
+ if (this.selectedFont !== detectedFont) {
257
+ this.selectedFont = detectedFont;
258
+ changed = true;
259
+ }
260
+ if (changed) {
261
+ this._change.detectChanges();
262
+ }
263
+ }
122
264
  setFontSize(event) {
123
265
  const select = event.target;
124
266
  const size = select.value;
@@ -127,32 +269,41 @@ class RapidTextEditorComponent {
127
269
  return;
128
270
  const range = selection.getRangeAt(0);
129
271
  if (!range.collapsed) {
130
- const parent = selection.anchorNode?.parentElement;
131
- if (parent &&
132
- parent.classList &&
133
- Array.from(parent.classList).some((c) => c.startsWith('fs-'))) {
134
- parent.style.fontSize = `${size}px`;
135
- parent.className = `fs-${size}`;
136
- }
137
- else {
138
- const span = document.createElement('span');
139
- span.style.fontSize = `${size}px`;
140
- span.classList.add(`fs-${size}`);
272
+ // Non-empty selection
273
+ const span = document.createElement('span');
274
+ span.style.setProperty('font-size', `${size}px`, 'important');
275
+ span.classList.add(`fs-${size}`);
276
+ try {
141
277
  range.surroundContents(span);
142
278
  }
279
+ catch {
280
+ // If selection spans multiple elements, use execCommand fallback
281
+ document.execCommand('fontSize', false, '7'); // temporary largest size
282
+ document.querySelectorAll('font[size="7"]').forEach((el) => {
283
+ el.removeAttribute('size');
284
+ el.style.setProperty('font-size', `${size}px`, 'important');
285
+ el.classList.add(`fs-${size}`);
286
+ });
287
+ }
143
288
  }
144
289
  else {
290
+ // Collapsed selection (no text selected)
145
291
  const span = document.createElement('span');
146
- span.style.fontSize = `${size}px`;
292
+ span.style.setProperty('font-size', `${size}px`, 'important');
147
293
  span.classList.add(`fs-${size}`);
148
294
  span.appendChild(document.createTextNode('\u200B')); // zero-width space
149
295
  range.insertNode(span);
296
+ // Move cursor inside span
150
297
  const newRange = document.createRange();
151
298
  newRange.setStart(span.firstChild, 1);
152
299
  newRange.collapse(true);
153
300
  selection.removeAllRanges();
154
301
  selection.addRange(newRange);
155
302
  }
303
+ const content = this.editor.nativeElement.innerHTML;
304
+ this.onChange(content);
305
+ this.updateCurrentFormat();
306
+ this._change.detectChanges();
156
307
  }
157
308
  setHeading(event) {
158
309
  const select = event.target;
@@ -167,33 +318,33 @@ class RapidTextEditorComponent {
167
318
  const newElem = document.createElement(tag);
168
319
  switch (tag) {
169
320
  case 'H1':
170
- newElem.style.fontSize = '32px';
171
- newElem.style.fontWeight = 'bold';
321
+ newElem.style.setProperty('font-size', '32px', 'important');
322
+ newElem.style.setProperty('font-weight', 'bold', 'important');
172
323
  break;
173
324
  case 'H2':
174
- newElem.style.fontSize = '28px';
175
- newElem.style.fontWeight = 'bold';
325
+ newElem.style.setProperty('font-size', '28px', 'important');
326
+ newElem.style.setProperty('font-weight', 'bold', 'important');
176
327
  break;
177
328
  case 'H3':
178
- newElem.style.fontSize = '24px';
179
- newElem.style.fontWeight = 'bold';
329
+ newElem.style.setProperty('font-size', '24px', 'important');
330
+ newElem.style.setProperty('font-weight', 'bold', 'important');
180
331
  break;
181
332
  case 'H4':
182
- newElem.style.fontSize = '20px';
183
- newElem.style.fontWeight = 'bold';
333
+ newElem.style.setProperty('font-size', '20px', 'important');
334
+ newElem.style.setProperty('font-weight', 'bold', 'important');
184
335
  break;
185
336
  case 'H5':
186
- newElem.style.fontSize = '18px';
187
- newElem.style.fontWeight = '600';
337
+ newElem.style.setProperty('font-size', '18px', 'important');
338
+ newElem.style.setProperty('font-weight', '600', 'important');
188
339
  break;
189
340
  case 'H6':
190
- newElem.style.fontSize = '16px';
191
- newElem.style.fontWeight = '600';
341
+ newElem.style.setProperty('font-size', '16px', 'important');
342
+ newElem.style.setProperty('font-weight', '600', 'important');
192
343
  break;
193
344
  case 'P':
194
345
  default:
195
- newElem.style.fontSize = '14px';
196
- newElem.style.fontWeight = 'normal';
346
+ newElem.style.setProperty('font-size', '14px', 'important');
347
+ newElem.style.setProperty('font-weight', 'normal', 'important');
197
348
  break;
198
349
  }
199
350
  const selectedText = selection.toString();
@@ -201,7 +352,7 @@ class RapidTextEditorComponent {
201
352
  newElem.textContent = selectedText;
202
353
  }
203
354
  else {
204
- newElem.innerHTML = '\u200B'; // Zero-width space to keep cursor visible
355
+ newElem.innerHTML = '\u200B'; // Keeps cursor visible
205
356
  }
206
357
  range.deleteContents();
207
358
  range.insertNode(newElem);
@@ -551,11 +702,11 @@ class RapidTextEditorComponent {
551
702
  }
552
703
  }
553
704
  createTableHTML(rowCount, colCount) {
554
- let tableHTML = '<table border="1" style="">';
705
+ let tableHTML = '<table style="font-size: 14px; width: 100%; border: 1px solid black; border-collapse: collapse;">';
555
706
  for (let i = 0; i < rowCount; i++) {
556
707
  tableHTML += '<tr>';
557
708
  for (let j = 0; j < colCount; j++) {
558
- tableHTML += `<td style="font-size: 14px; min-width: 1.5em; height: 2em; padding: .4em; border: 1px solid black"
709
+ tableHTML += `<td style="border: 1px solid black; border-collapse: collapse; height: 2em; padding: .4em; "
559
710
  role="textbox" contenteditable="true"></td>`;
560
711
  }
561
712
  tableHTML += '</tr>';
@@ -602,19 +753,25 @@ class RapidTextEditorComponent {
602
753
  }
603
754
  submitContent() {
604
755
  const editor = this.editor.nativeElement;
756
+ if (!editor)
757
+ return;
605
758
  const content = editor.innerHTML; // Get the HTML content from the editor
606
759
  const plainTextContent = editor.innerText; // Optionally, get plain text content
760
+ if (!editor.innerHTML.trim()) {
761
+ editor.innerHTML = '<p style="font-size:14px; font-weight:normal;">\u200B</p>';
762
+ // this.ensureParagraphAndFocus();
763
+ }
607
764
  this.onChange(content);
608
765
  }
609
766
  }
610
- RapidTextEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RapidTextEditorComponent, deps: [{ token: i1.MatDialog }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
767
+ RapidTextEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RapidTextEditorComponent, deps: [{ token: i1.MatDialog }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
611
768
  RapidTextEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: RapidTextEditorComponent, selector: "rapid-text-editor", inputs: { contentCapture: "contentCapture", height: "height", width: "width" }, outputs: { contentChange: "contentChange" }, providers: [
612
769
  {
613
770
  provide: NG_VALUE_ACCESSOR,
614
771
  useExisting: forwardRef(() => RapidTextEditorComponent),
615
772
  multi: true
616
773
  }
617
- ], viewQueries: [{ propertyName: "editor", first: true, predicate: ["editor"], descendants: true, static: true }, { propertyName: "tableDialog", first: true, predicate: ["tableDialog"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"dimension\">\r\n <div class=\"rich-text-editor\">\r\n <!-- Toolbar -->\r\n <div class=\"toolbar\">\r\n <select class=\"select-wrapper\" [(ngModel)]=\"selectedHead\" (change)=\"setHeading($event)\">\r\n <option value=\"P\" style=\"font-size: 14px;\">Paragraph</option>\r\n <option value=\"H1\" style=\"font-size: 32px; font-weight: bold;\">H1</option>\r\n <option value=\"H2\" style=\"font-size: 28px; font-weight: bold;\">H2</option>\r\n <option value=\"H3\" style=\"font-size: 24px; font-weight: bold;\">H3</option>\r\n <option value=\"H4\" style=\"font-size: 20px; font-weight: bold;\">H4</option>\r\n <option value=\"H5\" style=\"font-size: 18px; font-weight: 600;\">H5</option>\r\n <option value=\"H6\" style=\"font-size: 16px; font-weight: 600;\">H6</option>\r\n </select>\r\n <select class=\"select-wrapper\" (change)=\"onChange(null)\" [(ngModel)]=\"selectedFont\"\r\n (change)=\"setFontSize($event)\">\r\n <option style=\"font-size: 12px;\" value=\"12\">12px</option>\r\n <option style=\"font-size: 14px;\" value=\"14\" selected>14px</option>\r\n <option style=\"font-size: 16px;\" value=\"16\">16px</option>\r\n <option style=\"font-size: 18px;\" value=\"18\">18px</option>\r\n <option style=\"font-size: 24px;\" value=\"24\">24px</option>\r\n <option style=\"font-size: 32px;\" value=\"32\">32px</option>\r\n <option style=\"font-size: 48px;\" value=\"48\">48px</option>\r\n </select>\r\n <button (click)=\"format('bold')\" type=\"button\" aria-label=\"Bold\">\r\n <mat-icon>format_bold</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('italic')\" type=\"button\" aria-label=\"Italic\">\r\n <mat-icon>format_italic</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('underline')\" type=\"button\" aria-label=\"Underline\">\r\n <mat-icon>format_underline</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('strikethrough')\" type=\"button\" aria-label=\"Strikethrough\">\r\n <mat-icon>strikethrough_s</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyLeft')\" type=\"button\" aria-label=\"Align Left\">\r\n <mat-icon>format_align_left</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyCenter')\" type=\"button\" aria-label=\"Center\">\r\n <mat-icon>format_align_center</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyRight')\" type=\"button\" aria-label=\"Align Right\">\r\n <mat-icon>format_align_right</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyFull')\" type=\"button\" aria-label=\"Justify\">\r\n <mat-icon>format_align_justify</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertUnorderedList')\" type=\"button\" aria-label=\"Unordered List\">\r\n <mat-icon>format_list_bulleted</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertOrderedList')\" type=\"button\" aria-label=\"Ordered List\">\r\n <mat-icon>format_list_numbered</mat-icon>\r\n </button>\r\n <button color=\"secondary\" aria-label=\"Insert Image\" type=\"button\"\r\n style=\"position: relative; display: inline-flex; align-items: center; justify-content: center;\">\r\n <input type=\"file\" (change)=\"insertImageToEditor($event)\"\r\n style=\"position: absolute; left: -50%; top: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;\"\r\n aria-hidden=\"true\" />\r\n <mat-icon style=\"pointer-events: none;\">insert_photo_outlined</mat-icon>\r\n </button>\r\n <button (click)=\"openTableDialog($event)\" type=\"button\" color=\"secondary\"\r\n aria-label=\"Choose table rows and columns\">\r\n <mat-icon>border_all</mat-icon>\r\n </button>\r\n\r\n <button class=\"mb-1\" (click)=\"makeFirstRowHeader()\" type=\"button\" color=\"secondary\" aria-label=\"Make Header\">\r\n <span style=\"font-size: 20px;\" class=\"material-symbols-outlined\">\r\n page_header\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"editor\" id=\"editor\" contenteditable=\"true\" #editor (input)=\"submitContent()\" (blur)=\"onBlur()\"\r\n (drop)=\"drop($event)\" (dragover)=\"allowDrop($event)\">\r\n </div>\r\n </div>\r\n <ng-template #tableDialog let-dialogRef=\"dialogRef\">\r\n <h2 mat-dialog-title>Choose Table Size</h2>\r\n <mat-dialog-content>\r\n <div class=\"grid-container\">\r\n <div *ngFor=\"let cell of grid; let i = index\" [ngClass]=\"{\r\n 'grid-item': true,\r\n 'highlighted': i % 7 < cols && Math.floor(i / 7) < rows\r\n }\" (mouseenter)=\"updatePreview(i % 7 + 1, Math.floor(i / 7) + 1)\"\r\n (click)=\"updateSelection(i % 7 + 1, Math.floor(i / 7) + 1, dialogRef)\"></div>\r\n </div>\r\n <p>{{ rows }} x {{ cols }} </p>\r\n </mat-dialog-content>\r\n </ng-template>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.rich-text-editor{border:1px solid #ccc;border-radius:5px;font-family:Calibri}::ng-deep .editor{position:relative;min-height:300px;border:1px solid #ccc;padding:5px;overflow-y:auto;font-family:Calibri!important;outline:none!important;font-size:14px}::ng-deep .editor table{width:100%;border-collapse:collapse;margin:5px}.fs-12{font-size:12px}.fs-13{font-size:13px}.fs-14{font-size:14px}.fs-16{font-size:16px}.fs-18{font-size:18px}.fs-20{font-size:20px}.fs-24{font-size:24px}.fs-28{font-size:28px}.editor h1{font-size:32px;font-weight:700;margin:0}.editor h2{font-size:28px;font-weight:700;margin:0}.editor h3{font-size:24px;font-weight:700;margin:0}.editor h4{font-size:20px;font-weight:700;margin:0}.editor h5{font-size:18px;font-weight:600;margin:0}.editor h6{font-size:16px;font-weight:600;margin:0}.editor p{font-size:14px;font-weight:400;margin:0}button{width:20px;height:20px;background:none;border:none;margin-left:5px;cursor:pointer}button[mat-icon-button]{margin:0 4px;width:20px!important;height:20px;background:none;border:none}.small-icon-button{width:30px;height:30px;padding:4px}.small-icon-button mat-icon{font-size:16px}button[mat-icon-button]{position:relative;overflow:hidden}input[type=file]{padding:5px;cursor:pointer;margin-left:10px}.fileInput{display:flex;justify-content:center;align-items:center}.select-wrapper{display:inline-block;position:relative;width:70px}.select-wrapper select{appearance:none;width:100%;padding:10px 40px 10px 15px;font-size:16px;color:#333;background-color:#f4f4f4;border:1px solid #ddd;cursor:pointer;outline:none}.select-wrapper:after{content:\"\\25bc\";position:absolute;top:50%;right:15px;transform:translateY(-50%);pointer-events:none;color:#777;font-size:12px}.select-wrapper select:hover{background-color:#e9e9e9;border-color:#bbb}.select-wrapper select:focus{border-color:#007bff;background-color:#fff}.select-wrapper option{padding:8px;font-size:16px;color:#333;background-color:#fff}.toolbar{display:flex;flex-wrap:wrap;align-items:center;background-color:#f4f4f4;padding:10px;border-radius:8px;box-shadow:0 2px 8px #0000001a;gap:10px}.select-wrapper{padding:8px;font-size:14px;border:1px solid #ddd;cursor:pointer;background-color:#fff}.select-wrapper:focus{outline:none;border-color:#007bff}button{border:none;border-radius:5px;padding:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}button:hover{color:#007bff}mat-icon{font-size:20px;color:inherit}input[type=number]{width:60px;padding:5px;font-size:14px;border:1px solid #ddd;border-radius:5px;text-align:center}input[type=file]{border:1px solid #ddd;border-radius:5px;padding:5px;font-size:14px;background-color:#fff;cursor:pointer}input[type=file]:hover{border-color:#007bff}.table{width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.table:hover{background-color:#0056b3;color:#fff!important}.submit{margin-top:10px;width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.submit:hover{border:none;background-color:#0056b3;color:#fff!important}.custom-dialog-container{width:auto;max-width:200px}.grid-container{display:grid;grid-template-columns:repeat(7,20px);grid-gap:5px;gap:5px}.grid-item{width:20px;height:20px;border:1px solid #ddd}.highlighted{background-color:#2196f3}div[contenteditable=false]{display:inline-block;position:relative;resize:both;overflow:hidden;border:1px dashed #ccc;margin:5px}div[contenteditable=false]:hover{border-color:#007bff}div[contenteditable=false] img{display:block;width:100%;height:auto}.uploaded-images{display:flex;flex-wrap:wrap;margin-bottom:20px}.image-preview{margin:10px;padding:5px;border:1px dashed #ccc;cursor:pointer}.image-preview img{max-width:100px;max-height:100px;object-fit:cover}.editor{border:1px solid #ccc;min-height:300px;padding:20px;position:relative}.remove_btn{position:relative;top:10px}\n"], components: [{ type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
774
+ ], viewQueries: [{ propertyName: "editor", first: true, predicate: ["editor"], descendants: true, static: true }, { propertyName: "tableDialog", first: true, predicate: ["tableDialog"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"dimension\">\r\n <div class=\"rich-text-editor\">\r\n <!-- Toolbar -->\r\n <div class=\"toolbar\">\r\n <select class=\"select-wrapper\" [(ngModel)]=\"selectedHead\" (change)=\"setHeading($event)\">\r\n <option value=\"P\" style=\"font-size: 14px !important;\">Paragraph</option>\r\n <option value=\"H1\" style=\"font-size: 32px !important; font-weight: bold !important;\">H1</option>\r\n <option value=\"H2\" style=\"font-size: 28px !important; font-weight: bold !important;\">H2</option>\r\n <option value=\"H3\" style=\"font-size: 24px !important; font-weight: bold !important;\">H3</option>\r\n <option value=\"H4\" style=\"font-size: 20px !important; font-weight: bold !important;\">H4</option>\r\n <option value=\"H5\" style=\"font-size: 18px !important; font-weight: 600 !important;\">H5</option>\r\n <option value=\"H6\" style=\"font-size: 16px !important; font-weight: 600 !important;\">H6</option>\r\n </select>\r\n <select class=\"select-wrapper\" [(ngModel)]=\"selectedFont\"\r\n (change)=\"setFontSize($event)\">\r\n <option style=\"font-size: 12px !important;\" value=\"12\">12px</option>\r\n <option style=\"font-size: 14px !important;\" value=\"14\" selected>14px</option>\r\n <option style=\"font-size: 16px !important;\" value=\"16\">16px</option>\r\n <option style=\"font-size: 18px !important;\" value=\"18\">18px</option>\r\n <option style=\"font-size: 20px !important;\" value=\"20\">20px</option> \r\n <option style=\"font-size: 24px !important;\" value=\"24\">24px</option>\r\n <option style=\"font-size: 28px !important;\" value=\"28\">28px</option>\r\n <option style=\"font-size: 32px !important;\" value=\"32\">32px</option>\r\n <option style=\"font-size: 48px !important;\" value=\"48\">48px</option>\r\n </select>\r\n <button (click)=\"format('bold')\" type=\"button\" aria-label=\"Bold\">\r\n <mat-icon>format_bold</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('italic')\" type=\"button\" aria-label=\"Italic\">\r\n <mat-icon>format_italic</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('underline')\" type=\"button\" aria-label=\"Underline\">\r\n <mat-icon>format_underline</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('strikethrough')\" type=\"button\" aria-label=\"Strikethrough\">\r\n <mat-icon>strikethrough_s</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyLeft')\" type=\"button\" aria-label=\"Align Left\">\r\n <mat-icon>format_align_left</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyCenter')\" type=\"button\" aria-label=\"Center\">\r\n <mat-icon>format_align_center</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyRight')\" type=\"button\" aria-label=\"Align Right\">\r\n <mat-icon>format_align_right</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyFull')\" type=\"button\" aria-label=\"Justify\">\r\n <mat-icon>format_align_justify</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertUnorderedList')\" type=\"button\" aria-label=\"Unordered List\">\r\n <mat-icon>format_list_bulleted</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertOrderedList')\" type=\"button\" aria-label=\"Ordered List\">\r\n <mat-icon>format_list_numbered</mat-icon>\r\n </button>\r\n <button color=\"secondary\" aria-label=\"Insert Image\" type=\"button\"\r\n style=\"position: relative; display: inline-flex; align-items: center; justify-content: center;\">\r\n <input type=\"file\" (change)=\"insertImageToEditor($event)\"\r\n style=\"position: absolute; left: -50%; top: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;\"\r\n aria-hidden=\"true\" />\r\n <mat-icon style=\"pointer-events: none;\">insert_photo_outlined</mat-icon>\r\n </button>\r\n <button (click)=\"openTableDialog($event)\" type=\"button\" color=\"secondary\"\r\n aria-label=\"Choose table rows and columns\">\r\n <mat-icon>border_all</mat-icon>\r\n </button>\r\n\r\n <button class=\"mb-1\" (click)=\"makeFirstRowHeader()\" type=\"button\" color=\"secondary\" aria-label=\"Make Header\">\r\n <span style=\"font-size: 20px;\" class=\"material-symbols-outlined\">\r\n page_header\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"editor\" id=\"editor\" contenteditable=\"true\" #editor (input)=\"submitContent()\" (blur)=\"onBlur()\" (keyup)=\"onEditorKeyUp($event)\" (mouseup)=\"updateCurrentFormat()\"\r\n (drop)=\"drop($event)\" (dragover)=\"allowDrop($event)\">\r\n </div>\r\n </div>\r\n <ng-template #tableDialog let-dialogRef=\"dialogRef\">\r\n <h2 mat-dialog-title>Choose Table Size</h2>\r\n <mat-dialog-content>\r\n <div class=\"grid-container\">\r\n <div *ngFor=\"let cell of grid; let i = index\" [ngClass]=\"{\r\n 'grid-item': true,\r\n 'highlighted': i % 7 < cols && Math.floor(i / 7) < rows\r\n }\" (mouseenter)=\"updatePreview(i % 7 + 1, Math.floor(i / 7) + 1)\"\r\n (click)=\"updateSelection(i % 7 + 1, Math.floor(i / 7) + 1, dialogRef)\"></div>\r\n </div>\r\n <p>{{ rows }} x {{ cols }} </p>\r\n </mat-dialog-content>\r\n </ng-template>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.rich-text-editor{border:1px solid #ccc;border-radius:5px;font-family:Calibri}::ng-deep .editor{position:relative;min-height:300px;border:1px solid #ccc;padding:5px;overflow-y:auto;font-family:Calibri;outline:none!important;font-size:14px}::ng-deep .editor table{width:100%}::ng-deep .editor table,::ng-deep .editor th,::ng-deep .editor td{border:1px solid black;border-collapse:collapse}::ng-deep .editor th,::ng-deep .editor td{padding:.4rem}::ng-deep .editor th{background-color:#f3f3f3}.fs-12{font-size:12px!important}.fs-13{font-size:13px!important}.fs-14{font-size:14px!important}.fs-16{font-size:16px!important}.fs-18{font-size:18px!important}.fs-20{font-size:20px!important}.fs-24{font-size:24px!important}.fs-28{font-size:28px!important}.editor h1{font-size:32px!important;font-weight:700!important;margin:0}.editor h2{font-size:28px!important;font-weight:700!important;margin:0}.editor h3{font-size:24px!important;font-weight:700!important;margin:0}.editor h4{font-size:20px!important;font-weight:700!important;margin:0}.editor h5{font-size:18px!important;font-weight:600!important;margin:0}.editor h6{font-size:16px!important;font-weight:600!important;margin:0}.editor p{font-size:14px!important;font-weight:400;margin:0}button{width:20px;height:20px;background:none;border:none;margin-left:5px;cursor:pointer}button[mat-icon-button]{margin:0 4px;width:20px!important;height:20px;background:none;border:none}.small-icon-button{width:30px;height:30px;padding:4px}.small-icon-button mat-icon{font-size:16px}button[mat-icon-button]{position:relative;overflow:hidden}input[type=file]{padding:5px;cursor:pointer;margin-left:10px}.fileInput{display:flex;justify-content:center;align-items:center}.select-wrapper{display:inline-block;position:relative;width:70px}.select-wrapper select{appearance:none;width:100%;padding:10px 40px 10px 15px;font-size:16px;color:#333;background-color:#f4f4f4;border:1px solid #ddd;cursor:pointer;outline:none}.select-wrapper:after{content:\"\\25bc\";position:absolute;top:50%;right:15px;transform:translateY(-50%);pointer-events:none;color:#777;font-size:12px}.select-wrapper select:hover{background-color:#e9e9e9;border-color:#bbb}.select-wrapper select:focus{border-color:#007bff;background-color:#fff}.select-wrapper option{padding:8px;font-size:16px;color:#333;background-color:#fff}.toolbar{display:flex;flex-wrap:wrap;align-items:center;background-color:#f4f4f4;padding:10px;border-radius:8px;box-shadow:0 2px 8px #0000001a;gap:10px}.select-wrapper{padding:8px;font-size:14px;border:1px solid #ddd;cursor:pointer;background-color:#fff}.select-wrapper:focus{outline:none;border-color:#007bff}button{border:none;border-radius:5px;padding:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}button:hover{color:#007bff}mat-icon{font-size:20px;color:inherit}input[type=number]{width:60px;padding:5px;font-size:14px;border:1px solid #ddd;border-radius:5px;text-align:center}input[type=file]{border:1px solid #ddd;border-radius:5px;padding:5px;font-size:14px;background-color:#fff;cursor:pointer}input[type=file]:hover{border-color:#007bff}.table{width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.table:hover{background-color:#0056b3;color:#fff!important}.submit{margin-top:10px;width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.submit:hover{border:none;background-color:#0056b3;color:#fff!important}.custom-dialog-container{width:auto;max-width:200px}.grid-container{display:grid;grid-template-columns:repeat(7,20px);grid-gap:5px;gap:5px}.grid-item{width:20px;height:20px;border:1px solid #ddd}.highlighted{background-color:#2196f3}div[contenteditable=false]{display:inline-block;position:relative;resize:both;overflow:hidden;border:1px dashed #ccc;margin:5px}div[contenteditable=false]:hover{border-color:#007bff}div[contenteditable=false] img{display:block;width:100%;height:auto}.uploaded-images{display:flex;flex-wrap:wrap;margin-bottom:20px}.image-preview{margin:10px;padding:5px;border:1px dashed #ccc;cursor:pointer}.image-preview img{max-width:100px;max-height:100px;object-fit:cover}.editor{border:1px solid #ccc;min-height:300px;padding:20px;position:relative}.remove_btn{position:relative;top:10px}\n"], components: [{ type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
618
775
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RapidTextEditorComponent, decorators: [{
619
776
  type: Component,
620
777
  args: [{ selector: 'rapid-text-editor', providers: [
@@ -623,8 +780,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
623
780
  useExisting: forwardRef(() => RapidTextEditorComponent),
624
781
  multi: true
625
782
  }
626
- ], template: "<div class=\"dimension\">\r\n <div class=\"rich-text-editor\">\r\n <!-- Toolbar -->\r\n <div class=\"toolbar\">\r\n <select class=\"select-wrapper\" [(ngModel)]=\"selectedHead\" (change)=\"setHeading($event)\">\r\n <option value=\"P\" style=\"font-size: 14px;\">Paragraph</option>\r\n <option value=\"H1\" style=\"font-size: 32px; font-weight: bold;\">H1</option>\r\n <option value=\"H2\" style=\"font-size: 28px; font-weight: bold;\">H2</option>\r\n <option value=\"H3\" style=\"font-size: 24px; font-weight: bold;\">H3</option>\r\n <option value=\"H4\" style=\"font-size: 20px; font-weight: bold;\">H4</option>\r\n <option value=\"H5\" style=\"font-size: 18px; font-weight: 600;\">H5</option>\r\n <option value=\"H6\" style=\"font-size: 16px; font-weight: 600;\">H6</option>\r\n </select>\r\n <select class=\"select-wrapper\" (change)=\"onChange(null)\" [(ngModel)]=\"selectedFont\"\r\n (change)=\"setFontSize($event)\">\r\n <option style=\"font-size: 12px;\" value=\"12\">12px</option>\r\n <option style=\"font-size: 14px;\" value=\"14\" selected>14px</option>\r\n <option style=\"font-size: 16px;\" value=\"16\">16px</option>\r\n <option style=\"font-size: 18px;\" value=\"18\">18px</option>\r\n <option style=\"font-size: 24px;\" value=\"24\">24px</option>\r\n <option style=\"font-size: 32px;\" value=\"32\">32px</option>\r\n <option style=\"font-size: 48px;\" value=\"48\">48px</option>\r\n </select>\r\n <button (click)=\"format('bold')\" type=\"button\" aria-label=\"Bold\">\r\n <mat-icon>format_bold</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('italic')\" type=\"button\" aria-label=\"Italic\">\r\n <mat-icon>format_italic</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('underline')\" type=\"button\" aria-label=\"Underline\">\r\n <mat-icon>format_underline</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('strikethrough')\" type=\"button\" aria-label=\"Strikethrough\">\r\n <mat-icon>strikethrough_s</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyLeft')\" type=\"button\" aria-label=\"Align Left\">\r\n <mat-icon>format_align_left</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyCenter')\" type=\"button\" aria-label=\"Center\">\r\n <mat-icon>format_align_center</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyRight')\" type=\"button\" aria-label=\"Align Right\">\r\n <mat-icon>format_align_right</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyFull')\" type=\"button\" aria-label=\"Justify\">\r\n <mat-icon>format_align_justify</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertUnorderedList')\" type=\"button\" aria-label=\"Unordered List\">\r\n <mat-icon>format_list_bulleted</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertOrderedList')\" type=\"button\" aria-label=\"Ordered List\">\r\n <mat-icon>format_list_numbered</mat-icon>\r\n </button>\r\n <button color=\"secondary\" aria-label=\"Insert Image\" type=\"button\"\r\n style=\"position: relative; display: inline-flex; align-items: center; justify-content: center;\">\r\n <input type=\"file\" (change)=\"insertImageToEditor($event)\"\r\n style=\"position: absolute; left: -50%; top: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;\"\r\n aria-hidden=\"true\" />\r\n <mat-icon style=\"pointer-events: none;\">insert_photo_outlined</mat-icon>\r\n </button>\r\n <button (click)=\"openTableDialog($event)\" type=\"button\" color=\"secondary\"\r\n aria-label=\"Choose table rows and columns\">\r\n <mat-icon>border_all</mat-icon>\r\n </button>\r\n\r\n <button class=\"mb-1\" (click)=\"makeFirstRowHeader()\" type=\"button\" color=\"secondary\" aria-label=\"Make Header\">\r\n <span style=\"font-size: 20px;\" class=\"material-symbols-outlined\">\r\n page_header\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"editor\" id=\"editor\" contenteditable=\"true\" #editor (input)=\"submitContent()\" (blur)=\"onBlur()\"\r\n (drop)=\"drop($event)\" (dragover)=\"allowDrop($event)\">\r\n </div>\r\n </div>\r\n <ng-template #tableDialog let-dialogRef=\"dialogRef\">\r\n <h2 mat-dialog-title>Choose Table Size</h2>\r\n <mat-dialog-content>\r\n <div class=\"grid-container\">\r\n <div *ngFor=\"let cell of grid; let i = index\" [ngClass]=\"{\r\n 'grid-item': true,\r\n 'highlighted': i % 7 < cols && Math.floor(i / 7) < rows\r\n }\" (mouseenter)=\"updatePreview(i % 7 + 1, Math.floor(i / 7) + 1)\"\r\n (click)=\"updateSelection(i % 7 + 1, Math.floor(i / 7) + 1, dialogRef)\"></div>\r\n </div>\r\n <p>{{ rows }} x {{ cols }} </p>\r\n </mat-dialog-content>\r\n </ng-template>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.rich-text-editor{border:1px solid #ccc;border-radius:5px;font-family:Calibri}::ng-deep .editor{position:relative;min-height:300px;border:1px solid #ccc;padding:5px;overflow-y:auto;font-family:Calibri!important;outline:none!important;font-size:14px}::ng-deep .editor table{width:100%;border-collapse:collapse;margin:5px}.fs-12{font-size:12px}.fs-13{font-size:13px}.fs-14{font-size:14px}.fs-16{font-size:16px}.fs-18{font-size:18px}.fs-20{font-size:20px}.fs-24{font-size:24px}.fs-28{font-size:28px}.editor h1{font-size:32px;font-weight:700;margin:0}.editor h2{font-size:28px;font-weight:700;margin:0}.editor h3{font-size:24px;font-weight:700;margin:0}.editor h4{font-size:20px;font-weight:700;margin:0}.editor h5{font-size:18px;font-weight:600;margin:0}.editor h6{font-size:16px;font-weight:600;margin:0}.editor p{font-size:14px;font-weight:400;margin:0}button{width:20px;height:20px;background:none;border:none;margin-left:5px;cursor:pointer}button[mat-icon-button]{margin:0 4px;width:20px!important;height:20px;background:none;border:none}.small-icon-button{width:30px;height:30px;padding:4px}.small-icon-button mat-icon{font-size:16px}button[mat-icon-button]{position:relative;overflow:hidden}input[type=file]{padding:5px;cursor:pointer;margin-left:10px}.fileInput{display:flex;justify-content:center;align-items:center}.select-wrapper{display:inline-block;position:relative;width:70px}.select-wrapper select{appearance:none;width:100%;padding:10px 40px 10px 15px;font-size:16px;color:#333;background-color:#f4f4f4;border:1px solid #ddd;cursor:pointer;outline:none}.select-wrapper:after{content:\"\\25bc\";position:absolute;top:50%;right:15px;transform:translateY(-50%);pointer-events:none;color:#777;font-size:12px}.select-wrapper select:hover{background-color:#e9e9e9;border-color:#bbb}.select-wrapper select:focus{border-color:#007bff;background-color:#fff}.select-wrapper option{padding:8px;font-size:16px;color:#333;background-color:#fff}.toolbar{display:flex;flex-wrap:wrap;align-items:center;background-color:#f4f4f4;padding:10px;border-radius:8px;box-shadow:0 2px 8px #0000001a;gap:10px}.select-wrapper{padding:8px;font-size:14px;border:1px solid #ddd;cursor:pointer;background-color:#fff}.select-wrapper:focus{outline:none;border-color:#007bff}button{border:none;border-radius:5px;padding:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}button:hover{color:#007bff}mat-icon{font-size:20px;color:inherit}input[type=number]{width:60px;padding:5px;font-size:14px;border:1px solid #ddd;border-radius:5px;text-align:center}input[type=file]{border:1px solid #ddd;border-radius:5px;padding:5px;font-size:14px;background-color:#fff;cursor:pointer}input[type=file]:hover{border-color:#007bff}.table{width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.table:hover{background-color:#0056b3;color:#fff!important}.submit{margin-top:10px;width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.submit:hover{border:none;background-color:#0056b3;color:#fff!important}.custom-dialog-container{width:auto;max-width:200px}.grid-container{display:grid;grid-template-columns:repeat(7,20px);grid-gap:5px;gap:5px}.grid-item{width:20px;height:20px;border:1px solid #ddd}.highlighted{background-color:#2196f3}div[contenteditable=false]{display:inline-block;position:relative;resize:both;overflow:hidden;border:1px dashed #ccc;margin:5px}div[contenteditable=false]:hover{border-color:#007bff}div[contenteditable=false] img{display:block;width:100%;height:auto}.uploaded-images{display:flex;flex-wrap:wrap;margin-bottom:20px}.image-preview{margin:10px;padding:5px;border:1px dashed #ccc;cursor:pointer}.image-preview img{max-width:100px;max-height:100px;object-fit:cover}.editor{border:1px solid #ccc;min-height:300px;padding:20px;position:relative}.remove_btn{position:relative;top:10px}\n"] }]
627
- }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { contentCapture: [{
783
+ ], template: "<div class=\"dimension\">\r\n <div class=\"rich-text-editor\">\r\n <!-- Toolbar -->\r\n <div class=\"toolbar\">\r\n <select class=\"select-wrapper\" [(ngModel)]=\"selectedHead\" (change)=\"setHeading($event)\">\r\n <option value=\"P\" style=\"font-size: 14px !important;\">Paragraph</option>\r\n <option value=\"H1\" style=\"font-size: 32px !important; font-weight: bold !important;\">H1</option>\r\n <option value=\"H2\" style=\"font-size: 28px !important; font-weight: bold !important;\">H2</option>\r\n <option value=\"H3\" style=\"font-size: 24px !important; font-weight: bold !important;\">H3</option>\r\n <option value=\"H4\" style=\"font-size: 20px !important; font-weight: bold !important;\">H4</option>\r\n <option value=\"H5\" style=\"font-size: 18px !important; font-weight: 600 !important;\">H5</option>\r\n <option value=\"H6\" style=\"font-size: 16px !important; font-weight: 600 !important;\">H6</option>\r\n </select>\r\n <select class=\"select-wrapper\" [(ngModel)]=\"selectedFont\"\r\n (change)=\"setFontSize($event)\">\r\n <option style=\"font-size: 12px !important;\" value=\"12\">12px</option>\r\n <option style=\"font-size: 14px !important;\" value=\"14\" selected>14px</option>\r\n <option style=\"font-size: 16px !important;\" value=\"16\">16px</option>\r\n <option style=\"font-size: 18px !important;\" value=\"18\">18px</option>\r\n <option style=\"font-size: 20px !important;\" value=\"20\">20px</option> \r\n <option style=\"font-size: 24px !important;\" value=\"24\">24px</option>\r\n <option style=\"font-size: 28px !important;\" value=\"28\">28px</option>\r\n <option style=\"font-size: 32px !important;\" value=\"32\">32px</option>\r\n <option style=\"font-size: 48px !important;\" value=\"48\">48px</option>\r\n </select>\r\n <button (click)=\"format('bold')\" type=\"button\" aria-label=\"Bold\">\r\n <mat-icon>format_bold</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('italic')\" type=\"button\" aria-label=\"Italic\">\r\n <mat-icon>format_italic</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('underline')\" type=\"button\" aria-label=\"Underline\">\r\n <mat-icon>format_underline</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('strikethrough')\" type=\"button\" aria-label=\"Strikethrough\">\r\n <mat-icon>strikethrough_s</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyLeft')\" type=\"button\" aria-label=\"Align Left\">\r\n <mat-icon>format_align_left</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyCenter')\" type=\"button\" aria-label=\"Center\">\r\n <mat-icon>format_align_center</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyRight')\" type=\"button\" aria-label=\"Align Right\">\r\n <mat-icon>format_align_right</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('justifyFull')\" type=\"button\" aria-label=\"Justify\">\r\n <mat-icon>format_align_justify</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertUnorderedList')\" type=\"button\" aria-label=\"Unordered List\">\r\n <mat-icon>format_list_bulleted</mat-icon>\r\n </button>\r\n\r\n <button (click)=\"format('insertOrderedList')\" type=\"button\" aria-label=\"Ordered List\">\r\n <mat-icon>format_list_numbered</mat-icon>\r\n </button>\r\n <button color=\"secondary\" aria-label=\"Insert Image\" type=\"button\"\r\n style=\"position: relative; display: inline-flex; align-items: center; justify-content: center;\">\r\n <input type=\"file\" (change)=\"insertImageToEditor($event)\"\r\n style=\"position: absolute; left: -50%; top: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;\"\r\n aria-hidden=\"true\" />\r\n <mat-icon style=\"pointer-events: none;\">insert_photo_outlined</mat-icon>\r\n </button>\r\n <button (click)=\"openTableDialog($event)\" type=\"button\" color=\"secondary\"\r\n aria-label=\"Choose table rows and columns\">\r\n <mat-icon>border_all</mat-icon>\r\n </button>\r\n\r\n <button class=\"mb-1\" (click)=\"makeFirstRowHeader()\" type=\"button\" color=\"secondary\" aria-label=\"Make Header\">\r\n <span style=\"font-size: 20px;\" class=\"material-symbols-outlined\">\r\n page_header\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"editor\" id=\"editor\" contenteditable=\"true\" #editor (input)=\"submitContent()\" (blur)=\"onBlur()\" (keyup)=\"onEditorKeyUp($event)\" (mouseup)=\"updateCurrentFormat()\"\r\n (drop)=\"drop($event)\" (dragover)=\"allowDrop($event)\">\r\n </div>\r\n </div>\r\n <ng-template #tableDialog let-dialogRef=\"dialogRef\">\r\n <h2 mat-dialog-title>Choose Table Size</h2>\r\n <mat-dialog-content>\r\n <div class=\"grid-container\">\r\n <div *ngFor=\"let cell of grid; let i = index\" [ngClass]=\"{\r\n 'grid-item': true,\r\n 'highlighted': i % 7 < cols && Math.floor(i / 7) < rows\r\n }\" (mouseenter)=\"updatePreview(i % 7 + 1, Math.floor(i / 7) + 1)\"\r\n (click)=\"updateSelection(i % 7 + 1, Math.floor(i / 7) + 1, dialogRef)\"></div>\r\n </div>\r\n <p>{{ rows }} x {{ cols }} </p>\r\n </mat-dialog-content>\r\n </ng-template>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.rich-text-editor{border:1px solid #ccc;border-radius:5px;font-family:Calibri}::ng-deep .editor{position:relative;min-height:300px;border:1px solid #ccc;padding:5px;overflow-y:auto;font-family:Calibri;outline:none!important;font-size:14px}::ng-deep .editor table{width:100%}::ng-deep .editor table,::ng-deep .editor th,::ng-deep .editor td{border:1px solid black;border-collapse:collapse}::ng-deep .editor th,::ng-deep .editor td{padding:.4rem}::ng-deep .editor th{background-color:#f3f3f3}.fs-12{font-size:12px!important}.fs-13{font-size:13px!important}.fs-14{font-size:14px!important}.fs-16{font-size:16px!important}.fs-18{font-size:18px!important}.fs-20{font-size:20px!important}.fs-24{font-size:24px!important}.fs-28{font-size:28px!important}.editor h1{font-size:32px!important;font-weight:700!important;margin:0}.editor h2{font-size:28px!important;font-weight:700!important;margin:0}.editor h3{font-size:24px!important;font-weight:700!important;margin:0}.editor h4{font-size:20px!important;font-weight:700!important;margin:0}.editor h5{font-size:18px!important;font-weight:600!important;margin:0}.editor h6{font-size:16px!important;font-weight:600!important;margin:0}.editor p{font-size:14px!important;font-weight:400;margin:0}button{width:20px;height:20px;background:none;border:none;margin-left:5px;cursor:pointer}button[mat-icon-button]{margin:0 4px;width:20px!important;height:20px;background:none;border:none}.small-icon-button{width:30px;height:30px;padding:4px}.small-icon-button mat-icon{font-size:16px}button[mat-icon-button]{position:relative;overflow:hidden}input[type=file]{padding:5px;cursor:pointer;margin-left:10px}.fileInput{display:flex;justify-content:center;align-items:center}.select-wrapper{display:inline-block;position:relative;width:70px}.select-wrapper select{appearance:none;width:100%;padding:10px 40px 10px 15px;font-size:16px;color:#333;background-color:#f4f4f4;border:1px solid #ddd;cursor:pointer;outline:none}.select-wrapper:after{content:\"\\25bc\";position:absolute;top:50%;right:15px;transform:translateY(-50%);pointer-events:none;color:#777;font-size:12px}.select-wrapper select:hover{background-color:#e9e9e9;border-color:#bbb}.select-wrapper select:focus{border-color:#007bff;background-color:#fff}.select-wrapper option{padding:8px;font-size:16px;color:#333;background-color:#fff}.toolbar{display:flex;flex-wrap:wrap;align-items:center;background-color:#f4f4f4;padding:10px;border-radius:8px;box-shadow:0 2px 8px #0000001a;gap:10px}.select-wrapper{padding:8px;font-size:14px;border:1px solid #ddd;cursor:pointer;background-color:#fff}.select-wrapper:focus{outline:none;border-color:#007bff}button{border:none;border-radius:5px;padding:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}button:hover{color:#007bff}mat-icon{font-size:20px;color:inherit}input[type=number]{width:60px;padding:5px;font-size:14px;border:1px solid #ddd;border-radius:5px;text-align:center}input[type=file]{border:1px solid #ddd;border-radius:5px;padding:5px;font-size:14px;background-color:#fff;cursor:pointer}input[type=file]:hover{border-color:#007bff}.table{width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.table:hover{background-color:#0056b3;color:#fff!important}.submit{margin-top:10px;width:100px;height:30px;color:#007bff!important;font-weight:700;border:1px solid #007bff}.submit:hover{border:none;background-color:#0056b3;color:#fff!important}.custom-dialog-container{width:auto;max-width:200px}.grid-container{display:grid;grid-template-columns:repeat(7,20px);grid-gap:5px;gap:5px}.grid-item{width:20px;height:20px;border:1px solid #ddd}.highlighted{background-color:#2196f3}div[contenteditable=false]{display:inline-block;position:relative;resize:both;overflow:hidden;border:1px dashed #ccc;margin:5px}div[contenteditable=false]:hover{border-color:#007bff}div[contenteditable=false] img{display:block;width:100%;height:auto}.uploaded-images{display:flex;flex-wrap:wrap;margin-bottom:20px}.image-preview{margin:10px;padding:5px;border:1px dashed #ccc;cursor:pointer}.image-preview img{max-width:100px;max-height:100px;object-fit:cover}.editor{border:1px solid #ccc;min-height:300px;padding:20px;position:relative}.remove_btn{position:relative;top:10px}\n"] }]
784
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { contentCapture: [{
628
785
  type: Input
629
786
  }], height: [{
630
787
  type: Input