@lexical/react 0.13.0 → 0.14.0
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/LexicalAutoEmbedPlugin.dev.esm.js +131 -0
- package/LexicalAutoEmbedPlugin.esm.js +13 -0
- package/LexicalAutoEmbedPlugin.js +1 -1
- package/LexicalAutoEmbedPlugin.prod.esm.js +7 -0
- package/LexicalAutoFocusPlugin.dev.esm.js +42 -0
- package/LexicalAutoFocusPlugin.dev.js +0 -5
- package/LexicalAutoFocusPlugin.esm.js +10 -0
- package/LexicalAutoFocusPlugin.js +1 -1
- package/LexicalAutoFocusPlugin.prod.esm.js +7 -0
- package/LexicalAutoFocusPlugin.prod.js +1 -1
- package/LexicalAutoLinkPlugin.dev.esm.js +312 -0
- package/LexicalAutoLinkPlugin.dev.js +3 -1
- package/LexicalAutoLinkPlugin.esm.js +11 -0
- package/LexicalAutoLinkPlugin.js +1 -1
- package/LexicalAutoLinkPlugin.prod.esm.js +7 -0
- package/LexicalBlockWithAlignableContents.dev.esm.js +86 -0
- package/LexicalBlockWithAlignableContents.dev.js +1 -0
- package/LexicalBlockWithAlignableContents.esm.js +10 -0
- package/LexicalBlockWithAlignableContents.js +1 -1
- package/LexicalBlockWithAlignableContents.prod.esm.js +7 -0
- package/LexicalBlockWithAlignableContents.prod.js +1 -1
- package/LexicalCharacterLimitPlugin.d.ts +4 -1
- package/LexicalCharacterLimitPlugin.dev.esm.js +272 -0
- package/LexicalCharacterLimitPlugin.dev.js +12 -4
- package/LexicalCharacterLimitPlugin.esm.js +10 -0
- package/LexicalCharacterLimitPlugin.js +1 -1
- package/LexicalCharacterLimitPlugin.prod.esm.js +7 -0
- package/LexicalCharacterLimitPlugin.prod.js +9 -9
- package/LexicalCheckListPlugin.dev.esm.js +203 -0
- package/LexicalCheckListPlugin.esm.js +10 -0
- package/LexicalCheckListPlugin.js +1 -1
- package/LexicalCheckListPlugin.prod.esm.js +7 -0
- package/LexicalClearEditorPlugin.dev.esm.js +64 -0
- package/LexicalClearEditorPlugin.esm.js +10 -0
- package/LexicalClearEditorPlugin.js +1 -1
- package/LexicalClearEditorPlugin.prod.esm.js +7 -0
- package/LexicalClickableLinkPlugin.dev.esm.js +95 -0
- package/LexicalClickableLinkPlugin.esm.js +10 -0
- package/LexicalClickableLinkPlugin.js +1 -1
- package/LexicalClickableLinkPlugin.prod.esm.js +7 -0
- package/LexicalCollaborationContext.dev.esm.js +36 -0
- package/LexicalCollaborationContext.esm.js +11 -0
- package/LexicalCollaborationContext.js +1 -1
- package/LexicalCollaborationContext.prod.esm.js +7 -0
- package/LexicalCollaborationPlugin.dev.esm.js +308 -0
- package/LexicalCollaborationPlugin.esm.js +10 -0
- package/LexicalCollaborationPlugin.js +1 -1
- package/LexicalCollaborationPlugin.prod.esm.js +7 -0
- package/LexicalComposer.dev.esm.js +129 -0
- package/LexicalComposer.esm.js +10 -0
- package/LexicalComposer.js +1 -1
- package/LexicalComposer.prod.esm.js +7 -0
- package/LexicalComposerContext.dev.esm.js +42 -0
- package/LexicalComposerContext.esm.js +12 -0
- package/LexicalComposerContext.js +1 -1
- package/LexicalComposerContext.prod.esm.js +7 -0
- package/LexicalContentEditable.dev.esm.js +107 -0
- package/LexicalContentEditable.dev.js +5 -1
- package/LexicalContentEditable.esm.js +10 -0
- package/LexicalContentEditable.js +1 -1
- package/LexicalContentEditable.prod.esm.js +7 -0
- package/LexicalContentEditable.prod.js +3 -3
- package/LexicalContextMenuPlugin.dev.esm.js +455 -0
- package/LexicalContextMenuPlugin.dev.js +3 -1
- package/LexicalContextMenuPlugin.esm.js +11 -0
- package/LexicalContextMenuPlugin.js +1 -1
- package/LexicalContextMenuPlugin.prod.esm.js +7 -0
- package/LexicalDecoratorBlockNode.dev.esm.js +46 -0
- package/LexicalDecoratorBlockNode.esm.js +11 -0
- package/LexicalDecoratorBlockNode.js +1 -1
- package/LexicalDecoratorBlockNode.prod.esm.js +7 -0
- package/LexicalEditorRefPlugin.dev.esm.js +40 -0
- package/LexicalEditorRefPlugin.dev.js +10 -5
- package/LexicalEditorRefPlugin.esm.js +10 -0
- package/LexicalEditorRefPlugin.js +1 -1
- package/LexicalEditorRefPlugin.prod.esm.js +7 -0
- package/LexicalEditorRefPlugin.prod.js +1 -1
- package/LexicalErrorBoundary.dev.esm.js +157 -0
- package/LexicalErrorBoundary.esm.js +10 -0
- package/LexicalErrorBoundary.js +1 -1
- package/LexicalErrorBoundary.prod.esm.js +7 -0
- package/LexicalHashtagPlugin.dev.esm.js +163 -0
- package/LexicalHashtagPlugin.esm.js +10 -0
- package/LexicalHashtagPlugin.js +1 -1
- package/LexicalHashtagPlugin.prod.esm.js +7 -0
- package/LexicalHistoryPlugin.dev.esm.js +41 -0
- package/LexicalHistoryPlugin.esm.js +11 -0
- package/LexicalHistoryPlugin.js +1 -1
- package/LexicalHistoryPlugin.prod.esm.js +7 -0
- package/LexicalHorizontalRuleNode.dev.esm.js +118 -0
- package/LexicalHorizontalRuleNode.dev.js +1 -0
- package/LexicalHorizontalRuleNode.esm.js +13 -0
- package/LexicalHorizontalRuleNode.js +1 -1
- package/LexicalHorizontalRuleNode.prod.esm.js +7 -0
- package/LexicalHorizontalRuleNode.prod.js +1 -1
- package/LexicalHorizontalRulePlugin.dev.esm.js +39 -0
- package/LexicalHorizontalRulePlugin.esm.js +10 -0
- package/LexicalHorizontalRulePlugin.js +1 -1
- package/LexicalHorizontalRulePlugin.prod.esm.js +7 -0
- package/LexicalLinkPlugin.dev.esm.js +79 -0
- package/LexicalLinkPlugin.dev.js +6 -2
- package/LexicalLinkPlugin.esm.js +10 -0
- package/LexicalLinkPlugin.js +1 -1
- package/LexicalLinkPlugin.prod.esm.js +7 -0
- package/LexicalLinkPlugin.prod.js +1 -1
- package/LexicalListPlugin.dev.esm.js +59 -0
- package/LexicalListPlugin.esm.js +10 -0
- package/LexicalListPlugin.js +1 -1
- package/LexicalListPlugin.prod.esm.js +7 -0
- package/LexicalMarkdownShortcutPlugin.dev.esm.js +49 -0
- package/LexicalMarkdownShortcutPlugin.esm.js +11 -0
- package/LexicalMarkdownShortcutPlugin.js +1 -1
- package/LexicalMarkdownShortcutPlugin.prod.esm.js +7 -0
- package/LexicalNestedComposer.dev.esm.js +105 -0
- package/LexicalNestedComposer.esm.js +10 -0
- package/LexicalNestedComposer.js +1 -1
- package/LexicalNestedComposer.prod.esm.js +7 -0
- package/LexicalNodeEventPlugin.dev.esm.js +56 -0
- package/LexicalNodeEventPlugin.esm.js +10 -0
- package/LexicalNodeEventPlugin.js +1 -1
- package/LexicalNodeEventPlugin.prod.esm.js +7 -0
- package/LexicalNodeMenuPlugin.dev.esm.js +466 -0
- package/LexicalNodeMenuPlugin.dev.js +3 -1
- package/LexicalNodeMenuPlugin.esm.js +11 -0
- package/LexicalNodeMenuPlugin.js +1 -1
- package/LexicalNodeMenuPlugin.prod.esm.js +7 -0
- package/LexicalOnChangePlugin.dev.esm.js +62 -0
- package/LexicalOnChangePlugin.esm.js +10 -0
- package/LexicalOnChangePlugin.js +1 -1
- package/LexicalOnChangePlugin.prod.esm.js +7 -0
- package/LexicalPlainTextPlugin.dev.esm.js +161 -0
- package/LexicalPlainTextPlugin.esm.js +10 -0
- package/LexicalPlainTextPlugin.js +1 -1
- package/LexicalPlainTextPlugin.prod.esm.js +7 -0
- package/LexicalRichTextPlugin.dev.esm.js +161 -0
- package/LexicalRichTextPlugin.esm.js +10 -0
- package/LexicalRichTextPlugin.js +1 -1
- package/LexicalRichTextPlugin.prod.esm.js +7 -0
- package/LexicalTabIndentationPlugin.dev.esm.js +76 -0
- package/LexicalTabIndentationPlugin.esm.js +11 -0
- package/LexicalTabIndentationPlugin.js +1 -1
- package/LexicalTabIndentationPlugin.prod.esm.js +7 -0
- package/LexicalTableOfContents.dev.esm.js +157 -0
- package/LexicalTableOfContents.esm.js +10 -0
- package/LexicalTableOfContents.js +1 -1
- package/LexicalTableOfContents.prod.esm.js +7 -0
- package/LexicalTablePlugin.dev.esm.js +163 -0
- package/LexicalTablePlugin.esm.js +10 -0
- package/LexicalTablePlugin.js +1 -1
- package/LexicalTablePlugin.prod.esm.js +7 -0
- package/LexicalTreeView.dev.esm.js +483 -0
- package/LexicalTreeView.dev.js +3 -1
- package/LexicalTreeView.esm.js +10 -0
- package/LexicalTreeView.js +1 -1
- package/LexicalTreeView.prod.esm.js +7 -0
- package/LexicalTypeaheadMenuPlugin.dev.esm.js +569 -0
- package/LexicalTypeaheadMenuPlugin.dev.js +3 -1
- package/LexicalTypeaheadMenuPlugin.esm.js +16 -0
- package/LexicalTypeaheadMenuPlugin.js +1 -1
- package/LexicalTypeaheadMenuPlugin.prod.esm.js +7 -0
- package/package.json +583 -20
- package/useLexicalEditable.dev.esm.js +82 -0
- package/useLexicalEditable.esm.js +10 -0
- package/useLexicalEditable.js +1 -1
- package/useLexicalEditable.prod.esm.js +7 -0
- package/useLexicalIsTextContentEmpty.dev.esm.js +51 -0
- package/useLexicalIsTextContentEmpty.esm.js +10 -0
- package/useLexicalIsTextContentEmpty.js +1 -1
- package/useLexicalIsTextContentEmpty.prod.esm.js +7 -0
- package/useLexicalNodeSelection.dev.esm.js +69 -0
- package/useLexicalNodeSelection.esm.js +10 -0
- package/useLexicalNodeSelection.js +1 -1
- package/useLexicalNodeSelection.prod.esm.js +7 -0
- package/useLexicalSubscription.dev.esm.js +63 -0
- package/useLexicalSubscription.esm.js +10 -0
- package/useLexicalSubscription.js +1 -1
- package/useLexicalSubscription.prod.esm.js +7 -0
- package/useLexicalTextEntity.dev.esm.js +26 -0
- package/useLexicalTextEntity.esm.js +10 -0
- package/useLexicalTextEntity.js +1 -1
- package/useLexicalTextEntity.prod.esm.js +7 -0
|
@@ -68,7 +68,11 @@ function ContentEditable({
|
|
|
68
68
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
69
69
|
const [isEditable, setEditable] = React.useState(false);
|
|
70
70
|
const ref = React.useCallback(rootElement => {
|
|
71
|
-
|
|
71
|
+
// defaultView is required for a root element.
|
|
72
|
+
// In multi-window setups, the defaultView may not exist at certain points.
|
|
73
|
+
if (rootElement && rootElement.ownerDocument && rootElement.ownerDocument.defaultView) {
|
|
74
|
+
editor.setRootElement(rootElement);
|
|
75
|
+
}
|
|
72
76
|
}, [editor]);
|
|
73
77
|
useLayoutEffect(() => {
|
|
74
78
|
setEditable(editor.isEditable());
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
import * as modDev from './LexicalContentEditable.dev.esm.js';
|
|
8
|
+
import * as modProd from './LexicalContentEditable.prod.esm.js';
|
|
9
|
+
const mod = process.env.NODE_ENV === 'development' ? modDev : modProd;
|
|
10
|
+
export const ContentEditable = mod.ContentEditable;
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
'use strict'
|
|
8
|
-
const LexicalContentEditable = process.env.NODE_ENV === 'development' ? require('./LexicalContentEditable.dev.js') : require('./LexicalContentEditable.prod.js')
|
|
8
|
+
const LexicalContentEditable = process.env.NODE_ENV === 'development' ? require('./LexicalContentEditable.dev.js') : require('./LexicalContentEditable.prod.js');
|
|
9
9
|
module.exports = LexicalContentEditable;
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import*as a from"react";import{useLayoutEffect as t,useEffect as i,useState as r,useCallback as o}from"react";function n(){return n=Object.assign?Object.assign.bind():function(e){for(var a=1;a<arguments.length;a++){var t=arguments[a];for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])}return e},n.apply(this,arguments)}var d="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?t:i;function l({ariaActiveDescendant:t,ariaAutoComplete:i,ariaControls:l,ariaDescribedBy:c,ariaExpanded:s,ariaLabel:u,ariaLabelledBy:b,ariaMultiline:m,ariaOwns:p,ariaRequired:f,autoCapitalize:v,className:w,id:y,role:x="textbox",spellCheck:C=!0,style:E,tabIndex:h,"data-testid":L,...O}){const[g]=e(),[D,j]=r(!1),k=o((e=>{e&&e.ownerDocument&&e.ownerDocument.defaultView&&g.setRootElement(e)}),[g]);return d((()=>(j(g.isEditable()),g.registerEditableListener((e=>{j(e)})))),[g]),a.createElement("div",n({},O,{"aria-activedescendant":D?t:void 0,"aria-autocomplete":D?i:"none","aria-controls":D?l:void 0,"aria-describedby":c,"aria-expanded":D&&"combobox"===x?!!s:void 0,"aria-label":u,"aria-labelledby":b,"aria-multiline":m,"aria-owns":D?p:void 0,"aria-readonly":!D||void 0,"aria-required":f,autoCapitalize:v,className:w,contentEditable:D,"data-testid":L,id:y,ref:k,role:x,spellCheck:C,style:E,tabIndex:h}))}export{l as ContentEditable};
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
'use strict';var
|
|
8
|
-
exports.ContentEditable=function({ariaActiveDescendant:
|
|
9
|
-
n({},E,{"aria-activedescendant":a?
|
|
7
|
+
'use strict';var d=require("@lexical/react/LexicalComposerContext"),k=require("react");function n(){n=Object.assign?Object.assign.bind():function(h){for(var e=1;e<arguments.length;e++){var f=arguments[e],b;for(b in f)Object.prototype.hasOwnProperty.call(f,b)&&(h[b]=f[b])}return h};return n.apply(this,arguments)}var p="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?k.useLayoutEffect:k.useEffect;
|
|
8
|
+
exports.ContentEditable=function({ariaActiveDescendant:h,ariaAutoComplete:e,ariaControls:f,ariaDescribedBy:b,ariaExpanded:q,ariaLabel:r,ariaLabelledBy:t,ariaMultiline:u,ariaOwns:v,ariaRequired:w,autoCapitalize:x,className:y,id:z,role:l="textbox",spellCheck:A=!0,style:B,tabIndex:C,"data-testid":D,...E}){let [g]=d.useLexicalComposerContext(),[a,m]=k.useState(!1),F=k.useCallback(c=>{c&&c.ownerDocument&&c.ownerDocument.defaultView&&g.setRootElement(c)},[g]);p(()=>{m(g.isEditable());return g.registerEditableListener(c=>
|
|
9
|
+
{m(c)})},[g]);return k.createElement("div",n({},E,{"aria-activedescendant":a?h:void 0,"aria-autocomplete":a?e:"none","aria-controls":a?f:void 0,"aria-describedby":b,"aria-expanded":a?"combobox"===l?!!q:void 0:void 0,"aria-label":r,"aria-labelledby":t,"aria-multiline":u,"aria-owns":a?v:void 0,"aria-readonly":a?void 0:!0,"aria-required":w,autoCapitalize:x,className:y,contentEditable:a,"data-testid":D,id:z,ref:F,role:l,spellCheck:A,style:B,tabIndex:C}))}
|
|
@@ -0,0 +1,455 @@
|
|
|
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
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
8
|
+
import { createCommand, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection } from 'lexical';
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
import { useLayoutEffect as useLayoutEffect$1, useEffect, useState, useCallback, useMemo, useRef } from 'react';
|
|
11
|
+
import { mergeRegister } from '@lexical/utils';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
15
|
+
*
|
|
16
|
+
* This source code is licensed under the MIT license found in the
|
|
17
|
+
* LICENSE file in the root directory of this source tree.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
25
|
+
*
|
|
26
|
+
* This source code is licensed under the MIT license found in the
|
|
27
|
+
* LICENSE file in the root directory of this source tree.
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
const useLayoutEffectImpl = CAN_USE_DOM ? useLayoutEffect$1 : useEffect;
|
|
31
|
+
var useLayoutEffect = useLayoutEffectImpl;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
35
|
+
*
|
|
36
|
+
* This source code is licensed under the MIT license found in the
|
|
37
|
+
* LICENSE file in the root directory of this source tree.
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
class MenuOption {
|
|
41
|
+
constructor(key) {
|
|
42
|
+
this.key = key;
|
|
43
|
+
this.ref = {
|
|
44
|
+
current: null
|
|
45
|
+
};
|
|
46
|
+
this.setRefElement = this.setRefElement.bind(this);
|
|
47
|
+
}
|
|
48
|
+
setRefElement(element) {
|
|
49
|
+
this.ref = {
|
|
50
|
+
current: element
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const scrollIntoViewIfNeeded = target => {
|
|
55
|
+
const typeaheadContainerNode = document.getElementById('typeahead-menu');
|
|
56
|
+
if (!typeaheadContainerNode) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const typeaheadRect = typeaheadContainerNode.getBoundingClientRect();
|
|
60
|
+
if (typeaheadRect.top + typeaheadRect.height > window.innerHeight) {
|
|
61
|
+
typeaheadContainerNode.scrollIntoView({
|
|
62
|
+
block: 'center'
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (typeaheadRect.top < 0) {
|
|
66
|
+
typeaheadContainerNode.scrollIntoView({
|
|
67
|
+
block: 'center'
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
target.scrollIntoView({
|
|
71
|
+
block: 'nearest'
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Walk backwards along user input and forward through entity title to try
|
|
77
|
+
* and replace more of the user's text with entity.
|
|
78
|
+
*/
|
|
79
|
+
function getFullMatchOffset(documentText, entryText, offset) {
|
|
80
|
+
let triggerOffset = offset;
|
|
81
|
+
for (let i = triggerOffset; i <= entryText.length; i++) {
|
|
82
|
+
if (documentText.substr(-i) === entryText.substr(0, i)) {
|
|
83
|
+
triggerOffset = i;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return triggerOffset;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Split Lexical TextNode and return a new TextNode only containing matched text.
|
|
91
|
+
* Common use cases include: removing the node, replacing with a new node.
|
|
92
|
+
*/
|
|
93
|
+
function $splitNodeContainingQuery(match) {
|
|
94
|
+
const selection = $getSelection();
|
|
95
|
+
if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const anchor = selection.anchor;
|
|
99
|
+
if (anchor.type !== 'text') {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const anchorNode = anchor.getNode();
|
|
103
|
+
if (!anchorNode.isSimpleText()) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const selectionOffset = anchor.offset;
|
|
107
|
+
const textContent = anchorNode.getTextContent().slice(0, selectionOffset);
|
|
108
|
+
const characterOffset = match.replaceableString.length;
|
|
109
|
+
const queryOffset = getFullMatchOffset(textContent, match.matchingString, characterOffset);
|
|
110
|
+
const startOffset = selectionOffset - queryOffset;
|
|
111
|
+
if (startOffset < 0) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
let newNode;
|
|
115
|
+
if (startOffset === 0) {
|
|
116
|
+
[newNode] = anchorNode.splitText(selectionOffset);
|
|
117
|
+
} else {
|
|
118
|
+
[, newNode] = anchorNode.splitText(startOffset, selectionOffset);
|
|
119
|
+
}
|
|
120
|
+
return newNode;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Got from https://stackoverflow.com/a/42543908/2013580
|
|
124
|
+
function getScrollParent(element, includeHidden) {
|
|
125
|
+
let style = getComputedStyle(element);
|
|
126
|
+
const excludeStaticParent = style.position === 'absolute';
|
|
127
|
+
const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
|
|
128
|
+
if (style.position === 'fixed') {
|
|
129
|
+
return document.body;
|
|
130
|
+
}
|
|
131
|
+
for (let parent = element; parent = parent.parentElement;) {
|
|
132
|
+
style = getComputedStyle(parent);
|
|
133
|
+
if (excludeStaticParent && style.position === 'static') {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
|
|
137
|
+
return parent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return document.body;
|
|
141
|
+
}
|
|
142
|
+
function isTriggerVisibleInNearestScrollContainer(targetElement, containerElement) {
|
|
143
|
+
const tRect = targetElement.getBoundingClientRect();
|
|
144
|
+
const cRect = containerElement.getBoundingClientRect();
|
|
145
|
+
return tRect.top > cRect.top && tRect.top < cRect.bottom;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Reposition the menu on scroll, window resize, and element resize.
|
|
149
|
+
function useDynamicPositioning(resolution, targetElement, onReposition, onVisibilityChange) {
|
|
150
|
+
const [editor] = useLexicalComposerContext();
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (targetElement != null && resolution != null) {
|
|
153
|
+
const rootElement = editor.getRootElement();
|
|
154
|
+
const rootScrollParent = rootElement != null ? getScrollParent(rootElement, false) : document.body;
|
|
155
|
+
let ticking = false;
|
|
156
|
+
let previousIsInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
|
|
157
|
+
const handleScroll = function () {
|
|
158
|
+
if (!ticking) {
|
|
159
|
+
window.requestAnimationFrame(function () {
|
|
160
|
+
onReposition();
|
|
161
|
+
ticking = false;
|
|
162
|
+
});
|
|
163
|
+
ticking = true;
|
|
164
|
+
}
|
|
165
|
+
const isInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
|
|
166
|
+
if (isInView !== previousIsInView) {
|
|
167
|
+
previousIsInView = isInView;
|
|
168
|
+
if (onVisibilityChange != null) {
|
|
169
|
+
onVisibilityChange(isInView);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const resizeObserver = new ResizeObserver(onReposition);
|
|
174
|
+
window.addEventListener('resize', onReposition);
|
|
175
|
+
document.addEventListener('scroll', handleScroll, {
|
|
176
|
+
capture: true,
|
|
177
|
+
passive: true
|
|
178
|
+
});
|
|
179
|
+
resizeObserver.observe(targetElement);
|
|
180
|
+
return () => {
|
|
181
|
+
resizeObserver.unobserve(targetElement);
|
|
182
|
+
window.removeEventListener('resize', onReposition);
|
|
183
|
+
document.removeEventListener('scroll', handleScroll, true);
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
|
|
187
|
+
}
|
|
188
|
+
const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND = createCommand('SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND');
|
|
189
|
+
function LexicalMenu({
|
|
190
|
+
close,
|
|
191
|
+
editor,
|
|
192
|
+
anchorElementRef,
|
|
193
|
+
resolution,
|
|
194
|
+
options,
|
|
195
|
+
menuRenderFn,
|
|
196
|
+
onSelectOption,
|
|
197
|
+
shouldSplitNodeWithQuery = false,
|
|
198
|
+
commandPriority = COMMAND_PRIORITY_LOW
|
|
199
|
+
}) {
|
|
200
|
+
const [selectedIndex, setHighlightedIndex] = useState(null);
|
|
201
|
+
const matchingString = resolution.match && resolution.match.matchingString;
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
setHighlightedIndex(0);
|
|
204
|
+
}, [matchingString]);
|
|
205
|
+
const selectOptionAndCleanUp = useCallback(selectedEntry => {
|
|
206
|
+
editor.update(() => {
|
|
207
|
+
const textNodeContainingQuery = resolution.match != null && shouldSplitNodeWithQuery ? $splitNodeContainingQuery(resolution.match) : null;
|
|
208
|
+
onSelectOption(selectedEntry, textNodeContainingQuery, close, resolution.match ? resolution.match.matchingString : '');
|
|
209
|
+
});
|
|
210
|
+
}, [editor, shouldSplitNodeWithQuery, resolution.match, onSelectOption, close]);
|
|
211
|
+
const updateSelectedIndex = useCallback(index => {
|
|
212
|
+
const rootElem = editor.getRootElement();
|
|
213
|
+
if (rootElem !== null) {
|
|
214
|
+
rootElem.setAttribute('aria-activedescendant', 'typeahead-item-' + index);
|
|
215
|
+
setHighlightedIndex(index);
|
|
216
|
+
}
|
|
217
|
+
}, [editor]);
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
return () => {
|
|
220
|
+
const rootElem = editor.getRootElement();
|
|
221
|
+
if (rootElem !== null) {
|
|
222
|
+
rootElem.removeAttribute('aria-activedescendant');
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}, [editor]);
|
|
226
|
+
useLayoutEffect(() => {
|
|
227
|
+
if (options === null) {
|
|
228
|
+
setHighlightedIndex(null);
|
|
229
|
+
} else if (selectedIndex === null) {
|
|
230
|
+
updateSelectedIndex(0);
|
|
231
|
+
}
|
|
232
|
+
}, [options, selectedIndex, updateSelectedIndex]);
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
return mergeRegister(editor.registerCommand(SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND, ({
|
|
235
|
+
option
|
|
236
|
+
}) => {
|
|
237
|
+
if (option.ref && option.ref.current != null) {
|
|
238
|
+
scrollIntoViewIfNeeded(option.ref.current);
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
return false;
|
|
242
|
+
}, commandPriority));
|
|
243
|
+
}, [editor, updateSelectedIndex, commandPriority]);
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
return mergeRegister(editor.registerCommand(KEY_ARROW_DOWN_COMMAND, payload => {
|
|
246
|
+
const event = payload;
|
|
247
|
+
if (options !== null && options.length && selectedIndex !== null) {
|
|
248
|
+
const newSelectedIndex = selectedIndex !== options.length - 1 ? selectedIndex + 1 : 0;
|
|
249
|
+
updateSelectedIndex(newSelectedIndex);
|
|
250
|
+
const option = options[newSelectedIndex];
|
|
251
|
+
if (option.ref != null && option.ref.current) {
|
|
252
|
+
editor.dispatchCommand(SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND, {
|
|
253
|
+
index: newSelectedIndex,
|
|
254
|
+
option
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
event.preventDefault();
|
|
258
|
+
event.stopImmediatePropagation();
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
}, commandPriority), editor.registerCommand(KEY_ARROW_UP_COMMAND, payload => {
|
|
262
|
+
const event = payload;
|
|
263
|
+
if (options !== null && options.length && selectedIndex !== null) {
|
|
264
|
+
const newSelectedIndex = selectedIndex !== 0 ? selectedIndex - 1 : options.length - 1;
|
|
265
|
+
updateSelectedIndex(newSelectedIndex);
|
|
266
|
+
const option = options[newSelectedIndex];
|
|
267
|
+
if (option.ref != null && option.ref.current) {
|
|
268
|
+
scrollIntoViewIfNeeded(option.ref.current);
|
|
269
|
+
}
|
|
270
|
+
event.preventDefault();
|
|
271
|
+
event.stopImmediatePropagation();
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}, commandPriority), editor.registerCommand(KEY_ESCAPE_COMMAND, payload => {
|
|
275
|
+
const event = payload;
|
|
276
|
+
event.preventDefault();
|
|
277
|
+
event.stopImmediatePropagation();
|
|
278
|
+
close();
|
|
279
|
+
return true;
|
|
280
|
+
}, commandPriority), editor.registerCommand(KEY_TAB_COMMAND, payload => {
|
|
281
|
+
const event = payload;
|
|
282
|
+
if (options === null || selectedIndex === null || options[selectedIndex] == null) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
event.stopImmediatePropagation();
|
|
287
|
+
selectOptionAndCleanUp(options[selectedIndex]);
|
|
288
|
+
return true;
|
|
289
|
+
}, commandPriority), editor.registerCommand(KEY_ENTER_COMMAND, event => {
|
|
290
|
+
if (options === null || selectedIndex === null || options[selectedIndex] == null) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
if (event !== null) {
|
|
294
|
+
event.preventDefault();
|
|
295
|
+
event.stopImmediatePropagation();
|
|
296
|
+
}
|
|
297
|
+
selectOptionAndCleanUp(options[selectedIndex]);
|
|
298
|
+
return true;
|
|
299
|
+
}, commandPriority));
|
|
300
|
+
}, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex, commandPriority]);
|
|
301
|
+
const listItemProps = useMemo(() => ({
|
|
302
|
+
options,
|
|
303
|
+
selectOptionAndCleanUp,
|
|
304
|
+
selectedIndex,
|
|
305
|
+
setHighlightedIndex
|
|
306
|
+
}), [selectOptionAndCleanUp, selectedIndex, options]);
|
|
307
|
+
return menuRenderFn(anchorElementRef, listItemProps, resolution.match ? resolution.match.matchingString : '');
|
|
308
|
+
}
|
|
309
|
+
function useMenuAnchorRef(resolution, setResolution, className, parent = document.body) {
|
|
310
|
+
const [editor] = useLexicalComposerContext();
|
|
311
|
+
const anchorElementRef = useRef(document.createElement('div'));
|
|
312
|
+
const positionMenu = useCallback(() => {
|
|
313
|
+
anchorElementRef.current.style.top = anchorElementRef.current.style.bottom;
|
|
314
|
+
const rootElement = editor.getRootElement();
|
|
315
|
+
const containerDiv = anchorElementRef.current;
|
|
316
|
+
const menuEle = containerDiv.firstChild;
|
|
317
|
+
if (rootElement !== null && resolution !== null) {
|
|
318
|
+
const {
|
|
319
|
+
left,
|
|
320
|
+
top,
|
|
321
|
+
width,
|
|
322
|
+
height
|
|
323
|
+
} = resolution.getRect();
|
|
324
|
+
const anchorHeight = anchorElementRef.current.offsetHeight; // use to position under anchor
|
|
325
|
+
containerDiv.style.top = `${top + window.pageYOffset + anchorHeight + 3}px`;
|
|
326
|
+
containerDiv.style.left = `${left + window.pageXOffset}px`;
|
|
327
|
+
containerDiv.style.height = `${height}px`;
|
|
328
|
+
containerDiv.style.width = `${width}px`;
|
|
329
|
+
if (menuEle !== null) {
|
|
330
|
+
menuEle.style.top = `${top}`;
|
|
331
|
+
const menuRect = menuEle.getBoundingClientRect();
|
|
332
|
+
const menuHeight = menuRect.height;
|
|
333
|
+
const menuWidth = menuRect.width;
|
|
334
|
+
const rootElementRect = rootElement.getBoundingClientRect();
|
|
335
|
+
if (left + menuWidth > rootElementRect.right) {
|
|
336
|
+
containerDiv.style.left = `${rootElementRect.right - menuWidth + window.pageXOffset}px`;
|
|
337
|
+
}
|
|
338
|
+
if ((top + menuHeight > window.innerHeight || top + menuHeight > rootElementRect.bottom) && top - rootElementRect.top > menuHeight) {
|
|
339
|
+
containerDiv.style.top = `${top - menuHeight + window.pageYOffset - height}px`;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (!containerDiv.isConnected) {
|
|
343
|
+
if (className != null) {
|
|
344
|
+
containerDiv.className = className;
|
|
345
|
+
}
|
|
346
|
+
containerDiv.setAttribute('aria-label', 'Typeahead menu');
|
|
347
|
+
containerDiv.setAttribute('id', 'typeahead-menu');
|
|
348
|
+
containerDiv.setAttribute('role', 'listbox');
|
|
349
|
+
containerDiv.style.display = 'block';
|
|
350
|
+
containerDiv.style.position = 'absolute';
|
|
351
|
+
parent.append(containerDiv);
|
|
352
|
+
}
|
|
353
|
+
anchorElementRef.current = containerDiv;
|
|
354
|
+
rootElement.setAttribute('aria-controls', 'typeahead-menu');
|
|
355
|
+
}
|
|
356
|
+
}, [editor, resolution, className, parent]);
|
|
357
|
+
useEffect(() => {
|
|
358
|
+
const rootElement = editor.getRootElement();
|
|
359
|
+
if (resolution !== null) {
|
|
360
|
+
positionMenu();
|
|
361
|
+
return () => {
|
|
362
|
+
if (rootElement !== null) {
|
|
363
|
+
rootElement.removeAttribute('aria-controls');
|
|
364
|
+
}
|
|
365
|
+
const containerDiv = anchorElementRef.current;
|
|
366
|
+
if (containerDiv !== null && containerDiv.isConnected) {
|
|
367
|
+
containerDiv.remove();
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
}, [editor, positionMenu, resolution]);
|
|
372
|
+
const onVisibilityChange = useCallback(isInView => {
|
|
373
|
+
if (resolution !== null) {
|
|
374
|
+
if (!isInView) {
|
|
375
|
+
setResolution(null);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}, [resolution, setResolution]);
|
|
379
|
+
useDynamicPositioning(resolution, anchorElementRef.current, positionMenu, onVisibilityChange);
|
|
380
|
+
return anchorElementRef;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
385
|
+
*
|
|
386
|
+
* This source code is licensed under the MIT license found in the
|
|
387
|
+
* LICENSE file in the root directory of this source tree.
|
|
388
|
+
*
|
|
389
|
+
*/
|
|
390
|
+
const PRE_PORTAL_DIV_SIZE = 1;
|
|
391
|
+
function LexicalContextMenuPlugin({
|
|
392
|
+
options,
|
|
393
|
+
onClose,
|
|
394
|
+
onOpen,
|
|
395
|
+
onSelectOption,
|
|
396
|
+
menuRenderFn: contextMenuRenderFn,
|
|
397
|
+
anchorClassName,
|
|
398
|
+
commandPriority = COMMAND_PRIORITY_LOW,
|
|
399
|
+
parent
|
|
400
|
+
}) {
|
|
401
|
+
const [editor] = useLexicalComposerContext();
|
|
402
|
+
const [resolution, setResolution] = useState(null);
|
|
403
|
+
const menuRef = React.useRef(null);
|
|
404
|
+
const anchorElementRef = useMenuAnchorRef(resolution, setResolution, anchorClassName, parent);
|
|
405
|
+
const closeNodeMenu = useCallback(() => {
|
|
406
|
+
setResolution(null);
|
|
407
|
+
if (onClose != null && resolution !== null) {
|
|
408
|
+
onClose();
|
|
409
|
+
}
|
|
410
|
+
}, [onClose, resolution]);
|
|
411
|
+
const openNodeMenu = useCallback(res => {
|
|
412
|
+
setResolution(res);
|
|
413
|
+
if (onOpen != null && resolution === null) {
|
|
414
|
+
onOpen(res);
|
|
415
|
+
}
|
|
416
|
+
}, [onOpen, resolution]);
|
|
417
|
+
const handleContextMenu = useCallback(event => {
|
|
418
|
+
event.preventDefault();
|
|
419
|
+
openNodeMenu({
|
|
420
|
+
getRect: () => new DOMRect(event.clientX, event.clientY, PRE_PORTAL_DIV_SIZE, PRE_PORTAL_DIV_SIZE)
|
|
421
|
+
});
|
|
422
|
+
}, [openNodeMenu]);
|
|
423
|
+
const handleClick = useCallback(event => {
|
|
424
|
+
if (resolution !== null && menuRef.current != null && event.target != null && !menuRef.current.contains(event.target)) {
|
|
425
|
+
closeNodeMenu();
|
|
426
|
+
}
|
|
427
|
+
}, [closeNodeMenu, resolution]);
|
|
428
|
+
useEffect(() => {
|
|
429
|
+
const editorElement = editor.getRootElement();
|
|
430
|
+
if (editorElement) {
|
|
431
|
+
editorElement.addEventListener('contextmenu', handleContextMenu);
|
|
432
|
+
return () => editorElement.removeEventListener('contextmenu', handleContextMenu);
|
|
433
|
+
}
|
|
434
|
+
}, [editor, handleContextMenu]);
|
|
435
|
+
useEffect(() => {
|
|
436
|
+
document.addEventListener('click', handleClick);
|
|
437
|
+
return () => document.removeEventListener('click', handleClick);
|
|
438
|
+
}, [editor, handleClick]);
|
|
439
|
+
return resolution === null || editor === null ? null : /*#__PURE__*/React.createElement(LexicalMenu, {
|
|
440
|
+
close: closeNodeMenu,
|
|
441
|
+
resolution: resolution,
|
|
442
|
+
editor: editor,
|
|
443
|
+
anchorElementRef: anchorElementRef,
|
|
444
|
+
options: options,
|
|
445
|
+
menuRenderFn: (anchorRef, itemProps) => contextMenuRenderFn(anchorRef, itemProps, {
|
|
446
|
+
setMenuRef: ref => {
|
|
447
|
+
menuRef.current = ref;
|
|
448
|
+
}
|
|
449
|
+
}),
|
|
450
|
+
onSelectOption: onSelectOption,
|
|
451
|
+
commandPriority: commandPriority
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export { LexicalContextMenuPlugin, MenuOption };
|
|
@@ -54,7 +54,9 @@ class MenuOption {
|
|
|
54
54
|
}
|
|
55
55
|
const scrollIntoViewIfNeeded = target => {
|
|
56
56
|
const typeaheadContainerNode = document.getElementById('typeahead-menu');
|
|
57
|
-
if (!typeaheadContainerNode)
|
|
57
|
+
if (!typeaheadContainerNode) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
58
60
|
const typeaheadRect = typeaheadContainerNode.getBoundingClientRect();
|
|
59
61
|
if (typeaheadRect.top + typeaheadRect.height > window.innerHeight) {
|
|
60
62
|
typeaheadContainerNode.scrollIntoView({
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
import * as modDev from './LexicalContextMenuPlugin.dev.esm.js';
|
|
8
|
+
import * as modProd from './LexicalContextMenuPlugin.prod.esm.js';
|
|
9
|
+
const mod = process.env.NODE_ENV === 'development' ? modDev : modProd;
|
|
10
|
+
export const LexicalContextMenuPlugin = mod.LexicalContextMenuPlugin;
|
|
11
|
+
export const MenuOption = mod.MenuOption;
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
'use strict'
|
|
8
|
-
const LexicalContextMenuPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalContextMenuPlugin.dev.js') : require('./LexicalContextMenuPlugin.prod.js')
|
|
8
|
+
const LexicalContextMenuPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalContextMenuPlugin.dev.js') : require('./LexicalContextMenuPlugin.prod.js');
|
|
9
9
|
module.exports = LexicalContextMenuPlugin;
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
import{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{createCommand as e,KEY_ARROW_DOWN_COMMAND as n,KEY_ARROW_UP_COMMAND as o,KEY_ESCAPE_COMMAND as l,KEY_TAB_COMMAND as r,KEY_ENTER_COMMAND as i,COMMAND_PRIORITY_LOW as u,$getSelection as c,$isRangeSelection as s}from"lexical";import*as a from"react";import{useLayoutEffect as m,useEffect as d,useState as p,useCallback as f,useMemo as g,useRef as h}from"react";import{mergeRegister as w}from"@lexical/utils";var v="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?m:d;class y{constructor(t){this.key=t,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(t){this.ref={current:t}}}const b=t=>{const e=document.getElementById("typeahead-menu");if(!e)return;const n=e.getBoundingClientRect();n.top+n.height>window.innerHeight&&e.scrollIntoView({block:"center"}),n.top<0&&e.scrollIntoView({block:"center"}),t.scrollIntoView({block:"nearest"})};function E(t,e){const n=t.getBoundingClientRect(),o=e.getBoundingClientRect();return n.top>o.top&&n.top<o.bottom}function C(e,n,o,l){const[r]=t();d((()=>{if(null!=n&&null!=e){const t=r.getRootElement(),e=null!=t?function(t,e){let n=getComputedStyle(t);const o="absolute"===n.position,l=e?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===n.position)return document.body;for(let e=t;e=e.parentElement;)if(n=getComputedStyle(e),(!o||"static"!==n.position)&&l.test(n.overflow+n.overflowY+n.overflowX))return e;return document.body}(t,!1):document.body;let i=!1,u=E(n,e);const c=function(){i||(window.requestAnimationFrame((function(){o(),i=!1})),i=!0);const t=E(n,e);t!==u&&(u=t,null!=l&&l(t))},s=new ResizeObserver(o);return window.addEventListener("resize",o),document.addEventListener("scroll",c,{capture:!0,passive:!0}),s.observe(n),()=>{s.unobserve(n),window.removeEventListener("resize",o),document.removeEventListener("scroll",c,!0)}}}),[n,r,l,o,e])}const R=e("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function x({close:t,editor:e,anchorElementRef:a,resolution:m,options:h,menuRenderFn:y,onSelectOption:E,shouldSplitNodeWithQuery:C=!1,commandPriority:x=u}){const[O,I]=p(null),S=m.match&&m.match.matchingString;d((()=>{I(0)}),[S]);const A=f((n=>{e.update((()=>{const e=null!=m.match&&C?function(t){const e=c();if(!s(e)||!e.isCollapsed())return null;const n=e.anchor;if("text"!==n.type)return null;const o=n.getNode();if(!o.isSimpleText())return null;const l=n.offset,r=o.getTextContent().slice(0,l),i=t.replaceableString.length,u=l-function(t,e,n){let o=n;for(let n=o;n<=e.length;n++)t.substr(-n)===e.substr(0,n)&&(o=n);return o}(r,t.matchingString,i);if(u<0)return null;let a;return 0===u?[a]=o.splitText(l):[,a]=o.splitText(u,l),a}(m.match):null;E(n,e,t,m.match?m.match.matchingString:"")}))}),[e,C,m.match,E,t]),L=f((t=>{const n=e.getRootElement();null!==n&&(n.setAttribute("aria-activedescendant","typeahead-item-"+t),I(t))}),[e]);d((()=>()=>{const t=e.getRootElement();null!==t&&t.removeAttribute("aria-activedescendant")}),[e]),v((()=>{null===h?I(null):null===O&&L(0)}),[h,O,L]),d((()=>w(e.registerCommand(R,(({option:t})=>!(!t.ref||null==t.ref.current)&&(b(t.ref.current),!0)),x))),[e,L,x]),d((()=>w(e.registerCommand(n,(t=>{const n=t;if(null!==h&&h.length&&null!==O){const t=O!==h.length-1?O+1:0;L(t);const o=h[t];null!=o.ref&&o.ref.current&&e.dispatchCommand(R,{index:t,option:o}),n.preventDefault(),n.stopImmediatePropagation()}return!0}),x),e.registerCommand(o,(t=>{const e=t;if(null!==h&&h.length&&null!==O){const t=0!==O?O-1:h.length-1;L(t);const n=h[t];null!=n.ref&&n.ref.current&&b(n.ref.current),e.preventDefault(),e.stopImmediatePropagation()}return!0}),x),e.registerCommand(l,(e=>{const n=e;return n.preventDefault(),n.stopImmediatePropagation(),t(),!0}),x),e.registerCommand(r,(t=>{const e=t;return null!==h&&null!==O&&null!=h[O]&&(e.preventDefault(),e.stopImmediatePropagation(),A(h[O]),!0)}),x),e.registerCommand(i,(t=>null!==h&&null!==O&&null!=h[O]&&(null!==t&&(t.preventDefault(),t.stopImmediatePropagation()),A(h[O]),!0)),x))),[A,t,e,h,O,L,x]);return y(a,g((()=>({options:h,selectOptionAndCleanUp:A,selectedIndex:O,setHighlightedIndex:I})),[A,O,h]),m.match?m.match.matchingString:"")}function O({options:e,onClose:n,onOpen:o,onSelectOption:l,menuRenderFn:r,anchorClassName:i,commandPriority:c=u,parent:s}){const[m]=t(),[g,w]=p(null),v=a.useRef(null),y=function(e,n,o,l=document.body){const[r]=t(),i=h(document.createElement("div")),u=f((()=>{i.current.style.top=i.current.style.bottom;const t=r.getRootElement(),n=i.current,u=n.firstChild;if(null!==t&&null!==e){const{left:r,top:c,width:s,height:a}=e.getRect(),m=i.current.offsetHeight;if(n.style.top=`${c+window.pageYOffset+m+3}px`,n.style.left=`${r+window.pageXOffset}px`,n.style.height=`${a}px`,n.style.width=`${s}px`,null!==u){u.style.top=`${c}`;const e=u.getBoundingClientRect(),o=e.height,l=e.width,i=t.getBoundingClientRect();r+l>i.right&&(n.style.left=`${i.right-l+window.pageXOffset}px`),(c+o>window.innerHeight||c+o>i.bottom)&&c-i.top>o&&(n.style.top=c-o+window.pageYOffset-a+"px")}n.isConnected||(null!=o&&(n.className=o),n.setAttribute("aria-label","Typeahead menu"),n.setAttribute("id","typeahead-menu"),n.setAttribute("role","listbox"),n.style.display="block",n.style.position="absolute",l.append(n)),i.current=n,t.setAttribute("aria-controls","typeahead-menu")}}),[r,e,o,l]);d((()=>{const t=r.getRootElement();if(null!==e)return u(),()=>{null!==t&&t.removeAttribute("aria-controls");const e=i.current;null!==e&&e.isConnected&&e.remove()}}),[r,u,e]);const c=f((t=>{null!==e&&(t||n(null))}),[e,n]);return C(e,i.current,u,c),i}(g,w,i,s),b=f((()=>{w(null),null!=n&&null!==g&&n()}),[n,g]),E=f((t=>{w(t),null!=o&&null===g&&o(t)}),[o,g]),R=f((t=>{t.preventDefault(),E({getRect:()=>new DOMRect(t.clientX,t.clientY,1,1)})}),[E]),O=f((t=>{null===g||null==v.current||null==t.target||v.current.contains(t.target)||b()}),[b,g]);return d((()=>{const t=m.getRootElement();if(t)return t.addEventListener("contextmenu",R),()=>t.removeEventListener("contextmenu",R)}),[m,R]),d((()=>(document.addEventListener("click",O),()=>document.removeEventListener("click",O))),[m,O]),null===g||null===m?null:a.createElement(x,{close:b,resolution:g,editor:m,anchorElementRef:y,options:e,menuRenderFn:(t,e)=>r(t,e,{setMenuRef:t=>{v.current=t}}),onSelectOption:l,commandPriority:c})}export{O as LexicalContextMenuPlugin,y as MenuOption};
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
import { DecoratorNode } from 'lexical';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
11
|
+
*
|
|
12
|
+
* This source code is licensed under the MIT license found in the
|
|
13
|
+
* LICENSE file in the root directory of this source tree.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
class DecoratorBlockNode extends DecoratorNode {
|
|
17
|
+
constructor(format, key) {
|
|
18
|
+
super(key);
|
|
19
|
+
this.__format = format || '';
|
|
20
|
+
}
|
|
21
|
+
exportJSON() {
|
|
22
|
+
return {
|
|
23
|
+
format: this.__format || '',
|
|
24
|
+
type: 'decorator-block',
|
|
25
|
+
version: 1
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
createDOM() {
|
|
29
|
+
return document.createElement('div');
|
|
30
|
+
}
|
|
31
|
+
updateDOM() {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
setFormat(format) {
|
|
35
|
+
const self = this.getWritable();
|
|
36
|
+
self.__format = format;
|
|
37
|
+
}
|
|
38
|
+
isInline() {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function $isDecoratorBlockNode(node) {
|
|
43
|
+
return node instanceof DecoratorBlockNode;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { $isDecoratorBlockNode, DecoratorBlockNode };
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
import * as modDev from './LexicalDecoratorBlockNode.dev.esm.js';
|
|
8
|
+
import * as modProd from './LexicalDecoratorBlockNode.prod.esm.js';
|
|
9
|
+
const mod = process.env.NODE_ENV === 'development' ? modDev : modProd;
|
|
10
|
+
export const $isDecoratorBlockNode = mod.$isDecoratorBlockNode;
|
|
11
|
+
export const DecoratorBlockNode = mod.DecoratorBlockNode;
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
'use strict'
|
|
8
|
-
const LexicalDecoratorBlockNode = process.env.NODE_ENV === 'development' ? require('./LexicalDecoratorBlockNode.dev.js') : require('./LexicalDecoratorBlockNode.prod.js')
|
|
8
|
+
const LexicalDecoratorBlockNode = process.env.NODE_ENV === 'development' ? require('./LexicalDecoratorBlockNode.dev.js') : require('./LexicalDecoratorBlockNode.prod.js');
|
|
9
9
|
module.exports = LexicalDecoratorBlockNode;
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
import{DecoratorNode as t}from"lexical";class r extends t{constructor(t,r){super(r),this.__format=t||""}exportJSON(){return{format:this.__format||"",type:"decorator-block",version:1}}createDOM(){return document.createElement("div")}updateDOM(){return!1}setFormat(t){this.getWritable().__format=t}isInline(){return!1}}function e(t){return t instanceof r}export{e as $isDecoratorBlockNode,r as DecoratorBlockNode};
|