multi color comment support
This commit is contained in:
		
							parent
							
								
									2190cc06e4
								
							
						
					
					
						commit
						ca90d1c422
					
				@ -29,10 +29,16 @@
 | 
				
			|||||||
]" (overlayOutsideClick)="clickOutsideMenu($event)">
 | 
					]" (overlayOutsideClick)="clickOutsideMenu($event)">
 | 
				
			||||||
    <div class="mat-mdc-menu-panel" #menuContent>
 | 
					    <div class="mat-mdc-menu-panel" #menuContent>
 | 
				
			||||||
        <div class="mat-mdc-menu-content">
 | 
					        <div class="mat-mdc-menu-content">
 | 
				
			||||||
 | 
					            @if (filteredSelectionList.length > 0) {
 | 
				
			||||||
            @for (item of filteredSelectionList; track item; let index_ = $index) {
 | 
					            @for (item of filteredSelectionList; track item; let index_ = $index) {
 | 
				
			||||||
            <div class="mat-mdc-menu-item mat-focus-indicator"
 | 
					            <div class="mat-mdc-menu-item mat-focus-indicator"
 | 
				
			||||||
                [class.mat-mdc-menu-item-highlighted]="index_ === selectedDropdownItemIndex"
 | 
					                [class.mat-mdc-menu-item-highlighted]="index_ === selectedDropdownItemIndex"
 | 
				
			||||||
                [class.active]="index_ === selectedDropdownItemIndex" (click)="clickMention(index_)">{{item}}
 | 
					                [class.active]="index_ === selectedDropdownItemIndex" (click)="clickMention(index_)">{{item.title}}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            } @else {
 | 
				
			||||||
 | 
					            <div class="mat-mdc-menu-item mat-focus-indicator">
 | 
				
			||||||
 | 
					                Keine Übereinstimmung...
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -8,11 +8,13 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .mention {
 | 
					    .mention {
 | 
				
			||||||
 | 
					        --mention-color: blue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        display: inline-block;
 | 
					        display: inline-block;
 | 
				
			||||||
        position: relative;
 | 
					        position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        &:not(.ignore) {
 | 
					        &:not(.ignore) {
 | 
				
			||||||
            color: blue;
 | 
					            color: var(--mention-color);
 | 
				
			||||||
            background-color: transparent;
 | 
					            background-color: transparent;
 | 
				
			||||||
            font-style: italic;
 | 
					            font-style: italic;
 | 
				
			||||||
            font-size: 0.8rem;
 | 
					            font-size: 0.8rem;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,11 @@ import { OverlayModule } from '@angular/cdk/overlay';
 | 
				
			|||||||
import { DOWN_ARROW, ENTER, ESCAPE, TAB, UP_ARROW } from '@angular/cdk/keycodes';
 | 
					import { DOWN_ARROW, ENTER, ESCAPE, TAB, UP_ARROW } from '@angular/cdk/keycodes';
 | 
				
			||||||
import { Cursor, MentionHandleResult } from './cursor';
 | 
					import { Cursor, MentionHandleResult } from './cursor';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface MentionItem {
 | 
				
			||||||
 | 
					  title: string,
 | 
				
			||||||
 | 
					  color?: string,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-comment-box',
 | 
					  selector: 'app-comment-box',
 | 
				
			||||||
  imports: [MatMenuModule, OverlayModule],
 | 
					  imports: [MatMenuModule, OverlayModule],
 | 
				
			||||||
@ -155,7 +160,7 @@ export class CommentBoxComponent implements MatFormFieldControl<string>, Control
 | 
				
			|||||||
  @ViewChild('commentInput') _commentInputRef!: ElementRef;
 | 
					  @ViewChild('commentInput') _commentInputRef!: ElementRef;
 | 
				
			||||||
  @ViewChild('menuContent') _menuContent!: ElementRef;
 | 
					  @ViewChild('menuContent') _menuContent!: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Input() mentionListItems: string[] = [];
 | 
					  @Input() mentionListItems: MentionItem[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  selectedDropdownItemIndex = 0;
 | 
					  selectedDropdownItemIndex = 0;
 | 
				
			||||||
  menuOffsetX = 0;
 | 
					  menuOffsetX = 0;
 | 
				
			||||||
@ -163,7 +168,7 @@ export class CommentBoxComponent implements MatFormFieldControl<string>, Control
 | 
				
			|||||||
  menuOpenAboveYShift = 0;
 | 
					  menuOpenAboveYShift = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  isOpen = false;
 | 
					  isOpen = false;
 | 
				
			||||||
  filteredSelectionList: string[] = [];
 | 
					  filteredSelectionList: MentionItem[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleKeyEvent(event: KeyboardEvent) {
 | 
					  handleKeyEvent(event: KeyboardEvent) {
 | 
				
			||||||
    if (this.isOpen) {
 | 
					    if (this.isOpen) {
 | 
				
			||||||
@ -180,9 +185,16 @@ export class CommentBoxComponent implements MatFormFieldControl<string>, Control
 | 
				
			|||||||
          this.removeFocusedMention(event.target as HTMLInputElement);
 | 
					          this.removeFocusedMention(event.target as HTMLInputElement);
 | 
				
			||||||
          event.preventDefault();
 | 
					          event.preventDefault();
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case ENTER || TAB:
 | 
					        case ENTER:
 | 
				
			||||||
 | 
					        case TAB:
 | 
				
			||||||
 | 
					          if (this.filteredSelectionList[this.selectedDropdownItemIndex]) {
 | 
				
			||||||
            this.addMention(event.target as HTMLInputElement);
 | 
					            this.addMention(event.target as HTMLInputElement);
 | 
				
			||||||
            this.handleTextChanged(true, 1);
 | 
					            this.handleTextChanged(true, 1);
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            this.removeFocusedMention(event.target as HTMLInputElement);
 | 
				
			||||||
 | 
					            this.isOpen = false;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          event.preventDefault();
 | 
					          event.preventDefault();
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -230,7 +242,7 @@ export class CommentBoxComponent implements MatFormFieldControl<string>, Control
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      // filter menu entries
 | 
					      // filter menu entries
 | 
				
			||||||
      let searchQuery = focusedMentionElement.textContent?.substring(1);
 | 
					      let searchQuery = focusedMentionElement.textContent?.substring(1);
 | 
				
			||||||
      this.filteredSelectionList = this.mentionListItems.filter((element) => element.toLocaleLowerCase().includes(searchQuery?.toLocaleLowerCase() ?? ""))
 | 
					      this.filteredSelectionList = this.mentionListItems.filter((element) => element.title.toLocaleLowerCase().includes(searchQuery?.toLocaleLowerCase() ?? ""))
 | 
				
			||||||
      if (this.selectedDropdownItemIndex > this.filteredSelectionList.length - 1)
 | 
					      if (this.selectedDropdownItemIndex > this.filteredSelectionList.length - 1)
 | 
				
			||||||
        this.selectedDropdownItemIndex = this.filteredSelectionList.length - 1;
 | 
					        this.selectedDropdownItemIndex = this.filteredSelectionList.length - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -245,11 +257,12 @@ export class CommentBoxComponent implements MatFormFieldControl<string>, Control
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  handleMentionElements(innerHtml: string): MentionHandleResult {
 | 
					  handleMentionElements(innerHtml: string): MentionHandleResult {
 | 
				
			||||||
    let newOffset = null;
 | 
					    let newOffset = null;
 | 
				
			||||||
    innerHtml = innerHtml.replace(/(?<!(<div class[ \t]*=[ \t]*"[^"]*mention[^"]*">|\w))@\w*/g, (match) => {
 | 
					    // innerHtml = innerHtml.replace(/(?<!(<div class[ \t]*=[ \t]*"[^"]*mention[^"]*">|\w))@\w*/g, (match) => {
 | 
				
			||||||
 | 
					    innerHtml = innerHtml.replace(/(?<!(<div class[ \t]*=[ \t]*"[^"]*mention[^"]*"[ \t]*(style[ \t]*=[ \t]*".*[ \t]*")?>|\w))@\w*/g, (match) => {
 | 
				
			||||||
      newOffset = match.length;
 | 
					      newOffset = match.length;
 | 
				
			||||||
      return `<div class="${Cursor.focusedClassName} ignore mention">${match}</div>`;
 | 
					      return `<div class="${Cursor.focusedClassName} ignore mention">${match}</div>`;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    console.log(innerHtml)
 | 
				
			||||||
    // remove old focus classes if match was found
 | 
					    // remove old focus classes if match was found
 | 
				
			||||||
    if (newOffset) {
 | 
					    if (newOffset) {
 | 
				
			||||||
      innerHtml = innerHtml.replaceAll(/class="focused"/g, "");
 | 
					      innerHtml = innerHtml.replaceAll(/class="focused"/g, "");
 | 
				
			||||||
@ -303,14 +316,19 @@ export class CommentBoxComponent implements MatFormFieldControl<string>, Control
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  addMention(element: HTMLElement) {
 | 
					  addMention(element: HTMLElement) {
 | 
				
			||||||
 | 
					    const mentionItem = this.filteredSelectionList[this.selectedDropdownItemIndex];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let focusedMention = element.querySelector(`.mention.${Cursor.focusedClassName}`);
 | 
					    let focusedMention = element.querySelector(`.mention.${Cursor.focusedClassName}`);
 | 
				
			||||||
    let focusedElements = element.querySelectorAll(Cursor.focusedClassName);
 | 
					    let focusedElements = element.querySelectorAll(Cursor.focusedClassName);
 | 
				
			||||||
    if (focusedMention) {
 | 
					    if (focusedMention) {
 | 
				
			||||||
      // set text and remove ignore to style mention
 | 
					      // set text and remove ignore to style mention
 | 
				
			||||||
      focusedMention.textContent = `@${this.filteredSelectionList[this.selectedDropdownItemIndex]}`;
 | 
					      focusedMention.textContent = `@${mentionItem.title}`;
 | 
				
			||||||
      focusedMention.classList.remove(Cursor.focusedClassName);
 | 
					      focusedMention.classList.remove(Cursor.focusedClassName);
 | 
				
			||||||
      focusedMention.classList.remove("ignore")
 | 
					      focusedMention.classList.remove("ignore")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (mentionItem.color)
 | 
				
			||||||
 | 
					        focusedMention.setAttribute('style', `--mention-color:${mentionItem.color}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // remove all old focused classes
 | 
					      // remove all old focused classes
 | 
				
			||||||
      for (let node of focusedElements) {
 | 
					      for (let node of focusedElements) {
 | 
				
			||||||
        node.classList.remove(Cursor.focusedClassName);
 | 
					        node.classList.remove(Cursor.focusedClassName);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user