| 
					
				 | 
			
			
				@@ -47,7 +47,7 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   id: ExcalidrawElement["id"]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   appState: AppState; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   onChange?: (text: string) => void; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  onSubmit: (text: string) => void; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  onSubmit: (data: { text: string; viaKeyboard: boolean }) => void; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   getViewportCoords: (x: number, y: number) => [number, number]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   element: ExcalidrawElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   canvas: HTMLCanvasElement | null; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -136,12 +136,14 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   editable.onkeydown = (event) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (event.key === KEYS.ESCAPE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       event.preventDefault(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      submittedViaKeyboard = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       handleSubmit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else if (event.key === KEYS.ENTER && event[KEYS.CTRL_OR_CMD]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       event.preventDefault(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (event.isComposing || event.keyCode === 229) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      submittedViaKeyboard = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       handleSubmit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else if (event.key === KEYS.ENTER && !event.altKey) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       event.stopPropagation(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -153,8 +155,14 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     event.stopPropagation(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // using a state variable instead of passing it to the handleSubmit callback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // so that we don't need to create separate a callback for event handlers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let submittedViaKeyboard = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const handleSubmit = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    onSubmit(normalizeText(editable.value)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onSubmit({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      text: normalizeText(editable.value), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      viaKeyboard: submittedViaKeyboard, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cleanup(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -175,7 +183,7 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     window.removeEventListener("resize", updateWysiwygStyle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     window.removeEventListener("wheel", stopEvent, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     window.removeEventListener("pointerdown", onPointerDown); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    window.removeEventListener("pointerup", rebindBlur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    window.removeEventListener("pointerup", bindBlurEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     window.removeEventListener("blur", handleSubmit); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     unbindUpdate(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -183,10 +191,12 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     editable.remove(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const rebindBlur = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    window.removeEventListener("pointerup", rebindBlur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // deferred to guard against focus traps on various UIs that steal focus 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // upon pointerUp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const bindBlurEvent = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    window.removeEventListener("pointerup", bindBlurEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Deferred so that the pointerdown that initiates the wysiwyg doesn't 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // trigger the blur on ensuing pointerup. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Also to handle cases such as picking a color which would trigger a blur 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // in that same tick. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       editable.onblur = handleSubmit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // case: clicking on the same property → no change → no update → no focus 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -202,7 +212,7 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       !isWritableElement(event.target) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       editable.onblur = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      window.addEventListener("pointerup", rebindBlur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      window.addEventListener("pointerup", bindBlurEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // handle edge-case where pointerup doesn't fire e.g. due to user 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // alt-tabbing away 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       window.addEventListener("blur", handleSubmit); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -215,9 +225,14 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     editable.focus(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // --------------------------------------------------------------------------- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let isDestroyed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  editable.onblur = handleSubmit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // select on init (focusing is done separately inside the bindBlurEvent() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // because we need it to happen *after* the blur event from `pointerdown`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  editable.select(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bindBlurEvent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // reposition wysiwyg in case of canvas is resized. Using ResizeObserver 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // is preferred so we catch changes from host, where window may not resize. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -239,6 +254,4 @@ export const textWysiwyg = ({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   document 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     .querySelector(".excalidraw-textEditorContainer")! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     .appendChild(editable); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  editable.focus(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  editable.select(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 |