@@ -11,6 +11,7 @@ import type {BlockSvg} from './block_svg.js';
1111import * as browserEvents from './browser_events.js' ;
1212import { config } from './config.js' ;
1313import type {
14+ ActionContextMenuOption ,
1415 ContextMenuOption ,
1516 LegacyContextMenuOption ,
1617} from './contextmenu_registry.js' ;
@@ -25,6 +26,7 @@ import * as aria from './utils/aria.js';
2526import { Coordinate } from './utils/coordinate.js' ;
2627import * as dom from './utils/dom.js' ;
2728import { Rect } from './utils/rect.js' ;
29+ import { getShortcutKeysShort } from './utils/shortcut_formatting.js' ;
2830import * as svgMath from './utils/svg_math.js' ;
2931import * as WidgetDiv from './widgetdiv.js' ;
3032import type { WorkspaceSvg } from './workspace_svg.js' ;
@@ -134,7 +136,7 @@ function populate_(
134136 continue ;
135137 }
136138
137- const menuItem = new MenuItem ( option . text ) ;
139+ const menuItem = new MenuItem ( makeMenuitem ( option ) ) ;
138140 menuItem . setRightToLeft ( rtl ) ;
139141 menuItem . setRole ( aria . Role . MENUITEM ) ;
140142 menu . addChild ( menuItem ) ;
@@ -302,3 +304,48 @@ export function callbackFactory(
302304export function getMenu ( ) : Menu | null {
303305 return menu_ ;
304306}
307+
308+ /**
309+ * Creates a menu item to represent the given context menu option.
310+ * For text-based menu options, this wraps the text in a container with its
311+ * corresponding keyboard shortcut, if any. HTML-based menu options are displayed
312+ * as-is.
313+ *
314+ * @param option The context menu option to generate a menu item for.
315+ * @returns A `MenuItem` representing the given context menu option.
316+ */
317+ function makeMenuitem (
318+ option : ActionContextMenuOption | LegacyContextMenuOption ,
319+ ) {
320+ const text = option . text ;
321+ if ( text && ! ( text instanceof HTMLElement ) ) {
322+ const container = document . createElement ( 'div' ) ;
323+ container . className = 'blocklyShortcutContainer' ;
324+ const label = document . createElement ( 'span' ) ;
325+ label . textContent = text ;
326+ const shortcut = document . createElement ( 'span' ) ;
327+ shortcut . className = 'blocklyShortcut' ;
328+ shortcut . textContent = ` ${ getKeyboardShortcut ( option ) } ` ;
329+ container . appendChild ( label ) ;
330+ container . appendChild ( shortcut ) ;
331+ return container ;
332+ }
333+
334+ return option . text ;
335+ }
336+
337+ /**
338+ * Returns a textual representation of the keyboard shortcut for the given
339+ * context menu item, if any.
340+ *
341+ * @param option The context menu item to retrieve a keyboard shortcut for.
342+ * @returns A textual representation of the keyboard shortcut registered under
343+ * the name stored in the menu option's `associatedKeyboardShortcut` field,
344+ * if any.
345+ */
346+ function getKeyboardShortcut (
347+ option : ContextMenuOption | LegacyContextMenuOption ,
348+ ) : string {
349+ if ( ! ( 'id' in option ) || ! option . associatedKeyboardShortcut ) return '' ;
350+ return getShortcutKeysShort ( option . associatedKeyboardShortcut ) ;
351+ }
0 commit comments