From 0f02e7d00f1be0c201356be6d948f24ecaec6ae6 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Mon, 23 Jun 2025 18:07:46 +0000 Subject: [PATCH] feat(editor): Add wysiwyg editor --- ts_web/elements/wysiwyg/dees-input-wysiwyg.ts | 81 ++++++++++++------- ts_web/elements/wysiwyg/wysiwyg.blocks.ts | 2 - 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/ts_web/elements/wysiwyg/dees-input-wysiwyg.ts b/ts_web/elements/wysiwyg/dees-input-wysiwyg.ts index c7fec3c..8119b44 100644 --- a/ts_web/elements/wysiwyg/dees-input-wysiwyg.ts +++ b/ts_web/elements/wysiwyg/dees-input-wysiwyg.ts @@ -100,16 +100,25 @@ export class DeesInputWysiwyg extends DeesInputBase { } private setBlockContents() { - // Only set content for blocks that aren't being edited + // Set content for blocks that aren't being edited and don't already have content this.blocks.forEach(block => { const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${block.id}"]`); if (wrapperElement) { const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; if (blockElement && document.activeElement !== blockElement && block.type !== 'divider') { - if (block.type === 'list') { - blockElement.innerHTML = WysiwygBlocks.renderListContent(block.content, block.metadata); - } else { - blockElement.textContent = block.content; + // Only set content if the element is empty or has placeholder text + const currentContent = blockElement.textContent || ''; + const isEmpty = !currentContent || currentContent === 'Type \'/\' for commands...' || + currentContent === 'Heading 1' || currentContent === 'Heading 2' || + currentContent === 'Heading 3' || currentContent === 'Quote' || + currentContent === 'Code block'; + + if (isEmpty && block.content) { + if (block.type === 'list') { + blockElement.innerHTML = WysiwygBlocks.renderListContent(block.content, block.metadata); + } else { + blockElement.textContent = block.content; + } } } } @@ -256,9 +265,12 @@ export class DeesInputWysiwyg extends DeesInputBase { this.blocks = [...this.blocks.slice(0, blockIndex + 1), newBlock, ...this.blocks.slice(blockIndex + 1)]; setTimeout(() => { - const newBlockElement = this.shadowRoot!.querySelector(`[data-block-id="${newBlock.id}"]`) as HTMLDivElement; - if (newBlockElement) { - newBlockElement.focus(); + const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${newBlock.id}"]`); + if (wrapperElement) { + const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; + if (blockElement) { + blockElement.focus(); + } } }); @@ -391,10 +403,13 @@ export class DeesInputWysiwyg extends DeesInputBase { this.updateValue(); setTimeout(() => { - const prevBlockElement = this.shadowRoot!.querySelector(`[data-block-id="${prevBlock.id}"]`) as HTMLDivElement; - if (prevBlockElement && prevBlock.type !== 'divider') { - prevBlockElement.focus(); - WysiwygBlocks.setCursorToEnd(prevBlockElement); + const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${prevBlock.id}"]`); + if (wrapperElement && prevBlock.type !== 'divider') { + const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; + if (blockElement) { + blockElement.focus(); + WysiwygBlocks.setCursorToEnd(blockElement); + } } }); } @@ -509,10 +524,13 @@ export class DeesInputWysiwyg extends DeesInputBase { const target = e.target as HTMLElement; if (target.classList.contains('editor-content')) { const lastBlock = this.blocks[this.blocks.length - 1]; - const lastBlockElement = this.shadowRoot!.querySelector(`[data-block-id="${lastBlock.id}"]`) as HTMLDivElement; - if (lastBlockElement && lastBlock.type !== 'divider') { - lastBlockElement.focus(); - WysiwygBlocks.setCursorToEnd(lastBlockElement); + const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${lastBlock.id}"]`); + if (wrapperElement && lastBlock.type !== 'divider') { + const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; + if (blockElement) { + blockElement.focus(); + WysiwygBlocks.setCursorToEnd(blockElement); + } } } } @@ -535,28 +553,37 @@ export class DeesInputWysiwyg extends DeesInputBase { this.blocks = [...this.blocks.slice(0, currentBlockIndex + 1), newBlock, ...this.blocks.slice(currentBlockIndex + 1)]; setTimeout(() => { - const newBlockElement = this.shadowRoot!.querySelector(`[data-block-id="${newBlock.id}"]`) as HTMLDivElement; - if (newBlockElement) { - newBlockElement.focus(); + const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${newBlock.id}"]`); + if (wrapperElement) { + const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; + if (blockElement) { + blockElement.focus(); + } } }); } else if (type === 'list') { // Handle list type specially currentBlock.metadata = { listType: 'bullet' }; // Default to bullet list setTimeout(() => { - const blockElement = this.shadowRoot!.querySelector(`[data-block-id="${currentBlock.id}"]`) as HTMLDivElement; - if (blockElement) { - blockElement.innerHTML = '
'; - WysiwygBlocks.focusListItem(blockElement); + const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${currentBlock.id}"]`); + if (wrapperElement) { + const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; + if (blockElement) { + blockElement.innerHTML = '
'; + WysiwygBlocks.focusListItem(blockElement); + } } }); } else { // Force update the contenteditable element setTimeout(() => { - const blockElement = this.shadowRoot!.querySelector(`[data-block-id="${currentBlock.id}"]`) as HTMLDivElement; - if (blockElement) { - blockElement.textContent = ''; - blockElement.focus(); + const wrapperElement = this.shadowRoot!.querySelector(`[data-block-id="${currentBlock.id}"]`); + if (wrapperElement) { + const blockElement = wrapperElement.querySelector('.block') as HTMLDivElement; + if (blockElement) { + blockElement.textContent = ''; + blockElement.focus(); + } } }); } diff --git a/ts_web/elements/wysiwyg/wysiwyg.blocks.ts b/ts_web/elements/wysiwyg/wysiwyg.blocks.ts index 65e85ab..68b1c94 100644 --- a/ts_web/elements/wysiwyg/wysiwyg.blocks.ts +++ b/ts_web/elements/wysiwyg/wysiwyg.blocks.ts @@ -53,7 +53,6 @@ export class WysiwygBlocks { return html`
`; }