4
4
* MIT License
5
5
*/
6
6
7
- import type { JSX } from 'react' ;
8
-
9
- import {
10
- $isCodeNode ,
11
- CodeNode ,
12
- getLanguageFriendlyName ,
13
- normalizeCodeLang ,
14
- } from '@lexical/code' ;
15
- import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' ;
16
- import { $getNearestNodeFromDOMNode , isHTMLElement } from 'lexical' ;
17
- import { useEffect , useRef , useState } from 'react' ;
18
- import { createPortal } from 'react-dom' ;
19
-
20
- import { CopyButton } from '../components/CopyButton' ;
21
- import { canBePrettier , PrettierButton } from '../components/PrettierButton' ;
22
- import { useDebounce } from './../utils' ;
7
+ import { useEffect , useRef , useState } from 'react' ;
8
+ import type { JSX } from 'react' ;
9
+ import { createPortal } from 'react-dom' ;
10
+ import { $isCodeNode , CodeNode , getLanguageFriendlyName , normalizeCodeLang } from '@lexical/code' ;
11
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' ;
12
+ import { $getNearestNodeFromDOMNode , isHTMLElement } from 'lexical' ;
13
+ import { CopyButton } from '../components/CopyButton' ;
14
+ import { canBePrettier , PrettierButton } from '../components/PrettierButton' ;
15
+ import { useDebounce } from './../hooks' ;
23
16
24
17
import './../../style/lexical/CodeActionMenuPlugin.css' ;
25
18
26
19
const CODE_PADDING = 8 ;
27
20
28
- interface Position {
21
+ interface Position {
29
22
top : string ;
30
23
right : string ;
31
24
}
32
25
33
- function CodeActionMenuContainer ( {
34
- anchorElem,
35
- } : {
36
- anchorElem : HTMLElement ;
37
- } ) : JSX . Element {
26
+ function CodeActionMenuContainer ( { anchorElem } : { anchorElem : HTMLElement ; } ) : JSX . Element {
38
27
const [ editor ] = useLexicalComposerContext ( ) ;
39
-
40
28
const [ lang , setLang ] = useState ( '' ) ;
41
29
const [ isShown , setShown ] = useState < boolean > ( false ) ;
42
30
const [ shouldListenMouseMove , setShouldListenMouseMove ] =
@@ -48,19 +36,19 @@ function CodeActionMenuContainer({
48
36
const codeSetRef = useRef < Set < string > > ( new Set ( ) ) ;
49
37
const codeDOMNodeRef = useRef < HTMLElement | null > ( null ) ;
50
38
51
- function getCodeDOMNode ( ) : HTMLElement | null {
39
+ function getCodeDOMNode ( ) : HTMLElement | null {
52
40
return codeDOMNodeRef . current ;
53
41
}
54
42
55
43
const debouncedOnMouseMove = useDebounce (
56
- ( event : MouseEvent ) => {
57
- const { codeDOMNode, isOutside} = getMouseInfo ( event ) ;
58
- if ( isOutside ) {
44
+ ( event : MouseEvent ) => {
45
+ const { codeDOMNode, isOutside } = getMouseInfo ( event ) ;
46
+ if ( isOutside ) {
59
47
setShown ( false ) ;
60
48
return ;
61
49
}
62
50
63
- if ( ! codeDOMNode ) {
51
+ if ( ! codeDOMNode ) {
64
52
return ;
65
53
}
66
54
@@ -69,19 +57,19 @@ function CodeActionMenuContainer({
69
57
let codeNode : CodeNode | null = null ;
70
58
let _lang = '' ;
71
59
72
- editor . update ( ( ) => {
60
+ editor . update ( ( ) => {
73
61
const maybeCodeNode = $getNearestNodeFromDOMNode ( codeDOMNode ) ;
74
62
75
- if ( $isCodeNode ( maybeCodeNode ) ) {
63
+ if ( $isCodeNode ( maybeCodeNode ) ) {
76
64
codeNode = maybeCodeNode ;
77
65
_lang = codeNode . getLanguage ( ) || '' ;
78
66
}
79
67
} ) ;
80
68
81
- if ( codeNode ) {
82
- const { y : editorElemY , right : editorElemRight } =
69
+ if ( codeNode ) {
70
+ const { y : editorElemY , right : editorElemRight } =
83
71
anchorElem . getBoundingClientRect ( ) ;
84
- const { y, right} = codeDOMNode . getBoundingClientRect ( ) ;
72
+ const { y, right } = codeDOMNode . getBoundingClientRect ( ) ;
85
73
setLang ( _lang ) ;
86
74
setShown ( true ) ;
87
75
setPosition ( {
@@ -94,27 +82,27 @@ function CodeActionMenuContainer({
94
82
1000 ,
95
83
) ;
96
84
97
- useEffect ( ( ) => {
98
- if ( ! shouldListenMouseMove ) {
85
+ useEffect ( ( ) => {
86
+ if ( ! shouldListenMouseMove ) {
99
87
return ;
100
88
}
101
89
102
90
document . addEventListener ( 'mousemove' , debouncedOnMouseMove ) ;
103
91
104
- return ( ) => {
92
+ return ( ) => {
105
93
setShown ( false ) ;
106
94
debouncedOnMouseMove . cancel ( ) ;
107
95
document . removeEventListener ( 'mousemove' , debouncedOnMouseMove ) ;
108
96
} ;
109
97
} , [ shouldListenMouseMove , debouncedOnMouseMove ] ) ;
110
98
111
- useEffect ( ( ) => {
99
+ useEffect ( ( ) => {
112
100
return editor . registerMutationListener (
113
101
CodeNode ,
114
- ( mutations ) => {
115
- editor . getEditorState ( ) . read ( ( ) => {
116
- for ( const [ key , type ] of mutations ) {
117
- switch ( type ) {
102
+ ( mutations ) => {
103
+ editor . getEditorState ( ) . read ( ( ) => {
104
+ for ( const [ key , type ] of mutations ) {
105
+ switch ( type ) {
118
106
case 'created' :
119
107
codeSetRef . current . add ( key ) ;
120
108
break ;
@@ -130,7 +118,7 @@ function CodeActionMenuContainer({
130
118
} ) ;
131
119
setShouldListenMouseMove ( codeSetRef . current . size > 0 ) ;
132
120
} ,
133
- { skipInitialization : false } ,
121
+ { skipInitialization : false } ,
134
122
) ;
135
123
} , [ editor ] ) ;
136
124
@@ -139,11 +127,11 @@ function CodeActionMenuContainer({
139
127
140
128
return (
141
129
< >
142
- { isShown ? (
130
+ { isShown ? (
143
131
< div className = "code-action-menu-container" style = { { ...position } } >
144
132
< div className = "code-highlight-language" > { codeFriendlyName } </ div >
145
- < CopyButton editor = { editor } getCodeDOMNode = { getCodeDOMNode } />
146
- { canBePrettier ( normalizedLang ) ? (
133
+ < CopyButton editor = { editor } getCodeDOMNode = { getCodeDOMNode } />
134
+ { canBePrettier ( normalizedLang ) ? (
147
135
< PrettierButton
148
136
editor = { editor }
149
137
getCodeDOMNode = { getCodeDOMNode }
@@ -156,13 +144,13 @@ function CodeActionMenuContainer({
156
144
) ;
157
145
}
158
146
159
- function getMouseInfo ( event : MouseEvent ) : {
147
+ function getMouseInfo ( event : MouseEvent ) : {
160
148
codeDOMNode : HTMLElement | null ;
161
149
isOutside : boolean ;
162
- } {
150
+ } {
163
151
const target = event . target ;
164
152
165
- if ( isHTMLElement ( target ) ) {
153
+ if ( isHTMLElement ( target ) ) {
166
154
const codeDOMNode = target . closest < HTMLElement > (
167
155
'code.PlaygroundEditorTheme__code' ,
168
156
) ;
@@ -171,19 +159,19 @@ function getMouseInfo(event: MouseEvent): {
171
159
target . closest < HTMLElement > ( 'div.code-action-menu-container' )
172
160
) ;
173
161
174
- return { codeDOMNode, isOutside} ;
175
- } else {
176
- return { codeDOMNode : null , isOutside : true } ;
162
+ return { codeDOMNode, isOutside} ;
163
+ } else {
164
+ return { codeDOMNode : null , isOutside : true } ;
177
165
}
178
166
}
179
167
180
168
export function CodeActionMenuPlugin ( {
181
169
anchorElem = document . body ,
182
- } : {
170
+ } : {
183
171
anchorElem ?: HTMLElement ;
184
- } ) : React . ReactPortal | null {
172
+ } ) : React . ReactPortal | null {
185
173
return createPortal (
186
- < CodeActionMenuContainer anchorElem = { anchorElem } /> ,
174
+ < CodeActionMenuContainer anchorElem = { anchorElem } /> ,
187
175
anchorElem ,
188
176
) ;
189
177
}
0 commit comments