@@ -9,20 +9,38 @@ function resolveTargets(target) {
9
9
return [ target ?. current ] ;
10
10
}
11
11
12
- function hasSelection ( ) {
13
- const selection = window ?. getSelection ( ) ;
14
- return ! selection ?. isCollapsed ;
12
+ function getSelection ( e ) {
13
+ return getDomSelection ( e ) || getUISelection ( e ) ;
15
14
}
16
15
17
- function getSelection ( ) {
18
- if ( ! hasSelection ( ) ) return ;
16
+ /* Input and Textarea selections are rendered in the browsers native UI. We need to handle them differently */
17
+ function getUISelection ( e ) {
18
+ const focusedElement = document ?. activeElement ;
19
+
20
+ const selectedText = focusedElement ?. value ?. substring ?. (
21
+ focusedElement ?. selectionStart ,
22
+ focusedElement ?. selectionEnd
23
+ ) ;
24
+
25
+ if ( ! selectedText ) return ;
26
+
27
+ return {
28
+ baseNode : focusedElement ,
29
+ extentNode : focusedElement ,
30
+ range : focusedElement /* TODO: better support X,Y of mouse */ ,
31
+ selectedText,
32
+ } ;
33
+ }
34
+
35
+ /* Get the selection for non-UI elements */
36
+ function getDomSelection ( ) {
37
+ if ( window ?. getSelection ?. ( ) ?. isCollapsed ) return ;
19
38
const selection = window ?. getSelection ( ) ;
20
39
const range = selection ?. getRangeAt ( 0 ) ;
21
40
const selectedHtml = Serializer . serializeToString ( range ?. cloneContents ( ) ) ;
22
41
const selectedText = selection ?. toString ( ) ;
23
42
return {
24
43
baseNode : selection ?. anchorNode ,
25
- baseOffset : selection ?. anchorOffset ,
26
44
extentNode : selection ?. focusNode ,
27
45
range,
28
46
selectedHtml,
@@ -37,16 +55,17 @@ function isTargetInSelection(targets, selection) {
37
55
38
56
export function useTextSelection ( target ) {
39
57
const [ state , setState ] = useState ( ) ;
40
- const updateAnchorPos = ( ) => {
58
+
59
+ const updateAnchorPos = ( e ) => {
41
60
const targets = resolveTargets ( target ) ;
42
- const selection = getSelection ( ) ;
61
+ const selection = getSelection ( e ) ;
43
62
if ( isTargetInSelection ( targets , selection ) ) {
44
63
setState ( selection ) ;
45
64
}
46
65
} ;
47
66
48
- const onSelectionChange = ( ) => {
49
- const selection = getSelection ( ) ;
67
+ const onSelectionChange = ( e ) => {
68
+ const selection = getSelection ( e ) ;
50
69
if ( ! selection ?. range ) {
51
70
setState ( { } ) ;
52
71
}
@@ -64,6 +83,7 @@ export function useTextSelection(target) {
64
83
document . addEventListener ( "scroll" , onWindowScroll , {
65
84
capture : true ,
66
85
} ) ;
86
+
67
87
return ( ) => {
68
88
document . removeEventListener ( "mouseup" , updateAnchorPos ) ;
69
89
document . removeEventListener ( "selectionchange" , onSelectionChange ) ;
0 commit comments