146 lines
3.9 KiB
TypeScript
146 lines
3.9 KiB
TypeScript
![]() |
import { type IBlock } from './wysiwyg.types.js';
|
||
|
import { WysiwygShortcuts } from './wysiwyg.shortcuts.js';
|
||
|
import { WysiwygBlocks } from './wysiwyg.blocks.js';
|
||
|
|
||
|
export class WysiwygBlockOperations {
|
||
|
private component: any; // Will be typed properly when imported
|
||
|
|
||
|
constructor(component: any) {
|
||
|
this.component = component;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a new block with the specified parameters
|
||
|
*/
|
||
|
createBlock(type: IBlock['type'] = 'paragraph', content: string = '', metadata?: any): IBlock {
|
||
|
return {
|
||
|
id: WysiwygShortcuts.generateBlockId(),
|
||
|
type,
|
||
|
content,
|
||
|
...(metadata && { metadata })
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inserts a block after the specified block
|
||
|
*/
|
||
|
insertBlockAfter(afterBlock: IBlock, newBlock: IBlock, focusNewBlock: boolean = true): void {
|
||
|
const blocks = this.component.blocks;
|
||
|
const blockIndex = blocks.findIndex((b: IBlock) => b.id === afterBlock.id);
|
||
|
|
||
|
this.component.blocks = [
|
||
|
...blocks.slice(0, blockIndex + 1),
|
||
|
newBlock,
|
||
|
...blocks.slice(blockIndex + 1)
|
||
|
];
|
||
|
|
||
|
this.component.updateValue();
|
||
|
|
||
|
if (focusNewBlock && newBlock.type !== 'divider') {
|
||
|
setTimeout(() => {
|
||
|
this.focusBlock(newBlock.id);
|
||
|
}, 50);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes a block by its ID
|
||
|
*/
|
||
|
removeBlock(blockId: string): void {
|
||
|
this.component.blocks = this.component.blocks.filter((b: IBlock) => b.id !== blockId);
|
||
|
this.component.updateValue();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Finds a block by its ID
|
||
|
*/
|
||
|
findBlock(blockId: string): IBlock | undefined {
|
||
|
return this.component.blocks.find((b: IBlock) => b.id === blockId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the index of a block
|
||
|
*/
|
||
|
getBlockIndex(blockId: string): number {
|
||
|
return this.component.blocks.findIndex((b: IBlock) => b.id === blockId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Focuses a specific block
|
||
|
*/
|
||
|
focusBlock(blockId: string, cursorPosition: 'start' | 'end' = 'start'): void {
|
||
|
const wrapperElement = this.component.shadowRoot!.querySelector(`[data-block-id="${blockId}"]`);
|
||
|
if (wrapperElement) {
|
||
|
const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement;
|
||
|
if (blockElement) {
|
||
|
blockElement.focus();
|
||
|
if (cursorPosition === 'start') {
|
||
|
WysiwygBlocks.setCursorToStart(blockElement);
|
||
|
} else {
|
||
|
WysiwygBlocks.setCursorToEnd(blockElement);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates the content of a block
|
||
|
*/
|
||
|
updateBlockContent(blockId: string, content: string): void {
|
||
|
const block = this.findBlock(blockId);
|
||
|
if (block) {
|
||
|
block.content = content;
|
||
|
this.component.updateValue();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Transforms a block to a different type
|
||
|
*/
|
||
|
transformBlock(blockId: string, newType: IBlock['type'], metadata?: any): void {
|
||
|
const block = this.findBlock(blockId);
|
||
|
if (block) {
|
||
|
block.type = newType;
|
||
|
block.content = '';
|
||
|
if (metadata) {
|
||
|
block.metadata = metadata;
|
||
|
}
|
||
|
this.component.updateValue();
|
||
|
this.component.requestUpdate();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Moves a block to a new position
|
||
|
*/
|
||
|
moveBlock(blockId: string, targetIndex: number): void {
|
||
|
const blocks = [...this.component.blocks];
|
||
|
const currentIndex = this.getBlockIndex(blockId);
|
||
|
|
||
|
if (currentIndex === -1 || targetIndex < 0 || targetIndex >= blocks.length) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const [movedBlock] = blocks.splice(currentIndex, 1);
|
||
|
blocks.splice(targetIndex, 0, movedBlock);
|
||
|
|
||
|
this.component.blocks = blocks;
|
||
|
this.component.updateValue();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the previous block
|
||
|
*/
|
||
|
getPreviousBlock(blockId: string): IBlock | null {
|
||
|
const index = this.getBlockIndex(blockId);
|
||
|
return index > 0 ? this.component.blocks[index - 1] : null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the next block
|
||
|
*/
|
||
|
getNextBlock(blockId: string): IBlock | null {
|
||
|
const index = this.getBlockIndex(blockId);
|
||
|
return index < this.component.blocks.length - 1 ? this.component.blocks[index + 1] : null;
|
||
|
}
|
||
|
}
|