rapid-text-editor 1.0.12 → 1.0.14
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/lib/rapid-text-editor.component.mjs +65 -111
- package/fesm2015/rapid-text-editor.mjs +64 -110
- package/fesm2015/rapid-text-editor.mjs.map +1 -1
- package/fesm2020/rapid-text-editor.mjs +64 -110
- package/fesm2020/rapid-text-editor.mjs.map +1 -1
- package/lib/rapid-text-editor.component.d.ts +1 -0
- package/package.json +2 -1
|
@@ -29,7 +29,7 @@ class RapidTextEditorComponent {
|
|
|
29
29
|
this.renderer = renderer;
|
|
30
30
|
this.elRef = elRef;
|
|
31
31
|
this.contentCapture = false;
|
|
32
|
-
this.height = "
|
|
32
|
+
this.height = "auto";
|
|
33
33
|
this.width = "auto";
|
|
34
34
|
this.contentChange = new EventEmitter();
|
|
35
35
|
this.editorContent = '';
|
|
@@ -38,13 +38,9 @@ class RapidTextEditorComponent {
|
|
|
38
38
|
this.grid = Array(49).fill(0);
|
|
39
39
|
this.Math = Math;
|
|
40
40
|
this.uploadedImages = [];
|
|
41
|
-
//Two Way Data Binding Functionality
|
|
42
41
|
this.selectedHead = 'P';
|
|
43
42
|
this.selectedFont = '14';
|
|
44
43
|
this.onChange = (content) => {
|
|
45
|
-
setTimeout(() => {
|
|
46
|
-
console.log(this.editor.nativeElement.innerHTML);
|
|
47
|
-
}, 0);
|
|
48
44
|
if (this.editor.nativeElement.innerHTML == '<br>' || this.editor.nativeElement.innerHTML == '') {
|
|
49
45
|
this.selectedHead = 'P';
|
|
50
46
|
this.selectedFont = '14';
|
|
@@ -67,17 +63,29 @@ class RapidTextEditorComponent {
|
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
65
|
applyDimensions() {
|
|
70
|
-
const
|
|
66
|
+
const dimensionElement = this.elRef.nativeElement.querySelector('.dimension');
|
|
67
|
+
if (this.width) {
|
|
68
|
+
this.renderer.setStyle(dimensionElement, 'width', this.width);
|
|
69
|
+
}
|
|
70
|
+
const editorElement = this.elRef.nativeElement.querySelector('.editor');
|
|
71
71
|
if (this.height) {
|
|
72
72
|
this.renderer.setStyle(editorElement, 'height', this.height);
|
|
73
73
|
}
|
|
74
|
-
if (this.width) {
|
|
75
|
-
this.renderer.setStyle(editorElement, 'width', this.width);
|
|
76
|
-
}
|
|
77
74
|
}
|
|
78
75
|
ngAfterViewInit() {
|
|
79
76
|
const editor = this.el.nativeElement.querySelector('.editor');
|
|
80
|
-
if (
|
|
77
|
+
if (editor && (editor.innerHTML.trim() === "" || editor.innerHTML.trim() === "<br>")) {
|
|
78
|
+
editor.focus();
|
|
79
|
+
const range = document.createRange();
|
|
80
|
+
range.setStart(editor, 0);
|
|
81
|
+
range.collapse(true);
|
|
82
|
+
const selection = window.getSelection();
|
|
83
|
+
if (selection) {
|
|
84
|
+
selection.removeAllRanges();
|
|
85
|
+
selection.addRange(range);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
81
89
|
console.error('Editor element not found.');
|
|
82
90
|
}
|
|
83
91
|
}
|
|
@@ -97,17 +105,14 @@ class RapidTextEditorComponent {
|
|
|
97
105
|
getContent() {
|
|
98
106
|
return this.editorContent;
|
|
99
107
|
}
|
|
100
|
-
// Called by Angular to update the value programmatically
|
|
101
108
|
writeValue(content) {
|
|
102
109
|
if (this.editor && this.editor.nativeElement) {
|
|
103
110
|
this.editor.nativeElement.innerHTML = content || '';
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
|
-
// Registers the onChange callback to notify Angular of content changes
|
|
107
113
|
registerOnChange(fn) {
|
|
108
114
|
this.onChange = fn;
|
|
109
115
|
}
|
|
110
|
-
// Registers the onTouched callback for blur events
|
|
111
116
|
registerOnTouched(fn) {
|
|
112
117
|
this.onTouched = fn;
|
|
113
118
|
}
|
|
@@ -121,19 +126,32 @@ class RapidTextEditorComponent {
|
|
|
121
126
|
if (!selection || selection.rangeCount === 0)
|
|
122
127
|
return;
|
|
123
128
|
const range = selection.getRangeAt(0);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
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}`);
|
|
141
|
+
range.surroundContents(span);
|
|
142
|
+
}
|
|
131
143
|
}
|
|
132
144
|
else {
|
|
133
145
|
const span = document.createElement('span');
|
|
134
146
|
span.style.fontSize = `${size}px`;
|
|
135
147
|
span.classList.add(`fs-${size}`);
|
|
136
|
-
|
|
148
|
+
span.appendChild(document.createTextNode('\u200B')); // zero-width space
|
|
149
|
+
range.insertNode(span);
|
|
150
|
+
const newRange = document.createRange();
|
|
151
|
+
newRange.setStart(span.firstChild, 1);
|
|
152
|
+
newRange.collapse(true);
|
|
153
|
+
selection.removeAllRanges();
|
|
154
|
+
selection.addRange(newRange);
|
|
137
155
|
}
|
|
138
156
|
}
|
|
139
157
|
setHeading(event) {
|
|
@@ -143,13 +161,10 @@ class RapidTextEditorComponent {
|
|
|
143
161
|
if (!selection || selection.rangeCount === 0)
|
|
144
162
|
return;
|
|
145
163
|
const range = selection.getRangeAt(0);
|
|
146
|
-
// Get editor reference
|
|
147
164
|
const editor = document.getElementById('editor');
|
|
148
165
|
if (!editor)
|
|
149
166
|
return;
|
|
150
|
-
// Create the new element (heading or paragraph)
|
|
151
167
|
const newElem = document.createElement(tag);
|
|
152
|
-
// Apply styles based on the selected tag
|
|
153
168
|
switch (tag) {
|
|
154
169
|
case 'H1':
|
|
155
170
|
newElem.style.fontSize = '32px';
|
|
@@ -181,7 +196,6 @@ class RapidTextEditorComponent {
|
|
|
181
196
|
newElem.style.fontWeight = 'normal';
|
|
182
197
|
break;
|
|
183
198
|
}
|
|
184
|
-
// Get any selected text, or use a zero-width space if none is selected
|
|
185
199
|
const selectedText = selection.toString();
|
|
186
200
|
if (selectedText) {
|
|
187
201
|
newElem.textContent = selectedText;
|
|
@@ -189,16 +203,13 @@ class RapidTextEditorComponent {
|
|
|
189
203
|
else {
|
|
190
204
|
newElem.innerHTML = '\u200B'; // Zero-width space to keep cursor visible
|
|
191
205
|
}
|
|
192
|
-
// Delete the selected content and insert new heading/paragraph
|
|
193
206
|
range.deleteContents();
|
|
194
207
|
range.insertNode(newElem);
|
|
195
|
-
// Set the cursor at the end of the inserted node
|
|
196
208
|
const newRange = document.createRange();
|
|
197
209
|
newRange.setStart(newElem, newElem.childNodes.length);
|
|
198
210
|
newRange.collapse(true);
|
|
199
211
|
selection.removeAllRanges();
|
|
200
212
|
selection.addRange(newRange);
|
|
201
|
-
// Refocus the editor
|
|
202
213
|
editor.focus();
|
|
203
214
|
}
|
|
204
215
|
format(command) {
|
|
@@ -215,35 +226,7 @@ class RapidTextEditorComponent {
|
|
|
215
226
|
// Handle drop event in the editor
|
|
216
227
|
drop(event) {
|
|
217
228
|
event.preventDefault();
|
|
218
|
-
|
|
219
|
-
// if (imageUrl) {
|
|
220
|
-
// this.insertImageInEditor(imageUrl);
|
|
221
|
-
// }
|
|
222
|
-
}
|
|
223
|
-
// insertImage(event: any): void {
|
|
224
|
-
// const files: FileList = event.target.files;
|
|
225
|
-
// if (!files || files.length === 0) {
|
|
226
|
-
// console.error('No files selected.');
|
|
227
|
-
// return;
|
|
228
|
-
// }
|
|
229
|
-
// Array.from(files).forEach((file) => {
|
|
230
|
-
// // Check file type
|
|
231
|
-
// if (file.type !== 'image/png' && !file.type.startsWith('image/')) {
|
|
232
|
-
// console.error('Unsupported file type:', file.type);
|
|
233
|
-
// return;
|
|
234
|
-
// }
|
|
235
|
-
// // Read the image file
|
|
236
|
-
// const reader = new FileReader();
|
|
237
|
-
// reader.onload = (e: any) => {
|
|
238
|
-
// const imageUrl = e.target.result;
|
|
239
|
-
// // Add image to the uploaded images list
|
|
240
|
-
// this.uploadedImages.push(imageUrl);
|
|
241
|
-
// // Call insertImageInEditor to add the image to the editor
|
|
242
|
-
// this.insertImageInEditor(imageUrl);
|
|
243
|
-
// };
|
|
244
|
-
// reader.readAsDataURL(file);
|
|
245
|
-
// });
|
|
246
|
-
// } -> for PNG
|
|
229
|
+
}
|
|
247
230
|
removeImage(index) {
|
|
248
231
|
this.uploadedImages.splice(index, 1);
|
|
249
232
|
}
|
|
@@ -382,20 +365,6 @@ class RapidTextEditorComponent {
|
|
|
382
365
|
reader.readAsDataURL(file);
|
|
383
366
|
});
|
|
384
367
|
}
|
|
385
|
-
// insertImageByDrag(imageUrl: string): void {
|
|
386
|
-
// const editor = document.querySelector('.editor') as HTMLElement;
|
|
387
|
-
// if (!editor) {
|
|
388
|
-
// console.error('Editor element not found.');
|
|
389
|
-
// return;
|
|
390
|
-
// }
|
|
391
|
-
// const img = document.createElement('img');
|
|
392
|
-
// img.src = imageUrl;
|
|
393
|
-
// img.style.maxWidth = '100%';
|
|
394
|
-
// img.style.display = 'block';
|
|
395
|
-
// img.style.width = '300px';
|
|
396
|
-
// img.style.height = 'auto';
|
|
397
|
-
// editor.appendChild(img);
|
|
398
|
-
// }
|
|
399
368
|
insertImageToEditor(event) {
|
|
400
369
|
const file = event.target.files[0];
|
|
401
370
|
if (file) {
|
|
@@ -482,6 +451,7 @@ class RapidTextEditorComponent {
|
|
|
482
451
|
}
|
|
483
452
|
}
|
|
484
453
|
openTableDialog(event) {
|
|
454
|
+
this.insertMarker();
|
|
485
455
|
this.rows = 1;
|
|
486
456
|
this.cols = 1;
|
|
487
457
|
const dialogRef = this.dialog.open(this.tableDialog, {
|
|
@@ -548,6 +518,16 @@ class RapidTextEditorComponent {
|
|
|
548
518
|
}
|
|
549
519
|
return null;
|
|
550
520
|
}
|
|
521
|
+
insertMarker() {
|
|
522
|
+
const selection = window.getSelection();
|
|
523
|
+
if (selection && selection.rangeCount > 0) {
|
|
524
|
+
const range = selection.getRangeAt(0).cloneRange();
|
|
525
|
+
const marker = document.createElement('span');
|
|
526
|
+
marker.id = 'table-marker';
|
|
527
|
+
marker.style.display = 'none';
|
|
528
|
+
range.insertNode(marker);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
551
531
|
insertTable(rows, cols) {
|
|
552
532
|
const rowCount = parseInt(rows, 10);
|
|
553
533
|
const colCount = parseInt(cols, 10);
|
|
@@ -555,25 +535,21 @@ class RapidTextEditorComponent {
|
|
|
555
535
|
return;
|
|
556
536
|
}
|
|
557
537
|
const editor = this.editor.nativeElement;
|
|
558
|
-
const
|
|
559
|
-
// Ensure selection is inside the editor
|
|
560
|
-
if (!this.isSelectionInsideEditor(editor, selection)) {
|
|
561
|
-
// Append the table at the end if selection is outside editor
|
|
562
|
-
this.appendTable(editor, rowCount, colCount);
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
// Proceed to insert the table if selection is valid
|
|
538
|
+
const marker = editor.querySelector('#table-marker');
|
|
566
539
|
const tableHTML = this.createTableHTML(rowCount, colCount);
|
|
567
|
-
const range = selection.getRangeAt(0);
|
|
568
|
-
range.deleteContents(); // Remove any selected content
|
|
569
540
|
const tempDiv = document.createElement('div');
|
|
570
541
|
tempDiv.innerHTML = tableHTML;
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
542
|
+
const table = tempDiv.firstElementChild;
|
|
543
|
+
if (marker && table) {
|
|
544
|
+
marker.parentNode.replaceChild(table, marker);
|
|
545
|
+
this.setCursorToFirstCell(table);
|
|
546
|
+
editor.focus();
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
// fallback if no marker, just append
|
|
550
|
+
this.appendTable(editor, rowCount, colCount);
|
|
551
|
+
}
|
|
575
552
|
}
|
|
576
|
-
// Helper function: Create table HTML
|
|
577
553
|
createTableHTML(rowCount, colCount) {
|
|
578
554
|
let tableHTML = '<table border="1" style="">';
|
|
579
555
|
for (let i = 0; i < rowCount; i++) {
|
|
@@ -587,21 +563,17 @@ class RapidTextEditorComponent {
|
|
|
587
563
|
tableHTML += '</table>';
|
|
588
564
|
return tableHTML;
|
|
589
565
|
}
|
|
590
|
-
// Helper function: Append a table at the end of the editor
|
|
591
566
|
appendTable(editor, rowCount, colCount) {
|
|
592
567
|
const tableHTML = this.createTableHTML(rowCount, colCount);
|
|
593
568
|
editor.innerHTML += tableHTML;
|
|
594
|
-
// Set cursor inside the first cell of the new table
|
|
595
569
|
const lastInsertedTable = editor.querySelector('table:last-child');
|
|
596
570
|
this.setCursorToFirstCell(lastInsertedTable);
|
|
597
571
|
editor.focus();
|
|
598
572
|
}
|
|
599
|
-
// Helper function: Check if selection is inside the editor
|
|
600
573
|
isSelectionInsideEditor(editor, selection) {
|
|
601
574
|
if (!selection.rangeCount)
|
|
602
575
|
return false;
|
|
603
576
|
let node = selection.getRangeAt(0).commonAncestorContainer;
|
|
604
|
-
// Traverse up to see if the node belongs to the editor
|
|
605
577
|
while (node) {
|
|
606
578
|
if (node === editor)
|
|
607
579
|
return true;
|
|
@@ -609,26 +581,11 @@ class RapidTextEditorComponent {
|
|
|
609
581
|
}
|
|
610
582
|
return false;
|
|
611
583
|
}
|
|
612
|
-
// Helper function: Move cursor to the first cell
|
|
613
|
-
// private setCursorToFirstCell(table: HTMLElement) {
|
|
614
|
-
// const firstCell = table.querySelector('tr:first-child td:first-child') as HTMLElement;
|
|
615
|
-
// if (firstCell) {
|
|
616
|
-
// const newRange = document.createRange();
|
|
617
|
-
// newRange.setStart(firstCell, 0); // Start at the beginning of the cell
|
|
618
|
-
// newRange.collapse(true);
|
|
619
|
-
// const selection = window.getSelection();
|
|
620
|
-
// selection!.removeAllRanges();
|
|
621
|
-
// selection!.addRange(newRange);
|
|
622
|
-
// }
|
|
623
|
-
// }
|
|
624
584
|
setCursorToFirstCell(table) {
|
|
625
585
|
const firstCell = table.querySelector('tr:first-child td:first-child, tr:first-child th:first-child');
|
|
626
586
|
if (firstCell) {
|
|
627
|
-
// Ensure the cell is contenteditable
|
|
628
587
|
firstCell.setAttribute('contenteditable', 'true');
|
|
629
|
-
// Focus the cell
|
|
630
588
|
firstCell.focus();
|
|
631
|
-
// Create a range and place the cursor at the start of the cell
|
|
632
589
|
const newRange = document.createRange();
|
|
633
590
|
newRange.selectNodeContents(firstCell); // Select the contents of the cell
|
|
634
591
|
newRange.collapse(true); // Collapse to the start
|
|
@@ -647,10 +604,7 @@ class RapidTextEditorComponent {
|
|
|
647
604
|
const editor = this.editor.nativeElement;
|
|
648
605
|
const content = editor.innerHTML; // Get the HTML content from the editor
|
|
649
606
|
const plainTextContent = editor.innerText; // Optionally, get plain text content
|
|
650
|
-
// For demonstration, you can log it or process it as needed
|
|
651
607
|
this.onChange(content);
|
|
652
|
-
// Example: You could send this data to a server or use it elsewhere in your application
|
|
653
|
-
// this.yourService.submitContent({ content }); // Replace with your service call
|
|
654
608
|
}
|
|
655
609
|
}
|
|
656
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 });
|
|
@@ -660,7 +614,7 @@ RapidTextEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0
|
|
|
660
614
|
useExisting: forwardRef(() => RapidTextEditorComponent),
|
|
661
615
|
multi: true
|
|
662
616
|
}
|
|
663
|
-
], 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\r\n\r\n<div class=\"rich-text-editor\">\r\n <!-- Toolbar -->\r\n <div class=\"toolbar\">\r\n\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\r\n\r\n <select class=\"select-wrapper\" (change)=\"onChange(null)\" [(ngModel)]=\"selectedFont\" (change)=\"setFontSize($event)\">\r\n <option value=\"12\">12px</option>\r\n <option value=\"13\">13px</option>\r\n <option value=\"14\" selected>14px</option>\r\n <option value=\"16\">16px</option>\r\n <option value=\"18\">18px</option>\r\n <option value=\"20\">20px</option>\r\n <option value=\"24\">24px</option>\r\n <option value=\"28\">28px</option>\r\n </select>\r\n\r\n\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\r\n\r\n\r\n <button color=\"secondary\" aria-label=\"Insert Image\" type=\"button\" style=\"position: relative; display: inline-flex; align-items: center; justify-content: center;\">\r\n <input\r\n type=\"file\"\r\n (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 />\r\n\r\n <mat-icon style=\"pointer-events: none;\">insert_photo_outlined</mat-icon>\r\n </button>\r\n\r\n\r\n <button (click)=\"openTableDialog($event)\" type=\"button\" color=\"secondary\" 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\r\n\r\n\r\n </div>\r\n\r\n <!-- Editable Area -->\r\n <!-- (keypress)=\"onContentChange()\" need to be included -->\r\n <div class=\"editor\" id=\"editor\" contenteditable=\"true\" #editor (input)=\"submitContent()\" (blur)=\"onBlur()\" (drop)=\"drop($event)\" (dragover)=\"allowDrop($event)\" >\r\n <!-- Your content goes here -->\r\n </div>\r\n\r\n</div>\r\n\r\n<!-- <button mat-stroked-button class=\"submit\" (click)=\"submitContent()\">Submit</button> -->\r\n\r\n\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\r\n *ngFor=\"let cell of grid; let i = index\"\r\n [ngClass]=\"{\r\n 'grid-item': true,\r\n 'highlighted': i % 7 < cols && Math.floor(i / 7) < rows\r\n }\"\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)\"\r\n ></div>\r\n </div>\r\n <p>{{ rows }} x {{ cols }} </p>\r\n</mat-dialog-content>\r\n</ng-template>\r\n\r\n<!-- <div>\r\n <input class=\"mt-2\" type=\"file\" placeholder=\"Upload your images here...\" (change)=\"insertImage($event)\" accept=\"image/png,image/*\" multiple />\r\n <div class=\"uploaded-images\" *ngIf=\"uploadedImages.length > 0\">\r\n <div *ngFor=\"let imageUrl of uploadedImages; let i = index\" class=\"image-preview\">\r\n <img [src]=\"imageUrl\" alt=\"Uploaded Image\"\r\n draggable=\"true\" width=\"100px\" height=\"100px\"\r\n (dragstart)=\"drag($event, imageUrl)\" />\r\n <mat-icon style=\"color: red;\r\n position: absolute\" (click)=\"removeImage(i)\">cancel</mat-icon>\r\n\r\n </div>\r\n </div>\r\n</div> -->\r\n\r\n</div>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\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:150px}.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"] }] });
|
|
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"] }] });
|
|
664
618
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RapidTextEditorComponent, decorators: [{
|
|
665
619
|
type: Component,
|
|
666
620
|
args: [{ selector: 'rapid-text-editor', providers: [
|
|
@@ -669,7 +623,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
669
623
|
useExisting: forwardRef(() => RapidTextEditorComponent),
|
|
670
624
|
multi: true
|
|
671
625
|
}
|
|
672
|
-
], template: "<div class=\"dimension\">\r\n\r\n\r\n<div class=\"rich-text-editor\">\r\n <!-- Toolbar -->\r\n <div class=\"toolbar\">\r\n\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\r\n\r\n <select class=\"select-wrapper\" (change)=\"onChange(null)\" [(ngModel)]=\"selectedFont\" (change)=\"setFontSize($event)\">\r\n <option value=\"12\">12px</option>\r\n <option value=\"13\">13px</option>\r\n <option value=\"14\" selected>14px</option>\r\n <option value=\"16\">16px</option>\r\n <option value=\"18\">18px</option>\r\n <option value=\"20\">20px</option>\r\n <option value=\"24\">24px</option>\r\n <option value=\"28\">28px</option>\r\n </select>\r\n\r\n\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\r\n\r\n\r\n <button color=\"secondary\" aria-label=\"Insert Image\" type=\"button\" style=\"position: relative; display: inline-flex; align-items: center; justify-content: center;\">\r\n <input\r\n type=\"file\"\r\n (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 />\r\n\r\n <mat-icon style=\"pointer-events: none;\">insert_photo_outlined</mat-icon>\r\n </button>\r\n\r\n\r\n <button (click)=\"openTableDialog($event)\" type=\"button\" color=\"secondary\" 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\r\n\r\n\r\n </div>\r\n\r\n <!-- Editable Area -->\r\n <!-- (keypress)=\"onContentChange()\" need to be included -->\r\n <div class=\"editor\" id=\"editor\" contenteditable=\"true\" #editor (input)=\"submitContent()\" (blur)=\"onBlur()\" (drop)=\"drop($event)\" (dragover)=\"allowDrop($event)\" >\r\n <!-- Your content goes here -->\r\n </div>\r\n\r\n</div>\r\n\r\n<!-- <button mat-stroked-button class=\"submit\" (click)=\"submitContent()\">Submit</button> -->\r\n\r\n\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\r\n *ngFor=\"let cell of grid; let i = index\"\r\n [ngClass]=\"{\r\n 'grid-item': true,\r\n 'highlighted': i % 7 < cols && Math.floor(i / 7) < rows\r\n }\"\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)\"\r\n ></div>\r\n </div>\r\n <p>{{ rows }} x {{ cols }} </p>\r\n</mat-dialog-content>\r\n</ng-template>\r\n\r\n<!-- <div>\r\n <input class=\"mt-2\" type=\"file\" placeholder=\"Upload your images here...\" (change)=\"insertImage($event)\" accept=\"image/png,image/*\" multiple />\r\n <div class=\"uploaded-images\" *ngIf=\"uploadedImages.length > 0\">\r\n <div *ngFor=\"let imageUrl of uploadedImages; let i = index\" class=\"image-preview\">\r\n <img [src]=\"imageUrl\" alt=\"Uploaded Image\"\r\n draggable=\"true\" width=\"100px\" height=\"100px\"\r\n (dragstart)=\"drag($event, imageUrl)\" />\r\n <mat-icon style=\"color: red;\r\n position: absolute\" (click)=\"removeImage(i)\">cancel</mat-icon>\r\n\r\n </div>\r\n </div>\r\n</div> -->\r\n\r\n</div>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\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:150px}.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"] }]
|
|
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"] }]
|
|
673
627
|
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { contentCapture: [{
|
|
674
628
|
type: Input
|
|
675
629
|
}], height: [{
|