cax-design-system 2.6.1 → 2.7.0
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/README.md +1 -1
- package/commentbox/commentbox.d.ts +111 -0
- package/commentbox/commentbox.module.d.ts +17 -0
- package/commentbox/index.d.ts +5 -0
- package/commentbox/public_api.d.ts +2 -0
- package/esm2022/card/card.mjs +2 -2
- package/esm2022/commentbox/cax-design-system-commentbox.mjs +5 -0
- package/esm2022/commentbox/commentbox.mjs +541 -0
- package/esm2022/commentbox/commentbox.module.mjs +27 -0
- package/esm2022/commentbox/public_api.mjs +3 -0
- package/esm2022/inputtext/inputtext.component.mjs +13 -4
- package/esm2022/inputtextarea/inputtextarea.component.mjs +8 -4
- package/esm2022/table/components/column-filter/column-filter.mjs +2 -2
- package/esm2022/upload/cax-design-system-upload.mjs +5 -0
- package/esm2022/upload/public_api.mjs +3 -0
- package/esm2022/upload/upload.component.mjs +355 -0
- package/esm2022/upload/upload.component.module.mjs +21 -0
- package/fesm2022/cax-design-system-card.mjs +2 -2
- package/fesm2022/cax-design-system-card.mjs.map +1 -1
- package/fesm2022/cax-design-system-commentbox.mjs +572 -0
- package/fesm2022/cax-design-system-commentbox.mjs.map +1 -0
- package/fesm2022/cax-design-system-inputtext.mjs +12 -3
- package/fesm2022/cax-design-system-inputtext.mjs.map +1 -1
- package/fesm2022/cax-design-system-inputtextarea.mjs +7 -3
- package/fesm2022/cax-design-system-inputtextarea.mjs.map +1 -1
- package/fesm2022/cax-design-system-table.mjs +1 -1
- package/fesm2022/cax-design-system-table.mjs.map +1 -1
- package/fesm2022/cax-design-system-upload.mjs +380 -0
- package/fesm2022/cax-design-system-upload.mjs.map +1 -0
- package/inputtext/inputtext.component.d.ts +4 -1
- package/inputtextarea/inputtextarea.component.d.ts +2 -2
- package/package.json +156 -144
- package/resources/cax.min.scss +1 -1
- package/resources/cax.scss +83 -37
- package/resources/components/card/card.scss +1 -1
- package/resources/components/commentbox/commentbox.scss +604 -0
- package/resources/components/upload/upload.component.scss +147 -0
- package/upload/index.d.ts +5 -0
- package/upload/public_api.d.ts +2 -0
- package/upload/upload.component.d.ts +61 -0
- package/upload/upload.component.module.d.ts +11 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { EventEmitter, Component, Input, Output, ViewChild, HostListener, NgModule } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/platform-browser';
|
|
4
|
+
import * as i2 from '@angular/common';
|
|
5
|
+
import { CommonModule } from '@angular/common';
|
|
6
|
+
import * as i3 from '@angular/forms';
|
|
7
|
+
import { FormsModule } from '@angular/forms';
|
|
8
|
+
import * as i4 from 'cax-design-system/sidebar';
|
|
9
|
+
import { Sidebar } from 'cax-design-system/sidebar';
|
|
10
|
+
import * as i5 from 'cax-design-system/inputtext';
|
|
11
|
+
import { InputTextModule } from 'cax-design-system/inputtext';
|
|
12
|
+
import * as i6 from 'cax-design-system/button';
|
|
13
|
+
import { ButtonModule } from 'cax-design-system/button';
|
|
14
|
+
import * as i7 from 'cax-design-system/api';
|
|
15
|
+
import { SharedModule } from 'cax-design-system/api';
|
|
16
|
+
import * as i8 from 'cax-design-system/chip';
|
|
17
|
+
import { ChipModule } from 'cax-design-system/chip';
|
|
18
|
+
import * as i9 from 'cax-design-system/overlay';
|
|
19
|
+
import { OverlayModule } from 'cax-design-system/overlay';
|
|
20
|
+
import * as i10 from 'cax-design-system/avatar';
|
|
21
|
+
import { AvatarModule } from 'cax-design-system/avatar';
|
|
22
|
+
import { RippleModule } from 'cax-design-system/ripple';
|
|
23
|
+
|
|
24
|
+
class CommentboxComponent {
|
|
25
|
+
sanitizer;
|
|
26
|
+
comments = [];
|
|
27
|
+
mentionSuggestions = [];
|
|
28
|
+
hashtagSuggestions = [];
|
|
29
|
+
sidebarHeader;
|
|
30
|
+
isAdmin = true;
|
|
31
|
+
commentAdded = new EventEmitter();
|
|
32
|
+
fileSelected = new EventEmitter();
|
|
33
|
+
fileDownload = new EventEmitter();
|
|
34
|
+
visibleChange = new EventEmitter();
|
|
35
|
+
newComment = '';
|
|
36
|
+
isMentioning = false;
|
|
37
|
+
isHashtagging = false;
|
|
38
|
+
suggestions = [];
|
|
39
|
+
selectedSuggestion = null;
|
|
40
|
+
selectedSuggestionIndex = -1;
|
|
41
|
+
filteredSuggestions = [];
|
|
42
|
+
currentTokenType = null;
|
|
43
|
+
cursorPosition = 0;
|
|
44
|
+
fileInput;
|
|
45
|
+
suggestionPanel;
|
|
46
|
+
inputText;
|
|
47
|
+
commentsList;
|
|
48
|
+
countChip;
|
|
49
|
+
selectedFiles = [];
|
|
50
|
+
selectedFilesMap = new Map();
|
|
51
|
+
today = new Date();
|
|
52
|
+
overlayVisible = false;
|
|
53
|
+
filesOverlayVisible = false;
|
|
54
|
+
overlayPosition = { top: 0, left: 0 };
|
|
55
|
+
dateUpdateInterval;
|
|
56
|
+
// Keep track of should auto scroll
|
|
57
|
+
shouldAutoScroll = true;
|
|
58
|
+
isUserScrolling = false;
|
|
59
|
+
// Add new property for mutation observer
|
|
60
|
+
observer;
|
|
61
|
+
constructor(sanitizer) {
|
|
62
|
+
this.sanitizer = sanitizer;
|
|
63
|
+
this.updateCurrentDate();
|
|
64
|
+
this.dateUpdateInterval = setInterval(() => this.updateCurrentDate(), 60000);
|
|
65
|
+
// Initialize observer
|
|
66
|
+
this.observer = new MutationObserver(() => this.forceScrollToBottom());
|
|
67
|
+
}
|
|
68
|
+
ngAfterViewInit() {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
this.forceScrollToBottom();
|
|
71
|
+
}, 100);
|
|
72
|
+
// Set up observer to auto-scroll when content changes
|
|
73
|
+
if (this.commentsList?.nativeElement) {
|
|
74
|
+
this.observer.observe(this.commentsList.nativeElement, {
|
|
75
|
+
childList: true,
|
|
76
|
+
subtree: true,
|
|
77
|
+
characterData: true
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
ngOnDestroy() {
|
|
82
|
+
if (this.dateUpdateInterval) {
|
|
83
|
+
clearInterval(this.dateUpdateInterval);
|
|
84
|
+
}
|
|
85
|
+
// Disconnect the observer
|
|
86
|
+
this.observer.disconnect();
|
|
87
|
+
// Remove event listeners
|
|
88
|
+
document.removeEventListener('click', this.handleClickOutside);
|
|
89
|
+
}
|
|
90
|
+
updateCurrentDate() {
|
|
91
|
+
this.today = new Date();
|
|
92
|
+
}
|
|
93
|
+
formatDate(date) {
|
|
94
|
+
return date.toLocaleDateString(undefined, {
|
|
95
|
+
day: '2-digit',
|
|
96
|
+
month: '2-digit',
|
|
97
|
+
year: 'numeric',
|
|
98
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
formatMessageWithTags(text) {
|
|
102
|
+
if (!text)
|
|
103
|
+
return '';
|
|
104
|
+
const sanitizedText = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
105
|
+
const htmlContent = sanitizedText.replace(/(@\w+|#\w+)/g, (match) => {
|
|
106
|
+
if (match.startsWith('@')) {
|
|
107
|
+
return `<span class="mention" style="color: #0C4AF3; font-weight: 600;">${match}</span>`;
|
|
108
|
+
}
|
|
109
|
+
else if (match.startsWith('#')) {
|
|
110
|
+
return `<span class="hashtag" style="color: #0C4AF3; font-weight: 600;">${match}</span>`;
|
|
111
|
+
}
|
|
112
|
+
return match;
|
|
113
|
+
});
|
|
114
|
+
return this.sanitizer.bypassSecurityTrustHtml(htmlContent);
|
|
115
|
+
}
|
|
116
|
+
addComment() {
|
|
117
|
+
if (this.newComment.trim() || this.selectedFiles.length > 0) {
|
|
118
|
+
const newComment = {
|
|
119
|
+
text: this.newComment,
|
|
120
|
+
date: new Date(),
|
|
121
|
+
files: this.selectedFiles.length > 0 ? [...this.selectedFiles] : undefined,
|
|
122
|
+
isAdmin: this.isAdmin,
|
|
123
|
+
sender: this.isAdmin ? 'System Admin' : 'User'
|
|
124
|
+
};
|
|
125
|
+
this.comments = [...this.comments, newComment];
|
|
126
|
+
this.commentAdded.emit(newComment);
|
|
127
|
+
this.newComment = '';
|
|
128
|
+
this.selectedFiles = [];
|
|
129
|
+
this.selectedFilesMap.clear();
|
|
130
|
+
this.filesOverlayVisible = false;
|
|
131
|
+
if (this.suggestionPanel?.nativeElement) {
|
|
132
|
+
this.suggestionPanel.nativeElement.style.display = 'none';
|
|
133
|
+
}
|
|
134
|
+
// Always scroll to bottom immediately
|
|
135
|
+
this.scrollToBottom(true);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
forceScrollToBottom() {
|
|
139
|
+
if (!this.commentsList?.nativeElement)
|
|
140
|
+
return;
|
|
141
|
+
const element = this.commentsList.nativeElement;
|
|
142
|
+
requestAnimationFrame(() => {
|
|
143
|
+
try {
|
|
144
|
+
// Force immediate scroll
|
|
145
|
+
element.scrollTop = element.scrollHeight;
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
console.error('Scroll error:', err);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
scrollToBottom(force = false) {
|
|
153
|
+
if (force) {
|
|
154
|
+
this.forceScrollToBottom();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (!this.commentsList?.nativeElement)
|
|
158
|
+
return;
|
|
159
|
+
const element = this.commentsList.nativeElement;
|
|
160
|
+
// Use double RAF for reliable scrolling
|
|
161
|
+
requestAnimationFrame(() => {
|
|
162
|
+
requestAnimationFrame(() => {
|
|
163
|
+
try {
|
|
164
|
+
// Force immediate scroll for new comments
|
|
165
|
+
element.scrollTop = element.scrollHeight;
|
|
166
|
+
// Use smooth scrolling after initial jump
|
|
167
|
+
element.scrollTo({
|
|
168
|
+
top: element.scrollHeight,
|
|
169
|
+
behavior: 'smooth'
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
element.scrollTop = element.scrollHeight;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
set visible(value) {
|
|
179
|
+
if (this._visible !== value) {
|
|
180
|
+
this._visible = value;
|
|
181
|
+
this.visibleChange.emit(this._visible);
|
|
182
|
+
if (this._visible) {
|
|
183
|
+
this.shouldAutoScroll = true;
|
|
184
|
+
setTimeout(() => this.scrollToBottom(true), 300);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
get visible() {
|
|
189
|
+
return this._visible;
|
|
190
|
+
}
|
|
191
|
+
_visible = false;
|
|
192
|
+
toggleComments() {
|
|
193
|
+
this.visible = !this.visible;
|
|
194
|
+
}
|
|
195
|
+
onSidebarHide() {
|
|
196
|
+
this._visible = false;
|
|
197
|
+
this.visibleChange.emit(false);
|
|
198
|
+
}
|
|
199
|
+
onDocumentClick(event) {
|
|
200
|
+
const target = event.target;
|
|
201
|
+
const isInputClick = this.inputText?.nativeElement?.contains(target);
|
|
202
|
+
const isPanelClick = this.suggestionPanel?.nativeElement?.contains(target);
|
|
203
|
+
if (!isInputClick && !isPanelClick) {
|
|
204
|
+
this.overlayVisible = false;
|
|
205
|
+
this.currentTokenType = null;
|
|
206
|
+
this.filteredSuggestions = [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
handleKeyUp(event) {
|
|
210
|
+
// Update cursor position on every key press
|
|
211
|
+
const input = event.target;
|
|
212
|
+
this.cursorPosition = input.selectionStart || 0;
|
|
213
|
+
if (event.key === 'Escape') {
|
|
214
|
+
this.overlayVisible = false;
|
|
215
|
+
this.currentTokenType = null;
|
|
216
|
+
this.filteredSuggestions = [];
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (event.key === '@' || event.key === '#') {
|
|
220
|
+
this.currentTokenType = event.key === '@' ? 'mention' : 'hashtag';
|
|
221
|
+
this.filteredSuggestions = this.currentTokenType === 'mention' ? this.mentionSuggestions : this.hashtagSuggestions;
|
|
222
|
+
this.selectedSuggestionIndex = 0;
|
|
223
|
+
const rect = input.getBoundingClientRect();
|
|
224
|
+
const cursorPosition = this.getCursorPosition(input);
|
|
225
|
+
this.overlayVisible = true;
|
|
226
|
+
setTimeout(() => {
|
|
227
|
+
const panel = this.suggestionPanel?.nativeElement;
|
|
228
|
+
if (panel) {
|
|
229
|
+
panel.style.left = `${rect.left + cursorPosition.left}px`;
|
|
230
|
+
panel.style.top = `${rect.top - 10}px`;
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
if (this.currentTokenType) {
|
|
235
|
+
const token = this.getTokenAtCursor(input.value, this.cursorPosition);
|
|
236
|
+
if (token) {
|
|
237
|
+
const searchTerm = token.slice(1).toLowerCase();
|
|
238
|
+
this.filteredSuggestions = (this.currentTokenType === 'mention' ? this.mentionSuggestions : this.hashtagSuggestions).filter((item) => item.name.toLowerCase().includes(searchTerm) || item.id.toLowerCase().includes(searchTerm));
|
|
239
|
+
if (this.filteredSuggestions.length > 0) {
|
|
240
|
+
this.overlayVisible = true;
|
|
241
|
+
// Only reset selection index if we have new suggestions
|
|
242
|
+
if (this.selectedSuggestionIndex < 0 || this.selectedSuggestionIndex >= this.filteredSuggestions.length) {
|
|
243
|
+
this.selectedSuggestionIndex = 0;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
this.overlayVisible = false;
|
|
248
|
+
this.selectedSuggestionIndex = -1;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
this.overlayVisible = false;
|
|
253
|
+
this.currentTokenType = null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
getTokenAtCursor(text, cursorPos) {
|
|
258
|
+
const beforeCursor = text.slice(0, cursorPos);
|
|
259
|
+
const match = beforeCursor.match(/[@#][^\s]*$/);
|
|
260
|
+
return match ? match[0] : null;
|
|
261
|
+
}
|
|
262
|
+
getWordAtPosition(text, position) {
|
|
263
|
+
const left = text.slice(0, position).search(/[@#][^\s]*$/);
|
|
264
|
+
if (left === -1)
|
|
265
|
+
return '';
|
|
266
|
+
return text.slice(left, position);
|
|
267
|
+
}
|
|
268
|
+
selectSuggestion(suggestion) {
|
|
269
|
+
const input = this.newComment;
|
|
270
|
+
const wordStart = input.slice(0, this.cursorPosition).search(/[@#][^\s]*$/);
|
|
271
|
+
this.newComment = input.slice(0, wordStart) + suggestion.value + ' ' + input.slice(this.cursorPosition);
|
|
272
|
+
this.isMentioning = false;
|
|
273
|
+
this.isHashtagging = false;
|
|
274
|
+
}
|
|
275
|
+
onSuggestionSelect(item) {
|
|
276
|
+
const input = this.newComment;
|
|
277
|
+
const beforeCursor = input.slice(0, this.cursorPosition);
|
|
278
|
+
const afterCursor = input.slice(this.cursorPosition);
|
|
279
|
+
const lastTokenIndex = Math.max(beforeCursor.lastIndexOf('@'), beforeCursor.lastIndexOf('#'));
|
|
280
|
+
if (lastTokenIndex >= 0) {
|
|
281
|
+
// Insert the suggestion at the cursor position
|
|
282
|
+
this.newComment = beforeCursor.slice(0, lastTokenIndex) + item.id + ' ' + afterCursor;
|
|
283
|
+
}
|
|
284
|
+
this.suggestionPanel.nativeElement.style.display = 'none';
|
|
285
|
+
this.overlayVisible = false;
|
|
286
|
+
this.currentTokenType = null;
|
|
287
|
+
this.filteredSuggestions = [];
|
|
288
|
+
this.selectedSuggestionIndex = -1;
|
|
289
|
+
setTimeout(() => {
|
|
290
|
+
const inputEl = this.inputText.nativeElement.querySelector('input');
|
|
291
|
+
if (inputEl) {
|
|
292
|
+
inputEl.focus();
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
onSuggestionPanelHide() {
|
|
297
|
+
this.overlayVisible = false;
|
|
298
|
+
this.currentTokenType = null;
|
|
299
|
+
this.filteredSuggestions = [];
|
|
300
|
+
this.selectedSuggestionIndex = -1;
|
|
301
|
+
}
|
|
302
|
+
getCursorPosition(input) {
|
|
303
|
+
const selectionStart = input.selectionStart || 0;
|
|
304
|
+
const textBeforeCursor = input.value.substring(0, selectionStart);
|
|
305
|
+
const span = document.createElement('span');
|
|
306
|
+
span.textContent = textBeforeCursor;
|
|
307
|
+
span.style.cssText = window.getComputedStyle(input, null).cssText;
|
|
308
|
+
span.style.visibility = 'hidden';
|
|
309
|
+
document.body.appendChild(span);
|
|
310
|
+
const position = {
|
|
311
|
+
left: span.offsetWidth,
|
|
312
|
+
top: span.offsetHeight
|
|
313
|
+
};
|
|
314
|
+
document.body.removeChild(span);
|
|
315
|
+
return position;
|
|
316
|
+
}
|
|
317
|
+
onFileIconClick(event) {
|
|
318
|
+
event?.preventDefault();
|
|
319
|
+
event?.stopPropagation();
|
|
320
|
+
if (this.fileInput?.nativeElement) {
|
|
321
|
+
this.fileInput.nativeElement.click();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
onFileSelect(event) {
|
|
325
|
+
const input = event.target;
|
|
326
|
+
if (input.files && input.files.length > 0) {
|
|
327
|
+
Array.from(input.files).forEach((file) => {
|
|
328
|
+
// Check if file already exists in selection
|
|
329
|
+
const fileExists = this.selectedFiles.some((existingFile) => existingFile.name === file.name && existingFile.size === this.formatFileSize(file.size));
|
|
330
|
+
if (!fileExists) {
|
|
331
|
+
const fileInfo = {
|
|
332
|
+
name: file.name,
|
|
333
|
+
size: this.formatFileSize(file.size)
|
|
334
|
+
};
|
|
335
|
+
this.selectedFiles.push(fileInfo);
|
|
336
|
+
this.selectedFilesMap.set(this.selectedFiles.length - 1, fileInfo);
|
|
337
|
+
this.fileSelected.emit(file);
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
input.value = '';
|
|
341
|
+
const inputEl = document.querySelector('.chat-input input');
|
|
342
|
+
if (inputEl instanceof HTMLElement) {
|
|
343
|
+
inputEl.focus();
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
updateFileState(index, fromChip = true) {
|
|
348
|
+
const actualIndex = fromChip ? index : index + 4;
|
|
349
|
+
this.selectedFiles = this.selectedFiles.filter((_, i) => i !== actualIndex);
|
|
350
|
+
this.selectedFilesMap.clear();
|
|
351
|
+
this.selectedFiles.forEach((file, i) => {
|
|
352
|
+
this.selectedFilesMap.set(i, file);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
removeFile(index, fromChip = true) {
|
|
356
|
+
this.updateFileState(index, fromChip);
|
|
357
|
+
if (this.selectedFiles.length <= 4) {
|
|
358
|
+
this.hideFilesOverlay();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
getOverflowCount() {
|
|
362
|
+
// Return count of files beyond the first 4
|
|
363
|
+
return Math.max(0, this.selectedFiles.length - 4);
|
|
364
|
+
}
|
|
365
|
+
showFilesOverlay(event) {
|
|
366
|
+
const target = event.currentTarget;
|
|
367
|
+
const rect = target.getBoundingClientRect();
|
|
368
|
+
// Position the overlay below the count chip
|
|
369
|
+
this.overlayPosition = {
|
|
370
|
+
top: rect.bottom + 5,
|
|
371
|
+
left: rect.left - 250 + rect.width / 2 // Center the overlay horizontally
|
|
372
|
+
};
|
|
373
|
+
this.filesOverlayVisible = true;
|
|
374
|
+
// Add a click outside listener to close the overlay
|
|
375
|
+
setTimeout(() => {
|
|
376
|
+
document.addEventListener('click', this.handleClickOutside);
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
hideFilesOverlay() {
|
|
380
|
+
this.filesOverlayVisible = false;
|
|
381
|
+
document.removeEventListener('click', this.handleClickOutside);
|
|
382
|
+
}
|
|
383
|
+
handleClickOutside = (event) => {
|
|
384
|
+
const target = event.target;
|
|
385
|
+
const overlay = document.querySelector('.files-overlay');
|
|
386
|
+
const countChip = document.querySelector('.count-chip');
|
|
387
|
+
if (overlay && !overlay.contains(target) && countChip && !countChip.contains(target)) {
|
|
388
|
+
this.hideFilesOverlay();
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
formatFileSize(bytes) {
|
|
392
|
+
if (bytes === 0)
|
|
393
|
+
return '0 Bytes';
|
|
394
|
+
const k = 1024;
|
|
395
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
396
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
397
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
398
|
+
}
|
|
399
|
+
showSuggestions(_event, type) {
|
|
400
|
+
this.currentTokenType = type;
|
|
401
|
+
this.filteredSuggestions = type === 'mention' ? this.mentionSuggestions : this.hashtagSuggestions;
|
|
402
|
+
if (this.suggestionPanel) {
|
|
403
|
+
this.suggestionPanel.nativeElement.style.display = 'block';
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
onKeyDown(event) {
|
|
407
|
+
// If suggestions are visible, handle keyboard navigation
|
|
408
|
+
if (this.overlayVisible && this.filteredSuggestions.length > 0) {
|
|
409
|
+
switch (event.key) {
|
|
410
|
+
case 'ArrowDown':
|
|
411
|
+
event.preventDefault();
|
|
412
|
+
this.selectedSuggestionIndex = Math.min(this.selectedSuggestionIndex + 1, this.filteredSuggestions.length - 1);
|
|
413
|
+
this.scrollSuggestionIntoView();
|
|
414
|
+
break;
|
|
415
|
+
case 'ArrowUp':
|
|
416
|
+
event.preventDefault();
|
|
417
|
+
this.selectedSuggestionIndex = Math.max(this.selectedSuggestionIndex - 1, 0);
|
|
418
|
+
this.scrollSuggestionIntoView();
|
|
419
|
+
break;
|
|
420
|
+
case 'Tab':
|
|
421
|
+
event.preventDefault();
|
|
422
|
+
if (event.shiftKey) {
|
|
423
|
+
// Shift+Tab - move up
|
|
424
|
+
this.selectedSuggestionIndex = Math.max(this.selectedSuggestionIndex - 1, 0);
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
// Tab - move down
|
|
428
|
+
this.selectedSuggestionIndex = Math.min(this.selectedSuggestionIndex + 1, this.filteredSuggestions.length - 1);
|
|
429
|
+
}
|
|
430
|
+
this.scrollSuggestionIntoView();
|
|
431
|
+
break;
|
|
432
|
+
case 'Enter':
|
|
433
|
+
event.preventDefault();
|
|
434
|
+
if (this.selectedSuggestionIndex >= 0) {
|
|
435
|
+
this.onSuggestionSelect(this.filteredSuggestions[this.selectedSuggestionIndex]);
|
|
436
|
+
}
|
|
437
|
+
break;
|
|
438
|
+
case 'Escape':
|
|
439
|
+
event.preventDefault();
|
|
440
|
+
this.onSuggestionPanelHide();
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
// If no suggestions are visible, handle normal enter key press
|
|
446
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
447
|
+
event.preventDefault();
|
|
448
|
+
this.addComment();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
// Helper method to scroll the selected suggestion into view
|
|
452
|
+
scrollSuggestionIntoView() {
|
|
453
|
+
setTimeout(() => {
|
|
454
|
+
const suggestionList = this.suggestionPanel?.nativeElement.querySelector('.suggestion-list');
|
|
455
|
+
const selectedItem = suggestionList?.querySelector('.suggestion-item.selected');
|
|
456
|
+
if (suggestionList && selectedItem) {
|
|
457
|
+
const listRect = suggestionList.getBoundingClientRect();
|
|
458
|
+
const itemRect = selectedItem.getBoundingClientRect();
|
|
459
|
+
// Check if the selected item is outside the visible area
|
|
460
|
+
if (itemRect.bottom > listRect.bottom) {
|
|
461
|
+
// Item is below the visible area
|
|
462
|
+
selectedItem.scrollIntoView({ block: 'end', behavior: 'smooth' });
|
|
463
|
+
}
|
|
464
|
+
else if (itemRect.top < listRect.top) {
|
|
465
|
+
// Item is above the visible area
|
|
466
|
+
selectedItem.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
onFileDownload(file) {
|
|
472
|
+
this.fileDownload.emit(file);
|
|
473
|
+
}
|
|
474
|
+
get groupedComments() {
|
|
475
|
+
return this.comments
|
|
476
|
+
.reduce((groups, comment) => {
|
|
477
|
+
const commentDate = new Date(comment.date);
|
|
478
|
+
commentDate.setHours(0, 0, 0, 0);
|
|
479
|
+
const existingGroup = groups.find((group) => {
|
|
480
|
+
const groupDate = new Date(group.date);
|
|
481
|
+
groupDate.setHours(0, 0, 0, 0);
|
|
482
|
+
return groupDate.getTime() === commentDate.getTime();
|
|
483
|
+
});
|
|
484
|
+
if (existingGroup) {
|
|
485
|
+
existingGroup.items.push(comment);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
groups.push({
|
|
489
|
+
date: commentDate,
|
|
490
|
+
items: [comment]
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
return groups;
|
|
494
|
+
}, [])
|
|
495
|
+
.sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
496
|
+
}
|
|
497
|
+
getShortFileName(filename) {
|
|
498
|
+
if (filename.length <= 4)
|
|
499
|
+
return filename;
|
|
500
|
+
// Get file extension
|
|
501
|
+
const lastDotIndex = filename.lastIndexOf('.');
|
|
502
|
+
const extension = lastDotIndex !== -1 ? filename.substring(lastDotIndex) : '';
|
|
503
|
+
// Truncate the name part and add the extension
|
|
504
|
+
const namePart = filename.substring(0, lastDotIndex !== -1 ? lastDotIndex : filename.length);
|
|
505
|
+
return namePart.substring(0, 4) + '..' + extension;
|
|
506
|
+
}
|
|
507
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxComponent, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
|
|
508
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: CommentboxComponent, selector: "cax-comments", inputs: { comments: "comments", mentionSuggestions: "mentionSuggestions", hashtagSuggestions: "hashtagSuggestions", sidebarHeader: "sidebarHeader", isAdmin: "isAdmin", visible: "visible" }, outputs: { commentAdded: "commentAdded", fileSelected: "fileSelected", fileDownload: "fileDownload", visibleChange: "visibleChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "suggestionPanel", first: true, predicate: ["suggestionPanel"], descendants: true }, { propertyName: "inputText", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "commentsList", first: true, predicate: ["commentsList"], descendants: true }, { propertyName: "countChip", first: true, predicate: ["countChip"], descendants: true }], ngImport: i0, template: "<cax-sidebar [(visible)]=\"visible\" [position]=\"'right'\" [baseZIndex]=\"10000\" (onHide)=\"onSidebarHide()\" [headerText]=\"sidebarHeader\">\r\n <ng-template caxTemplate=\"content\">\r\n <div class=\"cax-comments-container\">\r\n <div class=\"cax-comments-list\" #commentsList>\r\n <ng-container *ngFor=\"let group of groupedComments\">\r\n <div class=\"cax-date-header\">{{ formatDate(group.date) }}</div>\r\n <div\r\n class=\"cax-comment-item\"\r\n *ngFor=\"let comment of group.items; let i = index\"\r\n [ngClass]=\"{\r\n 'cax-user-comment': !comment.isAdmin,\r\n 'cax-admin-comment': comment.isAdmin,\r\n 'consecutive-message': i > 0 && comment.isAdmin === group.items[i-1].isAdmin && comment.sender === group.items[i-1].sender,\r\n 'new-sender': i > 0 && comment.sender !== group.items[i-1].sender,\r\n 'new-date': i === 0 && group.items.length > 0\r\n }\"\r\n >\r\n <!-- User Message (Left Aligned) -->\r\n <ng-container *ngIf=\"!comment.isAdmin\">\r\n <div class=\"cax-commentbox-avatar-container\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">\r\n <cax-avatar [label]=\"comment.sender?.substring(0, 2).toUpperCase() || 'U'\" [avatarSize]=\"'xs'\" [shape]=\"'circle'\" styleclass=\"cax-commentbox-avatar\"> </cax-avatar>\r\n </div>\r\n <div class=\"cax-comment-content\" [class.no-avatar]=\"i > 0 && group.items[i-1].sender === comment.sender\">\r\n <div class=\"cax-comment-sender\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">{{comment.sender}}</div>\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Admin Message (Right Aligned) -->\r\n <ng-container *ngIf=\"comment.isAdmin\">\r\n <div class=\"cax-comment-content admin\">\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <cax-overlay #suggestionPanel [(visible)]=\"overlayVisible\" [appendTo]=\"inputText\" (onHide)=\"onSuggestionPanelHide()\" [styleClass]=\"'suggestion-panel'\">\r\n <div class=\"suggestion-list\">\r\n <div *ngFor=\"let item of filteredSuggestions; let i = index\" class=\"suggestion-item\" [ngClass]=\"{'selected': selectedSuggestionIndex === i}\" (click)=\"onSuggestionSelect(item)\" (mouseenter)=\"selectedSuggestionIndex = i\">\r\n <span class=\"suggestion-label\">{{item.name}}</span>\r\n <small class=\"suggestion-id\" *ngIf=\"currentTokenType === 'mention'\">{{item.id}}</small>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n <cax-overlay\r\n [(visible)]=\"filesOverlayVisible\"\r\n [appendTo]=\"countChip\"\r\n [showTransitionOptions]=\"'0.12s ease-out'\"\r\n [hideTransitionOptions]=\"'0.1s ease-in'\"\r\n [style]=\"{ width: '224px', right: '5%' }\"\r\n styleClass=\"files-list-overlay\"\r\n (onHide)=\"hideFilesOverlay()\"\r\n >\r\n <div class=\"files-overlay-content\">\r\n <div *ngFor=\"let file of selectedFiles.slice(4); let i = index\" class=\"file-item\">\r\n <span class=\"file-name\">{{getShortFileName(file.name)}}</span>\r\n <i class=\"cax cax-close-circle\" (click)=\"removeFile(i + 4)\"></i>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n\r\n <ng-template caxTemplate=\"footer\">\r\n <div class=\"chat-footer\">\r\n <div class=\"selected-files\" *ngIf=\"selectedFiles.length > 0\">\r\n <cax-chip *ngFor=\"let file of selectedFiles.slice(0, 4); let i = index\" [label]=\"getShortFileName(file.name)\" [removable]=\"true\" [size]=\"'lg'\" (onRemove)=\"removeFile(i, true)\">\r\n <ng-template caxTemplate=\"content\">\r\n <i class=\"cax cax-paperclip\"></i>\r\n </ng-template>\r\n </cax-chip>\r\n <cax-chip #countChip *ngIf=\"selectedFiles.length > 4\" [label]=\"'+' + getOverflowCount()\" [size]=\"'lg'\" (mouseenter)=\"showFilesOverlay($event)\"> </cax-chip>\r\n </div>\r\n <div class=\"cax-chat-input-container\">\r\n <div class=\"input-wrapper\">\r\n <cax-inputtext\r\n [(ngModel)]=\"newComment\"\r\n [size]=\"'lg'\"\r\n [rightIcon]=\"true\"\r\n [clearIcon]=\"false\"\r\n [rightIconClass]=\"'cax cax-paperclip'\"\r\n [rightIconClickable]=\"true\"\r\n (rightIconClick)=\"onFileIconClick($event)\"\r\n placeholder=\"Comment or mention others with @, \u2018#\u2019 for columns\"\r\n (keyup)=\"handleKeyUp($event)\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [class]=\"{'chat-input': true, 'admin-input': isAdminSender}\"\r\n [style]=\"{'border-radius': '8px', background: '#ffffff'}\"\r\n #inputText\r\n >\r\n </cax-inputtext>\r\n </div>\r\n\r\n <cax-button [icon]=\"'cax cax-plain'\" [severity]=\"'primary'\" [size]=\"'large'\" (click)=\"addComment()\" [disabled]=\"!newComment.trim() && selectedFiles.length === 0\" class=\"send-button\"> </cax-button>\r\n </div>\r\n\r\n <input #fileInput type=\"file\" (change)=\"onFileSelect($event)\" style=\"display: none\" accept=\"*/*\" multiple />\r\n </div>\r\n </ng-template>\r\n</cax-sidebar>\r\n", styles: ["@layer cax{.cax-comments-list{display:flex;flex-direction:column;gap:4px;flex:1;overflow-y:auto;overflow-x:hidden;height:100%;padding-bottom:0;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}.cax-comments-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}.cax-comments-list::-webkit-scrollbar-track{background:transparent}.cax-comments-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}.cax-comment-item{display:flex;align-items:flex-end;max-width:85%;gap:4px}.cax-comment-item.consecutive-message{margin-top:0}.cax-comment-item.new-sender{margin-top:12px}.cax-comment-item.new-date{margin-top:0}.cax-user-comment{align-self:flex-start;display:flex;flex-direction:row;text-align:left}.cax-user-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-user-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 12px 0}.cax-user-comment .cax-comment-content.no-avatar{border-radius:12px;margin-left:25px}.cax-user-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-user-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-admin-comment{align-self:flex-end;display:flex;flex-direction:row;justify-content:flex-end;text-align:right}.cax-admin-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-admin-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 0;text-align:left}.cax-admin-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-admin-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-commentbox-avatar{width:32px;height:32px;border-radius:50%;margin:0 8px}.cax-comment-content{background:var(--white-100);border-radius:12px 12px 12px 0;padding:8px;max-width:100%;word-wrap:break-word;display:flex;flex-direction:column;box-shadow:0 2px 4px #0000000d}.cax-comment-content .cax-comment-text{font-weight:400;font-size:14px;line-height:20px}.cax-comment-content .cax-comment-text ::ng-deep .mention{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-text ::ng-deep .hashtag{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-file-attachment{margin-bottom:12px}.cax-file-attachment .file-item{display:flex;align-items:center;gap:12px;border-color:1px solid var(--neutral-150);padding:10px 16px;background:var(--neutral-75);border-radius:8px;cursor:pointer;margin-bottom:8px}.cax-file-attachment .file-item .file-details{display:flex;flex:1;align-items:center;gap:12px}.cax-file-attachment .file-item .file-name{color:var(--neutral-900);font-weight:500;font-size:14px;line-height:20px;flex:1;white-space:nowrap;overflow:hidden}.cax-file-attachment .file-item .file-size{color:var(--neutral-600);font-weight:400;font-size:12px;line-height:18px;margin-right:8px}.cax-file-attachment .file-item i{color:var(--neutral-900);font-size:1.1rem;margin-left:auto;order:2}.cax-file-attachment .file-item i.cax-download{cursor:pointer;transition:color .2s ease}.cax-file-attachment .file-item i.cax-download:hover{color:var(--primary-600)}.cax-file-attachment .file-item i.cax-download:active{color:var(--primary-700)}.cax-file-attachment .file-item:last-child{margin-bottom:0}.cax-file-attachment:last-child{margin-bottom:0}.cax-comment-date{font-weight:400;font-size:12px;line-height:18px;color:var(--neutral-600);align-self:flex-end}.cax-chat-input-container{display:flex;gap:.5rem}.cax-chat-input-container .chat-input{flex:1}.cax-chat-input-container .send-button{cursor:pointer}.input-wrapper{position:relative;flex:1;display:flex;flex-direction:column}.cax-date-header{text-align:center;font-size:12px;font-weight:500;line-height:18px;color:var(--neutral-700);background:var(--neutral-100);align-self:center;width:fit-content;padding:4px 12px;border-radius:4px;margin:11px 0;position:relative;z-index:1}.cax-date-header:first-child{margin-top:0}.cax-comments-container{display:flex;flex-direction:column;height:calc(100vh - 200px);overflow:hidden;position:relative;transform:translateZ(0);backface-visibility:hidden}.selected-files{display:flex;flex-wrap:wrap;gap:.5rem;padding:0 0 5px;position:relative}.selected-files .cax-chip{background:var(--neutral-100)}.selected-files .cax-chip i{margin-right:.5rem}.selected-files .files-overlay{position:absolute;background:var(--white-100);border-radius:8px;box-shadow:0 4px 12px #00000026;width:300px;max-height:400px;z-index:1000;overflow:hidden;border:1px solid var(--neutral-200)}.selected-files .files-overlay .files-overlay-header{padding:12px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--neutral-100);background:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content{max-height:350px;overflow-y:auto;padding:8px 0}.selected-files .files-overlay .files-overlay-content .file-item{display:flex;align-items:center;padding:8px 16px;transition:background-color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content .file-item i.cax-paperclip{color:var(--neutral-600);margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;transition:color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times:hover{color:var --error-500}.selected-files :deep(.file-chip){background:var(--neutral-50);border:1px solid var(--neutral-100)}.selected-files :deep(.file-chip) .file-details{display:flex;align-items:center;gap:8px}.selected-files :deep(.file-chip) i{color:var(--primary-500);margin-right:8px}.selected-files :deep(.file-chip) .file-name{font-weight:500}.selected-files :deep(.file-chip) .file-size{color:var(--neutral-600);font-size:.8rem}:host ::ng-deep .cax-sidebar{width:589px!important;border:1px solid var(--neutral-200)!important}:host ::ng-deep .cax-sidebar .cax-sidebar-content{display:flex;flex-direction:column;background:var(--neutral-25);padding:24px 8px!important}:host ::ng-deep .cax-sidebar .cax-sidebar-footer{padding:12px!important;background:var(--neutral-50);border-top:1px solid var(--neutral-200)}:host ::ng-deep .cax-sidebar .cax-sidebar-header{border-bottom:1px solid var(--neutral-200);background:var(--neutral-50);padding:16px 24px!important}:host ::ng-deep .cax-overlay{position:absolute;bottom:0!important;top:unset!important;left:unset!important}:host ::ng-deep .suggestion-panel{background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;margin-left:20px;width:224px;border-radius:8px;border:1px solid var(--neutral-200)}:host ::ng-deep .suggestion-panel .suggestion-list{max-height:200px;overflow-y:auto;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item{padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;transition:background-color .2s ease;align-items:center}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item.selected{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-label{font-weight:500}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-id{color:var(--neutral-600);font-size:.85em}:host ::ng-deep .suggestion-panel .suggestion-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}:host ::ng-deep .chat-footer{position:relative;z-index:1}:host ::ng-deep .cax-chat-input-container .chat-input .cax-paperclip{color:var(--neutral-900)!important}:host ::ng-deep .files-list-overlay{border:1px solid var(--neutral-200);background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;width:224px;border-radius:8px}:host ::ng-deep .files-list-overlay.cax-overlay{transform-origin:right center!important}:host ::ng-deep .files-list-overlay .files-overlay-content{max-height:200px;overflow-y:auto}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item{transition:background-color .2s ease;padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;font-weight:500;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;border:1.1rem solid var(--neutral-200);transition:color .2s ease}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.Sidebar, selector: "cax-sidebar", inputs: ["headerText", "appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "contentTemplate", "headerTemplate", "headlessTemplate", "footerTemplate", "closeIconTemplate", "headerStyle"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "component", type: i5.InputTextComponent, selector: "cax-inputtext", inputs: ["value", "placeholder", "disabled", "maxlength", "successText", "errorText", "showLabel", "leftIcon", "rightIcon", "rightIconClickable", "clearIcon", "label", "iconPath", "disabledIcon", "showIcon", "iconClass", "leftIconClass", "rightIconClass", "invalid", "required", "style", "size", "styleClass"], outputs: ["valueChange", "rightIconClick"] }, { kind: "component", type: i6.Button, selector: "cax-button", inputs: ["type", "iconPos", "icon", "badge", "rightIcon", "leftIcon", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i7.CaxTemplate, selector: "[caxTemplate]", inputs: ["type", "caxTemplate"] }, { kind: "component", type: i8.Chip, selector: "cax-chip", inputs: ["label", "icon", "image", "alt", "style", "styleClass", "removable", "removeIcon", "size", "severity"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: i9.Overlay, selector: "cax-overlay", inputs: ["visible", "mode", "style", "styleClass", "contentStyle", "contentStyleClass", "target", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "listener", "responsive", "options"], outputs: ["visibleChange", "onBeforeShow", "onShow", "onBeforeHide", "onHide", "onAnimationStart", "onAnimationDone"] }, { kind: "component", type: i10.Avatar, selector: "cax-avatar", inputs: ["label", "icon", "image", "avatarSize", "shape", "style", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
|
|
509
|
+
}
|
|
510
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxComponent, decorators: [{
|
|
511
|
+
type: Component,
|
|
512
|
+
args: [{ selector: 'cax-comments', template: "<cax-sidebar [(visible)]=\"visible\" [position]=\"'right'\" [baseZIndex]=\"10000\" (onHide)=\"onSidebarHide()\" [headerText]=\"sidebarHeader\">\r\n <ng-template caxTemplate=\"content\">\r\n <div class=\"cax-comments-container\">\r\n <div class=\"cax-comments-list\" #commentsList>\r\n <ng-container *ngFor=\"let group of groupedComments\">\r\n <div class=\"cax-date-header\">{{ formatDate(group.date) }}</div>\r\n <div\r\n class=\"cax-comment-item\"\r\n *ngFor=\"let comment of group.items; let i = index\"\r\n [ngClass]=\"{\r\n 'cax-user-comment': !comment.isAdmin,\r\n 'cax-admin-comment': comment.isAdmin,\r\n 'consecutive-message': i > 0 && comment.isAdmin === group.items[i-1].isAdmin && comment.sender === group.items[i-1].sender,\r\n 'new-sender': i > 0 && comment.sender !== group.items[i-1].sender,\r\n 'new-date': i === 0 && group.items.length > 0\r\n }\"\r\n >\r\n <!-- User Message (Left Aligned) -->\r\n <ng-container *ngIf=\"!comment.isAdmin\">\r\n <div class=\"cax-commentbox-avatar-container\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">\r\n <cax-avatar [label]=\"comment.sender?.substring(0, 2).toUpperCase() || 'U'\" [avatarSize]=\"'xs'\" [shape]=\"'circle'\" styleclass=\"cax-commentbox-avatar\"> </cax-avatar>\r\n </div>\r\n <div class=\"cax-comment-content\" [class.no-avatar]=\"i > 0 && group.items[i-1].sender === comment.sender\">\r\n <div class=\"cax-comment-sender\" *ngIf=\"i === 0 || group.items[i-1].sender !== comment.sender\">{{comment.sender}}</div>\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Admin Message (Right Aligned) -->\r\n <ng-container *ngIf=\"comment.isAdmin\">\r\n <div class=\"cax-comment-content admin\">\r\n <div class=\"cax-file-attachment\" *ngIf=\"comment.files?.length\">\r\n <div *ngFor=\"let file of comment.files\" class=\"file-item\">\r\n <div class=\"file-details\">\r\n <span class=\"file-name\">{{ file.name.slice(0, 20) }}{{ file.name.includes('.') ? '.' + file.name.split('.').pop() : '' }}</span>\r\n <span class=\"file-size\">{{file.size}}</span>\r\n </div>\r\n <i class=\"cax cax-download\" (click)=\"onFileDownload(file)\" role=\"button\" tabindex=\"0\"></i>\r\n </div>\r\n </div>\r\n <div class=\"cax-comment-text\" [innerHTML]=\"formatMessageWithTags(comment.text)\"></div>\r\n <span class=\"cax-comment-date\">{{ comment.date | date: 'shortTime' }}</span>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <cax-overlay #suggestionPanel [(visible)]=\"overlayVisible\" [appendTo]=\"inputText\" (onHide)=\"onSuggestionPanelHide()\" [styleClass]=\"'suggestion-panel'\">\r\n <div class=\"suggestion-list\">\r\n <div *ngFor=\"let item of filteredSuggestions; let i = index\" class=\"suggestion-item\" [ngClass]=\"{'selected': selectedSuggestionIndex === i}\" (click)=\"onSuggestionSelect(item)\" (mouseenter)=\"selectedSuggestionIndex = i\">\r\n <span class=\"suggestion-label\">{{item.name}}</span>\r\n <small class=\"suggestion-id\" *ngIf=\"currentTokenType === 'mention'\">{{item.id}}</small>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n <cax-overlay\r\n [(visible)]=\"filesOverlayVisible\"\r\n [appendTo]=\"countChip\"\r\n [showTransitionOptions]=\"'0.12s ease-out'\"\r\n [hideTransitionOptions]=\"'0.1s ease-in'\"\r\n [style]=\"{ width: '224px', right: '5%' }\"\r\n styleClass=\"files-list-overlay\"\r\n (onHide)=\"hideFilesOverlay()\"\r\n >\r\n <div class=\"files-overlay-content\">\r\n <div *ngFor=\"let file of selectedFiles.slice(4); let i = index\" class=\"file-item\">\r\n <span class=\"file-name\">{{getShortFileName(file.name)}}</span>\r\n <i class=\"cax cax-close-circle\" (click)=\"removeFile(i + 4)\"></i>\r\n </div>\r\n </div>\r\n </cax-overlay>\r\n\r\n <ng-template caxTemplate=\"footer\">\r\n <div class=\"chat-footer\">\r\n <div class=\"selected-files\" *ngIf=\"selectedFiles.length > 0\">\r\n <cax-chip *ngFor=\"let file of selectedFiles.slice(0, 4); let i = index\" [label]=\"getShortFileName(file.name)\" [removable]=\"true\" [size]=\"'lg'\" (onRemove)=\"removeFile(i, true)\">\r\n <ng-template caxTemplate=\"content\">\r\n <i class=\"cax cax-paperclip\"></i>\r\n </ng-template>\r\n </cax-chip>\r\n <cax-chip #countChip *ngIf=\"selectedFiles.length > 4\" [label]=\"'+' + getOverflowCount()\" [size]=\"'lg'\" (mouseenter)=\"showFilesOverlay($event)\"> </cax-chip>\r\n </div>\r\n <div class=\"cax-chat-input-container\">\r\n <div class=\"input-wrapper\">\r\n <cax-inputtext\r\n [(ngModel)]=\"newComment\"\r\n [size]=\"'lg'\"\r\n [rightIcon]=\"true\"\r\n [clearIcon]=\"false\"\r\n [rightIconClass]=\"'cax cax-paperclip'\"\r\n [rightIconClickable]=\"true\"\r\n (rightIconClick)=\"onFileIconClick($event)\"\r\n placeholder=\"Comment or mention others with @, \u2018#\u2019 for columns\"\r\n (keyup)=\"handleKeyUp($event)\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [class]=\"{'chat-input': true, 'admin-input': isAdminSender}\"\r\n [style]=\"{'border-radius': '8px', background: '#ffffff'}\"\r\n #inputText\r\n >\r\n </cax-inputtext>\r\n </div>\r\n\r\n <cax-button [icon]=\"'cax cax-plain'\" [severity]=\"'primary'\" [size]=\"'large'\" (click)=\"addComment()\" [disabled]=\"!newComment.trim() && selectedFiles.length === 0\" class=\"send-button\"> </cax-button>\r\n </div>\r\n\r\n <input #fileInput type=\"file\" (change)=\"onFileSelect($event)\" style=\"display: none\" accept=\"*/*\" multiple />\r\n </div>\r\n </ng-template>\r\n</cax-sidebar>\r\n", styles: ["@layer cax{.cax-comments-list{display:flex;flex-direction:column;gap:4px;flex:1;overflow-y:auto;overflow-x:hidden;height:100%;padding-bottom:0;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}.cax-comments-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}.cax-comments-list::-webkit-scrollbar-track{background:transparent}.cax-comments-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}.cax-comment-item{display:flex;align-items:flex-end;max-width:85%;gap:4px}.cax-comment-item.consecutive-message{margin-top:0}.cax-comment-item.new-sender{margin-top:12px}.cax-comment-item.new-date{margin-top:0}.cax-user-comment{align-self:flex-start;display:flex;flex-direction:row;text-align:left}.cax-user-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-user-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 12px 0}.cax-user-comment .cax-comment-content.no-avatar{border-radius:12px;margin-left:25px}.cax-user-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-user-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-admin-comment{align-self:flex-end;display:flex;flex-direction:row;justify-content:flex-end;text-align:right}.cax-admin-comment .cax-commentbox-avatar-container{display:flex;align-items:flex-end}.cax-admin-comment .cax-comment-content{margin-bottom:0;display:flex;flex-direction:column;border-radius:12px 12px 0;text-align:left}.cax-admin-comment .cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-admin-comment.consecutive-message .cax-comment-content{border-radius:12px}.cax-commentbox-avatar{width:32px;height:32px;border-radius:50%;margin:0 8px}.cax-comment-content{background:var(--white-100);border-radius:12px 12px 12px 0;padding:8px;max-width:100%;word-wrap:break-word;display:flex;flex-direction:column;box-shadow:0 2px 4px #0000000d}.cax-comment-content .cax-comment-text{font-weight:400;font-size:14px;line-height:20px}.cax-comment-content .cax-comment-text ::ng-deep .mention{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-text ::ng-deep .hashtag{display:inline-block;font-weight:600;color:var(--primary-500)}.cax-comment-content .cax-comment-sender{font-size:14px;font-weight:600;color:var(--neutral-900);margin-bottom:0;line-height:20px}.cax-file-attachment{margin-bottom:12px}.cax-file-attachment .file-item{display:flex;align-items:center;gap:12px;border-color:1px solid var(--neutral-150);padding:10px 16px;background:var(--neutral-75);border-radius:8px;cursor:pointer;margin-bottom:8px}.cax-file-attachment .file-item .file-details{display:flex;flex:1;align-items:center;gap:12px}.cax-file-attachment .file-item .file-name{color:var(--neutral-900);font-weight:500;font-size:14px;line-height:20px;flex:1;white-space:nowrap;overflow:hidden}.cax-file-attachment .file-item .file-size{color:var(--neutral-600);font-weight:400;font-size:12px;line-height:18px;margin-right:8px}.cax-file-attachment .file-item i{color:var(--neutral-900);font-size:1.1rem;margin-left:auto;order:2}.cax-file-attachment .file-item i.cax-download{cursor:pointer;transition:color .2s ease}.cax-file-attachment .file-item i.cax-download:hover{color:var(--primary-600)}.cax-file-attachment .file-item i.cax-download:active{color:var(--primary-700)}.cax-file-attachment .file-item:last-child{margin-bottom:0}.cax-file-attachment:last-child{margin-bottom:0}.cax-comment-date{font-weight:400;font-size:12px;line-height:18px;color:var(--neutral-600);align-self:flex-end}.cax-chat-input-container{display:flex;gap:.5rem}.cax-chat-input-container .chat-input{flex:1}.cax-chat-input-container .send-button{cursor:pointer}.input-wrapper{position:relative;flex:1;display:flex;flex-direction:column}.cax-date-header{text-align:center;font-size:12px;font-weight:500;line-height:18px;color:var(--neutral-700);background:var(--neutral-100);align-self:center;width:fit-content;padding:4px 12px;border-radius:4px;margin:11px 0;position:relative;z-index:1}.cax-date-header:first-child{margin-top:0}.cax-comments-container{display:flex;flex-direction:column;height:calc(100vh - 200px);overflow:hidden;position:relative;transform:translateZ(0);backface-visibility:hidden}.selected-files{display:flex;flex-wrap:wrap;gap:.5rem;padding:0 0 5px;position:relative}.selected-files .cax-chip{background:var(--neutral-100)}.selected-files .cax-chip i{margin-right:.5rem}.selected-files .files-overlay{position:absolute;background:var(--white-100);border-radius:8px;box-shadow:0 4px 12px #00000026;width:300px;max-height:400px;z-index:1000;overflow:hidden;border:1px solid var(--neutral-200)}.selected-files .files-overlay .files-overlay-header{padding:12px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--neutral-100);background:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content{max-height:350px;overflow-y:auto;padding:8px 0}.selected-files .files-overlay .files-overlay-content .file-item{display:flex;align-items:center;padding:8px 16px;transition:background-color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}.selected-files .files-overlay .files-overlay-content .file-item i.cax-paperclip{color:var(--neutral-600);margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;transition:color .2s ease}.selected-files .files-overlay .files-overlay-content .file-item i.cax-times:hover{color:var --error-500}.selected-files :deep(.file-chip){background:var(--neutral-50);border:1px solid var(--neutral-100)}.selected-files :deep(.file-chip) .file-details{display:flex;align-items:center;gap:8px}.selected-files :deep(.file-chip) i{color:var(--primary-500);margin-right:8px}.selected-files :deep(.file-chip) .file-name{font-weight:500}.selected-files :deep(.file-chip) .file-size{color:var(--neutral-600);font-size:.8rem}:host ::ng-deep .cax-sidebar{width:589px!important;border:1px solid var(--neutral-200)!important}:host ::ng-deep .cax-sidebar .cax-sidebar-content{display:flex;flex-direction:column;background:var(--neutral-25);padding:24px 8px!important}:host ::ng-deep .cax-sidebar .cax-sidebar-footer{padding:12px!important;background:var(--neutral-50);border-top:1px solid var(--neutral-200)}:host ::ng-deep .cax-sidebar .cax-sidebar-header{border-bottom:1px solid var(--neutral-200);background:var(--neutral-50);padding:16px 24px!important}:host ::ng-deep .cax-overlay{position:absolute;bottom:0!important;top:unset!important;left:unset!important}:host ::ng-deep .suggestion-panel{background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;margin-left:20px;width:224px;border-radius:8px;border:1px solid var(--neutral-200)}:host ::ng-deep .suggestion-panel .suggestion-list{max-height:200px;overflow-y:auto;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item{padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;transition:background-color .2s ease;align-items:center}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item.selected{background-color:var(--neutral-50)}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-label{font-weight:500}:host ::ng-deep .suggestion-panel .suggestion-list .suggestion-item .suggestion-id{color:var(--neutral-600);font-size:.85em}:host ::ng-deep .suggestion-panel .suggestion-list:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .suggestion-panel .suggestion-list::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}:host ::ng-deep .chat-footer{position:relative;z-index:1}:host ::ng-deep .cax-chat-input-container .chat-input .cax-paperclip{color:var(--neutral-900)!important}:host ::ng-deep .files-list-overlay{border:1px solid var(--neutral-200);background:var(--white-100);box-shadow:0 2px 8px #0000001a;z-index:9999;padding:12px 4px;width:224px;border-radius:8px}:host ::ng-deep .files-list-overlay.cax-overlay{transform-origin:right center!important}:host ::ng-deep .files-list-overlay .files-overlay-content{max-height:200px;overflow-y:auto}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item{transition:background-color .2s ease;padding:6px 8px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;will-change:transform;transform:translateZ(0);backface-visibility:hidden;-webkit-backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:rgba(94,92,92,.3) transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:hover{background-color:var(--neutral-50)}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-name{flex:1;font-size:14px;font-weight:500;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item .file-size{color:var(--neutral-600);font-size:12px;margin-right:8px}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item i.cax-times{color:var(--neutral-600);cursor:pointer;border:1.1rem solid var(--neutral-200);transition:color .2s ease}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item:after{content:\"\";display:block;min-height:20px;scroll-snap-align:end}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-track{background:transparent}:host ::ng-deep .files-list-overlay .files-overlay-content .file-item::-webkit-scrollbar-thumb{background-color:#5553531a;border-radius:4px;border:2px solid transparent;background-clip:padding-box}}\n"] }]
|
|
513
|
+
}], ctorParameters: () => [{ type: i1.DomSanitizer }], propDecorators: { comments: [{
|
|
514
|
+
type: Input
|
|
515
|
+
}], mentionSuggestions: [{
|
|
516
|
+
type: Input
|
|
517
|
+
}], hashtagSuggestions: [{
|
|
518
|
+
type: Input
|
|
519
|
+
}], sidebarHeader: [{
|
|
520
|
+
type: Input
|
|
521
|
+
}], isAdmin: [{
|
|
522
|
+
type: Input
|
|
523
|
+
}], commentAdded: [{
|
|
524
|
+
type: Output
|
|
525
|
+
}], fileSelected: [{
|
|
526
|
+
type: Output
|
|
527
|
+
}], fileDownload: [{
|
|
528
|
+
type: Output
|
|
529
|
+
}], visibleChange: [{
|
|
530
|
+
type: Output
|
|
531
|
+
}], fileInput: [{
|
|
532
|
+
type: ViewChild,
|
|
533
|
+
args: ['fileInput']
|
|
534
|
+
}], suggestionPanel: [{
|
|
535
|
+
type: ViewChild,
|
|
536
|
+
args: ['suggestionPanel']
|
|
537
|
+
}], inputText: [{
|
|
538
|
+
type: ViewChild,
|
|
539
|
+
args: ['inputText']
|
|
540
|
+
}], commentsList: [{
|
|
541
|
+
type: ViewChild,
|
|
542
|
+
args: ['commentsList']
|
|
543
|
+
}], countChip: [{
|
|
544
|
+
type: ViewChild,
|
|
545
|
+
args: ['countChip']
|
|
546
|
+
}], visible: [{
|
|
547
|
+
type: Input
|
|
548
|
+
}], onDocumentClick: [{
|
|
549
|
+
type: HostListener,
|
|
550
|
+
args: ['document:click', ['$event']]
|
|
551
|
+
}] } });
|
|
552
|
+
|
|
553
|
+
class CommentboxModule {
|
|
554
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
555
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: CommentboxModule, declarations: [CommentboxComponent], imports: [CommonModule, FormsModule, Sidebar, InputTextModule, ButtonModule, ChipModule, OverlayModule, AvatarModule, RippleModule, SharedModule], exports: [CommentboxComponent] });
|
|
556
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxModule, imports: [CommonModule, FormsModule, Sidebar, InputTextModule, ButtonModule, ChipModule, OverlayModule, AvatarModule, RippleModule, SharedModule] });
|
|
557
|
+
}
|
|
558
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CommentboxModule, decorators: [{
|
|
559
|
+
type: NgModule,
|
|
560
|
+
args: [{
|
|
561
|
+
declarations: [CommentboxComponent],
|
|
562
|
+
imports: [CommonModule, FormsModule, Sidebar, InputTextModule, ButtonModule, ChipModule, OverlayModule, AvatarModule, RippleModule, SharedModule],
|
|
563
|
+
exports: [CommentboxComponent]
|
|
564
|
+
}]
|
|
565
|
+
}] });
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Generated bundle index. Do not edit.
|
|
569
|
+
*/
|
|
570
|
+
|
|
571
|
+
export { CommentboxComponent, CommentboxModule };
|
|
572
|
+
//# sourceMappingURL=cax-design-system-commentbox.mjs.map
|