Skip to content
14 changes: 12 additions & 2 deletions core/layer_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {getFocusManager} from './focus_manager.js';
import type {IFocusableNode} from './interfaces/i_focusable_node.js';
import {IRenderedElement} from './interfaces/i_rendered_element.js';
import * as layerNums from './layers.js';
import {Coordinate} from './utils/coordinate.js';
Expand Down Expand Up @@ -99,17 +101,25 @@ export class LayerManager {
*
* @internal
*/
moveToDragLayer(elem: IRenderedElement) {
moveToDragLayer(elem: IRenderedElement & IFocusableNode) {
this.dragLayer?.appendChild(elem.getSvgRoot());

// Since moving the element to the drag layer will cause it to lose focus,
// ensure it regains focus (to ensure proper highlights & sent events).
getFocusManager().focusNode(elem);
}

/**
* Moves the given element off of the drag layer.
*
* @internal
*/
moveOffDragLayer(elem: IRenderedElement, layerNum: number) {
moveOffDragLayer(elem: IRenderedElement & IFocusableNode, layerNum: number) {
this.append(elem, layerNum);

// Since moving the element off the drag layer will cause it to lose focus,
// ensure it regains focus (to ensure proper highlights & sent events).
getFocusManager().focusNode(elem);
}

/**
Expand Down
12 changes: 12 additions & 0 deletions core/renderers/zelos/path_object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import type {BlockSvg} from '../../block_svg.js';
import type {Connection} from '../../connection.js';
import {FocusManager} from '../../focus_manager.js';
import type {BlockStyle} from '../../theme.js';
import * as dom from '../../utils/dom.js';
import {Svg} from '../../utils/svg.js';
Expand Down Expand Up @@ -91,6 +92,17 @@ export class PathObject extends BasePathObject {
if (!this.svgPathSelected) {
this.svgPathSelected = this.svgPath.cloneNode(true) as SVGElement;
this.svgPathSelected.classList.add('blocklyPathSelected');
// Ensure focus-specific properties don't overlap with the block's path.
dom.removeClass(
this.svgPathSelected,
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
);
dom.removeClass(
this.svgPathSelected,
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
);
this.svgPathSelected.removeAttribute('tabindex');
this.svgPathSelected.removeAttribute('id');
this.svgRoot.appendChild(this.svgPathSelected);
}
} else {
Expand Down
9 changes: 9 additions & 0 deletions tests/mocha/layering_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ suite('Layering', function () {
const g = Blockly.utils.dom.createSvgElement('g', {});
return {
getSvgRoot: () => g,
getFocusableElement: () => {
throw new Error('Unsupported.');
},
getFocusableTree: () => {
throw new Error('Unsupported.');
},
onNodeFocus: () => {},
onNodeBlur: () => {},
canBeFocused: () => false,
};
}

Expand Down