Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
60b7ee1
release: merge master into develop after v12.2.0
maribethb Jul 10, 2025
d5f3d15
feat: Add support for keyboard navigation to/from block comments. (#9…
gonfunko Jul 11, 2025
2c6c2e1
fix: Fix toolbox categories tests (Almost)
RoboErikG Jul 11, 2025
802d3f8
chore(deps): bump google-closure-compiler (#9233)
dependabot[bot] Jul 14, 2025
52634e4
fix: Focus the first element in flyouts. (#9228)
gonfunko Jul 14, 2025
9f66f0c
fix: Fire a `VarTypeChange` event when changing a variable's type. (#…
gonfunko Jul 14, 2025
55bd1af
Enable categories test
RoboErikG Jul 14, 2025
ec01df4
chore(deps): bump @microsoft/api-documenter from 7.26.26 to 7.26.29 (…
dependabot[bot] Jul 14, 2025
7479c2b
fix: Fix order of arguments in `IVariableMap.createVariable()`. (#9231)
gonfunko Jul 14, 2025
c1c7ddb
chore(deps): bump chai from 5.2.0 to 5.2.1 (#9235)
dependabot[bot] Jul 14, 2025
7e47bf4
Merge pull request #9238 from RoboErikG/toolbox-categories-tests
RoboErikG Jul 14, 2025
908712e
fix: Refer to correct replacement method in deprecation warning. (#9237)
gonfunko Jul 15, 2025
3c7add5
fix: Make non-autoclosing flyouts stay open. (#9245)
gonfunko Jul 18, 2025
f37e7fe
chore: fix docs generation script (#9251)
maribethb Jul 24, 2025
0de5b17
chore(deps): bump @blockly/theme-modern from 6.0.10 to 7.0.1
dependabot[bot] Jul 24, 2025
b44f7bf
Merge pull request #9207 from google/dependabot/npm_and_yarn/develop/…
RoboErikG Jul 25, 2025
c9a8221
fix: Fix displaying HTML elements in `FieldDropdown`. (#9258)
gonfunko Jul 28, 2025
c661dd1
fix: dont save ids when copying blocks and comments (#9255)
maribethb Jul 28, 2025
8a578f5
fix: Allow overriding `VariableModel` via `options.plugins`. (#9257)
gonfunko Jul 30, 2025
c037e7d
fix: Scroll `CommentBarButton`s into view on selection. (#9259)
gonfunko Jul 30, 2025
d942189
fix: Check for existing event group in cleanUp() (#9265)
michaela-mm Aug 1, 2025
71256d6
chore(deps): bump eslint-plugin-jsdoc from 51.3.1 to 52.0.2
dependabot[bot] Aug 4, 2025
5e48e0d
chore(deps): bump concurrently from 9.1.2 to 9.2.0
dependabot[bot] Aug 4, 2025
65289dd
Merge pull request #9270 from google/dependabot/npm_and_yarn/develop/…
RoboErikG Aug 4, 2025
9fc0c38
Merge pull request #9275 from google/dependabot/npm_and_yarn/develop/…
RoboErikG Aug 4, 2025
d5e347d
chore(deps): bump actions/first-interaction from 1 to 2 (#9274)
dependabot[bot] Aug 4, 2025
683a435
chore(deps): bump gulp-rename from 2.0.0 to 2.1.0 (#9277)
dependabot[bot] Aug 4, 2025
f24940e
fix: dont add comments to full block fields (#9263)
maribethb Aug 4, 2025
88151fc
fix: Display focused icons without transparency. (#9268)
gonfunko Aug 4, 2025
44e78b1
feat: Add an option to copy subsequent blocks when getting copy data …
gonfunko Aug 5, 2025
af57a3e
refactor: Make `InsertionMarkerPreviewer`'s block serialization amena…
gonfunko Aug 6, 2025
62f3b89
chore: add tests for clipboard (#9254)
maribethb Aug 6, 2025
f9d0ec9
refactor: Associate comment bar buttons with the comment view. (#9278)
gonfunko Aug 6, 2025
7d1d745
fix: Drag immovable and shadow blocks along with their parent. (#9281)
gonfunko Aug 6, 2025
2e252a4
chore(deps): bump google-github-actions/deploy-appengine (#9273)
dependabot[bot] Aug 11, 2025
79d3140
chore(deps): bump actions/download-artifact from 4 to 5 (#9287)
dependabot[bot] Aug 11, 2025
b211c02
Change browser test timeout to 2 hours
RoboErikG Aug 11, 2025
fb63360
refactor: Remove duplicated method from contextmenu_items.ts. (#9289)
gonfunko Aug 12, 2025
e74910c
Update block-test version
RoboErikG Aug 12, 2025
4f4a450
Update dev-tools version in package.json
RoboErikG Aug 13, 2025
fba2231
Merge branch 'google:develop' into browser-test-2
RoboErikG Aug 13, 2025
7b784b5
Add a weekly schedule
RoboErikG Aug 13, 2025
34ea176
Update package-lock.json
RoboErikG Aug 13, 2025
d7efb28
Merge pull request #9297 from RoboErikG/browser-test-2
RoboErikG Aug 13, 2025
414f105
chore(deps): bump actions/first-interaction from 2 to 3
dependabot[bot] Aug 18, 2025
ef235cf
Merge pull request #9323 from google/dependabot/github_actions/develo…
RoboErikG Aug 18, 2025
a53db40
release: Merge branch 'develop' into rc/v12.3.0
gonfunko Aug 18, 2025
86da7dc
release: Update version number to 12.3.0-beta.0
gonfunko Aug 21, 2025
84933b9
chore: lint error on only in mocha tests (#9300)
maribethb Aug 19, 2025
29d5b43
chore(deps): bump actions/checkout from 4 to 5 (#9320)
dependabot[bot] Aug 19, 2025
10b1d1e
fix: Fix positioning of pasted blocks and comments in RTL. (#9302)
gonfunko Aug 19, 2025
9e1db9e
chore: Fix documentation generation warnings. (#9325)
gonfunko Aug 19, 2025
4a0b710
fix: Show the delete cursor when dragging a block by an editable fiel…
gonfunko Aug 20, 2025
cf93f07
fix: Correct the alignment of narrow text in input fields. (#9327)
gonfunko Aug 21, 2025
4891659
fix: Fix bug that caused inadvertent scrolling when the `WidgetDiv` w…
gonfunko Aug 21, 2025
c32f6db
chore(deps): bump eslint-plugin-prettier from 5.5.1 to 5.5.4 (#9319)
dependabot[bot] Aug 21, 2025
be5f5a2
fix: pointercancel event is not handled (#9250)
nianxy Aug 21, 2025
e358f4e
chore(deps): bump eslint-config-prettier from 10.1.5 to 10.1.8 (#9321)
dependabot[bot] Aug 22, 2025
cb69892
fix: Allow reregistering fields. (#9290)
gonfunko Aug 22, 2025
aeb3e5e
chore(deps): bump chai from 5.2.1 to 6.0.1 (#9330)
dependabot[bot] Aug 26, 2025
90580a8
chore(deps): bump eslint from 9.30.0 to 9.34.0 (#9329)
dependabot[bot] Aug 27, 2025
f10454c
chore: Add node.js v24 to CI build matrix (#9219)
cpcallen Aug 27, 2025
b0569c4
fix: Prevent mocha tests failures when window does not have focus. (#…
gonfunko Aug 27, 2025
e51efe4
fix: Fix bug that could cause errant line when rendering. (#9333)
gonfunko Aug 28, 2025
5afc0d6
refactor: Make focusable elements responsible for scrolling themselve…
gonfunko Aug 28, 2025
5f21e9b
release: Update version number to 12.3.0
gonfunko Aug 28, 2025
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
6 changes: 3 additions & 3 deletions .github/workflows/appengine_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
steps:
# Checks-out the repository under $GITHUB_WORKSPACE.
# When running manually this checks out the master branch.
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Prepare demo files
# Install all dependencies, then copy all the files needed for demos.
Expand All @@ -36,13 +36,13 @@ jobs:
needs: prepare
steps:
- name: Download prepared files
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: appengine_files
path: _deploy/

- name: Deploy to App Engine
uses: google-github-actions/deploy-appengine@v2.1.5
uses: google-github-actions/deploy-appengine@v2.1.7
# For parameters see:
# https://github.com/google-github-actions/deploy-appengine#inputs
with:
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/browser_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ name: Run browser manually

on:
workflow_dispatch:
schedule:
- cron: '0 6 * * 1' # Runs every Monday at 06:00 UTC

permissions:
contents: read

jobs:
build:
timeout-minutes: 10
timeout-minutes: 120
runs-on: ${{ matrix.os }}

strategy:
Expand All @@ -24,7 +26,7 @@ jobs:
# https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
persist-credentials: false

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ jobs:
# TODO (#2114): re-enable osx build.
# os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest]
node-version: [18.x, 20.x, 22.x]
node-version: [18.x, 20.x, 22.x, 24.x]
# See supported Node.js release schedule at
# https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
persist-credentials: false

Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Use Node.js 20.x
uses: actions/setup-node@v4
Expand All @@ -71,7 +71,7 @@ jobs:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Use Node.js 20.x
uses: actions/setup-node@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/keyboard_plugin_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ jobs:

steps:
- name: Checkout core Blockly
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
path: core-blockly

- name: Checkout keyboard navigation plugin
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
repository: 'google/blockly-keyboard-experimentation'
ref: 'main'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/welcome_new_contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: actions/first-interaction@v1
- uses: actions/first-interaction@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: >
Expand Down
46 changes: 28 additions & 18 deletions core/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,22 +501,32 @@ export class Block {
// Detach this block from the parent's tree.
this.previousConnection.disconnect();
}
const nextBlock = this.getNextBlock();
if (opt_healStack && nextBlock && !nextBlock.isShadow()) {
// Disconnect the next statement.
const nextTarget = this.nextConnection?.targetConnection ?? null;
nextTarget?.disconnect();
if (
previousTarget &&
this.workspace.connectionChecker.canConnect(
previousTarget,
nextTarget,
false,
)
) {
// Attach the next statement to the previous statement.
previousTarget.connect(nextTarget!);
}

if (!opt_healStack) return;

// Immovable or shadow next blocks need to move along with the block; keep
// going until we encounter a normal block or run off the end of the stack.
let nextBlock = this.getNextBlock();
while (nextBlock && (nextBlock.isShadow() || !nextBlock.isMovable())) {
nextBlock = nextBlock.getNextBlock();
}
if (!nextBlock) return;

// Disconnect the next statement.
const nextTarget =
nextBlock.previousConnection?.targetBlock()?.nextConnection
?.targetConnection ?? null;
nextTarget?.disconnect();
if (
previousTarget &&
this.workspace.connectionChecker.canConnect(
previousTarget,
nextTarget,
false,
)
) {
// Attach the next statement to the previous statement.
previousTarget.connect(nextTarget!);
}
}

Expand Down Expand Up @@ -1116,9 +1126,9 @@ export class Block {
/**
* Returns a generator that provides every field on the block.
*
* @yields A generator that can be used to iterate the fields on the block.
* @returns A generator that can be used to iterate the fields on the block.
*/
*getFields(): Generator<Field> {
*getFields(): Generator<Field, undefined, void> {
for (const input of this.inputList) {
for (const field of input.fieldRow) {
yield field;
Expand Down
11 changes: 9 additions & 2 deletions core/block_svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,17 +951,21 @@ export class BlockSvg
/**
* Encode a block for copying.
*
* @param addNextBlocks If true, copy subsequent blocks attached to this one
* as well.
*
* @returns Copy metadata, or null if the block is an insertion marker.
*/
toCopyData(): BlockCopyData | null {
toCopyData(addNextBlocks = false): BlockCopyData | null {
if (this.isInsertionMarker_) {
return null;
}
return {
paster: BlockPaster.TYPE,
blockState: blocks.save(this, {
addCoordinates: true,
addNextBlocks: false,
addNextBlocks,
saveIds: false,
}) as blocks.State,
typeCounts: common.getBlockTypeCounts(this, true),
};
Expand Down Expand Up @@ -1840,6 +1844,9 @@ export class BlockSvg
/** See IFocusableNode.onNodeFocus. */
onNodeFocus(): void {
this.select();
this.workspace.scrollBoundsIntoView(
this.getBoundingRectangleWithoutChildren(),
);
}

/** See IFocusableNode.onNodeBlur. */
Expand Down
37 changes: 36 additions & 1 deletion core/bubbles/bubble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import * as common from '../common.js';
import {BubbleDragStrategy} from '../dragging/bubble_drag_strategy.js';
import {getFocusManager} from '../focus_manager.js';
import {IBubble} from '../interfaces/i_bubble.js';
import type {IFocusableNode} from '../interfaces/i_focusable_node.js';
import type {IFocusableTree} from '../interfaces/i_focusable_tree.js';
import type {IHasBubble} from '../interfaces/i_has_bubble.js';
import {ISelectable} from '../interfaces/i_selectable.js';
import {ContainerRegion} from '../metrics_manager.js';
import {Scrollbar} from '../scrollbar.js';
Expand All @@ -27,7 +29,7 @@ import {WorkspaceSvg} from '../workspace_svg.js';
* bubble, where it has a "tail" that points to the block, and a "head" that
* displays arbitrary svg elements.
*/
export abstract class Bubble implements IBubble, ISelectable {
export abstract class Bubble implements IBubble, ISelectable, IFocusableNode {
/** The width of the border around the bubble. */
static readonly BORDER_WIDTH = 6;

Expand Down Expand Up @@ -100,12 +102,14 @@ export abstract class Bubble implements IBubble, ISelectable {
* element that's represented by this bubble (as a focusable node). This
* element will have its ID overwritten. If not provided, the focusable
* element of this node will default to the bubble's SVG root.
* @param owner The object responsible for hosting/spawning this bubble.
*/
constructor(
public readonly workspace: WorkspaceSvg,
protected anchor: Coordinate,
protected ownerRect?: Rect,
overriddenFocusableElement?: SVGElement | HTMLElement,
protected owner?: IHasBubble & IFocusableNode,
) {
this.id = idGenerator.getNextUniqueId();
this.svgRoot = dom.createSvgElement(
Expand Down Expand Up @@ -145,6 +149,13 @@ export abstract class Bubble implements IBubble, ISelectable {
this,
this.onMouseDown,
);

browserEvents.conditionalBind(
this.focusableElement,
'keydown',
this,
this.onKeyDown,
);
}

/** Dispose of this bubble. */
Expand Down Expand Up @@ -229,6 +240,19 @@ export abstract class Bubble implements IBubble, ISelectable {
getFocusManager().focusNode(this);
}

/**
* Handles key events when this bubble is focused. By default, closes the
* bubble on Escape.
*
* @param e The keyboard event to handle.
*/
protected onKeyDown(e: KeyboardEvent) {
if (e.key === 'Escape' && this.owner) {
this.owner.setBubbleVisible(false);
getFocusManager().focusNode(this.owner);
}
}

/** Positions the bubble relative to its anchor. Does not render its tail. */
protected positionRelativeToAnchor() {
let left = this.anchor.x;
Expand Down Expand Up @@ -683,6 +707,10 @@ export abstract class Bubble implements IBubble, ISelectable {
onNodeFocus(): void {
this.select();
this.bringToFront();
const xy = this.getRelativeToSurfaceXY();
const size = this.getSize();
const bounds = new Rect(xy.y, xy.y + size.height, xy.x, xy.x + size.width);
this.workspace.scrollBoundsIntoView(bounds);
}

/** See IFocusableNode.onNodeBlur. */
Expand All @@ -694,4 +722,11 @@ export abstract class Bubble implements IBubble, ISelectable {
canBeFocused(): boolean {
return true;
}

/**
* Returns the object that owns/hosts this bubble, if any.
*/
getOwner(): (IHasBubble & IFocusableNode) | undefined {
return this.owner;
}
}
Loading
Loading