import { ReactiveController, ReactiveControllerHost } from 'lit'; import { type PromptBoxElement, type PromptBoxSegment } from '../types'; export interface RichInputHost extends ReactiveControllerHost { allowElements: boolean; acceptedElementTypes: string[]; allowImages: boolean; disabled: boolean; readonly: boolean; pending: boolean; value: string; shadowRoot: ShadowRoot | null; dispatchEvent(event: Event): boolean; requestUpdate(): void; handlePastedImages(clipboardData: DataTransfer | null): boolean; } /** * Manages the contenteditable rich input: element badges, paste handling, * drag-and-drop, and segment parsing. */ export declare class RichInputController implements ReactiveController { private _host; private _elements; private _idCounter; private _dragCaret; isDragOver: boolean; richInputElement: HTMLDivElement | null; constructor(host: RichInputHost); hostConnected(): void; hostDisconnected(): void; get elements(): Map; get elementCount(): number; getSegments(): PromptBoxSegment[]; setSegments(value: PromptBoxSegment[]): void; insertElement(elementType: string, label: string, data: unknown, icon?: unknown): string; /** * Core insertion logic. When a range is provided it is used directly, * bypassing the Selection API (essential for Safari drag-and-drop where * the Selection API cannot address nodes inside Shadow DOM). * Pass `null` to read from the current selection, or `undefined` to skip * range-based insertion entirely and append at the end. */ private _insertElementAtRange; private _getSelectionRange; removeElement(id: string): void; getElements(): PromptBoxElement[]; clearElements(): void; handleRichInput: () => void; handleRichPaste: (e: ClipboardEvent) => void; handleRichDragOver: (e: DragEvent) => void; handleRichDragLeave: (e: DragEvent) => void; handleRichDrop: (e: DragEvent) => void; /** * Handle Backspace/Delete next to element badges. * Returns true if a badge was removed (caller should preventDefault). */ handleBadgeDelete(key: string): boolean; /** Find an element badge immediately before `offset` within `container`. */ private _findBadgeBefore; /** Find an element badge immediately after `offset` within `container`. */ private _findBadgeAfter; /** Plain text + inline labels, in segment order (used for `value` / textarea parity). */ private _segmentsToPlainText; private _cannotEditRichContent; /** * When there are no badges and no visible text, contenteditable still often * leaves `
` or zero-width-only nodes. That prevents `:empty` from matching, * so the CSS placeholder pseudo-element stays hidden. Clear the DOM in that case. */ private _cleanupSemanticallyEmptyRichInput; syncValue(): void; private _parseSegments; private _createBadgeNode; /** * Inserts a space text node after the given badge if the next character * is not already a space (or there is no next sibling). * * Prepends a zero-width space (U+200B) so Safari renders the caret at * the correct position instead of jumping to the start of the input. */ private _ensureSpaceAfter; private _showDragCaret; private _hideDragCaret; private _generateId; /** * Moves the caret to the character position closest to the given viewport * coordinates. Used during `dragover` to show a live caret preview. */ private _positionCaretAtPoint; }