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
|
}
|
|
@@ -122,19 +127,32 @@ class RapidTextEditorComponent {
|
|
|
122
127
|
if (!selection || selection.rangeCount === 0)
|
|
123
128
|
return;
|
|
124
129
|
const range = selection.getRangeAt(0);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
if (!range.collapsed) {
|
|
131
|
+
const parent = (_a = selection.anchorNode) === null || _a === void 0 ? void 0 : _a.parentElement;
|
|
132
|
+
if (parent &&
|
|
133
|
+
parent.classList &&
|
|
134
|
+
Array.from(parent.classList).some((c) => c.startsWith('fs-'))) {
|
|
135
|
+
parent.style.fontSize = `${size}px`;
|
|
136
|
+
parent.className = `fs-${size}`;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const span = document.createElement('span');
|
|
140
|
+
span.style.fontSize = `${size}px`;
|
|
141
|
+
span.classList.add(`fs-${size}`);
|
|
142
|
+
range.surroundContents(span);
|
|
143
|
+
}
|
|
132
144
|
}
|
|
133
145
|
else {
|
|
134
146
|
const span = document.createElement('span');
|
|
135
147
|
span.style.fontSize = `${size}px`;
|
|
136
148
|
span.classList.add(`fs-${size}`);
|
|
137
|
-
|
|
149
|
+
span.appendChild(document.createTextNode('\u200B')); // zero-width space
|
|
150
|
+
range.insertNode(span);
|
|
151
|
+
const newRange = document.createRange();
|
|
152
|
+
newRange.setStart(span.firstChild, 1);
|
|
153
|
+
newRange.collapse(true);
|
|
154
|
+
selection.removeAllRanges();
|
|
155
|
+
selection.addRange(newRange);
|
|
138
156
|
}
|
|
139
157
|
}
|
|
140
158
|
setHeading(event) {
|
|
@@ -144,13 +162,10 @@ class RapidTextEditorComponent {
|
|
|
144
162
|
if (!selection || selection.rangeCount === 0)
|
|
145
163
|
return;
|
|
146
164
|
const range = selection.getRangeAt(0);
|
|
147
|
-
// Get editor reference
|
|
148
165
|
const editor = document.getElementById('editor');
|
|
149
166
|
if (!editor)
|
|
150
167
|
return;
|
|
151
|
-
// Create the new element (heading or paragraph)
|
|
152
168
|
const newElem = document.createElement(tag);
|
|
153
|
-
// Apply styles based on the selected tag
|
|
154
169
|
switch (tag) {
|
|
155
170
|
case 'H1':
|
|
156
171
|
newElem.style.fontSize = '32px';
|
|
@@ -182,7 +197,6 @@ class RapidTextEditorComponent {
|
|
|
182
197
|
newElem.style.fontWeight = 'normal';
|
|
183
198
|
break;
|
|
184
199
|
}
|
|
185
|
-
// Get any selected text, or use a zero-width space if none is selected
|
|
186
200
|
const selectedText = selection.toString();
|
|
187
201
|
if (selectedText) {
|
|
188
202
|
newElem.textContent = selectedText;
|
|
@@ -190,16 +204,13 @@ class RapidTextEditorComponent {
|
|
|
190
204
|
else {
|
|
191
205
|
newElem.innerHTML = '\u200B'; // Zero-width space to keep cursor visible
|
|
192
206
|
}
|
|
193
|
-
// Delete the selected content and insert new heading/paragraph
|
|
194
207
|
range.deleteContents();
|
|
195
208
|
range.insertNode(newElem);
|
|
196
|
-
// Set the cursor at the end of the inserted node
|
|
197
209
|
const newRange = document.createRange();
|
|
198
210
|
newRange.setStart(newElem, newElem.childNodes.length);
|
|
199
211
|
newRange.collapse(true);
|
|
200
212
|
selection.removeAllRanges();
|
|
201
213
|
selection.addRange(newRange);
|
|
202
|
-
// Refocus the editor
|
|
203
214
|
editor.focus();
|
|
204
215
|
}
|
|
205
216
|
format(command) {
|
|
@@ -217,35 +228,7 @@ class RapidTextEditorComponent {
|
|
|
217
228
|
// Handle drop event in the editor
|
|
218
229
|
drop(event) {
|
|
219
230
|
event.preventDefault();
|
|
220
|
-
|
|
221
|
-
// if (imageUrl) {
|
|
222
|
-
// this.insertImageInEditor(imageUrl);
|
|
223
|
-
// }
|
|
224
|
-
}
|
|
225
|
-
// insertImage(event: any): void {
|
|
226
|
-
// const files: FileList = event.target.files;
|
|
227
|
-
// if (!files || files.length === 0) {
|
|
228
|
-
// console.error('No files selected.');
|
|
229
|
-
// return;
|
|
230
|
-
// }
|
|
231
|
-
// Array.from(files).forEach((file) => {
|
|
232
|
-
// // Check file type
|
|
233
|
-
// if (file.type !== 'image/png' && !file.type.startsWith('image/')) {
|
|
234
|
-
// console.error('Unsupported file type:', file.type);
|
|
235
|
-
// return;
|
|
236
|
-
// }
|
|
237
|
-
// // Read the image file
|
|
238
|
-
// const reader = new FileReader();
|
|
239
|
-
// reader.onload = (e: any) => {
|
|
240
|
-
// const imageUrl = e.target.result;
|
|
241
|
-
// // Add image to the uploaded images list
|
|
242
|
-
// this.uploadedImages.push(imageUrl);
|
|
243
|
-
// // Call insertImageInEditor to add the image to the editor
|
|
244
|
-
// this.insertImageInEditor(imageUrl);
|
|
245
|
-
// };
|
|
246
|
-
// reader.readAsDataURL(file);
|
|
247
|
-
// });
|
|
248
|
-
// } -> for PNG
|
|
231
|
+
}
|
|
249
232
|
removeImage(index) {
|
|
250
233
|
this.uploadedImages.splice(index, 1);
|
|
251
234
|
}
|
|
@@ -384,20 +367,6 @@ class RapidTextEditorComponent {
|
|
|
384
367
|
reader.readAsDataURL(file);
|
|
385
368
|
});
|
|
386
369
|
}
|
|
387
|
-
// insertImageByDrag(imageUrl: string): void {
|
|
388
|
-
// const editor = document.querySelector('.editor') as HTMLElement;
|
|
389
|
-
// if (!editor) {
|
|
390
|
-
// console.error('Editor element not found.');
|
|
391
|
-
// return;
|
|
392
|
-
// }
|
|
393
|
-
// const img = document.createElement('img');
|
|
394
|
-
// img.src = imageUrl;
|
|
395
|
-
// img.style.maxWidth = '100%';
|
|
396
|
-
// img.style.display = 'block';
|
|
397
|
-
// img.style.width = '300px';
|
|
398
|
-
// img.style.height = 'auto';
|
|
399
|
-
// editor.appendChild(img);
|
|
400
|
-
// }
|
|
401
370
|
insertImageToEditor(event) {
|
|
402
371
|
const file = event.target.files[0];
|
|
403
372
|
if (file) {
|
|
@@ -484,6 +453,7 @@ class RapidTextEditorComponent {
|
|
|
484
453
|
}
|
|
485
454
|
}
|
|
486
455
|
openTableDialog(event) {
|
|
456
|
+
this.insertMarker();
|
|
487
457
|
this.rows = 1;
|
|
488
458
|
this.cols = 1;
|
|
489
459
|
const dialogRef = this.dialog.open(this.tableDialog, {
|
|
@@ -550,6 +520,16 @@ class RapidTextEditorComponent {
|
|
|
550
520
|
}
|
|
551
521
|
return null;
|
|
552
522
|
}
|
|
523
|
+
insertMarker() {
|
|
524
|
+
const selection = window.getSelection();
|
|
525
|
+
if (selection && selection.rangeCount > 0) {
|
|
526
|
+
const range = selection.getRangeAt(0).cloneRange();
|
|
527
|
+
const marker = document.createElement('span');
|
|
528
|
+
marker.id = 'table-marker';
|
|
529
|
+
marker.style.display = 'none';
|
|
530
|
+
range.insertNode(marker);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
553
533
|
insertTable(rows, cols) {
|
|
554
534
|
const rowCount = parseInt(rows, 10);
|
|
555
535
|
const colCount = parseInt(cols, 10);
|
|
@@ -557,25 +537,21 @@ class RapidTextEditorComponent {
|
|
|
557
537
|
return;
|
|
558
538
|
}
|
|
559
539
|
const editor = this.editor.nativeElement;
|
|
560
|
-
const
|
|
561
|
-
// Ensure selection is inside the editor
|
|
562
|
-
if (!this.isSelectionInsideEditor(editor, selection)) {
|
|
563
|
-
// Append the table at the end if selection is outside editor
|
|
564
|
-
this.appendTable(editor, rowCount, colCount);
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
// Proceed to insert the table if selection is valid
|
|
540
|
+
const marker = editor.querySelector('#table-marker');
|
|
568
541
|
const tableHTML = this.createTableHTML(rowCount, colCount);
|
|
569
|
-
const range = selection.getRangeAt(0);
|
|
570
|
-
range.deleteContents(); // Remove any selected content
|
|
571
542
|
const tempDiv = document.createElement('div');
|
|
572
543
|
tempDiv.innerHTML = tableHTML;
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
544
|
+
const table = tempDiv.firstElementChild;
|
|
545
|
+
if (marker && table) {
|
|
546
|
+
marker.parentNode.replaceChild(table, marker);
|
|
547
|
+
this.setCursorToFirstCell(table);
|
|
548
|
+
editor.focus();
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
// fallback if no marker, just append
|
|
552
|
+
this.appendTable(editor, rowCount, colCount);
|
|
553
|
+
}
|
|
577
554
|
}
|
|
578
|
-
// Helper function: Create table HTML
|
|
579
555
|
createTableHTML(rowCount, colCount) {
|
|
580
556
|
let tableHTML = '<table border="1" style="">';
|
|
581
557
|
for (let i = 0; i < rowCount; i++) {
|
|
@@ -589,21 +565,17 @@ class RapidTextEditorComponent {
|
|
|
589
565
|
tableHTML += '</table>';
|
|
590
566
|
return tableHTML;
|
|
591
567
|
}
|
|
592
|
-
// Helper function: Append a table at the end of the editor
|
|
593
568
|
appendTable(editor, rowCount, colCount) {
|
|
594
569
|
const tableHTML = this.createTableHTML(rowCount, colCount);
|
|
595
570
|
editor.innerHTML += tableHTML;
|
|
596
|
-
// Set cursor inside the first cell of the new table
|
|
597
571
|
const lastInsertedTable = editor.querySelector('table:last-child');
|
|
598
572
|
this.setCursorToFirstCell(lastInsertedTable);
|
|
599
573
|
editor.focus();
|
|
600
574
|
}
|
|
601
|
-
// Helper function: Check if selection is inside the editor
|
|
602
575
|
isSelectionInsideEditor(editor, selection) {
|
|
603
576
|
if (!selection.rangeCount)
|
|
604
577
|
return false;
|
|
605
578
|
let node = selection.getRangeAt(0).commonAncestorContainer;
|
|
606
|
-
// Traverse up to see if the node belongs to the editor
|
|
607
579
|
while (node) {
|
|
608
580
|
if (node === editor)
|
|
609
581
|
return true;
|
|
@@ -611,26 +583,11 @@ class RapidTextEditorComponent {
|
|
|
611
583
|
}
|
|
612
584
|
return false;
|
|
613
585
|
}
|
|
614
|
-
// Helper function: Move cursor to the first cell
|
|
615
|
-
// private setCursorToFirstCell(table: HTMLElement) {
|
|
616
|
-
// const firstCell = table.querySelector('tr:first-child td:first-child') as HTMLElement;
|
|
617
|
-
// if (firstCell) {
|
|
618
|
-
// const newRange = document.createRange();
|
|
619
|
-
// newRange.setStart(firstCell, 0); // Start at the beginning of the cell
|
|
620
|
-
// newRange.collapse(true);
|
|
621
|
-
// const selection = window.getSelection();
|
|
622
|
-
// selection!.removeAllRanges();
|
|
623
|
-
// selection!.addRange(newRange);
|
|
624
|
-
// }
|
|
625
|
-
// }
|
|
626
586
|
setCursorToFirstCell(table) {
|
|
627
587
|
const firstCell = table.querySelector('tr:first-child td:first-child, tr:first-child th:first-child');
|
|
628
588
|
if (firstCell) {
|
|
629
|
-
// Ensure the cell is contenteditable
|
|
630
589
|
firstCell.setAttribute('contenteditable', 'true');
|
|
631
|
-
// Focus the cell
|
|
632
590
|
firstCell.focus();
|
|
633
|
-
// Create a range and place the cursor at the start of the cell
|
|
634
591
|
const newRange = document.createRange();
|
|
635
592
|
newRange.selectNodeContents(firstCell); // Select the contents of the cell
|
|
636
593
|
newRange.collapse(true); // Collapse to the start
|
|
@@ -649,10 +606,7 @@ class RapidTextEditorComponent {
|
|
|
649
606
|
const editor = this.editor.nativeElement;
|
|
650
607
|
const content = editor.innerHTML; // Get the HTML content from the editor
|
|
651
608
|
const plainTextContent = editor.innerText; // Optionally, get plain text content
|
|
652
|
-
// For demonstration, you can log it or process it as needed
|
|
653
609
|
this.onChange(content);
|
|
654
|
-
// Example: You could send this data to a server or use it elsewhere in your application
|
|
655
|
-
// this.yourService.submitContent({ content }); // Replace with your service call
|
|
656
610
|
}
|
|
657
611
|
}
|
|
658
612
|
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 });
|
|
@@ -662,7 +616,7 @@ RapidTextEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0
|
|
|
662
616
|
useExisting: forwardRef(() => RapidTextEditorComponent),
|
|
663
617
|
multi: true
|
|
664
618
|
}
|
|
665
|
-
], 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"] }] });
|
|
619
|
+
], 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"] }] });
|
|
666
620
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RapidTextEditorComponent, decorators: [{
|
|
667
621
|
type: Component,
|
|
668
622
|
args: [{ selector: 'rapid-text-editor', providers: [
|
|
@@ -671,7 +625,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
671
625
|
useExisting: forwardRef(() => RapidTextEditorComponent),
|
|
672
626
|
multi: true
|
|
673
627
|
}
|
|
674
|
-
], 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"] }]
|
|
628
|
+
], 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"] }]
|
|
675
629
|
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { contentCapture: [{
|
|
676
630
|
type: Input
|
|
677
631
|
}], height: [{
|