Răsfoiți Sursa

fix(admin-ui): Fix issues with rich text editor in custom field

Michael Bromley 3 ani în urmă
părinte
comite
aa13dcb519

+ 20 - 18
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.component.ts

@@ -13,8 +13,6 @@ import {
 import { BehaviorSubject, Observable, Subscription } from 'rxjs';
 import { distinctUntilChanged } from 'rxjs/operators';
 
-import { RichTextEditorComponent } from '../../rich-text-editor.component';
-
 import { ContextMenuConfig, ContextMenuItem, ContextMenuService } from './context-menu.service';
 
 type DropdownPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
@@ -26,6 +24,7 @@ type DropdownPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
 export class ContextMenuComponent implements AfterViewInit, OnDestroy {
+    @Input() editorMenuElement: HTMLElement | null | undefined;
     @ViewChild('contextMenu', { static: true }) private menuTemplate: TemplateRef<any>;
 
     menuConfig: ContextMenuConfig | undefined;
@@ -34,11 +33,10 @@ export class ContextMenuComponent implements AfterViewInit, OnDestroy {
     private menuPortal: TemplatePortal<any>;
     private overlayRef: OverlayRef;
     private contextMenuSub: Subscription;
-    private contentArea: HTMLDivElement;
+    private contentArea: HTMLDivElement | null;
     private hideTriggerHandler: (() => void) | undefined;
 
     constructor(
-        private richTextEditor: RichTextEditorComponent,
         private overlay: Overlay,
         private viewContainerRef: ViewContainerRef,
         public contextMenuService: ContextMenuService,
@@ -51,12 +49,11 @@ export class ContextMenuComponent implements AfterViewInit, OnDestroy {
     };
 
     ngAfterViewInit() {
-        // tslint:disable-next-line:no-non-null-assertion
-        this.contentArea = document.querySelector('.content-area')!;
+        this.contentArea = document.querySelector('.content-area');
         this.menuPortal = new TemplatePortal(this.menuTemplate, this.viewContainerRef);
 
         this.hideTrigger$ = this.triggerIsHidden.asObservable().pipe(distinctUntilChanged());
-        this.contentArea.addEventListener('scroll', this.onScroll, { passive: true });
+        this.contentArea?.addEventListener('scroll', this.onScroll, { passive: true });
 
         this.contextMenuSub = this.contextMenuService.contextMenu$.subscribe(contextMenuConfig => {
             this.overlayRef?.dispose();
@@ -71,25 +68,27 @@ export class ContextMenuComponent implements AfterViewInit, OnDestroy {
                 this.triggerIsHidden.next(false);
 
                 const triggerButton = this.overlayRef.hostElement.querySelector('.context-menu-trigger');
-                const editorMenu = this.richTextEditor.menuElement;
+                const editorMenu = this.editorMenuElement;
                 if (triggerButton) {
                     const overlapMarginPx = 5;
                     this.hideTriggerHandler = () => {
-                        if (
-                            triggerButton.getBoundingClientRect().top + overlapMarginPx <
-                            editorMenu.getBoundingClientRect().bottom
-                        ) {
-                            this.triggerIsHidden.next(true);
-                        } else {
-                            this.triggerIsHidden.next(false);
+                        if (editorMenu && triggerButton) {
+                            if (
+                                triggerButton.getBoundingClientRect().top + overlapMarginPx <
+                                editorMenu.getBoundingClientRect().bottom
+                            ) {
+                                this.triggerIsHidden.next(true);
+                            } else {
+                                this.triggerIsHidden.next(false);
+                            }
                         }
                     };
-                    this.contentArea.addEventListener('scroll', this.hideTriggerHandler, { passive: true });
+                    this.contentArea?.addEventListener('scroll', this.hideTriggerHandler, { passive: true });
                     requestAnimationFrame(() => this.hideTriggerHandler?.());
                 }
             } else {
                 if (this.hideTriggerHandler) {
-                    this.contentArea.removeEventListener('scroll', this.hideTriggerHandler);
+                    this.contentArea?.removeEventListener('scroll', this.hideTriggerHandler);
                 }
             }
         });
@@ -102,7 +101,10 @@ export class ContextMenuComponent implements AfterViewInit, OnDestroy {
     ngOnDestroy(): void {
         this.overlayRef?.dispose();
         this.contextMenuSub?.unsubscribe();
-        this.contentArea.removeEventListener('scroll', this.onScroll);
+        this.contentArea?.removeEventListener('scroll', this.onScroll);
+        if (this.hideTriggerHandler) {
+            this.contentArea?.removeEventListener('scroll', this.hideTriggerHandler);
+        }
     }
 
     clickItem(item: ContextMenuItem) {

+ 2 - 2
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.service.ts

@@ -1,5 +1,5 @@
 import { Injectable } from '@angular/core';
-import { BehaviorSubject, combineLatest, Observable, Subject, of, interval } from 'rxjs';
+import { BehaviorSubject, combineLatest, interval, Observable, of, Subject } from 'rxjs';
 import {
     bufferWhen,
     debounceTime,
@@ -77,6 +77,6 @@ export class ContextMenuService {
     }
 
     clearContextMenu() {
-        this.setContextMenuConfig$.next();
+        this.setContextMenuConfig$.next(undefined);
     }
 }

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/rich-text-editor.component.html

@@ -1,3 +1,3 @@
 <label class="clr-control-label">{{ label }}</label>
 <div #editor></div>
-<vdr-context-menu></vdr-context-menu>
+<vdr-context-menu [editorMenuElement]="menuElement"></vdr-context-menu>

+ 2 - 1
packages/admin-ui/src/lib/core/src/shared/components/rich-text-editor/rich-text-editor.component.ts

@@ -41,6 +41,7 @@ import { ProsemirrorService } from './prosemirror/prosemirror.service';
             multi: true,
         },
         ProsemirrorService,
+        ContextMenuService,
     ],
 })
 export class RichTextEditorComponent implements ControlValueAccessor, AfterViewInit, OnDestroy {
@@ -65,7 +66,7 @@ export class RichTextEditorComponent implements ControlValueAccessor, AfterViewI
         public contextMenuService: ContextMenuService,
     ) {}
 
-    get menuElement(): HTMLDivElement {
+    get menuElement(): HTMLDivElement | null {
         return this.viewContainerRef.element.nativeElement.querySelector('.ProseMirror-menubar');
     }