import { FC, TextareaHTMLAttributes, useCallback, useEffect, useRef, } from "react"; import { FMCompDef } from "../../../../../utils/types/meta-fn"; import { useGlobal, useLocal } from "web-utils"; import { EDGlobal } from "../../../logic/ed-global"; import { Tooltip } from "../../../../../utils/ui/tooltip"; export const EdPropInstanceText: FC<{ name: string; mprop: FMCompDef; }> = ({ name, mprop }) => { const p = useGlobal(EDGlobal, "EDITOR"); const local = useLocal({ value: "", codeEditing: false, timeout: null as any, }); const val = mprop.get("value"); const valBuilt = mprop.get("valueBuilt"); useEffect(() => { if (val) { try { eval(`local.value = ${valBuilt}`); } catch (e) {} } else { local.value = ""; } local.render(); }, [val, valBuilt]); const label = (
{name}
); return (
{name.length > 8 ? ( {label} ) : ( label )} { local.value = e.currentTarget.value; local.render(); clearTimeout(local.timeout); local.timeout = setTimeout(() => { mprop.doc?.transact(() => { mprop.set("value", `\`${local.value}\``); mprop.set("valueBuilt", `\`${local.value}\``); }); }, 1000); }} />
); }; export function AutoHeightTextarea({ minRows = 1, ...props }: TextareaHTMLAttributes & { minRows?: number }) { const ref = useRef(null); const calculateAndSetHeight = useCallback(() => { if (!ref.current) { return; } const { borderBottomWidth, borderTopWidth, boxSizing, lineHeight, paddingBottom, paddingTop, } = window.getComputedStyle(ref.current); ref.current.style.height = lineHeight; // set height temporarily to a single row to obtain scrollHeight, disregarding empty space after text (otherwise, scrollHeight would be equal to the height of the element) - this solves auto-shrinking of the textarea (it's not needed for auto-growing it) const { scrollHeight } = ref.current; // scrollHeight = content height + padding top + padding bottom if (boxSizing === "border-box") { const minHeight = parseFloat(lineHeight) * minRows + parseFloat(paddingTop) + parseFloat(paddingBottom) + parseFloat(borderTopWidth) + parseFloat(borderBottomWidth); const allTextHeight = scrollHeight + parseFloat(borderTopWidth) + parseFloat(borderBottomWidth); ref.current.style.height = `${Math.max(minHeight, allTextHeight)}px`; } else if (boxSizing === "content-box") { const minHeight = parseFloat(lineHeight) * minRows; const allTextHeight = scrollHeight - parseFloat(paddingTop) - parseFloat(paddingBottom); ref.current.style.height = `${Math.max(minHeight, allTextHeight)}px`; } else { console.error("Unknown box-sizing value."); } }, [minRows]); useEffect(() => { calculateAndSetHeight(); }, [calculateAndSetHeight]); const handleChange: React.ChangeEventHandler = (e) => { calculateAndSetHeight(); if (props.onChange) { props.onChange(e); } }; calculateAndSetHeight(); return