diff options
Diffstat (limited to 'apps/web/src/components/editor/panels/preview/text-edit-overlay.tsx')
| -rw-r--r-- | apps/web/src/components/editor/panels/preview/text-edit-overlay.tsx | 158 |
1 files changed, 0 insertions, 158 deletions
diff --git a/apps/web/src/components/editor/panels/preview/text-edit-overlay.tsx b/apps/web/src/components/editor/panels/preview/text-edit-overlay.tsx deleted file mode 100644 index eabbde8a..00000000 --- a/apps/web/src/components/editor/panels/preview/text-edit-overlay.tsx +++ /dev/null @@ -1,158 +0,0 @@ -"use client"; - -import { useCallback, useEffect, useRef } from "react"; -import { usePreviewViewport } from "@/components/editor/panels/preview/preview-viewport"; -import { useEditor } from "@/hooks/use-editor"; -import type { TextElement } from "@/lib/timeline"; -import { DEFAULTS } from "@/lib/timeline/defaults"; -import { - getElementLocalTime, - resolveTransformAtTime, -} from "@/lib/animation"; -import { resolveTextLayout } from "@/lib/text/primitives"; - -export function TextEditOverlay({ - trackId, - elementId, - element, - onCommit, -}: { - trackId: string; - elementId: string; - element: TextElement; - onCommit: () => void; -}) { - const editor = useEditor(); - const viewport = usePreviewViewport(); - const divRef = useRef<HTMLDivElement>(null); - - useEffect(() => { - const div = divRef.current; - if (!div) return; - div.focus(); - const range = document.createRange(); - range.selectNodeContents(div); - const selection = window.getSelection(); - selection?.removeAllRanges(); - selection?.addRange(range); - }, []); - - const handleInput = useCallback(() => { - const div = divRef.current; - if (!div) return; - const text = div.innerText; - editor.timeline.previewElements({ - updates: [{ trackId, elementId, updates: { content: text } }], - }); - }, [editor.timeline, trackId, elementId]); - - const handleKeyDown = useCallback( - ({ event }: { event: React.KeyboardEvent }) => { - const { key } = event; - if (key === "Escape") { - event.preventDefault(); - onCommit(); - return; - } - }, - [onCommit], - ); - - const canvasSize = editor.project.getActive().settings.canvasSize; - - if (!canvasSize) return null; - - const currentTime = editor.playback.getCurrentTime(); - const localTime = getElementLocalTime({ - timelineTime: currentTime, - elementStartTime: element.startTime, - elementDuration: element.duration, - }); - const transform = resolveTransformAtTime({ - baseTransform: element.transform, - animations: element.animations, - localTime, - }); - - const { x: posX, y: posY } = viewport.positionToOverlay({ - positionX: transform.position.x, - positionY: transform.position.y, - }); - - const { x: displayScaleX } = viewport.getDisplayScale(); - const resolvedTextLayout = resolveTextLayout({ - text: { - content: element.content, - fontSize: element.fontSize, - fontFamily: element.fontFamily, - fontWeight: element.fontWeight, - fontStyle: element.fontStyle, - textAlign: element.textAlign, - textDecoration: element.textDecoration, - letterSpacing: element.letterSpacing, - lineHeight: element.lineHeight, - }, - canvasHeight: canvasSize.height, - }); - - const lineHeight = element.lineHeight ?? DEFAULTS.text.lineHeight; - const canvasLetterSpacing = element.letterSpacing ?? 0; - const lineHeightPx = resolvedTextLayout.lineHeightPx; - - const bg = element.background; - const shouldShowBackground = - bg.enabled && bg.color && bg.color !== "transparent"; - const fontSizeRatio = resolvedTextLayout.fontSizeRatio; - const canvasPaddingX = shouldShowBackground - ? (bg.paddingX ?? DEFAULTS.text.background.paddingX) * fontSizeRatio - : 0; - const canvasPaddingY = shouldShowBackground - ? (bg.paddingY ?? DEFAULTS.text.background.paddingY) * fontSizeRatio - : 0; - - return ( - <div - className="absolute" - style={{ - left: posX, - top: posY, - transform: `translate(-50%, -50%) scale(${transform.scaleX * displayScaleX}, ${transform.scaleY * displayScaleX}) rotate(${transform.rotate}deg)`, - transformOrigin: "center center", - }} - > - {/* biome-ignore lint/a11y/useSemanticElements: contenteditable required for multiline, IME, paste */} - <div - ref={divRef} - contentEditable - suppressContentEditableWarning - tabIndex={0} - role="textbox" - aria-label="Edit text" - className="cursor-text select-text outline-none whitespace-pre" - style={{ - fontSize: resolvedTextLayout.scaledFontSize, - fontFamily: element.fontFamily, - fontWeight: element.fontWeight === "bold" ? "bold" : "normal", - fontStyle: element.fontStyle === "italic" ? "italic" : "normal", - textAlign: element.textAlign, - letterSpacing: `${canvasLetterSpacing}px`, - lineHeight, - color: "transparent", - caretColor: element.color, - backgroundColor: shouldShowBackground ? bg.color : "transparent", - minHeight: lineHeightPx, - textDecoration: element.textDecoration ?? "none", - padding: shouldShowBackground - ? `${canvasPaddingY}px ${canvasPaddingX}px` - : 0, - minWidth: 1, - }} - onInput={handleInput} - onBlur={onCommit} - onKeyDown={(event) => handleKeyDown({ event })} - > - {element.content || ""} - </div> - </div> - ); -} |
