tldraw
Version:
A tiny little drawing editor.
165 lines (164 loc) • 5.23 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { tlenv, tltime, useMaybeEditor } from "@tldraw/editor";
import classNames from "classnames";
import * as React from "react";
import { useTranslation } from "../../hooks/useTranslation/useTranslation.mjs";
import { TldrawUiIcon } from "./TldrawUiIcon.mjs";
const TldrawUiInput = React.forwardRef(
function TldrawUiInput2({
className,
label,
icon,
iconLeft,
iconLabel,
autoSelect = false,
autoFocus = false,
defaultValue,
placeholder,
onComplete,
onValueChange,
onCancel,
onFocus,
onBlur,
shouldManuallyMaintainScrollPositionWhenFocused = false,
children,
value,
"data-testid": dataTestId,
disabled,
"aria-label": ariaLabel
}, ref) {
const editor = useMaybeEditor();
const rInputRef = React.useRef(null);
React.useImperativeHandle(ref, () => rInputRef.current);
const msg = useTranslation();
const rInitialValue = React.useRef(defaultValue ?? "");
const rCurrentValue = React.useRef(defaultValue ?? "");
const isComposing = React.useRef(false);
const [isFocused, setIsFocused] = React.useState(false);
const handleFocus = React.useCallback(
(e) => {
setIsFocused(true);
const elm = e.currentTarget;
rCurrentValue.current = elm.value;
if (editor) {
editor.timers.requestAnimationFrame(() => {
if (autoSelect) {
elm.select();
}
});
} else {
tltime.requestAnimationFrame("anon", () => {
if (autoSelect) {
elm.select();
}
});
}
onFocus?.();
},
[autoSelect, editor, onFocus]
);
const handleChange = React.useCallback(
(e) => {
const value2 = e.currentTarget.value;
rCurrentValue.current = value2;
onValueChange?.(value2);
},
[onValueChange]
);
const handleKeyDownCapture = React.useCallback(
(e) => {
switch (e.key) {
case "Enter": {
if (isComposing.current) return;
e.currentTarget.blur();
e.stopPropagation();
onComplete?.(e.currentTarget.value);
break;
}
case "Escape": {
e.currentTarget.value = rInitialValue.current;
onCancel?.(e.currentTarget.value);
e.currentTarget.blur();
e.stopPropagation();
break;
}
}
},
[onComplete, onCancel]
);
const handleBlur = React.useCallback(
(e) => {
setIsFocused(false);
const value2 = e.currentTarget.value;
onBlur?.(value2);
},
[onBlur]
);
const handleCompositionStart = React.useCallback(() => isComposing.current = true, []);
const handleCompositionEnd = React.useCallback(() => isComposing.current = false, []);
React.useEffect(() => {
if (!tlenv.isIos) return void 0;
const visualViewport = window.visualViewport;
if (isFocused && shouldManuallyMaintainScrollPositionWhenFocused && visualViewport) {
const onViewportChange = () => {
rInputRef.current?.scrollIntoView({ block: "center" });
};
visualViewport.addEventListener("resize", onViewportChange);
visualViewport.addEventListener("scroll", onViewportChange);
if (editor) {
editor.timers.requestAnimationFrame(() => {
rInputRef.current?.scrollIntoView({ block: "center" });
});
} else {
tltime.requestAnimationFrame("anon", () => {
rInputRef.current?.scrollIntoView({ block: "center" });
});
}
return () => {
visualViewport.removeEventListener("resize", onViewportChange);
visualViewport.removeEventListener("scroll", onViewportChange);
};
}
return void 0;
}, [isFocused, editor, shouldManuallyMaintainScrollPositionWhenFocused]);
return /* @__PURE__ */ jsxs("div", { draggable: false, className: "tlui-input__wrapper", children: [
children,
label && /* @__PURE__ */ jsx("label", { children: msg(label) }),
iconLeft && /* @__PURE__ */ jsx(
TldrawUiIcon,
{
label: iconLabel ? msg(iconLabel) : "",
icon: iconLeft,
className: "tlui-icon-left",
small: true
}
),
/* @__PURE__ */ jsx(
"input",
{
ref: rInputRef,
className: classNames("tlui-input", className),
type: "text",
defaultValue,
onKeyDownCapture: handleKeyDownCapture,
onChange: handleChange,
onFocus: handleFocus,
onBlur: handleBlur,
onCompositionStart: handleCompositionStart,
onCompositionEnd: handleCompositionEnd,
autoFocus,
"aria-label": ariaLabel,
placeholder,
value,
"data-testid": dataTestId,
disabled
}
),
icon && /* @__PURE__ */ jsx(TldrawUiIcon, { label: iconLabel ? msg(iconLabel) : "", icon, small: !!label })
] });
}
);
export {
TldrawUiInput
};
//# sourceMappingURL=TldrawUiInput.mjs.map