@memberjunction/ng-composer 6.2.0-edge.0 → 6.2.0-edge.2

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.
@@ -71,12 +71,52 @@ function MentionEditorComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
71
71
  export class MentionEditorComponent {
72
72
  cdr;
73
73
  hostRef;
74
- editorRef;
75
- placeholder = 'Type @ to mention agents or users, # for entities...';
76
- disabled = false;
77
- currentUser;
74
+ EditorRef;
75
+ /** @deprecated Use {@link EditorRef}. */
76
+ get editorRef() {
77
+ return this.EditorRef;
78
+ }
79
+ /** @deprecated Use {@link EditorRef}. */
80
+ set editorRef(value) {
81
+ this.EditorRef = value;
82
+ }
83
+ Placeholder = 'Type @ to mention agents or users, # for entities...';
84
+ /** @deprecated Use {@link Placeholder}. */
85
+ set placeholder(value) {
86
+ this.Placeholder = value;
87
+ }
88
+ /** @deprecated Use {@link Placeholder}. */
89
+ get placeholder() {
90
+ return this.Placeholder;
91
+ }
92
+ Disabled = false;
93
+ /** @deprecated Use {@link Disabled}. */
94
+ set disabled(value) {
95
+ this.Disabled = value;
96
+ }
97
+ /** @deprecated Use {@link Disabled}. */
98
+ get disabled() {
99
+ return this.Disabled;
100
+ }
101
+ CurrentUser;
102
+ /** @deprecated Use {@link CurrentUser}. */
103
+ set currentUser(value) {
104
+ this.CurrentUser = value;
105
+ }
106
+ /** @deprecated Use {@link CurrentUser}. */
107
+ get currentUser() {
108
+ return this.CurrentUser;
109
+ }
78
110
  /** Master switch for all mention/command triggers. When false no providers are consulted. */
79
- enableMentions = true;
111
+ EnableMentions = true;
112
+ /** @deprecated Use {@link EnableMentions}. */
113
+ set enableMentions(value) {
114
+ this.EnableMentions = value;
115
+ }
116
+ /** @deprecated Use {@link EnableMentions}. */
117
+ get enableMentions() {
118
+ return this.EnableMentions;
119
+ }
80
120
  /**
81
121
  * Explicit trigger-provider list — when bound, EXACTLY these providers are active
82
122
  * (explicit list wins over discovery). Leave null to discover providers registered
@@ -91,30 +131,182 @@ export class MentionEditorComponent {
91
131
  /** Optional metadata provider scoping this editor (multi-provider hosts); passed through to trigger providers. */
92
132
  Provider = null;
93
133
  /** Auto-focus the editor after view init (the composer default). Disable when embedded in forms. */
94
- autoFocus = true;
134
+ AutoFocus = true;
135
+ /** @deprecated Use {@link AutoFocus}. */
136
+ set autoFocus(value) {
137
+ this.AutoFocus = value;
138
+ }
139
+ /** @deprecated Use {@link AutoFocus}. */
140
+ get autoFocus() {
141
+ return this.AutoFocus;
142
+ }
95
143
  // Attachment settings
96
- enableAttachments = true;
97
- maxAttachments = 10;
98
- maxAttachmentSizeBytes = 20 * 1024 * 1024; // 20MB default
99
- acceptedFileTypes = 'image/*'; // MIME types to accept
100
- valueChange = new EventEmitter();
101
- mentionSelected = new EventEmitter();
102
- enterPressed = new EventEmitter();
103
- attachmentsChanged = new EventEmitter();
104
- attachmentError = new EventEmitter();
105
- attachmentClicked = new EventEmitter();
144
+ EnableAttachments = true;
145
+ /** @deprecated Use {@link EnableAttachments}. */
146
+ set enableAttachments(value) {
147
+ this.EnableAttachments = value;
148
+ }
149
+ /** @deprecated Use {@link EnableAttachments}. */
150
+ get enableAttachments() {
151
+ return this.EnableAttachments;
152
+ }
153
+ MaxAttachments = 10;
154
+ /** @deprecated Use {@link MaxAttachments}. */
155
+ set maxAttachments(value) {
156
+ this.MaxAttachments = value;
157
+ }
158
+ /** @deprecated Use {@link MaxAttachments}. */
159
+ get maxAttachments() {
160
+ return this.MaxAttachments;
161
+ }
162
+ MaxAttachmentSizeBytes = 20 * 1024 * 1024;
163
+ /** @deprecated Use {@link MaxAttachmentSizeBytes}. */
164
+ set maxAttachmentSizeBytes(value) {
165
+ this.MaxAttachmentSizeBytes = value;
166
+ }
167
+ /** @deprecated Use {@link MaxAttachmentSizeBytes}. */
168
+ get maxAttachmentSizeBytes() {
169
+ return this.MaxAttachmentSizeBytes;
170
+ } // 20MB default
171
+ AcceptedFileTypes = 'image/*';
172
+ /** @deprecated Use {@link AcceptedFileTypes}. */
173
+ set acceptedFileTypes(value) {
174
+ this.AcceptedFileTypes = value;
175
+ }
176
+ /** @deprecated Use {@link AcceptedFileTypes}. */
177
+ get acceptedFileTypes() {
178
+ return this.AcceptedFileTypes;
179
+ } // MIME types to accept
180
+ ValueChange = new EventEmitter();
181
+ /**
182
+ * @deprecated Use {@link ValueChange}.
183
+ *
184
+ * The same emitter under the old binding name, so a template still binding
185
+ * (valueChange) keeps working. Must stay AFTER ValueChange: class fields
186
+ * initialise in order, and the other way round this captures undefined.
187
+ */
188
+ valueChange = this.ValueChange;
189
+ MentionSelected = new EventEmitter();
190
+ /**
191
+ * @deprecated Use {@link MentionSelected}.
192
+ *
193
+ * The same emitter under the old binding name, so a template still binding
194
+ * (mentionSelected) keeps working. Must stay AFTER MentionSelected: class fields
195
+ * initialise in order, and the other way round this captures undefined.
196
+ */
197
+ mentionSelected = this.MentionSelected;
198
+ EnterPressed = new EventEmitter();
199
+ /**
200
+ * @deprecated Use {@link EnterPressed}.
201
+ *
202
+ * The same emitter under the old binding name, so a template still binding
203
+ * (enterPressed) keeps working. Must stay AFTER EnterPressed: class fields
204
+ * initialise in order, and the other way round this captures undefined.
205
+ */
206
+ enterPressed = this.EnterPressed;
207
+ AttachmentsChanged = new EventEmitter();
208
+ /**
209
+ * @deprecated Use {@link AttachmentsChanged}.
210
+ *
211
+ * The same emitter under the old binding name, so a template still binding
212
+ * (attachmentsChanged) keeps working. Must stay AFTER AttachmentsChanged: class fields
213
+ * initialise in order, and the other way round this captures undefined.
214
+ */
215
+ attachmentsChanged = this.AttachmentsChanged;
216
+ AttachmentError = new EventEmitter();
217
+ /**
218
+ * @deprecated Use {@link AttachmentError}.
219
+ *
220
+ * The same emitter under the old binding name, so a template still binding
221
+ * (attachmentError) keeps working. Must stay AFTER AttachmentError: class fields
222
+ * initialise in order, and the other way round this captures undefined.
223
+ */
224
+ attachmentError = this.AttachmentError;
225
+ AttachmentClicked = new EventEmitter();
226
+ /**
227
+ * @deprecated Use {@link AttachmentClicked}.
228
+ *
229
+ * The same emitter under the old binding name, so a template still binding
230
+ * (attachmentClicked) keeps working. Must stay AFTER AttachmentClicked: class fields
231
+ * initialise in order, and the other way round this captures undefined.
232
+ */
233
+ attachmentClicked = this.AttachmentClicked;
106
234
  /** Fires when the contenteditable loses focus (hosts persist drafts on this). */
107
- editorBlurred = new EventEmitter();
235
+ EditorBlurred = new EventEmitter();
236
+ /**
237
+ * @deprecated Use {@link EditorBlurred}.
238
+ *
239
+ * The same emitter under the old binding name, so a template still binding
240
+ * (editorBlurred) keeps working. Must stay AFTER EditorBlurred: class fields
241
+ * initialise in order, and the other way round this captures undefined.
242
+ */
243
+ editorBlurred = this.EditorBlurred;
108
244
  // Pending attachments state
109
- pendingAttachments = [];
110
- isDragOver = false;
245
+ PendingAttachments = [];
246
+ /** @deprecated Use {@link PendingAttachments}. */
247
+ get pendingAttachments() {
248
+ return this.PendingAttachments;
249
+ }
250
+ /** @deprecated Use {@link PendingAttachments}. */
251
+ set pendingAttachments(value) {
252
+ this.PendingAttachments = value;
253
+ }
254
+ IsDragOver = false;
255
+ /** @deprecated Use {@link IsDragOver}. */
256
+ get isDragOver() {
257
+ return this.IsDragOver;
258
+ }
259
+ /** @deprecated Use {@link IsDragOver}. */
260
+ set isDragOver(value) {
261
+ this.IsDragOver = value;
262
+ }
111
263
  // Mention dropdown state
112
- showMentionDropdown = false;
113
- mentionSuggestions = [];
114
- mentionDropdownPosition = { top: 0, left: 0 };
115
- mentionDropdownShowAbove = false;
264
+ ShowMentionDropdown = false;
265
+ /** @deprecated Use {@link ShowMentionDropdown}. */
266
+ get showMentionDropdown() {
267
+ return this.ShowMentionDropdown;
268
+ }
269
+ /** @deprecated Use {@link ShowMentionDropdown}. */
270
+ set showMentionDropdown(value) {
271
+ this.ShowMentionDropdown = value;
272
+ }
273
+ MentionSuggestions = [];
274
+ /** @deprecated Use {@link MentionSuggestions}. */
275
+ get mentionSuggestions() {
276
+ return this.MentionSuggestions;
277
+ }
278
+ /** @deprecated Use {@link MentionSuggestions}. */
279
+ set mentionSuggestions(value) {
280
+ this.MentionSuggestions = value;
281
+ }
282
+ MentionDropdownPosition = { top: 0, left: 0 };
283
+ /** @deprecated Use {@link MentionDropdownPosition}. */
284
+ get mentionDropdownPosition() {
285
+ return this.MentionDropdownPosition;
286
+ }
287
+ /** @deprecated Use {@link MentionDropdownPosition}. */
288
+ set mentionDropdownPosition(value) {
289
+ this.MentionDropdownPosition = value;
290
+ }
291
+ MentionDropdownShowAbove = false;
292
+ /** @deprecated Use {@link MentionDropdownShowAbove}. */
293
+ get mentionDropdownShowAbove() {
294
+ return this.MentionDropdownShowAbove;
295
+ }
296
+ /** @deprecated Use {@link MentionDropdownShowAbove}. */
297
+ set mentionDropdownShowAbove(value) {
298
+ this.MentionDropdownShowAbove = value;
299
+ }
116
300
  /** Right-align the dropdown against its anchor. Only the button path sets this. */
117
- mentionDropdownAlignRight = false;
301
+ MentionDropdownAlignRight = false;
302
+ /** @deprecated Use {@link MentionDropdownAlignRight}. */
303
+ get mentionDropdownAlignRight() {
304
+ return this.MentionDropdownAlignRight;
305
+ }
306
+ /** @deprecated Use {@link MentionDropdownAlignRight}. */
307
+ set mentionDropdownAlignRight(value) {
308
+ this.MentionDropdownAlignRight = value;
309
+ }
118
310
  mentionStartIndex = -1;
119
311
  mentionQuery = '';
120
312
  /** The trigger char that opened the current mention dropdown */
@@ -145,7 +337,7 @@ export class MentionEditorComponent {
145
337
  */
146
338
  suggestionRequestSeq = 0;
147
339
  /** Cap on the suggestions displayed; passed to providers as `MaxResults`. */
148
- static MaxSuggestions = 50;
340
+ static maxSuggestions = 50;
149
341
  /**
150
342
  * The trigger providers this editor consults: the explicit `TriggerProviders` list
151
343
  * when bound, otherwise ClassFactory discovery filtered by `ExcludedTriggerKeys`.
@@ -153,7 +345,7 @@ export class MentionEditorComponent {
153
345
  * behaves as a plain text editor.
154
346
  */
155
347
  get activeProviders() {
156
- if (!this.enableMentions) {
348
+ if (!this.EnableMentions) {
157
349
  return [];
158
350
  }
159
351
  return this.TriggerProviders ?? DiscoverComposerTriggerProviders(this.ExcludedTriggerKeys);
@@ -169,7 +361,15 @@ export class MentionEditorComponent {
169
361
  return triggers;
170
362
  }
171
363
  onChange = () => { };
172
- onTouched = () => { };
364
+ OnTouched = () => { };
365
+ /** @deprecated Use {@link OnTouched}. */
366
+ get onTouched() {
367
+ return this.OnTouched;
368
+ }
369
+ /** @deprecated Use {@link OnTouched}. */
370
+ set onTouched(value) {
371
+ this.OnTouched = value;
372
+ }
173
373
  /** Value written via writeValue() before the view (editorRef) exists — applied in ngAfterViewInit. */
174
374
  pendingWriteValue = null;
175
375
  constructor(cdr, hostRef) {
@@ -196,21 +396,21 @@ export class MentionEditorComponent {
196
396
  // hundreds of ms, and without this the user's dismissing click is ignored and the menu pops
197
397
  // open afterwards, unbidden. closeMentionDropdown bumps the request sequence, which drops the
198
398
  // in-flight response.
199
- if (!this.showMentionDropdown && !this.virtualTriggerOpen) {
399
+ if (!this.ShowMentionDropdown && !this.virtualTriggerOpen) {
200
400
  return;
201
401
  }
202
402
  const target = event.target;
203
403
  if (target && this.hostRef.nativeElement.contains(target)) {
204
404
  return;
205
405
  }
206
- this.closeMentionDropdown();
406
+ this.CloseMentionDropdown();
207
407
  this.cdr.markForCheck();
208
408
  }
209
409
  async ngOnInit() {
210
410
  // Warm up the active providers (best-effort — a provider that fails to warm
211
411
  // simply serves its first real request cold).
212
- if (this.enableMentions) {
213
- const user = this.currentUser ?? null;
412
+ if (this.EnableMentions) {
413
+ const user = this.CurrentUser ?? null;
214
414
  await Promise.all(this.activeProviders.map((p) => p.Initialize(user).catch(() => undefined)));
215
415
  }
216
416
  }
@@ -222,18 +422,18 @@ export class MentionEditorComponent {
222
422
  this.pendingWriteValue = null;
223
423
  }
224
424
  // Auto-focus the editor
225
- if (this.autoFocus) {
425
+ if (this.AutoFocus) {
226
426
  setTimeout(() => {
227
- this.editorRef?.nativeElement?.focus();
427
+ this.EditorRef?.nativeElement?.focus();
228
428
  }, 100);
229
429
  }
230
430
  }
231
431
  /**
232
432
  * Handle clicks on the container - focus the editor if clicking outside the contentEditable
233
433
  */
234
- onContainerClick(event) {
434
+ OnContainerClick(event) {
235
435
  const target = event.target;
236
- const editor = this.editorRef?.nativeElement;
436
+ const editor = this.EditorRef?.nativeElement;
237
437
  // Don't handle clicks on the dropdown or its children
238
438
  if (target.closest('mj-mention-dropdown')) {
239
439
  return;
@@ -252,39 +452,51 @@ export class MentionEditorComponent {
252
452
  }
253
453
  }
254
454
  }
455
+ /** @deprecated Use {@link OnContainerClick}. */
456
+ onContainerClick(event) {
457
+ return this.OnContainerClick(event);
458
+ }
255
459
  /**
256
460
  * Handle input changes in contentEditable
257
461
  */
258
- onInput() {
462
+ OnInput() {
259
463
  const plainText = this.getPlainText();
260
464
  this.onChange(plainText);
261
- this.valueChange.emit(plainText);
465
+ this.ValueChange.emit(plainText);
262
466
  // Handle mention/command autocomplete via the active trigger providers
263
- if (this.enableMentions) {
467
+ if (this.EnableMentions) {
264
468
  this.handleMentionInput();
265
469
  }
266
470
  }
471
+ /** @deprecated Use {@link OnInput}. */
472
+ onInput() {
473
+ return this.OnInput();
474
+ }
267
475
  /**
268
476
  * Handle blur event - close dropdown when editor loses focus
269
477
  */
270
- onBlur() {
478
+ OnBlur() {
271
479
  // Call form control touched callback
272
- this.onTouched();
273
- this.editorBlurred.emit();
480
+ this.OnTouched();
481
+ this.EditorBlurred.emit();
274
482
  // Close dropdown when editor loses focus
275
483
  // Use setTimeout to allow mousedown events on dropdown to fire first
276
484
  setTimeout(() => {
277
- if (this.showMentionDropdown || this.virtualTriggerOpen) {
278
- this.closeMentionDropdown();
485
+ if (this.ShowMentionDropdown || this.virtualTriggerOpen) {
486
+ this.CloseMentionDropdown();
279
487
  }
280
488
  }, 200);
281
489
  }
490
+ /** @deprecated Use {@link OnBlur}. */
491
+ onBlur() {
492
+ return this.OnBlur();
493
+ }
282
494
  /**
283
495
  * Handle paste event - images or plain text
284
496
  */
285
- onPaste(event) {
497
+ OnPaste(event) {
286
498
  // Check for image data in clipboard
287
- if (this.enableAttachments && event.clipboardData?.items) {
499
+ if (this.EnableAttachments && event.clipboardData?.items) {
288
500
  const items = Array.from(event.clipboardData.items);
289
501
  const imageItems = items.filter(item => item.type.startsWith('image/'));
290
502
  if (imageItems.length > 0) {
@@ -320,24 +532,28 @@ export class MentionEditorComponent {
320
532
  selection.removeAllRanges();
321
533
  selection.addRange(range);
322
534
  // Trigger input event to update model
323
- this.onInput();
535
+ this.OnInput();
536
+ }
537
+ /** @deprecated Use {@link OnPaste}. */
538
+ onPaste(event) {
539
+ return this.OnPaste(event);
324
540
  }
325
541
  /**
326
542
  * Handle keydown events
327
543
  */
328
- onKeyDown(event) {
544
+ OnKeyDown(event) {
329
545
  // Enter alone: Send message. The dropdown only earns Enter when it has something to pick. A
330
546
  // button-opened menu stays open on an empty result set (so the press is not a silent no-op),
331
547
  // which made "showing but empty" reachable for the first time — and there Enter was neither
332
548
  // handled nor prevented, so it fell through to the contenteditable and inserted a newline
333
549
  // instead of sending.
334
- if (event.key === 'Enter' && !event.shiftKey && (!this.showMentionDropdown || this.mentionSuggestions.length === 0)) {
550
+ if (event.key === 'Enter' && !event.shiftKey && (!this.ShowMentionDropdown || this.MentionSuggestions.length === 0)) {
335
551
  event.preventDefault();
336
- if (this.showMentionDropdown) {
337
- this.closeMentionDropdown();
552
+ if (this.ShowMentionDropdown) {
553
+ this.CloseMentionDropdown();
338
554
  }
339
555
  const plainText = this.getPlainText();
340
- this.enterPressed.emit(plainText);
556
+ this.EnterPressed.emit(plainText);
341
557
  return;
342
558
  }
343
559
  // Backspace: Check if deleting a mention chip
@@ -345,11 +561,15 @@ export class MentionEditorComponent {
345
561
  this.handleBackspace(event);
346
562
  }
347
563
  // Handle mention dropdown navigation
348
- if (this.showMentionDropdown) {
564
+ if (this.ShowMentionDropdown) {
349
565
  // Let the dropdown handle arrow keys, enter, escape
350
566
  // (We'll pass these through to mention-dropdown component)
351
567
  }
352
568
  }
569
+ /** @deprecated Use {@link OnKeyDown}. */
570
+ onKeyDown(event) {
571
+ return this.OnKeyDown(event);
572
+ }
353
573
  /**
354
574
  * Handle mention/command trigger detection — finds the nearest active trigger char
355
575
  * before the cursor and kicks off the (async) provider suggestion fetch.
@@ -360,7 +580,7 @@ export class MentionEditorComponent {
360
580
  return;
361
581
  const activeTriggers = this.mentionTriggers;
362
582
  if (activeTriggers.length === 0) {
363
- this.closeMentionDropdown();
583
+ this.CloseMentionDropdown();
364
584
  return;
365
585
  }
366
586
  const range = selection.getRangeAt(0);
@@ -393,13 +613,13 @@ export class MentionEditorComponent {
393
613
  return;
394
614
  }
395
615
  }
396
- this.closeMentionDropdown();
616
+ this.CloseMentionDropdown();
397
617
  return;
398
618
  }
399
619
  // Check if there's a space between the trigger and cursor (means mention was completed)
400
620
  const textAfterTrigger = textBeforeCursor.substring(triggerIndex + 1);
401
621
  if (textAfterTrigger.includes(' ')) {
402
- this.closeMentionDropdown();
622
+ this.CloseMentionDropdown();
403
623
  return;
404
624
  }
405
625
  // A real trigger character now owns the session, so the virtual one must let go: otherwise
@@ -409,7 +629,7 @@ export class MentionEditorComponent {
409
629
  this.virtualTriggerOpen = false;
410
630
  this.virtualTriggerBaseline = 0;
411
631
  this.virtualTriggerAnchor = null;
412
- this.mentionDropdownAlignRight = false;
632
+ this.MentionDropdownAlignRight = false;
413
633
  }
414
634
  // Extract query
415
635
  this.mentionQuery = textAfterTrigger;
@@ -428,18 +648,18 @@ export class MentionEditorComponent {
428
648
  const providers = this.activeProviders.filter((p) => p.TriggerChar === triggerChar);
429
649
  const request = {
430
650
  Query: query,
431
- MaxResults: MentionEditorComponent.MaxSuggestions,
432
- ContextUser: this.currentUser ?? null,
651
+ MaxResults: MentionEditorComponent.maxSuggestions,
652
+ ContextUser: this.CurrentUser ?? null,
433
653
  Provider: this.Provider
434
654
  };
435
655
  const resultSets = await Promise.all(providers.map((p) => p.GetSuggestions(request).catch(() => [])));
436
656
  if (seq !== this.suggestionRequestSeq) {
437
657
  return; // superseded by a newer keystroke or an explicit close
438
658
  }
439
- const merged = resultSets.flat().slice(0, MentionEditorComponent.MaxSuggestions);
440
- this.mentionSuggestions = merged;
659
+ const merged = resultSets.flat().slice(0, MentionEditorComponent.maxSuggestions);
660
+ this.MentionSuggestions = merged;
441
661
  if (merged.length > 0) {
442
- this.showMentionDropdown = true;
662
+ this.ShowMentionDropdown = true;
443
663
  this.positionMentionDropdown();
444
664
  }
445
665
  else if (this.virtualTriggerOpen) {
@@ -447,11 +667,11 @@ export class MentionEditorComponent {
447
667
  // trigger (the user is mid-word and nothing matched yet), but a host with zero skills clicking
448
668
  // the button would get no feedback at all and read it as broken. Staying open surfaces the
449
669
  // dropdown's own empty state, which was otherwise unreachable.
450
- this.showMentionDropdown = true;
670
+ this.ShowMentionDropdown = true;
451
671
  this.positionMentionDropdown();
452
672
  }
453
673
  else {
454
- this.closeMentionDropdown();
674
+ this.CloseMentionDropdown();
455
675
  }
456
676
  this.cdr.detectChanges();
457
677
  }
@@ -460,7 +680,7 @@ export class MentionEditorComponent {
460
680
  */
461
681
  getTextBeforeCursor(range) {
462
682
  const tempRange = range.cloneRange();
463
- tempRange.selectNodeContents(this.editorRef.nativeElement);
683
+ tempRange.selectNodeContents(this.EditorRef.nativeElement);
464
684
  tempRange.setEnd(range.startContainer, range.startOffset);
465
685
  return tempRange.toString();
466
686
  }
@@ -468,7 +688,7 @@ export class MentionEditorComponent {
468
688
  * Position the mention dropdown
469
689
  */
470
690
  positionMentionDropdown() {
471
- const editor = this.editorRef?.nativeElement;
691
+ const editor = this.EditorRef?.nativeElement;
472
692
  if (!editor)
473
693
  return;
474
694
  // Get the parent container (message-input-box-container) for alignment
@@ -498,22 +718,22 @@ export class MentionEditorComponent {
498
718
  // Check space below vs above
499
719
  const spaceBelow = window.innerHeight - cursorRect.bottom;
500
720
  const spaceAbove = cursorRect.top;
501
- const dropdownHeight = Math.min(this.mentionSuggestions.length * 56, 300);
721
+ const dropdownHeight = Math.min(this.MentionSuggestions.length * 56, 300);
502
722
  // Prefer ABOVE. The composer sits at the bottom of the chat, so a dropdown that grows downward
503
723
  // lands on top of the very text being typed. Below is the fallback for the rare host that
504
724
  // mounts the composer high in a tall viewport.
505
- this.mentionDropdownAlignRight = false;
506
- this.mentionDropdownShowAbove = spaceAbove >= dropdownHeight || spaceAbove > spaceBelow;
507
- if (this.mentionDropdownShowAbove) {
725
+ this.MentionDropdownAlignRight = false;
726
+ this.MentionDropdownShowAbove = spaceAbove >= dropdownHeight || spaceAbove > spaceBelow;
727
+ if (this.MentionDropdownShowAbove) {
508
728
  // Position above, aligning with container top if possible
509
- this.mentionDropdownPosition = {
729
+ this.MentionDropdownPosition = {
510
730
  top: (containerRect ? containerRect.top : cursorRect.top) + window.scrollY - 8,
511
731
  left: cursorRect.left + window.scrollX
512
732
  };
513
733
  }
514
734
  else {
515
735
  // Position below cursor, but align bottom edge with container top
516
- this.mentionDropdownPosition = {
736
+ this.MentionDropdownPosition = {
517
737
  top: containerRect ? containerRect.top + window.scrollY : cursorRect.bottom + window.scrollY + 4,
518
738
  left: cursorRect.left + window.scrollX
519
739
  };
@@ -542,7 +762,7 @@ export class MentionEditorComponent {
542
762
  // which is what a menu anchored to a right-hand control needs.
543
763
  const assumedWidth = Math.min(400, window.innerWidth - GUTTER * 2);
544
764
  const overflowsRight = rect.left + assumedWidth > window.innerWidth - GUTTER;
545
- this.mentionDropdownAlignRight = overflowsRight;
765
+ this.MentionDropdownAlignRight = overflowsRight;
546
766
  // align-right shifts the box back by its own width, so `left` is then its RIGHT edge; otherwise
547
767
  // `left` is its left edge. Clamp both forms inside the gutter.
548
768
  //
@@ -562,14 +782,14 @@ export class MentionEditorComponent {
562
782
  // Not unconditional: `show-above` lifts the box by its own height, so forcing it where there is
563
783
  // no room renders it off the top of the viewport where it cannot be reached.
564
784
  const anchorTop = containerRect ? containerRect.top : rect.top;
565
- const dropdownHeight = Math.min(Math.max(this.mentionSuggestions.length, 1) * 56, 300);
785
+ const dropdownHeight = Math.min(Math.max(this.MentionSuggestions.length, 1) * 56, 300);
566
786
  // Prefer above, but when it does not fit, take whichever side has MORE room rather than
567
787
  // dropping below unconditionally — the composer is bottom-docked, so below is usually the worse
568
788
  // side. In a short viewport (a popped-out chat, or mobile with the keyboard up) that difference
569
789
  // is the whole menu versus a clipped sliver.
570
790
  const spaceBelow = window.innerHeight - rect.bottom;
571
791
  const showAbove = anchorTop >= dropdownHeight + GUTTER || anchorTop > spaceBelow;
572
- this.mentionDropdownShowAbove = showAbove;
792
+ this.MentionDropdownShowAbove = showAbove;
573
793
  // Above: `top` is the box's BOTTOM edge (the transform lifts it). Below: it is the top edge.
574
794
  // Clamped either way, because dropdownHeight is an estimate (rows with descriptions run taller
575
795
  // than 56px) and an underestimate would otherwise clip the first row off the top of the screen.
@@ -577,20 +797,24 @@ export class MentionEditorComponent {
577
797
  const top = showAbove
578
798
  ? Math.max(GUTTER + dropdownHeight, Math.min(rawTop, window.innerHeight - GUTTER))
579
799
  : Math.max(GUTTER, Math.min(rawTop, window.innerHeight - GUTTER - dropdownHeight));
580
- this.mentionDropdownPosition = { top, left };
800
+ this.MentionDropdownPosition = { top, left };
581
801
  }
582
802
  /**
583
803
  * Handle mention selection from dropdown
584
804
  */
585
- onMentionSelected(suggestion) {
805
+ OnMentionSelected(suggestion) {
586
806
  this.insertMentionChip(suggestion);
587
- this.closeMentionDropdown();
588
- this.mentionSelected.emit(suggestion);
807
+ this.CloseMentionDropdown();
808
+ this.MentionSelected.emit(suggestion);
589
809
  // Refocus the editor after selection
590
810
  setTimeout(() => {
591
- this.editorRef?.nativeElement?.focus();
811
+ this.EditorRef?.nativeElement?.focus();
592
812
  }, 50);
593
813
  }
814
+ /** @deprecated Use {@link OnMentionSelected}. */
815
+ onMentionSelected(suggestion) {
816
+ return this.OnMentionSelected(suggestion);
817
+ }
594
818
  /**
595
819
  * Insert a mention chip at the current cursor position
596
820
  */
@@ -606,7 +830,7 @@ export class MentionEditorComponent {
606
830
  */
607
831
  /** Focuses the editor and places the caret at the very end of its content. */
608
832
  FocusCaretAtEnd() {
609
- const editor = this.editorRef?.nativeElement;
833
+ const editor = this.EditorRef?.nativeElement;
610
834
  if (!editor) {
611
835
  return false;
612
836
  }
@@ -637,8 +861,8 @@ export class MentionEditorComponent {
637
861
  * @returns false when the editor is disabled, unavailable, or no active provider owns the char.
638
862
  */
639
863
  OpenTrigger(triggerChar, anchorEl) {
640
- const editor = this.editorRef?.nativeElement;
641
- if (!editor || this.disabled) {
864
+ const editor = this.EditorRef?.nativeElement;
865
+ if (!editor || this.Disabled) {
642
866
  return false;
643
867
  }
644
868
  if (!this.mentionTriggers.includes(triggerChar)) {
@@ -674,15 +898,15 @@ export class MentionEditorComponent {
674
898
  // virtualTriggerOpen covers the window between the press and the provider's response. Reporting
675
899
  // "closed" there makes the second press of a quick double-click re-run the open path instead of
676
900
  // toggling, re-emitting the Before/After pair.
677
- return (this.showMentionDropdown || this.virtualTriggerOpen) && this.activeTrigger === triggerChar;
901
+ return (this.ShowMentionDropdown || this.virtualTriggerOpen) && this.activeTrigger === triggerChar;
678
902
  }
679
903
  /** True when keyboard focus currently sits inside this editor. */
680
904
  get HasFocus() {
681
- const editor = this.editorRef?.nativeElement;
905
+ const editor = this.EditorRef?.nativeElement;
682
906
  return !!editor && (editor === document.activeElement || editor.contains(document.activeElement));
683
907
  }
684
908
  InsertMention(suggestion, focus = true) {
685
- const editor = this.editorRef?.nativeElement;
909
+ const editor = this.EditorRef?.nativeElement;
686
910
  if (!editor) {
687
911
  return false;
688
912
  }
@@ -708,7 +932,7 @@ export class MentionEditorComponent {
708
932
  if (!focus) {
709
933
  editor.blur();
710
934
  }
711
- this.onInput();
935
+ this.OnInput();
712
936
  return true;
713
937
  }
714
938
  insertMentionChip(suggestion) {
@@ -741,7 +965,7 @@ export class MentionEditorComponent {
741
965
  selection.removeAllRanges();
742
966
  selection.addRange(range);
743
967
  // Trigger change detection
744
- this.onInput();
968
+ this.OnInput();
745
969
  }
746
970
  /**
747
971
  * Create a mention chip DOM element
@@ -1082,33 +1306,37 @@ export class MentionEditorComponent {
1082
1306
  if (prevNode && prevNode.classList?.contains('mention-chip')) {
1083
1307
  event.preventDefault();
1084
1308
  prevNode.remove();
1085
- this.onInput();
1309
+ this.OnInput();
1086
1310
  }
1087
1311
  }
1088
1312
  }
1089
1313
  /**
1090
1314
  * Close mention dropdown
1091
1315
  */
1092
- closeMentionDropdown() {
1316
+ CloseMentionDropdown() {
1093
1317
  // No text cleanup: a virtual trigger never wrote anything into the editor, which is the whole
1094
1318
  // point of it. Dismissing leaves the message exactly as the user left it.
1095
1319
  this.virtualTriggerOpen = false;
1096
1320
  this.virtualTriggerBaseline = 0;
1097
1321
  this.virtualTriggerAnchor = null;
1098
- this.mentionDropdownAlignRight = false;
1322
+ this.MentionDropdownAlignRight = false;
1099
1323
  // Invalidate any in-flight suggestion fetch so a late response can't reopen the dropdown
1100
1324
  this.suggestionRequestSeq++;
1101
- this.showMentionDropdown = false;
1102
- this.mentionSuggestions = [];
1325
+ this.ShowMentionDropdown = false;
1326
+ this.MentionSuggestions = [];
1103
1327
  this.mentionStartIndex = -1;
1104
1328
  this.mentionQuery = '';
1105
1329
  this.activeTrigger = '@';
1106
1330
  }
1331
+ /** @deprecated Use {@link CloseMentionDropdown}. */
1332
+ closeMentionDropdown() {
1333
+ return this.CloseMentionDropdown();
1334
+ }
1107
1335
  /**
1108
1336
  * Convert editor HTML to plain text with @mentions
1109
1337
  */
1110
1338
  getPlainText() {
1111
- const editor = this.editorRef?.nativeElement;
1339
+ const editor = this.EditorRef?.nativeElement;
1112
1340
  if (!editor)
1113
1341
  return '';
1114
1342
  let text = '';
@@ -1180,7 +1408,7 @@ export class MentionEditorComponent {
1180
1408
  * strings (no tokens) take the fast path.
1181
1409
  */
1182
1410
  setEditorContent(text) {
1183
- const editor = this.editorRef?.nativeElement;
1411
+ const editor = this.EditorRef?.nativeElement;
1184
1412
  if (!editor)
1185
1413
  return;
1186
1414
  const segments = MentionEditorComponent.ParseSerializedMentions(text);
@@ -1290,7 +1518,7 @@ export class MentionEditorComponent {
1290
1518
  }
1291
1519
  // ControlValueAccessor implementation
1292
1520
  writeValue(value) {
1293
- const editor = this.editorRef?.nativeElement;
1521
+ const editor = this.EditorRef?.nativeElement;
1294
1522
  if (!editor) {
1295
1523
  // View not created yet — buffer the value; ngAfterViewInit applies it
1296
1524
  this.pendingWriteValue = value ?? '';
@@ -1307,36 +1535,44 @@ export class MentionEditorComponent {
1307
1535
  this.onChange = fn;
1308
1536
  }
1309
1537
  registerOnTouched(fn) {
1310
- this.onTouched = fn;
1538
+ this.OnTouched = fn;
1311
1539
  }
1312
1540
  setDisabledState(isDisabled) {
1313
- this.disabled = isDisabled;
1314
- if (this.editorRef?.nativeElement) {
1315
- this.editorRef.nativeElement.contentEditable = (!isDisabled).toString();
1541
+ this.Disabled = isDisabled;
1542
+ if (this.EditorRef?.nativeElement) {
1543
+ this.EditorRef.nativeElement.contentEditable = (!isDisabled).toString();
1316
1544
  }
1317
1545
  }
1318
1546
  /**
1319
1547
  * Focus the editor
1320
1548
  */
1549
+ Focus() {
1550
+ this.EditorRef?.nativeElement?.focus();
1551
+ }
1552
+ /** @deprecated Use {@link Focus}. */
1321
1553
  focus() {
1322
- this.editorRef?.nativeElement?.focus();
1554
+ return this.Focus();
1323
1555
  }
1324
1556
  /**
1325
1557
  * Clear the editor content and pending attachments
1326
1558
  */
1327
- clear() {
1328
- if (this.editorRef?.nativeElement) {
1329
- this.editorRef.nativeElement.textContent = '';
1330
- this.onInput();
1559
+ Clear() {
1560
+ if (this.EditorRef?.nativeElement) {
1561
+ this.EditorRef.nativeElement.textContent = '';
1562
+ this.OnInput();
1331
1563
  }
1332
- this.clearPendingAttachments();
1564
+ this.ClearPendingAttachments();
1565
+ }
1566
+ /** @deprecated Use {@link Clear}. */
1567
+ clear() {
1568
+ return this.Clear();
1333
1569
  }
1334
1570
  /**
1335
1571
  * Extract mention chips with their configuration data
1336
1572
  * Returns array of objects containing mention info and preset configuration
1337
1573
  */
1338
- getMentionChipsData() {
1339
- const editor = this.editorRef?.nativeElement;
1574
+ GetMentionChipsData() {
1575
+ const editor = this.EditorRef?.nativeElement;
1340
1576
  if (!editor)
1341
1577
  return [];
1342
1578
  const chips = [];
@@ -1358,13 +1594,17 @@ export class MentionEditorComponent {
1358
1594
  });
1359
1595
  return chips;
1360
1596
  }
1597
+ /** @deprecated Use {@link GetMentionChipsData}. */
1598
+ getMentionChipsData() {
1599
+ return this.GetMentionChipsData();
1600
+ }
1361
1601
  /**
1362
1602
  * Get the plain text value with mentions encoded as JSON
1363
1603
  * This format preserves configuration information when messages are saved
1364
1604
  * Format: @{type:"agent",id:"uuid",name:"Agent Name",configId:"uuid",config:"High"}
1365
1605
  */
1366
- getPlainTextWithJsonMentions() {
1367
- const editor = this.editorRef?.nativeElement;
1606
+ GetPlainTextWithJsonMentions() {
1607
+ const editor = this.EditorRef?.nativeElement;
1368
1608
  if (!editor)
1369
1609
  return '';
1370
1610
  let plainText = '';
@@ -1413,34 +1653,46 @@ export class MentionEditorComponent {
1413
1653
  }
1414
1654
  return plainText;
1415
1655
  }
1656
+ /** @deprecated Use {@link GetPlainTextWithJsonMentions}. */
1657
+ getPlainTextWithJsonMentions() {
1658
+ return this.GetPlainTextWithJsonMentions();
1659
+ }
1416
1660
  // ==================== Attachment Handling Methods ====================
1417
1661
  /**
1418
1662
  * Handle drag over event
1419
1663
  */
1420
- onDragOver(event) {
1421
- if (!this.enableAttachments)
1664
+ OnDragOver(event) {
1665
+ if (this.Disabled || !this.EnableAttachments)
1422
1666
  return;
1423
1667
  event.preventDefault();
1424
1668
  event.stopPropagation();
1425
- this.isDragOver = true;
1669
+ this.IsDragOver = true;
1670
+ }
1671
+ /** @deprecated Use {@link OnDragOver}. */
1672
+ onDragOver(event) {
1673
+ return this.OnDragOver(event);
1426
1674
  }
1427
1675
  /**
1428
1676
  * Handle drag leave event
1429
1677
  */
1430
- onDragLeave(event) {
1678
+ OnDragLeave(event) {
1431
1679
  event.preventDefault();
1432
1680
  event.stopPropagation();
1433
- this.isDragOver = false;
1681
+ this.IsDragOver = false;
1682
+ }
1683
+ /** @deprecated Use {@link OnDragLeave}. */
1684
+ onDragLeave(event) {
1685
+ return this.OnDragLeave(event);
1434
1686
  }
1435
1687
  /**
1436
1688
  * Handle drop event
1437
1689
  */
1438
- onDrop(event) {
1439
- if (!this.enableAttachments)
1690
+ OnDrop(event) {
1691
+ if (this.Disabled || !this.EnableAttachments)
1440
1692
  return;
1441
1693
  event.preventDefault();
1442
1694
  event.stopPropagation();
1443
- this.isDragOver = false;
1695
+ this.IsDragOver = false;
1444
1696
  if (event.dataTransfer?.files) {
1445
1697
  const files = Array.from(event.dataTransfer.files);
1446
1698
  for (const file of files) {
@@ -1450,10 +1702,14 @@ export class MentionEditorComponent {
1450
1702
  }
1451
1703
  }
1452
1704
  }
1705
+ /** @deprecated Use {@link OnDrop}. */
1706
+ onDrop(event) {
1707
+ return this.OnDrop(event);
1708
+ }
1453
1709
  /**
1454
1710
  * Handle file input change (from file picker)
1455
1711
  */
1456
- onFileSelected(event) {
1712
+ OnFileSelected(event) {
1457
1713
  const input = event.target;
1458
1714
  if (input.files) {
1459
1715
  const files = Array.from(input.files);
@@ -1464,6 +1720,10 @@ export class MentionEditorComponent {
1464
1720
  input.value = '';
1465
1721
  }
1466
1722
  }
1723
+ /** @deprecated Use {@link OnFileSelected}. */
1724
+ onFileSelected(event) {
1725
+ return this.OnFileSelected(event);
1726
+ }
1467
1727
  /**
1468
1728
  * Process a file for attachment
1469
1729
  */
@@ -1471,13 +1731,13 @@ export class MentionEditorComponent {
1471
1731
  // Validate file
1472
1732
  const validation = this.validateFile(file);
1473
1733
  if (!validation.valid) {
1474
- this.attachmentError.emit(validation.error);
1734
+ this.AttachmentError.emit(validation.error);
1475
1735
  return;
1476
1736
  }
1477
1737
  // Read file as data URL
1478
1738
  const dataUrl = await this.readFileAsDataUrl(file);
1479
1739
  if (!dataUrl) {
1480
- this.attachmentError.emit('Failed to read file');
1740
+ this.AttachmentError.emit('Failed to read file');
1481
1741
  return;
1482
1742
  }
1483
1743
  // Get image dimensions if applicable
@@ -1501,8 +1761,8 @@ export class MentionEditorComponent {
1501
1761
  thumbnailUrl: file.type.startsWith('image/') ? dataUrl : undefined
1502
1762
  };
1503
1763
  // Add to pending attachments
1504
- this.pendingAttachments.push(attachment);
1505
- this.attachmentsChanged.emit([...this.pendingAttachments]);
1764
+ this.PendingAttachments.push(attachment);
1765
+ this.AttachmentsChanged.emit([...this.PendingAttachments]);
1506
1766
  this.cdr.detectChanges();
1507
1767
  }
1508
1768
  /**
@@ -1510,15 +1770,15 @@ export class MentionEditorComponent {
1510
1770
  */
1511
1771
  validateFile(file) {
1512
1772
  // Check count limit
1513
- if (this.pendingAttachments.length >= this.maxAttachments) {
1773
+ if (this.PendingAttachments.length >= this.MaxAttachments) {
1514
1774
  return {
1515
1775
  valid: false,
1516
- error: `Maximum ${this.maxAttachments} attachments allowed`
1776
+ error: `Maximum ${this.MaxAttachments} attachments allowed`
1517
1777
  };
1518
1778
  }
1519
1779
  // Check size limit
1520
- if (file.size > this.maxAttachmentSizeBytes) {
1521
- const maxMB = (this.maxAttachmentSizeBytes / (1024 * 1024)).toFixed(1);
1780
+ if (file.size > this.MaxAttachmentSizeBytes) {
1781
+ const maxMB = (this.MaxAttachmentSizeBytes / (1024 * 1024)).toFixed(1);
1522
1782
  const fileMB = (file.size / (1024 * 1024)).toFixed(1);
1523
1783
  return {
1524
1784
  valid: false,
@@ -1538,10 +1798,10 @@ export class MentionEditorComponent {
1538
1798
  * Check if file type is accepted
1539
1799
  */
1540
1800
  isAcceptedFile(file) {
1541
- if (this.acceptedFileTypes === '*' || this.acceptedFileTypes === '*/*') {
1801
+ if (this.AcceptedFileTypes === '*' || this.AcceptedFileTypes === '*/*') {
1542
1802
  return true;
1543
1803
  }
1544
- const acceptedTypes = this.acceptedFileTypes.split(',').map(t => t.trim());
1804
+ const acceptedTypes = this.AcceptedFileTypes.split(',').map(t => t.trim());
1545
1805
  for (const accepted of acceptedTypes) {
1546
1806
  // Handle universal wildcard */* anywhere in the list
1547
1807
  if (accepted === '*/*') {
@@ -1602,19 +1862,27 @@ export class MentionEditorComponent {
1602
1862
  /**
1603
1863
  * Remove a pending attachment by ID
1604
1864
  */
1605
- removeAttachment(id) {
1606
- const index = this.pendingAttachments.findIndex(a => a.id === id);
1865
+ RemoveAttachment(id) {
1866
+ const index = this.PendingAttachments.findIndex(a => a.id === id);
1607
1867
  if (index !== -1) {
1608
- this.pendingAttachments.splice(index, 1);
1609
- this.attachmentsChanged.emit([...this.pendingAttachments]);
1868
+ this.PendingAttachments.splice(index, 1);
1869
+ this.AttachmentsChanged.emit([...this.PendingAttachments]);
1610
1870
  this.cdr.detectChanges();
1611
1871
  }
1612
1872
  }
1873
+ /** @deprecated Use {@link RemoveAttachment}. */
1874
+ removeAttachment(id) {
1875
+ return this.RemoveAttachment(id);
1876
+ }
1613
1877
  /**
1614
1878
  * Get all pending attachments
1615
1879
  */
1880
+ GetPendingAttachments() {
1881
+ return [...this.PendingAttachments];
1882
+ }
1883
+ /** @deprecated Use {@link GetPendingAttachments}. */
1616
1884
  getPendingAttachments() {
1617
- return [...this.pendingAttachments];
1885
+ return this.GetPendingAttachments();
1618
1886
  }
1619
1887
  /**
1620
1888
  * Add an artifact as a pending attachment programmatically.
@@ -1632,51 +1900,67 @@ export class MentionEditorComponent {
1632
1900
  source: 'artifact',
1633
1901
  artifactVersionId: artifact.artifactVersionId
1634
1902
  };
1635
- this.pendingAttachments.push(attachment);
1636
- this.attachmentsChanged.emit([...this.pendingAttachments]);
1903
+ this.PendingAttachments.push(attachment);
1904
+ this.AttachmentsChanged.emit([...this.PendingAttachments]);
1637
1905
  return attachment;
1638
1906
  }
1639
1907
  /**
1640
1908
  * Clear all pending attachments
1641
1909
  */
1642
- clearPendingAttachments() {
1643
- this.pendingAttachments = [];
1644
- this.attachmentsChanged.emit([]);
1910
+ ClearPendingAttachments() {
1911
+ this.PendingAttachments = [];
1912
+ this.AttachmentsChanged.emit([]);
1645
1913
  this.cdr.detectChanges();
1646
1914
  }
1915
+ /** @deprecated Use {@link ClearPendingAttachments}. */
1916
+ clearPendingAttachments() {
1917
+ return this.ClearPendingAttachments();
1918
+ }
1647
1919
  /**
1648
1920
  * Handle click on an attachment thumbnail
1649
1921
  */
1922
+ OnAttachmentClick(attachment) {
1923
+ this.AttachmentClicked.emit(attachment);
1924
+ }
1925
+ /** @deprecated Use {@link OnAttachmentClick}. */
1650
1926
  onAttachmentClick(attachment) {
1651
- this.attachmentClicked.emit(attachment);
1927
+ return this.OnAttachmentClick(attachment);
1652
1928
  }
1653
1929
  /**
1654
1930
  * Check if there are any pending attachments
1655
1931
  */
1932
+ HasAttachments() {
1933
+ return this.PendingAttachments.length > 0;
1934
+ }
1935
+ /** @deprecated Use {@link HasAttachments}. */
1656
1936
  hasAttachments() {
1657
- return this.pendingAttachments.length > 0;
1937
+ return this.HasAttachments();
1658
1938
  }
1659
1939
  /**
1660
1940
  * Trigger file picker programmatically
1661
1941
  */
1662
- openFilePicker() {
1942
+ OpenFilePicker() {
1663
1943
  const input = document.createElement('input');
1664
1944
  input.type = 'file';
1665
1945
  // If */* is in the list, accept all files (some browsers don't handle */* correctly)
1666
- input.accept = this.acceptedFileTypes.includes('*/*') ? '' : this.acceptedFileTypes;
1946
+ input.accept = this.AcceptedFileTypes.includes('*/*') ? '' : this.AcceptedFileTypes;
1667
1947
  input.multiple = true;
1668
- input.onchange = (e) => this.onFileSelected(e);
1948
+ input.onchange = (e) => this.OnFileSelected(e);
1669
1949
  input.click();
1670
1950
  }
1951
+ /** @deprecated Use {@link OpenFilePicker}. */
1952
+ openFilePicker() {
1953
+ return this.OpenFilePicker();
1954
+ }
1671
1955
  static ɵfac = function MentionEditorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MentionEditorComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef)); };
1672
1956
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MentionEditorComponent, selectors: [["mj-mention-editor"]], viewQuery: function MentionEditorComponent_Query(rf, ctx) { if (rf & 1) {
1673
1957
  i0.ɵɵviewQuery(_c0, 5);
1674
1958
  } if (rf & 2) {
1675
1959
  let _t;
1676
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.editorRef = _t.first);
1960
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.EditorRef = _t.first);
1677
1961
  } }, hostBindings: function MentionEditorComponent_HostBindings(rf, ctx) { if (rf & 1) {
1678
1962
  i0.ɵɵlistener("mousedown", function MentionEditorComponent_mousedown_HostBindingHandler($event) { return ctx.onDocumentMouseDown($event); }, i0.ɵɵresolveDocument);
1679
- } }, inputs: { placeholder: "placeholder", disabled: "disabled", currentUser: "currentUser", enableMentions: "enableMentions", TriggerProviders: "TriggerProviders", ExcludedTriggerKeys: "ExcludedTriggerKeys", Provider: "Provider", autoFocus: "autoFocus", enableAttachments: "enableAttachments", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes" }, outputs: { valueChange: "valueChange", mentionSelected: "mentionSelected", enterPressed: "enterPressed", attachmentsChanged: "attachmentsChanged", attachmentError: "attachmentError", attachmentClicked: "attachmentClicked", editorBlurred: "editorBlurred" }, standalone: false, features: [i0.ɵɵProvidersFeature([
1963
+ } }, inputs: { Placeholder: "Placeholder", placeholder: "placeholder", Disabled: "Disabled", disabled: "disabled", CurrentUser: "CurrentUser", currentUser: "currentUser", EnableMentions: "EnableMentions", enableMentions: "enableMentions", TriggerProviders: "TriggerProviders", ExcludedTriggerKeys: "ExcludedTriggerKeys", Provider: "Provider", AutoFocus: "AutoFocus", autoFocus: "autoFocus", EnableAttachments: "EnableAttachments", enableAttachments: "enableAttachments", MaxAttachments: "MaxAttachments", maxAttachments: "maxAttachments", MaxAttachmentSizeBytes: "MaxAttachmentSizeBytes", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", AcceptedFileTypes: "AcceptedFileTypes", acceptedFileTypes: "acceptedFileTypes" }, outputs: { ValueChange: "ValueChange", valueChange: "valueChange", MentionSelected: "MentionSelected", mentionSelected: "mentionSelected", EnterPressed: "EnterPressed", enterPressed: "enterPressed", AttachmentsChanged: "AttachmentsChanged", attachmentsChanged: "attachmentsChanged", AttachmentError: "AttachmentError", attachmentError: "attachmentError", AttachmentClicked: "AttachmentClicked", attachmentClicked: "attachmentClicked", EditorBlurred: "EditorBlurred", editorBlurred: "editorBlurred" }, standalone: false, features: [i0.ɵɵProvidersFeature([
1680
1964
  {
1681
1965
  provide: NG_VALUE_ACCESSOR,
1682
1966
  useExisting: forwardRef(() => MentionEditorComponent),
@@ -1713,15 +1997,23 @@ export class MentionEditorComponent {
1713
1997
  multi: true
1714
1998
  }
1715
1999
  ], template: "<div class=\"mention-editor-container\"\n [class.drag-over]=\"isDragOver\"\n (click)=\"onContainerClick($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n\n <!-- Pending Attachments Preview -->\n @if (pendingAttachments.length > 0) {\n <div class=\"pending-attachments\">\n @for (attachment of pendingAttachments; track attachment) {\n <div class=\"attachment-thumbnail\"\n (click)=\"onAttachmentClick(attachment)\">\n @if (attachment.thumbnailUrl) {\n <img\n [src]=\"attachment.thumbnailUrl\"\n [alt]=\"attachment.fileName\"\n class=\"thumbnail-image\">\n }\n @if (!attachment.thumbnailUrl) {\n <div class=\"thumbnail-placeholder\">\n <i class=\"fa-solid fa-file\"></i>\n <span class=\"file-name\">{{ attachment.fileName }}</span>\n </div>\n }\n <button class=\"remove-attachment\"\n (click)=\"removeAttachment(attachment.id); $event.stopPropagation()\"\n title=\"Remove attachment\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <div\n #editor\n class=\"mention-editor\"\n contenteditable=\"true\"\n [attr.contenteditable]=\"!disabled\"\n [attr.data-placeholder]=\"placeholder\"\n (input)=\"onInput()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n (paste)=\"onPaste($event)\"\n ></div>\n\n <!-- Drag & Drop Overlay -->\n @if (isDragOver) {\n <div class=\"drop-overlay\">\n <div class=\"drop-message\">\n <i class=\"fa-solid fa-cloud-arrow-up\"></i>\n <span>Drop files here</span>\n </div>\n </div>\n }\n\n <!-- Mention Dropdown -->\n @if (showMentionDropdown && enableMentions) {\n <mj-mention-dropdown\n [suggestions]=\"mentionSuggestions\"\n [position]=\"mentionDropdownPosition\"\n [showAbove]=\"mentionDropdownShowAbove\"\n [alignRight]=\"mentionDropdownAlignRight\"\n [useFixedPositioning]=\"true\"\n [visible]=\"true\"\n (suggestionSelected)=\"onMentionSelected($event)\"\n (closed)=\"closeMentionDropdown()\">\n </mj-mention-dropdown>\n }\n</div>\n", styles: [".mention-editor-container {\n position: relative;\n width: 100%;\n display: block;\n}\n\n.mention-editor-container.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--mj-brand-primary);\n}\n\n.mention-editor {\n display: block;\n width: 100%;\n min-height: 100px;\n max-height: 300px;\n padding: 7px 3.5rem 7px 12px;\n outline: none;\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.5;\n overflow-y: auto;\n overflow-x: hidden;\n word-wrap: break-word;\n white-space: pre-wrap;\n cursor: text;\n user-select: text;\n box-sizing: border-box;\n}\n.mention-editor:empty:before {\n content: attr(data-placeholder);\n color: var(--mj-text-muted);\n pointer-events: none;\n position: absolute;\n}\n.mention-editor:focus {\n outline: none;\n}\n.mention-editor[contenteditable=false] {\n cursor: not-allowed;\n opacity: 0.6;\n background: var(--mj-bg-surface-sunken);\n}\n@media (max-width: 768px) {\n .mention-editor {\n font-size: 16px;\n padding: 5px;\n padding-right: 3rem;\n }\n}\n\n::ng-deep .mention-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n margin: 0 3px;\n border-radius: 16px;\n font-size: 13px;\n font-weight: 600;\n cursor: default;\n user-select: none;\n vertical-align: middle;\n white-space: nowrap;\n pointer-events: all;\n -webkit-user-modify: read-only;\n -moz-user-modify: read-only;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n box-shadow: var(--mj-shadow-md);\n animation: chipInsert 0.15s ease-out;\n}\n::ng-deep .mention-chip i {\n font-size: 12px;\n opacity: 0.95;\n}\n::ng-deep .mention-chip[data-mention-type=user] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n::ng-deep .mention-chip:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-lg);\n transition: all 0.2s ease;\n}\n::ng-deep .mention-chip:focus, ::ng-deep .mention-chip.selected {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n@keyframes chipInsert {\n 0% {\n transform: scale(0.8);\n opacity: 0;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.mention-editor .mention-chip + .mention-chip {\n margin-left: 4px;\n}\n.mention-editor br {\n display: block;\n content: \"\";\n margin: 0;\n}\n\n.mention-editor::-webkit-scrollbar {\n width: 6px;\n}\n.mention-editor::-webkit-scrollbar-track {\n background: transparent;\n}\n.mention-editor::-webkit-scrollbar-thumb {\n background: color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n border-radius: 3px;\n}\n.mention-editor::-webkit-scrollbar-thumb:hover {\n background: color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n}\n\n/* ==================== Attachment Styles ==================== */\n\n.pending-attachments {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, transparent);\n}\n\n.attachment-thumbnail {\n position: relative;\n width: 80px;\n height: 80px;\n border-radius: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: transform 0.2s, box-shadow 0.2s;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n\n.attachment-thumbnail:hover {\n transform: scale(1.05);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.thumbnail-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.thumbnail-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 8px;\n color: var(--mj-text-secondary);\n}\n\n.thumbnail-placeholder i {\n font-size: 24px;\n margin-bottom: 4px;\n color: var(--mj-text-muted);\n}\n\n.thumbnail-placeholder .file-name {\n font-size: 10px;\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-height: 36px;\n overflow: hidden;\n}\n\n.remove-attachment {\n position: absolute;\n top: 4px;\n right: 4px;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-text-primary) 60%, transparent);\n color: var(--mj-text-inverse);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s, background 0.2s;\n}\n\n.attachment-thumbnail:hover .remove-attachment {\n opacity: 1;\n}\n\n.remove-attachment:hover {\n background: color-mix(in srgb, var(--mj-status-error) 90%, transparent);\n}\n\n.remove-attachment i {\n font-size: 10px;\n}\n\n/* Drop Overlay */\n.drop-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n backdrop-filter: blur(2px);\n border: 2px dashed var(--mj-brand-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n pointer-events: none;\n}\n\n.drop-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.drop-message i {\n font-size: 32px;\n}\n\n.drop-message span {\n font-size: 14px;\n}\n"] }]
1716
- }], () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], { editorRef: [{
2000
+ }], () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], { EditorRef: [{
1717
2001
  type: ViewChild,
1718
2002
  args: ['editor', { static: false }]
2003
+ }], Placeholder: [{
2004
+ type: Input
1719
2005
  }], placeholder: [{
1720
2006
  type: Input
2007
+ }], Disabled: [{
2008
+ type: Input
1721
2009
  }], disabled: [{
1722
2010
  type: Input
2011
+ }], CurrentUser: [{
2012
+ type: Input
1723
2013
  }], currentUser: [{
1724
2014
  type: Input
2015
+ }], EnableMentions: [{
2016
+ type: Input
1725
2017
  }], enableMentions: [{
1726
2018
  type: Input
1727
2019
  }], TriggerProviders: [{
@@ -1730,28 +2022,52 @@ export class MentionEditorComponent {
1730
2022
  type: Input
1731
2023
  }], Provider: [{
1732
2024
  type: Input
2025
+ }], AutoFocus: [{
2026
+ type: Input
1733
2027
  }], autoFocus: [{
1734
2028
  type: Input
2029
+ }], EnableAttachments: [{
2030
+ type: Input
1735
2031
  }], enableAttachments: [{
1736
2032
  type: Input
2033
+ }], MaxAttachments: [{
2034
+ type: Input
1737
2035
  }], maxAttachments: [{
1738
2036
  type: Input
2037
+ }], MaxAttachmentSizeBytes: [{
2038
+ type: Input
1739
2039
  }], maxAttachmentSizeBytes: [{
1740
2040
  type: Input
2041
+ }], AcceptedFileTypes: [{
2042
+ type: Input
1741
2043
  }], acceptedFileTypes: [{
1742
2044
  type: Input
2045
+ }], ValueChange: [{
2046
+ type: Output
1743
2047
  }], valueChange: [{
1744
2048
  type: Output
2049
+ }], MentionSelected: [{
2050
+ type: Output
1745
2051
  }], mentionSelected: [{
1746
2052
  type: Output
2053
+ }], EnterPressed: [{
2054
+ type: Output
1747
2055
  }], enterPressed: [{
1748
2056
  type: Output
2057
+ }], AttachmentsChanged: [{
2058
+ type: Output
1749
2059
  }], attachmentsChanged: [{
1750
2060
  type: Output
2061
+ }], AttachmentError: [{
2062
+ type: Output
1751
2063
  }], attachmentError: [{
1752
2064
  type: Output
2065
+ }], AttachmentClicked: [{
2066
+ type: Output
1753
2067
  }], attachmentClicked: [{
1754
2068
  type: Output
2069
+ }], EditorBlurred: [{
2070
+ type: Output
1755
2071
  }], editorBlurred: [{
1756
2072
  type: Output
1757
2073
  }], onDocumentMouseDown: [{