update
This commit is contained in:
@ -35,6 +35,9 @@ export class WysiwygKeyboardHandler {
|
||||
case 'Backspace':
|
||||
await this.handleBackspace(e, block);
|
||||
break;
|
||||
case 'Delete':
|
||||
await this.handleDelete(e, block);
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
await this.handleArrowUp(e, block);
|
||||
break;
|
||||
@ -116,6 +119,14 @@ export class WysiwygKeyboardHandler {
|
||||
private async handleEnter(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
const blockOps = this.component.blockOperations;
|
||||
|
||||
// For non-editable blocks, create a new paragraph after
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
const newBlock = blockOps.createBlock();
|
||||
await blockOps.insertBlockAfter(block, newBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (block.type === 'code') {
|
||||
if (e.shiftKey) {
|
||||
// Shift+Enter in code blocks creates a new block
|
||||
@ -222,6 +233,41 @@ export class WysiwygKeyboardHandler {
|
||||
private async handleBackspace(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
const blockOps = this.component.blockOperations;
|
||||
|
||||
// Handle non-editable blocks (divider, image)
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
|
||||
// Don't delete if it's the only block
|
||||
if (this.component.blocks.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save state for undo
|
||||
this.component.saveToHistory(false);
|
||||
|
||||
// Find the previous block to focus
|
||||
const prevBlock = blockOps.getPreviousBlock(block.id);
|
||||
const nextBlock = blockOps.getNextBlock(block.id);
|
||||
|
||||
// Remove the block
|
||||
blockOps.removeBlock(block.id);
|
||||
|
||||
// Focus the appropriate block
|
||||
if (prevBlock && prevBlock.type !== 'divider' && prevBlock.type !== 'image') {
|
||||
await blockOps.focusBlock(prevBlock.id, 'end');
|
||||
} else if (nextBlock && nextBlock.type !== 'divider' && nextBlock.type !== 'image') {
|
||||
await blockOps.focusBlock(nextBlock.id, 'start');
|
||||
} else if (prevBlock) {
|
||||
// If previous block is also non-editable, just select it
|
||||
await blockOps.focusBlock(prevBlock.id);
|
||||
} else if (nextBlock) {
|
||||
// If next block is also non-editable, just select it
|
||||
await blockOps.focusBlock(nextBlock.id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the block component to check cursor position
|
||||
const blockWrapper = this.component.shadowRoot?.querySelector(`[data-block-id="${block.id}"]`);
|
||||
const blockComponent = blockWrapper?.querySelector('dees-wysiwyg-block') as any;
|
||||
@ -321,10 +367,66 @@ export class WysiwygKeyboardHandler {
|
||||
// Otherwise, let browser handle normal backspace
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Delete key
|
||||
*/
|
||||
private async handleDelete(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
const blockOps = this.component.blockOperations;
|
||||
|
||||
// Handle non-editable blocks (divider, image) - same as backspace
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
|
||||
// Don't delete if it's the only block
|
||||
if (this.component.blocks.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save state for undo
|
||||
this.component.saveToHistory(false);
|
||||
|
||||
// Find the previous block to focus
|
||||
const prevBlock = blockOps.getPreviousBlock(block.id);
|
||||
const nextBlock = blockOps.getNextBlock(block.id);
|
||||
|
||||
// Remove the block
|
||||
blockOps.removeBlock(block.id);
|
||||
|
||||
// Focus the appropriate block
|
||||
if (nextBlock && nextBlock.type !== 'divider' && nextBlock.type !== 'image') {
|
||||
await blockOps.focusBlock(nextBlock.id, 'start');
|
||||
} else if (prevBlock && prevBlock.type !== 'divider' && prevBlock.type !== 'image') {
|
||||
await blockOps.focusBlock(prevBlock.id, 'end');
|
||||
} else if (nextBlock) {
|
||||
// If next block is also non-editable, just select it
|
||||
await blockOps.focusBlock(nextBlock.id);
|
||||
} else if (prevBlock) {
|
||||
// If previous block is also non-editable, just select it
|
||||
await blockOps.focusBlock(prevBlock.id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// For editable blocks, let browser handle normal delete
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles ArrowUp key - navigate to previous block if at beginning or first line
|
||||
*/
|
||||
private async handleArrowUp(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
// For non-editable blocks, always navigate to previous block
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
const blockOps = this.component.blockOperations;
|
||||
const prevBlock = blockOps.getPreviousBlock(block.id);
|
||||
|
||||
if (prevBlock) {
|
||||
await blockOps.focusBlock(prevBlock.id, prevBlock.type === 'divider' || prevBlock.type === 'image' ? undefined : 'end');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the block component from the wysiwyg component's shadow DOM
|
||||
const blockWrapper = this.component.shadowRoot?.querySelector(`[data-block-id="${block.id}"]`);
|
||||
const blockComponent = blockWrapper?.querySelector('dees-wysiwyg-block');
|
||||
@ -352,9 +454,9 @@ export class WysiwygKeyboardHandler {
|
||||
const blockOps = this.component.blockOperations;
|
||||
const prevBlock = blockOps.getPreviousBlock(block.id);
|
||||
|
||||
if (prevBlock && prevBlock.type !== 'divider') {
|
||||
if (prevBlock) {
|
||||
console.log('ArrowUp: Focusing previous block:', prevBlock.id);
|
||||
await blockOps.focusBlock(prevBlock.id, 'end');
|
||||
await blockOps.focusBlock(prevBlock.id, prevBlock.type === 'divider' || prevBlock.type === 'image' ? undefined : 'end');
|
||||
}
|
||||
}
|
||||
// Otherwise, let browser handle normal navigation
|
||||
@ -364,6 +466,18 @@ export class WysiwygKeyboardHandler {
|
||||
* Handles ArrowDown key - navigate to next block if at end or last line
|
||||
*/
|
||||
private async handleArrowDown(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
// For non-editable blocks, always navigate to next block
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
const blockOps = this.component.blockOperations;
|
||||
const nextBlock = blockOps.getNextBlock(block.id);
|
||||
|
||||
if (nextBlock) {
|
||||
await blockOps.focusBlock(nextBlock.id, nextBlock.type === 'divider' || nextBlock.type === 'image' ? undefined : 'start');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the block component from the wysiwyg component's shadow DOM
|
||||
const blockWrapper = this.component.shadowRoot?.querySelector(`[data-block-id="${block.id}"]`);
|
||||
const blockComponent = blockWrapper?.querySelector('dees-wysiwyg-block');
|
||||
@ -391,9 +505,9 @@ export class WysiwygKeyboardHandler {
|
||||
const blockOps = this.component.blockOperations;
|
||||
const nextBlock = blockOps.getNextBlock(block.id);
|
||||
|
||||
if (nextBlock && nextBlock.type !== 'divider') {
|
||||
if (nextBlock) {
|
||||
console.log('ArrowDown: Focusing next block:', nextBlock.id);
|
||||
await blockOps.focusBlock(nextBlock.id, 'start');
|
||||
await blockOps.focusBlock(nextBlock.id, nextBlock.type === 'divider' || nextBlock.type === 'image' ? undefined : 'start');
|
||||
}
|
||||
}
|
||||
// Otherwise, let browser handle normal navigation
|
||||
@ -419,6 +533,18 @@ export class WysiwygKeyboardHandler {
|
||||
* Handles ArrowLeft key - navigate to previous block if at beginning
|
||||
*/
|
||||
private async handleArrowLeft(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
// For non-editable blocks, navigate to previous block
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
const blockOps = this.component.blockOperations;
|
||||
const prevBlock = blockOps.getPreviousBlock(block.id);
|
||||
|
||||
if (prevBlock) {
|
||||
await blockOps.focusBlock(prevBlock.id, prevBlock.type === 'divider' || prevBlock.type === 'image' ? undefined : 'end');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the block component from the wysiwyg component's shadow DOM
|
||||
const blockWrapper = this.component.shadowRoot?.querySelector(`[data-block-id="${block.id}"]`);
|
||||
const blockComponent = blockWrapper?.querySelector('dees-wysiwyg-block');
|
||||
@ -448,9 +574,9 @@ export class WysiwygKeyboardHandler {
|
||||
const prevBlock = blockOps.getPreviousBlock(block.id);
|
||||
console.log('ArrowLeft: At start, previous block:', prevBlock?.id);
|
||||
|
||||
if (prevBlock && prevBlock.type !== 'divider') {
|
||||
if (prevBlock) {
|
||||
e.preventDefault();
|
||||
await blockOps.focusBlock(prevBlock.id, 'end');
|
||||
await blockOps.focusBlock(prevBlock.id, prevBlock.type === 'divider' || prevBlock.type === 'image' ? undefined : 'end');
|
||||
}
|
||||
}
|
||||
// Otherwise, let the browser handle normal left arrow navigation
|
||||
@ -460,6 +586,18 @@ export class WysiwygKeyboardHandler {
|
||||
* Handles ArrowRight key - navigate to next block if at end
|
||||
*/
|
||||
private async handleArrowRight(e: KeyboardEvent, block: IBlock): Promise<void> {
|
||||
// For non-editable blocks, navigate to next block
|
||||
if (block.type === 'divider' || block.type === 'image') {
|
||||
e.preventDefault();
|
||||
const blockOps = this.component.blockOperations;
|
||||
const nextBlock = blockOps.getNextBlock(block.id);
|
||||
|
||||
if (nextBlock) {
|
||||
await blockOps.focusBlock(nextBlock.id, nextBlock.type === 'divider' || nextBlock.type === 'image' ? undefined : 'start');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the block component from the wysiwyg component's shadow DOM
|
||||
const blockWrapper = this.component.shadowRoot?.querySelector(`[data-block-id="${block.id}"]`);
|
||||
const blockComponent = blockWrapper?.querySelector('dees-wysiwyg-block');
|
||||
@ -488,9 +626,9 @@ export class WysiwygKeyboardHandler {
|
||||
const blockOps = this.component.blockOperations;
|
||||
const nextBlock = blockOps.getNextBlock(block.id);
|
||||
|
||||
if (nextBlock && nextBlock.type !== 'divider') {
|
||||
if (nextBlock) {
|
||||
e.preventDefault();
|
||||
await blockOps.focusBlock(nextBlock.id, 'start');
|
||||
await blockOps.focusBlock(nextBlock.id, nextBlock.type === 'divider' || nextBlock.type === 'image' ? undefined : 'start');
|
||||
}
|
||||
}
|
||||
// Otherwise, let the browser handle normal right arrow navigation
|
||||
|
Reference in New Issue
Block a user