]> BookStack Code Mirror - bookstack/commitdiff
Lexical: Improved table resize bars
authorDan Brown <redacted>
Tue, 23 Jul 2024 11:45:58 +0000 (12:45 +0100)
committerDan Brown <redacted>
Tue, 23 Jul 2024 11:45:58 +0000 (12:45 +0100)
Added scoll & page resize handling.
Added cropping/limiting to edit area.

resources/js/wysiwyg/index.ts
resources/js/wysiwyg/todo.md
resources/js/wysiwyg/ui/framework/helpers/table-resizer.ts
resources/js/wysiwyg/ui/framework/manager.ts

index 5f131df5725562f1e7817423215551be66b2b7b9..469738e7fed93ca2c2969a0be470d746aeb568a3 100644 (file)
@@ -44,7 +44,7 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st
     mergeRegister(
         registerRichText(editor),
         registerHistory(editor, createEmptyHistoryState(), 300),
-        registerTableResizer(editor, editArea),
+        registerTableResizer(editor, editWrap),
     );
 
     setEditorContentFromHtml(editor, htmlContent);
index 7b958819471f93e976e2c216771a4cd0f11073e1..e39a4c655fee66335dfbe6c361f6f4b65c1cf920 100644 (file)
@@ -36,5 +36,5 @@
 ## Bugs
 
 - Image resizing currently bugged, maybe change to ghost resizer in decorator instead of updating core node.
-- Table resize bars often floating around in wrong place, and shows on hover or interrupts mouse actions.
-- Removing link around image via button deletes image, not just link 
\ No newline at end of file
+- Removing link around image via button deletes image, not just link 
+- `SELECTION_CHANGE_COMMAND` not fired when clicking out of a table cell. Prevents toolbar hiding on table unselect.
\ No newline at end of file
index 8f1e978e9dc5119a1a15ea7503b16322c48165bd..2d995883a5be46623a484e672ea0b888509efda0 100644 (file)
@@ -8,7 +8,7 @@ type MarkerDomRecord = {x: HTMLElement, y: HTMLElement};
 
 class TableResizer {
     protected editor: LexicalEditor;
-    protected editArea: HTMLElement;
+    protected editScrollContainer: HTMLElement;
     protected markerDom: MarkerDomRecord|null = null;
     protected mouseTracker: MouseDragTracker|null = null;
     protected dragging: boolean = false;
@@ -16,15 +16,17 @@ class TableResizer {
     protected xMarkerAtStart : boolean = false;
     protected yMarkerAtStart : boolean = false;
 
-    constructor(editor: LexicalEditor, editArea: HTMLElement) {
+    constructor(editor: LexicalEditor, editScrollContainer: HTMLElement) {
         this.editor = editor;
-        this.editArea = editArea;
+        this.editScrollContainer = editScrollContainer;
 
         this.setupListeners();
     }
 
     teardown() {
-        this.editArea.removeEventListener('mousemove', this.onCellMouseMove);
+        this.editScrollContainer.removeEventListener('mousemove', this.onCellMouseMove);
+        window.removeEventListener('scroll', this.onScrollOrResize, {capture: true});
+        window.removeEventListener('resize', this.onScrollOrResize);
         if (this.mouseTracker) {
             this.mouseTracker.teardown();
         }
@@ -32,7 +34,14 @@ class TableResizer {
 
     protected setupListeners() {
         this.onCellMouseMove = this.onCellMouseMove.bind(this);
-        this.editArea.addEventListener('mousemove', this.onCellMouseMove);
+        this.onScrollOrResize = this.onScrollOrResize.bind(this);
+        this.editScrollContainer.addEventListener('mousemove', this.onCellMouseMove);
+        window.addEventListener('scroll', this.onScrollOrResize, {capture: true, passive: true});
+        window.addEventListener('resize', this.onScrollOrResize, {passive: true});
+    }
+
+    protected onScrollOrResize(): void {
+        this.updateCurrentMarkerTargetPosition();
     }
 
     protected onCellMouseMove(event: MouseEvent) {
@@ -58,14 +67,33 @@ class TableResizer {
         const markers: MarkerDomRecord = this.getMarkers();
         const table = cell.closest('table') as HTMLElement;
         const tableRect = table.getBoundingClientRect();
+        const editBounds = this.editScrollContainer.getBoundingClientRect();
 
+        const maxTop = Math.max(tableRect.top, editBounds.top);
+        const maxBottom = Math.min(tableRect.bottom, editBounds.bottom);
+        const maxHeight = maxBottom - maxTop;
         markers.x.style.left = xPos + 'px';
-        markers.x.style.height = tableRect.height + 'px';
-        markers.x.style.top = tableRect.top + 'px';
+        markers.x.style.top = maxTop + 'px';
+        markers.x.style.height = maxHeight + 'px';
 
         markers.y.style.top = yPos + 'px';
         markers.y.style.left = tableRect.left + 'px';
         markers.y.style.width = tableRect.width + 'px';
+
+        // Hide markers when out of bounds
+        markers.y.hidden = yPos < editBounds.top || yPos > editBounds.bottom;
+        markers.x.hidden = tableRect.top > editBounds.bottom || tableRect.bottom < editBounds.top;
+    }
+
+    protected updateCurrentMarkerTargetPosition(): void {
+        if (!this.targetCell) {
+            return;
+        }
+
+        const rect = this.targetCell.getBoundingClientRect();
+        const xMarkerPos = this.xMarkerAtStart ? rect.left : rect.right;
+        const yMarkerPos = this.yMarkerAtStart ? rect.top : rect.bottom;
+        this.updateMarkersTo(this.targetCell, xMarkerPos, yMarkerPos);
     }
 
     protected getMarkers(): MarkerDomRecord {
@@ -77,7 +105,7 @@ class TableResizer {
             const wrapper = el('div', {
                 class: 'editor-table-marker-wrap',
             }, [this.markerDom.x, this.markerDom.y]);
-            this.editArea.after(wrapper);
+            this.editScrollContainer.after(wrapper);
             this.watchMarkerMouseDrags(wrapper);
         }
 
@@ -180,8 +208,8 @@ class TableResizer {
 }
 
 
-export function registerTableResizer(editor: LexicalEditor, editorArea: HTMLElement): (() => void) {
-    const resizer = new TableResizer(editor, editorArea);
+export function registerTableResizer(editor: LexicalEditor, editScrollContainer: HTMLElement): (() => void) {
+    const resizer = new TableResizer(editor, editScrollContainer);
 
     return () => {
         resizer.teardown();
index 29d959910757573d77484ef741c5a6b3281ef285..c0357c3ea80f9f9225ea9affb65dedb3472e588f 100644 (file)
@@ -175,6 +175,7 @@ export class EditorUIManager {
     protected setupEditor(editor: LexicalEditor) {
         // Update button states on editor selection change
         editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
+            console.log('select change', arguments);
             this.triggerStateUpdate({
                 editor: editor,
                 selection: $getSelection(),