mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-04-14 16:40:58 -04:00
This was added when we were computing the width without adding "pre" behavior. Now it is no longer an issue
123 lines
2.8 KiB
TypeScript
123 lines
2.8 KiB
TypeScript
import { KEYS } from "../keys";
|
|
import { selectNode } from "../utils";
|
|
|
|
type TextWysiwygParams = {
|
|
initText: string;
|
|
x: number;
|
|
y: number;
|
|
strokeColor: string;
|
|
font: string;
|
|
opacity: number;
|
|
zoom: number;
|
|
onSubmit: (text: string) => void;
|
|
onCancel: () => void;
|
|
};
|
|
|
|
export function textWysiwyg({
|
|
initText,
|
|
x,
|
|
y,
|
|
strokeColor,
|
|
font,
|
|
opacity,
|
|
zoom,
|
|
onSubmit,
|
|
onCancel,
|
|
}: TextWysiwygParams) {
|
|
const editable = document.createElement("div");
|
|
try {
|
|
editable.contentEditable = "plaintext-only";
|
|
} catch {
|
|
editable.contentEditable = "true";
|
|
}
|
|
editable.tabIndex = 0;
|
|
editable.innerText = initText;
|
|
editable.dataset.type = "wysiwyg";
|
|
|
|
Object.assign(editable.style, {
|
|
color: strokeColor,
|
|
position: "fixed",
|
|
opacity: opacity / 100,
|
|
top: `${y}px`,
|
|
left: `${x}px`,
|
|
transform: `translate(-50%, -50%) scale(${zoom})`,
|
|
textAlign: "left",
|
|
display: "inline-block",
|
|
font: font,
|
|
padding: "4px",
|
|
// This needs to have "1px solid" otherwise the carret doesn't show up
|
|
// the first time on Safari and Chrome!
|
|
outline: "1px solid transparent",
|
|
whiteSpace: "nowrap",
|
|
minHeight: "1em",
|
|
backfaceVisibility: "hidden",
|
|
});
|
|
|
|
editable.onpaste = ev => {
|
|
try {
|
|
const selection = window.getSelection();
|
|
if (!selection?.rangeCount) {
|
|
return;
|
|
}
|
|
selection.deleteFromDocument();
|
|
|
|
const text = ev.clipboardData!.getData("text").replace(/\r\n?/g, "\n");
|
|
|
|
const span = document.createElement("span");
|
|
span.innerText = text;
|
|
const range = selection.getRangeAt(0);
|
|
range.insertNode(span);
|
|
|
|
// deselect
|
|
window.getSelection()!.removeAllRanges();
|
|
range.setStart(span, span.childNodes.length);
|
|
range.setEnd(span, span.childNodes.length);
|
|
selection.addRange(range);
|
|
|
|
ev.preventDefault();
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
editable.onkeydown = ev => {
|
|
if (ev.key === KEYS.ESCAPE) {
|
|
ev.preventDefault();
|
|
handleSubmit();
|
|
}
|
|
if (ev.key === KEYS.ENTER && !ev.shiftKey) {
|
|
ev.preventDefault();
|
|
if (ev.isComposing || ev.keyCode === 229) {
|
|
return;
|
|
}
|
|
handleSubmit();
|
|
}
|
|
};
|
|
editable.onblur = handleSubmit;
|
|
|
|
function stopEvent(ev: Event) {
|
|
ev.stopPropagation();
|
|
}
|
|
|
|
function handleSubmit() {
|
|
if (editable.innerText) {
|
|
onSubmit(editable.innerText);
|
|
} else {
|
|
onCancel();
|
|
}
|
|
cleanup();
|
|
}
|
|
|
|
function cleanup() {
|
|
editable.onblur = null;
|
|
editable.onkeydown = null;
|
|
editable.onpaste = null;
|
|
window.removeEventListener("wheel", stopEvent, true);
|
|
document.body.removeChild(editable);
|
|
}
|
|
|
|
window.addEventListener("wheel", stopEvent, true);
|
|
document.body.appendChild(editable);
|
|
editable.focus();
|
|
selectNode(editable);
|
|
}
|