import { SelectionEdge, TLShapeId, canonicalizeRotation, getPointerInfo, toDomPrecision, useEditor, useIsEditing, useValue, } from '@tldraw/editor' import { preventDefault, stopEventPropagation } from '@tldraw/tldraw' import { useCallback, useEffect, useRef } from 'react' import { FrameLabelInput } from './FrameLabelInput' export function FrameHeading({ id, name, width, height, }: { id: TLShapeId name: string width: number height: number }) { const editor = useEditor() const pageRotation = useValue( 'shape rotation', () => canonicalizeRotation(editor.getShapePageTransform(id)!.rotation()), [editor, id] ) const isEditing = useIsEditing(id) const rInput = useRef(null) const handlePointerDown = useCallback( (e: React.PointerEvent) => { preventDefault(e) stopEventPropagation(e) const event = getPointerInfo(e) // If we're editing the frame label, we shouldn't hijack the pointer event if (editor.getEditingShapeId() === id) return editor.dispatch({ ...event, type: 'pointer', name: 'pointer_down', target: 'shape', shape: editor.getShape(id)!, }) }, [editor, id] ) useEffect(() => { const el = rInput.current if (el && isEditing) { // On iOS, we must focus here el.focus() el.select() requestAnimationFrame(() => { // On desktop, the input may have lost focus, so try try try again! if (document.activeElement !== el) { el.focus() el.select() } }) } }, [rInput, isEditing]) // rotate right 45 deg const offsetRotation = pageRotation + Math.PI / 4 const scaledRotation = (offsetRotation * (2 / Math.PI) + 4) % 4 const labelSide: SelectionEdge = (['top', 'left', 'bottom', 'right'] as const)[ Math.floor(scaledRotation) ] let labelTranslate: string switch (labelSide) { case 'top': labelTranslate = `` break case 'right': labelTranslate = `translate(${toDomPrecision(width)}px, 0px) rotate(90deg)` break case 'bottom': labelTranslate = `translate(${toDomPrecision(width)}px, ${toDomPrecision( height )}px) rotate(180deg)` break case 'left': labelTranslate = `translate(0px, ${toDomPrecision(height)}px) rotate(270deg)` break } return (
) }