mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Lexical: Completed initial table cell resize handle logic
This commit is contained in:
parent
b1130cb1c3
commit
72a0e081ca
@ -2,6 +2,7 @@ import {$getNearestNodeFromDOMNode, LexicalEditor} from "lexical";
|
|||||||
import {el} from "../../../helpers";
|
import {el} from "../../../helpers";
|
||||||
import {MouseDragTracker, MouseDragTrackerDistance} from "./mouse-drag-tracker";
|
import {MouseDragTracker, MouseDragTrackerDistance} from "./mouse-drag-tracker";
|
||||||
import {$getTableColumnWidth, $setTableColumnWidth, CustomTableNode} from "../../../nodes/custom-table";
|
import {$getTableColumnWidth, $setTableColumnWidth, CustomTableNode} from "../../../nodes/custom-table";
|
||||||
|
import {TableRowNode} from "@lexical/table";
|
||||||
|
|
||||||
type MarkerDomRecord = {x: HTMLElement, y: HTMLElement};
|
type MarkerDomRecord = {x: HTMLElement, y: HTMLElement};
|
||||||
|
|
||||||
@ -18,19 +19,28 @@ class TableResizer {
|
|||||||
constructor(editor: LexicalEditor, editArea: HTMLElement) {
|
constructor(editor: LexicalEditor, editArea: HTMLElement) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.editArea = editArea;
|
this.editArea = editArea;
|
||||||
|
|
||||||
this.setupListeners();
|
this.setupListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
setupListeners() {
|
teardown() {
|
||||||
this.editArea.addEventListener('mousemove', event => {
|
this.editArea.removeEventListener('mousemove', this.onCellMouseMove);
|
||||||
const cell = (event.target as HTMLElement).closest('td,th');
|
if (this.mouseTracker) {
|
||||||
if (cell && !this.dragging) {
|
this.mouseTracker.teardown();
|
||||||
this.onCellMouseMove(cell as HTMLElement, event);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onCellMouseMove(cell: HTMLElement, event: MouseEvent) {
|
protected setupListeners() {
|
||||||
|
this.onCellMouseMove = this.onCellMouseMove.bind(this);
|
||||||
|
this.editArea.addEventListener('mousemove', this.onCellMouseMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onCellMouseMove(event: MouseEvent) {
|
||||||
|
const cell = (event.target as HTMLElement).closest('td,th') as HTMLElement;
|
||||||
|
if (!cell || this.dragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const rect = cell.getBoundingClientRect();
|
const rect = cell.getBoundingClientRect();
|
||||||
const midX = rect.left + (rect.width / 2);
|
const midX = rect.left + (rect.width / 2);
|
||||||
const midY = rect.top + (rect.height / 2);
|
const midY = rect.top + (rect.height / 2);
|
||||||
@ -44,7 +54,7 @@ class TableResizer {
|
|||||||
this.updateMarkersTo(cell, xMarkerPos, yMarkerPos);
|
this.updateMarkersTo(cell, xMarkerPos, yMarkerPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMarkersTo(cell: HTMLElement, xPos: number, yPos: number) {
|
protected updateMarkersTo(cell: HTMLElement, xPos: number, yPos: number) {
|
||||||
const markers: MarkerDomRecord = this.getMarkers();
|
const markers: MarkerDomRecord = this.getMarkers();
|
||||||
const table = cell.closest('table') as HTMLElement;
|
const table = cell.closest('table') as HTMLElement;
|
||||||
const tableRect = table.getBoundingClientRect();
|
const tableRect = table.getBoundingClientRect();
|
||||||
@ -58,7 +68,7 @@ class TableResizer {
|
|||||||
markers.y.style.width = tableRect.width + 'px';
|
markers.y.style.width = tableRect.width + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
getMarkers(): MarkerDomRecord {
|
protected getMarkers(): MarkerDomRecord {
|
||||||
if (!this.markerDom) {
|
if (!this.markerDom) {
|
||||||
this.markerDom = {
|
this.markerDom = {
|
||||||
x: el('div', {class: 'editor-table-marker editor-table-marker-column'}),
|
x: el('div', {class: 'editor-table-marker editor-table-marker-column'}),
|
||||||
@ -74,7 +84,7 @@ class TableResizer {
|
|||||||
return this.markerDom;
|
return this.markerDom;
|
||||||
}
|
}
|
||||||
|
|
||||||
watchMarkerMouseDrags(wrapper: HTMLElement) {
|
protected watchMarkerMouseDrags(wrapper: HTMLElement) {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
let markerStart: number = 0;
|
let markerStart: number = 0;
|
||||||
let markerProp: 'left' | 'top' = 'left';
|
let markerProp: 'left' | 'top' = 'left';
|
||||||
@ -96,25 +106,55 @@ class TableResizer {
|
|||||||
marker.style.top = '0';
|
marker.style.top = '0';
|
||||||
|
|
||||||
_this.dragging = false;
|
_this.dragging = false;
|
||||||
console.log('up', distance, marker, markerProp, _this.targetCell);
|
|
||||||
const parentTable = _this.targetCell?.closest('table');
|
const parentTable = _this.targetCell?.closest('table');
|
||||||
|
|
||||||
if (markerProp === 'left' && _this.targetCell && parentTable) {
|
if (markerProp === 'left' && _this.targetCell && parentTable) {
|
||||||
const cellIndex = _this.getTargetCellColumnIndex();
|
let cellIndex = _this.getTargetCellColumnIndex();
|
||||||
|
let change = distance.x;
|
||||||
|
if (_this.xMarkerAtStart && cellIndex > 0) {
|
||||||
|
cellIndex -= 1;
|
||||||
|
} else if (_this.xMarkerAtStart && cellIndex === 0) {
|
||||||
|
change = -change;
|
||||||
|
}
|
||||||
|
|
||||||
_this.editor.update(() => {
|
_this.editor.update(() => {
|
||||||
const table = $getNearestNodeFromDOMNode(parentTable);
|
const table = $getNearestNodeFromDOMNode(parentTable);
|
||||||
if (table instanceof CustomTableNode) {
|
if (table instanceof CustomTableNode) {
|
||||||
const originalWidth = $getTableColumnWidth(_this.editor, table, cellIndex);
|
const originalWidth = $getTableColumnWidth(_this.editor, table, cellIndex);
|
||||||
const newWidth = Math.max(originalWidth + distance.x, 10);
|
const newWidth = Math.max(originalWidth + change, 10);
|
||||||
$setTableColumnWidth(table, cellIndex, newWidth);
|
$setTableColumnWidth(table, cellIndex, newWidth);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (markerProp === 'top' && _this.targetCell) {
|
||||||
|
const cellElement = _this.targetCell;
|
||||||
|
|
||||||
|
_this.editor.update(() => {
|
||||||
|
const cellNode = $getNearestNodeFromDOMNode(cellElement);
|
||||||
|
const rowNode = cellNode?.getParent();
|
||||||
|
let rowIndex = rowNode?.getIndexWithinParent() || 0;
|
||||||
|
|
||||||
|
let change = distance.y;
|
||||||
|
if (_this.yMarkerAtStart && rowIndex > 0) {
|
||||||
|
rowIndex -= 1;
|
||||||
|
} else if (_this.yMarkerAtStart && rowIndex === 0) {
|
||||||
|
change = -change;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetRow = rowNode?.getParent()?.getChildren()[rowIndex];
|
||||||
|
if (targetRow instanceof TableRowNode) {
|
||||||
|
const height = targetRow.getHeight() || 0;
|
||||||
|
const newHeight = Math.max(height + change, 10);
|
||||||
|
targetRow.setHeight(newHeight);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetCellColumnIndex(): number {
|
protected getTargetCellColumnIndex(): number {
|
||||||
const cell = this.targetCell;
|
const cell = this.targetCell;
|
||||||
if (cell === null) {
|
if (cell === null) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -143,6 +183,7 @@ class TableResizer {
|
|||||||
export function registerTableResizer(editor: LexicalEditor, editorArea: HTMLElement): (() => void) {
|
export function registerTableResizer(editor: LexicalEditor, editorArea: HTMLElement): (() => void) {
|
||||||
const resizer = new TableResizer(editor, editorArea);
|
const resizer = new TableResizer(editor, editorArea);
|
||||||
|
|
||||||
// TODO - Strip/close down resizer
|
return () => {
|
||||||
return () => {};
|
resizer.teardown();
|
||||||
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user