lexical
Version:
Lexical is an extensible text editor framework that provides excellent reliability, accessible and performance.
208 lines (207 loc) • 8.2 kB
TypeScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { DOMExportOutput, LexicalPrivateDOM, NodeKey, SerializedLexicalNode } from '../LexicalNode';
import type { BaseSelection, RangeSelection } from '../LexicalSelection';
import type { KlassConstructor, LexicalEditor, LexicalUpdateJSON, Spread, TextFormatType } from 'lexical';
import { TextNode } from '../index';
import { LexicalNode } from '../LexicalNode';
export type SerializedElementNode<T extends SerializedLexicalNode = SerializedLexicalNode> = Spread<{
children: Array<T>;
direction: 'ltr' | 'rtl' | null;
format: ElementFormatType;
indent: number;
textFormat?: number;
textStyle?: string;
}, SerializedLexicalNode>;
export type ElementFormatType = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
export interface ElementNode {
getTopLevelElement(): ElementNode | null;
getTopLevelElementOrThrow(): ElementNode;
}
/**
* A utility class for managing the DOM children of an ElementNode
*/
export declare class ElementDOMSlot<T extends HTMLElement = HTMLElement> {
readonly element: T;
readonly before: Node | null;
readonly after: Node | null;
constructor(
/** The element returned by createDOM */
element: T,
/** All managed children will be inserted before this node, if defined */
before?: Node | undefined | null,
/** All managed children will be inserted after this node, if defined */
after?: Node | undefined | null);
/**
* Return a new ElementDOMSlot where all managed children will be inserted before this node
*/
withBefore(before: Node | undefined | null): ElementDOMSlot<T>;
/**
* Return a new ElementDOMSlot where all managed children will be inserted after this node
*/
withAfter(after: Node | undefined | null): ElementDOMSlot<T>;
/**
* Return a new ElementDOMSlot with an updated root element
*/
withElement<ElementType extends HTMLElement>(element: ElementType): ElementDOMSlot<ElementType>;
/**
* Insert the given child before this.before and any reconciler managed line break node,
* or append it if this.before is not defined
*/
insertChild(dom: Node): this;
/**
* Remove the managed child from this container, will throw if it was not already there
*/
removeChild(dom: Node): this;
/**
* Replace managed child prevDom with dom. Will throw if prevDom is not a child
*
* @param dom The new node to replace prevDom
* @param prevDom the node that will be replaced
*/
replaceChild(dom: Node, prevDom: Node): this;
/**
* Returns the first managed child of this node,
* which will either be this.after.nextSibling or this.element.firstChild,
* and will never be this.before if it is defined.
*/
getFirstChild(): ChildNode | null;
/**
* @internal
*/
getManagedLineBreak(): Exclude<LexicalPrivateDOM['__lexicalLineBreak'], undefined>;
/** @internal */
setManagedLineBreak(lineBreakType: null | 'empty' | 'line-break' | 'decorator'): void;
/** @internal */
removeManagedLineBreak(): void;
/** @internal */
insertManagedLineBreak(webkitHack: boolean): void;
/**
* @internal
*
* Returns the offset of the first child
*/
getFirstChildOffset(): number;
/**
* @internal
*/
resolveChildIndex(element: ElementNode, elementDOM: HTMLElement, initialDOM: Node, initialOffset: number): [node: ElementNode, idx: number];
}
/** @noInheritDoc */
export declare class ElementNode extends LexicalNode {
['constructor']: KlassConstructor<typeof ElementNode>;
/** @internal */
__first: null | NodeKey;
/** @internal */
__last: null | NodeKey;
/** @internal */
__size: number;
/** @internal */
__format: number;
/** @internal */
__style: string;
/** @internal */
__indent: number;
/** @internal */
__dir: 'ltr' | 'rtl' | null;
/** @internal */
__textFormat: number;
/** @internal */
__textStyle: string;
constructor(key?: NodeKey);
afterCloneFrom(prevNode: this): void;
getFormat(): number;
getFormatType(): ElementFormatType;
getStyle(): string;
getIndent(): number;
getChildren<T extends LexicalNode>(): Array<T>;
getChildrenKeys(): Array<NodeKey>;
getChildrenSize(): number;
isEmpty(): boolean;
isDirty(): boolean;
isLastChild(): boolean;
getAllTextNodes(): Array<TextNode>;
getFirstDescendant<T extends LexicalNode>(): null | T;
getLastDescendant<T extends LexicalNode>(): null | T;
getDescendantByIndex<T extends LexicalNode>(index: number): null | T;
getFirstChild<T extends LexicalNode>(): null | T;
getFirstChildOrThrow<T extends LexicalNode>(): T;
getLastChild<T extends LexicalNode>(): null | T;
getLastChildOrThrow<T extends LexicalNode>(): T;
getChildAtIndex<T extends LexicalNode>(index: number): null | T;
getTextContent(): string;
getTextContentSize(): number;
getDirection(): 'ltr' | 'rtl' | null;
getTextFormat(): number;
hasFormat(type: ElementFormatType): boolean;
hasTextFormat(type: TextFormatType): boolean;
/**
* Returns the format flags applied to the node as a 32-bit integer.
*
* @returns a number representing the TextFormatTypes applied to the node.
*/
getFormatFlags(type: TextFormatType, alignWithFormat: null | number): number;
getTextStyle(): string;
select(_anchorOffset?: number, _focusOffset?: number): RangeSelection;
selectStart(): RangeSelection;
selectEnd(): RangeSelection;
clear(): this;
append(...nodesToAppend: LexicalNode[]): this;
setDirection(direction: 'ltr' | 'rtl' | null): this;
setFormat(type: ElementFormatType): this;
setStyle(style: string): this;
setTextFormat(type: number): this;
setTextStyle(style: string): this;
setIndent(indentLevel: number): this;
splice(start: number, deleteCount: number, nodesToInsert: Array<LexicalNode>): this;
/**
* @internal
*
* An experimental API that an ElementNode can override to control where its
* children are inserted into the DOM, this is useful to add a wrapping node
* or accessory nodes before or after the children. The root of the node returned
* by createDOM must still be exactly one HTMLElement.
*/
getDOMSlot(element: HTMLElement): ElementDOMSlot<HTMLElement>;
exportDOM(editor: LexicalEditor): DOMExportOutput;
exportJSON(): SerializedElementNode;
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedElementNode>): this;
insertNewAfter(selection: RangeSelection, restoreSelection?: boolean): null | LexicalNode;
canIndent(): boolean;
collapseAtStart(selection: RangeSelection): boolean;
excludeFromCopy(destination?: 'clone' | 'html'): boolean;
/** @deprecated @internal */
canReplaceWith(replacement: LexicalNode): boolean;
/** @deprecated @internal */
canInsertAfter(node: LexicalNode): boolean;
canBeEmpty(): boolean;
canInsertTextBefore(): boolean;
canInsertTextAfter(): boolean;
isInline(): boolean;
isShadowRoot(): boolean;
/** @deprecated @internal */
canMergeWith(node: ElementNode): boolean;
extractWithChild(child: LexicalNode, selection: BaseSelection | null, destination: 'clone' | 'html'): boolean;
/**
* Determines whether this node, when empty, can merge with a first block
* of nodes being inserted.
*
* This method is specifically called in {@link RangeSelection.insertNodes}
* to determine merging behavior during nodes insertion.
*
* @example
* // In a ListItemNode or QuoteNode implementation:
* canMergeWhenEmpty(): true {
* return true;
* }
*/
canMergeWhenEmpty(): boolean;
/** @internal */
reconcileObservedMutation(dom: HTMLElement, editor: LexicalEditor): void;
}
export declare function $isElementNode(node: LexicalNode | null | undefined): node is ElementNode;