2025-06-24 10:45:06 +00:00
|
|
|
import { type TemplateResult } from '@design.estate/dees-element';
|
|
|
|
import { type IBlock } from './wysiwyg.types.js';
|
|
|
|
import { DeesSlashMenu } from './dees-slash-menu.js';
|
|
|
|
import { DeesFormattingMenu } from './dees-formatting-menu.js';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interface for the main wysiwyg component
|
|
|
|
*/
|
|
|
|
export interface IWysiwygComponent {
|
|
|
|
// State
|
|
|
|
blocks: IBlock[];
|
|
|
|
selectedBlockId: string | null;
|
|
|
|
shadowRoot: ShadowRoot | null;
|
2025-06-24 13:41:12 +00:00
|
|
|
editorContentRef: HTMLDivElement;
|
|
|
|
draggedBlockId: string | null;
|
|
|
|
dragOverBlockId: string | null;
|
|
|
|
dragOverPosition: 'before' | 'after' | null;
|
|
|
|
isComposing: boolean;
|
2025-06-24 10:45:06 +00:00
|
|
|
|
|
|
|
// Menus
|
|
|
|
slashMenu: DeesSlashMenu;
|
|
|
|
formattingMenu: DeesFormattingMenu;
|
|
|
|
|
|
|
|
// Methods
|
|
|
|
updateValue(): void;
|
2025-06-24 13:41:12 +00:00
|
|
|
requestUpdate(): void;
|
2025-06-24 10:45:06 +00:00
|
|
|
updateComplete: Promise<boolean>;
|
|
|
|
insertBlock(type: string): Promise<void>;
|
|
|
|
closeSlashMenu(clearSlash?: boolean): void;
|
|
|
|
applyFormat(command: string): Promise<void>;
|
|
|
|
handleSlashMenuKeyboard(e: KeyboardEvent): void;
|
2025-06-24 13:41:12 +00:00
|
|
|
createBlockElement(block: IBlock): HTMLElement;
|
|
|
|
updateBlockElement(blockId: string): void;
|
|
|
|
handleDrop(e: DragEvent, targetBlock: IBlock): void;
|
|
|
|
renderBlocksProgrammatically(): void;
|
2025-06-24 10:45:06 +00:00
|
|
|
|
|
|
|
// Handlers
|
|
|
|
blockOperations: IBlockOperations;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interface for block operations
|
|
|
|
*/
|
|
|
|
export interface IBlockOperations {
|
|
|
|
createBlock(type?: IBlock['type'], content?: string, metadata?: any): IBlock;
|
|
|
|
insertBlockAfter(afterBlock: IBlock, newBlock: IBlock, focusNewBlock?: boolean): Promise<void>;
|
|
|
|
removeBlock(blockId: string): void;
|
|
|
|
findBlock(blockId: string): IBlock | undefined;
|
|
|
|
getBlockIndex(blockId: string): number;
|
|
|
|
focusBlock(blockId: string, cursorPosition?: 'start' | 'end' | number): Promise<void>;
|
|
|
|
updateBlockContent(blockId: string, content: string): void;
|
|
|
|
transformBlock(blockId: string, newType: IBlock['type'], metadata?: any): void;
|
|
|
|
moveBlock(blockId: string, targetIndex: number): void;
|
|
|
|
getPreviousBlock(blockId: string): IBlock | null;
|
|
|
|
getNextBlock(blockId: string): IBlock | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interface for block component
|
|
|
|
*/
|
|
|
|
export interface IWysiwygBlockComponent {
|
|
|
|
block: IBlock;
|
|
|
|
isSelected: boolean;
|
|
|
|
blockElement: HTMLDivElement | null;
|
|
|
|
|
|
|
|
focus(): void;
|
|
|
|
focusWithCursor(position: 'start' | 'end' | number): void;
|
|
|
|
getContent(): string;
|
|
|
|
setContent(content: string): void;
|
|
|
|
setCursorToStart(): void;
|
|
|
|
setCursorToEnd(): void;
|
|
|
|
focusListItem(): void;
|
|
|
|
getSplitContent(splitPosition: number): { before: string; after: string };
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Event handler interfaces
|
|
|
|
*/
|
|
|
|
export interface IBlockEventHandlers {
|
|
|
|
onInput: (e: InputEvent) => void;
|
|
|
|
onKeyDown: (e: KeyboardEvent) => void;
|
|
|
|
onFocus: () => void;
|
|
|
|
onBlur: () => void;
|
|
|
|
onCompositionStart: () => void;
|
|
|
|
onCompositionEnd: () => void;
|
|
|
|
onMouseUp?: (e: MouseEvent) => void;
|
|
|
|
}
|