resources/js/wysiwyg/lexical/yjs/CollabDecoratorNode.ts
/**
* 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 {Binding} from '.';
import type {CollabElementNode} from './CollabElementNode';
import type {DecoratorNode, NodeKey, NodeMap} from 'lexical';
import type {XmlElement} from 'yjs';
import {$getNodeByKey, $isDecoratorNode} from 'lexical';
import invariant from 'lexical/shared/invariant';
import {syncPropertiesFromLexical, syncPropertiesFromYjs} from './Utils';
export class CollabDecoratorNode {
_xmlElem: XmlElement;
_key: NodeKey;
_parent: CollabElementNode;
_type: string;
constructor(xmlElem: XmlElement, parent: CollabElementNode, type: string) {
this._key = '';
this._xmlElem = xmlElem;
this._parent = parent;
this._type = type;
}
getPrevNode(nodeMap: null | NodeMap): null | DecoratorNode<unknown> {
if (nodeMap === null) {
return null;
}
const node = nodeMap.get(this._key);
return $isDecoratorNode(node) ? node : null;
}
getNode(): null | DecoratorNode<unknown> {
const node = $getNodeByKey(this._key);
return $isDecoratorNode(node) ? node : null;
}
getSharedType(): XmlElement {
return this._xmlElem;
}
getType(): string {
return this._type;
}
getKey(): NodeKey {
return this._key;
}
getSize(): number {
return 1;
}
getOffset(): number {
const collabElementNode = this._parent;
return collabElementNode.getChildOffset(this);
}
syncPropertiesFromLexical(
binding: Binding,
nextLexicalNode: DecoratorNode<unknown>,
prevNodeMap: null | NodeMap,
): void {
const prevLexicalNode = this.getPrevNode(prevNodeMap);
const xmlElem = this._xmlElem;
syncPropertiesFromLexical(
binding,
xmlElem,
prevLexicalNode,
nextLexicalNode,
);
}
syncPropertiesFromYjs(
binding: Binding,
keysChanged: null | Set<string>,
): void {
const lexicalNode = this.getNode();
invariant(
lexicalNode !== null,
'syncPropertiesFromYjs: could not find decorator node',
);
const xmlElem = this._xmlElem;
syncPropertiesFromYjs(binding, xmlElem, lexicalNode, keysChanged);
}
destroy(binding: Binding): void {
const collabNodeMap = binding.collabNodeMap;
collabNodeMap.delete(this._key);
}
}
export function $createCollabDecoratorNode(
xmlElem: XmlElement,
parent: CollabElementNode,
type: string,
): CollabDecoratorNode {
const collabNode = new CollabDecoratorNode(xmlElem, parent, type);
xmlElem._collabNode = collabNode;
return collabNode;
}