diff --git a/src/element/index.ts b/src/element/index.ts index 2a96d8cf..1f6722f9 100644 --- a/src/element/index.ts +++ b/src/element/index.ts @@ -13,3 +13,4 @@ export { hitTest } from "./collision"; export { resizeTest } from "./resizeTest"; export { generateDraw } from "./generateDraw"; export { isTextElement } from "./typeChecks"; +export { textWysiwyg } from "./textWysiwyg"; diff --git a/src/element/textWysiwyg.tsx b/src/element/textWysiwyg.tsx new file mode 100644 index 00000000..e31a5941 --- /dev/null +++ b/src/element/textWysiwyg.tsx @@ -0,0 +1,54 @@ +import { KEYS } from "../index"; + +export function textWysiwyg( + x: number, + y: number, + onSubmit: (text: string) => void +) { + const input = document.createElement("input"); + + Object.assign(input.style, { + position: "absolute", + top: y - 8 + "px", + left: x + "px", + transform: "translate(-50%, -50%)", + boxShadow: "none", + textAlign: "center", + width: (window.innerWidth - x) * 2 + "px", + fontSize: "20px", + fontFamily: "Virgil", + border: "none", + background: "transparent" + }); + + input.onkeydown = ev => { + if (ev.key === KEYS.ESCAPE) { + cleanup(); + return; + } + if (ev.key === KEYS.ENTER) { + handleSubmit(); + } + }; + input.onblur = handleSubmit; + + function stopEvent(ev: Event) { + ev.stopPropagation(); + } + + function handleSubmit() { + if (input.value) { + onSubmit(input.value); + } + cleanup(); + } + + function cleanup() { + window.removeEventListener("wheel", stopEvent, true); + document.body.removeChild(input); + } + + window.addEventListener("wheel", stopEvent, true); + document.body.appendChild(input); + input.focus(); +} diff --git a/src/index.tsx b/src/index.tsx index cf30ed22..edb1110f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,7 +4,13 @@ import rough from "roughjs/bin/wrappers/rough"; import { moveOneLeft, moveAllLeft, moveOneRight, moveAllRight } from "./zindex"; import { randomSeed } from "./random"; -import { newElement, resizeTest, generateDraw, isTextElement } from "./element"; +import { + newElement, + resizeTest, + generateDraw, + isTextElement, + textWysiwyg +} from "./element"; import { renderScene, clearSelection, @@ -46,12 +52,13 @@ const DEFAULT_PROJECT_NAME = `excalidraw-${getDateTime()}`; const CANVAS_WINDOW_OFFSET_LEFT = 250; const CANVAS_WINDOW_OFFSET_TOP = 0; -const KEYS = { +export const KEYS = { ARROW_LEFT: "ArrowLeft", ARROW_RIGHT: "ArrowRight", ARROW_DOWN: "ArrowDown", ARROW_UP: "ArrowUp", ESCAPE: "Escape", + ENTER: "Enter", DELETE: "Delete", BACKSPACE: "Backspace" }; @@ -75,9 +82,8 @@ function resetCursor() { document.documentElement.style.cursor = ""; } -function addTextElement(element: ExcalidrawTextElement) { +function addTextElement(element: ExcalidrawTextElement, text = "") { resetCursor(); - const text = prompt("What text do you want?"); if (text === null || text === "") { return false; } @@ -728,22 +734,23 @@ class App extends React.Component<{}, AppState> { } if (isTextElement(element)) { - if (!addTextElement(element)) { - return; - } + textWysiwyg(e.clientX, e.clientY, text => { + addTextElement(element, text); + generateDraw(element); + elements.push(element); + element.isSelected = true; + + this.setState({ + draggingElement: null, + elementType: "selection" + }); + }); + return; } generateDraw(element); elements.push(element); - if (this.state.elementType === "text") { - this.setState({ - draggingElement: null, - elementType: "selection" - }); - element.isSelected = true; - } else { - this.setState({ draggingElement: element }); - } + this.setState({ draggingElement: element }); let lastX = x; let lastY = y; @@ -964,20 +971,17 @@ class App extends React.Component<{}, AppState> { 100 ); - if (!addTextElement(element as ExcalidrawTextElement)) { - return; - } + textWysiwyg(e.clientX, e.clientY, text => { + addTextElement(element as ExcalidrawTextElement, text); + generateDraw(element); + elements.push(element); + element.isSelected = true; - generateDraw(element); - elements.push(element); - - this.setState({ - draggingElement: null, - elementType: "selection" + this.setState({ + draggingElement: null, + elementType: "selection" + }); }); - element.isSelected = true; - - this.forceUpdate(); }} />