Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions packages/blockly/core/block_svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1905,4 +1905,58 @@ export class BlockSvg
canBeFocused(): boolean {
return true;
}

/**
* Returns a set of all of the parent blocks of the given block.
*
* @internal
* @returns A set of the parents of the given block.
*/
getParents(): Set<BlockSvg> {
const parents = new Set<BlockSvg>();
let parent = this.getParent();
while (parent) {
parents.add(parent);
parent = parent.getParent();
}

return parents;
}

/**
* Returns a set of all of the parent blocks connected to an output of the
* given block or one of its parents. Also includes the given block.
*
* @internal
* @returns A set of the output-connected parents of the given block.
*/
getOutputParents(): Set<BlockSvg> {
const parents = new Set<BlockSvg>();
parents.add(this);
let parent = this.outputConnection?.targetBlock();
while (parent) {
parents.add(parent);
parent = parent.outputConnection?.targetBlock();
}

return parents;
}

/**
* Returns an ID for the visual "row" this block is part of.
*
* @internal
*/
getRowId(): string {
const connectedInput =
this.outputConnection?.targetConnection?.getParentInput();
// Blocks with an output value have the same ID as the input they're
// connected to.
if (connectedInput) {
return connectedInput.getRowId();
}

// All other blocks are their own row.
return this.id;
}
}
31 changes: 16 additions & 15 deletions packages/blockly/core/blockly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,13 @@ import {
import {IVariableMap} from './interfaces/i_variable_map.js';
import {IVariableModel, IVariableState} from './interfaces/i_variable_model.js';
import * as internalConstants from './internal_constants.js';
import {LineCursor} from './keyboard_nav/line_cursor.js';
import {Marker} from './keyboard_nav/marker.js';
import {ToolboxNavigator} from './keyboard_nav/navigators/toolbox_navigator.js';
import {
KeyboardNavigationController,
keyboardNavigationController,
} from './keyboard_navigation_controller.js';
import type {LayerManager} from './layer_manager.js';
import * as layers from './layers.js';
import {MarkerManager} from './marker_manager.js';
import {Menu} from './menu.js';
import {MenuItem} from './menuitem.js';
import {MetricsManager} from './metrics_manager.js';
Expand Down Expand Up @@ -439,16 +437,21 @@ Names.prototype.populateProcedures = function (
};
// clang-format on

export * from './flyout_navigator.js';
export * from './interfaces/i_navigation_policy.js';
export * from './keyboard_nav/block_navigation_policy.js';
export * from './keyboard_nav/connection_navigation_policy.js';
export * from './keyboard_nav/field_navigation_policy.js';
export * from './keyboard_nav/flyout_button_navigation_policy.js';
export * from './keyboard_nav/flyout_navigation_policy.js';
export * from './keyboard_nav/flyout_separator_navigation_policy.js';
export * from './keyboard_nav/workspace_navigation_policy.js';
export * from './navigator.js';
export * from './keyboard_nav/navigation_policies/block_comment_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/block_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/comment_bar_button_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/comment_editor_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/connection_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/field_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/flyout_button_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/flyout_separator_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/icon_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/toolbox_item_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/workspace_comment_navigation_policy.js';
export * from './keyboard_nav/navigation_policies/workspace_navigation_policy.js';
export * from './keyboard_nav/navigators/flyout_navigator.js';
export * from './keyboard_nav/navigators/navigator.js';
export * from './toast.js';

// Re-export submodules that no longer declareLegacyNamespace.
Expand All @@ -471,7 +474,6 @@ export {
DragTarget,
Events,
Extensions,
LineCursor,
Procedures,
ShortcutItems,
Themes,
Expand Down Expand Up @@ -596,8 +598,6 @@ export {
KeyboardNavigationController,
LabelFlyoutInflater,
LayerManager,
Marker,
MarkerManager,
Menu,
MenuGenerator,
MenuGeneratorFunction,
Expand All @@ -619,6 +619,7 @@ export {
Toolbox,
ToolboxCategory,
ToolboxItem,
ToolboxNavigator,
ToolboxSeparator,
Trashcan,
UnattachedFieldError,
Expand Down
10 changes: 4 additions & 6 deletions packages/blockly/core/comments/comment_editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const COMMENT_EDITOR_FOCUS_IDENTIFIER = '_comment_textarea_';

/** The part of a comment that can be typed into. */
export class CommentEditor implements IFocusableNode {
id?: string;
id: string;
/** The foreignObject containing the HTML text area. */
private foreignObject: SVGForeignObjectElement;

Expand All @@ -42,7 +42,7 @@ export class CommentEditor implements IFocusableNode {

constructor(
public workspace: WorkspaceSvg,
commentId?: string,
commentId: string,
private onFinishEditing?: () => void,
) {
this.foreignObject = dom.createSvgElement(Svg.FOREIGNOBJECT, {
Expand All @@ -67,10 +67,8 @@ export class CommentEditor implements IFocusableNode {
body.appendChild(this.textArea);
this.foreignObject.appendChild(body);

if (commentId) {
this.id = commentId + COMMENT_EDITOR_FOCUS_IDENTIFIER;
this.textArea.setAttribute('id', this.id);
}
this.id = commentId + COMMENT_EDITOR_FOCUS_IDENTIFIER;
this.textArea.setAttribute('id', this.id);

// Register browser event listeners for the user typing in the textarea.
browserEvents.conditionalBind(
Expand Down
18 changes: 12 additions & 6 deletions packages/blockly/core/field_input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import './events/events_block_change.js';

import {BlockSvg} from './block_svg.js';
import {IFocusableNode} from './blockly.js';
import * as browserEvents from './browser_events.js';
import * as bumpObjects from './bump_objects.js';
import * as dialog from './dialog.js';
Expand All @@ -28,7 +29,6 @@ import {
UnattachedFieldError,
} from './field.js';
import {getFocusManager} from './focus_manager.js';
import type {IFocusableNode} from './interfaces/i_focusable_node.js';
import {Msg} from './msg.js';
import * as renderManagement from './render_management.js';
import * as aria from './utils/aria.js';
Expand Down Expand Up @@ -600,16 +600,20 @@ export abstract class FieldInput<T extends InputTypes> extends Field<
dropDownDiv.hideWithoutAnimation();
} else if (e.key === 'Tab') {
e.preventDefault();
const cursor = this.workspace_?.getCursor();
const navigator = this.workspace_?.getNavigator();

const isValidDestination = (node: IFocusableNode | null) =>
(node instanceof FieldInput ||
(node instanceof BlockSvg && node.isSimpleReporter())) &&
node !== this.getSourceBlock();

let target = e.shiftKey
? cursor?.getPreviousNode(this, isValidDestination, false)
: cursor?.getNextNode(this, isValidDestination, false);
// eslint-disable-next-line @typescript-eslint/no-this-alias
let target: IFocusableNode | null | undefined = this;
do {
target = e.shiftKey
? navigator?.getOutNode(target)
: navigator?.getInNode(target);
} while (target && !isValidDestination(target));
target =
target instanceof BlockSvg && target.isSimpleReporter()
? target.getFields().next().value
Expand All @@ -625,7 +629,9 @@ export abstract class FieldInput<T extends InputTypes> extends Field<
targetSourceBlock instanceof BlockSvg
) {
getFocusManager().focusNode(targetSourceBlock);
} else getFocusManager().focusNode(target);
} else {
getFocusManager().focusNode(target);
}
target.showEditor();
}
}
Expand Down
88 changes: 2 additions & 86 deletions packages/blockly/core/flyout_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ import {EventType} from './events/type.js';
import * as eventUtils from './events/utils.js';
import {FlyoutItem} from './flyout_item.js';
import {FlyoutMetricsManager} from './flyout_metrics_manager.js';
import {FlyoutNavigator} from './flyout_navigator.js';
import {FlyoutSeparator, SeparatorAxis} from './flyout_separator.js';
import {IAutoHideable} from './interfaces/i_autohideable.js';
import type {IFlyout} from './interfaces/i_flyout.js';
import type {IFlyoutInflater} from './interfaces/i_flyout_inflater.js';
import {IFocusableNode} from './interfaces/i_focusable_node.js';
import type {IFocusableTree} from './interfaces/i_focusable_tree.js';
import {FlyoutNavigator} from './keyboard_nav/navigators/flyout_navigator.js';
import type {Options} from './options.js';
import * as registry from './registry.js';
import * as renderManagement from './render_management.js';
Expand All @@ -42,7 +40,7 @@ import {WorkspaceSvg} from './workspace_svg.js';
*/
export abstract class Flyout
extends DeleteArea
implements IAutoHideable, IFlyout, IFocusableNode
implements IAutoHideable, IFlyout
{
/**
* Position the flyout.
Expand Down Expand Up @@ -797,86 +795,4 @@ export abstract class Flyout

return null;
}

/**
* See IFocusableNode.getFocusableElement.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
getFocusableElement(): HTMLElement | SVGElement {
throw new Error('Flyouts are not directly focusable.');
}

/**
* See IFocusableNode.getFocusableTree.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
getFocusableTree(): IFocusableTree {
throw new Error('Flyouts are not directly focusable.');
}

/** See IFocusableNode.onNodeFocus. */
onNodeFocus(): void {}

/** See IFocusableNode.onNodeBlur. */
onNodeBlur(): void {}

/** See IFocusableNode.canBeFocused. */
canBeFocused(): boolean {
return false;
}

/**
* See IFocusableNode.getRootFocusableNode.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
getRootFocusableNode(): IFocusableNode {
throw new Error('Flyouts are not directly focusable.');
}

/**
* See IFocusableNode.getRestoredFocusableNode.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
getRestoredFocusableNode(
_previousNode: IFocusableNode | null,
): IFocusableNode | null {
throw new Error('Flyouts are not directly focusable.');
}

/**
* See IFocusableNode.getNestedTrees.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
getNestedTrees(): Array<IFocusableTree> {
throw new Error('Flyouts are not directly focusable.');
}

/**
* See IFocusableNode.lookUpFocusableNode.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
lookUpFocusableNode(_id: string): IFocusableNode | null {
throw new Error('Flyouts are not directly focusable.');
}

/** See IFocusableTree.onTreeFocus. */
onTreeFocus(
_node: IFocusableNode,
_previousTree: IFocusableTree | null,
): void {}

/**
* See IFocusableNode.onTreeBlur.
*
* @deprecated v12: Use the Flyout's workspace for focus operations, instead.
*/
onTreeBlur(_nextTree: IFocusableTree | null): void {
throw new Error('Flyouts are not directly focusable.');
}
}
7 changes: 7 additions & 0 deletions packages/blockly/core/flyout_button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,13 @@ export class FlyoutButton
canBeFocused(): boolean {
return true;
}

/**
* Returns the ID of this FlyoutButton.
*/
getId() {
return this.id;
}
}

/** CSS for buttons and labels. See css.js for use. */
Expand Down
24 changes: 0 additions & 24 deletions packages/blockly/core/flyout_navigator.ts

This file was deleted.

Loading
Loading