11import type { Editor } from "@graphite/editor" ;
2+ import { insertAtCaret , readAtCaret } from "@graphite/utility-functions/clipboard" ;
23
34let editorRef : Editor | undefined = undefined ;
45
56export function createClipboardManager ( editor : Editor ) {
7+ destroyClipboardManager ( ) ;
8+
69 editorRef = editor ;
710
811 editor . subscriptions . subscribeFrontendMessage ( "TriggerClipboardWrite" , ( data ) => {
@@ -28,89 +31,7 @@ export function destroyClipboardManager() {
2831 editor . subscriptions . unsubscribeFrontendMessage ( "TriggerSelectionWrite" ) ;
2932}
3033
31- function readAtCaret ( cut : boolean ) : string | undefined {
32- const element = window . document . activeElement ;
33-
34- if ( element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement ) {
35- const start = element . selectionStart ;
36- const end = element . selectionEnd ;
37-
38- if ( ( ! start && start !== 0 ) || ( ! end && end !== 0 ) || start === end ) {
39- return undefined ;
40- }
41-
42- const value = element . value ;
43- const selectedText = value . slice ( start , end ) ;
44-
45- if ( cut ) {
46- element . value = value . slice ( 0 , start ) + value . slice ( end ) ;
47-
48- element . selectionStart = element . selectionEnd = start ;
49- element . dispatchEvent ( new Event ( "input" , { bubbles : true } ) ) ;
50- }
51-
52- return selectedText ;
53- }
54-
55- const selection = window . getSelection ( ) ;
56- if ( ! selection || selection . rangeCount === 0 ) {
57- return undefined ;
58- }
59-
60- const selectedText = String ( selection ) ;
61- if ( ! selectedText ) return undefined ;
62-
63- if ( cut ) {
64- const range = selection . getRangeAt ( 0 ) ;
65- range . deleteContents ( ) ;
66-
67- range . collapse ( true ) ;
68- selection . removeAllRanges ( ) ;
69- selection . addRange ( range ) ;
70- }
71-
72- return selectedText ;
73- }
74-
75- function insertAtCaret ( text : string ) {
76- const element = window . document . activeElement ;
77-
78- if ( ! element ) return ;
79-
80- if ( element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement ) {
81- const start = element . selectionStart ;
82- const end = element . selectionEnd ;
83-
84- if ( ( ! start && start !== 0 ) || ( ! end && end !== 0 ) ) return ;
85-
86- const value = element . value ;
87-
88- element . value = value . slice ( 0 , start ) + text + value . slice ( end ) ;
89-
90- const newPos = start + text . length ;
91- element . selectionStart = element . selectionEnd = newPos ;
92- } else if ( element instanceof HTMLElement && element . isContentEditable ) {
93- const selection = window . getSelection ( ) ;
94- if ( ! selection || selection . rangeCount === 0 ) return ;
95-
96- const range = selection . getRangeAt ( 0 ) ;
97- range . deleteContents ( ) ;
98-
99- const textNode = window . document . createTextNode ( text ) ;
100- range . insertNode ( textNode ) ;
101-
102- range . setStartAfter ( textNode ) ;
103- range . collapse ( true ) ;
104-
105- selection . removeAllRanges ( ) ;
106- selection . addRange ( range ) ;
107- }
108-
109- element . dispatchEvent ( new Event ( "input" , { bubbles : true } ) ) ;
110- }
111-
11234// Self-accepting HMR: tear down the old instance and re-create with the new module's code
11335import . meta. hot ?. accept ( ( newModule ) => {
114- destroyClipboardManager ( ) ;
11536 if ( editorRef ) newModule ?. createClipboardManager ( editorRef ) ;
11637} ) ;
0 commit comments