'use client'; import { useCallback, useRef, type CSSProperties } from 'react'; import type { PPTShapeElement, ShapeText } from '@openmaic/dsl'; import { useElementFlip } from '@openmaic/renderer/elements'; import { isSemanticallyEmptyText } from '../text/richText'; import { RendererTextEditor } from '../text/RendererTextEditor'; import type { TextContentChange, TextEditorController, TextFormatState } from '../text/types'; import type { EditIntent } from '../types'; export interface RendererShapeLabelEditorProps { element: PPTShapeElement; initialFocusPoint?: { left: number; top: number }; onContentChange?: (change: TextContentChange) => void; onFormatChange?: (elementId: string, state: TextFormatState) => void; onControllerChange?: (controller: TextEditorController | null) => void; onFocusChange?: (focused: boolean) => void; onElementsChange?: (intents: EditIntent[]) => void; onEscape?: () => void; } function shapeText(element: PPTShapeElement): ShapeText { return ( element.text ?? { content: '', align: 'middle', defaultFontName: 'Microsoft YaHei', defaultColor: '#333333', } ); } /** Inline ProseMirror label editor for a Shape selected in the renderer canvas. */ export function RendererShapeLabelEditor({ element, initialFocusPoint, onContentChange, onFormatChange, onControllerChange, onFocusChange, onElementsChange, onEscape, }: RendererShapeLabelEditorProps) { const controllerRef = useRef(null); const text = shapeText(element); const { flipStyle } = useElementFlip(element.flipH, element.flipV); const justifyContent = text.align === 'top' ? 'flex-start' : text.align === 'bottom' ? 'flex-end' : 'center'; const handleControllerChange = useCallback( (controller: TextEditorController | null) => { controllerRef.current = controller; onControllerChange?.(controller); }, [onControllerChange], ); const handleFocusChange = useCallback( (focused: boolean) => { onFocusChange?.(focused); if ( focused || !element.text || !isSemanticallyEmptyText(controllerRef.current?.getHTML() ?? '') ) { return; } onElementsChange?.([{ type: 'element.removeProps', id: element.id, props: ['text'] }]); }, [element.id, element.text, onElementsChange, onFocusChange], ); return (
); }