feat(editor): Add wysiwyg editor
This commit is contained in:
@ -100,16 +100,25 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
|
||||
}
|
||||
|
||||
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<string> {
|
||||
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<string> {
|
||||
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<string> {
|
||||
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<string> {
|
||||
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 = '<ul><li></li></ul>';
|
||||
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 = '<ul><li></li></ul>';
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ export class WysiwygBlocks {
|
||||
return html`
|
||||
<div
|
||||
class="block ${block.type} ${isSelected ? 'selected' : ''}"
|
||||
data-block-id="${block.id}"
|
||||
contenteditable="true"
|
||||
@input="${handlers.onInput}"
|
||||
@keydown="${handlers.onKeyDown}"
|
||||
@ -61,7 +60,6 @@ export class WysiwygBlocks {
|
||||
@blur="${handlers.onBlur}"
|
||||
@compositionstart="${handlers.onCompositionStart}"
|
||||
@compositionend="${handlers.onCompositionEnd}"
|
||||
.textContent="${block.content}"
|
||||
></div>
|
||||
`;
|
||||
}
|
||||
|
Reference in New Issue
Block a user