diff --git a/package.json b/package.json index 27881966479..ec57f5301c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "roosterjs", - "version": "7.3.1", + "version": "7.3.2", "description": "Framework-independent javascript editor", "repository": { "type": "git", diff --git a/packages/roosterjs-editor-core/lib/coreAPI/attachDomEvent.ts b/packages/roosterjs-editor-core/lib/coreAPI/attachDomEvent.ts index 3f57383d631..473d38f93ba 100644 --- a/packages/roosterjs-editor-core/lib/coreAPI/attachDomEvent.ts +++ b/packages/roosterjs-editor-core/lib/coreAPI/attachDomEvent.ts @@ -1,5 +1,5 @@ import EditorCore, { AttachDomEvent } from '../interfaces/EditorCore'; -import isModifierKey from '../eventApi/isModifierKey'; +import isCharacterValue from '../eventApi/isCharacterValue'; import { PluginDomEvent, PluginEventType } from 'roosterjs-editor-types'; const attachDomEvent: AttachDomEvent = ( @@ -14,10 +14,7 @@ const attachDomEvent: AttachDomEvent = ( // event.key is longer than 1 for num pad input. But here we just want to improve performance as much as possible. // So if we missed some case here it is still acceptable. if ( - (isKeyboardEvent(event) && - !isModifierKey(event) && - event.key && - event.key.length == 1) || + (isKeyboardEvent(event) && isCharacterValue(event)) || pluginEventType == PluginEventType.Input ) { event.stopPropagation(); diff --git a/packages/roosterjs-editor-core/lib/eventApi/isCharacterValue.ts b/packages/roosterjs-editor-core/lib/eventApi/isCharacterValue.ts new file mode 100644 index 00000000000..6a77d227e6d --- /dev/null +++ b/packages/roosterjs-editor-core/lib/eventApi/isCharacterValue.ts @@ -0,0 +1,12 @@ +import isModifierKey from './isModifierKey'; + +/** + * Returns true when the event was fired from a key that produces a character value, otherwise false + * This detection is not 100% accurate. event.key is not fully supported by all browsers, and in some browsers (e.g. IE), + * event.key is longer than 1 for num pad input. But here we just want to improve performance as much as possible. + * So if we missed some case here it is still acceptable. + * @param event The keyboard event object + */ +export default function isCharacterValue(event: KeyboardEvent): boolean { + return !isModifierKey(event) && event.key && event.key.length == 1; +} diff --git a/packages/roosterjs-editor-core/lib/eventApi/isModifierKey.ts b/packages/roosterjs-editor-core/lib/eventApi/isModifierKey.ts index 090ec4f64f9..d1644a74ddf 100644 --- a/packages/roosterjs-editor-core/lib/eventApi/isModifierKey.ts +++ b/packages/roosterjs-editor-core/lib/eventApi/isModifierKey.ts @@ -2,7 +2,10 @@ const CTRL_CHARCODE = 'Control'; const ALT_CHARCODE = 'Alt'; const META_CHARCODE = 'Meta'; -// Returns true when the event was fired from a modifier key, otherwise false +/** + * Returns true when the event was fired from a modifier key, otherwise false + * @param event The keyboard event object + */ export default function isModifierKey(event: KeyboardEvent): boolean { const isCtrlKey = event.ctrlKey || event.key === CTRL_CHARCODE; const isAltKey = event.altKey || event.key === ALT_CHARCODE; diff --git a/packages/roosterjs-editor-core/lib/index.ts b/packages/roosterjs-editor-core/lib/index.ts index 6d4aa8a58aa..e197183ae2c 100644 --- a/packages/roosterjs-editor-core/lib/index.ts +++ b/packages/roosterjs-editor-core/lib/index.ts @@ -44,3 +44,4 @@ export { } from './eventApi/cacheGetContentSearcher'; export { default as cacheGetElementAtCursor } from './eventApi/cacheGetElementAtCursor'; export { default as isModifierKey } from './eventApi/isModifierKey'; +export { default as isCharacterValue } from './eventApi/isCharacterValue'; diff --git a/packages/roosterjs-plugin-picker/lib/PickerDataProvider.ts b/packages/roosterjs-plugin-picker/lib/PickerDataProvider.ts index 1422d448467..017fd1f5e34 100644 --- a/packages/roosterjs-plugin-picker/lib/PickerDataProvider.ts +++ b/packages/roosterjs-plugin-picker/lib/PickerDataProvider.ts @@ -46,7 +46,7 @@ export interface PickerDataProvider { onIsSuggestingChanged: (isSuggesting: boolean) => void; // Function called when the query string (text after the trigger symbol) is updated. - queryStringUpdated: (queryString: string) => void; + queryStringUpdated: (queryString: string, isExactMatch: boolean) => void; // Function called when a keypress is issued that would "select" a currently highlighted option. selectOption?: () => void; diff --git a/packages/roosterjs-plugin-picker/lib/PickerPlugin.ts b/packages/roosterjs-plugin-picker/lib/PickerPlugin.ts index 4caa3ec19ad..12772e2e98b 100644 --- a/packages/roosterjs-plugin-picker/lib/PickerPlugin.ts +++ b/packages/roosterjs-plugin-picker/lib/PickerPlugin.ts @@ -1,8 +1,13 @@ import { Browser, createRange, PartialInlineElement } from 'roosterjs-editor-dom'; -import { cacheGetContentSearcher, Editor, EditorPlugin } from 'roosterjs-editor-core'; -import { isModifierKey } from 'roosterjs-editor-core'; import { PickerDataProvider, PickerPluginOptions } from './PickerDataProvider'; import { replaceWithNode } from 'roosterjs-editor-api'; +import { + cacheGetContentSearcher, + Editor, + EditorPlugin, + isCharacterValue, + isModifierKey, +} from 'roosterjs-editor-core'; import { NodePosition, PluginKeyboardEvent, @@ -128,6 +133,11 @@ export default class PickerPlugin 0 && trimmedWordBeforeCursor.split(' ').length <= 4) ) { - this.dataProvider.queryStringUpdated(trimmedWordBeforeCursor); + this.dataProvider.queryStringUpdated( + trimmedWordBeforeCursor, + wordBeforeCursorWithoutTriggerChar == trimmedWordBeforeCursor + ); this.setLastKnownRange(this.editor.getSelectionRange()); } else { this.setIsSuggesting(false); @@ -260,8 +275,12 @@ export default class PickerPlugin