Skip to content

Commit e14c457

Browse files
committed
Merge branch 'rc/v12.0.0' into make-toolbox-and-flyout-focusable
2 parents 57391a7 + b9b40f4 commit e14c457

File tree

17 files changed

+113
-315
lines changed

17 files changed

+113
-315
lines changed

core/block_svg.ts

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ import {IContextMenu} from './interfaces/i_contextmenu.js';
4444
import type {ICopyable} from './interfaces/i_copyable.js';
4545
import {IDeletable} from './interfaces/i_deletable.js';
4646
import type {IDragStrategy, IDraggable} from './interfaces/i_draggable.js';
47-
import type {IFocusableNode} from './interfaces/i_focusable_node.js';
48-
import type {IFocusableTree} from './interfaces/i_focusable_tree.js';
4947
import {IIcon} from './interfaces/i_icon.js';
5048
import * as internalConstants from './internal_constants.js';
5149
import {MarkerManager} from './marker_manager.js';
@@ -78,8 +76,7 @@ export class BlockSvg
7876
IContextMenu,
7977
ICopyable<BlockCopyData>,
8078
IDraggable,
81-
IDeletable,
82-
IFocusableNode
79+
IDeletable
8380
{
8481
/**
8582
* Constant for identifying rows that are to be rendered inline.
@@ -213,7 +210,6 @@ export class BlockSvg
213210

214211
// Expose this block's ID on its top-level SVG group.
215212
this.svgGroup.setAttribute('data-id', this.id);
216-
svgPath.id = this.id;
217213

218214
this.doInit_();
219215
}
@@ -309,14 +305,22 @@ export class BlockSvg
309305
(newParent as BlockSvg).getSvgRoot().appendChild(svgRoot);
310306
} else if (oldParent) {
311307
// If we are losing a parent, we want to move our DOM element to the
312-
// root of the workspace.
313-
const draggingBlock = this.workspace
308+
// root of the workspace. Try to insert it before any top-level
309+
// block being dragged, but note that blocks can have the
310+
// blocklyDragging class even if they're not top blocks (especially
311+
// at start and end of a drag).
312+
const draggingBlockElement = this.workspace
314313
.getCanvas()
315314
.querySelector('.blocklyDragging');
316-
if (draggingBlock) {
317-
this.workspace.getCanvas().insertBefore(svgRoot, draggingBlock);
315+
const draggingParentElement = draggingBlockElement?.parentElement as
316+
| SVGElement
317+
| null
318+
| undefined;
319+
const canvas = this.workspace.getCanvas();
320+
if (draggingParentElement === canvas) {
321+
canvas.insertBefore(svgRoot, draggingBlockElement);
318322
} else {
319-
this.workspace.getCanvas().appendChild(svgRoot);
323+
canvas.appendChild(svgRoot);
320324
}
321325
this.translate(oldXY.x, oldXY.y);
322326
}
@@ -1823,26 +1827,4 @@ export class BlockSvg
18231827
);
18241828
}
18251829
}
1826-
1827-
/** See IFocusableNode.getFocusableElement. */
1828-
getFocusableElement(): HTMLElement | SVGElement {
1829-
return this.pathObject.svgPath;
1830-
}
1831-
1832-
/** See IFocusableNode.getFocusableTree. */
1833-
getFocusableTree(): IFocusableTree {
1834-
return this.workspace;
1835-
}
1836-
1837-
/** See IFocusableNode.onNodeFocus. */
1838-
onNodeFocus(): void {
1839-
common.setSelected(this);
1840-
}
1841-
1842-
/** See IFocusableNode.onNodeBlur. */
1843-
onNodeBlur(): void {
1844-
if (common.getSelected() === this) {
1845-
common.setSelected(null);
1846-
}
1847-
}
18481830
}

core/dragging/block_drag_strategy.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export class BlockDragStrategy implements IDragStrategy {
238238
const currCandidate = this.connectionCandidate;
239239
const newCandidate = this.getConnectionCandidate(draggingBlock, delta);
240240
if (!newCandidate) {
241-
this.connectionPreviewer!.hidePreview();
241+
this.connectionPreviewer?.hidePreview();
242242
this.connectionCandidate = null;
243243
return;
244244
}
@@ -254,7 +254,7 @@ export class BlockDragStrategy implements IDragStrategy {
254254
local.type === ConnectionType.OUTPUT_VALUE ||
255255
local.type === ConnectionType.PREVIOUS_STATEMENT;
256256
const neighbourIsConnectedToRealBlock =
257-
neighbour.isConnected() && !neighbour.targetBlock()!.isInsertionMarker();
257+
neighbour.isConnected() && !neighbour.targetBlock()?.isInsertionMarker();
258258
if (
259259
localIsOutputOrPrevious &&
260260
neighbourIsConnectedToRealBlock &&
@@ -264,14 +264,14 @@ export class BlockDragStrategy implements IDragStrategy {
264264
local.type,
265265
)
266266
) {
267-
this.connectionPreviewer!.previewReplacement(
267+
this.connectionPreviewer?.previewReplacement(
268268
local,
269269
neighbour,
270270
neighbour.targetBlock()!,
271271
);
272272
return;
273273
}
274-
this.connectionPreviewer!.previewConnection(local, neighbour);
274+
this.connectionPreviewer?.previewConnection(local, neighbour);
275275
}
276276

277277
/**
@@ -385,7 +385,7 @@ export class BlockDragStrategy implements IDragStrategy {
385385
dom.stopTextWidthCache();
386386

387387
blockAnimation.disconnectUiStop();
388-
this.connectionPreviewer!.hidePreview();
388+
this.connectionPreviewer?.hidePreview();
389389

390390
if (!this.block.isDeadOrDying() && this.dragging) {
391391
// These are expensive and don't need to be done if we're deleting, or
@@ -413,7 +413,7 @@ export class BlockDragStrategy implements IDragStrategy {
413413

414414
// Must dispose after connections are applied to not break the dynamic
415415
// connections plugin. See #7859
416-
this.connectionPreviewer!.dispose();
416+
this.connectionPreviewer?.dispose();
417417
this.workspace.setResizesEnabled(true);
418418
eventUtils.setGroup(newGroup);
419419
}
@@ -445,6 +445,9 @@ export class BlockDragStrategy implements IDragStrategy {
445445
return;
446446
}
447447

448+
this.connectionPreviewer?.hidePreview();
449+
this.connectionCandidate = null;
450+
448451
this.startChildConn?.connect(this.block.nextConnection);
449452
if (this.startParentConn) {
450453
switch (this.startParentConn.type) {
@@ -471,9 +474,6 @@ export class BlockDragStrategy implements IDragStrategy {
471474
this.startChildConn = null;
472475
this.startParentConn = null;
473476

474-
this.connectionPreviewer!.hidePreview();
475-
this.connectionCandidate = null;
476-
477477
this.block.setDragging(false);
478478
this.dragging = false;
479479
}

core/flyout_base.ts

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,9 @@ import * as eventUtils from './events/utils.js';
2121
import {FlyoutItem} from './flyout_item.js';
2222
import {FlyoutMetricsManager} from './flyout_metrics_manager.js';
2323
import {FlyoutSeparator, SeparatorAxis} from './flyout_separator.js';
24-
import {getFocusManager} from './focus_manager.js';
2524
import {IAutoHideable} from './interfaces/i_autohideable.js';
2625
import type {IFlyout} from './interfaces/i_flyout.js';
2726
import type {IFlyoutInflater} from './interfaces/i_flyout_inflater.js';
28-
import {IFocusableNode} from './interfaces/i_focusable_node.js';
29-
import {IFocusableTree} from './interfaces/i_focusable_tree.js';
3027
import type {Options} from './options.js';
3128
import * as registry from './registry.js';
3229
import * as renderManagement from './render_management.js';
@@ -46,7 +43,7 @@ import {WorkspaceSvg} from './workspace_svg.js';
4643
*/
4744
export abstract class Flyout
4845
extends DeleteArea
49-
implements IAutoHideable, IFlyout, IFocusableNode
46+
implements IAutoHideable, IFlyout
5047
{
5148
/**
5249
* Position the flyout.
@@ -306,7 +303,6 @@ export abstract class Flyout
306303
// hide/show code will set up proper visibility and size later.
307304
this.svgGroup_ = dom.createSvgElement(tagName, {
308305
'class': 'blocklyFlyout',
309-
'tabindex': '0',
310306
});
311307
this.svgGroup_.style.display = 'none';
312308
this.svgBackground_ = dom.createSvgElement(
@@ -321,9 +317,6 @@ export abstract class Flyout
321317
this.workspace_
322318
.getThemeManager()
323319
.subscribe(this.svgBackground_, 'flyoutOpacity', 'fill-opacity');
324-
325-
getFocusManager().registerTree(this);
326-
327320
return this.svgGroup_;
328321
}
329322

@@ -405,7 +398,6 @@ export abstract class Flyout
405398
if (this.svgGroup_) {
406399
dom.removeNode(this.svgGroup_);
407400
}
408-
getFocusManager().unregisterTree(this);
409401
}
410402

411403
/**
@@ -969,63 +961,4 @@ export abstract class Flyout
969961

970962
return null;
971963
}
972-
973-
/** See IFocusableNode.getFocusableElement. */
974-
getFocusableElement(): HTMLElement | SVGElement {
975-
if (!this.svgGroup_) throw new Error('Flyout DOM is not yet created.');
976-
return this.svgGroup_;
977-
}
978-
979-
/** See IFocusableNode.getFocusableTree. */
980-
getFocusableTree(): IFocusableTree {
981-
return this;
982-
}
983-
984-
/** See IFocusableNode.onNodeFocus. */
985-
onNodeFocus(): void {}
986-
987-
/** See IFocusableNode.onNodeBlur. */
988-
onNodeBlur(): void {}
989-
990-
/** See IFocusableTree.getRootFocusableNode. */
991-
getRootFocusableNode(): IFocusableNode {
992-
return this;
993-
}
994-
995-
/** See IFocusableTree.getRestoredFocusableNode. */
996-
getRestoredFocusableNode(
997-
_previousNode: IFocusableNode | null,
998-
): IFocusableNode | null {
999-
return null;
1000-
}
1001-
1002-
/** See IFocusableTree.getNestedTrees. */
1003-
getNestedTrees(): Array<IFocusableTree> {
1004-
return [this.workspace_];
1005-
}
1006-
1007-
/** See IFocusableTree.lookUpFocusableNode. */
1008-
lookUpFocusableNode(_id: string): IFocusableNode | null {
1009-
// No focusable node needs to be returned since the flyout's subtree is a
1010-
// workspace that will manage its own focusable state.
1011-
return null;
1012-
}
1013-
1014-
/** See IFocusableTree.onTreeFocus. */
1015-
onTreeFocus(
1016-
_node: IFocusableNode,
1017-
_previousTree: IFocusableTree | null,
1018-
): void {}
1019-
1020-
/** See IFocusableTree.onTreeBlur. */
1021-
onTreeBlur(nextTree: IFocusableTree | null): void {
1022-
const toolbox = this.targetWorkspace.getToolbox();
1023-
// If focus is moving to either the toolbox or the flyout's workspace, do
1024-
// not close the flyout. For anything else, do close it since the flyout is
1025-
// no longer focused.
1026-
if (toolbox && nextTree === toolbox) return;
1027-
if (nextTree == this.workspace_) return;
1028-
if (toolbox) toolbox.clearSelection();
1029-
this.autoHide(false);
1030-
}
1031964
}

core/inject.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ import * as common from './common.js';
1313
import * as Css from './css.js';
1414
import * as dropDownDiv from './dropdowndiv.js';
1515
import {Grid} from './grid.js';
16+
import {Msg} from './msg.js';
1617
import {Options} from './options.js';
1718
import {ScrollbarPair} from './scrollbar_pair.js';
1819
import {ShortcutRegistry} from './shortcut_registry.js';
1920
import * as Tooltip from './tooltip.js';
2021
import * as Touch from './touch.js';
22+
import * as aria from './utils/aria.js';
2123
import * as dom from './utils/dom.js';
2224
import {Svg} from './utils/svg.js';
2325
import * as WidgetDiv from './widgetdiv.js';
@@ -54,6 +56,8 @@ export function inject(
5456
if (opt_options?.rtl) {
5557
dom.addClass(subContainer, 'blocklyRTL');
5658
}
59+
subContainer.tabIndex = 0;
60+
aria.setState(subContainer, aria.State.LABEL, Msg['WORKSPACE_ARIA_LABEL']);
5761

5862
containerElement!.appendChild(subContainer);
5963
const svg = createDom(subContainer, options);
@@ -122,6 +126,7 @@ function createDom(container: HTMLElement, options: Options): SVGElement {
122126
'xmlns:xlink': dom.XLINK_NS,
123127
'version': '1.1',
124128
'class': 'blocklySvg',
129+
'tabindex': '0',
125130
},
126131
container,
127132
);

core/interfaces/i_flyout.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ import type {Coordinate} from '../utils/coordinate.js';
1212
import type {Svg} from '../utils/svg.js';
1313
import type {FlyoutDefinition} from '../utils/toolbox.js';
1414
import type {WorkspaceSvg} from '../workspace_svg.js';
15-
import {IFocusableTree} from './i_focusable_tree.js';
1615
import type {IRegistrable} from './i_registrable.js';
1716

1817
/**
1918
* Interface for a flyout.
2019
*/
21-
export interface IFlyout extends IRegistrable, IFocusableTree {
20+
export interface IFlyout extends IRegistrable {
2221
/** Whether the flyout is laid out horizontally or not. */
2322
horizontalLayout: boolean;
2423

core/interfaces/i_toolbox.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@
99
import type {ToolboxInfo} from '../utils/toolbox.js';
1010
import type {WorkspaceSvg} from '../workspace_svg.js';
1111
import type {IFlyout} from './i_flyout.js';
12-
import type {IFocusableTree} from './i_focusable_tree.js';
1312
import type {IRegistrable} from './i_registrable.js';
1413
import type {IToolboxItem} from './i_toolbox_item.js';
1514

1615
/**
1716
* Interface for a toolbox.
1817
*/
19-
export interface IToolbox extends IRegistrable, IFocusableTree {
18+
export interface IToolbox extends IRegistrable {
2019
/** Initializes the toolbox. */
2120
init(): void;
2221

core/interfaces/i_toolbox_item.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66

77
// Former goog.module ID: Blockly.IToolboxItem
88

9-
import type {IFocusableNode} from './i_focusable_node.js';
10-
119
/**
1210
* Interface for an item in the toolbox.
1311
*/
14-
export interface IToolboxItem extends IFocusableNode {
12+
export interface IToolboxItem {
1513
/**
1614
* Initializes the toolbox item.
1715
* This includes creating the DOM and updating the state of any items based

core/keyboard_nav/line_cursor.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,12 @@ export class LineCursor extends Marker {
146146
if (!curNode) {
147147
return null;
148148
}
149-
const newNode = this.getPreviousNodeImpl(
149+
const newNode = this.getPreviousNode(
150150
curNode,
151151
this.validLineNode.bind(this),
152+
true,
152153
);
154+
153155
if (newNode) {
154156
this.setCurNode(newNode);
155157
}
@@ -168,9 +170,10 @@ export class LineCursor extends Marker {
168170
if (!curNode) {
169171
return null;
170172
}
171-
const newNode = this.getPreviousNodeImpl(
173+
const newNode = this.getPreviousNode(
172174
curNode,
173175
this.validInLineNode.bind(this),
176+
true,
174177
);
175178

176179
if (newNode) {

core/renderers/common/path_object.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class PathObject implements IPathObject {
6262
/** The primary path of the block. */
6363
this.svgPath = dom.createSvgElement(
6464
Svg.PATH,
65-
{'class': 'blocklyPath', 'tabindex': '-1'},
65+
{'class': 'blocklyPath'},
6666
this.svgRoot,
6767
);
6868

core/toolbox/category.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ export class ToolboxCategory
225225
*/
226226
protected createContainer_(): HTMLDivElement {
227227
const container = document.createElement('div');
228-
container.tabIndex = -1;
229-
container.id = this.getId();
230228
const className = this.cssConfig_['container'];
231229
if (className) {
232230
dom.addClass(container, className);

0 commit comments

Comments
 (0)