tldraw
Version:
A tiny little drawing editor.
122 lines (121 loc) • 3.31 kB
JavaScript
import {
getPointerInfo,
noop,
stopEventPropagation,
tlenv,
useEditor,
useValue
} from "@tldraw/editor";
import { useCallback, useEffect, useRef } from "react";
import { TextHelpers } from "./TextHelpers.mjs";
function useEditablePlainText(shapeId, type, text) {
const commonUseEditableTextHandlers = useEditableTextCommon(shapeId);
const isEditing = commonUseEditableTextHandlers.isEditing;
const editor = useEditor();
const rInput = useRef(null);
const isEmpty = (text || "").trim().length === 0;
useEffect(() => {
function selectAllIfEditing(event) {
if (event.shapeId === shapeId) {
rInput.current?.select?.();
}
}
editor.on("select-all-text", selectAllIfEditing);
return () => {
editor.off("select-all-text", selectAllIfEditing);
};
}, [editor, shapeId, isEditing]);
useEffect(() => {
if (!isEditing) return;
if (document.activeElement !== rInput.current) {
rInput.current?.focus();
}
if (editor.getInstanceState().isCoarsePointer) {
rInput.current?.select();
}
if (tlenv.isSafari) {
rInput.current?.blur();
rInput.current?.focus();
}
}, [editor, isEditing]);
const handleKeyDown = useCallback(
(e) => {
if (editor.getEditingShapeId() !== shapeId) return;
switch (e.key) {
case "Enter": {
if (e.ctrlKey || e.metaKey) {
editor.complete();
}
break;
}
}
},
[editor, shapeId]
);
const handleChange = useCallback(
({ plaintext }) => {
if (editor.getEditingShapeId() !== shapeId) return;
const normalizedPlaintext = TextHelpers.normalizeText(plaintext || "");
editor.updateShape({
id: shapeId,
type,
props: { text: normalizedPlaintext }
});
},
[editor, shapeId, type]
);
return {
rInput,
handleKeyDown,
handleChange,
isEmpty,
...commonUseEditableTextHandlers
};
}
function useIsReadyForEditing(editor, shapeId) {
return useValue(
"isReadyForEditing",
() => {
const editingShapeId = editor.getEditingShapeId();
return (
// something's being editing... and either it's this shape OR this shape is hovered
(editingShapeId !== null && (editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId))
);
},
[editor, shapeId]
);
}
function useEditableTextCommon(shapeId) {
const editor = useEditor();
const isEditing = useValue("isEditing", () => editor.getEditingShapeId() === shapeId, [editor]);
const isReadyForEditing = useIsReadyForEditing(editor, shapeId);
const handleInputPointerDown = useCallback(
(e) => {
editor.dispatch({
...getPointerInfo(e),
type: "pointer",
name: "pointer_down",
target: "shape",
shape: editor.getShape(shapeId)
});
stopEventPropagation(e);
},
[editor, shapeId]
);
return {
handleFocus: noop,
handleBlur: noop,
handleInputPointerDown,
handleDoubleClick: stopEventPropagation,
isEditing,
isReadyForEditing
};
}
const useEditableText = useEditablePlainText;
export {
useEditablePlainText,
useEditableText,
useEditableTextCommon,
useIsReadyForEditing
};
//# sourceMappingURL=useEditablePlainText.mjs.map