mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-01-03 23:42:28 +03:00
Lexical: Improved nested details interaction
- Set to open by default on insert. - Updated selection handling not to always fully cascade to lowest editable child on selection, so parents can be reliably selected. - Updated mouse handling to treat details panes like the root element, inserting within-details where relevant.
This commit is contained in:
@@ -383,6 +383,14 @@ export class LexicalNode {
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if this node should be selected directly instead of the default
|
||||
* where the selection would descend to the nearest initial child element.
|
||||
*/
|
||||
shouldSelectDirectly(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this nodes key.
|
||||
*/
|
||||
|
||||
@@ -476,12 +476,12 @@ export class RangeSelection implements BaseSelection {
|
||||
const startOffset = firstPoint.offset;
|
||||
const endOffset = lastPoint.offset;
|
||||
|
||||
if ($isElementNode(firstNode)) {
|
||||
if ($isElementNode(firstNode) && !firstNode.shouldSelectDirectly()) {
|
||||
const firstNodeDescendant =
|
||||
firstNode.getDescendantByIndex<ElementNode>(startOffset);
|
||||
firstNode = firstNodeDescendant != null ? firstNodeDescendant : firstNode;
|
||||
}
|
||||
if ($isElementNode(lastNode)) {
|
||||
if ($isElementNode(lastNode) && !lastNode.shouldSelectDirectly()) {
|
||||
let lastNodeDescendant =
|
||||
lastNode.getDescendantByIndex<ElementNode>(endOffset);
|
||||
// We don't want to over-select, as node selection infers the child before
|
||||
@@ -499,7 +499,7 @@ export class RangeSelection implements BaseSelection {
|
||||
let nodes: Array<LexicalNode>;
|
||||
|
||||
if (firstNode.is(lastNode)) {
|
||||
if ($isElementNode(firstNode) && firstNode.getChildrenSize() > 0) {
|
||||
if ($isElementNode(firstNode) && firstNode.getChildrenSize() > 0 && !firstNode.shouldSelectDirectly()) {
|
||||
nodes = [];
|
||||
} else {
|
||||
nodes = [firstNode];
|
||||
|
||||
@@ -150,6 +150,20 @@ export class ElementNode extends LexicalNode {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
getFirstSelectableDescendant<T extends LexicalNode>(): null | T {
|
||||
if (this.shouldSelectDirectly()) {
|
||||
return null;
|
||||
}
|
||||
let node = this.getFirstChild<T>();
|
||||
while ($isElementNode(node) && !node.shouldSelectDirectly()) {
|
||||
const child = node.getFirstChild<T>();
|
||||
if (child === null) {
|
||||
break;
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
getLastDescendant<T extends LexicalNode>(): null | T {
|
||||
let node = this.getLastChild<T>();
|
||||
while ($isElementNode(node)) {
|
||||
@@ -161,6 +175,20 @@ export class ElementNode extends LexicalNode {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
getLastSelectableDescendant<T extends LexicalNode>(): null | T {
|
||||
if (this.shouldSelectDirectly()) {
|
||||
return null;
|
||||
}
|
||||
let node = this.getLastChild<T>();
|
||||
while ($isElementNode(node) && !node.shouldSelectDirectly()) {
|
||||
const child = node.getLastChild<T>();
|
||||
if (child === null) {
|
||||
break;
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
getDescendantByIndex<T extends LexicalNode>(index: number): null | T {
|
||||
const children = this.getChildren<T>();
|
||||
const childrenLength = children.length;
|
||||
@@ -319,11 +347,11 @@ export class ElementNode extends LexicalNode {
|
||||
return selection;
|
||||
}
|
||||
selectStart(): RangeSelection {
|
||||
const firstNode = this.getFirstDescendant();
|
||||
const firstNode = this.getFirstSelectableDescendant();
|
||||
return firstNode ? firstNode.selectStart() : this.select();
|
||||
}
|
||||
selectEnd(): RangeSelection {
|
||||
const lastNode = this.getLastDescendant();
|
||||
const lastNode = this.getLastSelectableDescendant();
|
||||
return lastNode ? lastNode.selectEnd() : this.select();
|
||||
}
|
||||
clear(): this {
|
||||
|
||||
Reference in New Issue
Block a user