@lexical/react 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEPRECATED_useLexical.dev.js +84 -0
- package/DEPRECATED_useLexical.js +9 -2
- package/DEPRECATED_useLexical.prod.js +8 -0
- package/DEPRECATED_useLexicalAutoFormatter.dev.js +642 -0
- package/DEPRECATED_useLexicalAutoFormatter.js +9 -11
- package/DEPRECATED_useLexicalAutoFormatter.prod.js +22 -0
- package/DEPRECATED_useLexicalCanShowPlaceholder.dev.js +136 -0
- package/DEPRECATED_useLexicalCanShowPlaceholder.js +9 -3
- package/DEPRECATED_useLexicalCanShowPlaceholder.prod.js +8 -0
- package/DEPRECATED_useLexicalCharacterLimit.dev.js +294 -0
- package/DEPRECATED_useLexicalCharacterLimit.js +9 -8
- package/DEPRECATED_useLexicalCharacterLimit.prod.js +14 -0
- package/DEPRECATED_useLexicalDecorators.dev.js +82 -0
- package/DEPRECATED_useLexicalDecorators.js +9 -2
- package/DEPRECATED_useLexicalDecorators.prod.js +8 -0
- package/DEPRECATED_useLexicalEditor.dev.js +52 -0
- package/DEPRECATED_useLexicalEditor.js +9 -1
- package/DEPRECATED_useLexicalEditor.prod.js +7 -0
- package/DEPRECATED_useLexicalEditorEvents.dev.js +96 -0
- package/DEPRECATED_useLexicalEditorEvents.js +9 -2
- package/DEPRECATED_useLexicalEditorEvents.prod.js +8 -0
- package/DEPRECATED_useLexicalHistory.dev.js +339 -0
- package/DEPRECATED_useLexicalHistory.js +9 -7
- package/DEPRECATED_useLexicalHistory.prod.js +13 -0
- package/DEPRECATED_useLexicalList.dev.js +64 -0
- package/DEPRECATED_useLexicalList.js +9 -1
- package/DEPRECATED_useLexicalList.prod.js +7 -0
- package/DEPRECATED_useLexicalPlainText.dev.js +755 -0
- package/DEPRECATED_useLexicalPlainText.js +9 -16
- package/DEPRECATED_useLexicalPlainText.prod.js +22 -0
- package/DEPRECATED_useLexicalRichText.dev.js +1326 -0
- package/DEPRECATED_useLexicalRichText.js +9 -30
- package/DEPRECATED_useLexicalRichText.prod.js +35 -0
- package/LexicalAutoFormatterPlugin.dev.js +645 -0
- package/LexicalAutoFormatterPlugin.js +9 -12
- package/LexicalAutoFormatterPlugin.prod.js +23 -0
- package/LexicalAutoLinkPlugin.dev.js +227 -0
- package/LexicalAutoLinkPlugin.js +9 -6
- package/LexicalAutoLinkPlugin.prod.js +12 -0
- package/LexicalBootstrapPlugin.dev.js +124 -0
- package/LexicalBootstrapPlugin.js +9 -0
- package/LexicalBootstrapPlugin.prod.js +8 -0
- package/LexicalCharacterLimitPlugin.dev.js +352 -0
- package/LexicalCharacterLimitPlugin.js +9 -8
- package/LexicalCharacterLimitPlugin.prod.js +14 -0
- package/LexicalCollaborationPlugin.dev.js +235 -0
- package/LexicalCollaborationPlugin.js +9 -8
- package/LexicalCollaborationPlugin.prod.js +14 -0
- package/LexicalComposer.dev.js +76 -0
- package/LexicalComposer.js +9 -3
- package/LexicalComposer.prod.js +9 -0
- package/LexicalComposerContext.dev.js +53 -0
- package/LexicalComposerContext.js +9 -1
- package/LexicalComposerContext.prod.js +7 -0
- package/LexicalContentEditable.dev.js +71 -0
- package/LexicalContentEditable.js +9 -3
- package/LexicalContentEditable.prod.js +9 -0
- package/LexicalHashtagPlugin.dev.js +152 -0
- package/LexicalHashtagPlugin.js +9 -4
- package/LexicalHashtagPlugin.prod.js +10 -0
- package/LexicalHistoryPlugin.dev.js +344 -0
- package/LexicalHistoryPlugin.js +9 -7
- package/LexicalHistoryPlugin.prod.js +13 -0
- package/LexicalHorizontalRulePlugin.dev.js +51 -0
- package/LexicalHorizontalRulePlugin.js +9 -1
- package/LexicalHorizontalRulePlugin.prod.js +7 -0
- package/LexicalLinkPlugin.dev.js +137 -0
- package/LexicalLinkPlugin.js +9 -3
- package/LexicalLinkPlugin.prod.js +9 -0
- package/LexicalListPlugin.dev.js +67 -0
- package/LexicalListPlugin.js +9 -2
- package/LexicalListPlugin.prod.js +8 -0
- package/LexicalNestedComposer.dev.js +60 -0
- package/LexicalNestedComposer.js +9 -2
- package/LexicalNestedComposer.prod.js +8 -0
- package/LexicalOnChangePlugin.dev.js +57 -0
- package/LexicalOnChangePlugin.js +9 -1
- package/LexicalOnChangePlugin.prod.js +7 -0
- package/LexicalPlainTextPlugin.dev.js +565 -0
- package/LexicalPlainTextPlugin.js +9 -13
- package/LexicalPlainTextPlugin.prod.js +17 -0
- package/LexicalRichTextPlugin.dev.js +1136 -0
- package/LexicalRichTextPlugin.js +9 -27
- package/LexicalRichTextPlugin.prod.js +31 -0
- package/LexicalTablePlugin.dev.js +95 -0
- package/LexicalTablePlugin.js +9 -3
- package/LexicalTablePlugin.prod.js +9 -0
- package/LexicalTreeView.dev.js +340 -0
- package/LexicalTreeView.js +9 -13
- package/LexicalTreeView.prod.js +19 -0
- package/README.md +1 -0
- package/package.json +4 -4
- package/useLexicalDecoratorMap.dev.js +83 -0
- package/useLexicalDecoratorMap.js +9 -2
- package/useLexicalDecoratorMap.prod.js +8 -0
- package/useLexicalIsTextContentEmpty.dev.js +84 -0
- package/useLexicalIsTextContentEmpty.js +9 -2
- package/useLexicalIsTextContentEmpty.prod.js +8 -0
- package/withSubscriptions.dev.js +23 -0
- package/withSubscriptions.js +9 -1
- package/withSubscriptions.prod.js +7 -0
package/LexicalRichTextPlugin.js
CHANGED
|
@@ -1,27 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
a.parentNode;null!=f&&a!==f.lastChild&&c.push(x.$createLineBreakNode());return c}})};
|
|
11
|
-
function J(a,c,f,e=new Map){let d=[],b=null;var k=a.nodeName.toLowerCase(),h=(f._config.htmlTransforms||{})[k]||c[k],l=h?h(a):null;h=null;if(null!==l){h=l.after;b=l.node;if(null!==b){d.push(b);const q=Array.from(e.values());for(let m=0;m<q.length;m++)q[m](b)}null!=l.forChild&&e.set(k,l.forChild)}a=a.childNodes;k=[];for(l=0;l<a.length;l++)k.push(...J(a[l],c,f,e));null!=h&&(k=h(k));null==b?d=d.concat(k):x.$isElementNode(b)&&b.append(...k);return d}
|
|
12
|
-
function K(a,c,f){var e=a.getData("application/x-lexical-editor");if(e){var d=f._config.namespace;try{const l=JSON.parse(e);if(l.namespace===d){const {range:q,nodeMap:m}=l.state;var b=new Map(m);e=[];for(d=0;d<q.length;d++){var k=b.get(q[d]);if(void 0!==k){var h=x.$createNodeFromParse(k,b);e.push(h)}}c.insertNodes(e);return}}catch(l){}}if(b=a.getData("text/html")){b=(new DOMParser).parseFromString(b,"text/html");a=[];b=b.body?Array.from(b.body.childNodes):[];k=b.length;for(h=0;h<k;h++)e=J(b[h],I,
|
|
13
|
-
f),null!==e&&(a=a.concat(e));f=a;a=[];b=null;for(k=0;k<f.length;k++)h=f[k],!x.$isElementNode(h)||h.isInline()?(null===b&&(b=x.$createParagraphNode(),a.push(b)),null!==b&&b.append(h)):(a.push(h),b=null);c.insertNodes(a)}else f=a.getData("text/plain"),null!=f&&c.insertRawText(f)}
|
|
14
|
-
function L(a,c){var f=a.focus;a=f.offset;"element"===f.type?c=f.getNode().getChildAtIndex(c?a-1:a):(f=f.getNode(),c=c&&0===a||!c&&a===f.getTextContentSize()?c?f.getPreviousSibling():f.getNextSibling():null);return x.$isDecoratorNode(c)}function M(a,c){a.preventDefault();c.update(()=>{x.$log("onPasteForRichText");const f=x.$getSelection(),e=a.clipboardData;null!=e&&null!==f&&K(e,f,c)})}
|
|
15
|
-
function N(a,c){O(a,c);c.update(()=>{x.$log("onCutForRichText");const f=x.$getSelection();null!==f&&f.removeText()})}
|
|
16
|
-
function O(a,c){a.preventDefault();c.update(()=>{x.$log("onCopyForRichText");const f=a.clipboardData;var e=x.$getSelection();if(null!==e&&null!=f){var d=window.getSelection();if(!d.isCollapsed){var b=d.getRangeAt(0);b&&(d=document.createElement("div"),b=b.cloneContents(),d.appendChild(b),f.setData("text/html",d.innerHTML));f.setData("text/plain",e.getTextContent());d=c._config.namespace;b=f.setData;var k=JSON,h=k.stringify;{var l=e.anchor,q=e.focus;var m=l.getCharacterOffset();const y=q.getCharacterOffset();
|
|
17
|
-
var n=l.getNode(),r=q.getNode(),p=n.getParentOrThrow();if(n===r&&x.$isTextNode(n)&&(p.canBeEmpty()||1<p.getChildrenSize()))e=G(n),n=y>m,e.__text=e.__text.slice(n?m:y,n?y:m),m=e.getKey(),m={range:[m],nodeMap:[[m,e]]};else if(e=e.getNodes(),0===e.length)m={range:[],nodeMap:[]};else{n=e.length;r=e[0];p=r.getParent();if(null!==p&&!p.canBeEmpty()){var t=p.__children;if(t.length===n){var u=!0;for(var w=0;w<t.length;w++)if(t[w]!==e[w].__key){u=!1;break}u&&(n++,e.push(p))}}p=e[n-1];l=l.isBefore(q);q=new Map;
|
|
18
|
-
t=[];H(r,l?m:y,!0,t,q);for(r=0;r<n;r++)if(u=e[r],w=u.getKey(),!(q.has(w)||x.$isElementNode(u)&&u.excludeFromCopy())){const S=G(u);x.$isRootNode(u.getParent())&&t.push(u.getKey());q.set(w,S)}H(p,l?y:m,!1,t,q);m={range:t,nodeMap:Array.from(q.entries())}}}b.call(f,"application/x-lexical-editor",h.call(k,{namespace:d,state:m}))}}})}var P="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?g.useLayoutEffect:g.useEffect;
|
|
19
|
-
function Q(a,c){const f=x.$createParagraphNode();a.append(f);a=document.activeElement;(null!==x.$getSelection()||null!==a&&a===c.getRootElement())&&f.select()}function R(a){a.update(()=>{x.$log("initEditor");const c=x.$getRoot();null===c.getFirstChild()&&Q(c,a)})}function T(a,c){a.update(()=>{x.$log("clearEditor");const f=x.$getRoot();f.clear();Q(f,a)},{onUpdate:c})}
|
|
20
|
-
function U(a,c){P(()=>{const f=D(a.addListener("command",(e,d)=>{var b=x.$getSelection();if(null===b)return!1;switch(e){case "deleteCharacter":return b.deleteCharacter(d),!0;case "deleteWord":return b.deleteWord(d),!0;case "deleteLine":return b.deleteLine(d),!0;case "insertText":return"string"===typeof d?b.insertText(d):(e=d.dataTransfer,null!=e?K(e,b,a):(d=d.data)&&b.insertText(d)),!0;case "removeText":return b.removeText(),!0;case "formatText":return b.formatText(d),!0;case "formatElement":return b=
|
|
21
|
-
b.anchor.getNode(),(x.$isElementNode(b)?b:b.getParentOrThrow()).setFormat(d),!0;case "insertLineBreak":return b.insertLineBreak(d),!0;case "insertParagraph":return b.insertParagraph(),!0;case "indentContent":return b=b.anchor,b="element"===b.type?b.getNode():b.getNode().getParentOrThrow(),b.canInsertTab()?a.execCommand("insertText","\t"):10!==b.getIndent()&&b.setIndent(b.getIndent()+1),!0;case "outdentContent":return b=b.anchor,d=b.getNode(),e="element"===b.type?b.getNode():b.getNode().getParentOrThrow(),
|
|
22
|
-
e.canInsertTab()?"\t"===d.getTextContent()[b.offset-1]&&a.execCommand("deleteCharacter",!0):0!==e.getIndent()&&e.setIndent(e.getIndent()-1),!0;case "keyArrowLeft":e=d.shiftKey;if(L(b,!0))return d.preventDefault(),d=e,e="rtl"===b.anchor.getNode().getParentOrThrow().getDirection(),b.modify(d?"extend":"move",!e,"character"),!0;break;case "keyArrowRight":e=d.shiftKey;if(L(b,!1))return d.preventDefault(),d=e,e="rtl"===b.anchor.getNode().getParentOrThrow().getDirection(),b.modify(d?"extend":"move",e,"character"),
|
|
23
|
-
!0;break;case "keyBackspace":return d.preventDefault(),{anchor:d}=b,b.isCollapsed()&&0===d.offset&&0<("element"===d.type?d.getNode():d.getNode().getParentOrThrow()).getIndent()?a.execCommand("outdentContent"):a.execCommand("deleteCharacter",!0);case "keyDelete":return d.preventDefault(),a.execCommand("deleteCharacter",!1);case "keyEnter":return d.preventDefault(),d.shiftKey?a.execCommand("insertLineBreak"):a.execCommand("insertParagraph");case "keyTab":return d.preventDefault(),a.execCommand(d.shiftKey?
|
|
24
|
-
"outdentContent":"indentContent");case "keyEscape":return a.blur(),!0;case "clearEditor":T(a);break;case "copy":return O(d,a),!0;case "cut":return N(d,a),!0;case "paste":return M(d,a),!0;case "drop":case "dragstart":return d.preventDefault(),!0}return!1},0));c&&R(a);return f},[a,c]);F(a)}
|
|
25
|
-
function V(a){const [c,f]=g.useState(()=>a.getDecorators());P(()=>a.addListener("decorator",e=>{E.flushSync(()=>{f(e)})}),[a]);return g.useMemo(()=>{const e=[],d=Object.keys(c);for(let k=0;k<d.length;k++){var b=d[k];const h=c[b];b=a.getElementByKey(b);null!==b&&e.push(E.createPortal(h,b))}return e},[c,a])}function W(a,c=!0){if(a)return!1;a=x.$getRoot().getTextContent();c&&(a=a.trim());return""===a}
|
|
26
|
-
function X(a){if(!W(a,!1))return!1;a=x.$getRoot().getChildren();const c=a.length;if(1<c)return!1;for(let e=0;e<c;e++){var f=a[e];if(x.$isElementNode(f)){if("paragraph"!==f.__type||0!==f.__indent)return!1;f=f.getChildren();const d=f.length;for(let b=0;b<d;b++)if(!x.$isTextNode(f[e]))return!1}}return!0}function Y(a){return()=>X(a)}
|
|
27
|
-
function Z(a){const [c,f]=g.useState(a.getEditorState().read(Y(a.isComposing())));P(()=>a.addListener("update",({editorState:e})=>{const d=a.isComposing();e=e.read(Y(d));f(e)}),[a]);return c}module.exports=function({contentEditable:a,placeholder:c,skipInit:f}){const [e]=v.useLexicalComposerContext(),d=Z(e);U(e,!f);f=V(e);return g.createElement(g.Fragment,null,a,d&&c,f)};
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict'
|
|
8
|
+
const LexicalRichTextPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalRichTextPlugin.dev.js') : require('./LexicalRichTextPlugin.prod.js')
|
|
9
|
+
module.exports = LexicalRichTextPlugin;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';var g=require("@lexical/react/LexicalComposerContext"),v=require("react"),x=require("lexical"),z=require("react-dom"),A=require("@lexical/list"),B=require("lexical/CodeNode"),C=require("lexical/HeadingNode"),D=require("lexical/LinkNode");function E(a,e=!0){if(a)return!1;a=x.$getRoot().getTextContent();e&&(a=a.trim());return""===a}
|
|
8
|
+
function F(a){if(!E(a,!1))return!1;a=x.$getRoot().getChildren();const e=a.length;if(1<e)return!1;for(let b=0;b<e;b++){var c=a[b];if(x.$isElementNode(c)){if("paragraph"!==c.__type||0!==c.__indent)return!1;c=c.getChildren();const d=c.length;for(let f=0;f<d;f++)if(!x.$isTextNode(c[b]))return!1}}return!0}function G(a){return()=>F(a)}var H="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?v.useLayoutEffect:v.useEffect;
|
|
9
|
+
function I(a){const [e,c]=v.useState(a.getEditorState().read(G(a.isComposing())));H(()=>a.addListener("update",({editorState:b})=>{const d=a.isComposing();b=b.read(G(d));c(b)}),[a]);return e}function J(a){const [e,c]=v.useState(()=>a.getDecorators());H(()=>a.addListener("decorator",b=>{z.flushSync(()=>{c(b)})}),[a]);return v.useMemo(()=>{const b=[],d=Object.keys(e);for(let k=0;k<d.length;k++){var f=d[k];const h=e[f];f=a.getElementByKey(f);null!==f&&b.push(z.createPortal(h,f))}return b},[e,a])}
|
|
10
|
+
function K(a){a=a.getLatest();const e=a.constructor.clone(a);e.__parent=a.__parent;x.$isElementNode(a)&&x.$isElementNode(e)?(e.__children=Array.from(a.__children),e.__format=a.__format,e.__indent=a.__indent,e.__dir=a.__dir):x.$isTextNode(a)&&x.$isTextNode(e)?(e.__format=a.__format,e.__style=a.__style,e.__mode=a.__mode,e.__detail=a.__detail):x.$isDecoratorNode(a)&&x.$isDecoratorNode(e)&&(e.__state=a.__state);return e}
|
|
11
|
+
function L(a,e,c,b,d){for(var f=e;null!==a;){for(e=a.getParent();null!==e&&e.excludeFromCopy();)e=e.getParent();if(null===e)break;if(!x.$isElementNode(a)||!a.excludeFromCopy()){const k=a.getKey();let h=d.get(k);const l=void 0===h;l&&(h=K(a),d.set(k,h));!x.$isTextNode(h)||h.isSegmented()||h.isToken()?x.$isElementNode(h)&&(h.__children=h.__children.slice(c?f:0,c?void 0:f+1)):h.__text=h.__text.slice(c?f:0,c?void 0:f);if(x.$isRootNode(e)){l&&b.push(k);break}}f=d.get(e.getKey());f=x.$isElementNode(f)?
|
|
12
|
+
f.__children.indexOf(a.getKey()):a.getIndexWithinParent();a=e}}
|
|
13
|
+
const M={"#text":a=>({node:x.$createTextNode(a.textContent)}),a:a=>({node:a instanceof HTMLAnchorElement?D.$createLinkNode(a.href):x.$createTextNode(a.textContent)}),b:a=>{const e="normal"===a.style.fontWeight;return{forChild:c=>{x.$isTextNode(c)&&!e&&c.toggleFormat("bold")},node:null}},br:()=>({node:x.$createLineBreakNode()}),div:a=>({after:e=>{const c=a.parentNode;null!=c&&a!==c.lastChild&&e.push(x.$createLineBreakNode());return e},node:null!==a.style.fontFamily.match("monospace")?B.$createCodeNode():
|
|
14
|
+
null}),em:()=>({forChild:a=>{x.$isTextNode(a)&&a.toggleFormat("italic")},node:null}),h1:()=>({node:C.$createHeadingNode("h1")}),h2:()=>({node:C.$createHeadingNode("h2")}),h3:()=>({node:C.$createHeadingNode("h3")}),h4:()=>({node:C.$createHeadingNode("h4")}),h5:()=>({node:C.$createHeadingNode("h5")}),i:()=>({forChild:a=>{x.$isTextNode(a)&&a.toggleFormat("italic")},node:null}),li:()=>({node:A.$createListItemNode()}),ol:()=>({node:A.$createListNode("ol")}),p:()=>({node:x.$createParagraphNode()}),pre:()=>
|
|
15
|
+
({node:B.$createCodeNode()}),span:a=>{const e="700"===a.style.fontWeight;return{forChild:c=>{x.$isTextNode(c)&&e&&c.toggleFormat("bold")},node:null}},strong:()=>({forChild:a=>{x.$isTextNode(a)&&a.toggleFormat("bold")},node:null}),table:a=>({node:a.classList.contains("js-file-line-container")?B.$createCodeNode():null}),td:a=>{const e=a.classList.contains("js-file-line");return{after:c=>{e&&a.parentNode&&a.parentNode.nextSibling&&c.push(x.$createLineBreakNode());return c},node:null}},u:()=>({forChild:a=>
|
|
16
|
+
{x.$isTextNode(a)&&a.toggleFormat("underline")},node:null}),ul:()=>({node:A.$createListNode("ul")})};
|
|
17
|
+
function N(a,e,c,b=new Map){let d=[],f=null;var k=a.nodeName.toLowerCase(),h=(c._config.htmlTransforms||{})[k]||e[k],l=h?h(a):null;h=null;if(null!==l){h=l.after;f=l.node;if(null!==f){d.push(f);const q=Array.from(b.values());for(let m=0;m<q.length;m++)q[m](f)}null!=l.forChild&&b.set(k,l.forChild)}a=a.childNodes;k=[];for(l=0;l<a.length;l++)k.push(...N(a[l],e,c,b));null!=h&&(k=h(k));null==f?d=d.concat(k):x.$isElementNode(f)&&f.append(...k);return d}
|
|
18
|
+
function O(a,e,c){var b=a.getData("application/x-lexical-editor");if(b){var d=c._config.namespace;try{const l=JSON.parse(b);if(l.namespace===d){const {range:q,nodeMap:m}=l.state;var f=new Map(m);b=[];for(d=0;d<q.length;d++){var k=f.get(q[d]);if(void 0!==k){var h=x.$createNodeFromParse(k,f);b.push(h)}}e.insertNodes(b);return}}catch(l){}}if(f=a.getData("text/html")){f=(new DOMParser).parseFromString(f,"text/html");a=[];f=f.body?Array.from(f.body.childNodes):[];k=f.length;for(h=0;h<k;h++)b=N(f[h],M,
|
|
19
|
+
c),null!==b&&(a=a.concat(b));c=a;a=[];f=null;for(k=0;k<c.length;k++)h=c[k],!x.$isElementNode(h)||h.isInline()?(null===f&&(f=x.$createParagraphNode(),a.push(f)),null!==f&&f.append(h)):(a.push(h),f=null);e.insertNodes(a)}else c=a.getData("text/plain"),null!=c&&e.insertRawText(c)}
|
|
20
|
+
function P(a,e){var c=a.focus;a=c.offset;"element"===c.type?e=c.getNode().getChildAtIndex(e?a-1:a):(c=c.getNode(),e=e&&0===a||!e&&a===c.getTextContentSize()?e?c.getPreviousSibling():c.getNextSibling():null);return x.$isDecoratorNode(e)}function Q(a,e){a.preventDefault();e.update(()=>{x.$log("onPasteForRichText");const c=x.$getSelection(),b=a.clipboardData;null!=b&&null!==c&&O(b,c,e)})}
|
|
21
|
+
function R(a,e){S(a,e);e.update(()=>{x.$log("onCutForRichText");const c=x.$getSelection();null!==c&&c.removeText()})}
|
|
22
|
+
function S(a,e){a.preventDefault();e.update(()=>{x.$log("onCopyForRichText");const c=a.clipboardData;var b=x.$getSelection();if(null!==b&&null!=c){var d=window.getSelection();if(!d.isCollapsed){var f=d.getRangeAt(0);f&&(d=document.createElement("div"),f=f.cloneContents(),d.appendChild(f),c.setData("text/html",d.innerHTML));c.setData("text/plain",b.getTextContent());d=e._config.namespace;f=c.setData;var k=JSON,h=k.stringify;{var l=b.anchor,q=b.focus;var m=l.getCharacterOffset();const y=q.getCharacterOffset();
|
|
23
|
+
var n=l.getNode(),r=q.getNode(),p=n.getParentOrThrow();if(n===r&&x.$isTextNode(n)&&(p.canBeEmpty()||1<p.getChildrenSize()))b=K(n),n=y>m,b.__text=b.__text.slice(n?m:y,n?y:m),m=b.getKey(),m={nodeMap:[[m,b]],range:[m]};else if(b=b.getNodes(),0===b.length)m={nodeMap:[],range:[]};else{n=b.length;r=b[0];p=r.getParent();if(null!==p&&!p.canBeEmpty()){var t=p.__children;if(t.length===n){var u=!0;for(var w=0;w<t.length;w++)if(t[w]!==b[w].__key){u=!1;break}u&&(n++,b.push(p))}}p=b[n-1];l=l.isBefore(q);q=new Map;
|
|
24
|
+
t=[];L(r,l?m:y,!0,t,q);for(r=0;r<n;r++)if(u=b[r],w=u.getKey(),!(q.has(w)||x.$isElementNode(u)&&u.excludeFromCopy())){const T=K(u);x.$isRootNode(u.getParent())&&t.push(u.getKey());q.set(w,T)}L(p,l?y:m,!1,t,q);m={nodeMap:Array.from(q.entries()),range:t}}}f.call(c,"application/x-lexical-editor",h.call(k,{namespace:d,state:m}))}}})}
|
|
25
|
+
function U(a){v.useEffect(()=>{const e=c=>{var b=a.getRootElement();if(document.activeElement===b&&(b=c.data,"string"===typeof b)){try{var d=JSON.parse(b)}catch(f){return}if(d&&"nuanria_messaging"===d.protocol&&"request"===d.type&&(d=d.payload)&&"makeChanges"===d.functionId&&(d=d.args)){const [f,k,h,l,q]=d;a.update(()=>{x.$log("useLexicalDragonSupport");const m=x.$getSelection();if(null!==m){var n=m.anchor;let r=n.getNode(),p=0,t=0;x.$isTextNode(r)&&0<=f&&0<=k&&(p=f,t=f+k,m.setTextNodeRange(r,p,r,
|
|
26
|
+
t));if(p!==t||""!==h)m.insertRawText(h),r=n.getNode();x.$isTextNode(r)&&(p=l,t=l+q,n=r.getTextContentSize(),p=p>n?n:p,t=t>n?n:t,m.setTextNodeRange(r,p,r,t));c.stopImmediatePropagation()}})}}};window.addEventListener("message",e,!0);return()=>{window.removeEventListener("message",e,!0)}},[a])}
|
|
27
|
+
function V(a){H(()=>{const e=a.addListener("command",(c,b)=>{var d=x.$getSelection();if(null===d)return!1;switch(c){case "deleteCharacter":return d.deleteCharacter(b),!0;case "deleteWord":return d.deleteWord(b),!0;case "deleteLine":return d.deleteLine(b),!0;case "insertText":return"string"===typeof b?d.insertText(b):(c=b.dataTransfer,null!=c?O(c,d,a):(b=b.data)&&d.insertText(b)),!0;case "removeText":return d.removeText(),!0;case "formatText":return d.formatText(b),!0;case "formatElement":return d=
|
|
28
|
+
d.anchor.getNode(),(x.$isElementNode(d)?d:d.getParentOrThrow()).setFormat(b),!0;case "insertLineBreak":return d.insertLineBreak(b),!0;case "insertParagraph":return d.insertParagraph(),!0;case "indentContent":return d=d.anchor,d="element"===d.type?d.getNode():d.getNode().getParentOrThrow(),d.canInsertTab()?a.execCommand("insertText","\t"):10!==d.getIndent()&&d.setIndent(d.getIndent()+1),!0;case "outdentContent":return d=d.anchor,b=d.getNode(),c="element"===d.type?d.getNode():d.getNode().getParentOrThrow(),
|
|
29
|
+
c.canInsertTab()?"\t"===b.getTextContent()[d.offset-1]&&a.execCommand("deleteCharacter",!0):0!==c.getIndent()&&c.setIndent(c.getIndent()-1),!0;case "keyArrowLeft":c=b.shiftKey;if(P(d,!0))return b.preventDefault(),b=c,c="rtl"===d.anchor.getNode().getParentOrThrow().getDirection(),d.modify(b?"extend":"move",!c,"character"),!0;break;case "keyArrowRight":c=b.shiftKey;if(P(d,!1))return b.preventDefault(),b=c,c="rtl"===d.anchor.getNode().getParentOrThrow().getDirection(),d.modify(b?"extend":"move",c,"character"),
|
|
30
|
+
!0;break;case "keyBackspace":return b.preventDefault(),{anchor:b}=d,d.isCollapsed()&&0===b.offset&&0<("element"===b.type?b.getNode():b.getNode().getParentOrThrow()).getIndent()?a.execCommand("outdentContent"):a.execCommand("deleteCharacter",!0);case "keyDelete":return b.preventDefault(),a.execCommand("deleteCharacter",!1);case "keyEnter":return b.preventDefault(),b.shiftKey?a.execCommand("insertLineBreak"):a.execCommand("insertParagraph");case "keyTab":return b.preventDefault(),a.execCommand(b.shiftKey?
|
|
31
|
+
"outdentContent":"indentContent");case "keyEscape":return a.blur(),!0;case "copy":return S(b,a),!0;case "cut":return R(b,a),!0;case "paste":return Q(b,a),!0;case "drop":case "dragstart":return b.preventDefault(),!0}return!1},0);a.execCommand("bootstrapEditor");return e},[a]);U(a)}module.exports=function({contentEditable:a,placeholder:e}){var [c]=g.useLexicalComposerContext();const b=I(c);V(c);c=J(c);return v.createElement(v.Fragment,null,a,b&&e,c)};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var lexical = require('lexical');
|
|
10
|
+
var TableCellNode = require('lexical/TableCellNode');
|
|
11
|
+
var TableNode = require('lexical/TableNode');
|
|
12
|
+
var TableRowNode = require('lexical/TableRowNode');
|
|
13
|
+
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
14
|
+
var react = require('react');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
18
|
+
*
|
|
19
|
+
* This source code is licensed under the MIT license found in the
|
|
20
|
+
* LICENSE file in the root directory of this source tree.
|
|
21
|
+
*
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
function $createTableNodeWithDimensions(rowCount, columnCount, includeHeader = true) {
|
|
25
|
+
const tableNode = TableNode.$createTableNode();
|
|
26
|
+
|
|
27
|
+
for (let iRow = 0; iRow < rowCount; iRow++) {
|
|
28
|
+
const tableRowNode = TableRowNode.$createTableRowNode();
|
|
29
|
+
|
|
30
|
+
for (let iColumn = 0; iColumn < columnCount; iColumn++) {
|
|
31
|
+
const tableCellNode = TableCellNode.$createTableCellNode(iRow === 0 && includeHeader);
|
|
32
|
+
const paragraphNode = lexical.$createParagraphNode();
|
|
33
|
+
paragraphNode.append(lexical.$createTextNode());
|
|
34
|
+
tableCellNode.append(paragraphNode);
|
|
35
|
+
tableRowNode.append(tableCellNode);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
tableNode.append(tableRowNode);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return tableNode;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
46
|
+
*
|
|
47
|
+
* This source code is licensed under the MIT license found in the
|
|
48
|
+
* LICENSE file in the root directory of this source tree.
|
|
49
|
+
*
|
|
50
|
+
*
|
|
51
|
+
*/
|
|
52
|
+
const EditorPriority = 0;
|
|
53
|
+
function TablePlugin() {
|
|
54
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
55
|
+
react.useEffect(() => {
|
|
56
|
+
if (!editor.hasNodes([TableNode.TableNode, TableCellNode.TableCellNode, TableRowNode.TableRowNode])) {
|
|
57
|
+
{
|
|
58
|
+
throw Error(`TablePlugin: TableNode, TableCellNode or TableRowNode not registered on editor`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return editor.addListener('command', (type, payload) => {
|
|
63
|
+
if (type === 'insertTable') {
|
|
64
|
+
const {
|
|
65
|
+
columns,
|
|
66
|
+
rows
|
|
67
|
+
} = payload;
|
|
68
|
+
lexical.$log('handleAddTable');
|
|
69
|
+
const selection = lexical.$getSelection();
|
|
70
|
+
|
|
71
|
+
if (selection === null) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const focusNode = selection.focus.getNode();
|
|
76
|
+
|
|
77
|
+
if (focusNode !== null) {
|
|
78
|
+
const topLevelNode = focusNode.getTopLevelElementOrThrow();
|
|
79
|
+
const tableNode = $createTableNodeWithDimensions(rows, columns);
|
|
80
|
+
topLevelNode.insertAfter(tableNode);
|
|
81
|
+
tableNode.insertAfter(lexical.$createParagraphNode());
|
|
82
|
+
const firstCell = tableNode.getFirstChildOrThrow().getFirstChildOrThrow();
|
|
83
|
+
firstCell.select();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return false;
|
|
90
|
+
}, EditorPriority);
|
|
91
|
+
}, [editor]);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = TablePlugin;
|
package/LexicalTablePlugin.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict'
|
|
8
|
+
const LexicalTablePlugin = process.env.NODE_ENV === 'development' ? require('./LexicalTablePlugin.dev.js') : require('./LexicalTablePlugin.prod.js')
|
|
9
|
+
module.exports = LexicalTablePlugin;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';var c=require("lexical"),g=require("lexical/TableCellNode"),h=require("lexical/TableNode"),k=require("lexical/TableRowNode"),q=require("@lexical/react/LexicalComposerContext"),r=require("react");function t(d,a,b=!0){const f=h.$createTableNode();for(let e=0;e<d;e++){const l=k.$createTableRowNode();for(let m=0;m<a;m++){const n=g.$createTableCellNode(0===e&&b),p=c.$createParagraphNode();p.append(c.$createTextNode());n.append(p);l.append(n)}f.append(l)}return f}
|
|
8
|
+
module.exports=function(){const [d]=q.useLexicalComposerContext();r.useEffect(()=>{if(!d.hasNodes([h.TableNode,g.TableCellNode,k.TableRowNode]))throw Error("TablePlugin: TableNode, TableCellNode or TableRowNode not registered on editor");return d.addListener("command",(a,b)=>{if("insertTable"===a){const {columns:f,rows:e}=b;c.$log("handleAddTable");a=c.$getSelection();if(null===a)return!0;a=a.focus.getNode();null!==a&&(a=a.getTopLevelElementOrThrow(),b=t(e,f),a.insertAfter(b),b.insertAfter(c.$createParagraphNode()),
|
|
9
|
+
b.getFirstChildOrThrow().getFirstChildOrThrow().select());return!0}return!1},0)},[d]);return null};
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var lexical = require('lexical');
|
|
10
|
+
var React = require('react');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
const NON_SINGLE_WIDTH_CHARS_REPLACEMENT = Object.freeze({
|
|
21
|
+
'\t': '\\t',
|
|
22
|
+
'\n': '\\n'
|
|
23
|
+
});
|
|
24
|
+
const NON_SINGLE_WIDTH_CHARS_REGEX = new RegExp(Object.keys(NON_SINGLE_WIDTH_CHARS_REPLACEMENT).join('|'), 'g');
|
|
25
|
+
const SYMBOLS = Object.freeze({
|
|
26
|
+
ancestorHasNextSibling: '|',
|
|
27
|
+
ancestorIsLastChild: ' ',
|
|
28
|
+
hasNextSibling: '├',
|
|
29
|
+
isLastChild: '└',
|
|
30
|
+
selectedChar: '^',
|
|
31
|
+
selectedLine: '>'
|
|
32
|
+
});
|
|
33
|
+
function TreeView({
|
|
34
|
+
timeTravelButtonClassName,
|
|
35
|
+
timeTravelPanelSliderClassName,
|
|
36
|
+
timeTravelPanelButtonClassName,
|
|
37
|
+
viewClassName,
|
|
38
|
+
timeTravelPanelClassName,
|
|
39
|
+
editor
|
|
40
|
+
}) {
|
|
41
|
+
const [timeStampedEditorStates, setTimeStampedEditorStates] = React.useState([]);
|
|
42
|
+
const [content, setContent] = React.useState('');
|
|
43
|
+
const [timeTravelEnabled, setTimeTravelEnabled] = React.useState(false);
|
|
44
|
+
const playingIndexRef = React.useRef(0);
|
|
45
|
+
const treeElementRef = React.useRef(null);
|
|
46
|
+
const inputRef = React.useRef(null);
|
|
47
|
+
const [isPlaying, setIsPlaying] = React.useState(false);
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
setContent(generateContent(editor.getEditorState()));
|
|
50
|
+
return editor.addListener('update', ({
|
|
51
|
+
editorState
|
|
52
|
+
}) => {
|
|
53
|
+
const compositionKey = editor._compositionKey;
|
|
54
|
+
const treeText = generateContent(editor.getEditorState());
|
|
55
|
+
const compositionText = compositionKey !== null && `Composition key: ${compositionKey}`;
|
|
56
|
+
setContent([treeText, compositionText].filter(Boolean).join('\n\n'));
|
|
57
|
+
|
|
58
|
+
if (!timeTravelEnabled) {
|
|
59
|
+
setTimeStampedEditorStates(currentEditorStates => [...currentEditorStates, [Date.now(), editorState]]);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}, [timeTravelEnabled, editor]);
|
|
63
|
+
const totalEditorStates = timeStampedEditorStates.length;
|
|
64
|
+
React.useEffect(() => {
|
|
65
|
+
if (isPlaying) {
|
|
66
|
+
let timeoutId;
|
|
67
|
+
|
|
68
|
+
const play = () => {
|
|
69
|
+
const currentIndex = playingIndexRef.current;
|
|
70
|
+
|
|
71
|
+
if (currentIndex === totalEditorStates - 1) {
|
|
72
|
+
setIsPlaying(false);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const currentTime = timeStampedEditorStates[currentIndex][0];
|
|
77
|
+
const nextTime = timeStampedEditorStates[currentIndex + 1][0];
|
|
78
|
+
const timeDiff = nextTime - currentTime;
|
|
79
|
+
timeoutId = setTimeout(() => {
|
|
80
|
+
playingIndexRef.current++;
|
|
81
|
+
const index = playingIndexRef.current;
|
|
82
|
+
const input = inputRef.current;
|
|
83
|
+
|
|
84
|
+
if (input !== null) {
|
|
85
|
+
input.value = String(index);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
editor.setEditorState(timeStampedEditorStates[index][1]);
|
|
89
|
+
play();
|
|
90
|
+
}, timeDiff);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
play();
|
|
94
|
+
return () => {
|
|
95
|
+
window.clearTimeout(timeoutId);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}, [timeStampedEditorStates, isPlaying, editor, totalEditorStates]);
|
|
99
|
+
React.useEffect(() => {
|
|
100
|
+
const element = treeElementRef.current;
|
|
101
|
+
|
|
102
|
+
if (element !== null) {
|
|
103
|
+
// $FlowExpectedError[prop-missing] Internal field
|
|
104
|
+
element.__lexicalEditor = editor;
|
|
105
|
+
return () => {
|
|
106
|
+
// $FlowExpectedError[prop-missing] Internal field
|
|
107
|
+
element.__lexicalEditor = null;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}, [editor]);
|
|
111
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
112
|
+
className: viewClassName
|
|
113
|
+
}, !timeTravelEnabled && totalEditorStates > 2 && /*#__PURE__*/React.createElement("button", {
|
|
114
|
+
onClick: () => {
|
|
115
|
+
const rootElement = editor.getRootElement();
|
|
116
|
+
|
|
117
|
+
if (rootElement !== null) {
|
|
118
|
+
rootElement.contentEditable = 'false';
|
|
119
|
+
playingIndexRef.current = totalEditorStates - 1;
|
|
120
|
+
setTimeTravelEnabled(true);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
className: timeTravelButtonClassName
|
|
124
|
+
}, "Time Travel"), /*#__PURE__*/React.createElement("pre", {
|
|
125
|
+
ref: treeElementRef
|
|
126
|
+
}, content), timeTravelEnabled && /*#__PURE__*/React.createElement("div", {
|
|
127
|
+
className: timeTravelPanelClassName
|
|
128
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
129
|
+
className: timeTravelPanelButtonClassName,
|
|
130
|
+
onClick: () => {
|
|
131
|
+
setIsPlaying(!isPlaying);
|
|
132
|
+
}
|
|
133
|
+
}, isPlaying ? 'Pause' : 'Play'), /*#__PURE__*/React.createElement("input", {
|
|
134
|
+
className: timeTravelPanelSliderClassName,
|
|
135
|
+
ref: inputRef,
|
|
136
|
+
onChange: event => {
|
|
137
|
+
const editorStateIndex = Number(event.target.value);
|
|
138
|
+
const timeStampedEditorState = timeStampedEditorStates[editorStateIndex];
|
|
139
|
+
|
|
140
|
+
if (timeStampedEditorState) {
|
|
141
|
+
playingIndexRef.current = editorStateIndex;
|
|
142
|
+
editor.setEditorState(timeStampedEditorState[1]);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
type: "range",
|
|
146
|
+
min: "1",
|
|
147
|
+
max: totalEditorStates - 1
|
|
148
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
149
|
+
className: timeTravelPanelButtonClassName,
|
|
150
|
+
onClick: () => {
|
|
151
|
+
const rootElement = editor.getRootElement();
|
|
152
|
+
|
|
153
|
+
if (rootElement !== null) {
|
|
154
|
+
rootElement.contentEditable = 'true';
|
|
155
|
+
const index = timeStampedEditorStates.length - 1;
|
|
156
|
+
const timeStampedEditorState = timeStampedEditorStates[index];
|
|
157
|
+
editor.setEditorState(timeStampedEditorState[1]);
|
|
158
|
+
const input = inputRef.current;
|
|
159
|
+
|
|
160
|
+
if (input !== null) {
|
|
161
|
+
input.value = String(index);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
setTimeTravelEnabled(false);
|
|
165
|
+
setIsPlaying(false);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}, "Exit")));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function printRangeSelection(selection) {
|
|
172
|
+
let res = '';
|
|
173
|
+
const formatText = printFormatProperties(selection);
|
|
174
|
+
res += `: range ${formatText !== '' ? `{ ${formatText} }` : ''}`;
|
|
175
|
+
const anchor = selection.anchor;
|
|
176
|
+
const focus = selection.focus;
|
|
177
|
+
const anchorOffset = anchor.offset;
|
|
178
|
+
const focusOffset = focus.offset;
|
|
179
|
+
res += `\n ├ anchor { key: ${anchor.key}, offset: ${anchorOffset === null ? 'null' : anchorOffset}, type: ${anchor.type} }`;
|
|
180
|
+
res += `\n └ focus { key: ${focus.key}, offset: ${focusOffset === null ? 'null' : focusOffset}, type: ${focus.type} }`;
|
|
181
|
+
return res;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function generateContent(editorState) {
|
|
185
|
+
let res = ' root\n';
|
|
186
|
+
const selectionString = editorState.read(() => {
|
|
187
|
+
const selection = lexical.$getSelection();
|
|
188
|
+
visitTree(lexical.$getRoot(), (node, indent) => {
|
|
189
|
+
const nodeKey = node.getKey();
|
|
190
|
+
const nodeKeyDisplay = `(${nodeKey})`;
|
|
191
|
+
const typeDisplay = node.getType() || '';
|
|
192
|
+
const isSelected = node.isSelected();
|
|
193
|
+
res += `${isSelected ? SYMBOLS.selectedLine : ' '} ${indent.join(' ')} ${nodeKeyDisplay} ${typeDisplay} ${printNode(node)}\n`;
|
|
194
|
+
res += printSelectedCharsLine({
|
|
195
|
+
indent,
|
|
196
|
+
isSelected,
|
|
197
|
+
node,
|
|
198
|
+
nodeKeyDisplay,
|
|
199
|
+
selection,
|
|
200
|
+
typeDisplay
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
return selection === null ? ': null' : printRangeSelection(selection);
|
|
204
|
+
});
|
|
205
|
+
return res + '\n selection' + selectionString;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function visitTree(currentNode, visitor, indent = []) {
|
|
209
|
+
const childNodes = currentNode.getChildren();
|
|
210
|
+
const childNodesLength = childNodes.length;
|
|
211
|
+
childNodes.forEach((childNode, i) => {
|
|
212
|
+
visitor(childNode, indent.concat(i === childNodesLength - 1 ? SYMBOLS.isLastChild : SYMBOLS.hasNextSibling));
|
|
213
|
+
|
|
214
|
+
if (lexical.$isElementNode(childNode)) {
|
|
215
|
+
visitTree(childNode, visitor, indent.concat(i === childNodesLength - 1 ? SYMBOLS.ancestorIsLastChild : SYMBOLS.ancestorHasNextSibling));
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function normalize(text) {
|
|
221
|
+
return Object.entries(NON_SINGLE_WIDTH_CHARS_REPLACEMENT).reduce((acc, [key, value]) => acc.replace(new RegExp(key, 'g'), String(value)), text);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function printNode(node) {
|
|
225
|
+
if (lexical.$isTextNode(node)) {
|
|
226
|
+
const text = node.getTextContent(true);
|
|
227
|
+
const title = text.length === 0 ? '(empty)' : `"${normalize(text)}"`;
|
|
228
|
+
const properties = printAllProperties(node);
|
|
229
|
+
return [title, properties.length !== 0 ? `{ ${properties} }` : null].filter(Boolean).join(' ').trim();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return '';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const FORMAT_PREDICATES = [node => node.hasFormat('bold') && 'Bold', node => node.hasFormat('code') && 'Code', node => node.hasFormat('italic') && 'Italic', node => node.hasFormat('strikethrough') && 'Strikethrough', node => node.hasFormat('underline') && 'Underline'];
|
|
236
|
+
const DETAIL_PREDICATES = [node => node.isDirectionless() && 'Directionless', node => node.isUnmergeable() && 'Unmergeable'];
|
|
237
|
+
const MODE_PREDICATES = [node => node.isToken() && 'Token', node => node.isSegmented() && 'Segmented', node => node.isInert() && 'Inert'];
|
|
238
|
+
|
|
239
|
+
function printAllProperties(node) {
|
|
240
|
+
return [printFormatProperties(node), printDetailProperties(node), printModeProperties(node)].filter(Boolean).join(', ');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function printDetailProperties(nodeOrSelection) {
|
|
244
|
+
let str = DETAIL_PREDICATES.map(predicate => predicate(nodeOrSelection)).filter(Boolean).join(', ').toLocaleLowerCase();
|
|
245
|
+
|
|
246
|
+
if (str !== '') {
|
|
247
|
+
str = 'detail: ' + str;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return str;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function printModeProperties(nodeOrSelection) {
|
|
254
|
+
let str = MODE_PREDICATES.map(predicate => predicate(nodeOrSelection)).filter(Boolean).join(', ').toLocaleLowerCase();
|
|
255
|
+
|
|
256
|
+
if (str !== '') {
|
|
257
|
+
str = 'mode: ' + str;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return str;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function printFormatProperties(nodeOrSelection) {
|
|
264
|
+
let str = FORMAT_PREDICATES.map(predicate => predicate(nodeOrSelection)).filter(Boolean).join(', ').toLocaleLowerCase();
|
|
265
|
+
|
|
266
|
+
if (str !== '') {
|
|
267
|
+
str = 'format: ' + str;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return str;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function printSelectedCharsLine({
|
|
274
|
+
indent,
|
|
275
|
+
isSelected,
|
|
276
|
+
node,
|
|
277
|
+
nodeKeyDisplay,
|
|
278
|
+
selection,
|
|
279
|
+
typeDisplay
|
|
280
|
+
}) {
|
|
281
|
+
// No selection or node is not selected.
|
|
282
|
+
if (!lexical.$isTextNode(node) || selection === null || !isSelected || lexical.$isElementNode(node)) {
|
|
283
|
+
return '';
|
|
284
|
+
} // No selected characters.
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
const anchor = selection.anchor;
|
|
288
|
+
const focus = selection.focus;
|
|
289
|
+
|
|
290
|
+
if (node.getTextContent() === '' || anchor.getNode() === selection.focus.getNode() && anchor.offset === focus.offset) {
|
|
291
|
+
return '';
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const [start, end] = $getSelectionStartEnd(node, selection);
|
|
295
|
+
|
|
296
|
+
if (start === end) {
|
|
297
|
+
return '';
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const selectionLastIndent = indent[indent.length - 1] === SYMBOLS.hasNextSibling ? SYMBOLS.ancestorHasNextSibling : SYMBOLS.ancestorIsLastChild;
|
|
301
|
+
const indentionChars = [...indent.slice(0, indent.length - 1), selectionLastIndent];
|
|
302
|
+
const unselectedChars = Array(start).fill(' ');
|
|
303
|
+
const selectedChars = Array(end - start).fill(SYMBOLS.selectedChar);
|
|
304
|
+
const paddingLength = typeDisplay.length + 3; // 2 for the spaces around + 1 for the double quote.
|
|
305
|
+
|
|
306
|
+
const nodePrintSpaces = Array(nodeKeyDisplay.length + paddingLength).fill(' ');
|
|
307
|
+
return [SYMBOLS.selectedLine, indentionChars.join(' '), [...nodePrintSpaces, ...unselectedChars, ...selectedChars].join('')].join(' ') + '\n';
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function $getSelectionStartEnd(node, selection) {
|
|
311
|
+
const anchor = selection.anchor;
|
|
312
|
+
const focus = selection.focus;
|
|
313
|
+
const textContent = node.getTextContent(true);
|
|
314
|
+
const textLength = textContent.length;
|
|
315
|
+
let start = -1;
|
|
316
|
+
let end = -1; // Only one node is being selected.
|
|
317
|
+
|
|
318
|
+
if (anchor.type === 'text' && focus.type === 'text') {
|
|
319
|
+
const anchorNode = anchor.getNode();
|
|
320
|
+
const focusNode = focus.getNode();
|
|
321
|
+
|
|
322
|
+
if (anchorNode === focusNode && node === anchorNode && anchor.offset !== focus.offset) {
|
|
323
|
+
[start, end] = anchor.offset < focus.offset ? [anchor.offset, focus.offset] : [focus.offset, anchor.offset];
|
|
324
|
+
} else if (node === anchorNode) {
|
|
325
|
+
[start, end] = anchorNode.isBefore(focusNode) ? [anchor.offset, textLength] : [0, anchor.offset];
|
|
326
|
+
} else if (node === focusNode) {
|
|
327
|
+
[start, end] = focusNode.isBefore(anchorNode) ? [focus.offset, textLength] : [0, focus.offset];
|
|
328
|
+
} else {
|
|
329
|
+
// Node is within selection but not the anchor nor focus.
|
|
330
|
+
[start, end] = [0, textLength];
|
|
331
|
+
}
|
|
332
|
+
} // Account for non-single width characters.
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
const numNonSingleWidthCharBeforeSelection = (textContent.slice(0, start).match(NON_SINGLE_WIDTH_CHARS_REGEX) || []).length;
|
|
336
|
+
const numNonSingleWidthCharInSelection = (textContent.slice(start, end).match(NON_SINGLE_WIDTH_CHARS_REGEX) || []).length;
|
|
337
|
+
return [start + numNonSingleWidthCharBeforeSelection, end + numNonSingleWidthCharBeforeSelection + numNonSingleWidthCharInSelection];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
module.exports = TreeView;
|
package/LexicalTreeView.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
module.exports=function({timeTravelButtonClassName:a,timeTravelPanelSliderClassName:b,timeTravelPanelButtonClassName:c,viewClassName:e,timeTravelPanelClassName:d,editor:f}){const [g,m]=q.useState([]),[v,t]=q.useState(""),[r,l]=q.useState(!1),n=q.useRef(0),u=q.useRef(null),B=q.useRef(null),[z,C]=q.useState(!1);q.useEffect(()=>{t(H(f.getEditorState()));return f.addListener("update",({editorState:h})=>{const p=f._compositionKey,x=H(f.getEditorState());t([x,null!==p&&`Composition key: ${p}`].filter(Boolean).join("\n\n"));r||
|
|
11
|
-
m(A=>[...A,[Date.now(),h]])})},[r,f]);const y=g.length;q.useEffect(()=>{if(z){let h;const p=()=>{const x=n.current;x===y-1?C(!1):h=setTimeout(()=>{n.current++;const A=n.current,I=B.current;null!==I&&(I.value=String(A));f.setEditorState(g[A][1]);p()},g[x+1][0]-g[x][0])};p();return()=>{window.clearTimeout(h)}}},[g,z,f,y]);q.useEffect(()=>{u.current&&(u.current.__lexicalEditor=f)},[f]);return q.createElement("div",{className:e},!r&&2<y&&q.createElement("button",{onClick:()=>{const h=f.getRootElement();
|
|
12
|
-
null!==h&&(h.contentEditable="false",n.current=y-1,l(!0))},className:a},"Time Travel"),q.createElement("pre",{ref:u},v),r&&q.createElement("div",{className:d},q.createElement("button",{className:c,onClick:()=>{C(!z)}},z?"Pause":"Play"),q.createElement("input",{className:b,ref:B,onChange:h=>{h=Number(h.target.value);const p=g[h];p&&(n.current=h,f.setEditorState(p[1]))},type:"range",min:"1",max:y-1}),q.createElement("button",{className:c,onClick:()=>{var h=f.getRootElement();if(null!==h){h.contentEditable=
|
|
13
|
-
"true";h=g.length-1;f.setEditorState(g[h][1]);const p=B.current;null!==p&&(p.value=String(h));l(!1);C(!1)}}},"Exit")))};
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict'
|
|
8
|
+
const LexicalTreeView = process.env.NODE_ENV === 'development' ? require('./LexicalTreeView.dev.js') : require('./LexicalTreeView.prod.js')
|
|
9
|
+
module.exports = LexicalTreeView;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';var k=require("lexical"),q=require("react");const w=Object.freeze({"\t":"\\t","\n":"\\n"}),D=new RegExp(Object.keys(w).join("|"),"g"),E=Object.freeze({ancestorHasNextSibling:"|",ancestorIsLastChild:" ",hasNextSibling:"\u251c",isLastChild:"\u2514",selectedChar:"^",selectedLine:">"});
|
|
8
|
+
function F(a){let b="";const c=G(a),e=a.anchor;a=a.focus;const d=e.offset,f=a.offset;b=b+`: range ${""!==c?`{ ${c} }`:""}`+`\n \u251c anchor { key: ${e.key}, offset: ${null===d?"null":d}, type: ${e.type} }`;return b+=`\n \u2514 focus { key: ${a.key}, offset: ${null===f?"null":f}, type: ${a.type} }`}
|
|
9
|
+
function H(a){let b=" root\n";a=a.read(()=>{const c=k.$getSelection();J(k.$getRoot(),(e,d)=>{const f=`(${e.getKey()})`,g=e.getType()||"",m=e.isSelected();var u=b,t=m?E.selectedLine:" ",r=d.join(" ");if(k.$isTextNode(e)){var l=e.getTextContent(!0);const n=0===l.length?"(empty)":`"${K(l)}"`;l=[G(e),L(e),M(e)].filter(Boolean).join(", ");l=[n,0!==l.length?`{ ${l} }`:null].filter(Boolean).join(" ").trim()}else l="";b=u+`${t} ${r} ${f} ${g} ${l}\n`;b+=N({indent:d,isSelected:m,node:e,nodeKeyDisplay:f,selection:c,
|
|
10
|
+
typeDisplay:g})});return null===c?": null":F(c)});return b+"\n selection"+a}function J(a,b,c=[]){a=a.getChildren();const e=a.length;a.forEach((d,f)=>{b(d,c.concat(f===e-1?E.isLastChild:E.hasNextSibling));k.$isElementNode(d)&&J(d,b,c.concat(f===e-1?E.ancestorIsLastChild:E.ancestorHasNextSibling))})}function K(a){return Object.entries(w).reduce((b,[c,e])=>b.replace(new RegExp(c,"g"),String(e)),a)}
|
|
11
|
+
const O=[a=>a.hasFormat("bold")&&"Bold",a=>a.hasFormat("code")&&"Code",a=>a.hasFormat("italic")&&"Italic",a=>a.hasFormat("strikethrough")&&"Strikethrough",a=>a.hasFormat("underline")&&"Underline"],P=[a=>a.isDirectionless()&&"Directionless",a=>a.isUnmergeable()&&"Unmergeable"],Q=[a=>a.isToken()&&"Token",a=>a.isSegmented()&&"Segmented",a=>a.isInert()&&"Inert"];function L(a){let b=P.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="detail: "+b);return b}
|
|
12
|
+
function M(a){let b=Q.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="mode: "+b);return b}function G(a){let b=O.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="format: "+b);return b}
|
|
13
|
+
function N({indent:a,isSelected:b,node:c,nodeKeyDisplay:e,selection:d,typeDisplay:f}){if(!k.$isTextNode(c)||null===d||!b||k.$isElementNode(c))return"";b=d.anchor;var g=d.focus;if(""===c.getTextContent()||b.getNode()===d.focus.getNode()&&b.offset===g.offset)return"";g=d.anchor;const m=d.focus,u=c.getTextContent(!0),t=u.length;b=d=-1;if("text"===g.type&&"text"===m.type){const n=g.getNode(),v=m.getNode();n===v&&c===n&&g.offset!==m.offset?[d,b]=g.offset<m.offset?[g.offset,m.offset]:[m.offset,g.offset]:
|
|
14
|
+
c===n?[d,b]=n.isBefore(v)?[g.offset,t]:[0,g.offset]:c===v?[d,b]=v.isBefore(n)?[m.offset,t]:[0,m.offset]:[d,b]=[0,t]}c=(u.slice(0,d).match(D)||[]).length;g=(u.slice(d,b).match(D)||[]).length;const [r,l]=[d+c,b+c+g];if(r===l)return"";c=a[a.length-1]===E.hasNextSibling?E.ancestorHasNextSibling:E.ancestorIsLastChild;a=[...a.slice(0,a.length-1),c];c=Array(r).fill(" ");d=Array(l-r).fill(E.selectedChar);e=Array(e.length+(f.length+3)).fill(" ");return[E.selectedLine,a.join(" "),[...e,...c,...d].join("")].join(" ")+
|
|
15
|
+
"\n"}
|
|
16
|
+
module.exports=function({timeTravelButtonClassName:a,timeTravelPanelSliderClassName:b,timeTravelPanelButtonClassName:c,viewClassName:e,timeTravelPanelClassName:d,editor:f}){const [g,m]=q.useState([]),[u,t]=q.useState(""),[r,l]=q.useState(!1),n=q.useRef(0),v=q.useRef(null),B=q.useRef(null),[z,C]=q.useState(!1);q.useEffect(()=>{t(H(f.getEditorState()));return f.addListener("update",({editorState:h})=>{const p=f._compositionKey,x=H(f.getEditorState());t([x,null!==p&&`Composition key: ${p}`].filter(Boolean).join("\n\n"));r||
|
|
17
|
+
m(A=>[...A,[Date.now(),h]])})},[r,f]);const y=g.length;q.useEffect(()=>{if(z){let h;const p=()=>{const x=n.current;x===y-1?C(!1):h=setTimeout(()=>{n.current++;const A=n.current,I=B.current;null!==I&&(I.value=String(A));f.setEditorState(g[A][1]);p()},g[x+1][0]-g[x][0])};p();return()=>{window.clearTimeout(h)}}},[g,z,f,y]);q.useEffect(()=>{const h=v.current;if(null!==h)return h.__lexicalEditor=f,()=>{h.__lexicalEditor=null}},[f]);return q.createElement("div",{className:e},!r&&2<y&&q.createElement("button",
|
|
18
|
+
{onClick:()=>{const h=f.getRootElement();null!==h&&(h.contentEditable="false",n.current=y-1,l(!0))},className:a},"Time Travel"),q.createElement("pre",{ref:v},u),r&&q.createElement("div",{className:d},q.createElement("button",{className:c,onClick:()=>{C(!z)}},z?"Pause":"Play"),q.createElement("input",{className:b,ref:B,onChange:h=>{h=Number(h.target.value);const p=g[h];p&&(n.current=h,f.setEditorState(p[1]))},type:"range",min:"1",max:y-1}),q.createElement("button",{className:c,onClick:()=>{var h=f.getRootElement();
|
|
19
|
+
if(null!==h){h.contentEditable="true";h=g.length-1;f.setEditorState(g[h][1]);const p=B.current;null!==p&&(p.value=String(h));l(!1);C(!1)}}},"Exit")))};
|
package/README.md
CHANGED