diff --git a/packages/affine/components/src/rich-text/index.ts b/packages/affine/components/src/rich-text/index.ts index 3626cc306ef9..035361975689 100644 --- a/packages/affine/components/src/rich-text/index.ts +++ b/packages/affine/components/src/rich-text/index.ts @@ -37,6 +37,7 @@ export { getAffineInlineSpecsWithReference, toggleLinkPopup, } from './inline/index.js'; +export { textKeymap } from './keymap/index.js'; export { insertLinkedNode } from './linked-node.js'; export { markdownInput } from './markdown/index.js'; export { RichText } from './rich-text.js'; diff --git a/packages/affine/components/src/rich-text/keymap/basic.ts b/packages/affine/components/src/rich-text/keymap/basic.ts new file mode 100644 index 000000000000..296cff4e85a0 --- /dev/null +++ b/packages/affine/components/src/rich-text/keymap/basic.ts @@ -0,0 +1,72 @@ +import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std'; + +import { + focusTextModel, + getInlineEditorByModel, + selectTextModel, +} from '../dom.js'; + +export const textCommonKeymap = ( + std: BlockStdScope +): Record => { + return { + ArrowUp: () => { + const text = std.selection.find('text'); + if (!text) return; + const inline = getInlineEditorByModel(std.host, text.from.blockId); + if (!inline) return; + return !inline.isFirstLine(inline.getInlineRange()); + }, + ArrowDown: () => { + const text = std.selection.find('text'); + if (!text) return; + const inline = getInlineEditorByModel(std.host, text.from.blockId); + if (!inline) return; + return !inline.isLastLine(inline.getInlineRange()); + }, + Escape: ctx => { + const text = std.selection.find('text'); + if (!text) return; + + selectBlock(std, text.from.blockId); + ctx.get('keyboardState').raw.stopPropagation(); + return true; + }, + 'Mod-a': ctx => { + const text = std.selection.find('text'); + if (!text) return; + + const model = std.doc.getBlock(text.from.blockId)?.model; + if (!model || !model.text) return; + + ctx.get('keyboardState').raw.preventDefault(); + + if ( + text.from.index === 0 && + text.from.length === model.text.yText.length + ) { + selectBlock(std, text.from.blockId); + return true; + } + + selectTextModel(std, text.from.blockId, 0, model.text.yText.length); + return true; + }, + Enter: ctx => { + const blocks = std.selection.filter('block'); + const blockId = blocks.at(-1)?.blockId; + + if (!blockId) return; + const model = std.doc.getBlock(blockId)?.model; + if (!model || !model.text) return; + + ctx.get('keyboardState').raw.preventDefault(); + focusTextModel(std, blockId, model.text.yText.length); + return true; + }, + }; +}; + +function selectBlock(std: BlockStdScope, blockId: string) { + std.selection.setGroup('note', [std.selection.create('block', { blockId })]); +} diff --git a/packages/affine/components/src/rich-text/keymap/bracket.ts b/packages/affine/components/src/rich-text/keymap/bracket.ts new file mode 100644 index 000000000000..fad725d139c3 --- /dev/null +++ b/packages/affine/components/src/rich-text/keymap/bracket.ts @@ -0,0 +1,162 @@ +import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std'; +import type { InlineEditor } from '@blocksuite/inline'; + +import { BRACKET_PAIRS } from '@blocksuite/affine-shared/consts'; +import { + createDefaultDoc, + matchFlavours, +} from '@blocksuite/affine-shared/utils'; + +import { getInlineEditorByModel } from '../dom.js'; +import { insertLinkedNode } from '../linked-node.js'; + +export const bracketKeymap = ( + std: BlockStdScope +): Record => { + const keymap = BRACKET_PAIRS.reduce( + (acc, pair) => { + return { + ...acc, + [pair.right]: ctx => { + const { doc, selection } = std; + if (doc.readonly) return; + + const textSelection = selection.find('text'); + if (!textSelection) return; + const model = doc.getBlock(textSelection.from.blockId)?.model; + if (!model) return; + if (!matchFlavours(model, ['affine:code'])) return; + const inlineEditor = getInlineEditorByModel( + std.host, + textSelection.from.blockId + ); + if (!inlineEditor) return; + const inlineRange = inlineEditor.getInlineRange(); + if (!inlineRange) return; + const left = inlineEditor.yText.toString()[inlineRange.index - 1]; + const right = inlineEditor.yText.toString()[inlineRange.index]; + if (pair.left === left && pair.right === right) { + inlineEditor.setInlineRange({ + index: inlineRange.index + 1, + length: 0, + }); + ctx.get('keyboardState').raw.preventDefault(); + } + }, + [pair.left]: ctx => { + const { doc, selection } = std; + if (doc.readonly) return; + + const textSelection = selection.find('text'); + if (!textSelection) return; + const model = doc.getBlock(textSelection.from.blockId)?.model; + if (!model) return; + + const isCodeBlock = matchFlavours(model, ['affine:code']); + // When selection is collapsed, only trigger auto complete in code block + if (textSelection.isCollapsed() && !isCodeBlock) return; + if (!textSelection.isInSameBlock()) return; + + ctx.get('keyboardState').raw.preventDefault(); + + const inlineEditor = getInlineEditorByModel( + std.host, + textSelection.from.blockId + ); + if (!inlineEditor) return; + const inlineRange = inlineEditor.getInlineRange(); + if (!inlineRange) return; + const selectedText = inlineEditor.yText + .toString() + .slice(inlineRange.index, inlineRange.index + inlineRange.length); + if (!isCodeBlock && pair.name === 'square bracket') { + // [[Selected text]] should automatically be converted to a Linked doc with the title "Selected text". + // See https://github.com/toeverything/blocksuite/issues/2730 + const success = tryConvertToLinkedDoc(std, inlineEditor); + if (success) return true; + } + inlineEditor.insertText( + inlineRange, + pair.left + selectedText + pair.right + ); + + inlineEditor.setInlineRange({ + index: inlineRange.index + 1, + length: inlineRange.length, + }); + + return true; + }, + }; + }, + {} as Record + ); + + return { + ...keymap, + '`': ctx => { + const { doc, selection } = std; + if (doc.readonly) return; + + const textSelection = selection.find('text'); + if (!textSelection || textSelection.isCollapsed()) return; + if (!textSelection.isInSameBlock()) return; + const model = doc.getBlock(textSelection.from.blockId)?.model; + if (!model) return; + + ctx.get('keyboardState').raw.preventDefault(); + const inlineEditor = getInlineEditorByModel( + std.host, + textSelection.from.blockId + ); + if (!inlineEditor) return; + const inlineRange = inlineEditor.getInlineRange(); + if (!inlineRange) return; + inlineEditor.formatText(inlineRange, { code: true }); + + inlineEditor.setInlineRange({ + index: inlineRange.index, + length: inlineRange.length, + }); + + return true; + }, + }; +}; + +function tryConvertToLinkedDoc(std: BlockStdScope, inlineEditor: InlineEditor) { + const root = std.doc.root; + if (!root) return false; + const linkedDocWidgetEle = std.view.getWidget( + 'affine-linked-doc-widget', + root.id + ); + if (!linkedDocWidgetEle) return false; + + const inlineRange = inlineEditor.getInlineRange(); + if (!inlineRange) return false; + const text = inlineEditor.yText.toString(); + const left = text[inlineRange.index - 1]; + const right = text[inlineRange.index + inlineRange.length]; + const needConvert = left === '[' && right === ']'; + if (!needConvert) return false; + + const docName = text.slice( + inlineRange.index, + inlineRange.index + inlineRange.length + ); + inlineEditor.deleteText({ + index: inlineRange.index - 1, + length: inlineRange.length + 2, + }); + inlineEditor.setInlineRange({ index: inlineRange.index - 1, length: 0 }); + + const doc = createDefaultDoc(std.doc.collection, { + title: docName, + }); + insertLinkedNode({ + inlineEditor, + docId: doc.id, + }); + return true; +} diff --git a/packages/affine/components/src/rich-text/keymap/format.ts b/packages/affine/components/src/rich-text/keymap/format.ts new file mode 100644 index 000000000000..c51d31b68c4b --- /dev/null +++ b/packages/affine/components/src/rich-text/keymap/format.ts @@ -0,0 +1,26 @@ +import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std'; + +import { textFormatConfigs } from '../format/index.js'; + +export const textFormatKeymap = (std: BlockStdScope) => + textFormatConfigs + .filter(config => config.hotkey) + .reduce( + (acc, config) => { + return { + ...acc, + [config.hotkey as string]: ctx => { + const { doc, selection } = std; + if (doc.readonly) return; + + const textSelection = selection.find('text'); + if (!textSelection) return; + + config.action(std.host); + ctx.get('keyboardState').raw.preventDefault(); + return true; + }, + }; + }, + {} as Record + ); diff --git a/packages/affine/components/src/rich-text/keymap/index.ts b/packages/affine/components/src/rich-text/keymap/index.ts new file mode 100644 index 000000000000..9983ade1f054 --- /dev/null +++ b/packages/affine/components/src/rich-text/keymap/index.ts @@ -0,0 +1,15 @@ +import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std'; + +import { textCommonKeymap } from './basic.js'; +import { bracketKeymap } from './bracket.js'; +import { textFormatKeymap } from './format.js'; + +export const textKeymap = ( + std: BlockStdScope +): Record => { + return { + ...textCommonKeymap(std), + ...textFormatKeymap(std), + ...bracketKeymap(std), + }; +}; diff --git a/packages/affine/shared/src/utils/model.ts b/packages/affine/shared/src/utils/model.ts index d7cefc997650..7fe0b04de664 100644 --- a/packages/affine/shared/src/utils/model.ts +++ b/packages/affine/shared/src/utils/model.ts @@ -1,6 +1,6 @@ import type { NoteBlockModel } from '@blocksuite/affine-model'; import type { BlockComponent, EditorHost } from '@blocksuite/block-std'; -import type { BlockModel, Doc } from '@blocksuite/store'; +import type { BlockModel, Doc, DocCollection } from '@blocksuite/store'; import { minimatch } from 'minimatch'; @@ -67,3 +67,29 @@ export function findNoteBlockModel(model: BlockModel) { matchFlavours(m, ['affine:note']) ) as NoteBlockModel | null; } + +export function createDefaultDoc( + collection: DocCollection, + options: { id?: string; title?: string } = {} +) { + const doc = collection.createDoc({ id: options.id }); + + doc.load(); + const title = options.title ?? ''; + const rootId = doc.addBlock('affine:page', { + title: new doc.Text(title), + }); + collection.setDocMeta(doc.id, { + title, + }); + + // @ts-ignore FIXME: will be fixed when surface model migrated to affine-model + doc.addBlock('affine:surface', {}, rootId); + const noteId = doc.addBlock('affine:note', {}, rootId); + doc.addBlock('affine:paragraph', {}, noteId); + // To make sure the content of new doc would not be clear + // By undo operation for the first time + doc.resetHistory(); + + return doc; +} diff --git a/packages/blocks/src/_common/components/rich-text/keymap/container.ts b/packages/blocks/src/_common/components/rich-text/keymap/container.ts deleted file mode 100644 index aafc93223a51..000000000000 --- a/packages/blocks/src/_common/components/rich-text/keymap/container.ts +++ /dev/null @@ -1,252 +0,0 @@ -import type { BlockStdScope } from '@blocksuite/block-std'; -import type { - BlockComponent, - UIEventHandler, - UIEventStateContext, -} from '@blocksuite/block-std'; - -import { - focusTextModel, - getInlineEditorByModel, - insertLinkedNode, - selectTextModel, - textFormatConfigs, -} from '@blocksuite/affine-components/rich-text'; -import { BRACKET_PAIRS } from '@blocksuite/affine-shared/consts'; -import { matchFlavours } from '@blocksuite/affine-shared/utils'; -import { INLINE_ROOT_ATTR, type InlineRootElement } from '@blocksuite/inline'; - -import { createDefaultDoc } from '../../../utils/init.js'; - -function selectBlock(std: BlockStdScope, blockId: string) { - std.selection.setGroup('note', [std.selection.create('block', { blockId })]); -} - -export const textModelCommonHotkey = ( - std: BlockStdScope -): Record => { - return { - ArrowUp: () => { - const text = std.selection.find('text'); - if (!text) return; - const inline = getInlineEditorByModel(std.host, text.from.blockId); - if (!inline) return; - return !inline.isFirstLine(inline.getInlineRange()); - }, - ArrowDown: () => { - const text = std.selection.find('text'); - if (!text) return; - const inline = getInlineEditorByModel(std.host, text.from.blockId); - if (!inline) return; - return !inline.isLastLine(inline.getInlineRange()); - }, - Escape: ctx => { - const text = std.selection.find('text'); - if (!text) return; - - selectBlock(std, text.from.blockId); - ctx.get('keyboardState').raw.stopPropagation(); - return true; - }, - 'Mod-a': ctx => { - const text = std.selection.find('text'); - if (!text) return; - - const model = std.doc.getBlock(text.from.blockId)?.model; - if (!model || !model.text) return; - - ctx.get('keyboardState').raw.preventDefault(); - - if ( - text.from.index === 0 && - text.from.length === model.text.yText.length - ) { - selectBlock(std, text.from.blockId); - return true; - } - - selectTextModel(std, text.from.blockId, 0, model.text.yText.length); - return true; - }, - Enter: ctx => { - const blocks = std.selection.filter('block'); - const blockId = blocks.at(-1)?.blockId; - - if (!blockId) return; - const model = std.doc.getBlock(blockId)?.model; - if (!model || !model.text) return; - - ctx.get('keyboardState').raw.preventDefault(); - focusTextModel(std, blockId, model.text.yText.length); - return true; - }, - }; -}; - -// FIXME: use selection manager to set selection -export const bindContainerHotkey = (block: BlockComponent) => { - const model = block.model; - const editorHost = block.host; - - const _getInlineEditor = () => { - const inlineRoot = block.querySelector( - `[${INLINE_ROOT_ATTR}]` - ); - if (!inlineRoot) { - return null; - } - return inlineRoot.inlineEditor; - }; - - const _preventDefault = (ctx: UIEventStateContext) => { - const state = ctx.get('defaultState'); - state.event.preventDefault(); - }; - - textFormatConfigs.forEach(config => { - if (!config.hotkey) return; - - block.bindHotKey({ - [config.hotkey]: ctx => { - if (block.doc.readonly) return; - - const textSelection = block.selection.find('text'); - if (!textSelection) return; - - _preventDefault(ctx); - - config.action(editorHost); - return true; - }, - }); - }); - - function tryConvertToLinkedDoc() { - const root = model.doc.root; - if (!root) return false; - const linkedDocWidgetEle = block.host.view.getWidget( - 'affine-linked-doc-widget', - root.id - ); - if (!linkedDocWidgetEle) return false; - - const inlineEditor = _getInlineEditor(); - if (!inlineEditor) return; - const inlineRange = inlineEditor.getInlineRange(); - if (!inlineRange) return false; - const text = inlineEditor.yText.toString(); - const left = text[inlineRange.index - 1]; - const right = text[inlineRange.index + inlineRange.length]; - const needConvert = left === '[' && right === ']'; - if (!needConvert) return false; - - const docName = text.slice( - inlineRange.index, - inlineRange.index + inlineRange.length - ); - inlineEditor.deleteText({ - index: inlineRange.index - 1, - length: inlineRange.length + 2, - }); - inlineEditor.setInlineRange({ index: inlineRange.index - 1, length: 0 }); - - const doc = createDefaultDoc(block.doc.collection, { - title: docName, - }); - insertLinkedNode({ - inlineEditor, - docId: doc.id, - }); - return true; - } - - // Bracket auto complete - BRACKET_PAIRS.forEach(pair => { - block.bindHotKey({ - [pair.left]: ctx => { - if (block.doc.readonly) return; - - const textSelection = block.selection.find('text'); - if (!textSelection) return; - const isCodeBlock = matchFlavours(block.model, ['affine:code']); - // When selection is collapsed, only trigger auto complete in code block - if (textSelection.isCollapsed() && !isCodeBlock) return; - if (!textSelection.isInSameBlock()) return; - - _preventDefault(ctx); - - const inlineEditor = _getInlineEditor(); - if (!inlineEditor) return; - const inlineRange = inlineEditor.getInlineRange(); - if (!inlineRange) return; - const selectedText = inlineEditor.yText - .toString() - .slice(inlineRange.index, inlineRange.index + inlineRange.length); - if (!isCodeBlock && pair.name === 'square bracket') { - // [[Selected text]] should automatically be converted to a Linked doc with the title "Selected text". - // See https://github.com/toeverything/blocksuite/issues/2730 - const success = tryConvertToLinkedDoc(); - if (success) return true; - } - inlineEditor.insertText( - inlineRange, - pair.left + selectedText + pair.right - ); - - inlineEditor.setInlineRange({ - index: inlineRange.index + 1, - length: inlineRange.length, - }); - - return true; - }, - }); - }); - - // Skip redundant right bracket - BRACKET_PAIRS.forEach(pair => { - block.bindHotKey({ - [pair.right]: ctx => { - if (!matchFlavours(block.model, ['affine:code'])) return; - const inlineEditor = _getInlineEditor(); - if (!inlineEditor) return; - const inlineRange = inlineEditor.getInlineRange(); - if (!inlineRange) return; - const left = inlineEditor.yText.toString()[inlineRange.index - 1]; - const right = inlineEditor.yText.toString()[inlineRange.index]; - if (pair.left === left && pair.right === right) { - inlineEditor.setInlineRange({ - index: inlineRange.index + 1, - length: 0, - }); - _preventDefault(ctx); - } - }, - }); - }); - - // Convert the selected text into inline code - block.bindHotKey({ - '`': ctx => { - if (block.doc.readonly) return; - - const textSelection = block.selection.find('text'); - if (!textSelection || textSelection.isCollapsed()) return; - if (!textSelection.isInSameBlock()) return; - - _preventDefault(ctx); - const inlineEditor = _getInlineEditor(); - if (!inlineEditor) return; - const inlineRange = inlineEditor.getInlineRange(); - if (!inlineRange) return; - inlineEditor.formatText(inlineRange, { code: true }); - - inlineEditor.setInlineRange({ - index: inlineRange.index, - length: inlineRange.length, - }); - - return true; - }, - }); -}; diff --git a/packages/blocks/src/_common/components/rich-text/keymap/index.ts b/packages/blocks/src/_common/components/rich-text/keymap/index.ts deleted file mode 100644 index e8b94a6fb460..000000000000 --- a/packages/blocks/src/_common/components/rich-text/keymap/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './container.js'; diff --git a/packages/blocks/src/attachment-block/attachment-block.ts b/packages/blocks/src/attachment-block/attachment-block.ts index f4b76d844d47..4f8f1d1e6663 100644 --- a/packages/blocks/src/attachment-block/attachment-block.ts +++ b/packages/blocks/src/attachment-block/attachment-block.ts @@ -21,7 +21,6 @@ import { styleMap } from 'lit/directives/style-map.js'; import type { AttachmentBlockService } from './attachment-service.js'; import { CaptionedBlockComponent } from '../_common/components/index.js'; -import { bindContainerHotkey } from '../_common/components/rich-text/keymap/container.js'; import { getEmbedCardIcons } from '../_common/utils/url.js'; import { AttachmentOptionsTemplate } from './components/options.js'; import { renderEmbedView } from './embed.js'; @@ -120,8 +119,6 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent< override connectedCallback() { super.connectedCallback(); - bindContainerHotkey(this); - this.refreshData(); this.contentEditable = 'false'; diff --git a/packages/blocks/src/bookmark-block/bookmark-block.ts b/packages/blocks/src/bookmark-block/bookmark-block.ts index 700acf47a5d2..ac94cad6d40d 100644 --- a/packages/blocks/src/bookmark-block/bookmark-block.ts +++ b/packages/blocks/src/bookmark-block/bookmark-block.ts @@ -9,7 +9,6 @@ import type { EdgelessRootService } from '../root-block/index.js'; import type { BookmarkBlockService } from './bookmark-service.js'; import { CaptionedBlockComponent } from '../_common/components/captioned-block-component.js'; -import { bindContainerHotkey } from '../_common/components/rich-text/keymap/container.js'; import { EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH } from '../_common/consts.js'; import { BOOKMARK_MIN_WIDTH } from '../root-block/edgeless/utils/consts.js'; import './components/bookmark-card.js'; @@ -41,8 +40,6 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent< override connectedCallback() { super.connectedCallback(); - bindContainerHotkey(this); - this._fetchAbortController = new AbortController(); this.contentEditable = 'false'; diff --git a/packages/blocks/src/code-block/code-block-service.ts b/packages/blocks/src/code-block/code-block-service.ts index ba9292e28c9d..8925f27b3a2a 100644 --- a/packages/blocks/src/code-block/code-block-service.ts +++ b/packages/blocks/src/code-block/code-block-service.ts @@ -1,6 +1,7 @@ import { type AffineTextAttributes, InlineManager, + textKeymap, } from '@blocksuite/affine-components/rich-text'; import { type CodeBlockModel, ColorScheme } from '@blocksuite/affine-model'; import { ThemeObserver } from '@blocksuite/affine-shared/theme'; @@ -13,7 +14,6 @@ import { } from 'shiki'; import getWasm from 'shiki/wasm'; -import { textModelCommonHotkey } from '../_common/components/rich-text/keymap/index.js'; import { codeBlockInlineSpecs } from './highlight/code-block-inline-specs.js'; import { CODE_BLOCK_DEFAULT_DARK_THEME, @@ -34,7 +34,7 @@ export class CodeBlockService< override mounted(): void { super.mounted(); - this.bindHotKey(textModelCommonHotkey(this.std)); + this.bindHotKey(textKeymap(this.std)); this.inlineManager.registerSpecs(codeBlockInlineSpecs); createHighlighterCore({ diff --git a/packages/blocks/src/code-block/code-block.ts b/packages/blocks/src/code-block/code-block.ts index 6c0511ab3106..f1880cbbb59f 100644 --- a/packages/blocks/src/code-block/code-block.ts +++ b/packages/blocks/src/code-block/code-block.ts @@ -36,7 +36,6 @@ import { import type { CodeBlockService } from './code-block-service.js'; import { CaptionedBlockComponent } from '../_common/components/captioned-block-component.js'; -import { bindContainerHotkey } from '../_common/components/rich-text/keymap/index.js'; import { NOTE_SELECTOR } from '../_common/edgeless/note/consts.js'; import { getViewportElement } from '../_common/utils/query.js'; import { EdgelessRootBlockComponent } from '../root-block/edgeless/edgeless-root-block.js'; @@ -145,8 +144,6 @@ export class CodeBlockComponent extends CaptionedBlockComponent< }) ); - bindContainerHotkey(this); - const selectionManager = this.host.selection; const INDENT_SYMBOL = ' '; const LINE_BREAK_SYMBOL = '\n'; diff --git a/packages/blocks/src/list-block/list-block.ts b/packages/blocks/src/list-block/list-block.ts index bf7a3e6b98b3..845e5ea69194 100644 --- a/packages/blocks/src/list-block/list-block.ts +++ b/packages/blocks/src/list-block/list-block.ts @@ -17,7 +17,6 @@ import { customElement, query, state } from 'lit/decorators.js'; import type { ListBlockService } from './list-service.js'; import { CaptionedBlockComponent } from '../_common/components/captioned-block-component.js'; -import { bindContainerHotkey } from '../_common/components/rich-text/keymap/index.js'; import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT } from '../_common/consts.js'; import { NOTE_SELECTOR } from '../_common/edgeless/note/consts.js'; import { getViewportElement } from '../_common/utils/query.js'; @@ -125,8 +124,6 @@ export class ListBlockComponent extends CaptionedBlockComponent< override connectedCallback() { super.connectedCallback(); - bindContainerHotkey(this); - // TODO: move to service for better performance this.bindHotKey({ Enter: ctx => { diff --git a/packages/blocks/src/list-block/list-service.ts b/packages/blocks/src/list-block/list-service.ts index 8bc187655416..b7c2ee8e1080 100644 --- a/packages/blocks/src/list-block/list-service.ts +++ b/packages/blocks/src/list-block/list-service.ts @@ -6,12 +6,12 @@ import { ReferenceNodeConfig, affineInlineMarkdownMatches, getAffineInlineSpecsWithReference, + textKeymap, } from '@blocksuite/affine-components/rich-text'; import { ListBlockSchema } from '@blocksuite/affine-model'; import { matchFlavours } from '@blocksuite/affine-shared/utils'; import { BlockService } from '@blocksuite/block-std'; -import { textModelCommonHotkey } from '../_common/components/rich-text/keymap/index.js'; import { AffineDragHandleWidget } from '../root-block/widgets/drag-handle/drag-handle.js'; import { correctNumberedListsOrderToPrev } from './commands/utils.js'; import { listPrefix, toggleStyles } from './styles.js'; @@ -41,7 +41,7 @@ export class ListBlockService< this.inlineManager.registerSpecs(inlineSpecs); this.inlineManager.registerMarkdownMatches(affineInlineMarkdownMatches); - this.bindHotKey(textModelCommonHotkey(this.std)); + this.bindHotKey(textKeymap(this.std)); this.disposables.add( AffineDragHandleWidget.registerOption({ diff --git a/packages/blocks/src/paragraph-block/paragraph-block.ts b/packages/blocks/src/paragraph-block/paragraph-block.ts index 56ea22f761da..8530f080546a 100644 --- a/packages/blocks/src/paragraph-block/paragraph-block.ts +++ b/packages/blocks/src/paragraph-block/paragraph-block.ts @@ -16,7 +16,6 @@ import { customElement, query } from 'lit/decorators.js'; import type { ParagraphBlockService } from './paragraph-service.js'; import { CaptionedBlockComponent } from '../_common/components/captioned-block-component.js'; -import { bindContainerHotkey } from '../_common/components/rich-text/keymap/index.js'; import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT } from '../_common/consts.js'; import { NOTE_SELECTOR } from '../_common/edgeless/note/consts.js'; import { getViewportElement } from '../_common/utils/query.js'; @@ -52,7 +51,6 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent< override connectedCallback() { super.connectedCallback(); - bindContainerHotkey(this); this.bindHotKey({ Backspace: ctx => { const text = this.std.selection.find('text'); diff --git a/packages/blocks/src/paragraph-block/paragraph-service.ts b/packages/blocks/src/paragraph-block/paragraph-service.ts index ff273d37bcb0..6f2175c93874 100644 --- a/packages/blocks/src/paragraph-block/paragraph-service.ts +++ b/packages/blocks/src/paragraph-block/paragraph-service.ts @@ -6,11 +6,10 @@ import { ReferenceNodeConfig, affineInlineMarkdownMatches, getAffineInlineSpecsWithReference, + textKeymap, } from '@blocksuite/affine-components/rich-text'; import { BlockService } from '@blocksuite/block-std'; -import { textModelCommonHotkey } from '../_common/components/rich-text/keymap/index.js'; - export class ParagraphBlockService< TextAttributes extends AffineTextAttributes = AffineTextAttributes, > extends BlockService { @@ -38,7 +37,7 @@ export class ParagraphBlockService< override mounted(): void { super.mounted(); - this.bindHotKey(textModelCommonHotkey(this.std)); + this.bindHotKey(textKeymap(this.std)); this.referenceNodeConfig.setDoc(this.doc); const inlineSpecs = getAffineInlineSpecsWithReference( diff --git a/packages/blocks/src/surface-ref-block/surface-ref-block.ts b/packages/blocks/src/surface-ref-block/surface-ref-block.ts index eff7af312990..3e89d4727cd6 100644 --- a/packages/blocks/src/surface-ref-block/surface-ref-block.ts +++ b/packages/blocks/src/surface-ref-block/surface-ref-block.ts @@ -27,7 +27,6 @@ import type { EdgelessRootPreviewBlockComponent } from '../root-block/edgeless/e import type { EdgelessRootService } from '../root-block/index.js'; import type { SurfaceRefBlockService } from './surface-ref-service.js'; -import { bindContainerHotkey } from '../_common/components/rich-text/keymap/container.js'; import { SpecProvider } from '../specs/index.js'; import { type SurfaceBlockModel, @@ -518,8 +517,6 @@ export class SurfaceRefBlockComponent extends BlockComponent< override connectedCallback() { super.connectedCallback(); - bindContainerHotkey(this); - this.contentEditable = 'false'; if (!this._shouldRender) return;