From 6b4b3f2b51af4c142593d146051bdae3c5df2c10 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Wed, 24 Jun 2026 16:39:33 -0700 Subject: [PATCH 01/32] Update to Blockly 12.5.1 --- appinventor/lib/blockly/@types/block.d.ts | 32 +- .../blockly/@types/block_flyout_inflater.d.ts | 94 + appinventor/lib/blockly/@types/block_svg.d.ts | 107 +- appinventor/lib/blockly/@types/blockly.d.ts | 40 +- .../lib/blockly/@types/browser_events.d.ts | 10 +- .../lib/blockly/@types/bubbles/bubble.d.ts | 42 +- .../@types/bubbles/textinput_bubble.d.ts | 42 +- .../@types/button_flyout_inflater.d.ts | 42 + appinventor/lib/blockly/@types/clipboard.d.ts | 95 +- appinventor/lib/blockly/@types/comments.d.ts | 4 + .../comments/collapse_comment_bar_button.d.ts | 52 + .../@types/comments/comment_bar_button.d.ts | 62 + .../@types/comments/comment_editor.d.ts | 62 + .../blockly/@types/comments/comment_view.d.ts | 76 +- .../comments/delete_comment_bar_button.d.ts | 52 + .../comments/rendered_workspace_comment.d.ts | 27 +- appinventor/lib/blockly/@types/common.d.ts | 34 +- .../lib/blockly/@types/connection.d.ts | 7 +- .../lib/blockly/@types/contextmenu.d.ts | 13 +- .../blockly/@types/contextmenu_registry.d.ts | 97 +- appinventor/lib/blockly/@types/dialog.d.ts | 52 +- .../@types/dragging/block_drag_strategy.d.ts | 25 +- .../@types/dragging/bubble_drag_strategy.d.ts | 2 - .../dragging/comment_drag_strategy.d.ts | 2 - .../lib/blockly/@types/dropdowndiv.d.ts | 20 +- .../lib/blockly/@types/events/events.d.ts | 3 +- .../@types/events/events_marker_move.d.ts | 69 - .../@types/events/events_var_base.d.ts | 4 +- .../@types/events/events_var_create.d.ts | 9 +- .../@types/events/events_var_delete.d.ts | 6 +- .../@types/events/events_var_rename.d.ts | 6 +- .../@types/events/events_var_type_change.d.ts | 55 + .../lib/blockly/@types/events/predicates.d.ts | 3 - .../lib/blockly/@types/events/type.d.ts | 2 + .../lib/blockly/@types/events/utils.d.ts | 6 +- appinventor/lib/blockly/@types/field.d.ts | 84 +- .../lib/blockly/@types/field_checkbox.d.ts | 4 - .../lib/blockly/@types/field_dropdown.d.ts | 34 +- .../lib/blockly/@types/field_image.d.ts | 8 +- .../lib/blockly/@types/field_input.d.ts | 31 +- .../lib/blockly/@types/field_number.d.ts | 6 + .../lib/blockly/@types/field_registry.d.ts | 4 +- .../lib/blockly/@types/field_textinput.d.ts | 1 + .../lib/blockly/@types/field_variable.d.ts | 19 +- .../lib/blockly/@types/flyout_base.d.ts | 286 +- .../lib/blockly/@types/flyout_button.d.ts | 60 +- .../lib/blockly/@types/flyout_horizontal.d.ts | 8 +- .../lib/blockly/@types/flyout_item.d.ts | 26 + .../lib/blockly/@types/flyout_navigator.d.ts | 11 + .../lib/blockly/@types/flyout_separator.d.ts | 64 + .../lib/blockly/@types/flyout_vertical.d.ts | 10 +- .../lib/blockly/@types/focus_manager.d.ts | 266 ++ appinventor/lib/blockly/@types/gesture.d.ts | 5 - appinventor/lib/blockly/@types/grid.d.ts | 5 +- .../blockly/@types/icons/comment_icon.d.ts | 20 +- .../lib/blockly/@types/icons/icon.d.ts | 23 +- .../blockly/@types/icons/mutator_icon.d.ts | 3 + .../blockly/@types/icons/warning_icon.d.ts | 3 + .../@types/insertion_marker_manager.d.ts | 249 -- .../@types/insertion_marker_previewer.d.ts | 11 + .../interfaces/i_ast_node_location.d.ts | 11 - .../interfaces/i_ast_node_location_svg.d.ts | 24 - .../i_ast_node_location_with_block.d.ts | 19 - .../@types/interfaces/i_autohideable.d.ts | 2 + .../blockly/@types/interfaces/i_bubble.d.ts | 3 +- .../@types/interfaces/i_comment_icon.d.ts | 5 +- .../@types/interfaces/i_contextmenu.d.ts | 2 + .../blockly/@types/interfaces/i_copyable.d.ts | 9 +- .../blockly/@types/interfaces/i_flyout.d.ts | 5 +- .../@types/interfaces/i_flyout_inflater.d.ts | 48 + .../@types/interfaces/i_focusable_node.d.ts | 105 + .../@types/interfaces/i_focusable_tree.d.ts | 125 + .../@types/interfaces/i_has_bubble.d.ts | 13 + .../lib/blockly/@types/interfaces/i_icon.d.ts | 3 +- .../interfaces/i_legacy_procedure_blocks.d.ts | 4 +- .../@types/interfaces/i_metrics_manager.d.ts | 2 +- .../interfaces/i_navigation_policy.d.ts | 63 + .../@types/interfaces/i_rendered_element.d.ts | 5 +- .../@types/interfaces/i_selectable.d.ts | 10 +- .../blockly/@types/interfaces/i_toolbox.d.ts | 12 +- .../@types/interfaces/i_toolbox_item.d.ts | 3 +- .../i_variable_backed_parameter_model.d.ts | 4 +- .../@types/interfaces/i_variable_map.d.ts | 48 + .../@types/interfaces/i_variable_model.d.ts | 36 + .../blockly/@types/keyboard_nav/ast_node.d.ts | 297 -- .../@types/keyboard_nav/basic_cursor.d.ts | 96 - .../block_comment_navigation_policy.d.ts | 56 + .../keyboard_nav/block_navigation_policy.d.ts | 84 + .../comment_bar_button_navigation_policy.d.ts | 56 + .../comment_editor_navigation_policy.d.ts | 34 + .../connection_navigation_policy.d.ts | 67 + .../blockly/@types/keyboard_nav/cursor.d.ts | 44 - .../keyboard_nav/field_navigation_policy.d.ts | 56 + .../flyout_button_navigation_policy.d.ts | 56 + .../flyout_navigation_policy.d.ts | 65 + .../flyout_separator_navigation_policy.d.ts | 33 + .../keyboard_nav/icon_navigation_policy.d.ts | 56 + .../@types/keyboard_nav/line_cursor.d.ts | 187 ++ .../blockly/@types/keyboard_nav/marker.d.ts | 52 +- .../keyboard_nav/tab_navigate_cursor.d.ts | 20 - .../workspace_comment_navigation_policy.d.ts | 56 + .../workspace_navigation_policy.d.ts | 56 + .../keyboard_navigation_controller.d.ts | 48 + .../blockly/@types/label_flyout_inflater.d.ts | 42 + .../lib/blockly/@types/layer_manager.d.ts | 20 +- .../lib/blockly/@types/marker_manager.d.ts | 32 +- appinventor/lib/blockly/@types/menu.d.ts | 21 +- .../lib/blockly/@types/menu_separator.d.ts | 25 + appinventor/lib/blockly/@types/menuitem.d.ts | 15 +- .../lib/blockly/@types/metrics_manager.d.ts | 2 +- appinventor/lib/blockly/@types/names.d.ts | 10 +- appinventor/lib/blockly/@types/navigator.d.ts | 65 + .../lib/blockly/@types/procedures.d.ts | 11 +- appinventor/lib/blockly/@types/registry.d.ts | 10 +- .../blockly/@types/rendered_connection.d.ts | 28 +- .../renderers/common/block_rendering.d.ts | 3 +- .../@types/renderers/common/constants.d.ts | 7 +- .../@types/renderers/common/drawer.d.ts | 2 +- .../renderers/common/i_path_object.d.ts | 52 +- .../@types/renderers/common/marker_svg.d.ts | 256 -- .../@types/renderers/common/path_object.d.ts | 27 +- .../@types/renderers/common/renderer.d.ts | 42 +- .../@types/renderers/geras/renderer.d.ts | 2 +- .../renderers/measurables/in_row_spacer.d.ts | 1 + .../renderers/measurables/jagged_edge.d.ts | 1 + .../measurables/next_connection.d.ts | 1 + .../measurables/previous_connection.d.ts | 1 + .../renderers/measurables/round_corner.d.ts | 1 + .../renderers/measurables/square_corner.d.ts | 1 + .../measurables/statement_input.d.ts | 1 + .../@types/renderers/measurables/types.d.ts | 73 +- .../@types/renderers/zelos/constants.d.ts | 10 +- .../@types/renderers/zelos/drawer.d.ts | 2 +- .../@types/renderers/zelos/marker_svg.d.ts | 49 - .../@types/renderers/zelos/path_object.d.ts | 3 +- .../@types/renderers/zelos/renderer.d.ts | 18 - .../blockly/@types/renderers/zelos/zelos.d.ts | 3 +- .../@types/separator_flyout_inflater.d.ts | 57 + .../@types/serialization/variables.d.ts | 13 +- .../lib/blockly/@types/shortcut_items.d.ts | 7 +- .../lib/blockly/@types/shortcut_registry.d.ts | 9 +- appinventor/lib/blockly/@types/toast.d.ts | 74 + .../lib/blockly/@types/toolbox/toolbox.d.ts | 37 +- .../blockly/@types/toolbox/toolbox_item.d.ts | 11 + .../lib/blockly/@types/utils/aria.d.ts | 8 +- .../utils/focusable_tree_traverser.d.ts | 53 + .../lib/blockly/@types/utils/keycodes.d.ts | 3 +- .../lib/blockly/@types/utils/object.d.ts | 3 + .../lib/blockly/@types/utils/rect.d.ts | 9 + .../lib/blockly/@types/utils/toolbox.d.ts | 2 - .../lib/blockly/@types/variable_map.d.ts | 65 +- .../lib/blockly/@types/variable_model.d.ts | 48 +- appinventor/lib/blockly/@types/variables.d.ts | 72 +- .../lib/blockly/@types/variables_dynamic.d.ts | 12 +- appinventor/lib/blockly/@types/widgetdiv.d.ts | 11 +- appinventor/lib/blockly/@types/workspace.d.ts | 68 +- .../lib/blockly/@types/workspace_audio.d.ts | 23 +- .../lib/blockly/@types/workspace_dragger.d.ts | 11 +- .../lib/blockly/@types/workspace_svg.d.ts | 234 +- appinventor/lib/blockly/@types/xml.d.ts | 4 +- appinventor/lib/blockly/blockly_compressed.js | 2694 +++++++++-------- appinventor/lib/blockly/media/click.ogg | Bin 4865 -> 0 bytes appinventor/lib/blockly/media/click.wav | Bin 3782 -> 0 bytes appinventor/lib/blockly/media/delete.ogg | Bin 5731 -> 0 bytes appinventor/lib/blockly/media/delete.wav | Bin 9164 -> 0 bytes appinventor/lib/blockly/media/disconnect.ogg | Bin 4404 -> 0 bytes appinventor/lib/blockly/media/disconnect.wav | Bin 1492 -> 0 bytes appinventor/lib/blockly/msg/json/en.json | 99 +- 168 files changed, 5474 insertions(+), 3465 deletions(-) create mode 100644 appinventor/lib/blockly/@types/block_flyout_inflater.d.ts create mode 100644 appinventor/lib/blockly/@types/button_flyout_inflater.d.ts create mode 100644 appinventor/lib/blockly/@types/comments/collapse_comment_bar_button.d.ts create mode 100644 appinventor/lib/blockly/@types/comments/comment_bar_button.d.ts create mode 100644 appinventor/lib/blockly/@types/comments/comment_editor.d.ts create mode 100644 appinventor/lib/blockly/@types/comments/delete_comment_bar_button.d.ts delete mode 100644 appinventor/lib/blockly/@types/events/events_marker_move.d.ts create mode 100644 appinventor/lib/blockly/@types/events/events_var_type_change.d.ts create mode 100644 appinventor/lib/blockly/@types/flyout_item.d.ts create mode 100644 appinventor/lib/blockly/@types/flyout_navigator.d.ts create mode 100644 appinventor/lib/blockly/@types/flyout_separator.d.ts create mode 100644 appinventor/lib/blockly/@types/focus_manager.d.ts delete mode 100644 appinventor/lib/blockly/@types/insertion_marker_manager.d.ts delete mode 100644 appinventor/lib/blockly/@types/interfaces/i_ast_node_location.d.ts delete mode 100644 appinventor/lib/blockly/@types/interfaces/i_ast_node_location_svg.d.ts delete mode 100644 appinventor/lib/blockly/@types/interfaces/i_ast_node_location_with_block.d.ts create mode 100644 appinventor/lib/blockly/@types/interfaces/i_flyout_inflater.d.ts create mode 100644 appinventor/lib/blockly/@types/interfaces/i_focusable_node.d.ts create mode 100644 appinventor/lib/blockly/@types/interfaces/i_focusable_tree.d.ts create mode 100644 appinventor/lib/blockly/@types/interfaces/i_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/interfaces/i_variable_map.d.ts create mode 100644 appinventor/lib/blockly/@types/interfaces/i_variable_model.d.ts delete mode 100644 appinventor/lib/blockly/@types/keyboard_nav/ast_node.d.ts delete mode 100644 appinventor/lib/blockly/@types/keyboard_nav/basic_cursor.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/block_comment_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/block_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/comment_bar_button_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/comment_editor_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/connection_navigation_policy.d.ts delete mode 100644 appinventor/lib/blockly/@types/keyboard_nav/cursor.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/field_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/flyout_button_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/flyout_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/flyout_separator_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/icon_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/line_cursor.d.ts delete mode 100644 appinventor/lib/blockly/@types/keyboard_nav/tab_navigate_cursor.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/workspace_comment_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_nav/workspace_navigation_policy.d.ts create mode 100644 appinventor/lib/blockly/@types/keyboard_navigation_controller.d.ts create mode 100644 appinventor/lib/blockly/@types/label_flyout_inflater.d.ts create mode 100644 appinventor/lib/blockly/@types/menu_separator.d.ts create mode 100644 appinventor/lib/blockly/@types/navigator.d.ts delete mode 100644 appinventor/lib/blockly/@types/renderers/common/marker_svg.d.ts delete mode 100644 appinventor/lib/blockly/@types/renderers/zelos/marker_svg.d.ts create mode 100644 appinventor/lib/blockly/@types/separator_flyout_inflater.d.ts create mode 100644 appinventor/lib/blockly/@types/toast.d.ts create mode 100644 appinventor/lib/blockly/@types/utils/focusable_tree_traverser.d.ts delete mode 100644 appinventor/lib/blockly/media/click.ogg delete mode 100644 appinventor/lib/blockly/media/click.wav delete mode 100644 appinventor/lib/blockly/media/delete.ogg delete mode 100644 appinventor/lib/blockly/media/delete.wav delete mode 100644 appinventor/lib/blockly/media/disconnect.ogg delete mode 100644 appinventor/lib/blockly/media/disconnect.wav diff --git a/appinventor/lib/blockly/@types/block.d.ts b/appinventor/lib/blockly/@types/block.d.ts index 9ac16640233..894bf21863a 100644 --- a/appinventor/lib/blockly/@types/block.d.ts +++ b/appinventor/lib/blockly/@types/block.d.ts @@ -18,18 +18,17 @@ import type { Field } from './field.js'; import { IconType } from './icons/icon_types.js'; import type { MutatorIcon } from './icons/mutator_icon.js'; import { Input } from './inputs/input.js'; -import type { IASTNodeLocation } from './interfaces/i_ast_node_location.js'; import { type IIcon } from './interfaces/i_icon.js'; +import type { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import * as Tooltip from './tooltip.js'; import { Coordinate } from './utils/coordinate.js'; import { Size } from './utils/size.js'; -import type { VariableModel } from './variable_model.js'; import type { Workspace } from './workspace.js'; /** * Class for one block. * Not normally called directly, workspace.newBlock() is preferred. */ -export declare class Block implements IASTNodeLocation { +export declare class Block { /** * An optional callback method to use whenever the block's parent workspace * changes. This is usually only called from the constructor, the block type @@ -540,6 +539,12 @@ export declare class Block implements IASTNodeLocation { * @returns Named field, or null if field does not exist. */ getField(name: string): Field | null; + /** + * Returns a generator that provides every field on the block. + * + * @returns A generator that can be used to iterate the fields on the block. + */ + getFields(): Generator; /** * Return all variables referenced by this block. * @@ -552,7 +557,7 @@ export declare class Block implements IASTNodeLocation { * @returns List of variable models. * @internal */ - getVarModels(): VariableModel[]; + getVarModels(): IVariableModel[]; /** * Notification that a variable is renaming but keeping the same ID. If the * variable is in use on this block, rerender to show the new name. @@ -560,7 +565,7 @@ export declare class Block implements IASTNodeLocation { * @param variable The variable being renamed. * @internal */ - updateVarName(variable: VariableModel): void; + updateVarName(variable: IVariableModel): void; /** * Notification that a variable is renaming. * If the ID matches one of this block's variables, rename it. @@ -641,21 +646,6 @@ export declare class Block implements IASTNodeLocation { * @returns True if enabled. */ isEnabled(): boolean; - /** @deprecated v11 - Get whether the block is manually disabled. */ - private get disabled(); - /** @deprecated v11 - Set whether the block is manually disabled. */ - private set disabled(value); - /** - * @deprecated v11 - Set whether the block is manually enabled or disabled. - * The user can toggle whether a block is disabled from a context menu - * option. A block may still be disabled for other reasons even if the user - * attempts to manually enable it, such as when the block is in an invalid - * location. This method is deprecated and setDisabledReason should be used - * instead. - * - * @param enabled True if enabled. - */ - setEnabled(enabled: boolean): void; /** * Add or remove a reason why the block might be disabled. If a block has * any reasons to be disabled, then the block itself will be considered @@ -999,7 +989,7 @@ export declare class Block implements IASTNodeLocation { * * Intended to on be used in console logs and errors. If you need a string * that uses the user's native language (including block text, field values, - * and child blocks), use [toString()]{@link Block#toString}. + * and child blocks), use {@link (Block:class).toString | toString()}. * * @returns The description. */ diff --git a/appinventor/lib/blockly/@types/block_flyout_inflater.d.ts b/appinventor/lib/blockly/@types/block_flyout_inflater.d.ts new file mode 100644 index 00000000000..d6761627591 --- /dev/null +++ b/appinventor/lib/blockly/@types/block_flyout_inflater.d.ts @@ -0,0 +1,94 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { BlockSvg } from './block_svg.js'; +import * as browserEvents from './browser_events.js'; +import { FlyoutItem } from './flyout_item.js'; +import type { IFlyout } from './interfaces/i_flyout.js'; +import type { IFlyoutInflater } from './interfaces/i_flyout_inflater.js'; +import type { BlockInfo } from './utils/toolbox.js'; +import type { WorkspaceSvg } from './workspace_svg.js'; +/** + * Class responsible for creating blocks for flyouts. + */ +export declare class BlockFlyoutInflater implements IFlyoutInflater { + protected permanentlyDisabledBlocks: Set; + protected listeners: Map; + protected flyout?: IFlyout; + private capacityWrapper; + /** + * Creates a new BlockFlyoutInflater instance. + */ + constructor(); + /** + * Inflates a flyout block from the given state and adds it to the flyout. + * + * @param state A JSON representation of a flyout block. + * @param flyout The flyout to create the block on. + * @returns A newly created block. + */ + load(state: object, flyout: IFlyout): FlyoutItem; + /** + * Creates a block on the given workspace. + * + * @param blockDefinition A JSON representation of the block to create. + * @param workspace The workspace to create the block on. + * @returns The newly created block. + */ + createBlock(blockDefinition: BlockInfo, workspace: WorkspaceSvg): BlockSvg; + /** + * Returns the amount of space that should follow this block. + * + * @param state A JSON representation of a flyout block. + * @param defaultGap The default spacing for flyout items. + * @returns The amount of space that should follow this block. + */ + gapForItem(state: object, defaultGap: number): number; + /** + * Disposes of the given block. + * + * @param item The flyout block to dispose of. + */ + disposeItem(item: FlyoutItem): void; + /** + * Removes event listeners for the block with the given ID. + * + * @param blockId The ID of the block to remove event listeners from. + */ + protected removeListeners(blockId: string): void; + /** + * Updates this inflater's flyout. + * + * @param flyout The flyout that owns this inflater. + */ + protected setFlyout(flyout: IFlyout): void; + /** + * Updates the enabled state of the given block based on the capacity of the + * workspace. + * + * @param block The block to update the enabled/disabled state of. + */ + private updateStateBasedOnCapacity; + /** + * Add listeners to a block that has been added to the flyout. + * + * @param block The block to add listeners for. + */ + protected addBlockListeners(block: BlockSvg): void; + /** + * Updates the state of blocks in our owning flyout to be disabled/enabled + * based on the capacity of the workspace for more blocks of that type. + * + * @param event The event that triggered this update. + */ + private filterFlyoutBasedOnCapacity; + /** + * Returns the type of items this inflater is responsible for creating. + * + * @returns An identifier for the type of items this inflater creates. + */ + getType(): string; +} +//# sourceMappingURL=block_flyout_inflater.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/block_svg.d.ts b/appinventor/lib/blockly/@types/block_svg.d.ts index 3f92b169860..7dcaea35833 100644 --- a/appinventor/lib/blockly/@types/block_svg.d.ts +++ b/appinventor/lib/blockly/@types/block_svg.d.ts @@ -10,19 +10,20 @@ */ import './events/events_selected.js'; import { Block } from './block.js'; -import { IDeletable } from './blockly.js'; import { BlockCopyData } from './clipboard/block_paster.js'; import type { Connection } from './connection.js'; import { ConnectionType } from './connection_type.js'; import { ContextMenuOption, LegacyContextMenuOption } from './contextmenu_registry.js'; -import type { Field } from './field.js'; import { IconType } from './icons/icon_types.js'; import { MutatorIcon } from './icons/mutator_icon.js'; import type { Input } from './inputs/input.js'; -import type { IASTNodeLocationSvg } from './interfaces/i_ast_node_location_svg.js'; import type { IBoundedElement } from './interfaces/i_bounded_element.js'; +import { IContextMenu } from './interfaces/i_contextmenu.js'; import type { ICopyable } from './interfaces/i_copyable.js'; +import { IDeletable } from './interfaces/i_deletable.js'; import type { IDragStrategy, IDraggable } from './interfaces/i_draggable.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; import { IIcon } from './interfaces/i_icon.js'; import { RenderedConnection } from './rendered_connection.js'; import type { IPathObject } from './renderers/common/i_path_object.js'; @@ -36,7 +37,7 @@ import type { WorkspaceSvg } from './workspace_svg.js'; * Class for a block's SVG representation. * Not normally called directly, workspace.newBlock() is preferred. */ -export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBoundedElement, ICopyable, IDraggable, IDeletable { +export declare class BlockSvg extends Block implements IBoundedElement, IContextMenu, ICopyable, IDraggable, IDeletable, IFocusableNode { /** * Constant for identifying rows that are to be rendered inline. * Don't collide with Blockly.inputTypes. @@ -227,18 +228,17 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * @param collapsed True if collapsed. */ setCollapsed(collapsed: boolean): void; + /** + * Traverses child blocks to see if any of them have a warning. + * + * @returns true if any child has a warning, false otherwise. + */ + private childHasWarning; /** * Makes sure that when the block is collapsed, it is rendered correctly * for that state. */ private updateCollapsed; - /** - * Open the next (or previous) FieldTextInput. - * - * @param start Current field. - * @param forward If true go forward, otherwise backward. - */ - tab(start: Field, forward: boolean): void; /** * Handle a pointerdown on an SVG block. * @@ -256,14 +256,20 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * * @returns Context menu options or null if no menu. */ - protected generateContextMenu(): Array | null; + protected generateContextMenu(e: Event): Array | null; + /** + * Gets the location in which to show the context menu for this block. + * Use the location of a click if the block was clicked, or a location + * based on the block's fields otherwise. + */ + protected calculateContextMenuLocation(e: Event): Coordinate; /** * Show the context menu for this block. * * @param e Mouse event. * @internal */ - showContextMenu(e: PointerEvent): void; + showContextMenu(e: Event): void; /** * Updates the locations of any parts of the block that need to know where * they are (e.g. connections, icons). @@ -275,6 +281,18 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou private updateConnectionLocations; private updateIconLocations; private updateFieldLocations; + /** + * Add a CSS class to the SVG group of this block. + * + * @param className + */ + addClass(className: string): void; + /** + * Remove a CSS class from the SVG group of this block. + * + * @param className + */ + removeClass(className: string): void; /** * Recursively adds or removes the dragging class to this node and its * children. @@ -318,6 +336,10 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * @returns The root SVG node (probably a group). */ getSvgRoot(): SVGGElement; + /** + * Returns the closest live block to this one, if any. + */ + private getNearestNeighbour; /** * Dispose of this block. * @@ -343,9 +365,12 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou /** * 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?: boolean): BlockCopyData | null; /** * Updates the colour of the block to match the block's state. * @@ -380,17 +405,6 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou */ private createIconPointerDownListener; removeIcon(type: IconType): boolean; - /** - * @deprecated v11 - Set whether the block is manually enabled or disabled. - * The user can toggle whether a block is disabled from a context menu - * option. A block may still be disabled for other reasons even if the user - * attempts to manually enable it, such as when the block is in an invalid - * location. This method is deprecated and setDisabledReason should be used - * instead. - * - * @param enabled True if enabled. - */ - setEnabled(enabled: boolean): void; /** * Add or remove a reason why the block might be disabled. If a block has * any reasons to be disabled, then the block itself will be considered @@ -406,6 +420,11 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * update whether the block is currently disabled for this reason. */ setDisabledReason(disabled: boolean, reason: string): void; + /** + * Add blocklyNotDeletable class when block is not deletable + * Or remove class when block is deletable + */ + setDeletable(deletable: boolean): void; /** * Set whether the block is highlighted or not. Block highlighting is * often used to visually mark blocks currently being executed. @@ -649,24 +668,6 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * @internal */ tightenChildrenEfficiently(): void; - /** Redraw any attached marker or cursor svgs if needed. */ - protected updateMarkers_(): void; - /** - * Add the cursor SVG to this block's SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the block SVG - * group. - * @internal - */ - setCursorSvg(cursorSvg: SVGElement): void; - /** - * Add the marker SVG to this block's SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the block SVG - * group. - * @internal - */ - setMarkerSvg(markerSvg: SVGElement): void; /** * Returns a bounding box describing the dimensions of this block * and any blocks stacked below it. @@ -696,8 +697,17 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * @internal */ highlightShapeForInput(conn: RenderedConnection, add: boolean): void; + /** + * Returns the drag strategy currently in use by this block. + * + * @internal + * @returns This block's drag strategy. + */ + getDragStrategy(): IDragStrategy; /** Sets the drag strategy for this block. */ setDragStrategy(dragStrategy: IDragStrategy): void; + /** Returns whether this block is copyable or not. */ + isCopyable(): boolean; /** Returns whether this block is movable or not. */ isMovable(): boolean; /** Starts a drag on the block. */ @@ -712,5 +722,16 @@ export declare class BlockSvg extends Block implements IASTNodeLocationSvg, IBou * Returns a representation of this block that can be displayed in a flyout. */ toFlyoutInfo(): FlyoutItemInfo[]; + jsonInit(json: any): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; } //# sourceMappingURL=block_svg.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/blockly.d.ts b/appinventor/lib/blockly/@types/blockly.d.ts index 385e9f517ba..b0657c84563 100644 --- a/appinventor/lib/blockly/@types/blockly.d.ts +++ b/appinventor/lib/blockly/@types/blockly.d.ts @@ -9,12 +9,14 @@ import './events/events_ui_base.js'; import './events/events_var_create.js'; import { Block } from './block.js'; import * as blockAnimations from './block_animations.js'; +import { BlockFlyoutInflater } from './block_flyout_inflater.js'; import { BlockSvg } from './block_svg.js'; import { BlocklyOptions } from './blockly_options.js'; import { Blocks } from './blocks.js'; import * as browserEvents from './browser_events.js'; import * as bubbles from './bubbles.js'; import * as bumpObjects from './bump_objects.js'; +import { ButtonFlyoutInflater } from './button_flyout_inflater.js'; import * as clipboard from './clipboard.js'; import * as comments from './comments.js'; import * as common from './common.js'; @@ -38,7 +40,7 @@ import * as Events from './events/events.js'; import * as Extensions from './extensions.js'; import { Field, FieldConfig, FieldValidator, UnattachedFieldError } from './field.js'; import { FieldCheckbox, FieldCheckboxConfig, FieldCheckboxFromJsonConfig, FieldCheckboxValidator } from './field_checkbox.js'; -import { FieldDropdown, FieldDropdownConfig, FieldDropdownFromJsonConfig, FieldDropdownValidator, MenuGenerator, MenuGeneratorFunction, MenuOption } from './field_dropdown.js'; +import { FieldDropdown, FieldDropdownConfig, FieldDropdownFromJsonConfig, FieldDropdownValidator, ImageProperties, MenuGenerator, MenuGeneratorFunction, MenuOption } from './field_dropdown.js'; import { FieldImage, FieldImageConfig, FieldImageFromJsonConfig } from './field_image.js'; import { FieldLabel, FieldLabelConfig, FieldLabelFromJsonConfig } from './field_label.js'; import { FieldLabelSerializable } from './field_label_serializable.js'; @@ -49,20 +51,23 @@ import { FieldVariable, FieldVariableConfig, FieldVariableFromJsonConfig, FieldV import { Flyout } from './flyout_base.js'; import { FlyoutButton } from './flyout_button.js'; import { HorizontalFlyout } from './flyout_horizontal.js'; +import { FlyoutItem } from './flyout_item.js'; import { FlyoutMetricsManager } from './flyout_metrics_manager.js'; +import { FlyoutSeparator } from './flyout_separator.js'; import { VerticalFlyout } from './flyout_vertical.js'; +import { FocusManager, ReturnEphemeralFocus, getFocusManager } from './focus_manager.js'; import { CodeGenerator } from './generator.js'; import { Gesture } from './gesture.js'; import { Grid } from './grid.js'; import * as icons from './icons.js'; import { inject } from './inject.js'; import * as inputs from './inputs.js'; +import { IFlyoutInflater } from './interfaces/i_flyout_inflater.js'; +import { LabelFlyoutInflater } from './label_flyout_inflater.js'; +import { SeparatorFlyoutInflater } from './separator_flyout_inflater.js'; +import { FocusableTreeTraverser } from './utils/focusable_tree_traverser.js'; import { Input } from './inputs/input.js'; -import { InsertionMarkerManager } from './insertion_marker_manager.js'; import { InsertionMarkerPreviewer } from './insertion_marker_previewer.js'; -import { IASTNodeLocation } from './interfaces/i_ast_node_location.js'; -import { IASTNodeLocationSvg } from './interfaces/i_ast_node_location_svg.js'; -import { IASTNodeLocationWithBlock } from './interfaces/i_ast_node_location_with_block.js'; import { IAutoHideable } from './interfaces/i_autohideable.js'; import { IBoundedElement } from './interfaces/i_bounded_element.js'; import { IBubble } from './interfaces/i_bubble.js'; @@ -78,6 +83,8 @@ import { IDragTarget } from './interfaces/i_drag_target.js'; import { IDragStrategy, IDraggable, isDraggable } from './interfaces/i_draggable.js'; import { IDragger } from './interfaces/i_dragger.js'; import { IFlyout } from './interfaces/i_flyout.js'; +import { IFocusableNode } from './interfaces/i_focusable_node.js'; +import { IFocusableTree } from './interfaces/i_focusable_tree.js'; import { IHasBubble, hasBubble } from './interfaces/i_has_bubble.js'; import { IIcon, isIcon } from './interfaces/i_icon.js'; import { IKeyboardAccessible } from './interfaces/i_keyboard_accessible.js'; @@ -95,11 +102,11 @@ import { IStyleable } from './interfaces/i_styleable.js'; import { IToolbox } from './interfaces/i_toolbox.js'; import { IToolboxItem } from './interfaces/i_toolbox_item.js'; import { IVariableBackedParameterModel, isVariableBackedParameterModel } from './interfaces/i_variable_backed_parameter_model.js'; -import { ASTNode } from './keyboard_nav/ast_node.js'; -import { BasicCursor } from './keyboard_nav/basic_cursor.js'; -import { Cursor } from './keyboard_nav/cursor.js'; +import { IVariableMap } from './interfaces/i_variable_map.js'; +import { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; +import { LineCursor } from './keyboard_nav/line_cursor.js'; import { Marker } from './keyboard_nav/marker.js'; -import { TabNavigateCursor } from './keyboard_nav/tab_navigate_cursor.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'; @@ -262,7 +269,18 @@ export declare const VARIABLE_DYNAMIC_CATEGORY_NAME: string; * procedure blocks. */ export declare const PROCEDURE_CATEGORY_NAME: string; -export { ASTNode, BasicCursor, Block, BlockSvg, BlocklyOptions, Blocks, CollapsibleToolboxCategory, ComponentManager, Connection, ConnectionChecker, ConnectionDB, ConnectionType, ContextMenu, ContextMenuItems, ContextMenuRegistry, Css, Cursor, DeleteArea, DragTarget, Events, Extensions, Procedures, ShortcutItems, Themes, Tooltip, Touch, Variables, VariablesDynamic, WidgetDiv, Xml, blockAnimations, blockRendering, browserEvents, bubbles, bumpObjects, clipboard, comments, common, constants, dialog, dragging, fieldRegistry, geras, Procedures as procedures, registry, thrasos, uiPosition, utils, zelos, }; +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 './toast.js'; +export { Block, BlockSvg, BlocklyOptions, Blocks, CollapsibleToolboxCategory, ComponentManager, Connection, ConnectionChecker, ConnectionDB, ConnectionType, ContextMenu, ContextMenuItems, ContextMenuRegistry, Css, DeleteArea, DragTarget, Events, Extensions, LineCursor, Procedures, ShortcutItems, Themes, Tooltip, Touch, Variables, VariablesDynamic, WidgetDiv, Xml, blockAnimations, blockRendering, browserEvents, bubbles, bumpObjects, clipboard, comments, common, constants, dialog, dragging, fieldRegistry, geras, Procedures as procedures, registry, thrasos, uiPosition, utils, zelos, }; export declare const DropDownDiv: typeof dropDownDiv; -export { CodeGenerator, Field, FieldCheckbox, FieldCheckboxConfig, FieldCheckboxFromJsonConfig, FieldCheckboxValidator, FieldConfig, FieldDropdown, FieldDropdownConfig, FieldDropdownFromJsonConfig, FieldDropdownValidator, FieldImage, FieldImageConfig, FieldImageFromJsonConfig, FieldLabel, FieldLabelConfig, FieldLabelFromJsonConfig, FieldLabelSerializable, FieldNumber, FieldNumberConfig, FieldNumberFromJsonConfig, FieldNumberValidator, FieldTextInput, FieldTextInputConfig, FieldTextInputFromJsonConfig, FieldTextInputValidator, FieldValidator, FieldVariable, FieldVariableConfig, FieldVariableFromJsonConfig, FieldVariableValidator, Flyout, FlyoutButton, FlyoutMetricsManager, CodeGenerator as Generator, Gesture, Grid, HorizontalFlyout, IASTNodeLocation, IASTNodeLocationSvg, IASTNodeLocationWithBlock, IAutoHideable, IBoundedElement, IBubble, ICollapsibleToolboxItem, IComponent, IConnectionChecker, IConnectionPreviewer, IContextMenu, ICopyData, ICopyable, IDeletable, IDeleteArea, IDragStrategy, IDragTarget, IDraggable, IDragger, IFlyout, IHasBubble, IIcon, IKeyboardAccessible, IMetricsManager, IMovable, IObservable, IPaster, IPositionable, IRegistrable, IRenderedElement, ISelectable, ISelectableToolboxItem, ISerializable, IStyleable, IToolbox, IToolboxItem, IVariableBackedParameterModel, Input, InsertionMarkerManager, InsertionMarkerPreviewer, LayerManager, Marker, MarkerManager, Menu, MenuGenerator, MenuGeneratorFunction, MenuItem, MenuOption, MetricsManager, Msg, Names, Options, RenderedConnection, Scrollbar, ScrollbarPair, ShortcutRegistry, TabNavigateCursor, Theme, ThemeManager, Toolbox, ToolboxCategory, ToolboxItem, ToolboxSeparator, Trashcan, UnattachedFieldError, VariableMap, VariableModel, VerticalFlyout, Workspace, WorkspaceAudio, WorkspaceDragger, WorkspaceSvg, ZoomControls, config, hasBubble, icons, inject, inputs, isCopyable, isDeletable, isDraggable, isIcon, isObservable, isPaster, isRenderedElement, isSelectable, isSerializable, isVariableBackedParameterModel, layers, renderManagement, serialization, setLocale, }; +export { BlockFlyoutInflater, ButtonFlyoutInflater, CodeGenerator, Field, FieldCheckbox, FieldCheckboxConfig, FieldCheckboxFromJsonConfig, FieldCheckboxValidator, FieldConfig, FieldDropdown, FieldDropdownConfig, FieldDropdownFromJsonConfig, FieldDropdownValidator, FieldImage, FieldImageConfig, FieldImageFromJsonConfig, FieldLabel, FieldLabelConfig, FieldLabelFromJsonConfig, FieldLabelSerializable, FieldNumber, FieldNumberConfig, FieldNumberFromJsonConfig, FieldNumberValidator, FieldTextInput, FieldTextInputConfig, FieldTextInputFromJsonConfig, FieldTextInputValidator, FieldValidator, FieldVariable, FieldVariableConfig, FieldVariableFromJsonConfig, FieldVariableValidator, Flyout, FlyoutButton, FlyoutItem, FlyoutMetricsManager, FlyoutSeparator, FocusManager, FocusableTreeTraverser, CodeGenerator as Generator, Gesture, Grid, HorizontalFlyout, IAutoHideable, IBoundedElement, IBubble, ICollapsibleToolboxItem, IComponent, IConnectionChecker, IConnectionPreviewer, IContextMenu, ICopyData, ICopyable, IDeletable, IDeleteArea, IDragStrategy, IDragTarget, IDraggable, IDragger, IFlyout, IFlyoutInflater, IFocusableNode, IFocusableTree, IHasBubble, IIcon, IKeyboardAccessible, IMetricsManager, IMovable, IObservable, IPaster, IPositionable, IRegistrable, IRenderedElement, ISelectable, ISelectableToolboxItem, ISerializable, IStyleable, IToolbox, IToolboxItem, IVariableBackedParameterModel, IVariableMap, IVariableModel, IVariableState, ImageProperties, Input, InsertionMarkerPreviewer, KeyboardNavigationController, LabelFlyoutInflater, LayerManager, Marker, MarkerManager, Menu, MenuGenerator, MenuGeneratorFunction, MenuItem, MenuOption, MetricsManager, Msg, Names, Options, RenderedConnection, ReturnEphemeralFocus, Scrollbar, ScrollbarPair, SeparatorFlyoutInflater, ShortcutRegistry, Theme, ThemeManager, Toolbox, ToolboxCategory, ToolboxItem, ToolboxSeparator, Trashcan, UnattachedFieldError, VariableMap, VariableModel, VerticalFlyout, Workspace, WorkspaceAudio, WorkspaceDragger, WorkspaceSvg, ZoomControls, config, getFocusManager, hasBubble, icons, inject, inputs, isCopyable, isDeletable, isDraggable, isIcon, isObservable, isPaster, isRenderedElement, isSelectable, isSerializable, isVariableBackedParameterModel, keyboardNavigationController, layers, renderManagement, serialization, setLocale, }; //# sourceMappingURL=blockly.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/browser_events.d.ts b/appinventor/lib/blockly/@types/browser_events.d.ts index 5fcb1980c90..6b749fddff7 100644 --- a/appinventor/lib/blockly/@types/browser_events.d.ts +++ b/appinventor/lib/blockly/@types/browser_events.d.ts @@ -21,9 +21,12 @@ export type Data = [EventTarget, string, (e: Event) => void][]; * @param opt_noCaptureIdentifier True if triggering on this event should not * block execution of other event handlers on this touch or other * simultaneous touches. False by default. + * @param options An object with options controlling the behavior of the event + * listener. Passed through directly as the third argument to + * `addEventListener`. * @returns Opaque data that can be passed to unbindEvent_. */ -export declare function conditionalBind(node: EventTarget, name: string, thisObject: object | null, func: Function, opt_noCaptureIdentifier?: boolean): Data; +export declare function conditionalBind(node: EventTarget, name: string, thisObject: object | null, func: Function, opt_noCaptureIdentifier?: boolean, options?: AddEventListenerOptions): Data; /** * Bind an event handler that should be called regardless of whether it is part * of the active touch stream. @@ -34,9 +37,12 @@ export declare function conditionalBind(node: EventTarget, name: string, thisObj * @param name Event name to listen to (e.g. 'mousedown'). * @param thisObject The value of 'this' in the function. * @param func Function to call when event is triggered. + * @param options An object with options controlling the behavior of the event + * listener. Passed through directly as the third argument to + * `addEventListener`. * @returns Opaque data that can be passed to unbindEvent_. */ -export declare function bind(node: EventTarget, name: string, thisObject: object | null, func: Function): Data; +export declare function bind(node: EventTarget, name: string, thisObject: object | null, func: Function, options?: AddEventListenerOptions): Data; /** * Unbind one or more events event from a function call. * diff --git a/appinventor/lib/blockly/@types/bubbles/bubble.d.ts b/appinventor/lib/blockly/@types/bubbles/bubble.d.ts index 3e262649ef0..4f6569bf9ff 100644 --- a/appinventor/lib/blockly/@types/bubbles/bubble.d.ts +++ b/appinventor/lib/blockly/@types/bubbles/bubble.d.ts @@ -3,8 +3,11 @@ * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import { ISelectable } from '../blockly.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 { Coordinate } from '../utils/coordinate.js'; import { Rect } from '../utils/rect.js'; import { Size } from '../utils/size.js'; @@ -14,10 +17,11 @@ 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 declare abstract class Bubble implements IBubble, ISelectable { +export declare abstract class Bubble implements IBubble, ISelectable, IFocusableNode { readonly workspace: WorkspaceSvg; protected anchor: Coordinate; protected ownerRect?: Rect | undefined; + protected owner?: (IHasBubble & IFocusableNode) | undefined; /** The width of the border around the bubble. */ static readonly BORDER_WIDTH = 6; /** Double the width of the border around the bubble. */ @@ -60,14 +64,20 @@ export declare abstract class Bubble implements IBubble, ISelectable { /** The position of the left of the bubble realtive to its anchor. */ private relativeLeft; private dragStrategy; + private focusableElement; /** * @param workspace The workspace this bubble belongs to. * @param anchor The anchor location of the thing this bubble is attached to. * The tail of the bubble will point to this location. * @param ownerRect An optional rect we don't want the bubble to overlap with * when automatically positioning. + * @param overriddenFocusableElement An optional replacement to the focusable + * 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(workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined); + constructor(workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined, overriddenFocusableElement?: SVGElement | HTMLElement, owner?: (IHasBubble & IFocusableNode) | undefined); /** Dispose of this bubble. */ dispose(): void; /** @@ -96,8 +106,18 @@ export declare abstract class Bubble implements IBubble, ISelectable { protected getColour(): string; /** Sets the colour of the background and tail of this bubble. */ setColour(colour: string): void; - /** Brings the bubble to the front and passes the pointer event off to the gesture system. */ + /** + * Passes the pointer event off to the gesture system and ensures the bubble + * is focused. + */ private onMouseDown; + /** + * 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): void; /** Positions the bubble relative to its anchor. Does not render its tail. */ protected positionRelativeToAnchor(): void; /** @@ -190,5 +210,19 @@ export declare abstract class Bubble implements IBubble, ISelectable { revertDrag(): void; select(): void; unselect(): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; + /** + * Returns the object that owns/hosts this bubble, if any. + */ + getOwner(): (IHasBubble & IFocusableNode) | undefined; } //# sourceMappingURL=bubble.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/bubbles/textinput_bubble.d.ts b/appinventor/lib/blockly/@types/bubbles/textinput_bubble.d.ts index eb910720672..243d45d8c6f 100644 --- a/appinventor/lib/blockly/@types/bubbles/textinput_bubble.d.ts +++ b/appinventor/lib/blockly/@types/bubbles/textinput_bubble.d.ts @@ -3,6 +3,9 @@ * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +import { CommentEditor } from '../comments/comment_editor.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { IHasBubble } from '../interfaces/i_has_bubble.js'; import { Coordinate } from '../utils/coordinate.js'; import { Rect } from '../utils/rect.js'; import { Size } from '../utils/size.js'; @@ -16,10 +19,7 @@ export declare class TextInputBubble extends Bubble { readonly workspace: WorkspaceSvg; protected anchor: Coordinate; protected ownerRect?: Rect | undefined; - /** The root of the elements specific to the text element. */ - private inputRoot; - /** The text input area element. */ - private textArea; + protected owner?: (IHasBubble & IFocusableNode) | undefined; /** The group containing the lines indicating the bubble is resizable. */ private resizeGroup; /** @@ -32,25 +32,26 @@ export declare class TextInputBubble extends Bubble { * resize group. */ private resizePointerMoveListener; - /** Functions listening for changes to the text of this bubble. */ - private textChangeListeners; /** Functions listening for changes to the size of this bubble. */ private sizeChangeListeners; - /** The text of this bubble. */ - private text; + /** Functions listening for changes to the location of this bubble. */ + private locationChangeListeners; /** The default size of this bubble, including borders. */ private readonly DEFAULT_SIZE; /** The minimum size of this bubble, including borders. */ private readonly MIN_SIZE; private editable; + /** View responsible for supporting text editing. */ + private editor; /** * @param workspace The workspace this bubble belongs to. * @param anchor The anchor location of the thing this bubble is attached to. * The tail of the bubble will point to this location. * @param ownerRect An optional rect we don't want the bubble to overlap with * when automatically positioning. + * @param owner The object that owns/hosts this bubble. */ - constructor(workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined); + constructor(workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined, owner?: (IHasBubble & IFocusableNode) | undefined); /** @returns the text of this bubble. */ getText(): string; /** Sets the text of this bubble. Calls change listeners. */ @@ -63,10 +64,8 @@ export declare class TextInputBubble extends Bubble { addTextChangeListener(listener: () => void): void; /** Adds a change listener to be notified when this bubble's size changes. */ addSizeChangeListener(listener: () => void): void; - /** Creates the editor UI for this bubble. */ - private createEditor; - /** Binds events to the text area element. */ - private bindTextAreaEvents; + /** Adds a change listener to be notified when this bubble's location changes. */ + addLocationChangeListener(listener: () => void): void; /** Creates the resize handler elements and binds events to them. */ private createResizeHandle; /** @@ -80,19 +79,24 @@ export declare class TextInputBubble extends Bubble { setSize(size: Size, relayout?: boolean): void; /** @returns the size of this bubble. */ getSize(): Size; + moveDuringDrag(newLoc: Coordinate): void; + setPositionRelativeToAnchor(left: number, top: number): void; + protected positionByRect(rect?: Rect): void; /** Handles mouse down events on the resize target. */ private onResizePointerDown; /** Handles pointer up events on the resize target. */ private onResizePointerUp; /** Handles pointer move events on the resize target. */ private onResizePointerMove; - /** - * Handles starting an edit of the text area. Brings the bubble to the front. - */ - private onStartEdit; - /** Handles a text change event for the text area. Calls event listeners. */ - private onTextChange; /** Handles a size change event for the text area. Calls event listeners. */ private onSizeChange; + /** Handles a location change event for the text area. Calls event listeners. */ + private onLocationChange; + /** + * Returns the text editor component of this bubble. + * + * @internal + */ + getEditor(): CommentEditor; } //# sourceMappingURL=textinput_bubble.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/button_flyout_inflater.d.ts b/appinventor/lib/blockly/@types/button_flyout_inflater.d.ts new file mode 100644 index 00000000000..5be80bf1fe2 --- /dev/null +++ b/appinventor/lib/blockly/@types/button_flyout_inflater.d.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { FlyoutItem } from './flyout_item.js'; +import type { IFlyout } from './interfaces/i_flyout.js'; +import type { IFlyoutInflater } from './interfaces/i_flyout_inflater.js'; +/** + * Class responsible for creating buttons for flyouts. + */ +export declare class ButtonFlyoutInflater implements IFlyoutInflater { + /** + * Inflates a flyout button from the given state and adds it to the flyout. + * + * @param state A JSON representation of a flyout button. + * @param flyout The flyout to create the button on. + * @returns A newly created FlyoutButton. + */ + load(state: object, flyout: IFlyout): FlyoutItem; + /** + * Returns the amount of space that should follow this button. + * + * @param state A JSON representation of a flyout button. + * @param defaultGap The default spacing for flyout items. + * @returns The amount of space that should follow this button. + */ + gapForItem(state: object, defaultGap: number): number; + /** + * Disposes of the given button. + * + * @param item The flyout button to dispose of. + */ + disposeItem(item: FlyoutItem): void; + /** + * Returns the type of items this inflater is responsible for creating. + * + * @returns An identifier for the type of items this inflater creates. + */ + getType(): string; +} +//# sourceMappingURL=button_flyout_inflater.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/clipboard.d.ts b/appinventor/lib/blockly/@types/clipboard.d.ts index e8a3b70537f..2ee72e16e3e 100644 --- a/appinventor/lib/blockly/@types/clipboard.d.ts +++ b/appinventor/lib/blockly/@types/clipboard.d.ts @@ -3,17 +3,89 @@ * Copyright 2021 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import { BlockPaster } from './clipboard/block_paster.js'; +import { BlockCopyData, BlockPaster } from './clipboard/block_paster.js'; import * as registry from './clipboard/registry.js'; import type { ICopyData, ICopyable } from './interfaces/i_copyable.js'; import { Coordinate } from './utils/coordinate.js'; import { WorkspaceSvg } from './workspace_svg.js'; /** - * Private version of copy for stubbing in tests. + * Copy a copyable item, and record its data and the workspace it was + * copied from. + * + * This function does not perform any checks to ensure the copy + * should be allowed, e.g. to ensure the block is deletable. Such + * checks should be done before calling this function. + * + * Note that if the copyable item is not an `ISelectable` or its + * `workspace` property is not a `WorkspaceSvg`, the copy will be + * successful, but there will be no saved workspace data. This will + * impact the ability to paste the data unless you explictily pass + * a workspace into the paste method. + * + * @param toCopy item to copy. + * @param location location to save as a potential paste location. + * @returns the copied data if copy was successful, otherwise null. + */ +export declare function copy(toCopy: ICopyable, location?: Coordinate): T | null; +/** + * Gets the copy data for the last item copied. This is useful if you + * are implementing custom copy/paste behavior. If you want the default + * behavior, just use the copy and paste methods directly. + * + * @returns copy data for the last item copied, or null if none set. + */ +export declare function getLastCopiedData(): ICopyable.ICopyData | null; +/** + * Sets the last copied item. You should call this method if you implement + * custom copy behavior, so that other callers are working with the correct + * data. This method is called automatically if you use the built-in copy + * method. + * + * @param copyData copy data for the last item copied. + */ +export declare function setLastCopiedData(copyData: ICopyData): void; +/** + * Gets the workspace that was last copied from. This is useful if you + * are implementing custom copy/paste behavior and want to paste on the + * same workspace that was copied from. If you want the default behavior, + * just use the copy and paste methods directly. + * + * @returns workspace that was last copied from, or null if none set. */ -declare function copyInternal(toCopy: ICopyable): T | null; +export declare function getLastCopiedWorkspace(): WorkspaceSvg | null; /** - * Paste a pasteable element into the workspace. + * Sets the workspace that was last copied from. You should call this method + * if you implement custom copy behavior, so that other callers are working + * with the correct data. This method is called automatically if you use the + * built-in copy method. + * + * @param workspace workspace that was last copied from. + */ +export declare function setLastCopiedWorkspace(workspace: WorkspaceSvg): void; +/** + * Gets the location that was last copied from. This is useful if you + * are implementing custom copy/paste behavior. If you want the + * default behavior, just use the copy and paste methods directly. + * + * @returns last saved location, or null if none set. + */ +export declare function getLastCopiedLocation(): Coordinate | undefined; +/** + * Sets the location that was last copied from. You should call this method + * if you implement custom copy behavior, so that other callers are working + * with the correct data. This method is called automatically if you use the + * built-in copy method. + * + * @param location last saved location, which can be used to paste at. + */ +export declare function setLastCopiedLocation(location: Coordinate): void; +/** + * Paste a pasteable element into the given workspace. + * + * This function does not perform any checks to ensure the paste + * is allowed, e.g. that the workspace is rendered or the block + * is pasteable. Such checks should be done before calling this + * function. * * @param copyData The data to paste into the workspace. * @param workspace The workspace to paste the data into. @@ -22,21 +94,10 @@ declare function copyInternal(toCopy: ICopyable): T | nu */ export declare function paste(copyData: T, workspace: WorkspaceSvg, coordinate?: Coordinate): ICopyable | null; /** - * Pastes the last copied ICopyable into the workspace. + * Pastes the last copied ICopyable into the last copied-from workspace. * * @returns the pasted thing if the paste was successful, null otherwise. */ export declare function paste(): ICopyable | null; -/** - * Private version of duplicate for stubbing in tests. - */ -declare function duplicateInternal & IHasWorkspace>(toDuplicate: T): T | null; -interface IHasWorkspace { - workspace: WorkspaceSvg; -} -export declare const TEST_ONLY: { - duplicateInternal: typeof duplicateInternal; - copyInternal: typeof copyInternal; -}; -export { BlockPaster, registry }; +export { BlockCopyData, BlockPaster, registry }; //# sourceMappingURL=clipboard.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments.d.ts b/appinventor/lib/blockly/@types/comments.d.ts index 8056d635237..6e819623e00 100644 --- a/appinventor/lib/blockly/@types/comments.d.ts +++ b/appinventor/lib/blockly/@types/comments.d.ts @@ -3,7 +3,11 @@ * Copyright 2024 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +export { CollapseCommentBarButton } from './comments/collapse_comment_bar_button.js'; +export { CommentBarButton } from './comments/comment_bar_button.js'; +export { CommentEditor } from './comments/comment_editor.js'; export { CommentView } from './comments/comment_view.js'; +export { DeleteCommentBarButton } from './comments/delete_comment_bar_button.js'; export { RenderedWorkspaceComment } from './comments/rendered_workspace_comment.js'; export { WorkspaceComment } from './comments/workspace_comment.js'; //# sourceMappingURL=comments.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments/collapse_comment_bar_button.d.ts b/appinventor/lib/blockly/@types/comments/collapse_comment_bar_button.d.ts new file mode 100644 index 00000000000..34dc90e4791 --- /dev/null +++ b/appinventor/lib/blockly/@types/comments/collapse_comment_bar_button.d.ts @@ -0,0 +1,52 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { WorkspaceSvg } from '../workspace_svg.js'; +import { CommentBarButton } from './comment_bar_button.js'; +import type { CommentView } from './comment_view.js'; +/** + * Magic string appended to the comment ID to create a unique ID for this button. + */ +export declare const COMMENT_COLLAPSE_BAR_BUTTON_FOCUS_IDENTIFIER = "_collapse_bar_button"; +/** + * Button that toggles the collapsed state of a comment. + */ +export declare class CollapseCommentBarButton extends CommentBarButton { + protected readonly id: string; + protected readonly workspace: WorkspaceSvg; + protected readonly container: SVGGElement; + protected readonly commentView: CommentView; + /** + * Opaque ID used to unbind event handlers during disposal. + */ + private readonly bindId; + /** + * SVG image displayed on this button. + */ + protected readonly icon: SVGImageElement; + /** + * Creates a new CollapseCommentBarButton instance. + * + * @param id The ID of this button's parent comment. + * @param workspace The workspace this button's parent comment is displayed on. + * @param container An SVG group that this button should be a child of. + */ + constructor(id: string, workspace: WorkspaceSvg, container: SVGGElement, commentView: CommentView); + /** + * Disposes of this button. + */ + dispose(): void; + /** + * Adjusts the positioning of this button within its container. + */ + reposition(): void; + /** + * Toggles the collapsed state of the parent comment. + * + * @param e The event that triggered this action. + */ + performAction(e?: Event): void; +} +//# sourceMappingURL=collapse_comment_bar_button.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments/comment_bar_button.d.ts b/appinventor/lib/blockly/@types/comments/comment_bar_button.d.ts new file mode 100644 index 00000000000..427eeb5c934 --- /dev/null +++ b/appinventor/lib/blockly/@types/comments/comment_bar_button.d.ts @@ -0,0 +1,62 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import { Rect } from '../utils/rect.js'; +import type { WorkspaceSvg } from '../workspace_svg.js'; +import type { CommentView } from './comment_view.js'; +/** + * Button displayed on a comment's top bar. + */ +export declare abstract class CommentBarButton implements IFocusableNode { + protected readonly id: string; + protected readonly workspace: WorkspaceSvg; + protected readonly container: SVGGElement; + protected readonly commentView: CommentView; + /** + * SVG image displayed on this button. + */ + protected abstract readonly icon: SVGImageElement; + /** + * Creates a new CommentBarButton instance. + * + * @param id The ID of this button's parent comment. + * @param workspace The workspace this button's parent comment is on. + * @param container An SVG group that this button should be a child of. + */ + constructor(id: string, workspace: WorkspaceSvg, container: SVGGElement, commentView: CommentView); + /** + * Returns whether or not this button is currently visible. + */ + isVisible(): boolean; + /** + * Returns the parent comment view of this comment bar button. + */ + getCommentView(): CommentView; + /** Adjusts the position of this button within its parent container. */ + abstract reposition(): void; + /** Perform the action this button should take when it is acted on. */ + abstract performAction(e?: Event): void; + /** + * Returns the dimensions of this button in workspace coordinates. + * + * @param includeMargin True to include the margin when calculating the size. + * @returns The size of this button. + */ + getSize(includeMargin?: boolean): Rect; + /** Returns the margin in workspace coordinates surrounding this button. */ + getMargin(): number; + /** Returns a DOM element representing this button that can receive focus. */ + getFocusableElement(): SVGImageElement; + /** Returns the workspace this button is a child of. */ + getFocusableTree(): WorkspaceSvg; + /** Called when this button's focusable DOM element gains focus. */ + onNodeFocus(): void; + /** Called when this button's focusable DOM element loses focus. */ + onNodeBlur(): void; + /** Returns whether this button can be focused. True if it is visible. */ + canBeFocused(): boolean; +} +//# sourceMappingURL=comment_bar_button.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments/comment_editor.d.ts b/appinventor/lib/blockly/@types/comments/comment_editor.d.ts new file mode 100644 index 00000000000..246011df307 --- /dev/null +++ b/appinventor/lib/blockly/@types/comments/comment_editor.d.ts @@ -0,0 +1,62 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import { IFocusableTree } from '../interfaces/i_focusable_tree.js'; +import { Size } from '../utils/size.js'; +import { WorkspaceSvg } from '../workspace_svg.js'; +/** + * String added to the ID of a workspace comment to identify + * the focusable node for the comment editor. + */ +export declare const COMMENT_EDITOR_FOCUS_IDENTIFIER = "_comment_textarea_"; +/** The part of a comment that can be typed into. */ +export declare class CommentEditor implements IFocusableNode { + workspace: WorkspaceSvg; + private onFinishEditing?; + id?: string; + /** The foreignObject containing the HTML text area. */ + private foreignObject; + /** The text area where the user can type. */ + private textArea; + /** Listeners for changes to text. */ + private textChangeListeners; + /** The current text of the comment. Updates on text area change. */ + private text; + constructor(workspace: WorkspaceSvg, commentId?: string, onFinishEditing?: (() => void) | undefined); + /** Gets the dom structure for this comment editor. */ + getDom(): SVGForeignObjectElement; + /** Gets the current text of the comment. */ + getText(): string; + /** Sets the current text of the comment and fires change listeners. */ + setText(text: string): void; + /** + * Triggers listeners when the text of the comment changes, either + * programmatically or manually by the user. + */ + private onTextChange; + /** + * Do something when the user indicates they've finished editing. + * + * @param e Keyboard event. + */ + private handleKeyDown; + /** Registers a callback that listens for text changes. */ + addTextChangeListener(listener: (oldText: string, newText: string) => void): void; + /** Removes the given listener from the list of text change listeners. */ + removeTextChangeListener(listener: () => void): void; + /** Sets the placeholder text displayed for an empty comment. */ + setPlaceholderText(text: string): void; + /** Sets whether the textarea is editable. If not, the textarea will be readonly. */ + setEditable(isEditable: boolean): void; + /** Update the size of the comment editor element. */ + updateSize(size: Size, topBarSize: Size): void; + getFocusableElement(): HTMLElement | SVGElement; + getFocusableTree(): IFocusableTree; + onNodeFocus(): void; + onNodeBlur(): void; + canBeFocused(): boolean; +} +//# sourceMappingURL=comment_editor.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments/comment_view.d.ts b/appinventor/lib/blockly/@types/comments/comment_view.d.ts index 044256ef67a..8f9d3c6bcd4 100644 --- a/appinventor/lib/blockly/@types/comments/comment_view.d.ts +++ b/appinventor/lib/blockly/@types/comments/comment_view.d.ts @@ -3,36 +3,37 @@ * Copyright 2024 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +import type { IFocusableNode } from '../interfaces/i_focusable_node'; import { IRenderedElement } from '../interfaces/i_rendered_element.js'; import { Coordinate } from '../utils/coordinate.js'; import { Size } from '../utils/size.js'; import { WorkspaceSvg } from '../workspace_svg.js'; +import { CommentBarButton } from './comment_bar_button.js'; export declare class CommentView implements IRenderedElement { - private readonly workspace; + readonly workspace: WorkspaceSvg; + readonly commentId: string; /** The root group element of the comment view. */ private svgRoot; /** - * The svg rect element that we use to create a hightlight around the comment. + * The SVG rect element that we use to create a highlight around the comment. */ private highlightRect; /** The group containing all of the top bar elements. */ private topBarGroup; /** The rect background for the top bar. */ private topBarBackground; - /** The delete icon that goes in the top bar. */ - private deleteIcon; - /** The foldout icon that goes in the top bar. */ - private foldoutIcon; + /** The delete button that goes in the top bar. */ + private deleteButton; + /** The foldout button that goes in the top bar. */ + private foldoutButton; /** The text element that goes in the top bar. */ private textPreview; /** The actual text node in the text preview. */ private textPreviewNode; /** The resize handle element. */ private resizeHandle; - /** The foreignObject containing the HTML text area. */ - private foreignObject; - /** The text area where the user can type. */ - private textArea; + /** The part of the comment view that contains the textarea to edit the comment. */ + private commentEditor; /** The current size of the comment in workspace units. */ private size; /** Whether the comment is collapsed or not. */ @@ -41,10 +42,6 @@ export declare class CommentView implements IRenderedElement { private editable; /** The current location of the comment in workspace coordinates. */ private location; - /** The current text of the comment. Updates on text area change. */ - private text; - /** Listeners for changes to text. */ - private textChangeListeners; /** Listeners for changes to size. */ private sizeChangeListeners; /** Listeners for disposal. */ @@ -62,12 +59,14 @@ export declare class CommentView implements IRenderedElement { */ private resizePointerMoveListener; /** Whether this comment view is currently being disposed or not. */ - private disposing; + protected disposing: boolean; /** Whether this comment view has been disposed or not. */ - private disposed; + protected disposed: boolean; /** Size of this comment when the resize drag was initiated. */ private preResizeSize?; - constructor(workspace: WorkspaceSvg); + /** The default size of newly created comments. */ + static defaultCommentSize: Size; + constructor(workspace: WorkspaceSvg, commentId: string); /** * Creates the rect we use for highlighting the comment when it's selected. */ @@ -81,6 +80,11 @@ export declare class CommentView implements IRenderedElement { * Creates the text area where users can type. Registers event listeners. */ private createTextArea; + /** + * + * @returns The FocusableNode representing the editor portion of this comment. + */ + getEditorFocusableNode(): IFocusableNode; /** Creates the DOM elements for the comment resize handle. */ private createResizeHandle; /** Returns the root SVG group element of the comment view. */ @@ -109,24 +113,10 @@ export declare class CommentView implements IRenderedElement { * The minimum height is based on the height of the top bar. */ private calcMinSize; - /** Calculates the margin that should exist around the delete icon. */ - private calcDeleteMargin; - /** Calculates the margin that should exist around the foldout icon. */ - private calcFoldoutMargin; /** Updates the size of the highlight rect to reflect the new size. */ private updateHighlightRect; /** Updates the size of the top bar to reflect the new size. */ private updateTopBarSize; - /** Updates the size of the text area elements to reflect the new size. */ - private updateTextAreaSize; - /** - * Updates the position of the delete icon elements to reflect the new size. - */ - private updateDeleteIconPosition; - /** - * Updates the position of the foldout icon elements to reflect the new size. - */ - private updateFoldoutIconPosition; /** * Updates the size and position of the text preview elements to reflect the new size. */ @@ -169,11 +159,6 @@ export declare class CommentView implements IRenderedElement { addOnCollapseListener(listener: (newCollapse: boolean) => void): void; /** Removes the given listener from the list of on collapse listeners. */ removeOnCollapseListener(listener: () => void): void; - /** - * Toggles the collapsedness of the block when we receive a pointer down - * event on the foldout icon. - */ - private onFoldoutDown; /** Returns true if the comment is currently editable. */ isEditable(): boolean; /** Sets the editability of the comment. */ @@ -186,25 +171,22 @@ export declare class CommentView implements IRenderedElement { * @param location The location to move to in workspace coordinates. */ moveTo(location: Coordinate): void; - /** Retursn the current text of the comment. */ + /** Returns the current text of the comment. */ getText(): string; /** Sets the current text of the comment. */ setText(text: string): void; - /** Registers a callback that listens for text changes. */ + /** Sets the placeholder text displayed for an empty comment. */ + setPlaceholderText(text: string): void; + /** Registers a callback that listens for text changes on the comment editor. */ addTextChangeListener(listener: (oldText: string, newText: string) => void): void; - /** Removes the given listener from the list of text change listeners. */ + /** Removes the given listener from the comment editor. */ removeTextChangeListener(listener: () => void): void; - /** - * Triggers listeners when the text of the comment changes, either - * programmatically or manually by the user. - */ - private onTextChange; /** Updates the preview text element to reflect the given text. */ private updateTextPreview; /** Truncates the text to fit within the top view. */ private truncateText; /** Brings the workspace comment to the front of its layer. */ - private bringToFront; + bringToFront(): void; /** * Handles disposing of the comment when we get a pointer down event on the * delete icon. @@ -223,5 +205,9 @@ export declare class CommentView implements IRenderedElement { addDisposeListener(listener: () => void): void; /** Removes the given listener from the list of disposal listeners. */ removeDisposeListener(listener: () => void): void; + /** + * @internal + */ + getCommentBarButtons(): CommentBarButton[]; } //# sourceMappingURL=comment_view.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments/delete_comment_bar_button.d.ts b/appinventor/lib/blockly/@types/comments/delete_comment_bar_button.d.ts new file mode 100644 index 00000000000..2f807c4b720 --- /dev/null +++ b/appinventor/lib/blockly/@types/comments/delete_comment_bar_button.d.ts @@ -0,0 +1,52 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { WorkspaceSvg } from '../workspace_svg.js'; +import { CommentBarButton } from './comment_bar_button.js'; +import type { CommentView } from './comment_view.js'; +/** + * Magic string appended to the comment ID to create a unique ID for this button. + */ +export declare const COMMENT_DELETE_BAR_BUTTON_FOCUS_IDENTIFIER = "_delete_bar_button"; +/** + * Button that deletes a comment. + */ +export declare class DeleteCommentBarButton extends CommentBarButton { + protected readonly id: string; + protected readonly workspace: WorkspaceSvg; + protected readonly container: SVGGElement; + protected readonly commentView: CommentView; + /** + * Opaque ID used to unbind event handlers during disposal. + */ + private readonly bindId; + /** + * SVG image displayed on this button. + */ + protected readonly icon: SVGImageElement; + /** + * Creates a new DeleteCommentBarButton instance. + * + * @param id The ID of this button's parent comment. + * @param workspace The workspace this button's parent comment is shown on. + * @param container An SVG group that this button should be a child of. + */ + constructor(id: string, workspace: WorkspaceSvg, container: SVGGElement, commentView: CommentView); + /** + * Disposes of this button. + */ + dispose(): void; + /** + * Adjusts the positioning of this button within its container. + */ + reposition(): void; + /** + * Deletes parent comment. + * + * @param e The event that triggered this action. + */ + performAction(e?: Event): void; +} +//# sourceMappingURL=delete_comment_bar_button.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/comments/rendered_workspace_comment.d.ts b/appinventor/lib/blockly/@types/comments/rendered_workspace_comment.d.ts index b74ac39e889..ac980a7faa3 100644 --- a/appinventor/lib/blockly/@types/comments/rendered_workspace_comment.d.ts +++ b/appinventor/lib/blockly/@types/comments/rendered_workspace_comment.d.ts @@ -9,16 +9,19 @@ import { IContextMenu } from '../interfaces/i_contextmenu.js'; import { ICopyable } from '../interfaces/i_copyable.js'; import { IDeletable } from '../interfaces/i_deletable.js'; import { IDraggable } from '../interfaces/i_draggable.js'; +import { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { IFocusableTree } from '../interfaces/i_focusable_tree.js'; import { IRenderedElement } from '../interfaces/i_rendered_element.js'; import { ISelectable } from '../interfaces/i_selectable.js'; import { Coordinate } from '../utils/coordinate.js'; import { Rect } from '../utils/rect.js'; import { Size } from '../utils/size.js'; import { WorkspaceSvg } from '../workspace_svg.js'; +import { CommentView } from './comment_view.js'; import { WorkspaceComment } from './workspace_comment.js'; -export declare class RenderedWorkspaceComment extends WorkspaceComment implements IBoundedElement, IRenderedElement, IDraggable, ISelectable, IDeletable, ICopyable, IContextMenu { +export declare class RenderedWorkspaceComment extends WorkspaceComment implements IBoundedElement, IRenderedElement, IDraggable, ISelectable, IDeletable, ICopyable, IContextMenu, IFocusableNode { /** The class encompassing the svg elements making up the workspace comment. */ - private view; + view: CommentView; readonly workspace: WorkspaceSvg; private dragStrategy; /** Constructs the workspace comment, including the view. */ @@ -30,6 +33,8 @@ export declare class RenderedWorkspaceComment extends WorkspaceComment implement private addModelUpdateBindings; /** Sets the text of the comment. */ setText(text: string): void; + /** Sets the placeholder text displayed if the comment is empty. */ + setPlaceholderText(text: string): void; /** Sets the size of the comment. */ setSize(size: Size): void; /** Sets whether the comment is collapsed or not. */ @@ -73,6 +78,8 @@ export declare class RenderedWorkspaceComment extends WorkspaceComment implement private startGesture; /** Visually indicates that this comment would be deleted if dropped. */ setDeleteStyle(wouldDelete: boolean): void; + /** Returns whether this comment is copyable or not */ + isCopyable(): boolean; /** Returns whether this comment is movable or not. */ isMovable(): boolean; /** Starts a drag on the comment. */ @@ -93,8 +100,22 @@ export declare class RenderedWorkspaceComment extends WorkspaceComment implement */ toCopyData(): WorkspaceCommentCopyData | null; /** Show a context menu for this comment. */ - showContextMenu(e: PointerEvent): void; + showContextMenu(e: Event): void; /** Snap this comment to the nearest grid point. */ snapToGrid(): void; + /** + * @returns The FocusableNode representing the editor portion of this comment. + */ + getEditorFocusableNode(): IFocusableNode; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; } //# sourceMappingURL=rendered_workspace_comment.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/common.d.ts b/appinventor/lib/blockly/@types/common.d.ts index 1e4680bdae1..bab5da5aab4 100644 --- a/appinventor/lib/blockly/@types/common.d.ts +++ b/appinventor/lib/blockly/@types/common.d.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { Block } from './block.js'; -import { ISelectable } from './blockly.js'; import { BlockDefinition } from './blocks.js'; import type { Connection } from './connection.js'; +import { ISelectable } from './interfaces/i_selectable.js'; import type { Workspace } from './workspace.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** @@ -49,18 +49,30 @@ export declare function getMainWorkspace(): Workspace; */ export declare function setMainWorkspace(workspace: Workspace): void; /** - * Returns the currently selected copyable object. + * Returns the current selection. */ export declare function getSelected(): ISelectable | null; /** - * Sets the currently selected block. This function does not visually mark the - * block as selected or fire the required events. If you wish to - * programmatically select a block, use `BlockSvg#select`. + * Sets the current selection. * - * @param newSelection The newly selected block. + * To clear the current selection, select another ISelectable or focus a + * non-selectable (like the workspace root node). + * + * @param newSelection The new selection to make. + * @internal + */ +export declare function setSelected(newSelection: ISelectable): void; +/** + * Fires a selection change event based on the new selection. + * + * This is only expected to be called by ISelectable implementations and should + * always be called before updating the current selection state. It does not + * change focus or selection state. + * + * @param newSelection The new selection. * @internal */ -export declare function setSelected(newSelection: ISelectable | null): void; +export declare function fireSelectedEvent(newSelection: ISelectable | null): void; /** * Get the container element in which to render the WidgetDiv, DropDownDiv and * Tooltip. @@ -136,6 +148,14 @@ export declare function createBlockDefinitionsFromJsonArray(jsonArray: any[]): { export declare function defineBlocks(blocks: { [key: string]: BlockDefinition; }): void; +/** + * Handle a key-down on SVG drawing surface. Does nothing if the main workspace + * is not visible. + * + * @internal + * @param e Key down event. + */ +export declare function globalShortcutHandler(e: KeyboardEvent): void; export declare const TEST_ONLY: { defineBlocksWithJsonArrayInternal: typeof defineBlocksWithJsonArrayInternal; }; diff --git a/appinventor/lib/blockly/@types/connection.d.ts b/appinventor/lib/blockly/@types/connection.d.ts index 44413ee390d..74afc8edcb1 100644 --- a/appinventor/lib/blockly/@types/connection.d.ts +++ b/appinventor/lib/blockly/@types/connection.d.ts @@ -10,13 +10,12 @@ */ import type { Block } from './block.js'; import type { Input } from './inputs/input.js'; -import type { IASTNodeLocationWithBlock } from './interfaces/i_ast_node_location_with_block.js'; import type { IConnectionChecker } from './interfaces/i_connection_checker.js'; import * as blocks from './serialization/blocks.js'; /** * Class for a connection between blocks. */ -export declare class Connection implements IASTNodeLocationWithBlock { +export declare class Connection { type: number; /** Constants for checking whether two connections are compatible. */ static CAN_CONNECT: number; @@ -41,6 +40,8 @@ export declare class Connection implements IASTNodeLocationWithBlock { private check; /** DOM representation of a shadow block, or null if none. */ private shadowDom; + /** The unique ID of this connection. */ + id: string; /** * Horizontal location of this connection. * @@ -216,7 +217,7 @@ export declare class Connection implements IASTNodeLocationWithBlock { * * Headless configurations (the default) do not have neighboring connection, * and always return an empty list (the default). - * {@link RenderedConnection#neighbours} overrides this behavior with a list + * {@link (RenderedConnection:class).neighbours} overrides this behavior with a list * computed from the rendered positioning. * * @param _maxLimit The maximum radius to another connection. diff --git a/appinventor/lib/blockly/@types/contextmenu.d.ts b/appinventor/lib/blockly/@types/contextmenu.d.ts index d100f896709..3e6379512fe 100644 --- a/appinventor/lib/blockly/@types/contextmenu.d.ts +++ b/appinventor/lib/blockly/@types/contextmenu.d.ts @@ -6,10 +6,14 @@ import type { Block } from './block.js'; import type { BlockSvg } from './block_svg.js'; import type { ContextMenuOption, LegacyContextMenuOption } from './contextmenu_registry.js'; +import { Menu } from './menu.js'; import * as serializationBlocks from './serialization/blocks.js'; +import { Coordinate } from './utils/coordinate.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** * Gets the block the context menu is currently attached to. + * It is not recommended that you use this function; instead, + * use the scope object passed to the context menu callback. * * @returns The block the context menu is attached to. */ @@ -23,12 +27,13 @@ export declare function setCurrentBlock(block: Block | null): void; /** * Construct the menu based on the list of options and show the menu. * - * @param e Mouse event. + * @param menuOpenEvent Event that caused the menu to open. * @param options Array of menu options. * @param rtl True if RTL, false if LTR. * @param workspace The workspace associated with the context menu, if any. + * @param location The screen coordinates at which to show the menu. */ -export declare function show(e: PointerEvent, options: (ContextMenuOption | LegacyContextMenuOption)[], rtl: boolean, workspace?: WorkspaceSvg): void; +export declare function show(menuOpenEvent: Event, options: (ContextMenuOption | LegacyContextMenuOption)[], rtl: boolean, workspace?: WorkspaceSvg, location?: Coordinate): void; /** * Hide the context menu. */ @@ -46,4 +51,8 @@ export declare function dispose(): void; * @returns Function that creates a block. */ export declare function callbackFactory(block: Block, state: Element | serializationBlocks.State): () => BlockSvg; +/** + * Returns the contextual menu if it is currently being shown. + */ +export declare function getMenu(): Menu | null; //# sourceMappingURL=contextmenu.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/contextmenu_registry.d.ts b/appinventor/lib/blockly/@types/contextmenu_registry.d.ts index 04e6a129f82..4f6970e8643 100644 --- a/appinventor/lib/blockly/@types/contextmenu_registry.d.ts +++ b/appinventor/lib/blockly/@types/contextmenu_registry.d.ts @@ -10,6 +10,8 @@ */ import type { BlockSvg } from './block_svg.js'; import { RenderedWorkspaceComment } from './comments/rendered_workspace_comment.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import { Coordinate } from './utils/coordinate.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** * Class for the registry of context menu items. This is intended to be a @@ -44,17 +46,16 @@ export declare class ContextMenuRegistry { */ getItem(id: string): RegistryItem | null; /** - * Gets the valid context menu options for the given scope type (e.g. block or - * workspace) and scope. Blocks are only shown if the preconditionFn shows + * Gets the valid context menu options for the given scope. + * Options are only included if the preconditionFn shows * they should not be hidden. * - * @param scopeType Type of scope where menu should be shown (e.g. on a block - * or on a workspace) * @param scope Current scope of context menu (i.e., the exact workspace or - * block being clicked on) + * block being clicked on). + * @param menuOpenEvent Event that caused the menu to open. * @returns the list of ContextMenuOptions */ - getContextMenuOptions(scopeType: ScopeType, scope: Scope): ContextMenuOption[]; + getContextMenuOptions(scope: Scope, menuOpenEvent: Event): ContextMenuOption[]; } export declare namespace ContextMenuRegistry { /** @@ -62,62 +63,106 @@ export declare namespace ContextMenuRegistry { * rendered in multiple scopes, e.g. on both a block and a workspace, it * should be registered for each scope. */ - enum ScopeType { + export enum ScopeType { BLOCK = "block", WORKSPACE = "workspace", COMMENT = "comment" } /** - * The actual workspace/block where the menu is being rendered. This is passed - * to callback and displayText functions that depend on this information. + * The actual workspace/block/focused object where the menu is being + * rendered. This is passed to callback and displayText functions + * that depend on this information. */ - interface Scope { + export interface Scope { block?: BlockSvg; workspace?: WorkspaceSvg; comment?: RenderedWorkspaceComment; + focusedNode?: IFocusableNode; } /** - * A menu item as entered in the registry. + * Fields common to all context menu registry items. + */ + interface CoreRegistryItem { + scopeType?: ScopeType; + weight: number; + id: string; + preconditionFn?: (p1: Scope, menuOpenEvent: Event) => string; + } + /** + * A representation of a normal, clickable menu item in the registry. */ - interface RegistryItem { + interface ActionRegistryItem extends CoreRegistryItem { /** * @param scope Object that provides a reference to the thing that had its * context menu opened. - * @param e The original event that triggered the context menu to open. Not - * the event that triggered the click on the option. + * @param menuOpenEvent The original event that triggered the context menu to open. + * @param menuSelectEvent The event that triggered the option being selected. + * @param location The location in screen coordinates where the menu was opened. */ - callback: (scope: Scope, e: PointerEvent) => void; - scopeType: ScopeType; + callback: (scope: Scope, menuOpenEvent: Event, menuSelectEvent: Event, location: Coordinate) => void; displayText: ((p1: Scope) => string | HTMLElement) | string | HTMLElement; - preconditionFn: (p1: Scope) => string; + separator?: never; + preconditionFn: (p1: Scope, menuOpenEvent: Event) => string; + } + /** + * A representation of a menu separator item in the registry. + */ + interface SeparatorRegistryItem extends CoreRegistryItem { + separator: true; + callback?: never; + displayText?: never; + } + /** + * A menu item as entered in the registry. + */ + export type RegistryItem = ActionRegistryItem | SeparatorRegistryItem; + /** + * Fields common to all context menu items as used by contextmenu.ts. + */ + export interface CoreContextMenuOption { + scope: Scope; weight: number; - id: string; } /** - * A menu item as presented to contextmenu.js. + * A representation of a normal, clickable menu item in contextmenu.ts. */ - interface ContextMenuOption { + export interface ActionContextMenuOption extends CoreContextMenuOption { text: string | HTMLElement; enabled: boolean; /** * @param scope Object that provides a reference to the thing that had its * context menu opened. - * @param e The original event that triggered the context menu to open. Not - * the event that triggered the click on the option. + * @param menuOpenEvent The original event that triggered the context menu to open. + * @param menuSelectEvent The event that triggered the option being selected. + * @param location The location in screen coordinates where the menu was opened. */ - callback: (scope: Scope, e: PointerEvent) => void; - scope: Scope; - weight: number; + callback: (scope: Scope, menuOpenEvent: Event, menuSelectEvent: Event, location: Coordinate) => void; + separator?: never; + } + /** + * A representation of a menu separator item in contextmenu.ts. + */ + export interface SeparatorContextMenuOption extends CoreContextMenuOption { + separator: true; + text?: never; + enabled?: never; + callback?: never; } + /** + * A menu item as presented to contextmenu.ts. + */ + export type ContextMenuOption = ActionContextMenuOption | SeparatorContextMenuOption; /** * A subset of ContextMenuOption corresponding to what was publicly * documented. ContextMenuOption should be preferred for new code. */ - interface LegacyContextMenuOption { + export interface LegacyContextMenuOption { text: string; enabled: boolean; callback: (p1: Scope) => void; + separator?: never; } + export {}; } export type ScopeType = ContextMenuRegistry.ScopeType; export declare const ScopeType: typeof ContextMenuRegistry.ScopeType; diff --git a/appinventor/lib/blockly/@types/dialog.d.ts b/appinventor/lib/blockly/@types/dialog.d.ts index 3d91f6b1294..87a8d54b5f1 100644 --- a/appinventor/lib/blockly/@types/dialog.d.ts +++ b/appinventor/lib/blockly/@types/dialog.d.ts @@ -3,6 +3,8 @@ * Copyright 2021 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +import type { ToastOptions } from './toast.js'; +import type { WorkspaceSvg } from './workspace_svg.js'; /** * Wrapper to window.alert() that app developers may override via setAlert to * provide alternatives to the modal browser window. @@ -14,10 +16,11 @@ export declare function alert(message: string, opt_callback?: () => void): void; /** * Sets the function to be run when Blockly.dialog.alert() is called. * - * @param alertFunction The function to be run. + * @param alertFunction The function to be run, or undefined to restore the + * default implementation. * @see Blockly.dialog.alert */ -export declare function setAlert(alertFunction: (p1: string, p2?: () => void) => void): void; +export declare function setAlert(alertFunction?: (message: string, callback?: () => void) => void): void; /** * Wrapper to window.confirm() that app developers may override via setConfirm * to provide alternatives to the modal browser window. @@ -25,18 +28,15 @@ export declare function setAlert(alertFunction: (p1: string, p2?: () => void) => * @param message The message to display to the user. * @param callback The callback for handling user response. */ -export declare function confirm(message: string, callback: (p1: boolean) => void): void; -/** - * Private version of confirm for stubbing in tests. - */ -declare function confirmInternal(message: string, callback: (p1: boolean) => void): void; +export declare function confirm(message: string, callback: (result: boolean) => void): void; /** * Sets the function to be run when Blockly.dialog.confirm() is called. * - * @param confirmFunction The function to be run. + * @param confirmFunction The function to be run, or undefined to restore the + * default implementation. * @see Blockly.dialog.confirm */ -export declare function setConfirm(confirmFunction: (p1: string, p2: (p1: boolean) => void) => void): void; +export declare function setConfirm(confirmFunction?: (message: string, callback: (result: boolean) => void) => void): void; /** * Wrapper to window.prompt() that app developers may override via setPrompt to * provide alternatives to the modal browser window. Built-in browser prompts @@ -47,16 +47,36 @@ export declare function setConfirm(confirmFunction: (p1: string, p2: (p1: boolea * @param defaultValue The value to initialize the prompt with. * @param callback The callback for handling user response. */ -export declare function prompt(message: string, defaultValue: string, callback: (p1: string | null) => void): void; +export declare function prompt(message: string, defaultValue: string, callback: (result: string | null) => void): void; /** * Sets the function to be run when Blockly.dialog.prompt() is called. * - * @param promptFunction The function to be run. + * **Important**: When overridding this, be aware that non-native prompt + * experiences may require managing ephemeral focus in FocusManager. This isn't + * needed for the native window prompt because it prevents focus from being + * changed while open. + * + * @param promptFunction The function to be run, or undefined to restore the + * default implementation. * @see Blockly.dialog.prompt */ -export declare function setPrompt(promptFunction: (p1: string, p2: string, p3: (p1: string | null) => void) => void): void; -export declare const TEST_ONLY: { - confirmInternal: typeof confirmInternal; -}; -export {}; +export declare function setPrompt(promptFunction?: (message: string, defaultValue: string, callback: (result: string | null) => void) => void): void; +/** + * Displays a temporary notification atop the workspace. Blockly provides a + * default toast implementation, but developers may provide their own via + * setToast. For simple appearance customization, CSS should be sufficient. + * + * @param workspace The workspace to display the toast notification atop. + * @param options Configuration options for the notification, including its + * message and duration. + */ +export declare function toast(workspace: WorkspaceSvg, options: ToastOptions): void; +/** + * Sets the function to be run when Blockly.dialog.toast() is called. + * + * @param toastFunction The function to be run, or undefined to restore the + * default implementation. + * @see Blockly.dialog.toast + */ +export declare function setToast(toastFunction?: (workspace: WorkspaceSvg, options: ToastOptions) => void): void; //# sourceMappingURL=dialog.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/dragging/block_drag_strategy.d.ts b/appinventor/lib/blockly/@types/dragging/block_drag_strategy.d.ts index f6bb168d483..bafed1ffc4d 100644 --- a/appinventor/lib/blockly/@types/dragging/block_drag_strategy.d.ts +++ b/appinventor/lib/blockly/@types/dragging/block_drag_strategy.d.ts @@ -25,8 +25,8 @@ export declare class BlockDragStrategy implements IDragStrategy { * block, to add to the drag location. In workspace units. */ private dragOffset; - /** Was there already an event group in progress when the drag started? */ - private inGroup; + /** Used to persist an event group when snapping is done async. */ + private originalEventGroup; constructor(block: BlockSvg); /** Returns true if the block is currently movable. False otherwise. */ isMovable(): boolean; @@ -35,6 +35,23 @@ export declare class BlockDragStrategy implements IDragStrategy { * from any parent blocks. */ startDrag(e?: PointerEvent): void; + /** + * Returns an array of visible bubbles attached to the given block or its + * descendants. + * + * @param block The block to identify open bubbles on. + * @returns An array of all currently visible bubbles on the given block or + * its descendants. + */ + private getVisibleBubbles; + /** + * Get whether the drag should act on a single block or a block stack. + * + * @param e The instigating pointer event, if any. + * @returns True if just the initial block should be dragged out, false + * if all following blocks should also be dragged. + */ + protected shouldHealStack(e: PointerEvent | undefined): boolean; /** Starts a drag on a shadow, recording the drag offset. */ private startDraggingShadow; /** @@ -84,6 +101,10 @@ export declare class BlockDragStrategy implements IDragStrategy { * compatible type (input, output, etc) and connection check. */ private getConnectionCandidate; + /** + * Get the radius to use when searching for a nearby valid connection. + */ + protected getSearchRadius(): number; /** * Returns all of the connections we might connect to blocks on the workspace. * diff --git a/appinventor/lib/blockly/@types/dragging/bubble_drag_strategy.d.ts b/appinventor/lib/blockly/@types/dragging/bubble_drag_strategy.d.ts index 497748bfbc1..34017731e75 100644 --- a/appinventor/lib/blockly/@types/dragging/bubble_drag_strategy.d.ts +++ b/appinventor/lib/blockly/@types/dragging/bubble_drag_strategy.d.ts @@ -10,8 +10,6 @@ export declare class BubbleDragStrategy implements IDragStrategy { private bubble; private workspace; private startLoc; - /** Was there already an event group in progress when the drag started? */ - private inGroup; constructor(bubble: IBubble, workspace: WorkspaceSvg); isMovable(): boolean; startDrag(): void; diff --git a/appinventor/lib/blockly/@types/dragging/comment_drag_strategy.d.ts b/appinventor/lib/blockly/@types/dragging/comment_drag_strategy.d.ts index cce82892655..4b9f03d4bcc 100644 --- a/appinventor/lib/blockly/@types/dragging/comment_drag_strategy.d.ts +++ b/appinventor/lib/blockly/@types/dragging/comment_drag_strategy.d.ts @@ -10,8 +10,6 @@ export declare class CommentDragStrategy implements IDragStrategy { private comment; private startLoc; private workspace; - /** Was there already an event group in progress when the drag started? */ - private inGroup; constructor(comment: RenderedWorkspaceComment); isMovable(): boolean; startDrag(): void; diff --git a/appinventor/lib/blockly/@types/dropdowndiv.d.ts b/appinventor/lib/blockly/@types/dropdowndiv.d.ts index cdb65d44c77..a5f25d3c8a5 100644 --- a/appinventor/lib/blockly/@types/dropdowndiv.d.ts +++ b/appinventor/lib/blockly/@types/dropdowndiv.d.ts @@ -75,7 +75,7 @@ export declare function getOwner(): Field | null; * * @returns Div to populate with content. */ -export declare function getContentDiv(): Element; +export declare function getContentDiv(): HTMLDivElement; /** Clear the content of the drop-down. */ export declare function clearContent(): void; /** @@ -95,9 +95,14 @@ export declare function setColour(backgroundColour: string, borderColour: string * @param block Block to position the drop-down around. * @param opt_onHide Optional callback for when the drop-down is hidden. * @param opt_secondaryYOffset Optional Y offset for above-block positioning. + * @param manageEphemeralFocus Whether ephemeral focus should be managed + * according to the drop-down div's lifetime. Note that if a false value is + * passed in here then callers should manage ephemeral focus directly + * otherwise focus may not properly restore when the widget closes. Defaults + * to true. * @returns True if the menu rendered below block; false if above. */ -export declare function showPositionedByBlock(field: Field, block: BlockSvg, opt_onHide?: () => void, opt_secondaryYOffset?: number): boolean; +export declare function showPositionedByBlock(field: Field, block: BlockSvg, opt_onHide?: () => void, opt_secondaryYOffset?: number, manageEphemeralFocus?: boolean): boolean; /** * Shortcut to show and place the drop-down with positioning determined * by a particular field. The primary position will be below the field, @@ -107,9 +112,14 @@ export declare function showPositionedByBlock(field: Field, block: BlockSv * @param field The field to position the dropdown against. * @param opt_onHide Optional callback for when the drop-down is hidden. * @param opt_secondaryYOffset Optional Y offset for above-block positioning. + * @param manageEphemeralFocus Whether ephemeral focus should be managed + * according to the drop-down div's lifetime. Note that if a false value is + * passed in here then callers should manage ephemeral focus directly + * otherwise focus may not properly restore when the widget closes. Defaults + * to true. * @returns True if the menu rendered below block; false if above. */ -export declare function showPositionedByField(field: Field, opt_onHide?: () => void, opt_secondaryYOffset?: number): boolean; +export declare function showPositionedByField(field: Field, opt_onHide?: () => void, opt_secondaryYOffset?: number, manageEphemeralFocus?: boolean): boolean; /** * Show and place the drop-down. * The drop-down is placed with an absolute "origin point" (x, y) - i.e., @@ -126,10 +136,12 @@ export declare function showPositionedByField(field: Field, opt_onHide?: ( * @param secondaryX Secondary/alternative origin point x, in absolute px. * @param secondaryY Secondary/alternative origin point y, in absolute px. * @param opt_onHide Optional callback for when the drop-down is hidden. + * @param manageEphemeralFocus Whether ephemeral focus should be managed + * according to the widget div's lifetime. * @returns True if the menu rendered at the primary origin point. * @internal */ -export declare function show(newOwner: Field, rtl: boolean, primaryX: number, primaryY: number, secondaryX: number, secondaryY: number, opt_onHide?: () => void): boolean; +export declare function show(newOwner: Field, rtl: boolean, primaryX: number, primaryY: number, secondaryX: number, secondaryY: number, manageEphemeralFocus: boolean, opt_onHide?: () => void): boolean; /** * Get the x positions for the left side of the DropDownDiv and the arrow, * accounting for the bounds of the workspace. diff --git a/appinventor/lib/blockly/@types/events/events.d.ts b/appinventor/lib/blockly/@types/events/events.d.ts index ea5051e91e6..5d3e3b2d568 100644 --- a/appinventor/lib/blockly/@types/events/events.d.ts +++ b/appinventor/lib/blockly/@types/events/events.d.ts @@ -22,7 +22,6 @@ export { CommentDelete } from './events_comment_delete.js'; export { CommentDrag, CommentDragJson } from './events_comment_drag.js'; export { CommentMove, CommentMoveJson } from './events_comment_move.js'; export { CommentResize, CommentResizeJson } from './events_comment_resize.js'; -export { MarkerMove, MarkerMoveJson } from './events_marker_move.js'; export { Selected, SelectedJson } from './events_selected.js'; export { ThemeChange, ThemeChangeJson } from './events_theme_change.js'; export { ToolboxItemSelect, ToolboxItemSelectJson, } from './events_toolbox_item_select.js'; @@ -32,6 +31,7 @@ export { VarBase, VarBaseJson } from './events_var_base.js'; export { VarCreate, VarCreateJson } from './events_var_create.js'; export { VarDelete, VarDeleteJson } from './events_var_delete.js'; export { VarRename, VarRenameJson } from './events_var_rename.js'; +export { VarTypeChange, VarTypeChangeJson } from './events_var_type_change.js'; export { ViewportChange, ViewportChangeJson } from './events_viewport.js'; export { FinishedLoading } from './workspace_events.js'; export type { BumpEvent } from './utils.js'; @@ -56,7 +56,6 @@ export declare const CREATE = EventType.BLOCK_CREATE; /** @deprecated Use BLOCK_DELETE instead */ export declare const DELETE = EventType.BLOCK_DELETE; export declare const FINISHED_LOADING = EventType.FINISHED_LOADING; -export declare const MARKER_MOVE = EventType.MARKER_MOVE; /** @deprecated Use BLOCK_MOVE instead */ export declare const MOVE = EventType.BLOCK_MOVE; export declare const SELECTED = EventType.SELECTED; diff --git a/appinventor/lib/blockly/@types/events/events_marker_move.d.ts b/appinventor/lib/blockly/@types/events/events_marker_move.d.ts deleted file mode 100644 index 790896d762f..00000000000 --- a/appinventor/lib/blockly/@types/events/events_marker_move.d.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * Events fired as a result of a marker move. - * - * @class - */ -import type { Block } from '../block.js'; -import { ASTNode } from '../keyboard_nav/ast_node.js'; -import type { Workspace } from '../workspace.js'; -import { AbstractEventJson } from './events_abstract.js'; -import { UiBase } from './events_ui_base.js'; -import { EventType } from './type.js'; -/** - * Notifies listeners that a marker (used for keyboard navigation) has - * moved. - */ -export declare class MarkerMove extends UiBase { - /** The ID of the block the marker is now on, if any. */ - blockId?: string; - /** The old node the marker used to be on, if any. */ - oldNode?: ASTNode; - /** The new node the marker is now on. */ - newNode?: ASTNode; - /** - * True if this is a cursor event, false otherwise. - * For information about cursors vs markers see {@link - * https://blocklycodelabs.dev/codelabs/keyboard-navigation/index.html?index=..%2F..index#1}. - */ - isCursor?: boolean; - type: EventType; - /** - * @param opt_block The affected block. Null if current node is of type - * workspace. Undefined for a blank event. - * @param isCursor Whether this is a cursor event. Undefined for a blank - * event. - * @param opt_oldNode The old node the marker used to be on. - * Undefined for a blank event. - * @param opt_newNode The new node the marker is now on. - * Undefined for a blank event. - */ - constructor(opt_block?: Block | null, isCursor?: boolean, opt_oldNode?: ASTNode | null, opt_newNode?: ASTNode); - /** - * Encode the event as JSON. - * - * @returns JSON representation. - */ - toJson(): MarkerMoveJson; - /** - * Deserializes the JSON event. - * - * @param event The event to append new properties to. Should be a subclass - * of MarkerMove, but we can't specify that due to the fact that - * parameters to static methods in subclasses must be supertypes of - * parameters to static methods in superclasses. - * @internal - */ - static fromJson(json: MarkerMoveJson, workspace: Workspace, event?: any): MarkerMove; -} -export interface MarkerMoveJson extends AbstractEventJson { - isCursor: boolean; - blockId?: string; - oldNode?: ASTNode; - newNode: ASTNode; -} -//# sourceMappingURL=events_marker_move.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/events/events_var_base.d.ts b/appinventor/lib/blockly/@types/events/events_var_base.d.ts index 8eeb70dd872..9ddd5032c82 100644 --- a/appinventor/lib/blockly/@types/events/events_var_base.d.ts +++ b/appinventor/lib/blockly/@types/events/events_var_base.d.ts @@ -8,7 +8,7 @@ * * @class */ -import type { VariableModel } from '../variable_model.js'; +import type { IVariableModel, IVariableState } from '../interfaces/i_variable_model.js'; import type { Workspace } from '../workspace.js'; import { Abstract as AbstractEvent, AbstractEventJson } from './events_abstract.js'; /** @@ -22,7 +22,7 @@ export declare class VarBase extends AbstractEvent { * @param opt_variable The variable this event corresponds to. Undefined for * a blank event. */ - constructor(opt_variable?: VariableModel); + constructor(opt_variable?: IVariableModel); /** * Encode the event as JSON. * diff --git a/appinventor/lib/blockly/@types/events/events_var_create.d.ts b/appinventor/lib/blockly/@types/events/events_var_create.d.ts index 2084495f34d..f0cc80f61f1 100644 --- a/appinventor/lib/blockly/@types/events/events_var_create.d.ts +++ b/appinventor/lib/blockly/@types/events/events_var_create.d.ts @@ -3,7 +3,12 @@ * Copyright 2018 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import type { VariableModel } from '../variable_model.js'; +/** + * Class for a variable creation event. + * + * @class + */ +import type { IVariableModel, IVariableState } from '../interfaces/i_variable_model.js'; import type { Workspace } from '../workspace.js'; import { VarBase, VarBaseJson } from './events_var_base.js'; import { EventType } from './type.js'; @@ -19,7 +24,7 @@ export declare class VarCreate extends VarBase { /** * @param opt_variable The created variable. Undefined for a blank event. */ - constructor(opt_variable?: VariableModel); + constructor(opt_variable?: IVariableModel); /** * Encode the event as JSON. * diff --git a/appinventor/lib/blockly/@types/events/events_var_delete.d.ts b/appinventor/lib/blockly/@types/events/events_var_delete.d.ts index 8fdf2348a4d..c3335ed59b7 100644 --- a/appinventor/lib/blockly/@types/events/events_var_delete.d.ts +++ b/appinventor/lib/blockly/@types/events/events_var_delete.d.ts @@ -3,14 +3,12 @@ * Copyright 2018 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import type { VariableModel } from '../variable_model.js'; +import type { IVariableModel, IVariableState } from '../interfaces/i_variable_model.js'; import type { Workspace } from '../workspace.js'; import { VarBase, VarBaseJson } from './events_var_base.js'; import { EventType } from './type.js'; /** * Notifies listeners that a variable model has been deleted. - * - * @class */ export declare class VarDelete extends VarBase { type: EventType; @@ -21,7 +19,7 @@ export declare class VarDelete extends VarBase { /** * @param opt_variable The deleted variable. Undefined for a blank event. */ - constructor(opt_variable?: VariableModel); + constructor(opt_variable?: IVariableModel); /** * Encode the event as JSON. * diff --git a/appinventor/lib/blockly/@types/events/events_var_rename.d.ts b/appinventor/lib/blockly/@types/events/events_var_rename.d.ts index 20b44fbbbd0..6336ba39871 100644 --- a/appinventor/lib/blockly/@types/events/events_var_rename.d.ts +++ b/appinventor/lib/blockly/@types/events/events_var_rename.d.ts @@ -3,14 +3,12 @@ * Copyright 2018 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import type { VariableModel } from '../variable_model.js'; +import type { IVariableModel, IVariableState } from '../interfaces/i_variable_model.js'; import type { Workspace } from '../workspace.js'; import { VarBase, VarBaseJson } from './events_var_base.js'; import { EventType } from './type.js'; /** * Notifies listeners that a variable model was renamed. - * - * @class */ export declare class VarRename extends VarBase { type: EventType; @@ -22,7 +20,7 @@ export declare class VarRename extends VarBase { * @param opt_variable The renamed variable. Undefined for a blank event. * @param newName The new name the variable will be changed to. */ - constructor(opt_variable?: VariableModel, newName?: string); + constructor(opt_variable?: IVariableModel, newName?: string); /** * Encode the event as JSON. * diff --git a/appinventor/lib/blockly/@types/events/events_var_type_change.d.ts b/appinventor/lib/blockly/@types/events/events_var_type_change.d.ts new file mode 100644 index 00000000000..bfa37693fe3 --- /dev/null +++ b/appinventor/lib/blockly/@types/events/events_var_type_change.d.ts @@ -0,0 +1,55 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Class for a variable type change event. + * + * @class + */ +import type { IVariableModel, IVariableState } from '../interfaces/i_variable_model.js'; +import type { Workspace } from '../workspace.js'; +import { VarBase, VarBaseJson } from './events_var_base.js'; +import { EventType } from './type.js'; +/** + * Notifies listeners that a variable's type has changed. + */ +export declare class VarTypeChange extends VarBase { + oldType?: string | undefined; + newType?: string | undefined; + type: EventType; + /** + * @param variable The variable whose type changed. Undefined for a blank event. + * @param oldType The old type of the variable. Undefined for a blank event. + * @param newType The new type of the variable. Undefined for a blank event. + */ + constructor(variable?: IVariableModel, oldType?: string | undefined, newType?: string | undefined); + /** + * Encode the event as JSON. + * + * @returns JSON representation. + */ + toJson(): VarTypeChangeJson; + /** + * Deserializes the JSON event. + * + * @param event The event to append new properties to. Should be a subclass + * of VarTypeChange, but we can't specify that due to the fact that + * parameters to static methods in subclasses must be supertypes of + * parameters to static methods in superclasses. + * @internal + */ + static fromJson(json: VarTypeChangeJson, workspace: Workspace, event?: any): VarTypeChange; + /** + * Run a variable type change event. + * + * @param forward True if run forward, false if run backward (undo). + */ + run(forward: boolean): void; +} +export interface VarTypeChangeJson extends VarBaseJson { + oldType: string; + newType: string; +} +//# sourceMappingURL=events_var_type_change.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/events/predicates.d.ts b/appinventor/lib/blockly/@types/events/predicates.d.ts index 8756da18088..444f217cfaf 100644 --- a/appinventor/lib/blockly/@types/events/predicates.d.ts +++ b/appinventor/lib/blockly/@types/events/predicates.d.ts @@ -27,7 +27,6 @@ import type { CommentDelete } from './events_comment_delete.js'; import type { CommentDrag } from './events_comment_drag.js'; import type { CommentMove } from './events_comment_move.js'; import type { CommentResize } from './events_comment_resize.js'; -import type { MarkerMove } from './events_marker_move.js'; import type { Selected } from './events_selected.js'; import type { ThemeChange } from './events_theme_change.js'; import type { ToolboxItemSelect } from './events_toolbox_item_select.js'; @@ -59,8 +58,6 @@ export declare function isBlockDrag(event: Abstract): event is BlockDrag; export declare function isSelected(event: Abstract): event is Selected; /** @returns true iff event.type is EventType.CLICK */ export declare function isClick(event: Abstract): event is Click; -/** @returns true iff event.type is EventType.MARKER_MOVE */ -export declare function isMarkerMove(event: Abstract): event is MarkerMove; /** @returns true iff event.type is EventType.BUBBLE_OPEN */ export declare function isBubbleOpen(event: Abstract): event is BubbleOpen; /** @returns true iff event.type is EventType.TRASHCAN_OPEN */ diff --git a/appinventor/lib/blockly/@types/events/type.d.ts b/appinventor/lib/blockly/@types/events/type.d.ts index 2ee208dd7b6..2d67ea53d11 100644 --- a/appinventor/lib/blockly/@types/events/type.d.ts +++ b/appinventor/lib/blockly/@types/events/type.d.ts @@ -27,6 +27,8 @@ export declare enum EventType { VAR_DELETE = "var_delete", /** Type of event that renames a variable. */ VAR_RENAME = "var_rename", + /** Type of event that changes the type of a variable. */ + VAR_TYPE_CHANGE = "var_type_change", /** * Type of generic event that records a UI change. * diff --git a/appinventor/lib/blockly/@types/events/utils.d.ts b/appinventor/lib/blockly/@types/events/utils.d.ts index 3196b99c8e6..c42025ae71b 100644 --- a/appinventor/lib/blockly/@types/events/utils.d.ts +++ b/appinventor/lib/blockly/@types/events/utils.d.ts @@ -129,13 +129,9 @@ declare function enqueueEvent(event: Abstract): void; * cause them to be reordered. * * @param queue Array of events. - * @param forward True if forward (redo), false if backward (undo). - * This parameter is deprecated: true is now the default and - * calling filter with it set to false will in future not be - * supported. * @returns Array of filtered events. */ -export declare function filter(queue: Abstract[], forward?: boolean): Abstract[]; +export declare function filter(queue: Abstract[]): Abstract[]; /** * Modify pending undo events so that when they are fired they don't land * in the undo stack. Called by Workspace.clearUndo. diff --git a/appinventor/lib/blockly/@types/field.d.ts b/appinventor/lib/blockly/@types/field.d.ts index 6e7fff87f73..5cc98d26dfa 100644 --- a/appinventor/lib/blockly/@types/field.d.ts +++ b/appinventor/lib/blockly/@types/field.d.ts @@ -13,8 +13,8 @@ import './events/events_block_change.js'; import type { Block } from './block.js'; import type { Input } from './inputs/input.js'; -import type { IASTNodeLocationSvg } from './interfaces/i_ast_node_location_svg.js'; -import type { IASTNodeLocationWithBlock } from './interfaces/i_ast_node_location_with_block.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; import type { IKeyboardAccessible } from './interfaces/i_keyboard_accessible.js'; import type { IRegistrable } from './interfaces/i_registrable.js'; import { ISerializable } from './interfaces/i_serializable.js'; @@ -45,7 +45,7 @@ export type FieldValidator = (newValue: T) => T | null | undefined; * * @typeParam T - The value stored on the field. */ -export declare abstract class Field implements IASTNodeLocationSvg, IASTNodeLocationWithBlock, IKeyboardAccessible, IRegistrable, ISerializable { +export declare abstract class Field implements IKeyboardAccessible, IRegistrable, ISerializable, IFocusableNode { /** * To overwrite the default value which is set in **Field**, directly update * the prototype. @@ -75,17 +75,18 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * field is not yet initialized. Is *not* guaranteed to be accurate. */ private tooltip; - protected size_: Size; - /** - * Holds the cursors svg element when the cursor is attached to the field. - * This is null if there is no cursor on the field. - */ - private cursorSvg; - /** - * Holds the markers svg element when the marker is attached to the field. - * This is null if there is no marker on the field. - */ - private markerSvg; + /** This field's dimensions. */ + private size; + /** + * Gets the size of this field. Because getSize() and updateSize() have side + * effects, this acts as a shim for subclasses which wish to adjust field + * bounds when setting/getting the size without triggering unwanted rendering + * or other side effects. Note that subclasses must override *both* get and + * set if either is overridden; the implementation may just call directly + * through to super, but it must exist per the JS spec. + */ + protected get size_(): Size; + protected set size_(newValue: Size); /** The rendered field's SVG group element. */ protected fieldGroup_: SVGGElement | null; /** The rendered field's SVG border element. */ @@ -141,8 +142,8 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * case by default so that SERIALIZABLE is backwards compatible. */ SERIALIZABLE: boolean; - /** Mouse cursor style when over the hotspot that initiates the editor. */ - CURSOR: string; + /** The unique ID of this field. */ + private id_; /** * @param value The initial value of the field. * Also accepts Field.SKIP_SETUP if you wish to skip setup (only used by @@ -207,8 +208,10 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * intend because the behavior was kind of hacked in. If you are thinking * about overriding this function, post on the forum with your intended * behavior to see if there's another approach. + * + * @internal */ - protected isFullBlockField(): boolean; + isFullBlockField(): boolean; /** * Create a field border rect element. Not to be overridden by subclasses. * Instead modify the result of the function inside initView, or create a @@ -231,7 +234,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * called by Blockly.Xml. * * @param fieldElement The element containing info about the field's state. - * @internal */ fromXml(fieldElement: Element): void; /** @@ -240,7 +242,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * @param fieldElement The element to populate with info about the field's * state. * @returns The element containing info about the field's state. - * @internal */ toXml(fieldElement: Element): Element; /** @@ -254,7 +255,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * {@link https://developers.devsite.google.com/blockly/guides/create-custom-blocks/fields/customizing-fields/creating#full_serialization_and_backing_data | field serialization docs} * for more information. * @returns JSON serializable state. - * @internal */ saveState(_doFullSerialization?: boolean): any; /** @@ -262,7 +262,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * called by the serialization system. * * @param state The state we want to apply to the field. - * @internal */ loadState(state: any): void; /** @@ -287,8 +286,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS loadLegacyState(callingClass: FieldProto, state: any): boolean; /** * Dispose of all DOM objects and events belonging to this editable field. - * - * @internal */ dispose(): void; /** Add or remove the UI indicating if this field is editable or not. */ @@ -540,8 +537,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * rerender this field and adjust for any sizing changes. * Other fields on the same block will not rerender, because their sizes have * already been recorded. - * - * @internal */ forceRerender(): void; /** @@ -651,14 +646,11 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * Subclasses may override this. * * @returns True if this field has any variable references. - * @internal */ referencesVariables(): boolean; /** * Refresh the variable name referenced by this field if this field references * variables. - * - * @internal */ refreshVariableName(): void; /** @@ -675,12 +667,6 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * @returns True if we should flip in RTL. */ getFlipRtl(): boolean; - /** - * Returns whether or not the field is tab navigable. - * - * @returns True if the field is tab navigable. - */ - isTabNavigable(): boolean; /** * Handles the given keyboard shortcut. * @@ -688,26 +674,16 @@ export declare abstract class Field implements IASTNodeLocationSvg, IAS * @returns True if the shortcut has been handled, false otherwise. */ onShortcut(_shortcut: KeyboardShortcut): boolean; - /** - * Add the cursor SVG to this fields SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the field group. - * @internal - */ - setCursorSvg(cursorSvg: SVGElement): void; - /** - * Add the marker SVG to this fields SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the field group. - * @internal - */ - setMarkerSvg(markerSvg: SVGElement): void; - /** - * Redraw any attached marker or cursor svgs if needed. - * - * @internal - */ - updateMarkers_(): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; /** * Subclasses should reimplement this method to construct their Field * subclass from a JSON arg object. diff --git a/appinventor/lib/blockly/@types/field_checkbox.d.ts b/appinventor/lib/blockly/@types/field_checkbox.d.ts index 3e860b53090..8781234c03d 100644 --- a/appinventor/lib/blockly/@types/field_checkbox.d.ts +++ b/appinventor/lib/blockly/@types/field_checkbox.d.ts @@ -24,10 +24,6 @@ export declare class FieldCheckbox extends Field { * are not. Editable fields should also be serializable. */ SERIALIZABLE: boolean; - /** - * Mouse cursor style when over the hotspot that initiates editability. - */ - CURSOR: string; /** * NOTE: The default value is set in `Field`, so maintain that value instead * of overwriting it here or in the constructor. diff --git a/appinventor/lib/blockly/@types/field_dropdown.d.ts b/appinventor/lib/blockly/@types/field_dropdown.d.ts index ec0257a9cd4..dbe28dfd76d 100644 --- a/appinventor/lib/blockly/@types/field_dropdown.d.ts +++ b/appinventor/lib/blockly/@types/field_dropdown.d.ts @@ -10,13 +10,10 @@ import { MenuItem } from './menuitem.js'; * Class for an editable dropdown field. */ export declare class FieldDropdown extends Field { - /** Horizontal distance that a checkmark overhangs the dropdown. */ - static CHECKMARK_OVERHANG: number; /** - * Maximum height of the dropdown menu, as a percentage of the viewport - * height. + * Magic constant used to represent a separator in a list of dropdown items. */ - static MAX_MENU_HEIGHT_VH: number; + static readonly SEPARATOR = "separator"; static ARROW_CHAR: string; /** A reference to the currently selected menu item. */ private selectedMenuItem; @@ -35,8 +32,6 @@ export declare class FieldDropdown extends Field { * are not. Editable fields should also be serializable. */ SERIALIZABLE: boolean; - /** Mouse cursor style when over the hotspot that initiates the editor. */ - CURSOR: string; protected menuGenerator_?: MenuGenerator; /** A cache of the most recently generated options. */ private generatedOptions; @@ -149,6 +144,13 @@ export declare class FieldDropdown extends Field { * @throws {TypeError} If generated options are incorrectly structured. */ getOptions(useCache?: boolean): MenuOption[]; + /** + * Update the options on this dropdown. This will reset the selected item to + * the first item in the list. + * + * @param menuGenerator The array of options or a generator function. + */ + setOptions(menuGenerator: MenuGenerator): void; /** * Ensure that the input value is a valid language-neutral option. * @@ -189,7 +191,13 @@ export declare class FieldDropdown extends Field { /** * Use the `getText_` developer hook to override the field's text * representation. Get the selected option text. If the selected option is - * an image we return the image alt text. + * an image we return the image alt text. If the selected option is + * an HTMLElement, return the title, ariaLabel, or innerText of the + * element. + * + * If you use HTMLElement options in Node.js and call this function, + * ensure that you are supplying an implementation of HTMLElement, + * such as through jsdom-global. * * @returns Selected option text. */ @@ -241,11 +249,13 @@ export interface ImageProperties { height: number; } /** - * An individual option in the dropdown menu. The first element is the human- - * readable value (text or image), and the second element is the language- - * neutral value. + * An individual option in the dropdown menu. Can be either the string literal + * `separator` for a menu separator item, or an array for normal action menu + * items. In the latter case, the first element is the human-readable value + * (text, ImageProperties object, or HTML element), and the second element is + * the language-neutral value. */ -export type MenuOption = [string | ImageProperties, string]; +export type MenuOption = [string | ImageProperties | HTMLElement, string] | 'separator'; /** * A function that generates an array of menu options for FieldDropdown * or its descendants. diff --git a/appinventor/lib/blockly/@types/field_image.d.ts b/appinventor/lib/blockly/@types/field_image.d.ts index 90c19bcd123..f032515d290 100644 --- a/appinventor/lib/blockly/@types/field_image.d.ts +++ b/appinventor/lib/blockly/@types/field_image.d.ts @@ -9,7 +9,6 @@ * @class */ import { Field, FieldConfig } from './field.js'; -import { Size } from './utils/size.js'; /** * Class for an image on a block. */ @@ -19,7 +18,6 @@ export declare class FieldImage extends Field { * of the field. */ private static readonly Y_PADDING; - protected size_: Size; protected readonly imageHeight: number; /** The function to be called when this field is clicked. */ private clickHandler; @@ -94,6 +92,12 @@ export declare class FieldImage extends Field { * @param alt New alt text. */ setAlt(alt: string | null): void; + /** + * Check whether this field should be clickable. + * + * @returns Whether this field is clickable. + */ + isClickable(): boolean; /** * If field click is called, and click handler defined, * call the handler. diff --git a/appinventor/lib/blockly/@types/field_input.d.ts b/appinventor/lib/blockly/@types/field_input.d.ts index 8394c55da37..8f8679b7f33 100644 --- a/appinventor/lib/blockly/@types/field_input.d.ts +++ b/appinventor/lib/blockly/@types/field_input.d.ts @@ -48,8 +48,8 @@ export declare abstract class FieldInput extends Field extends Field extends Field | null, config?: FieldInputConfig); protected configure_(config: FieldInputConfig): void; initView(): void; - protected isFullBlockField(): boolean; + isFullBlockField(): boolean; /** * Called by setValue if the text input is not valid. If the field is * currently being edited it reverts value of the field to the previous @@ -143,8 +146,12 @@ export declare abstract class FieldInput extends Field extends Field extends Field extends Field { * @returns The newly created number input editor. */ protected widgetCreate_(): HTMLInputElement; + /** + * Initialize the field's DOM. + * + * @override + */ + initView(): void; /** * Construct a FieldNumber from a JSON arg object. * diff --git a/appinventor/lib/blockly/@types/field_registry.d.ts b/appinventor/lib/blockly/@types/field_registry.d.ts index e3bdb196e35..25a79454cc5 100644 --- a/appinventor/lib/blockly/@types/field_registry.d.ts +++ b/appinventor/lib/blockly/@types/field_registry.d.ts @@ -48,8 +48,8 @@ export interface RegistrableField { * @param type The field type name as used in the JSON definition. * @param fieldClass The field class containing a fromJson function that can * construct an instance of the field. - * @throws {Error} if the type name is empty, the field is already registered, - * or the fieldClass is not an object containing a fromJson function. + * @throws {Error} if the type name is empty or the fieldClass is not an object + * containing a fromJson function. */ export declare function register(type: string, fieldClass: RegistrableField): void; /** diff --git a/appinventor/lib/blockly/@types/field_textinput.d.ts b/appinventor/lib/blockly/@types/field_textinput.d.ts index 1c93f649bc9..2d2e9f919ba 100644 --- a/appinventor/lib/blockly/@types/field_textinput.d.ts +++ b/appinventor/lib/blockly/@types/field_textinput.d.ts @@ -30,6 +30,7 @@ export declare class FieldTextInput extends FieldInput { * for a list of properties this parameter supports. */ constructor(value?: string | typeof Field.SKIP_SETUP, validator?: FieldTextInputValidator | null, config?: FieldTextInputConfig); + initView(): void; /** * Ensure that the input value casts to a valid string. * diff --git a/appinventor/lib/blockly/@types/field_variable.d.ts b/appinventor/lib/blockly/@types/field_variable.d.ts index 989df78dc6d..ffe50c17600 100644 --- a/appinventor/lib/blockly/@types/field_variable.d.ts +++ b/appinventor/lib/blockly/@types/field_variable.d.ts @@ -12,10 +12,9 @@ import './events/events_block_change.js'; import type { Block } from './block.js'; import { Field, FieldConfig } from './field.js'; import { FieldDropdown, FieldDropdownValidator, MenuGenerator, MenuOption } from './field_dropdown.js'; +import { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import type { Menu } from './menu.js'; import type { MenuItem } from './menuitem.js'; -import { Size } from './utils/size.js'; -import { VariableModel } from './variable_model.js'; /** * Class for a variable's dropdown field. */ @@ -29,7 +28,6 @@ export declare class FieldVariable extends FieldDropdown { * dropdown. */ variableTypes: string[] | null; - protected size_: Size; /** The variable model associated with this field. */ private variable; /** @@ -47,7 +45,8 @@ export declare class FieldVariable extends FieldDropdown { * field's value. Takes in a variable ID & returns a validated variable * ID, or null to abort the change. * @param variableTypes A list of the types of variables to include in the - * dropdown. Will only be used if config is not provided. + * dropdown. Pass `null` to include all types that exist on the + * workspace. Will only be used if config is not provided. * @param defaultType The type of variable to create if this field's value * is not explicitly set. Defaults to ''. Will only be used if config * is not provided. @@ -56,7 +55,7 @@ export declare class FieldVariable extends FieldDropdown { * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/variable#creation} * for a list of properties this parameter supports. */ - constructor(varName: string | null | typeof Field.SKIP_SETUP, validator?: FieldVariableValidator, variableTypes?: string[], defaultType?: string, config?: FieldVariableConfig); + constructor(varName: string | null | typeof Field.SKIP_SETUP, validator?: FieldVariableValidator, variableTypes?: string[] | null, defaultType?: string, config?: FieldVariableConfig); /** * Configure the field based on the given map of options. * @@ -69,6 +68,7 @@ export declare class FieldVariable extends FieldDropdown { * a variable rather than let the value be invalid. */ initModel(): void; + initView(): void; shouldAddBorderRect_(): boolean; /** * Initialize this field based on the given XML. @@ -129,7 +129,13 @@ export declare class FieldVariable extends FieldDropdown { * @returns The selected variable, or null if none was selected. * @internal */ - getVariable(): VariableModel | null; + getVariable(): IVariableModel | null; + /** + * Gets the type of this field's default variable. + * + * @returns The default type for this variable field. + */ + protected getDefaultType(): string; /** * Gets the validation function for this field, or null if not set. * Returns null if the variable is not set, because validators should not @@ -166,7 +172,6 @@ export declare class FieldVariable extends FieldDropdown { * Return a list of variable types to include in the dropdown. * * @returns Array of variable types. - * @throws {Error} if variableTypes is an empty array. */ private getVariableTypes; /** diff --git a/appinventor/lib/blockly/@types/flyout_base.d.ts b/appinventor/lib/blockly/@types/flyout_base.d.ts index 7d7a1626c19..0e500b16d6d 100644 --- a/appinventor/lib/blockly/@types/flyout_base.d.ts +++ b/appinventor/lib/blockly/@types/flyout_base.d.ts @@ -3,25 +3,29 @@ * Copyright 2011 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +/** + * Flyout tray containing blocks which may be created. + * + * @class + */ import { BlockSvg } from './block_svg.js'; import { DeleteArea } from './delete_area.js'; -import { FlyoutButton } from './flyout_button.js'; +import { FlyoutItem } from './flyout_item.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 type { Options } from './options.js'; import * as blocks from './serialization/blocks.js'; import { Coordinate } from './utils/coordinate.js'; import { Svg } from './utils/svg.js'; import * as toolbox from './utils/toolbox.js'; import { WorkspaceSvg } from './workspace_svg.js'; -declare enum FlyoutItemType { - BLOCK = "block", - BUTTON = "button" -} /** * Class for a flyout. */ -export declare abstract class Flyout extends DeleteArea implements IAutoHideable, IFlyout { +export declare abstract class Flyout extends DeleteArea implements IAutoHideable, IFlyout, IFocusableNode { /** * Position the flyout. */ @@ -48,12 +52,11 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable y?: number; }): void; /** - * Lay out the blocks in the flyout. + * Lay out the elements in the flyout. * - * @param contents The blocks and buttons to lay out. - * @param gaps The visible gaps between blocks. + * @param contents The flyout elements to lay out. */ - protected abstract layout_(contents: FlyoutItem[], gaps: number[]): void; + protected abstract layout_(contents: FlyoutItem[]): void; /** * Scroll the flyout. * @@ -61,8 +64,8 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable */ protected abstract wheel_(e: WheelEvent): void; /** - * Compute height of flyout. Position mat under each block. - * For RTL: Lay out the blocks right-aligned. + * Compute bounds of flyout. + * For RTL: Lay out the elements right-aligned. */ protected abstract reflowInternal_(): void; /** @@ -81,10 +84,6 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable * Scroll the flyout to the beginning of its contents. */ abstract scrollToStart(): void; - /** - * The type of a flyout content item. - */ - static FlyoutItemType: typeof FlyoutItemType; protected workspace_: WorkspaceSvg; RTL: boolean; /** @@ -102,36 +101,18 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable private boundEvents; /** * Function that will be registered as a change listener on the workspace - * to reflow when blocks in the flyout workspace change. + * to reflow when elements in the flyout workspace change. */ private reflowWrapper; /** - * Function that disables blocks in the flyout based on max block counts - * allowed in the target workspace. Registered as a change listener on the - * target workspace. - */ - private filterWrapper; - /** - * List of background mats that lurk behind each block to catch clicks - * landing in the blocks' lakes and bays. - */ - private mats; - /** - * List of visible buttons. + * If true, prevents the reflow wrapper from running. Used to prevent infinite + * recursion. */ - protected buttons_: FlyoutButton[]; + private inhibitReflowWrapper; /** - * List of visible buttons and blocks. + * List of flyout elements. */ protected contents: FlyoutItem[]; - /** - * List of event listeners. - */ - private listeners; - /** - * List of blocks that should always be disabled. - */ - private permanentlyDisabled; protected readonly tabWidth_: number; /** * The target workspace. @@ -139,10 +120,6 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable * @internal */ targetWorkspace: WorkspaceSvg; - /** - * A list of blocks that can be reused. - */ - private recycledBlocks; /** * Does the flyout automatically close when a block is created? */ @@ -155,7 +132,6 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable * Whether the workspace containing this flyout is visible. */ private containerVisible; - protected rectMap_: WeakMap; /** * Corner radius of the flyout background. */ @@ -205,6 +181,11 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable * The root SVG group for the button or label. */ protected svgGroup_: SVGGElement | null; + /** + * Map from flyout content type to the corresponding inflater class + * responsible for creating concrete instances of the content type. + */ + protected inflaters: Map; /** * @param workspaceOptions Dictionary of options for the * workspace. @@ -291,13 +272,13 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable */ setContainerVisible(visible: boolean): void; /** - * Get the list of buttons and blocks of the current flyout. + * Get the list of elements of the current flyout. * - * @returns The array of flyout buttons and blocks. + * @returns The array of flyout elements. */ getContents(): FlyoutItem[]; /** - * Store the list of buttons and blocks on the flyout. + * Store the list of elements on the flyout. * * @param contents - The array of items for the flyout. */ @@ -334,9 +315,21 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable * * @param parsedContent The array * of objects to show in the flyout. - * @returns The list of contents and gaps needed to lay out the flyout. + * @returns The list of contents needed to lay out the flyout. */ private createFlyoutInfo; + /** + * Updates and returns the provided list of flyout contents to flatten + * separators as needed. + * + * When multiple separators occur one after another, the value of the last one + * takes precedence and the earlier separators in the group are removed. + * + * @param contents The list of flyout contents to flatten separators in. + * @returns An updated list of flyout contents with only one separator between + * each non-separator item. + */ + protected normalizeSeparators(contents: FlyoutItem[]): FlyoutItem[]; /** * Gets the flyout definition for the dynamic category. * @@ -346,89 +339,9 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable */ private getDynamicCategoryContents; /** - * Creates a flyout button or a flyout label. - * - * @param btnInfo The object holding information about a button or a label. - * @param isLabel True if the button is a label, false otherwise. - * @returns The object used to display the button in the - * flyout. - */ - private createButton; - /** - * Create a block from the xml and permanently disable any blocks that were - * defined as disabled. - * - * @param blockInfo The info of the block. - * @returns The block created from the blockInfo. - */ - private createFlyoutBlock; - /** - * Returns a block from the array of recycled blocks with the given type, or - * undefined if one cannot be found. - * - * @param blockType The type of the block to try to recycle. - * @returns The recycled block, or undefined if - * one could not be recycled. - */ - private getRecycledBlock; - /** - * Adds a gap in the flyout based on block info. - * - * @param blockInfo Information about a block. - * @param gaps The list of gaps between items in the flyout. - * @param defaultGap The default gap between one element and the - * next. - */ - private addBlockGap; - /** - * Add the necessary gap in the flyout for a separator. - * - * @param sepInfo The object holding - * information about a separator. - * @param gaps The list gaps between items in the flyout. - * @param defaultGap The default gap between the button and next - * element. - */ - private addSeparatorGap; - /** - * Delete blocks, mats and buttons from a previous showing of the flyout. + * Delete elements from a previous showing of the flyout. */ private clearOldBlocks; - /** - * Empties all of the recycled blocks, properly disposing of them. - */ - private emptyRecycledBlocks; - /** - * Returns whether the given block can be recycled or not. - * - * @param _block The block to check for recyclability. - * @returns True if the block can be recycled. False otherwise. - */ - protected blockIsRecyclable_(_block: BlockSvg): boolean; - /** - * Puts a previously created block into the recycle bin and moves it to the - * top of the workspace. Used during large workspace swaps to limit the number - * of new DOM elements we need to create. - * - * @param block The block to recycle. - */ - private recycleBlock; - /** - * Add listeners to a block that has been added to the flyout. - * - * @param root The root node of the SVG group the block is in. - * @param block The block to add listeners for. - * @param rect The invisible rectangle under the block that acts - * as a mat for that block. - */ - protected addBlockListeners_(root: SVGElement, block: BlockSvg, rect: SVGElement): void; - /** - * Handle a pointerdown on an SVG block in a non-closing flyout. - * - * @param block The flyout block to copy. - * @returns Function to call when block is clicked. - */ - private blockMouseDown; /** * Pointer down on the flyout background. Start a vertical scroll drag. * @@ -455,85 +368,86 @@ export declare abstract class Flyout extends DeleteArea implements IAutoHideable */ createBlock(originalBlock: BlockSvg): BlockSvg; /** - * Initialize the given button: move it to the correct location, - * add listeners, etc. + * Reflow flyout contents. + */ + reflow(): void; + /** + * @returns True if this flyout may be scrolled with a scrollbar or + * by dragging. + * @internal + */ + isScrollable(): boolean; + /** + * Serialize a block to JSON. + * + * @param block The block to serialize. + * @returns A serialized representation of the block. + */ + protected serializeBlock(block: BlockSvg): blocks.State; + /** + * Positions a block on the target workspace. * - * @param button The button to initialize and place. - * @param x The x position of the cursor during this layout pass. - * @param y The y position of the cursor during this layout pass. + * @param oldBlock The flyout block being copied. + * @param block The block to posiiton. */ - protected initFlyoutButton_(button: FlyoutButton, x: number, y: number): void; + private positionNewBlock; /** - * Create and place a rectangle corresponding to the given block. + * Returns the inflater responsible for constructing items of the given type. * - * @param block The block to associate the rect to. - * @param x The x position of the cursor during this layout pass. - * @param y The y position of the cursor during this layout pass. - * @param blockHW The height and width of - * the block. - * @param index The index into the mats list where this rect should - * be placed. - * @returns Newly created SVG element for the rectangle behind - * the block. + * @param type The type of flyout content item to provide an inflater for. + * @returns An inflater object for the given type, or null if no inflater + * is registered for that type. */ - protected createRect_(block: BlockSvg, x: number, y: number, blockHW: { - height: number; - width: number; - }, index: number): SVGElement; + protected getInflaterForType(type: string): IFlyoutInflater | null; /** - * Move a rectangle to sit exactly behind a block, taking into account tabs, - * hats, and any other protrusions we invent. + * See IFocusableNode.getFocusableElement. * - * @param rect The rectangle to move directly behind the block. - * @param block The block the rectangle should be behind. + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - protected moveRectToBlock_(rect: SVGElement, block: BlockSvg): void; + getFocusableElement(): HTMLElement | SVGElement; /** - * Filter the blocks on the flyout to disable the ones that are above the - * capacity limit. For instance, if the user may only place two more blocks - * on the workspace, an "a + b" block that has two shadow blocks would be - * disabled. + * See IFocusableNode.getFocusableTree. + * + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - private filterForCapacity; + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; /** - * Reflow blocks and their mats. + * See IFocusableNode.getRootFocusableNode. + * + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - reflow(): void; + getRootFocusableNode(): IFocusableNode; /** - * @returns True if this flyout may be scrolled with a scrollbar or - * by dragging. - * @internal + * See IFocusableNode.getRestoredFocusableNode. + * + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - isScrollable(): boolean; + getRestoredFocusableNode(_previousNode: IFocusableNode | null): IFocusableNode | null; /** - * Copy a block from the flyout to the workspace and position it correctly. + * See IFocusableNode.getNestedTrees. * - * @param oldBlock The flyout block to copy. - * @returns The new block in the main workspace. + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - private placeNewBlock; + getNestedTrees(): Array; /** - * Serialize a block to JSON. + * See IFocusableNode.lookUpFocusableNode. * - * @param block The block to serialize. - * @returns A serialized representation of the block. + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - protected serializeBlock(block: BlockSvg): blocks.State; + lookUpFocusableNode(_id: string): IFocusableNode | null; + /** See IFocusableTree.onTreeFocus. */ + onTreeFocus(_node: IFocusableNode, _previousTree: IFocusableTree | null): void; /** - * Positions a block on the target workspace. + * See IFocusableNode.onTreeBlur. * - * @param oldBlock The flyout block being copied. - * @param block The block to posiiton. + * @deprecated v12: Use the Flyout's workspace for focus operations, instead. */ - private positionNewBlock; -} -/** - * A flyout content item. - */ -export interface FlyoutItem { - type: FlyoutItemType; - button?: FlyoutButton | undefined; - block?: BlockSvg | undefined; + onTreeBlur(_nextTree: IFocusableTree | null): void; } -export {}; //# sourceMappingURL=flyout_base.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/flyout_button.d.ts b/appinventor/lib/blockly/@types/flyout_button.d.ts index 71880ab9f04..e623abf6b39 100644 --- a/appinventor/lib/blockly/@types/flyout_button.d.ts +++ b/appinventor/lib/blockly/@types/flyout_button.d.ts @@ -3,19 +3,18 @@ * Copyright 2016 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -/** - * Class for a button in the flyout. - * - * @class - */ -import type { IASTNodeLocationSvg } from './blockly.js'; +import type { IBoundedElement } from './interfaces/i_bounded_element.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; +import type { IRenderedElement } from './interfaces/i_rendered_element.js'; import { Coordinate } from './utils/coordinate.js'; +import { Rect } from './utils/rect.js'; import type * as toolbox from './utils/toolbox.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** * Class for a button or label in the flyout. */ -export declare class FlyoutButton implements IASTNodeLocationSvg { +export declare class FlyoutButton implements IBoundedElement, IRenderedElement, IFocusableNode { private readonly workspace; private readonly targetWorkspace; private readonly isFlyoutLabel; @@ -25,11 +24,13 @@ export declare class FlyoutButton implements IASTNodeLocationSvg { static TEXT_MARGIN_Y: number; /** The radius of the flyout button's borders. */ static BORDER_RADIUS: number; + /** The key to the function called when this button is activated. */ + readonly callbackKey: string; private readonly text; private readonly position; - private readonly callbackKey; private readonly cssClass; /** Mouse up event data. */ + private onMouseDownWrapper; private onMouseUpWrapper; info: toolbox.ButtonOrLabelInfo; /** The width of the button's rect. */ @@ -45,6 +46,8 @@ export declare class FlyoutButton implements IASTNodeLocationSvg { * This is null if there is no cursor on the button. */ cursorSvg: SVGElement | null; + /** The unique ID for this FlyoutButton. */ + private id; /** * @param workspace The workspace in which to place this button. * @param targetWorkspace The flyout's target workspace. @@ -53,11 +56,6 @@ export declare class FlyoutButton implements IASTNodeLocationSvg { * @internal */ constructor(workspace: WorkspaceSvg, targetWorkspace: WorkspaceSvg, json: toolbox.ButtonOrLabelInfo, isFlyoutLabel: boolean); - /** - * Create the button elements. - * - * @returns The button's SVG group. - */ createDom(): SVGElement; /** Correctly position the flyout button and make it visible. */ show(): void; @@ -70,6 +68,14 @@ export declare class FlyoutButton implements IASTNodeLocationSvg { * @param y The new y coordinate. */ moveTo(x: number, y: number): void; + /** + * Move the element by a relative offset. + * + * @param dx Horizontal offset in workspace units. + * @param dy Vertical offset in workspace units. + * @param _reason Why is this move happening? 'user', 'bump', 'snap'... + */ + moveBy(dx: number, dy: number, _reason?: string[]): void; /** @returns Whether or not the button is a label. */ isLabel(): boolean; /** @@ -79,6 +85,13 @@ export declare class FlyoutButton implements IASTNodeLocationSvg { * @internal */ getPosition(): Coordinate; + /** + * Returns the coordinates of a bounded element describing the dimensions of + * the element. Coordinate system: workspace coordinates. + * + * @returns Object with coordinates of the bounded element. + */ + getBoundingRectangle(): Rect; /** @returns Text of the button. */ getButtonText(): string; /** @@ -102,17 +115,26 @@ export declare class FlyoutButton implements IASTNodeLocationSvg { * group. */ setCursorSvg(cursorSvg: SVGElement): void; - /** - * Required by IASTNodeLocationSvg, but not used. A marker cannot be set on a - * button. If the 'mark' shortcut is used on a button, its associated callback - * function is triggered. - */ - setMarkerSvg(): void; /** * Do something when the button is clicked. * * @param e Pointer up event. */ private onMouseUp; + private onMouseDown; + /** + * @returns The root SVG element of this rendered element. + */ + getSvgRoot(): SVGGElement; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; } //# sourceMappingURL=flyout_button.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/flyout_horizontal.d.ts b/appinventor/lib/blockly/@types/flyout_horizontal.d.ts index f956f0d6c80..daba074aebf 100644 --- a/appinventor/lib/blockly/@types/flyout_horizontal.d.ts +++ b/appinventor/lib/blockly/@types/flyout_horizontal.d.ts @@ -3,7 +3,8 @@ * Copyright 2017 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import { Flyout, FlyoutItem } from './flyout_base.js'; +import { Flyout } from './flyout_base.js'; +import type { FlyoutItem } from './flyout_item.js'; import type { Options } from './options.js'; import type { Coordinate } from './utils/coordinate.js'; import { Rect } from './utils/rect.js'; @@ -56,10 +57,9 @@ export declare class HorizontalFlyout extends Flyout { /** * Lay out the blocks in the flyout. * - * @param contents The blocks and buttons to lay out. - * @param gaps The visible gaps between blocks. + * @param contents The flyout items to lay out. */ - protected layout_(contents: FlyoutItem[], gaps: number[]): void; + protected layout_(contents: FlyoutItem[]): void; /** * Determine if a drag delta is toward the workspace, based on the position * and orientation of the flyout. This is used in determineDragIntention_ to diff --git a/appinventor/lib/blockly/@types/flyout_item.d.ts b/appinventor/lib/blockly/@types/flyout_item.d.ts new file mode 100644 index 00000000000..a5224088104 --- /dev/null +++ b/appinventor/lib/blockly/@types/flyout_item.d.ts @@ -0,0 +1,26 @@ +import type { IBoundedElement } from './interfaces/i_bounded_element.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +/** + * Representation of an item displayed in a flyout. + */ +export declare class FlyoutItem { + private element; + private type; + /** + * Creates a new FlyoutItem. + * + * @param element The element that will be displayed in the flyout. + * @param type The type of element. Should correspond to the type of the + * flyout inflater that created this object. + */ + constructor(element: IBoundedElement & IFocusableNode, type: string); + /** + * Returns the element displayed in the flyout. + */ + getElement(): IBoundedElement & IFocusableNode; + /** + * Returns the type of flyout element this item represents. + */ + getType(): string; +} +//# sourceMappingURL=flyout_item.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/flyout_navigator.d.ts b/appinventor/lib/blockly/@types/flyout_navigator.d.ts new file mode 100644 index 00000000000..e7840e43503 --- /dev/null +++ b/appinventor/lib/blockly/@types/flyout_navigator.d.ts @@ -0,0 +1,11 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFlyout } from './interfaces/i_flyout.js'; +import { Navigator } from './navigator.js'; +export declare class FlyoutNavigator extends Navigator { + constructor(flyout: IFlyout); +} +//# sourceMappingURL=flyout_navigator.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/flyout_separator.d.ts b/appinventor/lib/blockly/@types/flyout_separator.d.ts new file mode 100644 index 00000000000..07ea31850a4 --- /dev/null +++ b/appinventor/lib/blockly/@types/flyout_separator.d.ts @@ -0,0 +1,64 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IBoundedElement } from './interfaces/i_bounded_element.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; +import { Rect } from './utils/rect.js'; +/** + * Representation of a gap between elements in a flyout. + */ +export declare class FlyoutSeparator implements IBoundedElement, IFocusableNode { + private gap; + private axis; + private x; + private y; + /** + * Creates a new separator. + * + * @param gap The amount of space this separator should occupy. + * @param axis The axis along which this separator occupies space. + */ + constructor(gap: number, axis: SeparatorAxis); + /** + * Returns the bounding box of this separator. + * + * @returns The bounding box of this separator. + */ + getBoundingRectangle(): Rect; + /** + * Repositions this separator. + * + * @param dx The distance to move this separator on the X axis. + * @param dy The distance to move this separator on the Y axis. + * @param _reason The reason this move was initiated. + */ + moveBy(dx: number, dy: number, _reason?: string[]): void; + /** + * Returns false to prevent this separator from being navigated to by the + * keyboard. + * + * @returns False. + */ + isNavigable(): boolean; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; +} +/** + * Representation of an axis along which a separator occupies space. + */ +export declare const enum SeparatorAxis { + X = "x", + Y = "y" +} +//# sourceMappingURL=flyout_separator.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/flyout_vertical.d.ts b/appinventor/lib/blockly/@types/flyout_vertical.d.ts index 925e0353589..a3dec11112f 100644 --- a/appinventor/lib/blockly/@types/flyout_vertical.d.ts +++ b/appinventor/lib/blockly/@types/flyout_vertical.d.ts @@ -3,7 +3,8 @@ * Copyright 2017 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import { Flyout, FlyoutItem } from './flyout_base.js'; +import { Flyout } from './flyout_base.js'; +import type { FlyoutItem } from './flyout_item.js'; import type { Options } from './options.js'; import type { Coordinate } from './utils/coordinate.js'; import { Rect } from './utils/rect.js'; @@ -57,10 +58,9 @@ export declare class VerticalFlyout extends Flyout { /** * Lay out the blocks in the flyout. * - * @param contents The blocks and buttons to lay out. - * @param gaps The visible gaps between blocks. + * @param contents The flyout items to lay out. */ - protected layout_(contents: FlyoutItem[], gaps: number[]): void; + protected layout_(contents: FlyoutItem[]): void; /** * Determine if a drag delta is toward the workspace, based on the position * and orientation of the flyout. This is used in determineDragIntention_ to @@ -80,7 +80,7 @@ export declare class VerticalFlyout extends Flyout { */ getClientRect(): Rect | null; /** - * Compute width of flyout. toolbox.Position mat under each block. + * Compute width of flyout. * For RTL: Lay out the blocks and buttons to be right-aligned. */ protected reflowInternal_(): void; diff --git a/appinventor/lib/blockly/@types/focus_manager.d.ts b/appinventor/lib/blockly/@types/focus_manager.d.ts new file mode 100644 index 00000000000..4723555e341 --- /dev/null +++ b/appinventor/lib/blockly/@types/focus_manager.d.ts @@ -0,0 +1,266 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; +/** + * Type declaration for returning focus to FocusManager upon completing an + * ephemeral UI flow (such as a dialog). + * + * See FocusManager.takeEphemeralFocus for more details. + */ +export type ReturnEphemeralFocus = () => void; +/** + * A per-page singleton that manages Blockly focus across one or more + * IFocusableTrees, and bidirectionally synchronizes this focus with the DOM. + * + * Callers that wish to explicitly change input focus for select Blockly + * components on the page should use the focus functions in this manager. + * + * The manager is responsible for handling focus events from the DOM (which may + * may arise from users clicking on page elements) and ensuring that + * corresponding IFocusableNodes are clearly marked as actively/passively + * highlighted in the same way that this would be represented with calls to + * focusNode(). + */ +export declare class FocusManager { + /** + * The CSS class assigned to IFocusableNode elements that presently have + * active DOM and Blockly focus. + * + * This should never be used directly. Instead, rely on FocusManager to ensure + * nodes have active focus (either automatically through DOM focus or manually + * through the various focus* methods provided by this class). + * + * It's recommended to not query using this class name, either. Instead, use + * FocusableTreeTraverser or IFocusableTree's methods to find a specific node. + */ + static readonly ACTIVE_FOCUS_NODE_CSS_CLASS_NAME = "blocklyActiveFocus"; + /** + * The CSS class assigned to IFocusableNode elements that presently have + * passive focus (that is, they were the most recent node in their relative + * tree to have active focus--see ACTIVE_FOCUS_NODE_CSS_CLASS_NAME--and will + * receive active focus again if their surrounding tree is requested to become + * focused, i.e. using focusTree below). + * + * See ACTIVE_FOCUS_NODE_CSS_CLASS_NAME for caveats and limitations around + * using this constant directly (generally it never should need to be used). + */ + static readonly PASSIVE_FOCUS_NODE_CSS_CLASS_NAME = "blocklyPassiveFocus"; + private focusedNode; + private previouslyFocusedNode; + private registeredTrees; + private currentlyHoldsEphemeralFocus; + private lockFocusStateChanges; + private recentlyLostAllFocus; + private isUpdatingFocusedNode; + constructor(addGlobalEventListener: (type: string, listener: EventListener) => void); + /** + * Registers a new IFocusableTree for automatic focus management. + * + * If the tree currently has an element with DOM focus, it will not affect the + * internal state in this manager until the focus changes to a new, + * now-monitored element/node. + * + * This function throws if the provided tree is already currently registered + * in this manager. Use isRegistered to check in cases when it can't be + * certain whether the tree has been registered. + * + * The tree's registration can be customized to configure automatic tab stops. + * This specifically provides capability for the user to be able to tab + * navigate to the root of the tree but only when the tree doesn't hold active + * focus. If this functionality is disabled then the tree's root will + * automatically be made focusable (but not tabbable) when it is first focused + * in the same way as any other focusable node. + * + * @param tree The IFocusableTree to register. + * @param rootShouldBeAutoTabbable Whether the root of this tree should be + * added as a top-level page tab stop when it doesn't hold active focus. + */ + registerTree(tree: IFocusableTree, rootShouldBeAutoTabbable?: boolean): void; + /** + * Returns whether the specified tree has already been registered in this + * manager using registerTree and hasn't yet been unregistered using + * unregisterTree. + */ + isRegistered(tree: IFocusableTree): boolean; + /** + * Returns the TreeRegistration for the specified tree, or null if the tree is + * not currently registered. + */ + private lookUpRegistration; + /** + * Unregisters a IFocusableTree from automatic focus management. + * + * If the tree had a previous focused node, it will have its highlight + * removed. This function does NOT change DOM focus. + * + * This function throws if the provided tree is not currently registered in + * this manager. + * + * This function will reset the tree's root element tabindex if the tree was + * registered with automatic tab management. + */ + unregisterTree(tree: IFocusableTree): void; + /** + * Returns the current IFocusableTree that has focus, or null if none + * currently do. + * + * Note also that if ephemeral focus is currently captured (e.g. using + * takeEphemeralFocus) then the returned tree here may not currently have DOM + * focus. + */ + getFocusedTree(): IFocusableTree | null; + /** + * Returns the current IFocusableNode with focus (which is always tied to a + * focused IFocusableTree), or null if there isn't one. + * + * Note that this function will maintain parity with + * IFocusableTree.getFocusedNode(). That is, if a tree itself has focus but + * none of its non-root children do, this will return null but + * getFocusedTree() will not. + * + * Note also that if ephemeral focus is currently captured (e.g. using + * takeEphemeralFocus) then the returned node here may not currently have DOM + * focus. + */ + getFocusedNode(): IFocusableNode | null; + /** + * Focuses the specific IFocusableTree. This either means restoring active + * focus to the tree's passively focused node, or focusing the tree's root + * node. + * + * Note that if the specified tree already has a focused node then this will + * not change any existing focus (unless that node has passive focus, then it + * will be restored to active focus). + * + * See getFocusedNode for details on how other nodes are affected. + * + * @param focusableTree The tree that should receive active + * focus. + */ + focusTree(focusableTree: IFocusableTree): void; + /** + * Focuses DOM input on the specified node, and marks it as actively focused. + * + * Any previously focused node will be updated to be passively highlighted (if + * it's in a different focusable tree) or blurred (if it's in the same one). + * + * **Important**: If the provided node is not able to be focused (e.g. its + * canBeFocused() method returns false), it will be ignored and any existing + * focus state will remain unchanged. + * + * Note that this may update the specified node's element's tabindex to ensure + * that it can be properly read out by screenreaders while focused. + * + * The focused node will not be automatically scrolled into view. + * + * @param focusableNode The node that should receive active focus. + */ + focusNode(focusableNode: IFocusableNode): void; + /** + * Ephemerally captures focus for a specific element until the returned lambda + * is called. This is expected to be especially useful for ephemeral UI flows + * like dialogs. + * + * IMPORTANT: the returned lambda *must* be called, otherwise automatic focus + * will no longer work anywhere on the page. It is highly recommended to tie + * the lambda call to the closure of the corresponding UI so that if input is + * manually changed to an element outside of the ephemeral UI, the UI should + * close and automatic input restored. Note that this lambda must be called + * exactly once and that subsequent calls will throw an error. + * + * Note that the manager will continue to track DOM input signals even when + * ephemeral focus is active, but it won't actually change node state until + * the returned lambda is called. Additionally, only 1 ephemeral focus context + * can be active at any given time (attempting to activate more than one + * simultaneously will result in an error being thrown). + * + * This method does not scroll the ephemerally focused element into view. + */ + takeEphemeralFocus(focusableElement: HTMLElement | SVGElement): ReturnEphemeralFocus; + /** + * @returns whether something is currently holding ephemeral focus + */ + ephemeralFocusTaken(): boolean; + /** + * Ensures that the manager is currently allowing operations that change its + * internal focus state (such as via focusNode()). + * + * If the manager is currently not allowing state changes, an exception is + * thrown. + */ + private ensureManagerIsUnlocked; + /** + * Updates the internally tracked focused node to the specified node, or null + * if focus is being lost. This also updates previous focus tracking. + * + * @param newFocusedNode The new node to set as focused. + */ + private updateFocusedNode; + /** + * Defocuses the current actively focused node tracked by the manager, iff + * there's a node being tracked and the manager doesn't have ephemeral focus. + */ + private defocusCurrentFocusedNode; + /** + * Marks the specified node as actively focused, also calling related + * lifecycle callback methods for both the node and its parent tree. This + * ensures that the node is properly styled to indicate its active focus. + * + * This does not change the manager's currently tracked node, nor does it + * change any other nodes. + * + * @param node The node to be actively focused. + * @param prevTree The tree of the previously actively focused node, or null + * if there wasn't a previously actively focused node. + */ + private activelyFocusNode; + /** + * Marks the specified node as passively focused, also calling related + * lifecycle callback methods for both the node and its parent tree. This + * ensures that the node is properly styled to indicate its passive focus. + * + * This does not change the manager's currently tracked node, nor does it + * change any other nodes. + * + * @param node The node to be passively focused. + * @param nextTree The tree of the node receiving active focus, or null if no + * node will be actively focused. + */ + private passivelyFocusNode; + /** + * Updates the node's styling to indicate that it should have an active focus + * indicator. + * + * @param node The node to be styled for active focus. + */ + private setNodeToVisualActiveFocus; + /** + * Updates the node's styling to indicate that it should have a passive focus + * indicator. + * + * @param node The node to be styled for passive focus. + */ + private setNodeToVisualPassiveFocus; + /** + * Removes any active/passive indicators for the specified node. + * + * @param node The node which should have neither passive nor active focus + * indication. + */ + private removeHighlight; + private static focusManager; + /** + * Returns the page-global FocusManager. + * + * The returned instance is guaranteed to not change across function calls, + * but may change across page loads. + */ + static getFocusManager(): FocusManager; +} +/** Convenience function for FocusManager.getFocusManager. */ +export declare function getFocusManager(): FocusManager; +//# sourceMappingURL=focus_manager.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/gesture.d.ts b/appinventor/lib/blockly/@types/gesture.d.ts index 201cfce67f8..8b65a8e7237 100644 --- a/appinventor/lib/blockly/@types/gesture.d.ts +++ b/appinventor/lib/blockly/@types/gesture.d.ts @@ -332,11 +332,6 @@ export declare class Gesture { * @param _e A pointerup event. */ private doWorkspaceClick; - /** - * Move the dragged/clicked block to the front of the workspace so that it is - * not occluded by other blocks. - */ - private bringBlockToFront; /** * Record the field that a gesture started on. * diff --git a/appinventor/lib/blockly/@types/grid.d.ts b/appinventor/lib/blockly/@types/grid.d.ts index fc55cfa26d7..9a50f91a7bb 100644 --- a/appinventor/lib/blockly/@types/grid.d.ts +++ b/appinventor/lib/blockly/@types/grid.d.ts @@ -113,9 +113,12 @@ export declare class Grid { * @param rnd A random ID to append to the pattern's ID. * @param gridOptions The object containing grid configuration. * @param defs The root SVG element for this workspace's defs. + * @param injectionDiv The div containing the parent workspace and all related + * workspaces and block containers. CSS variables representing SVG patterns + * will be scoped to this container. * @returns The SVG element for the grid pattern. * @internal */ - static createDom(rnd: string, gridOptions: GridOptions, defs: SVGElement): SVGElement; + static createDom(rnd: string, gridOptions: GridOptions, defs: SVGElement, injectionDiv?: HTMLElement): SVGElement; } //# sourceMappingURL=grid.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/icons/comment_icon.d.ts b/appinventor/lib/blockly/@types/icons/comment_icon.d.ts index e5722e9bdb1..c1c85291227 100644 --- a/appinventor/lib/blockly/@types/icons/comment_icon.d.ts +++ b/appinventor/lib/blockly/@types/icons/comment_icon.d.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { Block } from '../block.js'; +import { TextInputBubble } from '../bubbles/textinput_bubble.js'; import type { IHasBubble } from '../interfaces/i_has_bubble.js'; import type { ISerializable } from '../interfaces/i_serializable.js'; import { Coordinate } from '../utils.js'; @@ -28,10 +29,12 @@ export declare class CommentIcon extends Icon implements IHasBubble, ISerializab private text; /** The size of this comment (which is applied to the editable bubble). */ private bubbleSize; + /** The location of the comment bubble in workspace coordinates. */ + private bubbleLocation?; /** * The visibility of the bubble for this comment. * - * This is used to track what the visibile state /should/ be, not necessarily + * This is used to track what the visible state /should/ be, not necessarily * what it currently /is/. E.g. sometimes this will be true, but the block * hasn't been rendered yet, so the bubble will not currently be visible. */ @@ -60,6 +63,14 @@ export declare class CommentIcon extends Icon implements IHasBubble, ISerializab setBubbleSize(size: Size): void; /** @returns the size of the editable bubble for this comment. */ getBubbleSize(): Size; + /** + * Sets the location of the comment bubble in the workspace. + */ + setBubbleLocation(location: Coordinate): void; + /** + * @returns the location of the comment bubble in the workspace. + */ + getBubbleLocation(): Coordinate | undefined; /** * @returns the state of the comment as a JSON serializable value if the * comment has text. Otherwise returns null. @@ -79,8 +90,11 @@ export declare class CommentIcon extends Icon implements IHasBubble, ISerializab * input bubble. */ onSizeChange(): void; + onBubbleLocationChange(): void; bubbleIsVisible(): boolean; setBubbleVisible(visible: boolean): Promise; + /** See IHasBubble.getBubble. */ + getBubble(): TextInputBubble | null; /** * Shows the editable text bubble for this comment, and adds change listeners * to update the state of this icon in response to changes in the bubble. @@ -112,5 +126,9 @@ export interface CommentState { height?: number; /** The width of the comment bubble. */ width?: number; + /** The X coordinate of the comment bubble. */ + x?: number; + /** The Y coordinate of the comment bubble. */ + y?: number; } //# sourceMappingURL=comment_icon.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/icons/icon.d.ts b/appinventor/lib/blockly/@types/icons/icon.d.ts index f172fa90d24..5d30ca56391 100644 --- a/appinventor/lib/blockly/@types/icons/icon.d.ts +++ b/appinventor/lib/blockly/@types/icons/icon.d.ts @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { Block } from '../block.js'; +import type { IContextMenu } from '../interfaces/i_contextmenu.js'; +import type { IFocusableTree } from '../interfaces/i_focusable_tree.js'; import type { IIcon } from '../interfaces/i_icon.js'; import * as tooltip from '../tooltip.js'; import { Coordinate } from '../utils/coordinate.js'; @@ -15,7 +17,7 @@ import type { IconType } from './icon_types.js'; * block (such as warnings or comments) as opposed to fields, which provide * "actual" information, related to how a block functions. */ -export declare abstract class Icon implements IIcon { +export declare abstract class Icon implements IIcon, IContextMenu { protected sourceBlock: Block; /** * The position of this icon relative to its blocks top-start, @@ -28,6 +30,8 @@ export declare abstract class Icon implements IIcon { protected svgRoot: SVGGElement | null; /** The tooltip for this icon. */ protected tooltip: tooltip.TipInfo; + /** The unique ID of this icon. */ + private id; constructor(sourceBlock: Block); getType(): IconType; initView(pointerdownListener: (e: PointerEvent) => void): void; @@ -59,5 +63,22 @@ export declare abstract class Icon implements IIcon { * @returns Whether the icon should be clickable while the block is in a flyout. */ isClickableInFlyout(autoClosingFlyout: boolean): boolean; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; + /** + * Returns the block that this icon is attached to. + * + * @returns The block this icon is attached to. + */ + getSourceBlock(): Block; + showContextMenu(e: PointerEvent): void; } //# sourceMappingURL=icon.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/icons/mutator_icon.d.ts b/appinventor/lib/blockly/@types/icons/mutator_icon.d.ts index 3c4bdf3025d..6d5a739ba73 100644 --- a/appinventor/lib/blockly/@types/icons/mutator_icon.d.ts +++ b/appinventor/lib/blockly/@types/icons/mutator_icon.d.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { BlockSvg } from '../block_svg.js'; +import { MiniWorkspaceBubble } from '../bubbles/mini_workspace_bubble.js'; import type { Abstract } from '../events/events_abstract.js'; import type { IHasBubble } from '../interfaces/i_has_bubble.js'; import { Coordinate } from '../utils/coordinate.js'; @@ -54,6 +55,8 @@ export declare class MutatorIcon extends Icon implements IHasBubble { isClickableInFlyout(): boolean; bubbleIsVisible(): boolean; setBubbleVisible(visible: boolean): Promise; + /** See IHasBubble.getBubble. */ + getBubble(): MiniWorkspaceBubble | null; /** @returns the configuration the mini workspace should have. */ private getMiniWorkspaceConfig; /** diff --git a/appinventor/lib/blockly/@types/icons/warning_icon.d.ts b/appinventor/lib/blockly/@types/icons/warning_icon.d.ts index 775ad7acf88..3e952b26579 100644 --- a/appinventor/lib/blockly/@types/icons/warning_icon.d.ts +++ b/appinventor/lib/blockly/@types/icons/warning_icon.d.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { BlockSvg } from '../block_svg.js'; +import type { IBubble } from '../interfaces/i_bubble.js'; import type { IHasBubble } from '../interfaces/i_has_bubble.js'; import { Size } from '../utils.js'; import { Coordinate } from '../utils/coordinate.js'; @@ -60,6 +61,8 @@ export declare class WarningIcon extends Icon implements IHasBubble { isClickableInFlyout(): boolean; bubbleIsVisible(): boolean; setBubbleVisible(visible: boolean): Promise; + /** See IHasBubble.getBubble. */ + getBubble(): IBubble | null; /** * @returns the location the bubble should be anchored to. * I.E. the middle of this icon. diff --git a/appinventor/lib/blockly/@types/insertion_marker_manager.d.ts b/appinventor/lib/blockly/@types/insertion_marker_manager.d.ts deleted file mode 100644 index 895489cd479..00000000000 --- a/appinventor/lib/blockly/@types/insertion_marker_manager.d.ts +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import type { BlockSvg } from './block_svg.js'; -import type { IDragTarget } from './interfaces/i_drag_target.js'; -import type { Coordinate } from './utils/coordinate.js'; -/** - * Class that controls updates to connections during drags. It is primarily - * responsible for finding the closest eligible connection and highlighting or - * unhighlighting it as needed during a drag. - * - * @deprecated v10 - Use an IConnectionPreviewer instead. - */ -export declare class InsertionMarkerManager { - /** - * The top block in the stack being dragged. - * Does not change during a drag. - */ - private readonly topBlock; - /** - * The workspace on which these connections are being dragged. - * Does not change during a drag. - */ - private readonly workspace; - /** - * The last connection on the stack, if it's not the last connection on the - * first block. - * Set in initAvailableConnections, if at all. - */ - private lastOnStack; - /** - * The insertion marker corresponding to the last block in the stack, if - * that's not the same as the first block in the stack. - * Set in initAvailableConnections, if at all - */ - private lastMarker; - /** - * The insertion marker that shows up between blocks to show where a block - * would go if dropped immediately. - */ - private firstMarker; - /** - * Information about the connection that would be made if the dragging block - * were released immediately. Updated on every mouse move. - */ - private activeCandidate; - /** - * Whether the block would be deleted if it were dropped immediately. - * Updated on every mouse move. - * - * @internal - */ - wouldDeleteBlock: boolean; - /** - * Connection on the insertion marker block that corresponds to - * the active candidate's local connection on the currently dragged block. - */ - private markerConnection; - /** The block that currently has an input being highlighted, or null. */ - private highlightedBlock; - /** The block being faded to indicate replacement, or null. */ - private fadedBlock; - /** - * The connections on the dragging blocks that are available to connect to - * other blocks. This includes all open connections on the top block, as - * well as the last connection on the block stack. - */ - private availableConnections; - /** @param block The top block in the stack being dragged. */ - constructor(block: BlockSvg); - /** - * Sever all links from this object. - * - * @internal - */ - dispose(): void; - /** - * Update the available connections for the top block. These connections can - * change if a block is unplugged and the stack is healed. - * - * @internal - */ - updateAvailableConnections(): void; - /** - * Return whether the block would be connected if dropped immediately, based - * on information from the most recent move event. - * - * @returns True if the block would be connected if dropped immediately. - * @internal - */ - wouldConnectBlock(): boolean; - /** - * Connect to the closest connection and render the results. - * This should be called at the end of a drag. - * - * @internal - */ - applyConnections(): void; - /** - * Update connections based on the most recent move location. - * - * @param dxy Position relative to drag start, in workspace units. - * @param dragTarget The drag target that the block is currently over. - * @internal - */ - update(dxy: Coordinate, dragTarget: IDragTarget | null): void; - /** - * Create an insertion marker that represents the given block. - * - * @param sourceBlock The block that the insertion marker will represent. - * @returns The insertion marker that represents the given block. - */ - private createMarkerBlock; - /** - * Populate the list of available connections on this block stack. If the - * stack has more than one block, this function will also update lastOnStack. - * - * @returns A list of available connections. - */ - private initAvailableConnections; - /** - * Whether the previews (insertion marker and replacement marker) should be - * updated based on the closest candidate and the current drag distance. - * - * @param newCandidate A new candidate connection that may replace the current - * best candidate. - * @param dxy Position relative to drag start, in workspace units. - * @returns Whether the preview should be updated. - */ - private shouldUpdatePreviews; - /** - * Find the nearest valid connection, which may be the same as the current - * closest connection. - * - * @param dxy Position relative to drag start, in workspace units. - * @returns An object containing a local connection, a closest connection, and - * a radius. - */ - private getCandidate; - /** - * Decide the radius at which to start searching for the closest connection. - * - * @returns The radius at which to start the search for the closest - * connection. - */ - private getStartRadius; - /** - * Whether ending the drag would delete the block. - * - * @param newCandidate Whether there is a candidate connection that the - * block could connect to if the drag ended immediately. - * @param dragTarget The drag target that the block is currently over. - * @returns Whether dropping the block immediately would delete the block. - */ - private shouldDelete; - /** - * Show an insertion marker or replacement highlighting during a drag, if - * needed. - * At the beginning of this function, this.activeConnection should be null. - * - * @param newCandidate A new candidate connection that may replace the current - * best candidate. - */ - private maybeShowPreview; - /** - * A preview should be shown. This function figures out if it should be a - * block highlight or an insertion marker, and shows the appropriate one. - * - * @param activeCandidate The connection that will be made if the drag ends - * immediately. - */ - private showPreview; - /** - * Hide an insertion marker or replacement highlighting during a drag, if - * needed. - * At the end of this function, this.activeCandidate will be null. - * - * @param newCandidate A new candidate connection that may replace the current - * best candidate. - */ - private maybeHidePreview; - /** - * A preview should be hidden. Loop through all possible preview modes - * and hide everything. - */ - private hidePreview; - /** - * Shows an insertion marker connected to the appropriate blocks (based on - * manager state). - * - * @param activeCandidate The connection that will be made if the drag ends - * immediately. - */ - private showInsertionMarker; - /** - * Disconnects and hides the current insertion marker. Should return the - * blocks to their original state. - */ - private hideInsertionMarker; - /** - * Shows an outline around the input the closest connection belongs to. - * - * @param activeCandidate The connection that will be made if the drag ends - * immediately. - */ - private showInsertionInputOutline; - /** Hides any visible input outlines. */ - private hideInsertionInputOutline; - /** - * Shows a replacement fade affect on the closest connection's target block - * (the block that is currently connected to it). - * - * @param activeCandidate The connection that will be made if the drag ends - * immediately. - */ - private showReplacementFade; - /** - * Hides/Removes any visible fade affects. - */ - private hideReplacementFade; - /** - * Get a list of the insertion markers that currently exist. Drags have 0, 1, - * or 2 insertion markers. - * - * @returns A possibly empty list of insertion marker blocks. - * @internal - */ - getInsertionMarkers(): BlockSvg[]; - /** - * Safely disposes of an insertion marker. - */ - private disposeInsertionMarker; -} -export declare namespace InsertionMarkerManager { - /** - * An enum describing different kinds of previews the InsertionMarkerManager - * could display. - */ - enum PREVIEW_TYPE { - INSERTION_MARKER = 0, - INPUT_OUTLINE = 1, - REPLACEMENT_FADE = 2 - } -} -export type PreviewType = InsertionMarkerManager.PREVIEW_TYPE; -export declare const PreviewType: typeof InsertionMarkerManager.PREVIEW_TYPE; -//# sourceMappingURL=insertion_marker_manager.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/insertion_marker_previewer.d.ts b/appinventor/lib/blockly/@types/insertion_marker_previewer.d.ts index e574eb5e841..51d3a9812e1 100644 --- a/appinventor/lib/blockly/@types/insertion_marker_previewer.d.ts +++ b/appinventor/lib/blockly/@types/insertion_marker_previewer.d.ts @@ -6,6 +6,7 @@ import { BlockSvg } from './block_svg.js'; import { IConnectionPreviewer } from './interfaces/i_connection_previewer.js'; import { RenderedConnection } from './rendered_connection.js'; +import * as blocks from './serialization/blocks.js'; export declare class InsertionMarkerPreviewer implements IConnectionPreviewer { private readonly workspace; private fadedBlock; @@ -36,6 +37,16 @@ export declare class InsertionMarkerPreviewer implements IConnectionPreviewer { previewConnection(draggedConn: RenderedConnection, staticConn: RenderedConnection): void; private shouldUseMarkerPreview; private previewMarker; + /** + * Transforms the given block into a JSON representation used to construct an + * insertion marker. + * + * @param block The block to serialize and use as an insertion marker. + * @returns A JSON-formatted string corresponding to a serialized + * representation of the given block suitable for use as an insertion + * marker. + */ + protected serializeBlockToInsertionMarker(block: BlockSvg): blocks.State; private createInsertionMarker; /** * Gets the connection on the marker block that matches the original diff --git a/appinventor/lib/blockly/@types/interfaces/i_ast_node_location.d.ts b/appinventor/lib/blockly/@types/interfaces/i_ast_node_location.d.ts deleted file mode 100644 index 6fdcc20f384..00000000000 --- a/appinventor/lib/blockly/@types/interfaces/i_ast_node_location.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * An AST node location interface. - */ -export interface IASTNodeLocation { -} -//# sourceMappingURL=i_ast_node_location.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_ast_node_location_svg.d.ts b/appinventor/lib/blockly/@types/interfaces/i_ast_node_location_svg.d.ts deleted file mode 100644 index e354b286128..00000000000 --- a/appinventor/lib/blockly/@types/interfaces/i_ast_node_location_svg.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import type { IASTNodeLocation } from './i_ast_node_location.js'; -/** - * An AST node location SVG interface. - */ -export interface IASTNodeLocationSvg extends IASTNodeLocation { - /** - * Add the marker SVG to this node's SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the SVG group. - */ - setMarkerSvg(markerSvg: SVGElement | null): void; - /** - * Add the cursor SVG to this node's SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the SVG group. - */ - setCursorSvg(cursorSvg: SVGElement | null): void; -} -//# sourceMappingURL=i_ast_node_location_svg.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_ast_node_location_with_block.d.ts b/appinventor/lib/blockly/@types/interfaces/i_ast_node_location_with_block.d.ts deleted file mode 100644 index 27bc6b73b4a..00000000000 --- a/appinventor/lib/blockly/@types/interfaces/i_ast_node_location_with_block.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import type { Block } from '../block.js'; -import type { IASTNodeLocation } from './i_ast_node_location.js'; -/** - * An AST node location that has an associated block. - */ -export interface IASTNodeLocationWithBlock extends IASTNodeLocation { - /** - * Get the source block associated with this node. - * - * @returns The source block. - */ - getSourceBlock(): Block | null; -} -//# sourceMappingURL=i_ast_node_location_with_block.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_autohideable.d.ts b/appinventor/lib/blockly/@types/interfaces/i_autohideable.d.ts index d6a84244e2a..15a02dea46f 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_autohideable.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_autohideable.d.ts @@ -16,4 +16,6 @@ export interface IAutoHideable extends IComponent { */ autoHide(onlyClosePopups: boolean): void; } +/** Returns true if the given object is autohideable. */ +export declare function isAutoHideable(obj: any): obj is IAutoHideable; //# sourceMappingURL=i_autohideable.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_bubble.d.ts b/appinventor/lib/blockly/@types/interfaces/i_bubble.d.ts index b8543930760..730bebe2b22 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_bubble.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_bubble.d.ts @@ -6,10 +6,11 @@ import type { Coordinate } from '../utils/coordinate.js'; import type { IContextMenu } from './i_contextmenu.js'; import type { IDraggable } from './i_draggable.js'; +import { IFocusableNode } from './i_focusable_node.js'; /** * A bubble interface. */ -export interface IBubble extends IDraggable, IContextMenu { +export interface IBubble extends IDraggable, IContextMenu, IFocusableNode { /** * Return the coordinates of the top-left corner of this bubble's body * relative to the drawing surface's origin (0,0), in workspace units. diff --git a/appinventor/lib/blockly/@types/interfaces/i_comment_icon.d.ts b/appinventor/lib/blockly/@types/interfaces/i_comment_icon.d.ts index e7c9951c2a0..ddb68f56afb 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_comment_icon.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_comment_icon.d.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ import { CommentState } from '../icons/comment_icon.js'; +import { Coordinate } from '../utils/coordinate.js'; import { Size } from '../utils/size.js'; import { IHasBubble } from './i_has_bubble.js'; import { IIcon } from './i_icon.js'; @@ -13,9 +14,11 @@ export interface ICommentIcon extends IIcon, IHasBubble, ISerializable { getText(): string; setBubbleSize(size: Size): void; getBubbleSize(): Size; + setBubbleLocation(location: Coordinate): void; + getBubbleLocation(): Coordinate | undefined; saveState(): CommentState; loadState(state: CommentState): void; } /** Checks whether the given object is an ICommentIcon. */ -export declare function isCommentIcon(obj: object): obj is ICommentIcon; +export declare function isCommentIcon(obj: any): obj is ICommentIcon; //# sourceMappingURL=i_comment_icon.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_contextmenu.d.ts b/appinventor/lib/blockly/@types/interfaces/i_contextmenu.d.ts index 1b194c05fc5..f6a44dbd945 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_contextmenu.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_contextmenu.d.ts @@ -11,4 +11,6 @@ export interface IContextMenu { */ showContextMenu(e: Event): void; } +/** @returns true if the given object implements IContextMenu. */ +export declare function hasContextMenu(obj: any): obj is IContextMenu; //# sourceMappingURL=i_contextmenu.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_copyable.d.ts b/appinventor/lib/blockly/@types/interfaces/i_copyable.d.ts index 29a63a4225a..d93c0f127af 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_copyable.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_copyable.d.ts @@ -11,6 +11,13 @@ export interface ICopyable extends ISelectable { * @returns Copy metadata. */ toCopyData(): T | null; + /** + * Whether this instance is currently copyable. The standard implementation + * is to return true if isOwnDeletable and isOwnMovable return true. + * + * @returns True if it can currently be copied. + */ + isCopyable?(): boolean; } export declare namespace ICopyable { interface ICopyData { @@ -18,6 +25,6 @@ export declare namespace ICopyable { } } export type ICopyData = ICopyable.ICopyData; -/** @returns true if the given object is copyable. */ +/** @returns true if the given object is an ICopyable. */ export declare function isCopyable(obj: any): obj is ICopyable; //# sourceMappingURL=i_copyable.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_flyout.d.ts b/appinventor/lib/blockly/@types/interfaces/i_flyout.d.ts index fa965d394a3..c95bb8d68de 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_flyout.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_flyout.d.ts @@ -4,16 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { BlockSvg } from '../block_svg.js'; -import { FlyoutItem } from '../flyout_base.js'; +import type { FlyoutItem } from '../flyout_item.js'; import type { Coordinate } from '../utils/coordinate.js'; import type { Svg } from '../utils/svg.js'; import type { FlyoutDefinition } from '../utils/toolbox.js'; import type { WorkspaceSvg } from '../workspace_svg.js'; +import { IFocusableTree } from './i_focusable_tree.js'; import type { IRegistrable } from './i_registrable.js'; /** * Interface for a flyout. */ -export interface IFlyout extends IRegistrable { +export interface IFlyout extends IRegistrable, IFocusableTree { /** Whether the flyout is laid out horizontally or not. */ horizontalLayout: boolean; /** Is RTL vs LTR. */ diff --git a/appinventor/lib/blockly/@types/interfaces/i_flyout_inflater.d.ts b/appinventor/lib/blockly/@types/interfaces/i_flyout_inflater.d.ts new file mode 100644 index 00000000000..7aa0d8acf31 --- /dev/null +++ b/appinventor/lib/blockly/@types/interfaces/i_flyout_inflater.d.ts @@ -0,0 +1,48 @@ +import type { FlyoutItem } from '../flyout_item.js'; +import type { IFlyout } from './i_flyout.js'; +export interface IFlyoutInflater { + /** + * Loads the object represented by the given state onto the workspace. + * + * Note that this method's interface is identical to that in ISerializer, to + * allow for code reuse. + * + * @param state A JSON representation of an element to inflate on the flyout. + * @param flyout The flyout on whose workspace the inflated element + * should be created. If the inflated element is an `IRenderedElement` it + * itself or the inflater should append it to the workspace; the flyout + * will not do so itself. The flyout is responsible for positioning the + * element, however. + * @returns The newly inflated flyout element. + */ + load(state: object, flyout: IFlyout): FlyoutItem; + /** + * Returns the amount of spacing that should follow the element corresponding + * to the given JSON representation. + * + * @param state A JSON representation of the element preceding the gap. + * @param defaultGap The default gap for elements in this flyout. + * @returns The gap that should follow the given element. + */ + gapForItem(state: object, defaultGap: number): number; + /** + * Disposes of the given element. + * + * If the element in question resides on the flyout workspace, it should remove + * itself. Implementers are not otherwise required to fully dispose of the + * element; it may be e.g. cached for performance purposes. + * + * @param element The flyout element to dispose of. + */ + disposeItem(item: FlyoutItem): void; + /** + * Returns the type of items that this inflater is responsible for inflating. + * This should be the same as the name under which this inflater registers + * itself, as well as the value returned by `getType()` on the `FlyoutItem` + * objects returned by `load()`. + * + * @returns The type of items this inflater creates. + */ + getType(): string; +} +//# sourceMappingURL=i_flyout_inflater.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_focusable_node.d.ts b/appinventor/lib/blockly/@types/interfaces/i_focusable_node.d.ts new file mode 100644 index 00000000000..0b71faac54f --- /dev/null +++ b/appinventor/lib/blockly/@types/interfaces/i_focusable_node.d.ts @@ -0,0 +1,105 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableTree } from './i_focusable_tree.js'; +/** Represents anything that can have input focus. */ +export interface IFocusableNode { + /** + * Returns the DOM element that can be explicitly requested to receive focus. + * + * IMPORTANT: Please note that this element is expected to have a visual + * presence on the page as it will both be explicitly focused and have its + * style changed depending on its current focus state (i.e. blurred, actively + * focused, and passively focused). The element will have one of two styles + * attached (where no style indicates blurred/not focused): + * - blocklyActiveFocus + * - blocklyPassiveFocus + * + * The returned element must also have a valid ID specified, and this ID + * should be unique across the entire page. Failing to have a properly unique + * ID could result in trying to focus one node (such as via a mouse click) + * leading to another node with the same ID actually becoming focused by + * FocusManager. + * + * The returned element must be visible if the node is ever focused via + * FocusManager.focusNode() or FocusManager.focusTree(). It's allowed for an + * element to be hidden until onNodeFocus() is called, or become hidden with a + * call to onNodeBlur(). + * + * It's expected the actual returned element will not change for the lifetime + * of the node (that is, its properties can change but a new element should + * never be returned). Also, the returned element will have its tabindex + * overwritten throughout the lifecycle of this node and FocusManager. + * + * If a node requires the ability to be focused directly without first being + * focused via FocusManager then it must set its own tab index. + * + * @returns The HTMLElement or SVGElement which can both receive focus and be + * visually represented as actively or passively focused for this node. + */ + getFocusableElement(): HTMLElement | SVGElement; + /** + * Returns the closest parent tree of this node (in cases where a tree has + * distinct trees underneath it), which represents the tree to which this node + * belongs. + * + * @returns The node's IFocusableTree. + */ + getFocusableTree(): IFocusableTree; + /** + * Called when this node receives active focus. + * + * Note that it's fine for implementations to change visibility modifiers, but + * they should avoid the following: + * - Creating or removing DOM elements (including via the renderer or drawer). + * - Affecting focus via DOM focus() calls or the FocusManager. + * + * Implementations may consider scrolling themselves into view here; that is + * not handled by the focus manager. + */ + onNodeFocus(): void; + /** + * Called when this node loses active focus. It may still have passive focus. + * + * This has the same implementation restrictions as onNodeFocus(). + */ + onNodeBlur(): void; + /** + * Indicates whether this node allows focus. If this returns false then none + * of the other IFocusableNode methods will be called. + * + * Note that special care must be taken if implementations of this function + * dynamically change their return value value over the lifetime of the node + * as certain environment conditions could affect the focusability of this + * node's DOM element (such as whether the element has a positive or zero + * tabindex). Also, changing from a true to a false value while the node holds + * focus will not immediately change the current focus of the node nor + * FocusManager's internal state, and thus may result in some of the node's + * functions being called later on when defocused (since it was previously + * considered focusable at the time of being focused). + * + * Implementations should generally always return true here unless there are + * circumstances under which this node should be skipped for focus + * considerations. Examples may include being disabled, read-only, a purely + * visual decoration, or a node with no visual representation that must + * implement this interface (e.g. due to a parent interface extending it). + * Keep in mind accessibility best practices when determining whether a node + * should be focusable since even disabled and read-only elements are still + * often relevant to providing organizational context to users (particularly + * when using a screen reader). + * + * @returns Whether this node can be focused by FocusManager. + */ + canBeFocused(): boolean; +} +/** + * Determines whether the provided object fulfills the contract of + * IFocusableNode. + * + * @param obj The object to test. + * @returns Whether the provided object can be used as an IFocusableNode. + */ +export declare function isFocusableNode(obj: any): obj is IFocusableNode; +//# sourceMappingURL=i_focusable_node.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_focusable_tree.d.ts b/appinventor/lib/blockly/@types/interfaces/i_focusable_tree.d.ts new file mode 100644 index 00000000000..c8ac22b3b8f --- /dev/null +++ b/appinventor/lib/blockly/@types/interfaces/i_focusable_tree.d.ts @@ -0,0 +1,125 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from './i_focusable_node.js'; +/** + * Represents a tree of focusable elements with its own active/passive focus + * context. + * + * Note that focus is handled by FocusManager, and tree implementations can have + * at most one IFocusableNode focused at one time. If the tree itself has focus, + * then the tree's focused node is considered 'active' ('passive' if another + * tree has focus). + * + * Focus is shared between one or more trees, where each tree can have exactly + * one active or passive node (and only one active node can exist on the whole + * page at any given time). The idea of passive focus is to provide context to + * users on where their focus will be restored upon navigating back to a + * previously focused tree. + * + * Note that if the tree's current focused node (passive or active) is needed, + * FocusableTreeTraverser.findFocusedNode can be used. + * + * Note that if specific nodes are needed to be retrieved for this tree, either + * use lookUpFocusableNode or FocusableTreeTraverser.findFocusableNodeFor. + */ +export interface IFocusableTree { + /** + * Returns the top-level focusable node of the tree. + * + * It's expected that the returned node will be focused in cases where + * FocusManager wants to focus a tree in a situation where it does not + * currently have a focused node. + */ + getRootFocusableNode(): IFocusableNode; + /** + * Returns the IFocusableNode of this tree that should receive active focus + * when the tree itself has focus returned to it. + * + * There are some very important notes to consider about a tree's focus + * lifecycle when implementing a version of this method that doesn't return + * null: + * 1. A null previousNode does not guarantee first-time focus state as nodes + * can be deleted. + * 2. This method is only used when the tree itself is focused, either through + * tab navigation or via FocusManager.focusTree(). In many cases, the + * previously focused node will be directly focused instead which will + * bypass this method. + * 3. The default behavior (i.e. returning null here) involves either + * restoring the previous node (previousNode) or focusing the tree's root. + * 4. The provided node may sometimes no longer be valid, such as in the case + * an attempt is made to focus a node that has been recently removed from + * its parent tree. Implementations can check for the validity of the node + * in order to specialize the node to which focus should fall back. + * + * This method is largely intended to provide tree implementations with the + * means of specifying a better default node than their root. + * + * @param previousNode The node that previously held passive focus for this + * tree, or null if the tree hasn't yet been focused. + * @returns The IFocusableNode that should now receive focus, or null if + * default behavior should be used, instead. + */ + getRestoredFocusableNode(previousNode: IFocusableNode | null): IFocusableNode | null; + /** + * Returns all directly nested trees under this tree. + * + * Note that the returned list of trees doesn't need to be stable, however all + * returned trees *do* need to be registered with FocusManager. Additionally, + * this must return actual nested trees as omitting a nested tree will affect + * how focus changes map to a specific node and its tree, potentially leading + * to user confusion. + */ + getNestedTrees(): Array; + /** + * Returns the IFocusableNode corresponding to the specified element ID, or + * null if there's no exact node within this tree with that ID or if the ID + * corresponds to the root of the tree. + * + * This will never match against nested trees. + * + * @param id The ID of the node's focusable HTMLElement or SVGElement. + */ + lookUpFocusableNode(id: string): IFocusableNode | null; + /** + * Called when a node of this tree has received active focus. + * + * Note that a null previousTree does not necessarily indicate that this is + * the first time Blockly is receiving focus. In fact, few assumptions can be + * made about previous focus state as a previous null tree simply indicates + * that Blockly did not hold active focus prior to this tree becoming focused + * (which can happen due to focus exiting the Blockly injection div, or for + * other cases like ephemeral focus). + * + * See IFocusableNode.onNodeFocus() as implementations have the same + * restrictions as with that method. + * + * @param node The node receiving active focus. + * @param previousTree The previous tree that held active focus, or null if + * none. + */ + onTreeFocus(node: IFocusableNode, previousTree: IFocusableTree | null): void; + /** + * Called when the previously actively focused node of this tree is now + * passively focused and there is no other active node of this tree taking its + * place. + * + * This has the same implementation restrictions and considerations as + * onTreeFocus(). + * + * @param nextTree The next tree receiving active focus, or null if none (such + * as in the case that Blockly is entirely losing DOM focus). + */ + onTreeBlur(nextTree: IFocusableTree | null): void; +} +/** + * Determines whether the provided object fulfills the contract of + * IFocusableTree. + * + * @param obj The object to test. + * @returns Whether the provided object can be used as an IFocusableTree. + */ +export declare function isFocusableTree(obj: any): obj is IFocusableTree; +//# sourceMappingURL=i_focusable_tree.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_has_bubble.d.ts b/appinventor/lib/blockly/@types/interfaces/i_has_bubble.d.ts index 73c47522a15..fae6c083165 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_has_bubble.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_has_bubble.d.ts @@ -3,11 +3,24 @@ * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +import type { IBubble } from './i_bubble'; export interface IHasBubble { /** @returns True if the bubble is currently open, false otherwise. */ bubbleIsVisible(): boolean; /** Sets whether the bubble is open or not. */ setBubbleVisible(visible: boolean): Promise; + /** + * Returns the current IBubble that implementations are managing, or null if + * there isn't one. + * + * Note that this cannot be expected to return null if bubbleIsVisible() + * returns false, i.e., the nullability of the returned bubble does not + * necessarily imply visibility. + * + * @returns The current IBubble maintained by implementations, or null if + * there is not one. + */ + getBubble(): IBubble | null; } /** Type guard that checks whether the given object is a IHasBubble. */ export declare function hasBubble(obj: any): obj is IHasBubble; diff --git a/appinventor/lib/blockly/@types/interfaces/i_icon.d.ts b/appinventor/lib/blockly/@types/interfaces/i_icon.d.ts index 78abd88d496..c2147d1475b 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_icon.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_icon.d.ts @@ -6,7 +6,8 @@ import type { IconType } from '../icons/icon_types.js'; import type { Coordinate } from '../utils/coordinate.js'; import type { Size } from '../utils/size.js'; -export interface IIcon { +import { IFocusableNode } from './i_focusable_node.js'; +export interface IIcon extends IFocusableNode { /** * @returns the IconType representing the type of the icon. This value should * also be used to register the icon via `Blockly.icons.registry.register`. diff --git a/appinventor/lib/blockly/@types/interfaces/i_legacy_procedure_blocks.d.ts b/appinventor/lib/blockly/@types/interfaces/i_legacy_procedure_blocks.d.ts index 715ed99e773..e63d5f4cbf0 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_legacy_procedure_blocks.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_legacy_procedure_blocks.d.ts @@ -23,12 +23,12 @@ export interface LegacyProcedureDefBlock { getProcedureDef: () => ProcedureTuple; } /** @internal */ -export declare function isLegacyProcedureDefBlock(block: object): block is LegacyProcedureDefBlock; +export declare function isLegacyProcedureDefBlock(obj: any): obj is LegacyProcedureDefBlock; /** @internal */ export interface LegacyProcedureCallBlock { getProcedureCall: () => string; renameProcedure: (p1: string, p2: string) => void; } /** @internal */ -export declare function isLegacyProcedureCallBlock(block: object): block is LegacyProcedureCallBlock; +export declare function isLegacyProcedureCallBlock(obj: any): obj is LegacyProcedureCallBlock; //# sourceMappingURL=i_legacy_procedure_blocks.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_metrics_manager.d.ts b/appinventor/lib/blockly/@types/interfaces/i_metrics_manager.d.ts index 39cad48db99..b8f351d3fdc 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_metrics_manager.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_metrics_manager.d.ts @@ -47,7 +47,7 @@ export interface IMetricsManager { * Gets the width, height and position of the toolbox on the workspace in * pixel coordinates. Returns 0 for the width and height if the workspace has * a simple toolbox instead of a category toolbox. To get the width and height - * of a simple toolbox, see {@link IMetricsManager#getFlyoutMetrics}. + * of a simple toolbox, see {@link IMetricsManager.getFlyoutMetrics}. * * @returns The object with the width, height and position of the toolbox. */ diff --git a/appinventor/lib/blockly/@types/interfaces/i_navigation_policy.d.ts b/appinventor/lib/blockly/@types/interfaces/i_navigation_policy.d.ts new file mode 100644 index 00000000000..52828dd157b --- /dev/null +++ b/appinventor/lib/blockly/@types/interfaces/i_navigation_policy.d.ts @@ -0,0 +1,63 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from './i_focusable_node.js'; +/** + * A set of rules that specify where keyboard navigation should proceed. + */ +export interface INavigationPolicy { + /** + * Returns the first child element of the given element, if any. + * + * @param current The element which the user is navigating into. + * @returns The current element's first child, or null if it has none. + */ + getFirstChild(current: T): IFocusableNode | null; + /** + * Returns the parent element of the given element, if any. + * + * @param current The element which the user is navigating out of. + * @returns The parent element of the current element, or null if it has none. + */ + getParent(current: T): IFocusableNode | null; + /** + * Returns the peer element following the given element, if any. + * + * @param current The element which the user is navigating past. + * @returns The next peer element of the current element, or null if there is + * none. + */ + getNextSibling(current: T): IFocusableNode | null; + /** + * Returns the peer element preceding the given element, if any. + * + * @param current The element which the user is navigating past. + * @returns The previous peer element of the current element, or null if + * there is none. + */ + getPreviousSibling(current: T): IFocusableNode | null; + /** + * Returns whether or not the given instance should be reachable via keyboard + * navigation. + * + * Implementors should generally return true, unless there are circumstances + * under which this item should be skipped while using keyboard navigation. + * Common examples might include being disabled, invalid, readonly, or purely + * a visual decoration. For example, while Fields are navigable, non-editable + * fields return false, since they cannot be interacted with when focused. + * + * @returns True if this element should be included in keyboard navigation. + */ + isNavigable(current: T): boolean; + /** + * Returns whether or not this navigation policy corresponds to the type of + * the given object. + * + * @param current An instance to check whether this policy applies to. + * @returns True if the given object is of a type handled by this policy. + */ + isApplicable(current: any): current is T; +} +//# sourceMappingURL=i_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_rendered_element.d.ts b/appinventor/lib/blockly/@types/interfaces/i_rendered_element.d.ts index ca3ae7b7423..9b8480f8862 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_rendered_element.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_rendered_element.d.ts @@ -3,17 +3,14 @@ * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -/** @internal */ export interface IRenderedElement { /** - * @returns The root SVG element of htis rendered element. + * @returns The root SVG element of this rendered element. */ getSvgRoot(): SVGElement; } /** * @returns True if the given object is an IRenderedElement. - * - * @internal */ export declare function isRenderedElement(obj: any): obj is IRenderedElement; //# sourceMappingURL=i_rendered_element.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_selectable.d.ts b/appinventor/lib/blockly/@types/interfaces/i_selectable.d.ts index 2916761e060..ab350832ff5 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_selectable.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_selectable.d.ts @@ -4,10 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { Workspace } from '../workspace.js'; +import { IFocusableNode } from './i_focusable_node.js'; /** * The interface for an object that is selectable. + * + * Implementations are generally expected to use their implementations of + * onNodeFocus() and onNodeBlur() to call setSelected() with themselves and + * null, respectively, in order to ensure that selections are correctly updated + * and the selection change event is fired. */ -export interface ISelectable { +export interface ISelectable extends IFocusableNode { id: string; workspace: Workspace; /** Select this. Highlight it visually. */ @@ -16,5 +22,5 @@ export interface ISelectable { unselect(): void; } /** Checks whether the given object is an ISelectable. */ -export declare function isSelectable(obj: object): obj is ISelectable; +export declare function isSelectable(obj: any): obj is ISelectable; //# sourceMappingURL=i_selectable.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_toolbox.d.ts b/appinventor/lib/blockly/@types/interfaces/i_toolbox.d.ts index ff4f2af952c..47a39a09ebb 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_toolbox.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_toolbox.d.ts @@ -6,12 +6,13 @@ import type { ToolboxInfo } from '../utils/toolbox.js'; import type { WorkspaceSvg } from '../workspace_svg.js'; import type { IFlyout } from './i_flyout.js'; +import type { IFocusableTree } from './i_focusable_tree.js'; import type { IRegistrable } from './i_registrable.js'; import type { IToolboxItem } from './i_toolbox_item.js'; /** * Interface for a toolbox. */ -export interface IToolbox extends IRegistrable { +export interface IToolbox extends IRegistrable, IFocusableTree { /** Initializes the toolbox. */ init(): void; /** @@ -77,7 +78,7 @@ export interface IToolbox extends IRegistrable { */ setVisible(isVisible: boolean): void; /** - * Selects the toolbox item by it's position in the list of toolbox items. + * Selects the toolbox item by its position in the list of toolbox items. * * @param position The position of the item to select. */ @@ -88,6 +89,13 @@ export interface IToolbox extends IRegistrable { * @returns The selected item, or null if no item is currently selected. */ getSelectedItem(): IToolboxItem | null; + /** + * Sets the selected item. + * + * @param item The toolbox item to select, or null to remove the current + * selection. + */ + setSelectedItem(item: IToolboxItem | null): void; /** Disposes of this toolbox. */ dispose(): void; } diff --git a/appinventor/lib/blockly/@types/interfaces/i_toolbox_item.d.ts b/appinventor/lib/blockly/@types/interfaces/i_toolbox_item.d.ts index 5001c677396..0b07e097ec7 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_toolbox_item.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_toolbox_item.d.ts @@ -3,10 +3,11 @@ * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +import type { IFocusableNode } from './i_focusable_node.js'; /** * Interface for an item in the toolbox. */ -export interface IToolboxItem { +export interface IToolboxItem extends IFocusableNode { /** * Initializes the toolbox item. * This includes creating the DOM and updating the state of any items based diff --git a/appinventor/lib/blockly/@types/interfaces/i_variable_backed_parameter_model.d.ts b/appinventor/lib/blockly/@types/interfaces/i_variable_backed_parameter_model.d.ts index 5472a029eed..21b43f9a0f1 100644 --- a/appinventor/lib/blockly/@types/interfaces/i_variable_backed_parameter_model.d.ts +++ b/appinventor/lib/blockly/@types/interfaces/i_variable_backed_parameter_model.d.ts @@ -3,12 +3,12 @@ * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import type { VariableModel } from '../variable_model.js'; import { IParameterModel } from './i_parameter_model.js'; +import type { IVariableModel, IVariableState } from './i_variable_model.js'; /** Interface for a parameter model that holds a variable model. */ export interface IVariableBackedParameterModel extends IParameterModel { /** Returns the variable model held by this type. */ - getVariableModel(): VariableModel; + getVariableModel(): IVariableModel; } /** * Returns whether the given object is a variable holder or not. diff --git a/appinventor/lib/blockly/@types/interfaces/i_variable_map.d.ts b/appinventor/lib/blockly/@types/interfaces/i_variable_map.d.ts new file mode 100644 index 00000000000..e17e39627bc --- /dev/null +++ b/appinventor/lib/blockly/@types/interfaces/i_variable_map.d.ts @@ -0,0 +1,48 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IVariableModel, IVariableState } from './i_variable_model.js'; +/** + * Variable maps are container objects responsible for storing and managing the + * set of variables referenced on a workspace. + * + * Any of these methods may define invariants about which names and types are + * legal, and throw if they are not met. + */ +export interface IVariableMap> { + getVariableById(id: string): T | null; + /** + * Returns the variable with the given name, or null if not found. If `type` + * is provided, the variable's type must also match, or null should be + * returned. + */ + getVariable(name: string, type?: string): T | null; + getAllVariables(): T[]; + /** + * Returns a list of all of the variables of the given type managed by this + * variable map. + */ + getVariablesOfType(type: string): T[]; + /** + * Returns a list of the set of types of the variables managed by this + * variable map. + */ + getTypes(): string[]; + /** + * Creates a new variable with the given name. If ID is not specified, the + * variable map should create one. Returns the new variable. + */ + createVariable(name: string, type?: string, id?: string | null): T; + addVariable(variable: T): void; + /** + * Changes the name of the given variable to the name provided and returns the + * renamed variable. + */ + renameVariable(variable: T, newName: string): T; + changeVariableType(variable: T, newType: string): T; + deleteVariable(variable: T): void; + clear(): void; +} +//# sourceMappingURL=i_variable_map.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/interfaces/i_variable_model.d.ts b/appinventor/lib/blockly/@types/interfaces/i_variable_model.d.ts new file mode 100644 index 00000000000..a5f538cfba1 --- /dev/null +++ b/appinventor/lib/blockly/@types/interfaces/i_variable_model.d.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { Workspace } from '../workspace.js'; +export interface IVariableModel { + getId(): string; + getName(): string; + /** + * Returns the type of the variable like 'int' or 'string'. Does not need to be + * unique. This will default to '' which is a specific type. + */ + getType(): string; + setName(name: string): this; + setType(type: string): this; + getWorkspace(): Workspace; + save(): T; +} +export interface IVariableModelStatic { + new (workspace: Workspace, name: string, type?: string, id?: string): IVariableModel; + /** + * Creates a new IVariableModel corresponding to the given state on the + * specified workspace. This method must be static in your implementation. + */ + load(state: T, workspace: Workspace): IVariableModel; +} +/** + * Represents the state of a given variable. + */ +export interface IVariableState { + name: string; + id: string; + type?: string; +} +//# sourceMappingURL=i_variable_model.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/ast_node.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/ast_node.d.ts deleted file mode 100644 index 620fbc199d8..00000000000 --- a/appinventor/lib/blockly/@types/keyboard_nav/ast_node.d.ts +++ /dev/null @@ -1,297 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * The class representing an AST node. - * Used to traverse the Blockly AST. - * - * @class - */ -import { Block } from '../block.js'; -import type { Connection } from '../connection.js'; -import type { Field } from '../field.js'; -import { FlyoutButton } from '../flyout_button.js'; -import type { Input } from '../inputs/input.js'; -import type { IASTNodeLocation } from '../interfaces/i_ast_node_location.js'; -import { Coordinate } from '../utils/coordinate.js'; -import type { Workspace } from '../workspace.js'; -/** - * Class for an AST node. - * It is recommended that you use one of the createNode methods instead of - * creating a node directly. - */ -export declare class ASTNode { - /** - * True to navigate to all fields. False to only navigate to clickable fields. - */ - static NAVIGATE_ALL_FIELDS: boolean; - /** - * The default y offset to use when moving the cursor from a stack to the - * workspace. - */ - private static readonly DEFAULT_OFFSET_Y; - private readonly type; - private readonly isConnectionLocation; - private readonly location; - /** The coordinate on the workspace. */ - private wsCoordinate; - /** - * @param type The type of the location. - * Must be in ASTNode.types. - * @param location The position in the AST. - * @param opt_params Optional dictionary of options. - */ - constructor(type: string, location: IASTNodeLocation, opt_params?: Params); - /** - * Parse the optional parameters. - * - * @param params The user specified parameters. - */ - private processParams; - /** - * Gets the value pointed to by this node. - * It is the callers responsibility to check the node type to figure out what - * type of object they get back from this. - * - * @returns The current field, connection, workspace, or block the cursor is - * on. - */ - getLocation(): IASTNodeLocation; - /** - * The type of the current location. - * One of ASTNode.types - * - * @returns The type of the location. - */ - getType(): string; - /** - * The coordinate on the workspace. - * - * @returns The workspace coordinate or null if the location is not a - * workspace. - */ - getWsCoordinate(): Coordinate; - /** - * Whether the node points to a connection. - * - * @returns [description] - * @internal - */ - isConnection(): boolean; - /** - * Given an input find the next editable field or an input with a non null - * connection in the same block. The current location must be an input - * connection. - * - * @returns The AST node holding the next field or connection or null if there - * is no editable field or input connection after the given input. - */ - private findNextForInput; - /** - * Given a field find the next editable field or an input with a non null - * connection in the same block. The current location must be a field. - * - * @returns The AST node pointing to the next field or connection or null if - * there is no editable field or input connection after the given input. - */ - private findNextForField; - /** - * Given an input find the previous editable field or an input with a non null - * connection in the same block. The current location must be an input - * connection. - * - * @returns The AST node holding the previous field or connection. - */ - private findPrevForInput; - /** - * Given a field find the previous editable field or an input with a non null - * connection in the same block. The current location must be a field. - * - * @returns The AST node holding the previous input or field. - */ - private findPrevForField; - /** - * Navigate between stacks of blocks on the workspace. - * - * @param forward True to go forward. False to go backwards. - * @returns The first block of the next stack or null if there are no blocks - * on the workspace. - */ - private navigateBetweenStacks; - /** - * Navigate between buttons and stacks of blocks on the flyout workspace. - * - * @param forward True to go forward. False to go backwards. - * @returns The next button, or next stack's first block, or null - */ - private navigateFlyoutContents; - /** - * Finds the next (or previous if navigating backward) item in the flyout that should be navigated to. - * - * @param flyoutContents Contents of the current flyout. - * @param currentLocation Current ASTNode location. - * @param forward True if we're navigating forward, else false. - * @returns The next (or previous) FlyoutItem, or null if there is none. - */ - private findNextLocationInFlyout; - /** - * Finds the top most AST node for a given block. - * This is either the previous connection, output connection or block - * depending on what kind of connections the block has. - * - * @param block The block that we want to find the top connection on. - * @returns The AST node containing the top connection. - */ - private findTopASTNodeForBlock; - /** - * Get the AST node pointing to the input that the block is nested under or if - * the block is not nested then get the stack AST node. - * - * @param block The source block of the current location. - * @returns The AST node pointing to the input connection or the top block of - * the stack this block is in. - */ - private getOutAstNodeForBlock; - /** - * Find the first editable field or input with a connection on a given block. - * - * @param block The source block of the current location. - * @returns An AST node pointing to the first field or input. - * Null if there are no editable fields or inputs with connections on the - * block. - */ - private findFirstFieldOrInput; - /** - * Finds the source block of the location of this node. - * - * @returns The source block of the location, or null if the node is of type - * workspace or button. - */ - getSourceBlock(): Block | null; - /** - * Find the element to the right of the current element in the AST. - * - * @returns An AST node that wraps the next field, connection, block, or - * workspace. Or null if there is no node to the right. - */ - next(): ASTNode | null; - /** - * Find the element one level below and all the way to the left of the current - * location. - * - * @returns An AST node that wraps the next field, connection, workspace, or - * block. Or null if there is nothing below this node. - */ - in(): ASTNode | null; - /** - * Find the element to the left of the current element in the AST. - * - * @returns An AST node that wraps the previous field, connection, workspace - * or block. Or null if no node exists to the left. null. - */ - prev(): ASTNode | null; - /** - * Find the next element that is one position above and all the way to the - * left of the current location. - * - * @returns An AST node that wraps the next field, connection, workspace or - * block. Or null if we are at the workspace level. - */ - out(): ASTNode | null; - /** - * Whether an AST node of the given type points to a connection. - * - * @param type The type to check. One of ASTNode.types. - * @returns True if a node of the given type points to a connection. - */ - private static isConnectionType; - /** - * Create an AST node pointing to a field. - * - * @param field The location of the AST node. - * @returns An AST node pointing to a field. - */ - static createFieldNode(field: Field): ASTNode | null; - /** - * Creates an AST node pointing to a connection. If the connection has a - * parent input then create an AST node of type input that will hold the - * connection. - * - * @param connection This is the connection the node will point to. - * @returns An AST node pointing to a connection. - */ - static createConnectionNode(connection: Connection): ASTNode | null; - /** - * Creates an AST node pointing to an input. Stores the input connection as - * the location. - * - * @param input The input used to create an AST node. - * @returns An AST node pointing to a input. - */ - static createInputNode(input: Input): ASTNode | null; - /** - * Creates an AST node pointing to a block. - * - * @param block The block used to create an AST node. - * @returns An AST node pointing to a block. - */ - static createBlockNode(block: Block): ASTNode | null; - /** - * Create an AST node of type stack. A stack, represented by its top block, is - * the set of all blocks connected to a top block, including the top - * block. - * - * @param topBlock A top block has no parent and can be found in the list - * returned by workspace.getTopBlocks(). - * @returns An AST node of type stack that points to the top block on the - * stack. - */ - static createStackNode(topBlock: Block): ASTNode | null; - /** - * Create an AST node of type button. A button in this case refers - * specifically to a button in a flyout. - * - * @param button A top block has no parent and can be found in the list - * returned by workspace.getTopBlocks(). - * @returns An AST node of type stack that points to the top block on the - * stack. - */ - static createButtonNode(button: FlyoutButton): ASTNode | null; - /** - * Creates an AST node pointing to a workspace. - * - * @param workspace The workspace that we are on. - * @param wsCoordinate The position on the workspace for this node. - * @returns An AST node pointing to a workspace and a position on the - * workspace. - */ - static createWorkspaceNode(workspace: Workspace | null, wsCoordinate: Coordinate | null): ASTNode | null; - /** - * Creates an AST node for the top position on a block. - * This is either an output connection, previous connection, or block. - * - * @param block The block to find the top most AST node on. - * @returns The AST node holding the top most position on the block. - */ - static createTopNode(block: Block): ASTNode | null; -} -export declare namespace ASTNode { - interface Params { - wsCoordinate: Coordinate; - } - enum types { - FIELD = "field", - BLOCK = "block", - INPUT = "input", - OUTPUT = "output", - NEXT = "next", - PREVIOUS = "previous", - STACK = "stack", - WORKSPACE = "workspace", - BUTTON = "button" - } -} -export type Params = ASTNode.Params; -//# sourceMappingURL=ast_node.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/basic_cursor.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/basic_cursor.d.ts deleted file mode 100644 index 0ee710ef6e1..00000000000 --- a/appinventor/lib/blockly/@types/keyboard_nav/basic_cursor.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { ASTNode } from './ast_node.js'; -import { Cursor } from './cursor.js'; -/** - * Class for a basic cursor. - * This will allow the user to get to all nodes in the AST by hitting next or - * previous. - */ -export declare class BasicCursor extends Cursor { - /** Name used for registering a basic cursor. */ - static readonly registrationName = "basicCursor"; - constructor(); - /** - * Find the next node in the pre order traversal. - * - * @returns The next node, or null if the current node is not set or there is - * no next value. - */ - next(): ASTNode | null; - /** - * For a basic cursor we only have the ability to go next and previous, so - * in will also allow the user to get to the next node in the pre order - * traversal. - * - * @returns The next node, or null if the current node is not set or there is - * no next value. - */ - in(): ASTNode | null; - /** - * Find the previous node in the pre order traversal. - * - * @returns The previous node, or null if the current node is not set or there - * is no previous value. - */ - prev(): ASTNode | null; - /** - * For a basic cursor we only have the ability to go next and previous, so - * out will allow the user to get to the previous node in the pre order - * traversal. - * - * @returns The previous node, or null if the current node is not set or there - * is no previous value. - */ - out(): ASTNode | null; - /** - * Uses pre order traversal to navigate the Blockly AST. This will allow - * a user to easily navigate the entire Blockly AST without having to go in - * and out levels on the tree. - * - * @param node The current position in the AST. - * @param isValid A function true/false depending on whether the given node - * should be traversed. - * @returns The next node in the traversal. - */ - protected getNextNode_(node: ASTNode | null, isValid: (p1: ASTNode | null) => boolean): ASTNode | null; - /** - * Reverses the pre order traversal in order to find the previous node. This - * will allow a user to easily navigate the entire Blockly AST without having - * to go in and out levels on the tree. - * - * @param node The current position in the AST. - * @param isValid A function true/false depending on whether the given node - * should be traversed. - * @returns The previous node in the traversal or null if no previous node - * exists. - */ - protected getPreviousNode_(node: ASTNode | null, isValid: (p1: ASTNode | null) => boolean): ASTNode | null; - /** - * Decides what nodes to traverse and which ones to skip. Currently, it - * skips output, stack and workspace nodes. - * - * @param node The AST node to check whether it is valid. - * @returns True if the node should be visited, false otherwise. - */ - protected validNode_(node: ASTNode | null): boolean; - /** - * From the given node find either the next valid sibling or parent. - * - * @param node The current position in the AST. - * @returns The parent AST node or null if there are no valid parents. - */ - private findSiblingOrParent; - /** - * Get the right most child of a node. - * - * @param node The node to find the right most child of. - * @returns The right most child of the given node, or the node if no child - * exists. - */ - private getRightMostChild; -} -//# sourceMappingURL=basic_cursor.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/block_comment_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/block_comment_navigation_policy.d.ts new file mode 100644 index 00000000000..4ebe014b305 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/block_comment_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { TextInputBubble } from '../bubbles/textinput_bubble.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from an TextInputBubble. + */ +export declare class BlockCommentNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given block comment. + * + * @param current The block comment to return the first child of. + * @returns The text editor of the given block comment bubble. + */ + getFirstChild(current: TextInputBubble): IFocusableNode | null; + /** + * Returns the parent of the given block comment. + * + * @param current The block comment to return the parent of. + * @returns The parent block of the given block comment. + */ + getParent(current: TextInputBubble): IFocusableNode | null; + /** + * Returns the next peer node of the given block comment. + * + * @param _current The block comment to find the following element of. + * @returns Null. + */ + getNextSibling(_current: TextInputBubble): IFocusableNode | null; + /** + * Returns the previous peer node of the given block comment. + * + * @param _current The block comment to find the preceding element of. + * @returns Null. + */ + getPreviousSibling(_current: TextInputBubble): IFocusableNode | null; + /** + * Returns whether or not the given block comment can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given block comment can be focused. + */ + isNavigable(current: TextInputBubble): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is an TextInputBubble. + */ + isApplicable(current: any): current is TextInputBubble; +} +//# sourceMappingURL=block_comment_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/block_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/block_navigation_policy.d.ts new file mode 100644 index 00000000000..9654abcac9e --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/block_navigation_policy.d.ts @@ -0,0 +1,84 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { BlockSvg } from '../block_svg.js'; +import type { Field } from '../field.js'; +import type { Icon } from '../icons/icon.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +import type { ISelectable } from '../interfaces/i_selectable.js'; +import { RenderedConnection } from '../rendered_connection.js'; +/** + * Set of rules controlling keyboard navigation from a block. + */ +export declare class BlockNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given block. + * + * @param current The block to return the first child of. + * @returns The first field or input of the given block, if any. + */ + getFirstChild(current: BlockSvg): IFocusableNode | null; + /** + * Returns the parent of the given block. + * + * @param current The block to return the parent of. + * @returns The top block of the given block's stack, or the connection to + * which it is attached. + */ + getParent(current: BlockSvg): IFocusableNode | null; + /** + * Returns the next peer node of the given block. + * + * @param current The block to find the following element of. + * @returns The first node of the next input/stack if the given block is a terminal + * block, or its next connection. + */ + getNextSibling(current: BlockSvg): IFocusableNode | null; + /** + * Returns the previous peer node of the given block. + * + * @param current The block to find the preceding element of. + * @returns The block's previous/output connection, or the last + * connection/block of the previous block stack if it is a root block. + */ + getPreviousSibling(current: BlockSvg): IFocusableNode | null; + /** + * Returns whether or not the given block can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given block can be focused. + */ + isNavigable(current: BlockSvg): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a BlockSvg. + */ + isApplicable(current: any): current is BlockSvg; +} +/** + * Returns the next/previous stack relative to the given element's stack. + * + * @param current The element whose stack will be navigated relative to. + * @param delta The difference in index to navigate; positive values navigate + * to the nth next stack, while negative values navigate to the nth previous + * stack. + * @returns The first element in the stack offset by `delta` relative to the + * current element's stack, or the last element in the stack offset by + * `delta` relative to the current element's stack when navigating backwards. + */ +export declare function navigateStacks(current: ISelectable, delta: number): IFocusableNode | null; +/** + * Returns the next navigable item relative to the provided block child. + * + * @param current The navigable block child item to navigate relative to. + * @param delta The difference in index to navigate; positive values navigate + * forward by n, while negative values navigate backwards by n. + * @returns The navigable block child offset by `delta` relative to `current`. + */ +export declare function navigateBlock(current: Icon | Field | RenderedConnection | BlockSvg, delta: number): IFocusableNode | null; +//# sourceMappingURL=block_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/comment_bar_button_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/comment_bar_button_navigation_policy.d.ts new file mode 100644 index 00000000000..37440ff1b7c --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/comment_bar_button_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { CommentBarButton } from '../comments/comment_bar_button.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from a CommentBarButton. + */ +export declare class CommentBarButtonNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given CommentBarButton. + * + * @param _current The CommentBarButton to return the first child of. + * @returns Null. + */ + getFirstChild(_current: CommentBarButton): IFocusableNode | null; + /** + * Returns the parent of the given CommentBarButton. + * + * @param current The CommentBarButton to return the parent of. + * @returns The parent comment of the given CommentBarButton. + */ + getParent(current: CommentBarButton): IFocusableNode | null; + /** + * Returns the next peer node of the given CommentBarButton. + * + * @param current The CommentBarButton to find the following element of. + * @returns The next CommentBarButton, if any. + */ + getNextSibling(current: CommentBarButton): IFocusableNode | null; + /** + * Returns the previous peer node of the given CommentBarButton. + * + * @param current The CommentBarButton to find the preceding element of. + * @returns The CommentBarButton's previous CommentBarButton, if any. + */ + getPreviousSibling(current: CommentBarButton): IFocusableNode | null; + /** + * Returns whether or not the given CommentBarButton can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given CommentBarButton can be focused. + */ + isNavigable(current: CommentBarButton): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is an CommentBarButton. + */ + isApplicable(current: any): current is CommentBarButton; +} +//# sourceMappingURL=comment_bar_button_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/comment_editor_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/comment_editor_navigation_policy.d.ts new file mode 100644 index 00000000000..d0c0b9e9b34 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/comment_editor_navigation_policy.d.ts @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { CommentEditor } from '../comments/comment_editor.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from a comment editor. + * This is a no-op placeholder (other than isNavigable/isApplicable) since + * comment editors handle their own navigation when editing ends. + */ +export declare class CommentEditorNavigationPolicy implements INavigationPolicy { + getFirstChild(_current: CommentEditor): IFocusableNode | null; + getParent(_current: CommentEditor): IFocusableNode | null; + getNextSibling(_current: CommentEditor): IFocusableNode | null; + getPreviousSibling(_current: CommentEditor): IFocusableNode | null; + /** + * Returns whether or not the given comment editor can be navigated to. + * + * @param current The instance to check for navigability. + * @returns False. + */ + isNavigable(current: CommentEditor): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a CommentEditor. + */ + isApplicable(current: any): current is CommentEditor; +} +//# sourceMappingURL=comment_editor_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/connection_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/connection_navigation_policy.d.ts new file mode 100644 index 00000000000..236bc58b22c --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/connection_navigation_policy.d.ts @@ -0,0 +1,67 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { BlockSvg } from '../block_svg.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +import { RenderedConnection } from '../rendered_connection.js'; +/** + * Set of rules controlling keyboard navigation from a connection. + */ +export declare class ConnectionNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given connection. + * + * @param current The connection to return the first child of. + * @returns The connection's first child element, or null if not none. + */ + getFirstChild(current: RenderedConnection): IFocusableNode | null; + /** + * Returns the parent of the given connection. + * + * @param current The connection to return the parent of. + * @returns The given connection's parent connection or block. + */ + getParent(current: RenderedConnection): IFocusableNode | null; + /** + * Returns the next element following the given connection. + * + * @param current The connection to navigate from. + * @returns The field, input connection or block following this connection. + */ + getNextSibling(current: RenderedConnection): IFocusableNode | null; + /** + * Returns the element preceding the given connection. + * + * @param current The connection to navigate from. + * @returns The field, input connection or block preceding this connection. + */ + getPreviousSibling(current: RenderedConnection): IFocusableNode | null; + /** + * Gets the parent connection on a block. + * This is either an output connection, previous connection or undefined. + * If both connections exist return the one that is actually connected + * to another block. + * + * @param block The block to find the parent connection on. + * @returns The connection connecting to the parent of the block. + */ + protected getParentConnection(block: BlockSvg): RenderedConnection; + /** + * Returns whether or not the given connection can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given connection can be focused. + */ + isNavigable(current: RenderedConnection): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a RenderedConnection. + */ + isApplicable(current: any): current is RenderedConnection; +} +//# sourceMappingURL=connection_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/cursor.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/cursor.d.ts deleted file mode 100644 index e7f38fb2175..00000000000 --- a/appinventor/lib/blockly/@types/keyboard_nav/cursor.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { ASTNode } from './ast_node.js'; -import { Marker } from './marker.js'; -/** - * Class for a cursor. - * A cursor controls how a user navigates the Blockly AST. - */ -export declare class Cursor extends Marker { - type: string; - constructor(); - /** - * Find the next connection, field, or block. - * - * @returns The next element, or null if the current node is not set or there - * is no next value. - */ - next(): ASTNode | null; - /** - * Find the in connection or field. - * - * @returns The in element, or null if the current node is not set or there is - * no in value. - */ - in(): ASTNode | null; - /** - * Find the previous connection, field, or block. - * - * @returns The previous element, or null if the current node is not set or - * there is no previous value. - */ - prev(): ASTNode | null; - /** - * Find the out connection, field, or block. - * - * @returns The out element, or null if the current node is not set or there - * is no out value. - */ - out(): ASTNode | null; -} -//# sourceMappingURL=cursor.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/field_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/field_navigation_policy.d.ts new file mode 100644 index 00000000000..ad1a75b1500 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/field_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { Field } from '../field.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from a field. + */ +export declare class FieldNavigationPolicy implements INavigationPolicy> { + /** + * Returns null since fields do not have children. + * + * @param _current The field to navigate from. + * @returns Null. + */ + getFirstChild(_current: Field): IFocusableNode | null; + /** + * Returns the parent block of the given field. + * + * @param current The field to navigate from. + * @returns The given field's parent block. + */ + getParent(current: Field): IFocusableNode | null; + /** + * Returns the next field or input following the given field. + * + * @param current The field to navigate from. + * @returns The next field or input in the given field's block. + */ + getNextSibling(current: Field): IFocusableNode | null; + /** + * Returns the field or input preceding the given field. + * + * @param current The field to navigate from. + * @returns The preceding field or input in the given field's block. + */ + getPreviousSibling(current: Field): IFocusableNode | null; + /** + * Returns whether or not the given field can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given field can be focused and navigated to. + */ + isNavigable(current: Field): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a Field. + */ + isApplicable(current: any): current is Field; +} +//# sourceMappingURL=field_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/flyout_button_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/flyout_button_navigation_policy.d.ts new file mode 100644 index 00000000000..90a76e9fc93 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/flyout_button_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { FlyoutButton } from '../flyout_button.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from a flyout button. + */ +export declare class FlyoutButtonNavigationPolicy implements INavigationPolicy { + /** + * Returns null since flyout buttons have no children. + * + * @param _current The FlyoutButton instance to navigate from. + * @returns Null. + */ + getFirstChild(_current: FlyoutButton): IFocusableNode | null; + /** + * Returns the parent workspace of the given flyout button. + * + * @param current The FlyoutButton instance to navigate from. + * @returns The given flyout button's parent workspace. + */ + getParent(current: FlyoutButton): IFocusableNode | null; + /** + * Returns null since inter-item navigation is done by FlyoutNavigationPolicy. + * + * @param _current The FlyoutButton instance to navigate from. + * @returns Null. + */ + getNextSibling(_current: FlyoutButton): IFocusableNode | null; + /** + * Returns null since inter-item navigation is done by FlyoutNavigationPolicy. + * + * @param _current The FlyoutButton instance to navigate from. + * @returns Null. + */ + getPreviousSibling(_current: FlyoutButton): IFocusableNode | null; + /** + * Returns whether or not the given flyout button can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given flyout button can be focused. + */ + isNavigable(current: FlyoutButton): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a FlyoutButton. + */ + isApplicable(current: any): current is FlyoutButton; +} +//# sourceMappingURL=flyout_button_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/flyout_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/flyout_navigation_policy.d.ts new file mode 100644 index 00000000000..1fa87efaae4 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/flyout_navigation_policy.d.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFlyout } from '../interfaces/i_flyout.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Generic navigation policy that navigates between items in the flyout. + */ +export declare class FlyoutNavigationPolicy implements INavigationPolicy { + private policy; + private flyout; + /** + * Creates a new FlyoutNavigationPolicy instance. + * + * @param policy The policy to defer to for parents/children. + * @param flyout The flyout this policy will control navigation in. + */ + constructor(policy: INavigationPolicy, flyout: IFlyout); + /** + * Returns null to prevent navigating into flyout items. + * + * @param _current The flyout item to navigate from. + * @returns Null to prevent navigating into flyout items. + */ + getFirstChild(_current: T): IFocusableNode | null; + /** + * Returns the parent of the given flyout item. + * + * @param current The flyout item to navigate from. + * @returns The parent of the given flyout item. + */ + getParent(current: T): IFocusableNode | null; + /** + * Returns the next item in the flyout relative to the given item. + * + * @param current The flyout item to navigate from. + * @returns The flyout item following the given one. + */ + getNextSibling(current: T): IFocusableNode | null; + /** + * Returns the previous item in the flyout relative to the given item. + * + * @param current The flyout item to navigate from. + * @returns The flyout item preceding the given one. + */ + getPreviousSibling(current: T): IFocusableNode | null; + /** + * Returns whether or not the given flyout item can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given flyout item can be focused. + */ + isNavigable(current: T): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a BlockSvg. + */ + isApplicable(current: any): current is T; +} +//# sourceMappingURL=flyout_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/flyout_separator_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/flyout_separator_navigation_policy.d.ts new file mode 100644 index 00000000000..ab6586de2ba --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/flyout_separator_navigation_policy.d.ts @@ -0,0 +1,33 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { FlyoutSeparator } from '../flyout_separator.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from a flyout separator. + * This is a no-op placeholder, since flyout separators can't be navigated to. + */ +export declare class FlyoutSeparatorNavigationPolicy implements INavigationPolicy { + getFirstChild(_current: FlyoutSeparator): IFocusableNode | null; + getParent(_current: FlyoutSeparator): IFocusableNode | null; + getNextSibling(_current: FlyoutSeparator): IFocusableNode | null; + getPreviousSibling(_current: FlyoutSeparator): IFocusableNode | null; + /** + * Returns whether or not the given flyout separator can be navigated to. + * + * @param _current The instance to check for navigability. + * @returns False. + */ + isNavigable(_current: FlyoutSeparator): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a FlyoutSeparator. + */ + isApplicable(current: any): current is FlyoutSeparator; +} +//# sourceMappingURL=flyout_separator_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/icon_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/icon_navigation_policy.d.ts new file mode 100644 index 00000000000..86397350117 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/icon_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { Icon } from '../icons/icon.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from an icon. + */ +export declare class IconNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given icon. + * + * @param current The icon to return the first child of. + * @returns Null. + */ + getFirstChild(current: Icon): IFocusableNode | null; + /** + * Returns the parent of the given icon. + * + * @param current The icon to return the parent of. + * @returns The source block of the given icon. + */ + getParent(current: Icon): IFocusableNode | null; + /** + * Returns the next peer node of the given icon. + * + * @param current The icon to find the following element of. + * @returns The next icon, field or input following this icon, if any. + */ + getNextSibling(current: Icon): IFocusableNode | null; + /** + * Returns the previous peer node of the given icon. + * + * @param current The icon to find the preceding element of. + * @returns The icon's previous icon, if any. + */ + getPreviousSibling(current: Icon): IFocusableNode | null; + /** + * Returns whether or not the given icon can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given icon can be focused. + */ + isNavigable(current: Icon): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is an Icon. + */ + isApplicable(current: any): current is Icon; +} +//# sourceMappingURL=icon_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/line_cursor.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/line_cursor.d.ts new file mode 100644 index 00000000000..5b53a511aff --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/line_cursor.d.ts @@ -0,0 +1,187 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @fileoverview The class representing a line cursor. + * A line cursor tries to traverse the blocks and connections on a block as if + * they were lines of code in a text editor. Previous and next traverse previous + * connections, next connections and blocks, while in and out traverse input + * connections and fields. + * @author aschmiedt@google.com (Abby Schmiedt) + */ +import { BlockSvg } from '../block_svg.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { WorkspaceSvg } from '../workspace_svg.js'; +import { Marker } from './marker.js'; +/** + * Class for a line cursor. + */ +export declare class LineCursor extends Marker { + protected readonly workspace: WorkspaceSvg; + type: string; + /** Locations to try moving the cursor to after a deletion. */ + private potentialNodes; + /** + * @param workspace The workspace this cursor belongs to. + */ + constructor(workspace: WorkspaceSvg); + /** + * Moves the cursor to the next block or workspace comment in the pre-order + * traversal. + * + * @returns The next node, or null if the current node is not set or there is + * no next value. + */ + next(): IFocusableNode | null; + /** + * Moves the cursor to the next input connection or field + * in the pre order traversal. + * + * @returns The next node, or null if the current node is + * not set or there is no next value. + */ + in(): IFocusableNode | null; + /** + * Moves the cursor to the previous block or workspace comment in the + * pre-order traversal. + * + * @returns The previous node, or null if the current node is not set or there + * is no previous value. + */ + prev(): IFocusableNode | null; + /** + * Moves the cursor to the previous input connection or field in the pre order + * traversal. + * + * @returns The previous node, or null if the current node + * is not set or there is no previous value. + */ + out(): IFocusableNode | null; + /** + * Returns true iff the node to which we would navigate if in() were + * called is the same as the node to which we would navigate if next() were + * called - in effect, if the LineCursor is at the end of the 'current + * line' of the program. + */ + atEndOfLine(): boolean; + /** + * Uses pre order traversal to navigate the Blockly AST. This will allow + * a user to easily navigate the entire Blockly AST without having to go in + * and out levels on the tree. + * + * @param node The current position in the AST. + * @param isValid A function true/false depending on whether the given node + * should be traversed. + * @param visitedNodes A set of previously visited nodes used to avoid cycles. + * @returns The next node in the traversal. + */ + private getNextNodeImpl; + /** + * Get the next node in the AST, optionally allowing for loopback. + * + * @param node The current position in the AST. + * @param isValid A function true/false depending on whether the given node + * should be traversed. + * @param loop Whether to loop around to the beginning of the workspace if no + * valid node was found. + * @returns The next node in the traversal. + */ + getNextNode(node: IFocusableNode | null, isValid: (p1: IFocusableNode | null) => boolean, loop: boolean): IFocusableNode | null; + /** + * Reverses the pre order traversal in order to find the previous node. This + * will allow a user to easily navigate the entire Blockly AST without having + * to go in and out levels on the tree. + * + * @param node The current position in the AST. + * @param isValid A function true/false depending on whether the given node + * should be traversed. + * @param visitedNodes A set of previously visited nodes used to avoid cycles. + * @returns The previous node in the traversal or null if no previous node + * exists. + */ + private getPreviousNodeImpl; + /** + * Get the previous node in the AST, optionally allowing for loopback. + * + * @param node The current position in the AST. + * @param isValid A function true/false depending on whether the given node + * should be traversed. + * @param loop Whether to loop around to the end of the workspace if no valid + * node was found. + * @returns The previous node in the traversal or null if no previous node + * exists. + */ + getPreviousNode(node: IFocusableNode | null, isValid: (p1: IFocusableNode | null) => boolean, loop: boolean): IFocusableNode | null; + /** + * Get the right most child of a node. + * + * @param node The node to find the right most child of. + * @returns The right most child of the given node, or the node if no child + * exists. + */ + private getRightMostChild; + /** + * Prepare for the deletion of a block by making a list of nodes we + * could move the cursor to afterwards and save it to + * this.potentialNodes. + * + * After the deletion has occurred, call postDelete to move it to + * the first valid node on that list. + * + * The locations to try (in order of preference) are: + * + * - The current location. + * - The connection to which the deleted block is attached. + * - The block connected to the next connection of the deleted block. + * - The parent block of the deleted block. + * - A location on the workspace beneath the deleted block. + * + * N.B.: When block is deleted, all of the blocks conneccted to that + * block's inputs are also deleted, but not blocks connected to its + * next connection. + * + * @param deletedBlock The block that is being deleted. + */ + preDelete(deletedBlock: BlockSvg): void; + /** + * Move the cursor to the first valid location in + * this.potentialNodes, following a block deletion. + */ + postDelete(): void; + /** + * Get the current location of the cursor. + * + * Overrides normal Marker getCurNode to update the current node from the + * selected block. This typically happens via the selection listener but that + * is not called immediately when `Gesture` calls + * `Blockly.common.setSelected`. In particular the listener runs after showing + * the context menu. + * + * @returns The current field, connection, or block the cursor is on. + */ + getCurNode(): IFocusableNode | null; + /** + * Set the location of the cursor and draw it. + * + * Overrides normal Marker setCurNode logic to call + * this.drawMarker() instead of this.drawer.draw() directly. + * + * @param newNode The new location of the cursor. + */ + setCurNode(newNode: IFocusableNode): void; + /** + * Get the first navigable node on the workspace, or null if none exist. + * + * @returns The first navigable node on the workspace, or null. + */ + getFirstNode(): IFocusableNode | null; + /** + * Get the last navigable node on the workspace, or null if none exist. + * + * @returns The last navigable node on the workspace, or null. + */ + getLastNode(): IFocusableNode | null; +} +//# sourceMappingURL=line_cursor.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/marker.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/marker.d.ts index fe69353e9e3..5d44ce43497 100644 --- a/appinventor/lib/blockly/@types/keyboard_nav/marker.d.ts +++ b/appinventor/lib/blockly/@types/keyboard_nav/marker.d.ts @@ -9,8 +9,8 @@ * * @class */ -import type { MarkerSvg } from '../renderers/common/marker_svg.js'; -import type { ASTNode } from './ast_node.js'; +import { BlockSvg } from '../block_svg.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; /** * Class for a marker. * This is used in keyboard navigation to save a location in the Blockly AST. @@ -19,51 +19,35 @@ export declare class Marker { /** The colour of the marker. */ colour: string | null; /** The current location of the marker. */ - private curNode; - /** - * The object in charge of drawing the visual representation of the current - * node. - */ - private drawer; + protected curNode: IFocusableNode | null; /** The type of the marker. */ type: string; - /** Constructs a new Marker instance. */ - constructor(); - /** - * Sets the object in charge of drawing the marker. - * - * @param drawer The object in charge of drawing the marker. - */ - setDrawer(drawer: MarkerSvg): void; - /** - * Get the current drawer for the marker. - * - * @returns The object in charge of drawing the marker. - */ - getDrawer(): MarkerSvg; /** * Gets the current location of the marker. * * @returns The current field, connection, or block the marker is on. */ - getCurNode(): ASTNode; + getCurNode(): IFocusableNode | null; /** * Set the location of the marker and call the update method. - * Setting isStack to true will only work if the newLocation is the top most - * output or previous connection on a stack. * - * @param newNode The new location of the marker. + * @param newNode The new location of the marker, or null to remove it. */ - setCurNode(newNode: ASTNode): void; + setCurNode(newNode: IFocusableNode | null): void; + /** Dispose of this marker. */ + dispose(): void; /** - * Redraw the current marker. + * Returns the block that the given node is a child of. * - * @internal + * @returns The parent block of the node if any, otherwise null. */ - draw(): void; - /** Hide the marker SVG. */ - hide(): void; - /** Dispose of this marker. */ - dispose(): void; + getSourceBlockFromNode(node: IFocusableNode | null): BlockSvg | null; + /** + * Returns the block that this marker's current node is a child of. + * + * @returns The parent block of the marker's current node if any, otherwise + * null. + */ + getSourceBlock(): BlockSvg | null; } //# sourceMappingURL=marker.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/tab_navigate_cursor.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/tab_navigate_cursor.d.ts deleted file mode 100644 index 238f5e8b116..00000000000 --- a/appinventor/lib/blockly/@types/keyboard_nav/tab_navigate_cursor.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { ASTNode } from './ast_node.js'; -import { BasicCursor } from './basic_cursor.js'; -/** - * A cursor for navigating between tab navigable fields. - */ -export declare class TabNavigateCursor extends BasicCursor { - /** - * Skip all nodes except for tab navigable fields. - * - * @param node The AST node to check whether it is valid. - * @returns True if the node should be visited, false otherwise. - */ - validNode_(node: ASTNode | null): boolean; -} -//# sourceMappingURL=tab_navigate_cursor.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/workspace_comment_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/workspace_comment_navigation_policy.d.ts new file mode 100644 index 00000000000..5630ad3423e --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/workspace_comment_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { RenderedWorkspaceComment } from '../comments/rendered_workspace_comment.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +/** + * Set of rules controlling keyboard navigation from an RenderedWorkspaceComment. + */ +export declare class WorkspaceCommentNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given workspace comment. + * + * @param current The workspace comment to return the first child of. + * @returns The first child button of the given comment. + */ + getFirstChild(current: RenderedWorkspaceComment): IFocusableNode | null; + /** + * Returns the parent of the given workspace comment. + * + * @param current The workspace comment to return the parent of. + * @returns The parent workspace of the given comment. + */ + getParent(current: RenderedWorkspaceComment): IFocusableNode | null; + /** + * Returns the next peer node of the given workspace comment. + * + * @param current The workspace comment to find the following element of. + * @returns The next workspace comment or block stack, if any. + */ + getNextSibling(current: RenderedWorkspaceComment): IFocusableNode | null; + /** + * Returns the previous peer node of the given workspace comment. + * + * @param current The workspace comment to find the preceding element of. + * @returns The previous workspace comment or block stack, if any. + */ + getPreviousSibling(current: RenderedWorkspaceComment): IFocusableNode | null; + /** + * Returns whether or not the given workspace comment can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given workspace comment can be focused. + */ + isNavigable(current: RenderedWorkspaceComment): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is an RenderedWorkspaceComment. + */ + isApplicable(current: any): current is RenderedWorkspaceComment; +} +//# sourceMappingURL=workspace_comment_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_nav/workspace_navigation_policy.d.ts b/appinventor/lib/blockly/@types/keyboard_nav/workspace_navigation_policy.d.ts new file mode 100644 index 00000000000..305960bd3e2 --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_nav/workspace_navigation_policy.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from '../interfaces/i_navigation_policy.js'; +import { WorkspaceSvg } from '../workspace_svg.js'; +/** + * Set of rules controlling keyboard navigation from a workspace. + */ +export declare class WorkspaceNavigationPolicy implements INavigationPolicy { + /** + * Returns the first child of the given workspace. + * + * @param current The workspace to return the first child of. + * @returns The top block of the first block stack, if any. + */ + getFirstChild(current: WorkspaceSvg): IFocusableNode | null; + /** + * Returns the parent of the given workspace. + * + * @param _current The workspace to return the parent of. + * @returns Null. + */ + getParent(_current: WorkspaceSvg): IFocusableNode | null; + /** + * Returns the next sibling of the given workspace. + * + * @param _current The workspace to return the next sibling of. + * @returns Null. + */ + getNextSibling(_current: WorkspaceSvg): IFocusableNode | null; + /** + * Returns the previous sibling of the given workspace. + * + * @param _current The workspace to return the previous sibling of. + * @returns Null. + */ + getPreviousSibling(_current: WorkspaceSvg): IFocusableNode | null; + /** + * Returns whether or not the given workspace can be navigated to. + * + * @param current The instance to check for navigability. + * @returns True if the given workspace can be focused. + */ + isNavigable(current: WorkspaceSvg): boolean; + /** + * Returns whether the given object can be navigated from by this policy. + * + * @param current The object to check if this policy applies to. + * @returns True if the object is a WorkspaceSvg. + */ + isApplicable(current: any): current is WorkspaceSvg; +} +//# sourceMappingURL=workspace_navigation_policy.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/keyboard_navigation_controller.d.ts b/appinventor/lib/blockly/@types/keyboard_navigation_controller.d.ts new file mode 100644 index 00000000000..53ab7507b0d --- /dev/null +++ b/appinventor/lib/blockly/@types/keyboard_navigation_controller.d.ts @@ -0,0 +1,48 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * The KeyboardNavigationController handles coordinating Blockly-wide + * keyboard navigation behavior, such as enabling/disabling full + * cursor visualization. + */ +export declare class KeyboardNavigationController { + /** Whether the user is actively using keyboard navigation. */ + private isActive; + /** Css class name added to body if keyboard nav is active. */ + private activeClassName; + /** + * Sets whether a user is actively using keyboard navigation. + * + * If they are, apply a css class to the entire page so that + * focused items can apply additional styling for keyboard users. + * + * Note that since enabling keyboard navigation presents significant UX changes + * (such as cursor visualization and move mode), callers should take care to + * only set active keyboard navigation when they have a high confidence in that + * being the correct state. In general, in any given mouse or key input situation + * callers can choose one of three paths: + * 1. Do nothing. This should be the choice for neutral actions that don't + * predominantly imply keyboard or mouse usage (such as clicking to select a block). + * 2. Disable keyboard navigation. This is the best choice when a user is definitely + * predominantly using the mouse (such as using a right click to open the context menu). + * 3. Enable keyboard navigation. This is the best choice when there's high confidence + * a user actually intends to use it (such as attempting to use the arrow keys to move + * around). + * + * @param isUsing + */ + setIsActive(isUsing?: boolean): void; + /** + * @returns true if the user is actively using keyboard navigation + * (e.g., has recently taken some action that is only relevant to keyboard users) + */ + getIsActive(): boolean; + /** Adds or removes the css class that indicates keyboard navigation is active. */ + private updateActiveVisualization; +} +/** Singleton instance of the keyboard navigation controller. */ +export declare const keyboardNavigationController: KeyboardNavigationController; +//# sourceMappingURL=keyboard_navigation_controller.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/label_flyout_inflater.d.ts b/appinventor/lib/blockly/@types/label_flyout_inflater.d.ts new file mode 100644 index 00000000000..8da884868cc --- /dev/null +++ b/appinventor/lib/blockly/@types/label_flyout_inflater.d.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { FlyoutItem } from './flyout_item.js'; +import type { IFlyout } from './interfaces/i_flyout.js'; +import type { IFlyoutInflater } from './interfaces/i_flyout_inflater.js'; +/** + * Class responsible for creating labels for flyouts. + */ +export declare class LabelFlyoutInflater implements IFlyoutInflater { + /** + * Inflates a flyout label from the given state and adds it to the flyout. + * + * @param state A JSON representation of a flyout label. + * @param flyout The flyout to create the label on. + * @returns A FlyoutButton configured as a label. + */ + load(state: object, flyout: IFlyout): FlyoutItem; + /** + * Returns the amount of space that should follow this label. + * + * @param state A JSON representation of a flyout label. + * @param defaultGap The default spacing for flyout items. + * @returns The amount of space that should follow this label. + */ + gapForItem(state: object, defaultGap: number): number; + /** + * Disposes of the given label. + * + * @param item The flyout label to dispose of. + */ + disposeItem(item: FlyoutItem): void; + /** + * Returns the type of items this inflater is responsible for creating. + * + * @returns An identifier for the type of items this inflater creates. + */ + getType(): string; +} +//# sourceMappingURL=label_flyout_inflater.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/layer_manager.d.ts b/appinventor/lib/blockly/@types/layer_manager.d.ts index df3192b1bc9..65001a0f5d3 100644 --- a/appinventor/lib/blockly/@types/layer_manager.d.ts +++ b/appinventor/lib/blockly/@types/layer_manager.d.ts @@ -3,6 +3,7 @@ * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; import { IRenderedElement } from './interfaces/i_rendered_element.js'; import { Coordinate } from './utils/coordinate.js'; import { WorkspaceSvg } from './workspace_svg.js'; @@ -37,15 +38,24 @@ export declare class LayerManager { * Moves the given element to the drag layer, which exists on top of all other * layers, and the drag surface. * + * @param elem The element to move onto the drag layer. + * @param focus Whether or not to focus the element post-move. + * * @internal */ - moveToDragLayer(elem: IRenderedElement): void; + moveToDragLayer(elem: IRenderedElement & IFocusableNode, focus?: boolean): void; /** * Moves the given element off of the drag layer. * + * @param elem The element to move off of the drag layer. + * @param layerNum The identifier of the layer to move the element onto. + * Should be a constant from layers.ts. + * @param focus Whether or not the element should be focused once moved onto + * the destination layer. + * * @internal */ - moveOffDragLayer(elem: IRenderedElement, layerNum: number): void; + moveOffDragLayer(elem: IRenderedElement & IFocusableNode, layerNum: number, focus?: boolean): void; /** * Appends the given element to a layer. If the layer does not exist, it is * created. @@ -81,5 +91,11 @@ export declare class LayerManager { * @internal */ getBubbleLayer(): SVGGElement; + /** + * Returns the drag layer. + * + * @internal + */ + getDragLayer(): SVGGElement | undefined; } //# sourceMappingURL=layer_manager.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/marker_manager.d.ts b/appinventor/lib/blockly/@types/marker_manager.d.ts index b8f8da0147a..ecb3b0716fc 100644 --- a/appinventor/lib/blockly/@types/marker_manager.d.ts +++ b/appinventor/lib/blockly/@types/marker_manager.d.ts @@ -8,7 +8,7 @@ * * @class */ -import type { Cursor } from './keyboard_nav/cursor.js'; +import { LineCursor } from './keyboard_nav/line_cursor.js'; import type { Marker } from './keyboard_nav/marker.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** @@ -20,12 +20,8 @@ export declare class MarkerManager { static readonly LOCAL_MARKER = "local_marker_1"; /** The cursor. */ private cursor; - /** The cursor's SVG element. */ - private cursorSvg; /** The map of markers for the workspace. */ private markers; - /** The marker's SVG element. */ - private markerSvg; /** * @param workspace The workspace for the marker manager. * @internal @@ -49,7 +45,7 @@ export declare class MarkerManager { * * @returns The cursor for this workspace. */ - getCursor(): Cursor | null; + getCursor(): LineCursor; /** * Get a single marker that corresponds to the given ID. * @@ -64,29 +60,7 @@ export declare class MarkerManager { * * @param cursor The cursor used to move around this workspace. */ - setCursor(cursor: Cursor): void; - /** - * Add the cursor SVG to this workspace SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the workspace - * SVG group. - * @internal - */ - setCursorSvg(cursorSvg: SVGElement | null): void; - /** - * Add the marker SVG to this workspaces SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the workspace - * SVG group. - * @internal - */ - setMarkerSvg(markerSvg: SVGElement | null): void; - /** - * Redraw the attached cursor SVG if needed. - * - * @internal - */ - updateMarkers(): void; + setCursor(cursor: LineCursor): void; /** * Dispose of the marker manager. * Go through and delete all markers associated with this marker manager. diff --git a/appinventor/lib/blockly/@types/menu.d.ts b/appinventor/lib/blockly/@types/menu.d.ts index b07e25d52c1..b9751598fa0 100644 --- a/appinventor/lib/blockly/@types/menu.d.ts +++ b/appinventor/lib/blockly/@types/menu.d.ts @@ -3,7 +3,8 @@ * Copyright 2019 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import type { MenuItem } from './menuitem.js'; +import type { MenuSeparator } from './menu_separator.js'; +import { MenuItem } from './menuitem.js'; import * as aria from './utils/aria.js'; import { Coordinate } from './utils/coordinate.js'; import type { Size } from './utils/size.js'; @@ -12,9 +13,7 @@ import type { Size } from './utils/size.js'; */ export declare class Menu { /** - * Array of menu items. - * (Nulls are never in the array, but typing the array as nullable prevents - * the compiler from objecting to .indexOf(null)) + * Array of menu items and separators. */ private readonly menuItems; /** @@ -47,10 +46,10 @@ export declare class Menu { /** * Add a new menu item to the bottom of this menu. * - * @param menuItem Menu item to append. + * @param menuItem Menu item or separator to append. * @internal */ - addChild(menuItem: MenuItem): void; + addChild(menuItem: MenuItem | MenuSeparator): void; /** * Creates the menu DOM. * @@ -149,9 +148,7 @@ export declare class Menu { */ private handlePointerLeave; /** - * Attempts to handle a keyboard event, if the menu item is enabled, by - * calling - * {@link Menu#handleKeyEventInternal_}. + * Attempts to handle a keyboard event. * * @param e Key event to handle. */ @@ -163,5 +160,11 @@ export declare class Menu { * @internal */ getSize(): Size; + /** + * Returns the action menu items (omitting separators) in this menu. + * + * @returns The MenuItem objects displayed in this menu. + */ + private getMenuItems; } //# sourceMappingURL=menu.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/menu_separator.d.ts b/appinventor/lib/blockly/@types/menu_separator.d.ts new file mode 100644 index 00000000000..9ccfac6ec43 --- /dev/null +++ b/appinventor/lib/blockly/@types/menu_separator.d.ts @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Representation of a section separator in a menu. + */ +export declare class MenuSeparator { + /** + * DOM element representing this separator in a menu. + */ + private element; + /** + * Creates the DOM representation of this separator. + * + * @returns An
element. + */ + createDom(): HTMLHRElement; + /** + * Disposes of this separator. + */ + dispose(): void; +} +//# sourceMappingURL=menu_separator.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/menuitem.d.ts b/appinventor/lib/blockly/@types/menuitem.d.ts index ec610694df6..0414d3c7097 100644 --- a/appinventor/lib/blockly/@types/menuitem.d.ts +++ b/appinventor/lib/blockly/@types/menuitem.d.ts @@ -120,9 +120,12 @@ export declare class MenuItem { * Performs the appropriate action when the menu item is activated * by the user. * + * @param menuSelectEvent the event that triggered the selection + * of the menu item. + * * @internal */ - performAction(): void; + performAction(menuSelectEvent: Event): void; /** * Set the handler that's called when the menu item is activated by the user. * `obj` will be used as the 'this' object in the function when called. @@ -131,6 +134,14 @@ export declare class MenuItem { * @param obj Used as the 'this' object in fn when called. * @internal */ - onAction(fn: (p1: MenuItem) => void, obj: object): void; + onAction(fn: (p1: MenuItem, menuSelectEvent: Event) => void, obj: object): void; + /** + * Adds or removes the checkmark indicator on this menu item. + * The indicator is present even if this menu item is not checked, as long + * as it is checkable; its visibility is controlled with CSS. + * + * @param add True to add the checkmark indicator, false to remove it. + */ + private toggleHasCheckbox; } //# sourceMappingURL=menuitem.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/metrics_manager.d.ts b/appinventor/lib/blockly/@types/metrics_manager.d.ts index a507922159f..e877dbfa98d 100644 --- a/appinventor/lib/blockly/@types/metrics_manager.d.ts +++ b/appinventor/lib/blockly/@types/metrics_manager.d.ts @@ -48,7 +48,7 @@ export declare class MetricsManager implements IMetricsManager { * Gets the width, height and position of the toolbox on the workspace in * pixel coordinates. Returns 0 for the width and height if the workspace has * a simple toolbox instead of a category toolbox. To get the width and height - * of a simple toolbox, see {@link MetricsManager#getFlyoutMetrics}. + * of a simple toolbox, see {@link (MetricsManager:class).getFlyoutMetrics}. * * @returns The object with the width, height and position of the toolbox. */ diff --git a/appinventor/lib/blockly/@types/names.d.ts b/appinventor/lib/blockly/@types/names.d.ts index 44303ee7043..202e7b869a2 100644 --- a/appinventor/lib/blockly/@types/names.d.ts +++ b/appinventor/lib/blockly/@types/names.d.ts @@ -3,7 +3,13 @@ * Copyright 2012 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import type { VariableMap } from './variable_map.js'; +/** + * Utility functions for handling variable and procedure names. + * + * @class + */ +import type { IVariableMap } from './interfaces/i_variable_map.js'; +import type { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import type { Workspace } from './workspace.js'; /** * Class for a database of entity names (variables, procedures, etc). @@ -40,7 +46,7 @@ export declare class Names { * * @param map The map to track. */ - setVariableMap(map: VariableMap): void; + setVariableMap(map: IVariableMap>): void; /** * Get the name for a user-defined variable, based on its ID. * This should only be used for variables of NameType VARIABLE. diff --git a/appinventor/lib/blockly/@types/navigator.d.ts b/appinventor/lib/blockly/@types/navigator.d.ts new file mode 100644 index 00000000000..465cecc8923 --- /dev/null +++ b/appinventor/lib/blockly/@types/navigator.d.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { INavigationPolicy } from './interfaces/i_navigation_policy.js'; +type RuleList = INavigationPolicy[]; +/** + * Class responsible for determining where focus should move in response to + * keyboard navigation commands. + */ +export declare class Navigator { + /** + * Map from classes to a corresponding ruleset to handle navigation from + * instances of that class. + */ + protected rules: RuleList; + /** + * Adds a navigation ruleset to this Navigator. + * + * @param policy A ruleset that determines where focus should move starting + * from an instance of its managed class. + */ + addNavigationPolicy(policy: INavigationPolicy): void; + /** + * Returns the navigation ruleset associated with the given object instance's + * class. + * + * @param current An object to retrieve a navigation ruleset for. + * @returns The navigation ruleset of objects of the given object's class, or + * undefined if no ruleset has been registered for the object's class. + */ + private get; + /** + * Returns the first child of the given object instance, if any. + * + * @param current The object to retrieve the first child of. + * @returns The first child node of the given object, if any. + */ + getFirstChild(current: IFocusableNode): IFocusableNode | null; + /** + * Returns the parent of the given object instance, if any. + * + * @param current The object to retrieve the parent of. + * @returns The parent node of the given object, if any. + */ + getParent(current: IFocusableNode): IFocusableNode | null; + /** + * Returns the next sibling of the given object instance, if any. + * + * @param current The object to retrieve the next sibling node of. + * @returns The next sibling node of the given object, if any. + */ + getNextSibling(current: IFocusableNode): IFocusableNode | null; + /** + * Returns the previous sibling of the given object instance, if any. + * + * @param current The object to retrieve the previous sibling node of. + * @returns The previous sibling node of the given object, if any. + */ + getPreviousSibling(current: IFocusableNode): IFocusableNode | null; +} +export {}; +//# sourceMappingURL=navigator.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/procedures.d.ts b/appinventor/lib/blockly/@types/procedures.d.ts index fc4efcb1402..f983f73b833 100644 --- a/appinventor/lib/blockly/@types/procedures.d.ts +++ b/appinventor/lib/blockly/@types/procedures.d.ts @@ -13,6 +13,7 @@ import { IProcedureBlock, isProcedureBlock } from './interfaces/i_procedure_bloc import { IProcedureMap } from './interfaces/i_procedure_map.js'; import { IProcedureModel } from './interfaces/i_procedure_model.js'; import { ObservableProcedureMap } from './observable_procedure_map.js'; +import type { FlyoutItemInfo } from './utils/toolbox.js'; import type { Workspace } from './workspace.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** @@ -64,12 +65,14 @@ export declare function isNameUsed(name: string, workspace: Workspace, opt_exclu */ export declare function rename(this: Field, name: string): string; /** - * Construct the blocks required by the flyout for the procedure category. + * Internal wrapper that returns the contents of the procedure category. * - * @param workspace The workspace containing procedures. - * @returns Array of XML block elements. + * @internal + * @param workspace The workspace to populate procedure blocks for. */ -export declare function flyoutCategory(workspace: WorkspaceSvg): Element[]; +export declare function internalFlyoutCategory(workspace: WorkspaceSvg): FlyoutItemInfo[]; +export declare function flyoutCategory(workspace: WorkspaceSvg, useXml: true): Element[]; +export declare function flyoutCategory(workspace: WorkspaceSvg, useXml: false): FlyoutItemInfo[]; /** * Listens for when a procedure mutator is opened. Then it triggers a flyout * update and adds a mutator change listener to the mutator workspace. diff --git a/appinventor/lib/blockly/@types/registry.d.ts b/appinventor/lib/blockly/@types/registry.d.ts index e9a072511bc..da40a64f207 100644 --- a/appinventor/lib/blockly/@types/registry.d.ts +++ b/appinventor/lib/blockly/@types/registry.d.ts @@ -11,12 +11,15 @@ import type { IConnectionPreviewer } from './interfaces/i_connection_previewer.j import type { ICopyable } from './interfaces/i_copyable.js'; import type { IDragger } from './interfaces/i_dragger.js'; import type { IFlyout } from './interfaces/i_flyout.js'; +import type { IFlyoutInflater } from './interfaces/i_flyout_inflater.js'; import type { IIcon } from './interfaces/i_icon.js'; import type { IMetricsManager } from './interfaces/i_metrics_manager.js'; import type { IPaster } from './interfaces/i_paster.js'; import type { ISerializer } from './interfaces/i_serializer.js'; import type { IToolbox } from './interfaces/i_toolbox.js'; -import type { Cursor } from './keyboard_nav/cursor.js'; +import type { IVariableMap } from './interfaces/i_variable_map.js'; +import type { IVariableModel, IVariableModelStatic, IVariableState } from './interfaces/i_variable_model.js'; +import type { LineCursor } from './keyboard_nav/line_cursor.js'; import type { Options } from './options.js'; import type { Renderer } from './renderers/common/renderer.js'; import type { Theme } from './theme.js'; @@ -47,7 +50,7 @@ export declare class Type<_T> { toString(): string; static CONNECTION_CHECKER: Type; static CONNECTION_PREVIEWER: Type; - static CURSOR: Type; + static CURSOR: Type; static EVENT: Type; static FIELD: Type>; static INPUT: Type; @@ -57,6 +60,7 @@ export declare class Type<_T> { static TOOLBOX_ITEM: Type; static FLYOUTS_VERTICAL_TOOLBOX: Type; static FLYOUTS_HORIZONTAL_TOOLBOX: Type; + static FLYOUT_INFLATER: Type; static METRICS_MANAGER: Type; /** * Type for an IDragger. Formerly behavior was mostly covered by @@ -69,6 +73,8 @@ export declare class Type<_T> { static ICON: Type; /** @internal */ static PASTER: Type>>; + static VARIABLE_MODEL: Type & IVariableModel>; + static VARIABLE_MAP: Type>>; } /** * Registers a class based on a type and name. diff --git a/appinventor/lib/blockly/@types/rendered_connection.d.ts b/appinventor/lib/blockly/@types/rendered_connection.d.ts index b7608101e55..ed46e6f0e7f 100644 --- a/appinventor/lib/blockly/@types/rendered_connection.d.ts +++ b/appinventor/lib/blockly/@types/rendered_connection.d.ts @@ -8,14 +8,16 @@ * * @class */ -import type { Block } from './block.js'; import type { BlockSvg } from './block_svg.js'; import { Connection } from './connection.js'; +import { IContextMenu } from './interfaces/i_contextmenu.js'; +import type { IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; import { Coordinate } from './utils/coordinate.js'; /** * Class for a connection between blocks that may be rendered on screen. */ -export declare class RenderedConnection extends Connection { +export declare class RenderedConnection extends Connection implements IContextMenu, IFocusableNode { sourceBlock_: BlockSvg; private readonly db; private readonly dbOpposite; @@ -161,7 +163,7 @@ export declare class RenderedConnection extends Connection { * * @returns List of blocks to render. */ - startTrackingAll(): Block[]; + startTrackingAll(): BlockSvg[]; /** * Behaviour after a connection attempt fails. * Bumps this connection away from the other connection. Called when an @@ -216,6 +218,26 @@ export declare class RenderedConnection extends Connection { * @returns The connection being modified (to allow chaining). */ setCheck(check: string | string[] | null): RenderedConnection; + /** + * Handles showing the context menu when it is opened on a connection. + * Note that typically the context menu can't be opened with the mouse + * on a connection, because you can't select a connection. But keyboard + * users may open the context menu with a keyboard shortcut. + * + * @param e Event that triggered the opening of the context menu. + */ + showContextMenu(e: Event): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; + private findHighlightSvg; } export declare namespace RenderedConnection { /** diff --git a/appinventor/lib/blockly/@types/renderers/common/block_rendering.d.ts b/appinventor/lib/blockly/@types/renderers/common/block_rendering.d.ts index aaccb82f000..c602198d5e1 100644 --- a/appinventor/lib/blockly/@types/renderers/common/block_rendering.d.ts +++ b/appinventor/lib/blockly/@types/renderers/common/block_rendering.d.ts @@ -29,7 +29,6 @@ import { Types } from '../measurables/types.js'; import { Drawer } from './drawer.js'; import type { IPathObject } from './i_path_object.js'; import { RenderInfo } from './info.js'; -import { MarkerSvg } from './marker_svg.js'; import { PathObject } from './path_object.js'; import { Renderer } from './renderer.js'; /** @@ -59,6 +58,6 @@ export declare function unregister(name: string): void; export declare function init(name: string, theme: Theme, opt_rendererOverrides?: { [rendererConstant: string]: any; }): Renderer; -export { BottomRow, Connection, Drawer, ExternalValueInput, Field, Hat, Icon, InlineInput, InputConnection, InputRow, InRowSpacer, IPathObject, JaggedEdge, MarkerSvg, Measurable, NextConnection, OutputConnection, PathObject, PreviousConnection, Renderer, RenderInfo, RoundCorner, Row, SpacerRow, SquareCorner, StatementInput, TopRow, Types, }; +export { BottomRow, Connection, Drawer, ExternalValueInput, Field, Hat, Icon, InlineInput, InputConnection, InputRow, InRowSpacer, IPathObject, JaggedEdge, Measurable, NextConnection, OutputConnection, PathObject, PreviousConnection, Renderer, RenderInfo, RoundCorner, Row, SpacerRow, SquareCorner, StatementInput, TopRow, Types, }; export { BaseShape, ConstantProvider, DynamicShape, InsideCorners, JaggedTeeth, Notch, OutsideCorners, PuzzleTab, StartHat, } from './constants.js'; //# sourceMappingURL=block_rendering.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/common/constants.d.ts b/appinventor/lib/blockly/@types/renderers/common/constants.d.ts index e59ee6ded1f..0f03e8092ff 100644 --- a/appinventor/lib/blockly/@types/renderers/common/constants.d.ts +++ b/appinventor/lib/blockly/@types/renderers/common/constants.d.ts @@ -424,8 +424,13 @@ export declare class ConstantProvider { * @param svg The root of the workspace's SVG. * @param tagName The name to use for the CSS style tag. * @param selector The CSS selector to use. + * @param injectionDivIfIsParent The div containing the parent workspace and + * all related workspaces and block containers, if this renderer is for the + * parent workspace. CSS variables representing SVG patterns will be scoped + * to this container. Child workspaces should not override the CSS variables + * created by the parent and thus do not need access to the injection div. */ - createDom(svg: SVGElement, tagName: string, selector: string): void; + createDom(svg: SVGElement, tagName: string, selector: string, injectionDivIfIsParent?: HTMLElement): void; /** * Create a filter for highlighting the currently rendering block during * render debugging. diff --git a/appinventor/lib/blockly/@types/renderers/common/drawer.d.ts b/appinventor/lib/blockly/@types/renderers/common/drawer.d.ts index f500101c84c..bf0c6e41e61 100644 --- a/appinventor/lib/blockly/@types/renderers/common/drawer.d.ts +++ b/appinventor/lib/blockly/@types/renderers/common/drawer.d.ts @@ -141,7 +141,7 @@ export declare class Drawer { */ protected updateConnectionHighlights(): void; /** Returns a path to highlight the given connection. */ - drawConnectionHighlightPath(measurable: Connection): void; + drawConnectionHighlightPath(measurable: Connection): SVGElement | undefined; /** * Returns a path to highlight the given conneciton, assuming it is an * input or output connection. diff --git a/appinventor/lib/blockly/@types/renderers/common/i_path_object.d.ts b/appinventor/lib/blockly/@types/renderers/common/i_path_object.d.ts index 804296b85b3..1e7d4fd5e1f 100644 --- a/appinventor/lib/blockly/@types/renderers/common/i_path_object.d.ts +++ b/appinventor/lib/blockly/@types/renderers/common/i_path_object.d.ts @@ -23,53 +23,16 @@ export interface IPathObject { constants: ConstantProvider; /** The primary path of the block. */ style: BlockStyle; - /** - * Holds the cursors SVG element when the cursor is attached to the block. - * This is null if there is no cursor on the block. - */ - cursorSvg: SVGElement | null; - /** - * Holds the markers SVG element when the marker is attached to the block. - * This is null if there is no marker on the block. - */ - markerSvg: SVGElement | null; /** * Set the path generated by the renderer onto the respective SVG element. * * @param pathString The path. */ setPath(pathString: string): void; - /** - * Apply the stored colours to the block's path, taking into account whether - * the paths belong to a shadow block. - * - * @param block The source block. - */ - applyColour(block: BlockSvg): void; - /** - * Update the style. - * - * @param blockStyle The block style to use. - */ - setStyle(blockStyle: BlockStyle): void; /** * Flip the SVG paths in RTL. */ flipRTL(): void; - /** - * Add the cursor SVG to this block's SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the block SVG - * group. - */ - setCursorSvg(cursorSvg: SVGElement): void; - /** - * Add the marker SVG to this block's SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the block SVG - * group. - */ - setMarkerSvg(markerSvg: SVGElement): void; /** * Set whether the block shows a highlight or not. Block highlighting is * often used to visually mark blocks currently being executed. @@ -103,10 +66,23 @@ export interface IPathObject { */ updateMovable(enabled: boolean): void; /** Adds the given path as a connection highlight for the given connection. */ - addConnectionHighlight?(connection: RenderedConnection, connectionPath: string, offset: Coordinate, rtl: boolean): void; + addConnectionHighlight?(connection: RenderedConnection, connectionPath: string, offset: Coordinate, rtl: boolean): SVGElement; + /** + * Apply the stored colours to the block's path, taking into account whether + * the paths belong to a shadow block. + * + * @param block The source block. + */ + applyColour?(block: BlockSvg): void; /** * Removes any highlight associated with the given connection, if it exists. */ removeConnectionHighlight?(connection: RenderedConnection): void; + /** + * Update the style. + * + * @param blockStyle The block style to use. + */ + setStyle?(blockStyle: BlockStyle): void; } //# sourceMappingURL=i_path_object.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/common/marker_svg.d.ts b/appinventor/lib/blockly/@types/renderers/common/marker_svg.d.ts deleted file mode 100644 index 594da25a3af..00000000000 --- a/appinventor/lib/blockly/@types/renderers/common/marker_svg.d.ts +++ /dev/null @@ -1,256 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import '../../events/events_marker_move.js'; -import type { IASTNodeLocationSvg } from '../../interfaces/i_ast_node_location_svg.js'; -import { ASTNode } from '../../keyboard_nav/ast_node.js'; -import type { Marker } from '../../keyboard_nav/marker.js'; -import type { RenderedConnection } from '../../rendered_connection.js'; -import type { WorkspaceSvg } from '../../workspace_svg.js'; -import type { ConstantProvider, Notch, PuzzleTab } from './constants.js'; -/** - * Class for a marker, containing methods for graphically rendering a marker as - * SVG. - */ -export declare class MarkerSvg { - protected readonly workspace: WorkspaceSvg; - protected readonly marker: Marker; - /** - * The workspace, field, or block that the marker SVG element should be - * attached to. - */ - protected parent: IASTNodeLocationSvg | null; - /** The current SVG element for the marker. */ - currentMarkerSvg: SVGElement | null; - colour_: string; - /** The root SVG group containing the marker. */ - protected markerSvg_: SVGGElement | null; - protected svgGroup_: SVGGElement | null; - protected markerBlock_: SVGPathElement | null; - protected markerInput_: SVGPathElement | null; - protected markerSvgLine_: SVGRectElement | null; - protected markerSvgRect_: SVGRectElement | null; - /** The constants necessary to draw the marker. */ - protected constants_: ConstantProvider; - /** - * @param workspace The workspace the marker belongs to. - * @param constants The constants for the renderer. - * @param marker The marker to draw. - */ - constructor(workspace: WorkspaceSvg, constants: ConstantProvider, marker: Marker); - /** - * Return the root node of the SVG or null if none exists. - * - * @returns The root SVG node. - */ - getSvgRoot(): SVGElement | null; - /** - * Get the marker. - * - * @returns The marker to draw for. - */ - getMarker(): Marker; - /** - * True if the marker should be drawn as a cursor, false otherwise. - * A cursor is drawn as a flashing line. A marker is drawn as a solid line. - * - * @returns True if the marker is a cursor, false otherwise. - */ - isCursor(): boolean; - /** - * Create the DOM element for the marker. - * - * @returns The marker controls SVG group. - */ - createDom(): SVGElement; - /** - * Attaches the SVG root of the marker to the SVG group of the parent. - * - * @param newParent The workspace, field, or block that the marker SVG element - * should be attached to. - */ - protected setParent_(newParent: IASTNodeLocationSvg): void; - /** - * Update the marker. - * - * @param oldNode The previous node the marker was on or null. - * @param curNode The node that we want to draw the marker for. - */ - draw(oldNode: ASTNode, curNode: ASTNode): void; - /** - * Update the marker's visible state based on the type of curNode.. - * - * @param curNode The node that we want to draw the marker for. - */ - protected showAtLocation_(curNode: ASTNode): void; - /************************** - * Display - **************************/ - /** - * Show the marker as a combination of the previous connection and block, - * the output connection and block, or just the block. - * - * @param curNode The node to draw the marker for. - */ - protected showWithBlockPrevOutput(curNode: ASTNode): void; - /** - * Position and display the marker for a block. - * - * @param curNode The node to draw the marker for. - */ - protected showWithBlock_(curNode: ASTNode): void; - /** - * Position and display the marker for a previous connection. - * - * @param curNode The node to draw the marker for. - */ - protected showWithPrevious_(curNode: ASTNode): void; - /** - * Position and display the marker for an output connection. - * - * @param curNode The node to draw the marker for. - */ - protected showWithOutput_(curNode: ASTNode): void; - /** - * Position and display the marker for a workspace coordinate. - * This is a horizontal line. - * - * @param curNode The node to draw the marker for. - */ - protected showWithCoordinates_(curNode: ASTNode): void; - /** - * Position and display the marker for a field. - * This is a box around the field. - * - * @param curNode The node to draw the marker for. - */ - protected showWithField_(curNode: ASTNode): void; - /** - * Position and display the marker for an input. - * This is a puzzle piece. - * - * @param curNode The node to draw the marker for. - */ - protected showWithInput_(curNode: ASTNode): void; - /** - * Position and display the marker for a next connection. - * This is a horizontal line. - * - * @param curNode The node to draw the marker for. - */ - protected showWithNext_(curNode: ASTNode): void; - /** - * Position and display the marker for a stack. - * This is a box with extra padding around the entire stack of blocks. - * - * @param curNode The node to draw the marker for. - */ - protected showWithStack_(curNode: ASTNode): void; - /** - * Position and display the marker for a flyout button. - * This is a box with extra padding around the button. - * - * @param curNode The node to draw the marker for. - */ - protected showWithButton_(curNode: ASTNode): void; - /** Show the current marker. */ - protected showCurrent_(): void; - /************************** - * Position - **************************/ - /** - * Position the marker for a block. - * Displays an outline of the top half of a rectangle around a block. - * - * @param width The width of the block. - * @param markerOffset The extra padding for around the block. - * @param markerHeight The height of the marker. - */ - protected positionBlock_(width: number, markerOffset: number, markerHeight: number): void; - /** - * Position the marker for an input connection. - * Displays a filled in puzzle piece. - * - * @param connection The connection to position marker around. - */ - protected positionInput_(connection: RenderedConnection): void; - /** - * Move and show the marker at the specified coordinate in workspace units. - * Displays a horizontal line. - * - * @param x The new x, in workspace units. - * @param y The new y, in workspace units. - * @param width The new width, in workspace units. - */ - protected positionLine_(x: number, y: number, width: number): void; - /** - * Position the marker for an output connection. - * Displays a puzzle outline and the top and bottom path. - * - * @param width The width of the block. - * @param height The height of the block. - * @param connectionShape The shape object for the connection. - */ - protected positionOutput_(width: number, height: number, connectionShape: PuzzleTab): void; - /** - * Position the marker for a previous connection. - * Displays a half rectangle with a notch in the top to represent the previous - * connection. - * - * @param width The width of the block. - * @param markerOffset The offset of the marker from around the block. - * @param markerHeight The height of the marker. - * @param connectionShape The shape object for the connection. - */ - protected positionPrevious_(width: number, markerOffset: number, markerHeight: number, connectionShape: Notch): void; - /** - * Move and show the marker at the specified coordinate in workspace units. - * Displays a filled in rectangle. - * - * @param x The new x, in workspace units. - * @param y The new y, in workspace units. - * @param width The new width, in workspace units. - * @param height The new height, in workspace units. - */ - protected positionRect_(x: number, y: number, width: number, height: number): void; - /** - * Flip the SVG paths in RTL. - * - * @param markerSvg The marker that we want to flip. - */ - private flipRtl; - /** Hide the marker. */ - hide(): void; - /** - * Fire event for the marker or marker. - * - * @param oldNode The old node the marker used to be on. - * @param curNode The new node the marker is currently on. - */ - protected fireMarkerEvent(oldNode: ASTNode, curNode: ASTNode): void; - /** - * Get the properties to make a marker blink. - * - * @returns The object holding attributes to make the marker blink. - */ - protected getBlinkProperties_(): { - [key: string]: string; - }; - /** - * Create the marker SVG. - * - * @returns The SVG node created. - */ - protected createDomInternal_(): Element; - /** - * Apply the marker's colour. - * - * @param _curNode The node that we want to draw the marker for. - */ - protected applyColour_(_curNode: ASTNode): void; - /** Dispose of this marker. */ - dispose(): void; -} -//# sourceMappingURL=marker_svg.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/common/path_object.d.ts b/appinventor/lib/blockly/@types/renderers/common/path_object.d.ts index ba83f196b59..8f0056fbdf4 100644 --- a/appinventor/lib/blockly/@types/renderers/common/path_object.d.ts +++ b/appinventor/lib/blockly/@types/renderers/common/path_object.d.ts @@ -17,16 +17,6 @@ import type { IPathObject } from './i_path_object.js'; export declare class PathObject implements IPathObject { svgRoot: SVGElement; svgPath: SVGElement; - /** - * Holds the cursors svg element when the cursor is attached to the block. - * This is null if there is no cursor on the block. - */ - cursorSvg: SVGElement | null; - /** - * Holds the markers svg element when the marker is attached to the block. - * This is null if there is no marker on the block. - */ - markerSvg: SVGElement | null; constants: ConstantProvider; style: BlockStyle; /** Highlight paths associated with connections. */ @@ -49,20 +39,6 @@ export declare class PathObject implements IPathObject { * Flip the SVG paths in RTL. */ flipRTL(): void; - /** - * Add the cursor SVG to this block's SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the block SVG - * group. - */ - setCursorSvg(cursorSvg: SVGElement): void; - /** - * Add the marker SVG to this block's SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the block SVG - * group. - */ - setMarkerSvg(markerSvg: SVGElement): void; /** * Apply the stored colours to the block's path, taking into account whether * the paths belong to a shadow block. @@ -145,8 +121,7 @@ export declare class PathObject implements IPathObject { */ updateShapeForInputHighlight(_conn: Connection, _enable: boolean): void; /** Adds the given path as a connection highlight for the given connection. */ - addConnectionHighlight(connection: RenderedConnection, connectionPath: string, offset: Coordinate, rtl: boolean): void; - private currentHighlightMatchesNew; + addConnectionHighlight(connection: RenderedConnection, connectionPath: string, offset: Coordinate, rtl: boolean): SVGElement; /** * Removes any highlight associated with the given connection, if it exists. */ diff --git a/appinventor/lib/blockly/@types/renderers/common/renderer.d.ts b/appinventor/lib/blockly/@types/renderers/common/renderer.d.ts index ecf114718f0..1fe6573e16e 100644 --- a/appinventor/lib/blockly/@types/renderers/common/renderer.d.ts +++ b/appinventor/lib/blockly/@types/renderers/common/renderer.d.ts @@ -5,17 +5,12 @@ */ import type { BlockSvg } from '../../block_svg.js'; import { Connection } from '../../connection.js'; -import { PreviewType } from '../../insertion_marker_manager.js'; import type { IRegistrable } from '../../interfaces/i_registrable.js'; -import type { Marker } from '../../keyboard_nav/marker.js'; -import type { RenderedConnection } from '../../rendered_connection.js'; import type { BlockStyle, Theme } from '../../theme.js'; -import type { WorkspaceSvg } from '../../workspace_svg.js'; import { ConstantProvider } from './constants.js'; import { Drawer } from './drawer.js'; import type { IPathObject } from './i_path_object.js'; import { RenderInfo } from './info.js'; -import { MarkerSvg } from './marker_svg.js'; /** * The base class for a block renderer. */ @@ -49,20 +44,30 @@ export declare class Renderer implements IRegistrable { /** * Create any DOM elements that this renderer needs. * If you need to create additional DOM elements, override the - * {@link ConstantProvider#createDom} method instead. + * {@link blockRendering#ConstantProvider.createDom} method instead. * * @param svg The root of the workspace's SVG. * @param theme The workspace theme object. + * @param injectionDivIfIsParent The div containing the parent workspace and + * all related workspaces and block containers, if this renderer is for the + * parent workspace. CSS variables representing SVG patterns will be scoped + * to this container. Child workspaces should not override the CSS variables + * created by the parent and thus do not need access to the injection div. * @internal */ - createDom(svg: SVGElement, theme: Theme): void; + createDom(svg: SVGElement, theme: Theme, injectionDivIfIsParent?: HTMLElement): void; /** * Refresh the renderer after a theme change. * * @param svg The root of the workspace's SVG. * @param theme The workspace theme object. + * @param injectionDivIfIsParent The div containing the parent workspace and + * all related workspaces and block containers, if this renderer is for the + * parent workspace. CSS variables representing SVG patterns will be scoped + * to this container. Child workspaces should not override the CSS variables + * created by the parent and thus do not need access to the injection div. */ - refreshDom(svg: SVGElement, theme: Theme): void; + refreshDom(svg: SVGElement, theme: Theme, injectionDivIfIsParent?: HTMLElement): void; /** * Dispose of this renderer. * Delete all DOM elements that this renderer and its constants created. @@ -90,14 +95,6 @@ export declare class Renderer implements IRegistrable { * @returns The drawer. */ protected makeDrawer_(block: BlockSvg, info: RenderInfo): Drawer; - /** - * Create a new instance of the renderer's marker drawer. - * - * @param workspace The workspace the marker belongs to. - * @param marker The marker. - * @returns The object in charge of drawing the marker. - */ - makeMarkerDrawer(workspace: WorkspaceSvg, marker: Marker): MarkerSvg; /** * Create a new instance of a renderer path object. * @@ -133,19 +130,6 @@ export declare class Renderer implements IRegistrable { * @returns Whether there is a home for the orphan or not. */ protected orphanCanConnectAtEnd(topBlock: BlockSvg, orphanBlock: BlockSvg, localType: number): boolean; - /** - * Chooses a connection preview method based on the available connection, the - * current dragged connection, and the block being dragged. - * - * @param closest The available connection. - * @param local The connection currently being dragged. - * @param topBlock The block currently being dragged. - * @returns The preview type to display. - * - * @deprecated v10 - This function is no longer respected. A custom - * IConnectionPreviewer may be able to fulfill the functionality. - */ - getConnectionPreviewMethod(closest: RenderedConnection, local: RenderedConnection, topBlock: BlockSvg): PreviewType; /** * Render the block. * diff --git a/appinventor/lib/blockly/@types/renderers/geras/renderer.d.ts b/appinventor/lib/blockly/@types/renderers/geras/renderer.d.ts index 00ab2dd0563..4233663c44a 100644 --- a/appinventor/lib/blockly/@types/renderers/geras/renderer.d.ts +++ b/appinventor/lib/blockly/@types/renderers/geras/renderer.d.ts @@ -34,7 +34,7 @@ export declare class Renderer extends BaseRenderer { init(theme: Theme, opt_rendererOverrides?: { [rendererConstant: string]: any; }): void; - refreshDom(svg: SVGElement, theme: Theme): void; + refreshDom(svg: SVGElement, theme: Theme, injectionDiv: HTMLElement): void; makeConstants_(): ConstantProvider; /** * Create a new instance of the renderer's render info object. diff --git a/appinventor/lib/blockly/@types/renderers/measurables/in_row_spacer.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/in_row_spacer.d.ts index 1fd642582f4..67c32a0375f 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/in_row_spacer.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/in_row_spacer.d.ts @@ -10,6 +10,7 @@ import { Measurable } from './base.js'; * row. */ export declare class InRowSpacer extends Measurable { + private inRowSpacer; /** * @param constants The rendering constants provider. * @param width The width of the spacer. diff --git a/appinventor/lib/blockly/@types/renderers/measurables/jagged_edge.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/jagged_edge.d.ts index fee0e00e3f0..3c8339fd2b6 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/jagged_edge.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/jagged_edge.d.ts @@ -10,6 +10,7 @@ import { Measurable } from './base.js'; * collapsed block takes up during rendering. */ export declare class JaggedEdge extends Measurable { + private jaggedEdge; /** * @param constants The rendering constants provider. */ diff --git a/appinventor/lib/blockly/@types/renderers/measurables/next_connection.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/next_connection.d.ts index e7a8221968f..9cbc4c19b52 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/next_connection.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/next_connection.d.ts @@ -11,6 +11,7 @@ import { Connection } from './connection.js'; * up during rendering. */ export declare class NextConnection extends Connection { + private nextConnection; /** * @param constants The rendering constants provider. * @param connectionModel The connection object on the block that this diff --git a/appinventor/lib/blockly/@types/renderers/measurables/previous_connection.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/previous_connection.d.ts index ddad788e1ba..6aba066c3f0 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/previous_connection.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/previous_connection.d.ts @@ -11,6 +11,7 @@ import { Connection } from './connection.js'; * up during rendering. */ export declare class PreviousConnection extends Connection { + private previousConnection; /** * @param constants The rendering constants provider. * @param connectionModel The connection object on the block that this diff --git a/appinventor/lib/blockly/@types/renderers/measurables/round_corner.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/round_corner.d.ts index 709033a65db..c5949ed7c67 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/round_corner.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/round_corner.d.ts @@ -10,6 +10,7 @@ import { Measurable } from './base.js'; * during rendering. */ export declare class RoundCorner extends Measurable { + private roundCorner; /** * @param constants The rendering constants provider. * @param opt_position The position of this corner. diff --git a/appinventor/lib/blockly/@types/renderers/measurables/square_corner.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/square_corner.d.ts index e0f0c8b7e9a..edf5887614d 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/square_corner.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/square_corner.d.ts @@ -10,6 +10,7 @@ import { Measurable } from './base.js'; * during rendering. */ export declare class SquareCorner extends Measurable { + private squareCorner; /** * @param constants The rendering constants provider. * @param opt_position The position of this corner. diff --git a/appinventor/lib/blockly/@types/renderers/measurables/statement_input.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/statement_input.d.ts index bc37c0d195d..320650d463e 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/statement_input.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/statement_input.d.ts @@ -11,6 +11,7 @@ import { InputConnection } from './input_connection.js'; * during rendering */ export declare class StatementInput extends InputConnection { + private statementInput; /** * @param constants The rendering constants provider. * @param input The statement input to measure and store information for. diff --git a/appinventor/lib/blockly/@types/renderers/measurables/types.d.ts b/appinventor/lib/blockly/@types/renderers/measurables/types.d.ts index fc170ba7178..0d9c81fa1e9 100644 --- a/appinventor/lib/blockly/@types/renderers/measurables/types.d.ts +++ b/appinventor/lib/blockly/@types/renderers/measurables/types.d.ts @@ -4,7 +4,24 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { Measurable } from './base.js'; +import type { BottomRow } from './bottom_row.js'; +import type { ExternalValueInput } from './external_value_input.js'; +import type { Field } from './field.js'; +import type { Hat } from './hat.js'; +import type { Icon } from './icon.js'; +import type { InRowSpacer } from './in_row_spacer.js'; +import type { InlineInput } from './inline_input.js'; +import type { InputConnection } from './input_connection.js'; +import type { InputRow } from './input_row.js'; +import type { JaggedEdge } from './jagged_edge.js'; +import type { NextConnection } from './next_connection.js'; +import type { PreviousConnection } from './previous_connection.js'; +import type { RoundCorner } from './round_corner.js'; import type { Row } from './row.js'; +import type { SpacerRow } from './spacer_row.js'; +import type { SquareCorner } from './square_corner.js'; +import type { StatementInput } from './statement_input.js'; +import type { TopRow } from './top_row.js'; /** * Types of rendering elements. */ @@ -63,77 +80,84 @@ declare class TypesContainer { * @param elem The element to check. * @returns 1 if the object stores information about a field. */ - isField(elem: Measurable): number; + isField(elem: Measurable): elem is Field; /** * Whether a measurable stores information about a hat. * * @param elem The element to check. * @returns 1 if the object stores information about a hat. */ - isHat(elem: Measurable): number; + isHat(elem: Measurable): elem is Hat; /** * Whether a measurable stores information about an icon. * * @param elem The element to check. * @returns 1 if the object stores information about an icon. */ - isIcon(elem: Measurable): number; + isIcon(elem: Measurable): elem is Icon; /** * Whether a measurable stores information about a spacer. * * @param elem The element to check. * @returns 1 if the object stores information about a spacer. */ - isSpacer(elem: Measurable | Row): number; + isSpacer(elem: Measurable | Row): elem is SpacerRow | InRowSpacer; /** * Whether a measurable stores information about an in-row spacer. * * @param elem The element to check. * @returns 1 if the object stores information about an in-row spacer. */ - isInRowSpacer(elem: Measurable): number; + isInRowSpacer(elem: Measurable): elem is InRowSpacer; + /** + * Whether a row is a spacer row. + * + * @param row The row to check. + * @returns True if the row is a spacer row. + */ + isSpacerRow(row: Row): row is SpacerRow; /** * Whether a measurable stores information about an input. * * @param elem The element to check. * @returns 1 if the object stores information about an input. */ - isInput(elem: Measurable): number; + isInput(elem: Measurable): elem is InputConnection; /** * Whether a measurable stores information about an external input. * * @param elem The element to check. * @returns 1 if the object stores information about an external input. */ - isExternalInput(elem: Measurable): number; + isExternalInput(elem: Measurable): elem is ExternalValueInput; /** * Whether a measurable stores information about an inline input. * * @param elem The element to check. * @returns 1 if the object stores information about an inline input. */ - isInlineInput(elem: Measurable): number; + isInlineInput(elem: Measurable): elem is InlineInput; /** * Whether a measurable stores information about a statement input. * * @param elem The element to check. * @returns 1 if the object stores information about a statement input. */ - isStatementInput(elem: Measurable): number; + isStatementInput(elem: Measurable): elem is StatementInput; /** * Whether a measurable stores information about a previous connection. * * @param elem The element to check. * @returns 1 if the object stores information about a previous connection. */ - isPreviousConnection(elem: Measurable): number; + isPreviousConnection(elem: Measurable): elem is PreviousConnection; /** * Whether a measurable stores information about a next connection. * * @param elem The element to check. * @returns 1 if the object stores information about a next connection. */ - isNextConnection(elem: Measurable): number; + isNextConnection(elem: Measurable): elem is NextConnection; /** * Whether a measurable stores information about a previous or next * connection. @@ -142,91 +166,92 @@ declare class TypesContainer { * @returns 1 if the object stores information about a previous or next * connection. */ - isPreviousOrNextConnection(elem: Measurable): number; + isPreviousOrNextConnection(elem: Measurable): elem is PreviousConnection | NextConnection; + isRoundCorner(elem: Measurable): elem is RoundCorner; /** * Whether a measurable stores information about a left round corner. * * @param elem The element to check. * @returns 1 if the object stores information about a left round corner. */ - isLeftRoundedCorner(elem: Measurable): number; + isLeftRoundedCorner(elem: Measurable): boolean; /** * Whether a measurable stores information about a right round corner. * * @param elem The element to check. * @returns 1 if the object stores information about a right round corner. */ - isRightRoundedCorner(elem: Measurable): number; + isRightRoundedCorner(elem: Measurable): boolean; /** * Whether a measurable stores information about a left square corner. * * @param elem The element to check. * @returns 1 if the object stores information about a left square corner. */ - isLeftSquareCorner(elem: Measurable): number; + isLeftSquareCorner(elem: Measurable): boolean; /** * Whether a measurable stores information about a right square corner. * * @param elem The element to check. * @returns 1 if the object stores information about a right square corner. */ - isRightSquareCorner(elem: Measurable): number; + isRightSquareCorner(elem: Measurable): boolean; /** * Whether a measurable stores information about a corner. * * @param elem The element to check. * @returns 1 if the object stores information about a corner. */ - isCorner(elem: Measurable): number; + isCorner(elem: Measurable): elem is SquareCorner | RoundCorner; /** * Whether a measurable stores information about a jagged edge. * * @param elem The element to check. * @returns 1 if the object stores information about a jagged edge. */ - isJaggedEdge(elem: Measurable): number; + isJaggedEdge(elem: Measurable): elem is JaggedEdge; /** * Whether a measurable stores information about a row. * * @param row The row to check. * @returns 1 if the object stores information about a row. */ - isRow(row: Row): number; + isRow(row: Row): row is Row; /** * Whether a measurable stores information about a between-row spacer. * * @param row The row to check. * @returns 1 if the object stores information about a between-row spacer. */ - isBetweenRowSpacer(row: Row): number; + isBetweenRowSpacer(row: Row): row is SpacerRow; /** * Whether a measurable stores information about a top row. * * @param row The row to check. * @returns 1 if the object stores information about a top row. */ - isTopRow(row: Row): number; + isTopRow(row: Row): row is TopRow; /** * Whether a measurable stores information about a bottom row. * * @param row The row to check. * @returns 1 if the object stores information about a bottom row. */ - isBottomRow(row: Row): number; + isBottomRow(row: Row): row is BottomRow; /** * Whether a measurable stores information about a top or bottom row. * * @param row The row to check. * @returns 1 if the object stores information about a top or bottom row. */ - isTopOrBottomRow(row: Row): number; + isTopOrBottomRow(row: Row): row is TopRow | BottomRow; /** * Whether a measurable stores information about an input row. * * @param row The row to check. * @returns 1 if the object stores information about an input row. */ - isInputRow(row: Row): number; + isInputRow(row: Row): row is InputRow; } export declare const Types: TypesContainer; export {}; diff --git a/appinventor/lib/blockly/@types/renderers/zelos/constants.d.ts b/appinventor/lib/blockly/@types/renderers/zelos/constants.d.ts index c1eca8dbbe1..0c81bebfadb 100644 --- a/appinventor/lib/blockly/@types/renderers/zelos/constants.d.ts +++ b/appinventor/lib/blockly/@types/renderers/zelos/constants.d.ts @@ -102,7 +102,13 @@ export declare class ConstantProvider extends BaseConstantProvider { * rectangular reporter block. Null before init is called. */ SQUARED: Shape | null; - constructor(); + /** + * Creates a new ConstantProvider. + * + * @param gridUnit If set, defines the base unit used to calculate other + * constants. + */ + constructor(gridUnit?: number); setFontConstants_(theme: Theme): void; init(): void; setDynamicProperties_(theme: Theme): void; @@ -153,7 +159,7 @@ export declare class ConstantProvider extends BaseConstantProvider { }; generateSecondaryColour_(colour: string): string; generateTertiaryColour_(colour: string): string; - createDom(svg: SVGElement, tagName: string, selector: string): void; + createDom(svg: SVGElement, tagName: string, selector: string, injectionDivIfIsParent?: HTMLElement): void; getCSS_(selector: string): string[]; } //# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/zelos/drawer.d.ts b/appinventor/lib/blockly/@types/renderers/zelos/drawer.d.ts index 0a2a90d34e9..0ecd33bff22 100644 --- a/appinventor/lib/blockly/@types/renderers/zelos/drawer.d.ts +++ b/appinventor/lib/blockly/@types/renderers/zelos/drawer.d.ts @@ -46,6 +46,6 @@ export declare class Drawer extends BaseDrawer { private getInlineInputPath; drawStatementInput_(row: Row): void; /** Returns a path to highlight the given connection. */ - drawConnectionHighlightPath(measurable: Connection): void; + drawConnectionHighlightPath(measurable: Connection): SVGElement | undefined; } //# sourceMappingURL=drawer.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/zelos/marker_svg.d.ts b/appinventor/lib/blockly/@types/renderers/zelos/marker_svg.d.ts deleted file mode 100644 index 41faedc6d13..00000000000 --- a/appinventor/lib/blockly/@types/renderers/zelos/marker_svg.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import type { ASTNode } from '../../keyboard_nav/ast_node.js'; -import type { Marker } from '../../keyboard_nav/marker.js'; -import type { WorkspaceSvg } from '../../workspace_svg.js'; -import type { ConstantProvider as BaseConstantProvider } from '../common/constants.js'; -import { MarkerSvg as BaseMarkerSvg } from '../common/marker_svg.js'; -import type { ConstantProvider as ZelosConstantProvider } from './constants.js'; -/** - * Class to draw a marker. - */ -export declare class MarkerSvg extends BaseMarkerSvg { - constants_: ZelosConstantProvider; - private markerCircle; - /** - * @param workspace The workspace the marker belongs to. - * @param constants The constants for the renderer. - * @param marker The marker to draw. - */ - constructor(workspace: WorkspaceSvg, constants: BaseConstantProvider, marker: Marker); - /** - * Position and display the marker for an input or an output connection. - * - * @param curNode The node to draw the marker for. - */ - private showWithInputOutput; - showWithOutput_(curNode: ASTNode): void; - showWithInput_(curNode: ASTNode): void; - /** - * Draw a rectangle around the block. - * - * @param curNode The current node of the marker. - */ - showWithBlock_(curNode: ASTNode): void; - /** - * Position the circle we use for input and output connections. - * - * @param x The x position of the circle. - * @param y The y position of the circle. - */ - private positionCircle; - hide(): void; - createDomInternal_(): SVGGElement; - applyColour_(curNode: ASTNode): void; -} -//# sourceMappingURL=marker_svg.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/zelos/path_object.d.ts b/appinventor/lib/blockly/@types/renderers/zelos/path_object.d.ts index 7278f16386e..2421b4ea13e 100644 --- a/appinventor/lib/blockly/@types/renderers/zelos/path_object.d.ts +++ b/appinventor/lib/blockly/@types/renderers/zelos/path_object.d.ts @@ -61,10 +61,11 @@ export declare class PathObject extends BasePathObject { /** * Create's an outline path for the specified input. * + * @internal * @param name The input name. * @returns The SVG outline path. */ - private getOutlinePath; + getOutlinePath(name: string): SVGElement; /** * Remove an outline path that is associated with the specified input. * diff --git a/appinventor/lib/blockly/@types/renderers/zelos/renderer.d.ts b/appinventor/lib/blockly/@types/renderers/zelos/renderer.d.ts index 1cc5e1a8394..960d804a577 100644 --- a/appinventor/lib/blockly/@types/renderers/zelos/renderer.d.ts +++ b/appinventor/lib/blockly/@types/renderers/zelos/renderer.d.ts @@ -4,17 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { BlockSvg } from '../../block_svg.js'; -import { InsertionMarkerManager } from '../../insertion_marker_manager.js'; -import type { Marker } from '../../keyboard_nav/marker.js'; -import type { RenderedConnection } from '../../rendered_connection.js'; import type { BlockStyle } from '../../theme.js'; -import type { WorkspaceSvg } from '../../workspace_svg.js'; import type { RenderInfo as BaseRenderInfo } from '../common/info.js'; import { Renderer as BaseRenderer } from '../common/renderer.js'; import { ConstantProvider } from './constants.js'; import { Drawer } from './drawer.js'; import { RenderInfo } from './info.js'; -import { MarkerSvg } from './marker_svg.js'; import { PathObject } from './path_object.js'; /** * The zelos renderer. This renderer emulates Scratch-style and MakeCode-style @@ -50,14 +45,6 @@ export declare class Renderer extends BaseRenderer { * @returns The drawer. */ protected makeDrawer_(block: BlockSvg, info: BaseRenderInfo): Drawer; - /** - * Create a new instance of the renderer's cursor drawer. - * - * @param workspace The workspace the cursor belongs to. - * @param marker The marker. - * @returns The object in charge of drawing the marker. - */ - makeMarkerDrawer(workspace: WorkspaceSvg, marker: Marker): MarkerSvg; /** * Create a new instance of a renderer path object. * @@ -73,10 +60,5 @@ export declare class Renderer extends BaseRenderer { * @returns The constant provider. */ getConstants(): ConstantProvider; - /** - * @deprecated v10 - This function is no longer respected. A custom - * IConnectionPreviewer may be able to fulfill the functionality. - */ - getConnectionPreviewMethod(closest: RenderedConnection, local: RenderedConnection, topBlock: BlockSvg): InsertionMarkerManager.PREVIEW_TYPE; } //# sourceMappingURL=renderer.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/renderers/zelos/zelos.d.ts b/appinventor/lib/blockly/@types/renderers/zelos/zelos.d.ts index 379a737b239..970f549ee15 100644 --- a/appinventor/lib/blockly/@types/renderers/zelos/zelos.d.ts +++ b/appinventor/lib/blockly/@types/renderers/zelos/zelos.d.ts @@ -7,12 +7,11 @@ import { ConstantProvider } from './constants.js'; import { Drawer } from './drawer.js'; import { RenderInfo } from './info.js'; -import { MarkerSvg } from './marker_svg.js'; import { BottomRow } from './measurables/bottom_row.js'; import { StatementInput } from './measurables/inputs.js'; import { RightConnectionShape } from './measurables/row_elements.js'; import { TopRow } from './measurables/top_row.js'; import { PathObject } from './path_object.js'; import { Renderer } from './renderer.js'; -export { BottomRow, ConstantProvider, Drawer, MarkerSvg, PathObject, Renderer, RenderInfo, RightConnectionShape, StatementInput, TopRow, }; +export { BottomRow, ConstantProvider, Drawer, PathObject, Renderer, RenderInfo, RightConnectionShape, StatementInput, TopRow, }; //# sourceMappingURL=zelos.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/separator_flyout_inflater.d.ts b/appinventor/lib/blockly/@types/separator_flyout_inflater.d.ts new file mode 100644 index 00000000000..2448ced4369 --- /dev/null +++ b/appinventor/lib/blockly/@types/separator_flyout_inflater.d.ts @@ -0,0 +1,57 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { FlyoutItem } from './flyout_item.js'; +import type { IFlyout } from './interfaces/i_flyout.js'; +import type { IFlyoutInflater } from './interfaces/i_flyout_inflater.js'; +/** + * @internal + */ +export declare const SEPARATOR_TYPE = "sep"; +/** + * Class responsible for creating separators for flyouts. + */ +export declare class SeparatorFlyoutInflater implements IFlyoutInflater { + /** + * Inflates a dummy flyout separator. + * + * The flyout automatically creates separators between every element with a + * size determined by calling gapForElement on the relevant inflater. + * Additionally, users can explicitly add separators in the flyout definition. + * When separators (implicitly or explicitly created) follow one another, the + * gap of the last one propagates backwards and flattens to one separator. + * This flattening is not additive; if there are initially separators of 2, 3, + * and 4 pixels, after normalization there will be one separator of 4 pixels. + * Therefore, this method returns a zero-width separator, which will be + * replaced by the one implicitly created by the flyout based on the value + * returned by gapForElement, which knows the default gap, unlike this method. + * + * @param _state A JSON representation of a flyout separator. + * @param flyout The flyout to create the separator for. + * @returns A newly created FlyoutSeparator. + */ + load(_state: object, flyout: IFlyout): FlyoutItem; + /** + * Returns the size of the separator. See `load` for more details. + * + * @param state A JSON representation of a flyout separator. + * @param defaultGap The default spacing for flyout items. + * @returns The desired size of the separator. + */ + gapForItem(state: object, defaultGap: number): number; + /** + * Disposes of the given separator. Intentional no-op. + * + * @param _item The flyout separator to dispose of. + */ + disposeItem(_item: FlyoutItem): void; + /** + * Returns the type of items this inflater is responsible for creating. + * + * @returns An identifier for the type of items this inflater creates. + */ + getType(): string; +} +//# sourceMappingURL=separator_flyout_inflater.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/serialization/variables.d.ts b/appinventor/lib/blockly/@types/serialization/variables.d.ts index e95e061d2f8..843ae898b9c 100644 --- a/appinventor/lib/blockly/@types/serialization/variables.d.ts +++ b/appinventor/lib/blockly/@types/serialization/variables.d.ts @@ -4,15 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { ISerializer } from '../interfaces/i_serializer.js'; +import type { IVariableState } from '../interfaces/i_variable_model.js'; import type { Workspace } from '../workspace.js'; -/** - * Represents the state of a given variable. - */ -export interface State { - name: string; - id: string; - type: string | undefined; -} /** * Serializer for saving and loading variable state. */ @@ -26,7 +19,7 @@ export declare class VariableSerializer implements ISerializer { * @returns The state of the workspace's variables, or null if there are no * variables. */ - save(workspace: Workspace): State[] | null; + save(workspace: Workspace): IVariableState[] | null; /** * Deserializes the variable defined by the given state into the given * workspace. @@ -34,7 +27,7 @@ export declare class VariableSerializer implements ISerializer { * @param state The state of the variables to deserialize. * @param workspace The workspace to deserialize into. */ - load(state: State[], workspace: Workspace): void; + load(state: IVariableState[], workspace: Workspace): void; /** * Disposes of any variables that exist on the workspace. * diff --git a/appinventor/lib/blockly/@types/shortcut_items.d.ts b/appinventor/lib/blockly/@types/shortcut_items.d.ts index dd414b972a3..4bbe6b64be9 100644 --- a/appinventor/lib/blockly/@types/shortcut_items.d.ts +++ b/appinventor/lib/blockly/@types/shortcut_items.d.ts @@ -13,7 +13,8 @@ export declare enum names { CUT = "cut", PASTE = "paste", UNDO = "undo", - REDO = "redo" + REDO = "redo", + MENU = "menu" } /** * Keyboard shortcut to hide chaff on escape. @@ -44,6 +45,10 @@ export declare function registerUndo(): void; * or alt+shift+z. */ export declare function registerRedo(): void; +/** + * Keyboard shortcut to show the context menu on ctrl/cmd+Enter. + */ +export declare function registerShowContextMenu(): void; /** * Registers all default keyboard shortcut item. This should be called once per * instance of KeyboardShortcutRegistry. diff --git a/appinventor/lib/blockly/@types/shortcut_registry.d.ts b/appinventor/lib/blockly/@types/shortcut_registry.d.ts index b822d29de69..e273347f220 100644 --- a/appinventor/lib/blockly/@types/shortcut_registry.d.ts +++ b/appinventor/lib/blockly/@types/shortcut_registry.d.ts @@ -9,6 +9,7 @@ * * @class */ +import { Scope } from './contextmenu_registry.js'; import { KeyCodes } from './utils/keycodes.js'; import { WorkspaceSvg } from './workspace_svg.js'; /** @@ -183,12 +184,14 @@ export declare namespace ShortcutRegistry { * @param e The event that caused the shortcut to be activated. * @param shortcut The `KeyboardShortcut` that was activated * (i.e., the one this callback is attached to). + * @param scope Information about the focused item when the + * shortcut was invoked. * @returns Returning true ends processing of the invoked keycode. * Returning false causes processing to continue with the * next-most-recently registered shortcut for the invoked * keycode. */ - callback?: (workspace: WorkspaceSvg, e: Event, shortcut: KeyboardShortcut) => boolean; + callback?: (workspace: WorkspaceSvg, e: Event, shortcut: KeyboardShortcut, scope: Scope) => boolean; /** The name of the shortcut. Should be unique. */ name: string; /** @@ -198,9 +201,11 @@ export declare namespace ShortcutRegistry { * * @param workspace The `WorkspaceSvg` where the shortcut was * invoked. + * @param scope Information about the focused item when the + * shortcut would be invoked. * @returns True iff `callback` function should be called. */ - preconditionFn?: (workspace: WorkspaceSvg) => boolean; + preconditionFn?: (workspace: WorkspaceSvg, scope: Scope) => boolean; /** Optional arbitray extra data attached to the shortcut. */ metadata?: object; /** diff --git a/appinventor/lib/blockly/@types/toast.d.ts b/appinventor/lib/blockly/@types/toast.d.ts new file mode 100644 index 00000000000..b7bc497b98e --- /dev/null +++ b/appinventor/lib/blockly/@types/toast.d.ts @@ -0,0 +1,74 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { WorkspaceSvg } from './workspace_svg.js'; +/** + * Display/configuration options for a toast notification. + */ +export interface ToastOptions { + /** + * Toast ID. If set along with `oncePerSession`, will cause subsequent toasts + * with this ID to not be shown. + */ + id?: string; + /** + * Flag to show the toast once per session only. + * Subsequent calls are ignored. + */ + oncePerSession?: boolean; + /** + * Text of the message to display on the toast. + */ + message: string; + /** + * Duration in seconds before the toast is removed. Defaults to 5. + */ + duration?: number; + /** + * How prominently/interrupting the readout of the toast should be for + * screenreaders. Corresponds to aria-live and defaults to polite. + */ + assertiveness?: Toast.Assertiveness; +} +/** + * Class that allows for showing and dismissing temporary notifications. + */ +export declare class Toast { + /** IDs of toasts that have previously been shown. */ + private static shownIds; + /** + * Shows a toast notification. + * + * @param workspace The workspace to show the toast on. + * @param options Configuration options for the toast message, duration, etc. + */ + static show(workspace: WorkspaceSvg, options: ToastOptions): void; + /** + * Creates the DOM representation of a toast. + * + * @param workspace The workspace to inject the toast notification onto. + * @param options Configuration options for the toast. + * @returns The root DOM element of the toast. + */ + protected static createDom(workspace: WorkspaceSvg, options: ToastOptions): HTMLDivElement; + /** + * Dismiss a toast, e.g. in response to a user action. + * + * @param workspace The workspace to dismiss a toast in. + * @param id The toast ID, or undefined to clear any toast. + */ + static hide(workspace: WorkspaceSvg, id?: string): void; +} +/** + * Options for how aggressively toasts should be read out by screenreaders. + * Values correspond to those for aria-live. + */ +export declare namespace Toast { + enum Assertiveness { + ASSERTIVE = "assertive", + POLITE = "polite" + } +} +//# sourceMappingURL=toast.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/toolbox/toolbox.d.ts b/appinventor/lib/blockly/@types/toolbox/toolbox.d.ts index 229ea055295..72b19ad039f 100644 --- a/appinventor/lib/blockly/@types/toolbox/toolbox.d.ts +++ b/appinventor/lib/blockly/@types/toolbox/toolbox.d.ts @@ -6,9 +6,11 @@ import * as browserEvents from '../browser_events.js'; import { DeleteArea } from '../delete_area.js'; import '../events/events_toolbox_item_select.js'; -import type { IAutoHideable } from '../interfaces/i_autohideable.js'; +import { type IAutoHideable } from '../interfaces/i_autohideable.js'; import type { IDraggable } from '../interfaces/i_draggable.js'; import type { IFlyout } from '../interfaces/i_flyout.js'; +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { IFocusableTree } from '../interfaces/i_focusable_tree.js'; import type { IKeyboardAccessible } from '../interfaces/i_keyboard_accessible.js'; import type { ISelectableToolboxItem } from '../interfaces/i_selectable_toolbox_item.js'; import type { IStyleable } from '../interfaces/i_styleable.js'; @@ -22,7 +24,7 @@ import type { WorkspaceSvg } from '../workspace_svg.js'; * Class for a Toolbox. * Creates the toolbox's DOM. */ -export declare class Toolbox extends DeleteArea implements IAutoHideable, IKeyboardAccessible, IStyleable, IToolbox { +export declare class Toolbox extends DeleteArea implements IAutoHideable, IKeyboardAccessible, IStyleable, IToolbox, IFocusableNode { /** * The unique ID for this component that is used to register with the * ComponentManager. @@ -36,8 +38,6 @@ export declare class Toolbox extends DeleteArea implements IAutoHideable, IKeybo protected contentsDiv_: HTMLDivElement | null; /** Whether the Toolbox is visible. */ protected isVisible_: boolean; - /** The list of items in the toolbox. */ - protected contents_: IToolboxItem[]; /** The width of the toolbox. */ protected width_: number; /** The height of the toolbox. */ @@ -45,9 +45,8 @@ export declare class Toolbox extends DeleteArea implements IAutoHideable, IKeybo RTL: boolean; /** The flyout for the toolbox. */ private flyout; - protected contentMap_: { - [key: string]: IToolboxItem; - }; + /** Map from ID to the corresponding toolbox item. */ + protected contents: Map; toolboxPosition: toolbox.Position; /** The currently selected item. */ protected selectedItem_: ISelectableToolboxItem | null; @@ -61,6 +60,8 @@ export declare class Toolbox extends DeleteArea implements IAutoHideable, IKeybo protected boundEvents_: browserEvents.Data[]; /** The workspace this toolbox is on. */ protected readonly workspace_: WorkspaceSvg; + /** Whether the mouse is currently being clicked. */ + private mouseDown; /** @param workspace The workspace in which to create new blocks. */ constructor(workspace: WorkspaceSvg); /** @@ -392,5 +393,27 @@ export declare class Toolbox extends DeleteArea implements IAutoHideable, IKeybo private selectPrevious; /** Disposes of this toolbox. */ dispose(): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; + /** See IFocusableTree.getRootFocusableNode. */ + getRootFocusableNode(): IFocusableNode; + /** See IFocusableTree.getRestoredFocusableNode. */ + getRestoredFocusableNode(previousNode: IFocusableNode | null): IFocusableNode | null; + /** See IFocusableTree.getNestedTrees. */ + getNestedTrees(): Array; + /** See IFocusableTree.lookUpFocusableNode. */ + lookUpFocusableNode(id: string): IFocusableNode | null; + /** See IFocusableTree.onTreeFocus. */ + onTreeFocus(node: IFocusableNode, _previousTree: IFocusableTree | null): void; + /** See IFocusableTree.onTreeBlur. */ + onTreeBlur(nextTree: IFocusableTree | null): void; } //# sourceMappingURL=toolbox.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/toolbox/toolbox_item.d.ts b/appinventor/lib/blockly/@types/toolbox/toolbox_item.d.ts index 8ed5c5642fa..cacc0071c5f 100644 --- a/appinventor/lib/blockly/@types/toolbox/toolbox_item.d.ts +++ b/appinventor/lib/blockly/@types/toolbox/toolbox_item.d.ts @@ -9,6 +9,7 @@ * @class */ import type { ICollapsibleToolboxItem } from '../interfaces/i_collapsible_toolbox_item.js'; +import type { IFocusableTree } from '../interfaces/i_focusable_tree.js'; import type { IToolbox } from '../interfaces/i_toolbox.js'; import type { IToolboxItem } from '../interfaces/i_toolbox_item.js'; import type * as toolbox from '../utils/toolbox.js'; @@ -94,5 +95,15 @@ export declare class ToolboxItem implements IToolboxItem { * @param _isVisible True if category should be visible. */ setVisible_(_isVisible: boolean): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; } //# sourceMappingURL=toolbox_item.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/utils/aria.d.ts b/appinventor/lib/blockly/@types/utils/aria.d.ts index 9c1220b1b08..cddc00bf984 100644 --- a/appinventor/lib/blockly/@types/utils/aria.d.ts +++ b/appinventor/lib/blockly/@types/utils/aria.d.ts @@ -19,7 +19,9 @@ export declare enum Role { PRESENTATION = "presentation", ROW = "row", TREE = "tree", - TREEITEM = "treeitem" + TREEITEM = "treeitem", + SEPARATOR = "separator", + STATUS = "status" } /** * ARIA states and properties. @@ -40,7 +42,9 @@ export declare enum State { SELECTED = "selected", SETSIZE = "setsize", VALUEMAX = "valuemax", - VALUEMIN = "valuemin" + VALUEMIN = "valuemin", + LIVE = "live", + HIDDEN = "hidden" } /** * Sets the role of an element. diff --git a/appinventor/lib/blockly/@types/utils/focusable_tree_traverser.d.ts b/appinventor/lib/blockly/@types/utils/focusable_tree_traverser.d.ts new file mode 100644 index 00000000000..564f470cad8 --- /dev/null +++ b/appinventor/lib/blockly/@types/utils/focusable_tree_traverser.d.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { IFocusableNode } from '../interfaces/i_focusable_node.js'; +import type { IFocusableTree } from '../interfaces/i_focusable_tree.js'; +/** + * A helper utility for IFocusableTree implementations to aid with common + * tree traversals. + */ +export declare class FocusableTreeTraverser { + private static readonly ACTIVE_CLASS_NAME; + private static readonly PASSIVE_CSS_CLASS_NAME; + private static readonly ACTIVE_FOCUS_NODE_CSS_SELECTOR; + private static readonly PASSIVE_FOCUS_NODE_CSS_SELECTOR; + /** + * Returns the current IFocusableNode that is styled (and thus represented) as + * having either passive or active focus, only considering HTML and SVG + * elements. + * + * This can match against the tree's root. + * + * Note that this will never return a node from a nested sub-tree as that tree + * should specifically be used to retrieve its focused node. + * + * @param tree The IFocusableTree in which to search for a focused node. + * @returns The IFocusableNode currently with focus, or null if none. + */ + static findFocusedNode(tree: IFocusableTree): IFocusableNode | null; + /** + * Returns the IFocusableNode corresponding to the specified HTML or SVG + * element iff it's the root element or a descendent of the root element of + * the specified IFocusableTree. + * + * If the element exists within the specified tree's DOM structure but does + * not directly correspond to a node, the nearest parent node (or the tree's + * root) will be returned to represent the provided element. + * + * If the tree contains another nested IFocusableTree, the nested tree may be + * traversed but its nodes will never be returned here per the contract of + * IFocusableTree.lookUpFocusableNode. + * + * The provided element must have a non-null, non-empty ID that conforms to + * the contract mentioned in IFocusableNode. + * + * @param element The HTML or SVG element being sought. + * @param tree The tree under which the provided element may be a descendant. + * @returns The matching IFocusableNode, or null if there is no match. + */ + static findFocusableNodeFor(element: HTMLElement | SVGElement, tree: IFocusableTree): IFocusableNode | null; +} +//# sourceMappingURL=focusable_tree_traverser.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/utils/keycodes.d.ts b/appinventor/lib/blockly/@types/utils/keycodes.d.ts index 77dc8dbaef8..a3da5e34adf 100644 --- a/appinventor/lib/blockly/@types/utils/keycodes.d.ts +++ b/appinventor/lib/blockly/@types/utils/keycodes.d.ts @@ -131,6 +131,7 @@ export declare enum KeyCodes { MAC_WK_CMD_RIGHT = 93,// WebKit Right Command key fired, different from META WIN_IME = 229, VK_NONAME = 252, - PHANTOM = 255 + PHANTOM = 255, + CTRL_CMD } //# sourceMappingURL=keycodes.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/utils/object.d.ts b/appinventor/lib/blockly/@types/utils/object.d.ts index fc0bb9acab5..136d0905ff6 100644 --- a/appinventor/lib/blockly/@types/utils/object.d.ts +++ b/appinventor/lib/blockly/@types/utils/object.d.ts @@ -6,6 +6,9 @@ /** * Complete a deep merge of all members of a source object with a target object. * + * N.B. This is not a very sophisticated merge algorithm and does not + * handle complex cases. Use with caution. + * * @param target Target. * @param source Source. * @returns The resulting object. diff --git a/appinventor/lib/blockly/@types/utils/rect.d.ts b/appinventor/lib/blockly/@types/utils/rect.d.ts index 022de6296d7..1108538ee63 100644 --- a/appinventor/lib/blockly/@types/utils/rect.d.ts +++ b/appinventor/lib/blockly/@types/utils/rect.d.ts @@ -26,6 +26,13 @@ export declare class Rect { * @param right Right. */ constructor(top: number, bottom: number, left: number, right: number); + /** + * Converts a DOM or SVG Rect to a Blockly Rect. + * + * @param rect The rectangle to convert. + * @returns A representation of the same rectangle as a Blockly Rect. + */ + static from(rect: DOMRect | SVGRect): Rect; /** * Creates a new copy of this rectangle. * @@ -36,6 +43,8 @@ export declare class Rect { getHeight(): number; /** Returns the width of this rectangle. */ getWidth(): number; + /** Returns the top left coordinate of this rectangle. */ + getOrigin(): Coordinate; /** * Tests whether this rectangle contains a x/y coordinate. * diff --git a/appinventor/lib/blockly/@types/utils/toolbox.d.ts b/appinventor/lib/blockly/@types/utils/toolbox.d.ts index 730ad95b32b..0274c7ce2b4 100644 --- a/appinventor/lib/blockly/@types/utils/toolbox.d.ts +++ b/appinventor/lib/blockly/@types/utils/toolbox.d.ts @@ -19,8 +19,6 @@ export interface BlockInfo { disabledReasons?: string[]; enabled?: boolean; id?: string; - x?: number; - y?: number; collapsed?: boolean; inline?: boolean; data?: string; diff --git a/appinventor/lib/blockly/@types/variable_map.d.ts b/appinventor/lib/blockly/@types/variable_map.d.ts index a4d5338bfb4..2c84a6800f8 100644 --- a/appinventor/lib/blockly/@types/variable_map.d.ts +++ b/appinventor/lib/blockly/@types/variable_map.d.ts @@ -11,23 +11,29 @@ import './events/events_var_delete.js'; import './events/events_var_rename.js'; import type { Block } from './block.js'; -import { VariableModel } from './variable_model.js'; +import type { IVariableMap } from './interfaces/i_variable_map.js'; +import { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import type { Workspace } from './workspace.js'; /** * Class for a variable map. This contains a dictionary data structure with * variable types as keys and lists of variables as values. The list of * variables are the type indicated by the key. */ -export declare class VariableMap { +export declare class VariableMap implements IVariableMap> { workspace: Workspace; + potentialMap: boolean; /** - * A map from variable type to list of variable names. The lists contain + * A map from variable type to map of IDs to variables. The maps contain * all of the named variables in the workspace, including variables that are * not currently in use. */ private variableMap; - /** @param workspace The workspace this map belongs to. */ - constructor(workspace: Workspace); + /** + * @param workspace The workspace this map belongs to. + * @param potentialMap True if this holds variables that don't exist in the + * workspace yet. + */ + constructor(workspace: Workspace, potentialMap?: boolean); /** Clear the variable map. Fires events for every deletion. */ clear(): void; /** @@ -35,13 +41,15 @@ export declare class VariableMap { * * @param variable Variable to rename. * @param newName New variable name. - * @internal + * @returns The newly renamed variable. */ - renameVariable(variable: VariableModel, newName: string): void; + renameVariable(variable: IVariableModel, newName: string): IVariableModel; + changeVariableType(variable: IVariableModel, newType: string): IVariableModel; /** * Rename a variable by updating its name in the variable map. Identify the * variable to rename with the given ID. * + * @deprecated v12: use VariableMap.renameVariable. * @param id ID of the variable to rename. * @param newName New variable name. */ @@ -78,29 +86,27 @@ export declare class VariableMap { * @param opt_id The unique ID of the variable. This will default to a UUID. * @returns The newly created variable. */ - createVariable(name: string, opt_type?: string | null, opt_id?: string | null): VariableModel; + createVariable(name: string, opt_type?: string, opt_id?: string): IVariableModel; + /** + * Adds the given variable to this variable map. + * + * @param variable The variable to add. + */ + addVariable(variable: IVariableModel): void; /** - * Delete a variable. + * Delete a variable and all of its uses without confirmation. * * @param variable Variable to delete. */ - deleteVariable(variable: VariableModel): void; + deleteVariable(variable: IVariableModel): void; /** * Delete a variables by the passed in ID and all of its uses from this * workspace. May prompt the user for confirmation. * + * @deprecated v12: use Blockly.Variables.deleteVariable. * @param id ID of variable to delete. */ deleteVariableById(id: string): void; - /** - * Deletes a variable and all of its uses from this workspace without asking - * the user for confirmation. - * - * @param variable Variable to delete. - * @param uses An array of uses of the variable. - * @internal - */ - deleteVariableInternal(variable: VariableModel, uses: Block[]): void; /** * Find the variable by the given name and type and return it. Return null if * it is not found. @@ -110,14 +116,14 @@ export declare class VariableMap { * the empty string, which is a specific type. * @returns The variable with the given name, or null if it was not found. */ - getVariable(name: string, opt_type?: string | null): VariableModel | null; + getVariable(name: string, opt_type?: string): IVariableModel | null; /** * Find the variable by the given ID and return it. Return null if not found. * * @param id The ID to check for. * @returns The variable with the given ID. */ - getVariableById(id: string): VariableModel | null; + getVariableById(id: string): IVariableModel | null; /** * Get a list containing all of the variables of a specified type. If type is * null, return list of variables with empty string type. @@ -126,33 +132,30 @@ export declare class VariableMap { * @returns The sought after variables of the passed in type. An empty array * if none are found. */ - getVariablesOfType(type: string | null): VariableModel[]; + getVariablesOfType(type: string | null): IVariableModel[]; /** - * Return all variable and potential variable types. This list always - * contains the empty string. + * Returns a list of unique types of variables in this variable map. * - * @param ws The workspace used to look for potential variables. This can be - * different than the workspace stored on this object if the passed in ws - * is a flyout workspace. - * @returns List of variable types. - * @internal + * @returns A list of unique types of variables in this variable map. */ - getVariableTypes(ws: Workspace | null): string[]; + getTypes(): string[]; /** * Return all variables of all types. * * @returns List of variable models. */ - getAllVariables(): VariableModel[]; + getAllVariables(): IVariableModel[]; /** * Returns all of the variable names of all types. * + * @deprecated v12: use Blockly.Variables.getAllVariables. * @returns All of the variable names of all types. */ getAllVariableNames(): string[]; /** * Find all the uses of a named variable. * + * @deprecated v12: use Blockly.Variables.getVariableUsesById. * @param id ID of the variable to find. * @returns Array of block usages. */ diff --git a/appinventor/lib/blockly/@types/variable_model.d.ts b/appinventor/lib/blockly/@types/variable_model.d.ts index 95d24cc0d91..ee4cfe94626 100644 --- a/appinventor/lib/blockly/@types/variable_model.d.ts +++ b/appinventor/lib/blockly/@types/variable_model.d.ts @@ -9,6 +9,7 @@ * @class */ import './events/events_var_create.js'; +import { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import type { Workspace } from './workspace.js'; /** * Class for a variable model. @@ -16,10 +17,10 @@ import type { Workspace } from './workspace.js'; * * @see {Blockly.FieldVariable} */ -export declare class VariableModel { - workspace: Workspace; - name: string; - type: string; +export declare class VariableModel implements IVariableModel { + private readonly workspace; + private name; + private type; private readonly id; /** * @param workspace The variable's workspace. @@ -33,15 +34,40 @@ export declare class VariableModel { constructor(workspace: Workspace, name: string, opt_type?: string, opt_id?: string); /** @returns The ID for the variable. */ getId(): string; + /** @returns The name of this variable. */ + getName(): string; /** - * A custom compare function for the VariableModel objects. + * Updates the user-visible name of this variable. * - * @param var1 First variable to compare. - * @param var2 Second variable to compare. - * @returns -1 if name of var1 is less than name of var2, 0 if equal, and 1 if - * greater. - * @internal + * @returns The newly-updated variable. */ - static compareByName(var1: VariableModel, var2: VariableModel): number; + setName(newName: string): this; + /** @returns The type of this variable. */ + getType(): string; + /** + * Updates the type of this variable. + * + * @returns The newly-updated variable. + */ + setType(newType: string): this; + /** + * Returns the workspace this VariableModel belongs to. + * + * @returns The workspace this VariableModel belongs to. + */ + getWorkspace(): Workspace; + /** + * Serializes this VariableModel. + * + * @returns a JSON representation of this VariableModel. + */ + save(): IVariableState; + /** + * Loads the persisted state into a new variable in the given workspace. + * + * @param state The serialized state of a variable model from save(). + * @param workspace The workspace to create the new variable in. + */ + static load(state: IVariableState, workspace: Workspace): void; } //# sourceMappingURL=variable_model.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/variables.d.ts b/appinventor/lib/blockly/@types/variables.d.ts index 2332ed85812..b1a892718c4 100644 --- a/appinventor/lib/blockly/@types/variables.d.ts +++ b/appinventor/lib/blockly/@types/variables.d.ts @@ -3,7 +3,9 @@ * Copyright 2012 Google LLC * SPDX-License-Identifier: Apache-2.0 */ -import { VariableModel } from './variable_model.js'; +import type { Block } from './block.js'; +import { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; +import type { BlockInfo, FlyoutItemInfo } from './utils/toolbox.js'; import type { Workspace } from './workspace.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** @@ -17,15 +19,17 @@ export declare const CATEGORY_NAME = "VARIABLE"; /** * Find all user-created variables that are in use in the workspace. * For use by generators. + * * To get a list of all variables on a workspace, including unused variables, - * call Workspace.getAllVariables. + * call getAllVariables. * * @param ws The workspace to search for variables. * @returns Array of variable models. */ -export declare function allUsedVarModels(ws: Workspace): VariableModel[]; +export declare function allUsedVarModels(ws: Workspace): IVariableModel[]; /** * Find all developer variables used by blocks in the workspace. + * * Developer variables are never shown to the user, but are declared as global * variables in the generated code. * To declare developer variables, define the getDeveloperVariables function on @@ -37,13 +41,26 @@ export declare function allUsedVarModels(ws: Workspace): VariableModel[]; */ export declare function allDeveloperVariables(workspace: Workspace): string[]; /** - * Construct the elements (blocks and button) required by the flyout for the - * variable category. + * Internal wrapper that returns the contents of the variables category. + * + * @internal + * @param workspace The workspace to populate variable blocks for. + */ +export declare function internalFlyoutCategory(workspace: WorkspaceSvg): FlyoutItemInfo[]; +export declare function flyoutCategory(workspace: WorkspaceSvg, useXml: true): Element[]; +export declare function flyoutCategory(workspace: WorkspaceSvg, useXml: false): FlyoutItemInfo[]; +/** + * Construct the blocks required by the flyout for the variable category. * + * @internal * @param workspace The workspace containing variables. - * @returns Array of XML elements. + * @param variables List of variables to create blocks for. + * @param includeChangeBlocks True to include `change x by _` blocks. + * @param getterType The type of the variable getter block to generate. + * @param setterType The type of the variable setter block to generate. + * @returns JSON list of blocks. */ -export declare function flyoutCategory(workspace: WorkspaceSvg): Element[]; +export declare function jsonFlyoutCategoryBlocks(workspace: Workspace, variables: IVariableModel[], includeChangeBlocks: boolean, getterType?: string, setterType?: string): BlockInfo[]; /** * Construct the blocks required by the flyout for the variable category. * @@ -104,7 +121,7 @@ export declare function createVariableButtonHandler(workspace: Workspace, opt_ca * name, or null if change is to be aborted (cancel button), or undefined if * an existing variable was chosen. */ -export declare function renameVariable(workspace: Workspace, variable: VariableModel, opt_callback?: (p1?: string | null) => void): void; +export declare function renameVariable(workspace: Workspace, variable: IVariableModel, opt_callback?: (p1?: string | null) => void): void; /** * Prompt the user for a new variable name. * @@ -121,7 +138,7 @@ export declare function promptName(promptText: string, defaultText: string, call * @param workspace The workspace to search for the variable. * @returns The variable with the given name, or null if none was found. */ -export declare function nameUsedWithAnyType(name: string, workspace: Workspace): VariableModel | null; +export declare function nameUsedWithAnyType(name: string, workspace: Workspace): IVariableModel | null; /** * Returns the name of the procedure with a conflicting parameter name, or null * if one does not exist. @@ -141,7 +158,7 @@ export declare function nameUsedWithConflictingParam(oldName: string, newName: s * @param variableModel The variable model to represent. * @returns The generated DOM. */ -export declare function generateVariableFieldDom(variableModel: VariableModel): Element; +export declare function generateVariableFieldDom(variableModel: IVariableModel): Element; /** * Helper function to look up or create a variable on the given workspace. * If no variable exists, creates and returns it. @@ -154,7 +171,7 @@ export declare function generateVariableFieldDom(variableModel: VariableModel): * @returns The variable corresponding to the given ID or name + type * combination. */ -export declare function getOrCreateVariablePackage(workspace: Workspace, id: string | null, opt_name?: string, opt_type?: string): VariableModel; +export declare function getOrCreateVariablePackage(workspace: Workspace, id: string | null, opt_name?: string, opt_type?: string): IVariableModel; /** * Look up a variable on the given workspace. * Always looks in the main workspace before looking in the flyout workspace. @@ -170,7 +187,7 @@ export declare function getOrCreateVariablePackage(workspace: Workspace, id: str * @returns The variable corresponding to the given ID or name + type * combination, or null if not found. */ -export declare function getVariable(workspace: Workspace, id: string | null, opt_name?: string, opt_type?: string): VariableModel | null; +export declare function getVariable(workspace: Workspace, id: string | null, opt_name?: string, opt_type?: string): IVariableModel | null; /** * Helper function to get the list of variables that have been added to the * workspace after adding a new block, using the given list of variables that @@ -184,7 +201,36 @@ export declare function getVariable(workspace: Workspace, id: string | null, opt * workspace. * @internal */ -export declare function getAddedVariables(workspace: Workspace, originalVariables: VariableModel[]): VariableModel[]; +export declare function getAddedVariables(workspace: Workspace, originalVariables: IVariableModel[]): IVariableModel[]; +/** + * A custom compare function for the VariableModel objects. + * + * @param var1 First variable to compare. + * @param var2 Second variable to compare. + * @returns -1 if name of var1 is less than name of var2, 0 if equal, and 1 if + * greater. + * @internal + */ +export declare function compareByName(var1: IVariableModel, var2: IVariableModel): number; +/** + * Find all the uses of a named variable. + * + * @param workspace The workspace to search for the variable. + * @param id ID of the variable to find. + * @returns Array of block usages. + */ +export declare function getVariableUsesById(workspace: Workspace, id: string): Block[]; +/** + * Delete a variable and all of its uses from the given workspace. May prompt + * the user for confirmation. + * + * @param workspace The workspace from which to delete the variable. + * @param variable The variable to delete. + * @param triggeringBlock The block from which this deletion was triggered, if + * any. Used to exclude it from checking and warning about blocks + * referencing the variable being deleted. + */ +export declare function deleteVariable(workspace: Workspace, variable: IVariableModel, triggeringBlock?: Block): void; export declare const TEST_ONLY: { generateUniqueNameInternal: typeof generateUniqueNameInternal; }; diff --git a/appinventor/lib/blockly/@types/variables_dynamic.d.ts b/appinventor/lib/blockly/@types/variables_dynamic.d.ts index c5234ba47cb..ec8e9ef1251 100644 --- a/appinventor/lib/blockly/@types/variables_dynamic.d.ts +++ b/appinventor/lib/blockly/@types/variables_dynamic.d.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ import type { FlyoutButton } from './flyout_button.js'; +import type { FlyoutItemInfo } from './utils/toolbox.js'; import type { Workspace } from './workspace.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** @@ -36,13 +37,14 @@ export declare const onCreateVariableButtonClick_Number: typeof numberButtonClic declare function colourButtonClickHandler(button: FlyoutButton): void; export declare const onCreateVariableButtonClick_Colour: typeof colourButtonClickHandler; /** - * Construct the elements (blocks and button) required by the flyout for the - * variable category. + * Internal wrapper that returns the contents of the dynamic variables category. * - * @param workspace The workspace containing variables. - * @returns Array of XML elements. + * @internal + * @param workspace The workspace to populate variable blocks for. */ -export declare function flyoutCategory(workspace: WorkspaceSvg): Element[]; +export declare function internalFlyoutCategory(workspace: WorkspaceSvg): FlyoutItemInfo[]; +export declare function flyoutCategory(workspace: WorkspaceSvg, useXml: true): Element[]; +export declare function flyoutCategory(workspace: WorkspaceSvg, useXml: false): FlyoutItemInfo[]; /** * Construct the blocks required by the flyout for the variable category. * diff --git a/appinventor/lib/blockly/@types/widgetdiv.d.ts b/appinventor/lib/blockly/@types/widgetdiv.d.ts index 99c90e44f19..ffc9e99c1b2 100644 --- a/appinventor/lib/blockly/@types/widgetdiv.d.ts +++ b/appinventor/lib/blockly/@types/widgetdiv.d.ts @@ -31,8 +31,13 @@ export declare function createDom(): void; * @param newDispose Optional cleanup function to be run when the widget is * closed. * @param workspace The workspace associated with the widget owner. + * @param manageEphemeralFocus Whether ephemeral focus should be managed + * according to the widget div's lifetime. Note that if a false value is + * passed in here then callers should manage ephemeral focus directly + * otherwise focus may not properly restore when the widget closes. Defaults + * to true. */ -export declare function show(newOwner: unknown, rtl: boolean, newDispose: () => void, workspace?: WorkspaceSvg | null): void; +export declare function show(newOwner: unknown, rtl: boolean, newDispose: () => void, workspace?: WorkspaceSvg | null, manageEphemeralFocus?: boolean): void; /** * Destroy the widget and hide the div. */ @@ -54,9 +59,9 @@ export declare function hideIfOwner(oldOwner: unknown): void; * Destroy the widget and hide the div if it is being used by an object in the * specified workspace, or if it is used by an unknown workspace. * - * @param oldOwnerWorkspace The workspace that was using this container. + * @param workspace The workspace that was using this container. */ -export declare function hideIfOwnerIsInWorkspace(oldOwnerWorkspace: WorkspaceSvg): void; +export declare function hideIfOwnerIsInWorkspace(workspace: WorkspaceSvg): void; /** * Position the widget div based on an anchor rectangle. * The widget should be placed adjacent to but not overlapping the anchor diff --git a/appinventor/lib/blockly/@types/workspace.d.ts b/appinventor/lib/blockly/@types/workspace.d.ts index 990b8ddd535..373db8a2dd4 100644 --- a/appinventor/lib/blockly/@types/workspace.d.ts +++ b/appinventor/lib/blockly/@types/workspace.d.ts @@ -13,18 +13,18 @@ import type { Block } from './block.js'; import { WorkspaceComment } from './comments/workspace_comment.js'; import type { ConnectionDB } from './connection_db.js'; import type { Abstract } from './events/events_abstract.js'; -import type { IASTNodeLocation } from './interfaces/i_ast_node_location.js'; +import type { IBoundedElement } from './interfaces/i_bounded_element.js'; import type { IConnectionChecker } from './interfaces/i_connection_checker.js'; import { IProcedureMap } from './interfaces/i_procedure_map.js'; +import type { IVariableMap } from './interfaces/i_variable_map.js'; +import type { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import { Options } from './options.js'; import type * as toolbox from './utils/toolbox.js'; -import { VariableMap } from './variable_map.js'; -import type { VariableModel } from './variable_model.js'; /** * Class for a workspace. This is a data structure that contains blocks. * There is no UI, and can be created headlessly. */ -export declare class Workspace implements IASTNodeLocation { +export declare class Workspace { /** * Angle away from the horizontal to sweep for blocks. Order of execution is * generally top to bottom, but a small angle changes the scan to give a bit @@ -82,6 +82,7 @@ export declare class Workspace implements IASTNodeLocation { private readonly typedBlocksDB; private variableMap; private procedureMap; + private readOnly; /** * Blocks in the flyout can refer to variables that don't exist in the main * workspace. For instance, the "get item in list" block refers to an @@ -108,6 +109,15 @@ export declare class Workspace implements IASTNodeLocation { * a's index. */ private sortObjects; + /** + * Sorts bounded elements on the workspace by their relative position, top to + * bottom (with slight LTR or RTL bias). + * + * @param a The first element to sort. + * @param b The second elment to sort. + * @returns -1, 0 or 1 depending on the sort order. + */ + protected sortByOrigin(a: IBoundedElement, b: IBoundedElement): number; /** * Adds a block to the list of top blocks. * @@ -183,9 +193,10 @@ export declare class Workspace implements IASTNodeLocation { /** Dispose of all blocks and comments in workspace. */ clear(): void; /** - * Rename a variable by updating its name in the variable map. Identify the - * variable to rename with the given ID. + * Rename a variable by updating its name in the variable + * map. Identify the variable to rename with the given ID. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().renameVariable * @param id ID of the variable to rename. * @param newName New variable name. */ @@ -193,6 +204,7 @@ export declare class Workspace implements IASTNodeLocation { /** * Create a variable with a given name, optional type, and optional ID. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().createVariable. * @param name The name of the variable. This must be unique across variables * and procedures. * @param opt_type The type of the variable like 'int' or 'string'. @@ -201,10 +213,11 @@ export declare class Workspace implements IASTNodeLocation { * @param opt_id The unique ID of the variable. This will default to a UUID. * @returns The newly created variable. */ - createVariable(name: string, opt_type?: string | null, opt_id?: string | null): VariableModel; + createVariable(name: string, opt_type?: string | null, opt_id?: string | null): IVariableModel; /** * Find all the uses of the given variable, which is identified by ID. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().getVariableUsesById * @param id ID of the variable to find. * @returns Array of block usages. */ @@ -213,6 +226,7 @@ export declare class Workspace implements IASTNodeLocation { * Delete a variables by the passed in ID and all of its uses from this * workspace. May prompt the user for confirmation. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().deleteVariable. * @param id ID of variable to delete. */ deleteVariableById(id: string): void; @@ -220,44 +234,42 @@ export declare class Workspace implements IASTNodeLocation { * Find the variable by the given name and return it. Return null if not * found. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().getVariable. * @param name The name to check for. * @param opt_type The type of the variable. If not provided it defaults to * the empty string, which is a specific type. * @returns The variable with the given name. */ - getVariable(name: string, opt_type?: string): VariableModel | null; + getVariable(name: string, opt_type?: string): IVariableModel | null; /** * Find the variable by the given ID and return it. Return null if not found. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().getVariableById. * @param id The ID to check for. * @returns The variable with the given ID. */ - getVariableById(id: string): VariableModel | null; + getVariableById(id: string): IVariableModel | null; /** * Find the variable with the specified type. If type is null, return list of * variables with empty string type. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().getVariablesOfType. * @param type Type of the variables to find. * @returns The sought after variables of the passed in type. An empty array * if none are found. */ - getVariablesOfType(type: string | null): VariableModel[]; - /** - * Return all variable types. - * - * @returns List of variable types. - * @internal - */ - getVariableTypes(): string[]; + getVariablesOfType(type: string | null): IVariableModel[]; /** * Return all variables of all types. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().getAllVariables. * @returns List of variable models. */ - getAllVariables(): VariableModel[]; + getAllVariables(): IVariableModel[]; /** * Returns all variable names of all types. * + * @deprecated v12: use Blockly.Workspace.getVariableMap().getAllVariables. * @returns List of all variable names of all types. */ getAllVariableNames(): string[]; @@ -409,9 +421,8 @@ export declare class Workspace implements IASTNodeLocation { * These exist in the flyout but not in the workspace. * * @returns The potential variable map. - * @internal */ - getPotentialVariableMap(): VariableMap | null; + getPotentialVariableMap(): IVariableMap> | null; /** * Create and store the potential variable map for this workspace. * @@ -423,14 +434,14 @@ export declare class Workspace implements IASTNodeLocation { * * @returns The variable map. */ - getVariableMap(): VariableMap; + getVariableMap(): IVariableMap>; /** * Set the map of all variables on the workspace. * * @param variableMap The variable map. * @internal */ - setVariableMap(variableMap: VariableMap): void; + setVariableMap(variableMap: IVariableMap>): void; /** Returns the map of all procedures on the workpace. */ getProcedureMap(): IProcedureMap; /** @@ -454,5 +465,18 @@ export declare class Workspace implements IASTNodeLocation { * @returns Array of workspaces. */ static getAll(): Workspace[]; + protected getVariableMapClass(): new (...p1: any[]) => IVariableMap>; + /** + * Returns whether or not this workspace is in readonly mode. + * + * @returns True if the workspace is readonly, otherwise false. + */ + isReadOnly(): boolean; + /** + * Sets whether or not this workspace is in readonly mode. + * + * @param readOnly True to make the workspace readonly, otherwise false. + */ + setIsReadOnly(readOnly: boolean): void; } //# sourceMappingURL=workspace.d.ts.map \ No newline at end of file diff --git a/appinventor/lib/blockly/@types/workspace_audio.d.ts b/appinventor/lib/blockly/@types/workspace_audio.d.ts index 9121f0fcaa5..6969f133c02 100644 --- a/appinventor/lib/blockly/@types/workspace_audio.d.ts +++ b/appinventor/lib/blockly/@types/workspace_audio.d.ts @@ -3,6 +3,12 @@ * Copyright 2017 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +/** + * Object in charge of loading, storing, and playing audio for a + * workspace. + * + * @class + */ import type { WorkspaceSvg } from './workspace_svg.js'; /** * Class for loading, storing, and playing audio for a workspace. @@ -15,6 +21,8 @@ export declare class WorkspaceAudio { private lastSound; /** Whether the audio is muted or not. */ private muted; + /** Audio context used for playback. */ + private readonly context?; /** * @param parentWorkspace The parent of the workspace this audio object * belongs to, or null. @@ -29,18 +37,11 @@ export declare class WorkspaceAudio { /** * Load an audio file. Cache it, ready for instantaneous playing. * - * @param filenames List of file types in decreasing order of preference (i.e. - * increasing size). E.g. ['media/go.mp3', 'media/go.wav'] Filenames - * include path from Blockly's root. File extensions matter. + * @param filenames Single-item array containing the URL for the sound file. + * Any items after the first item are ignored. * @param name Name of sound. */ - load(filenames: string[], name: string): void; - /** - * Preload all the audio files so that they play quickly when asked for. - * - * @internal - */ - preload(): void; + load(filenames: string[], name: string): Promise; /** * Play a named sound at specified volume. If volume is not specified, * use full volume (1). @@ -48,7 +49,7 @@ export declare class WorkspaceAudio { * @param name Name of sound. * @param opt_volume Volume of sound (0-1). */ - play(name: string, opt_volume?: number): void; + play(name: string, opt_volume?: number): Promise; /** * @param muted If true, mute sounds. Otherwise, play them. */ diff --git a/appinventor/lib/blockly/@types/workspace_dragger.d.ts b/appinventor/lib/blockly/@types/workspace_dragger.d.ts index a060bca30a3..0051dba7feb 100644 --- a/appinventor/lib/blockly/@types/workspace_dragger.d.ts +++ b/appinventor/lib/blockly/@types/workspace_dragger.d.ts @@ -3,6 +3,11 @@ * Copyright 2017 Google LLC * SPDX-License-Identifier: Apache-2.0 */ +/** + * Methods for dragging a workspace visually. + * + * @class + */ import { Coordinate } from './utils/coordinate.js'; import type { WorkspaceSvg } from './workspace_svg.js'; /** @@ -17,12 +22,6 @@ export declare class WorkspaceDragger { protected startScrollXY_: Coordinate; /** @param workspace The workspace to drag. */ constructor(workspace: WorkspaceSvg); - /** - * Sever all links from this object. - * - * @internal - */ - dispose(): void; /** * Start dragging the workspace. * diff --git a/appinventor/lib/blockly/@types/workspace_svg.d.ts b/appinventor/lib/blockly/@types/workspace_svg.d.ts index 821f36bfbc9..a5d4b3dc78f 100644 --- a/appinventor/lib/blockly/@types/workspace_svg.d.ts +++ b/appinventor/lib/blockly/@types/workspace_svg.d.ts @@ -14,22 +14,26 @@ import './events/events_viewport.js'; import type { Block } from './block.js'; import type { BlockSvg } from './block_svg.js'; import * as browserEvents from './browser_events.js'; +import { RenderedWorkspaceComment } from './comments/rendered_workspace_comment.js'; import { WorkspaceComment } from './comments/workspace_comment.js'; import { ComponentManager } from './component_manager.js'; import { ContextMenuOption } from './contextmenu_registry.js'; import type { FlyoutButton } from './flyout_button.js'; import { Gesture } from './gesture.js'; import { Grid } from './grid.js'; -import type { IASTNodeLocationSvg } from './interfaces/i_ast_node_location_svg.js'; import type { IBoundedElement } from './interfaces/i_bounded_element.js'; +import { IContextMenu } from './interfaces/i_contextmenu.js'; import type { IDragTarget } from './interfaces/i_drag_target.js'; import type { IFlyout } from './interfaces/i_flyout.js'; +import { type IFocusableNode } from './interfaces/i_focusable_node.js'; +import type { IFocusableTree } from './interfaces/i_focusable_tree.js'; import type { IMetricsManager } from './interfaces/i_metrics_manager.js'; import type { IToolbox } from './interfaces/i_toolbox.js'; -import type { Cursor } from './keyboard_nav/cursor.js'; +import type { LineCursor } from './keyboard_nav/line_cursor.js'; import type { Marker } from './keyboard_nav/marker.js'; import { LayerManager } from './layer_manager.js'; import { MarkerManager } from './marker_manager.js'; +import { Navigator } from './navigator.js'; import { Options } from './options.js'; import type { Renderer } from './renderers/common/renderer.js'; import type { ScrollbarPair } from './scrollbar_pair.js'; @@ -42,7 +46,6 @@ import { Rect } from './utils/rect.js'; import { Size } from './utils/size.js'; import { Svg } from './utils/svg.js'; import * as toolbox from './utils/toolbox.js'; -import type { VariableModel } from './variable_model.js'; import { Workspace } from './workspace.js'; import { WorkspaceAudio } from './workspace_audio.js'; import { ZoomControls } from './zoom_controls.js'; @@ -50,7 +53,7 @@ import { ZoomControls } from './zoom_controls.js'; * Class for a workspace. This is an onscreen area with optional trashcan, * scrollbars, bubbles, and dragging. */ -export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { +export declare class WorkspaceSvg extends Workspace implements IContextMenu, IFocusableNode, IFocusableTree { /** * A wrapper function called when a resize event occurs. * You can pass the result to `eventHandling.unbind`. @@ -234,6 +237,8 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS private cachedParentSvg; /** True if keyboard accessibility mode is on, false otherwise. */ keyboardAccessibilityMode: boolean; + /** True iff a keyboard-initiated move ("drag") is in progress. */ + keyboardMoveInProgress: boolean; /** The list of top-level bounded elements on the workspace. */ private topBoundedElements; /** The recorded drag targets. */ @@ -245,6 +250,11 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS svgBlockCanvas_: SVGElement; svgBubbleCanvas_: SVGElement; zoomControls_: ZoomControls | null; + /** + * Navigator that handles moving focus between items in this workspace in + * response to keyboard navigation commands. + */ + private navigator; /** * @param options Dictionary of options. */ @@ -274,22 +284,6 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * @returns The component manager. */ getComponentManager(): ComponentManager; - /** - * Add the cursor SVG to this workspaces SVG group. - * - * @param cursorSvg The SVG root of the cursor to be added to the workspace - * SVG group. - * @internal - */ - setCursorSvg(cursorSvg: SVGElement): void; - /** - * Add the marker SVG to this workspaces SVG group. - * - * @param markerSvg The SVG root of the marker to be added to the workspace - * SVG group. - * @internal - */ - setMarkerSvg(markerSvg: SVGElement): void; /** * Get the marker with the given ID. * @@ -304,7 +298,7 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * * @returns The cursor for the workspace. */ - getCursor(): Cursor | null; + getCursor(): LineCursor; /** * Get the block renderer attached to this workspace. * @@ -392,7 +386,7 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * @returns The first parent div with 'injectionDiv' in the name. * @internal */ - getInjectionDiv(): Element; + getInjectionDiv(): HTMLElement; /** * Returns the SVG group for the workspace. * @@ -419,7 +413,7 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * 'blocklyMutatorBackground'. * @returns The workspace's SVG group. */ - createDom(opt_backgroundClass?: string, injectionDiv?: Element): Element; + createDom(opt_backgroundClass?: string, injectionDiv?: HTMLElement): Element; /** * Dispose of this workspace. * Unlink from all DOM elements to prevent memory leaks. @@ -442,6 +436,13 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * @internal */ addZoomControls(): void; + /** + * Creates a new set of options from this workspace's options with just the + * values that are relevant to a flyout. + * + * @returns A subset of this workspace's options. + */ + copyOptionsForFlyout(): Options; /** * Add a flyout element in an element with the given tag name. * @@ -495,6 +496,7 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS updateScreenCalculationsIfScrolled(): void; /** * @returns The layer manager for this workspace. + * @internal */ getLayerManager(): LayerManager | null; /** @@ -572,38 +574,17 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS */ highlightBlock(id: string | null, opt_state?: boolean): void; /** - * Refresh the toolbox unless there's a drag in progress. + * Handles any necessary updates when a variable changes. * * @internal */ - refreshToolboxSelection(): void; - /** - * Rename a variable by updating its name in the variable map. Update the - * flyout to show the renamed variable immediately. - * - * @param id ID of the variable to rename. - * @param newName New variable name. - */ - renameVariableById(id: string, newName: string): void; - /** - * Delete a variable by the passed in ID. Update the flyout to show - * immediately that the variable is deleted. - * - * @param id ID of variable to delete. - */ - deleteVariableById(id: string): void; + private variableChangeCallback; /** - * Create a new variable with the given name. Update the flyout to show the - * new variable immediately. + * Refresh the toolbox unless there's a drag in progress. * - * @param name The new variable's name. - * @param opt_type The type of the variable like 'int' or 'string'. - * Does not need to be unique. Field_variable can filter variables based - * on their type. This will default to '' which is a specific type. - * @param opt_id The unique ID of the variable. This will default to a UUID. - * @returns The newly created variable. + * @internal */ - createVariable(name: string, opt_type?: string | null, opt_id?: string | null): VariableModel; + refreshToolboxSelection(): void; /** Make a list of all the delete areas for this workspace. */ recordDragTargets(): void; /** @@ -653,9 +634,36 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS */ moveDrag(e: PointerEvent): Coordinate; /** - * Is the user currently dragging a block or scrolling the flyout/workspace? + * Indicate whether a keyboard move is in progress or not. + * + * Should be called with true when a keyboard move of an IDraggable + * is starts, and false when it finishes or is aborted. + * + * N.B.: This method is experimental and internal-only. It is + * intended only to called only from the keyboard navigation plugin. + * Its signature and behaviour may be modified, or the method + * removed, at an time without notice and without being treated + * as a breaking change. + * + * TODO(#8960): Delete this. + * + * @internal + * @param inProgress Is a keyboard-initated move in progress? + */ + setKeyboardMoveInProgress(inProgress: boolean): void; + /** + * Returns true iff the user is currently engaged in a drag gesture, + * or if a keyboard-initated move is in progress. * - * @returns True if currently dragging or scrolling. + * Dragging gestures normally entail moving a block or other item on + * the workspace, or scrolling the flyout/workspace. + * + * Keyboard-initated movements are implemnted using the dragging + * infrastructure and are intended to emulate (a subset of) drag + * gestures and so should typically be treated as if they were a + * gesture-based drag. + * + * @returns True iff a drag gesture or keyboard move is in porgress. */ isDragging(): boolean; /** @@ -710,7 +718,7 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * @param e Mouse event. * @internal */ - showContextMenu(e: PointerEvent): void; + showContextMenu(e: Event): void; /** * Modify the block tree on the existing toolbox. * @@ -773,12 +781,27 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS */ setScale(newScale: number): void; /** - * Get the workspace's zoom factor. If the workspace has a parent, we call - * into the parent to get the workspace scale. + * Get the workspace's zoom factor. * * @returns The workspace zoom factor. Units: (pixels / workspaceUnit). */ getScale(): number; + /** + * Returns the absolute scale of the workspace. + * + * Workspace scaling is multiplicative; if a workspace B (e.g. a mutator editor) + * with scale Y is nested within a root workspace A with scale X, workspace B's + * effective scale is X * Y, because, as a child of A, it is already transformed + * by A's scaling factor, and then further transforms itself by its own scaling + * factor. Normally this Just Works, but for global elements (e.g. field + * editors) that are visually associated with a particular workspace but live at + * the top level of the DOM rather than being a child of their associated + * workspace, the absolute/effective scale may be needed to render + * appropriately. + * + * @returns The absolute/effective scale of the given workspace. + */ + getAbsoluteScale(): number; /** * Scroll the workspace to a specified offset (in pixels), keeping in the * workspace bounds. See comment on workspaceSvg.scrollX for more detail on @@ -828,13 +851,27 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * * @param comment comment to add. */ - addTopComment(comment: WorkspaceComment): void; + addTopComment(comment: RenderedWorkspaceComment): void; /** * Removes a comment from the list of top comments. * * @param comment comment to remove. */ - removeTopComment(comment: WorkspaceComment): void; + removeTopComment(comment: RenderedWorkspaceComment): void; + /** + * Returns a list of comments on this workspace. + * + * @param ordered If true, sorts the comments based on their position. + * @returns A list of workspace comments. + */ + getTopComments(ordered?: boolean): RenderedWorkspaceComment[]; + /** + * Returns the workspace comment with the given ID, if any. + * + * @param id The ID of the comment to retrieve. + * @returns The workspace comment with the given ID, or null. + */ + getCommentById(id: string): RenderedWorkspaceComment | null; getRootWorkspace(): WorkspaceSvg | null; /** * Adds a bounded element to the list of top bounded elements. @@ -853,7 +890,7 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * * @returns The top-level bounded elements. */ - getTopBoundedElements(): IBoundedElement[]; + getTopBoundedElements(ordered?: boolean): IBoundedElement[]; /** * Update whether this workspace has resizes enabled. * If enabled, workspace will resize when appropriate. @@ -921,14 +958,24 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS removeToolboxCategoryCallback(key: string): void; /** * Look up the gesture that is tracking this touch stream on this workspace. - * May create a new gesture. + * + * Returns the gesture in progress, except: + * + * - If there is a keyboard-initiate move in progress then null will + * be returned - after calling event.preventDefault() and + * event.stopPropagation() to ensure the pointer event is ignored. + * - If there is a gesture in progress but event.type is + * 'pointerdown' then the in-progress gesture will be cancelled; + * this will result in null being returned. + * - If no gesutre is in progress but event is a pointerdown then a + * new gesture will be created and returned. * * @param e Pointer event. * @returns The gesture that is tracking this touch stream, or null if no * valid gesture exists. * @internal */ - getGesture(e: PointerEvent): Gesture | null; + getGesture(e?: PointerEvent): Gesture | null; /** * Clear the reference to the current gesture. * @@ -975,6 +1022,75 @@ export declare class WorkspaceSvg extends Workspace implements IASTNodeLocationS * and 1 specifying the degree of scrolling. */ private static setTopLevelWorkspaceMetrics; + /** + * Adds a CSS class to the workspace. + * + * @param className Name of class to add. + */ + addClass(className: string): void; + /** + * Removes a CSS class from the workspace. + * + * @param className Name of class to remove. + */ + removeClass(className: string): void; + setIsReadOnly(readOnly: boolean): void; + /** + * Scrolls the provided bounds into view. + * + * In the case of small workspaces/large bounds, this function prioritizes + * getting the top left corner of the bounds into view. It also adds some + * padding around the bounds to allow the element to be comfortably in view. + * + * @internal + * @param bounds A rectangle to scroll into view, as best as possible. + * @param padding Amount of spacing to put between the bounds and the edge of + * the workspace's viewport. + */ + scrollBoundsIntoView(bounds: Rect, padding?: number): void; + /** See IFocusableNode.getFocusableElement. */ + getFocusableElement(): HTMLElement | SVGElement; + /** See IFocusableNode.getFocusableTree. */ + getFocusableTree(): IFocusableTree; + /** See IFocusableNode.onNodeFocus. */ + onNodeFocus(): void; + /** See IFocusableNode.onNodeBlur. */ + onNodeBlur(): void; + /** See IFocusableNode.canBeFocused. */ + canBeFocused(): boolean; + /** See IFocusableTree.getRootFocusableNode. */ + getRootFocusableNode(): IFocusableNode; + /** See IFocusableTree.getRestoredFocusableNode. */ + getRestoredFocusableNode(previousNode: IFocusableNode | null): IFocusableNode | null; + /** See IFocusableTree.getNestedTrees. */ + getNestedTrees(): Array; + /** + * Used for searching for a specific workspace comment. + * We can't use this.getWorkspaceCommentById because the workspace + * comment ids might not be globally unique, but the id assigned to + * the focusable element for the comment should be. + */ + private searchForWorkspaceComment; + /** See IFocusableTree.lookUpFocusableNode. */ + lookUpFocusableNode(id: string): IFocusableNode | null; + /** See IFocusableTree.onTreeFocus. */ + onTreeFocus(_node: IFocusableNode, _previousTree: IFocusableTree | null): void; + /** See IFocusableTree.onTreeBlur. */ + onTreeBlur(nextTree: IFocusableTree | null): void; + /** + * Returns an object responsible for coordinating movement of focus between + * items on this workspace in response to keyboard navigation commands. + * + * @returns This workspace's Navigator instance. + */ + getNavigator(): Navigator; + /** + * Sets the Navigator instance used by this workspace. + * + * @param newNavigator A Navigator object to coordinate movement between + * elements on the workspace. + */ + setNavigator(newNavigator: Navigator): void; } /** * Size the workspace when the contents change. This also updates diff --git a/appinventor/lib/blockly/@types/xml.d.ts b/appinventor/lib/blockly/@types/xml.d.ts index 0101e3b45cc..0b45fa83c1e 100644 --- a/appinventor/lib/blockly/@types/xml.d.ts +++ b/appinventor/lib/blockly/@types/xml.d.ts @@ -5,7 +5,7 @@ */ import type { Block } from './block.js'; import { WorkspaceComment } from './comments/workspace_comment.js'; -import type { VariableModel } from './variable_model.js'; +import type { IVariableModel, IVariableState } from './interfaces/i_variable_model.js'; import type { Workspace } from './workspace.js'; import { WorkspaceSvg } from './workspace_svg.js'; /** @@ -25,7 +25,7 @@ export declare function saveWorkspaceComment(comment: WorkspaceComment, skipId?: * @param variableList List of all variable models. * @returns Tree of XML elements. */ -export declare function variablesToDom(variableList: VariableModel[]): Element; +export declare function variablesToDom(variableList: IVariableModel[]): Element; /** * Encode a block subtree as XML with XY coordinates. * diff --git a/appinventor/lib/blockly/blockly_compressed.js b/appinventor/lib/blockly/blockly_compressed.js index bd950fee422..66ae2a2a28b 100644 --- a/appinventor/lib/blockly/blockly_compressed.js +++ b/appinventor/lib/blockly/blockly_compressed.js @@ -11,108 +11,114 @@ } }(this, function() { var $={}; -var register$$module$build$src$core$registry,validate$$module$build$src$core$registry,unregister$$module$build$src$core$registry,getItem$$module$build$src$core$registry,hasItem$$module$build$src$core$registry,getClass$$module$build$src$core$registry,getObject$$module$build$src$core$registry,getAllItems$$module$build$src$core$registry,getClassFromOptions$$module$build$src$core$registry,warn$$module$build$src$core$utils$deprecation,getNextUniqueId$$module$build$src$core$utils$idgenerator,genUid$$module$build$src$core$utils$idgenerator, -isBlockCreate$$module$build$src$core$events$predicates,isBlockDelete$$module$build$src$core$events$predicates,isBlockChange$$module$build$src$core$events$predicates,isBlockFieldIntermediateChange$$module$build$src$core$events$predicates,isBlockMove$$module$build$src$core$events$predicates,isVarCreate$$module$build$src$core$events$predicates,isVarDelete$$module$build$src$core$events$predicates,isVarRename$$module$build$src$core$events$predicates,isBlockDrag$$module$build$src$core$events$predicates, -isSelected$$module$build$src$core$events$predicates,isClick$$module$build$src$core$events$predicates,isMarkerMove$$module$build$src$core$events$predicates,isBubbleOpen$$module$build$src$core$events$predicates,isTrashcanOpen$$module$build$src$core$events$predicates,isToolboxItemSelect$$module$build$src$core$events$predicates,isThemeChange$$module$build$src$core$events$predicates,isViewportChange$$module$build$src$core$events$predicates,isCommentCreate$$module$build$src$core$events$predicates,isCommentDelete$$module$build$src$core$events$predicates, -isCommentChange$$module$build$src$core$events$predicates,isCommentMove$$module$build$src$core$events$predicates,isCommentResize$$module$build$src$core$events$predicates,isCommentDrag$$module$build$src$core$events$predicates,isCommentCollapse$$module$build$src$core$events$predicates,isFinishedLoading$$module$build$src$core$events$predicates,getRecordUndo$$module$build$src$core$events$utils,fire$$module$build$src$core$events$utils,fireInternal$$module$build$src$core$events$utils,fireNow$$module$build$src$core$events$utils, -enqueueEvent$$module$build$src$core$events$utils,filter$$module$build$src$core$events$utils,clearPendingUndo$$module$build$src$core$events$utils,isEnabled$$module$build$src$core$events$utils,setGroupInternal$$module$build$src$core$events$utils,getDescendantIds$$module$build$src$core$events$utils,fromJson$$module$build$src$core$events$utils,get$$module$build$src$core$events$utils,disableOrphans$$module$build$src$core$events$utils,getWorkspaceById$$module$build$src$core$common,getAllWorkspaces$$module$build$src$core$common, -registerWorkspace$$module$build$src$core$common,unregisterWorkpace$$module$build$src$core$common,getMainWorkspace$$module$build$src$core$common,setMainWorkspace$$module$build$src$core$common,getSelected$$module$build$src$core$common,getParentContainer$$module$build$src$core$common,setParentContainer$$module$build$src$core$common,svgResize$$module$build$src$core$common,getBlockTypeCounts$$module$build$src$core$common,jsonInitFactory$$module$build$src$core$common,defineBlocksWithJsonArray$$module$build$src$core$common, -defineBlocksWithJsonArrayInternal$$module$build$src$core$common,longStart$$module$build$src$core$touch,longStop$$module$build$src$core$touch,clearTouchIdentifier$$module$build$src$core$touch,shouldHandleEvent$$module$build$src$core$touch,getTouchIdentifierFromEvent$$module$build$src$core$touch,checkTouchIdentifier$$module$build$src$core$touch,conditionalBind$$module$build$src$core$browser_events,bind$$module$build$src$core$browser_events,unbind$$module$build$src$core$browser_events,isTargetInput$$module$build$src$core$browser_events, -isRightButton$$module$build$src$core$browser_events,mouseToSvg$$module$build$src$core$browser_events,getScrollDeltaPixels$$module$build$src$core$browser_events,removeElem$$module$build$src$core$utils$array,register$$module$build$src$core$css,inject$$module$build$src$core$css,createSvgElement$$module$build$src$core$utils$dom,addClass$$module$build$src$core$utils$dom,removeClasses$$module$build$src$core$utils$dom,removeClass$$module$build$src$core$utils$dom,hasClass$$module$build$src$core$utils$dom, -removeNode$$module$build$src$core$utils$dom,insertAfter$$module$build$src$core$utils$dom,setCssTransform$$module$build$src$core$utils$dom,startTextWidthCache$$module$build$src$core$utils$dom,stopTextWidthCache$$module$build$src$core$utils$dom,getTextWidth$$module$build$src$core$utils$dom,getFastTextWidth$$module$build$src$core$utils$dom,getFastTextWidthWithSizeString$$module$build$src$core$utils$dom,measureFontMetrics$$module$build$src$core$utils$dom,getSize$$module$build$src$core$utils$style,getSizeInternal$$module$build$src$core$utils$style, -getSizeWithDisplay$$module$build$src$core$utils$style,getComputedStyle$$module$build$src$core$utils$style,getPageOffset$$module$build$src$core$utils$style,getViewportPageOffset$$module$build$src$core$utils$style,getBorderBox$$module$build$src$core$utils$style,scrollIntoContainerView$$module$build$src$core$utils$style,getContainerOffsetToScrollInto$$module$build$src$core$utils$style,getRelativeXY$$module$build$src$core$utils$svg_math,getInjectionDivXY$$module$build$src$core$utils$svg_math,getViewportBBox$$module$build$src$core$utils$svg_math, -getDocumentScroll$$module$build$src$core$utils$svg_math,screenToWsCoordinates$$module$build$src$core$utils$svg_math,wsToScreenCoordinates$$module$build$src$core$utils$svg_math,injectDependencies$$module$build$src$core$utils$xml,domToText$$module$build$src$core$utils$xml,sanitizeText$$module$build$src$core$utils$xml,convertToolboxDefToJson$$module$build$src$core$utils$toolbox,validateToolbox$$module$build$src$core$utils$toolbox,convertFlyoutDefToJsonArray$$module$build$src$core$utils$toolbox,hasCategories$$module$build$src$core$utils$toolbox, -hasCategoriesInternal$$module$build$src$core$utils$toolbox,isCategoryCollapsible$$module$build$src$core$utils$toolbox,convertToToolboxJson$$module$build$src$core$utils$toolbox,xmlToJsonArray$$module$build$src$core$utils$toolbox,addAttributes$$module$build$src$core$utils$toolbox,parseToolboxTree$$module$build$src$core$utils$toolbox,getStartPositionRect$$module$build$src$core$positionable_helpers,getCornerOppositeToolbox$$module$build$src$core$positionable_helpers,bumpPositionRect$$module$build$src$core$positionable_helpers, -register$$module$build$src$core$serialization$registry,unregister$$module$build$src$core$serialization$registry,save$$module$build$src$core$serialization$workspace_comments,append$$module$build$src$core$serialization$workspace_comments,register$$module$build$src$core$clipboard$registry,unregister$$module$build$src$core$clipboard$registry,moveCommentToNotConflict$$module$build$src$core$clipboard$workspace_comment_paster,commentOverlapsOtherExactly$$module$build$src$core$clipboard$workspace_comment_paster, -setRole$$module$build$src$core$utils$aria,setState$$module$build$src$core$utils$aria,isSerializable$$module$build$src$core$interfaces$i_serializable,queueRender$$module$build$src$core$render_management,finishQueuedRenders$$module$build$src$core$render_management,triggerQueuedRenders$$module$build$src$core$render_management,alwaysImmediatelyRender$$module$build$src$core$render_management,queueBlock$$module$build$src$core$render_management,doRenders$$module$build$src$core$render_management,dequeueBlock$$module$build$src$core$render_management, -shouldRenderRootBlock$$module$build$src$core$render_management,renderBlock$$module$build$src$core$render_management,alert$$module$build$src$core$dialog,setAlert$$module$build$src$core$dialog,confirm$$module$build$src$core$dialog,confirmInternal$$module$build$src$core$dialog,setConfirm$$module$build$src$core$dialog,prompt$$module$build$src$core$dialog,setPrompt$$module$build$src$core$dialog,isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks,isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks, -isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model,flyoutCategory$$module$build$src$core$variables,flyoutCategoryBlocks$$module$build$src$core$variables,generateUniqueName$$module$build$src$core$variables,generateUniqueNameInternal$$module$build$src$core$variables,generateUniqueNameFromOptions$$module$build$src$core$variables,createVariableButtonHandler$$module$build$src$core$variables,promptName$$module$build$src$core$variables,nameUsedWithOtherType$$module$build$src$core$variables, -nameUsedWithAnyType$$module$build$src$core$variables,nameUsedWithConflictingParam$$module$build$src$core$variables,checkForConflictingParamWithProcedureModels$$module$build$src$core$variables,checkForConflictingParamWithLegacyProcedures$$module$build$src$core$variables,generateVariableFieldDom$$module$build$src$core$variables,createVariable$$module$build$src$core$variables,getAddedVariables$$module$build$src$core$variables,save$$module$build$src$core$serialization$blocks,saveAttributes$$module$build$src$core$serialization$blocks, -saveCoords$$module$build$src$core$serialization$blocks,saveExtraState$$module$build$src$core$serialization$blocks,saveIcons$$module$build$src$core$serialization$blocks,saveFields$$module$build$src$core$serialization$blocks,saveInputBlocks$$module$build$src$core$serialization$blocks,saveNextBlocks$$module$build$src$core$serialization$blocks,saveConnection$$module$build$src$core$serialization$blocks,append$$module$build$src$core$serialization$blocks,appendInternal$$module$build$src$core$serialization$blocks, -appendPrivate$$module$build$src$core$serialization$blocks,checkNewVariables$$module$build$src$core$serialization$blocks,loadCoords$$module$build$src$core$serialization$blocks,loadAttributes$$module$build$src$core$serialization$blocks,loadExtraState$$module$build$src$core$serialization$blocks,tryToConnectParent$$module$build$src$core$serialization$blocks,loadIcons$$module$build$src$core$serialization$blocks,loadFields$$module$build$src$core$serialization$blocks,loadInputBlocks$$module$build$src$core$serialization$blocks, -loadNextBlocks$$module$build$src$core$serialization$blocks,loadConnection$$module$build$src$core$serialization$blocks,initBlock$$module$build$src$core$serialization$blocks,hasBubble$$module$build$src$core$interfaces$i_has_bubble,toRadians$$module$build$src$core$utils$math,toDegrees$$module$build$src$core$utils$math,clamp$$module$build$src$core$utils$math,createDom$$module$build$src$core$dropdowndiv,setBoundsElement$$module$build$src$core$dropdowndiv,getOwner$$module$build$src$core$dropdowndiv,getContentDiv$$module$build$src$core$dropdowndiv, -clearContent$$module$build$src$core$dropdowndiv,setColour$$module$build$src$core$dropdowndiv,showPositionedByBlock$$module$build$src$core$dropdowndiv,showPositionedByField$$module$build$src$core$dropdowndiv,getScaledBboxOfBlock$$module$build$src$core$dropdowndiv,getScaledBboxOfField$$module$build$src$core$dropdowndiv,showPositionedByRect$$module$build$src$core$dropdowndiv,show$$module$build$src$core$dropdowndiv,getPositionBelowMetrics$$module$build$src$core$dropdowndiv,getPositionAboveMetrics$$module$build$src$core$dropdowndiv, -getPositionTopOfPageMetrics$$module$build$src$core$dropdowndiv,getPositionX$$module$build$src$core$dropdowndiv,isVisible$$module$build$src$core$dropdowndiv,hideIfOwner$$module$build$src$core$dropdowndiv,hide$$module$build$src$core$dropdowndiv,hideWithoutAnimation$$module$build$src$core$dropdowndiv,positionInternal$$module$build$src$core$dropdowndiv,repositionForWindowResize$$module$build$src$core$dropdowndiv,shortestStringLength$$module$build$src$core$utils$string,commonWordPrefix$$module$build$src$core$utils$string, -commonWordSuffix$$module$build$src$core$utils$string,wrapLine$$module$build$src$core$utils$string,wrapScore$$module$build$src$core$utils$string,wrapMutate$$module$build$src$core$utils$string,wrapToText$$module$build$src$core$utils$string,setCustomTooltip$$module$build$src$core$tooltip,getCustomTooltip$$module$build$src$core$tooltip,isVisible$$module$build$src$core$tooltip,getDiv$$module$build$src$core$tooltip,getTooltipOfObject$$module$build$src$core$tooltip,getTargetObject$$module$build$src$core$tooltip, -createDom$$module$build$src$core$tooltip,bindMouseEvents$$module$build$src$core$tooltip,unbindMouseEvents$$module$build$src$core$tooltip,onMouseOver$$module$build$src$core$tooltip,onMouseOut$$module$build$src$core$tooltip,onMouseMove$$module$build$src$core$tooltip,dispose$$module$build$src$core$tooltip,hide$$module$build$src$core$tooltip,block$$module$build$src$core$tooltip,unblock$$module$build$src$core$tooltip,renderContent$$module$build$src$core$tooltip,renderDefaultContent$$module$build$src$core$tooltip, -getPosition$$module$build$src$core$tooltip,show$$module$build$src$core$tooltip,getHsvSaturation$$module$build$src$core$utils$colour,setHsvSaturation$$module$build$src$core$utils$colour,getHsvValue$$module$build$src$core$utils$colour,setHsvValue$$module$build$src$core$utils$colour,parse$$module$build$src$core$utils$colour,rgbToHex$$module$build$src$core$utils$colour,hexToRgb$$module$build$src$core$utils$colour,hsvToHex$$module$build$src$core$utils$colour,blend$$module$build$src$core$utils$colour,hueToHex$$module$build$src$core$utils$colour, -tokenizeInterpolationInternal$$module$build$src$core$utils$parsing,tokenizeInterpolation$$module$build$src$core$utils$parsing,replaceMessageReferences$$module$build$src$core$utils$parsing,checkMessageReferences$$module$build$src$core$utils$parsing,parseBlockColour$$module$build$src$core$utils$parsing,getDiv$$module$build$src$core$widgetdiv,testOnly_setDiv$$module$build$src$core$widgetdiv,createDom$$module$build$src$core$widgetdiv,show$$module$build$src$core$widgetdiv,hide$$module$build$src$core$widgetdiv, -isVisible$$module$build$src$core$widgetdiv,hideIfOwner$$module$build$src$core$widgetdiv,hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv,positionInternal$$module$build$src$core$widgetdiv,positionWithAnchor$$module$build$src$core$widgetdiv,calculateX$$module$build$src$core$widgetdiv,calculateY$$module$build$src$core$widgetdiv,isRepositionable$$module$build$src$core$widgetdiv,repositionForWindowResize$$module$build$src$core$widgetdiv,getCurrentBlock$$module$build$src$core$contextmenu,setCurrentBlock$$module$build$src$core$contextmenu, -show$$module$build$src$core$contextmenu,populate_$$module$build$src$core$contextmenu,position_$$module$build$src$core$contextmenu,createWidget_$$module$build$src$core$contextmenu,haltPropagation$$module$build$src$core$contextmenu,hide$$module$build$src$core$contextmenu,dispose$$module$build$src$core$contextmenu,mouseToWorkspacePoint$$module$build$src$core$utils$drag,start$$module$build$src$core$utils$drag,move$$module$build$src$core$utils$drag,workspaceToDom$$module$build$src$core$xml,saveWorkspaceComment$$module$build$src$core$xml, -variablesToDom$$module$build$src$core$xml,blockToDomWithXY$$module$build$src$core$xml,fieldToDom$$module$build$src$core$xml,allFieldsToDom$$module$build$src$core$xml,blockToDom$$module$build$src$core$xml,cloneShadow$$module$build$src$core$xml,domToText$$module$build$src$core$xml,domToPrettyText$$module$build$src$core$xml,clearWorkspaceAndLoadFromXml$$module$build$src$core$xml,loadWorkspaceComment$$module$build$src$core$xml,appendDomToWorkspace$$module$build$src$core$xml,domToBlockInternal$$module$build$src$core$xml, -domToVariables$$module$build$src$core$xml,mapSupportedXmlTags$$module$build$src$core$xml,applyMutationTagNodes$$module$build$src$core$xml,applyCommentTagNodes$$module$build$src$core$xml,applyDataTagNodes$$module$build$src$core$xml,applyFieldTagNodes$$module$build$src$core$xml,findChildBlocks$$module$build$src$core$xml,applyInputTagNodes$$module$build$src$core$xml,applyNextTagNodes$$module$build$src$core$xml,domToBlockHeadless$$module$build$src$core$xml,domToField$$module$build$src$core$xml,deleteNext$$module$build$src$core$xml, -isElement$$module$build$src$core$xml,disposeUiEffect$$module$build$src$core$block_animations,disposeUiStep$$module$build$src$core$block_animations,connectionUiEffect$$module$build$src$core$block_animations,disconnectUiEffect$$module$build$src$core$block_animations,disconnectUiStep$$module$build$src$core$block_animations,disconnectUiStop$$module$build$src$core$block_animations,isDraggable$$module$build$src$core$interfaces$i_draggable,deepMerge$$module$build$src$core$utils$object,register$$module$build$src$core$field_registry, -unregister$$module$build$src$core$field_registry,fromJsonInternal$$module$build$src$core$field_registry,unregister$$module$build$src$core$extensions,isRegistered$$module$build$src$core$extensions,apply$$module$build$src$core$extensions,checkNoMutatorProperties$$module$build$src$core$extensions,checkXmlHooks$$module$build$src$core$extensions,checkJsonHooks$$module$build$src$core$extensions,checkMutatorDialog$$module$build$src$core$extensions,checkHasFunctionPair$$module$build$src$core$extensions,checkHasMutatorProperties$$module$build$src$core$extensions, +var register$$module$build$src$core$registry,validate$$module$build$src$core$registry,unregister$$module$build$src$core$registry,getItem$$module$build$src$core$registry,hasItem$$module$build$src$core$registry,getClass$$module$build$src$core$registry,getObject$$module$build$src$core$registry,getAllItems$$module$build$src$core$registry,getClassFromOptions$$module$build$src$core$registry,longStart$$module$build$src$core$touch,longStop$$module$build$src$core$touch,clearTouchIdentifier$$module$build$src$core$touch, +shouldHandleEvent$$module$build$src$core$touch,getTouchIdentifierFromEvent$$module$build$src$core$touch,checkTouchIdentifier$$module$build$src$core$touch,conditionalBind$$module$build$src$core$browser_events,bind$$module$build$src$core$browser_events,unbind$$module$build$src$core$browser_events,isTargetInput$$module$build$src$core$browser_events,isRightButton$$module$build$src$core$browser_events,mouseToSvg$$module$build$src$core$browser_events,getScrollDeltaPixels$$module$build$src$core$browser_events, +getNextUniqueId$$module$build$src$core$utils$idgenerator,genUid$$module$build$src$core$utils$idgenerator,isBlockCreate$$module$build$src$core$events$predicates,isBlockDelete$$module$build$src$core$events$predicates,isBlockChange$$module$build$src$core$events$predicates,isBlockFieldIntermediateChange$$module$build$src$core$events$predicates,isBlockMove$$module$build$src$core$events$predicates,isVarCreate$$module$build$src$core$events$predicates,isVarDelete$$module$build$src$core$events$predicates, +isVarRename$$module$build$src$core$events$predicates,isBlockDrag$$module$build$src$core$events$predicates,isSelected$$module$build$src$core$events$predicates,isClick$$module$build$src$core$events$predicates,isBubbleOpen$$module$build$src$core$events$predicates,isTrashcanOpen$$module$build$src$core$events$predicates,isToolboxItemSelect$$module$build$src$core$events$predicates,isThemeChange$$module$build$src$core$events$predicates,isViewportChange$$module$build$src$core$events$predicates,isCommentCreate$$module$build$src$core$events$predicates, +isCommentDelete$$module$build$src$core$events$predicates,isCommentChange$$module$build$src$core$events$predicates,isCommentMove$$module$build$src$core$events$predicates,isCommentResize$$module$build$src$core$events$predicates,isCommentDrag$$module$build$src$core$events$predicates,isCommentCollapse$$module$build$src$core$events$predicates,isFinishedLoading$$module$build$src$core$events$predicates,getRecordUndo$$module$build$src$core$events$utils,fire$$module$build$src$core$events$utils,fireInternal$$module$build$src$core$events$utils, +fireNow$$module$build$src$core$events$utils,enqueueEvent$$module$build$src$core$events$utils,filter$$module$build$src$core$events$utils,clearPendingUndo$$module$build$src$core$events$utils,isEnabled$$module$build$src$core$events$utils,setGroupInternal$$module$build$src$core$events$utils,getDescendantIds$$module$build$src$core$events$utils,fromJson$$module$build$src$core$events$utils,get$$module$build$src$core$events$utils,disableOrphans$$module$build$src$core$events$utils,createSvgElement$$module$build$src$core$utils$dom, +addClass$$module$build$src$core$utils$dom,removeClasses$$module$build$src$core$utils$dom,removeClass$$module$build$src$core$utils$dom,hasClass$$module$build$src$core$utils$dom,removeNode$$module$build$src$core$utils$dom,insertAfter$$module$build$src$core$utils$dom,setCssTransform$$module$build$src$core$utils$dom,startTextWidthCache$$module$build$src$core$utils$dom,stopTextWidthCache$$module$build$src$core$utils$dom,getTextWidth$$module$build$src$core$utils$dom,getFastTextWidth$$module$build$src$core$utils$dom, +getFastTextWidthWithSizeString$$module$build$src$core$utils$dom,measureFontMetrics$$module$build$src$core$utils$dom,isFocusableNode$$module$build$src$core$interfaces$i_focusable_node,isSelectable$$module$build$src$core$interfaces$i_selectable,deepMerge$$module$build$src$core$utils$object,getWorkspaceById$$module$build$src$core$common,getAllWorkspaces$$module$build$src$core$common,registerWorkspace$$module$build$src$core$common,unregisterWorkpace$$module$build$src$core$common,getMainWorkspace$$module$build$src$core$common, +setMainWorkspace$$module$build$src$core$common,getSelected$$module$build$src$core$common,setSelected$$module$build$src$core$common,fireSelectedEvent$$module$build$src$core$common,getParentContainer$$module$build$src$core$common,setParentContainer$$module$build$src$core$common,svgResize$$module$build$src$core$common,getBlockTypeCounts$$module$build$src$core$common,jsonInitFactory$$module$build$src$core$common,defineBlocksWithJsonArray$$module$build$src$core$common,defineBlocksWithJsonArrayInternal$$module$build$src$core$common, +globalShortcutHandler$$module$build$src$core$common,removeElem$$module$build$src$core$utils$array,register$$module$build$src$core$css,inject$$module$build$src$core$css,getSize$$module$build$src$core$utils$style,getSizeInternal$$module$build$src$core$utils$style,getSizeWithDisplay$$module$build$src$core$utils$style,getComputedStyle$$module$build$src$core$utils$style,getPageOffset$$module$build$src$core$utils$style,getViewportPageOffset$$module$build$src$core$utils$style,getBorderBox$$module$build$src$core$utils$style, +scrollIntoContainerView$$module$build$src$core$utils$style,getContainerOffsetToScrollInto$$module$build$src$core$utils$style,getRelativeXY$$module$build$src$core$utils$svg_math,getInjectionDivXY$$module$build$src$core$utils$svg_math,getViewportBBox$$module$build$src$core$utils$svg_math,getDocumentScroll$$module$build$src$core$utils$svg_math,screenToWsCoordinates$$module$build$src$core$utils$svg_math,wsToScreenCoordinates$$module$build$src$core$utils$svg_math,injectDependencies$$module$build$src$core$utils$xml, +domToText$$module$build$src$core$utils$xml,sanitizeText$$module$build$src$core$utils$xml,convertToolboxDefToJson$$module$build$src$core$utils$toolbox,validateToolbox$$module$build$src$core$utils$toolbox,convertFlyoutDefToJsonArray$$module$build$src$core$utils$toolbox,hasCategories$$module$build$src$core$utils$toolbox,hasCategoriesInternal$$module$build$src$core$utils$toolbox,isCategoryCollapsible$$module$build$src$core$utils$toolbox,convertToToolboxJson$$module$build$src$core$utils$toolbox,xmlToJsonArray$$module$build$src$core$utils$toolbox, +addAttributes$$module$build$src$core$utils$toolbox,parseToolboxTree$$module$build$src$core$utils$toolbox,getStartPositionRect$$module$build$src$core$positionable_helpers,getCornerOppositeToolbox$$module$build$src$core$positionable_helpers,bumpPositionRect$$module$build$src$core$positionable_helpers,register$$module$build$src$core$serialization$registry,unregister$$module$build$src$core$serialization$registry,save$$module$build$src$core$serialization$workspace_comments,append$$module$build$src$core$serialization$workspace_comments, +register$$module$build$src$core$clipboard$registry,unregister$$module$build$src$core$clipboard$registry,moveCommentToNotConflict$$module$build$src$core$clipboard$workspace_comment_paster,commentOverlapsOtherExactly$$module$build$src$core$clipboard$workspace_comment_paster,setRole$$module$build$src$core$utils$aria,setState$$module$build$src$core$utils$aria,isSerializable$$module$build$src$core$interfaces$i_serializable,queueRender$$module$build$src$core$render_management,finishQueuedRenders$$module$build$src$core$render_management, +triggerQueuedRenders$$module$build$src$core$render_management,alwaysImmediatelyRender$$module$build$src$core$render_management,queueBlock$$module$build$src$core$render_management,doRenders$$module$build$src$core$render_management,dequeueBlock$$module$build$src$core$render_management,shouldRenderRootBlock$$module$build$src$core$render_management,renderBlock$$module$build$src$core$render_management,alert$$module$build$src$core$dialog,setAlert$$module$build$src$core$dialog,confirm$$module$build$src$core$dialog, +setConfirm$$module$build$src$core$dialog,prompt$$module$build$src$core$dialog,setPrompt$$module$build$src$core$dialog,toast$$module$build$src$core$dialog,setToast$$module$build$src$core$dialog,isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks,isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks,isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model,warn$$module$build$src$core$utils$deprecation, +internalFlyoutCategory$$module$build$src$core$variables,flyoutCategory$$module$build$src$core$variables,generateVariableFieldJson$$module$build$src$core$variables,jsonFlyoutCategoryBlocks$$module$build$src$core$variables,xmlFlyoutCategory$$module$build$src$core$variables,flyoutCategoryBlocks$$module$build$src$core$variables,generateUniqueName$$module$build$src$core$variables,generateUniqueNameInternal$$module$build$src$core$variables,generateUniqueNameFromOptions$$module$build$src$core$variables, +createVariableButtonHandler$$module$build$src$core$variables,promptName$$module$build$src$core$variables,nameUsedWithOtherType$$module$build$src$core$variables,nameUsedWithAnyType$$module$build$src$core$variables,nameUsedWithConflictingParam$$module$build$src$core$variables,checkForConflictingParamWithProcedureModels$$module$build$src$core$variables,checkForConflictingParamWithLegacyProcedures$$module$build$src$core$variables,generateVariableFieldDom$$module$build$src$core$variables,createVariable$$module$build$src$core$variables, +getAddedVariables$$module$build$src$core$variables,compareByName$$module$build$src$core$variables,getVariableUsesById$$module$build$src$core$variables,save$$module$build$src$core$serialization$blocks,saveAttributes$$module$build$src$core$serialization$blocks,saveCoords$$module$build$src$core$serialization$blocks,saveExtraState$$module$build$src$core$serialization$blocks,saveIcons$$module$build$src$core$serialization$blocks,saveFields$$module$build$src$core$serialization$blocks,saveInputBlocks$$module$build$src$core$serialization$blocks, +saveNextBlocks$$module$build$src$core$serialization$blocks,saveConnection$$module$build$src$core$serialization$blocks,append$$module$build$src$core$serialization$blocks,appendInternal$$module$build$src$core$serialization$blocks,appendPrivate$$module$build$src$core$serialization$blocks,checkNewVariables$$module$build$src$core$serialization$blocks,loadCoords$$module$build$src$core$serialization$blocks,loadAttributes$$module$build$src$core$serialization$blocks,loadExtraState$$module$build$src$core$serialization$blocks, +tryToConnectParent$$module$build$src$core$serialization$blocks,loadIcons$$module$build$src$core$serialization$blocks,loadFields$$module$build$src$core$serialization$blocks,loadInputBlocks$$module$build$src$core$serialization$blocks,loadNextBlocks$$module$build$src$core$serialization$blocks,loadConnection$$module$build$src$core$serialization$blocks,initBlock$$module$build$src$core$serialization$blocks,hasBubble$$module$build$src$core$interfaces$i_has_bubble,toRadians$$module$build$src$core$utils$math, +toDegrees$$module$build$src$core$utils$math,clamp$$module$build$src$core$utils$math,createDom$$module$build$src$core$dropdowndiv,setBoundsElement$$module$build$src$core$dropdowndiv,getOwner$$module$build$src$core$dropdowndiv,getContentDiv$$module$build$src$core$dropdowndiv,clearContent$$module$build$src$core$dropdowndiv,setColour$$module$build$src$core$dropdowndiv,showPositionedByBlock$$module$build$src$core$dropdowndiv,showPositionedByField$$module$build$src$core$dropdowndiv,getScaledBboxOfBlock$$module$build$src$core$dropdowndiv, +getScaledBboxOfField$$module$build$src$core$dropdowndiv,showPositionedByRect$$module$build$src$core$dropdowndiv,show$$module$build$src$core$dropdowndiv,getPositionBelowMetrics$$module$build$src$core$dropdowndiv,getPositionAboveMetrics$$module$build$src$core$dropdowndiv,getPositionTopOfPageMetrics$$module$build$src$core$dropdowndiv,getPositionX$$module$build$src$core$dropdowndiv,isVisible$$module$build$src$core$dropdowndiv,hideIfOwner$$module$build$src$core$dropdowndiv,hide$$module$build$src$core$dropdowndiv, +hideWithoutAnimation$$module$build$src$core$dropdowndiv,positionInternal$$module$build$src$core$dropdowndiv,repositionForWindowResize$$module$build$src$core$dropdowndiv,shortestStringLength$$module$build$src$core$utils$string,commonWordPrefix$$module$build$src$core$utils$string,commonWordSuffix$$module$build$src$core$utils$string,wrapLine$$module$build$src$core$utils$string,wrapScore$$module$build$src$core$utils$string,wrapMutate$$module$build$src$core$utils$string,wrapToText$$module$build$src$core$utils$string, +setCustomTooltip$$module$build$src$core$tooltip,getCustomTooltip$$module$build$src$core$tooltip,isVisible$$module$build$src$core$tooltip,getDiv$$module$build$src$core$tooltip,getTooltipOfObject$$module$build$src$core$tooltip,getTargetObject$$module$build$src$core$tooltip,createDom$$module$build$src$core$tooltip,bindMouseEvents$$module$build$src$core$tooltip,unbindMouseEvents$$module$build$src$core$tooltip,onMouseOver$$module$build$src$core$tooltip,onMouseOut$$module$build$src$core$tooltip,onMouseMove$$module$build$src$core$tooltip, +dispose$$module$build$src$core$tooltip,hide$$module$build$src$core$tooltip,block$$module$build$src$core$tooltip,unblock$$module$build$src$core$tooltip,renderContent$$module$build$src$core$tooltip,renderDefaultContent$$module$build$src$core$tooltip,getPosition$$module$build$src$core$tooltip,show$$module$build$src$core$tooltip,getHsvSaturation$$module$build$src$core$utils$colour,setHsvSaturation$$module$build$src$core$utils$colour,getHsvValue$$module$build$src$core$utils$colour,setHsvValue$$module$build$src$core$utils$colour, +parse$$module$build$src$core$utils$colour,rgbToHex$$module$build$src$core$utils$colour,hexToRgb$$module$build$src$core$utils$colour,hsvToHex$$module$build$src$core$utils$colour,blend$$module$build$src$core$utils$colour,hueToHex$$module$build$src$core$utils$colour,tokenizeInterpolationInternal$$module$build$src$core$utils$parsing,tokenizeInterpolation$$module$build$src$core$utils$parsing,replaceMessageReferences$$module$build$src$core$utils$parsing,checkMessageReferences$$module$build$src$core$utils$parsing, +parseBlockColour$$module$build$src$core$utils$parsing,getDiv$$module$build$src$core$widgetdiv,testOnly_setDiv$$module$build$src$core$widgetdiv,createDom$$module$build$src$core$widgetdiv,show$$module$build$src$core$widgetdiv,hide$$module$build$src$core$widgetdiv,isVisible$$module$build$src$core$widgetdiv,hideIfOwner$$module$build$src$core$widgetdiv,hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv,positionInternal$$module$build$src$core$widgetdiv,positionWithAnchor$$module$build$src$core$widgetdiv, +calculateX$$module$build$src$core$widgetdiv,calculateY$$module$build$src$core$widgetdiv,isRepositionable$$module$build$src$core$widgetdiv,repositionForWindowResize$$module$build$src$core$widgetdiv,getCurrentBlock$$module$build$src$core$contextmenu,setCurrentBlock$$module$build$src$core$contextmenu,show$$module$build$src$core$contextmenu,populate_$$module$build$src$core$contextmenu,position_$$module$build$src$core$contextmenu,createWidget_$$module$build$src$core$contextmenu,haltPropagation$$module$build$src$core$contextmenu, +hide$$module$build$src$core$contextmenu,dispose$$module$build$src$core$contextmenu,getMenu$$module$build$src$core$contextmenu,mouseToWorkspacePoint$$module$build$src$core$utils$drag,start$$module$build$src$core$utils$drag,move$$module$build$src$core$utils$drag,workspaceToDom$$module$build$src$core$xml,saveWorkspaceComment$$module$build$src$core$xml,variablesToDom$$module$build$src$core$xml,blockToDomWithXY$$module$build$src$core$xml,fieldToDom$$module$build$src$core$xml,allFieldsToDom$$module$build$src$core$xml, +blockToDom$$module$build$src$core$xml,cloneShadow$$module$build$src$core$xml,domToText$$module$build$src$core$xml,domToPrettyText$$module$build$src$core$xml,clearWorkspaceAndLoadFromXml$$module$build$src$core$xml,loadWorkspaceComment$$module$build$src$core$xml,appendDomToWorkspace$$module$build$src$core$xml,domToBlockInternal$$module$build$src$core$xml,domToVariables$$module$build$src$core$xml,mapSupportedXmlTags$$module$build$src$core$xml,applyMutationTagNodes$$module$build$src$core$xml,applyCommentTagNodes$$module$build$src$core$xml, +applyDataTagNodes$$module$build$src$core$xml,applyFieldTagNodes$$module$build$src$core$xml,findChildBlocks$$module$build$src$core$xml,applyInputTagNodes$$module$build$src$core$xml,applyNextTagNodes$$module$build$src$core$xml,domToBlockHeadless$$module$build$src$core$xml,domToField$$module$build$src$core$xml,deleteNext$$module$build$src$core$xml,isElement$$module$build$src$core$xml,register$$module$build$src$core$field_registry,unregister$$module$build$src$core$field_registry,fromJsonInternal$$module$build$src$core$field_registry, +isImageProperties$$module$build$src$core$field_dropdown,unregister$$module$build$src$core$extensions,isRegistered$$module$build$src$core$extensions,apply$$module$build$src$core$extensions,checkNoMutatorProperties$$module$build$src$core$extensions,checkXmlHooks$$module$build$src$core$extensions,checkJsonHooks$$module$build$src$core$extensions,checkMutatorDialog$$module$build$src$core$extensions,checkHasFunctionPair$$module$build$src$core$extensions,checkHasMutatorProperties$$module$build$src$core$extensions, getMutatorProperties$$module$build$src$core$extensions,mutatorPropertiesMatch$$module$build$src$core$extensions,runAfterPageLoad$$module$build$src$core$extensions,checkDropdownOptionsInTable$$module$build$src$core$extensions,extensionParentTooltip$$module$build$src$core$extensions,point$$module$build$src$core$utils$svg_paths,curve$$module$build$src$core$utils$svg_paths,moveTo$$module$build$src$core$utils$svg_paths,moveBy$$module$build$src$core$utils$svg_paths,lineTo$$module$build$src$core$utils$svg_paths, -line$$module$build$src$core$utils$svg_paths,lineOnAxis$$module$build$src$core$utils$svg_paths,arc$$module$build$src$core$utils$svg_paths,register$$module$build$src$core$icons$registry,unregister$$module$build$src$core$icons$registry,isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block,isObservable$$module$build$src$core$interfaces$i_observable,allProcedures$$module$build$src$core$procedures,procTupleComparator$$module$build$src$core$procedures,isLegalName$$module$build$src$core$procedures, -isNameUsed$$module$build$src$core$procedures,flyoutCategory$$module$build$src$core$procedures,updateMutatorFlyout$$module$build$src$core$procedures,mutatorOpenListener$$module$build$src$core$procedures,mutatorChangeListener$$module$build$src$core$procedures,getCallers$$module$build$src$core$procedures,blockIsModernCallerFor$$module$build$src$core$procedures,isDynamicShape$$module$build$src$core$renderers$common$constants,isPuzzleTab$$module$build$src$core$renderers$common$constants,isNotch$$module$build$src$core$renderers$common$constants, -connectReciprocally$$module$build$src$core$connection,getSingleConnection$$module$build$src$core$connection,getConnectionForOrphanedOutput$$module$build$src$core$connection,isIcon$$module$build$src$core$interfaces$i_icon,isCommentIcon$$module$build$src$core$interfaces$i_comment_icon,getParentConnection$$module$build$src$core$keyboard_nav$ast_node,register$$module$build$src$core$renderers$common$block_rendering,unregister$$module$build$src$core$renderers$common$block_rendering,init$$module$build$src$core$renderers$common$block_rendering, -stringButtonClickHandler$$module$build$src$core$variables_dynamic,numberButtonClickHandler$$module$build$src$core$variables_dynamic,colourButtonClickHandler$$module$build$src$core$variables_dynamic,flyoutCategory$$module$build$src$core$variables_dynamic,flyoutCategoryBlocks$$module$build$src$core$variables_dynamic,resizeSvgContents$$module$build$src$core$workspace_svg,moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster,blockOverlapsOtherExactly$$module$build$src$core$clipboard$block_paster, -blockIsInSnapRadius$$module$build$src$core$clipboard$block_paster,bumpObjectIntoBounds$$module$build$src$core$bump_objects,bumpIntoBoundsHandler$$module$build$src$core$bump_objects,extractObjectFromEvent$$module$build$src$core$bump_objects,bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects,isDeletable$$module$build$src$core$interfaces$i_deletable,copyInternal$$module$build$src$core$clipboard,paste$$module$build$src$core$clipboard,pasteFromData$$module$build$src$core$clipboard,duplicateInternal$$module$build$src$core$clipboard, -isCopyable$$module$build$src$core$interfaces$i_copyable,registerEscape$$module$build$src$core$shortcut_items,registerDelete$$module$build$src$core$shortcut_items,registerCopy$$module$build$src$core$shortcut_items,registerCut$$module$build$src$core$shortcut_items,registerPaste$$module$build$src$core$shortcut_items,registerUndo$$module$build$src$core$shortcut_items,registerRedo$$module$build$src$core$shortcut_items,registerDefaultShortcuts$$module$build$src$core$shortcut_items,saveProcedure$$module$build$src$core$serialization$procedures, -loadProcedure$$module$build$src$core$serialization$procedures,save$$module$build$src$core$serialization$workspaces,load$$module$build$src$core$serialization$workspaces,inject$$module$build$src$core$inject,createDom$$module$build$src$core$inject,createMainWorkspace$$module$build$src$core$inject,init$$module$build$src$core$inject,onKeyDown$$module$build$src$core$inject,bindDocumentEvents$$module$build$src$core$inject,loadSounds$$module$build$src$core$inject,registerUndo$$module$build$src$core$contextmenu_items, -registerRedo$$module$build$src$core$contextmenu_items,registerCleanup$$module$build$src$core$contextmenu_items,toggleOption_$$module$build$src$core$contextmenu_items,registerCollapse$$module$build$src$core$contextmenu_items,registerExpand$$module$build$src$core$contextmenu_items,addDeletableBlocks_$$module$build$src$core$contextmenu_items,getDeletableBlocks_$$module$build$src$core$contextmenu_items,deleteNext_$$module$build$src$core$contextmenu_items,registerDeleteAll$$module$build$src$core$contextmenu_items, -registerWorkspaceOptions_$$module$build$src$core$contextmenu_items,registerDuplicate$$module$build$src$core$contextmenu_items,registerComment$$module$build$src$core$contextmenu_items,registerInline$$module$build$src$core$contextmenu_items,registerCollapseExpandBlock$$module$build$src$core$contextmenu_items,registerDisable$$module$build$src$core$contextmenu_items,registerDelete$$module$build$src$core$contextmenu_items,registerHelp$$module$build$src$core$contextmenu_items,registerCommentDelete$$module$build$src$core$contextmenu_items, -registerCommentDuplicate$$module$build$src$core$contextmenu_items,registerCommentCreate$$module$build$src$core$contextmenu_items,pixelsToWorkspaceCoords$$module$build$src$core$contextmenu_items,registerBlockOptions_$$module$build$src$core$contextmenu_items,registerCommentOptions$$module$build$src$core$contextmenu_items,registerDefaultOptions$$module$build$src$core$contextmenu_items,isPaster$$module$build$src$core$interfaces$i_paster,isRenderedElement$$module$build$src$core$interfaces$i_rendered_element, -isSelectable$$module$build$src$core$interfaces$i_selectable,isSelectableToolboxItem$$module$build$src$core$interfaces$i_selectable_toolbox_item,hideChaff$$module$build$src$core$blockly,$jscomp; -register$$module$build$src$core$registry=function(a,b,c,d){if(!(a instanceof Type$$module$build$src$core$registry)&&"string"!==typeof a||""===`${a}`.trim())throw Error('Invalid type "'+a+'". The type must be a non-empty string or a Blockly.registry.Type.');a=`${a}`.toLowerCase();if("string"!==typeof b||""===b.trim())throw Error('Invalid name "'+b+'". The name must be a non-empty string.');const e=b.toLowerCase();if(!c)throw Error("Can not register a null value");let f=typeMap$$module$build$src$core$registry[a], +line$$module$build$src$core$utils$svg_paths,lineOnAxis$$module$build$src$core$utils$svg_paths,arc$$module$build$src$core$utils$svg_paths,connectReciprocally$$module$build$src$core$connection,getSingleConnection$$module$build$src$core$connection,getConnectionForOrphanedOutput$$module$build$src$core$connection,isIcon$$module$build$src$core$interfaces$i_icon,isCommentIcon$$module$build$src$core$interfaces$i_comment_icon,disposeUiEffect$$module$build$src$core$block_animations,disposeUiStep$$module$build$src$core$block_animations, +connectionUiEffect$$module$build$src$core$block_animations,disconnectUiEffect$$module$build$src$core$block_animations,disconnectUiStep$$module$build$src$core$block_animations,disconnectUiStop$$module$build$src$core$block_animations,moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster,blockOverlapsOtherExactly$$module$build$src$core$clipboard$block_paster,blockIsInSnapRadius$$module$build$src$core$clipboard$block_paster,bumpObjectIntoBounds$$module$build$src$core$bump_objects,bumpIntoBoundsHandler$$module$build$src$core$bump_objects, +extractObjectFromEvent$$module$build$src$core$bump_objects,bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects,isDeletable$$module$build$src$core$interfaces$i_deletable,getBlockNavigationCandidates$$module$build$src$core$keyboard_nav$block_navigation_policy,navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy,navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy,register$$module$build$src$core$icons$registry,unregister$$module$build$src$core$icons$registry, +hasContextMenu$$module$build$src$core$interfaces$i_contextmenu,isDraggable$$module$build$src$core$interfaces$i_draggable,isAutoHideable$$module$build$src$core$interfaces$i_autohideable,isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block,isObservable$$module$build$src$core$interfaces$i_observable,allProcedures$$module$build$src$core$procedures,procTupleComparator$$module$build$src$core$procedures,isLegalName$$module$build$src$core$procedures,isNameUsed$$module$build$src$core$procedures, +xmlFlyoutCategory$$module$build$src$core$procedures,internalFlyoutCategory$$module$build$src$core$procedures,flyoutCategory$$module$build$src$core$procedures,updateMutatorFlyout$$module$build$src$core$procedures,mutatorOpenListener$$module$build$src$core$procedures,mutatorChangeListener$$module$build$src$core$procedures,getCallers$$module$build$src$core$procedures,blockIsModernCallerFor$$module$build$src$core$procedures,isDynamicShape$$module$build$src$core$renderers$common$constants,isPuzzleTab$$module$build$src$core$renderers$common$constants, +isNotch$$module$build$src$core$renderers$common$constants,register$$module$build$src$core$renderers$common$block_rendering,unregister$$module$build$src$core$renderers$common$block_rendering,init$$module$build$src$core$renderers$common$block_rendering,stringButtonClickHandler$$module$build$src$core$variables_dynamic,numberButtonClickHandler$$module$build$src$core$variables_dynamic,colourButtonClickHandler$$module$build$src$core$variables_dynamic,internalFlyoutCategory$$module$build$src$core$variables_dynamic, +flyoutCategory$$module$build$src$core$variables_dynamic,xmlFlyoutCategory$$module$build$src$core$variables_dynamic,flyoutCategoryBlocks$$module$build$src$core$variables_dynamic,resizeSvgContents$$module$build$src$core$workspace_svg,copy$$module$build$src$core$clipboard,getLastCopiedData$$module$build$src$core$clipboard,setLastCopiedData$$module$build$src$core$clipboard,getLastCopiedWorkspace$$module$build$src$core$clipboard,setLastCopiedWorkspace$$module$build$src$core$clipboard,getLastCopiedLocation$$module$build$src$core$clipboard, +setLastCopiedLocation$$module$build$src$core$clipboard,paste$$module$build$src$core$clipboard,pasteFromData$$module$build$src$core$clipboard,isCopyable$$module$build$src$core$interfaces$i_copyable,registerEscape$$module$build$src$core$shortcut_items,registerDelete$$module$build$src$core$shortcut_items,isCopyable$$module$build$src$core$shortcut_items,isCuttable$$module$build$src$core$shortcut_items,registerCopy$$module$build$src$core$shortcut_items,registerCut$$module$build$src$core$shortcut_items, +registerPaste$$module$build$src$core$shortcut_items,registerUndo$$module$build$src$core$shortcut_items,registerRedo$$module$build$src$core$shortcut_items,registerShowContextMenu$$module$build$src$core$shortcut_items,registerDefaultShortcuts$$module$build$src$core$shortcut_items,saveProcedure$$module$build$src$core$serialization$procedures,loadProcedure$$module$build$src$core$serialization$procedures,save$$module$build$src$core$serialization$workspaces,load$$module$build$src$core$serialization$workspaces, +inject$$module$build$src$core$inject,createDom$$module$build$src$core$inject,createMainWorkspace$$module$build$src$core$inject,init$$module$build$src$core$inject,bindDocumentEvents$$module$build$src$core$inject,loadSounds$$module$build$src$core$inject,isFullBlockField$$module$build$src$core$contextmenu_items,registerUndo$$module$build$src$core$contextmenu_items,registerRedo$$module$build$src$core$contextmenu_items,registerCleanup$$module$build$src$core$contextmenu_items,toggleOption_$$module$build$src$core$contextmenu_items, +registerCollapse$$module$build$src$core$contextmenu_items,registerExpand$$module$build$src$core$contextmenu_items,addDeletableBlocks_$$module$build$src$core$contextmenu_items,getDeletableBlocks_$$module$build$src$core$contextmenu_items,deleteNext_$$module$build$src$core$contextmenu_items,registerDeleteAll$$module$build$src$core$contextmenu_items,registerWorkspaceOptions_$$module$build$src$core$contextmenu_items,registerDuplicate$$module$build$src$core$contextmenu_items,registerComment$$module$build$src$core$contextmenu_items, +registerInline$$module$build$src$core$contextmenu_items,registerCollapseExpandBlock$$module$build$src$core$contextmenu_items,registerDisable$$module$build$src$core$contextmenu_items,registerDelete$$module$build$src$core$contextmenu_items,registerHelp$$module$build$src$core$contextmenu_items,registerCommentDelete$$module$build$src$core$contextmenu_items,registerCommentDuplicate$$module$build$src$core$contextmenu_items,registerCommentCreate$$module$build$src$core$contextmenu_items,registerBlockOptions_$$module$build$src$core$contextmenu_items, +registerCommentOptions$$module$build$src$core$contextmenu_items,registerDefaultOptions$$module$build$src$core$contextmenu_items,isPaster$$module$build$src$core$interfaces$i_paster,isRenderedElement$$module$build$src$core$interfaces$i_rendered_element,isSelectableToolboxItem$$module$build$src$core$interfaces$i_selectable_toolbox_item,hideChaff$$module$build$src$core$blockly,isFocusableTree$$module$build$src$core$interfaces$i_focusable_tree,$jscomp; +register$$module$build$src$core$registry=function(a,b,c,d){if(!(a instanceof Type$$module$build$src$core$registry)&&typeof a!=="string"||`${a}`.trim()==="")throw Error('Invalid type "'+a+'". The type must be a non-empty string or a Blockly.registry.Type.');a=`${a}`.toLowerCase();if(typeof b!=="string"||b.trim()==="")throw Error('Invalid name "'+b+'". The name must be a non-empty string.');const e=b.toLowerCase();if(!c)throw Error("Can not register a null value");let f=typeMap$$module$build$src$core$registry[a], g=nameMap$$module$build$src$core$registry[a];f||(f=typeMap$$module$build$src$core$registry[a]=Object.create(null),g=nameMap$$module$build$src$core$registry[a]=Object.create(null));validate$$module$build$src$core$registry(a,c);if(!d&&f[e]&&f[e]!==c)throw Error('Name "'+e+'" with type "'+a+'" already registered.');f[e]=c;g[e]=b}; -validate$$module$build$src$core$registry=function(a,b){switch(a){case String(Type$$module$build$src$core$registry.FIELD):if("function"!==typeof b.fromJson)throw Error('Type "'+a+'" must have a fromJson function');}}; +validate$$module$build$src$core$registry=function(a,b){switch(a){case String(Type$$module$build$src$core$registry.FIELD):if(typeof b.fromJson!=="function")throw Error('Type "'+a+'" must have a fromJson function');}}; unregister$$module$build$src$core$registry=function(a,b){a=`${a}`.toLowerCase();b=b.toLowerCase();const c=typeMap$$module$build$src$core$registry[a];c&&c[b]?(delete typeMap$$module$build$src$core$registry[a][b],delete nameMap$$module$build$src$core$registry[a][b]):console.warn("Unable to unregister ["+b+"]["+a+"] from the registry.")}; getItem$$module$build$src$core$registry=function(a,b,c){a=`${a}`.toLowerCase();b=b.toLowerCase();const d=typeMap$$module$build$src$core$registry[a];if(!d||!d[b]){b="Unable to find ["+b+"]["+a+"] in the registry.";if(c)throw Error(b+" You must require or register a "+a+" plugin.");console.warn(b);return null}return d[b]};hasItem$$module$build$src$core$registry=function(a,b){a=`${a}`.toLowerCase();b=b.toLowerCase();return(a=typeMap$$module$build$src$core$registry[a])?!!a[b]:!1}; getClass$$module$build$src$core$registry=function(a,b,c){return getItem$$module$build$src$core$registry(a,b,c)};getObject$$module$build$src$core$registry=function(a,b,c){return getItem$$module$build$src$core$registry(a,b,c)}; getAllItems$$module$build$src$core$registry=function(a,b,c){a=`${a}`.toLowerCase();var d=typeMap$$module$build$src$core$registry[a];if(!d){d=`Unable to find [${a}] in the registry.`;if(c)throw Error(`${d} You must require or register a ${a} plugin.`);console.warn(d);return null}if(!b)return d;a=nameMap$$module$build$src$core$registry[a];c=Object.create(null);for(const e of Object.keys(d))c[a[e]]=d[e];return c}; -getClassFromOptions$$module$build$src$core$registry=function(a,b,c){b=b.plugins[String(a)]||DEFAULT$$module$build$src$core$registry;return"function"===typeof b?b:getClass$$module$build$src$core$registry(a,b,c)};warn$$module$build$src$core$utils$deprecation=function(a,b,c,d){a=a+" was deprecated in "+b+" and will be deleted in "+c+".";d&&(a+="\nUse "+d+" instead.");previousWarnings$$module$build$src$core$utils$deprecation.has(a)||(previousWarnings$$module$build$src$core$utils$deprecation.add(a),console.warn(a))}; +getClassFromOptions$$module$build$src$core$registry=function(a,b,c){b=b.plugins[String(a)]||DEFAULT$$module$build$src$core$registry;return typeof b==="function"?b:getClass$$module$build$src$core$registry(a,b,c)};longStart$$module$build$src$core$touch=function(a,b){longStop$$module$build$src$core$touch();longPid_$$module$build$src$core$touch=setTimeout(function(){b&&b.handleRightClick(a)},LONGPRESS$$module$build$src$core$touch)}; +longStop$$module$build$src$core$touch=function(){longPid_$$module$build$src$core$touch&&(clearTimeout(longPid_$$module$build$src$core$touch),longPid_$$module$build$src$core$touch=0)};clearTouchIdentifier$$module$build$src$core$touch=function(){touchIdentifier_$$module$build$src$core$touch=null};shouldHandleEvent$$module$build$src$core$touch=function(a){return!a.type.startsWith("pointer")||a instanceof PointerEvent&&checkTouchIdentifier$$module$build$src$core$touch(a)}; +getTouchIdentifierFromEvent$$module$build$src$core$touch=function(a){return`${a.pointerId}`};checkTouchIdentifier$$module$build$src$core$touch=function(a){const b=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);return touchIdentifier_$$module$build$src$core$touch?touchIdentifier_$$module$build$src$core$touch===b:a.type==="pointerdown"?(touchIdentifier_$$module$build$src$core$touch=b,!0):!1}; +conditionalBind$$module$build$src$core$browser_events=function(a,b,c,d,e,f){function g(k){if(e||shouldHandleEvent$$module$build$src$core$touch(k))c?d.call(c,k):d(k)}const h=[];if(b in TOUCH_MAP$$module$build$src$core$touch)for(let k=0;k{setTimeout(fireNow$$module$build$src$core$events$utils,0)})}catch(b){setTimeout(fireNow$$module$build$src$core$events$utils,0)}enqueueEvent$$module$build$src$core$events$utils(a)}}; -fireNow$$module$build$src$core$events$utils=function(){const a=filter$$module$build$src$core$events$utils(FIRE_QUEUE$$module$build$src$core$events$utils,!0);FIRE_QUEUE$$module$build$src$core$events$utils.length=0;for(const b of a){if(!b.workspaceId)continue;let c;null==(c=getWorkspaceById$$module$build$src$core$common(b.workspaceId))||c.fireChangeListener(b)}}; -enqueueEvent$$module$build$src$core$events$utils=function(a){if(isBlockChange$$module$build$src$core$events$predicates(a)&&"mutation"===a.element){let b;for(b=FIRE_QUEUE$$module$build$src$core$events$utils.length;0!d.isNull());b||a.reverse();return a};clearPendingUndo$$module$build$src$core$events$utils=function(){for(let a=0,b;b=FIRE_QUEUE$$module$build$src$core$events$utils[a];a++)b.recordUndo=!1};$.disable$$module$build$src$core$events$utils=function(){disabled$$module$build$src$core$events$utils++}; -$.enable$$module$build$src$core$events$utils=function(){disabled$$module$build$src$core$events$utils--};isEnabled$$module$build$src$core$events$utils=function(){return 0===disabled$$module$build$src$core$events$utils};$.getGroup$$module$build$src$core$events$utils=function(){return group$$module$build$src$core$events$utils};$.setGroup$$module$build$src$core$events$utils=function(a){TEST_ONLY$$module$build$src$core$events$utils.setGroupInternal(a)}; -setGroupInternal$$module$build$src$core$events$utils=function(a){group$$module$build$src$core$events$utils="boolean"===typeof a?a?genUid$$module$build$src$core$utils$idgenerator():"":a};getDescendantIds$$module$build$src$core$events$utils=function(a){const b=[];a=a.getDescendants(!1);for(let c=0,d;d=a[c];c++)b[c]=d.id;return b}; +fireNow$$module$build$src$core$events$utils=function(){const a=filter$$module$build$src$core$events$utils(FIRE_QUEUE$$module$build$src$core$events$utils);FIRE_QUEUE$$module$build$src$core$events$utils.length=0;for(const b of a){if(!b.workspaceId)continue;let c;(c=getWorkspaceById$$module$build$src$core$common(b.workspaceId))==null||c.fireChangeListener(b)}}; +enqueueEvent$$module$build$src$core$events$utils=function(a){if(isBlockChange$$module$build$src$core$events$predicates(a)&&a.element==="mutation"){let b;for(b=FIRE_QUEUE$$module$build$src$core$events$utils.length;b>0;b--){const c=FIRE_QUEUE$$module$build$src$core$events$utils[b-1];if(c.group!==a.group||c.workspaceId!==a.workspaceId||!isBlockMove$$module$build$src$core$events$predicates(c)||c.newParentId!==a.blockId)break}FIRE_QUEUE$$module$build$src$core$events$utils.splice(b,0,a)}else FIRE_QUEUE$$module$build$src$core$events$utils.push(a)}; +filter$$module$build$src$core$events$utils=function(a){const b=[];for(const c of a)if(a=b[b.length-1],!c.isNull())if(a&&a.workspaceId===c.workspaceId&&a.group===c.group)if(isBlockMove$$module$build$src$core$events$predicates(c)&&isBlockMove$$module$build$src$core$events$predicates(a)&&c.blockId===a.blockId){if(a.newParentId=c.newParentId,a.newInputName=c.newInputName,a.newCoordinate=c.newCoordinate,a.reason||c.reason){let d,e;a.reason=Array.from(new Set(((d=a.reason)!=null?d:[]).concat((e=c.reason)!= +null?e:[])))}}else isBlockChange$$module$build$src$core$events$predicates(c)&&isBlockChange$$module$build$src$core$events$predicates(a)&&c.blockId===a.blockId&&c.element===a.element&&c.name===a.name?a.newValue=c.newValue:isViewportChange$$module$build$src$core$events$predicates(c)&&isViewportChange$$module$build$src$core$events$predicates(a)?(a.viewTop=c.viewTop,a.viewLeft=c.viewLeft,a.scale=c.scale,a.oldScale=c.oldScale):isClick$$module$build$src$core$events$predicates(c)&&isBubbleOpen$$module$build$src$core$events$predicates(a)|| +b.push(c);else b.push(c);return a=b.filter(c=>!c.isNull())};clearPendingUndo$$module$build$src$core$events$utils=function(){for(let a=0,b;b=FIRE_QUEUE$$module$build$src$core$events$utils[a];a++)b.recordUndo=!1};$.disable$$module$build$src$core$events$utils=function(){disabled$$module$build$src$core$events$utils++};$.enable$$module$build$src$core$events$utils=function(){disabled$$module$build$src$core$events$utils--}; +isEnabled$$module$build$src$core$events$utils=function(){return disabled$$module$build$src$core$events$utils===0};$.getGroup$$module$build$src$core$events$utils=function(){return group$$module$build$src$core$events$utils};$.setGroup$$module$build$src$core$events$utils=function(a){TEST_ONLY$$module$build$src$core$events$utils.setGroupInternal(a)}; +setGroupInternal$$module$build$src$core$events$utils=function(a){group$$module$build$src$core$events$utils=typeof a==="boolean"?a?genUid$$module$build$src$core$utils$idgenerator():"":a};getDescendantIds$$module$build$src$core$events$utils=function(a){const b=[];a=a.getDescendants(!1);for(let c=0,d;d=a[c];c++)b[c]=d.id;return b}; fromJson$$module$build$src$core$events$utils=function(a,b){const c=get$$module$build$src$core$events$utils(a.type);if(!c)throw Error("Unknown event type.");return c.fromJson(a,b)};get$$module$build$src$core$events$utils=function(a){const b=getClass$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,a);if(!b)throw Error(`Event type ${a} not found in registry.`);return b}; disableOrphans$$module$build$src$core$events$utils=function(a){if((isBlockMove$$module$build$src$core$events$predicates(a)||isBlockCreate$$module$build$src$core$events$predicates(a))&&a.workspaceId){var b=getWorkspaceById$$module$build$src$core$common(a.workspaceId);if(!a.blockId)throw Error("Encountered a blockEvent without a proper blockId");if(a=b.getBlockById(a.blockId)){const c=recordUndo$$module$build$src$core$events$utils;try{recordUndo$$module$build$src$core$events$utils=!1;const d=a.getParent(); if(d&&!d.hasDisabledReason(ORPHANED_BLOCK_DISABLED_REASON$$module$build$src$core$events$utils)){const e=a.getDescendants(!1);for(let f=0,g;g=e[f];f++)g.setDisabledReason(!1,ORPHANED_BLOCK_DISABLED_REASON$$module$build$src$core$events$utils)}else if((a.outputConnection||a.previousConnection)&&!b.isDragging()){do a.setDisabledReason(!0,ORPHANED_BLOCK_DISABLED_REASON$$module$build$src$core$events$utils),a=a.getNextBlock();while(a)}}finally{recordUndo$$module$build$src$core$events$utils=c}}}}; -getWorkspaceById$$module$build$src$core$common=function(a){return WorkspaceDB_$$module$build$src$core$common[a]||null};getAllWorkspaces$$module$build$src$core$common=function(){const a=[];for(const b in WorkspaceDB_$$module$build$src$core$common)a.push(WorkspaceDB_$$module$build$src$core$common[b]);return a};registerWorkspace$$module$build$src$core$common=function(a){WorkspaceDB_$$module$build$src$core$common[a.id]=a};unregisterWorkpace$$module$build$src$core$common=function(a){delete WorkspaceDB_$$module$build$src$core$common[a.id]}; -getMainWorkspace$$module$build$src$core$common=function(){return mainWorkspace$$module$build$src$core$common};setMainWorkspace$$module$build$src$core$common=function(a){mainWorkspace$$module$build$src$core$common=a};getSelected$$module$build$src$core$common=function(){return selected$$module$build$src$core$common}; -$.setSelected$$module$build$src$core$common=function(a){if(selected$$module$build$src$core$common!==a){var b,c,d,e,f,g,h=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.SELECTED))(null!=(d=null==(b=selected$$module$build$src$core$common)?void 0:b.id)?d:null,null!=(e=null==a?void 0:a.id)?e:null,null!=(g=null!=(f=null==a?void 0:a.workspace.id)?f:null==(c=selected$$module$build$src$core$common)?void 0:c.workspace.id)?g:"");fire$$module$build$src$core$events$utils(h); -var k;null==(k=selected$$module$build$src$core$common)||k.unselect();selected$$module$build$src$core$common=a;var l;null==(l=selected$$module$build$src$core$common)||l.select()}};getParentContainer$$module$build$src$core$common=function(){return parentContainer$$module$build$src$core$common};setParentContainer$$module$build$src$core$common=function(a){parentContainer$$module$build$src$core$common=a}; -svgResize$$module$build$src$core$common=function(a){for(;a.options.parentWorkspace;)a=a.options.parentWorkspace;const b=a.getParentSvg(),c=a.getCachedParentSvgSize();var d=b.parentElement;if(d instanceof HTMLElement){var e=d.offsetWidth;d=d.offsetHeight;c.width!==e&&(b.setAttribute("width",e+"px"),a.setCachedParentSvgSize(e,null));c.height!==d&&(b.setAttribute("height",d+"px"),a.setCachedParentSvgSize(null,d));a.resize()}}; -getBlockTypeCounts$$module$build$src$core$common=function(a,b){const c=Object.create(null),d=a.getDescendants(!0);b&&(a=a.getNextBlock())&&(a=d.indexOf(a),d.splice(a,d.length-a));for(let e=0,f;f=d[e];e++)c[f.type]?c[f.type]++:c[f.type]=1;return c};jsonInitFactory$$module$build$src$core$common=function(a){return function(){this.jsonInit(a)}};defineBlocksWithJsonArray$$module$build$src$core$common=function(a){TEST_ONLY$$module$build$src$core$common.defineBlocksWithJsonArrayInternal(a)}; -defineBlocksWithJsonArrayInternal$$module$build$src$core$common=function(a){$.defineBlocks$$module$build$src$core$common($.createBlockDefinitionsFromJsonArray$$module$build$src$core$common(a))}; -$.createBlockDefinitionsFromJsonArray$$module$build$src$core$common=function(a){const b={};for(let c=0;c>>/g,a),content$$module$build$src$core$css="",a=document.createElement("style"),a.id="blockly-common-style",b=document.createTextNode(b),a.appendChild(b),document.head.insertBefore(a,document.head.firstChild)))}; createSvgElement$$module$build$src$core$utils$dom=function(a,b,c){a=document.createElementNS(SVG_NS$$module$build$src$core$utils$dom,`${a}`);for(const d in b)a.setAttribute(d,`${b[d]}`);c&&c.appendChild(a);return a};addClass$$module$build$src$core$utils$dom=function(a,b){b=b.split(" ");if(b.every(c=>a.classList.contains(c)))return!1;a.classList.add(...b);return!0};removeClasses$$module$build$src$core$utils$dom=function(a,b){a.classList.remove(...b.split(" "))}; removeClass$$module$build$src$core$utils$dom=function(a,b){b=b.split(" ");if(b.every(c=>!a.classList.contains(c)))return!1;a.classList.remove(...b);return!0};hasClass$$module$build$src$core$utils$dom=function(a,b){return a.classList.contains(b)};removeNode$$module$build$src$core$utils$dom=function(a){return a&&a.parentNode?a.parentNode.removeChild(a):null}; insertAfter$$module$build$src$core$utils$dom=function(a,b){const c=b.nextSibling;b=b.parentNode;if(!b)throw Error("Reference node has no parent.");c?b.insertBefore(a,c):b.appendChild(a)};setCssTransform$$module$build$src$core$utils$dom=function(a,b){a.style.transform=b;a.style["-webkit-transform"]=b}; startTextWidthCache$$module$build$src$core$utils$dom=function(){cacheReference$$module$build$src$core$utils$dom++;cacheWidths$$module$build$src$core$utils$dom||(cacheWidths$$module$build$src$core$utils$dom=Object.create(null))};stopTextWidthCache$$module$build$src$core$utils$dom=function(){cacheReference$$module$build$src$core$utils$dom--;cacheReference$$module$build$src$core$utils$dom||(cacheWidths$$module$build$src$core$utils$dom=null)}; -getTextWidth$$module$build$src$core$utils$dom=function(a){const b=a.textContent+"\n"+a.className.baseVal;let c;if(cacheWidths$$module$build$src$core$utils$dom&&(c=cacheWidths$$module$build$src$core$utils$dom[b]))return c;try{c=a.getComputedTextLength()}catch(d){return 8*a.textContent.length}cacheWidths$$module$build$src$core$utils$dom&&(cacheWidths$$module$build$src$core$utils$dom[b]=c);return c}; +getTextWidth$$module$build$src$core$utils$dom=function(a){const b=a.textContent+"\n"+a.className.baseVal;var c;if(cacheWidths$$module$build$src$core$utils$dom&&(c=cacheWidths$$module$build$src$core$utils$dom[b]))return c;c=window.getComputedStyle(a);c=getFastTextWidthWithSizeString$$module$build$src$core$utils$dom(a,c.fontSize,c.fontWeight,c.fontFamily);cacheWidths$$module$build$src$core$utils$dom&&(cacheWidths$$module$build$src$core$utils$dom[b]=c);return c}; getFastTextWidth$$module$build$src$core$utils$dom=function(a,b,c,d){return getFastTextWidthWithSizeString$$module$build$src$core$utils$dom(a,b+"pt",c,d)}; -getFastTextWidthWithSizeString$$module$build$src$core$utils$dom=function(a,b,c,d){const e=a.textContent;a=e+"\n"+a.className.baseVal;var f;if(cacheWidths$$module$build$src$core$utils$dom&&(f=cacheWidths$$module$build$src$core$utils$dom[a]))return f;canvasContext$$module$build$src$core$utils$dom||(f=document.createElement("canvas"),f.className="blocklyComputeCanvas",document.body.appendChild(f),canvasContext$$module$build$src$core$utils$dom=f.getContext("2d"));canvasContext$$module$build$src$core$utils$dom.font= -c+" "+b+" "+d;f=e?canvasContext$$module$build$src$core$utils$dom.measureText(e).width:0;cacheWidths$$module$build$src$core$utils$dom&&(cacheWidths$$module$build$src$core$utils$dom[a]=f);return f}; +getFastTextWidthWithSizeString$$module$build$src$core$utils$dom=function(a,b,c,d){const e=a.textContent;a=e+"\n"+a.className.baseVal;var f;if(cacheWidths$$module$build$src$core$utils$dom&&(f=cacheWidths$$module$build$src$core$utils$dom[a]))return f;canvasContext$$module$build$src$core$utils$dom||(f=document.createElement("canvas"),f.className="blocklyComputeCanvas",document.body.appendChild(f),canvasContext$$module$build$src$core$utils$dom=f.getContext("2d"));e&&canvasContext$$module$build$src$core$utils$dom? +(canvasContext$$module$build$src$core$utils$dom.font=c+" "+b+" "+d,f=canvasContext$$module$build$src$core$utils$dom.measureText(e).width):f=0;cacheWidths$$module$build$src$core$utils$dom&&(cacheWidths$$module$build$src$core$utils$dom[a]=f);return f}; measureFontMetrics$$module$build$src$core$utils$dom=function(a,b,c,d){const e=document.createElement("span");e.style.font=c+" "+b+" "+d;e.textContent=a;a=document.createElement("div");a.style.width="1px";a.style.height="0";b=document.createElement("div");b.style.display="flex";b.style.position="fixed";b.style.top="0";b.style.left="0";b.appendChild(e);b.appendChild(a);document.body.appendChild(b);c={height:0,baseline:0};try{b.style.alignItems="baseline",c.baseline=a.offsetTop-e.offsetTop,b.style.alignItems= -"flex-end",c.height=a.offsetTop-e.offsetTop}finally{document.body.removeChild(b)}return c};getSize$$module$build$src$core$utils$style=function(a){return TEST_ONLY$$module$build$src$core$utils$style.getSizeInternal(a)}; -getSizeInternal$$module$build$src$core$utils$style=function(a){if("none"!==getComputedStyle$$module$build$src$core$utils$style(a,"display"))return getSizeWithDisplay$$module$build$src$core$utils$style(a);const b=a.style,c=b.display,d=b.visibility,e=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";const f=a.offsetWidth;a=a.offsetHeight;b.display=c;b.position=e;b.visibility=d;return new Size$$module$build$src$core$utils$size(f,a)}; +"flex-end",c.height=a.offsetTop-e.offsetTop}finally{document.body.removeChild(b)}return c};$.getFocusManager$$module$build$src$core$focus_manager=function(){return FocusManager$$module$build$src$core$focus_manager.getFocusManager()};isFocusableNode$$module$build$src$core$interfaces$i_focusable_node=function(a){return a&&typeof a.getFocusableElement==="function"&&typeof a.getFocusableTree==="function"&&typeof a.onNodeFocus==="function"&&typeof a.onNodeBlur==="function"&&typeof a.canBeFocused==="function"}; +isSelectable$$module$build$src$core$interfaces$i_selectable=function(a){return isFocusableNode$$module$build$src$core$interfaces$i_focusable_node(a)&&typeof a.id==="string"&&typeof a.workspace==="object"&&typeof a.select==="function"&&typeof a.unselect==="function"}; +deepMerge$$module$build$src$core$utils$object=function(a,b){for(const c in b)b[c]!==null&&Array.isArray(b[c])?a[c]=deepMerge$$module$build$src$core$utils$object(a[c]||[],b[c]):a[c]=b[c]!==null&&typeof b[c]==="object"?deepMerge$$module$build$src$core$utils$object(a[c]||Object.create(null),b[c]):b[c];return a};getWorkspaceById$$module$build$src$core$common=function(a){return WorkspaceDB_$$module$build$src$core$common[a]||null}; +getAllWorkspaces$$module$build$src$core$common=function(){const a=[];for(const b in WorkspaceDB_$$module$build$src$core$common)a.push(WorkspaceDB_$$module$build$src$core$common[b]);return a};registerWorkspace$$module$build$src$core$common=function(a){WorkspaceDB_$$module$build$src$core$common[a.id]=a};unregisterWorkpace$$module$build$src$core$common=function(a){delete WorkspaceDB_$$module$build$src$core$common[a.id]};getMainWorkspace$$module$build$src$core$common=function(){return mainWorkspace$$module$build$src$core$common}; +setMainWorkspace$$module$build$src$core$common=function(a){mainWorkspace$$module$build$src$core$common=a};getSelected$$module$build$src$core$common=function(){const a=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode();return a&&isSelectable$$module$build$src$core$interfaces$i_selectable(a)?a:null};setSelected$$module$build$src$core$common=function(a){$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a)}; +fireSelectedEvent$$module$build$src$core$common=function(a){const b=getSelected$$module$build$src$core$common();let c,d,e,f;const g=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.SELECTED))((c=b==null?void 0:b.id)!=null?c:null,(d=a==null?void 0:a.id)!=null?d:null,(f=(e=a==null?void 0:a.workspace.id)!=null?e:b==null?void 0:b.workspace.id)!=null?f:"");fire$$module$build$src$core$events$utils(g)};getParentContainer$$module$build$src$core$common=function(){return parentContainer$$module$build$src$core$common}; +setParentContainer$$module$build$src$core$common=function(a){parentContainer$$module$build$src$core$common=a}; +svgResize$$module$build$src$core$common=function(a){for(;a.options.parentWorkspace;)a=a.options.parentWorkspace;const b=a.getParentSvg(),c=a.getCachedParentSvgSize();var d=b.parentElement;if(d instanceof HTMLElement){var e=d.offsetWidth;d=d.offsetHeight;c.width!==e&&(b.setAttribute("width",e+"px"),a.setCachedParentSvgSize(e,null));c.height!==d&&(b.setAttribute("height",d+"px"),a.setCachedParentSvgSize(null,d));a.resize()}}; +getBlockTypeCounts$$module$build$src$core$common=function(a,b){const c=Object.create(null),d=a.getDescendants(!0);b&&(a=a.getNextBlock())&&(a=d.indexOf(a),d.splice(a,d.length-a));for(let e=0,f;f=d[e];e++)c[f.type]?c[f.type]++:c[f.type]=1;return c};jsonInitFactory$$module$build$src$core$common=function(a){return function(){this.jsonInit(a)}};defineBlocksWithJsonArray$$module$build$src$core$common=function(a){TEST_ONLY$$module$build$src$core$common.defineBlocksWithJsonArrayInternal(a)}; +defineBlocksWithJsonArrayInternal$$module$build$src$core$common=function(a){$.defineBlocks$$module$build$src$core$common($.createBlockDefinitionsFromJsonArray$$module$build$src$core$common(a))}; +$.createBlockDefinitionsFromJsonArray$$module$build$src$core$common=function(a){const b={};for(let c=0;c>>/g,a),content$$module$build$src$core$css="",a=document.createElement("style"),a.id="blockly-common-style",b=document.createTextNode(b),a.appendChild(b),document.head.insertBefore(a,document.head.firstChild)))};getSize$$module$build$src$core$utils$style=function(a){return TEST_ONLY$$module$build$src$core$utils$style.getSizeInternal(a)}; +getSizeInternal$$module$build$src$core$utils$style=function(a){if(getComputedStyle$$module$build$src$core$utils$style(a,"display")!=="none")return getSizeWithDisplay$$module$build$src$core$utils$style(a);const b=a.style,c=b.display,d=b.visibility,e=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";const f=a.offsetWidth;a=a.offsetHeight;b.display=c;b.position=e;b.visibility=d;return new Size$$module$build$src$core$utils$size(f,a)}; getSizeWithDisplay$$module$build$src$core$utils$style=function(a){return new Size$$module$build$src$core$utils$size(a.offsetWidth,a.offsetHeight)};getComputedStyle$$module$build$src$core$utils$style=function(a,b){a=window.getComputedStyle(a);return a[b]||a.getPropertyValue(b)}; getPageOffset$$module$build$src$core$utils$style=function(a){const b=new Coordinate$$module$build$src$core$utils$coordinate(0,0);a=a.getBoundingClientRect();var c=document.documentElement;c=new Coordinate$$module$build$src$core$utils$coordinate(window.pageXOffset||c.scrollLeft,window.pageYOffset||c.scrollTop);b.x=a.left+c.x;b.y=a.top+c.y;return b}; getViewportPageOffset$$module$build$src$core$utils$style=function(){const a=document.body,b=document.documentElement;return new Coordinate$$module$build$src$core$utils$coordinate(a.scrollLeft||b.scrollLeft,a.scrollTop||b.scrollTop)}; @@ -127,28 +133,28 @@ screenToWsCoordinates$$module$build$src$core$utils$svg_math=function(a,b){var c= wsToScreenCoordinates$$module$build$src$core$utils$svg_math=function(a,b){var c=b.scale(a.scale);b=c.x;c=c.y;const d=a.getInjectionDiv().getBoundingClientRect();a=a.getOriginOffsetInPixels();return new Coordinate$$module$build$src$core$utils$coordinate(b+d.left+a.x,c+d.top+a.y)}; injectDependencies$$module$build$src$core$utils$xml=function(a){({document:document$$module$build$src$core$utils$xml=document$$module$build$src$core$utils$xml,DOMParser:DOMParser$$module$build$src$core$utils$xml=DOMParser$$module$build$src$core$utils$xml,XMLSerializer:XMLSerializer$$module$build$src$core$utils$xml=XMLSerializer$$module$build$src$core$utils$xml}=a);domParser$$module$build$src$core$utils$xml=new DOMParser$$module$build$src$core$utils$xml;xmlSerializer$$module$build$src$core$utils$xml= new XMLSerializer$$module$build$src$core$utils$xml};$.createElement$$module$build$src$core$utils$xml=function(a){return document$$module$build$src$core$utils$xml.createElementNS(NAME_SPACE$$module$build$src$core$utils$xml,a)};$.createTextNode$$module$build$src$core$utils$xml=function(a){return document$$module$build$src$core$utils$xml.createTextNode(a)}; -$.textToDom$$module$build$src$core$utils$xml=function(a){let b=domParser$$module$build$src$core$utils$xml.parseFromString(a,"text/xml");if(b&&b.documentElement&&!b.getElementsByTagName("parsererror").length)return b.documentElement;if((b=domParser$$module$build$src$core$utils$xml.parseFromString(a,"text/html"))&&b.body.firstChild&&"xml"===b.body.firstChild.nodeName.toLowerCase())return b.body.firstChild;throw Error(`DOMParser was unable to parse: ${a}`);}; +$.textToDom$$module$build$src$core$utils$xml=function(a){let b=domParser$$module$build$src$core$utils$xml.parseFromString(a,"text/xml");if(b&&b.documentElement&&!b.getElementsByTagName("parsererror").length)return b.documentElement;if((b=domParser$$module$build$src$core$utils$xml.parseFromString(a,"text/html"))&&b.body.firstChild&&b.body.firstChild.nodeName.toLowerCase()==="xml")return b.body.firstChild;throw Error(`DOMParser was unable to parse: ${a}`);}; domToText$$module$build$src$core$utils$xml=function(a){return sanitizeText$$module$build$src$core$utils$xml(xmlSerializer$$module$build$src$core$utils$xml.serializeToString(a))};sanitizeText$$module$build$src$core$utils$xml=function(a){return a.replace(INVALID_CONTROL_CHARS$$module$build$src$core$utils$xml,b=>`&#${b.charCodeAt(0)};`)}; -convertToolboxDefToJson$$module$build$src$core$utils$toolbox=function(a){if(!a)return null;if(a instanceof Element||"string"===typeof a)a=parseToolboxTree$$module$build$src$core$utils$toolbox(a),a=convertToToolboxJson$$module$build$src$core$utils$toolbox(a);validateToolbox$$module$build$src$core$utils$toolbox(a);return a}; +convertToolboxDefToJson$$module$build$src$core$utils$toolbox=function(a){if(!a)return null;if(a instanceof Element||typeof a==="string")a=parseToolboxTree$$module$build$src$core$utils$toolbox(a),a=convertToToolboxJson$$module$build$src$core$utils$toolbox(a);validateToolbox$$module$build$src$core$utils$toolbox(a);return a}; validateToolbox$$module$build$src$core$utils$toolbox=function(a){const b=a.kind;a=a.contents;if(b&&b!==FLYOUT_TOOLBOX_KIND$$module$build$src$core$utils$toolbox&&b!==CATEGORY_TOOLBOX_KIND$$module$build$src$core$utils$toolbox)throw Error("Invalid toolbox kind "+b+". Please supply either "+FLYOUT_TOOLBOX_KIND$$module$build$src$core$utils$toolbox+" or "+CATEGORY_TOOLBOX_KIND$$module$build$src$core$utils$toolbox);if(!a)throw Error("Toolbox must have a contents attribute.");}; -convertFlyoutDefToJsonArray$$module$build$src$core$utils$toolbox=function(a){return a?a.contents?a.contents:Array.isArray(a)&&0"CATEGORY"===c.kind.toUpperCase()).length};isCategoryCollapsible$$module$build$src$core$utils$toolbox=function(a){return a&&a.contents?!!a.contents.filter(function(b){return"CATEGORY"===b.kind.toUpperCase()}).length:!1}; +convertFlyoutDefToJsonArray$$module$build$src$core$utils$toolbox=function(a){return a?a.contents?a.contents:Array.isArray(a)&&a.length>0&&!a[0].nodeType?a:xmlToJsonArray$$module$build$src$core$utils$toolbox(a):[]};hasCategories$$module$build$src$core$utils$toolbox=function(a){return TEST_ONLY$$module$build$src$core$utils$toolbox.hasCategoriesInternal(a)}; +hasCategoriesInternal$$module$build$src$core$utils$toolbox=function(a){if(!a)return!1;const b=a.kind;return b?b===CATEGORY_TOOLBOX_KIND$$module$build$src$core$utils$toolbox:!!a.contents.filter(c=>c.kind.toUpperCase()==="CATEGORY").length};isCategoryCollapsible$$module$build$src$core$utils$toolbox=function(a){return a&&a.contents?!!a.contents.filter(function(b){return b.kind.toUpperCase()==="CATEGORY"}).length:!1}; convertToToolboxJson$$module$build$src$core$utils$toolbox=function(a){const b={contents:xmlToJsonArray$$module$build$src$core$utils$toolbox(a)};a instanceof Node&&addAttributes$$module$build$src$core$utils$toolbox(a,b);return b}; -xmlToJsonArray$$module$build$src$core$utils$toolbox=function(a){const b=[];let c=a.childNodes;c||(c=a);for(let d=0,e;e=c[d];d++){if(!e.tagName)continue;a={};const f=e.tagName.toUpperCase();a.kind=f;"BLOCK"===f?a.blockxml=e:e.childNodes&&00&&(a.contents=xmlToJsonArray$$module$build$src$core$utils$toolbox(e));addAttributes$$module$build$src$core$utils$toolbox(e,a);b.push(a)}return b}; addAttributes$$module$build$src$core$utils$toolbox=function(a,b){for(let c=0;c document.");}else a instanceof Element&&(b=a);return b}; +parseToolboxTree$$module$build$src$core$utils$toolbox=function(a){let b=null;if(a)if(typeof a==="string"){if(b=$.textToDom$$module$build$src$core$utils$xml(a),b.nodeName.toLowerCase()!=="xml")throw TypeError("Toolbox should be an document.");}else a instanceof Element&&(b=a);return b}; getStartPositionRect$$module$build$src$core$positionable_helpers=function(a,b,c,d,e,f){const g=f.scrollbar&&f.scrollbar.canScrollVertically();a.horizontal===horizontalPosition$$module$build$src$core$positionable_helpers.LEFT?(c=e.absoluteMetrics.left+c,g&&f.RTL&&(c+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness)):(c=e.absoluteMetrics.left+e.viewMetrics.width-b.width-c,g&&!f.RTL&&(c-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness));a.vertical===verticalPosition$$module$build$src$core$positionable_helpers.TOP? a=e.absoluteMetrics.top+d:(a=e.absoluteMetrics.top+e.viewMetrics.height-b.height-d,f.scrollbar&&f.scrollbar.canScrollHorizontally()&&(a-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness));return new Rect$$module$build$src$core$utils$rect(a,a+b.height,c,c+b.width)}; getCornerOppositeToolbox$$module$build$src$core$positionable_helpers=function(a,b){return{horizontal:b.toolboxMetrics.position===Position$$module$build$src$core$utils$toolbox.LEFT||a.horizontalLayout&&!a.RTL?horizontalPosition$$module$build$src$core$positionable_helpers.RIGHT:horizontalPosition$$module$build$src$core$positionable_helpers.LEFT,vertical:b.toolboxMetrics.position===Position$$module$build$src$core$utils$toolbox.BOTTOM?verticalPosition$$module$build$src$core$positionable_helpers.TOP:verticalPosition$$module$build$src$core$positionable_helpers.BOTTOM}}; bumpPositionRect$$module$build$src$core$positionable_helpers=function(a,b,c,d){const e=a.left,f=a.right-a.left,g=a.bottom-a.top;for(let h=0;hf.id!==a.id).map(f=>f.getRelativeToSurfaceXY());for(;commentOverlapsOtherExactly$$module$build$src$core$clipboard$workspace_comment_paster(Coordinate$$module$build$src$core$utils$coordinate.sum(c,d),e);)d.translate(b.RTL?-30:30,30);a.moveTo(Coordinate$$module$build$src$core$utils$coordinate.sum(c, -d))};commentOverlapsOtherExactly$$module$build$src$core$clipboard$workspace_comment_paster=function(a,b){return b.some(c=>1>=Math.abs(c.x-a.x)&&1>=Math.abs(c.y-a.y))};setRole$$module$build$src$core$utils$aria=function(a,b){a.setAttribute(ROLE_ATTRIBUTE$$module$build$src$core$utils$aria,b)};setState$$module$build$src$core$utils$aria=function(a,b,c){Array.isArray(c)&&(c=c.join(" "));a.setAttribute(ARIA_PREFIX$$module$build$src$core$utils$aria+b,`${c}`)}; -isSerializable$$module$build$src$core$interfaces$i_serializable=function(a){return void 0!==a.saveState&&void 0!==a.loadState}; +d))};commentOverlapsOtherExactly$$module$build$src$core$clipboard$workspace_comment_paster=function(a,b){return b.some(c=>Math.abs(c.x-a.x)<=1&&Math.abs(c.y-a.y)<=1)};setRole$$module$build$src$core$utils$aria=function(a,b){a.setAttribute(ROLE_ATTRIBUTE$$module$build$src$core$utils$aria,b)};setState$$module$build$src$core$utils$aria=function(a,b,c){Array.isArray(c)&&(c=c.join(" "));a.setAttribute(ARIA_PREFIX$$module$build$src$core$utils$aria+b,`${c}`)}; +isSerializable$$module$build$src$core$interfaces$i_serializable=function(a){return a&&typeof a.saveState==="function"&&typeof a.loadState==="function"}; queueRender$$module$build$src$core$render_management=function(a){queueBlock$$module$build$src$core$render_management(a);if(alwaysImmediatelyRender$$module$build$src$core$render_management())return doRenders$$module$build$src$core$render_management(),Promise.resolve();afterRendersPromise$$module$build$src$core$render_management||(afterRendersPromise$$module$build$src$core$render_management=new Promise(b=>{afterRendersResolver$$module$build$src$core$render_management=b;animationRequestId$$module$build$src$core$render_management= window.requestAnimationFrame(()=>{doRenders$$module$build$src$core$render_management();b()})}));return afterRendersPromise$$module$build$src$core$render_management};finishQueuedRenders$$module$build$src$core$render_management=function(){return afterRendersPromise$$module$build$src$core$render_management?afterRendersPromise$$module$build$src$core$render_management:Promise.resolve()}; triggerQueuedRenders$$module$build$src$core$render_management=function(a){a||window.cancelAnimationFrame(animationRequestId$$module$build$src$core$render_management);doRenders$$module$build$src$core$render_management(a);!a&&afterRendersResolver$$module$build$src$core$render_management&&afterRendersResolver$$module$build$src$core$render_management()};alwaysImmediatelyRender$$module$build$src$core$render_management=function(){return JavaFx$$module$build$src$core$utils$useragent}; @@ -156,46 +162,54 @@ queueBlock$$module$build$src$core$render_management=function(a){dirtyBlocks$$mod doRenders$$module$build$src$core$render_management=function(a){const b=a?new Set([a]):new Set([...rootBlocks$$module$build$src$core$render_management].map(f=>f.workspace)),c=[...rootBlocks$$module$build$src$core$render_management].filter(shouldRenderRootBlock$$module$build$src$core$render_management).filter(f=>b.has(f.workspace));for(var d of c)renderBlock$$module$build$src$core$render_management(d);for(const f of b)f.resizeContents();for(var e of c)d=e.getRelativeToSurfaceXY(),e.updateComponentLocations(d); for(const f of c)e=$.getGroup$$module$build$src$core$events$utils(),(d=eventGroups$$module$build$src$core$render_management.get(f))&&$.setGroup$$module$build$src$core$events$utils(d),f.bumpNeighbours(),$.setGroup$$module$build$src$core$events$utils(e);for(const f of c)dequeueBlock$$module$build$src$core$render_management(f);a||(afterRendersPromise$$module$build$src$core$render_management=null)}; dequeueBlock$$module$build$src$core$render_management=function(a){rootBlocks$$module$build$src$core$render_management.delete(a);dirtyBlocks$$module$build$src$core$render_management.delete(a);eventGroups$$module$build$src$core$render_management.delete(a);for(const b of a.getChildren(!1))dequeueBlock$$module$build$src$core$render_management(b)};shouldRenderRootBlock$$module$build$src$core$render_management=function(a){return!a.isDisposed()&&!a.getParent()}; -renderBlock$$module$build$src$core$render_management=function(a){if(dirtyBlocks$$module$build$src$core$render_management.has(a)&&a.initialized){for(const b of a.getChildren(!1))renderBlock$$module$build$src$core$render_management(b);a.renderEfficiently()}};alert$$module$build$src$core$dialog=function(a,b){alertImplementation$$module$build$src$core$dialog(a,b)};setAlert$$module$build$src$core$dialog=function(a){alertImplementation$$module$build$src$core$dialog=a}; -confirm$$module$build$src$core$dialog=function(a,b){TEST_ONLY$$module$build$src$core$dialog.confirmInternal(a,b)};confirmInternal$$module$build$src$core$dialog=function(a,b){confirmImplementation$$module$build$src$core$dialog(a,b)};setConfirm$$module$build$src$core$dialog=function(a){confirmImplementation$$module$build$src$core$dialog=a};prompt$$module$build$src$core$dialog=function(a,b,c){promptImplementation$$module$build$src$core$dialog(a,b,c)}; -setPrompt$$module$build$src$core$dialog=function(a){promptImplementation$$module$build$src$core$dialog=a};isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks=function(a){return void 0!==a.getProcedureDef};isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks=function(a){return void 0!==a.getProcedureCall&&void 0!==a.renameProcedure}; -isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model=function(a){return void 0!==a.getVariableModel};$.allUsedVarModels$$module$build$src$core$variables=function(a){a=a.getAllBlocks(!1);const b=new Set;for(let c=0;c1'),d.appendChild(c),b.push(d));if(Blocks$$module$build$src$core$blocks.variables_get){a.sort(VariableModel$$module$build$src$core$variable_model.compareByName); +renderBlock$$module$build$src$core$render_management=function(a){if(dirtyBlocks$$module$build$src$core$render_management.has(a)&&a.initialized){for(const b of a.getChildren(!1))renderBlock$$module$build$src$core$render_management(b);a.renderEfficiently()}};alert$$module$build$src$core$dialog=function(a,b){alertImplementation$$module$build$src$core$dialog(a,b)}; +setAlert$$module$build$src$core$dialog=function(a=defaultAlert$$module$build$src$core$dialog){alertImplementation$$module$build$src$core$dialog=a};confirm$$module$build$src$core$dialog=function(a,b){confirmImplementation$$module$build$src$core$dialog(a,b)};setConfirm$$module$build$src$core$dialog=function(a=defaultConfirm$$module$build$src$core$dialog){confirmImplementation$$module$build$src$core$dialog=a}; +prompt$$module$build$src$core$dialog=function(a,b,c){promptImplementation$$module$build$src$core$dialog(a,b,c)};setPrompt$$module$build$src$core$dialog=function(a=defaultPrompt$$module$build$src$core$dialog){promptImplementation$$module$build$src$core$dialog=a};toast$$module$build$src$core$dialog=function(a,b){toastImplementation$$module$build$src$core$dialog(a,b)}; +setToast$$module$build$src$core$dialog=function(a=defaultToast$$module$build$src$core$dialog){toastImplementation$$module$build$src$core$dialog=a};isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks=function(a){return a&&typeof a.getProcedureDef==="function"};isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks=function(a){return a&&typeof a.getProcedureCall==="function"&&typeof a.renameProcedure==="function"}; +isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model=function(a){return a.getVariableModel!==void 0};warn$$module$build$src$core$utils$deprecation=function(a,b,c,d){a=a+" was deprecated in "+b+" and will be deleted in "+c+".";d&&(a+="\nUse "+d+" instead.");previousWarnings$$module$build$src$core$utils$deprecation.has(a)||(previousWarnings$$module$build$src$core$utils$deprecation.add(a),console.warn(a))}; +$.allUsedVarModels$$module$build$src$core$variables=function(a){a=a.getAllBlocks(!1);const b=new Set;for(let c=0;c({kind:"block",type:d,gap:8,fields:generateVariableFieldJson$$module$build$src$core$variables(g)})));return a}; +xmlFlyoutCategory$$module$build$src$core$variables=function(a){let b=[];const c=document.createElement("button");c.setAttribute("text","%{BKY_NEW_VARIABLE}");c.setAttribute("callbackKey","CREATE_VARIABLE");a.registerButtonCallback("CREATE_VARIABLE",function(d){createVariableButtonHandler$$module$build$src$core$variables(d.getTargetWorkspace())});b.push(c);a=flyoutCategoryBlocks$$module$build$src$core$variables(a);return b=b.concat(a)}; +flyoutCategoryBlocks$$module$build$src$core$variables=function(a){a=a.getVariableMap().getVariablesOfType("");const b=[];if(a.length>0){var c=a[a.length-1];if(Blocks$$module$build$src$core$blocks.variables_set){var d=$.createElement$$module$build$src$core$utils$xml("block");d.setAttribute("type","variables_set");d.setAttribute("gap",Blocks$$module$build$src$core$blocks.math_change?"8":"24");d.appendChild(generateVariableFieldDom$$module$build$src$core$variables(c));b.push(d)}Blocks$$module$build$src$core$blocks.math_change&& +(d=$.createElement$$module$build$src$core$utils$xml("block"),d.setAttribute("type","math_change"),d.setAttribute("gap",Blocks$$module$build$src$core$blocks.variables_get?"20":"8"),d.appendChild(generateVariableFieldDom$$module$build$src$core$variables(c)),c=$.textToDom$$module$build$src$core$utils$xml('1'),d.appendChild(c),b.push(d));if(Blocks$$module$build$src$core$blocks.variables_get){a.sort(compareByName$$module$build$src$core$variables); for(let e=0,f;f=a[e];e++)c=$.createElement$$module$build$src$core$utils$xml("block"),c.setAttribute("type","variables_get"),c.setAttribute("gap","8"),c.appendChild(generateVariableFieldDom$$module$build$src$core$variables(f)),b.push(c)}}return b};generateUniqueName$$module$build$src$core$variables=function(a){return TEST_ONLY$$module$build$src$core$variables.generateUniqueNameInternal(a)}; -generateUniqueNameInternal$$module$build$src$core$variables=function(a){return generateUniqueNameFromOptions$$module$build$src$core$variables(VAR_LETTER_OPTIONS$$module$build$src$core$variables.charAt(0),a.getAllVariableNames())}; +generateUniqueNameInternal$$module$build$src$core$variables=function(a){return generateUniqueNameFromOptions$$module$build$src$core$variables(VAR_LETTER_OPTIONS$$module$build$src$core$variables.charAt(0),a.getVariableMap().getAllVariables().map(b=>b.getName()))}; generateUniqueNameFromOptions$$module$build$src$core$variables=function(a,b){if(!b.length)return a;const c=VAR_LETTER_OPTIONS$$module$build$src$core$variables;let d="",e=c.indexOf(a);for(;;){let f=!1;for(let g=0;gf.getVariableModel().name);if(d&&(c=d.some(f=>f.toLowerCase()===a),d=d.some(f=>f.toLowerCase()===b),c&&d))return e.getName()}return null}; +createVariableButtonHandler$$module$build$src$core$variables=function(a,b,c){function d(f){promptName$$module$build$src$core$variables($.Msg$$module$build$src$core$msg.NEW_VARIABLE_TITLE,f,function(g){if(g){var h=nameUsedWithAnyType$$module$build$src$core$variables(g,a);if(h){if(h.getType()===e)var k=$.Msg$$module$build$src$core$msg.VARIABLE_ALREADY_EXISTS.replace("%1",h.getName());else k=$.Msg$$module$build$src$core$msg.VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE,k=k.replace("%1",h.getName()).replace("%2", +h.getType());alert$$module$build$src$core$dialog(k,function(){d(g)})}else a.getVariableMap().createVariable(g,e),b&&b(g)}else b&&b(null)})}const e=c||"";d("")}; +$.renameVariable$$module$build$src$core$variables=function(a,b,c){function d(e){const f=$.Msg$$module$build$src$core$msg.RENAME_VARIABLE_TITLE.replace("%1",b.getName());promptName$$module$build$src$core$variables(f,e,function(g){if(g){var h=nameUsedWithOtherType$$module$build$src$core$variables(g,b.getType(),a),k=nameUsedWithConflictingParam$$module$build$src$core$variables(b.getName(),g,a);if(h||k){var l="";h?l=$.Msg$$module$build$src$core$msg.VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE.replace("%1", +h.getName()).replace("%2",h.getType()):k&&(l=$.Msg$$module$build$src$core$msg.VARIABLE_ALREADY_EXISTS_FOR_A_PARAMETER.replace("%1",g).replace("%2",k));alert$$module$build$src$core$dialog(l,function(){d(g)})}else a.getVariableMap().renameVariable(b,g),c&&c(g)}else c&&c(null)})}d("")}; +promptName$$module$build$src$core$variables=function(a,b,c){prompt$$module$build$src$core$dialog(a,b,function(d){d&&(d=d.replace(/[\s\xa0]+/g," ").trim(),d===$.Msg$$module$build$src$core$msg.RENAME_VARIABLE||d===$.Msg$$module$build$src$core$msg.NEW_VARIABLE)&&(d=null);c(d)})};nameUsedWithOtherType$$module$build$src$core$variables=function(a,b,c){c=c.getVariableMap().getAllVariables();a=a.toLowerCase();for(let d=0,e;e=c[d];d++)if(e.getName().toLowerCase()===a&&e.getType()!==b)return e;return null}; +nameUsedWithAnyType$$module$build$src$core$variables=function(a,b){b=b.getVariableMap().getAllVariables();a=a.toLowerCase();for(let c=0,d;d=b[c];c++)if(d.getName().toLowerCase()===a)return d;return null};nameUsedWithConflictingParam$$module$build$src$core$variables=function(a,b,c){return c.getProcedureMap().getProcedures().length?checkForConflictingParamWithProcedureModels$$module$build$src$core$variables(a,b,c):checkForConflictingParamWithLegacyProcedures$$module$build$src$core$variables(a,b,c)}; +checkForConflictingParamWithProcedureModels$$module$build$src$core$variables=function(a,b,c){a=a.toLowerCase();b=b.toLowerCase();c=c.getProcedureMap().getProcedures();for(const e of c){var d=e.getParameters().filter(isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model).map(f=>f.getVariableModel().getName());if(d&&(c=d.some(f=>f.toLowerCase()===a),d=d.some(f=>f.toLowerCase()===b),c&&d))return e.getName()}return null}; checkForConflictingParamWithLegacyProcedures$$module$build$src$core$variables=function(a,b,c){a=a.toLowerCase();b=b.toLowerCase();c=c.getAllBlocks(!1);for(const e of c){if(!isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(e))continue;c=e.getProcedureDef();var d=c[1];const f=d.some(g=>g.toLowerCase()===a);d=d.some(g=>g.toLowerCase()===b);if(f&&d)return c[0]}return null}; -generateVariableFieldDom$$module$build$src$core$variables=function(a){const b=$.createElement$$module$build$src$core$utils$xml("field");b.setAttribute("name","VAR");b.setAttribute("id",a.getId());b.setAttribute("variabletype",a.type);a=$.createTextNode$$module$build$src$core$utils$xml(a.name);b.appendChild(a);return b}; +generateVariableFieldDom$$module$build$src$core$variables=function(a){const b=$.createElement$$module$build$src$core$utils$xml("field");b.setAttribute("name","VAR");b.setAttribute("id",a.getId());b.setAttribute("variabletype",a.getType());a=$.createTextNode$$module$build$src$core$utils$xml(a.getName());b.appendChild(a);return b}; $.getOrCreateVariablePackage$$module$build$src$core$variables=function(a,b,c,d){let e=$.getVariable$$module$build$src$core$variables(a,b,c,d);e||(e=createVariable$$module$build$src$core$variables(a,b,c,d));return e}; -$.getVariable$$module$build$src$core$variables=function(a,b,c,d){const e=a.getPotentialVariableMap();let f=null;if(b&&(f=a.getVariableById(b),!f&&e&&(f=e.getVariableById(b)),f))return f;if(c){if(void 0===d)throw Error("Tried to look up a variable by name without a type");f=a.getVariable(c,d);!f&&e&&(f=e.getVariable(c,d))}return f}; -createVariable$$module$build$src$core$variables=function(a,b,c,d){const e=a.getPotentialVariableMap();c||(c=generateUniqueName$$module$build$src$core$variables(a.isFlyout?a.targetWorkspace:a));return e?e.createVariable(c,d,b):a.createVariable(c,d,b)};getAddedVariables$$module$build$src$core$variables=function(a,b){a=a.getAllVariables();const c=[];if(b.length!==a.length)for(let d=0;d=0;f--){const g=e[f];if(g.type==="procedures_defnoreturn"||g.type==="procedures_defreturn"){c=String(g.getFieldValue("NAME"));d=$.Msg$$module$build$src$core$msg.CANNOT_DELETE_VARIABLE_PROCEDURE.replace("%1",d).replace("%2",c);alert$$module$build$src$core$dialog(d);return}g===c&&e.splice(f,1)}c&&e.length||e.length>1?(d= +$.Msg$$module$build$src$core$msg.DELETE_VARIABLE_CONFIRMATION.replace("%1",String(e.length+(c&&!c.workspace.isFlyout?1:0))).replace("%2",d),confirm$$module$build$src$core$dialog(d,f=>{f&&b&&a.getVariableMap().deleteVariable(b)})):a.getVariableMap().deleteVariable(b)}; save$$module$build$src$core$serialization$blocks=function(a,{addCoordinates:b=!1,addInputBlocks:c=!0,addNextBlocks:d=!0,doFullSerialization:e=!0,saveIds:f=!0}={}){if(a.isInsertionMarker())return null;const g={type:a.type,id:f?a.id:void 0};b&&saveCoords$$module$build$src$core$serialization$blocks(a,g);saveAttributes$$module$build$src$core$serialization$blocks(a,g);saveExtraState$$module$build$src$core$serialization$blocks(a,g,e);saveIcons$$module$build$src$core$serialization$blocks(a,g,e);saveFields$$module$build$src$core$serialization$blocks(a, g,e);c&&saveInputBlocks$$module$build$src$core$serialization$blocks(a,g,e,f);d&&saveNextBlocks$$module$build$src$core$serialization$blocks(a,g,e,f);return g}; -saveAttributes$$module$build$src$core$serialization$blocks=function(a,b){a.isCollapsed()&&(b.collapsed=!0);a.isEnabled()||(b.disabledReasons=Array.from(a.getDisabledReasons()));a.isOwnDeletable()||(b.deletable=!1);a.isOwnMovable()||(b.movable=!1);a.isOwnEditable()||(b.editable=!1);void 0!==a.inputsInline&&a.inputsInline!==a.inputsInlineDefault&&(b.inline=a.inputsInline);a.data&&(b.data=a.data)}; -saveCoords$$module$build$src$core$serialization$blocks=function(a,b){const c=a.workspace;a=a.getRelativeToSurfaceXY();b.x=Math.round(c.RTL?c.getWidth()-a.x:a.x);b.y=Math.round(a.y)};saveExtraState$$module$build$src$core$serialization$blocks=function(a,b,c){a.saveExtraState?(a=a.saveExtraState(c),null!==a&&(b.extraState=a)):a.mutationToDom&&(a=a.mutationToDom(),null!==a&&(b.extraState=domToText$$module$build$src$core$xml(a).replace(' xmlns="https://developers.google.com/blockly/xml"',"")))}; -saveIcons$$module$build$src$core$serialization$blocks=function(a,b,c){const d=Object.create(null);for(const e of a.getIcons())isSerializable$$module$build$src$core$interfaces$i_serializable(e)&&(a=e.saveState(c))&&(d[e.getType().toString()]=a);Object.keys(d).length&&(b.icons=d)}; -saveFields$$module$build$src$core$serialization$blocks=function(a,b,c){const d=Object.create(null);for(let e=0;e{k.disposed||k.setConnectionTracking(!0)}, -1)}return h}; +appendInternal$$module$build$src$core$serialization$blocks=function(a,b,{parentConnection:c,isShadow:d=!1,recordUndo:e=!1}={}){const f=getRecordUndo$$module$build$src$core$events$utils();$.setRecordUndo$$module$build$src$core$events$utils(e);(e=$.getGroup$$module$build$src$core$events$utils())||$.setGroup$$module$build$src$core$events$utils(!0);$.disable$$module$build$src$core$events$utils();const g=b.getVariableMap().getAllVariables();let h;try{h=appendPrivate$$module$build$src$core$serialization$blocks(a, +b,{parentConnection:c,isShadow:d})}finally{$.enable$$module$build$src$core$events$utils()}checkNewVariables$$module$build$src$core$serialization$blocks(b,g);isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CREATE))(h));$.setGroup$$module$build$src$core$events$utils(e);$.setRecordUndo$$module$build$src$core$events$utils(f);if(b.rendered){const k=h;setTimeout(()=> +{k.disposed||k.setConnectionTracking(!0)},1)}return h}; appendPrivate$$module$build$src$core$serialization$blocks=function(a,b,{parentConnection:c,isShadow:d=!1}={}){if(!a.type)throw new MissingBlockType$$module$build$src$core$serialization$exceptions(a);const e=b.newBlock(a.type,a.id);e.setShadow(d);loadCoords$$module$build$src$core$serialization$blocks(e,a);loadAttributes$$module$build$src$core$serialization$blocks(e,a);loadExtraState$$module$build$src$core$serialization$blocks(e,a);tryToConnectParent$$module$build$src$core$serialization$blocks(c,e, a);loadIcons$$module$build$src$core$serialization$blocks(e,a);loadFields$$module$build$src$core$serialization$blocks(e,a);loadInputBlocks$$module$build$src$core$serialization$blocks(e,a);loadNextBlocks$$module$build$src$core$serialization$blocks(e,a);initBlock$$module$build$src$core$serialization$blocks(e,b.rendered);return e}; checkNewVariables$$module$build$src$core$serialization$blocks=function(a,b){if(isEnabled$$module$build$src$core$events$utils())for(a=getAddedVariables$$module$build$src$core$variables(a,b),b=0;bb&&(b=c[d].length);var e=-Infinity;let f,g=1;do{d=e;f=a;a=[];e=c.length/g;let h=1;for(let k=0;kd);return f}; -wrapScore$$module$build$src$core$utils$string=function(a,b,c){const d=[0],e=[];for(var f=0;f1&&d[d.length-1]<=d[d.length-2]&&(b+=.5);return b}; wrapMutate$$module$build$src$core$utils$string=function(a,b,c){let d=wrapScore$$module$build$src$core$utils$string(a,b,c),e;for(let f=0;fd&&(d=h,e=g)}return e?wrapMutate$$module$build$src$core$utils$string(a,e,c):b}; -wrapToText$$module$build$src$core$utils$string=function(a,b){const c=[];for(let d=0;dc+window.scrollY&&(e-=containerDiv$$module$build$src$core$tooltip.offsetHeight+ 2*OFFSET_Y$$module$build$src$core$tooltip);a?d=Math.max(MARGINS$$module$build$src$core$tooltip-window.scrollX,d):d+containerDiv$$module$build$src$core$tooltip.offsetWidth>b+window.scrollX-2*MARGINS$$module$build$src$core$tooltip&&(d=b-containerDiv$$module$build$src$core$tooltip.offsetWidth-2*MARGINS$$module$build$src$core$tooltip);return{x:d,y:e}}; show$$module$build$src$core$tooltip=function(){if(!blocked$$module$build$src$core$tooltip&&(poisonedElement$$module$build$src$core$tooltip=element$$module$build$src$core$tooltip,containerDiv$$module$build$src$core$tooltip)){containerDiv$$module$build$src$core$tooltip.textContent="";renderContent$$module$build$src$core$tooltip();var a=element$$module$build$src$core$tooltip.RTL;containerDiv$$module$build$src$core$tooltip.style.direction=a?"rtl":"ltr";containerDiv$$module$build$src$core$tooltip.style.display= "block";visible$$module$build$src$core$tooltip=!0;var {x:b,y:c}=getPosition$$module$build$src$core$tooltip(a);containerDiv$$module$build$src$core$tooltip.style.left=b+"px";containerDiv$$module$build$src$core$tooltip.style.top=c+"px"}};getHsvSaturation$$module$build$src$core$utils$colour=function(){return hsvSaturation$$module$build$src$core$utils$colour};setHsvSaturation$$module$build$src$core$utils$colour=function(a){hsvSaturation$$module$build$src$core$utils$colour=a}; getHsvValue$$module$build$src$core$utils$colour=function(){return hsvValue$$module$build$src$core$utils$colour};setHsvValue$$module$build$src$core$utils$colour=function(a){hsvValue$$module$build$src$core$utils$colour=a}; -parse$$module$build$src$core$utils$colour=function(a){a=`${a}`.toLowerCase().trim();var b=names$$module$build$src$core$utils$colour[a];if(b)return b;b="0x"===a.substring(0,2)?"#"+a.substring(2):a;b="#"===b[0]?b:"#"+b;if(/^#[0-9a-f]{6}$/.test(b))return b;if(/^#[0-9a-f]{3}$/.test(b))return["#",b[1],b[1],b[2],b[2],b[3],b[3]].join("");var c=a.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);return c&&(a=Number(c[1]),b=Number(c[2]),c=Number(c[3]),0<=a&&256>a&&0<=b&&256>b&&0<=c&&256>c)?rgbToHex$$module$build$src$core$utils$colour(a, -b,c):null};rgbToHex$$module$build$src$core$utils$colour=function(a,b,c){b=a<<16|b<<8|c;return 16>a?"#"+(16777216|b).toString(16).substr(1):"#"+b.toString(16)};hexToRgb$$module$build$src$core$utils$colour=function(a){a=parse$$module$build$src$core$utils$colour(a);if(!a)return[0,0,0];a=parseInt(a.substr(1),16);return[a>>16,a>>8&255,a&255]}; -hsvToHex$$module$build$src$core$utils$colour=function(a,b,c){let d=0,e=0,f=0;if(0===b)f=e=d=c;else{const g=Math.floor(a/60),h=a/60-g;a=c*(1-b);const k=c*(1-b*h);b=c*(1-b*(1-h));switch(g){case 1:d=k;e=c;f=a;break;case 2:d=a;e=c;f=b;break;case 3:d=a;e=k;f=c;break;case 4:d=b;e=a;f=c;break;case 5:d=c;e=a;f=k;break;case 6:case 0:d=c,e=b,f=a}}return rgbToHex$$module$build$src$core$utils$colour(Math.floor(d),Math.floor(e),Math.floor(f))}; +parse$$module$build$src$core$utils$colour=function(a){a=`${a}`.toLowerCase().trim();var b=names$$module$build$src$core$utils$colour[a];if(b)return b;b=a.substring(0,2)==="0x"?"#"+a.substring(2):a;b=b[0]==="#"?b:"#"+b;if(/^#[0-9a-f]{6}$/.test(b))return b;if(/^#[0-9a-f]{3}$/.test(b))return["#",b[1],b[1],b[2],b[2],b[3],b[3]].join("");var c=a.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);return c&&(a=Number(c[1]),b=Number(c[2]),c=Number(c[3]),a>=0&&a<256&&b>=0&&b<256&&c>=0&&c<256)?rgbToHex$$module$build$src$core$utils$colour(a, +b,c):null};rgbToHex$$module$build$src$core$utils$colour=function(a,b,c){b=a<<16|b<<8|c;return a<16?"#"+(16777216|b).toString(16).substr(1):"#"+b.toString(16)};hexToRgb$$module$build$src$core$utils$colour=function(a){a=parse$$module$build$src$core$utils$colour(a);if(!a)return[0,0,0];a=parseInt(a.substr(1),16);return[a>>16,a>>8&255,a&255]}; +hsvToHex$$module$build$src$core$utils$colour=function(a,b,c){let d=0,e=0,f=0;if(b===0)f=e=d=c;else{const g=Math.floor(a/60),h=a/60-g;a=c*(1-b);const k=c*(1-b*h);b=c*(1-b*(1-h));switch(g){case 1:d=k;e=c;f=a;break;case 2:d=a;e=c;f=b;break;case 3:d=a;e=k;f=c;break;case 4:d=b;e=a;f=c;break;case 5:d=c;e=a;f=k;break;case 6:case 0:d=c,e=b,f=a}}return rgbToHex$$module$build$src$core$utils$colour(Math.floor(d),Math.floor(e),Math.floor(f))}; blend$$module$build$src$core$utils$colour=function(a,b,c){a=parse$$module$build$src$core$utils$colour(a);if(!a)return null;b=parse$$module$build$src$core$utils$colour(b);if(!b)return null;a=hexToRgb$$module$build$src$core$utils$colour(a);b=hexToRgb$$module$build$src$core$utils$colour(b);return rgbToHex$$module$build$src$core$utils$colour(Math.round(b[0]+c*(a[0]-b[0])),Math.round(b[1]+c*(a[1]-b[1])),Math.round(b[2]+c*(a[2]-b[2])))}; -hueToHex$$module$build$src$core$utils$colour=function(a){return hsvToHex$$module$build$src$core$utils$colour(a,hsvSaturation$$module$build$src$core$utils$colour,255*hsvValue$$module$build$src$core$utils$colour)}; -tokenizeInterpolationInternal$$module$build$src$core$utils$parsing=function(a,b,c){const d=[];var e=a.split("");e.push("");var f=0;a=[];let g=null;for(let l=0;l=h?(f=2,g=h,(h=a.join(""))&&d.push(h),a.length=0):"{"===h?f=3:(a.push("%",h),f=0);else if(2===f)if("0"<=h&&"9">= -h)g+=h;else{var k=void 0;d.push(parseInt(null!=(k=g)?k:"",10));l--;f=0}else 3===f&&(""===h?(a.splice(0,0,"%{"),l--,f=0):"}"!==h?a.push(h):(f=a.join(""),/[A-Z]\w*/i.test(f)?(h=f.toUpperCase(),(h=h.startsWith("BKY_")?h.substring(4):null)&&h in $.Msg$$module$build$src$core$msg?(f=$.Msg$$module$build$src$core$msg[h],"string"===typeof f?Array.prototype.push.apply(d,tokenizeInterpolationInternal$$module$build$src$core$utils$parsing(f,b,c)):b?d.push(`${f}`):d.push(f)):d.push("%{"+f+"}")):d.push("%{"+f+"}"), -f=a.length=0))}(b=a.join(""))&&d.push(b);k=[];a.length=0;for(e=0;e=c)return{hue:c,hex:hsvToHex$$module$build$src$core$utils$colour(c,getHsvSaturation$$module$build$src$core$utils$colour(),255*getHsvValue$$module$build$src$core$utils$colour())};if(c=parse$$module$build$src$core$utils$colour(b))return{hue:null,hex:c};c='Invalid colour: "'+b+'"';a!==b&&(c+=' (from "'+ -a+'")');throw Error(c);};getDiv$$module$build$src$core$widgetdiv=function(){return containerDiv$$module$build$src$core$widgetdiv};testOnly_setDiv$$module$build$src$core$widgetdiv=function(a){containerDiv$$module$build$src$core$widgetdiv=a;if(null===a){let b;null==(b=document.querySelector("."+containerClassName$$module$build$src$core$widgetdiv))||b.remove()}}; -createDom$$module$build$src$core$widgetdiv=function(){const a=getParentContainer$$module$build$src$core$common()||document.body;document.querySelector("."+containerClassName$$module$build$src$core$widgetdiv)?containerDiv$$module$build$src$core$widgetdiv=document.querySelector("."+containerClassName$$module$build$src$core$widgetdiv):(containerDiv$$module$build$src$core$widgetdiv=document.createElement("div"),containerDiv$$module$build$src$core$widgetdiv.className=containerClassName$$module$build$src$core$widgetdiv); -a.appendChild(containerDiv$$module$build$src$core$widgetdiv)}; -show$$module$build$src$core$widgetdiv=function(a,b,c,d){hide$$module$build$src$core$widgetdiv();owner$$module$build$src$core$widgetdiv=a;dispose$$module$build$src$core$widgetdiv=c;if(c=containerDiv$$module$build$src$core$widgetdiv){c.style.direction=b?"rtl":"ltr";c.style.display="block";if(!d&&a instanceof Field$$module$build$src$core$field){let g;d=null==(g=a.getSourceBlock())?void 0:g.workspace}var e;ownerWorkspace$$module$build$src$core$widgetdiv=null!=(e=d)?e:null;var f;a=null!=(f=d)?f:getMainWorkspace$$module$build$src$core$common(); -rendererClassName$$module$build$src$core$widgetdiv=a.getRenderer().getClassName();themeClassName$$module$build$src$core$widgetdiv=a.getTheme().getClassName();rendererClassName$$module$build$src$core$widgetdiv&&addClass$$module$build$src$core$utils$dom(c,rendererClassName$$module$build$src$core$widgetdiv);themeClassName$$module$build$src$core$widgetdiv&&addClass$$module$build$src$core$utils$dom(c,themeClassName$$module$build$src$core$widgetdiv)}}; -hide$$module$build$src$core$widgetdiv=function(){if(isVisible$$module$build$src$core$widgetdiv()){owner$$module$build$src$core$widgetdiv=null;var a=containerDiv$$module$build$src$core$widgetdiv;a&&(a.style.display="none",a.style.left="",a.style.top="",dispose$$module$build$src$core$widgetdiv&&dispose$$module$build$src$core$widgetdiv(),dispose$$module$build$src$core$widgetdiv=null,a.textContent="",rendererClassName$$module$build$src$core$widgetdiv&&(removeClass$$module$build$src$core$utils$dom(a,rendererClassName$$module$build$src$core$widgetdiv), -rendererClassName$$module$build$src$core$widgetdiv=""),themeClassName$$module$build$src$core$widgetdiv&&(removeClass$$module$build$src$core$utils$dom(a,themeClassName$$module$build$src$core$widgetdiv),themeClassName$$module$build$src$core$widgetdiv=""),getMainWorkspace$$module$build$src$core$common().markFocused())}};isVisible$$module$build$src$core$widgetdiv=function(){return!!owner$$module$build$src$core$widgetdiv}; -hideIfOwner$$module$build$src$core$widgetdiv=function(a){owner$$module$build$src$core$widgetdiv===a&&hide$$module$build$src$core$widgetdiv()};hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv=function(a){null!==ownerWorkspace$$module$build$src$core$widgetdiv&&ownerWorkspace$$module$build$src$core$widgetdiv!==a||hide$$module$build$src$core$widgetdiv()}; +hueToHex$$module$build$src$core$utils$colour=function(a){return hsvToHex$$module$build$src$core$utils$colour(a,hsvSaturation$$module$build$src$core$utils$colour,hsvValue$$module$build$src$core$utils$colour*255)}; +tokenizeInterpolationInternal$$module$build$src$core$utils$parsing=function(a,b,c){const d=[];var e=a.split("");e.push("");var f=0;a=[];let g=null;for(let l=0;le?positionInternal$$module$build$src$core$widgetdiv(a,0,c.height+e):positionInternal$$module$build$src$core$widgetdiv(a,e,c.height)};calculateX$$module$build$src$core$widgetdiv=function(a,b,c,d){return d?Math.min(Math.max(b.right-c.width,a.left),a.right-c.width):Math.max(Math.min(b.left,a.right-c.width),a.left)}; -calculateY$$module$build$src$core$widgetdiv=function(a,b,c){return b.bottom+c.height>=a.bottom?b.top-c.height:b.bottom};isRepositionable$$module$build$src$core$widgetdiv=function(a){return!(null==a||!a.repositionForWindowResize)};repositionForWindowResize$$module$build$src$core$widgetdiv=function(){isRepositionable$$module$build$src$core$widgetdiv(owner$$module$build$src$core$widgetdiv)&&owner$$module$build$src$core$widgetdiv.repositionForWindowResize()||hide$$module$build$src$core$widgetdiv()}; +positionWithAnchor$$module$build$src$core$widgetdiv=function(a,b,c,d){const e=calculateY$$module$build$src$core$widgetdiv(a,b,c);a=calculateX$$module$build$src$core$widgetdiv(a,b,c,d);e<0?positionInternal$$module$build$src$core$widgetdiv(a,0,c.height+e):positionInternal$$module$build$src$core$widgetdiv(a,e,c.height)};calculateX$$module$build$src$core$widgetdiv=function(a,b,c,d){return d?Math.min(Math.max(b.right-c.width,a.left),a.right-c.width):Math.max(Math.min(b.left,a.right-c.width),a.left)}; +calculateY$$module$build$src$core$widgetdiv=function(a,b,c){return b.bottom+c.height>=a.bottom?b.top-c.height:b.bottom};isRepositionable$$module$build$src$core$widgetdiv=function(a){return!(a==null||!a.repositionForWindowResize)};repositionForWindowResize$$module$build$src$core$widgetdiv=function(){isRepositionable$$module$build$src$core$widgetdiv(owner$$module$build$src$core$widgetdiv)&&owner$$module$build$src$core$widgetdiv.repositionForWindowResize()||hide$$module$build$src$core$widgetdiv()}; getCurrentBlock$$module$build$src$core$contextmenu=function(){return currentBlock$$module$build$src$core$contextmenu};setCurrentBlock$$module$build$src$core$contextmenu=function(a){currentBlock$$module$build$src$core$contextmenu=a}; -show$$module$build$src$core$contextmenu=function(a,b,c,d){show$$module$build$src$core$widgetdiv(dummyOwner$$module$build$src$core$contextmenu,c,dispose$$module$build$src$core$contextmenu,d);if(b.length){var e=populate_$$module$build$src$core$contextmenu(b,c,a);menu_$$module$build$src$core$contextmenu=e;position_$$module$build$src$core$contextmenu(e,a,c);setTimeout(function(){e.focus()},1);currentBlock$$module$build$src$core$contextmenu=null}else hide$$module$build$src$core$contextmenu()}; -populate_$$module$build$src$core$contextmenu=function(a,b,c){const d=new Menu$$module$build$src$core$menu;d.setRole(Role$$module$build$src$core$utils$aria.MENU);for(let e=0;e{setTimeout(()=>{f.callback(f.scope, -c)},0)})},{})}return d};position_$$module$build$src$core$contextmenu=function(a,b,c){const d=getViewportBBox$$module$build$src$core$utils$svg_math();b=new Rect$$module$build$src$core$utils$rect(b.clientY+d.top,b.clientY+d.top,b.clientX+d.left,b.clientX+d.left);createWidget_$$module$build$src$core$contextmenu(a);const e=a.getSize();c&&(b.left+=e.width,b.right+=e.width,d.left+=e.width,d.right+=e.width);positionWithAnchor$$module$build$src$core$widgetdiv(d,b,e,c);a.focus()}; +show$$module$build$src$core$contextmenu=function(a,b,c,d,e){show$$module$build$src$core$widgetdiv(dummyOwner$$module$build$src$core$contextmenu,c,dispose$$module$build$src$core$contextmenu,d);if(b.length){e||(a instanceof PointerEvent?e=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY):(console.warn("Context menu opened with keyboard but no location given"),e=new Coordinate$$module$build$src$core$utils$coordinate(0,0)));var f=populate_$$module$build$src$core$contextmenu(b, +c,a,e);menu_$$module$build$src$core$contextmenu=f;position_$$module$build$src$core$contextmenu(f,c,e);setTimeout(function(){f.focus()},1);currentBlock$$module$build$src$core$contextmenu=null}else hide$$module$build$src$core$contextmenu()}; +populate_$$module$build$src$core$contextmenu=function(a,b,c,d){const e=new Menu$$module$build$src$core$menu;e.setRole(Role$$module$build$src$core$utils$aria.MENU);for(let f=0;f{setTimeout(()=>{g.callback(g.scope,c,l,d)},0)})},{})}return e}; +position_$$module$build$src$core$contextmenu=function(a,b,c){const d=getViewportBBox$$module$build$src$core$utils$svg_math();c=new Rect$$module$build$src$core$utils$rect(c.y+d.top,c.y+d.top,c.x+d.left,c.x+d.left);createWidget_$$module$build$src$core$contextmenu(a);const e=a.getSize();b&&(c.left+=e.width,c.right+=e.width,d.left+=e.width,d.right+=e.width);positionWithAnchor$$module$build$src$core$widgetdiv(d,c,e,b);a.focus()}; createWidget_$$module$build$src$core$contextmenu=function(a){var b=getDiv$$module$build$src$core$widgetdiv();if(!b)throw Error("Attempting to create a context menu when widget div is null");b=a.render(b);addClass$$module$build$src$core$utils$dom(b,"blocklyContextMenu");conditionalBind$$module$build$src$core$browser_events(b,"contextmenu",null,haltPropagation$$module$build$src$core$contextmenu);a.focus()};haltPropagation$$module$build$src$core$contextmenu=function(a){a.preventDefault();a.stopPropagation()}; -hide$$module$build$src$core$contextmenu=function(){hideIfOwner$$module$build$src$core$widgetdiv(dummyOwner$$module$build$src$core$contextmenu);currentBlock$$module$build$src$core$contextmenu=null};dispose$$module$build$src$core$contextmenu=function(){menu_$$module$build$src$core$contextmenu&&(menu_$$module$build$src$core$contextmenu.dispose(),menu_$$module$build$src$core$contextmenu=null)}; -$.callbackFactory$$module$build$src$core$contextmenu=function(a,b){return()=>{$.disable$$module$build$src$core$events$utils();let c;try{c=b instanceof Element?domToBlockInternal$$module$build$src$core$xml(b,a.workspace):appendInternal$$module$build$src$core$serialization$blocks(b,a.workspace);const d=a.getRelativeToSurfaceXY();d.x=a.RTL?d.x-$.config$$module$build$src$core$config.snapRadius:d.x+$.config$$module$build$src$core$config.snapRadius;d.y+=2*$.config$$module$build$src$core$config.snapRadius; -c.moveBy(d.x,d.y)}finally{$.enable$$module$build$src$core$events$utils()}isEnabled$$module$build$src$core$events$utils()&&!c.isShadow()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CREATE))(c));$.setSelected$$module$build$src$core$common(c);return c}}; +hide$$module$build$src$core$contextmenu=function(){hideIfOwner$$module$build$src$core$widgetdiv(dummyOwner$$module$build$src$core$contextmenu);currentBlock$$module$build$src$core$contextmenu=null;let a;(a=menu_$$module$build$src$core$contextmenu)==null||a.dispose();menu_$$module$build$src$core$contextmenu=null}; +dispose$$module$build$src$core$contextmenu=function(){menu_$$module$build$src$core$contextmenu&&(menu_$$module$build$src$core$contextmenu.dispose(),menu_$$module$build$src$core$contextmenu=null)}; +$.callbackFactory$$module$build$src$core$contextmenu=function(a,b){return()=>{$.disable$$module$build$src$core$events$utils();let c;try{c=b instanceof Element?domToBlockInternal$$module$build$src$core$xml(b,a.workspace):appendInternal$$module$build$src$core$serialization$blocks(b,a.workspace);const d=a.getRelativeToSurfaceXY();d.x=a.RTL?d.x-$.config$$module$build$src$core$config.snapRadius:d.x+$.config$$module$build$src$core$config.snapRadius;d.y+=$.config$$module$build$src$core$config.snapRadius* +2;c.moveBy(d.x,d.y)}finally{$.enable$$module$build$src$core$events$utils()}isEnabled$$module$build$src$core$events$utils()&&!c.isShadow()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CREATE))(c));$.getFocusManager$$module$build$src$core$focus_manager().focusNode(c);return c}};getMenu$$module$build$src$core$contextmenu=function(){return menu_$$module$build$src$core$contextmenu}; mouseToWorkspacePoint$$module$build$src$core$utils$drag=function(a,b){b=mouseToSvg$$module$build$src$core$browser_events(b,a.getParentSvg(),a.getInverseScreenCTM());b.x/=a.scale;b.y/=a.scale;return b};start$$module$build$src$core$utils$drag=function(a,b,c){b=mouseToWorkspacePoint$$module$build$src$core$utils$drag(a,b);workspaceToDragDelta$$module$build$src$core$utils$drag.set(a,Coordinate$$module$build$src$core$utils$coordinate.difference(c,b))}; move$$module$build$src$core$utils$drag=function(a,b){b=mouseToWorkspacePoint$$module$build$src$core$utils$drag(a,b);a=workspaceToDragDelta$$module$build$src$core$utils$drag.get(a);if(!a)throw Error("Drag not initialized");return Coordinate$$module$build$src$core$utils$coordinate.sum(a,b)}; workspaceToDom$$module$build$src$core$xml=function(a,b=!1){const c=$.createElement$$module$build$src$core$utils$xml("xml");var d=variablesToDom$$module$build$src$core$xml($.allUsedVarModels$$module$build$src$core$variables(a));d.hasChildNodes()&&c.appendChild(d);for(const e of a.getTopComments())c.appendChild(saveWorkspaceComment$$module$build$src$core$xml(e,b));a=a.getTopBlocks(!0);for(d=0;d/g,"<$1$2>")}; -domToPrettyText$$module$build$src$core$xml=function(a){a=domToText$$module$build$src$core$xml(a).split("<");let b="";for(let c=1;c"!==d.slice(-2)&&(b+=" ")}a=a.join("\n");a=a.replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1");return a.replace(/^\n/,"")}; +f=e.getBubbleSize(),g=e.bubbleIsVisible();e=e.getBubbleLocation();var h=$.createElement$$module$build$src$core$utils$xml("comment");h.appendChild($.createTextNode$$module$build$src$core$utils$xml(d));h.setAttribute("pinned",`${g}`);h.setAttribute("h",`${f.height}`);h.setAttribute("w",`${f.width}`);e&&(h.setAttribute("x",`${a.workspace.RTL?a.workspace.getWidth()-(e.x+f.width):e.x}`),h.setAttribute("y",`${e.y}`));c.appendChild(h)}a.data&&(d=$.createElement$$module$build$src$core$utils$xml("data"),d.appendChild($.createTextNode$$module$build$src$core$utils$xml(a.data)), +c.appendChild(d));for(d=0;d/g,"<$1$2>")}; +domToPrettyText$$module$build$src$core$xml=function(a){a=domToText$$module$build$src$core$xml(a).split("<");let b="";for(let c=1;c"&&(b+=" ")}a=a.join("\n");a=a.replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1");return a.replace(/^\n/,"")}; clearWorkspaceAndLoadFromXml$$module$build$src$core$xml=function(a,b){b.setResizesEnabled(!1);b.clear();a=$.domToWorkspace$$module$build$src$core$xml(a,b);b.setResizesEnabled(!0);return a}; -$.domToWorkspace$$module$build$src$core$xml=function(a,b){let c=0;b.RTL&&(c=b.getWidth());const d=[];startTextWidthCache$$module$build$src$core$utils$dom();const e=$.getGroup$$module$build$src$core$events$utils();e||$.setGroup$$module$build$src$core$events$utils(!0);b.setResizesEnabled&&b.setResizesEnabled(!1);let f=!0;try{for(let g=0,h;h=a.childNodes[g];g++){const k=h.nodeName.toLowerCase(),l=h;if("block"===k||"shadow"===k&&!getRecordUndo$$module$build$src$core$events$utils()){const m=domToBlockInternal$$module$build$src$core$xml(l, -b);d.push(m.id);let n;const p=parseInt(null!=(n=l.getAttribute("x"))?n:"10",10);let q;const r=parseInt(null!=(q=l.getAttribute("y"))?q:"10",10);isNaN(p)||isNaN(r)||m.moveBy(b.RTL?c-p:p,r,["create"]);f=!1}else{if("shadow"===k)throw TypeError("Shadow block cannot be a top-level block.");if("comment"===k)loadWorkspaceComment$$module$build$src$core$xml(l,b);else if("variables"===k){if(f)domToVariables$$module$build$src$core$xml(l,b);else throw Error("'variables' tag must exist once before block and shadow tag elements in the workspace XML, but it was found in another location."); +$.domToWorkspace$$module$build$src$core$xml=function(a,b){let c=0;b.RTL&&(c=b.getWidth());const d=[];startTextWidthCache$$module$build$src$core$utils$dom();const e=$.getGroup$$module$build$src$core$events$utils();e||$.setGroup$$module$build$src$core$events$utils(!0);b.setResizesEnabled&&b.setResizesEnabled(!1);let f=!0;try{for(let g=0,h;h=a.childNodes[g];g++){const k=h.nodeName.toLowerCase(),l=h;if(k==="block"||k==="shadow"&&!getRecordUndo$$module$build$src$core$events$utils()){const m=domToBlockInternal$$module$build$src$core$xml(l, +b);d.push(m.id);let n;const p=parseInt((n=l.getAttribute("x"))!=null?n:"10",10);let r;const q=parseInt((r=l.getAttribute("y"))!=null?r:"10",10);isNaN(p)||isNaN(q)||m.moveBy(b.RTL?c-p:p,q,["create"]);f=!1}else{if(k==="shadow")throw TypeError("Shadow block cannot be a top-level block.");if(k==="comment")loadWorkspaceComment$$module$build$src$core$xml(l,b);else if(k==="variables"){if(f)domToVariables$$module$build$src$core$xml(l,b);else throw Error("'variables' tag must exist once before block and shadow tag elements in the workspace XML, but it was found in another location."); f=!1}}}}finally{$.setGroup$$module$build$src$core$events$utils(e),b.setResizesEnabled&&b.setResizesEnabled(!0),b.rendered&&triggerQueuedRenders$$module$build$src$core$render_management(),stopTextWidthCache$$module$build$src$core$utils$dom()}fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.FINISHED_LOADING))(b));return d}; -loadWorkspaceComment$$module$build$src$core$xml=function(a,b){var c;const d=null!=(c=a.getAttribute("id"))?c:void 0;c=b.rendered?new RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment(b,d):new WorkspaceComment$$module$build$src$core$comments$workspace_comment(b,d);var e;c.setText(null!=(e=a.textContent)?e:"");var f;e=parseInt(null!=(f=a.getAttribute("x"))?f:"",10);let g;f=parseInt(null!=(g=a.getAttribute("y"))?g:"",10);isNaN(e)||isNaN(f)||(e=b.RTL?b.getWidth()-e:e, -c.moveTo(new Coordinate$$module$build$src$core$utils$coordinate(e,f)));var h;b=parseInt(null!=(h=a.getAttribute("w"))?h:"",10);let k;h=parseInt(null!=(k=a.getAttribute("h"))?k:"",10);isNaN(b)||isNaN(h)||c.setSize(new Size$$module$build$src$core$utils$size(b,h));"true"===a.getAttribute("collapsed")&&c.setCollapsed(!0);"false"===a.getAttribute("editable")&&c.setEditable(!1);"false"===a.getAttribute("movable")&&c.setMovable(!1);"false"===a.getAttribute("deletable")&&c.setDeletable(!1);return c}; +loadWorkspaceComment$$module$build$src$core$xml=function(a,b){var c;const d=(c=a.getAttribute("id"))!=null?c:void 0;c=b.rendered?new RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment(b,d):new WorkspaceComment$$module$build$src$core$comments$workspace_comment(b,d);var e;c.setText((e=a.textContent)!=null?e:"");var f;e=parseInt((f=a.getAttribute("x"))!=null?f:"",10);let g;f=parseInt((g=a.getAttribute("y"))!=null?g:"",10);isNaN(e)||isNaN(f)||(e=b.RTL?b.getWidth()-e:e, +c.moveTo(new Coordinate$$module$build$src$core$utils$coordinate(e,f)));var h;b=parseInt((h=a.getAttribute("w"))!=null?h:"",10);let k;h=parseInt((k=a.getAttribute("h"))!=null?k:"",10);isNaN(b)||isNaN(h)||c.setSize(new Size$$module$build$src$core$utils$size(b,h));a.getAttribute("collapsed")==="true"&&c.setCollapsed(!0);a.getAttribute("editable")==="false"&&c.setEditable(!1);a.getAttribute("movable")==="false"&&c.setMovable(!1);a.getAttribute("deletable")==="false"&&c.setDeletable(!1);return c}; appendDomToWorkspace$$module$build$src$core$xml=function(a,b){if(!b.getBlocksBoundingBox)return $.domToWorkspace$$module$build$src$core$xml(a,b);var c=b.getBlocksBoundingBox();a=$.domToWorkspace$$module$build$src$core$xml(a,b);if(c&&c.top!==c.bottom){var d=c.bottom;c=b.RTL?c.right:c.left;var e=Infinity;let f=-Infinity,g=Infinity;for(let h=0;hf&&(f=k.x)}d=d-g+10;c=b.RTL?c-f:c-e;for(e=0;e=0;g--)f[g].initSvg();for(let g=f.length-1;g>=0;g--)f[g].queueRender();setTimeout(function(){e.disposed||e.setConnectionTracking(!0)},1);b.resizeContents()}else{const e=d.getDescendants(!1); +for(let f=e.length-1;f>=0;f--)e[f].initModel()}}finally{$.enable$$module$build$src$core$events$utils()}if(isEnabled$$module$build$src$core$events$utils()){a=getAddedVariables$$module$build$src$core$variables(b,c);for(b=0;bl.setBubbleVisible(f), -1)}};applyDataTagNodes$$module$build$src$core$xml=function(a,b){for(let c=0;ce});disposeUiStep$$module$build$src$core$block_animations(e,{x:d.x,y:d.y,width:a.width,height:a.height},b.RTL,new Date)}}; -disposeUiStep$$module$build$src$core$block_animations=function(a,b,c,d){const e=((new Date).getTime()-d.getTime())/150;1c)){var d=b.getSvgXY(a.getSvgRoot());a.outputConnection?(d.x+=(a.RTL?3:-3)*c,d.y+=13*c):a.previousConnection&&(d.x+=(a.RTL?-23:23)*c,d.y+=3*c);var e=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE,{cx:d.x,cy:d.y,r:0,fill:"none",stroke:"#888","stroke-width":10},b.getParentSvg());a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.ANIMATE, -{id:"animationCircle",begin:"indefinite",attributeName:"r",dur:"150ms",from:0,to:25*c},e);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.ANIMATE,{id:"animationOpacity",begin:"indefinite",attributeName:"opacity",dur:"150ms",from:1,to:0},e);a.beginElement();b.beginElement();setTimeout(()=>void removeNode$$module$build$src$core$utils$dom(e),150)}}; -disconnectUiEffect$$module$build$src$core$block_animations=function(a){disconnectUiStop$$module$build$src$core$block_animations();a.workspace.getAudioManager().play("disconnect");if(!(1>a.workspace.scale)){var b=a.getHeightWidth().height;b=Math.atan(10/b)/Math.PI*180;a.RTL||(b*=-1);wobblingBlock$$module$build$src$core$block_animations=a;disconnectUiStep$$module$build$src$core$block_animations(a,b,new Date,0)}}; -disconnectUiStep$$module$build$src$core$block_animations=function(a,b,c,d){const e=[.66,1,.66,0,-.66,-1,-.66,0];let f="";c.getTime()+200>(new Date).getTime()&&(f=`skewX(${Math.round(e[d%e.length]*b)})`,disconnectPid$$module$build$src$core$block_animations=setTimeout(disconnectUiStep$$module$build$src$core$block_animations,15,a,b,c,d+1));a.getSvgRoot().setAttribute("transform",`${a.getTranslation()} ${f}`)}; -disconnectUiStop$$module$build$src$core$block_animations=function(){wobblingBlock$$module$build$src$core$block_animations&&(disconnectPid$$module$build$src$core$block_animations&&(clearTimeout(disconnectPid$$module$build$src$core$block_animations),disconnectPid$$module$build$src$core$block_animations=null),wobblingBlock$$module$build$src$core$block_animations.getSvgRoot().setAttribute("transform",wobblingBlock$$module$build$src$core$block_animations.getTranslation()),wobblingBlock$$module$build$src$core$block_animations= -null)};isDraggable$$module$build$src$core$interfaces$i_draggable=function(a){return void 0!==a.getRelativeToSurfaceXY&&void 0!==a.isMovable&&void 0!==a.startDrag&&void 0!==a.drag&&void 0!==a.endDrag&&void 0!==a.revertDrag};deepMerge$$module$build$src$core$utils$object=function(a,b){for(const c in b)a[c]=null!==b[c]&&"object"===typeof b[c]?deepMerge$$module$build$src$core$utils$object(a[c]||Object.create(null),b[c]):b[c];return a}; -register$$module$build$src$core$field_registry=function(a,b){register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FIELD,a,b)};unregister$$module$build$src$core$field_registry=function(a){unregister$$module$build$src$core$registry(Type$$module$build$src$core$registry.FIELD,a)};$.fromJson$$module$build$src$core$field_registry=function(a){return TEST_ONLY$$module$build$src$core$field_registry.fromJsonInternal(a)}; +applyCommentTagNodes$$module$build$src$core$xml=function(a,b){for(let c=0;c{isNaN(n)||isNaN(r)||(n=b.workspace.RTL?b.workspace.getWidth()-(n+h):n,q.setBubbleLocation(new Coordinate$$module$build$src$core$utils$coordinate(n,r)));q.setBubbleVisible(f)},1)}};applyDataTagNodes$$module$build$src$core$xml=function(a,b){for(let c=0;c100)){var b=a.workspace,c=a.getSvgRoot();b.getAudioManager().play("delete");var d=a.getRelativeToSurfaceXY(),e=c.cloneNode(!0);e.setAttribute("transform","translate("+d.x+","+d.y+")");var f;(f=b.getLayerManager())==null||f.appendToAnimationLayer({getSvgRoot:()=>e});disposeUiStep$$module$build$src$core$block_animations(e,{x:d.x,y:d.y,width:a.width,height:a.height},b.RTL,new Date)}}; +disposeUiStep$$module$build$src$core$block_animations=function(a,b,c,d){const e=((new Date).getTime()-d.getTime())/150;e>1?removeNode$$module$build$src$core$utils$dom(a):(a.setAttribute("transform","translate("+(b.x+(c?-1:1)*b.width/2*e)+","+(b.y+b.height/2*e)+") scale("+(1-e)+")"),setTimeout(disposeUiStep$$module$build$src$core$block_animations,10,a,b,c,d))}; +connectionUiEffect$$module$build$src$core$block_animations=function(a){var b=a.workspace;const c=b.scale;b.getAudioManager().play("click");if(!(c<1)){var d=b.getSvgXY(a.getSvgRoot());a.outputConnection?(d.x+=(a.RTL?3:-3)*c,d.y+=13*c):a.previousConnection&&(d.x+=(a.RTL?-23:23)*c,d.y+=3*c);var e=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE,{cx:d.x,cy:d.y,r:0,fill:"none",stroke:"#888","stroke-width":10},b.getParentSvg());a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.ANIMATE, +{id:"animationCircle",begin:"indefinite",attributeName:"r",dur:"150ms",from:0,to:25*c},e);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.ANIMATE,{id:"animationOpacity",begin:"indefinite",attributeName:"opacity",dur:"150ms",from:1,to:0},e);a.beginElement();b.beginElement();setTimeout(()=>void removeNode$$module$build$src$core$utils$dom(e),150)}}; +disconnectUiEffect$$module$build$src$core$block_animations=function(a){disconnectUiStop$$module$build$src$core$block_animations();a.workspace.getAudioManager().play("disconnect");if(!(a.workspace.scale<1)){var b=a.getHeightWidth().height;b=Math.atan(10/b)/Math.PI*180;a.RTL||(b*=-1);wobblingBlock$$module$build$src$core$block_animations=a;disconnectUiStep$$module$build$src$core$block_animations(a,b,new Date,0)}}; +disconnectUiStep$$module$build$src$core$block_animations=function(a,b,c,d){const e=[.66,1,.66,0,-.66,-1,-.66,0];let f="";c.getTime()+200>(new Date).getTime()&&(f=`skewX(${Math.round(e[d%e.length]*b)})`,disconnectPid$$module$build$src$core$block_animations=setTimeout(disconnectUiStep$$module$build$src$core$block_animations,15,a,b,c,d+1));a.getSvgRoot().setAttribute("transform",`${a.getTranslation()} ${f}`)}; +disconnectUiStop$$module$build$src$core$block_animations=function(){wobblingBlock$$module$build$src$core$block_animations&&(disconnectPid$$module$build$src$core$block_animations&&(clearTimeout(disconnectPid$$module$build$src$core$block_animations),disconnectPid$$module$build$src$core$block_animations=null),wobblingBlock$$module$build$src$core$block_animations.getSvgRoot().setAttribute("transform",wobblingBlock$$module$build$src$core$block_animations.getTranslation()),wobblingBlock$$module$build$src$core$block_animations= +null)}; +moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster=function(a,b){a.workspace.RTL&&(b.x=a.workspace.getWidth()-b.x);const c=a.workspace,d=$.config$$module$build$src$core$config.snapRadius,e=Coordinate$$module$build$src$core$utils$coordinate.difference(b,a.getRelativeToSurfaceXY()),f=new Coordinate$$module$build$src$core$utils$coordinate(0,0),g=c.getAllBlocks(!1).filter(h=>h.id!=a.id).map(h=>h.getRelativeToSurfaceXY());for(;blockOverlapsOtherExactly$$module$build$src$core$clipboard$block_paster(Coordinate$$module$build$src$core$utils$coordinate.sum(b,f), +g)||blockIsInSnapRadius$$module$build$src$core$clipboard$block_paster(a,Coordinate$$module$build$src$core$utils$coordinate.sum(e,f),d);)c.RTL?f.translate(-d,d*2):f.translate(d,d*2);a.moveTo(Coordinate$$module$build$src$core$utils$coordinate.sum(b,f))};blockOverlapsOtherExactly$$module$build$src$core$clipboard$block_paster=function(a,b){return b.some(c=>Math.abs(c.x-a.x)<=1&&Math.abs(c.y-a.y)<=1)}; +blockIsInSnapRadius$$module$build$src$core$clipboard$block_paster=function(a,b,c){return a.getConnections_(!1).some(d=>!!d.closest(c,b).connection)}; +bumpObjectIntoBounds$$module$build$src$core$bump_objects=function(a,b,c){const d=c.getBoundingRectangle(),e=d.right-d.left,f=clamp$$module$build$src$core$utils$math(b.top,d.top,b.top+b.height-(d.bottom-d.top))-d.top;let g=b.left;b=b.left+b.width-e;a.RTL?g=Math.min(b,g):b=Math.max(g,b);return(a=clamp$$module$build$src$core$utils$math(g,d.left,b)-d.left)||f?(c.moveBy(a,f,["inbounds"]),!0):!1}; +bumpIntoBoundsHandler$$module$build$src$core$bump_objects=function(a){return b=>{var c=a.getMetricsManager();if(c.hasFixedEdges()&&!a.isDragging()){var d;if(BUMP_EVENTS$$module$build$src$core$events$type.includes((d=b.type)!=null?d:"")){d=c.getScrollMetrics(!0);const e=extractObjectFromEvent$$module$build$src$core$bump_objects(a,b);e&&(c=$.getGroup$$module$build$src$core$events$utils()||!1,$.setGroup$$module$build$src$core$events$utils(b.group),bumpObjectIntoBounds$$module$build$src$core$bump_objects(a, +d,e)&&!b.group&&console.warn("Moved object in bounds but there was no event group. This may break undo."),$.setGroup$$module$build$src$core$events$utils(c))}else isViewportChange$$module$build$src$core$events$predicates(b)&&b.scale&&b.oldScale&&b.scale>b.oldScale&&bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects(a)}}}; +extractObjectFromEvent$$module$build$src$core$bump_objects=function(a,b){let c=null;switch(b.type){case EventType$$module$build$src$core$events$type.BLOCK_CREATE:case EventType$$module$build$src$core$events$type.BLOCK_MOVE:(c=a.getBlockById(b.blockId))&&(c=c.getRootBlock());break;case EventType$$module$build$src$core$events$type.COMMENT_CREATE:case EventType$$module$build$src$core$events$type.COMMENT_MOVE:case EventType$$module$build$src$core$events$type.COMMENT_RESIZE:c=a.getCommentById(b.commentId)}return c}; +bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects=function(a){var b=a.getMetricsManager();if(b.hasFixedEdges()&&!a.isDragging()){b=b.getScrollMetrics(!0);var c=a.getTopBoundedElements();for(let d=0,e;e=c[d];d++)bumpObjectIntoBounds$$module$build$src$core$bump_objects(a,b,e)}};isDeletable$$module$build$src$core$interfaces$i_deletable=function(a){return a&&typeof a.isDeletable==="function"&&typeof a.dispose==="function"&&typeof a.setDeleteStyle==="function"}; +getBlockNavigationCandidates$$module$build$src$core$keyboard_nav$block_navigation_policy=function(a,b){const c=a.getIcons();for(const d of a.inputList){if(!d.isVisible())continue;c.push(...d.fieldRow);let e;if((e=d.connection)==null?0:e.targetBlock())if(a=d.connection.targetBlock(),d.connection.type!==ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT||b)c.push(a);else{let f;(a=(f=a.lastConnectionInStack(!1))==null?void 0:f.getSourceBlock())&&c.push(a)}else{let f;((f=d.connection)== +null?void 0:f.type)===ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE&&c.push(d.connection)}}return c}; +navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy=function(a,b){const c=a.workspace.getTopBoundedElements(!0).filter(e=>isFocusableNode$$module$build$src$core$interfaces$i_focusable_node(e));a=c.indexOf(a instanceof BlockSvg$$module$build$src$core$block_svg?a.getRootBlock():a)+b;let d=null;a>=0&&a=c.length&&(d=c[0]);if(b<0&&d instanceof BlockSvg$$module$build$src$core$block_svg){let e,f;return(f=(e=d.lastConnectionInStack(!1))==null? +void 0:e.getSourceBlock())!=null?f:d}return d}; +navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy=function(a,b){var c;let d;const e=a instanceof BlockSvg$$module$build$src$core$block_svg?(d=(c=a.outputConnection)==null?void 0:c.targetBlock())!=null?d:a.getSurroundParent():a.getSourceBlock();if(!(e instanceof BlockSvg$$module$build$src$core$block_svg))return null;c=getBlockNavigationCandidates$$module$build$src$core$keyboard_nav$block_navigation_policy(e,b>0);a=c.indexOf(a);if(a===-1)return null;b=a+b;return b>=0&&b!d.getReturnTypes()).map(d=>[d.getName(),d.getParameters().map(e=>e.getName()),!1]);a.getBlocksByType("procedures_defnoreturn",!1).forEach(d=>{!isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(d)&&isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(d)&&b.push(d.getProcedureDef())});const c=a.getProcedureMap().getProcedures().filter(d=> !!d.getReturnTypes()).map(d=>[d.getName(),d.getParameters().map(e=>e.getName()),!0]);a.getBlocksByType("procedures_defreturn",!1).forEach(d=>{!isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(d)&&isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(d)&&c.push(d.getProcedureDef())});b.sort(procTupleComparator$$module$build$src$core$procedures);c.sort(procTupleComparator$$module$build$src$core$procedures);return[b,c]}; procTupleComparator$$module$build$src$core$procedures=function(a,b){return a[0].localeCompare(b[0],void 0,{sensitivity:"base"})};$.findLegalName$$module$build$src$core$procedures=function(a,b){if(b.isInFlyout)return a;for(a=a||$.Msg$$module$build$src$core$msg.UNNAMED_KEY||"unnamed";!isLegalName$$module$build$src$core$procedures(a,b.workspace,b);){const c=a.match(/^(.*?)(\d+)$/);a=c?c[1]+(parseInt(c[2])+1):a+"2"}return a}; isLegalName$$module$build$src$core$procedures=function(a,b,c){return!isNameUsed$$module$build$src$core$procedures(a,b,c)}; -isNameUsed$$module$build$src$core$procedures=function(a,b,c){for(const d of b.getAllBlocks(!1))if(d!==c&&isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(d)&&$.Names$$module$build$src$core$names.equals(d.getProcedureDef()[0],a))return!0;c=c&&isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(c)?null==c?void 0:c.getProcedureModel():void 0;for(const d of b.getProcedureMap().getProcedures())if(d!==c&&$.Names$$module$build$src$core$names.equals(d.getName(), +isNameUsed$$module$build$src$core$procedures=function(a,b,c){for(const d of b.getAllBlocks(!1))if(d!==c&&isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(d)&&$.Names$$module$build$src$core$names.equals(d.getProcedureDef()[0],a))return!0;c=c&&isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(c)?c==null?void 0:c.getProcedureModel():void 0;for(const d of b.getProcedureMap().getProcedures())if(d!==c&&$.Names$$module$build$src$core$names.equals(d.getName(), a))return!0;return!1}; $.rename$$module$build$src$core$procedures=function(a){var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;a=a.trim();const c=$.findLegalName$$module$build$src$core$procedures(a,b);isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(b)&&!b.isInsertionMarker()&&b.getProcedureModel().setName(c);const d=this.getValue();if(d!==a&&d!==c)for(a=b.workspace.getAllBlocks(!1),b=0;bblockIsModernCallerFor$$module$build$src$core$procedures(c,a)||isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(c)&&$.Names$$module$build$src$core$names.equals(c.getProcedureCall(),a))}; blockIsModernCallerFor$$module$build$src$core$procedures=function(a,b){return isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(a)&&!a.isProcedureDef()&&a.getProcedureModel()&&$.Names$$module$build$src$core$names.equals(a.getProcedureModel().getName(),b)}; $.mutateCallers$$module$build$src$core$procedures=function(a){const b=getRecordUndo$$module$build$src$core$events$utils();var c=a.getProcedureDef()[0];const d=a.mutationToDom(!0);a=getCallers$$module$build$src$core$procedures(c,a.workspace);for(let f=0,g;g=a[f];f++){c=(c=g.mutationToDom())&&domToText$$module$build$src$core$utils$xml(c);g.domToMutation&&g.domToMutation(d);var e=g.mutationToDom();e=e&&domToText$$module$build$src$core$utils$xml(e);c!==e&&($.setRecordUndo$$module$build$src$core$events$utils(!1), fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(g,"mutation",null,c,e)),$.setRecordUndo$$module$build$src$core$events$utils(b))}}; $.getDefinition$$module$build$src$core$procedures=function(a,b){for(const c of b.getAllBlocks(!1))if(isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block(c)&&c.isProcedureDef()&&$.Names$$module$build$src$core$names.equals(c.getProcedureModel().getName(),a)||isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks(c)&&$.Names$$module$build$src$core$names.equals(c.getProcedureDef()[0],a))return c;return null}; -isDynamicShape$$module$build$src$core$renderers$common$constants=function(a){return a.isDynamic};isPuzzleTab$$module$build$src$core$renderers$common$constants=function(a){return void 0!==a.pathDown&&void 0!==a.pathUp};isNotch$$module$build$src$core$renderers$common$constants=function(a){return void 0!==a.pathLeft&&void 0!==a.pathRight}; -connectReciprocally$$module$build$src$core$connection=function(a,b){if(!a||!b)throw Error("Cannot connect null connections.");a.targetConnection=b;b.targetConnection=a};getSingleConnection$$module$build$src$core$connection=function(a,b){let c=null;b=b.outputConnection;const d=null==b?void 0:b.getConnectionChecker();for(let e=0,f;f=a.inputList[e];e++){const g=f.connection;let h;if(g&&(null==(h=d)?0:h.canConnect(b,g,!1))){if(c)return null;c=g}}return c}; -getConnectionForOrphanedOutput$$module$build$src$core$connection=function(a,b){let c;for(;c=getSingleConnection$$module$build$src$core$connection(a,b);)if(a=c.targetBlock(),!a||a.isShadow())return c;return null}; -isIcon$$module$build$src$core$interfaces$i_icon=function(a){return void 0!==a.getType&&void 0!==a.initView&&void 0!==a.dispose&&void 0!==a.getWeight&&void 0!==a.getSize&&void 0!==a.applyColour&&void 0!==a.hideForInsertionMarker&&void 0!==a.updateEditable&&void 0!==a.updateCollapsed&&void 0!==a.isShownWhenCollapsed&&void 0!==a.setOffsetInBlock&&void 0!==a.onLocationChange&&void 0!==a.onClick}; -isCommentIcon$$module$build$src$core$interfaces$i_comment_icon=function(a){return isIcon$$module$build$src$core$interfaces$i_icon(a)&&hasBubble$$module$build$src$core$interfaces$i_has_bubble(a)&&isSerializable$$module$build$src$core$interfaces$i_serializable(a)&&void 0!==a.setText&&void 0!==a.getText&&void 0!==a.setBubbleSize&&void 0!==a.getBubbleSize&&a.getType()===IconType$$module$build$src$core$icons$icon_types.COMMENT}; -getParentConnection$$module$build$src$core$keyboard_nav$ast_node=function(a){let b=a.outputConnection;if(!b||a.previousConnection&&a.previousConnection.isConnected())b=a.previousConnection;return b};register$$module$build$src$core$renderers$common$block_rendering=function(a,b){register$$module$build$src$core$registry(Type$$module$build$src$core$registry.RENDERER,a,b)}; -unregister$$module$build$src$core$renderers$common$block_rendering=function(a){unregister$$module$build$src$core$registry(Type$$module$build$src$core$registry.RENDERER,a)};init$$module$build$src$core$renderers$common$block_rendering=function(a,b,c){a=new (getClass$$module$build$src$core$registry(Type$$module$build$src$core$registry.RENDERER,a))(a);a.init(b,c);return a}; -stringButtonClickHandler$$module$build$src$core$variables_dynamic=function(a){createVariableButtonHandler$$module$build$src$core$variables(a.getTargetWorkspace(),void 0,"String")};numberButtonClickHandler$$module$build$src$core$variables_dynamic=function(a){createVariableButtonHandler$$module$build$src$core$variables(a.getTargetWorkspace(),void 0,"Number")}; -colourButtonClickHandler$$module$build$src$core$variables_dynamic=function(a){createVariableButtonHandler$$module$build$src$core$variables(a.getTargetWorkspace(),void 0,"Colour")}; -flyoutCategory$$module$build$src$core$variables_dynamic=function(a){let b=[],c=document.createElement("button");c.setAttribute("text",$.Msg$$module$build$src$core$msg.NEW_STRING_VARIABLE);c.setAttribute("callbackKey","CREATE_VARIABLE_STRING");b.push(c);c=document.createElement("button");c.setAttribute("text",$.Msg$$module$build$src$core$msg.NEW_NUMBER_VARIABLE);c.setAttribute("callbackKey","CREATE_VARIABLE_NUMBER");b.push(c);c=document.createElement("button");c.setAttribute("text",$.Msg$$module$build$src$core$msg.NEW_COLOUR_VARIABLE); +isDynamicShape$$module$build$src$core$renderers$common$constants=function(a){return a.isDynamic};isPuzzleTab$$module$build$src$core$renderers$common$constants=function(a){return a.pathDown!==void 0&&a.pathUp!==void 0};isNotch$$module$build$src$core$renderers$common$constants=function(a){return a.pathLeft!==void 0&&a.pathRight!==void 0}; +register$$module$build$src$core$renderers$common$block_rendering=function(a,b){register$$module$build$src$core$registry(Type$$module$build$src$core$registry.RENDERER,a,b)};unregister$$module$build$src$core$renderers$common$block_rendering=function(a){unregister$$module$build$src$core$registry(Type$$module$build$src$core$registry.RENDERER,a)}; +init$$module$build$src$core$renderers$common$block_rendering=function(a,b,c){a=new (getClass$$module$build$src$core$registry(Type$$module$build$src$core$registry.RENDERER,a))(a);a.init(b,c);return a};stringButtonClickHandler$$module$build$src$core$variables_dynamic=function(a){createVariableButtonHandler$$module$build$src$core$variables(a.getTargetWorkspace(),void 0,"String")}; +numberButtonClickHandler$$module$build$src$core$variables_dynamic=function(a){createVariableButtonHandler$$module$build$src$core$variables(a.getTargetWorkspace(),void 0,"Number")};colourButtonClickHandler$$module$build$src$core$variables_dynamic=function(a){createVariableButtonHandler$$module$build$src$core$variables(a.getTargetWorkspace(),void 0,"Colour")}; +internalFlyoutCategory$$module$build$src$core$variables_dynamic=function(a){return flyoutCategory$$module$build$src$core$variables_dynamic(a,!1)}; +flyoutCategory$$module$build$src$core$variables_dynamic=function(a,b=!0){Blocks$$module$build$src$core$blocks.variables_set_dynamic||Blocks$$module$build$src$core$blocks.variables_get_dynamic||console.warn("There are no dynamic variable blocks, but there is a dynamic variable category.");if(b)return warn$$module$build$src$core$utils$deprecation("The XML return value of Blockly.VariablesDynamic.flyoutCategory()","v12","v13","the same method, but handle a return type of FlyoutItemInfo[] (JSON) instead."), +xmlFlyoutCategory$$module$build$src$core$variables_dynamic(a);a.registerButtonCallback("CREATE_VARIABLE_STRING",stringButtonClickHandler$$module$build$src$core$variables_dynamic);a.registerButtonCallback("CREATE_VARIABLE_NUMBER",numberButtonClickHandler$$module$build$src$core$variables_dynamic);a.registerButtonCallback("CREATE_VARIABLE_COLOUR",colourButtonClickHandler$$module$build$src$core$variables_dynamic);return[{kind:"button",text:$.Msg$$module$build$src$core$msg.NEW_STRING_VARIABLE,callbackkey:"CREATE_VARIABLE_STRING"}, +{kind:"button",text:$.Msg$$module$build$src$core$msg.NEW_NUMBER_VARIABLE,callbackkey:"CREATE_VARIABLE_NUMBER"},{kind:"button",text:$.Msg$$module$build$src$core$msg.NEW_COLOUR_VARIABLE,callbackkey:"CREATE_VARIABLE_COLOUR"},...jsonFlyoutCategoryBlocks$$module$build$src$core$variables(a,a.getVariableMap().getAllVariables(),!1,"variables_get_dynamic","variables_set_dynamic")]}; +xmlFlyoutCategory$$module$build$src$core$variables_dynamic=function(a){let b=[],c=document.createElement("button");c.setAttribute("text",$.Msg$$module$build$src$core$msg.NEW_STRING_VARIABLE);c.setAttribute("callbackKey","CREATE_VARIABLE_STRING");b.push(c);c=document.createElement("button");c.setAttribute("text",$.Msg$$module$build$src$core$msg.NEW_NUMBER_VARIABLE);c.setAttribute("callbackKey","CREATE_VARIABLE_NUMBER");b.push(c);c=document.createElement("button");c.setAttribute("text",$.Msg$$module$build$src$core$msg.NEW_COLOUR_VARIABLE); c.setAttribute("callbackKey","CREATE_VARIABLE_COLOUR");b.push(c);a.registerButtonCallback("CREATE_VARIABLE_STRING",stringButtonClickHandler$$module$build$src$core$variables_dynamic);a.registerButtonCallback("CREATE_VARIABLE_NUMBER",numberButtonClickHandler$$module$build$src$core$variables_dynamic);a.registerButtonCallback("CREATE_VARIABLE_COLOUR",colourButtonClickHandler$$module$build$src$core$variables_dynamic);a=flyoutCategoryBlocks$$module$build$src$core$variables_dynamic(a);return b=b.concat(a)}; -flyoutCategoryBlocks$$module$build$src$core$variables_dynamic=function(a){a=a.getAllVariables();const b=[];if(00){if(Blocks$$module$build$src$core$blocks.variables_set_dynamic){var c=a[a.length-1];const d=$.createElement$$module$build$src$core$utils$xml("block");d.setAttribute("type","variables_set_dynamic");d.setAttribute("gap","24");d.appendChild(generateVariableFieldDom$$module$build$src$core$variables(c));b.push(d)}if(Blocks$$module$build$src$core$blocks.variables_get_dynamic){a.sort(compareByName$$module$build$src$core$variables); for(let d=0,e;e=a[d];d++)c=$.createElement$$module$build$src$core$utils$xml("block"),c.setAttribute("type","variables_get_dynamic"),c.setAttribute("gap","8"),c.appendChild(generateVariableFieldDom$$module$build$src$core$variables(e)),b.push(c)}}return b};resizeSvgContents$$module$build$src$core$workspace_svg=function(a){a.resizeContents()}; -moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster=function(a,b){const c=a.workspace,d=$.config$$module$build$src$core$config.snapRadius,e=Coordinate$$module$build$src$core$utils$coordinate.difference(b,a.getRelativeToSurfaceXY()),f=new Coordinate$$module$build$src$core$utils$coordinate(0,0),g=c.getAllBlocks(!1).filter(h=>h.id!=a.id).map(h=>h.getRelativeToSurfaceXY());for(;blockOverlapsOtherExactly$$module$build$src$core$clipboard$block_paster(Coordinate$$module$build$src$core$utils$coordinate.sum(b, -f),g)||blockIsInSnapRadius$$module$build$src$core$clipboard$block_paster(a,Coordinate$$module$build$src$core$utils$coordinate.sum(e,f),d);)c.RTL?f.translate(-d,2*d):f.translate(d,2*d);a.moveTo(Coordinate$$module$build$src$core$utils$coordinate.sum(b,f))};blockOverlapsOtherExactly$$module$build$src$core$clipboard$block_paster=function(a,b){return b.some(c=>1>=Math.abs(c.x-a.x)&&1>=Math.abs(c.y-a.y))}; -blockIsInSnapRadius$$module$build$src$core$clipboard$block_paster=function(a,b,c){return a.getConnections_(!1).some(d=>!!d.closest(c,b).connection)}; -bumpObjectIntoBounds$$module$build$src$core$bump_objects=function(a,b,c){const d=c.getBoundingRectangle(),e=d.right-d.left,f=clamp$$module$build$src$core$utils$math(b.top,d.top,b.top+b.height-(d.bottom-d.top))-d.top;let g=b.left;b=b.left+b.width-e;a.RTL?g=Math.min(b,g):b=Math.max(g,b);return(a=clamp$$module$build$src$core$utils$math(g,d.left,b)-d.left)||f?(c.moveBy(a,f,["inbounds"]),!0):!1}; -bumpIntoBoundsHandler$$module$build$src$core$bump_objects=function(a){return b=>{var c=a.getMetricsManager();if(c.hasFixedEdges()&&!a.isDragging()){var d;if(BUMP_EVENTS$$module$build$src$core$events$type.includes(null!=(d=b.type)?d:"")){d=c.getScrollMetrics(!0);const e=extractObjectFromEvent$$module$build$src$core$bump_objects(a,b);e&&(c=$.getGroup$$module$build$src$core$events$utils()||!1,$.setGroup$$module$build$src$core$events$utils(b.group),bumpObjectIntoBounds$$module$build$src$core$bump_objects(a, -d,e)&&!b.group&&console.warn("Moved object in bounds but there was no event group. This may break undo."),$.setGroup$$module$build$src$core$events$utils(c))}else isViewportChange$$module$build$src$core$events$predicates(b)&&b.scale&&b.oldScale&&b.scale>b.oldScale&&bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects(a)}}}; -extractObjectFromEvent$$module$build$src$core$bump_objects=function(a,b){let c=null;switch(b.type){case EventType$$module$build$src$core$events$type.BLOCK_CREATE:case EventType$$module$build$src$core$events$type.BLOCK_MOVE:(c=a.getBlockById(b.blockId))&&(c=c.getRootBlock());break;case EventType$$module$build$src$core$events$type.COMMENT_CREATE:case EventType$$module$build$src$core$events$type.COMMENT_MOVE:case EventType$$module$build$src$core$events$type.COMMENT_RESIZE:c=a.getCommentById(b.commentId)}return c}; -bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects=function(a){var b=a.getMetricsManager();if(b.hasFixedEdges()&&!a.isDragging()){b=b.getScrollMetrics(!0);var c=a.getTopBoundedElements();for(let d=0,e;e=c[d];d++)bumpObjectIntoBounds$$module$build$src$core$bump_objects(a,b,e)}};isDeletable$$module$build$src$core$interfaces$i_deletable=function(a){return void 0!==a.isDeletable&&void 0!==a.dispose&&void 0!==a.setDeleteStyle}; -copyInternal$$module$build$src$core$clipboard=function(a){const b=a.toCopyData();stashedCopyData$$module$build$src$core$clipboard=b;let c;stashedWorkspace$$module$build$src$core$clipboard=null!=(c=a.workspace)?c:null;return b}; -paste$$module$build$src$core$clipboard=function(a,b,c){return a&&b?pasteFromData$$module$build$src$core$clipboard(a,b,c):stashedCopyData$$module$build$src$core$clipboard&&stashedWorkspace$$module$build$src$core$clipboard?pasteFromData$$module$build$src$core$clipboard(stashedCopyData$$module$build$src$core$clipboard,stashedWorkspace$$module$build$src$core$clipboard):null}; -pasteFromData$$module$build$src$core$clipboard=function(a,b,c){let d;b=b.isMutator?b:null!=(d=b.getRootWorkspace())?d:b;let e,f;return null!=(f=null==(e=getObject$$module$build$src$core$registry(Type$$module$build$src$core$registry.PASTER,a.paster,!1))?void 0:e.paste(a,b,c))?f:null};duplicateInternal$$module$build$src$core$clipboard=function(a){const b=a.toCopyData();return b?paste$$module$build$src$core$clipboard(b,a.workspace):null}; -isCopyable$$module$build$src$core$interfaces$i_copyable=function(a){return void 0!==a.toCopyData};registerEscape$$module$build$src$core$shortcut_items=function(){ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.ESCAPE,preconditionFn(a){return!a.options.readOnly},callback(a){a.hideChaff();return!0},keyCodes:[KeyCodes$$module$build$src$core$utils$keycodes.ESC]})}; -registerDelete$$module$build$src$core$shortcut_items=function(){ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.DELETE,preconditionFn(a){const b=getSelected$$module$build$src$core$common();return!a.options.readOnly&&null!=b&&isDeletable$$module$build$src$core$interfaces$i_deletable(b)&&b.isDeletable()&&!Gesture$$module$build$src$core$gesture.inProgress()},callback(a,b){b.preventDefault();a=getSelected$$module$build$src$core$common(); -a instanceof BlockSvg$$module$build$src$core$block_svg?a.checkAndDelete():isDeletable$$module$build$src$core$interfaces$i_deletable(a)&&a.isDeletable()&&($.setGroup$$module$build$src$core$events$utils(!0),a.dispose(),$.setGroup$$module$build$src$core$events$utils(!1));return!0},keyCodes:[KeyCodes$$module$build$src$core$utils$keycodes.DELETE,KeyCodes$$module$build$src$core$utils$keycodes.BACKSPACE]})}; -registerCopy$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.C,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL]),b=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.C,[KeyCodes$$module$build$src$core$utils$keycodes.ALT]),c=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.C, -[KeyCodes$$module$build$src$core$utils$keycodes.META]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.COPY,preconditionFn(d){const e=getSelected$$module$build$src$core$common();return!d.options.readOnly&&!Gesture$$module$build$src$core$gesture.inProgress()&&null!=e&&isDeletable$$module$build$src$core$interfaces$i_deletable(e)&&e.isDeletable()&&isDraggable$$module$build$src$core$interfaces$i_draggable(e)&&e.isMovable()&& -isCopyable$$module$build$src$core$interfaces$i_copyable(e)},callback(d,e){e.preventDefault();d.hideChaff();e=getSelected$$module$build$src$core$common();if(!e||!isCopyable$$module$build$src$core$interfaces$i_copyable(e))return!1;copyData$$module$build$src$core$shortcut_items=e.toCopyData();copyWorkspace$$module$build$src$core$shortcut_items=e.workspace instanceof WorkspaceSvg$$module$build$src$core$workspace_svg?e.workspace:d;copyCoords$$module$build$src$core$shortcut_items=isDraggable$$module$build$src$core$interfaces$i_draggable(e)? -e.getRelativeToSurfaceXY():null;return!!copyData$$module$build$src$core$shortcut_items},keyCodes:[a,b,c]})}; -registerCut$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.X,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL]),b=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.X,[KeyCodes$$module$build$src$core$utils$keycodes.ALT]),c=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.X, -[KeyCodes$$module$build$src$core$utils$keycodes.META]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.CUT,preconditionFn(d){const e=getSelected$$module$build$src$core$common();return!d.options.readOnly&&!Gesture$$module$build$src$core$gesture.inProgress()&&null!=e&&isDeletable$$module$build$src$core$interfaces$i_deletable(e)&&e.isDeletable()&&isDraggable$$module$build$src$core$interfaces$i_draggable(e)&&e.isMovable()&& -!e.workspace.isFlyout},callback(d){const e=getSelected$$module$build$src$core$common();return e instanceof BlockSvg$$module$build$src$core$block_svg?(copyData$$module$build$src$core$shortcut_items=e.toCopyData(),copyWorkspace$$module$build$src$core$shortcut_items=d,copyCoords$$module$build$src$core$shortcut_items=e.getRelativeToSurfaceXY(),e.checkAndDelete(),!0):isDeletable$$module$build$src$core$interfaces$i_deletable(e)&&e.isDeletable()&&isCopyable$$module$build$src$core$interfaces$i_copyable(e)? -(copyData$$module$build$src$core$shortcut_items=e.toCopyData(),copyWorkspace$$module$build$src$core$shortcut_items=d,copyCoords$$module$build$src$core$shortcut_items=isDraggable$$module$build$src$core$interfaces$i_draggable(e)?e.getRelativeToSurfaceXY():null,e.dispose(),!0):!1},keyCodes:[a,b,c]})}; -registerPaste$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.V,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL]),b=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.V,[KeyCodes$$module$build$src$core$utils$keycodes.ALT]),c=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.V, -[KeyCodes$$module$build$src$core$utils$keycodes.META]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.PASTE,preconditionFn(d){return!d.options.readOnly&&!Gesture$$module$build$src$core$gesture.inProgress()},callback(){if(!copyData$$module$build$src$core$shortcut_items||!copyWorkspace$$module$build$src$core$shortcut_items)return!1;if(!copyCoords$$module$build$src$core$shortcut_items)return!!paste$$module$build$src$core$clipboard(copyData$$module$build$src$core$shortcut_items, -copyWorkspace$$module$build$src$core$shortcut_items);const {left:d,top:e,width:f,height:g}=copyWorkspace$$module$build$src$core$shortcut_items.getMetricsManager().getViewMetrics(!0);if((new Rect$$module$build$src$core$utils$rect(e,e+g,d,d+f)).contains(copyCoords$$module$build$src$core$shortcut_items.x,copyCoords$$module$build$src$core$shortcut_items.y))return!!paste$$module$build$src$core$clipboard(copyData$$module$build$src$core$shortcut_items,copyWorkspace$$module$build$src$core$shortcut_items); -const h=new Coordinate$$module$build$src$core$utils$coordinate(d+f/2,e+g/2);return!!paste$$module$build$src$core$clipboard(copyData$$module$build$src$core$shortcut_items,copyWorkspace$$module$build$src$core$shortcut_items,h)},keyCodes:[a,b,c]})}; -registerUndo$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL]),b=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.ALT]),c=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z, -[KeyCodes$$module$build$src$core$utils$keycodes.META]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.UNDO,preconditionFn(d){return!d.options.readOnly&&!Gesture$$module$build$src$core$gesture.inProgress()},callback(d,e){d.hideChaff();d.undo(!1);e.preventDefault();return!0},keyCodes:[a,b,c]})}; -registerRedo$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.SHIFT,KeyCodes$$module$build$src$core$utils$keycodes.CTRL]),b=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.SHIFT, -KeyCodes$$module$build$src$core$utils$keycodes.ALT]),c=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.SHIFT,KeyCodes$$module$build$src$core$utils$keycodes.META]),d=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Y,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.REDO, -preconditionFn(e){return!Gesture$$module$build$src$core$gesture.inProgress()&&!e.options.readOnly},callback(e,f){e.hideChaff();e.undo(!0);f.preventDefault();return!0},keyCodes:[a,b,c,d]})}; -registerDefaultShortcuts$$module$build$src$core$shortcut_items=function(){registerEscape$$module$build$src$core$shortcut_items();registerDelete$$module$build$src$core$shortcut_items();registerCopy$$module$build$src$core$shortcut_items();registerCut$$module$build$src$core$shortcut_items();registerPaste$$module$build$src$core$shortcut_items();registerUndo$$module$build$src$core$shortcut_items();registerRedo$$module$build$src$core$shortcut_items()}; +copy$$module$build$src$core$clipboard=function(a,b){const c=a.toCopyData();stashedCopyData$$module$build$src$core$clipboard=c;stashedWorkspace$$module$build$src$core$clipboard=isSelectable$$module$build$src$core$interfaces$i_selectable(a)&&a.workspace instanceof WorkspaceSvg$$module$build$src$core$workspace_svg?a.workspace:null;stashedCoordinates$$module$build$src$core$clipboard=b;return c};getLastCopiedData$$module$build$src$core$clipboard=function(){return stashedCopyData$$module$build$src$core$clipboard}; +setLastCopiedData$$module$build$src$core$clipboard=function(a){stashedCopyData$$module$build$src$core$clipboard=a};getLastCopiedWorkspace$$module$build$src$core$clipboard=function(){return stashedWorkspace$$module$build$src$core$clipboard};setLastCopiedWorkspace$$module$build$src$core$clipboard=function(a){stashedWorkspace$$module$build$src$core$clipboard=a};getLastCopiedLocation$$module$build$src$core$clipboard=function(){return stashedCoordinates$$module$build$src$core$clipboard}; +setLastCopiedLocation$$module$build$src$core$clipboard=function(a){stashedCoordinates$$module$build$src$core$clipboard=a}; +paste$$module$build$src$core$clipboard=function(a,b,c){return a&&b?pasteFromData$$module$build$src$core$clipboard(a,b,c):stashedCopyData$$module$build$src$core$clipboard&&stashedWorkspace$$module$build$src$core$clipboard?pasteFromData$$module$build$src$core$clipboard(stashedCopyData$$module$build$src$core$clipboard,stashedWorkspace$$module$build$src$core$clipboard,stashedCoordinates$$module$build$src$core$clipboard):null}; +pasteFromData$$module$build$src$core$clipboard=function(a,b,c){let d;b=b.isMutator?b:(d=b.options.parentWorkspace)!=null?d:b;let e,f;return(f=(e=getObject$$module$build$src$core$registry(Type$$module$build$src$core$registry.PASTER,a.paster,!1))==null?void 0:e.paste(a,b,c))!=null?f:null};isCopyable$$module$build$src$core$interfaces$i_copyable=function(a){return a&&typeof a.toCopyData==="function"}; +registerEscape$$module$build$src$core$shortcut_items=function(){ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.ESCAPE,preconditionFn(a){return!a.isReadOnly()},callback(a){a.hideChaff();return!0},keyCodes:[KeyCodes$$module$build$src$core$utils$keycodes.ESC]})}; +registerDelete$$module$build$src$core$shortcut_items=function(){ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.DELETE,preconditionFn(a,b){b=b.focusedNode;return!a.isReadOnly()&&b!=null&&isDeletable$$module$build$src$core$interfaces$i_deletable(b)&&b.isDeletable()&&!a.isDragging()&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()},callback(a,b,c,d){b.preventDefault();a=d.focusedNode;a instanceof +BlockSvg$$module$build$src$core$block_svg?a.checkAndDelete():isDeletable$$module$build$src$core$interfaces$i_deletable(a)&&a.isDeletable()&&($.setGroup$$module$build$src$core$events$utils(!0),a.dispose(),$.setGroup$$module$build$src$core$events$utils(!1));return!0},keyCodes:[KeyCodes$$module$build$src$core$utils$keycodes.DELETE,KeyCodes$$module$build$src$core$utils$keycodes.BACKSPACE]})}; +isCopyable$$module$build$src$core$shortcut_items=function(a){return isCopyable$$module$build$src$core$interfaces$i_copyable(a)&&isDeletable$$module$build$src$core$interfaces$i_deletable(a)&&isDraggable$$module$build$src$core$interfaces$i_draggable(a)?a.isCopyable?a.isCopyable():a instanceof BlockSvg$$module$build$src$core$block_svg||a instanceof RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment?a.isOwnDeletable()&&a.isOwnMovable():a.isDeletable()&&a.isMovable():!1}; +isCuttable$$module$build$src$core$shortcut_items=function(a){return isCopyable$$module$build$src$core$shortcut_items(a)&&isDeletable$$module$build$src$core$interfaces$i_deletable(a)&&a.isDeletable()}; +registerCopy$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.C,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL_CMD]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.COPY,preconditionFn(b,c){c=c.focusedNode;b=b.isFlyout?b.targetWorkspace:b;return!!c&&!!b&&!b.isDragging()&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()&& +isCopyable$$module$build$src$core$shortcut_items(c)},callback(b,c,d,e){c.preventDefault();c=e.focusedNode;if(!c||!isCopyable$$module$build$src$core$interfaces$i_copyable(c)||!isCopyable$$module$build$src$core$shortcut_items(c))return!1;b=b.isFlyout?b.targetWorkspace:b;if(!b)return!1;c.workspace.isFlyout||b.hideChaff();b=isDraggable$$module$build$src$core$interfaces$i_draggable(c)&&c.workspace==b?c.getRelativeToSurfaceXY():void 0;return!!copy$$module$build$src$core$clipboard(c,b)},keyCodes:[a]})}; +registerCut$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.X,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL_CMD]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.CUT,preconditionFn(b,c){c=c.focusedNode;return!!c&&!b.isReadOnly()&&!b.isDragging()&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()&& +isCuttable$$module$build$src$core$shortcut_items(c)},callback(b,c,d,e){b=e.focusedNode;if(!b||!isCuttable$$module$build$src$core$shortcut_items(b)||!isCopyable$$module$build$src$core$interfaces$i_copyable(b))return!1;c=isDraggable$$module$build$src$core$interfaces$i_draggable(b)?b.getRelativeToSurfaceXY():void 0;c=copy$$module$build$src$core$clipboard(b,c);b instanceof BlockSvg$$module$build$src$core$block_svg?b.checkAndDelete():isDeletable$$module$build$src$core$interfaces$i_deletable(b)&&b.dispose(); +return!!c},keyCodes:[a]})}; +registerPaste$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.V,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL_CMD]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.PASTE,preconditionFn(){var b=getLastCopiedWorkspace$$module$build$src$core$clipboard();if(!b||!b.rendered)return!1; +b=b.isFlyout?b.targetWorkspace:b;return!!getLastCopiedData$$module$build$src$core$clipboard()&&!!b&&!b.isReadOnly()&&!b.isDragging()&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()},callback(b,c){b=getLastCopiedData$$module$build$src$core$clipboard();if(!b)return!1;var d=getLastCopiedWorkspace$$module$build$src$core$clipboard();if(!d)return!1;d=d.isFlyout?d.targetWorkspace:d;if(!d||d.isReadOnly())return!1;if(c instanceof PointerEvent)return c=screenToWsCoordinates$$module$build$src$core$utils$svg_math(d, +new Coordinate$$module$build$src$core$utils$coordinate(c.clientX,c.clientY)),!!paste$$module$build$src$core$clipboard(b,d,c);c=getLastCopiedLocation$$module$build$src$core$clipboard();if(!c)return!!paste$$module$build$src$core$clipboard(b,d);const {left:e,top:f,width:g,height:h}=d.getMetricsManager().getViewMetrics(!0);if((new Rect$$module$build$src$core$utils$rect(f,f+h,e,e+g)).contains(c.x,c.y))return!!paste$$module$build$src$core$clipboard(b,d);c=new Coordinate$$module$build$src$core$utils$coordinate(e+ +g/2,f+h/2);return!!paste$$module$build$src$core$clipboard(b,d,c)},keyCodes:[a]})}; +registerUndo$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL_CMD]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.UNDO,preconditionFn(b){return!b.isReadOnly()&&!b.isDragging()&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()}, +callback(b,c){b.hideChaff();b.undo(!1);c.preventDefault();return!0},keyCodes:[a]})}; +registerRedo$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Z,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL_CMD,KeyCodes$$module$build$src$core$utils$keycodes.SHIFT]),b=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.Y,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL]); +ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.REDO,preconditionFn(c){return!c.isDragging()&&!c.isReadOnly()&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()},callback(c,d){c.hideChaff();c.undo(!0);d.preventDefault();return!0},keyCodes:[a,b]})}; +registerShowContextMenu$$module$build$src$core$shortcut_items=function(){const a=ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.createSerializedKey(KeyCodes$$module$build$src$core$utils$keycodes.ENTER,[KeyCodes$$module$build$src$core$utils$keycodes.CTRL_CMD]);ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.register({name:names$$module$build$src$core$shortcut_items.MENU,preconditionFn:b=>!b.isDragging(),callback:(b,c)=>{b=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode(); +if(hasContextMenu$$module$build$src$core$interfaces$i_contextmenu(b)){b.showContextMenu(c);let d;(d=getMenu$$module$build$src$core$contextmenu())==null||d.highlightNext();return!0}return!1},keyCodes:[a]})}; +registerDefaultShortcuts$$module$build$src$core$shortcut_items=function(){registerEscape$$module$build$src$core$shortcut_items();registerDelete$$module$build$src$core$shortcut_items();registerCopy$$module$build$src$core$shortcut_items();registerCut$$module$build$src$core$shortcut_items();registerPaste$$module$build$src$core$shortcut_items();registerUndo$$module$build$src$core$shortcut_items();registerRedo$$module$build$src$core$shortcut_items();registerShowContextMenu$$module$build$src$core$shortcut_items()}; saveProcedure$$module$build$src$core$serialization$procedures=function(a){const b=a.saveState();if(!a.getParameters().length)return b;b.parameters=a.getParameters().map(c=>c.saveState());return b};loadProcedure$$module$build$src$core$serialization$procedures=function(a,b,c,d){a=a.loadState(c,d);if(!c.parameters)return a;for(const [e,f]of c.parameters.entries())a.insertParameter(b.loadState(f,d),e);return a}; -save$$module$build$src$core$serialization$workspaces=function(a){const b=Object.create(null),c=getAllItems$$module$build$src$core$registry(Type$$module$build$src$core$registry.SERIALIZER,!0);for(const d in c){let e;const f=null==(e=c[d])?void 0:e.save(a);f&&(b[d]=f)}return b}; +save$$module$build$src$core$serialization$workspaces=function(a){const b=Object.create(null),c=getAllItems$$module$build$src$core$registry(Type$$module$build$src$core$registry.SERIALIZER,!0);for(const d in c){let e;const f=(e=c[d])==null?void 0:e.save(a);f&&(b[d]=f)}return b}; load$$module$build$src$core$serialization$workspaces=function(a,b,{recordUndo:c=!1}={}){var d=getAllItems$$module$build$src$core$registry(Type$$module$build$src$core$registry.SERIALIZER,!0);if(d){d=Object.entries(d).sort((f,g)=>g[1].priority-f[1].priority);var e=getRecordUndo$$module$build$src$core$events$utils();$.setRecordUndo$$module$build$src$core$events$utils(c);(c=$.getGroup$$module$build$src$core$events$utils())||$.setGroup$$module$build$src$core$events$utils(!0);startTextWidthCache$$module$build$src$core$utils$dom(); -b instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&b.setResizesEnabled(!1);for(const [,f]of d.reverse()){let g;null==(g=f)||g.clear(b)}for(const [f,g]of d.reverse())if(a[f]){let h;null==(h=g)||h.load(a[f],b)}b instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&b.setResizesEnabled(!0);stopTextWidthCache$$module$build$src$core$utils$dom();fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.FINISHED_LOADING))(b)); +b instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&b.setResizesEnabled(!1);for(const [,f]of d.reverse()){let g;(g=f)==null||g.clear(b)}for(const [f,g]of d.reverse())if(a[f]){let h;(h=g)==null||h.load(a[f],b)}b instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&b.setResizesEnabled(!0);stopTextWidthCache$$module$build$src$core$utils$dom();fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.FINISHED_LOADING))(b)); $.setGroup$$module$build$src$core$events$utils(c);$.setRecordUndo$$module$build$src$core$events$utils(e)}}; -inject$$module$build$src$core$inject=function(a,b){let c=null;c="string"===typeof a?document.getElementById(a)||document.querySelector(a):a;var d;if(!document.contains(c)&&document!==(null==(d=c)?void 0:d.ownerDocument))throw Error("Error: container is not in current document");a=new Options$$module$build$src$core$options(b||{});d=document.createElement("div");addClass$$module$build$src$core$utils$dom(d,"injectionDiv");(null==b?0:b.rtl)&&addClass$$module$build$src$core$utils$dom(d,"blocklyRTL");d.tabIndex= -0;setState$$module$build$src$core$utils$aria(d,State$$module$build$src$core$utils$aria.LABEL,$.Msg$$module$build$src$core$msg.WORKSPACE_ARIA_LABEL);c.appendChild(d);b=createDom$$module$build$src$core$inject(d,a);const e=createMainWorkspace$$module$build$src$core$inject(d,b,a);init$$module$build$src$core$inject(e);setMainWorkspace$$module$build$src$core$common(e);svgResize$$module$build$src$core$common(e);d.addEventListener("focusin",function(){setMainWorkspace$$module$build$src$core$common(e)});conditionalBind$$module$build$src$core$browser_events(d, -"keydown",null,onKeyDown$$module$build$src$core$inject);conditionalBind$$module$build$src$core$browser_events(getContentDiv$$module$build$src$core$dropdowndiv(),"keydown",null,onKeyDown$$module$build$src$core$inject);(b=getDiv$$module$build$src$core$widgetdiv())&&conditionalBind$$module$build$src$core$browser_events(b,"keydown",null,onKeyDown$$module$build$src$core$inject);return e}; -createDom$$module$build$src$core$inject=function(a,b){a.setAttribute("dir","LTR");inject$$module$build$src$core$css(b.hasCss,b.pathToMedia);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{xmlns:SVG_NS$$module$build$src$core$utils$dom,"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1","class":"blocklySvg",tabindex:"0"},a);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.DEFS, -{},a),d=String(Math.random()).substring(2);b.gridPattern=Grid$$module$build$src$core$grid.createDom(d,b.gridOptions,c);return a}; +inject$$module$build$src$core$inject=function(a,b){let c=null;c=typeof a==="string"?document.getElementById(a)||document.querySelector(a):a;var d;if(!document.contains(c)&&document!==((d=c)==null?void 0:d.ownerDocument))throw Error("Error: container is not in current document");a=new Options$$module$build$src$core$options(b||{});d=document.createElement("div");addClass$$module$build$src$core$utils$dom(d,"injectionDiv");(b==null?0:b.rtl)&&addClass$$module$build$src$core$utils$dom(d,"blocklyRTL");c.appendChild(d); +b=createDom$$module$build$src$core$inject(d,a);const e=createMainWorkspace$$module$build$src$core$inject(d,b,a);init$$module$build$src$core$inject(e);setMainWorkspace$$module$build$src$core$common(e);svgResize$$module$build$src$core$common(e);d.addEventListener("focusin",function(){setMainWorkspace$$module$build$src$core$common(e)});conditionalBind$$module$build$src$core$browser_events(d,"keydown",null,globalShortcutHandler$$module$build$src$core$common);return e}; +createDom$$module$build$src$core$inject=function(a,b){a.setAttribute("dir","LTR");inject$$module$build$src$core$css(b.hasCss,b.pathToMedia);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{xmlns:SVG_NS$$module$build$src$core$utils$dom,"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1","class":"blocklySvg"},a),d=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.DEFS, +{},c),e=String(Math.random()).substring(2);b.gridPattern=Grid$$module$build$src$core$grid.createDom(e,b.gridOptions,d,a);return c}; createMainWorkspace$$module$build$src$core$inject=function(a,b,c){c.parentWorkspace=null;c=new WorkspaceSvg$$module$build$src$core$workspace_svg(c);const d=c.options;c.scale=d.zoomOptions.startScale;b.appendChild(c.createDom("blocklyMainBackground",a));var e=c.getRenderer().getClassName();e&&addClass$$module$build$src$core$utils$dom(a,e);(e=c.getTheme().getClassName())&&addClass$$module$build$src$core$utils$dom(a,e);!d.hasCategories&&d.languageTree&&(a=c.addFlyout(Svg$$module$build$src$core$utils$svg.SVG), insertAfter$$module$build$src$core$utils$dom(a,b));d.hasTrashcan&&c.addTrashcan();d.zoomOptions&&d.zoomOptions.controls&&c.addZoomControls();c.getThemeManager().subscribe(b,"workspaceBackgroundColour","background-color");c.translate(0,0);c.addChangeListener(bumpIntoBoundsHandler$$module$build$src$core$bump_objects(c));svgResize$$module$build$src$core$common(c);createDom$$module$build$src$core$widgetdiv();createDom$$module$build$src$core$dropdowndiv();createDom$$module$build$src$core$tooltip();return c}; init$$module$build$src$core$inject=function(a){const b=a.options;var c=a.getParentSvg();conditionalBind$$module$build$src$core$browser_events(c.parentNode,"contextmenu",null,function(d){isTargetInput$$module$build$src$core$browser_events(d)||d.preventDefault()});c=conditionalBind$$module$build$src$core$browser_events(window,"resize",null,function(){hide$$module$build$src$core$tooltip();a.hideComponents(!0);repositionForWindowResize$$module$build$src$core$dropdowndiv();repositionForWindowResize$$module$build$src$core$widgetdiv(); -svgResize$$module$build$src$core$common(a);bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects(a)});a.setResizeHandlerWrapper(c);bindDocumentEvents$$module$build$src$core$inject();if(b.languageTree){c=a.getToolbox();const d=a.getFlyout(!0);c?c.init():d&&(d.init(a),d.show(b.languageTree),"function"===typeof d.scrollToStart&&d.scrollToStart())}b.hasTrashcan&&a.trashcan.init();b.zoomOptions&&b.zoomOptions.controls&&a.zoomControls_.init();b.moveOptions&&b.moveOptions.scrollbars?(a.scrollbar= -new ScrollbarPair$$module$build$src$core$scrollbar_pair(a,!0===b.moveOptions.scrollbars||!!b.moveOptions.scrollbars.horizontal,!0===b.moveOptions.scrollbars||!!b.moveOptions.scrollbars.vertical,"blocklyMainWorkspaceScrollbar"),a.scrollbar.resize()):a.setMetrics({x:.5,y:.5});b.hasSounds&&loadSounds$$module$build$src$core$inject(b.pathToMedia,a)}; -onKeyDown$$module$build$src$core$inject=function(a){const b=getMainWorkspace$$module$build$src$core$common();if(b&&!(isTargetInput$$module$build$src$core$browser_events(a)||b.rendered&&!b.isVisible()))ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.onKeyDown(b,a)}; +svgResize$$module$build$src$core$common(a);bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects(a)});a.setResizeHandlerWrapper(c);bindDocumentEvents$$module$build$src$core$inject();if(b.languageTree){c=a.getToolbox();const d=a.getFlyout(!0);c?c.init():d&&(d.init(a),d.show(b.languageTree),typeof d.scrollToStart==="function"&&d.scrollToStart())}b.hasTrashcan&&a.trashcan.init();b.zoomOptions&&b.zoomOptions.controls&&a.zoomControls_.init();b.moveOptions&&b.moveOptions.scrollbars?(a.scrollbar= +new ScrollbarPair$$module$build$src$core$scrollbar_pair(a,b.moveOptions.scrollbars===!0||!!b.moveOptions.scrollbars.horizontal,b.moveOptions.scrollbars===!0||!!b.moveOptions.scrollbars.vertical,"blocklyMainWorkspaceScrollbar"),a.scrollbar.resize()):a.setMetrics({x:.5,y:.5});b.hasSounds&&loadSounds$$module$build$src$core$inject(b.pathToMedia,a)}; bindDocumentEvents$$module$build$src$core$inject=function(){documentEventsBound$$module$build$src$core$inject||(conditionalBind$$module$build$src$core$browser_events(document,"scroll",null,function(){const a=getAllWorkspaces$$module$build$src$core$common();for(let b=0,c;c=a[b];b++)c instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&c.updateInverseScreenCTM()}),bind$$module$build$src$core$browser_events(document,"touchend",null,longStop$$module$build$src$core$touch),bind$$module$build$src$core$browser_events(document, -"touchcancel",null,longStop$$module$build$src$core$touch));documentEventsBound$$module$build$src$core$inject=!0}; -loadSounds$$module$build$src$core$inject=function(a,b){function c(){for(;e.length;){const f=e.pop();f&&unbind$$module$build$src$core$browser_events(f)}d.preload()}const d=b.getAudioManager();d.load([a+"click.mp3",a+"click.wav",a+"click.ogg"],"click");d.load([a+"disconnect.wav",a+"disconnect.mp3",a+"disconnect.ogg"],"disconnect");d.load([a+"delete.mp3",a+"delete.ogg",a+"delete.wav"],"delete");const e=[];e.push(conditionalBind$$module$build$src$core$browser_events(document,"pointermove",null,c,!0)); -e.push(conditionalBind$$module$build$src$core$browser_events(document,"touchstart",null,c,!0))}; -registerUndo$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return $.Msg$$module$build$src$core$msg.UNDO},preconditionFn(a){return 00?"enabled":"disabled"},callback(a){a.workspace.undo(!1)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,id:"undoWorkspace",weight:1})}; +registerRedo$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return $.Msg$$module$build$src$core$msg.REDO},preconditionFn(a){return a.workspace.getRedoStack().length>0?"enabled":"disabled"},callback(a){a.workspace.undo(!0)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,id:"redoWorkspace",weight:2})}; +registerCleanup$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return $.Msg$$module$build$src$core$msg.CLEAN_UP},preconditionFn(a){return a.workspace.isMovable()?a.workspace.getTopBlocks(!1).length>1?"enabled":"disabled":"hidden"},callback(a){a.workspace.cleanUp()},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,id:"cleanWorkspace",weight:3})}; +toggleOption_$$module$build$src$core$contextmenu_items=function(a,b){function c(f){e--;f.setCollapsed(a);e===0&&$.setGroup$$module$build$src$core$events$utils(!1)}let d=0,e=0;$.setGroup$$module$build$src$core$events$utils(!0);for(let f=0;fb.length?deleteNext_$$module$build$src$core$contextmenu_items(b):confirm$$module$build$src$core$dialog($.Msg$$module$build$src$core$msg.DELETE_ALL_BLOCKS.replace("%1",String(b.length)),function(c){c&&deleteNext_$$module$build$src$core$contextmenu_items(b)})}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE, +registerDeleteAll$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){if(!a.workspace)return"";a=getDeletableBlocks_$$module$build$src$core$contextmenu_items(a.workspace).length;return a===1?$.Msg$$module$build$src$core$msg.DELETE_BLOCK:$.Msg$$module$build$src$core$msg.DELETE_X_BLOCKS.replace("%1",`${a}`)},preconditionFn(a){return a.workspace?getDeletableBlocks_$$module$build$src$core$contextmenu_items(a.workspace).length> +0?"enabled":"disabled":"disabled"},callback(a){if(a.workspace){a.workspace.cancelCurrentGesture();var b=getDeletableBlocks_$$module$build$src$core$contextmenu_items(a.workspace);b.length<2?deleteNext_$$module$build$src$core$contextmenu_items(b):confirm$$module$build$src$core$dialog($.Msg$$module$build$src$core$msg.DELETE_ALL_BLOCKS.replace("%1",String(b.length)),function(c){c&&deleteNext_$$module$build$src$core$contextmenu_items(b)})}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE, id:"workspaceDelete",weight:6})};registerWorkspaceOptions_$$module$build$src$core$contextmenu_items=function(){registerUndo$$module$build$src$core$contextmenu_items();registerRedo$$module$build$src$core$contextmenu_items();registerCleanup$$module$build$src$core$contextmenu_items();registerCollapse$$module$build$src$core$contextmenu_items();registerExpand$$module$build$src$core$contextmenu_items();registerDeleteAll$$module$build$src$core$contextmenu_items()}; registerDuplicate$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return $.Msg$$module$build$src$core$msg.DUPLICATE_BLOCK},preconditionFn(a){a=a.block;return!a.isInFlyout&&a.isDeletable()&&a.isMovable()?a.isDuplicatable()?"enabled":"disabled":"hidden"},callback(a){if(a.block){var b=a.block.toCopyData();b&&paste$$module$build$src$core$clipboard(b,a.block.workspace)}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK, id:"blockDuplicate",weight:1})}; -registerComment$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){return a.block.hasIcon(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE)?$.Msg$$module$build$src$core$msg.REMOVE_COMMENT:$.Msg$$module$build$src$core$msg.ADD_COMMENT},preconditionFn(a){a=a.block;return!a.isInFlyout&&a.workspace.options.comments&&!a.isCollapsed()&&a.isEditable()?"enabled":"hidden"},callback(a){a=a.block;a.hasIcon(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE)? -a.setCommentText(null):a.setCommentText("")},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockComment",weight:2})}; +registerComment$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){return a.block.hasIcon(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE)?$.Msg$$module$build$src$core$msg.REMOVE_COMMENT:$.Msg$$module$build$src$core$msg.ADD_COMMENT},preconditionFn(a){a=a.block;return!a||a.isInFlyout||!a.workspace.options.comments||a.isCollapsed()||!a.isEditable()||!a.hasIcon(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE)&&isFullBlockField$$module$build$src$core$contextmenu_items(a)? +"hidden":"enabled"},callback(a){(a=a.block)&&a.hasIcon(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE)?a.setCommentText(null):a.setCommentText("")},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockComment",weight:2})}; registerInline$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){return a.block.getInputsInline()?$.Msg$$module$build$src$core$msg.EXTERNAL_INPUTS:$.Msg$$module$build$src$core$msg.INLINE_INPUTS},preconditionFn(a){a=a.block;if(!a.isInFlyout&&a.isMovable()&&!a.isCollapsed())for(let b=1;b(b.has(MANUALLY_DISABLED$$module$build$src$core$constants)? 1:0);return a.getInheritedDisabled()||b?"disabled":"enabled"}return"hidden"},callback(a){a=a.block;const b=$.getGroup$$module$build$src$core$events$utils();b||$.setGroup$$module$build$src$core$events$utils(!0);a.setDisabledReason(!a.hasDisabledReason(MANUALLY_DISABLED$$module$build$src$core$constants),MANUALLY_DISABLED$$module$build$src$core$constants);$.setGroup$$module$build$src$core$events$utils(b)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockDisable", weight:5})}; -registerDelete$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){var b=a.block;a=b.getDescendants(!1).length;(b=b.getNextBlock())&&(a-=b.getDescendants(!1).length);return 1===a?$.Msg$$module$build$src$core$msg.DELETE_BLOCK:$.Msg$$module$build$src$core$msg.DELETE_X_BLOCKS.replace("%1",`${a}`)},preconditionFn(a){return!a.block.isInFlyout&&a.block.isDeletable()?"enabled":"hidden"},callback(a){a.block&&a.block.checkAndDelete()}, +registerDelete$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){var b=a.block;a=b.getDescendants(!1).length;(b=b.getNextBlock())&&(a-=b.getDescendants(!1).length);return a===1?$.Msg$$module$build$src$core$msg.DELETE_BLOCK:$.Msg$$module$build$src$core$msg.DELETE_X_BLOCKS.replace("%1",`${a}`)},preconditionFn(a){return!a.block.isInFlyout&&a.block.isDeletable()?"enabled":"hidden"},callback(a){a.block&&a.block.checkAndDelete()}, scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockDelete",weight:6})}; -registerHelp$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return $.Msg$$module$build$src$core$msg.HELP},preconditionFn(a){a=a.block;return("function"===typeof a.helpUrl?a.helpUrl():a.helpUrl)?"enabled":"hidden"},callback(a){a.block.showHelp()},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockHelp",weight:7})}; -registerCommentDelete$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText:()=>$.Msg$$module$build$src$core$msg.REMOVE_COMMENT,preconditionFn(a){let b;return(null==(b=a.comment)?0:b.isDeletable())?"enabled":"hidden"},callback(a){$.setGroup$$module$build$src$core$events$utils(!0);let b;null==(b=a.comment)||b.dispose();$.setGroup$$module$build$src$core$events$utils(!1)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.COMMENT, +registerHelp$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return $.Msg$$module$build$src$core$msg.HELP},preconditionFn(a){a=a.block;return(typeof a.helpUrl==="function"?a.helpUrl():a.helpUrl)?"enabled":"hidden"},callback(a){a.block.showHelp()},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockHelp",weight:7})}; +registerCommentDelete$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText:()=>$.Msg$$module$build$src$core$msg.REMOVE_COMMENT,preconditionFn(a){let b;return((b=a.comment)==null?0:b.isDeletable())?"enabled":"hidden"},callback(a){$.setGroup$$module$build$src$core$events$utils(!0);let b;(b=a.comment)==null||b.dispose();$.setGroup$$module$build$src$core$events$utils(!1)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.COMMENT, id:"commentDelete",weight:6})}; -registerCommentDuplicate$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText:()=>$.Msg$$module$build$src$core$msg.DUPLICATE_COMMENT,preconditionFn(a){let b;return(null==(b=a.comment)?0:b.isMovable())?"enabled":"hidden"},callback(a){if(a.comment){var b=a.comment.toCopyData();b&&paste$$module$build$src$core$clipboard(b,a.comment.workspace)}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.COMMENT,id:"commentDuplicate", +registerCommentDuplicate$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText:()=>$.Msg$$module$build$src$core$msg.DUPLICATE_COMMENT,preconditionFn(a){let b;return((b=a.comment)==null?0:b.isMovable())?"enabled":"hidden"},callback(a){if(a.comment){var b=a.comment.toCopyData();b&&paste$$module$build$src$core$clipboard(b,a.comment.workspace)}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.COMMENT,id:"commentDuplicate", weight:1})}; -registerCommentCreate$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText:()=>$.Msg$$module$build$src$core$msg.ADD_COMMENT,preconditionFn:a=>{let b;return(null==(b=a.workspace)?0:b.isMutator)?"hidden":"enabled"},callback:(a,b)=>{if(a=a.workspace){$.setGroup$$module$build$src$core$events$utils(!0);var c=new RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment(a);c.setText($.Msg$$module$build$src$core$msg.WORKSPACE_COMMENT_DEFAULT_TEXT); -c.moveTo(pixelsToWorkspaceCoords$$module$build$src$core$contextmenu_items(new Coordinate$$module$build$src$core$utils$coordinate(b.clientX,b.clientY),a));$.setSelected$$module$build$src$core$common(c);$.setGroup$$module$build$src$core$events$utils(!1)}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,id:"commentCreate",weight:8})}; -pixelsToWorkspaceCoords$$module$build$src$core$contextmenu_items=function(a,b){var c=b.getInjectionDiv().getBoundingClientRect();a=new Coordinate$$module$build$src$core$utils$coordinate(a.x-c.left,a.y-c.top);c=b.getOriginOffsetInPixels();a=Coordinate$$module$build$src$core$utils$coordinate.difference(a,c);a.scale(1/b.scale);return a}; +registerCommentCreate$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText:()=>$.Msg$$module$build$src$core$msg.ADD_COMMENT,preconditionFn:a=>{let b;return((b=a.workspace)==null?0:b.isMutator)?"hidden":"enabled"},callback:(a,b,c,d)=>{if(a=a.workspace)$.setGroup$$module$build$src$core$events$utils(!0),b=new RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment(a),b.moveTo(screenToWsCoordinates$$module$build$src$core$utils$svg_math(a, +new Coordinate$$module$build$src$core$utils$coordinate(d.x,d.y))),$.getFocusManager$$module$build$src$core$focus_manager().focusNode(b),$.setGroup$$module$build$src$core$events$utils(!1)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,id:"commentCreate",weight:8})}; registerBlockOptions_$$module$build$src$core$contextmenu_items=function(){registerDuplicate$$module$build$src$core$contextmenu_items();registerComment$$module$build$src$core$contextmenu_items();registerInline$$module$build$src$core$contextmenu_items();registerCollapseExpandBlock$$module$build$src$core$contextmenu_items();registerDisable$$module$build$src$core$contextmenu_items();registerDelete$$module$build$src$core$contextmenu_items();registerHelp$$module$build$src$core$contextmenu_items()}; registerCommentOptions$$module$build$src$core$contextmenu_items=function(){registerCommentDuplicate$$module$build$src$core$contextmenu_items();registerCommentDelete$$module$build$src$core$contextmenu_items();registerCommentCreate$$module$build$src$core$contextmenu_items()};registerDefaultOptions$$module$build$src$core$contextmenu_items=function(){registerWorkspaceOptions_$$module$build$src$core$contextmenu_items();registerBlockOptions_$$module$build$src$core$contextmenu_items()}; -isPaster$$module$build$src$core$interfaces$i_paster=function(a){return void 0!==a.paste};isRenderedElement$$module$build$src$core$interfaces$i_rendered_element=function(a){return void 0!==a.getSvgRoot};isSelectable$$module$build$src$core$interfaces$i_selectable=function(a){return"string"===typeof a.id&&void 0!==a.workspace&&void 0!==a.select&&void 0!==a.unselect};isSelectableToolboxItem$$module$build$src$core$interfaces$i_selectable_toolbox_item=function(a){return a.isSelectable()}; -hideChaff$$module$build$src$core$blockly=function(a){getMainWorkspace$$module$build$src$core$common().hideChaff(a)};$jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;$jscomp.FORCE_POLYFILL_PROMISE=!1;$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION=!1; -$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};$jscomp.getGlobal=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b>>0,$jscomp.propertyToPolyfillSymbol[e]=$jscomp.IS_SYMBOL_NATIVE? -$jscomp.global.Symbol(e):$jscomp.POLYFILL_PREFIX+c+"$"+e),$jscomp.defineProperty(d,$jscomp.propertyToPolyfillSymbol[e],{configurable:!0,writable:!0,value:b})))};$jscomp.underscoreProtoCanBeSet=function(){var a={a:!0},b={};try{return b.__proto__=a,b.a}catch(c){}return!1}; -$jscomp.setPrototypeOf=$jscomp.TRUST_ES6_POLYFILLS&&"function"==typeof Object.setPrototypeOf?Object.setPrototypeOf:$jscomp.underscoreProtoCanBeSet()?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null;$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b>>0,$jscomp.propertyToPolyfillSymbol[e]=$jscomp.IS_SYMBOL_NATIVE? +$jscomp.global.Symbol(e):$jscomp.POLYFILL_PREFIX+c+"$"+e),$jscomp.defineProperty(d,$jscomp.propertyToPolyfillSymbol[e],{configurable:!0,writable:!0,value:b})))}; +$jscomp.getConstructImplementation=function(){function a(){function c(){}new c;Reflect.construct(c,[],function(){});return new c instanceof c}if($jscomp.TRUST_ES6_POLYFILLS&&typeof Reflect!="undefined"&&Reflect.construct){if(a())return Reflect.construct;var b=Reflect.construct;return function(c,d,e){c=b(c,d);e&&Reflect.setPrototypeOf(c,e.prototype);return c}}return function(c,d,e){e===void 0&&(e=c);e=$jscomp.objectCreate(e.prototype||Object.prototype);return Function.prototype.apply.call(c,e,d)|| +e}};$jscomp.construct={valueOf:$jscomp.getConstructImplementation}.valueOf();$jscomp.underscoreProtoCanBeSet=function(){var a={a:!0},b={};try{return b.__proto__=a,b.a}catch(c){}return!1};$jscomp.setPrototypeOf=$jscomp.ASSUME_ES6||$jscomp.TRUST_ES6_POLYFILLS&&typeof Object.setPrototypeOf=="function"?Object.setPrototypeOf:$jscomp.underscoreProtoCanBeSet()?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null; +$jscomp.inherits=function(a,b){a.prototype=$jscomp.objectCreate(b.prototype);a.prototype.constructor=a;if($jscomp.ASSUME_ES6||$jscomp.setPrototypeOf){var c=$jscomp.setPrototypeOf;c(a,b)}else for(c in b)if(c!="prototype")if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.superClass_=b.prototype};$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b0;){var a=this.properties_.pop();if(a in this.object_)return a}return null};$jscomp.generator.Context.PropertyIterator.prototype.getNext=$jscomp.generator.Context.PropertyIterator.prototype.getNext;$jscomp.generator.Engine_=function(a){this.context_=new $jscomp.generator.Context;this.program_=a}; $jscomp.generator.Engine_.prototype.next_=function(a){this.context_.start_();if(this.context_.yieldAllIterator_)return this.yieldAllStep_(this.context_.yieldAllIterator_.next,a,this.context_.next_);this.context_.next_(a);return this.nextStep_()}; $jscomp.generator.Engine_.prototype.return_=function(a){this.context_.start_();var b=this.context_.yieldAllIterator_;if(b)return this.yieldAllStep_("return"in b?b["return"]:function(c){return{value:c,done:!0}},a,this.context_.return);this.context_.return(a);return this.nextStep_()}; $jscomp.generator.Engine_.prototype.throw_=function(a){this.context_.start_();if(this.context_.yieldAllIterator_)return this.yieldAllStep_(this.context_.yieldAllIterator_["throw"],a,this.context_.next_);this.context_.throw_(a);return this.nextStep_()}; @@ -493,81 +531,111 @@ $jscomp.generator.Engine_.prototype.yieldAllStep_=function(a,b,c){try{var d=a.ca $jscomp.generator.Engine_.prototype.nextStep_=function(){for(;this.context_.nextAddress;)try{var a=this.program_(this.context_);if(a)return this.context_.stop_(),{value:a.value,done:!1}}catch(b){this.context_.yieldResult=void 0,this.context_.throw_(b)}this.context_.stop_();if(this.context_.abruptCompletion_){a=this.context_.abruptCompletion_;this.context_.abruptCompletion_=null;if(a.isException)throw a.exception;return{value:a.return,done:!0}}return{value:void 0,done:!0}}; $jscomp.generator.Generator_=function(a){this.next=function(b){return a.next_(b)};this.throw=function(b){return a.throw_(b)};this.return=function(b){return a.return_(b)};this[Symbol.iterator]=function(){return this}};$jscomp.generator.createGenerator=function(a,b){b=new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(b));$jscomp.setPrototypeOf&&a.prototype&&$jscomp.setPrototypeOf(b,a.prototype);return b}; $jscomp.asyncExecutePromiseGenerator=function(a){function b(d){return a.next(d)}function c(d){return a.throw(d)}return new Promise(function(d,e){function f(g){g.done?d(g.value):Promise.resolve(g.value).then(b,c).then(f,e)}f(a.next())})};$jscomp.asyncExecutePromiseGeneratorFunction=function(a){return $jscomp.asyncExecutePromiseGenerator(a())};$jscomp.asyncExecutePromiseGeneratorProgram=function(a){return $jscomp.asyncExecutePromiseGenerator(new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(a)))}; -$jscomp.polyfill("globalThis",function(a){return a||$jscomp.global},"es_2020","es3");$jscomp.polyfill("Array.prototype.includes",function(a){return a?a:function(b,c){var d=this;d instanceof String&&(d=String(d));var e=d.length;c=c||0;for(0>c&&(c=Math.max(c+e,0));c0?(d=Array.prototype.flat.call(d,b-1),c.push.apply(c,d)):c.push(d)});return c}},"es9","es5"); +$jscomp.polyfill("Object.entries",function(a){return a?a:function(b){var c=[],d;for(d in b)$jscomp.owns(b,d)&&c.push([d,b[d]]);return c}},"es8","es3");$jscomp.polyfill("Object.values",function(a){return a?a:function(b){var c=[],d;for(d in b)$jscomp.owns(b,d)&&c.push(b[d]);return c}},"es8","es3"); var typeMap$$module$build$src$core$registry=Object.create(null),TEST_ONLY$$module$build$src$core$registry={typeMap:typeMap$$module$build$src$core$registry},nameMap$$module$build$src$core$registry=Object.create(null),DEFAULT$$module$build$src$core$registry="default",Type$$module$build$src$core$registry=class{constructor(a){this.name=a}toString(){return this.name}};Type$$module$build$src$core$registry.CONNECTION_CHECKER=new Type$$module$build$src$core$registry("connectionChecker"); Type$$module$build$src$core$registry.CONNECTION_PREVIEWER=new Type$$module$build$src$core$registry("connectionPreviewer");Type$$module$build$src$core$registry.CURSOR=new Type$$module$build$src$core$registry("cursor");Type$$module$build$src$core$registry.EVENT=new Type$$module$build$src$core$registry("event");Type$$module$build$src$core$registry.FIELD=new Type$$module$build$src$core$registry("field");Type$$module$build$src$core$registry.INPUT=new Type$$module$build$src$core$registry("input"); Type$$module$build$src$core$registry.RENDERER=new Type$$module$build$src$core$registry("renderer");Type$$module$build$src$core$registry.TOOLBOX=new Type$$module$build$src$core$registry("toolbox");Type$$module$build$src$core$registry.THEME=new Type$$module$build$src$core$registry("theme");Type$$module$build$src$core$registry.TOOLBOX_ITEM=new Type$$module$build$src$core$registry("toolboxItem");Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX=new Type$$module$build$src$core$registry("flyoutsVerticalToolbox"); -Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX=new Type$$module$build$src$core$registry("flyoutsHorizontalToolbox");Type$$module$build$src$core$registry.METRICS_MANAGER=new Type$$module$build$src$core$registry("metricsManager");Type$$module$build$src$core$registry.BLOCK_DRAGGER=new Type$$module$build$src$core$registry("blockDragger");Type$$module$build$src$core$registry.SERIALIZER=new Type$$module$build$src$core$registry("serializer");Type$$module$build$src$core$registry.ICON=new Type$$module$build$src$core$registry("icon"); -Type$$module$build$src$core$registry.PASTER=new Type$$module$build$src$core$registry("paster");var module$build$src$core$registry={DEFAULT:DEFAULT$$module$build$src$core$registry,TEST_ONLY:TEST_ONLY$$module$build$src$core$registry};module$build$src$core$registry.Type=Type$$module$build$src$core$registry;module$build$src$core$registry.getAllItems=getAllItems$$module$build$src$core$registry;module$build$src$core$registry.getClass=getClass$$module$build$src$core$registry; -module$build$src$core$registry.getClassFromOptions=getClassFromOptions$$module$build$src$core$registry;module$build$src$core$registry.getObject=getObject$$module$build$src$core$registry;module$build$src$core$registry.hasItem=hasItem$$module$build$src$core$registry;module$build$src$core$registry.register=register$$module$build$src$core$registry;module$build$src$core$registry.unregister=unregister$$module$build$src$core$registry;var Blocks$$module$build$src$core$blocks=Object.create(null),module$build$src$core$blocks={Blocks:Blocks$$module$build$src$core$blocks};var EventType$$module$build$src$core$events$type; -(function(a){a.BLOCK_CREATE="create";a.BLOCK_DELETE="delete";a.BLOCK_CHANGE="change";a.BLOCK_FIELD_INTERMEDIATE_CHANGE="block_field_intermediate_change";a.BLOCK_MOVE="move";a.VAR_CREATE="var_create";a.VAR_DELETE="var_delete";a.VAR_RENAME="var_rename";a.UI="ui";a.BLOCK_DRAG="drag";a.SELECTED="selected";a.CLICK="click";a.MARKER_MOVE="marker_move";a.BUBBLE_OPEN="bubble_open";a.TRASHCAN_OPEN="trashcan_open";a.TOOLBOX_ITEM_SELECT="toolbox_item_select";a.THEME_CHANGE="theme_change";a.VIEWPORT_CHANGE="viewport_change"; -a.COMMENT_CREATE="comment_create";a.COMMENT_DELETE="comment_delete";a.COMMENT_CHANGE="comment_change";a.COMMENT_MOVE="comment_move";a.COMMENT_RESIZE="comment_resize";a.COMMENT_DRAG="comment_drag";a.COMMENT_COLLAPSE="comment_collapse";a.FINISHED_LOADING="finished_loading"})(EventType$$module$build$src$core$events$type||(EventType$$module$build$src$core$events$type={})); -var BUMP_EVENTS$$module$build$src$core$events$type=[EventType$$module$build$src$core$events$type.BLOCK_CREATE,EventType$$module$build$src$core$events$type.BLOCK_MOVE,EventType$$module$build$src$core$events$type.COMMENT_CREATE,EventType$$module$build$src$core$events$type.COMMENT_MOVE],module$build$src$core$events$type={BUMP_EVENTS:BUMP_EVENTS$$module$build$src$core$events$type};module$build$src$core$events$type.EventType=EventType$$module$build$src$core$events$type;var previousWarnings$$module$build$src$core$utils$deprecation=new Set,module$build$src$core$utils$deprecation={};module$build$src$core$utils$deprecation.warn=warn$$module$build$src$core$utils$deprecation;var soup$$module$build$src$core$utils$idgenerator="!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",internal$$module$build$src$core$utils$idgenerator={genUid:()=>{const a=soup$$module$build$src$core$utils$idgenerator.length,b=[];for(let c=0;20>c;c++)b[c]=soup$$module$build$src$core$utils$idgenerator.charAt(Math.random()*a);return b.join("")}},TEST_ONLY$$module$build$src$core$utils$idgenerator=internal$$module$build$src$core$utils$idgenerator,nextId$$module$build$src$core$utils$idgenerator= -0,module$build$src$core$utils$idgenerator={TEST_ONLY:internal$$module$build$src$core$utils$idgenerator};module$build$src$core$utils$idgenerator.genUid=genUid$$module$build$src$core$utils$idgenerator;module$build$src$core$utils$idgenerator.getNextUniqueId=getNextUniqueId$$module$build$src$core$utils$idgenerator;var module$build$src$core$events$predicates={};module$build$src$core$events$predicates.isBlockChange=isBlockChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockCreate=isBlockCreate$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockDelete=isBlockDelete$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockDrag=isBlockDrag$$module$build$src$core$events$predicates; -module$build$src$core$events$predicates.isBlockFieldIntermediateChange=isBlockFieldIntermediateChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockMove=isBlockMove$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBubbleOpen=isBubbleOpen$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isClick=isClick$$module$build$src$core$events$predicates; -module$build$src$core$events$predicates.isCommentChange=isCommentChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentCollapse=isCommentCollapse$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentCreate=isCommentCreate$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentDelete=isCommentDelete$$module$build$src$core$events$predicates; -module$build$src$core$events$predicates.isCommentDrag=isCommentDrag$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentMove=isCommentMove$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentResize=isCommentResize$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isFinishedLoading=isFinishedLoading$$module$build$src$core$events$predicates; -module$build$src$core$events$predicates.isMarkerMove=isMarkerMove$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isSelected=isSelected$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isThemeChange=isThemeChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isToolboxItemSelect=isToolboxItemSelect$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isTrashcanOpen=isTrashcanOpen$$module$build$src$core$events$predicates; -module$build$src$core$events$predicates.isVarCreate=isVarCreate$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isVarDelete=isVarDelete$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isVarRename=isVarRename$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isViewportChange=isViewportChange$$module$build$src$core$events$predicates;var group$$module$build$src$core$events$utils="",recordUndo$$module$build$src$core$events$utils=!0,disabled$$module$build$src$core$events$utils=0,ORPHANED_BLOCK_DISABLED_REASON$$module$build$src$core$events$utils="ORPHANED_BLOCK",FIRE_QUEUE$$module$build$src$core$events$utils=[],TEST_ONLY$$module$build$src$core$events$utils={FIRE_QUEUE:FIRE_QUEUE$$module$build$src$core$events$utils,enqueueEvent:enqueueEvent$$module$build$src$core$events$utils,fireNow:fireNow$$module$build$src$core$events$utils,fireInternal:fireInternal$$module$build$src$core$events$utils, -setGroupInternal:setGroupInternal$$module$build$src$core$events$utils},module$build$src$core$events$utils={TEST_ONLY:TEST_ONLY$$module$build$src$core$events$utils};module$build$src$core$events$utils.clearPendingUndo=clearPendingUndo$$module$build$src$core$events$utils;module$build$src$core$events$utils.disable=$.disable$$module$build$src$core$events$utils;module$build$src$core$events$utils.disableOrphans=disableOrphans$$module$build$src$core$events$utils; -module$build$src$core$events$utils.enable=$.enable$$module$build$src$core$events$utils;module$build$src$core$events$utils.filter=filter$$module$build$src$core$events$utils;module$build$src$core$events$utils.fire=fire$$module$build$src$core$events$utils;module$build$src$core$events$utils.fromJson=fromJson$$module$build$src$core$events$utils;module$build$src$core$events$utils.get=get$$module$build$src$core$events$utils;module$build$src$core$events$utils.getDescendantIds=getDescendantIds$$module$build$src$core$events$utils; -module$build$src$core$events$utils.getGroup=$.getGroup$$module$build$src$core$events$utils;module$build$src$core$events$utils.getRecordUndo=getRecordUndo$$module$build$src$core$events$utils;module$build$src$core$events$utils.isEnabled=isEnabled$$module$build$src$core$events$utils;module$build$src$core$events$utils.setGroup=$.setGroup$$module$build$src$core$events$utils;module$build$src$core$events$utils.setRecordUndo=$.setRecordUndo$$module$build$src$core$events$utils;var WorkspaceDB_$$module$build$src$core$common=Object.create(null),mainWorkspace$$module$build$src$core$common,selected$$module$build$src$core$common=null,parentContainer$$module$build$src$core$common,draggingConnections$$module$build$src$core$common=[],TEST_ONLY$$module$build$src$core$common={defineBlocksWithJsonArrayInternal:defineBlocksWithJsonArrayInternal$$module$build$src$core$common},module$build$src$core$common={TEST_ONLY:TEST_ONLY$$module$build$src$core$common}; -module$build$src$core$common.createBlockDefinitionsFromJsonArray=$.createBlockDefinitionsFromJsonArray$$module$build$src$core$common;module$build$src$core$common.defineBlocks=$.defineBlocks$$module$build$src$core$common;module$build$src$core$common.defineBlocksWithJsonArray=defineBlocksWithJsonArray$$module$build$src$core$common;module$build$src$core$common.draggingConnections=draggingConnections$$module$build$src$core$common;module$build$src$core$common.getAllWorkspaces=getAllWorkspaces$$module$build$src$core$common; -module$build$src$core$common.getBlockTypeCounts=getBlockTypeCounts$$module$build$src$core$common;module$build$src$core$common.getMainWorkspace=getMainWorkspace$$module$build$src$core$common;module$build$src$core$common.getParentContainer=getParentContainer$$module$build$src$core$common;module$build$src$core$common.getSelected=getSelected$$module$build$src$core$common;module$build$src$core$common.getWorkspaceById=getWorkspaceById$$module$build$src$core$common; -module$build$src$core$common.registerWorkspace=registerWorkspace$$module$build$src$core$common;module$build$src$core$common.setMainWorkspace=setMainWorkspace$$module$build$src$core$common;module$build$src$core$common.setParentContainer=setParentContainer$$module$build$src$core$common;module$build$src$core$common.setSelected=$.setSelected$$module$build$src$core$common;module$build$src$core$common.svgResize=svgResize$$module$build$src$core$common;module$build$src$core$common.unregisterWorkpace=unregisterWorkpace$$module$build$src$core$common;var Abstract$$module$build$src$core$events$events_abstract=class{constructor(){this.workspaceId=void 0;this.isUiEvent=!1;this.type="";this.group=$.getGroup$$module$build$src$core$events$utils();this.recordUndo=getRecordUndo$$module$build$src$core$events$utils()}toJson(){return{type:this.type,group:this.group}}static fromJson(a,b,c){c.isBlank=!1;c.group=a.group||"";c.workspaceId=b.id;return c}isNull(){return!1}run(a){}getEventWorkspace_(){let a;this.workspaceId&&(a=getWorkspaceById$$module$build$src$core$common(this.workspaceId)); -if(!a)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return a}},module$build$src$core$events$events_abstract={};module$build$src$core$events$events_abstract.Abstract=Abstract$$module$build$src$core$events$events_abstract;var UiBase$$module$build$src$core$events$events_ui_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.recordUndo=!1;this.isUiEvent=!0;this.isBlank="undefined"===typeof a;this.workspaceId=a?a:""}},module$build$src$core$events$events_ui_base={};module$build$src$core$events$events_ui_base.UiBase=UiBase$$module$build$src$core$events$events_ui_base;var Click$$module$build$src$core$events$events_click=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){b=a?a.workspace.id:b;null===b&&(b=void 0);super(b);this.type=EventType$$module$build$src$core$events$type.CLICK;this.blockId=a?a.id:void 0;this.targetType=c}toJson(){const a=super.toJson();if(!this.targetType)throw Error("The click target type is undefined. Either pass a block to the constructor, or call fromJson");a.targetType=this.targetType;a.blockId=this.blockId; -return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new Click$$module$build$src$core$events$events_click);b.targetType=a.targetType;b.blockId=a.blockId;return b}},ClickTarget$$module$build$src$core$events$events_click;(function(a){a.BLOCK="block";a.WORKSPACE="workspace";a.ZOOM_CONTROLS="zoom_controls"})(ClickTarget$$module$build$src$core$events$events_click||(ClickTarget$$module$build$src$core$events$events_click={})); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.CLICK,Click$$module$build$src$core$events$events_click);var module$build$src$core$events$events_click={};module$build$src$core$events$events_click.Click=Click$$module$build$src$core$events$events_click;module$build$src$core$events$events_click.ClickTarget=ClickTarget$$module$build$src$core$events$events_click;var LONGPRESS$$module$build$src$core$touch=750,TOUCH_ENABLED$$module$build$src$core$touch="ontouchstart"in globalThis||!!(globalThis.document&&document.documentElement&&"ontouchstart"in document.documentElement)||!(!globalThis.navigator||!globalThis.navigator.maxTouchPoints&&!globalThis.navigator.msMaxTouchPoints),touchIdentifier_$$module$build$src$core$touch=null,TOUCH_MAP$$module$build$src$core$touch={mousedown:["pointerdown"],mouseenter:["pointerenter"],mouseleave:["pointerleave"],mousemove:["pointermove"], +Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX=new Type$$module$build$src$core$registry("flyoutsHorizontalToolbox");Type$$module$build$src$core$registry.FLYOUT_INFLATER=new Type$$module$build$src$core$registry("flyoutInflater");Type$$module$build$src$core$registry.METRICS_MANAGER=new Type$$module$build$src$core$registry("metricsManager");Type$$module$build$src$core$registry.BLOCK_DRAGGER=new Type$$module$build$src$core$registry("blockDragger"); +Type$$module$build$src$core$registry.SERIALIZER=new Type$$module$build$src$core$registry("serializer");Type$$module$build$src$core$registry.ICON=new Type$$module$build$src$core$registry("icon");Type$$module$build$src$core$registry.PASTER=new Type$$module$build$src$core$registry("paster");Type$$module$build$src$core$registry.VARIABLE_MODEL=new Type$$module$build$src$core$registry("variableModel");Type$$module$build$src$core$registry.VARIABLE_MAP=new Type$$module$build$src$core$registry("variableMap"); +var module$build$src$core$registry={DEFAULT:DEFAULT$$module$build$src$core$registry,TEST_ONLY:TEST_ONLY$$module$build$src$core$registry};module$build$src$core$registry.Type=Type$$module$build$src$core$registry;module$build$src$core$registry.getAllItems=getAllItems$$module$build$src$core$registry;module$build$src$core$registry.getClass=getClass$$module$build$src$core$registry;module$build$src$core$registry.getClassFromOptions=getClassFromOptions$$module$build$src$core$registry; +module$build$src$core$registry.getObject=getObject$$module$build$src$core$registry;module$build$src$core$registry.hasItem=hasItem$$module$build$src$core$registry;module$build$src$core$registry.register=register$$module$build$src$core$registry;module$build$src$core$registry.unregister=unregister$$module$build$src$core$registry;var Blocks$$module$build$src$core$blocks=Object.create(null),module$build$src$core$blocks={Blocks:Blocks$$module$build$src$core$blocks};var LONGPRESS$$module$build$src$core$touch=750,TOUCH_ENABLED$$module$build$src$core$touch="ontouchstart"in globalThis||!!(globalThis.document&&document.documentElement&&"ontouchstart"in document.documentElement)||!(!globalThis.navigator||!globalThis.navigator.maxTouchPoints&&!globalThis.navigator.msMaxTouchPoints),touchIdentifier_$$module$build$src$core$touch=null,TOUCH_MAP$$module$build$src$core$touch={mousedown:["pointerdown"],mouseenter:["pointerenter"],mouseleave:["pointerleave"],mousemove:["pointermove"], mouseout:["pointerout"],mouseover:["pointerover"],mouseup:["pointerup","pointercancel"],touchend:["pointerup"],touchcancel:["pointercancel"]},longPid_$$module$build$src$core$touch=0,module$build$src$core$touch={TOUCH_ENABLED:TOUCH_ENABLED$$module$build$src$core$touch,TOUCH_MAP:TOUCH_MAP$$module$build$src$core$touch};module$build$src$core$touch.checkTouchIdentifier=checkTouchIdentifier$$module$build$src$core$touch;module$build$src$core$touch.clearTouchIdentifier=clearTouchIdentifier$$module$build$src$core$touch; module$build$src$core$touch.getTouchIdentifierFromEvent=getTouchIdentifierFromEvent$$module$build$src$core$touch;module$build$src$core$touch.longStart=longStart$$module$build$src$core$touch;module$build$src$core$touch.longStop=longStop$$module$build$src$core$touch;module$build$src$core$touch.shouldHandleEvent=shouldHandleEvent$$module$build$src$core$touch;var rawUserAgent$$module$build$src$core$utils$useragent,isJavaFx$$module$build$src$core$utils$useragent,isWebKit$$module$build$src$core$utils$useragent,isGecko$$module$build$src$core$utils$useragent,isAndroid$$module$build$src$core$utils$useragent,isIPad$$module$build$src$core$utils$useragent,isIPhone$$module$build$src$core$utils$useragent,isMac$$module$build$src$core$utils$useragent,isTablet$$module$build$src$core$utils$useragent,isMobile$$module$build$src$core$utils$useragent; (function(a){function b(d){return c.includes(d.toUpperCase())}rawUserAgent$$module$build$src$core$utils$useragent=a;const c=rawUserAgent$$module$build$src$core$utils$useragent.toUpperCase();isJavaFx$$module$build$src$core$utils$useragent=b("JavaFX");isWebKit$$module$build$src$core$utils$useragent=b("WebKit");isGecko$$module$build$src$core$utils$useragent=b("Gecko")&&!isWebKit$$module$build$src$core$utils$useragent;isAndroid$$module$build$src$core$utils$useragent=b("Android");a=globalThis.navigator&& -globalThis.navigator.maxTouchPoints;isIPad$$module$build$src$core$utils$useragent=b("iPad")||b("Macintosh")&&00;isIPhone$$module$build$src$core$utils$useragent=b("iPhone")&&!isIPad$$module$build$src$core$utils$useragent;isMac$$module$build$src$core$utils$useragent=b("Macintosh");isTablet$$module$build$src$core$utils$useragent=isIPad$$module$build$src$core$utils$useragent||isAndroid$$module$build$src$core$utils$useragent&&!b("Mobile")||b("Silk");isMobile$$module$build$src$core$utils$useragent=!isTablet$$module$build$src$core$utils$useragent&& (isIPhone$$module$build$src$core$utils$useragent||isAndroid$$module$build$src$core$utils$useragent)})(globalThis.navigator&&globalThis.navigator.userAgent||""); var raw$$module$build$src$core$utils$useragent=rawUserAgent$$module$build$src$core$utils$useragent,JavaFx$$module$build$src$core$utils$useragent=isJavaFx$$module$build$src$core$utils$useragent,GECKO$$module$build$src$core$utils$useragent=isGecko$$module$build$src$core$utils$useragent,ANDROID$$module$build$src$core$utils$useragent=isAndroid$$module$build$src$core$utils$useragent,IPAD$$module$build$src$core$utils$useragent=isIPad$$module$build$src$core$utils$useragent,IPHONE$$module$build$src$core$utils$useragent= isIPhone$$module$build$src$core$utils$useragent,MAC$$module$build$src$core$utils$useragent=isMac$$module$build$src$core$utils$useragent,MOBILE$$module$build$src$core$utils$useragent=isMobile$$module$build$src$core$utils$useragent,module$build$src$core$utils$useragent={ANDROID:ANDROID$$module$build$src$core$utils$useragent,GECKO:GECKO$$module$build$src$core$utils$useragent,IPAD:IPAD$$module$build$src$core$utils$useragent,IPHONE:IPHONE$$module$build$src$core$utils$useragent,JavaFx:JavaFx$$module$build$src$core$utils$useragent, MAC:MAC$$module$build$src$core$utils$useragent,MOBILE:MOBILE$$module$build$src$core$utils$useragent,raw:raw$$module$build$src$core$utils$useragent};var LINE_MODE_MULTIPLIER$$module$build$src$core$browser_events=40,PAGE_MODE_MULTIPLIER$$module$build$src$core$browser_events=125,module$build$src$core$browser_events={};module$build$src$core$browser_events.bind=bind$$module$build$src$core$browser_events;module$build$src$core$browser_events.conditionalBind=conditionalBind$$module$build$src$core$browser_events;module$build$src$core$browser_events.getScrollDeltaPixels=getScrollDeltaPixels$$module$build$src$core$browser_events; -module$build$src$core$browser_events.isRightButton=isRightButton$$module$build$src$core$browser_events;module$build$src$core$browser_events.isTargetInput=isTargetInput$$module$build$src$core$browser_events;module$build$src$core$browser_events.mouseToSvg=mouseToSvg$$module$build$src$core$browser_events;module$build$src$core$browser_events.unbind=unbind$$module$build$src$core$browser_events;var module$build$src$core$utils$array={};module$build$src$core$utils$array.removeElem=removeElem$$module$build$src$core$utils$array;var Capability$$module$build$src$core$component_manager=class{constructor(a){this.name=a}toString(){return this.name}};Capability$$module$build$src$core$component_manager.POSITIONABLE=new Capability$$module$build$src$core$component_manager("positionable");Capability$$module$build$src$core$component_manager.DRAG_TARGET=new Capability$$module$build$src$core$component_manager("drag_target");Capability$$module$build$src$core$component_manager.DELETE_AREA=new Capability$$module$build$src$core$component_manager("delete_area"); +module$build$src$core$browser_events.isRightButton=isRightButton$$module$build$src$core$browser_events;module$build$src$core$browser_events.isTargetInput=isTargetInput$$module$build$src$core$browser_events;module$build$src$core$browser_events.mouseToSvg=mouseToSvg$$module$build$src$core$browser_events;module$build$src$core$browser_events.unbind=unbind$$module$build$src$core$browser_events;var EventType$$module$build$src$core$events$type; +(function(a){a.BLOCK_CREATE="create";a.BLOCK_DELETE="delete";a.BLOCK_CHANGE="change";a.BLOCK_FIELD_INTERMEDIATE_CHANGE="block_field_intermediate_change";a.BLOCK_MOVE="move";a.VAR_CREATE="var_create";a.VAR_DELETE="var_delete";a.VAR_RENAME="var_rename";a.VAR_TYPE_CHANGE="var_type_change";a.UI="ui";a.BLOCK_DRAG="drag";a.SELECTED="selected";a.CLICK="click";a.MARKER_MOVE="marker_move";a.BUBBLE_OPEN="bubble_open";a.TRASHCAN_OPEN="trashcan_open";a.TOOLBOX_ITEM_SELECT="toolbox_item_select";a.THEME_CHANGE= +"theme_change";a.VIEWPORT_CHANGE="viewport_change";a.COMMENT_CREATE="comment_create";a.COMMENT_DELETE="comment_delete";a.COMMENT_CHANGE="comment_change";a.COMMENT_MOVE="comment_move";a.COMMENT_RESIZE="comment_resize";a.COMMENT_DRAG="comment_drag";a.COMMENT_COLLAPSE="comment_collapse";a.FINISHED_LOADING="finished_loading"})(EventType$$module$build$src$core$events$type||(EventType$$module$build$src$core$events$type={})); +var BUMP_EVENTS$$module$build$src$core$events$type=[EventType$$module$build$src$core$events$type.BLOCK_CREATE,EventType$$module$build$src$core$events$type.BLOCK_MOVE,EventType$$module$build$src$core$events$type.COMMENT_CREATE,EventType$$module$build$src$core$events$type.COMMENT_MOVE],module$build$src$core$events$type={BUMP_EVENTS:BUMP_EVENTS$$module$build$src$core$events$type};module$build$src$core$events$type.EventType=EventType$$module$build$src$core$events$type;var soup$$module$build$src$core$utils$idgenerator="!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",internal$$module$build$src$core$utils$idgenerator={genUid:()=>{const a=soup$$module$build$src$core$utils$idgenerator.length,b=[];for(let c=0;c<20;c++)b[c]=soup$$module$build$src$core$utils$idgenerator.charAt(Math.random()*a);return b.join("")}},TEST_ONLY$$module$build$src$core$utils$idgenerator=internal$$module$build$src$core$utils$idgenerator,nextId$$module$build$src$core$utils$idgenerator= +0,module$build$src$core$utils$idgenerator={TEST_ONLY:internal$$module$build$src$core$utils$idgenerator};module$build$src$core$utils$idgenerator.genUid=genUid$$module$build$src$core$utils$idgenerator;module$build$src$core$utils$idgenerator.getNextUniqueId=getNextUniqueId$$module$build$src$core$utils$idgenerator;var module$build$src$core$events$predicates={};module$build$src$core$events$predicates.isBlockChange=isBlockChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockCreate=isBlockCreate$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockDelete=isBlockDelete$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockDrag=isBlockDrag$$module$build$src$core$events$predicates; +module$build$src$core$events$predicates.isBlockFieldIntermediateChange=isBlockFieldIntermediateChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBlockMove=isBlockMove$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isBubbleOpen=isBubbleOpen$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isClick=isClick$$module$build$src$core$events$predicates; +module$build$src$core$events$predicates.isCommentChange=isCommentChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentCollapse=isCommentCollapse$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentCreate=isCommentCreate$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentDelete=isCommentDelete$$module$build$src$core$events$predicates; +module$build$src$core$events$predicates.isCommentDrag=isCommentDrag$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentMove=isCommentMove$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isCommentResize=isCommentResize$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isFinishedLoading=isFinishedLoading$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isSelected=isSelected$$module$build$src$core$events$predicates; +module$build$src$core$events$predicates.isThemeChange=isThemeChange$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isToolboxItemSelect=isToolboxItemSelect$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isTrashcanOpen=isTrashcanOpen$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isVarCreate=isVarCreate$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isVarDelete=isVarDelete$$module$build$src$core$events$predicates; +module$build$src$core$events$predicates.isVarRename=isVarRename$$module$build$src$core$events$predicates;module$build$src$core$events$predicates.isViewportChange=isViewportChange$$module$build$src$core$events$predicates;var group$$module$build$src$core$events$utils="",recordUndo$$module$build$src$core$events$utils=!0,disabled$$module$build$src$core$events$utils=0,ORPHANED_BLOCK_DISABLED_REASON$$module$build$src$core$events$utils="ORPHANED_BLOCK",FIRE_QUEUE$$module$build$src$core$events$utils=[],TEST_ONLY$$module$build$src$core$events$utils={FIRE_QUEUE:FIRE_QUEUE$$module$build$src$core$events$utils,enqueueEvent:enqueueEvent$$module$build$src$core$events$utils,fireNow:fireNow$$module$build$src$core$events$utils,fireInternal:fireInternal$$module$build$src$core$events$utils, +setGroupInternal:setGroupInternal$$module$build$src$core$events$utils},module$build$src$core$events$utils={TEST_ONLY:TEST_ONLY$$module$build$src$core$events$utils};module$build$src$core$events$utils.clearPendingUndo=clearPendingUndo$$module$build$src$core$events$utils;module$build$src$core$events$utils.disable=$.disable$$module$build$src$core$events$utils;module$build$src$core$events$utils.disableOrphans=disableOrphans$$module$build$src$core$events$utils; +module$build$src$core$events$utils.enable=$.enable$$module$build$src$core$events$utils;module$build$src$core$events$utils.filter=filter$$module$build$src$core$events$utils;module$build$src$core$events$utils.fire=fire$$module$build$src$core$events$utils;module$build$src$core$events$utils.fromJson=fromJson$$module$build$src$core$events$utils;module$build$src$core$events$utils.get=get$$module$build$src$core$events$utils;module$build$src$core$events$utils.getDescendantIds=getDescendantIds$$module$build$src$core$events$utils; +module$build$src$core$events$utils.getGroup=$.getGroup$$module$build$src$core$events$utils;module$build$src$core$events$utils.getRecordUndo=getRecordUndo$$module$build$src$core$events$utils;module$build$src$core$events$utils.isEnabled=isEnabled$$module$build$src$core$events$utils;module$build$src$core$events$utils.setGroup=$.setGroup$$module$build$src$core$events$utils;module$build$src$core$events$utils.setRecordUndo=$.setRecordUndo$$module$build$src$core$events$utils;var SVG_NS$$module$build$src$core$utils$dom="http://www.w3.org/2000/svg",HTML_NS$$module$build$src$core$utils$dom="http://www.w3.org/1999/xhtml",XLINK_NS$$module$build$src$core$utils$dom="http://www.w3.org/1999/xlink",NodeType$$module$build$src$core$utils$dom;(function(a){a[a.ELEMENT_NODE=1]="ELEMENT_NODE";a[a.TEXT_NODE=3]="TEXT_NODE";a[a.COMMENT_NODE=8]="COMMENT_NODE"})(NodeType$$module$build$src$core$utils$dom||(NodeType$$module$build$src$core$utils$dom={})); +var cacheWidths$$module$build$src$core$utils$dom=null,cacheReference$$module$build$src$core$utils$dom=0,canvasContext$$module$build$src$core$utils$dom=null,module$build$src$core$utils$dom={HTML_NS:HTML_NS$$module$build$src$core$utils$dom};module$build$src$core$utils$dom.NodeType=NodeType$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.SVG_NS=SVG_NS$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.XLINK_NS=XLINK_NS$$module$build$src$core$utils$dom; +module$build$src$core$utils$dom.addClass=addClass$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.createSvgElement=createSvgElement$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.getFastTextWidth=getFastTextWidth$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.getFastTextWidthWithSizeString=getFastTextWidthWithSizeString$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.getTextWidth=getTextWidth$$module$build$src$core$utils$dom; +module$build$src$core$utils$dom.hasClass=hasClass$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.insertAfter=insertAfter$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.measureFontMetrics=measureFontMetrics$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.removeClass=removeClass$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.removeClasses=removeClasses$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.removeNode=removeNode$$module$build$src$core$utils$dom; +module$build$src$core$utils$dom.setCssTransform=setCssTransform$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.startTextWidthCache=startTextWidthCache$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.stopTextWidthCache=stopTextWidthCache$$module$build$src$core$utils$dom;var FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser=class{static findFocusedNode(a){var b=a.getRootFocusableNode();if(!b.canBeFocused())return null;var c=b.getFocusableElement();if(hasClass$$module$build$src$core$utils$dom(c,FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.ACTIVE_CLASS_NAME)||hasClass$$module$build$src$core$utils$dom(c,FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.PASSIVE_CSS_CLASS_NAME))return b; +b=c.querySelector(this.ACTIVE_FOCUS_NODE_CSS_SELECTOR);if(b instanceof HTMLElement||b instanceof SVGElement)if(b=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusableNodeFor(b,a))return b;c=c.querySelector(this.PASSIVE_FOCUS_NODE_CSS_SELECTOR);if(c instanceof HTMLElement||c instanceof SVGElement)if(a=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusableNodeFor(c,a))return a;return null}static findFocusableNodeFor(a,b){if(!a.id|| +a.id==="null"||b.getNestedTrees().map(e=>FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusableNodeFor(a,e)).findIndex(e=>!!e)!==-1)return null;var c=b.getRootFocusableNode();if(c.canBeFocused()&&a===c.getFocusableElement())return c;var d;if(c=(d=b.lookUpFocusableNode(a.id))!=null?d:null)return c;d=a.parentElement;return!c&&d?FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusableNodeFor(d,b):null}}; +FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.ACTIVE_CLASS_NAME="blocklyActiveFocus";FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.PASSIVE_CSS_CLASS_NAME="blocklyPassiveFocus";FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.ACTIVE_FOCUS_NODE_CSS_SELECTOR=`.${FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.ACTIVE_CLASS_NAME}`; +FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.PASSIVE_FOCUS_NODE_CSS_SELECTOR=`.${FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.PASSIVE_CSS_CLASS_NAME}`;var module$build$src$core$utils$focusable_tree_traverser={};module$build$src$core$utils$focusable_tree_traverser.FocusableTreeTraverser=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser;var TreeRegistration$$module$build$src$core$focus_manager=class{constructor(a,b){this.tree=a;this.rootShouldBeAutoTabbable=b}},FocusManager$$module$build$src$core$focus_manager=class{constructor(a){this.previouslyFocusedNode=this.focusedNode=null;this.registeredTrees=[];this.isUpdatingFocusedNode=this.recentlyLostAllFocus=this.lockFocusStateChanges=this.currentlyHoldsEphemeralFocus=!1;const b=c=>{if(!this.isUpdatingFocusedNode){this.recentlyLostAllFocus=!c;var d=null;if(c instanceof HTMLElement|| +c instanceof SVGElement)for(var e of this.registeredTrees)if(d=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusableNodeFor(c,e.tree))break;if(d&&d.canBeFocused()){c=d.getFocusableTree();let f;e=(f=this.focusedNode)==null?void 0:f.getFocusableTree();d===c.getRootFocusableNode()&&c!==e?this.focusTree(c):this.focusNode(d)}else this.defocusCurrentFocusedNode()}};a("focusin",c=>{c instanceof FocusEvent&&b(document.activeElement)});a("focusout",c=>{c instanceof FocusEvent&& +b(c.relatedTarget)})}registerTree(a,b=!1){this.ensureManagerIsUnlocked();if(this.isRegistered(a))throw Error(`Attempted to re-register already registered tree: ${a}.`);this.registeredTrees.push(new TreeRegistration$$module$build$src$core$focus_manager(a,b));const c=a.getRootFocusableNode().getFocusableElement();if(!c.id||c.id==="null")throw Error("Attempting to register a tree with a root element that has an "+`invalid ID: ${a}.`);b&&(c.tabIndex=0)}isRegistered(a){return!!this.lookUpRegistration(a)}lookUpRegistration(a){let b; +return(b=this.registeredTrees.find(c=>c.tree===a))!=null?b:null}unregisterTree(a){this.ensureManagerIsUnlocked();if(!this.isRegistered(a))throw Error(`Attempted to unregister not registered tree: ${a}.`);var b=this.registeredTrees.findIndex(e=>e.tree===a);const c=this.registeredTrees[b];this.registeredTrees.splice(b,1);b=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusedNode(a);const d=a.getRootFocusableNode();b&&this.removeHighlight(b);this.focusedNode!==b&& +this.focusedNode!==d||this.updateFocusedNode(null);this.removeHighlight(d);c.rootShouldBeAutoTabbable&&a.getRootFocusableNode().getFocusableElement().removeAttribute("tabindex")}getFocusedTree(){let a,b;return(b=(a=this.focusedNode)==null?void 0:a.getFocusableTree())!=null?b:null}getFocusedNode(){return this.focusedNode}focusTree(a){this.ensureManagerIsUnlocked();if(!this.isRegistered(a))throw Error(`Attempted to focus unregistered tree: ${a}.`);const b=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusedNode(a), +c=a.getRestoredFocusableNode(b);a=a.getRootFocusableNode();let d;this.focusNode((d=c!=null?c:b)!=null?d:a)}focusNode(a){this.ensureManagerIsUnlocked();const b=!this.currentlyHoldsEphemeralFocus;b&&(this.isUpdatingFocusedNode=!0);var c,d=((c=this.focusedNode)==null?void 0:c.getFocusableElement())!==document.activeElement;if(this.focusedNode!==a||d)if(a.canBeFocused()){c=a.getFocusableTree();if(!this.isRegistered(c))throw Error(`Attempted to focus unregistered node: ${a}.`);d=a.getFocusableElement(); +d.id&&d.id!=="null"||console.warn("Trying to focus a node that has an invalid ID.");var e=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusableNodeFor(d,c);d=FocusableTreeTraverser$$module$build$src$core$utils$focusable_tree_traverser.findFocusedNode(c);var f=a;if(e!==a){f=c.getRestoredFocusableNode(d);a=c.getRootFocusableNode();var g;f=(g=f!=null?f:d)!=null?g:a}a=this.focusedNode;g=a==null?void 0:a.getFocusableTree();a&&this.passivelyFocusNode(a,c);c=c.getRootFocusableNode(); +d&&this.removeHighlight(d);c!==f&&this.removeHighlight(c);this.currentlyHoldsEphemeralFocus||this.activelyFocusNode(f,g!=null?g:null);this.updateFocusedNode(f)}else console.warn("Trying to focus a node that can't be focused.");b&&(this.isUpdatingFocusedNode=!1)}takeEphemeralFocus(a){this.ensureManagerIsUnlocked();if(this.currentlyHoldsEphemeralFocus)throw Error("Attempted to take ephemeral focus when it's already held, "+`with new element: ${a}.`);this.currentlyHoldsEphemeralFocus=!0;this.focusedNode&& +this.passivelyFocusNode(this.focusedNode,null);a.focus({preventScroll:!0});let b=!1;return()=>{if(b)throw Error("Attempted to finish ephemeral focus twice for element: "+`${a}.`);b=!0;this.currentlyHoldsEphemeralFocus=!1;if(this.focusedNode){this.activelyFocusNode(this.focusedNode,null);const c=this.focusedNode;setTimeout(()=>{!this.focusedNode&&this.previouslyFocusedNode===c&&this.recentlyLostAllFocus&&this.focusNode(c)},0)}}}ephemeralFocusTaken(){return this.currentlyHoldsEphemeralFocus}ensureManagerIsUnlocked(){if(this.lockFocusStateChanges)throw Error("FocusManager state changes cannot happen in a tree/node focus/blur callback."); +}updateFocusedNode(a){this.previouslyFocusedNode=this.focusedNode;this.focusedNode=a}defocusCurrentFocusedNode(){this.focusedNode&&!this.currentlyHoldsEphemeralFocus&&(this.passivelyFocusNode(this.focusedNode,null),this.updateFocusedNode(null))}activelyFocusNode(a,b){this.lockFocusStateChanges=!0;const c=a.getFocusableTree(),d=a.getFocusableElement();let e;const f=(e=this.lookUpRegistration(c))==null?void 0:e.rootShouldBeAutoTabbable;c!==b&&(c.onTreeFocus(a,b),f&&(c.getRootFocusableNode().getFocusableElement().tabIndex= +-1));a.onNodeFocus();this.lockFocusStateChanges=!1;f&&a===c.getRootFocusableNode()||d.hasAttribute("tabindex")||(d.tabIndex=-1);this.setNodeToVisualActiveFocus(a);d.focus({preventScroll:!0})}passivelyFocusNode(a,b){this.lockFocusStateChanges=!0;const c=a.getFocusableTree();if(c!==b){c.onTreeBlur(b);let d;if((d=this.lookUpRegistration(c))==null?0:d.rootShouldBeAutoTabbable)c.getRootFocusableNode().getFocusableElement().tabIndex=0}a.onNodeBlur();this.lockFocusStateChanges=!1;c!==b&&this.setNodeToVisualPassiveFocus(a)}setNodeToVisualActiveFocus(a){a= +a.getFocusableElement();addClass$$module$build$src$core$utils$dom(a,FocusManager$$module$build$src$core$focus_manager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME);removeClass$$module$build$src$core$utils$dom(a,FocusManager$$module$build$src$core$focus_manager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME)}setNodeToVisualPassiveFocus(a){a=a.getFocusableElement();removeClass$$module$build$src$core$utils$dom(a,FocusManager$$module$build$src$core$focus_manager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME);addClass$$module$build$src$core$utils$dom(a, +FocusManager$$module$build$src$core$focus_manager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME)}removeHighlight(a){a=a.getFocusableElement();removeClass$$module$build$src$core$utils$dom(a,FocusManager$$module$build$src$core$focus_manager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME);removeClass$$module$build$src$core$utils$dom(a,FocusManager$$module$build$src$core$focus_manager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME)}static getFocusManager(){FocusManager$$module$build$src$core$focus_manager.focusManager||(FocusManager$$module$build$src$core$focus_manager.focusManager= +new FocusManager$$module$build$src$core$focus_manager(document.addEventListener));return FocusManager$$module$build$src$core$focus_manager.focusManager}};FocusManager$$module$build$src$core$focus_manager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME="blocklyActiveFocus";FocusManager$$module$build$src$core$focus_manager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME="blocklyPassiveFocus";FocusManager$$module$build$src$core$focus_manager.focusManager=null;var module$build$src$core$focus_manager={}; +module$build$src$core$focus_manager.FocusManager=FocusManager$$module$build$src$core$focus_manager;module$build$src$core$focus_manager.getFocusManager=$.getFocusManager$$module$build$src$core$focus_manager;var module$build$src$core$interfaces$i_focusable_node={};module$build$src$core$interfaces$i_focusable_node.isFocusableNode=isFocusableNode$$module$build$src$core$interfaces$i_focusable_node;var module$build$src$core$interfaces$i_selectable={};module$build$src$core$interfaces$i_selectable.isSelectable=isSelectable$$module$build$src$core$interfaces$i_selectable;var module$build$src$core$utils$object={};module$build$src$core$utils$object.deepMerge=deepMerge$$module$build$src$core$utils$object;var ShortcutRegistry$$module$build$src$core$shortcut_registry=class{constructor(){this.shortcuts=new Map;this.keyMap=new Map;this.reset()}reset(){this.shortcuts.clear();this.keyMap.clear()}register(a,b){if(this.shortcuts.get(a.name)&&!b)throw Error(`Shortcut named "${a.name}" already exists.`);this.shortcuts.set(a.name,a);b=a.keyCodes;if(b==null?0:b.length)for(const c of b)this.addKeyMapping(c,a.name,!!a.allowCollision)}unregister(a){if(!this.shortcuts.get(a))return console.warn(`Keyboard shortcut named "${a}" not found.`), +!1;this.removeAllKeyMappings(a);this.shortcuts.delete(a);return!0}addKeyMapping(a,b,c){a=`${a}`;const d=this.keyMap.get(a);if(d&&!c)throw Error(`Shortcut named "${b}" collides with shortcuts "${d}"`);d&&c?d.unshift(b):this.keyMap.set(a,[b])}removeKeyMapping(a,b,c){const d=this.keyMap.get(a);if(!d)return c||console.warn(`No keyboard shortcut named "${b}" registered with key code "${a}"`),!1;const e=d.indexOf(b);if(e>-1)return d.splice(e,1),d.length===0&&this.keyMap.delete(a),!0;c||console.warn(`No keyboard shortcut named "${b}" registered with key code "${a}"`); +return!1}removeAllKeyMappings(a){for(const b of this.keyMap.keys())this.removeKeyMapping(b,a,!0)}setKeyMap(a){this.keyMap.clear();for(const b in a)this.keyMap.set(b,a[b])}getKeyMap(){const a=Object.create(null);for(const [b,c]of this.keyMap)a[b]=c;return a}getRegistry(){const a=Object.create(null);for(const [b,c]of this.shortcuts)a[b]=c;return deepMerge$$module$build$src$core$utils$object(Object.create(null),a)}onKeyDown(a,b){var c=this.serializeKeyEvent(b);c=this.getShortcutNamesByKeyCode(c);if(!c)return!1; +for(const d of c){c=this.shortcuts.get(d);let e;if(!c||c.preconditionFn&&!c.preconditionFn(a,{focusedNode:(e=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode())!=null?e:void 0}))continue;let f,g,h;if((g=(f=c).callback)==null?0:g.call(f,a,b,c,{focusedNode:(h=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode())!=null?h:void 0}))return!0}return!1}getShortcutNamesByKeyCode(a){let b;return((b=this.keyMap.get(a))==null?void 0:b.slice())||[]}getKeyCodesByShortcutName(a){const b= +[];for(const [c,d]of this.keyMap)d.indexOf(a)>-1&&b.push(c);return b}serializeKeyEvent(a){let b="";for(const c in ShortcutRegistry$$module$build$src$core$shortcut_registry.modifierKeys)a.getModifierState(c)&&(b!==""&&(b+="+"),b+=c);b!==""&&a.keyCode?b+="+"+a.keyCode:a.keyCode&&(b=String(a.keyCode));return b}checkModifiers(a){for(const b of a)if(!(b in ShortcutRegistry$$module$build$src$core$shortcut_registry.modifierKeys))throw Error(b+" is not a valid modifier key.");}createSerializedKey(a,b){let c= +"";if(b){this.checkModifiers(b);for(const d in ShortcutRegistry$$module$build$src$core$shortcut_registry.modifierKeys)b.includes(ShortcutRegistry$$module$build$src$core$shortcut_registry.modifierKeys[d])&&(c!==""&&(c+="+"),c+=d)}c!==""&&a?c+="+"+a:a&&(c=`${a}`);return c}};ShortcutRegistry$$module$build$src$core$shortcut_registry.registry=new ShortcutRegistry$$module$build$src$core$shortcut_registry; +(function(a){a=a.modifierKeys||(a.modifierKeys={});a[a.Shift=16]="Shift";a[a.Control=17]="Control";a[a.Alt=18]="Alt";a[a.Meta=91]="Meta"})(ShortcutRegistry$$module$build$src$core$shortcut_registry||(ShortcutRegistry$$module$build$src$core$shortcut_registry={}));var module$build$src$core$shortcut_registry={};module$build$src$core$shortcut_registry.ShortcutRegistry=ShortcutRegistry$$module$build$src$core$shortcut_registry;var WorkspaceDB_$$module$build$src$core$common=Object.create(null),mainWorkspace$$module$build$src$core$common,parentContainer$$module$build$src$core$common,draggingConnections$$module$build$src$core$common=[],TEST_ONLY$$module$build$src$core$common={defineBlocksWithJsonArrayInternal:defineBlocksWithJsonArrayInternal$$module$build$src$core$common},module$build$src$core$common={TEST_ONLY:TEST_ONLY$$module$build$src$core$common};module$build$src$core$common.createBlockDefinitionsFromJsonArray=$.createBlockDefinitionsFromJsonArray$$module$build$src$core$common; +module$build$src$core$common.defineBlocks=$.defineBlocks$$module$build$src$core$common;module$build$src$core$common.defineBlocksWithJsonArray=defineBlocksWithJsonArray$$module$build$src$core$common;module$build$src$core$common.draggingConnections=draggingConnections$$module$build$src$core$common;module$build$src$core$common.fireSelectedEvent=fireSelectedEvent$$module$build$src$core$common;module$build$src$core$common.getAllWorkspaces=getAllWorkspaces$$module$build$src$core$common; +module$build$src$core$common.getBlockTypeCounts=getBlockTypeCounts$$module$build$src$core$common;module$build$src$core$common.getMainWorkspace=getMainWorkspace$$module$build$src$core$common;module$build$src$core$common.getParentContainer=getParentContainer$$module$build$src$core$common;module$build$src$core$common.getSelected=getSelected$$module$build$src$core$common;module$build$src$core$common.getWorkspaceById=getWorkspaceById$$module$build$src$core$common; +module$build$src$core$common.globalShortcutHandler=globalShortcutHandler$$module$build$src$core$common;module$build$src$core$common.registerWorkspace=registerWorkspace$$module$build$src$core$common;module$build$src$core$common.setMainWorkspace=setMainWorkspace$$module$build$src$core$common;module$build$src$core$common.setParentContainer=setParentContainer$$module$build$src$core$common;module$build$src$core$common.setSelected=setSelected$$module$build$src$core$common; +module$build$src$core$common.svgResize=svgResize$$module$build$src$core$common;module$build$src$core$common.unregisterWorkpace=unregisterWorkpace$$module$build$src$core$common;var Abstract$$module$build$src$core$events$events_abstract=class{constructor(){this.workspaceId=void 0;this.isUiEvent=!1;this.type="";this.group=$.getGroup$$module$build$src$core$events$utils();this.recordUndo=getRecordUndo$$module$build$src$core$events$utils()}toJson(){return{type:this.type,group:this.group}}static fromJson(a,b,c){c.isBlank=!1;c.group=a.group||"";c.workspaceId=b.id;return c}isNull(){return!1}run(a){}getEventWorkspace_(){let a;this.workspaceId&&(a=getWorkspaceById$$module$build$src$core$common(this.workspaceId)); +if(!a)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return a}},module$build$src$core$events$events_abstract={};module$build$src$core$events$events_abstract.Abstract=Abstract$$module$build$src$core$events$events_abstract;var UiBase$$module$build$src$core$events$events_ui_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!0;this.recordUndo=!1;this.isUiEvent=!0;this.isBlank=typeof a==="undefined";this.workspaceId=a?a:""}},module$build$src$core$events$events_ui_base={};module$build$src$core$events$events_ui_base.UiBase=UiBase$$module$build$src$core$events$events_ui_base;var Click$$module$build$src$core$events$events_click=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){b=a?a.workspace.id:b;b===null&&(b=void 0);super(b);this.type=EventType$$module$build$src$core$events$type.CLICK;this.blockId=a?a.id:void 0;this.targetType=c}toJson(){const a=super.toJson();if(!this.targetType)throw Error("The click target type is undefined. Either pass a block to the constructor, or call fromJson");a.targetType=this.targetType;a.blockId=this.blockId; +return a}static fromJson(a,b,c){b=UiBase$$module$build$src$core$events$events_ui_base.fromJson(a,b,c!=null?c:new Click$$module$build$src$core$events$events_click);b.targetType=a.targetType;b.blockId=a.blockId;return b}},ClickTarget$$module$build$src$core$events$events_click;(function(a){a.BLOCK="block";a.WORKSPACE="workspace";a.ZOOM_CONTROLS="zoom_controls"})(ClickTarget$$module$build$src$core$events$events_click||(ClickTarget$$module$build$src$core$events$events_click={})); +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.CLICK,Click$$module$build$src$core$events$events_click);var module$build$src$core$events$events_click={};module$build$src$core$events$events_click.Click=Click$$module$build$src$core$events$events_click;module$build$src$core$events$events_click.ClickTarget=ClickTarget$$module$build$src$core$events$events_click;var module$build$src$core$utils$array={};module$build$src$core$utils$array.removeElem=removeElem$$module$build$src$core$utils$array;var Capability$$module$build$src$core$component_manager=class{constructor(a){this.name=a}toString(){return this.name}};Capability$$module$build$src$core$component_manager.POSITIONABLE=new Capability$$module$build$src$core$component_manager("positionable");Capability$$module$build$src$core$component_manager.DRAG_TARGET=new Capability$$module$build$src$core$component_manager("drag_target");Capability$$module$build$src$core$component_manager.DELETE_AREA=new Capability$$module$build$src$core$component_manager("delete_area"); Capability$$module$build$src$core$component_manager.AUTOHIDEABLE=new Capability$$module$build$src$core$component_manager("autohideable"); -var ComponentManager$$module$build$src$core$component_manager=class{constructor(){this.componentData=new Map;this.capabilityToComponentIds=new Map}addComponent(a,b){const c=a.component.id;if(!b&&this.componentData.has(c)){var d;throw Error('Plugin "'+c+'" with capabilities "'+(null==(d=this.componentData.get(c))?void 0:d.capabilities)+'" already added.');}this.componentData.set(c,a);b=[];for(d=0;d +var ComponentManager$$module$build$src$core$component_manager=class{constructor(){this.componentData=new Map;this.capabilityToComponentIds=new Map}addComponent(a,b){const c=a.component.id;if(!b&&this.componentData.has(c)){var d;throw Error('Plugin "'+c+'" with capabilities "'+((d=this.componentData.get(c))==null?void 0:d.capabilities)+'" already added.');}this.componentData.set(c,a);b=[];for(d=0;d {d.push(this.componentData.get(e))});d.sort(function(e,f){return e.weight-f.weight});d.forEach(function(e){c.push(e.component)})}else a.forEach(d=>{c.push(this.componentData.get(d).component)});return c}};ComponentManager$$module$build$src$core$component_manager.Capability=Capability$$module$build$src$core$component_manager; (function(a){a=a.ComponentWeight||(a.ComponentWeight={});a[a.TOOLBOX_WEIGHT=0]="TOOLBOX_WEIGHT";a[a.FLYOUT_WEIGHT=1]="FLYOUT_WEIGHT";a[a.TRASHCAN_WEIGHT=2]="TRASHCAN_WEIGHT";a[a.ZOOM_CONTROLS_WEIGHT=3]="ZOOM_CONTROLS_WEIGHT"})(ComponentManager$$module$build$src$core$component_manager||(ComponentManager$$module$build$src$core$component_manager={})); -var ComponentWeight$$module$build$src$core$component_manager=ComponentManager$$module$build$src$core$component_manager.ComponentWeight,module$build$src$core$component_manager={};module$build$src$core$component_manager.ComponentManager=ComponentManager$$module$build$src$core$component_manager;module$build$src$core$component_manager.ComponentWeight=ComponentWeight$$module$build$src$core$component_manager;var injected$$module$build$src$core$css=!1,content$$module$build$src$core$css='\n.blocklySvg {\n background-color: #fff;\n outline: none;\n overflow: hidden; /* IE overflows by default. */\n position: absolute;\n display: block;\n}\n\n.blocklyWidgetDiv {\n display: none;\n position: absolute;\n z-index: 99999; /* big value for bootstrap3 compatibility */\n}\n\n.injectionDiv {\n height: 100%;\n position: relative;\n overflow: hidden; /* So blocks in drag surface disappear at edges */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.blocklyNonSelectable {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n}\n\n.blocklyBlockCanvas.blocklyCanvasTransitioning,\n.blocklyBubbleCanvas.blocklyCanvasTransitioning {\n transition: transform .5s;\n}\n\n.blocklyTooltipDiv {\n background-color: #ffffc7;\n border: 1px solid #ddc;\n box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);\n color: #000;\n display: none;\n font: 9pt sans-serif;\n opacity: .9;\n padding: 2px;\n position: absolute;\n z-index: 100000; /* big value for bootstrap3 compatibility */\n}\n\n.blocklyDropDownDiv {\n position: absolute;\n left: 0;\n top: 0;\n z-index: 1000;\n display: none;\n border: 1px solid;\n border-color: #dadce0;\n background-color: #fff;\n border-radius: 2px;\n padding: 4px;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv.blocklyFocused {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownContent {\n max-height: 300px; /* @todo: spec for maximum height. */\n overflow: auto;\n overflow-x: hidden;\n position: relative;\n}\n\n.blocklyDropDownArrow {\n position: absolute;\n left: 0;\n top: 0;\n width: 16px;\n height: 16px;\n z-index: -1;\n background-color: inherit;\n border-color: inherit;\n}\n\n.blocklyDropDownButton {\n display: inline-block;\n float: left;\n padding: 0;\n margin: 4px;\n border-radius: 4px;\n outline: none;\n border: 1px solid;\n transition: box-shadow .1s;\n cursor: pointer;\n}\n\n.blocklyArrowTop {\n border-top: 1px solid;\n border-left: 1px solid;\n border-top-left-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyArrowBottom {\n border-bottom: 1px solid;\n border-right: 1px solid;\n border-bottom-right-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyResizeSE {\n cursor: se-resize;\n fill: #aaa;\n}\n\n.blocklyResizeSW {\n cursor: sw-resize;\n fill: #aaa;\n}\n\n.blocklyResizeLine {\n stroke: #515A5A;\n stroke-width: 1;\n}\n\n.blocklyHighlightedConnectionPath {\n fill: none;\n stroke: #fc3;\n stroke-width: 4px;\n}\n\n.blocklyPathLight {\n fill: none;\n stroke-linecap: round;\n stroke-width: 1;\n}\n\n.blocklySelected>.blocklyPathLight {\n display: none;\n}\n\n.blocklyDraggable {\n cursor: grab;\n cursor: -webkit-grab;\n}\n\n.blocklyDragging {\n cursor: grabbing;\n cursor: -webkit-grabbing;\n /* Drag surface disables events to not block the toolbox, so we have to\n * reenable them here for the cursor values to work. */\n pointer-events: auto;\n}\n\n /* Changes cursor on mouse down. Not effective in Firefox because of\n https://bugzilla.mozilla.org/show_bug.cgi?id=771241 */\n.blocklyDraggable:active {\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n.blocklyDragging.blocklyDraggingDelete {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyDragging>.blocklyPath,\n.blocklyDragging>.blocklyPathLight {\n fill-opacity: .8;\n stroke-opacity: .8;\n}\n\n.blocklyDragging>.blocklyPathDark {\n display: none;\n}\n\n.blocklyDisabled>.blocklyPath {\n fill-opacity: .5;\n stroke-opacity: .5;\n}\n\n.blocklyDisabled>.blocklyPathLight,\n.blocklyDisabled>.blocklyPathDark {\n display: none;\n}\n\n.blocklyInsertionMarker>.blocklyPath,\n.blocklyInsertionMarker>.blocklyPathLight,\n.blocklyInsertionMarker>.blocklyPathDark {\n fill-opacity: .2;\n stroke: none;\n}\n\n.blocklyNonEditableText>text {\n pointer-events: none;\n}\n\n.blocklyFlyout {\n position: absolute;\n z-index: 20;\n}\n\n.blocklyText text {\n cursor: default;\n}\n\n.blocklyHidden {\n display: none;\n}\n\n.blocklyFieldDropdown:not(.blocklyHidden) {\n display: block;\n}\n\n.blocklyIconGroup {\n cursor: default;\n}\n\n.blocklyIconGroup:not(:hover),\n.blocklyIconGroupReadonly {\n opacity: .6;\n}\n\n.blocklyIconShape {\n fill: #00f;\n stroke: #fff;\n stroke-width: 1px;\n}\n\n.blocklyIconSymbol {\n fill: #fff;\n}\n\n.blocklyMinimalBody {\n margin: 0;\n padding: 0;\n height: 100%;\n}\n\n.blocklyHtmlInput {\n border: none;\n border-radius: 4px;\n height: 100%;\n margin: 0;\n outline: none;\n padding: 0;\n width: 100%;\n text-align: center;\n display: block;\n box-sizing: border-box;\n}\n\n/* Remove the increase and decrease arrows on the field number editor */\ninput.blocklyHtmlInput[type=number]::-webkit-inner-spin-button,\ninput.blocklyHtmlInput[type=number]::-webkit-outer-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\ninput[type=number] {\n -moz-appearance: textfield;\n}\n\n.blocklyMainBackground {\n stroke-width: 1;\n stroke: #c6c6c6; /* Equates to #ddd due to border being off-pixel. */\n}\n\n.blocklyMutatorBackground {\n fill: #fff;\n stroke: #ddd;\n stroke-width: 1;\n}\n\n.blocklyFlyoutBackground {\n fill: #ddd;\n fill-opacity: .8;\n}\n\n.blocklyMainWorkspaceScrollbar {\n z-index: 20;\n}\n\n.blocklyFlyoutScrollbar {\n z-index: 30;\n}\n\n.blocklyScrollbarHorizontal,\n.blocklyScrollbarVertical {\n position: absolute;\n outline: none;\n}\n\n.blocklyScrollbarBackground {\n opacity: 0;\n pointer-events: none;\n}\n\n.blocklyScrollbarHandle {\n fill: #ccc;\n}\n\n.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyScrollbarHandle:hover {\n fill: #bbb;\n}\n\n/* Darken flyout scrollbars due to being on a grey background. */\n/* By contrast, workspace scrollbars are on a white background. */\n.blocklyFlyout .blocklyScrollbarHandle {\n fill: #bbb;\n}\n\n.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyFlyout .blocklyScrollbarHandle:hover {\n fill: #aaa;\n}\n\n.blocklyInvalidInput {\n background: #faa;\n}\n\n.blocklyVerticalMarker {\n stroke-width: 3px;\n fill: rgba(255,255,255,.5);\n pointer-events: none;\n}\n\n.blocklyComputeCanvas {\n position: absolute;\n width: 0;\n height: 0;\n}\n\n.blocklyNoPointerEvents {\n pointer-events: none;\n}\n\n.blocklyContextMenu {\n border-radius: 4px;\n max-height: 100%;\n}\n\n.blocklyDropdownMenu {\n border-radius: 2px;\n padding: 0 !important;\n}\n\n.blocklyDropdownMenu .blocklyMenuItem {\n /* 28px on the left for icon or checkbox. */\n padding-left: 28px;\n}\n\n/* BiDi override for the resting state. */\n.blocklyDropdownMenu .blocklyMenuItemRtl {\n /* Flip left/right padding for BiDi. */\n padding-left: 5px;\n padding-right: 28px;\n}\n\n.blocklyWidgetDiv .blocklyMenu {\n background: #fff;\n border: 1px solid transparent;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n font: normal 13px Arial, sans-serif;\n margin: 0;\n outline: none;\n padding: 4px 0;\n position: absolute;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 100%;\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n.blocklyWidgetDiv .blocklyMenu.blocklyFocused {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv .blocklyMenu {\n background: inherit; /* Compatibility with gapi, reset from goog-menu */\n border: inherit; /* Compatibility with gapi, reset from goog-menu */\n font: normal 13px "Helvetica Neue", Helvetica, sans-serif;\n outline: none;\n position: relative; /* Compatibility with gapi, reset from goog-menu */\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n/* State: resting. */\n.blocklyMenuItem {\n border: none;\n color: #000;\n cursor: pointer;\n list-style: none;\n margin: 0;\n /* 7em on the right for shortcut. */\n min-width: 7em;\n padding: 6px 15px;\n white-space: nowrap;\n}\n\n/* State: disabled. */\n.blocklyMenuItemDisabled {\n color: #ccc;\n cursor: inherit;\n}\n\n/* State: hover. */\n.blocklyMenuItemHighlight {\n background-color: rgba(0,0,0,.1);\n}\n\n/* State: selected/checked. */\n.blocklyMenuItemCheckbox {\n height: 16px;\n position: absolute;\n width: 16px;\n}\n\n.blocklyMenuItemSelected .blocklyMenuItemCheckbox {\n background: url(<<>>/sprites.png) no-repeat -48px -16px;\n float: left;\n margin-left: -24px;\n position: static; /* Scroll with the menu. */\n}\n\n.blocklyMenuItemRtl .blocklyMenuItemCheckbox {\n float: right;\n margin-right: -24px;\n}\n\n.blocklyBlockDragSurface, .blocklyAnimationLayer {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n overflow: visible !important;\n z-index: 80;\n pointer-events: none;\n}\n', +var ComponentWeight$$module$build$src$core$component_manager=ComponentManager$$module$build$src$core$component_manager.ComponentWeight,module$build$src$core$component_manager={};module$build$src$core$component_manager.ComponentManager=ComponentManager$$module$build$src$core$component_manager;module$build$src$core$component_manager.ComponentWeight=ComponentWeight$$module$build$src$core$component_manager;var injected$$module$build$src$core$css=!1,content$$module$build$src$core$css='\n.blocklySvg {\n background-color: #fff;\n outline: none;\n overflow: hidden; /* IE overflows by default. */\n position: absolute;\n display: block;\n}\n\n.blocklyWidgetDiv {\n display: none;\n position: absolute;\n z-index: 99999; /* big value for bootstrap3 compatibility */\n}\n\n.injectionDiv {\n height: 100%;\n position: relative;\n overflow: hidden; /* So blocks in drag surface disappear at edges */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.blocklyBlockCanvas.blocklyCanvasTransitioning,\n.blocklyBubbleCanvas.blocklyCanvasTransitioning {\n transition: transform .5s;\n}\n\n.blocklyEmboss {\n filter: var(--blocklyEmbossFilter);\n}\n\n.blocklyTooltipDiv {\n background-color: #ffffc7;\n border: 1px solid #ddc;\n box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);\n color: #000;\n display: none;\n font: 9pt sans-serif;\n opacity: .9;\n padding: 2px;\n position: absolute;\n z-index: 100000; /* big value for bootstrap3 compatibility */\n}\n\n.blocklyDropDownDiv {\n position: absolute;\n left: 0;\n top: 0;\n z-index: 1000;\n display: none;\n border: 1px solid;\n border-color: #dadce0;\n background-color: #fff;\n border-radius: 2px;\n padding: 4px;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv:focus {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownContent {\n max-height: 300px; /* @todo: spec for maximum height. */\n}\n\n.blocklyDropDownArrow {\n position: absolute;\n left: 0;\n top: 0;\n width: 16px;\n height: 16px;\n z-index: -1;\n background-color: inherit;\n border-color: inherit;\n border-top: 1px solid;\n border-left: 1px solid;\n border-top-left-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyHighlighted>.blocklyPath {\n filter: var(--blocklyEmbossFilter);\n}\n\n.blocklyHighlightedConnectionPath {\n fill: none;\n stroke: #fc3;\n stroke-width: 4px;\n}\n\n.blocklyPathLight {\n fill: none;\n stroke-linecap: round;\n stroke-width: 1;\n}\n\n.blocklySelected>.blocklyPathLight {\n display: none;\n}\n\n.blocklyDraggable {\n cursor: grab;\n cursor: -webkit-grab;\n}\n\n.blocklyDragging {\n cursor: grabbing;\n cursor: -webkit-grabbing;\n /* Drag surface disables events to not block the toolbox, so we have to\n * reenable them here for the cursor values to work. */\n pointer-events: auto;\n}\n\n /* Changes cursor on mouse down. Not effective in Firefox because of\n https://bugzilla.mozilla.org/show_bug.cgi?id=771241 */\n.blocklyDraggable:active {\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n.blocklyDragging.blocklyDraggingDelete,\n.blocklyDragging.blocklyDraggingDelete .blocklyField {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyDragging>.blocklyPath,\n.blocklyDragging>.blocklyPathLight {\n fill-opacity: .8;\n stroke-opacity: .8;\n}\n\n.blocklyDragging>.blocklyPathDark {\n display: none;\n}\n\n.blocklyDisabledPattern>.blocklyPath {\n fill: var(--blocklyDisabledPattern);\n fill-opacity: .5;\n stroke-opacity: .5;\n}\n\n.blocklyDisabled>.blocklyPathLight,\n.blocklyDisabled>.blocklyPathDark {\n display: none;\n}\n\n.blocklyInsertionMarker>.blocklyPath,\n.blocklyInsertionMarker>.blocklyPathLight,\n.blocklyInsertionMarker>.blocklyPathDark {\n fill-opacity: .2;\n stroke: none;\n}\n\n.blocklyNonEditableField>text {\n pointer-events: none;\n}\n\n.blocklyFlyout {\n position: absolute;\n z-index: 20;\n}\n\n.blocklyText text {\n cursor: default;\n}\n\n/*\n Don\'t allow users to select text. It gets annoying when trying to\n drag a block and selected text moves instead.\n*/\n.blocklySvg text {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n cursor: inherit;\n}\n\n.blocklyIconGroup {\n cursor: default;\n}\n\n.blocklyIconGroup:not(:hover):not(:focus),\n.blocklyIconGroupReadonly {\n opacity: .6;\n}\n\n.blocklyIconShape {\n fill: #00f;\n stroke: #fff;\n stroke-width: 1px;\n}\n\n.blocklyIconSymbol {\n fill: #fff;\n}\n\n.blocklyMinimalBody {\n margin: 0;\n padding: 0;\n height: 100%;\n}\n\n.blocklyHtmlInput {\n border: none;\n border-radius: 4px;\n height: 100%;\n margin: 0;\n outline: none;\n padding: 0;\n width: 100%;\n text-align: center;\n display: block;\n box-sizing: border-box;\n}\n\n/* Remove the increase and decrease arrows on the field number editor */\ninput.blocklyHtmlInput[type=number]::-webkit-inner-spin-button,\ninput.blocklyHtmlInput[type=number]::-webkit-outer-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\ninput[type=number] {\n -moz-appearance: textfield;\n}\n\n.blocklyMainBackground {\n stroke-width: 1;\n stroke: #c6c6c6; /* Equates to #ddd due to border being off-pixel. */\n}\n\n.blocklyMutatorBackground {\n fill: #fff;\n stroke: #ddd;\n stroke-width: 1;\n}\n\n.blocklyFlyoutBackground {\n fill: #ddd;\n fill-opacity: .8;\n}\n\n.blocklyMainWorkspaceScrollbar {\n z-index: 20;\n}\n\n.blocklyFlyoutScrollbar {\n z-index: 30;\n}\n\n.blocklyScrollbarHorizontal,\n.blocklyScrollbarVertical {\n position: absolute;\n outline: none;\n}\n\n.blocklyScrollbarBackground {\n opacity: 0;\n pointer-events: none;\n}\n\n.blocklyScrollbarHandle {\n fill: #ccc;\n}\n\n.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyScrollbarHandle:hover {\n fill: #bbb;\n}\n\n/* Darken flyout scrollbars due to being on a grey background. */\n/* By contrast, workspace scrollbars are on a white background. */\n.blocklyFlyout .blocklyScrollbarHandle {\n fill: #bbb;\n}\n\n.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyFlyout .blocklyScrollbarHandle:hover {\n fill: #aaa;\n}\n\n.blocklyInvalidInput {\n background: #faa;\n}\n\n.blocklyVerticalMarker {\n stroke-width: 3px;\n fill: rgba(255,255,255,.5);\n pointer-events: none;\n}\n\n.blocklyComputeCanvas {\n position: absolute;\n width: 0;\n height: 0;\n}\n\n.blocklyNoPointerEvents {\n pointer-events: none;\n}\n\n.blocklyContextMenu {\n border-radius: 4px;\n max-height: 100%;\n}\n\n.blocklyDropdownMenu {\n border-radius: 2px;\n padding: 0 !important;\n}\n\n.blocklyDropdownMenu .blocklyMenuItem {\n /* 28px on the left for icon or checkbox. */\n padding-left: 28px;\n}\n\n/* BiDi override for the resting state. */\n.blocklyDropdownMenu .blocklyMenuItemRtl {\n /* Flip left/right padding for BiDi. */\n padding-left: 5px;\n padding-right: 28px;\n}\n\n.blocklyWidgetDiv .blocklyMenu {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n background: #fff;\n border: 1px solid transparent;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n font: normal 13px Arial, sans-serif;\n margin: 0;\n outline: none;\n padding: 4px 0;\n position: absolute;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 100%;\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n.blocklyWidgetDiv .blocklyMenu:focus {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv .blocklyMenu {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n background: inherit; /* Compatibility with gapi, reset from goog-menu */\n border: inherit; /* Compatibility with gapi, reset from goog-menu */\n font: normal 13px "Helvetica Neue", Helvetica, sans-serif;\n outline: none;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 100%;\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n/* State: resting. */\n.blocklyMenuItem {\n border: none;\n color: #000;\n cursor: pointer;\n list-style: none;\n margin: 0;\n /* 7em on the right for shortcut. */\n min-width: 7em;\n padding: 6px 15px;\n white-space: nowrap;\n}\n\n/* State: disabled. */\n.blocklyMenuItemDisabled {\n color: #ccc;\n cursor: inherit;\n}\n\n/* State: hover. */\n.blocklyMenuItemHighlight {\n background-color: rgba(0,0,0,.1);\n}\n\n/* State: selected/checked. */\n.blocklyMenuItemSelected .blocklyMenuItemCheckbox {\n background: url(<<>>/sprites.png) no-repeat -48px -16px;\n float: left;\n margin-left: -24px;\n width: 16px;\n height: 16px;\n position: static; /* Scroll with the menu. */\n display: block;\n}\n\n.blocklyMenuItemRtl .blocklyMenuItemCheckbox {\n float: right;\n margin-right: -24px;\n}\n\n.blocklyMenuSeparator {\n background-color: #ccc;\n height: 1px;\n border: 0;\n margin-left: 4px;\n margin-right: 4px;\n}\n\n.blocklyBlockDragSurface, .blocklyAnimationLayer {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n overflow: visible !important;\n z-index: 80;\n pointer-events: none;\n}\n\n.blocklyField {\n cursor: default;\n}\n\n.blocklyInputField {\n cursor: text;\n}\n\n.blocklyDragging .blocklyField,\n.blocklyDragging .blocklyIconGroup {\n cursor: grabbing;\n}\n\n.blocklyActiveFocus:is(\n .blocklyFlyout,\n .blocklyWorkspace,\n .blocklyField,\n .blocklyPath,\n .blocklyHighlightedConnectionPath,\n .blocklyComment,\n .blocklyBubble,\n .blocklyIconGroup,\n .blocklyTextarea\n) {\n outline: none;\n}\n', module$build$src$core$css={};module$build$src$core$css.inject=inject$$module$build$src$core$css;module$build$src$core$css.register=register$$module$build$src$core$css;var Coordinate$$module$build$src$core$utils$coordinate=class{constructor(a,b){this.x=a;this.y=b}clone(){return new Coordinate$$module$build$src$core$utils$coordinate(this.x,this.y)}scale(a){this.x*=a;this.y*=a;return this}translate(a,b){this.x+=a;this.y+=b;return this}static equals(a,b){return a===b?!0:a&&b?a.x===b.x&&a.y===b.y:!1}static distance(a,b){const c=a.x-b.x;a=a.y-b.y;return Math.sqrt(c*c+a*a)}static magnitude(a){return Math.sqrt(a.x*a.x+a.y*a.y)}static difference(a,b){return new Coordinate$$module$build$src$core$utils$coordinate(a.x- -b.x,a.y-b.y)}static sum(a,b){return new Coordinate$$module$build$src$core$utils$coordinate(a.x+b.x,a.y+b.y)}},module$build$src$core$utils$coordinate={};module$build$src$core$utils$coordinate.Coordinate=Coordinate$$module$build$src$core$utils$coordinate;var SVG_NS$$module$build$src$core$utils$dom="http://www.w3.org/2000/svg",HTML_NS$$module$build$src$core$utils$dom="http://www.w3.org/1999/xhtml",XLINK_NS$$module$build$src$core$utils$dom="http://www.w3.org/1999/xlink",NodeType$$module$build$src$core$utils$dom;(function(a){a[a.ELEMENT_NODE=1]="ELEMENT_NODE";a[a.TEXT_NODE=3]="TEXT_NODE";a[a.COMMENT_NODE=8]="COMMENT_NODE"})(NodeType$$module$build$src$core$utils$dom||(NodeType$$module$build$src$core$utils$dom={})); -var cacheWidths$$module$build$src$core$utils$dom=null,cacheReference$$module$build$src$core$utils$dom=0,canvasContext$$module$build$src$core$utils$dom=null,module$build$src$core$utils$dom={HTML_NS:HTML_NS$$module$build$src$core$utils$dom};module$build$src$core$utils$dom.NodeType=NodeType$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.SVG_NS=SVG_NS$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.XLINK_NS=XLINK_NS$$module$build$src$core$utils$dom; -module$build$src$core$utils$dom.addClass=addClass$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.createSvgElement=createSvgElement$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.getFastTextWidth=getFastTextWidth$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.getFastTextWidthWithSizeString=getFastTextWidthWithSizeString$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.getTextWidth=getTextWidth$$module$build$src$core$utils$dom; -module$build$src$core$utils$dom.hasClass=hasClass$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.insertAfter=insertAfter$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.measureFontMetrics=measureFontMetrics$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.removeClass=removeClass$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.removeClasses=removeClasses$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.removeNode=removeNode$$module$build$src$core$utils$dom; -module$build$src$core$utils$dom.setCssTransform=setCssTransform$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.startTextWidthCache=startTextWidthCache$$module$build$src$core$utils$dom;module$build$src$core$utils$dom.stopTextWidthCache=stopTextWidthCache$$module$build$src$core$utils$dom;var Svg$$module$build$src$core$utils$svg=class{constructor(a){this.tagName=a}toString(){return this.tagName}};Svg$$module$build$src$core$utils$svg.ANIMATE=new Svg$$module$build$src$core$utils$svg("animate");Svg$$module$build$src$core$utils$svg.CIRCLE=new Svg$$module$build$src$core$utils$svg("circle");Svg$$module$build$src$core$utils$svg.CLIPPATH=new Svg$$module$build$src$core$utils$svg("clipPath");Svg$$module$build$src$core$utils$svg.DEFS=new Svg$$module$build$src$core$utils$svg("defs"); +b.x,a.y-b.y)}static sum(a,b){return new Coordinate$$module$build$src$core$utils$coordinate(a.x+b.x,a.y+b.y)}},module$build$src$core$utils$coordinate={};module$build$src$core$utils$coordinate.Coordinate=Coordinate$$module$build$src$core$utils$coordinate;var Svg$$module$build$src$core$utils$svg=class{constructor(a){this.tagName=a}toString(){return this.tagName}};Svg$$module$build$src$core$utils$svg.ANIMATE=new Svg$$module$build$src$core$utils$svg("animate");Svg$$module$build$src$core$utils$svg.CIRCLE=new Svg$$module$build$src$core$utils$svg("circle");Svg$$module$build$src$core$utils$svg.CLIPPATH=new Svg$$module$build$src$core$utils$svg("clipPath");Svg$$module$build$src$core$utils$svg.DEFS=new Svg$$module$build$src$core$utils$svg("defs"); Svg$$module$build$src$core$utils$svg.FECOMPOSITE=new Svg$$module$build$src$core$utils$svg("feComposite");Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER=new Svg$$module$build$src$core$utils$svg("feComponentTransfer");Svg$$module$build$src$core$utils$svg.FEFLOOD=new Svg$$module$build$src$core$utils$svg("feFlood");Svg$$module$build$src$core$utils$svg.FEFUNCA=new Svg$$module$build$src$core$utils$svg("feFuncA");Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR=new Svg$$module$build$src$core$utils$svg("feGaussianBlur"); Svg$$module$build$src$core$utils$svg.FEPOINTLIGHT=new Svg$$module$build$src$core$utils$svg("fePointLight");Svg$$module$build$src$core$utils$svg.FESPECULARLIGHTING=new Svg$$module$build$src$core$utils$svg("feSpecularLighting");Svg$$module$build$src$core$utils$svg.FILTER=new Svg$$module$build$src$core$utils$svg("filter");Svg$$module$build$src$core$utils$svg.FOREIGNOBJECT=new Svg$$module$build$src$core$utils$svg("foreignObject");Svg$$module$build$src$core$utils$svg.G=new Svg$$module$build$src$core$utils$svg("g"); Svg$$module$build$src$core$utils$svg.IMAGE=new Svg$$module$build$src$core$utils$svg("image");Svg$$module$build$src$core$utils$svg.LINE=new Svg$$module$build$src$core$utils$svg("line");Svg$$module$build$src$core$utils$svg.PATH=new Svg$$module$build$src$core$utils$svg("path");Svg$$module$build$src$core$utils$svg.PATTERN=new Svg$$module$build$src$core$utils$svg("pattern");Svg$$module$build$src$core$utils$svg.POLYGON=new Svg$$module$build$src$core$utils$svg("polygon"); -Svg$$module$build$src$core$utils$svg.RECT=new Svg$$module$build$src$core$utils$svg("rect");Svg$$module$build$src$core$utils$svg.SVG=new Svg$$module$build$src$core$utils$svg("svg");Svg$$module$build$src$core$utils$svg.TEXT=new Svg$$module$build$src$core$utils$svg("text");Svg$$module$build$src$core$utils$svg.TSPAN=new Svg$$module$build$src$core$utils$svg("tspan");var module$build$src$core$utils$svg={};module$build$src$core$utils$svg.Svg=Svg$$module$build$src$core$utils$svg;var Rect$$module$build$src$core$utils$rect=class{constructor(a,b,c,d){this.top=a;this.bottom=b;this.left=c;this.right=d}clone(){return new Rect$$module$build$src$core$utils$rect(this.top,this.bottom,this.left,this.right)}getHeight(){return this.bottom-this.top}getWidth(){return this.right-this.left}contains(a,b){return a>=this.left&&a<=this.right&&b>=this.top&&b<=this.bottom}intersects(a){return this.left<=a.right&&this.right>=a.left&&this.bottom>=a.top&&this.top<=a.bottom}static equals(a,b){return a=== -b?!0:a&&b?a.top===b.top&&a.bottom===b.bottom&&a.left===b.left&&a.right===b.right:!1}static createFromPoint(a,b,c){const d=a.x;a=a.y;return new Rect$$module$build$src$core$utils$rect(a,a+c,d,d+b)}},module$build$src$core$utils$rect={};module$build$src$core$utils$rect.Rect=Rect$$module$build$src$core$utils$rect;var Size$$module$build$src$core$utils$size=class{constructor(a,b){this.width=a;this.height=b}static equals(a,b){return a===b?!0:a&&b?a.width===b.width&&a.height===b.height:!1}static max(a,b){return new Size$$module$build$src$core$utils$size(Math.max(a.width,b.width),Math.max(a.height,b.height))}static min(a,b){return new Size$$module$build$src$core$utils$size(Math.min(a.width,b.width),Math.min(a.height,b.height))}},module$build$src$core$utils$size={};module$build$src$core$utils$size.Size=Size$$module$build$src$core$utils$size;var TEST_ONLY$$module$build$src$core$utils$style={getSizeInternal:getSizeInternal$$module$build$src$core$utils$style},module$build$src$core$utils$style={TEST_ONLY:TEST_ONLY$$module$build$src$core$utils$style};module$build$src$core$utils$style.getBorderBox=getBorderBox$$module$build$src$core$utils$style;module$build$src$core$utils$style.getComputedStyle=getComputedStyle$$module$build$src$core$utils$style;module$build$src$core$utils$style.getContainerOffsetToScrollInto=getContainerOffsetToScrollInto$$module$build$src$core$utils$style; +Svg$$module$build$src$core$utils$svg.RECT=new Svg$$module$build$src$core$utils$svg("rect");Svg$$module$build$src$core$utils$svg.SVG=new Svg$$module$build$src$core$utils$svg("svg");Svg$$module$build$src$core$utils$svg.TEXT=new Svg$$module$build$src$core$utils$svg("text");Svg$$module$build$src$core$utils$svg.TSPAN=new Svg$$module$build$src$core$utils$svg("tspan");var module$build$src$core$utils$svg={};module$build$src$core$utils$svg.Svg=Svg$$module$build$src$core$utils$svg;var Rect$$module$build$src$core$utils$rect=class{constructor(a,b,c,d){this.top=a;this.bottom=b;this.left=c;this.right=d}static from(a){return new Rect$$module$build$src$core$utils$rect(a.y,a.y+a.height,a.x,a.x+a.width)}clone(){return new Rect$$module$build$src$core$utils$rect(this.top,this.bottom,this.left,this.right)}getHeight(){return this.bottom-this.top}getWidth(){return this.right-this.left}getOrigin(){return new Coordinate$$module$build$src$core$utils$coordinate(this.left,this.top)}contains(a, +b){return a>=this.left&&a<=this.right&&b>=this.top&&b<=this.bottom}intersects(a){return this.left<=a.right&&this.right>=a.left&&this.bottom>=a.top&&this.top<=a.bottom}static equals(a,b){return a===b?!0:a&&b?a.top===b.top&&a.bottom===b.bottom&&a.left===b.left&&a.right===b.right:!1}static createFromPoint(a,b,c){const d=a.x;a=a.y;return new Rect$$module$build$src$core$utils$rect(a,a+c,d,d+b)}},module$build$src$core$utils$rect={};module$build$src$core$utils$rect.Rect=Rect$$module$build$src$core$utils$rect;var Size$$module$build$src$core$utils$size=class{constructor(a,b){this.width=a;this.height=b}static equals(a,b){return a===b?!0:a&&b?a.width===b.width&&a.height===b.height:!1}static max(a,b){return new Size$$module$build$src$core$utils$size(Math.max(a.width,b.width),Math.max(a.height,b.height))}static min(a,b){return new Size$$module$build$src$core$utils$size(Math.min(a.width,b.width),Math.min(a.height,b.height))}},module$build$src$core$utils$size={};module$build$src$core$utils$size.Size=Size$$module$build$src$core$utils$size;var TEST_ONLY$$module$build$src$core$utils$style={getSizeInternal:getSizeInternal$$module$build$src$core$utils$style},module$build$src$core$utils$style={TEST_ONLY:TEST_ONLY$$module$build$src$core$utils$style};module$build$src$core$utils$style.getBorderBox=getBorderBox$$module$build$src$core$utils$style;module$build$src$core$utils$style.getComputedStyle=getComputedStyle$$module$build$src$core$utils$style;module$build$src$core$utils$style.getContainerOffsetToScrollInto=getContainerOffsetToScrollInto$$module$build$src$core$utils$style; module$build$src$core$utils$style.getPageOffset=getPageOffset$$module$build$src$core$utils$style;module$build$src$core$utils$style.getSize=getSize$$module$build$src$core$utils$style;module$build$src$core$utils$style.getViewportPageOffset=getViewportPageOffset$$module$build$src$core$utils$style;module$build$src$core$utils$style.scrollIntoContainerView=scrollIntoContainerView$$module$build$src$core$utils$style;var XY_REGEX$$module$build$src$core$utils$svg_math=/translate\(\s*([-+\d.e]+)([ ,]\s*([-+\d.e]+)\s*)?/,XY_STYLE_REGEX$$module$build$src$core$utils$svg_math=/transform:\s*translate(?:3d)?\(\s*([-+\d.e]+)\s*px([ ,]\s*([-+\d.e]+)\s*px)?/,TEST_ONLY$$module$build$src$core$utils$svg_math={XY_REGEX:XY_REGEX$$module$build$src$core$utils$svg_math,XY_STYLE_REGEX:XY_STYLE_REGEX$$module$build$src$core$utils$svg_math},module$build$src$core$utils$svg_math={TEST_ONLY:TEST_ONLY$$module$build$src$core$utils$svg_math}; module$build$src$core$utils$svg_math.getDocumentScroll=getDocumentScroll$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.getInjectionDivXY=getInjectionDivXY$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.getRelativeXY=getRelativeXY$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.getViewportBBox=getViewportBBox$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.screenToWsCoordinates=screenToWsCoordinates$$module$build$src$core$utils$svg_math; module$build$src$core$utils$svg_math.wsToScreenCoordinates=wsToScreenCoordinates$$module$build$src$core$utils$svg_math;var Scrollbar$$module$build$src$core$scrollbar=class{constructor(a,b,c,d,e){this.workspace=a;this.horizontal=b;this.oldHostMetrics=null;this.ratio=1;this.origin=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.startDragHandle=this.handlePosition=this.handleLength=this.scrollbarLength=this.startDragMouse=0;this.containerVisible=this.isHandleVisible=!0;this.position=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.onMouseMoveWrapper_=this.onMouseUpWrapper_=null;this.pair= -c||!1;this.margin=void 0!==e?e:Scrollbar$$module$build$src$core$scrollbar.DEFAULT_SCROLLBAR_MARGIN;a="blocklyScrollbar"+(this.horizontal?"Horizontal":"Vertical");d&&(a+=" "+d);this.outerSvg=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{"class":a});d=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},this.outerSvg);this.svgBackground=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT, +c||!1;this.margin=e!==void 0?e:Scrollbar$$module$build$src$core$scrollbar.DEFAULT_SCROLLBAR_MARGIN;a="blocklyScrollbar"+(this.horizontal?"Horizontal":"Vertical");d&&(a+=" "+d);this.outerSvg=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{"class":a});d=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},this.outerSvg);this.svgBackground=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT, {"class":"blocklyScrollbarBackground"},d);a=Math.floor((Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-5)/2);this.svgHandle=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyScrollbarHandle",rx:a,ry:a},d);this.workspace.getThemeManager().subscribe(this.svgHandle,"scrollbarColour","fill");this.workspace.getThemeManager().subscribe(this.svgHandle,"scrollbarOpacity","fill-opacity");insertAfter$$module$build$src$core$utils$dom(this.outerSvg, this.workspace.getParentSvg());this.setInitialThickness();b?(this.lengthAttribute_="width",this.positionAttribute_="x"):(this.lengthAttribute_="height",this.positionAttribute_="y");this.onMouseDownBarWrapper_=conditionalBind$$module$build$src$core$browser_events(this.svgBackground,"pointerdown",this,this.onMouseDownBar);this.onMouseDownHandleWrapper_=conditionalBind$$module$build$src$core$browser_events(this.svgHandle,"pointerdown",this,this.onMouseDownHandle)}setInitialThickness(){const a=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness; this.horizontal?(this.svgBackground.setAttribute("height",String(a)),this.outerSvg.setAttribute("height",String(a)),this.svgHandle.setAttribute("height",String(a-5)),this.svgHandle.setAttribute("y","2.5")):(this.svgBackground.setAttribute("width",String(a)),this.outerSvg.setAttribute("width",String(a)),this.svgHandle.setAttribute("width",String(a-5)),this.svgHandle.setAttribute("x","2.5"))}dispose(){this.cleanUp();unbind$$module$build$src$core$browser_events(this.onMouseDownBarWrapper_);unbind$$module$build$src$core$browser_events(this.onMouseDownHandleWrapper_); -removeNode$$module$build$src$core$utils$dom(this.outerSvg);this.workspace.getThemeManager().unsubscribe(this.svgHandle)}constrainHandleLength(a){return a=0>=a||isNaN(a)?0:Math.min(a,this.scrollbarLength)}setHandleLength(a){this.handleLength=a;this.svgHandle.setAttribute(this.lengthAttribute_,String(this.handleLength))}constrainHandlePosition(a){return a=0>=a||isNaN(a)?0:Math.min(a,this.scrollbarLength-this.handleLength)}setHandlePosition(a){this.handlePosition=a;this.svgHandle.setAttribute(this.positionAttribute_, +removeNode$$module$build$src$core$utils$dom(this.outerSvg);this.workspace.getThemeManager().unsubscribe(this.svgHandle)}constrainHandleLength(a){return a=a<=0||isNaN(a)?0:Math.min(a,this.scrollbarLength)}setHandleLength(a){this.handleLength=a;this.svgHandle.setAttribute(this.lengthAttribute_,String(this.handleLength))}constrainHandlePosition(a){return a=a<=0||isNaN(a)?0:Math.min(a,this.scrollbarLength-this.handleLength)}setHandlePosition(a){this.handlePosition=a;this.svgHandle.setAttribute(this.positionAttribute_, String(this.handlePosition))}setScrollbarLength(a){this.scrollbarLength=a;this.outerSvg.setAttribute(this.lengthAttribute_,String(this.scrollbarLength));this.svgBackground.setAttribute(this.lengthAttribute_,String(this.scrollbarLength))}setPosition(a,b){this.position.x=a;this.position.y=b;setCssTransform$$module$build$src$core$utils$dom(this.outerSvg,"translate("+(this.position.x+this.origin.x)+"px,"+(this.position.y+this.origin.y)+"px)")}resize(a){if(!a&&(a=this.workspace.getMetrics(),!a))return; this.oldHostMetrics&&Scrollbar$$module$build$src$core$scrollbar.metricsAreEquivalent(a,this.oldHostMetrics)||(this.horizontal?this.resizeHorizontal(a):this.resizeVertical(a),this.oldHostMetrics=a,this.updateMetrics())}requiresViewResize(a){return this.oldHostMetrics?this.oldHostMetrics.viewWidth!==a.viewWidth||this.oldHostMetrics.viewHeight!==a.viewHeight||this.oldHostMetrics.absoluteLeft!==a.absoluteLeft||this.oldHostMetrics.absoluteTop!==a.absoluteTop:!0}resizeHorizontal(a){this.requiresViewResize(a)? -this.resizeViewHorizontal(a):this.resizeContentHorizontal(a)}resizeViewHorizontal(a){var b=a.viewWidth-2*this.margin;this.pair&&(b-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setScrollbarLength(Math.max(0,b));b=a.absoluteLeft+this.margin;this.pair&&this.workspace.RTL&&(b+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setPosition(b,a.absoluteTop+a.viewHeight-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-this.margin);this.resizeContentHorizontal(a)}resizeContentHorizontal(a){if(a.viewWidth>= +this.resizeViewHorizontal(a):this.resizeContentHorizontal(a)}resizeViewHorizontal(a){var b=a.viewWidth-this.margin*2;this.pair&&(b-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setScrollbarLength(Math.max(0,b));b=a.absoluteLeft+this.margin;this.pair&&this.workspace.RTL&&(b+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setPosition(b,a.absoluteTop+a.viewHeight-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-this.margin);this.resizeContentHorizontal(a)}resizeContentHorizontal(a){if(a.viewWidth>= a.scrollWidth)this.setHandleLength(this.scrollbarLength),this.setHandlePosition(0),this.pair||this.setVisible(!1);else{this.pair||this.setVisible(!0);var b=this.scrollbarLength*a.viewWidth/a.scrollWidth;b=this.constrainHandleLength(b);this.setHandleLength(b);b=a.scrollWidth-a.viewWidth;var c=this.scrollbarLength-this.handleLength;a=(a.viewLeft-a.scrollLeft)/b*c;a=this.constrainHandlePosition(a);this.setHandlePosition(a);this.ratio=c/b}}resizeVertical(a){this.requiresViewResize(a)?this.resizeViewVertical(a): -this.resizeContentVertical(a)}resizeViewVertical(a){let b=a.viewHeight-2*this.margin;this.pair&&(b-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setScrollbarLength(Math.max(0,b));this.setPosition(this.workspace.RTL?a.absoluteLeft+this.margin:a.absoluteLeft+a.viewWidth-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-this.margin,a.absoluteTop+this.margin);this.resizeContentVertical(a)}resizeContentVertical(a){if(a.viewHeight>=a.scrollHeight)this.setHandleLength(this.scrollbarLength), +this.resizeContentVertical(a)}resizeViewVertical(a){let b=a.viewHeight-this.margin*2;this.pair&&(b-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setScrollbarLength(Math.max(0,b));this.setPosition(this.workspace.RTL?a.absoluteLeft+this.margin:a.absoluteLeft+a.viewWidth-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-this.margin,a.absoluteTop+this.margin);this.resizeContentVertical(a)}resizeContentVertical(a){if(a.viewHeight>=a.scrollHeight)this.setHandleLength(this.scrollbarLength), this.setHandlePosition(0),this.pair||this.setVisible(!1);else{this.pair||this.setVisible(!0);var b=this.scrollbarLength*a.viewHeight/a.scrollHeight;b=this.constrainHandleLength(b);this.setHandleLength(b);b=a.scrollHeight-a.viewHeight;var c=this.scrollbarLength-this.handleLength;a=(a.viewTop-a.scrollTop)/b*c;a=this.constrainHandlePosition(a);this.setHandlePosition(a);this.ratio=c/b}}isVisible(){return this.isHandleVisible}setContainerVisible(a){const b=a!==this.containerVisible;this.containerVisible= a;b&&this.updateDisplay_()}setVisible(a){if(this.pair)throw Error("Unable to toggle visibility of paired scrollbars.");this.setVisibleInternal(a)}setVisibleInternal(a){const b=a!==this.isVisible();this.isHandleVisible=a;b&&this.updateDisplay_()}updateDisplay_(){this.containerVisible&&this.isVisible()?this.outerSvg.setAttribute("display","block"):this.outerSvg.setAttribute("display","none")}onMouseDownBar(a){this.workspace.markFocused();clearTouchIdentifier$$module$build$src$core$touch();this.cleanUp(); -if(isRightButton$$module$build$src$core$browser_events(a))a.stopPropagation();else{var b=mouseToSvg$$module$build$src$core$browser_events(a,this.workspace.getParentSvg(),this.workspace.getInverseScreenCTM());b=this.horizontal?b.x:b.y;var c=getInjectionDivXY$$module$build$src$core$utils$svg_math(this.svgHandle);c=this.horizontal?c.x:c.y;var d=this.handlePosition,e=.95*this.handleLength;b<=c?d-=e:b>=c+this.handleLength&&(d+=e);this.setHandlePosition(this.constrainHandlePosition(d));this.updateMetrics(); +if(isRightButton$$module$build$src$core$browser_events(a))a.stopPropagation();else{var b=mouseToSvg$$module$build$src$core$browser_events(a,this.workspace.getParentSvg(),this.workspace.getInverseScreenCTM());b=this.horizontal?b.x:b.y;var c=getInjectionDivXY$$module$build$src$core$utils$svg_math(this.svgHandle);c=this.horizontal?c.x:c.y;var d=this.handlePosition,e=this.handleLength*.95;b<=c?d-=e:b>=c+this.handleLength&&(d+=e);this.setHandlePosition(this.constrainHandlePosition(d));this.updateMetrics(); a.stopPropagation();a.preventDefault()}}onMouseDownHandle(a){this.workspace.markFocused();this.cleanUp();isRightButton$$module$build$src$core$browser_events(a)?a.stopPropagation():(this.startDragHandle=this.handlePosition,this.startDragMouse=this.horizontal?a.clientX:a.clientY,this.onMouseUpWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"pointerup",this,this.onMouseUpHandle),this.onMouseMoveWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"pointermove", this,this.onMouseMoveHandle),a.stopPropagation(),a.preventDefault())}onMouseMoveHandle(a){this.setHandlePosition(this.constrainHandlePosition(this.startDragHandle+((this.horizontal?a.clientX:a.clientY)-this.startDragMouse)));this.updateMetrics()}onMouseUpHandle(){clearTouchIdentifier$$module$build$src$core$touch();this.cleanUp()}cleanUp(){this.workspace.hideChaff(!0);this.onMouseUpWrapper_&&(unbind$$module$build$src$core$browser_events(this.onMouseUpWrapper_),this.onMouseUpWrapper_=null);this.onMouseMoveWrapper_&& -(unbind$$module$build$src$core$browser_events(this.onMouseMoveWrapper_),this.onMouseMoveWrapper_=null)}getRatio_(){let a=this.handlePosition/(this.scrollbarLength-this.handleLength);isNaN(a)&&(a=0);return a}updateMetrics(){const a=this.getRatio_();this.horizontal?this.workspace.setMetrics({x:a}):this.workspace.setMetrics({y:a})}set(a,b){this.setHandlePosition(this.constrainHandlePosition(a*this.ratio));(b||void 0===b)&&this.updateMetrics()}setOrigin(a,b){this.origin=new Coordinate$$module$build$src$core$utils$coordinate(a, +(unbind$$module$build$src$core$browser_events(this.onMouseMoveWrapper_),this.onMouseMoveWrapper_=null)}getRatio_(){let a=this.handlePosition/(this.scrollbarLength-this.handleLength);isNaN(a)&&(a=0);return a}updateMetrics(){const a=this.getRatio_();this.horizontal?this.workspace.setMetrics({x:a}):this.workspace.setMetrics({y:a})}set(a,b){this.setHandlePosition(this.constrainHandlePosition(a*this.ratio));(b||b===void 0)&&this.updateMetrics()}setOrigin(a,b){this.origin=new Coordinate$$module$build$src$core$utils$coordinate(a, b)}static metricsAreEquivalent(a,b){return a.viewWidth===b.viewWidth&&a.viewHeight===b.viewHeight&&a.viewLeft===b.viewLeft&&a.viewTop===b.viewTop&&a.absoluteTop===b.absoluteTop&&a.absoluteLeft===b.absoluteLeft&&a.scrollWidth===b.scrollWidth&&a.scrollHeight===b.scrollHeight&&a.scrollLeft===b.scrollLeft&&a.scrollTop===b.scrollTop}};Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness=TOUCH_ENABLED$$module$build$src$core$touch?25:15; Scrollbar$$module$build$src$core$scrollbar.DEFAULT_SCROLLBAR_MARGIN=.5;var module$build$src$core$scrollbar={};module$build$src$core$scrollbar.Scrollbar=Scrollbar$$module$build$src$core$scrollbar;var domParser$$module$build$src$core$utils$xml={parseFromString:function(){throw Error("DOMParser was not found in the global scope and was not properly injected using injectDependencies");}},xmlSerializer$$module$build$src$core$utils$xml={serializeToString:function(){throw Error("XMLSerializer was not foundin the global scope and was not properly injected using injectDependencies");}},{document:document$$module$build$src$core$utils$xml,DOMParser:DOMParser$$module$build$src$core$utils$xml,XMLSerializer:XMLSerializer$$module$build$src$core$utils$xml}= globalThis;DOMParser$$module$build$src$core$utils$xml&&(domParser$$module$build$src$core$utils$xml=new DOMParser$$module$build$src$core$utils$xml);XMLSerializer$$module$build$src$core$utils$xml&&(xmlSerializer$$module$build$src$core$utils$xml=new XMLSerializer$$module$build$src$core$utils$xml); @@ -580,8 +648,8 @@ module$build$src$core$positionable_helpers.getCornerOppositeToolbox=getCornerOpp this.createZoomOutSvg(a);this.createZoomInSvg(a);this.workspace.isMovable()&&this.createZoomResetSvg(a);return this.svgGroup}init(){this.workspace.getComponentManager().addComponent({component:this,weight:ComponentManager$$module$build$src$core$component_manager.ComponentWeight.ZOOM_CONTROLS_WEIGHT,capabilities:[ComponentManager$$module$build$src$core$component_manager.Capability.POSITIONABLE]});this.initialized=!0}dispose(){this.workspace.getComponentManager().removeComponent("zoomControls");this.svgGroup&& removeNode$$module$build$src$core$utils$dom(this.svgGroup);for(const a of this.boundEvents)unbind$$module$build$src$core$browser_events(a);this.boundEvents.length=0}getBoundingRectangle(){let a=this.SMALL_SPACING+2*this.HEIGHT;this.zoomResetGroup&&(a+=this.LARGE_SPACING+this.HEIGHT);return new Rect$$module$build$src$core$utils$rect(this.top,this.top+a,this.left,this.left+this.WIDTH)}position(a,b){if(this.initialized){var c=getCornerOppositeToolbox$$module$build$src$core$positionable_helpers(this.workspace, a),d=this.SMALL_SPACING+2*this.HEIGHT;this.zoomResetGroup&&(d+=this.LARGE_SPACING+this.HEIGHT);a=getStartPositionRect$$module$build$src$core$positionable_helpers(c,new Size$$module$build$src$core$utils$size(this.WIDTH,d),this.MARGIN_HORIZONTAL,this.MARGIN_VERTICAL,a,this.workspace);c=c.vertical;b=bumpPositionRect$$module$build$src$core$positionable_helpers(a,this.MARGIN_VERTICAL,c===verticalPosition$$module$build$src$core$positionable_helpers.TOP?bumpDirection$$module$build$src$core$positionable_helpers.DOWN: -bumpDirection$$module$build$src$core$positionable_helpers.UP,b);if(c===verticalPosition$$module$build$src$core$positionable_helpers.TOP){var e=this.SMALL_SPACING+this.HEIGHT,f;null==(f=this.zoomInGroup)||f.setAttribute("transform","translate(0, "+e+")");this.zoomResetGroup&&this.zoomResetGroup.setAttribute("transform","translate(0, "+(e+this.LARGE_SPACING+this.HEIGHT)+")")}else{f=this.zoomResetGroup?this.LARGE_SPACING+this.HEIGHT:0;let h;null==(h=this.zoomInGroup)||h.setAttribute("transform","translate(0, "+ -f+")");f=f+this.SMALL_SPACING+this.HEIGHT;null==(e=this.zoomOutGroup)||e.setAttribute("transform","translate(0, "+f+")")}this.top=b.top;this.left=b.left;var g;null==(g=this.svgGroup)||g.setAttribute("transform","translate("+this.left+","+this.top+")")}}createZoomOutSvg(a){this.zoomOutGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyZoom blocklyZoomOut"},this.svgGroup);const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH, +bumpDirection$$module$build$src$core$positionable_helpers.UP,b);if(c===verticalPosition$$module$build$src$core$positionable_helpers.TOP){var e=this.SMALL_SPACING+this.HEIGHT,f;(f=this.zoomInGroup)==null||f.setAttribute("transform","translate(0, "+e+")");this.zoomResetGroup&&this.zoomResetGroup.setAttribute("transform","translate(0, "+(e+this.LARGE_SPACING+this.HEIGHT)+")")}else{f=this.zoomResetGroup?this.LARGE_SPACING+this.HEIGHT:0;let h;(h=this.zoomInGroup)==null||h.setAttribute("transform","translate(0, "+ +f+")");f=f+this.SMALL_SPACING+this.HEIGHT;(e=this.zoomOutGroup)==null||e.setAttribute("transform","translate(0, "+f+")")}this.top=b.top;this.left=b.left;var g;(g=this.svgGroup)==null||g.setAttribute("transform","translate("+this.left+","+this.top+")")}}createZoomOutSvg(a){this.zoomOutGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyZoom blocklyZoomOut"},this.svgGroup);const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH, {id:"blocklyZoomoutClipPath"+a},this.zoomOutGroup);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:32,height:32},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{width:SPRITE$$module$build$src$core$sprites.width,height:SPRITE$$module$build$src$core$sprites.height,x:-64,y:-92,"clip-path":"url(#blocklyZoomoutClipPath"+a+")"},this.zoomOutGroup).setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href", this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(this.zoomOutGroup,"pointerdown",null,this.zoom.bind(this,-1)))}createZoomInSvg(a){this.zoomInGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyZoom blocklyZoomIn"},this.svgGroup);const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH,{id:"blocklyZoominClipPath"+ a},this.zoomInGroup);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:32,height:32},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{width:SPRITE$$module$build$src$core$sprites.width,height:SPRITE$$module$build$src$core$sprites.height,x:-32,y:-92,"clip-path":"url(#blocklyZoominClipPath"+a+")"},this.zoomInGroup).setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.workspace.options.pathToMedia+ @@ -593,242 +661,252 @@ var module$build$src$core$zoom_controls={};module$build$src$core$zoom_controls.Z WORKSPACE_COMMENTS:WORKSPACE_COMMENTS$$module$build$src$core$serialization$priorities};var module$build$src$core$serialization$registry={};module$build$src$core$serialization$registry.register=register$$module$build$src$core$serialization$registry;module$build$src$core$serialization$registry.unregister=unregister$$module$build$src$core$serialization$registry;var saveComment$$module$build$src$core$serialization$workspace_comments=save$$module$build$src$core$serialization$workspace_comments,WorkspaceCommentSerializer$$module$build$src$core$serialization$workspace_comments=class{constructor(){this.priority=WORKSPACE_COMMENTS$$module$build$src$core$serialization$priorities}save(a){const b=[];for(const c of a.getTopComments())(a=save$$module$build$src$core$serialization$workspace_comments(c,{addCoordinates:!0,saveIds:!0}))&&b.push(a);return b.length?b:null}load(a, b){for(const c of a)append$$module$build$src$core$serialization$workspace_comments(c,b,{recordUndo:getRecordUndo$$module$build$src$core$events$utils()})}clear(a){for(const b of a.getTopComments())b.dispose()}};register$$module$build$src$core$serialization$registry("workspaceComments",new WorkspaceCommentSerializer$$module$build$src$core$serialization$workspace_comments);var module$build$src$core$serialization$workspace_comments={}; module$build$src$core$serialization$workspace_comments.WorkspaceCommentSerializer=WorkspaceCommentSerializer$$module$build$src$core$serialization$workspace_comments;module$build$src$core$serialization$workspace_comments.append=append$$module$build$src$core$serialization$workspace_comments;module$build$src$core$serialization$workspace_comments.save=save$$module$build$src$core$serialization$workspace_comments;var module$build$src$core$clipboard$registry={};module$build$src$core$clipboard$registry.register=register$$module$build$src$core$clipboard$registry;module$build$src$core$clipboard$registry.unregister=unregister$$module$build$src$core$clipboard$registry;var WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster=class{paste(a,b,c){a=a.commentState;c&&(a.x=c.x,a.y=c.y);$.disable$$module$build$src$core$events$utils();let d;try{d=append$$module$build$src$core$serialization$workspace_comments(a,b),moveCommentToNotConflict$$module$build$src$core$clipboard$workspace_comment_paster(d)}finally{$.enable$$module$build$src$core$events$utils()}if(!d)return null;isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_CREATE))(d)); -$.setSelected$$module$build$src$core$common(d);return d}};WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster.TYPE="workspace-comment";register$$module$build$src$core$clipboard$registry(WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster.TYPE,new WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster);var module$build$src$core$clipboard$workspace_comment_paster={}; -module$build$src$core$clipboard$workspace_comment_paster.WorkspaceCommentPaster=WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster;var DEFAULT_SNAP_RADIUS$$module$build$src$core$config,module$build$src$core$config;DEFAULT_SNAP_RADIUS$$module$build$src$core$config=28;$.config$$module$build$src$core$config={dragRadius:5,flyoutDragRadius:10,snapRadius:DEFAULT_SNAP_RADIUS$$module$build$src$core$config,connectingSnapRadius:DEFAULT_SNAP_RADIUS$$module$build$src$core$config,currentConnectionPreference:8,bumpDelay:250};module$build$src$core$config={config:$.config$$module$build$src$core$config};var ARIA_PREFIX$$module$build$src$core$utils$aria="aria-",ROLE_ATTRIBUTE$$module$build$src$core$utils$aria="role",Role$$module$build$src$core$utils$aria;(function(a){a.GRID="grid";a.GRIDCELL="gridcell";a.GROUP="group";a.LISTBOX="listbox";a.MENU="menu";a.MENUITEM="menuitem";a.MENUITEMCHECKBOX="menuitemcheckbox";a.OPTION="option";a.PRESENTATION="presentation";a.ROW="row";a.TREE="tree";a.TREEITEM="treeitem"})(Role$$module$build$src$core$utils$aria||(Role$$module$build$src$core$utils$aria={}));var State$$module$build$src$core$utils$aria; -(function(a){a.ACTIVEDESCENDANT="activedescendant";a.COLCOUNT="colcount";a.DISABLED="disabled";a.EXPANDED="expanded";a.INVALID="invalid";a.LABEL="label";a.LABELLEDBY="labelledby";a.LEVEL="level";a.ORIENTATION="orientation";a.POSINSET="posinset";a.ROWCOUNT="rowcount";a.SELECTED="selected";a.SETSIZE="setsize";a.VALUEMAX="valuemax";a.VALUEMIN="valuemin"})(State$$module$build$src$core$utils$aria||(State$$module$build$src$core$utils$aria={}));var module$build$src$core$utils$aria={}; -module$build$src$core$utils$aria.Role=Role$$module$build$src$core$utils$aria;module$build$src$core$utils$aria.State=State$$module$build$src$core$utils$aria;module$build$src$core$utils$aria.setRole=setRole$$module$build$src$core$utils$aria;module$build$src$core$utils$aria.setState=setState$$module$build$src$core$utils$aria;var Menu$$module$build$src$core$menu=class{constructor(){this.menuItems=[];this.roleName=this.element=this.onKeyDownHandler=this.pointerLeaveHandler=this.pointerEnterHandler=this.clickHandler=this.pointerMoveHandler=this.highlightedItem=this.openingCoords=null}addChild(a){this.menuItems.push(a)}render(a){const b=document.createElement("div");b.className="blocklyMenu goog-menu blocklyNonSelectable";b.tabIndex=0;this.roleName&&setRole$$module$build$src$core$utils$aria(b,this.roleName);this.element= -b;for(let c=0,d;d=this.menuItems[c];c++)b.appendChild(d.createDom());this.pointerMoveHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointermove",this,this.handlePointerMove,!0);this.clickHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointerup",this,this.handleClick,!0);this.pointerEnterHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointerenter",this,this.handlePointerEnter,!0);this.pointerLeaveHandler=conditionalBind$$module$build$src$core$browser_events(b, -"pointerleave",this,this.handlePointerLeave,!0);this.onKeyDownHandler=conditionalBind$$module$build$src$core$browser_events(b,"keydown",this,this.handleKeyEvent);a.appendChild(b);return b}getElement(){return this.element}focus(){const a=this.getElement();a&&(a.focus({preventScroll:!0}),addClass$$module$build$src$core$utils$dom(a,"blocklyFocused"))}blur(){const a=this.getElement();a&&(a.blur(),removeClass$$module$build$src$core$utils$dom(a,"blocklyFocused"))}setRole(a){this.roleName=a}dispose(){this.pointerMoveHandler&& -(unbind$$module$build$src$core$browser_events(this.pointerMoveHandler),this.pointerMoveHandler=null);this.clickHandler&&(unbind$$module$build$src$core$browser_events(this.clickHandler),this.clickHandler=null);this.pointerEnterHandler&&(unbind$$module$build$src$core$browser_events(this.pointerEnterHandler),this.pointerEnterHandler=null);this.pointerLeaveHandler&&(unbind$$module$build$src$core$browser_events(this.pointerLeaveHandler),this.pointerLeaveHandler=null);this.onKeyDownHandler&&(unbind$$module$build$src$core$browser_events(this.onKeyDownHandler), -this.onKeyDownHandler=null);for(let a=0,b;b=this.menuItems[a];a++)b.dispose();this.element=null}getMenuItem(a){const b=this.getElement();for(;a&&a!==b;){if(a.classList.contains("blocklyMenuItem"))for(let c=0,d;d=this.menuItems[c];c++)if(d.getElement()===a)return d;a=a.parentElement}return null}setHighlighted(a){var b=this.highlightedItem;b&&(b.setHighlighted(!1),this.highlightedItem=null);if(a){a.setHighlighted(!0);this.highlightedItem=a;b=this.getElement();const c=null==b?void 0:b.parentElement, -d=a.getElement();c&&d&&(scrollIntoContainerView$$module$build$src$core$utils$style(d,c),setState$$module$build$src$core$utils$aria(b,State$$module$build$src$core$utils$aria.ACTIVEDESCENDANT,a.getId()))}}highlightNext(){const a=this.highlightedItem?this.menuItems.indexOf(this.highlightedItem):-1;this.highlightHelper(a,1)}highlightPrevious(){const a=this.highlightedItem?this.menuItems.indexOf(this.highlightedItem):-1;this.highlightHelper(0>a?this.menuItems.length:a,-1)}highlightFirst(){this.highlightHelper(-1, -1)}highlightLast(){this.highlightHelper(this.menuItems.length,-1)}highlightHelper(a,b){a+=b;let c;for(;c=this.menuItems[a];){if(c.isEnabled()){this.setHighlighted(c);break}a+=b}}handlePointerMove(a){0!==Math.max(Math.abs(a.movementX),Math.abs(a.movementY))&&(a=this.getMenuItem(a.target))&&(a.isEnabled()?this.highlightedItem!==a&&this.setHighlighted(a):this.setHighlighted(null))}handleClick(a){const b=this.openingCoords;this.openingCoords=null;if(b&&"number"===typeof a.clientX){const c=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX, -a.clientY);if(1>Coordinate$$module$build$src$core$utils$coordinate.distance(b,c))return}(a=this.getMenuItem(a.target))&&a.performAction()}handlePointerEnter(a){this.focus()}handlePointerLeave(a){this.getElement()&&this.setHighlighted(null)}handleKeyEvent(a){if(this.menuItems.length&&!(a.shiftKey||a.ctrlKey||a.metaKey||a.altKey)){var b=this.highlightedItem;switch(a.key){case "Enter":case " ":b&&b.performAction();break;case "ArrowUp":this.highlightPrevious();break;case "ArrowDown":this.highlightNext(); -break;case "PageUp":case "Home":this.highlightFirst();break;case "PageDown":case "End":this.highlightLast();break;default:return}a.preventDefault();a.stopPropagation()}}getSize(){const a=this.getElement(),b=getSize$$module$build$src$core$utils$style(a);b.height=a.scrollHeight;return b}},module$build$src$core$menu={};module$build$src$core$menu.Menu=Menu$$module$build$src$core$menu;var MenuItem$$module$build$src$core$menuitem=class{constructor(a,b){this.content=a;this.opt_value=b;this.enabled=!0;this.element=null;this.rightToLeft=!1;this.roleName=null;this.highlight=this.checked=this.checkable=!1;this.actionHandler=null}createDom(){const a=document.createElement("div");a.id=getNextUniqueId$$module$build$src$core$utils$idgenerator();this.element=a;a.className="blocklyMenuItem goog-menuitem "+(this.enabled?"":"blocklyMenuItemDisabled goog-menuitem-disabled ")+(this.checked?"blocklyMenuItemSelected goog-option-selected ": -"")+(this.highlight?"blocklyMenuItemHighlight goog-menuitem-highlight ":"")+(this.rightToLeft?"blocklyMenuItemRtl goog-menuitem-rtl ":"");const b=document.createElement("div");b.className="blocklyMenuItemContent goog-menuitem-content";if(this.checkable){var c=document.createElement("div");c.className="blocklyMenuItemCheckbox goog-menuitem-checkbox";b.appendChild(c)}c=this.content;"string"===typeof this.content&&(c=document.createTextNode(this.content));b.appendChild(c);a.appendChild(b);this.roleName&& -setRole$$module$build$src$core$utils$aria(a,this.roleName);setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.SELECTED,this.checkable&&this.checked||!1);setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.DISABLED,!this.enabled);return a}dispose(){this.element=null}getElement(){return this.element}getId(){return this.element.id}getValue(){let a;return null!=(a=this.opt_value)?a:null}setRightToLeft(a){this.rightToLeft=a}setRole(a){this.roleName= -a}setCheckable(a){this.checkable=a}setChecked(a){this.checked=a}setHighlighted(a){this.highlight=a;const b=this.getElement();b&&this.isEnabled()&&(a?(addClass$$module$build$src$core$utils$dom(b,"blocklyMenuItemHighlight"),addClass$$module$build$src$core$utils$dom(b,"goog-menuitem-highlight")):(removeClass$$module$build$src$core$utils$dom(b,"blocklyMenuItemHighlight"),removeClass$$module$build$src$core$utils$dom(b,"goog-menuitem-highlight")))}isEnabled(){return this.enabled}setEnabled(a){this.enabled= -a}performAction(){this.isEnabled()&&this.actionHandler&&this.actionHandler(this)}onAction(a,b){this.actionHandler=a.bind(b)}},module$build$src$core$menuitem={};module$build$src$core$menuitem.MenuItem=MenuItem$$module$build$src$core$menuitem;var COLLAPSED_INPUT_NAME$$module$build$src$core$constants="_TEMP_COLLAPSED_INPUT",COLLAPSED_FIELD_NAME$$module$build$src$core$constants="_TEMP_COLLAPSED_FIELD",MANUALLY_DISABLED$$module$build$src$core$constants="MANUALLY_DISABLED",module$build$src$core$constants={COLLAPSED_FIELD_NAME:COLLAPSED_FIELD_NAME$$module$build$src$core$constants,COLLAPSED_INPUT_NAME:COLLAPSED_INPUT_NAME$$module$build$src$core$constants,MANUALLY_DISABLED:MANUALLY_DISABLED$$module$build$src$core$constants};(function(a){a[a.VALUE=1]="VALUE";a[a.STATEMENT=3]="STATEMENT";a[a.DUMMY=5]="DUMMY";a[a.CUSTOM=6]="CUSTOM";a[a.END_ROW=7]="END_ROW"})($.inputTypes$$module$build$src$core$inputs$input_types||($.inputTypes$$module$build$src$core$inputs$input_types={}));var module$build$src$core$inputs$input_types={};module$build$src$core$inputs$input_types.inputTypes=$.inputTypes$$module$build$src$core$inputs$input_types;var module$build$src$core$interfaces$i_serializable={};module$build$src$core$interfaces$i_serializable.isSerializable=isSerializable$$module$build$src$core$interfaces$i_serializable;var rootBlocks$$module$build$src$core$render_management=new Set,dirtyBlocks$$module$build$src$core$render_management=new WeakSet,eventGroups$$module$build$src$core$render_management=new WeakMap,afterRendersPromise$$module$build$src$core$render_management=null,afterRendersResolver$$module$build$src$core$render_management=null,animationRequestId$$module$build$src$core$render_management=0,module$build$src$core$render_management={};module$build$src$core$render_management.finishQueuedRenders=finishQueuedRenders$$module$build$src$core$render_management; -module$build$src$core$render_management.queueRender=queueRender$$module$build$src$core$render_management;module$build$src$core$render_management.triggerQueuedRenders=triggerQueuedRenders$$module$build$src$core$render_management;var alertImplementation$$module$build$src$core$dialog=function(a,b){window.alert(a);b&&b()},confirmImplementation$$module$build$src$core$dialog=function(a,b){b(window.confirm(a))},promptImplementation$$module$build$src$core$dialog=function(a,b,c){c(window.prompt(a,b))},TEST_ONLY$$module$build$src$core$dialog={confirmInternal:confirmInternal$$module$build$src$core$dialog},module$build$src$core$dialog={TEST_ONLY:TEST_ONLY$$module$build$src$core$dialog};module$build$src$core$dialog.alert=alert$$module$build$src$core$dialog; -module$build$src$core$dialog.confirm=confirm$$module$build$src$core$dialog;module$build$src$core$dialog.prompt=prompt$$module$build$src$core$dialog;module$build$src$core$dialog.setAlert=setAlert$$module$build$src$core$dialog;module$build$src$core$dialog.setConfirm=setConfirm$$module$build$src$core$dialog;module$build$src$core$dialog.setPrompt=setPrompt$$module$build$src$core$dialog;var module$build$src$core$interfaces$i_legacy_procedure_blocks={};module$build$src$core$interfaces$i_legacy_procedure_blocks.isLegacyProcedureCallBlock=isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks;module$build$src$core$interfaces$i_legacy_procedure_blocks.isLegacyProcedureDefBlock=isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks;var module$build$src$core$interfaces$i_variable_backed_parameter_model={};module$build$src$core$interfaces$i_variable_backed_parameter_model.isVariableBackedParameterModel=isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model;var setLocale$$module$build$src$core$msg,module$build$src$core$msg;$.Msg$$module$build$src$core$msg=Object.create(null);setLocale$$module$build$src$core$msg=function(a){Object.keys(a).forEach(function(b){$.Msg$$module$build$src$core$msg[b]=a[b]})};module$build$src$core$msg={Msg:$.Msg$$module$build$src$core$msg,setLocale:setLocale$$module$build$src$core$msg};var VarBase$$module$build$src$core$events$events_var_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank="undefined"===typeof a;a&&(this.varId=a.getId(),this.workspaceId=a.workspace.id)}toJson(){const a=super.toJson();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");a.varId=this.varId;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new VarBase$$module$build$src$core$events$events_var_base); -b.varId=a.varId;return b}},module$build$src$core$events$events_var_base={};module$build$src$core$events$events_var_base.VarBase=VarBase$$module$build$src$core$events$events_var_base;var VarCreate$$module$build$src$core$events$events_var_create=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a){super(a);this.type=EventType$$module$build$src$core$events$type.VAR_CREATE;a&&(this.varType=a.type,this.varName=a.name)}toJson(){const a=super.toJson();if(void 0===this.varType)throw Error("The var type is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); -a.varType=this.varType;a.varName=this.varName;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new VarCreate$$module$build$src$core$events$events_var_create);b.varType=a.varType;b.varName=a.varName;return b}run(a){const b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson");a?b.createVariable(this.varName, -this.varType,this.varId):b.deleteVariableById(this.varId)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VAR_CREATE,VarCreate$$module$build$src$core$events$events_var_create);var module$build$src$core$events$events_var_create={};module$build$src$core$events$events_var_create.VarCreate=VarCreate$$module$build$src$core$events$events_var_create;var VariableModel$$module$build$src$core$variable_model=class{constructor(a,b,c,d){this.workspace=a;this.name=b;this.type=c||"";this.id=d||genUid$$module$build$src$core$utils$idgenerator()}getId(){return this.id}static compareByName(a,b){return a.name.localeCompare(b.name,void 0,{sensitivity:"base"})}},module$build$src$core$variable_model={};module$build$src$core$variable_model.VariableModel=VariableModel$$module$build$src$core$variable_model;var CATEGORY_NAME$$module$build$src$core$variables="VARIABLE",VAR_LETTER_OPTIONS$$module$build$src$core$variables="ijkmnopqrstuvwxyzabcdefgh",TEST_ONLY$$module$build$src$core$variables={generateUniqueNameInternal:generateUniqueNameInternal$$module$build$src$core$variables},module$build$src$core$variables={CATEGORY_NAME:CATEGORY_NAME$$module$build$src$core$variables,TEST_ONLY:TEST_ONLY$$module$build$src$core$variables,VAR_LETTER_OPTIONS:VAR_LETTER_OPTIONS$$module$build$src$core$variables}; -module$build$src$core$variables.allDeveloperVariables=$.allDeveloperVariables$$module$build$src$core$variables;module$build$src$core$variables.allUsedVarModels=$.allUsedVarModels$$module$build$src$core$variables;module$build$src$core$variables.createVariableButtonHandler=createVariableButtonHandler$$module$build$src$core$variables;module$build$src$core$variables.flyoutCategory=flyoutCategory$$module$build$src$core$variables;module$build$src$core$variables.flyoutCategoryBlocks=flyoutCategoryBlocks$$module$build$src$core$variables; -module$build$src$core$variables.generateUniqueName=generateUniqueName$$module$build$src$core$variables;module$build$src$core$variables.generateUniqueNameFromOptions=generateUniqueNameFromOptions$$module$build$src$core$variables;module$build$src$core$variables.generateVariableFieldDom=generateVariableFieldDom$$module$build$src$core$variables;module$build$src$core$variables.getAddedVariables=getAddedVariables$$module$build$src$core$variables; -module$build$src$core$variables.getOrCreateVariablePackage=$.getOrCreateVariablePackage$$module$build$src$core$variables;module$build$src$core$variables.getVariable=$.getVariable$$module$build$src$core$variables;module$build$src$core$variables.nameUsedWithAnyType=nameUsedWithAnyType$$module$build$src$core$variables;module$build$src$core$variables.nameUsedWithConflictingParam=nameUsedWithConflictingParam$$module$build$src$core$variables;module$build$src$core$variables.promptName=promptName$$module$build$src$core$variables; -module$build$src$core$variables.renameVariable=$.renameVariable$$module$build$src$core$variables;var DeserializationError$$module$build$src$core$serialization$exceptions=class extends Error{},MissingBlockType$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a){super("Expected to find a 'type' property, defining the block type");this.state=a}},MissingConnection$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a, +$.getFocusManager$$module$build$src$core$focus_manager().focusNode(d);return d}};WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster.TYPE="workspace-comment";register$$module$build$src$core$clipboard$registry(WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster.TYPE,new WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster);var module$build$src$core$clipboard$workspace_comment_paster={}; +module$build$src$core$clipboard$workspace_comment_paster.WorkspaceCommentPaster=WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster;var DEFAULT_SNAP_RADIUS$$module$build$src$core$config,module$build$src$core$config;DEFAULT_SNAP_RADIUS$$module$build$src$core$config=28;$.config$$module$build$src$core$config={dragRadius:5,flyoutDragRadius:10,snapRadius:DEFAULT_SNAP_RADIUS$$module$build$src$core$config,connectingSnapRadius:DEFAULT_SNAP_RADIUS$$module$build$src$core$config,currentConnectionPreference:8,bumpDelay:250};module$build$src$core$config={config:$.config$$module$build$src$core$config};var ARIA_PREFIX$$module$build$src$core$utils$aria="aria-",ROLE_ATTRIBUTE$$module$build$src$core$utils$aria="role",Role$$module$build$src$core$utils$aria; +(function(a){a.GRID="grid";a.GRIDCELL="gridcell";a.GROUP="group";a.LISTBOX="listbox";a.MENU="menu";a.MENUITEM="menuitem";a.MENUITEMCHECKBOX="menuitemcheckbox";a.OPTION="option";a.PRESENTATION="presentation";a.ROW="row";a.TREE="tree";a.TREEITEM="treeitem";a.SEPARATOR="separator";a.STATUS="status"})(Role$$module$build$src$core$utils$aria||(Role$$module$build$src$core$utils$aria={}));var State$$module$build$src$core$utils$aria; +(function(a){a.ACTIVEDESCENDANT="activedescendant";a.COLCOUNT="colcount";a.DISABLED="disabled";a.EXPANDED="expanded";a.INVALID="invalid";a.LABEL="label";a.LABELLEDBY="labelledby";a.LEVEL="level";a.ORIENTATION="orientation";a.POSINSET="posinset";a.ROWCOUNT="rowcount";a.SELECTED="selected";a.SETSIZE="setsize";a.VALUEMAX="valuemax";a.VALUEMIN="valuemin";a.LIVE="live";a.HIDDEN="hidden"})(State$$module$build$src$core$utils$aria||(State$$module$build$src$core$utils$aria={})); +var module$build$src$core$utils$aria={};module$build$src$core$utils$aria.Role=Role$$module$build$src$core$utils$aria;module$build$src$core$utils$aria.State=State$$module$build$src$core$utils$aria;module$build$src$core$utils$aria.setRole=setRole$$module$build$src$core$utils$aria;module$build$src$core$utils$aria.setState=setState$$module$build$src$core$utils$aria;var MenuItem$$module$build$src$core$menuitem=class{constructor(a,b){this.content=a;this.opt_value=b;this.enabled=!0;this.element=null;this.rightToLeft=!1;this.roleName=null;this.highlight=this.checked=this.checkable=!1;this.actionHandler=null}createDom(){const a=document.createElement("div");a.id=getNextUniqueId$$module$build$src$core$utils$idgenerator();this.element=a;a.className="blocklyMenuItem "+(this.enabled?"":"blocklyMenuItemDisabled ")+(this.checked?"blocklyMenuItemSelected ":"")+(this.highlight? +"blocklyMenuItemHighlight ":"")+(this.rightToLeft?"blocklyMenuItemRtl ":"");const b=document.createElement("div");b.className="blocklyMenuItemContent";let c=this.content;typeof this.content==="string"&&(c=document.createTextNode(this.content));b.appendChild(c);a.appendChild(b);this.checkable&&this.toggleHasCheckbox(!0);this.roleName&&setRole$$module$build$src$core$utils$aria(a,this.roleName);setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.SELECTED,this.checkable&& +this.checked||!1);setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.DISABLED,!this.enabled);return a}dispose(){this.element=null}getElement(){return this.element}getId(){return this.element.id}getValue(){let a;return(a=this.opt_value)!=null?a:null}setRightToLeft(a){this.rightToLeft=a;let b;(b=this.getElement())==null||b.classList.toggle("blocklyMenuItemRtl",this.rightToLeft)}setRole(a){this.roleName=a}setCheckable(a){(this.checkable=a)||this.setChecked(!1);this.toggleHasCheckbox(a)}setChecked(a){if(!a|| +this.checkable)if(this.checked=a,a=this.getElement())a.classList.toggle("blocklyMenuItemSelected",this.checked),setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.SELECTED,this.checked)}setHighlighted(a){this.highlight=a;if(this.isEnabled()){let b;(b=this.getElement())==null||b.classList.toggle("blocklyMenuItemHighlight",this.highlight)}}isEnabled(){return this.enabled}setEnabled(a){this.enabled=a;if(a=this.getElement())a.classList.toggle("blocklyMenuItemDisabled", +!this.enabled),setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.DISABLED,!this.enabled)}performAction(a){this.isEnabled()&&this.actionHandler&&this.actionHandler(this,a)}onAction(a,b){this.actionHandler=a.bind(b)}toggleHasCheckbox(a){if(a){let d;if((d=this.getElement())==null||!d.querySelector(".blocklyMenuItemContent .blocklyMenuItemCheckbox")){a=document.createElement("div");a.className="blocklyMenuItemCheckbox ";var b,c;(b=this.getElement())==null||(c=b.querySelector(".blocklyMenuItemContent"))== +null||c.prepend(a)}}else{let d,e;(d=this.getElement())==null||(e=d.querySelector(".blocklyMenuItemContent .blocklyMenuItemCheckbox"))==null||e.remove()}}},module$build$src$core$menuitem={};module$build$src$core$menuitem.MenuItem=MenuItem$$module$build$src$core$menuitem;var Menu$$module$build$src$core$menu=class{constructor(){this.menuItems=[];this.roleName=this.element=this.onKeyDownHandler=this.pointerLeaveHandler=this.pointerEnterHandler=this.clickHandler=this.pointerMoveHandler=this.highlightedItem=this.openingCoords=null}addChild(a){this.menuItems.push(a)}render(a){const b=document.createElement("div");b.className="blocklyMenu";b.tabIndex=0;this.roleName&&setRole$$module$build$src$core$utils$aria(b,this.roleName);this.element=b;for(let c=0,d;d=this.menuItems[c];c++)b.appendChild(d.createDom()); +this.pointerMoveHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointermove",this,this.handlePointerMove,!0);this.clickHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointerup",this,this.handleClick,!0);this.pointerEnterHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointerenter",this,this.handlePointerEnter,!0);this.pointerLeaveHandler=conditionalBind$$module$build$src$core$browser_events(b,"pointerleave",this,this.handlePointerLeave,!0);this.onKeyDownHandler= +conditionalBind$$module$build$src$core$browser_events(b,"keydown",this,this.handleKeyEvent);a.appendChild(b);return b}getElement(){return this.element}focus(){const a=this.getElement();a&&a.focus({preventScroll:!0})}blur(){const a=this.getElement();a&&a.blur()}setRole(a){this.roleName=a}dispose(){this.pointerMoveHandler&&(unbind$$module$build$src$core$browser_events(this.pointerMoveHandler),this.pointerMoveHandler=null);this.clickHandler&&(unbind$$module$build$src$core$browser_events(this.clickHandler), +this.clickHandler=null);this.pointerEnterHandler&&(unbind$$module$build$src$core$browser_events(this.pointerEnterHandler),this.pointerEnterHandler=null);this.pointerLeaveHandler&&(unbind$$module$build$src$core$browser_events(this.pointerLeaveHandler),this.pointerLeaveHandler=null);this.onKeyDownHandler&&(unbind$$module$build$src$core$browser_events(this.onKeyDownHandler),this.onKeyDownHandler=null);for(let a=0,b;b=this.menuItems[a];a++)b.dispose();this.element=null}getMenuItem(a){const b=this.getElement(); +for(;a&&a!==b;){if(a.classList.contains("blocklyMenuItem")){const c=this.getMenuItems();for(let d=0,e;e=c[d];d++)if(e.getElement()===a)return e}a=a.parentElement}return null}setHighlighted(a){var b=this.highlightedItem;b&&(b.setHighlighted(!1),this.highlightedItem=null);if(a){a.setHighlighted(!0);this.highlightedItem=a;b=this.getElement();const c=a.getElement();b&&c&&(scrollIntoContainerView$$module$build$src$core$utils$style(c,b),setState$$module$build$src$core$utils$aria(b,State$$module$build$src$core$utils$aria.ACTIVEDESCENDANT, +a.getId()))}}highlightNext(){const a=this.highlightedItem?this.getMenuItems().indexOf(this.highlightedItem):-1;this.highlightHelper(a,1)}highlightPrevious(){const a=this.highlightedItem?this.getMenuItems().indexOf(this.highlightedItem):-1;this.highlightHelper(a<0?this.menuItems.length:a,-1)}highlightFirst(){this.highlightHelper(-1,1)}highlightLast(){this.highlightHelper(this.menuItems.length,-1)}highlightHelper(a,b){a+=b;let c;const d=this.getMenuItems();for(;c=d[a];){if(c.isEnabled()){this.setHighlighted(c); +break}a+=b}}handlePointerMove(a){Math.max(Math.abs(a.movementX),Math.abs(a.movementY))!==0&&(a=this.getMenuItem(a.target))&&(a.isEnabled()?this.highlightedItem!==a&&this.setHighlighted(a):this.setHighlighted(null))}handleClick(a){var b=this.openingCoords;this.openingCoords=null;if(b&&typeof a.clientX==="number"){const c=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY);if(Coordinate$$module$build$src$core$utils$coordinate.distance(b,c)<1)return}(b=this.getMenuItem(a.target))&& +b.performAction(a)}handlePointerEnter(a){this.focus()}handlePointerLeave(a){this.getElement()&&this.setHighlighted(null)}handleKeyEvent(a){if(this.menuItems.length&&!(a.shiftKey||a.ctrlKey||a.metaKey||a.altKey)){var b=this.highlightedItem;switch(a.key){case "Enter":case " ":b&&b.performAction(a);break;case "ArrowUp":this.highlightPrevious();break;case "ArrowDown":this.highlightNext();break;case "PageUp":case "Home":this.highlightFirst();break;case "PageDown":case "End":this.highlightLast();break; +default:return}a.preventDefault();a.stopPropagation()}}getSize(){const a=this.getElement(),b=getSize$$module$build$src$core$utils$style(a);b.height=a.scrollHeight;return b}getMenuItems(){return this.menuItems.filter(a=>a instanceof MenuItem$$module$build$src$core$menuitem)}},module$build$src$core$menu={};module$build$src$core$menu.Menu=Menu$$module$build$src$core$menu;var MenuSeparator$$module$build$src$core$menu_separator=class{constructor(){this.element=null}createDom(){this.element=document.createElement("hr");this.element.className="blocklyMenuSeparator";setRole$$module$build$src$core$utils$aria(this.element,Role$$module$build$src$core$utils$aria.SEPARATOR);return this.element}dispose(){let a;(a=this.element)==null||a.remove();this.element=null}},module$build$src$core$menu_separator={};module$build$src$core$menu_separator.MenuSeparator=MenuSeparator$$module$build$src$core$menu_separator;var COLLAPSED_INPUT_NAME$$module$build$src$core$constants="_TEMP_COLLAPSED_INPUT",COLLAPSED_FIELD_NAME$$module$build$src$core$constants="_TEMP_COLLAPSED_FIELD",MANUALLY_DISABLED$$module$build$src$core$constants="MANUALLY_DISABLED",module$build$src$core$constants={COLLAPSED_FIELD_NAME:COLLAPSED_FIELD_NAME$$module$build$src$core$constants,COLLAPSED_INPUT_NAME:COLLAPSED_INPUT_NAME$$module$build$src$core$constants,MANUALLY_DISABLED:MANUALLY_DISABLED$$module$build$src$core$constants};(function(a){a[a.VALUE=1]="VALUE";a[a.STATEMENT=3]="STATEMENT";a[a.DUMMY=5]="DUMMY";a[a.CUSTOM=6]="CUSTOM";a[a.END_ROW=7]="END_ROW"})($.inputTypes$$module$build$src$core$inputs$input_types||($.inputTypes$$module$build$src$core$inputs$input_types={}));var module$build$src$core$inputs$input_types={};module$build$src$core$inputs$input_types.inputTypes=$.inputTypes$$module$build$src$core$inputs$input_types;var module$build$src$core$interfaces$i_serializable={};module$build$src$core$interfaces$i_serializable.isSerializable=isSerializable$$module$build$src$core$interfaces$i_serializable;var rootBlocks$$module$build$src$core$render_management=new Set,dirtyBlocks$$module$build$src$core$render_management=new WeakSet,eventGroups$$module$build$src$core$render_management=new WeakMap,afterRendersPromise$$module$build$src$core$render_management=null,afterRendersResolver$$module$build$src$core$render_management=null,animationRequestId$$module$build$src$core$render_management=0,module$build$src$core$render_management={};module$build$src$core$render_management.finishQueuedRenders=finishQueuedRenders$$module$build$src$core$render_management; +module$build$src$core$render_management.queueRender=queueRender$$module$build$src$core$render_management;module$build$src$core$render_management.triggerQueuedRenders=triggerQueuedRenders$$module$build$src$core$render_management;var setLocale$$module$build$src$core$msg,module$build$src$core$msg;$.Msg$$module$build$src$core$msg=Object.create(null);setLocale$$module$build$src$core$msg=function(a){Object.keys(a).forEach(function(b){$.Msg$$module$build$src$core$msg[b]=a[b]})};module$build$src$core$msg={Msg:$.Msg$$module$build$src$core$msg,setLocale:setLocale$$module$build$src$core$msg};var CLASS_NAME$$module$build$src$core$toast="blocklyToast",MESSAGE_CLASS_NAME$$module$build$src$core$toast="blocklyToastMessage",CLOSE_BUTTON_CLASS_NAME$$module$build$src$core$toast="blocklyToastCloseButton",Toast$$module$build$src$core$toast=class{static show(a,b){if(b.oncePerSession&&b.id){if(this.shownIds.has(b.id))return;this.shownIds.add(b.id)}this.hide(a);const c=this.createDom(a,b);requestAnimationFrame(()=>{c.style.bottom="2rem"})}static createDom(a,b){const {message:c,duration:d=5,assertiveness:e= +Toast$$module$build$src$core$toast.Assertiveness.POLITE}=b,f=document.createElement("div");a.getInjectionDiv().appendChild(f);f.dataset.toastId=b.id;f.className=CLASS_NAME$$module$build$src$core$toast;setRole$$module$build$src$core$utils$aria(f,Role$$module$build$src$core$utils$aria.STATUS);setState$$module$build$src$core$utils$aria(f,State$$module$build$src$core$utils$aria.LIVE,e);b=f.appendChild(document.createElement("div"));b.className=MESSAGE_CLASS_NAME$$module$build$src$core$toast;b.innerText= +c;b=f.appendChild(document.createElement("button"));b.className=CLOSE_BUTTON_CLASS_NAME$$module$build$src$core$toast;setState$$module$build$src$core$utils$aria(b,State$$module$build$src$core$utils$aria.LABEL,$.Msg$$module$build$src$core$msg.CLOSE);var g=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{width:24,height:24,viewBox:"0 0 24 24",fill:"none"},b);setState$$module$build$src$core$utils$aria(g,State$$module$build$src$core$utils$aria.HIDDEN,!0);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT, +{x:19.7782,y:2.80762,width:2,height:24,transform:"rotate(45, 19.7782, 2.80762)",fill:"black"},g);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{x:2.80762,y:4.22183,width:2,height:24,transform:"rotate(-45, 2.80762, 4.22183)",fill:"black"},g);b.addEventListener("click",()=>{f.remove();a.markFocused()});let h;b=()=>{h=setTimeout(()=>f.remove(),d*1E3)};g=()=>clearTimeout(h);f.addEventListener("focusin",g);f.addEventListener("focusout",b);f.addEventListener("mouseenter", +g);f.addEventListener("mousemove",g);f.addEventListener("mouseleave",b);b();return f}static hide(a,b){a=a.getInjectionDiv().querySelector(`.${CLASS_NAME$$module$build$src$core$toast}`);a instanceof HTMLElement&&(!b||b===a.dataset.toastId)&&a.remove()}};Toast$$module$build$src$core$toast.shownIds=new Set;(function(a){a=a.Assertiveness||(a.Assertiveness={});a.ASSERTIVE="assertive";a.POLITE="polite"})(Toast$$module$build$src$core$toast||(Toast$$module$build$src$core$toast={}));register$$module$build$src$core$css(` +.${CLASS_NAME$$module$build$src$core$toast} { + font-size: 1.2rem; + position: absolute; + bottom: -10rem; + right: 2rem; + padding: 1rem; + color: black; + background-color: white; + border: 2px solid black; + border-radius: 0.4rem; + z-index: 999; + display: flex; + align-items: center; + gap: 0.8rem; + line-height: 1.5; + transition: bottom 0.3s ease-out; +} + +.${CLASS_NAME$$module$build$src$core$toast} .${MESSAGE_CLASS_NAME$$module$build$src$core$toast} { + maxWidth: 18rem; +} + +.${CLASS_NAME$$module$build$src$core$toast} .${CLOSE_BUTTON_CLASS_NAME$$module$build$src$core$toast} { + margin: 0; + padding: 0.2rem; + background-color: transparent; + color: black; + border: none; + cursor: pointer; +} +`);var module$build$src$core$toast={};module$build$src$core$toast.Toast=Toast$$module$build$src$core$toast;var defaultAlert$$module$build$src$core$dialog=function(a,b){window.alert(a);b&&b()},alertImplementation$$module$build$src$core$dialog=defaultAlert$$module$build$src$core$dialog,defaultConfirm$$module$build$src$core$dialog=function(a,b){b(window.confirm(a))},confirmImplementation$$module$build$src$core$dialog=defaultConfirm$$module$build$src$core$dialog,defaultPrompt$$module$build$src$core$dialog=function(a,b,c){c(window.prompt(a,b))},promptImplementation$$module$build$src$core$dialog=defaultPrompt$$module$build$src$core$dialog, +defaultToast$$module$build$src$core$dialog=Toast$$module$build$src$core$toast.show.bind(Toast$$module$build$src$core$toast),toastImplementation$$module$build$src$core$dialog=defaultToast$$module$build$src$core$dialog,module$build$src$core$dialog={};module$build$src$core$dialog.alert=alert$$module$build$src$core$dialog;module$build$src$core$dialog.confirm=confirm$$module$build$src$core$dialog;module$build$src$core$dialog.prompt=prompt$$module$build$src$core$dialog; +module$build$src$core$dialog.setAlert=setAlert$$module$build$src$core$dialog;module$build$src$core$dialog.setConfirm=setConfirm$$module$build$src$core$dialog;module$build$src$core$dialog.setPrompt=setPrompt$$module$build$src$core$dialog;module$build$src$core$dialog.setToast=setToast$$module$build$src$core$dialog;module$build$src$core$dialog.toast=toast$$module$build$src$core$dialog;var module$build$src$core$interfaces$i_legacy_procedure_blocks={};module$build$src$core$interfaces$i_legacy_procedure_blocks.isLegacyProcedureCallBlock=isLegacyProcedureCallBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks;module$build$src$core$interfaces$i_legacy_procedure_blocks.isLegacyProcedureDefBlock=isLegacyProcedureDefBlock$$module$build$src$core$interfaces$i_legacy_procedure_blocks;var module$build$src$core$interfaces$i_variable_backed_parameter_model={};module$build$src$core$interfaces$i_variable_backed_parameter_model.isVariableBackedParameterModel=isVariableBackedParameterModel$$module$build$src$core$interfaces$i_variable_backed_parameter_model;var previousWarnings$$module$build$src$core$utils$deprecation=new Set,module$build$src$core$utils$deprecation={};module$build$src$core$utils$deprecation.warn=warn$$module$build$src$core$utils$deprecation;var CATEGORY_NAME$$module$build$src$core$variables="VARIABLE",VAR_LETTER_OPTIONS$$module$build$src$core$variables="ijkmnopqrstuvwxyzabcdefgh",TEST_ONLY$$module$build$src$core$variables={generateUniqueNameInternal:generateUniqueNameInternal$$module$build$src$core$variables},module$build$src$core$variables={CATEGORY_NAME:CATEGORY_NAME$$module$build$src$core$variables,TEST_ONLY:TEST_ONLY$$module$build$src$core$variables,VAR_LETTER_OPTIONS:VAR_LETTER_OPTIONS$$module$build$src$core$variables}; +module$build$src$core$variables.allDeveloperVariables=$.allDeveloperVariables$$module$build$src$core$variables;module$build$src$core$variables.allUsedVarModels=$.allUsedVarModels$$module$build$src$core$variables;module$build$src$core$variables.compareByName=compareByName$$module$build$src$core$variables;module$build$src$core$variables.createVariableButtonHandler=createVariableButtonHandler$$module$build$src$core$variables;module$build$src$core$variables.deleteVariable=$.deleteVariable$$module$build$src$core$variables; +module$build$src$core$variables.flyoutCategory=flyoutCategory$$module$build$src$core$variables;module$build$src$core$variables.flyoutCategoryBlocks=flyoutCategoryBlocks$$module$build$src$core$variables;module$build$src$core$variables.generateUniqueName=generateUniqueName$$module$build$src$core$variables;module$build$src$core$variables.generateUniqueNameFromOptions=generateUniqueNameFromOptions$$module$build$src$core$variables;module$build$src$core$variables.generateVariableFieldDom=generateVariableFieldDom$$module$build$src$core$variables; +module$build$src$core$variables.getAddedVariables=getAddedVariables$$module$build$src$core$variables;module$build$src$core$variables.getOrCreateVariablePackage=$.getOrCreateVariablePackage$$module$build$src$core$variables;module$build$src$core$variables.getVariable=$.getVariable$$module$build$src$core$variables;module$build$src$core$variables.getVariableUsesById=getVariableUsesById$$module$build$src$core$variables;module$build$src$core$variables.internalFlyoutCategory=internalFlyoutCategory$$module$build$src$core$variables; +module$build$src$core$variables.jsonFlyoutCategoryBlocks=jsonFlyoutCategoryBlocks$$module$build$src$core$variables;module$build$src$core$variables.nameUsedWithAnyType=nameUsedWithAnyType$$module$build$src$core$variables;module$build$src$core$variables.nameUsedWithConflictingParam=nameUsedWithConflictingParam$$module$build$src$core$variables;module$build$src$core$variables.promptName=promptName$$module$build$src$core$variables;module$build$src$core$variables.renameVariable=$.renameVariable$$module$build$src$core$variables;var DeserializationError$$module$build$src$core$serialization$exceptions=class extends Error{},MissingBlockType$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a){super("Expected to find a 'type' property, defining the block type");this.state=a}},MissingConnection$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a, b,c){super(`The block ${b.toDevString()} is missing a(n) ${a} connection`);this.block=b;this.state=c}},BadConnectionCheck$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a,b,c,d){super(`The block ${c.toDevString()} could not connect its ${b} to its parent, because: ${a}`);this.childBlock=c;this.childState=d}},RealChildOfShadow$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a){super("Encountered a real block which is defined as a child of a shadow\nblock. It is an invariant of Blockly that shadow blocks only have shadow\nchildren");this.state=a}},UnregisteredIcon$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a, -b,c){super(`Cannot add an icon of type '${a}' to the block `+`${b.toDevString()}, because there is no icon registered with `+`type '${a}'. Make sure that all of your icons have been `+"registered.");this.block=b;this.state=c}},module$build$src$core$serialization$exceptions={};module$build$src$core$serialization$exceptions.BadConnectionCheck=BadConnectionCheck$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.DeserializationError=DeserializationError$$module$build$src$core$serialization$exceptions; +b,c){super(`Cannot add an icon of type '${a}' to the block ${b.toDevString()}, because there is no icon registered with type '${a}'. Make sure that all of your icons have been `+"registered.");this.block=b;this.state=c}},module$build$src$core$serialization$exceptions={};module$build$src$core$serialization$exceptions.BadConnectionCheck=BadConnectionCheck$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.DeserializationError=DeserializationError$$module$build$src$core$serialization$exceptions; module$build$src$core$serialization$exceptions.MissingBlockType=MissingBlockType$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.MissingConnection=MissingConnection$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.RealChildOfShadow=RealChildOfShadow$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.UnregisteredIcon=UnregisteredIcon$$module$build$src$core$serialization$exceptions;var saveBlock$$module$build$src$core$serialization$blocks=save$$module$build$src$core$serialization$blocks,BlockSerializer$$module$build$src$core$serialization$blocks=class{constructor(){this.priority=BLOCKS$$module$build$src$core$serialization$priorities}save(a){const b=[];for(const c of a.getTopBlocks(!1))(a=save$$module$build$src$core$serialization$blocks(c,{addCoordinates:!0,doFullSerialization:!1}))&&b.push(a);return b.length?{languageVersion:0,blocks:b}:null}load(a,b){a=a.blocks;for(const c of a)append$$module$build$src$core$serialization$blocks(c, b,{recordUndo:getRecordUndo$$module$build$src$core$events$utils()})}clear(a){for(const b of a.getTopBlocks(!1))b.dispose(!1)}};register$$module$build$src$core$serialization$registry("blocks",new BlockSerializer$$module$build$src$core$serialization$blocks);var module$build$src$core$serialization$blocks={};module$build$src$core$serialization$blocks.BlockSerializer=BlockSerializer$$module$build$src$core$serialization$blocks;module$build$src$core$serialization$blocks.append=append$$module$build$src$core$serialization$blocks; module$build$src$core$serialization$blocks.appendInternal=appendInternal$$module$build$src$core$serialization$blocks;module$build$src$core$serialization$blocks.save=save$$module$build$src$core$serialization$blocks;var IconType$$module$build$src$core$icons$icon_types=class{constructor(a){this.name=a}toString(){return this.name}equals(a){return this.name===a.toString()}};IconType$$module$build$src$core$icons$icon_types.MUTATOR=new IconType$$module$build$src$core$icons$icon_types("mutator");IconType$$module$build$src$core$icons$icon_types.WARNING=new IconType$$module$build$src$core$icons$icon_types("warning");IconType$$module$build$src$core$icons$icon_types.COMMENT=new IconType$$module$build$src$core$icons$icon_types("comment"); -var module$build$src$core$icons$icon_types={};module$build$src$core$icons$icon_types.IconType=IconType$$module$build$src$core$icons$icon_types;var module$build$src$core$interfaces$i_has_bubble={};module$build$src$core$interfaces$i_has_bubble.hasBubble=hasBubble$$module$build$src$core$interfaces$i_has_bubble;var BlockBase$$module$build$src$core$events$events_block_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!a;a&&(this.blockId=a.id,this.workspaceId=a.workspace.id)}toJson(){const a=super.toJson();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");a.blockId=this.blockId;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new BlockBase$$module$build$src$core$events$events_block_base); -b.blockId=a.blockId;return b}},module$build$src$core$events$events_block_base={};module$build$src$core$events$events_block_base.BlockBase=BlockBase$$module$build$src$core$events$events_block_base;var BlockChange$$module$build$src$core$events$events_block_change=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a,b,c,d,e){super(a);this.type=EventType$$module$build$src$core$events$type.BLOCK_CHANGE;a&&(this.element=b,this.name=c||void 0,this.oldValue=d,this.newValue=e)}toJson(){const a=super.toJson();if(!this.element)throw Error("The changed element is undefined. Either pass an element to the constructor, or call fromJson");a.element=this.element;a.name=this.name; -a.oldValue=this.oldValue;a.newValue=this.newValue;this.disabledReason&&(a.disabledReason=this.disabledReason);return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new BlockChange$$module$build$src$core$events$events_block_change);b.element=a.element;b.name=a.name;b.oldValue=a.oldValue;b.newValue=a.newValue;void 0!==a.disabledReason&&(b.disabledReason=a.disabledReason);return b}setDisabledReason(a){if("disabled"!==this.element)throw Error('Cannot set the disabled reason for a BlockChange event if the element is not "disabled".'); +var module$build$src$core$icons$icon_types={};module$build$src$core$icons$icon_types.IconType=IconType$$module$build$src$core$icons$icon_types;var module$build$src$core$interfaces$i_has_bubble={};module$build$src$core$interfaces$i_has_bubble.hasBubble=hasBubble$$module$build$src$core$interfaces$i_has_bubble;var BlockBase$$module$build$src$core$events$events_block_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!0;this.isBlank=!a;a&&(this.blockId=a.id,this.workspaceId=a.workspace.id)}toJson(){const a=super.toJson();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");a.blockId=this.blockId;return a}static fromJson(a,b,c){b=Abstract$$module$build$src$core$events$events_abstract.fromJson(a, +b,c!=null?c:new BlockBase$$module$build$src$core$events$events_block_base);b.blockId=a.blockId;return b}},module$build$src$core$events$events_block_base={};module$build$src$core$events$events_block_base.BlockBase=BlockBase$$module$build$src$core$events$events_block_base;var BlockChange$$module$build$src$core$events$events_block_change=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a,b,c,d,e){super(a);this.type=EventType$$module$build$src$core$events$type.BLOCK_CHANGE;a&&(this.element=b,this.name=c||void 0,this.oldValue=d,this.newValue=e)}toJson(){const a=super.toJson();if(!this.element)throw Error("The changed element is undefined. Either pass an element to the constructor, or call fromJson");a.element=this.element;a.name=this.name; +a.oldValue=this.oldValue;a.newValue=this.newValue;this.disabledReason&&(a.disabledReason=this.disabledReason);return a}static fromJson(a,b,c){b=BlockBase$$module$build$src$core$events$events_block_base.fromJson(a,b,c!=null?c:new BlockChange$$module$build$src$core$events$events_block_change);b.element=a.element;b.name=a.name;b.oldValue=a.oldValue;b.newValue=a.newValue;a.disabledReason!==void 0&&(b.disabledReason=a.disabledReason);return b}setDisabledReason(a){if(this.element!=="disabled")throw Error('Cannot set the disabled reason for a BlockChange event if the element is not "disabled".'); this.disabledReason=a}isNull(){return this.oldValue===this.newValue}run(a){var b=this.getEventWorkspace_();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");b=b.getBlockById(this.blockId);if(!b)throw Error("The associated block is undefined. Either pass a block to the constructor, or call fromJson");const c=b.getIcon(IconType$$module$build$src$core$icons$icon_types.MUTATOR);c&&hasBubble$$module$build$src$core$interfaces$i_has_bubble(c)&& -c.bubbleIsVisible()&&c.setBubbleVisible(!1);a=a?this.newValue:this.oldValue;switch(this.element){case "field":(b=b.getField(this.name))?b.setValue(a):console.warn("Can't set non-existent field: "+this.name);break;case "comment":b.setCommentText(a||null);break;case "collapsed":b.setCollapsed(!!a);break;case "disabled":var d;b.setDisabledReason(!!a,null!=(d=this.disabledReason)?d:MANUALLY_DISABLED$$module$build$src$core$constants);break;case "inline":b.setInputsInline(!!a);break;case "mutation":d=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(b); -b.loadExtraState?b.loadExtraState(JSON.parse(a||"{}")):b.domToMutation&&b.domToMutation($.textToDom$$module$build$src$core$utils$xml(a||""));fire$$module$build$src$core$events$utils(new BlockChange$$module$build$src$core$events$events_block_change(b,"mutation",null,d,a));break;default:console.warn("Unknown change type: "+this.element)}}static getExtraBlockState_(a){return a.saveExtraState?(a=a.saveExtraState(!0))?JSON.stringify(a):"":a.mutationToDom?(a=a.mutationToDom())?domToText$$module$build$src$core$xml(a): -"":""}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.BLOCK_CHANGE,BlockChange$$module$build$src$core$events$events_block_change);var module$build$src$core$events$events_block_change={};module$build$src$core$events$events_block_change.BlockChange=BlockChange$$module$build$src$core$events$events_block_change;var module$build$src$core$utils$math={};module$build$src$core$utils$math.clamp=clamp$$module$build$src$core$utils$math;module$build$src$core$utils$math.toDegrees=toDegrees$$module$build$src$core$utils$math;module$build$src$core$utils$math.toRadians=toRadians$$module$build$src$core$utils$math;var ARROW_SIZE$$module$build$src$core$dropdowndiv=16,BORDER_SIZE$$module$build$src$core$dropdowndiv=1,ARROW_HORIZONTAL_PADDING$$module$build$src$core$dropdowndiv=12,PADDING_Y$$module$build$src$core$dropdowndiv=16,ANIMATION_TIME$$module$build$src$core$dropdowndiv=.25,animateOutTimer$$module$build$src$core$dropdowndiv=null,onHide$$module$build$src$core$dropdowndiv=null,renderedClassName$$module$build$src$core$dropdowndiv="",themeClassName$$module$build$src$core$dropdowndiv="",div$$module$build$src$core$dropdowndiv, -content$$module$build$src$core$dropdowndiv,arrow$$module$build$src$core$dropdowndiv,boundsElement$$module$build$src$core$dropdowndiv=null,owner$$module$build$src$core$dropdowndiv=null,positionToField$$module$build$src$core$dropdowndiv=null,internal$$module$build$src$core$dropdowndiv={getBoundsInfo:function(){const a=getPageOffset$$module$build$src$core$utils$style(boundsElement$$module$build$src$core$dropdowndiv),b=getSize$$module$build$src$core$utils$style(boundsElement$$module$build$src$core$dropdowndiv); -return{left:a.x,right:a.x+b.width,top:a.y,bottom:a.y+b.height,width:b.width,height:b.height}},getPositionMetrics:function(a,b,c,d){const e=internal$$module$build$src$core$dropdowndiv.getBoundsInfo(),f=getSize$$module$build$src$core$utils$style(div$$module$build$src$core$dropdowndiv);return b+f.heighte.top?getPositionAboveMetrics$$module$build$src$core$dropdowndiv(c,d,e,f):b+f.heightdocument.documentElement.clientTop?getPositionAboveMetrics$$module$build$src$core$dropdowndiv(c,d,e,f):getPositionTopOfPageMetrics$$module$build$src$core$dropdowndiv(a,e,f)}},TEST_ONLY$$module$build$src$core$dropdowndiv=internal$$module$build$src$core$dropdowndiv,module$build$src$core$dropdowndiv={ANIMATION_TIME:ANIMATION_TIME$$module$build$src$core$dropdowndiv,ARROW_HORIZONTAL_PADDING:ARROW_HORIZONTAL_PADDING$$module$build$src$core$dropdowndiv, +c.bubbleIsVisible()&&c.setBubbleVisible(!1);a=a?this.newValue:this.oldValue;switch(this.element){case "field":(b=b.getField(this.name))?b.setValue(a):console.warn("Can't set non-existent field: "+this.name);break;case "comment":b.setCommentText(a!=null?a:null);break;case "collapsed":b.setCollapsed(!!a);break;case "disabled":var d;b.setDisabledReason(!!a,(d=this.disabledReason)!=null?d:MANUALLY_DISABLED$$module$build$src$core$constants);break;case "inline":b.setInputsInline(!!a);break;case "mutation":d= +BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(b);b.loadExtraState?b.loadExtraState(JSON.parse(a||"{}")):b.domToMutation&&b.domToMutation($.textToDom$$module$build$src$core$utils$xml(a||""));fire$$module$build$src$core$events$utils(new BlockChange$$module$build$src$core$events$events_block_change(b,"mutation",null,d,a));break;default:console.warn("Unknown change type: "+this.element)}}static getExtraBlockState_(a){return a.saveExtraState?(a=a.saveExtraState(!0))? +JSON.stringify(a):"":a.mutationToDom?(a=a.mutationToDom())?domToText$$module$build$src$core$xml(a):"":""}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.BLOCK_CHANGE,BlockChange$$module$build$src$core$events$events_block_change);var module$build$src$core$events$events_block_change={};module$build$src$core$events$events_block_change.BlockChange=BlockChange$$module$build$src$core$events$events_block_change;var module$build$src$core$utils$math={};module$build$src$core$utils$math.clamp=clamp$$module$build$src$core$utils$math;module$build$src$core$utils$math.toDegrees=toDegrees$$module$build$src$core$utils$math;module$build$src$core$utils$math.toRadians=toRadians$$module$build$src$core$utils$math;var ARROW_SIZE$$module$build$src$core$dropdowndiv=16,BORDER_SIZE$$module$build$src$core$dropdowndiv=1,ARROW_HORIZONTAL_PADDING$$module$build$src$core$dropdowndiv=12,PADDING_Y$$module$build$src$core$dropdowndiv=16,ANIMATION_TIME$$module$build$src$core$dropdowndiv=.25,animateOutTimer$$module$build$src$core$dropdowndiv=null,onHide$$module$build$src$core$dropdowndiv=null,renderedClassName$$module$build$src$core$dropdowndiv="",themeClassName$$module$build$src$core$dropdowndiv="",div$$module$build$src$core$dropdowndiv, +content$$module$build$src$core$dropdowndiv,arrow$$module$build$src$core$dropdowndiv,boundsElement$$module$build$src$core$dropdowndiv=null,owner$$module$build$src$core$dropdowndiv=null,positionToField$$module$build$src$core$dropdowndiv=null,returnEphemeralFocus$$module$build$src$core$dropdowndiv=null,keydownListener$$module$build$src$core$dropdowndiv=null,internal$$module$build$src$core$dropdowndiv={getBoundsInfo:function(){const a=getPageOffset$$module$build$src$core$utils$style(boundsElement$$module$build$src$core$dropdowndiv), +b=getSize$$module$build$src$core$utils$style(boundsElement$$module$build$src$core$dropdowndiv);return{left:a.x,right:a.x+b.width,top:a.y,bottom:a.y+b.height,width:b.width,height:b.height}},getPositionMetrics:function(a,b,c,d){const e=internal$$module$build$src$core$dropdowndiv.getBoundsInfo(),f=getSize$$module$build$src$core$utils$style(div$$module$build$src$core$dropdowndiv);return b+f.heighte.top?getPositionAboveMetrics$$module$build$src$core$dropdowndiv(c, +d,e,f):b+f.heightdocument.documentElement.clientTop?getPositionAboveMetrics$$module$build$src$core$dropdowndiv(c,d,e,f):getPositionTopOfPageMetrics$$module$build$src$core$dropdowndiv(a,e,f)}},TEST_ONLY$$module$build$src$core$dropdowndiv=internal$$module$build$src$core$dropdowndiv,module$build$src$core$dropdowndiv={ANIMATION_TIME:ANIMATION_TIME$$module$build$src$core$dropdowndiv,ARROW_HORIZONTAL_PADDING:ARROW_HORIZONTAL_PADDING$$module$build$src$core$dropdowndiv, ARROW_SIZE:ARROW_SIZE$$module$build$src$core$dropdowndiv,BORDER_SIZE:BORDER_SIZE$$module$build$src$core$dropdowndiv,PADDING_Y:PADDING_Y$$module$build$src$core$dropdowndiv,TEST_ONLY:internal$$module$build$src$core$dropdowndiv};module$build$src$core$dropdowndiv.clearContent=clearContent$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.createDom=createDom$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.getContentDiv=getContentDiv$$module$build$src$core$dropdowndiv; module$build$src$core$dropdowndiv.getOwner=getOwner$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.getPositionX=getPositionX$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.hide=hide$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.hideIfOwner=hideIfOwner$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.hideWithoutAnimation=hideWithoutAnimation$$module$build$src$core$dropdowndiv; module$build$src$core$dropdowndiv.isVisible=isVisible$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.repositionForWindowResize=repositionForWindowResize$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.setBoundsElement=setBoundsElement$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.setColour=setColour$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.show=show$$module$build$src$core$dropdowndiv; -module$build$src$core$dropdowndiv.showPositionedByBlock=showPositionedByBlock$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.showPositionedByField=showPositionedByField$$module$build$src$core$dropdowndiv;var MarkerManager$$module$build$src$core$marker_manager=class{constructor(a){this.workspace=a;this.cursorSvg=this.cursor=null;this.markers=new Map;this.markerSvg=null}registerMarker(a,b){this.markers.has(a)&&this.unregisterMarker(a);b.setDrawer(this.workspace.getRenderer().makeMarkerDrawer(this.workspace,b));this.setMarkerSvg(b.getDrawer().createDom());this.markers.set(a,b)}unregisterMarker(a){const b=this.markers.get(a);if(b)b.dispose(),this.markers.delete(a);else throw Error("Marker with ID "+a+ -" does not exist. Can only unregister markers that exist.");}getCursor(){return this.cursor}getMarker(a){return this.markers.get(a)||null}setCursor(a){this.cursor&&this.cursor.getDrawer()&&this.cursor.getDrawer().dispose();if(this.cursor=a)a=this.workspace.getRenderer().makeMarkerDrawer(this.workspace,this.cursor),this.cursor.setDrawer(a),this.setCursorSvg(this.cursor.getDrawer().createDom())}setCursorSvg(a){a?(this.workspace.getBlockCanvas().appendChild(a),this.cursorSvg=a):this.cursorSvg=null}setMarkerSvg(a){a? -this.workspace.getBlockCanvas()&&(this.cursorSvg?this.workspace.getBlockCanvas().insertBefore(a,this.cursorSvg):this.workspace.getBlockCanvas().appendChild(a)):this.markerSvg=null}updateMarkers(){this.workspace.keyboardAccessibilityMode&&this.cursorSvg&&this.workspace.getCursor().draw()}dispose(){const a=Object.keys(this.markers);for(let b=0,c;c=a[b];b++)this.unregisterMarker(c);this.markers.clear();this.cursor&&(this.cursor.dispose(),this.cursor=null)}}; -MarkerManager$$module$build$src$core$marker_manager.LOCAL_MARKER="local_marker_1";var module$build$src$core$marker_manager={};module$build$src$core$marker_manager.MarkerManager=MarkerManager$$module$build$src$core$marker_manager;var module$build$src$core$utils$string={};module$build$src$core$utils$string.commonWordPrefix=commonWordPrefix$$module$build$src$core$utils$string;module$build$src$core$utils$string.commonWordSuffix=commonWordSuffix$$module$build$src$core$utils$string;module$build$src$core$utils$string.isNumber=$.isNumber$$module$build$src$core$utils$string;module$build$src$core$utils$string.shortestStringLength=shortestStringLength$$module$build$src$core$utils$string;module$build$src$core$utils$string.wrap=$.wrap$$module$build$src$core$utils$string;var customTooltip$$module$build$src$core$tooltip=void 0,visible$$module$build$src$core$tooltip=!1,blocked$$module$build$src$core$tooltip=!1,LIMIT$$module$build$src$core$tooltip=50,mouseOutPid$$module$build$src$core$tooltip=0,showPid$$module$build$src$core$tooltip=0,lastX$$module$build$src$core$tooltip=0,lastY$$module$build$src$core$tooltip=0,element$$module$build$src$core$tooltip=null,poisonedElement$$module$build$src$core$tooltip=null,OFFSET_X$$module$build$src$core$tooltip=0,OFFSET_Y$$module$build$src$core$tooltip= +module$build$src$core$dropdowndiv.showPositionedByBlock=showPositionedByBlock$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.showPositionedByField=showPositionedByField$$module$build$src$core$dropdowndiv;var module$build$src$core$utils$string={};module$build$src$core$utils$string.commonWordPrefix=commonWordPrefix$$module$build$src$core$utils$string;module$build$src$core$utils$string.commonWordSuffix=commonWordSuffix$$module$build$src$core$utils$string;module$build$src$core$utils$string.isNumber=$.isNumber$$module$build$src$core$utils$string;module$build$src$core$utils$string.shortestStringLength=shortestStringLength$$module$build$src$core$utils$string;module$build$src$core$utils$string.wrap=$.wrap$$module$build$src$core$utils$string;var customTooltip$$module$build$src$core$tooltip=void 0,visible$$module$build$src$core$tooltip=!1,blocked$$module$build$src$core$tooltip=!1,LIMIT$$module$build$src$core$tooltip=50,mouseOutPid$$module$build$src$core$tooltip=0,showPid$$module$build$src$core$tooltip=0,lastX$$module$build$src$core$tooltip=0,lastY$$module$build$src$core$tooltip=0,element$$module$build$src$core$tooltip=null,poisonedElement$$module$build$src$core$tooltip=null,OFFSET_X$$module$build$src$core$tooltip=0,OFFSET_Y$$module$build$src$core$tooltip= 10,RADIUS_OK$$module$build$src$core$tooltip=10,HOVER_MS$$module$build$src$core$tooltip=750,MARGINS$$module$build$src$core$tooltip=5,containerDiv$$module$build$src$core$tooltip=null,module$build$src$core$tooltip={HOVER_MS:HOVER_MS$$module$build$src$core$tooltip,LIMIT:LIMIT$$module$build$src$core$tooltip,MARGINS:MARGINS$$module$build$src$core$tooltip,OFFSET_X:OFFSET_X$$module$build$src$core$tooltip,OFFSET_Y:OFFSET_Y$$module$build$src$core$tooltip,RADIUS_OK:RADIUS_OK$$module$build$src$core$tooltip}; module$build$src$core$tooltip.bindMouseEvents=bindMouseEvents$$module$build$src$core$tooltip;module$build$src$core$tooltip.block=block$$module$build$src$core$tooltip;module$build$src$core$tooltip.createDom=createDom$$module$build$src$core$tooltip;module$build$src$core$tooltip.dispose=dispose$$module$build$src$core$tooltip;module$build$src$core$tooltip.getCustomTooltip=getCustomTooltip$$module$build$src$core$tooltip;module$build$src$core$tooltip.getDiv=getDiv$$module$build$src$core$tooltip; module$build$src$core$tooltip.getTooltipOfObject=getTooltipOfObject$$module$build$src$core$tooltip;module$build$src$core$tooltip.hide=hide$$module$build$src$core$tooltip;module$build$src$core$tooltip.isVisible=isVisible$$module$build$src$core$tooltip;module$build$src$core$tooltip.setCustomTooltip=setCustomTooltip$$module$build$src$core$tooltip;module$build$src$core$tooltip.unbindMouseEvents=unbindMouseEvents$$module$build$src$core$tooltip;module$build$src$core$tooltip.unblock=unblock$$module$build$src$core$tooltip;var hsvSaturation$$module$build$src$core$utils$colour=.45,hsvValue$$module$build$src$core$utils$colour=.65,names$$module$build$src$core$utils$colour={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00"},module$build$src$core$utils$colour={};module$build$src$core$utils$colour.blend=blend$$module$build$src$core$utils$colour; module$build$src$core$utils$colour.getHsvSaturation=getHsvSaturation$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.getHsvValue=getHsvValue$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.hexToRgb=hexToRgb$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.hsvToHex=hsvToHex$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.hueToHex=hueToHex$$module$build$src$core$utils$colour; -module$build$src$core$utils$colour.names=names$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.parse=parse$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.rgbToHex=rgbToHex$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.setHsvSaturation=setHsvSaturation$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.setHsvValue=setHsvValue$$module$build$src$core$utils$colour;var module$build$src$core$utils$parsing={};module$build$src$core$utils$parsing.checkMessageReferences=checkMessageReferences$$module$build$src$core$utils$parsing;module$build$src$core$utils$parsing.parseBlockColour=parseBlockColour$$module$build$src$core$utils$parsing;module$build$src$core$utils$parsing.replaceMessageReferences=replaceMessageReferences$$module$build$src$core$utils$parsing;module$build$src$core$utils$parsing.tokenizeInterpolation=tokenizeInterpolation$$module$build$src$core$utils$parsing;var Field$$module$build$src$core$field=class{constructor(a,b,c){this.DEFAULT_VALUE=null;this.name=void 0;this.constants_=this.mouseDownWrapper=this.textContent_=this.textElement_=this.borderRect_=this.fieldGroup_=this.markerSvg=this.cursorSvg=this.tooltip=this.validator_=null;this.disposed=!1;this.maxDisplayLength=50;this.sourceBlock_=null;this.enabled_=this.visible_=this.isDirty_=!0;this.suffixField=this.prefixField=this.clickTarget_=null;this.EDITABLE=!0;this.SERIALIZABLE=!1;this.CURSOR="";this.value_= -"DEFAULT_VALUE"in new.target.prototype?new.target.prototype.DEFAULT_VALUE:this.DEFAULT_VALUE;this.size_=new Size$$module$build$src$core$utils$size(0,0);a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){a.tooltip&&this.setTooltip(replaceMessageReferences$$module$build$src$core$utils$parsing(a.tooltip))}setSourceBlock(a){if(this.sourceBlock_)throw Error("Field already bound to a block");this.sourceBlock_=a}getConstants(){!this.constants_&& -this.sourceBlock_&&!this.sourceBlock_.isDeadOrDying()&&this.sourceBlock_.workspace.rendered&&(this.constants_=this.sourceBlock_.workspace.getRenderer().getConstants());return this.constants_}getSourceBlock(){return this.sourceBlock_}init(){this.fieldGroup_||(this.fieldGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{}),this.isVisible()||(this.fieldGroup_.style.display="none"),this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_),this.initView(), -this.updateEditable(),this.setTooltip(this.tooltip),this.bindEvents_(),this.initModel(),this.applyColour())}initView(){this.createBorderRect_();this.createTextElement_()}initModel(){}isFullBlockField(){return!this.borderRect_}createBorderRect_(){this.borderRect_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{rx:this.getConstants().FIELD_BORDER_RECT_RADIUS,ry:this.getConstants().FIELD_BORDER_RECT_RADIUS,x:0,y:0,height:this.size_.height,width:this.size_.width, -"class":"blocklyFieldRect"},this.fieldGroup_)}createTextElement_(){this.textElement_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT,{"class":"blocklyText"},this.fieldGroup_);this.getConstants().FIELD_TEXT_BASELINE_CENTER&&this.textElement_.setAttribute("dominant-baseline","central");this.textContent_=document.createTextNode("");this.textElement_.appendChild(this.textContent_)}bindEvents_(){const a=this.getClickTarget_();if(!a)throw Error("A click target has not been set."); -bindMouseEvents$$module$build$src$core$tooltip(a);this.mouseDownWrapper=conditionalBind$$module$build$src$core$browser_events(a,"pointerdown",this,this.onMouseDown_)}fromXml(a){this.setValue(a.textContent)}toXml(a){a.textContent=this.getValue();return a}saveState(a){a=this.saveLegacyState(Field$$module$build$src$core$field);return null!==a?a:this.getValue()}loadState(a){this.loadLegacyState(Field$$module$build$src$core$field,a)||this.setValue(a)}saveLegacyState(a){return a.prototype.saveState===this.saveState&& -a.prototype.toXml!==this.toXml?(a=$.createElement$$module$build$src$core$utils$xml("field"),a.setAttribute("name",this.name||""),domToText$$module$build$src$core$utils$xml(this.toXml(a)).replace(' xmlns="https://developers.google.com/blockly/xml"',"")):null}loadLegacyState(a,b){return a.prototype.loadState===this.loadState&&a.prototype.fromXml!==this.fromXml?(this.fromXml($.textToDom$$module$build$src$core$utils$xml(b)),!0):!1}dispose(){hideIfOwner$$module$build$src$core$dropdowndiv(this);hideIfOwner$$module$build$src$core$widgetdiv(this); -let a;(null==(a=this.getSourceBlock())?0:a.isDeadOrDying())||removeNode$$module$build$src$core$utils$dom(this.fieldGroup_);this.disposed=!0}updateEditable(){const a=this.fieldGroup_,b=this.getSourceBlock();this.EDITABLE&&a&&b&&(this.enabled_&&b.isEditable()?(addClass$$module$build$src$core$utils$dom(a,"blocklyEditableText"),removeClass$$module$build$src$core$utils$dom(a,"blocklyNonEditableText"),a.style.cursor=this.CURSOR):(addClass$$module$build$src$core$utils$dom(a,"blocklyNonEditableText"),removeClass$$module$build$src$core$utils$dom(a, -"blocklyEditableText"),a.style.cursor=""))}setEnabled(a){this.enabled_=a;this.updateEditable()}isEnabled(){return this.enabled_}isClickable(){return this.enabled_&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()&&this.showEditor_!==Field$$module$build$src$core$field.prototype.showEditor_}isClickableInFlyout(a){return!a}isCurrentlyEditable(){return this.enabled_&&this.EDITABLE&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()}isSerializable(){let a=!1;this.name&&(this.SERIALIZABLE?a=!0:this.EDITABLE&& -(console.warn("Detected an editable field that was not serializable. Please define SERIALIZABLE property as true on all editable custom fields. Proceeding with serialization."),a=!0));return a}isVisible(){return this.visible_}setVisible(a){if(this.visible_!==a){this.visible_=a;var b=this.fieldGroup_;b&&(b.style.display=a?"block":"none")}}setValidator(a){this.validator_=a}getValidator(){return this.validator_}getSvgRoot(){return this.fieldGroup_}getBorderRect(){if(!this.borderRect_)throw Error(`The border rectangle is ${this.borderRect_}.`); -return this.borderRect_}getTextElement(){if(!this.textElement_)throw Error(`The text element is ${this.textElement_}.`);return this.textElement_}getTextContent(){if(!this.textContent_)throw Error(`The text content is ${this.textContent_}.`);return this.textContent_}applyColour(){}render_(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_());this.updateSize_()}showEditor(a){this.isClickable()&&this.showEditor_(a)}showEditor_(a){}repositionForWindowResize(){return!1}updateSize_(a){const b= -this.getConstants();a=void 0!==a?a:this.isFullBlockField()?0:this.getConstants().FIELD_BORDER_RECT_X_PADDING;let c=2*a,d=b.FIELD_TEXT_HEIGHT,e=0;this.textElement_&&(e=getFastTextWidth$$module$build$src$core$utils$dom(this.textElement_,b.FIELD_TEXT_FONTSIZE,b.FIELD_TEXT_FONTWEIGHT,b.FIELD_TEXT_FONTFAMILY),c+=e);this.isFullBlockField()||(d=Math.max(d,b.FIELD_BORDER_RECT_HEIGHT));this.size_.height=d;this.size_.width=c;this.positionTextElement_(a,e);this.positionBorderRect_()}positionTextElement_(a,b){if(this.textElement_){var c= -this.getConstants(),d=this.size_.height/2,e;this.textElement_.setAttribute("x",String((null==(e=this.getSourceBlock())?0:e.RTL)?this.size_.width-b-a:a));this.textElement_.setAttribute("y",String(c.FIELD_TEXT_BASELINE_CENTER?d:d-c.FIELD_TEXT_HEIGHT/2+c.FIELD_TEXT_BASELINE))}}positionBorderRect_(){this.borderRect_&&(this.borderRect_.setAttribute("width",String(this.size_.width)),this.borderRect_.setAttribute("height",String(this.size_.height)),this.borderRect_.setAttribute("rx",String(this.getConstants().FIELD_BORDER_RECT_RADIUS)), -this.borderRect_.setAttribute("ry",String(this.getConstants().FIELD_BORDER_RECT_RADIUS)))}getSize(){if(!this.isVisible())return new Size$$module$build$src$core$utils$size(0,0);this.isDirty_?(this.render_(),this.isDirty_=!1):this.visible_&&0===this.size_.width&&(this.render_(),0!==this.size_.width&&console.warn("Deprecated use of setting size_.width to 0 to rerender a field. Set field.isDirty_ to true instead."));return this.size_}getScaledBBox(){let a;var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field; -if(this.isFullBlockField()){var c=this.sourceBlock_.getHeightWidth();const d=b.workspace.scale;a=this.getAbsoluteXY_();b=(c.width+1)*d;c=(c.height+1)*d;GECKO$$module$build$src$core$utils$useragent?(a.x+=1.5*d,a.y+=1.5*d):(a.x-=.5*d,a.y-=.5*d)}else c=this.borderRect_.getBoundingClientRect(),a=getPageOffset$$module$build$src$core$utils$style(this.borderRect_),b=c.width,c=c.height;return new Rect$$module$build$src$core$utils$rect(a.y,a.y+c,a.x,a.x+b)}onLocationChange(a){}getDisplayText_(){let a=this.getText(); -if(!a)return Field$$module$build$src$core$field.NBSP;a.length>this.maxDisplayLength&&(a=a.substring(0,this.maxDisplayLength-2)+"\u2026");a=a.replace(/\s/g,Field$$module$build$src$core$field.NBSP);this.sourceBlock_&&this.sourceBlock_.RTL&&(a+="\u200f");return a}getText(){const a=this.getText_();return null!==a?String(a):String(this.getValue())}getText_(){return null}markDirty(){this.isDirty_=!0;this.constants_=null}forceRerender(){this.isDirty_=!0;this.sourceBlock_&&this.sourceBlock_.rendered&&this.sourceBlock_.queueRender()}setValue(a, -b=!0){if(null!==a){var c=$.getGroup$$module$build$src$core$events$utils();c||$.setGroup$$module$build$src$core$events$utils(!0);try{const k=this.doClassValidation_(a),l=this.processValidation(a,k,b);if(!(l instanceof Error)){var d,e=null==(d=this.getValidator())?void 0:d.call(this,l),f=this.processValidation(l,e,b);if(!(f instanceof Error)){var g=this.sourceBlock_;if(!g||!g.disposed){var h=this.getValue();h===f?this.doValueUpdate_(f):(this.doValueUpdate_(f),b&&g&&isEnabled$$module$build$src$core$events$utils()&& -fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(g,"field",this.name||null,h,f)),this.isDirty_&&this.forceRerender())}}}}finally{$.setGroup$$module$build$src$core$events$utils(c)}}}processValidation(a,b,c){return null===b?(this.doValueInvalid_(a,c),this.isDirty_&&this.forceRerender(),Error()):void 0===b?a:b}getValue(){return this.value_}doClassValidation_(a){return null===a||void 0===a?null:a}doValueUpdate_(a){this.value_= -a;this.isDirty_=!0}doValueInvalid_(a,b){}onMouseDown_(a){this.sourceBlock_&&!this.sourceBlock_.isDeadOrDying()&&(a=this.sourceBlock_.workspace.getGesture(a))&&a.setStartField(this)}setTooltip(a){a||""===a||(a=this.sourceBlock_);const b=this.getClickTarget_();b?b.tooltip=a:this.tooltip=a}getTooltip(){const a=this.getClickTarget_();return a?getTooltipOfObject$$module$build$src$core$tooltip(a):getTooltipOfObject$$module$build$src$core$tooltip({tooltip:this.tooltip})}getClickTarget_(){return this.clickTarget_|| -this.getSvgRoot()}getAbsoluteXY_(){return getPageOffset$$module$build$src$core$utils$style(this.getClickTarget_())}referencesVariables(){return!1}refreshVariableName(){}getParentInput(){let a=null;const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;const c=b.inputList;for(let d=0;dthis.maxDisplayLength&&(a=a.substring(0,this.maxDisplayLength-2)+"\u2026");a=a.replace(/\s/g,Field$$module$build$src$core$field.NBSP);this.sourceBlock_&&this.sourceBlock_.RTL&&(a+="\u200f");return a}getText(){const a=this.getText_();return a!==null?String(a):String(this.getValue())}getText_(){return null}markDirty(){this.isDirty_=!0;this.constants_=null}forceRerender(){this.isDirty_=!0;this.sourceBlock_&&this.sourceBlock_.rendered&& +this.sourceBlock_.queueRender()}setValue(a,b=!0){if(a!==null){var c=$.getGroup$$module$build$src$core$events$utils();c||$.setGroup$$module$build$src$core$events$utils(!0);try{const k=this.doClassValidation_(a),l=this.processValidation(a,k,b);if(!(l instanceof Error)){var d,e=(d=this.getValidator())==null?void 0:d.call(this,l),f=this.processValidation(l,e,b);if(!(f instanceof Error)){var g=this.sourceBlock_;if(!g||!g.disposed){var h=this.getValue();h===f?this.doValueUpdate_(f):(this.doValueUpdate_(f), +b&&g&&isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(g,"field",this.name||null,h,f)),this.isDirty_&&this.forceRerender())}}}}finally{$.setGroup$$module$build$src$core$events$utils(c)}}}processValidation(a,b,c){return b===null?(this.doValueInvalid_(a,c),this.isDirty_&&this.forceRerender(),Error()):b===void 0?a:b}getValue(){return this.value_}doClassValidation_(a){return a=== +null||a===void 0?null:a}doValueUpdate_(a){this.value_=a;this.isDirty_=!0}doValueInvalid_(a,b){}onMouseDown_(a){this.sourceBlock_&&!this.sourceBlock_.isDeadOrDying()&&(a=this.sourceBlock_.workspace.getGesture(a))&&a.setStartField(this)}setTooltip(a){a||a===""||(a=this.sourceBlock_);const b=this.getClickTarget_();b?b.tooltip=a:this.tooltip=a}getTooltip(){const a=this.getClickTarget_();return a?getTooltipOfObject$$module$build$src$core$tooltip(a):getTooltipOfObject$$module$build$src$core$tooltip({tooltip:this.tooltip})}getClickTarget_(){return this.clickTarget_|| +this.getSvgRoot()}getAbsoluteXY_(){return getPageOffset$$module$build$src$core$utils$style(this.getClickTarget_())}referencesVariables(){return!1}refreshVariableName(){}getParentInput(){let a=null;const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;const c=b.inputList;for(let d=0;d{d.stopPropagation();$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this); +clearTouchIdentifier$$module$build$src$core$touch()});conditionalBind$$module$build$src$core$browser_events(this.textArea,"wheel",this,d=>{d.stopPropagation()},!1,{passive:!0});conditionalBind$$module$build$src$core$browser_events(this.textArea,"keydown",this,this.handleKeyDown)}getDom(){return this.foreignObject}getText(){return this.text}setText(a){this.textArea.value=a;this.onTextChange()}onTextChange(){const a=this.text;this.text=this.textArea.value;for(let b=this.textChangeListeners.length-1;b>= +0;b--)this.textChangeListeners[b](a,this.text)}handleKeyDown(a){if(a.key==="Escape"||a.key==="Enter"&&(a.ctrlKey||a.metaKey)){if(this.onFinishEditing)this.onFinishEditing();a.stopPropagation()}}addTextChangeListener(a){this.textChangeListeners.push(a)}removeTextChangeListener(a){this.textChangeListeners.splice(this.textChangeListeners.indexOf(a),1)}setPlaceholderText(a){this.textArea.placeholder=a}setEditable(a){a?this.textArea.removeAttribute("readonly"):this.textArea.setAttribute("readonly","true")}updateSize(a, +b){this.foreignObject.setAttribute("height",`${a.height-b.height}`);this.foreignObject.setAttribute("width",`${a.width}`);this.foreignObject.setAttribute("y",`${b.height}`);this.workspace.RTL&&this.foreignObject.setAttribute("x",`${-a.width}`)}getFocusableElement(){return this.textArea}getFocusableTree(){return this.workspace}onNodeFocus(){const a=Rect$$module$build$src$core$utils$rect.from(this.foreignObject.getBoundingClientRect());this.workspace.scrollBoundsIntoView(Rect$$module$build$src$core$utils$rect.createFromPoint(screenToWsCoordinates$$module$build$src$core$utils$svg_math(this.workspace, +a.getOrigin()),a.getWidth(),a.getHeight()))}onNodeBlur(){}canBeFocused(){return this.id?!0:!1}},module$build$src$core$comments$comment_editor={COMMENT_EDITOR_FOCUS_IDENTIFIER:COMMENT_EDITOR_FOCUS_IDENTIFIER$$module$build$src$core$comments$comment_editor};module$build$src$core$comments$comment_editor.CommentEditor=CommentEditor$$module$build$src$core$comments$comment_editor;var COMMENT_DELETE_BAR_BUTTON_FOCUS_IDENTIFIER$$module$build$src$core$comments$delete_comment_bar_button="_delete_bar_button",DeleteCommentBarButton$$module$build$src$core$comments$delete_comment_bar_button=class extends CommentBarButton$$module$build$src$core$comments$comment_bar_button{constructor(a,b,c,d){super(a,b,c,d);this.id=a;this.workspace=b;this.container=c;this.commentView=d;this.icon=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{"class":"blocklyDeleteIcon", +href:`${this.workspace.options.pathToMedia}delete-icon.svg`,id:`${this.id}${COMMENT_DELETE_BAR_BUTTON_FOCUS_IDENTIFIER$$module$build$src$core$comments$delete_comment_bar_button}`},c);this.bindId=conditionalBind$$module$build$src$core$browser_events(this.icon,"pointerdown",this,this.performAction.bind(this))}dispose(){unbind$$module$build$src$core$browser_events(this.bindId)}reposition(){const a=this.getMargin();this.icon.setAttribute("x","0");const b=this.container.getBBox();this.icon.setAttribute("y", +`${a}`);this.icon.setAttribute("x",`${b.width-this.getSize(!0).getWidth()}`)}performAction(a){clearTouchIdentifier$$module$build$src$core$touch();a&&a instanceof PointerEvent&&isRightButton$$module$build$src$core$browser_events(a)?a.stopPropagation():(this.getCommentView().dispose(),a==null||a.stopPropagation(),$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this.workspace))}},module$build$src$core$comments$delete_comment_bar_button={COMMENT_DELETE_BAR_BUTTON_FOCUS_IDENTIFIER:COMMENT_DELETE_BAR_BUTTON_FOCUS_IDENTIFIER$$module$build$src$core$comments$delete_comment_bar_button}; +module$build$src$core$comments$delete_comment_bar_button.DeleteCommentBarButton=DeleteCommentBarButton$$module$build$src$core$comments$delete_comment_bar_button;var CommentView$$module$build$src$core$comments$comment_view=class{constructor(a,b){this.workspace=a;this.commentId=b;this.collapsed=!1;this.editable=!0;this.location=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.sizeChangeListeners=[];this.disposeListeners=[];this.collapseChangeListeners=[];this.resizePointerMoveListener=this.resizePointerUpListener=null;this.disposed=this.disposing=!1;this.svgRoot=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G, +{"class":"blocklyComment blocklyEditable blocklyDraggable"});this.highlightRect=this.createHighlightRect(this.svgRoot);({topBarGroup:this.topBarGroup,topBarBackground:this.topBarBackground,deleteButton:this.deleteButton,foldoutButton:this.foldoutButton,textPreview:this.textPreview,textPreviewNode:this.textPreviewNode}=this.createTopBar(this.svgRoot));this.commentEditor=this.createTextArea();this.resizeHandle=this.createResizeHandle(this.svgRoot,a);let c;(c=a.getLayerManager())==null||c.append(this, +BLOCK$$module$build$src$core$layers);this.size=CommentView$$module$build$src$core$comments$comment_view.defaultCommentSize;this.setSizeWithoutFiringEvents(this.size);this.moveTo(new Coordinate$$module$build$src$core$utils$coordinate(0,0))}createHighlightRect(a){return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyCommentHighlight"},a)}createTopBar(a){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G, +{"class":"blocklyCommentTopbar"},a);const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyCommentTopbarBackground"},a),c=new DeleteCommentBarButton$$module$build$src$core$comments$delete_comment_bar_button(this.commentId,this.workspace,a,this),d=new CollapseCommentBarButton$$module$build$src$core$comments$collapse_comment_bar_button(this.commentId,this.workspace,a,this);this.addDisposeListener(()=>{c.dispose();d.dispose()});const e=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT, +{"class":"blocklyCommentPreview blocklyCommentText blocklyText"},a),f=document.createTextNode("");e.appendChild(f);return{topBarGroup:a,topBarBackground:b,deleteButton:c,foldoutButton:d,textPreview:e,textPreviewNode:f}}createTextArea(){const a=new CommentEditor$$module$build$src$core$comments$comment_editor(this.workspace,this.commentId,()=>this.svgRoot.focus());this.svgRoot.appendChild(a.getDom());a.addTextChangeListener((b,c)=>{this.updateTextPreview(c);this.setSize(this.size)});return a}getEditorFocusableNode(){return this.commentEditor}createResizeHandle(a, +b){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{"class":"blocklyResizeHandle",href:`${b.options.pathToMedia}resize-handle.svg`},a);conditionalBind$$module$build$src$core$browser_events(a,"pointerdown",this,this.onResizePointerDown);return a}getSvgRoot(){return this.svgRoot}getSize(){return this.collapsed?this.topBarBackground.getBBox():this.size}setSizeWithoutFiringEvents(a){const b=this.topBarBackground.getBBox(),c=this.textPreview.getBBox(),d=this.resizeHandle.getBBox(); +this.size=a=Size$$module$build$src$core$utils$size.max(a,this.calcMinSize(b));this.svgRoot.setAttribute("height",`${a.height}`);this.svgRoot.setAttribute("width",`${a.width}`);this.updateHighlightRect(a);this.updateTopBarSize(a);this.commentEditor.updateSize(a,b);this.deleteButton.reposition();this.foldoutButton.reposition();this.updateTextPreviewSize(a,b,c);this.updateResizeHandlePosition(a,d)}setSize(a){const b=this.preResizeSize||this.size;this.setSizeWithoutFiringEvents(a);this.onSizeChange(b, +this.size)}calcMinSize(a){var b;this.updateTextPreview((b=this.commentEditor.getText())!=null?b:"");let c=b=getTextWidth$$module$build$src$core$utils$dom(this.textPreview);this.foldoutButton.isVisible()?c+=this.foldoutButton.getSize(!0).getWidth():b&&(c+=4);this.deleteButton.isVisible()?c+=this.deleteButton.getSize(!0).getWidth():b&&(c+=4);return new Size$$module$build$src$core$utils$size(c,a.height+20)}updateHighlightRect(a){this.highlightRect.setAttribute("height",`${a.height}`);this.highlightRect.setAttribute("width", +`${a.width}`);this.workspace.RTL&&this.highlightRect.setAttribute("x",`${-a.width}`)}updateTopBarSize(a){this.topBarBackground.setAttribute("width",`${a.width}`)}updateTextPreviewSize(a,b,c){b=(b.height-c.height)/2;const d=this.foldoutButton.getSize(!0),e=this.deleteButton.getSize(!0);a=a.width-d.getWidth()-e.getWidth();this.textPreview.setAttribute("x",`${(this.workspace.RTL?-1:1)*d.getWidth()}`);this.textPreview.setAttribute("y",`${b+c.height/2}`);this.textPreview.setAttribute("width",`${a}`)}updateResizeHandlePosition(a, +b){this.resizeHandle.setAttribute("y",`${a.height-b.height}`);this.resizeHandle.setAttribute("x",`${a.width-b.width}`)}onSizeChange(a,b){for(let c=this.sizeChangeListeners.length-1;c>=0;c--)this.sizeChangeListeners[c](a,b)}addSizeChangeListener(a){this.sizeChangeListeners.push(a)}removeSizeChangeListener(a){this.sizeChangeListeners.splice(this.sizeChangeListeners.indexOf(a),1)}onResizePointerDown(a){this.isEditable()&&(this.bringToFront(),isRightButton$$module$build$src$core$browser_events(a)||(this.preResizeSize= this.getSize(),start$$module$build$src$core$utils$drag(this.workspace,a,new Coordinate$$module$build$src$core$utils$coordinate(this.workspace.RTL?-this.getSize().width:this.getSize().width,this.getSize().height)),this.resizePointerUpListener=conditionalBind$$module$build$src$core$browser_events(document,"pointerup",this,this.onResizePointerUp),this.resizePointerMoveListener=conditionalBind$$module$build$src$core$browser_events(document,"pointermove",this,this.onResizePointerMove),this.workspace.hideChaff()), a.stopPropagation())}onResizePointerUp(a){clearTouchIdentifier$$module$build$src$core$touch();this.resizePointerUpListener&&(unbind$$module$build$src$core$browser_events(this.resizePointerUpListener),this.resizePointerUpListener=null);this.resizePointerMoveListener&&(unbind$$module$build$src$core$browser_events(this.resizePointerMoveListener),this.resizePointerMoveListener=null);this.setSize(this.size);this.preResizeSize=void 0}onResizePointerMove(a){a=move$$module$build$src$core$utils$drag(this.workspace, -a);this.setSizeWithoutFiringEvents(new Size$$module$build$src$core$utils$size(this.workspace.RTL?-a.x:a.x,a.y))}isCollapsed(){return this.collapsed}setCollapsed(a){(this.collapsed=a)?addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyCollapsed"):removeClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyCollapsed");this.setSizeWithoutFiringEvents(this.size);this.onCollapse()}onCollapse(){for(let a=this.collapseChangeListeners.length-1;0<=a;a--)this.collapseChangeListeners[a](this.collapsed)}addOnCollapseListener(a){this.collapseChangeListeners.push(a)}removeOnCollapseListener(a){this.collapseChangeListeners.splice(this.collapseChangeListeners.indexOf(a), -1)}onFoldoutDown(a){clearTouchIdentifier$$module$build$src$core$touch();this.bringToFront();isRightButton$$module$build$src$core$browser_events(a)||(this.setCollapsed(!this.collapsed),this.workspace.hideChaff());a.stopPropagation()}isEditable(){return this.editable}setEditable(a){(this.editable=a)?(addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyEditable"),removeClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyReadonly"),this.textArea.removeAttribute("readonly")):(removeClass$$module$build$src$core$utils$dom(this.svgRoot, -"blocklyEditable"),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyReadonly"),this.textArea.setAttribute("readonly","true"))}getRelativeToSurfaceXY(){return this.location}moveTo(a){this.location=a;this.svgRoot.setAttribute("transform",`translate(${a.x}, ${a.y})`)}getText(){return this.text}setText(a){this.textArea.value=a;this.onTextChange()}addTextChangeListener(a){this.textChangeListeners.push(a)}removeTextChangeListener(a){this.textChangeListeners.splice(this.textChangeListeners.indexOf(a), -1)}onTextChange(){const a=this.text;this.text=this.textArea.value;this.updateTextPreview(this.text);this.setSize(this.size);for(let b=this.textChangeListeners.length-1;0<=b;b--)this.textChangeListeners[b](a,this.text)}updateTextPreview(a){this.textPreviewNode.textContent=this.truncateText(a)}truncateText(a){return 12<=a.length?`${a.substring(0,9)}...`:a}bringToFront(){const a=this.svgRoot.parentNode,b=a.childNodes;b[b.length-1]!==this.svgRoot&&a.appendChild(this.svgRoot)}onDeleteDown(a){clearTouchIdentifier$$module$build$src$core$touch(); -isRightButton$$module$build$src$core$browser_events(a)||this.dispose();a.stopPropagation()}dispose(){this.disposing=!0;removeNode$$module$build$src$core$utils$dom(this.svgRoot);for(let a=this.disposeListeners.length-1;0<=a;a--)this.disposeListeners[a]();this.disposed=!0}isDisposed(){return this.disposed}isDeadOrDying(){return this.disposing||this.disposed}addDisposeListener(a){this.disposeListeners.push(a)}removeDisposeListener(a){this.disposeListeners.splice(this.disposeListeners.indexOf(a),1)}}; -register$$module$build$src$core$css("\n.injectionDiv {\n --commentFillColour: #FFFCC7;\n --commentBorderColour: #F2E49B;\n}\n\n.blocklyComment .blocklyTextarea {\n background-color: var(--commentFillColour);\n border: 1px solid var(--commentBorderColour);\n box-sizing: border-box;\n display: block;\n outline: 0;\n padding: 5px;\n resize: none;\n width: 100%;\n height: 100%;\n}\n\n.blocklyReadonly.blocklyComment .blocklyTextarea {\n cursor: inherit;\n}\n\n.blocklyDeleteIcon {\n width: 20px;\n height: 20px;\n display: none;\n cursor: pointer;\n}\n\n.blocklyFoldoutIcon {\n width: 20px;\n height: 20px;\n transform-origin: 12px 12px;\n cursor: pointer;\n}\n.blocklyResizeHandle {\n width: 12px;\n height: 12px;\n cursor: se-resize;\n}\n.blocklyReadonly.blocklyComment .blocklyResizeHandle {\n cursor: inherit;\n}\n\n.blocklyCommentTopbarBackground {\n fill: var(--commentBorderColour);\n height: 24px;\n}\n\n.blocklyComment .blocklyCommentPreview.blocklyText {\n fill: #000;\n dominant-baseline: middle;\n visibility: hidden;\n}\n\n.blocklyCollapsed.blocklyComment .blocklyCommentPreview {\n visibility: visible;\n}\n\n.blocklyCollapsed.blocklyComment .blocklyCommentForeignObject,\n.blocklyCollapsed.blocklyComment .blocklyResizeHandle {\n display: none;\n}\n\n.blocklyCollapsed.blocklyComment .blocklyFoldoutIcon {\n transform: rotate(-90deg);\n}\n\n.blocklyRTL .blocklyCommentTopbar {\n transform: scale(-1, 1);\n}\n\n.blocklyRTL .blocklyCommentForeignObject {\n direction: rtl;\n}\n\n.blocklyRTL .blocklyCommentPreview {\n /* Revert the scale and control RTL using direction instead. */\n transform: scale(-1, 1);\n direction: rtl;\n}\n\n.blocklyRTL .blocklyResizeHandle {\n transform: scale(-1, 1);\n cursor: sw-resize;\n}\n\n.blocklyCommentHighlight {\n fill: none;\n}\n\n.blocklySelected .blocklyCommentHighlight {\n stroke: #fc3;\n stroke-width: 3px;\n}\n\n.blocklyCollapsed.blocklySelected .blocklyCommentHighlight {\n stroke: none;\n}\n\n.blocklyCollapsed.blocklySelected .blocklyCommentTopbarBackground {\n stroke: #fc3;\n stroke-width: 3px;\n}\n"); -var module$build$src$core$comments$comment_view={};module$build$src$core$comments$comment_view.CommentView=CommentView$$module$build$src$core$comments$comment_view;var WorkspaceComment$$module$build$src$core$comments$workspace_comment=class{constructor(a,b){this.workspace=a;this.text="";this.size=new Size$$module$build$src$core$utils$size(120,100);this.collapsed=!1;this.deletable=this.movable=this.editable=!0;this.location=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.disposing=this.disposed=!1;this.id=b&&!a.getCommentById(b)?b:genUid$$module$build$src$core$utils$idgenerator();a.addTopComment(this);this.fireCreateEvent()}fireCreateEvent(){isEnabled$$module$build$src$core$events$utils()&& +a);this.setSizeWithoutFiringEvents(new Size$$module$build$src$core$utils$size(this.workspace.RTL?-a.x:a.x,a.y))}isCollapsed(){return this.collapsed}setCollapsed(a){(this.collapsed=a)?addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyCollapsed"):removeClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyCollapsed");this.setSizeWithoutFiringEvents(this.size);this.onCollapse()}onCollapse(){for(let a=this.collapseChangeListeners.length-1;a>=0;a--)this.collapseChangeListeners[a](this.collapsed)}addOnCollapseListener(a){this.collapseChangeListeners.push(a)}removeOnCollapseListener(a){this.collapseChangeListeners.splice(this.collapseChangeListeners.indexOf(a), +1)}isEditable(){return this.editable}setEditable(a){(this.editable=a)?(addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyEditable"),removeClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyReadonly")):(removeClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyEditable"),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyReadonly"));this.commentEditor.setEditable(a)}getRelativeToSurfaceXY(){return this.location}moveTo(a){this.location=a;this.svgRoot.setAttribute("transform", +`translate(${a.x}, ${a.y})`)}getText(){return this.commentEditor.getText()}setText(a){this.commentEditor.setText(a)}setPlaceholderText(a){this.commentEditor.setPlaceholderText(a)}addTextChangeListener(a){this.commentEditor.addTextChangeListener(a)}removeTextChangeListener(a){this.commentEditor.removeTextChangeListener(a)}updateTextPreview(a){this.textPreviewNode.textContent=this.truncateText(a)}truncateText(a){return a.length>=12?`${a.substring(0,9)}...`:a}bringToFront(){const a=this.svgRoot.parentNode, +b=a.childNodes;b[b.length-1]!==this.svgRoot&&a.appendChild(this.svgRoot)}onDeleteDown(a){clearTouchIdentifier$$module$build$src$core$touch();isRightButton$$module$build$src$core$browser_events(a)||this.dispose();a.stopPropagation()}dispose(){this.disposing=!0;removeNode$$module$build$src$core$utils$dom(this.svgRoot);for(let a=this.disposeListeners.length-1;a>=0;a--)this.disposeListeners[a]();this.disposeListeners.length=0;this.disposed=!0}isDisposed(){return this.disposed}isDeadOrDying(){return this.disposing|| +this.disposed}addDisposeListener(a){this.disposeListeners.push(a)}removeDisposeListener(a){this.disposeListeners.splice(this.disposeListeners.indexOf(a),1)}getCommentBarButtons(){return[this.foldoutButton,this.deleteButton]}};CommentView$$module$build$src$core$comments$comment_view.defaultCommentSize=new Size$$module$build$src$core$utils$size(120,100);register$$module$build$src$core$css("\n.injectionDiv {\n --commentFillColour: #FFFCC7;\n --commentBorderColour: #F2E49B;\n}\n\n.blocklyComment .blocklyTextarea {\n background-color: var(--commentFillColour);\n border: 1px solid var(--commentBorderColour);\n box-sizing: border-box;\n display: block;\n outline: 0;\n padding: 5px;\n resize: none;\n width: 100%;\n height: 100%;\n}\n\n.blocklyReadonly.blocklyComment .blocklyTextarea {\n cursor: inherit;\n}\n\n.blocklyDeleteIcon {\n width: 20px;\n height: 20px;\n display: none;\n cursor: pointer;\n}\n\n.blocklyFoldoutIcon {\n width: 20px;\n height: 20px;\n transform-origin: 12px 12px;\n cursor: pointer;\n}\n.blocklyResizeHandle {\n width: 12px;\n height: 12px;\n cursor: se-resize;\n}\n.blocklyReadonly.blocklyComment .blocklyResizeHandle {\n cursor: inherit;\n}\n\n.blocklyCommentTopbarBackground {\n fill: var(--commentBorderColour);\n height: 24px;\n}\n\n.blocklyComment .blocklyCommentPreview.blocklyText {\n fill: #000;\n dominant-baseline: middle;\n visibility: hidden;\n}\n\n.blocklyCollapsed.blocklyComment .blocklyCommentPreview {\n visibility: visible;\n}\n\n.blocklyCollapsed.blocklyComment .blocklyCommentForeignObject,\n.blocklyCollapsed.blocklyComment .blocklyResizeHandle {\n display: none;\n}\n\n.blocklyCollapsed.blocklyComment .blocklyFoldoutIcon {\n transform: rotate(-90deg);\n}\n\n.blocklyRTL .blocklyCommentTopbar {\n transform: scale(-1, 1);\n}\n\n.blocklyRTL .blocklyCommentForeignObject {\n direction: rtl;\n}\n\n.blocklyRTL .blocklyCommentPreview {\n /* Revert the scale and control RTL using direction instead. */\n transform: scale(-1, 1);\n direction: rtl;\n}\n\n.blocklyRTL .blocklyResizeHandle {\n transform: scale(-1, 1);\n cursor: sw-resize;\n}\n\n.blocklyCommentHighlight {\n fill: none;\n}\n\n.blocklyCommentText.blocklyActiveFocus {\n border-color: #fc3;\n border-width: 2px;\n}\n\n.blocklySelected .blocklyCommentHighlight {\n stroke: #fc3;\n stroke-width: 3px;\n}\n\n.blocklyCollapsed.blocklySelected .blocklyCommentHighlight {\n stroke: none;\n}\n\n.blocklyCollapsed.blocklySelected .blocklyCommentTopbarBackground {\n stroke: #fc3;\n stroke-width: 3px;\n}\n"); +var module$build$src$core$comments$comment_view={};module$build$src$core$comments$comment_view.CommentView=CommentView$$module$build$src$core$comments$comment_view;var WorkspaceComment$$module$build$src$core$comments$workspace_comment=class{constructor(a,b){this.workspace=a;this.text="";this.collapsed=!1;this.deletable=this.movable=this.editable=!0;this.location=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.disposing=this.disposed=!1;this.id=b&&!a.getCommentById(b)?b:genUid$$module$build$src$core$utils$idgenerator();this.size=CommentView$$module$build$src$core$comments$comment_view.defaultCommentSize;a.addTopComment(this);this.fireCreateEvent()}fireCreateEvent(){isEnabled$$module$build$src$core$events$utils()&& fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_CREATE))(this))}fireDeleteEvent(){isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_DELETE))(this))}fireChangeEvent(a,b){isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_CHANGE))(this, a,b))}fireCollapseEvent(a){isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_COLLAPSE))(this,a))}setText(a){const b=this.text;this.text=a;this.fireChangeEvent(b,a)}getText(){return this.text}setSize(a){const b=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_RESIZE))(this);this.size=a;b.recordCurrentSizeAsNewSize(); -fire$$module$build$src$core$events$utils(b)}getSize(){return this.size}setCollapsed(a){this.collapsed=a;this.fireCollapseEvent(a)}isCollapsed(){return this.collapsed}setEditable(a){this.editable=a}isEditable(){return this.isOwnEditable()&&!this.workspace.options.readOnly}isOwnEditable(){return this.editable}setMovable(a){this.movable=a}isMovable(){return this.isOwnMovable()&&!this.workspace.options.readOnly}isOwnMovable(){return this.movable}setDeletable(a){this.deletable=a}isDeletable(){return this.isOwnDeletable()&& -!this.isDeadOrDying()&&!this.workspace.options.readOnly}isOwnDeletable(){return this.deletable}moveTo(a,b){const c=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_MOVE))(this);b&&c.setReason(b);this.location=a;c.recordNew();fire$$module$build$src$core$events$utils(c)}getRelativeToSurfaceXY(){return this.location}dispose(){this.disposing=!0;this.fireDeleteEvent();this.workspace.removeTopComment(this);this.disposed=!0}isDisposed(){return this.disposed}isDeadOrDying(){return this.disposing|| -this.disposed}},module$build$src$core$comments$workspace_comment={};module$build$src$core$comments$workspace_comment.WorkspaceComment=WorkspaceComment$$module$build$src$core$comments$workspace_comment;var RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment=class extends WorkspaceComment$$module$build$src$core$comments$workspace_comment{constructor(a,b){super(a,b);this.dragStrategy=new CommentDragStrategy$$module$build$src$core$dragging$comment_drag_strategy(this);this.workspace=a;this.view=new CommentView$$module$build$src$core$comments$comment_view(a);this.view.setSize(this.getSize());this.view.setEditable(this.isEditable());this.view.getSvgRoot().setAttribute("data-id", -this.id);this.addModelUpdateBindings();conditionalBind$$module$build$src$core$browser_events(this.view.getSvgRoot(),"pointerdown",this,this.startGesture);conditionalBind$$module$build$src$core$browser_events(this.view.getSvgRoot(),"wheel",this,c=>{c.stopPropagation()})}addModelUpdateBindings(){this.view.addTextChangeListener((a,b)=>void super.setText(b));this.view.addSizeChangeListener((a,b)=>void super.setSize(b));this.view.addOnCollapseListener(()=>void super.setCollapsed(this.view.isCollapsed())); -this.view.addDisposeListener(()=>{this.isDeadOrDying()||this.dispose()})}setText(a){this.view.setText(a)}setSize(a){this.view.setSize(a)}setCollapsed(a){this.view.setCollapsed(a)}setEditable(a){super.setEditable(a);this.view.setEditable(this.isEditable())}getSvgRoot(){return this.view.getSvgRoot()}getSize(){return super.getSize()}getBoundingRectangle(){const a=this.getRelativeToSurfaceXY();var b,c;const d=null!=(c=null==(b=this.view)?void 0:b.getSize())?c:this.getSize();this.workspace.RTL?(b=a.x- -d.width,c=a.x):(b=a.x,c=a.x+d.width);return new Rect$$module$build$src$core$utils$rect(a.y,a.y+d.height,b,c)}moveBy(a,b,c){const d=this.getRelativeToSurfaceXY();a=new Coordinate$$module$build$src$core$utils$coordinate(d.x+a,d.y+b);this.moveTo(a,c)}moveTo(a,b){super.moveTo(a,b);this.view.moveTo(a)}moveDuringDrag(a){this.location=a;this.view.moveTo(a)}setDragging(a){a?addClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklyDragging"):removeClass$$module$build$src$core$utils$dom(this.getSvgRoot(), -"blocklyDragging")}dispose(){this.disposing=!0;this.view.isDeadOrDying()||this.view.dispose();super.dispose()}startGesture(a){const b=this.workspace.getGesture(a);if(b){if(isTargetInput$$module$build$src$core$browser_events(a))a.stopPropagation();else{b.handleCommentStart(a,this);let c;null==(c=this.workspace.getLayerManager())||c.append(this,BLOCK$$module$build$src$core$layers)}$.setSelected$$module$build$src$core$common(this)}}setDeleteStyle(a){a?addClass$$module$build$src$core$utils$dom(this.getSvgRoot(), -"blocklyDraggingDelete"):removeClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklyDraggingDelete")}isMovable(){return this.dragStrategy.isMovable()}startDrag(){this.dragStrategy.startDrag()}drag(a){this.dragStrategy.drag(a)}endDrag(){this.dragStrategy.endDrag()}revertDrag(){this.dragStrategy.revertDrag()}select(){addClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklySelected")}unselect(){removeClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklySelected")}toCopyData(){return{paster:WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster.TYPE, -commentState:save$$module$build$src$core$serialization$workspace_comments(this,{addCoordinates:!0})}}showContextMenu(a){const b=ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.getContextMenuOptions(ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.COMMENT,{comment:this});show$$module$build$src$core$contextmenu(a,b,this.workspace.RTL,this.workspace)}snapToGrid(){if(!this.isDeadOrDying()){var a=this.workspace.getGrid();if(null!=a&&a.shouldSnap()){var b= -this.getRelativeToSurfaceXY();a=a.alignXY(b);a!==b&&this.moveTo(a,["snap"])}}}},module$build$src$core$comments$rendered_workspace_comment={};module$build$src$core$comments$rendered_workspace_comment.RenderedWorkspaceComment=RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment;var module$build$src$core$xml={};module$build$src$core$xml.appendDomToWorkspace=appendDomToWorkspace$$module$build$src$core$xml;module$build$src$core$xml.blockToDom=blockToDom$$module$build$src$core$xml;module$build$src$core$xml.blockToDomWithXY=blockToDomWithXY$$module$build$src$core$xml;module$build$src$core$xml.clearWorkspaceAndLoadFromXml=clearWorkspaceAndLoadFromXml$$module$build$src$core$xml;module$build$src$core$xml.deleteNext=deleteNext$$module$build$src$core$xml; +fire$$module$build$src$core$events$utils(b)}getSize(){return this.size}setCollapsed(a){this.collapsed=a;this.fireCollapseEvent(a)}isCollapsed(){return this.collapsed}setEditable(a){this.editable=a}isEditable(){return this.isOwnEditable()&&!this.workspace.isReadOnly()}isOwnEditable(){return this.editable}setMovable(a){this.movable=a}isMovable(){return this.isOwnMovable()&&!this.workspace.isReadOnly()&&!this.workspace.isFlyout}isOwnMovable(){return this.movable}setDeletable(a){this.deletable=a}isDeletable(){return this.isOwnDeletable()&& +!this.isDeadOrDying()&&!this.workspace.isReadOnly()&&!this.workspace.isFlyout}isOwnDeletable(){return this.deletable}moveTo(a,b){const c=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.COMMENT_MOVE))(this);b&&c.setReason(b);this.location=a;c.recordNew();fire$$module$build$src$core$events$utils(c)}getRelativeToSurfaceXY(){return this.location}dispose(){this.disposing=!0;this.fireDeleteEvent();this.workspace.removeTopComment(this);this.disposed=!0}isDisposed(){return this.disposed}isDeadOrDying(){return this.disposing|| +this.disposed}},module$build$src$core$comments$workspace_comment={};module$build$src$core$comments$workspace_comment.WorkspaceComment=WorkspaceComment$$module$build$src$core$comments$workspace_comment;var RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment=class extends WorkspaceComment$$module$build$src$core$comments$workspace_comment{constructor(a,b){super(a,b);this.dragStrategy=new CommentDragStrategy$$module$build$src$core$dragging$comment_drag_strategy(this);this.workspace=a;this.view=new CommentView$$module$build$src$core$comments$comment_view(a,this.id);this.view.setSize(this.getSize());this.view.setEditable(this.isEditable());this.view.getSvgRoot().setAttribute("data-id", +this.id);this.view.getSvgRoot().setAttribute("id",this.id);this.addModelUpdateBindings();conditionalBind$$module$build$src$core$browser_events(this.view.getSvgRoot(),"pointerdown",this,this.startGesture)}addModelUpdateBindings(){this.view.addTextChangeListener((a,b)=>void super.setText(b));this.view.addSizeChangeListener((a,b)=>void super.setSize(b));this.view.addOnCollapseListener(()=>void super.setCollapsed(this.view.isCollapsed()));this.view.addDisposeListener(()=>{this.isDeadOrDying()||this.dispose()})}setText(a){this.view.setText(a)}setPlaceholderText(a){this.view.setPlaceholderText(a)}setSize(a){this.view.setSize(a)}setCollapsed(a){this.view.setCollapsed(a)}setEditable(a){super.setEditable(a); +this.view.setEditable(this.isEditable())}getSvgRoot(){return this.view.getSvgRoot()}getSize(){return super.getSize()}getBoundingRectangle(){const a=this.getRelativeToSurfaceXY();var b,c;const d=(c=(b=this.view)==null?void 0:b.getSize())!=null?c:this.getSize();this.workspace.RTL?(b=a.x-d.width,c=a.x):(b=a.x,c=a.x+d.width);return new Rect$$module$build$src$core$utils$rect(a.y,a.y+d.height,b,c)}moveBy(a,b,c){const d=this.getRelativeToSurfaceXY();a=new Coordinate$$module$build$src$core$utils$coordinate(d.x+ +a,d.y+b);this.moveTo(a,c)}moveTo(a,b){super.moveTo(a,b);this.view.moveTo(a)}moveDuringDrag(a){this.location=a;this.view.moveTo(a)}setDragging(a){a?addClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklyDragging"):removeClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklyDragging")}dispose(){this.disposing=!0;const a=$.getFocusManager$$module$build$src$core$focus_manager();a.getFocusedNode()===this&&setTimeout(()=>a.focusTree(this.workspace),0);this.view.isDeadOrDying()|| +this.view.dispose();super.dispose()}startGesture(a){const b=this.workspace.getGesture(a);b&&(b.handleCommentStart(a,this),$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this))}setDeleteStyle(a){a?addClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklyDraggingDelete"):removeClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklyDraggingDelete")}isCopyable(){return this.isOwnMovable()&&this.isOwnDeletable()}isMovable(){return this.dragStrategy.isMovable()}startDrag(){this.dragStrategy.startDrag()}drag(a){this.dragStrategy.drag(a)}endDrag(){this.dragStrategy.endDrag()}revertDrag(){this.dragStrategy.revertDrag()}select(){addClass$$module$build$src$core$utils$dom(this.getSvgRoot(), +"blocklySelected");fireSelectedEvent$$module$build$src$core$common(this)}unselect(){removeClass$$module$build$src$core$utils$dom(this.getSvgRoot(),"blocklySelected");fireSelectedEvent$$module$build$src$core$common(null)}toCopyData(){return{paster:WorkspaceCommentPaster$$module$build$src$core$clipboard$workspace_comment_paster.TYPE,commentState:save$$module$build$src$core$serialization$workspace_comments(this,{addCoordinates:!0,saveIds:!1})}}showContextMenu(a){const b=ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.getContextMenuOptions({comment:this, +focusedNode:this},a);let c;c=a instanceof PointerEvent?new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY):wsToScreenCoordinates$$module$build$src$core$utils$svg_math(this.workspace,this.getRelativeToSurfaceXY()).translate(10,10);show$$module$build$src$core$contextmenu(a,b,this.workspace.RTL,this.workspace,c)}snapToGrid(){if(!this.isDeadOrDying()){var a=this.workspace.getGrid();if(a!=null&&a.shouldSnap()){var b=this.getRelativeToSurfaceXY();a=a.alignXY(b);a!==b&&this.moveTo(a, +["snap"])}}}getEditorFocusableNode(){return this.view.getEditorFocusableNode()}getFocusableElement(){return this.getSvgRoot()}getFocusableTree(){return this.workspace}onNodeFocus(){this.select();let a;(a=this.getSvgRoot().parentElement)==null||a.appendChild(this.getSvgRoot());this.workspace.scrollBoundsIntoView(this.getBoundingRectangle())}onNodeBlur(){this.unselect()}canBeFocused(){return!0}},module$build$src$core$comments$rendered_workspace_comment={}; +module$build$src$core$comments$rendered_workspace_comment.RenderedWorkspaceComment=RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment;var module$build$src$core$xml={};module$build$src$core$xml.appendDomToWorkspace=appendDomToWorkspace$$module$build$src$core$xml;module$build$src$core$xml.blockToDom=blockToDom$$module$build$src$core$xml;module$build$src$core$xml.blockToDomWithXY=blockToDomWithXY$$module$build$src$core$xml;module$build$src$core$xml.clearWorkspaceAndLoadFromXml=clearWorkspaceAndLoadFromXml$$module$build$src$core$xml;module$build$src$core$xml.deleteNext=deleteNext$$module$build$src$core$xml; module$build$src$core$xml.domToBlock=$.domToBlock$$module$build$src$core$xml;module$build$src$core$xml.domToBlockInternal=domToBlockInternal$$module$build$src$core$xml;module$build$src$core$xml.domToPrettyText=domToPrettyText$$module$build$src$core$xml;module$build$src$core$xml.domToText=domToText$$module$build$src$core$xml;module$build$src$core$xml.domToVariables=domToVariables$$module$build$src$core$xml;module$build$src$core$xml.domToWorkspace=$.domToWorkspace$$module$build$src$core$xml; module$build$src$core$xml.loadWorkspaceComment=loadWorkspaceComment$$module$build$src$core$xml;module$build$src$core$xml.saveWorkspaceComment=saveWorkspaceComment$$module$build$src$core$xml;module$build$src$core$xml.variablesToDom=variablesToDom$$module$build$src$core$xml;module$build$src$core$xml.workspaceToDom=workspaceToDom$$module$build$src$core$xml;var BlockCreate$$module$build$src$core$events$events_block_create=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a){super(a);this.type=EventType$$module$build$src$core$events$type.BLOCK_CREATE;a&&(a.isShadow()&&(this.recordUndo=!1),this.xml=blockToDomWithXY$$module$build$src$core$xml(a),this.ids=getDescendantIds$$module$build$src$core$events$utils(a),this.json=save$$module$build$src$core$serialization$blocks(a,{addCoordinates:!0}))}toJson(){const a=super.toJson(); if(!this.xml)throw Error("The block XML is undefined. Either pass a block to the constructor, or call fromJson");if(!this.ids)throw Error("The block IDs are undefined. Either pass a block to the constructor, or call fromJson");if(!this.json)throw Error("The block JSON is undefined. Either pass a block to the constructor, or call fromJson");a.xml=domToText$$module$build$src$core$xml(this.xml);a.ids=this.ids;a.json=this.json;this.recordUndo||(a.recordUndo=this.recordUndo);return a}static fromJson(a, -b,c){b=super.fromJson(a,b,null!=c?c:new BlockCreate$$module$build$src$core$events$events_block_create);b.xml=$.textToDom$$module$build$src$core$utils$xml(a.xml);b.ids=a.ids;b.json=a.json;void 0!==a.recordUndo&&(b.recordUndo=a.recordUndo);return b}run(a){const b=this.getEventWorkspace_();if(!this.json)throw Error("The block JSON is undefined. Either pass a block to the constructor, or call fromJson");if(!this.ids)throw Error("The block IDs are undefined. Either pass a block to the constructor, or call fromJson"); +b,c){b=BlockBase$$module$build$src$core$events$events_block_base.fromJson(a,b,c!=null?c:new BlockCreate$$module$build$src$core$events$events_block_create);b.xml=$.textToDom$$module$build$src$core$utils$xml(a.xml);b.ids=a.ids;b.json=a.json;a.recordUndo!==void 0&&(b.recordUndo=a.recordUndo);return b}run(a){const b=this.getEventWorkspace_();if(!this.json)throw Error("The block JSON is undefined. Either pass a block to the constructor, or call fromJson");if(!this.ids)throw Error("The block IDs are undefined. Either pass a block to the constructor, or call fromJson"); if(!allShadowBlocks$$module$build$src$core$events$events_block_create(b,this.ids))if(a)append$$module$build$src$core$serialization$blocks(this.json,b);else for(a=0;aa.getBlockById(c)).filter(c=>c&&c.isShadow()).length===b.length}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.BLOCK_CREATE,BlockCreate$$module$build$src$core$events$events_block_create);var module$build$src$core$events$events_block_create={};module$build$src$core$events$events_block_create.BlockCreate=BlockCreate$$module$build$src$core$events$events_block_create;var ThemeChange$$module$build$src$core$events$events_theme_change=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b){super(b);this.type=EventType$$module$build$src$core$events$type.THEME_CHANGE;this.themeName=a}toJson(){const a=super.toJson();if(!this.themeName)throw Error("The theme name is undefined. Either pass a theme name to the constructor, or call fromJson");a.themeName=this.themeName;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new ThemeChange$$module$build$src$core$events$events_theme_change); -b.themeName=a.themeName;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.THEME_CHANGE,ThemeChange$$module$build$src$core$events$events_theme_change);var module$build$src$core$events$events_theme_change={};module$build$src$core$events$events_theme_change.ThemeChange=ThemeChange$$module$build$src$core$events$events_theme_change;var ViewportChange$$module$build$src$core$events$events_viewport=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c,d,e){super(d);this.type=EventType$$module$build$src$core$events$type.VIEWPORT_CHANGE;this.viewTop=a;this.viewLeft=b;this.scale=c;this.oldScale=e}toJson(){const a=super.toJson();if(void 0===this.viewTop)throw Error("The view top is undefined. Either pass a value to the constructor, or call fromJson");if(void 0===this.viewLeft)throw Error("The view left is undefined. Either pass a value to the constructor, or call fromJson"); -if(void 0===this.scale)throw Error("The scale is undefined. Either pass a value to the constructor, or call fromJson");if(void 0===this.oldScale)throw Error("The old scale is undefined. Either pass a value to the constructor, or call fromJson");a.viewTop=this.viewTop;a.viewLeft=this.viewLeft;a.scale=this.scale;a.oldScale=this.oldScale;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new ViewportChange$$module$build$src$core$events$events_viewport);b.viewTop=a.viewTop;b.viewLeft=a.viewLeft; -b.scale=a.scale;b.oldScale=a.oldScale;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VIEWPORT_CHANGE,ViewportChange$$module$build$src$core$events$events_viewport);var module$build$src$core$events$events_viewport={};module$build$src$core$events$events_viewport.ViewportChange=ViewportChange$$module$build$src$core$events$events_viewport;var ConnectionType$$module$build$src$core$connection_type;(function(a){a[a.INPUT_VALUE=1]="INPUT_VALUE";a[a.OUTPUT_VALUE=2]="OUTPUT_VALUE";a[a.NEXT_STATEMENT=3]="NEXT_STATEMENT";a[a.PREVIOUS_STATEMENT=4]="PREVIOUS_STATEMENT"})(ConnectionType$$module$build$src$core$connection_type||(ConnectionType$$module$build$src$core$connection_type={}));var module$build$src$core$connection_type={};module$build$src$core$connection_type.ConnectionType=ConnectionType$$module$build$src$core$connection_type;var ConnectionDB$$module$build$src$core$connection_db=class{constructor(a){this.connectionChecker=a;this.connections=[]}addConnection(a,b){b=this.calculateIndexForYPos(b);this.connections.splice(b,0,a)}findIndexOfConnection(a,b){if(!this.connections.length)return-1;const c=this.calculateIndexForYPos(b);if(c>=this.connections.length)return-1;b=a.y;let d=c;for(;0<=d&&this.connections[d].y===b;){if(this.connections[d]===a)return d;d--}for(d=c;da)c=d;else{b=d;break}}return b}removeConnection(a,b){a=this.findIndexOfConnection(a,b);if(-1===a)throw Error("Unable to find connection in connectionDB.");this.connections.splice(a,1)}getNeighbours(a,b){function c(l){const m=e-d[l].x,n=f-d[l].y;Math.sqrt(m*m+n*n)<=b&&k.push(d[l]); -return n -(this.flyout?$.config$$module$build$src$core$config.flyoutDragRadius:$.config$$module$build$src$core$config.dragRadius)}updateIsDraggingFromFlyout(){let a;if(!this.targetBlock||null==(a=this.flyout)||!a.isBlockCreatable(this.targetBlock))return!1;if(!this.flyout.targetWorkspace)throw Error("Cannot update dragging from the flyout because the ' +\n 'flyout's target workspace is undefined");return!this.flyout.isScrollable()||this.flyout.isDragTowardWorkspace(this.currentDragDeltaXY)?(this.startWorkspace_= -this.flyout.targetWorkspace,this.startWorkspace_.updateScreenCalculationsIfScrolled(),$.getGroup$$module$build$src$core$events$utils()||$.setGroup$$module$build$src$core$events$utils(!0),this.startBlock=null,this.targetBlock=this.flyout.createBlock(this.targetBlock),$.setSelected$$module$build$src$core$common(this.targetBlock),!0):!1}updateIsDraggingWorkspace(){if(!this.startWorkspace_)throw Error("Cannot update dragging the workspace because the start workspace is undefined");if(this.flyout?this.flyout.isScrollable(): -this.startWorkspace_&&this.startWorkspace_.isDraggable())this.dragging=!0,this.workspaceDragger=new WorkspaceDragger$$module$build$src$core$workspace_dragger(this.startWorkspace_),this.workspaceDragger.startDrag()}updateIsDragging(a){if(!this.startWorkspace_)throw Error("Cannot update dragging because the start workspace is undefined");if(this.calledUpdateIsDragging)throw Error("updateIsDragging_ should only be called once per gesture.");this.calledUpdateIsDragging=!0;this.flyout&&this.updateIsDraggingFromFlyout(); -const b=getSelected$$module$build$src$core$common();b&&isDraggable$$module$build$src$core$interfaces$i_draggable(b)&&b.isMovable()?(this.dragging=!0,this.dragger=this.createDragger(b,this.startWorkspace_),this.dragger.onDragStart(a),this.dragger.onDrag(a,this.currentDragDeltaXY)):this.updateIsDraggingWorkspace()}createDragger(a,b){return new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.BLOCK_DRAGGER,this.creatorWorkspace.options,!0))(a,b)}doStart(a){if(!this.startWorkspace_)throw Error("Cannot start the touch gesture becauase the start workspace is undefined"); -this.isPinchZoomEnabled=this.startWorkspace_.options.zoomOptions&&this.startWorkspace_.options.zoomOptions.pinch;isTargetInput$$module$build$src$core$browser_events(a)?this.cancel():(this.gestureHasStarted=!0,disconnectUiStop$$module$build$src$core$block_animations(),this.startWorkspace_.updateScreenCalculationsIfScrolled(),this.startWorkspace_.isMutator&&this.startWorkspace_.resize(),this.currentDropdownOwner=getOwner$$module$build$src$core$dropdowndiv(),this.startWorkspace_.hideChaff(!!this.flyout), -this.startWorkspace_.markFocused(),this.mostRecentEvent=a,block$$module$build$src$core$tooltip(),isRightButton$$module$build$src$core$browser_events(a)?this.handleRightClick(a):("pointerdown"===a.type.toLowerCase()&&"mouse"!==a.pointerType&&longStart$$module$build$src$core$touch(a,this),this.mouseDownXY=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY),this.bindMouseEvents(a),this.isEnding_||this.handleTouchStart(a)))}bindMouseEvents(a){this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document, -"pointerdown",null,this.handleStart.bind(this),!0));this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document,"pointermove",null,this.handleMove.bind(this),!0));this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document,"pointerup",null,this.handleUp.bind(this),!0));a.preventDefault();a.stopPropagation()}handleStart(a){this.isDragging()||(this.handleTouchStart(a),this.isMultiTouch()&&longStop$$module$build$src$core$touch())}handleMove(a){if(this.isDragging()&& -shouldHandleEvent$$module$build$src$core$touch(a)||!this.isMultiTouch()){this.updateFromEvent(a);if(this.workspaceDragger)this.workspaceDragger.drag(this.currentDragDeltaXY);else if(this.dragger)this.dragger.onDrag(this.mostRecentEvent,this.currentDragDeltaXY);a.preventDefault();a.stopPropagation()}else this.isMultiTouch()&&(this.handleTouchMove(a),longStop$$module$build$src$core$touch())}handleUp(a){this.isDragging()||this.handleTouchEnd(a);if(!this.isMultiTouch()||this.isDragging()){if(!shouldHandleEvent$$module$build$src$core$touch(a))return; -this.updateFromEvent(a);longStop$$module$build$src$core$touch();if(this.isEnding_){console.log("Trying to end a gesture recursively.");return}this.isEnding_=!0;if(this.dragger)this.dragger.onDragEnd(a,this.currentDragDeltaXY);else this.workspaceDragger?this.workspaceDragger.endDrag(this.currentDragDeltaXY):this.isBubbleClick()||this.isCommentClick()||(this.isFieldClick()?this.doFieldClick():this.isIconClick()?this.doIconClick():this.isBlockClick()?this.doBlockClick():this.isWorkspaceClick()&&this.doWorkspaceClick(a))}a.preventDefault(); -a.stopPropagation();this.dispose()}handleTouchStart(a){var b=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);this.cachedPoints.set(b,this.getTouchPoint(a));var c=Array.from(this.cachedPoints.keys());2===c.length&&(b=this.cachedPoints.get(c[0]),c=this.cachedPoints.get(c[1]),this.startDistance=Coordinate$$module$build$src$core$utils$coordinate.distance(b,c),this.multiTouch=!0,a.preventDefault())}handleTouchMove(a){const b=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);this.cachedPoints.set(b, -this.getTouchPoint(a));if(this.isPinchZoomEnabled&&2===this.cachedPoints.size)this.handlePinch(a);else{this.updateFromEvent(a);if(this.workspaceDragger)this.workspaceDragger.drag(this.currentDragDeltaXY);else if(this.dragger)this.dragger.onDrag(this.mostRecentEvent,this.currentDragDeltaXY);a.preventDefault();a.stopPropagation()}}handlePinch(a){var b=Array.from(this.cachedPoints.keys()),c=this.cachedPoints.get(b[0]);b=this.cachedPoints.get(b[1]);c=Coordinate$$module$build$src$core$utils$coordinate.distance(c, -b)/this.startDistance;if(0this.previousScale){b=c-this.previousScale;b=0this.cachedPoints.size&&(this.cachedPoints.clear(),this.previousScale=0)}getTouchPoint(a){return this.startWorkspace_?new Coordinate$$module$build$src$core$utils$coordinate(a.pageX,a.pageY):null}isMultiTouch(){return this.multiTouch}cancel(){if(!this.isEnding_){longStop$$module$build$src$core$touch();if(this.dragger)this.dragger.onDragEnd(this.mostRecentEvent,this.currentDragDeltaXY); -else this.workspaceDragger&&this.workspaceDragger.endDrag(this.currentDragDeltaXY);this.dispose()}}handleRightClick(a){this.targetBlock?(this.bringBlockToFront(),this.targetBlock.workspace.hideChaff(!!this.flyout),this.targetBlock.showContextMenu(a)):this.startBubble?this.startBubble.showContextMenu(a):this.startComment?(this.startComment.workspace.hideChaff(),this.startComment.showContextMenu(a)):this.startWorkspace_&&!this.flyout&&(this.startWorkspace_.hideChaff(),this.startWorkspace_.showContextMenu(a)); -a.preventDefault();a.stopPropagation();this.dispose()}handleWsStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleWsStart, but the gesture had already been started.");this.setStartWorkspace(b);this.mostRecentEvent=a;this.startBlock||this.startBubble||this.startComment||$.setSelected$$module$build$src$core$common(null);this.doStart(a)}fireWorkspaceClick(a){fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.CLICK))(null, -a.id,"workspace"))}handleFlyoutStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleFlyoutStart, but the gesture had already been started.");this.setStartFlyout(b);this.handleWsStart(a,b.getWorkspace())}handleBlockStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleBlockStart, but the gesture had already been started.");this.setStartBlock(b);this.mostRecentEvent=a}handleBubbleStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleBubbleStart, but the gesture had already been started."); -this.setStartBubble(b);this.mostRecentEvent=a}handleCommentStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleCommentStart, but the gesture had already been started.");this.setStartComment(b);this.mostRecentEvent=a}doFieldClick(){if(!this.startField)throw Error("Cannot do a field click because the start field is undefined");this.currentDropdownOwner!==this.startField&&this.startField.showEditor(this.mostRecentEvent);this.bringBlockToFront()}doIconClick(){if(!this.startIcon)throw Error("Cannot do an icon click because the start icon is undefined"); -this.bringBlockToFront();this.startIcon.onClick()}doBlockClick(){if(this.flyout&&this.flyout.autoClose){if(!this.targetBlock)throw Error("Cannot do a block click because the target block is undefined");if(this.targetBlock.isEnabled()){$.getGroup$$module$build$src$core$events$utils()||$.setGroup$$module$build$src$core$events$utils(!0);var a=this.flyout.createBlock(this.targetBlock);a.snapToGrid();a.bumpNeighbours()}}else{if(!this.startWorkspace_)throw Error("Cannot do a block click because the start workspace is undefined"); -a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.CLICK))(this.startBlock,this.startWorkspace_.id,"block");fire$$module$build$src$core$events$utils(a)}this.bringBlockToFront();$.setGroup$$module$build$src$core$events$utils(!1)}doWorkspaceClick(a){a=this.creatorWorkspace;getSelected$$module$build$src$core$common()&&getSelected$$module$build$src$core$common().unselect();this.fireWorkspaceClick(this.startWorkspace_||a)}bringBlockToFront(){this.targetBlock&&!this.flyout&& -this.targetBlock.bringToFront()}setStartField(a){if(this.gestureHasStarted)throw Error("Tried to call gesture.setStartField, but the gesture had already been started.");this.startField||(this.startField=a)}setStartIcon(a){if(this.gestureHasStarted)throw Error("Tried to call gesture.setStartIcon, but the gesture had already been started.");this.startIcon||(this.startIcon=a)}setStartBubble(a){this.startBubble||(this.startBubble=a)}setStartComment(a){this.startComment||(this.startComment=a)}setStartBlock(a){this.startBlock|| -this.startBubble||(this.startBlock=a,$.setSelected$$module$build$src$core$common(this.startBlock),a.isInFlyout&&a!==a.getRootBlock()?this.setTargetBlock(a.getRootBlock()):this.setTargetBlock(a))}setTargetBlock(a){a.isShadow()?this.setTargetBlock(a.getParent()):this.targetBlock=a}setStartWorkspace(a){this.startWorkspace_||(this.startWorkspace_=a)}setStartFlyout(a){this.flyout||(this.flyout=a)}isBubbleClick(){return!!this.startBubble&&!this.hasExceededDragRadius}isCommentClick(){return!!this.startComment&& -!this.hasExceededDragRadius}isBlockClick(){return!!this.startBlock&&!this.hasExceededDragRadius&&!this.isFieldClick()&&!this.isIconClick()}isFieldClick(){return this.startField?this.startField.isClickable()&&!this.hasExceededDragRadius&&(!this.flyout||this.startField.isClickableInFlyout(this.flyout.autoClose)):!1}isIconClick(){if(!this.startIcon)return!1;const a=!this.flyout||!this.startIcon.isClickableInFlyout||this.startIcon.isClickableInFlyout(this.flyout.autoClose);return!this.hasExceededDragRadius&& -a}isWorkspaceClick(){return!this.startBlock&&!this.startBubble&&!this.startField&&!this.hasExceededDragRadius}getCurrentDragger(){let a,b;return null!=(b=null!=(a=this.workspaceDragger)?a:this.dragger)?b:null}isDragging(){return this.dragging}hasStarted(){return this.gestureHasStarted}static inProgress(){const a=getAllWorkspaces$$module$build$src$core$common();for(let b=0,c;c=a[b];b++)if(c.currentGesture_)return!0;return!1}},module$build$src$core$gesture={};module$build$src$core$gesture.Gesture=Gesture$$module$build$src$core$gesture;var Grid$$module$build$src$core$grid=class{constructor(a,b){this.pattern=a;this.scale=1;let c;this.spacing=null!=(c=b.spacing)?c:0;let d;this.length=null!=(d=b.length)?d:1;this.line2=(this.line1=a.firstChild)&&this.line1.nextSibling;let e;this.snapToGrid=null!=(e=b.snap)?e:!1}setSpacing(a){this.spacing=a;this.update(this.scale)}getSpacing(){return this.spacing}setLength(a){this.length=a;this.update(this.scale)}getLength(){return this.length}setSnapToGrid(a){this.snapToGrid=a}shouldSnap(){return this.snapToGrid}getPatternId(){return this.pattern.id}update(a){this.scale= -a;var b=this.spacing*a;this.pattern.setAttribute("width",`${b}`);this.pattern.setAttribute("height",`${b}`);b=Math.floor(this.spacing/2)+.5;let c=b-this.length/2,d=b+this.length/2;b*=a;c*=a;d*=a;this.setLineAttributes(this.line1,a,c,d,b,b);this.setLineAttributes(this.line2,a,b,b,c,d)}setLineAttributes(a,b,c,d,e,f){a&&(a.setAttribute("stroke-width",`${b}`),a.setAttribute("x1",`${c}`),a.setAttribute("y1",`${e}`),a.setAttribute("x2",`${d}`),a.setAttribute("y2",`${f}`))}moveTo(a,b){this.pattern.setAttribute("x", -`${a}`);this.pattern.setAttribute("y",`${b}`)}alignXY(a){var b=this.getSpacing();const c=b/2,d=Math.round(Math.round((a.x-c)/b)*b+c);b=Math.round(Math.round((a.y-c)/b)*b+c);return d===a.x&&b===a.y?a:new Coordinate$$module$build$src$core$utils$coordinate(d,b)}static createDom(a,b,c){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATTERN,{id:"blocklyGridPattern"+a,patternUnits:"userSpaceOnUse"},c);let d,e;if(0<(null!=(d=b.length)?d:1)&&0<(null!=(e=b.spacing)? -e:0)){createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{stroke:b.colour},a);let f;null!=(f=b.length)&&f&&createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{stroke:b.colour},a)}else createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{},a);return a}},module$build$src$core$grid={};module$build$src$core$grid.Grid=Grid$$module$build$src$core$grid;var LayerManager$$module$build$src$core$layer_manager=class{constructor(a){this.workspace=a;this.layers=new Map;if(a=a.getInjectionDiv())this.dragLayer=this.createDragLayer(a),this.animationLayer=this.createAnimationLayer(a);a=this.createLayer(BLOCK$$module$build$src$core$layers);addClass$$module$build$src$core$utils$dom(a,"blocklyBlockCanvas");a=this.createLayer(BUBBLE$$module$build$src$core$layers);addClass$$module$build$src$core$utils$dom(a,"blocklyBubbleCanvas")}createDragLayer(a){const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG, -{"class":"blocklyBlockDragSurface",xmlns:SVG_NS$$module$build$src$core$utils$dom,"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1"});a.append(b);return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},b)}createAnimationLayer(a){const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{"class":"blocklyAnimationLayer",xmlns:SVG_NS$$module$build$src$core$utils$dom, -"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1"});a.append(b);return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},b)}appendToAnimationLayer(a){let b;const c=null==(b=this.dragLayer)?void 0:b.getAttribute("transform");if(c){let e;null==(e=this.animationLayer)||e.setAttribute("transform",c)}let d;null==(d=this.animationLayer)||d.appendChild(a.getSvgRoot())}translateLayers(a,b){a= -`translate(${a.x}, ${a.y}) scale(${b})`;let c;null==(c=this.dragLayer)||c.setAttribute("transform",a);for(const [,d]of this.layers)d.setAttribute("transform",a)}moveToDragLayer(a){let b;null==(b=this.dragLayer)||b.appendChild(a.getSvgRoot())}moveOffDragLayer(a,b){this.append(a,b)}append(a,b){this.layers.has(b)||this.createLayer(b);let c;null==(c=this.layers.get(b))||c.appendChild(a.getSvgRoot())}createLayer(a){const b=this.workspace.getSvgGroup(),c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G, -{});let d=!1;const e=[...this.layers].sort((f,g)=>f[0]-g[0]);for(const [f,g]of e)if(ab[1]===a)?a:(this.sourceBlock_&&console.warn("Cannot set the dropdown's value to an unavailable option. Block type: "+this.sourceBlock_.type+", Field name: "+this.name+", Value: "+a),null)}doValueUpdate_(a){super.doValueUpdate_(a); +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.BLOCK_CREATE,BlockCreate$$module$build$src$core$events$events_block_create);var module$build$src$core$events$events_block_create={};module$build$src$core$events$events_block_create.BlockCreate=BlockCreate$$module$build$src$core$events$events_block_create;var ThemeChange$$module$build$src$core$events$events_theme_change=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b){super(b);this.type=EventType$$module$build$src$core$events$type.THEME_CHANGE;this.themeName=a}toJson(){const a=super.toJson();if(!this.themeName)throw Error("The theme name is undefined. Either pass a theme name to the constructor, or call fromJson");a.themeName=this.themeName;return a}static fromJson(a,b,c){b=UiBase$$module$build$src$core$events$events_ui_base.fromJson(a, +b,c!=null?c:new ThemeChange$$module$build$src$core$events$events_theme_change);b.themeName=a.themeName;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.THEME_CHANGE,ThemeChange$$module$build$src$core$events$events_theme_change);var module$build$src$core$events$events_theme_change={};module$build$src$core$events$events_theme_change.ThemeChange=ThemeChange$$module$build$src$core$events$events_theme_change;var ViewportChange$$module$build$src$core$events$events_viewport=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c,d,e){super(d);this.type=EventType$$module$build$src$core$events$type.VIEWPORT_CHANGE;this.viewTop=a;this.viewLeft=b;this.scale=c;this.oldScale=e}toJson(){const a=super.toJson();if(this.viewTop===void 0)throw Error("The view top is undefined. Either pass a value to the constructor, or call fromJson");if(this.viewLeft===void 0)throw Error("The view left is undefined. Either pass a value to the constructor, or call fromJson"); +if(this.scale===void 0)throw Error("The scale is undefined. Either pass a value to the constructor, or call fromJson");if(this.oldScale===void 0)throw Error("The old scale is undefined. Either pass a value to the constructor, or call fromJson");a.viewTop=this.viewTop;a.viewLeft=this.viewLeft;a.scale=this.scale;a.oldScale=this.oldScale;return a}static fromJson(a,b,c){b=UiBase$$module$build$src$core$events$events_ui_base.fromJson(a,b,c!=null?c:new ViewportChange$$module$build$src$core$events$events_viewport); +b.viewTop=a.viewTop;b.viewLeft=a.viewLeft;b.scale=a.scale;b.oldScale=a.oldScale;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VIEWPORT_CHANGE,ViewportChange$$module$build$src$core$events$events_viewport);var module$build$src$core$events$events_viewport={};module$build$src$core$events$events_viewport.ViewportChange=ViewportChange$$module$build$src$core$events$events_viewport;var TEST_ONLY$$module$build$src$core$field_registry={fromJsonInternal:fromJsonInternal$$module$build$src$core$field_registry},module$build$src$core$field_registry={TEST_ONLY:TEST_ONLY$$module$build$src$core$field_registry};module$build$src$core$field_registry.fromJson=$.fromJson$$module$build$src$core$field_registry;module$build$src$core$field_registry.register=register$$module$build$src$core$field_registry;module$build$src$core$field_registry.unregister=unregister$$module$build$src$core$field_registry;var FieldDropdown$$module$build$src$core$field_dropdown=class extends Field$$module$build$src$core$field{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.svgArrow=this.arrow=this.imageElement=this.menu_=this.selectedMenuItem=null;this.SERIALIZABLE=!0;this.clickTarget_=this.suffixField=this.prefixField=this.generatedOptions=null;a!==Field$$module$build$src$core$field.SKIP_SETUP&&(this.setOptions(a),c&&this.configure_(c),b&&this.setValidator(b))}fromXml(a){this.isOptionListDynamic()&& +this.getOptions(!1);this.setValue(a.textContent)}loadState(a){this.loadLegacyState(FieldDropdown$$module$build$src$core$field_dropdown,a)||(this.isOptionListDynamic()&&this.getOptions(!1),this.setValue(a))}initView(){this.shouldAddBorderRect_()?this.createBorderRect_():this.clickTarget_=this.sourceBlock_.getSvgRoot();this.createTextElement_();this.imageElement=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{},this.fieldGroup_);this.getConstants().FIELD_DROPDOWN_SVG_ARROW? +this.createSVGArrow_():this.createTextArrow_();this.borderRect_&&addClass$$module$build$src$core$utils$dom(this.borderRect_,"blocklyDropdownRect");this.fieldGroup_&&(addClass$$module$build$src$core$utils$dom(this.fieldGroup_,"blocklyField"),addClass$$module$build$src$core$utils$dom(this.fieldGroup_,"blocklyDropdownField"))}shouldAddBorderRect_(){let a;return!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW&&!((a=this.getSourceBlock())== +null?0:a.isShadow())}createTextArrow_(){this.arrow=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TSPAN,{},this.textElement_);let a;this.arrow.appendChild(document.createTextNode(((a=this.getSourceBlock())==null?0:a.RTL)?FieldDropdown$$module$build$src$core$field_dropdown.ARROW_CHAR+" ":" "+FieldDropdown$$module$build$src$core$field_dropdown.ARROW_CHAR));this.getConstants().FIELD_TEXT_BASELINE_CENTER&&this.arrow.setAttribute("dominant-baseline","central");let b; +((b=this.getSourceBlock())==null?0:b.RTL)?this.getTextElement().insertBefore(this.arrow,this.textContent_):this.getTextElement().appendChild(this.arrow)}createSVGArrow_(){this.svgArrow=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{height:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px",width:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px"},this.fieldGroup_);this.svgArrow.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href", +this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI)}showEditor_(a){var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.dropdownCreate();this.menu_&&(this.menu_.openingCoords=a&&typeof a.clientX==="number"?new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY):null,clearContent$$module$build$src$core$dropdowndiv(),a=this.menu_.render(getContentDiv$$module$build$src$core$dropdowndiv()),addClass$$module$build$src$core$utils$dom(a, +"blocklyDropdownMenu"),this.getConstants().FIELD_DROPDOWN_COLOURED_DIV&&(b=b.getColour(),a=this.sourceBlock_.getColourTertiary(),setColour$$module$build$src$core$dropdowndiv(b,a)),showPositionedByField$$module$build$src$core$dropdowndiv(this,this.dropdownDispose_.bind(this)),getContentDiv$$module$build$src$core$dropdowndiv().style.height=`${this.menu_.getSize().height}px`,this.menu_.focus(),this.selectedMenuItem&&this.menu_.setHighlighted(this.selectedMenuItem),this.applyColour())}dropdownCreate(){const a= +this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;const b=new Menu$$module$build$src$core$menu;b.setRole(Role$$module$build$src$core$utils$aria.LISTBOX);this.menu_=b;const c=this.getOptions(!1);this.selectedMenuItem=null;for(let e=0;eb[1]===a)?a:(this.sourceBlock_&&console.warn("Cannot set the dropdown's value to an unavailable option. Block type: "+this.sourceBlock_.type+", Field name: "+this.name+", Value: "+a),null)}doValueUpdate_(a){super.doValueUpdate_(a); a=this.getOptions(!0);for(let b=0,c;c=a[b];b++)c[1]===this.value_&&(this.selectedOption=c)}applyColour(){const a=this.sourceBlock_;this.borderRect_&&(this.borderRect_.setAttribute("stroke",a.getColourTertiary()),this.menu_?this.borderRect_.setAttribute("fill",a.getColourTertiary()):this.borderRect_.setAttribute("fill","transparent"));a&&this.arrow&&(a.isShadow()?this.arrow.style.fill=a.getColourSecondary():this.arrow.style.fill=a.getColour())}render_(){this.getTextContent().nodeValue="";this.imageElement.style.display= -"none";const a=this.selectedOption&&this.selectedOption[0];a&&"object"===typeof a?this.renderSelectedImage(a):this.renderSelectedText();this.positionBorderRect_()}renderSelectedImage(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.imageElement.style.display="";this.imageElement.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",a.src);this.imageElement.setAttribute("height",String(a.height));this.imageElement.setAttribute("width", -String(a.width));const c=Number(a.height);a=Number(a.width);var d=!!this.borderRect_;const e=Math.max(d?this.getConstants().FIELD_DROPDOWN_BORDER_RECT_HEIGHT:0,c+FieldDropdown$$module$build$src$core$field_dropdown.IMAGE_Y_PADDING);d=d?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0;let f;f=this.svgArrow?this.positionSVGArrow(a+d,e/2-this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE/2):getFastTextWidth$$module$build$src$core$utils$dom(this.arrow,this.getConstants().FIELD_TEXT_FONTSIZE,this.getConstants().FIELD_TEXT_FONTWEIGHT, -this.getConstants().FIELD_TEXT_FONTFAMILY);this.size_.width=a+f+2*d;this.size_.height=e;let g=0;b.RTL?this.imageElement.setAttribute("x",`${d+f}`):(g=a+f,this.getTextElement().setAttribute("text-anchor","end"),this.imageElement.setAttribute("x",`${d}`));this.imageElement.setAttribute("y",String(e/2-c/2));this.positionTextElement_(g+d,a+f)}renderSelectedText(){this.getTextContent().nodeValue=this.getDisplayText_();var a=this.getTextElement();addClass$$module$build$src$core$utils$dom(a,"blocklyDropdownText"); -a.setAttribute("text-anchor","start");var b=!!this.borderRect_;a=Math.max(b?this.getConstants().FIELD_DROPDOWN_BORDER_RECT_HEIGHT:0,this.getConstants().FIELD_TEXT_HEIGHT);const c=getFastTextWidth$$module$build$src$core$utils$dom(this.getTextElement(),this.getConstants().FIELD_TEXT_FONTSIZE,this.getConstants().FIELD_TEXT_FONTWEIGHT,this.getConstants().FIELD_TEXT_FONTFAMILY);b=b?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0;let d=0;this.svgArrow&&(d=this.positionSVGArrow(c+b,a/2-this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE/ -2));this.size_.width=c+d+2*b;this.size_.height=a;this.positionTextElement_(b,c)}positionSVGArrow(a,b){if(!this.svgArrow)return 0;const c=this.getSourceBlock();if(!c)throw new UnattachedFieldError$$module$build$src$core$field;const d=this.borderRect_?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0,e=this.getConstants().FIELD_DROPDOWN_SVG_ARROW_PADDING,f=this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE;this.svgArrow.setAttribute("transform","translate("+(c.RTL?d:a+e)+","+b+")");return f+e}getText_(){if(!this.selectedOption)return null; -const a=this.selectedOption[0];return"object"===typeof a?a.alt:a}static fromJson(a){if(!a.options)throw Error("options are required for the dropdown field. The options property must be assigned an array of [humanReadableValue, languageNeutralValue] tuples.");return new this(a.options,void 0,a)}trimOptions(a){let b=!1;const c=a.map(([g,h])=>{if("string"===typeof g)return[replaceMessageReferences$$module$build$src$core$utils$parsing(g),h];b=!0;return[null!==g.alt?Object.assign({},g,{alt:replaceMessageReferences$$module$build$src$core$utils$parsing(g.alt)}): -Object.assign({},g),h]});if(b||2>a.length)return{options:c};var d=c.map(([g])=>g),e=shortestStringLength$$module$build$src$core$utils$string(d);a=commonWordPrefix$$module$build$src$core$utils$string(d,e);const f=commonWordSuffix$$module$build$src$core$utils$string(d,e);if(!a&&!f||e<=a+f)return{options:c};e=a?d[0].substring(0,a-1):void 0;d=f?d[0].substr(1-f):void 0;return{options:this.applyTrim(c,a,f),prefix:e,suffix:d}}applyTrim(a,b,c){return a.map(([d,e])=>[d.substring(b,d.length-c),e])}validateOptions(a){if(!Array.isArray(a))throw TypeError("FieldDropdown options must be an array."); -if(!a.length)throw TypeError("FieldDropdown options must not be an empty array.");let b=!1;for(let c=0;ca.width)return b;a=this.getWorkspaceViewRect(a);if(this.workspace.RTL){var c=this.anchor.x-b;c-this.size.widtha.right&&(b=-(a.right-this.anchor.x))}else{c=b+this.anchor.x;const d=c+this.size.width;ca.right&&(b=a.right-this.anchor.x-this.size.width)}return b}getOptimalRelativeTop(a){let b=-this.size.height/4;if(this.size.height>a.height)return b;const c=this.anchor.y+b,d=c+this.size.height;a=this.getWorkspaceViewRect(a);ca.bottom&&(b=a.bottom-this.anchor.y-this.size.height);return b}getWorkspaceViewRect(a){const b=a.top;let c=a.top+a.height,d=a.left;a=a.left+a.width;c-=this.getScrollbarThickness();this.workspace.RTL?d-=this.getScrollbarThickness():a-=this.getScrollbarThickness(); -return new Rect$$module$build$src$core$utils$rect(b,c,d,a)}getScrollbarThickness(){return Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness/this.workspace.scale}renderTail(){const a=[];var b=this.size.width/2,c=this.size.height/2,d=-this.relativeLeft,e=-this.relativeTop;if(b===d&&c===e)a.push("M "+b+","+c);else{e-=c;d-=b;this.workspace.RTL&&(d*=-1);var f=Math.sqrt(e*e+d*d),g=Math.acos(d/f);0>e&&(g=2*Math.PI-g);var h=g+Math.PI/2;h>2*Math.PI&&(h-=2*Math.PI);var k=Math.sin(h);const m=Math.cos(h); -let n=(this.size.width+this.size.height)/_a$$module$build$src$core$bubbles$bubble.TAIL_THICKNESS;n=Math.min(n,this.size.width,this.size.height)/4;h=1-_a$$module$build$src$core$bubbles$bubble.ANCHOR_RADIUS/f;d=b+h*d;e=c+h*e;h=b+n*m;const p=c+n*k;b-=n*m;c-=n*k;k=toRadians$$module$build$src$core$utils$math(this.workspace.RTL?-_a$$module$build$src$core$bubbles$bubble.TAIL_ANGLE:_a$$module$build$src$core$bubbles$bubble.TAIL_ANGLE);k=g+k;k>2*Math.PI&&(k-=2*Math.PI);g=Math.sin(k)*f/_a$$module$build$src$core$bubbles$bubble.TAIL_BEND; -f=Math.cos(k)*f/_a$$module$build$src$core$bubbles$bubble.TAIL_BEND;a.push("M"+h+","+p);a.push("C"+(h+f)+","+(p+g)+" "+d+","+e+" "+d+","+e);a.push("C"+d+","+e+" "+(b+f)+","+(c+g)+" "+b+","+c)}a.push("z");let l;null==(l=this.tail)||l.setAttribute("d",a.join(" "))}bringToFront(){let a;const b=null==(a=this.svgRoot)?void 0:a.parentNode;return this.svgRoot&&(null==b?void 0:b.lastChild)!==this.svgRoot?(null==b||b.appendChild(this.svgRoot),!0):!1}getRelativeToSurfaceXY(){return new Coordinate$$module$build$src$core$utils$coordinate(this.workspace.RTL? --this.relativeLeft+this.anchor.x-this.size.width:this.anchor.x+this.relativeLeft,this.anchor.y+this.relativeTop)}getSvgRoot(){return this.svgRoot}moveDuringDrag(a){this.moveTo(a.x,a.y);this.relativeLeft=this.workspace.RTL?this.anchor.x-a.x-this.size.width:a.x-this.anchor.x;this.relativeTop=a.y-this.anchor.y;this.renderTail()}setDragging(a){}setDeleteStyle(a){}isDeletable(){return!1}showContextMenu(a){}isMovable(){return!0}startDrag(){this.dragStrategy.startDrag()}drag(a){this.dragStrategy.drag(a)}endDrag(){this.dragStrategy.endDrag()}revertDrag(){this.dragStrategy.revertDrag()}select(){}unselect(){}}; -_a$$module$build$src$core$bubbles$bubble=Bubble$$module$build$src$core$bubbles$bubble;Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH=6;Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER=2*_a$$module$build$src$core$bubbles$bubble.BORDER_WIDTH;Bubble$$module$build$src$core$bubbles$bubble.MIN_SIZE=_a$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER;Bubble$$module$build$src$core$bubbles$bubble.TAIL_THICKNESS=1;Bubble$$module$build$src$core$bubbles$bubble.TAIL_ANGLE=20; -Bubble$$module$build$src$core$bubbles$bubble.TAIL_BEND=4;Bubble$$module$build$src$core$bubbles$bubble.ANCHOR_RADIUS=8;var module$build$src$core$bubbles$bubble={};module$build$src$core$bubbles$bubble.Bubble=Bubble$$module$build$src$core$bubbles$bubble;var MiniWorkspaceBubble$$module$build$src$core$bubbles$mini_workspace_bubble=class extends Bubble$$module$build$src$core$bubbles$bubble{constructor(a,b,c,d){super(b,c,d);this.workspace=b;this.anchor=c;this.ownerRect=d;this.autoLayout=!0;b=new Options$$module$build$src$core$options(a);this.validateWorkspaceOptions(b);this.svgDialog=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{x:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH,y:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH}, -this.contentContainer);a.parentWorkspace=this.workspace;this.miniWorkspace=this.newWorkspaceSvg(new Options$$module$build$src$core$options(a));this.miniWorkspace.internalIsMutator=!0;a=this.miniWorkspace.createDom("blocklyMutatorBackground");this.svgDialog.appendChild(a);b.languageTree&&(a.insertBefore(this.miniWorkspace.addFlyout(Svg$$module$build$src$core$utils$svg.G),this.miniWorkspace.getCanvas()),a=this.miniWorkspace.getFlyout(),null==a||a.init(this.miniWorkspace),null==a||a.show(b.languageTree)); -this.miniWorkspace.addChangeListener(this.onWorkspaceChange.bind(this));let e,f;null==(e=this.miniWorkspace.getFlyout())||null==(f=e.getWorkspace())||f.addChangeListener(this.onWorkspaceChange.bind(this));this.updateBubbleSize()}dispose(){this.miniWorkspace.dispose();super.dispose()}getWorkspace(){return this.miniWorkspace}addWorkspaceChangeListener(a){this.miniWorkspace.addChangeListener(a)}validateWorkspaceOptions(a){if(a.hasCategories)throw Error("The miniworkspace bubble does not support toolboxes with categories"); +"none";const a=this.selectedOption&&this.selectedOption[0];isImageProperties$$module$build$src$core$field_dropdown(a)?this.renderSelectedImage(a):this.renderSelectedText();this.positionBorderRect_()}renderSelectedImage(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.imageElement.style.display="";this.imageElement.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",a.src);this.imageElement.setAttribute("height",String(a.height)); +this.imageElement.setAttribute("width",String(a.width));const c=Number(a.height);a=Number(a.width);var d=!!this.borderRect_;const e=Math.max(d?this.getConstants().FIELD_DROPDOWN_BORDER_RECT_HEIGHT:0,c+FieldDropdown$$module$build$src$core$field_dropdown.IMAGE_Y_PADDING);d=d?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0;let f;f=this.svgArrow?this.positionSVGArrow(a+d,e/2-this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE/2):getTextWidth$$module$build$src$core$utils$dom(this.arrow);this.size_=new Size$$module$build$src$core$utils$size(a+ +f+d*2,e);let g=0;b.RTL?this.imageElement.setAttribute("x",`${d+f}`):(g=a+f,this.getTextElement().setAttribute("text-anchor","end"),this.imageElement.setAttribute("x",`${d}`));this.imageElement.setAttribute("y",String(e/2-c/2));this.positionTextElement_(g+d,a+f)}renderSelectedText(){this.getTextContent().nodeValue=this.getDisplayText_();var a=this.getTextElement();addClass$$module$build$src$core$utils$dom(a,"blocklyDropdownText");a.setAttribute("text-anchor","start");var b=!!this.borderRect_;a=Math.max(b? +this.getConstants().FIELD_DROPDOWN_BORDER_RECT_HEIGHT:0,this.getConstants().FIELD_TEXT_HEIGHT);const c=getTextWidth$$module$build$src$core$utils$dom(this.getTextElement());b=b?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0;let d=0;this.svgArrow&&(d=this.positionSVGArrow(c+b,a/2-this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE/2));this.size_=new Size$$module$build$src$core$utils$size(c+d+b*2,a);this.positionTextElement_(b,c)}positionSVGArrow(a,b){if(!this.svgArrow)return 0;const c=this.getSourceBlock(); +if(!c)throw new UnattachedFieldError$$module$build$src$core$field;const d=this.borderRect_?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0,e=this.getConstants().FIELD_DROPDOWN_SVG_ARROW_PADDING,f=this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE;this.svgArrow.setAttribute("transform","translate("+(c.RTL?d:a+e)+","+b+")");return f+e}getText_(){if(!this.selectedOption)return null;const a=this.selectedOption[0];if(isImageProperties$$module$build$src$core$field_dropdown(a))return a.alt;if(typeof HTMLElement!== +"undefined"&&a instanceof HTMLElement){let b,c;return(c=(b=a.title)!=null?b:a.ariaLabel)!=null?c:a.innerText}if(typeof a==="string")return a;console.warn("Can't get text for existing dropdown option. If you're using HTMLElement dropdown options in node, ensure you're using jsdom-global or similar.");return null}static fromJson(a){if(!a.options)throw Error("options are required for the dropdown field. The options property must be assigned an array of [humanReadableValue, languageNeutralValue] tuples."); +return new this(a.options,void 0,a)}trimOptions(a){let b=!1;const c=a.map(g=>{if(g===FieldDropdown$$module$build$src$core$field_dropdown.SEPARATOR)return b=!0,g;const [h,k]=g;if(typeof h==="string")return[replaceMessageReferences$$module$build$src$core$utils$parsing(h),k];b=!0;return[isImageProperties$$module$build$src$core$field_dropdown(h)?Object.assign({},h,{alt:replaceMessageReferences$$module$build$src$core$utils$parsing(h.alt)}):h,k]});if(b||a.length<2)return{options:c};var d=c.map(([g])=>g), +e=shortestStringLength$$module$build$src$core$utils$string(d);a=commonWordPrefix$$module$build$src$core$utils$string(d,e);const f=commonWordSuffix$$module$build$src$core$utils$string(d,e);if(!a&&!f||e<=a+f)return{options:c};e=a?d[0].substring(0,a-1):void 0;d=f?d[0].substr(1-f):void 0;return{options:this.applyTrim(c,a,f),prefix:e,suffix:d}}applyTrim(a,b,c){return a.map(([d,e])=>[d.substring(b,d.length-c),e])}validateOptions(a){if(!Array.isArray(a))throw TypeError("FieldDropdown options must be an array."); +if(!a.length)throw TypeError("FieldDropdown options must not be an empty array.");let b=!1;for(let c=0;c0&&!!a.snap;return b}static parseThemeOptions(a){a=a.theme||Classic$$module$build$src$core$theme$classic;return typeof a==="string"?getObject$$module$build$src$core$registry(Type$$module$build$src$core$registry.THEME,a):a instanceof Theme$$module$build$src$core$theme?a:Theme$$module$build$src$core$theme.defineTheme(a.name||"builtin"+getNextUniqueId$$module$build$src$core$utils$idgenerator(),a)}},module$build$src$core$options= +{};module$build$src$core$options.Options=Options$$module$build$src$core$options;var BubbleDragStrategy$$module$build$src$core$dragging$bubble_drag_strategy=class{constructor(a,b){this.bubble=a;this.workspace=b;this.startLoc=null}isMovable(){return!0}startDrag(){this.startLoc=this.bubble.getRelativeToSurfaceXY();this.workspace.setResizesEnabled(!1);let a;(a=this.workspace.getLayerManager())==null||a.moveToDragLayer(this.bubble);this.bubble.setDragging&&this.bubble.setDragging(!0)}drag(a){this.bubble.moveDuringDrag(a)}endDrag(){this.workspace.setResizesEnabled(!0);let a;(a=this.workspace.getLayerManager())== +null||a.moveOffDragLayer(this.bubble,BUBBLE$$module$build$src$core$layers);this.bubble.setDragging(!1)}revertDrag(){this.startLoc&&this.bubble.moveDuringDrag(this.startLoc)}},module$build$src$core$dragging$bubble_drag_strategy={};module$build$src$core$dragging$bubble_drag_strategy.BubbleDragStrategy=BubbleDragStrategy$$module$build$src$core$dragging$bubble_drag_strategy;var _a$$module$build$src$core$bubbles$bubble,Bubble$$module$build$src$core$bubbles$bubble=class{constructor(a,b,c,d,e){this.workspace=a;this.anchor=b;this.ownerRect=c;this.owner=e;this.size=new Size$$module$build$src$core$utils$size(0,0);this.colour="#ffffff";this.disposed=!1;this.relativeLeft=this.relativeTop=0;this.dragStrategy=new BubbleDragStrategy$$module$build$src$core$dragging$bubble_drag_strategy(this,this.workspace);this.id=getNextUniqueId$$module$build$src$core$utils$idgenerator();this.svgRoot= +createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyBubble"},a.getBubbleCanvas());a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyEmboss"},this.svgRoot);this.tail=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyBubbleTail"},a);this.background=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT, +{"class":"blocklyDraggable",x:0,y:0,rx:_a$$module$build$src$core$bubbles$bubble.BORDER_WIDTH,ry:_a$$module$build$src$core$bubbles$bubble.BORDER_WIDTH},a);this.contentContainer=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},this.svgRoot);this.focusableElement=d!=null?d:this.svgRoot;this.focusableElement.setAttribute("id",this.id);conditionalBind$$module$build$src$core$browser_events(this.background,"pointerdown",this,this.onMouseDown);conditionalBind$$module$build$src$core$browser_events(this.focusableElement, +"keydown",this,this.onKeyDown)}dispose(){removeNode$$module$build$src$core$utils$dom(this.svgRoot);this.disposed=!0}setAnchorLocation(a,b=!1){this.anchor=a;b?this.positionByRect(this.ownerRect):this.positionRelativeToAnchor();this.renderTail()}setPositionRelativeToAnchor(a,b){this.relativeLeft=a;this.relativeTop=b;this.positionRelativeToAnchor();this.renderTail()}getSize(){return this.size}setSize(a,b=!1){a.width=Math.max(a.width,_a$$module$build$src$core$bubbles$bubble.MIN_SIZE);a.height=Math.max(a.height, +_a$$module$build$src$core$bubbles$bubble.MIN_SIZE);this.size=a;this.background.setAttribute("width",`${a.width}`);this.background.setAttribute("height",`${a.height}`);b?this.positionByRect(this.ownerRect):this.positionRelativeToAnchor();this.renderTail()}getColour(){return this.colour}setColour(a){this.colour=a;this.tail.setAttribute("fill",a);this.background.setAttribute("fill",a)}onMouseDown(a){let b;(b=this.workspace.getGesture(a))==null||b.handleBubbleStart(a,this);$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this)}onKeyDown(a){a.key=== +"Escape"&&this.owner&&(this.owner.setBubbleVisible(!1),$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this.owner))}positionRelativeToAnchor(){let a=this.anchor.x;a=this.workspace.RTL?a-(this.relativeLeft+this.size.width):a+this.relativeLeft;this.moveTo(a,this.relativeTop+this.anchor.y)}moveTo(a,b){this.svgRoot.setAttribute("transform",`translate(${a}, ${b})`)}positionByRect(a=new Rect$$module$build$src$core$utils$rect(0,0,0,0)){var b=this.workspace.getMetricsManager().getViewMetrics(!0), +c=this.getOptimalRelativeLeft(b),d=this.getOptimalRelativeTop(b);const e={x:c,y:-this.size.height-this.workspace.getRenderer().getConstants().MIN_BLOCK_HEIGHT},f={x:-this.size.width-30,y:d};d={x:a.getWidth(),y:d};var g={x:c,y:a.getHeight()};c=a.getWidth()a.width)return b;a=this.getWorkspaceViewRect(a);if(this.workspace.RTL){var c=this.anchor.x-b;c-this.size.widtha.right&&(b=-(a.right-this.anchor.x))}else{c=b+this.anchor.x;const d=c+this.size.width;ca.right&&(b=a.right-this.anchor.x-this.size.width)}return b}getOptimalRelativeTop(a){let b=-this.size.height/4;if(this.size.height>a.height)return b;const c=this.anchor.y+b,d=c+this.size.height;a=this.getWorkspaceViewRect(a); +ca.bottom&&(b=a.bottom-this.anchor.y-this.size.height);return b}getWorkspaceViewRect(a){const b=a.top;let c=a.top+a.height,d=a.left;a=a.left+a.width;c-=this.getScrollbarThickness();this.workspace.RTL?d-=this.getScrollbarThickness():a-=this.getScrollbarThickness();return new Rect$$module$build$src$core$utils$rect(b,c,d,a)}getScrollbarThickness(){return Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness/this.workspace.scale}renderTail(){const a=[];var b=this.size.width/ +2,c=this.size.height/2,d=-this.relativeLeft,e=-this.relativeTop;if(b===d&&c===e)a.push("M "+b+","+c);else{e-=c;d-=b;this.workspace.RTL&&(d*=-1);var f=Math.sqrt(e*e+d*d),g=Math.acos(d/f);e<0&&(g=2*Math.PI-g);var h=g+Math.PI/2;h>Math.PI*2&&(h-=Math.PI*2);var k=Math.sin(h);const m=Math.cos(h);let n=(this.size.width+this.size.height)/_a$$module$build$src$core$bubbles$bubble.TAIL_THICKNESS;n=Math.min(n,this.size.width,this.size.height)/4;h=1-_a$$module$build$src$core$bubbles$bubble.ANCHOR_RADIUS/f;d=b+ +h*d;e=c+h*e;h=b+n*m;const p=c+n*k;b-=n*m;c-=n*k;k=toRadians$$module$build$src$core$utils$math(this.workspace.RTL?-_a$$module$build$src$core$bubbles$bubble.TAIL_ANGLE:_a$$module$build$src$core$bubbles$bubble.TAIL_ANGLE);k=g+k;k>Math.PI*2&&(k-=Math.PI*2);g=Math.sin(k)*f/_a$$module$build$src$core$bubbles$bubble.TAIL_BEND;f=Math.cos(k)*f/_a$$module$build$src$core$bubbles$bubble.TAIL_BEND;a.push("M"+h+","+p);a.push("C"+(h+f)+","+(p+g)+" "+d+","+e+" "+d+","+e);a.push("C"+d+","+e+" "+(b+f)+","+(c+g)+" "+ +b+","+c)}a.push("z");let l;(l=this.tail)==null||l.setAttribute("d",a.join(" "))}bringToFront(){let a;const b=(a=this.svgRoot)==null?void 0:a.parentNode;return this.svgRoot&&(b==null?void 0:b.lastChild)!==this.svgRoot?(b==null||b.appendChild(this.svgRoot),!0):!1}getRelativeToSurfaceXY(){return new Coordinate$$module$build$src$core$utils$coordinate(this.workspace.RTL?-this.relativeLeft+this.anchor.x-this.size.width:this.anchor.x+this.relativeLeft,this.anchor.y+this.relativeTop)}getSvgRoot(){return this.svgRoot}moveDuringDrag(a){this.moveTo(a.x, +a.y);this.relativeLeft=this.workspace.RTL?this.anchor.x-a.x-this.size.width:a.x-this.anchor.x;this.relativeTop=a.y-this.anchor.y;this.renderTail()}setDragging(a){}setDeleteStyle(a){}isDeletable(){return!1}showContextMenu(a){}isMovable(){return!0}startDrag(){this.dragStrategy.startDrag()}drag(a){this.dragStrategy.drag(a)}endDrag(){this.dragStrategy.endDrag()}revertDrag(){this.dragStrategy.revertDrag()}select(){fireSelectedEvent$$module$build$src$core$common(this)}unselect(){fireSelectedEvent$$module$build$src$core$common(null)}getFocusableElement(){return this.focusableElement}getFocusableTree(){return this.workspace}onNodeFocus(){this.select(); +this.bringToFront();var a=this.getRelativeToSurfaceXY();const b=this.getSize();a=new Rect$$module$build$src$core$utils$rect(a.y,a.y+b.height,a.x,a.x+b.width);this.workspace.scrollBoundsIntoView(a)}onNodeBlur(){this.unselect()}canBeFocused(){return!0}getOwner(){return this.owner}};_a$$module$build$src$core$bubbles$bubble=Bubble$$module$build$src$core$bubbles$bubble;Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH=6; +Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER=_a$$module$build$src$core$bubbles$bubble.BORDER_WIDTH*2;Bubble$$module$build$src$core$bubbles$bubble.MIN_SIZE=_a$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER;Bubble$$module$build$src$core$bubbles$bubble.TAIL_THICKNESS=1;Bubble$$module$build$src$core$bubbles$bubble.TAIL_ANGLE=20;Bubble$$module$build$src$core$bubbles$bubble.TAIL_BEND=4;Bubble$$module$build$src$core$bubbles$bubble.ANCHOR_RADIUS=8; +var module$build$src$core$bubbles$bubble={};module$build$src$core$bubbles$bubble.Bubble=Bubble$$module$build$src$core$bubbles$bubble;var MiniWorkspaceBubble$$module$build$src$core$bubbles$mini_workspace_bubble=class extends Bubble$$module$build$src$core$bubbles$bubble{constructor(a,b,c,d){super(b,c,d);this.workspace=b;this.anchor=c;this.ownerRect=d;this.autoLayout=!0;b=new Options$$module$build$src$core$options(a);this.validateWorkspaceOptions(b);this.svgDialog=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{x:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH,y:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH}, +this.contentContainer);a.parentWorkspace=this.workspace;this.miniWorkspace=this.newWorkspaceSvg(new Options$$module$build$src$core$options(a));this.miniWorkspace.internalIsMutator=!0;a=this.miniWorkspace.createDom("blocklyMutatorBackground");this.svgDialog.appendChild(a);b.languageTree&&(a.insertBefore(this.miniWorkspace.addFlyout(Svg$$module$build$src$core$utils$svg.G),this.miniWorkspace.getCanvas()),a=this.miniWorkspace.getFlyout(),a==null||a.init(this.miniWorkspace),a==null||a.show(b.languageTree)); +addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyMiniWorkspaceBubble");this.miniWorkspace.addChangeListener(this.onWorkspaceChange.bind(this));let e,f;(e=this.miniWorkspace.getFlyout())==null||(f=e.getWorkspace())==null||f.addChangeListener(this.onWorkspaceChange.bind(this));this.updateBubbleSize()}dispose(){this.miniWorkspace.dispose();super.dispose()}getWorkspace(){return this.miniWorkspace}addWorkspaceChangeListener(a){this.miniWorkspace.addChangeListener(a)}validateWorkspaceOptions(a){if(a.hasCategories)throw Error("The miniworkspace bubble does not support toolboxes with categories"); if(a.hasTrashcan)throw Error("The miniworkspace bubble does not support trashcans");if(a.zoomOptions.controls||a.zoomOptions.wheel||a.zoomOptions.pinch)throw Error("The miniworkspace bubble does not support zooming");if(a.moveOptions.scrollbars||a.moveOptions.wheel||a.moveOptions.drag)throw Error("The miniworkspace bubble does not scrolling/moving the workspace");if(a.horizontalLayout)throw Error("The miniworkspace bubble does not support horizontal layouts");}onWorkspaceChange(){this.bumpBlocksIntoBounds(); -this.updateBubbleSize()}bumpBlocksIntoBounds(){if(!this.miniWorkspace.isDragging())for(const a of this.miniWorkspace.getTopBlocks(!1)){const b=a.getRelativeToSurfaceXY();20>b.y&&a.moveBy(0,20-b.y);if(a.RTL){let c=-20;const d=this.miniWorkspace.getFlyout();d&&(c-=d.getWidth());b.x>c&&a.moveBy(c-b.x,0)}else 20>b.x&&a.moveBy(20-b.x,0)}}updateBubbleSize(){if(!this.miniWorkspace.isDragging()){var a=this.getSize(),b=this.calculateWorkspaceSize();Math.abs(a.width-b.width)c&&a.moveBy(c-b.x,0)}else b.x<20&&a.moveBy(20-b.x,0)}}updateBubbleSize(){if(!this.miniWorkspace.isDragging()||this.miniWorkspace.keyboardMoveInProgress){this.autoLayout&&(this.autoLayout= +!this.miniWorkspace.keyboardMoveInProgress);var a=this.getSize(),b=this.calculateWorkspaceSize();Math.abs(a.width-b.width)({kind:"block",type:c}))});return b}getAnchorLocation(){const a=SIZE$$module$build$src$core$icons$mutator_icon/ +this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE,{"class":"blocklyIconShape",r:"2.7",cx:"8",cy:"8"},this.svgRoot),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyMutatorIcon"))}dispose(){super.dispose();let a;(a=this.miniWorkspaceBubble)==null||a.dispose()}getWeight(){return $.MutatorIcon$$module$build$src$core$icons$mutator_icon.WEIGHT}getSize(){return new Size$$module$build$src$core$utils$size(SIZE$$module$build$src$core$icons$mutator_icon, +SIZE$$module$build$src$core$icons$mutator_icon)}applyColour(){super.applyColour();let a;(a=this.miniWorkspaceBubble)==null||a.setColour(this.sourceBlock.getColour());let b;(b=this.miniWorkspaceBubble)==null||b.updateBlockStyles()}updateCollapsed(){super.updateCollapsed();this.sourceBlock.isCollapsed()&&this.setBubbleVisible(!1)}onLocationChange(a){super.onLocationChange(a);let b;(b=this.miniWorkspaceBubble)==null||b.setAnchorLocation(this.getAnchorLocation())}onClick(){super.onClick();this.sourceBlock.isEditable()&& +this.setBubbleVisible(!this.bubbleIsVisible())}isClickableInFlyout(){return!1}bubbleIsVisible(){return!!this.miniWorkspaceBubble}setBubbleVisible(a){const b=this;return(0,$jscomp.asyncExecutePromiseGeneratorFunction)(function*(){if(b.bubbleIsVisible()!==a){yield finishQueuedRenders$$module$build$src$core$render_management();if(a){b.miniWorkspaceBubble=new MiniWorkspaceBubble$$module$build$src$core$bubbles$mini_workspace_bubble(b.getMiniWorkspaceConfig(),b.sourceBlock.workspace,b.getAnchorLocation(), +b.getBubbleOwnerRect());b.applyColour();b.createRootBlock();b.addSaveConnectionsListener();let c;(c=b.miniWorkspaceBubble)==null||c.addWorkspaceChangeListener(b.createMiniWorkspaceChangeListener())}else{let c;(c=b.miniWorkspaceBubble)==null||c.dispose();b.miniWorkspaceBubble=null;b.saveConnectionsListener&&b.sourceBlock.workspace.removeChangeListener(b.saveConnectionsListener);b.saveConnectionsListener=null}fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BUBBLE_OPEN))(b.sourceBlock, +a,"mutator"))}})}getBubble(){return this.miniWorkspaceBubble}getMiniWorkspaceConfig(){let a;const b={disable:!1,media:this.sourceBlock.workspace.options.pathToMedia,rtl:this.sourceBlock.RTL,renderer:this.sourceBlock.workspace.options.renderer,rendererOverrides:(a=this.sourceBlock.workspace.options.rendererOverrides)!=null?a:void 0};this.flyoutBlockTypes.length&&(b.toolbox={kind:"flyoutToolbox",contents:this.flyoutBlockTypes.map(c=>({kind:"block",type:c}))});return b}getAnchorLocation(){const a=SIZE$$module$build$src$core$icons$mutator_icon/ 2;return Coordinate$$module$build$src$core$utils$coordinate.sum(this.workspaceLocation,new Coordinate$$module$build$src$core$utils$coordinate(a,a))}getBubbleOwnerRect(){const a=this.sourceBlock.getSvgRoot().getBBox();return new Rect$$module$build$src$core$utils$rect(a.y,a.y+a.height,a.x,a.x+a.width)}createRootBlock(){if(!this.sourceBlock.decompose)throw Error("Blocks with mutator icons must include a decompose method");this.rootBlock=this.sourceBlock.decompose(this.miniWorkspaceBubble.getWorkspace()); -for(var a of this.rootBlock.getDescendants(!1))a.queueRender();this.rootBlock.setMovable(!1);this.rootBlock.setDeletable(!1);let b,c,d,e;a=null!=(e=null==(b=this.miniWorkspaceBubble)?void 0:null==(c=b.getWorkspace())?void 0:null==(d=c.getFlyout())?void 0:d.getWidth())?e:0;this.rootBlock.moveBy(this.rootBlock.RTL?-(a+WORKSPACE_MARGIN$$module$build$src$core$icons$mutator_icon):WORKSPACE_MARGIN$$module$build$src$core$icons$mutator_icon,WORKSPACE_MARGIN$$module$build$src$core$icons$mutator_icon)}addSaveConnectionsListener(){this.sourceBlock.saveConnections&& +for(var a of this.rootBlock.getDescendants(!1))a.queueRender();this.rootBlock.setMovable(!1);this.rootBlock.setDeletable(!1);let b,c,d,e;a=(e=(b=this.miniWorkspaceBubble)==null?void 0:(c=b.getWorkspace())==null?void 0:(d=c.getFlyout())==null?void 0:d.getWidth())!=null?e:0;this.rootBlock.moveBy(this.rootBlock.RTL?-(a+WORKSPACE_MARGIN$$module$build$src$core$icons$mutator_icon):WORKSPACE_MARGIN$$module$build$src$core$icons$mutator_icon,WORKSPACE_MARGIN$$module$build$src$core$icons$mutator_icon)}addSaveConnectionsListener(){this.sourceBlock.saveConnections&& this.rootBlock&&(this.saveConnectionsListener=()=>{this.sourceBlock.saveConnections&&this.rootBlock&&this.sourceBlock.saveConnections(this.rootBlock)},this.saveConnectionsListener(),this.sourceBlock.workspace.addChangeListener(this.saveConnectionsListener))}createMiniWorkspaceChangeListener(){return a=>{$.MutatorIcon$$module$build$src$core$icons$mutator_icon.isIgnorableMutatorEvent(a)||this.updateWorkspacePid||(this.updateWorkspacePid=setTimeout(()=>{this.updateWorkspacePid=null;this.recomposeSourceBlock()}, -0))}}static isIgnorableMutatorEvent(a){return a.isUiEvent||isBlockCreate$$module$build$src$core$events$predicates(a)||isBlockChange$$module$build$src$core$events$predicates(a)&&"disabled"===a.element}recomposeSourceBlock(){if(this.rootBlock){if(!this.sourceBlock.compose)throw Error("Blocks with mutator icons must include a compose method");var a=$.getGroup$$module$build$src$core$events$utils();a||$.setGroup$$module$build$src$core$events$utils(!0);var b=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(this.sourceBlock); -this.sourceBlock.compose(this.rootBlock);var c=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(this.sourceBlock);b!==c&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock,"mutation",null,b,c));$.setGroup$$module$build$src$core$events$utils(a)}}getWorkspace(){let a;return null==(a=this.miniWorkspaceBubble)?void 0:a.getWorkspace()}}; +0))}}static isIgnorableMutatorEvent(a){return a.isUiEvent||isBlockCreate$$module$build$src$core$events$predicates(a)||isBlockChange$$module$build$src$core$events$predicates(a)&&a.element==="disabled"}recomposeSourceBlock(){if(this.rootBlock){if(!this.sourceBlock.compose)throw Error("Blocks with mutator icons must include a compose method");var a=$.getGroup$$module$build$src$core$events$utils();a||$.setGroup$$module$build$src$core$events$utils(!0);var b=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(this.sourceBlock); +this.sourceBlock.compose(this.rootBlock);var c=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(this.sourceBlock);b!==c&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock,"mutation",null,b,c));$.setGroup$$module$build$src$core$events$utils(a)}}getWorkspace(){let a;return(a=this.miniWorkspaceBubble)==null?void 0:a.getWorkspace()}}; $.MutatorIcon$$module$build$src$core$icons$mutator_icon.TYPE=IconType$$module$build$src$core$icons$icon_types.MUTATOR;$.MutatorIcon$$module$build$src$core$icons$mutator_icon.WEIGHT=1;var module$build$src$core$icons$mutator_icon={};module$build$src$core$icons$mutator_icon.MutatorIcon=$.MutatorIcon$$module$build$src$core$icons$mutator_icon;var allExtensions$$module$build$src$core$extensions=Object.create(null),TEST_ONLY$$module$build$src$core$extensions={allExtensions:allExtensions$$module$build$src$core$extensions};$.register$$module$build$src$core$extensions("parent_tooltip_when_inline",extensionParentTooltip$$module$build$src$core$extensions);var module$build$src$core$extensions={TEST_ONLY:TEST_ONLY$$module$build$src$core$extensions};module$build$src$core$extensions.apply=apply$$module$build$src$core$extensions; module$build$src$core$extensions.buildTooltipForDropdown=$.buildTooltipForDropdown$$module$build$src$core$extensions;module$build$src$core$extensions.buildTooltipWithFieldText=$.buildTooltipWithFieldText$$module$build$src$core$extensions;module$build$src$core$extensions.isRegistered=isRegistered$$module$build$src$core$extensions;module$build$src$core$extensions.register=$.register$$module$build$src$core$extensions;module$build$src$core$extensions.registerMixin=$.registerMixin$$module$build$src$core$extensions; module$build$src$core$extensions.registerMutator=$.registerMutator$$module$build$src$core$extensions;module$build$src$core$extensions.runAfterPageLoad=runAfterPageLoad$$module$build$src$core$extensions;module$build$src$core$extensions.unregister=unregister$$module$build$src$core$extensions;var KeyCodes$$module$build$src$core$utils$keycodes; @@ -837,296 +915,413 @@ module$build$src$core$extensions.registerMutator=$.registerMutator$$module$build a[a.A=65]="A";a[a.B=66]="B";a[a.C=67]="C";a[a.D=68]="D";a[a.E=69]="E";a[a.F=70]="F";a[a.G=71]="G";a[a.H=72]="H";a[a.I=73]="I";a[a.J=74]="J";a[a.K=75]="K";a[a.L=76]="L";a[a.M=77]="M";a[a.N=78]="N";a[a.O=79]="O";a[a.P=80]="P";a[a.Q=81]="Q";a[a.R=82]="R";a[a.S=83]="S";a[a.T=84]="T";a[a.U=85]="U";a[a.V=86]="V";a[a.W=87]="W";a[a.X=88]="X";a[a.Y=89]="Y";a[a.Z=90]="Z";a[a.META=91]="META";a[a.WIN_KEY_RIGHT=92]="WIN_KEY_RIGHT";a[a.CONTEXT_MENU=93]="CONTEXT_MENU";a[a.NUM_ZERO=96]="NUM_ZERO";a[a.NUM_ONE=97]= "NUM_ONE";a[a.NUM_TWO=98]="NUM_TWO";a[a.NUM_THREE=99]="NUM_THREE";a[a.NUM_FOUR=100]="NUM_FOUR";a[a.NUM_FIVE=101]="NUM_FIVE";a[a.NUM_SIX=102]="NUM_SIX";a[a.NUM_SEVEN=103]="NUM_SEVEN";a[a.NUM_EIGHT=104]="NUM_EIGHT";a[a.NUM_NINE=105]="NUM_NINE";a[a.NUM_MULTIPLY=106]="NUM_MULTIPLY";a[a.NUM_PLUS=107]="NUM_PLUS";a[a.NUM_MINUS=109]="NUM_MINUS";a[a.NUM_PERIOD=110]="NUM_PERIOD";a[a.NUM_DIVISION=111]="NUM_DIVISION";a[a.F1=112]="F1";a[a.F2=113]="F2";a[a.F3=114]="F3";a[a.F4=115]="F4";a[a.F5=116]="F5";a[a.F6= 117]="F6";a[a.F7=118]="F7";a[a.F8=119]="F8";a[a.F9=120]="F9";a[a.F10=121]="F10";a[a.F11=122]="F11";a[a.F12=123]="F12";a[a.NUMLOCK=144]="NUMLOCK";a[a.SCROLL_LOCK=145]="SCROLL_LOCK";a[a.FIRST_MEDIA_KEY=166]="FIRST_MEDIA_KEY";a[a.LAST_MEDIA_KEY=183]="LAST_MEDIA_KEY";a[a.SEMICOLON=186]="SEMICOLON";a[a.DASH=189]="DASH";a[a.EQUALS=187]="EQUALS";a[a.COMMA=188]="COMMA";a[a.PERIOD=190]="PERIOD";a[a.SLASH=191]="SLASH";a[a.APOSTROPHE=192]="APOSTROPHE";a[a.TILDE=192]="TILDE";a[a.SINGLE_QUOTE=222]="SINGLE_QUOTE"; -a[a.OPEN_SQUARE_BRACKET=219]="OPEN_SQUARE_BRACKET";a[a.BACKSLASH=220]="BACKSLASH";a[a.CLOSE_SQUARE_BRACKET=221]="CLOSE_SQUARE_BRACKET";a[a.WIN_KEY=224]="WIN_KEY";a[a.MAC_FF_META=224]="MAC_FF_META";a[a.MAC_WK_CMD_LEFT=91]="MAC_WK_CMD_LEFT";a[a.MAC_WK_CMD_RIGHT=93]="MAC_WK_CMD_RIGHT";a[a.WIN_IME=229]="WIN_IME";a[a.VK_NONAME=252]="VK_NONAME";a[a.PHANTOM=255]="PHANTOM"})(KeyCodes$$module$build$src$core$utils$keycodes||(KeyCodes$$module$build$src$core$utils$keycodes={})); -var module$build$src$core$utils$keycodes={};module$build$src$core$utils$keycodes.KeyCodes=KeyCodes$$module$build$src$core$utils$keycodes;var module$build$src$core$utils$svg_paths={};module$build$src$core$utils$svg_paths.arc=arc$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.curve=curve$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.line=line$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.lineOnAxis=lineOnAxis$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.lineTo=lineTo$$module$build$src$core$utils$svg_paths; +a[a.OPEN_SQUARE_BRACKET=219]="OPEN_SQUARE_BRACKET";a[a.BACKSLASH=220]="BACKSLASH";a[a.CLOSE_SQUARE_BRACKET=221]="CLOSE_SQUARE_BRACKET";a[a.WIN_KEY=224]="WIN_KEY";a[a.MAC_FF_META=224]="MAC_FF_META";a[a.MAC_WK_CMD_LEFT=91]="MAC_WK_CMD_LEFT";a[a.MAC_WK_CMD_RIGHT=93]="MAC_WK_CMD_RIGHT";a[a.WIN_IME=229]="WIN_IME";a[a.VK_NONAME=252]="VK_NONAME";a[a.PHANTOM=255]="PHANTOM";a[a.CTRL_CMD=MAC$$module$build$src$core$utils$useragent||IPHONE$$module$build$src$core$utils$useragent||IPAD$$module$build$src$core$utils$useragent? +a.MAC_WK_CMD_LEFT:a.CTRL]="CTRL_CMD"})(KeyCodes$$module$build$src$core$utils$keycodes||(KeyCodes$$module$build$src$core$utils$keycodes={}));var module$build$src$core$utils$keycodes={};module$build$src$core$utils$keycodes.KeyCodes=KeyCodes$$module$build$src$core$utils$keycodes;var module$build$src$core$utils$svg_paths={};module$build$src$core$utils$svg_paths.arc=arc$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.curve=curve$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.line=line$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.lineOnAxis=lineOnAxis$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.lineTo=lineTo$$module$build$src$core$utils$svg_paths; module$build$src$core$utils$svg_paths.moveBy=moveBy$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.moveTo=moveTo$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.point=point$$module$build$src$core$utils$svg_paths;var module$build$src$core$utils={};module$build$src$core$utils.Coordinate=Coordinate$$module$build$src$core$utils$coordinate;module$build$src$core$utils.KeyCodes=KeyCodes$$module$build$src$core$utils$keycodes;module$build$src$core$utils.Rect=Rect$$module$build$src$core$utils$rect;module$build$src$core$utils.Size=Size$$module$build$src$core$utils$size;module$build$src$core$utils.Svg=Svg$$module$build$src$core$utils$svg;module$build$src$core$utils.aria=module$build$src$core$utils$aria; module$build$src$core$utils.array=module$build$src$core$utils$array;module$build$src$core$utils.browserEvents=module$build$src$core$browser_events;module$build$src$core$utils.colour=module$build$src$core$utils$colour;module$build$src$core$utils.deprecation=module$build$src$core$utils$deprecation;module$build$src$core$utils.dom=module$build$src$core$utils$dom;module$build$src$core$utils.extensions=module$build$src$core$extensions;module$build$src$core$utils.idGenerator=module$build$src$core$utils$idgenerator; module$build$src$core$utils.math=module$build$src$core$utils$math;module$build$src$core$utils.object=module$build$src$core$utils$object;module$build$src$core$utils.parsing=module$build$src$core$utils$parsing;module$build$src$core$utils.string=module$build$src$core$utils$string;module$build$src$core$utils.style=module$build$src$core$utils$style;module$build$src$core$utils.svgMath=module$build$src$core$utils$svg_math;module$build$src$core$utils.svgPaths=module$build$src$core$utils$svg_paths; -module$build$src$core$utils.toolbox=module$build$src$core$utils$toolbox;module$build$src$core$utils.userAgent=module$build$src$core$utils$useragent;module$build$src$core$utils.xml=module$build$src$core$utils$xml;var TextInputBubble$$module$build$src$core$bubbles$textinput_bubble=class extends Bubble$$module$build$src$core$bubbles$bubble{constructor(a,b,c){super(a,b,c);this.workspace=a;this.anchor=b;this.ownerRect=c;this.resizePointerMoveListener=this.resizePointerUpListener=null;this.textChangeListeners=[];this.sizeChangeListeners=[];this.text="";this.DEFAULT_SIZE=new Size$$module$build$src$core$utils$size(160+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER,80+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER); -this.MIN_SIZE=new Size$$module$build$src$core$utils$size(45+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER,20+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER);this.editable=!0;addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyTextInputBubble");({inputRoot:this.inputRoot,textArea:this.textArea}=this.createEditor(this.contentContainer));this.resizeGroup=this.createResizeHandle(this.svgRoot,a);this.setSize(this.DEFAULT_SIZE,!0)}getText(){return this.text}setText(a){this.text= -a;this.textArea.value=a;this.onTextChange()}setEditable(a){(this.editable=a)?this.textArea.removeAttribute("readonly"):this.textArea.setAttribute("readonly","")}isEditable(){return this.editable}addTextChangeListener(a){this.textChangeListeners.push(a)}addSizeChangeListener(a){this.sizeChangeListeners.push(a)}createEditor(a){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FOREIGNOBJECT,{x:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH,y:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH}, -a);const b=document.createElementNS(HTML_NS$$module$build$src$core$utils$dom,"body");b.setAttribute("xmlns",HTML_NS$$module$build$src$core$utils$dom);b.className="blocklyMinimalBody";const c=document.createElementNS(HTML_NS$$module$build$src$core$utils$dom,"textarea");c.className="blocklyTextarea blocklyText";c.setAttribute("dir",this.workspace.RTL?"RTL":"LTR");b.appendChild(c);a.appendChild(b);this.bindTextAreaEvents(c);setTimeout(()=>{c.focus()},0);return{inputRoot:a,textArea:c}}bindTextAreaEvents(a){conditionalBind$$module$build$src$core$browser_events(a, -"wheel",this,b=>{b.stopPropagation()});conditionalBind$$module$build$src$core$browser_events(a,"focus",this,this.onStartEdit,!0);conditionalBind$$module$build$src$core$browser_events(a,"change",this,this.onTextChange)}createResizeHandle(a,b){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{"class":"blocklyResizeHandle",href:`${b.options.pathToMedia}resize-handle.svg`},a);conditionalBind$$module$build$src$core$browser_events(a,"pointerdown",this,this.onResizePointerDown); -return a}setSize(a,b=!1){a.width=Math.max(a.width,this.MIN_SIZE.width);a.height=Math.max(a.height,this.MIN_SIZE.height);const c=a.width-Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER,d=a.height-Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER;this.inputRoot.setAttribute("width",`${c}`);this.inputRoot.setAttribute("height",`${d}`);this.resizeGroup.setAttribute("y",`${d}`);this.workspace.RTL?this.resizeGroup.setAttribute("x",`${-Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER}`): -this.resizeGroup.setAttribute("x",`${c}`);super.setSize(a,b);this.onSizeChange()}getSize(){return super.getSize()}onResizePointerDown(a){this.bringToFront();isRightButton$$module$build$src$core$browser_events(a)||(start$$module$build$src$core$utils$drag(this.workspace,a,new Coordinate$$module$build$src$core$utils$coordinate(this.workspace.RTL?-this.getSize().width:this.getSize().width,this.getSize().height)),this.resizePointerUpListener=conditionalBind$$module$build$src$core$browser_events(document, -"pointerup",this,this.onResizePointerUp),this.resizePointerMoveListener=conditionalBind$$module$build$src$core$browser_events(document,"pointermove",this,this.onResizePointerMove),this.workspace.hideChaff());a.stopPropagation()}onResizePointerUp(a){clearTouchIdentifier$$module$build$src$core$touch();this.resizePointerUpListener&&(unbind$$module$build$src$core$browser_events(this.resizePointerUpListener),this.resizePointerUpListener=null);this.resizePointerMoveListener&&(unbind$$module$build$src$core$browser_events(this.resizePointerMoveListener), -this.resizePointerMoveListener=null)}onResizePointerMove(a){a=move$$module$build$src$core$utils$drag(this.workspace,a);this.setSize(new Size$$module$build$src$core$utils$size(this.workspace.RTL?-a.x:a.x,a.y),!1);this.onSizeChange()}onStartEdit(){this.bringToFront()&&this.textArea.focus()}onTextChange(){this.text=this.textArea.value;for(const a of this.textChangeListeners)a()}onSizeChange(){for(const a of this.sizeChangeListeners)a()}};register$$module$build$src$core$css("\n.blocklyTextInputBubble .blocklyTextarea {\n background-color: var(--commentFillColour);\n border: 0;\n box-sizing: border-box;\n display: block;\n outline: 0;\n padding: 5px;\n resize: none;\n width: 100%;\n height: 100%;\n}\n"); -var module$build$src$core$bubbles$textinput_bubble={};module$build$src$core$bubbles$textinput_bubble.TextInputBubble=TextInputBubble$$module$build$src$core$bubbles$textinput_bubble;var module$build$src$core$icons$registry={};module$build$src$core$icons$registry.register=register$$module$build$src$core$icons$registry;module$build$src$core$icons$registry.unregister=unregister$$module$build$src$core$icons$registry;var SIZE$$module$build$src$core$icons$comment_icon=17,DEFAULT_BUBBLE_WIDTH$$module$build$src$core$icons$comment_icon=160,DEFAULT_BUBBLE_HEIGHT$$module$build$src$core$icons$comment_icon=80,CommentIcon$$module$build$src$core$icons$comment_icon=class extends Icon$$module$build$src$core$icons$icon{constructor(a){super(a);this.sourceBlock=a;this.textInputBubble=null;this.text="";this.bubbleSize=new Size$$module$build$src$core$utils$size(DEFAULT_BUBBLE_WIDTH$$module$build$src$core$icons$comment_icon,DEFAULT_BUBBLE_HEIGHT$$module$build$src$core$icons$comment_icon); +module$build$src$core$utils.toolbox=module$build$src$core$utils$toolbox;module$build$src$core$utils.userAgent=module$build$src$core$utils$useragent;module$build$src$core$utils.xml=module$build$src$core$utils$xml;var TextInputBubble$$module$build$src$core$bubbles$textinput_bubble=class extends Bubble$$module$build$src$core$bubbles$bubble{constructor(a,b,c,d){super(a,b,c,void 0,d);this.workspace=a;this.anchor=b;this.ownerRect=c;this.owner=d;this.resizePointerMoveListener=this.resizePointerUpListener=null;this.sizeChangeListeners=[];this.locationChangeListeners=[];this.DEFAULT_SIZE=new Size$$module$build$src$core$utils$size(160+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER,80+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER); +this.MIN_SIZE=new Size$$module$build$src$core$utils$size(45+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER,20+Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER);this.editable=!0;addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyTextInputBubble");this.editor=new CommentEditor$$module$build$src$core$comments$comment_editor(a,this.id,()=>{$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this)});this.contentContainer.appendChild(this.editor.getDom()); +this.resizeGroup=this.createResizeHandle(this.svgRoot,a);this.setSize(this.DEFAULT_SIZE,!0)}getText(){return this.editor.getText()}setText(a){this.editor.setText(a)}setEditable(a){this.editable=a;this.editor.setEditable(a)}isEditable(){return this.editable}addTextChangeListener(a){this.editor.addTextChangeListener(a)}addSizeChangeListener(a){this.sizeChangeListeners.push(a)}addLocationChangeListener(a){this.locationChangeListeners.push(a)}createResizeHandle(a,b){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE, +{"class":"blocklyResizeHandle",href:`${b.options.pathToMedia}resize-handle.svg`},a);conditionalBind$$module$build$src$core$browser_events(a,"pointerdown",this,this.onResizePointerDown);return a}setSize(a,b=!1){a.width=Math.max(a.width,this.MIN_SIZE.width);a.height=Math.max(a.height,this.MIN_SIZE.height);const c=a.width-Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER,d=a.height-Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER;this.editor.updateSize(new Size$$module$build$src$core$utils$size(c, +d),new Size$$module$build$src$core$utils$size(0,0));this.editor.getDom().setAttribute("x",`${Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER/2}`);this.editor.getDom().setAttribute("y",`${Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER/2}`);this.resizeGroup.setAttribute("y",`${d}`);this.workspace.RTL?this.resizeGroup.setAttribute("x",`${-Bubble$$module$build$src$core$bubbles$bubble.DOUBLE_BORDER}`):this.resizeGroup.setAttribute("x",`${c}`);super.setSize(a,b);this.onSizeChange()}getSize(){return super.getSize()}moveDuringDrag(a){super.moveDuringDrag(a); +this.onLocationChange()}setPositionRelativeToAnchor(a,b){super.setPositionRelativeToAnchor(a,b);this.onLocationChange()}positionByRect(a=new Rect$$module$build$src$core$utils$rect(0,0,0,0)){super.positionByRect(a);this.onLocationChange()}onResizePointerDown(a){this.bringToFront();isRightButton$$module$build$src$core$browser_events(a)||(start$$module$build$src$core$utils$drag(this.workspace,a,new Coordinate$$module$build$src$core$utils$coordinate(this.workspace.RTL?-this.getSize().width:this.getSize().width, +this.getSize().height)),this.resizePointerUpListener=conditionalBind$$module$build$src$core$browser_events(document,"pointerup",this,this.onResizePointerUp),this.resizePointerMoveListener=conditionalBind$$module$build$src$core$browser_events(document,"pointermove",this,this.onResizePointerMove),this.workspace.hideChaff());a.stopPropagation()}onResizePointerUp(a){clearTouchIdentifier$$module$build$src$core$touch();this.resizePointerUpListener&&(unbind$$module$build$src$core$browser_events(this.resizePointerUpListener), +this.resizePointerUpListener=null);this.resizePointerMoveListener&&(unbind$$module$build$src$core$browser_events(this.resizePointerMoveListener),this.resizePointerMoveListener=null)}onResizePointerMove(a){a=move$$module$build$src$core$utils$drag(this.workspace,a);this.setSize(new Size$$module$build$src$core$utils$size(this.workspace.RTL?-a.x:a.x,a.y),!1);this.onSizeChange()}onSizeChange(){for(const a of this.sizeChangeListeners)a()}onLocationChange(){for(const a of this.locationChangeListeners)a()}getEditor(){return this.editor}}; +register$$module$build$src$core$css("\n.blocklyTextInputBubble .blocklyTextarea {\n background-color: var(--commentFillColour);\n border: 0;\n box-sizing: border-box;\n display: block;\n outline: 0;\n padding: 5px;\n resize: none;\n width: 100%;\n height: 100%;\n}\n");var module$build$src$core$bubbles$textinput_bubble={};module$build$src$core$bubbles$textinput_bubble.TextInputBubble=TextInputBubble$$module$build$src$core$bubbles$textinput_bubble;var ConnectionType$$module$build$src$core$connection_type;(function(a){a[a.INPUT_VALUE=1]="INPUT_VALUE";a[a.OUTPUT_VALUE=2]="OUTPUT_VALUE";a[a.NEXT_STATEMENT=3]="NEXT_STATEMENT";a[a.PREVIOUS_STATEMENT=4]="PREVIOUS_STATEMENT"})(ConnectionType$$module$build$src$core$connection_type||(ConnectionType$$module$build$src$core$connection_type={}));var module$build$src$core$connection_type={};module$build$src$core$connection_type.ConnectionType=ConnectionType$$module$build$src$core$connection_type;var ConnectionDB$$module$build$src$core$connection_db=class{constructor(a){this.connectionChecker=a;this.connections=[]}addConnection(a,b){b=this.calculateIndexForYPos(b);this.connections.splice(b,0,a)}findIndexOfConnection(a,b){if(!this.connections.length)return-1;const c=this.calculateIndexForYPos(b);if(c>=this.connections.length)return-1;b=a.y;let d=c;for(;d>=0&&this.connections[d].y===b;){if(this.connections[d]===a)return d;d--}for(d=c;da)c=d;else{b=d;break}}return b}removeConnection(a,b){a=this.findIndexOfConnection(a,b);if(a===-1)throw Error("Unable to find connection in connectionDB.");this.connections.splice(a,1)}getNeighbours(a,b){function c(l){const m=e-d[l].x,n=f-d[l].y;Math.sqrt(m*m+n*n)<=b&&k.push(d[l]); +return n=0&&c(a);)a--;do g++;while(g=0&&this.isInYRange(k,a.y,b);)h=this.connections[k], +this.connectionChecker.canConnect(a,h,!0,g)&&(c=h,g=h.distanceFrom(a)),k--;for(;fthis.fieldRow.length)throw Error("index "+a+" out of bounds.");if(!(b|| +b===""&&c))return a;typeof b==="string"&&(b=$.fromJson$$module$build$src$core$field_registry({type:"field_label",text:b}));b.setSourceBlock(this.sourceBlock);this.sourceBlock.initialized&&this.initField(b);b.name=c;b.setVisible(this.isVisible());b.prefixField&&(a=this.insertFieldAt(a,b.prefixField));this.fieldRow.splice(a,0,b);a++;b.suffixField&&(a=this.insertFieldAt(a,b.suffixField));this.sourceBlock.rendered&&this.sourceBlock.queueRender();return a}removeField(a,b){for(let c=0,d;d=this.fieldRow[c];c++)if(d.name=== +a)return d.dispose(),this.fieldRow.splice(c,1),this.sourceBlock.rendered&&this.sourceBlock.queueRender(),!0;if(b)return!1;throw Error('Field "'+a+'" not found.');}isVisible(){return this.visible}setVisible(a){let b=[];if(this.visible===a)return b;this.visible=a;for(let c=0,d;d=this.fieldRow[c];c++)d.setVisible(a);if(this.connection&&this.connection instanceof RenderedConnection$$module$build$src$core$rendered_connection){a?b=this.connection.startTrackingAll():this.connection.stopTrackingAll();const c= +this.connection.targetBlock();c&&(c.getSvgRoot().style.display=a?"block":"none")}return b}markDirty(){for(let a=0,b;b=this.fieldRow[a];a++)b.markDirty()}setCheck(a){if(!this.connection)throw Error("This input does not have a connection.");this.connection.setCheck(a);return this}setAlign(a){this.align=a;this.sourceBlock.rendered&&this.sourceBlock.queueRender();return this}setShadowDom(a){if(!this.connection)throw Error("This input does not have a connection.");this.connection.setShadowDom(a);return this}getShadowDom(){if(!this.connection)throw Error("This input does not have a connection."); +return this.connection.getShadowDom()}init(){for(const a of this.fieldRow)a.init()}initModel(){for(const a of this.fieldRow)a.initModel()}initField(a){this.sourceBlock.rendered?a.init():a.initModel()}dispose(){for(let a=0,b;b=this.fieldRow[a];a++)b.dispose();this.connection&&this.connection.dispose()}makeConnection(a){return this.sourceBlock.makeConnection_(a)}},module$build$src$core$inputs$input={};module$build$src$core$inputs$input.Input=Input$$module$build$src$core$inputs$input;var DummyInput$$module$build$src$core$inputs$dummy_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.DUMMY}},module$build$src$core$inputs$dummy_input={};module$build$src$core$inputs$dummy_input.DummyInput=DummyInput$$module$build$src$core$inputs$dummy_input;var EndRowInput$$module$build$src$core$inputs$end_row_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.END_ROW}},module$build$src$core$inputs$end_row_input={};module$build$src$core$inputs$end_row_input.EndRowInput=EndRowInput$$module$build$src$core$inputs$end_row_input;var StatementInput$$module$build$src$core$inputs$statement_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){if(!a)throw Error("Statement inputs must have a non-empty name");super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.STATEMENT;this.connection=this.makeConnection(ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT)}},module$build$src$core$inputs$statement_input={}; +module$build$src$core$inputs$statement_input.StatementInput=StatementInput$$module$build$src$core$inputs$statement_input;var module$build$src$core$inputs$value_input;$.ValueInput$$module$build$src$core$inputs$value_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){if(!a)throw Error("Value inputs must have a non-empty name");super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.VALUE;this.connection=this.makeConnection(ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE)}};module$build$src$core$inputs$value_input={}; +module$build$src$core$inputs$value_input.ValueInput=$.ValueInput$$module$build$src$core$inputs$value_input;var module$build$src$core$interfaces$i_icon={};module$build$src$core$interfaces$i_icon.isIcon=isIcon$$module$build$src$core$interfaces$i_icon;var module$build$src$core$interfaces$i_comment_icon={};module$build$src$core$interfaces$i_comment_icon.isCommentIcon=isCommentIcon$$module$build$src$core$interfaces$i_comment_icon;var Block$$module$build$src$core$block=class{constructor(a,b,c){this.data=null;this.disposed=!1;this.hue=null;this.colour_="#000000";this.styleName_="";this.suppressPrefixSuffix=!1;this.previousConnection=this.nextConnection=this.outputConnection=null;this.inputList=[];this.icons=[];this.disabledReasons=new Set;this.tooltip="";this.contextMenu=!0;this.parentBlock_=null;this.childBlocks_=[];this.editable=this.movable=this.deletable=!0;this.collapsed_=this.shadow=!1;this.outputShape_=null;this.rendered= +this.isInsertionMarker_=this.initialized=this.disposing=!1;this.onchangeWrapper=this.helpUrl=null;this.statementInputCount=0;this.workspace=a;this.id=c&&!a.getBlockById(c)?c:genUid$$module$build$src$core$utils$idgenerator();a.setBlockById(this.id,this);this.xy=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.isInFlyout=a.isFlyout;this.isInMutator=a.isMutator;this.RTL=a.RTL;if(b){this.type=b;c=Blocks$$module$build$src$core$blocks[b];if(!c||typeof c!=="object")throw TypeError("Invalid block definition for type: "+ +b);Object.assign(this,c)}a.addTopBlock(this);a.addTypedBlock(this);new.target===Block$$module$build$src$core$block&&this.doInit_()}doInit_(){const a=$.getGroup$$module$build$src$core$events$utils();a||$.setGroup$$module$build$src$core$events$utils(!0);const b=getRecordUndo$$module$build$src$core$events$utils();try{typeof this.init==="function"&&($.setRecordUndo$$module$build$src$core$events$utils(!1),this.init(),$.setRecordUndo$$module$build$src$core$events$utils(b)),isEnabled$$module$build$src$core$events$utils()&& +fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CREATE))(this))}finally{$.setGroup$$module$build$src$core$events$utils(a),$.setRecordUndo$$module$build$src$core$events$utils(b)}this.inputsInlineDefault=this.inputsInline;typeof this.onchange==="function"&&this.setOnChange(this.onchange)}dispose(a=!1){this.disposing=!0;this.onchangeWrapper&&this.workspace.removeChangeListener(this.onchangeWrapper);this.unplug(a); +isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_DELETE))(this));this.workspace.removeTopBlock(this);this.disposeInternal()}disposeInternal(){this.disposing=!0;this.onchangeWrapper&&this.workspace.removeChangeListener(this.onchangeWrapper);this.workspace.removeTypedBlock(this);this.workspace.removeBlockById(this.id);typeof this.destroy==="function"&&this.destroy(); +this.childBlocks_.forEach(a=>a.disposeInternal());this.inputList.forEach(a=>a.dispose());this.inputList.length=0;this.getConnections_(!0).forEach(a=>a.dispose());this.disposed=!0}isDeadOrDying(){return this.disposing||this.disposed}initModel(){if(!this.initialized){for(const a of this.inputList)a.initModel();this.initialized=!0}}unplug(a){this.outputConnection&&this.unplugFromRow(a);this.previousConnection&&this.unplugFromStack(a)}unplugFromRow(a){let b=null,c;if((c=this.outputConnection)==null?0: +c.isConnected())b=this.outputConnection.targetConnection,this.outputConnection.disconnect();b&&a&&(a=this.getOnlyValueConnection())&&a.isConnected()&&!a.targetBlock().isShadow()&&(a=a.targetConnection,a==null||a.disconnect(),this.workspace.connectionChecker.canConnect(a,b,!1)?b.connect(a):a==null||a.onFailedConnect(b))}getOnlyValueConnection(){let a=null;for(let b=0;b1)return!1;return!0}getMatchingConnection(a, +b){const c=this.getConnections_(!0);a=a.getConnections_(!0);if(c.length!==a.length)throw Error("Connection lists did not match in length.");for(let d=0;d{d=d+(c==="("||e===")"?"":" ")+e;c=e[e.length-1];return d},"");b=b.trim()||"???";a&&b.length>a&&(b=b.substring(0,a-3)+"...");return b}toTokens(a="?"){const b=[];for(const d of this.inputList)if(d.name!=COLLAPSED_INPUT_NAME$$module$build$src$core$constants){for(const e of d.fieldRow)b.push(e.getText());if(d.connection){const e=d.connection.targetBlock();if(e){var c=d.connection;let f=c.getCheck(); +!f&&c.targetConnection&&(f=c.targetConnection.getCheck());(c=!!f&&(f.includes("Boolean")||f.includes("Number")))&&b.push("(");b.push(...e.toTokens(a));c&&b.push(")")}else b.push(a)}}return b}appendValueInput(a){return this.appendInput(new $.ValueInput$$module$build$src$core$inputs$value_input(a,this))}appendStatementInput(a){this.statementInputCount++;return this.appendInput(new StatementInput$$module$build$src$core$inputs$statement_input(a,this))}appendDummyInput(a=""){return this.appendInput(new DummyInput$$module$build$src$core$inputs$dummy_input(a, +this))}appendEndRowInput(a=""){return this.appendInput(new EndRowInput$$module$build$src$core$inputs$end_row_input(a,this))}appendInput(a){this.inputList.push(a);return a}appendInputFromRegistry(a,b){return(a=getClass$$module$build$src$core$registry(Type$$module$build$src$core$registry.INPUT,a,!1))?this.appendInput(new a(b,this)):null}jsonInit(a){var b=a.type?'Block "'+a.type+'": ':"";if(a.output&&a.previousStatement)throw Error(b+"Must not have both an output and a previousStatement.");for(var c= +0;a["args"+c];){if(a["message"+c]===void 0)throw Error(b+`args${c} must have a corresponding message (message${c}).`);c++}a.style&&a.style.hat&&(this.hat=a.style.hat,a.style=null);if(a.style&&a.colour)throw Error(b+"Must not have both a colour and a style.");a.style?this.jsonInitStyle(a,b):this.jsonInitColour(a,b);for(c=0;a["message"+c]!==void 0;)this.interpolate(a["message"+c],a["args"+c]||[],a["implicitAlign"+c]||a["lastDummyAlign"+c],b),c++;a.inputsInline!==void 0&&($.disable$$module$build$src$core$events$utils(), +this.setInputsInline(a.inputsInline),$.enable$$module$build$src$core$events$utils());a.output!==void 0&&this.setOutput(!0,a.output);a.outputShape!==void 0&&this.setOutputShape(a.outputShape);a.previousStatement!==void 0&&this.setPreviousStatement(!0,a.previousStatement);a.nextStatement!==void 0&&this.setNextStatement(!0,a.nextStatement);a.tooltip!==void 0&&(c=replaceMessageReferences$$module$build$src$core$utils$parsing(a.tooltip),this.setTooltip(c));a.enableContextMenu!==void 0&&(this.contextMenu= +!!a.enableContextMenu);a.suppressPrefixSuffix!==void 0&&(this.suppressPrefixSuffix=!!a.suppressPrefixSuffix);a.helpUrl!==void 0&&(c=replaceMessageReferences$$module$build$src$core$utils$parsing(a.helpUrl),this.setHelpUrl(c));typeof a.extensions==="string"&&(console.warn(b+"JSON attribute 'extensions' should be an array of strings. Found raw string in JSON for '"+a.type+"' block."),a.extensions=[a.extensions]);a.mutator!==void 0&&apply$$module$build$src$core$extensions(a.mutator,this,!0);a=a.extensions; +if(Array.isArray(a))for(b=0;bb)throw Error('Block "'+this.type+'": Message index %'+f+" out of range.");if(c[f])throw Error('Block "'+this.type+'": Message index %'+f+" duplicated.");c[f]=!0;d++}}if(d!==b)throw Error('Block "'+this.type+'": Message does not reference all '+b+" arg(s).");}interpolateArguments(a,b,c){const d=[];for(let f=0;f=this.inputList.length)throw RangeError("Input index "+a+" out of bounds.");if(b>this.inputList.length)throw RangeError("Reference input "+b+" out of bounds.");const c=this.inputList[a];this.inputList.splice(a,1);ab.getWeight()-c.getWeight());return a}removeIcon(a){if(!this.hasIcon(a))return!1;let b;(b=this.getIcon(a))==null||b.dispose();this.icons=this.icons.filter(c=>!c.getType().equals(a));return!0}hasIcon(a){return this.icons.some(b=>b.getType().equals(a))}getIcon(a){return a instanceof IconType$$module$build$src$core$icons$icon_types? +this.icons.find(b=>b.getType().equals(a)):this.icons.find(b=>b.getType().toString()===a)}getIcons(){return[...this.icons]}getRelativeToSurfaceXY(){return this.xy}moveBy(a,b,c){if(this.parentBlock_)throw Error("Block has parent");const d=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_MOVE))(this);c&&d.setReason(c);this.xy.translate(a,b);d.recordNew();fire$$module$build$src$core$events$utils(d)}makeConnection_(a){return new Connection$$module$build$src$core$connection(this, +a)}allInputsFilled(a){a===void 0&&(a=!0);if(!a&&this.isShadow())return!1;for(let c=0,d;d=this.inputList[c];c++)if(d.connection){var b=d.connection.targetBlock();if(!b||!b.allInputsFilled(a))return!1}return(b=this.getNextBlock())?b.allInputsFilled(a):!0}toDevString(){let a=this.type?'"'+this.type+'" block':"Block";this.id&&(a+=' (id="'+this.id+'")');return a}};Block$$module$build$src$core$block.COLLAPSED_INPUT_NAME=COLLAPSED_INPUT_NAME$$module$build$src$core$constants; +Block$$module$build$src$core$block.COLLAPSED_FIELD_NAME=COLLAPSED_FIELD_NAME$$module$build$src$core$constants;var module$build$src$core$block={};module$build$src$core$block.Block=Block$$module$build$src$core$block;var disconnectPid$$module$build$src$core$block_animations=null,wobblingBlock$$module$build$src$core$block_animations=null,module$build$src$core$block_animations={};module$build$src$core$block_animations.connectionUiEffect=connectionUiEffect$$module$build$src$core$block_animations;module$build$src$core$block_animations.disconnectUiEffect=disconnectUiEffect$$module$build$src$core$block_animations;module$build$src$core$block_animations.disconnectUiStop=disconnectUiStop$$module$build$src$core$block_animations; +module$build$src$core$block_animations.disposeUiEffect=disposeUiEffect$$module$build$src$core$block_animations;var BlockPaster$$module$build$src$core$clipboard$block_paster=class{paste(a,b,c){if(!b.isCapacityAvailable(a.typeCounts))return null;c&&(a.blockState.x=c.x,a.blockState.y=c.y);c=c||new Coordinate$$module$build$src$core$utils$coordinate(a.blockState.x||0,a.blockState.y||0);$.disable$$module$build$src$core$events$utils();let d;try{d=append$$module$build$src$core$serialization$blocks(a.blockState,b),moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster(d,c)}finally{$.enable$$module$build$src$core$events$utils()}if(!d)return d; +isEnabled$$module$build$src$core$events$utils()&&!d.isShadow()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CREATE))(d));const e=d;finishQueuedRenders$$module$build$src$core$render_management().then(()=>$.getFocusManager$$module$build$src$core$focus_manager().focusNode(e));return d}};BlockPaster$$module$build$src$core$clipboard$block_paster.TYPE="block"; +register$$module$build$src$core$clipboard$registry(BlockPaster$$module$build$src$core$clipboard$block_paster.TYPE,new BlockPaster$$module$build$src$core$clipboard$block_paster);var module$build$src$core$clipboard$block_paster={};module$build$src$core$clipboard$block_paster.BlockPaster=BlockPaster$$module$build$src$core$clipboard$block_paster;module$build$src$core$clipboard$block_paster.moveBlockToNotConflict=moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster;var bumpIntoBounds$$module$build$src$core$bump_objects=bumpObjectIntoBounds$$module$build$src$core$bump_objects,module$build$src$core$bump_objects={};module$build$src$core$bump_objects.bumpIntoBounds=bumpObjectIntoBounds$$module$build$src$core$bump_objects;module$build$src$core$bump_objects.bumpIntoBoundsHandler=bumpIntoBoundsHandler$$module$build$src$core$bump_objects;module$build$src$core$bump_objects.bumpTopObjectsIntoBounds=bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects;var BlockDragStrategy$$module$build$src$core$dragging$block_drag_strategy=class{constructor(a){this.block=a;this.connectionPreviewer=this.connectionCandidate=this.startLoc=this.startChildConn=this.startParentConn=null;this.dragging=!1;this.dragOffset=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.originalEventGroup="";this.workspace=a.workspace}isMovable(){if(this.block.isShadow()){let a,b;return(b=(a=this.block.getParent())==null?void 0:a.isMovable())!=null?b:!1}return this.block.isOwnMovable()&& +!this.block.isDeadOrDying()&&!this.workspace.isReadOnly()&&!this.block.isInFlyout}startDrag(a){if(this.block.isShadow())this.startDraggingShadow(a);else{this.dragging=!0;this.fireDragStartEvent();this.startLoc=this.block.getRelativeToSurfaceXY();this.connectionCandidate=null;this.connectionPreviewer=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.CONNECTION_PREVIEWER,this.workspace.options))(this.block);startTextWidthCache$$module$build$src$core$utils$dom(); +this.workspace.setResizesEnabled(!1);disconnectUiStop$$module$build$src$core$block_animations();a=this.shouldHealStack(a);this.shouldDisconnect(a)&&this.disconnectBlock(a);this.block.setDragging(!0);var b;(b=this.workspace.getLayerManager())==null||b.moveToDragLayer(this.block);this.getVisibleBubbles(this.block).forEach(c=>{let d;(d=this.workspace.getLayerManager())==null||d.moveToDragLayer(c,!1)})}}getVisibleBubbles(a){return a.getDescendants(!1).flatMap(b=>b.getIcons()).filter(b=>hasBubble$$module$build$src$core$interfaces$i_has_bubble(b)&& +b.bubbleIsVisible()).map(b=>b.getBubble()).filter(b=>!!b).sort((b,c)=>{b=b.getSvgRoot().compareDocumentPosition(c.getSvgRoot());return b&Node.DOCUMENT_POSITION_PRECEDING?1:b&Node.DOCUMENT_POSITION_FOLLOWING?-1:0})}shouldHealStack(a){return!!a&&(a.altKey||a.ctrlKey||a.metaKey)}startDraggingShadow(a){const b=this.block.getParent();if(!b)throw Error("Tried to drag a shadow block with no parent. Shadow blocks should always have parents.");this.dragOffset=Coordinate$$module$build$src$core$utils$coordinate.difference(b.getRelativeToSurfaceXY(), +this.block.getRelativeToSurfaceXY());b.startDrag(a)}shouldDisconnect(a){return!!(this.block.getParent()||a&&this.block.nextConnection&&this.block.nextConnection.targetBlock())}disconnectBlock(a){let b,c,d;this.startParentConn=(d=(b=this.block.outputConnection)==null?void 0:b.targetConnection)!=null?d:(c=this.block.previousConnection)==null?void 0:c.targetConnection;if(a){let e;this.startChildConn=(e=this.block.nextConnection)==null?void 0:e.targetConnection}this.block.unplug(a);disconnectUiEffect$$module$build$src$core$block_animations(this.block)}fireDragStartEvent(){const a= +new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_DRAG))(this.block,!0,this.block.getDescendants(!1));fire$$module$build$src$core$events$utils(a)}fireDragEndEvent(){const a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_DRAG))(this.block,!1,this.block.getDescendants(!1));fire$$module$build$src$core$events$utils(a)}fireMoveEvent(){if(!this.block.isDeadOrDying()){var a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_MOVE))(this.block); +a.setReason(["drag"]);a.oldCoordinate=this.startLoc;a.recordNew();fire$$module$build$src$core$events$utils(a)}}drag(a){if(this.block.isShadow()){let b;(b=this.block.getParent())==null||b.drag(Coordinate$$module$build$src$core$utils$coordinate.sum(a,this.dragOffset))}else this.block.moveDuringDrag(a),this.updateConnectionPreview(this.block,Coordinate$$module$build$src$core$utils$coordinate.difference(a,this.startLoc))}updateConnectionPreview(a,b){var c=this.connectionCandidate;const d=this.getConnectionCandidate(a, +b);if(d){this.connectionCandidate=b=c&&this.currCandidateIsBetter(c,b,d)?c:d;var {local:e,neighbour:f}=b;b=e.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE||e.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT;var g;c=f.isConnected()&&!((g=f.targetBlock())==null?0:g.isInsertionMarker());if(b&&c&&!this.orphanCanConnectAtEnd(a,f.targetBlock(),e.type)){let k;(k=this.connectionPreviewer)==null||k.previewReplacement(e,f,f.targetBlock())}else{var h; +(h=this.connectionPreviewer)==null||h.previewConnection(e,f)}}else{let k;(k=this.connectionPreviewer)==null||k.hidePreview();this.connectionCandidate=null}}orphanCanConnectAtEnd(a,b,c){return!!Connection$$module$build$src$core$connection.getConnectionForOrphanedConnection(a,c===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE?b.outputConnection:b.previousConnection)}currCandidateIsBetter(a,b,c){const {local:d,neighbour:e}=a;a=new Coordinate$$module$build$src$core$utils$coordinate(d.x, +d.y);const f=new Coordinate$$module$build$src$core$utils$coordinate(e.x,e.y);b=Coordinate$$module$build$src$core$utils$coordinate.distance(Coordinate$$module$build$src$core$utils$coordinate.sum(a,b),f);return c.distance>b-$.config$$module$build$src$core$config.currentConnectionPreference}getConnectionCandidate(a,b){a=this.getLocalConnections(a);let c=this.getSearchRadius(),d=null;for(const e of a){const {connection:f,radius:g}=e.closest(c,b);f&&(d={local:e,neighbour:f,distance:g},c=g)}return d}getSearchRadius(){return this.connectionCandidate? +$.config$$module$build$src$core$config.connectingSnapRadius:$.config$$module$build$src$core$config.snapRadius}getLocalConnections(a){const b=a.getConnections_(!1),c=a.lastConnectionInStack(!0);c&&c!==a.nextConnection&&b.push(c);return b}endDrag(a){if(this.block.isShadow()){let c;(c=this.block.getParent())==null||c.endDrag(a)}else{this.originalEventGroup=$.getGroup$$module$build$src$core$events$utils();this.fireDragEndEvent();this.fireMoveEvent();stopTextWidthCache$$module$build$src$core$utils$dom(); +disconnectUiStop$$module$build$src$core$block_animations();var b;(b=this.connectionPreviewer)==null||b.hidePreview();if(!this.block.isDeadOrDying()&&this.dragging){let c;(c=this.workspace.getLayerManager())==null||c.moveOffDragLayer(this.block,BLOCK$$module$build$src$core$layers);this.getVisibleBubbles(this.block).forEach(d=>{let e;return(e=this.workspace.getLayerManager())==null?void 0:e.moveOffDragLayer(d,BUBBLE$$module$build$src$core$layers,!1)});this.block.setDragging(!1)}this.connectionCandidate? +(this.applyConnections(this.connectionCandidate),this.disposeStep()):this.block.queueRender().then(()=>this.disposeStep())}}disposeStep(){const a=$.getGroup$$module$build$src$core$events$utils();$.setGroup$$module$build$src$core$events$utils(this.originalEventGroup);this.block.snapToGrid();let b;(b=this.connectionPreviewer)==null||b.dispose();this.workspace.setResizesEnabled(!0);$.setGroup$$module$build$src$core$events$utils(a)}applyConnections(a){const {local:b,neighbour:c}=a;b.connect(c);const d= +b.isSuperior()?c:b,e=this.block.getRootBlock();finishQueuedRenders$$module$build$src$core$render_management().then(()=>{connectionUiEffect$$module$build$src$core$block_animations(d.getSourceBlock());setTimeout(()=>{e.bringToFront()},0)})}revertDrag(){if(this.block.isShadow()){let c;(c=this.block.getParent())==null||c.revertDrag()}else{var a;(a=this.connectionPreviewer)==null||a.hidePreview();this.connectionCandidate=null;var b;(b=this.startChildConn)==null||b.connect(this.block.nextConnection);if(this.startParentConn)switch(this.startParentConn.type){case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:this.startParentConn.connect(this.block.outputConnection); +break;case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:this.startParentConn.connect(this.block.previousConnection)}else{this.block.moveTo(this.startLoc,["drag"]);let c;(c=this.workspace.getLayerManager())==null||c.moveOffDragLayer(this.block,BLOCK$$module$build$src$core$layers);this.getVisibleBubbles(this.block).forEach(d=>{let e;return(e=this.workspace.getLayerManager())==null?void 0:e.moveOffDragLayer(d,BUBBLE$$module$build$src$core$layers,!1)});bumpObjectIntoBounds$$module$build$src$core$bump_objects(this.workspace, +this.workspace.getMetricsManager().getScrollMetrics(!0),this.block)}this.startParentConn=this.startChildConn=null;this.block.setDragging(!1);this.dragging=!1}}},module$build$src$core$dragging$block_drag_strategy={};module$build$src$core$dragging$block_drag_strategy.BlockDragStrategy=BlockDragStrategy$$module$build$src$core$dragging$block_drag_strategy;var TextBubble$$module$build$src$core$bubbles$text_bubble=class extends Bubble$$module$build$src$core$bubbles$bubble{constructor(a,b,c,d){super(b,c,d);this.text=a;this.workspace=b;this.anchor=c;this.ownerRect=d;this.paragraph=this.stringToSvg(a,this.contentContainer);this.updateBubbleSize();addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyTextBubble")}getText(){return this.text}setText(a){this.text=a;removeNode$$module$build$src$core$utils$dom(this.paragraph);this.paragraph=this.stringToSvg(a, +this.contentContainer);this.updateBubbleSize()}stringToSvg(a,b){b=this.createParagraph(b);a=this.createTextFragments(b,a);this.workspace.RTL&&this.rightAlignTextFragments(b.getBBox().width,a);return b}createParagraph(a){return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyText blocklyBubbleText blocklyNoPointerEvents",transform:`translate(0,${Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH})`,style:`direction: ${this.workspace.RTL? +"rtl":"ltr"}`},a)}createTextFragments(a,b){let c=1;return b.split("\n").map(d=>{const e=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT,{y:`${c}em`,x:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH},a);d=document.createTextNode(d);e.appendChild(d);c+=1;return e})}rightAlignTextFragments(a,b){for(const c of b)c.setAttribute("text-anchor","start"),c.setAttribute("x",`${a+Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH}`)}updateBubbleSize(){const a= +this.paragraph.getBBox();this.setSize(new Size$$module$build$src$core$utils$size(a.width+Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH*2,a.height+Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH*2),!0)}},module$build$src$core$bubbles$text_bubble={};module$build$src$core$bubbles$text_bubble.TextBubble=TextBubble$$module$build$src$core$bubbles$text_bubble;var SIZE$$module$build$src$core$icons$warning_icon=17,WarningIcon$$module$build$src$core$icons$warning_icon=class extends Icon$$module$build$src$core$icons$icon{constructor(a){super(a);this.sourceBlock=a;this.textMap=new Map;this.textBubble=null}getType(){return WarningIcon$$module$build$src$core$icons$warning_icon.TYPE}initView(a){this.svgRoot||(super.initView(a),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyIconShape",d:"M2,15Q-1,15 0.5,12L6.5,1.7Q8,-1 9.5,1.7L15.5,12Q17,15 14,15z"}, +this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyIconSymbol",d:"m7,4.8v3.16l0.27,2.27h1.46l0.27,-2.27v-3.16z"},this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyIconSymbol",x:"7",y:"11",height:"2",width:"2"},this.svgRoot),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyWarningIcon"))}dispose(){super.dispose();let a;(a=this.textBubble)==null|| +a.dispose()}getWeight(){return WarningIcon$$module$build$src$core$icons$warning_icon.WEIGHT}getSize(){return new Size$$module$build$src$core$utils$size(SIZE$$module$build$src$core$icons$warning_icon,SIZE$$module$build$src$core$icons$warning_icon)}applyColour(){super.applyColour();let a;(a=this.textBubble)==null||a.setColour(this.sourceBlock.getColour())}updateCollapsed(){}isShownWhenCollapsed(){return!0}onLocationChange(a){super.onLocationChange(a);let b;(b=this.textBubble)==null||b.setAnchorLocation(this.getAnchorLocation())}addMessage(a, +b){if(this.textMap.get(b)===a)return this;a?this.textMap.set(b,a):this.textMap.delete(b);let c;(c=this.textBubble)==null||c.setText(this.getText());return this}getText(){return[...this.textMap.values()].join("\n")}onClick(){super.onClick();this.setBubbleVisible(!this.bubbleIsVisible())}isClickableInFlyout(){return!1}bubbleIsVisible(){return!!this.textBubble}setBubbleVisible(a){const b=this;return(0,$jscomp.asyncExecutePromiseGeneratorFunction)(function*(){if(b.bubbleIsVisible()!==a){yield finishQueuedRenders$$module$build$src$core$render_management(); +if(a)b.textBubble=new TextBubble$$module$build$src$core$bubbles$text_bubble(b.getText(),b.sourceBlock.workspace,b.getAnchorLocation(),b.getBubbleOwnerRect()),b.applyColour();else{let c;(c=b.textBubble)==null||c.dispose();b.textBubble=null}fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BUBBLE_OPEN))(b.sourceBlock,a,"warning"))}})}getBubble(){return this.textBubble}getAnchorLocation(){const a=SIZE$$module$build$src$core$icons$warning_icon/ +2;return Coordinate$$module$build$src$core$utils$coordinate.sum(this.workspaceLocation,new Coordinate$$module$build$src$core$utils$coordinate(a,a))}getBubbleOwnerRect(){const a=this.sourceBlock.getSvgRoot().getBBox();return new Rect$$module$build$src$core$utils$rect(a.y,a.y+a.height,a.x,a.x+a.width)}};WarningIcon$$module$build$src$core$icons$warning_icon.TYPE=IconType$$module$build$src$core$icons$icon_types.WARNING;WarningIcon$$module$build$src$core$icons$warning_icon.WEIGHT=2; +var module$build$src$core$icons$warning_icon={};module$build$src$core$icons$warning_icon.WarningIcon=WarningIcon$$module$build$src$core$icons$warning_icon;var BlockSvg$$module$build$src$core$block_svg=class extends Block$$module$build$src$core$block{constructor(a,b,c){super(a,b,c);this.childlessWidth=this.width=this.height=0;this.warningTextDb=new Map;this.mutator=null;this.rendered=!0;this.visuallyDisabled=!1;this.translation="";this.dragging=!1;this.relativeCoords=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.dragStrategy=new BlockDragStrategy$$module$build$src$core$dragging$block_drag_strategy(this);if(!a.rendered)throw TypeError("Cannot create a rendered block in a headless workspace"); +this.workspace=a;this.svgGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{});b&&addClass$$module$build$src$core$utils$dom(this.svgGroup,b);this.style=a.getRenderer().getConstants().getBlockStyle(null);this.pathObject=a.getRenderer().makePathObject(this.svgGroup,this.style);a=this.pathObject.svgPath;a.tooltip=this;bindMouseEvents$$module$build$src$core$tooltip(a);this.svgGroup.setAttribute("data-id",this.id);a.id=getNextUniqueId$$module$build$src$core$utils$idgenerator(); +this.doInit_()}initSvg(){if(!this.initialized){for(var a of this.inputList)a.init();for(const b of this.getIcons())b.initView(this.createIconPointerDownListener(b)),b.updateEditable();this.applyColour();this.pathObject.updateMovable(this.isMovable()||this.isInFlyout);(a=this.getSvgRoot())&&conditionalBind$$module$build$src$core$browser_events(a,"pointerdown",this,this.onMouseDown);a.parentNode||this.workspace.getCanvas().appendChild(a);this.initialized=!0}}getColourSecondary(){return this.style.colourSecondary}getColourTertiary(){return this.style.colourTertiary}select(){this.addSelect(); +fireSelectedEvent$$module$build$src$core$common(this)}unselect(){this.removeSelect();fireSelectedEvent$$module$build$src$core$common(null)}setParent(a){var b=this.parentBlock_;if(a!==b){startTextWidthCache$$module$build$src$core$utils$dom();super.setParent(a);stopTextWidthCache$$module$build$src$core$utils$dom();var c=this.getSvgRoot();if(!this.workspace.isClearing&&c){var d=this.getRelativeToSurfaceXY(),e=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode(),f,g=this.getSvgRoot().contains((f= +e==null?void 0:e.getFocusableElement())!=null?f:null);a?(a.getSvgRoot().appendChild(c),g&&e&&$.getFocusManager$$module$build$src$core$focus_manager().focusNode(e)):b&&(a=this.workspace.getCanvas().querySelector(".blocklyDragging"),b=a==null?void 0:a.parentElement,f=this.workspace.getCanvas(),b===f?f.insertBefore(c,a):(f.appendChild(c),g&&e&&$.getFocusManager$$module$build$src$core$focus_manager().focusNode(e)),this.translate(d.x,d.y));this.applyColour()}}}getRelativeToSurfaceXY(){const a=this.workspace.getLayerManager(); +if(!a)throw Error("Cannot calculate position because the workspace has not been appended");let b=0,c=0,d=this.getSvgRoot();if(d){do{const e=getRelativeXY$$module$build$src$core$utils$svg_math(d);b+=e.x;c+=e.y;d=d.parentNode}while(d&&!a.hasLayer(d))}return new Coordinate$$module$build$src$core$utils$coordinate(b,c)}moveBy(a,b,c){if(this.parentBlock_)throw Error("Block has parent");const d=isEnabled$$module$build$src$core$events$utils();let e=null;d&&(e=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_MOVE))(this), +c&&e.setReason(c));a=new Coordinate$$module$build$src$core$utils$coordinate(a,b);b=this.getRelativeToSurfaceXY();a=Coordinate$$module$build$src$core$utils$coordinate.sum(b,a);this.translate(a.x,a.y);this.updateComponentLocations(a);d&&e&&(e.recordNew(),fire$$module$build$src$core$events$utils(e));this.workspace.resizeContents()}translate(a,b){this.translation=`translate(${a}, ${b})`;this.relativeCoords=new Coordinate$$module$build$src$core$utils$coordinate(a,b);this.getSvgRoot().setAttribute("transform", +this.getTranslation())}getTranslation(){return this.translation}moveTo(a,b){const c=this.getRelativeToSurfaceXY();this.moveBy(a.x-c.x,a.y-c.y,b)}moveDuringDrag(a){this.translate(a.x,a.y);this.getSvgRoot().setAttribute("transform",this.getTranslation());this.updateComponentLocations(a)}snapToGrid(){if(!this.isDeadOrDying()&&!this.getParent()&&!this.isInFlyout){var a=this.workspace.getGrid();if(a!=null&&a.shouldSnap()){var b=this.getRelativeToSurfaceXY();a=a.alignXY(b);a!==b&&this.moveTo(a,["snap"])}}}getBoundingRectangle(){return this.getBoundingRectangleWithDimensions(this.getHeightWidth())}getBoundingRectangleWithoutChildren(){return this.getBoundingRectangleWithDimensions({height:this.height, +width:this.childlessWidth})}getBoundingRectangleWithDimensions(a){const b=this.getRelativeToSurfaceXY();let c,d;this.RTL?(c=b.x-a.width,d=b.x):(c=b.x,d=b.x+a.width);return new Rect$$module$build$src$core$utils$rect(b.y,b.y+a.height,c,d)}markDirty(){this.pathObject.constants=this.workspace.getRenderer().getConstants();for(let a=0,b;b=this.inputList[a];a++)b.markDirty()}setCollapsed(a){this.collapsed_!==a&&(super.setCollapsed(a),this.updateCollapsed())}childHasWarning(){var a=this.getNextBlock();a= +a?new Set(a.getDescendants(!1)):null;const b=this.getDescendants(!1);for(const c of b){if(c===this)continue;let d;if(((d=a)==null||!d.has(c))&&c.getIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE))return!0}return!1}updateCollapsed(){var a=this.isCollapsed();const b=COLLAPSED_INPUT_NAME$$module$build$src$core$constants,c=COLLAPSED_FIELD_NAME$$module$build$src$core$constants;for(let e=0,f;f=this.inputList[e];e++)f.name!==b&&f.setVisible(!a);for(var d of this.getIcons())d.updateCollapsed(); +a?(addClass$$module$build$src$core$utils$dom(this.svgGroup,"blocklyCollapsed"),this.childHasWarning()&&this.setWarningText($.Msg$$module$build$src$core$msg.COLLAPSED_WARNINGS_WARNING,BlockSvg$$module$build$src$core$block_svg.COLLAPSED_WARNING_ID),a=this.toString(COLLAPSE_CHARS$$module$build$src$core$internal_constants),(d=this.getField(c))?d.setValue(a):(this.getInput(b)||this.appendDummyInput(b)).appendField(new FieldLabel$$module$build$src$core$field_label(a),c)):(this.updateDisabled(),this.removeInput(b), +removeClass$$module$build$src$core$utils$dom(this.svgGroup,"blocklyCollapsed"),this.setWarningText(null,BlockSvg$$module$build$src$core$block_svg.COLLAPSED_WARNING_ID))}onMouseDown(a){if(!this.workspace.isReadOnly()){var b=this.workspace.getGesture(a);b&&b.handleBlockStart(a,this)}}showHelp(){const a=typeof this.helpUrl==="function"?this.helpUrl():this.helpUrl;a&&window.open(a)}generateContextMenu(a){if(this.workspace.isReadOnly()||!this.contextMenu)return null;a=ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.getContextMenuOptions({block:this, +focusedNode:this},a);this.customContextMenu&&this.customContextMenu(a);return a}calculateContextMenuLocation(a){if(a instanceof PointerEvent)return new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY);a=wsToScreenCoordinates$$module$build$src$core$utils$svg_math(this.workspace,this.getRelativeToSurfaceXY());let b,c;const d=(b=this.inputList.filter(e=>e.isVisible()).flatMap(e=>e.fieldRow).find(e=>e.isVisible()))==null?void 0:(c=b.getSvgRoot())==null?void 0:c.getBoundingClientRect(); +return new Coordinate$$module$build$src$core$utils$coordinate(this.RTL?a.x-5:a.x+5,(d&&d.height?d.y+d.height:a.y+this.height)+5)}showContextMenu(a){const b=this.generateContextMenu(a),c=this.calculateContextMenuLocation(a);b&&b.length&&(show$$module$build$src$core$contextmenu(a,b,this.RTL,this.workspace,c),setCurrentBlock$$module$build$src$core$contextmenu(this))}updateComponentLocations(a){this.dragging||this.updateConnectionLocations(a);this.updateIconLocations(a);this.updateFieldLocations(a);for(const b of this.getChildren(!1))b.updateComponentLocations(Coordinate$$module$build$src$core$utils$coordinate.sum(a, +b.relativeCoords))}updateConnectionLocations(a){for(const b of this.getConnections_(!1))b.moveToOffset(a)}updateIconLocations(a){for(const b of this.getIcons())b.onLocationChange(a)}updateFieldLocations(a){for(const b of this.inputList)for(const c of b.fieldRow)c.onLocationChange(a)}addClass(a){addClass$$module$build$src$core$utils$dom(this.svgGroup,a)}removeClass(a){removeClass$$module$build$src$core$utils$dom(this.svgGroup,a)}setDragging(a){(this.dragging=a)?(this.translation="",draggingConnections$$module$build$src$core$common.push(...this.getConnections_(!0)), +this.addClass("blocklyDragging")):(draggingConnections$$module$build$src$core$common.length=0,this.removeClass("blocklyDragging"));for(let b=0;b!e.isDeadOrDying());let b=null,c=Number.MAX_SAFE_INTEGER;const d= +this.getRelativeToSurfaceXY();for(const e of a)a=e.getRelativeToSurfaceXY(),a=Math.sqrt(Math.pow(a.x-d.x,2)+Math.pow(a.y-d.y,2)),a{this.workspace.rendered&&c.focusTree(this.workspace)},0)}b&&(this.unplug(a),disposeUiEffect$$module$build$src$core$block_animations(this));super.dispose(!!a);removeNode$$module$build$src$core$utils$dom(this.svgGroup)}disposeInternal(){this.disposing=!0;super.disposeInternal(); +$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode()===this&&this.workspace.cancelCurrentGesture();[...this.warningTextDb.values()].forEach(a=>clearTimeout(a));this.warningTextDb.clear();this.getIcons().forEach(a=>a.dispose())}checkAndDelete(){this.workspace.isFlyout||($.setGroup$$module$build$src$core$events$utils(!0),this.workspace.hideChaff(),this.outputConnection?this.dispose(!1,!0):this.dispose(!0,!0),$.setGroup$$module$build$src$core$events$utils(!1))}toCopyData(a=!1){return this.isInsertionMarker_? +null:{paster:BlockPaster$$module$build$src$core$clipboard$block_paster.TYPE,blockState:save$$module$build$src$core$serialization$blocks(this,{addCoordinates:!0,addNextBlocks:a,saveIds:!1}),typeCounts:getBlockTypeCounts$$module$build$src$core$common(this,!0)}}applyColour(){var a,b;(b=(a=this.pathObject).applyColour)==null||b.call(a,this);a=this.getIcons();for(b=0;b{this.isDeadOrDying()||(this.warningTextDb.delete(b), +this.setWarningText(a,b))},100));else if(this.isInFlyout&&(a=null),c=this.getIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE),a){let d=this.getSurroundParent(),e=null;for(;d;)d.isCollapsed()&&(e=d),d=d.getSurroundParent();e&&e.setWarningText($.Msg$$module$build$src$core$msg.COLLAPSED_WARNINGS_WARNING,BlockSvg$$module$build$src$core$block_svg.COLLAPSED_WARNING_ID);c?c.addMessage(a,b):this.addIcon((new WarningIcon$$module$build$src$core$icons$warning_icon(this)).addMessage(a,b))}else c&& +(b?(c.addMessage("",b),c.getText()||this.removeIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE)):this.removeIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE))}setMutator(a){this.removeIcon($.MutatorIcon$$module$build$src$core$icons$mutator_icon.TYPE);a&&this.addIcon(a)}addIcon(a){super.addIcon(a);a instanceof $.MutatorIcon$$module$build$src$core$icons$mutator_icon&&(this.mutator=a);a.initView(this.createIconPointerDownListener(a));a.applyColour();a.updateEditable(); +this.queueRender();return a}createIconPointerDownListener(a){return b=>{!this.isDeadOrDying()&&(b=this.workspace.getGesture(b))&&(this.bringToFront(),b.setStartIcon(a),$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a))}}removeIcon(a){const b=super.removeIcon(a);a.equals($.MutatorIcon$$module$build$src$core$icons$mutator_icon.TYPE)&&(this.mutator=null);this.queueRender();return b}setDisabledReason(a,b){const c=this.isEnabled();super.setDisabledReason(a,b);this.isEnabled()===c|| +this.getInheritedDisabled()||this.updateDisabled()}setDeletable(a){super.setDeletable(a);a?removeClass$$module$build$src$core$utils$dom(this.svgGroup,"blocklyNotDeletable"):addClass$$module$build$src$core$utils$dom(this.svgGroup,"blocklyNotDeletable")}setHighlighted(a){this.pathObject.updateHighlighted(a)}addSelect(){this.pathObject.updateSelected(!0)}removeSelect(){this.pathObject.updateSelected(!1)}setDeleteStyle(a){this.pathObject.updateDraggingDelete(a)}getColour(){return this.style.colourPrimary}setColour(a){super.setColour(a); +a=this.workspace.getRenderer().getConstants().getBlockStyleForColour(this.colour_);let b,c;(c=(b=this.pathObject).setStyle)==null||c.call(b,a.style);this.style=a.style;this.styleName_=a.name;this.applyColour()}setStyle(a){const b=this.workspace.getRenderer().getConstants().getBlockStyle(a);this.styleName_&&removeClass$$module$build$src$core$utils$dom(this.svgGroup,this.styleName_);if(b){this.hat=b.hat;let c,d;(d=(c=this.pathObject).setStyle)==null||d.call(c,b);this.colour_=b.colourPrimary;this.style= +b;this.applyColour();addClass$$module$build$src$core$utils$dom(this.svgGroup,a);this.styleName_=a}else throw Error("Invalid style name: "+a);}getStyle(){return this.style}bringToFront(a=!1){const b=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode();let c=this;if(!c.isDeadOrDying()){do{const d=c.getSvgRoot(),e=d.parentNode,f=e.childNodes;f[f.length-1]!==d&&e.appendChild(d);if(a)break;c=c.getParent()}while(c);b&&$.getFocusManager$$module$build$src$core$focus_manager().focusNode(b)}}setPreviousStatement(a, +b){super.setPreviousStatement(a,b);this.queueRender()}setNextStatement(a,b){super.setNextStatement(a,b);this.queueRender()}setOutput(a,b){super.setOutput(a,b);this.queueRender()}setInputsInline(a){super.setInputsInline(a);this.queueRender()}removeInput(a,b){a=super.removeInput(a,b);this.queueRender();return a}moveNumberedInputBefore(a,b){super.moveNumberedInputBefore(a,b);this.queueRender()}appendInput(a){super.appendInput(a);this.queueRender();return a}setConnectionTracking(a){this.previousConnection&& +this.previousConnection.setTracking(a);this.outputConnection&&this.outputConnection.setTracking(a);if(this.nextConnection){this.nextConnection.setTracking(a);var b=this.nextConnection.targetBlock();b&&b.setConnectionTracking(a)}if(!this.collapsed_)for(b=0;bd.getElement()===a);if(c===-1)return null;c++;c>=b.length&&(c=0);return b[c].getElement()}getPreviousSibling(a){const b=this.flyout.getContents();if(!b)return null;let c=b.findIndex(d=>d.getElement()=== +a);if(c===-1)return null;c--;c<0&&(c=b.length-1);return b[c].getElement()}isNavigable(a){return this.policy.isNavigable(a)}isApplicable(a){return this.policy.isApplicable(a)}},module$build$src$core$keyboard_nav$flyout_navigation_policy={};module$build$src$core$keyboard_nav$flyout_navigation_policy.FlyoutNavigationPolicy=FlyoutNavigationPolicy$$module$build$src$core$keyboard_nav$flyout_navigation_policy;var FlyoutSeparator$$module$build$src$core$flyout_separator=class{constructor(a,b){this.gap=a;this.axis=b;this.y=this.x=0}getBoundingRectangle(){switch(this.axis){case "x":return new Rect$$module$build$src$core$utils$rect(this.y,this.y,this.x,this.x+this.gap);case "y":return new Rect$$module$build$src$core$utils$rect(this.y,this.y+this.gap,this.x,this.x)}}moveBy(a,b,c){this.x+=a;this.y+=b}isNavigable(){return!1}getFocusableElement(){throw Error("Cannot be focused");}getFocusableTree(){throw Error("Cannot be focused"); +}onNodeFocus(){}onNodeBlur(){}canBeFocused(){return!1}},module$build$src$core$flyout_separator={};module$build$src$core$flyout_separator.FlyoutSeparator=FlyoutSeparator$$module$build$src$core$flyout_separator;var FlyoutSeparatorNavigationPolicy$$module$build$src$core$keyboard_nav$flyout_separator_navigation_policy=class{getFirstChild(a){return null}getParent(a){return null}getNextSibling(a){return null}getPreviousSibling(a){return null}isNavigable(a){return!1}isApplicable(a){return a instanceof FlyoutSeparator$$module$build$src$core$flyout_separator}},module$build$src$core$keyboard_nav$flyout_separator_navigation_policy={}; +module$build$src$core$keyboard_nav$flyout_separator_navigation_policy.FlyoutSeparatorNavigationPolicy=FlyoutSeparatorNavigationPolicy$$module$build$src$core$keyboard_nav$flyout_separator_navigation_policy;var BlockCommentNavigationPolicy$$module$build$src$core$keyboard_nav$block_comment_navigation_policy=class{getFirstChild(a){return a.getEditor()}getParent(a){let b;return(b=a.getOwner())!=null?b:null}getNextSibling(a){return null}getPreviousSibling(a){return null}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof TextInputBubble$$module$build$src$core$bubbles$textinput_bubble}},module$build$src$core$keyboard_nav$block_comment_navigation_policy={}; +module$build$src$core$keyboard_nav$block_comment_navigation_policy.BlockCommentNavigationPolicy=BlockCommentNavigationPolicy$$module$build$src$core$keyboard_nav$block_comment_navigation_policy;var BlockNavigationPolicy$$module$build$src$core$keyboard_nav$block_navigation_policy=class{getFirstChild(a){return getBlockNavigationCandidates$$module$build$src$core$keyboard_nav$block_navigation_policy(a,!0)[0]}getParent(a){var b;if((b=a.previousConnection)==null?0:b.targetBlock()){if(b=a.getSurroundParent())return b}else{let c;if((c=a.outputConnection)==null?0:c.targetBlock())return a.outputConnection.targetBlock()}return a.workspace}getNextSibling(a){let b;if((b=a.nextConnection)==null?0:b.targetBlock()){let d; +return(d=a.nextConnection)==null?void 0:d.targetBlock()}let c;return((c=a.outputConnection)==null?0:c.targetBlock())?navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,1):a.getSurroundParent()?navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a.getTopStackBlock(),1):this.getParent(a)instanceof WorkspaceSvg$$module$build$src$core$workspace_svg?navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy(a,1):null}getPreviousSibling(a){let b; +if((b=a.previousConnection)==null?0:b.targetBlock()){let d;return(d=a.previousConnection)==null?void 0:d.targetBlock()}let c;return((c=a.outputConnection)==null?0:c.targetBlock())?navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,-1):this.getParent(a)instanceof WorkspaceSvg$$module$build$src$core$workspace_svg?navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy(a,-1):null}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof BlockSvg$$module$build$src$core$block_svg}}, +module$build$src$core$keyboard_nav$block_navigation_policy={};module$build$src$core$keyboard_nav$block_navigation_policy.BlockNavigationPolicy=BlockNavigationPolicy$$module$build$src$core$keyboard_nav$block_navigation_policy;module$build$src$core$keyboard_nav$block_navigation_policy.navigateBlock=navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy;module$build$src$core$keyboard_nav$block_navigation_policy.navigateStacks=navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy;var CommentBarButtonNavigationPolicy$$module$build$src$core$keyboard_nav$comment_bar_button_navigation_policy=class{getFirstChild(a){return null}getParent(a){return a.getCommentView().workspace.getCommentById(a.getCommentView().commentId)}getNextSibling(a){const b=a.getCommentView().getCommentBarButtons();a=b.indexOf(a);return a>=0&&a+10?b[a-1]:null}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof +CommentBarButton$$module$build$src$core$comments$comment_bar_button}},module$build$src$core$keyboard_nav$comment_bar_button_navigation_policy={};module$build$src$core$keyboard_nav$comment_bar_button_navigation_policy.CommentBarButtonNavigationPolicy=CommentBarButtonNavigationPolicy$$module$build$src$core$keyboard_nav$comment_bar_button_navigation_policy;var CommentEditorNavigationPolicy$$module$build$src$core$keyboard_nav$comment_editor_navigation_policy=class{getFirstChild(a){return null}getParent(a){return null}getNextSibling(a){return null}getPreviousSibling(a){return null}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof CommentEditor$$module$build$src$core$comments$comment_editor}},module$build$src$core$keyboard_nav$comment_editor_navigation_policy={}; +module$build$src$core$keyboard_nav$comment_editor_navigation_policy.CommentEditorNavigationPolicy=CommentEditorNavigationPolicy$$module$build$src$core$keyboard_nav$comment_editor_navigation_policy;var ConnectionNavigationPolicy$$module$build$src$core$keyboard_nav$connection_navigation_policy=class{getFirstChild(a){return a.getParentInput()?a.targetConnection:null}getParent(a){return a.getSourceBlock()}getNextSibling(a){if(a.getParentInput())return navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,1);if(a.type===ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT){const c=a.targetConnection;var b=a.getSourceBlock();if(!c&&b.getRootBlock().lastConnectionInStack(!1)=== +a){a=b.workspace.getTopBlocks(!0);b=a.indexOf(b.getRootBlock())+1;b>=a.length&&(b=0);b=a[b];let d;return(d=this.getParentConnection(b))!=null?d:b}return c}return a.getSourceBlock()}getPreviousSibling(a){if(a.getParentInput())return navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,-1);if(a.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT||a.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE){const c=a.targetConnection&& +!a.targetConnection.getParentInput()?a.targetConnection:null;var b=a.getSourceBlock();if(!c&&this.getParentConnection(b.getRootBlock())===a){a=b.workspace.getTopBlocks(!0);b=a.indexOf(b.getRootBlock())-1;b<0&&(b=a.length-1);b=a[b];let d;return(d=b.lastConnectionInStack(!1))!=null?d:b}return c}return a.type===ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT?a.getSourceBlock():null}getParentConnection(a){let b;return!a.outputConnection||((b=a.previousConnection)==null?0:b.isConnected())? +a.previousConnection:a.outputConnection}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof RenderedConnection$$module$build$src$core$rendered_connection}},module$build$src$core$keyboard_nav$connection_navigation_policy={};module$build$src$core$keyboard_nav$connection_navigation_policy.ConnectionNavigationPolicy=ConnectionNavigationPolicy$$module$build$src$core$keyboard_nav$connection_navigation_policy;var FieldNavigationPolicy$$module$build$src$core$keyboard_nav$field_navigation_policy=class{getFirstChild(a){return null}getParent(a){return a.getSourceBlock()}getNextSibling(a){return navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,1)}getPreviousSibling(a){return navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,-1)}isNavigable(a){let b;return a.canBeFocused()&&a.isVisible()&&(a.isClickable()||a.isCurrentlyEditable())&&!(((b=a.getSourceBlock())== +null?0:b.isSimpleReporter())&&a.isFullBlockField())&&a.getParentInput().isVisible()}isApplicable(a){return a instanceof Field$$module$build$src$core$field}},module$build$src$core$keyboard_nav$field_navigation_policy={};module$build$src$core$keyboard_nav$field_navigation_policy.FieldNavigationPolicy=FieldNavigationPolicy$$module$build$src$core$keyboard_nav$field_navigation_policy;var module$build$src$core$icons$registry={};module$build$src$core$icons$registry.register=register$$module$build$src$core$icons$registry;module$build$src$core$icons$registry.unregister=unregister$$module$build$src$core$icons$registry;var SIZE$$module$build$src$core$icons$comment_icon=17,DEFAULT_BUBBLE_WIDTH$$module$build$src$core$icons$comment_icon=160,DEFAULT_BUBBLE_HEIGHT$$module$build$src$core$icons$comment_icon=80,CommentIcon$$module$build$src$core$icons$comment_icon=class extends Icon$$module$build$src$core$icons$icon{constructor(a){super(a);this.sourceBlock=a;this.textInputBubble=null;this.text="";this.bubbleSize=new Size$$module$build$src$core$utils$size(DEFAULT_BUBBLE_WIDTH$$module$build$src$core$icons$comment_icon,DEFAULT_BUBBLE_HEIGHT$$module$build$src$core$icons$comment_icon); this.bubbleVisiblity=!1}getType(){return CommentIcon$$module$build$src$core$icons$comment_icon.TYPE}initView(a){this.svgRoot||(super.initView(a),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE,{"class":"blocklyIconShape",r:"8",cx:"8",cy:"8"},this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyIconSymbol",d:"m6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.4050.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25-1.201,0.998 -1.201,1.528 -1.204,2.19z"}, -this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyIconSymbol",x:"6.8",y:"10.78",height:"2",width:"2"},this.svgRoot),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blockly-icon-comment"))}dispose(){super.dispose();let a;null==(a=this.textInputBubble)||a.dispose()}getWeight(){return CommentIcon$$module$build$src$core$icons$comment_icon.WEIGHT}getSize(){return new Size$$module$build$src$core$utils$size(SIZE$$module$build$src$core$icons$comment_icon, -SIZE$$module$build$src$core$icons$comment_icon)}applyColour(){super.applyColour();const a=this.sourceBlock.getColour();let b;null==(b=this.textInputBubble)||b.setColour(a)}updateEditable(){const a=this,b=()=>super.updateEditable;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){b().call(a);a.bubbleIsVisible()&&(yield a.setBubbleVisible(!1),yield a.setBubbleVisible(!0))})}onLocationChange(a){super.onLocationChange(a);a=this.getAnchorLocation();let b;null==(b=this.textInputBubble)||b.setAnchorLocation(a)}setText(a){const b= -this.text;fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock,"comment",null,b,a));this.text=a;let c;null==(c=this.textInputBubble)||c.setText(this.text)}getText(){return this.text}setBubbleSize(a){this.bubbleSize=a;let b;null==(b=this.textInputBubble)||b.setSize(this.bubbleSize,!0)}getBubbleSize(){return this.bubbleSize}saveState(){return this.text?{text:this.text,pinned:this.bubbleIsVisible(), -height:this.bubbleSize.height,width:this.bubbleSize.width}:null}loadState(a){let b;this.text=null!=(b=a.text)?b:"";let c,d;this.bubbleSize=new Size$$module$build$src$core$utils$size(null!=(c=a.width)?c:DEFAULT_BUBBLE_WIDTH$$module$build$src$core$icons$comment_icon,null!=(d=a.height)?d:DEFAULT_BUBBLE_HEIGHT$$module$build$src$core$icons$comment_icon);let e;this.bubbleVisiblity=null!=(e=a.pinned)?e:!1;this.setBubbleVisible(this.bubbleVisiblity)}onClick(){super.onClick();this.setBubbleVisible(!this.bubbleIsVisible())}isClickableInFlyout(){return!1}onTextChange(){if(this.textInputBubble){var a= -this.textInputBubble.getText();this.text!==a&&(fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock,"comment",null,this.text,a)),this.text=a)}}onSizeChange(){this.textInputBubble&&(this.bubbleSize=this.textInputBubble.getSize())}bubbleIsVisible(){return this.bubbleVisiblity}setBubbleVisible(a){const b=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){b.bubbleVisiblity!== -a&&(b.bubbleVisiblity=a,yield finishQueuedRenders$$module$build$src$core$render_management(),!b.sourceBlock.rendered||b.sourceBlock.isInFlyout||b.sourceBlock.isInsertionMarker()||(a?(b.sourceBlock.isEditable()?b.showEditableBubble():b.showNonEditableBubble(),b.applyColour()):b.hideBubble(),fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BUBBLE_OPEN))(b.sourceBlock,a,"comment"))))})}showEditableBubble(){this.createBubble(); -let a;null==(a=this.textInputBubble)||a.addTextChangeListener(()=>this.onTextChange());let b;null==(b=this.textInputBubble)||b.addSizeChangeListener(()=>this.onSizeChange())}showNonEditableBubble(){this.createBubble();let a;null==(a=this.textInputBubble)||a.setEditable(!1)}createBubble(){this.textInputBubble=new TextInputBubble$$module$build$src$core$bubbles$textinput_bubble(this.sourceBlock.workspace,this.getAnchorLocation(),this.getBubbleOwnerRect());this.textInputBubble.setText(this.getText()); -this.textInputBubble.setSize(this.bubbleSize,!0)}hideBubble(){let a;null==(a=this.textInputBubble)||a.dispose();this.textInputBubble=null}getAnchorLocation(){const a=SIZE$$module$build$src$core$icons$comment_icon/2;return Coordinate$$module$build$src$core$utils$coordinate.sum(this.workspaceLocation,new Coordinate$$module$build$src$core$utils$coordinate(a,a))}getBubbleOwnerRect(){return this.sourceBlock.getBoundingRectangleWithoutChildren()}}; -CommentIcon$$module$build$src$core$icons$comment_icon.TYPE=IconType$$module$build$src$core$icons$icon_types.COMMENT;CommentIcon$$module$build$src$core$icons$comment_icon.WEIGHT=3;register$$module$build$src$core$icons$registry(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE,CommentIcon$$module$build$src$core$icons$comment_icon);var module$build$src$core$icons$comment_icon={};module$build$src$core$icons$comment_icon.CommentIcon=CommentIcon$$module$build$src$core$icons$comment_icon;var DuplicateIconType$$module$build$src$core$icons$exceptions=class extends Error{constructor(a){super(`Tried to append an icon of type ${a.getType()} when an icon of `+"that type already exists on the block. Use getIcon to access the existing icon.");this.icon=a}},module$build$src$core$icons$exceptions={};module$build$src$core$icons$exceptions.DuplicateIconType=DuplicateIconType$$module$build$src$core$icons$exceptions;var TextBubble$$module$build$src$core$bubbles$text_bubble=class extends Bubble$$module$build$src$core$bubbles$bubble{constructor(a,b,c,d){super(b,c,d);this.text=a;this.workspace=b;this.anchor=c;this.ownerRect=d;this.paragraph=this.stringToSvg(a,this.contentContainer);this.updateBubbleSize()}getText(){return this.text}setText(a){this.text=a;removeNode$$module$build$src$core$utils$dom(this.paragraph);this.paragraph=this.stringToSvg(a,this.contentContainer);this.updateBubbleSize()}stringToSvg(a,b){b= -this.createParagraph(b);a=this.createTextFragments(b,a);this.workspace.RTL&&this.rightAlignTextFragments(b.getBBox().width,a);return b}createParagraph(a){return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyText blocklyBubbleText blocklyNoPointerEvents",transform:`translate(0,${Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH})`,style:`direction: ${this.workspace.RTL?"rtl":"ltr"}`},a)}createTextFragments(a,b){let c=1;return b.split("\n").map(d=> -{const e=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT,{y:`${c}em`,x:Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH},a);d=document.createTextNode(d);e.appendChild(d);c+=1;return e})}rightAlignTextFragments(a,b){for(const c of b)c.setAttribute("text-anchor","start"),c.setAttribute("x",`${a+Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH}`)}updateBubbleSize(){const a=this.paragraph.getBBox();this.setSize(new Size$$module$build$src$core$utils$size(a.width+ -2*Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH,a.height+2*Bubble$$module$build$src$core$bubbles$bubble.BORDER_WIDTH),!0)}},module$build$src$core$bubbles$text_bubble={};module$build$src$core$bubbles$text_bubble.TextBubble=TextBubble$$module$build$src$core$bubbles$text_bubble;var SIZE$$module$build$src$core$icons$warning_icon=17,WarningIcon$$module$build$src$core$icons$warning_icon=class extends Icon$$module$build$src$core$icons$icon{constructor(a){super(a);this.sourceBlock=a;this.textMap=new Map;this.textBubble=null}getType(){return WarningIcon$$module$build$src$core$icons$warning_icon.TYPE}initView(a){this.svgRoot||(super.initView(a),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyIconShape",d:"M2,15Q-1,15 0.5,12L6.5,1.7Q8,-1 9.5,1.7L15.5,12Q17,15 14,15z"}, -this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyIconSymbol",d:"m7,4.8v3.16l0.27,2.27h1.46l0.27,-2.27v-3.16z"},this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyIconSymbol",x:"7",y:"11",height:"2",width:"2"},this.svgRoot),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blockly-icon-warning"))}dispose(){super.dispose();let a;null==(a=this.textBubble)|| -a.dispose()}getWeight(){return WarningIcon$$module$build$src$core$icons$warning_icon.WEIGHT}getSize(){return new Size$$module$build$src$core$utils$size(SIZE$$module$build$src$core$icons$warning_icon,SIZE$$module$build$src$core$icons$warning_icon)}applyColour(){super.applyColour();let a;null==(a=this.textBubble)||a.setColour(this.sourceBlock.getColour())}updateCollapsed(){}isShownWhenCollapsed(){return!0}onLocationChange(a){super.onLocationChange(a);let b;null==(b=this.textBubble)||b.setAnchorLocation(this.getAnchorLocation())}addMessage(a, -b){if(this.textMap.get(b)===a)return this;a?this.textMap.set(b,a):this.textMap.delete(b);let c;null==(c=this.textBubble)||c.setText(this.getText());return this}getText(){return[...this.textMap.values()].join("\n")}onClick(){super.onClick();this.setBubbleVisible(!this.bubbleIsVisible())}isClickableInFlyout(){return!1}bubbleIsVisible(){return!!this.textBubble}setBubbleVisible(a){const b=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(b.bubbleIsVisible()!==a){yield finishQueuedRenders$$module$build$src$core$render_management(); -if(a)b.textBubble=new TextBubble$$module$build$src$core$bubbles$text_bubble(b.getText(),b.sourceBlock.workspace,b.getAnchorLocation(),b.getBubbleOwnerRect()),b.applyColour();else{let c;null==(c=b.textBubble)||c.dispose();b.textBubble=null}fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BUBBLE_OPEN))(b.sourceBlock,a,"warning"))}})}getAnchorLocation(){const a=SIZE$$module$build$src$core$icons$warning_icon/2;return Coordinate$$module$build$src$core$utils$coordinate.sum(this.workspaceLocation, -new Coordinate$$module$build$src$core$utils$coordinate(a,a))}getBubbleOwnerRect(){const a=this.sourceBlock.getSvgRoot().getBBox();return new Rect$$module$build$src$core$utils$rect(a.y,a.y+a.height,a.x,a.x+a.width)}};WarningIcon$$module$build$src$core$icons$warning_icon.TYPE=IconType$$module$build$src$core$icons$icon_types.WARNING;WarningIcon$$module$build$src$core$icons$warning_icon.WEIGHT=2;var module$build$src$core$icons$warning_icon={};module$build$src$core$icons$warning_icon.WarningIcon=WarningIcon$$module$build$src$core$icons$warning_icon;var module$build$src$core$icons={};module$build$src$core$icons.CommentIcon=CommentIcon$$module$build$src$core$icons$comment_icon;module$build$src$core$icons.Icon=Icon$$module$build$src$core$icons$icon;module$build$src$core$icons.IconType=IconType$$module$build$src$core$icons$icon_types;module$build$src$core$icons.MutatorIcon=$.MutatorIcon$$module$build$src$core$icons$mutator_icon;module$build$src$core$icons.WarningIcon=WarningIcon$$module$build$src$core$icons$warning_icon; -module$build$src$core$icons.exceptions=module$build$src$core$icons$exceptions;module$build$src$core$icons.registry=module$build$src$core$icons$registry;var module$build$src$core$interfaces$i_procedure_block={};module$build$src$core$interfaces$i_procedure_block.isProcedureBlock=isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block;$.Names$$module$build$src$core$names=class{constructor(a,b){this.db=new Map;this.dbReverse=new Set;this.variableMap=null;this.variablePrefix=b||"";this.reservedWords=new Set(a?a.split(","):[])}reset(){this.db.clear();this.dbReverse.clear();this.variableMap=null}setVariableMap(a){this.variableMap=a}getNameForUserVariable(a){return this.variableMap?(a=this.variableMap.getVariableById(a))?a.name:null:(console.warn("Deprecated call to Names.prototype.getName without defining a variable map. To fix, add the following code in your generator's init() function:\nBlockly.YourGeneratorName.nameDB_.setVariableMap(workspace.getVariableMap());"), +this.svgRoot),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyIconSymbol",x:"6.8",y:"10.78",height:"2",width:"2"},this.svgRoot),addClass$$module$build$src$core$utils$dom(this.svgRoot,"blocklyCommentIcon"))}dispose(){super.dispose();let a;(a=this.textInputBubble)==null||a.dispose()}getWeight(){return CommentIcon$$module$build$src$core$icons$comment_icon.WEIGHT}getSize(){return new Size$$module$build$src$core$utils$size(SIZE$$module$build$src$core$icons$comment_icon, +SIZE$$module$build$src$core$icons$comment_icon)}applyColour(){super.applyColour();const a=this.sourceBlock.getColour();let b;(b=this.textInputBubble)==null||b.setColour(a)}updateEditable(){const a=this,b=()=>super.updateEditable;return(0,$jscomp.asyncExecutePromiseGeneratorFunction)(function*(){b().call(a);a.bubbleIsVisible()&&(yield a.setBubbleVisible(!1),yield a.setBubbleVisible(!0))})}onLocationChange(a){const b=this.workspaceLocation;super.onLocationChange(a);this.bubbleLocation&&(a=Coordinate$$module$build$src$core$utils$coordinate.difference(this.workspaceLocation, +b),this.bubbleLocation=Coordinate$$module$build$src$core$utils$coordinate.sum(this.bubbleLocation,a));a=this.getAnchorLocation();let c;(c=this.textInputBubble)==null||c.setAnchorLocation(a)}setText(a){const b=this.text;fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock,"comment",null,b,a));this.text=a;let c;(c=this.textInputBubble)==null||c.setText(this.text)}getText(){return this.text}setBubbleSize(a){this.bubbleSize= +a;let b;(b=this.textInputBubble)==null||b.setSize(this.bubbleSize,!0)}getBubbleSize(){return this.bubbleSize}setBubbleLocation(a){this.bubbleLocation=a;let b;(b=this.textInputBubble)==null||b.moveDuringDrag(a)}getBubbleLocation(){return this.bubbleLocation}saveState(){if(this.text){const a={text:this.text,pinned:this.bubbleIsVisible(),height:this.bubbleSize.height,width:this.bubbleSize.width},b=this.getBubbleLocation();b&&(a.x=this.sourceBlock.workspace.RTL?this.sourceBlock.workspace.getWidth()-(b.x+ +this.bubbleSize.width):b.x,a.y=b.y);return a}return null}loadState(a){let b;this.text=(b=a.text)!=null?b:"";let c,d;this.bubbleSize=new Size$$module$build$src$core$utils$size((c=a.width)!=null?c:DEFAULT_BUBBLE_WIDTH$$module$build$src$core$icons$comment_icon,(d=a.height)!=null?d:DEFAULT_BUBBLE_HEIGHT$$module$build$src$core$icons$comment_icon);let e;this.bubbleVisiblity=(e=a.pinned)!=null?e:!1;this.setBubbleVisible(this.bubbleVisiblity);let f=a.x;const g=a.y;finishQueuedRenders$$module$build$src$core$render_management().then(()=> +{f&&g&&(f=this.sourceBlock.workspace.RTL?this.sourceBlock.workspace.getWidth()-(f+this.bubbleSize.width):f,this.setBubbleLocation(new Coordinate$$module$build$src$core$utils$coordinate(f,g)))})}onClick(){super.onClick();this.setBubbleVisible(!this.bubbleIsVisible())}isClickableInFlyout(){return!1}onTextChange(){if(this.textInputBubble){var a=this.textInputBubble.getText();this.text!==a&&(fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock, +"comment",null,this.text,a)),this.text=a)}}onSizeChange(){this.textInputBubble&&(this.bubbleSize=this.textInputBubble.getSize())}onBubbleLocationChange(){this.textInputBubble&&(this.bubbleLocation=this.textInputBubble.getRelativeToSurfaceXY())}bubbleIsVisible(){return this.bubbleVisiblity}setBubbleVisible(a){const b=this;return(0,$jscomp.asyncExecutePromiseGeneratorFunction)(function*(){b.bubbleVisiblity!==a&&(b.bubbleVisiblity=a,yield finishQueuedRenders$$module$build$src$core$render_management(), +!b.sourceBlock.rendered||b.sourceBlock.isInFlyout||b.sourceBlock.isInsertionMarker()||(a?(b.sourceBlock.isEditable()?b.showEditableBubble():b.showNonEditableBubble(),b.applyColour()):b.hideBubble(),fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BUBBLE_OPEN))(b.sourceBlock,a,"comment"))))})}getBubble(){return this.textInputBubble}showEditableBubble(){this.createBubble();let a;(a=this.textInputBubble)==null||a.addTextChangeListener(()=> +this.onTextChange());let b;(b=this.textInputBubble)==null||b.addSizeChangeListener(()=>this.onSizeChange())}showNonEditableBubble(){this.createBubble();let a;(a=this.textInputBubble)==null||a.setEditable(!1)}createBubble(){this.textInputBubble=new TextInputBubble$$module$build$src$core$bubbles$textinput_bubble(this.sourceBlock.workspace,this.getAnchorLocation(),this.getBubbleOwnerRect(),this);this.textInputBubble.setText(this.getText());this.textInputBubble.setSize(this.bubbleSize,!0);this.bubbleLocation&& +this.textInputBubble.moveDuringDrag(this.bubbleLocation);this.textInputBubble.addTextChangeListener(()=>this.onTextChange());this.textInputBubble.addSizeChangeListener(()=>this.onSizeChange());this.textInputBubble.addLocationChangeListener(()=>this.onBubbleLocationChange())}hideBubble(){let a;(a=this.textInputBubble)==null||a.dispose();this.textInputBubble=null}getAnchorLocation(){const a=SIZE$$module$build$src$core$icons$comment_icon/2;return Coordinate$$module$build$src$core$utils$coordinate.sum(this.workspaceLocation, +new Coordinate$$module$build$src$core$utils$coordinate(a,a))}getBubbleOwnerRect(){return this.sourceBlock.getBoundingRectangleWithoutChildren()}};CommentIcon$$module$build$src$core$icons$comment_icon.TYPE=IconType$$module$build$src$core$icons$icon_types.COMMENT;CommentIcon$$module$build$src$core$icons$comment_icon.WEIGHT=3;register$$module$build$src$core$icons$registry(CommentIcon$$module$build$src$core$icons$comment_icon.TYPE,CommentIcon$$module$build$src$core$icons$comment_icon); +var module$build$src$core$icons$comment_icon={};module$build$src$core$icons$comment_icon.CommentIcon=CommentIcon$$module$build$src$core$icons$comment_icon;var IconNavigationPolicy$$module$build$src$core$keyboard_nav$icon_navigation_policy=class{getFirstChild(a){if(a instanceof $.MutatorIcon$$module$build$src$core$icons$mutator_icon&&a.bubbleIsVisible()&&$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode()===a){let b,c;return(c=(b=a.getBubble())==null?void 0:b.getWorkspace())!=null?c:null}if(a instanceof CommentIcon$$module$build$src$core$icons$comment_icon&&a.bubbleIsVisible()&&$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode()=== +a){let b,c;return(c=(b=a.getBubble())==null?void 0:b.getEditor())!=null?c:null}return null}getParent(a){return a.getSourceBlock()}getNextSibling(a){return navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,1)}getPreviousSibling(a){return navigateBlock$$module$build$src$core$keyboard_nav$block_navigation_policy(a,-1)}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof Icon$$module$build$src$core$icons$icon}},module$build$src$core$keyboard_nav$icon_navigation_policy= +{};module$build$src$core$keyboard_nav$icon_navigation_policy.IconNavigationPolicy=IconNavigationPolicy$$module$build$src$core$keyboard_nav$icon_navigation_policy;var WorkspaceCommentNavigationPolicy$$module$build$src$core$keyboard_nav$workspace_comment_navigation_policy=class{getFirstChild(a){return a.view.getCommentBarButtons()[0]}getParent(a){return a.workspace}getNextSibling(a){return navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy(a,1)}getPreviousSibling(a){return navigateStacks$$module$build$src$core$keyboard_nav$block_navigation_policy(a,-1)}isNavigable(a){return a.canBeFocused()}isApplicable(a){return a instanceof RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment}}, +module$build$src$core$keyboard_nav$workspace_comment_navigation_policy={};module$build$src$core$keyboard_nav$workspace_comment_navigation_policy.WorkspaceCommentNavigationPolicy=WorkspaceCommentNavigationPolicy$$module$build$src$core$keyboard_nav$workspace_comment_navigation_policy;var WorkspaceNavigationPolicy$$module$build$src$core$keyboard_nav$workspace_navigation_policy=class{getFirstChild(a){a=a.getTopBlocks(!0);return a.length?a[0]:null}getParent(a){return null}getNextSibling(a){return null}getPreviousSibling(a){return null}isNavigable(a){return a.canBeFocused()&&!a.isMutator}isApplicable(a){return a instanceof WorkspaceSvg$$module$build$src$core$workspace_svg}},module$build$src$core$keyboard_nav$workspace_navigation_policy={}; +module$build$src$core$keyboard_nav$workspace_navigation_policy.WorkspaceNavigationPolicy=WorkspaceNavigationPolicy$$module$build$src$core$keyboard_nav$workspace_navigation_policy;var Navigator$$module$build$src$core$navigator=class{constructor(){this.rules=[new BlockNavigationPolicy$$module$build$src$core$keyboard_nav$block_navigation_policy,new FieldNavigationPolicy$$module$build$src$core$keyboard_nav$field_navigation_policy,new ConnectionNavigationPolicy$$module$build$src$core$keyboard_nav$connection_navigation_policy,new WorkspaceNavigationPolicy$$module$build$src$core$keyboard_nav$workspace_navigation_policy,new IconNavigationPolicy$$module$build$src$core$keyboard_nav$icon_navigation_policy, +new WorkspaceCommentNavigationPolicy$$module$build$src$core$keyboard_nav$workspace_comment_navigation_policy,new CommentBarButtonNavigationPolicy$$module$build$src$core$keyboard_nav$comment_bar_button_navigation_policy,new BlockCommentNavigationPolicy$$module$build$src$core$keyboard_nav$block_comment_navigation_policy,new CommentEditorNavigationPolicy$$module$build$src$core$keyboard_nav$comment_editor_navigation_policy]}addNavigationPolicy(a){this.rules.push(a)}get(a){return this.rules.find(b=>b.isApplicable(a))}getFirstChild(a){let b; +const c=(b=this.get(a))==null?void 0:b.getFirstChild(a);if(!c)return null;let d;return(d=this.get(c))!=null&&d.isNavigable(c)?c:this.getFirstChild(c)||this.getNextSibling(c)}getParent(a){let b;const c=(b=this.get(a))==null?void 0:b.getParent(a);if(!c)return null;let d;return(d=this.get(c))!=null&&d.isNavigable(c)?c:this.getParent(c)}getNextSibling(a){let b;const c=(b=this.get(a))==null?void 0:b.getNextSibling(a);if(!c)return null;let d;return(d=this.get(c))!=null&&d.isNavigable(c)?c:this.getNextSibling(c)}getPreviousSibling(a){let b; +const c=(b=this.get(a))==null?void 0:b.getPreviousSibling(a);if(!c)return null;let d;return(d=this.get(c))!=null&&d.isNavigable(c)?c:this.getPreviousSibling(c)}},module$build$src$core$navigator={};module$build$src$core$navigator.Navigator=Navigator$$module$build$src$core$navigator;var FlyoutNavigator$$module$build$src$core$flyout_navigator=class extends Navigator$$module$build$src$core$navigator{constructor(a){super();this.rules.push(new FlyoutButtonNavigationPolicy$$module$build$src$core$keyboard_nav$flyout_button_navigation_policy,new FlyoutSeparatorNavigationPolicy$$module$build$src$core$keyboard_nav$flyout_separator_navigation_policy);this.rules=this.rules.map(b=>new FlyoutNavigationPolicy$$module$build$src$core$keyboard_nav$flyout_navigation_policy(b,a))}},module$build$src$core$flyout_navigator= +{};module$build$src$core$flyout_navigator.FlyoutNavigator=FlyoutNavigator$$module$build$src$core$flyout_navigator;var ScrollbarPair$$module$build$src$core$scrollbar_pair=class{constructor(a,b,c,d,e){this.workspace=a;this.oldHostMetrics=this.corner_=this.vScroll=this.hScroll=null;b=b===void 0?!0:b;c=c===void 0?!0:c;const f=b&&c;b&&(this.hScroll=new Scrollbar$$module$build$src$core$scrollbar(a,!0,f,d,e));c&&(this.vScroll=new Scrollbar$$module$build$src$core$scrollbar(a,!1,f,d,e));f&&(this.corner_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{height:Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness, +width:Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness,"class":"blocklyScrollbarBackground"}),insertAfter$$module$build$src$core$utils$dom(this.corner_,a.getBubbleCanvas()))}dispose(){removeNode$$module$build$src$core$utils$dom(this.corner_);this.oldHostMetrics=this.corner_=null;this.hScroll&&(this.hScroll.dispose(),this.hScroll=null);this.vScroll&&(this.vScroll.dispose(),this.vScroll=null)}resize(){const a=this.workspace.getMetrics();if(a){var b=!1,c=!1;this.oldHostMetrics&&this.oldHostMetrics.viewWidth=== +a.viewWidth&&this.oldHostMetrics.viewHeight===a.viewHeight&&this.oldHostMetrics.absoluteTop===a.absoluteTop&&this.oldHostMetrics.absoluteLeft===a.absoluteLeft?(this.oldHostMetrics&&this.oldHostMetrics.scrollWidth===a.scrollWidth&&this.oldHostMetrics.viewLeft===a.viewLeft&&this.oldHostMetrics.scrollLeft===a.scrollLeft||(b=!0),this.oldHostMetrics&&this.oldHostMetrics.scrollHeight===a.scrollHeight&&this.oldHostMetrics.viewTop===a.viewTop&&this.oldHostMetrics.scrollTop===a.scrollTop||(c=!0)):c=b=!0;if(b|| +c){try{$.disable$$module$build$src$core$events$utils(),this.hScroll&&b&&this.hScroll.resize(a),this.vScroll&&c&&this.vScroll.resize(a)}finally{$.enable$$module$build$src$core$events$utils()}this.workspace.maybeFireViewportChangeEvent()}if(this.hScroll&&this.vScroll){if(!this.oldHostMetrics||this.oldHostMetrics.viewWidth!==a.viewWidth||this.oldHostMetrics.absoluteLeft!==a.absoluteLeft){let d;(d=this.corner_)==null||d.setAttribute("x",String(this.vScroll.position.x))}if(!this.oldHostMetrics||this.oldHostMetrics.viewHeight!== +a.viewHeight||this.oldHostMetrics.absoluteTop!==a.absoluteTop){let d;(d=this.corner_)==null||d.setAttribute("y",String(this.hScroll.position.y))}}this.oldHostMetrics=a}}canScrollHorizontally(){return!!this.hScroll}canScrollVertically(){return!!this.vScroll}setOrigin(a,b){this.hScroll&&this.hScroll.setOrigin(a,b);this.vScroll&&this.vScroll.setOrigin(a,b)}set(a,b,c){this.hScroll&&this.hScroll.set(a,!1);this.vScroll&&this.vScroll.set(b,!1);if(c||c===void 0)a={},this.hScroll&&(a.x=this.hScroll.getRatio_()), +this.vScroll&&(a.y=this.vScroll.getRatio_()),this.workspace.setMetrics(a)}setX(a){this.hScroll&&this.hScroll.set(a,!0)}setY(a){this.vScroll&&this.vScroll.set(a,!0)}setContainerVisible(a){this.hScroll&&this.hScroll.setContainerVisible(a);this.vScroll&&this.vScroll.setContainerVisible(a)}isVisible(){let a=!1;this.hScroll&&(a=this.hScroll.isVisible());this.vScroll&&(a=a||this.vScroll.isVisible());return a}setVisible(a){this.hScroll&&this.hScroll.setVisibleInternal(a);this.vScroll&&this.vScroll.setVisibleInternal(a)}resizeContent(a){this.hScroll&& +this.hScroll.resizeContentHorizontal(a);this.vScroll&&this.vScroll.resizeContentVertical(a)}resizeView(a){this.hScroll&&this.hScroll.resizeViewHorizontal(a);this.vScroll&&this.vScroll.resizeViewVertical(a)}},module$build$src$core$scrollbar_pair={};module$build$src$core$scrollbar_pair.ScrollbarPair=ScrollbarPair$$module$build$src$core$scrollbar_pair;var SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater="sep",SeparatorFlyoutInflater$$module$build$src$core$separator_flyout_inflater=class{load(a,b){a=new FlyoutSeparator$$module$build$src$core$flyout_separator(0,b.horizontalLayout?"x":"y");return new FlyoutItem$$module$build$src$core$flyout_item(a,SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater)}gapForItem(a,b){let c;return(c=parseInt(String(a.gap)))!=null?c:b}disposeItem(a){}getType(){return SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater}}; +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUT_INFLATER,SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater,SeparatorFlyoutInflater$$module$build$src$core$separator_flyout_inflater);var module$build$src$core$separator_flyout_inflater={SEPARATOR_TYPE:SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater};module$build$src$core$separator_flyout_inflater.SeparatorFlyoutInflater=SeparatorFlyoutInflater$$module$build$src$core$separator_flyout_inflater;var Flyout$$module$build$src$core$flyout_base=class extends DeleteArea$$module$build$src$core$delete_area{constructor(a){super();this.horizontalLayout=!1;this.boundEvents=[];this.reflowWrapper=null;this.inhibitReflowWrapper=!1;this.contents=[];this.autoClose=!0;this.visible=!1;this.containerVisible=!0;this.CORNER_RADIUS=8;this.SCROLLBAR_MARGIN=2.5;this.height_=this.width_=0;this.dragAngleRange_=70;this.svgGroup_=this.svgBackground_=null;this.inflaters=new Map;a.setMetrics=this.setMetrics_.bind(this); +this.workspace_=new WorkspaceSvg$$module$build$src$core$workspace_svg(a);this.workspace_.setMetricsManager(new FlyoutMetricsManager$$module$build$src$core$flyout_metrics_manager(this.workspace_,this));this.workspace_.internalIsFlyout=!0;this.workspace_.setVisible(this.visible);this.workspace_.setNavigator(new FlyoutNavigator$$module$build$src$core$flyout_navigator(this));this.id=genUid$$module$build$src$core$utils$idgenerator();this.RTL=!!a.RTL;this.toolboxPosition_=a.toolboxPosition;this.tabWidth_= +this.workspace_.getRenderer().getConstants().TAB_WIDTH;this.MARGIN=this.CORNER_RADIUS;this.GAP_X=this.MARGIN*3;this.GAP_Y=this.MARGIN*3}createDom(a){this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(a,{"class":"blocklyFlyout"});this.svgGroup_.style.display="none";this.svgBackground_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyFlyoutBackground"},this.svgGroup_);this.svgGroup_.appendChild(this.workspace_.createDom());this.workspace_.getThemeManager().subscribe(this.svgBackground_, +"flyoutBackgroundColour","fill");this.workspace_.getThemeManager().subscribe(this.svgBackground_,"flyoutOpacity","fill-opacity");return this.svgGroup_}init(a){this.targetWorkspace=a;this.workspace_.targetWorkspace=a;this.workspace_.scrollbar=new ScrollbarPair$$module$build$src$core$scrollbar_pair(this.workspace_,this.horizontalLayout,!this.horizontalLayout,"blocklyFlyoutScrollbar",this.SCROLLBAR_MARGIN);this.hide();this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(this.svgGroup_, +"wheel",this,this.wheel_,!1,{passive:!1}));this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(this.svgBackground_,"pointerdown",this,this.onMouseDown));this.workspace_.getGesture=this.targetWorkspace.getGesture.bind(this.targetWorkspace);this.workspace_.setVariableMap(this.targetWorkspace.getVariableMap());this.workspace_.createPotentialVariableMap();a.getComponentManager().addComponent({component:this,weight:ComponentManager$$module$build$src$core$component_manager.ComponentWeight.FLYOUT_WEIGHT, +capabilities:[ComponentManager$$module$build$src$core$component_manager.Capability.AUTOHIDEABLE,ComponentManager$$module$build$src$core$component_manager.Capability.DELETE_AREA,ComponentManager$$module$build$src$core$component_manager.Capability.DRAG_TARGET]})}dispose(){this.hide();this.targetWorkspace.getComponentManager().removeComponent(this.id);for(const a of this.boundEvents)unbind$$module$build$src$core$browser_events(a);this.boundEvents.length=0;this.workspace_&&(this.workspace_.getThemeManager().unsubscribe(this.svgBackground_), +this.workspace_.dispose());this.svgGroup_&&removeNode$$module$build$src$core$utils$dom(this.svgGroup_)}getWidth(){return this.width_}getHeight(){return this.height_}getFlyoutScale(){return this.targetWorkspace.scale}getWorkspace(){return this.workspace_}setAutoClose(a){this.autoClose=a;this.targetWorkspace.recordDragTargets();this.targetWorkspace.resizeContents()}autoHide(a){!a&&this.targetWorkspace.getFlyout(!0)===this&&this.autoClose&&this.hide()}getTargetWorkspace(){return this.targetWorkspace}isVisible(){return this.visible}setVisible(a){const b= +a!==this.isVisible();this.visible=a;b&&(this.autoClose||this.targetWorkspace.recordDragTargets(),this.updateDisplay())}setContainerVisible(a){const b=a!==this.containerVisible;this.containerVisible=a;b&&this.updateDisplay()}getContents(){return this.contents}setContents(a){this.contents=a}updateDisplay(){let a;a=this.containerVisible?this.isVisible():!1;this.svgGroup_&&(this.svgGroup_.style.display=a?"block":"none");let b;(b=this.workspace_.scrollbar)==null||b.setContainerVisible(a)}positionAt_(a, +b,c,d){let e;(e=this.svgGroup_)==null||e.setAttribute("width",`${a}`);let f;(f=this.svgGroup_)==null||f.setAttribute("height",`${b}`);this.workspace_.setCachedParentSvgSize(a,b);this.svgGroup_&&setCssTransform$$module$build$src$core$utils$dom(this.svgGroup_,"translate("+c+"px,"+d+"px)");if(a=this.workspace_.scrollbar)a.setOrigin(c,d),a.resize(),a.hScroll&&a.hScroll.setPosition(a.hScroll.position.x,a.hScroll.position.y),a.vScroll&&a.vScroll.setPosition(a.vScroll.position.x,a.vScroll.position.y)}hide(){this.isVisible()&& +(this.setVisible(!1),this.reflowWrapper&&(this.workspace_.removeChangeListener(this.reflowWrapper),this.reflowWrapper=null))}show(a){this.workspace_.setResizesEnabled(!1);$.setRecordUndo$$module$build$src$core$events$utils(!1);this.hide();this.clearOldBlocks();typeof a==="string"&&(a=this.getDynamicCategoryContents(a));this.setVisible(!0);a=convertFlyoutDefToJsonArray$$module$build$src$core$utils$toolbox(a);a=this.createFlyoutInfo(a);triggerQueuedRenders$$module$build$src$core$render_management(this.workspace_); +this.setContents(a);this.layout_(a);this.horizontalLayout?this.height_=0:this.width_=0;this.reflow();$.setRecordUndo$$module$build$src$core$events$utils(!0);this.workspace_.setResizesEnabled(!0);this.reflowWrapper=b=>{this.inhibitReflowWrapper||b.type!==EventType$$module$build$src$core$events$type.BLOCK_CHANGE&&b.type!==EventType$$module$build$src$core$events$type.BLOCK_FIELD_INTERMEDIATE_CHANGE||this.reflow()};this.workspace_.addChangeListener(this.reflowWrapper)}createFlyoutInfo(a){const b=[],c= +this.horizontalLayout?this.GAP_X:this.GAP_Y;for(const d of a)if("custom"in d&&(a=this.getDynamicCategoryContents(d.custom),a=convertFlyoutDefToJsonArray$$module$build$src$core$utils$toolbox(a),b.push(...this.createFlyoutInfo(a))),a=d.kind.toLowerCase(),a=this.getInflaterForType(a))b.push(a.load(d,this)),(a=a.gapForItem(d,c))&&b.push(new FlyoutItem$$module$build$src$core$flyout_item(new FlyoutSeparator$$module$build$src$core$flyout_separator(a,this.horizontalLayout?"x":"y"),SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater)); +return this.normalizeSeparators(b)}normalizeSeparators(a){for(let b=a.length-1;b>0;b--){const c=a[b].getType().toLowerCase(),d=a[b-1].getType().toLowerCase();c===SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater&&d===SEPARATOR_TYPE$$module$build$src$core$separator_flyout_inflater&&a.splice(b-1,1)}return a}getDynamicCategoryContents(a){a=this.workspace_.targetWorkspace.getToolboxCategoryCallback(a);if(typeof a!=="function")throw TypeError("Couldn't find a callback function when opening a toolbox category."); +return a(this.workspace_.targetWorkspace)}clearOldBlocks(){this.getContents().forEach(b=>{let c;(c=this.getInflaterForType(b.getType()))==null||c.disposeItem(b)});let a;(a=this.workspace_.getPotentialVariableMap())==null||a.clear()}onMouseDown(a){const b=this.targetWorkspace.getGesture(a);b&&b.handleFlyoutStart(a,this)}isBlockCreatable(a){return a.isEnabled()&&!this.getTargetWorkspace().isReadOnly()}createBlock(a){const b=this.targetWorkspace;if(!a.getSvgRoot())throw Error("oldBlock is not rendered"); +var c=this.serializeBlock(a);b.setResizesEnabled(!1);c=appendInternal$$module$build$src$core$serialization$blocks(c,b,{recordUndo:!0});this.positionNewBlock(a,c);b.hideChaff();return c}reflow(){this.inhibitReflowWrapper=!0;this.reflowInternal_();this.inhibitReflowWrapper=!1}isScrollable(){return this.workspace_.scrollbar?this.workspace_.scrollbar.isVisible():!1}serializeBlock(a){return save$$module$build$src$core$serialization$blocks(a)}positionNewBlock(a,b){const c=this.targetWorkspace;var d=c.getOriginOffsetInPixels(), +e=this.workspace_.getOriginOffsetInPixels();a=a.getRelativeToSurfaceXY();a.scale(this.workspace_.scale);e=Coordinate$$module$build$src$core$utils$coordinate.sum(e,a);d=Coordinate$$module$build$src$core$utils$coordinate.difference(e,d);d.scale(1/c.scale);b.moveTo(new Coordinate$$module$build$src$core$utils$coordinate(d.x,d.y))}getInflaterForType(a){if(this.inflaters.has(a)){var b;return(b=this.inflaters.get(a))!=null?b:null}return(b=getClass$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUT_INFLATER, +a))?(b=new b,this.inflaters.set(a,b),b):null}getFocusableElement(){throw Error("Flyouts are not directly focusable.");}getFocusableTree(){throw Error("Flyouts are not directly focusable.");}onNodeFocus(){}onNodeBlur(){}canBeFocused(){return!1}getRootFocusableNode(){throw Error("Flyouts are not directly focusable.");}getRestoredFocusableNode(a){throw Error("Flyouts are not directly focusable.");}getNestedTrees(){throw Error("Flyouts are not directly focusable.");}lookUpFocusableNode(a){throw Error("Flyouts are not directly focusable."); +}onTreeFocus(a,b){}onTreeBlur(a){throw Error("Flyouts are not directly focusable.");}},module$build$src$core$flyout_base={};module$build$src$core$flyout_base.Flyout=Flyout$$module$build$src$core$flyout_base;var module$build$src$core$interfaces$i_contextmenu={};module$build$src$core$interfaces$i_contextmenu.hasContextMenu=hasContextMenu$$module$build$src$core$interfaces$i_contextmenu;var module$build$src$core$interfaces$i_draggable={};module$build$src$core$interfaces$i_draggable.isDraggable=isDraggable$$module$build$src$core$interfaces$i_draggable;var KeyboardNavigationController$$module$build$src$core$keyboard_navigation_controller=class{constructor(){this.isActive=!1;this.activeClassName="blocklyKeyboardNavigation"}setIsActive(a=!0){this.isActive=a;this.updateActiveVisualization()}getIsActive(){return this.isActive}updateActiveVisualization(){this.isActive?document.body.classList.add(this.activeClassName):document.body.classList.remove(this.activeClassName)}},keyboardNavigationController$$module$build$src$core$keyboard_navigation_controller= +new KeyboardNavigationController$$module$build$src$core$keyboard_navigation_controller,module$build$src$core$keyboard_navigation_controller={};module$build$src$core$keyboard_navigation_controller.KeyboardNavigationController=KeyboardNavigationController$$module$build$src$core$keyboard_navigation_controller;module$build$src$core$keyboard_navigation_controller.keyboardNavigationController=keyboardNavigationController$$module$build$src$core$keyboard_navigation_controller;var WorkspaceDragger$$module$build$src$core$workspace_dragger=class{constructor(a){this.workspace=a;this.horizontalScrollEnabled=this.workspace.isMovableHorizontally();this.verticalScrollEnabled=this.workspace.isMovableVertically();this.startScrollXY_=new Coordinate$$module$build$src$core$utils$coordinate(a.scrollX,a.scrollY)}startDrag(){}endDrag(a){this.drag(a)}drag(a){a=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startScrollXY_,a);if(this.horizontalScrollEnabled&&this.verticalScrollEnabled)this.workspace.scroll(a.x, +a.y);else if(this.horizontalScrollEnabled)this.workspace.scroll(a.x,this.workspace.scrollY);else if(this.verticalScrollEnabled)this.workspace.scroll(this.workspace.scrollX,a.y);else throw new TypeError("Invalid state.");}},module$build$src$core$workspace_dragger={};module$build$src$core$workspace_dragger.WorkspaceDragger=WorkspaceDragger$$module$build$src$core$workspace_dragger;var ZOOM_IN_MULTIPLIER$$module$build$src$core$gesture=5,ZOOM_OUT_MULTIPLIER$$module$build$src$core$gesture=6,Gesture$$module$build$src$core$gesture=class{constructor(a,b){this.creatorWorkspace=b;this.mouseDownXY=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.startWorkspace_=this.targetBlock=this.startComment=this.startBlock=this.startIcon=this.startField=this.startBubble=null;this.hasExceededDragRadius=!1;this.boundEvents=[];this.workspaceDragger=this.dragger=null;this.dragging= +!1;this.flyout=null;this.multiTouch=this.isEnding_=this.gestureHasStarted=this.calledUpdateIsDragging=!1;this.cachedPoints=new Map;this.startDistance=this.previousScale=0;this.currentDropdownOwner=this.isPinchZoomEnabled=null;this.mostRecentEvent=a;this.currentDragDeltaXY=new Coordinate$$module$build$src$core$utils$coordinate(0,0)}dispose(){clearTouchIdentifier$$module$build$src$core$touch();unblock$$module$build$src$core$tooltip();this.creatorWorkspace.clearGesture();for(const a of this.boundEvents)unbind$$module$build$src$core$browser_events(a); +this.boundEvents.length=0}updateFromEvent(a){const b=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY);this.updateDragDelta(b)&&(this.updateIsDragging(a),longStop$$module$build$src$core$touch());this.mostRecentEvent=a}updateDragDelta(a){this.currentDragDeltaXY=Coordinate$$module$build$src$core$utils$coordinate.difference(a,this.mouseDownXY);return this.hasExceededDragRadius?!1:this.hasExceededDragRadius=Coordinate$$module$build$src$core$utils$coordinate.magnitude(this.currentDragDeltaXY)> +(this.flyout?$.config$$module$build$src$core$config.flyoutDragRadius:$.config$$module$build$src$core$config.dragRadius)}updateIsDraggingFromFlyout(){let a;if(!this.targetBlock||(a=this.flyout)==null||!a.isBlockCreatable(this.targetBlock))return!1;if(!this.flyout.targetWorkspace)throw Error("Cannot update dragging from the flyout because the ' +\n 'flyout's target workspace is undefined");this.startWorkspace_=this.flyout.targetWorkspace;this.startWorkspace_.updateScreenCalculationsIfScrolled(); +$.getGroup$$module$build$src$core$events$utils()||$.setGroup$$module$build$src$core$events$utils(!0);this.startBlock=null;this.targetBlock=this.flyout.createBlock(this.targetBlock);$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this.targetBlock);return!0}updateIsDraggingWorkspace(){if(!this.startWorkspace_)throw Error("Cannot update dragging the workspace because the start workspace is undefined");if(this.flyout?this.flyout.isScrollable():this.startWorkspace_&&this.startWorkspace_.isDraggable())this.dragging= +!0,this.workspaceDragger=new WorkspaceDragger$$module$build$src$core$workspace_dragger(this.startWorkspace_),this.workspaceDragger.startDrag()}updateIsDragging(a){if(!this.startWorkspace_)throw Error("Cannot update dragging because the start workspace is undefined");if(this.calledUpdateIsDragging)throw Error("updateIsDragging_ should only be called once per gesture.");this.calledUpdateIsDragging=!0;this.flyout&&this.updateIsDraggingFromFlyout();const b=getSelected$$module$build$src$core$common(); +b&&isDraggable$$module$build$src$core$interfaces$i_draggable(b)&&b.isMovable()?(this.dragging=!0,this.dragger=this.createDragger(b,this.startWorkspace_),this.dragger.onDragStart(a),this.dragger.onDrag(a,this.currentDragDeltaXY)):this.updateIsDraggingWorkspace()}createDragger(a,b){return new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.BLOCK_DRAGGER,this.creatorWorkspace.options,!0))(a,b)}doStart(a){if(!this.startWorkspace_)throw Error("Cannot start the touch gesture becauase the start workspace is undefined"); +this.isPinchZoomEnabled=this.startWorkspace_.options.zoomOptions&&this.startWorkspace_.options.zoomOptions.pinch;isTargetInput$$module$build$src$core$browser_events(a)?this.cancel():(this.gestureHasStarted=!0,disconnectUiStop$$module$build$src$core$block_animations(),this.startWorkspace_.updateScreenCalculationsIfScrolled(),this.startWorkspace_.isMutator&&this.startWorkspace_.resize(),this.currentDropdownOwner=getOwner$$module$build$src$core$dropdowndiv(),this.startWorkspace_.hideChaff(!!this.flyout), +this.startWorkspace_.markFocused(),this.mostRecentEvent=a,block$$module$build$src$core$tooltip(),isRightButton$$module$build$src$core$browser_events(a)?this.handleRightClick(a):(a.type.toLowerCase()==="pointerdown"&&a.pointerType!=="mouse"&&longStart$$module$build$src$core$touch(a,this),this.mouseDownXY=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY),this.bindMouseEvents(a),this.isEnding_||this.handleTouchStart(a)))}bindMouseEvents(a){this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document, +"pointerdown",null,this.handleStart.bind(this),!0));this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document,"pointermove",null,this.handleMove.bind(this),!0));this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document,"pointerup",null,this.handleUp.bind(this),!0));this.boundEvents.push(conditionalBind$$module$build$src$core$browser_events(document,"pointercancel",null,this.handleUp.bind(this),!0));a.preventDefault();a.stopPropagation()}handleStart(a){this.isDragging()|| +(this.handleTouchStart(a),this.isMultiTouch()&&longStop$$module$build$src$core$touch())}handleMove(a){if(this.isDragging()&&shouldHandleEvent$$module$build$src$core$touch(a)||!this.isMultiTouch()){this.updateFromEvent(a);if(this.workspaceDragger)this.workspaceDragger.drag(this.currentDragDeltaXY);else if(this.dragger)this.dragger.onDrag(this.mostRecentEvent,this.currentDragDeltaXY);a.preventDefault();a.stopPropagation()}else this.isMultiTouch()&&(this.handleTouchMove(a),longStop$$module$build$src$core$touch())}handleUp(a){this.isDragging()|| +this.handleTouchEnd(a);if(!this.isMultiTouch()||this.isDragging()){if(!shouldHandleEvent$$module$build$src$core$touch(a))return;this.updateFromEvent(a);longStop$$module$build$src$core$touch();if(this.isEnding_){console.log("Trying to end a gesture recursively.");return}this.isEnding_=!0;this.dragger?(keyboardNavigationController$$module$build$src$core$keyboard_navigation_controller.setIsActive(!1),this.dragger.onDragEnd(a,this.currentDragDeltaXY)):this.workspaceDragger?(keyboardNavigationController$$module$build$src$core$keyboard_navigation_controller.setIsActive(!1), +this.workspaceDragger.endDrag(this.currentDragDeltaXY)):this.isBubbleClick()||this.isCommentClick()||(this.isFieldClick()?this.doFieldClick():this.isIconClick()?this.doIconClick():this.isBlockClick()?this.doBlockClick():this.isWorkspaceClick()&&this.doWorkspaceClick(a))}a.preventDefault();a.stopPropagation();this.dispose()}handleTouchStart(a){var b=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);this.cachedPoints.set(b,this.getTouchPoint(a));var c=Array.from(this.cachedPoints.keys()); +c.length===2&&(b=this.cachedPoints.get(c[0]),c=this.cachedPoints.get(c[1]),this.startDistance=Coordinate$$module$build$src$core$utils$coordinate.distance(b,c),this.multiTouch=!0,a.preventDefault())}handleTouchMove(a){const b=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);this.cachedPoints.set(b,this.getTouchPoint(a));if(this.isPinchZoomEnabled&&this.cachedPoints.size===2)this.handlePinch(a);else{this.updateFromEvent(a);if(this.workspaceDragger)this.workspaceDragger.drag(this.currentDragDeltaXY); +else if(this.dragger)this.dragger.onDrag(this.mostRecentEvent,this.currentDragDeltaXY);a.preventDefault();a.stopPropagation()}}handlePinch(a){var b=Array.from(this.cachedPoints.keys()),c=this.cachedPoints.get(b[0]);b=this.cachedPoints.get(b[1]);c=Coordinate$$module$build$src$core$utils$coordinate.distance(c,b)/this.startDistance;if(this.previousScale>0&&this.previousScale0?b*ZOOM_IN_MULTIPLIER$$module$build$src$core$gesture:b*ZOOM_OUT_MULTIPLIER$$module$build$src$core$gesture; +if(!this.startWorkspace_)throw Error("Cannot handle a pinch because the start workspace is undefined");const d=this.startWorkspace_,e=mouseToSvg$$module$build$src$core$browser_events(a,d.getParentSvg(),d.getInverseScreenCTM());d.zoom(e.x,e.y,b)}this.previousScale=c;a.preventDefault()}handleTouchEnd(a){a=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);this.cachedPoints.has(a)&&this.cachedPoints.delete(a);this.cachedPoints.size<2&&(this.cachedPoints.clear(),this.previousScale=0)}getTouchPoint(a){return this.startWorkspace_? +new Coordinate$$module$build$src$core$utils$coordinate(a.pageX,a.pageY):null}isMultiTouch(){return this.multiTouch}cancel(){if(!this.isEnding_){longStop$$module$build$src$core$touch();if(this.dragger)this.dragger.onDragEnd(this.mostRecentEvent,this.currentDragDeltaXY);else this.workspaceDragger&&this.workspaceDragger.endDrag(this.currentDragDeltaXY);this.dispose()}}handleRightClick(a){const b=$.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode();if(hasContextMenu$$module$build$src$core$interfaces$i_contextmenu(b)){let c; +(c=this.startWorkspace_)==null||c.hideChaff(!!this.flyout);b.showContextMenu(a)}a.preventDefault();a.stopPropagation();keyboardNavigationController$$module$build$src$core$keyboard_navigation_controller.setIsActive(!1);this.dispose()}handleWsStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleWsStart, but the gesture had already been started.");this.setStartWorkspace(b);this.mostRecentEvent=a;this.targetBlock||this.startBubble||this.startComment||this.startIcon||$.getFocusManager$$module$build$src$core$focus_manager().focusNode(b); +this.doStart(a)}fireWorkspaceClick(a){fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.CLICK))(null,a.id,"workspace"))}handleFlyoutStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleFlyoutStart, but the gesture had already been started.");this.setStartFlyout(b);this.handleWsStart(a,b.getWorkspace())}handleBlockStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleBlockStart, but the gesture had already been started."); +this.setStartBlock(b);this.mostRecentEvent=a}handleBubbleStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleBubbleStart, but the gesture had already been started.");this.setStartBubble(b);this.mostRecentEvent=a}handleCommentStart(a,b){if(this.gestureHasStarted)throw Error("Tried to call gesture.handleCommentStart, but the gesture had already been started.");this.setStartComment(b);this.mostRecentEvent=a}doFieldClick(){if(!this.startField)throw Error("Cannot do a field click because the start field is undefined"); +this.currentDropdownOwner!==this.startField&&this.startField.showEditor(this.mostRecentEvent)}doIconClick(){if(!this.startIcon)throw Error("Cannot do an icon click because the start icon is undefined");this.startIcon.onClick()}doBlockClick(){if(this.flyout&&this.flyout.autoClose){if(!this.targetBlock)throw Error("Cannot do a block click because the target block is undefined");if(this.flyout.isBlockCreatable(this.targetBlock)){$.getGroup$$module$build$src$core$events$utils()||$.setGroup$$module$build$src$core$events$utils(!0); +var a=this.flyout.createBlock(this.targetBlock);a.snapToGrid();a.bumpNeighbours();$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a)}}else{if(!this.startWorkspace_)throw Error("Cannot do a block click because the start workspace is undefined");a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.CLICK))(this.startBlock,this.startWorkspace_.id,"block");fire$$module$build$src$core$events$utils(a)}$.setGroup$$module$build$src$core$events$utils(!1)}doWorkspaceClick(a){this.fireWorkspaceClick(this.startWorkspace_|| +this.creatorWorkspace)}setStartField(a){if(this.gestureHasStarted)throw Error("Tried to call gesture.setStartField, but the gesture had already been started.");this.startField||(this.startField=a)}setStartIcon(a){if(this.gestureHasStarted)throw Error("Tried to call gesture.setStartIcon, but the gesture had already been started.");this.startIcon||(this.startIcon=a)}setStartBubble(a){this.startBubble||(this.startBubble=a)}setStartComment(a){this.startComment||(this.startComment=a)}setStartBlock(a){this.startBlock|| +this.startBubble||this.startIcon||(this.startBlock=a,a.isInFlyout&&a!==a.getRootBlock()?this.setTargetBlock(a.getRootBlock()):this.setTargetBlock(a))}setTargetBlock(a){a.isShadow()?this.setTargetBlock(a.getParent()):(this.targetBlock=a,$.getFocusManager$$module$build$src$core$focus_manager().focusNode(this.targetBlock),this.targetBlock.bringToFront())}setStartWorkspace(a){this.startWorkspace_||(this.startWorkspace_=a)}setStartFlyout(a){this.flyout||(this.flyout=a)}isBubbleClick(){return!!this.startBubble&& +!this.hasExceededDragRadius}isCommentClick(){return!!this.startComment&&!this.hasExceededDragRadius}isBlockClick(){return!!this.startBlock&&!this.hasExceededDragRadius&&!this.isFieldClick()&&!this.isIconClick()}isFieldClick(){return this.startField?this.startField.isClickable()&&!this.hasExceededDragRadius&&(!this.flyout||this.startField.isClickableInFlyout(this.flyout.autoClose)):!1}isIconClick(){if(!this.startIcon)return!1;const a=!this.flyout||!this.startIcon.isClickableInFlyout||this.startIcon.isClickableInFlyout(this.flyout.autoClose); +return!this.hasExceededDragRadius&&a}isWorkspaceClick(){return!this.startBlock&&!this.startBubble&&!this.startField&&!this.hasExceededDragRadius}getCurrentDragger(){let a,b;return(b=(a=this.workspaceDragger)!=null?a:this.dragger)!=null?b:null}isDragging(){return this.dragging}hasStarted(){return this.gestureHasStarted}static inProgress(){const a=getAllWorkspaces$$module$build$src$core$common();for(let b=0,c;c=a[b];b++)if(c.currentGesture_)return!0;return!1}},module$build$src$core$gesture={}; +module$build$src$core$gesture.Gesture=Gesture$$module$build$src$core$gesture;var Grid$$module$build$src$core$grid=class{constructor(a,b){this.pattern=a;this.scale=1;let c;this.spacing=(c=b.spacing)!=null?c:0;let d;this.length=(d=b.length)!=null?d:1;this.line2=(this.line1=a.firstChild)&&this.line1.nextSibling;let e;this.snapToGrid=(e=b.snap)!=null?e:!1}setSpacing(a){this.spacing=a;this.update(this.scale)}getSpacing(){return this.spacing}setLength(a){this.length=a;this.update(this.scale)}getLength(){return this.length}setSnapToGrid(a){this.snapToGrid=a}shouldSnap(){return this.snapToGrid}getPatternId(){return this.pattern.id}update(a){this.scale= +a;var b=this.spacing*a;this.pattern.setAttribute("width",`${b}`);this.pattern.setAttribute("height",`${b}`);b=Math.floor(this.spacing/2)+.5;let c=b-this.length/2,d=b+this.length/2;b*=a;c*=a;d*=a;this.setLineAttributes(this.line1,a,c,d,b,b);this.setLineAttributes(this.line2,a,b,b,c,d)}setLineAttributes(a,b,c,d,e,f){a&&(a.setAttribute("stroke-width",`${b}`),a.setAttribute("x1",`${c}`),a.setAttribute("y1",`${e}`),a.setAttribute("x2",`${d}`),a.setAttribute("y2",`${f}`))}moveTo(a,b){this.pattern.setAttribute("x", +`${a}`);this.pattern.setAttribute("y",`${b}`)}alignXY(a){var b=this.getSpacing();const c=b/2,d=Math.round(Math.round((a.x-c)/b)*b+c);b=Math.round(Math.round((a.y-c)/b)*b+c);return d===a.x&&b===a.y?a:new Coordinate$$module$build$src$core$utils$coordinate(d,b)}static createDom(a,b,c,d){a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATTERN,{id:"blocklyGridPattern"+a,patternUnits:"userSpaceOnUse"},c);let e,f;if(((e=b.length)!=null?e:1)>0&&((f=b.spacing)!=null? +f:0)>0){createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{stroke:b.colour},a);let g;(g=b.length)!=null&&g&&createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{stroke:b.colour},a)}else createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{},a);d&&d.style.setProperty("--blocklyGridPattern",`url(#${a.id})`);return a}},module$build$src$core$grid={}; +module$build$src$core$grid.Grid=Grid$$module$build$src$core$grid;var module$build$src$core$interfaces$i_autohideable={};module$build$src$core$interfaces$i_autohideable.isAutoHideable=isAutoHideable$$module$build$src$core$interfaces$i_autohideable;var LayerManager$$module$build$src$core$layer_manager=class{constructor(a){this.workspace=a;this.layers=new Map;if(a=a.getInjectionDiv())this.dragLayer=this.createDragLayer(a),this.animationLayer=this.createAnimationLayer(a);a=this.createLayer(BLOCK$$module$build$src$core$layers);addClass$$module$build$src$core$utils$dom(a,"blocklyBlockCanvas");a=this.createLayer(BUBBLE$$module$build$src$core$layers);addClass$$module$build$src$core$utils$dom(a,"blocklyBubbleCanvas")}createDragLayer(a){const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG, +{"class":"blocklyBlockDragSurface",xmlns:SVG_NS$$module$build$src$core$utils$dom,"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1"});a.append(b);return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},b)}createAnimationLayer(a){const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{"class":"blocklyAnimationLayer",xmlns:SVG_NS$$module$build$src$core$utils$dom, +"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1"});a.append(b);return createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},b)}appendToAnimationLayer(a){let b;const c=(b=this.dragLayer)==null?void 0:b.getAttribute("transform");if(c){let e;(e=this.animationLayer)==null||e.setAttribute("transform",c)}let d;(d=this.animationLayer)==null||d.appendChild(a.getSvgRoot())}translateLayers(a,b){a= +`translate(${a.x}, ${a.y}) scale(${b})`;let c;(c=this.dragLayer)==null||c.setAttribute("transform",a);for(const [,d]of this.layers)d.setAttribute("transform",a)}moveToDragLayer(a,b=!0){let c;(c=this.dragLayer)==null||c.appendChild(a.getSvgRoot());b&&a.canBeFocused()&&$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a)}moveOffDragLayer(a,b,c=!0){this.append(a,b);c&&a.canBeFocused()&&$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a)}append(a,b){this.layers.has(b)|| +this.createLayer(b);a=a.getSvgRoot();let c;if(((c=this.layers.get(b))==null?void 0:c.lastChild)!==a){let d;(d=this.layers.get(b))==null||d.appendChild(a)}}createLayer(a){const b=this.workspace.getSvgGroup(),c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{});let d=!1;const e=[...this.layers].sort((f,g)=>f[0]-g[0]);for(const [f,g]of e)if(a{let c;return b instanceof BlockSvg$$module$build$src$core$block_svg&&!((c=b.outputConnection)==null?0:c.targetBlock())||b instanceof RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment}, +!0))&&this.setCurNode(a);return a}in(){var a=this.getCurNode();if(!a)return null;(a=this.getNextNode(a,()=>!0,!0))&&this.setCurNode(a);return a}prev(){var a=this.getCurNode();if(!a)return null;(a=this.getPreviousNode(a,b=>{let c;return b instanceof BlockSvg$$module$build$src$core$block_svg&&!((c=b.outputConnection)==null?0:c.targetBlock())||b instanceof RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment},!0))&&this.setCurNode(a);return a}out(){var a=this.getCurNode(); +if(!a)return null;(a=this.getPreviousNode(a,()=>!0,!0))&&this.setCurNode(a);return a}atEndOfLine(){var a=this.getCurNode();if(!a)return!1;const b=this.getNextNode(a,()=>!0,!0);a=this.getNextNode(a,c=>{let d;return c instanceof BlockSvg$$module$build$src$core$block_svg&&!((d=c.outputConnection)==null?0:d.targetBlock())},!0);return b===a}getNextNodeImpl(a,b,c=new Set){if(!a||c.has(a))return null;let d=this.workspace.getNavigator().getFirstChild(a)||this.workspace.getNavigator().getNextSibling(a);for(var e= +a;e&&!d;){e=this.workspace.getNavigator().getParent(e);if(!e)break;d=this.workspace.getNavigator().getNextSibling(e)}return b(d)?d:d?(c.add(a),this.getNextNodeImpl(d,b,c)):null}getNextNode(a,b,c){return!a||!c&&this.getLastNode()===a?null:this.getNextNodeImpl(a,b)}getPreviousNodeImpl(a,b,c=new Set){if(!a||c.has(a))return null;const d=this.getRightMostChild(this.workspace.getNavigator().getPreviousSibling(a),a)||this.workspace.getNavigator().getParent(a);return b(d)?d:d?(c.add(a),this.getPreviousNodeImpl(d, +b,c)):null}getPreviousNode(a,b,c){return!a||!c&&this.getFirstNode()===a?null:this.getPreviousNodeImpl(a,b)}getRightMostChild(a,b){if(!a)return a;let c=this.workspace.getNavigator().getFirstChild(a);if(!c||c===b)return a;for(a=c;a&&a!==b;a=this.workspace.getNavigator().getNextSibling(c))c=a;return this.getRightMostChild(c,b)}preDelete(a){var b=this.getCurNode();b=b?[b]:[];var c;let d,e;const f=(e=(c=a.previousConnection)==null?void 0:c.targetConnection)!=null?e:(d=a.outputConnection)==null?void 0: +d.targetConnection;f&&b.push(f);(c=a.getNextBlock())&&b.push(c);(a=a.getParent())&&b.push(a);b.push(this.workspace);this.potentialNodes=b}postDelete(){const a=this.potentialNodes;this.potentialNodes=null;if(!a)throw Error("must call preDelete first");for(const b of a){let c;if((c=this.getSourceBlockFromNode(b))==null||!c.disposed){this.setCurNode(b);return}}throw Error("no valid nodes in this.potentialNodes");}getCurNode(){return $.getFocusManager$$module$build$src$core$focus_manager().getFocusedNode()}setCurNode(a){$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a)}getFirstNode(){return this.workspace.getNavigator().getFirstChild(this.workspace)}getLastNode(){const a= +this.getFirstNode();return this.getPreviousNode(a,()=>!0,!0)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.CURSOR,DEFAULT$$module$build$src$core$registry,LineCursor$$module$build$src$core$keyboard_nav$line_cursor);var module$build$src$core$keyboard_nav$line_cursor={};module$build$src$core$keyboard_nav$line_cursor.LineCursor=LineCursor$$module$build$src$core$keyboard_nav$line_cursor;var MarkerManager$$module$build$src$core$marker_manager=class{constructor(a){this.workspace=a;this.markers=new Map;this.cursor=new LineCursor$$module$build$src$core$keyboard_nav$line_cursor(this.workspace)}registerMarker(a,b){this.markers.has(a)&&this.unregisterMarker(a);this.markers.set(a,b)}unregisterMarker(a){const b=this.markers.get(a);if(b)b.dispose(),this.markers.delete(a);else throw Error("Marker with ID "+a+" does not exist. Can only unregister markers that exist.");}getCursor(){return this.cursor}getMarker(a){return this.markers.get(a)|| +null}setCursor(a){this.cursor=a}dispose(){const a=Object.keys(this.markers);for(let b=0,c;c=a[b];b++)this.unregisterMarker(c);this.markers.clear();this.cursor.dispose()}};MarkerManager$$module$build$src$core$marker_manager.LOCAL_MARKER="local_marker_1";var module$build$src$core$marker_manager={};module$build$src$core$marker_manager.MarkerManager=MarkerManager$$module$build$src$core$marker_manager;var module$build$src$core$icons={};module$build$src$core$icons.CommentIcon=CommentIcon$$module$build$src$core$icons$comment_icon;module$build$src$core$icons.Icon=Icon$$module$build$src$core$icons$icon;module$build$src$core$icons.IconType=IconType$$module$build$src$core$icons$icon_types;module$build$src$core$icons.MutatorIcon=$.MutatorIcon$$module$build$src$core$icons$mutator_icon;module$build$src$core$icons.WarningIcon=WarningIcon$$module$build$src$core$icons$warning_icon; +module$build$src$core$icons.exceptions=module$build$src$core$icons$exceptions;module$build$src$core$icons.registry=module$build$src$core$icons$registry;var module$build$src$core$interfaces$i_procedure_block={};module$build$src$core$interfaces$i_procedure_block.isProcedureBlock=isProcedureBlock$$module$build$src$core$interfaces$i_procedure_block;$.Names$$module$build$src$core$names=class{constructor(a,b){this.db=new Map;this.dbReverse=new Set;this.variableMap=null;this.variablePrefix=b||"";this.reservedWords=new Set(a?a.split(","):[])}reset(){this.db.clear();this.dbReverse.clear();this.variableMap=null}setVariableMap(a){this.variableMap=a}getNameForUserVariable(a){return this.variableMap?(a=this.variableMap.getVariableById(a))?a.getName():null:(console.warn("Deprecated call to Names.prototype.getName without defining a variable map. To fix, add the following code in your generator's init() function:\nBlockly.YourGeneratorName.nameDB_.setVariableMap(workspace.getVariableMap());"), null)}populateVariables(a){a=$.allUsedVarModels$$module$build$src$core$variables(a);for(let b=0;b=1}isHat(a){return(a.type&this.HAT)>=1}isIcon(a){return(a.type& +this.ICON)>=1}isSpacer(a){return(a.type&this.SPACER)>=1}isInRowSpacer(a){return(a.type&this.IN_ROW_SPACER)>=1}isSpacerRow(a){return(a.type&this.BETWEEN_ROW_SPACER)>=1}isInput(a){return(a.type&this.INPUT)>=1}isExternalInput(a){return(a.type&this.EXTERNAL_VALUE_INPUT)>=1}isInlineInput(a){return(a.type&this.INLINE_INPUT)>=1}isStatementInput(a){return(a.type&this.STATEMENT_INPUT)>=1}isPreviousConnection(a){return(a.type&this.PREVIOUS_CONNECTION)>=1}isNextConnection(a){return(a.type&this.NEXT_CONNECTION)>= +1}isPreviousOrNextConnection(a){return this.isPreviousConnection(a)||this.isNextConnection(a)}isRoundCorner(a){return(a.type&this.LEFT_ROUND_CORNER)>=1||(a.type&this.RIGHT_ROUND_CORNER)>=1}isLeftRoundedCorner(a){return this.isRoundCorner(a)&&(a.type&this.LEFT_ROUND_CORNER)>=1}isRightRoundedCorner(a){return this.isRoundCorner(a)&&(a.type&this.RIGHT_ROUND_CORNER)>=1}isLeftSquareCorner(a){return(a.type&this.LEFT_SQUARE_CORNER)>=1}isRightSquareCorner(a){return(a.type&this.RIGHT_SQUARE_CORNER)>=1}isCorner(a){return(a.type& +this.CORNER)>=1}isJaggedEdge(a){return(a.type&this.JAGGED_EDGE)>=1}isRow(a){return(a.type&this.ROW)>=1}isBetweenRowSpacer(a){return(a.type&this.BETWEEN_ROW_SPACER)>=1}isTopRow(a){return(a.type&this.TOP_ROW)>=1}isBottomRow(a){return(a.type&this.BOTTOM_ROW)>=1}isTopOrBottomRow(a){return this.isTopRow(a)||this.isBottomRow(a)}isInputRow(a){return(a.type&this.INPUT_ROW)>=1}},Types$$module$build$src$core$renderers$measurables$types=new TypesContainer$$module$build$src$core$renderers$measurables$types,module$build$src$core$renderers$measurables$types= +{Types:Types$$module$build$src$core$renderers$measurables$types};var Measurable$$module$build$src$core$renderers$measurables$base=class{constructor(a){this.centerline=this.xPos=this.height=this.width=0;this.constants_=a;this.type=Types$$module$build$src$core$renderers$measurables$types.NONE;this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT}},module$build$src$core$renderers$measurables$base={};module$build$src$core$renderers$measurables$base.Measurable=Measurable$$module$build$src$core$renderers$measurables$base;var Row$$module$build$src$core$renderers$measurables$row=class{constructor(a){this.elements=[];this.xPos=this.yPos=this.widthWithConnectedBlocks=this.minWidth=this.minHeight=this.width=this.height=0;this.hasStatement=this.hasExternalInput=!1;this.statementEdge=0;this.hasJaggedEdge=this.hasDummyInput=this.hasInlineInput=!1;this.align=null;this.constants_=a;this.type=Types$$module$build$src$core$renderers$measurables$types.ROW;this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT}getLastInput(){for(let a= +this.elements.length-1;a>=0;a--){const b=this.elements[a];if(Types$$module$build$src$core$renderers$measurables$types.isInput(b))return b}return null}measure(){throw Error("Unexpected attempt to measure a base Row.");}startsWithElemSpacer(){return!0}endsWithElemSpacer(){return!0}getFirstSpacer(){for(let a=0;a=0;a--){const b=this.elements[a];if(Types$$module$build$src$core$renderers$measurables$types.isInRowSpacer(b))return b}return null}},module$build$src$core$renderers$measurables$row={};module$build$src$core$renderers$measurables$row.Row=Row$$module$build$src$core$renderers$measurables$row;var BottomRow$$module$build$src$core$renderers$measurables$bottom_row=class extends Row$$module$build$src$core$renderers$measurables$row{constructor(a){super(a);this.hasNextConnection=!1;this.connection=null;this.baseline=this.descenderHeight=0;this.type|=Types$$module$build$src$core$renderers$measurables$types.BOTTOM_ROW}hasLeftSquareCorner(a){return!!a.outputConnection||!!a.getNextBlock()}hasRightSquareCorner(a){return!0}measure(){let a=0,b=0,c=0;for(let d=0;drect,`,`${a} .blocklyEditableText>rect {`,`fill: ${this.FIELD_BORDER_RECT_COLOUR};`,"fill-opacity: .6;","stroke: none;","}",`${a} .blocklyNonEditableText>text,`,`${a} .blocklyEditableText>text {`,"fill: #000;","}",`${a} .blocklyFlyoutLabelText {`,"fill: #000;","}",`${a} .blocklyText.blocklyBubbleText {`,"fill: #000;","}",`${a} .blocklyEditableText:not(.editing):hover>rect {`,"stroke: #fff;","stroke-width: 2;","}",`${a} .blocklyHtmlInput {`, -`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,`font-weight: ${this.FIELD_TEXT_FONTWEIGHT};`,"}",`${a} .blocklySelected>.blocklyPath {`,"stroke: #fc3;","stroke-width: 3px;","}",`${a} .blocklyHighlightedConnectionPath {`,"stroke: #fc3;","}",`${a} .blocklyReplaceable .blocklyPath {`,"fill-opacity: .5;","}",`${a} .blocklyReplaceable .blocklyPathLight,`,`${a} .blocklyReplaceable .blocklyPathDark {`,"display: none;","}",`${a} .blocklyInsertionMarker>.blocklyPath {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`, -"stroke: none;","}"]}},module$build$src$core$renderers$common$constants={};module$build$src$core$renderers$common$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$common$constants;module$build$src$core$renderers$common$constants.isDynamicShape=isDynamicShape$$module$build$src$core$renderers$common$constants;module$build$src$core$renderers$common$constants.isNotch=isNotch$$module$build$src$core$renderers$common$constants; -module$build$src$core$renderers$common$constants.isPuzzleTab=isPuzzleTab$$module$build$src$core$renderers$common$constants;var Drawer$$module$build$src$core$renderers$common$drawer=class{constructor(a,b){this.inlinePath_=this.outlinePath_="";this.block_=a;this.info_=b;this.topLeft_=a.getRelativeToSurfaceXY();this.constants_=b.getRenderer().getConstants()}draw(){this.drawOutline_();this.drawInternals_();this.updateConnectionHighlights();this.block_.pathObject.setPath(this.outlinePath_+"\n"+this.inlinePath_);this.info_.RTL&&this.block_.pathObject.flipRTL();this.recordSizeOnBlock_()}recordSizeOnBlock_(){this.block_.height= +{d:"M 0 0 L 10 10 M 10 0 L 0 10",stroke:"#cc0"},a);this.disabledPatternId=a.id;this.disabledPattern=a;this.createDebugFilter();d&&(d.style.setProperty("--blocklyEmbossFilter",`url(#${this.embossFilterId})`),d.style.setProperty("--blocklyDisabledPattern",`url(#${this.disabledPatternId})`),d.style.setProperty("--blocklyDebugFilter",`url(#${this.debugFilterId})`))}createDebugFilter(){if(!this.debugFilter){const a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER, +{id:"blocklyDebugFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},this.defs),b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER,{result:"outBlur"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":"#ff0000", +"flood-opacity":.5,result:"outColor"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in",result:"outGlow"},a);this.debugFilterId=a.id;this.debugFilter=a}}injectCSS_(a,b){b=this.getCSS_(b);a="blockly-renderer-style-"+a;this.cssNode=document.getElementById(a);const c=b.join("\n");this.cssNode?this.cssNode.firstChild.textContent=c:(b=document.createElement("style"),b.id=a,a=document.createTextNode(c),b.appendChild(a), +document.head.insertBefore(b,document.head.firstChild),this.cssNode=b)}getCSS_(a){return[`${a} .blocklyText, `,`${a} .blocklyFlyoutLabelText {`,`font: ${this.FIELD_TEXT_FONTWEIGHT} ${this.FIELD_TEXT_FONTSIZE}pt ${this.FIELD_TEXT_FONTFAMILY};`,"}",`${a} .blocklyText {`,"fill: #fff;","}",`${a} .blocklyNonEditableField>rect,`,`${a} .blocklyEditableField>rect {`,`fill: ${this.FIELD_BORDER_RECT_COLOUR};`,"fill-opacity: .6;","stroke: none;","}",`${a} .blocklyNonEditableField>text,`,`${a} .blocklyEditableField>text {`, +"fill: #000;","}",`${a} .blocklyFlyoutLabelText {`,"fill: #000;","}",`${a} .blocklyText.blocklyBubbleText {`,"fill: #000;","}",`${a} .blocklyEditableField:not(.blocklyEditing):hover>rect {`,"stroke: #fff;","stroke-width: 2;","}",`${a} .blocklyHtmlInput {`,`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,`font-weight: ${this.FIELD_TEXT_FONTWEIGHT};`,"}",`${a} .blocklySelected>.blocklyPath {`,"stroke: #fc3;","stroke-width: 3px;","}",`${a} .blocklyHighlightedConnectionPath {`,"stroke: #fc3;","}",`${a} .blocklyReplaceable .blocklyPath {`, +"fill-opacity: .5;","}",`${a} .blocklyReplaceable .blocklyPathLight,`,`${a} .blocklyReplaceable .blocklyPathDark {`,"display: none;","}",`${a} .blocklyInsertionMarker>.blocklyPath {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;","}"]}},module$build$src$core$renderers$common$constants={};module$build$src$core$renderers$common$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$common$constants; +module$build$src$core$renderers$common$constants.isDynamicShape=isDynamicShape$$module$build$src$core$renderers$common$constants;module$build$src$core$renderers$common$constants.isNotch=isNotch$$module$build$src$core$renderers$common$constants;module$build$src$core$renderers$common$constants.isPuzzleTab=isPuzzleTab$$module$build$src$core$renderers$common$constants;var Drawer$$module$build$src$core$renderers$common$drawer=class{constructor(a,b){this.inlinePath_=this.outlinePath_="";this.block_=a;this.info_=b;this.topLeft_=a.getRelativeToSurfaceXY();this.constants_=b.getRenderer().getConstants()}draw(){this.drawOutline_();this.drawInternals_();this.updateConnectionHighlights();this.block_.pathObject.setPath(this.outlinePath_+"\n"+this.inlinePath_);this.info_.RTL&&this.block_.pathObject.flipRTL();this.recordSizeOnBlock_()}recordSizeOnBlock_(){this.block_.height= this.info_.height;this.block_.width=this.info_.widthWithChildren;this.block_.childlessWidth=this.info_.width}drawOutline_(){this.drawTop_();for(let a=1;aa||a>this.fieldRow.length)throw Error("index "+a+" out of bounds.");if(!(b|| -""===b&&c))return a;"string"===typeof b&&(b=$.fromJson$$module$build$src$core$field_registry({type:"field_label",text:b}));b.setSourceBlock(this.sourceBlock);this.sourceBlock.initialized&&this.initField(b);b.name=c;b.setVisible(this.isVisible());b.prefixField&&(a=this.insertFieldAt(a,b.prefixField));this.fieldRow.splice(a,0,b);a++;b.suffixField&&(a=this.insertFieldAt(a,b.suffixField));this.sourceBlock.rendered&&this.sourceBlock.queueRender();return a}removeField(a,b){for(let c=0,d;d=this.fieldRow[c];c++)if(d.name=== -a)return d.dispose(),this.fieldRow.splice(c,1),this.sourceBlock.rendered&&this.sourceBlock.queueRender(),!0;if(b)return!1;throw Error('Field "'+a+'" not found.');}isVisible(){return this.visible}setVisible(a){let b=[];if(this.visible===a)return b;this.visible=a;for(let d=0,e;e=this.fieldRow[d];d++)e.setVisible(a);if(this.connection){var c=this.connection;a?b=c.startTrackingAll():c.stopTrackingAll();if(c=c.targetBlock())c.getSvgRoot().style.display=a?"block":"none"}return b}markDirty(){for(let a=0, -b;b=this.fieldRow[a];a++)b.markDirty()}setCheck(a){if(!this.connection)throw Error("This input does not have a connection.");this.connection.setCheck(a);return this}setAlign(a){this.align=a;this.sourceBlock.rendered&&this.sourceBlock.queueRender();return this}setShadowDom(a){if(!this.connection)throw Error("This input does not have a connection.");this.connection.setShadowDom(a);return this}getShadowDom(){if(!this.connection)throw Error("This input does not have a connection.");return this.connection.getShadowDom()}init(){for(const a of this.fieldRow)a.init()}initModel(){for(const a of this.fieldRow)a.initModel()}initField(a){this.sourceBlock.rendered? -a.init():a.initModel()}dispose(){for(let a=0,b;b=this.fieldRow[a];a++)b.dispose();this.connection&&this.connection.dispose()}makeConnection(a){return this.sourceBlock.makeConnection_(a)}},module$build$src$core$inputs$input={};module$build$src$core$inputs$input.Input=Input$$module$build$src$core$inputs$input;var DummyInput$$module$build$src$core$inputs$dummy_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.DUMMY}},module$build$src$core$inputs$dummy_input={};module$build$src$core$inputs$dummy_input.DummyInput=DummyInput$$module$build$src$core$inputs$dummy_input;var EndRowInput$$module$build$src$core$inputs$end_row_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.END_ROW}},module$build$src$core$inputs$end_row_input={};module$build$src$core$inputs$end_row_input.EndRowInput=EndRowInput$$module$build$src$core$inputs$end_row_input;var StatementInput$$module$build$src$core$inputs$statement_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){if(!a)throw Error("Statement inputs must have a non-empty name");super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.STATEMENT;this.connection=this.makeConnection(ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT)}},module$build$src$core$inputs$statement_input={}; -module$build$src$core$inputs$statement_input.StatementInput=StatementInput$$module$build$src$core$inputs$statement_input;var module$build$src$core$inputs$value_input;$.ValueInput$$module$build$src$core$inputs$value_input=class extends Input$$module$build$src$core$inputs$input{constructor(a,b){if(!a)throw Error("Value inputs must have a non-empty name");super(a,b);this.name=a;this.type=$.inputTypes$$module$build$src$core$inputs$input_types.VALUE;this.connection=this.makeConnection(ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE)}};module$build$src$core$inputs$value_input={}; -module$build$src$core$inputs$value_input.ValueInput=$.ValueInput$$module$build$src$core$inputs$value_input;var RenderInfo$$module$build$src$core$renderers$common$info=class{constructor(a,b){this.statementEdge=this.width=this.widthWithChildren=this.height=0;this.rows=[];this.inputRows=[];this.startY=this.startX=0;this.renderer_=a;this.block_=b;this.constants_=this.renderer_.getConstants();this.outputConnection=b.outputConnection?new OutputConnection$$module$build$src$core$renderers$measurables$output_connection(this.constants_,b.outputConnection):null;this.isInline=b.getInputsInline()&&!b.isCollapsed(); +moveBy$$module$build$src$core$utils$svg_paths(a.xPos,this.info_.startY);for(let c=0,d;d=b[c];c++)Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(d)?this.outlinePath_+=this.constants_.OUTSIDE_CORNERS.topLeft:Types$$module$build$src$core$renderers$measurables$types.isRightRoundedCorner(d)?this.outlinePath_+=this.constants_.OUTSIDE_CORNERS.topRight:Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(d)?this.outlinePath_+=d.shape.pathLeft:Types$$module$build$src$core$renderers$measurables$types.isHat(d)? +this.outlinePath_+=this.constants_.START_HAT.path:Types$$module$build$src$core$renderers$measurables$types.isSpacer(d)&&(this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("h",d.width));this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height-a.ascenderHeight)}drawJaggedEdge_(a){this.outlinePath_+=this.constants_.JAGGED_TEETH.path+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height-this.constants_.JAGGED_TEETH.height)}drawValueInput_(a){const b= +a.getLastInput();this.positionExternalValueConnection_(a);const c=isDynamicShape$$module$build$src$core$renderers$common$constants(b.shape)?b.shape.pathDown(b.height):b.shape.pathDown;this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",b.xPos+b.width)+c+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height-b.connectionHeight)}drawStatementInput_(a){var b=a.getLastInput();if(b){var c=b.xPos+b.notchOffset+b.shape.width;b=b.shape.pathRight+lineOnAxis$$module$build$src$core$utils$svg_paths("h", +-(b.notchOffset-this.constants_.INSIDE_CORNERS.width))+this.constants_.INSIDE_CORNERS.pathTop;var d=a.height-2*this.constants_.INSIDE_CORNERS.height;this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",c)+b+lineOnAxis$$module$build$src$core$utils$svg_paths("v",d)+this.constants_.INSIDE_CORNERS.pathBottom+lineOnAxis$$module$build$src$core$utils$svg_paths("H",a.xPos+a.width);this.positionStatementInputConnection_(a)}}drawRightSideRow_(a){this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V", +a.yPos+a.height)}drawBottom_(){const a=this.info_.bottomRow,b=a.elements;this.positionNextConnection_();let c=0,d="";for(let e=b.length-1,f;f=b[e];e--)Types$$module$build$src$core$renderers$measurables$types.isNextConnection(f)?d+=f.shape.pathRight:Types$$module$build$src$core$renderers$measurables$types.isLeftSquareCorner(f)?d+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",a.xPos):Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(f)?d+=this.constants_.OUTSIDE_CORNERS.bottomLeft: +Types$$module$build$src$core$renderers$measurables$types.isRightRoundedCorner(f)?(d+=this.constants_.OUTSIDE_CORNERS.bottomRight,c=this.constants_.OUTSIDE_CORNERS.rightHeight):Types$$module$build$src$core$renderers$measurables$types.isSpacer(f)&&(d+=lineOnAxis$$module$build$src$core$utils$svg_paths("h",f.width*-1));this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.baseline-c);this.outlinePath_+=d}drawLeft_(){var a=this.info_.outputConnection;this.positionOutputConnection_(); +if(a){const b=a.connectionOffsetY+a.height;a=isDynamicShape$$module$build$src$core$renderers$common$constants(a.shape)?a.shape.pathUp(a.height):a.shape.pathUp;this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",b)+a}this.outlinePath_+="z"}drawInternals_(){for(let a=0,b;b=this.info_.rows[a];a++)for(let c=0,d;d=b.elements[c];c++)Types$$module$build$src$core$renderers$measurables$types.isInlineInput(d)?this.drawInlineInput_(d):(Types$$module$build$src$core$renderers$measurables$types.isIcon(d)|| +Types$$module$build$src$core$renderers$measurables$types.isField(d))&&this.layoutField_(d)}layoutField_(a){const b=a.centerline-a.height/2;let c=a.xPos;var d="";this.info_.RTL&&(c=-(c+a.width),a.flipRtl&&(c+=a.width,d="scale(-1 1)"));Types$$module$build$src$core$renderers$measurables$types.isIcon(a)?(d=a.icon,d.setOffsetInBlock(new Coordinate$$module$build$src$core$utils$coordinate(c,b)),this.info_.isInsertionMarker&&d.hideForInsertionMarker()):(a=a.field.getSvgRoot(),a.setAttribute("transform","translate("+ +c+","+b+")"+d),this.info_.isInsertionMarker&&a.setAttribute("display","none"))}drawInlineInput_(a){const b=a.width,c=a.height,d=a.connectionOffsetY,e=a.connectionHeight+d;this.inlinePath_+=moveTo$$module$build$src$core$utils$svg_paths(a.xPos+a.connectionWidth,a.centerline-c/2)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",d)+a.shape.pathDown+lineOnAxis$$module$build$src$core$utils$svg_paths("v",c-e)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",b-a.connectionWidth)+lineOnAxis$$module$build$src$core$utils$svg_paths("v", +-c)+"z";this.positionInlineInputConnection_(a)}positionInlineInputConnection_(a){const b=a.centerline-a.height/2;if(a.connectionModel){let c=a.xPos+a.connectionWidth+a.connectionOffsetX;this.info_.RTL&&(c*=-1);a.connectionModel.setOffsetInBlock(c,b+a.connectionOffsetY)}}positionStatementInputConnection_(a){const b=a.getLastInput();if(b==null?0:b.connectionModel){let c=a.xPos+a.statementEdge+b.notchOffset;this.info_.RTL&&(c*=-1);b.connectionModel.setOffsetInBlock(c,a.yPos)}}positionExternalValueConnection_(a){const b= +a.getLastInput();if(b&&b.connectionModel){let c=a.xPos+a.width;this.info_.RTL&&(c*=-1);b.connectionModel.setOffsetInBlock(c,a.yPos)}}positionPreviousConnection_(){const a=this.info_.topRow;if(a.connection){const b=a.xPos+a.notchOffset;a.connection.connectionModel.setOffsetInBlock(this.info_.RTL?-b:b,0)}}positionNextConnection_(){const a=this.info_.bottomRow;if(a.connection){const b=a.connection,c=b.xPos;b.connectionModel.setOffsetInBlock(this.info_.RTL?-c:c,a.baseline)}}positionOutputConnection_(){if(this.info_.outputConnection){const a= +this.info_.startX+this.info_.outputConnection.connectionOffsetX;this.block_.outputConnection.setOffsetInBlock(this.info_.RTL?-a:a,this.info_.outputConnection.connectionOffsetY)}}updateConnectionHighlights(){for(const a of this.info_.rows)for(const b of a.elements){if(!(b instanceof Connection$$module$build$src$core$renderers$measurables$connection))continue;const c=this.drawConnectionHighlightPath(b);c&&(c.style.display=b.highlighted?"":"none")}}drawConnectionHighlightPath(a){const b=a.connectionModel; +a=b.type===ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE||b.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE?this.getExpressionConnectionHighlightPath(a):this.getStatementConnectionHighlightPath(a);const c=b.getSourceBlock();let d,e;return(e=(d=c.pathObject).addConnectionHighlight)==null?void 0:e.call(d,b,a,b.getOffsetInBlock(),c.RTL)}getExpressionConnectionHighlightPath(a){let b="";isDynamicShape$$module$build$src$core$renderers$common$constants(a.shape)? +b=a.shape.pathDown(a.height):isPuzzleTab$$module$build$src$core$renderers$common$constants(a.shape)&&(b=a.shape.pathDown);a=this.constants_.TAB_OFFSET_FROM_TOP;return moveBy$$module$build$src$core$utils$svg_paths(0,-a)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a)+b+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a)}getStatementConnectionHighlightPath(a){if(!isNotch$$module$build$src$core$renderers$common$constants(a.shape))throw Error("Statement connections should have notch shapes"); +const b=this.constants_.NOTCH_OFFSET_LEFT-this.constants_.CORNER_RADIUS;return moveBy$$module$build$src$core$utils$svg_paths(-b,0)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",b)+a.shape.pathLeft+lineOnAxis$$module$build$src$core$utils$svg_paths("h",b)}},module$build$src$core$renderers$common$drawer={};module$build$src$core$renderers$common$drawer.Drawer=Drawer$$module$build$src$core$renderers$common$drawer;var RenderInfo$$module$build$src$core$renderers$common$info=class{constructor(a,b){this.statementEdge=this.width=this.widthWithChildren=this.height=0;this.rows=[];this.inputRows=[];this.startY=this.startX=0;this.renderer_=a;this.block_=b;this.constants_=this.renderer_.getConstants();this.outputConnection=b.outputConnection?new OutputConnection$$module$build$src$core$renderers$measurables$output_connection(this.constants_,b.outputConnection):null;this.isInline=b.getInputsInline()&&!b.isCollapsed(); this.isCollapsed=b.isCollapsed();this.isInsertionMarker=b.isInsertionMarker();this.RTL=b.RTL;this.topRow=new TopRow$$module$build$src$core$renderers$measurables$top_row(this.constants_);this.bottomRow=new BottomRow$$module$build$src$core$renderers$measurables$bottom_row(this.constants_)}getRenderer(){return this.renderer_}measure(){this.createRows_();this.addElemSpacing_();this.addRowSpacing_();this.computeBounds_();this.alignRowElements_();this.finalize_()}createRows_(){this.populateTopRow_();this.rows.push(this.topRow); let a=new InputRow$$module$build$src$core$renderers$measurables$input_row(this.constants_);this.inputRows.push(a);var b=this.block_.getIcons();for(let c=0,d;d=b[c];c++){const e=new Icon$$module$build$src$core$renderers$measurables$icon(this.constants_,d);this.isCollapsed&&!d.isShownWhenCollapsed()||a.elements.push(e)}b=void 0;for(let c=0,d;d=this.block_.inputList[c];c++)if(d.isVisible()){this.shouldStartNewRow_(d,b)&&(this.rows.push(a),a=new InputRow$$module$build$src$core$renderers$measurables$input_row(this.constants_), this.inputRows.push(a));for(let e=0,f;f=d.fieldRow[e];e++)a.elements.push(new Field$$module$build$src$core$renderers$measurables$field(this.constants_,f,d));this.addInput_(d,a);b=d}this.isCollapsed&&(a.hasJaggedEdge=!0,a.elements.push(new JaggedEdge$$module$build$src$core$renderers$measurables$jagged_edge(this.constants_)));(a.elements.length||a.hasDummyInput)&&this.rows.push(a);this.populateBottomRow_();this.rows.push(this.bottomRow)}populateTopRow_(){var a=!!this.block_.previousConnection;const b= -(this.block_.hat?"cap"===this.block_.hat:this.constants_.ADD_START_HATS)&&!this.outputConnection&&!a;let c=this.topRow.hasLeftSquareCorner(this.block_)?SquareCorner$$module$build$src$core$renderers$measurables$square_corner:RoundCorner$$module$build$src$core$renderers$measurables$round_corner;this.topRow.elements.push(new c(this.constants_));b?(a=new Hat$$module$build$src$core$renderers$measurables$hat(this.constants_),this.topRow.elements.push(a),this.topRow.capline=a.ascenderHeight):a&&(this.topRow.hasPreviousConnection= -!0,this.topRow.connection=new PreviousConnection$$module$build$src$core$renderers$measurables$previous_connection(this.constants_,this.block_.previousConnection),this.topRow.elements.push(this.topRow.connection));this.block_.inputList.length&&this.block_.inputList[0]instanceof StatementInput$$module$build$src$core$inputs$statement_input&&!this.block_.isCollapsed()?this.topRow.minHeight=this.constants_.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT:this.topRow.minHeight=this.constants_.TOP_ROW_MIN_HEIGHT;c= -this.topRow.hasRightSquareCorner(this.block_)?SquareCorner$$module$build$src$core$renderers$measurables$square_corner:RoundCorner$$module$build$src$core$renderers$measurables$round_corner;this.topRow.elements.push(new c(this.constants_,"right"))}populateBottomRow_(){this.bottomRow.hasNextConnection=!!this.block_.nextConnection;this.bottomRow.minHeight=this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1]instanceof StatementInput$$module$build$src$core$inputs$statement_input? -this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT:this.constants_.BOTTOM_ROW_MIN_HEIGHT;this.bottomRow.hasLeftSquareCorner(this.block_)?this.bottomRow.elements.push(new SquareCorner$$module$build$src$core$renderers$measurables$square_corner(this.constants_)):this.bottomRow.elements.push(new RoundCorner$$module$build$src$core$renderers$measurables$round_corner(this.constants_));this.bottomRow.hasNextConnection&&(this.bottomRow.connection=new NextConnection$$module$build$src$core$renderers$measurables$next_connection(this.constants_, -this.block_.nextConnection),this.bottomRow.elements.push(this.bottomRow.connection));this.bottomRow.hasRightSquareCorner(this.block_)?this.bottomRow.elements.push(new SquareCorner$$module$build$src$core$renderers$measurables$square_corner(this.constants_,"right")):this.bottomRow.elements.push(new RoundCorner$$module$build$src$core$renderers$measurables$round_corner(this.constants_,"right"))}addInput_(a,b){if(this.isInline&&a instanceof $.ValueInput$$module$build$src$core$inputs$value_input)b.elements.push(new InlineInput$$module$build$src$core$renderers$measurables$inline_input(this.constants_, +(this.block_.hat?this.block_.hat==="cap":this.constants_.ADD_START_HATS)&&!this.outputConnection&&!a;let c=this.topRow.hasLeftSquareCorner(this.block_)?SquareCorner$$module$build$src$core$renderers$measurables$square_corner:RoundCorner$$module$build$src$core$renderers$measurables$round_corner;this.topRow.elements.push(new c(this.constants_));b?(a=new Hat$$module$build$src$core$renderers$measurables$hat(this.constants_),this.topRow.elements.push(a)):a&&(this.topRow.hasPreviousConnection=!0,this.topRow.connection= +new PreviousConnection$$module$build$src$core$renderers$measurables$previous_connection(this.constants_,this.block_.previousConnection),this.topRow.elements.push(this.topRow.connection));this.block_.inputList.length&&this.block_.inputList[0]instanceof StatementInput$$module$build$src$core$inputs$statement_input&&!this.block_.isCollapsed()?this.topRow.minHeight=this.constants_.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT:this.topRow.minHeight=this.constants_.TOP_ROW_MIN_HEIGHT;c=this.topRow.hasRightSquareCorner(this.block_)? +SquareCorner$$module$build$src$core$renderers$measurables$square_corner:RoundCorner$$module$build$src$core$renderers$measurables$round_corner;this.topRow.elements.push(new c(this.constants_,"right"))}populateBottomRow_(){this.bottomRow.hasNextConnection=!!this.block_.nextConnection;this.bottomRow.minHeight=this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1]instanceof StatementInput$$module$build$src$core$inputs$statement_input?this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT: +this.constants_.BOTTOM_ROW_MIN_HEIGHT;this.bottomRow.hasLeftSquareCorner(this.block_)?this.bottomRow.elements.push(new SquareCorner$$module$build$src$core$renderers$measurables$square_corner(this.constants_)):this.bottomRow.elements.push(new RoundCorner$$module$build$src$core$renderers$measurables$round_corner(this.constants_));this.bottomRow.hasNextConnection&&(this.bottomRow.connection=new NextConnection$$module$build$src$core$renderers$measurables$next_connection(this.constants_,this.block_.nextConnection), +this.bottomRow.elements.push(this.bottomRow.connection));this.bottomRow.hasRightSquareCorner(this.block_)?this.bottomRow.elements.push(new SquareCorner$$module$build$src$core$renderers$measurables$square_corner(this.constants_,"right")):this.bottomRow.elements.push(new RoundCorner$$module$build$src$core$renderers$measurables$round_corner(this.constants_,"right"))}addInput_(a,b){if(this.isInline&&a instanceof $.ValueInput$$module$build$src$core$inputs$value_input)b.elements.push(new InlineInput$$module$build$src$core$renderers$measurables$inline_input(this.constants_, a)),b.hasInlineInput=!0;else if(a instanceof StatementInput$$module$build$src$core$inputs$statement_input)b.elements.push(new StatementInput$$module$build$src$core$renderers$measurables$statement_input(this.constants_,a)),b.hasStatement=!0;else if(a instanceof $.ValueInput$$module$build$src$core$inputs$value_input)b.elements.push(new ExternalValueInput$$module$build$src$core$renderers$measurables$external_value_input(this.constants_,a)),b.hasExternalInput=!0;else if(a instanceof DummyInput$$module$build$src$core$inputs$dummy_input|| -a instanceof EndRowInput$$module$build$src$core$inputs$end_row_input)b.minHeight=Math.max(b.minHeight,a.getSourceBlock()&&a.getSourceBlock().isShadow()?this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT:this.constants_.DUMMY_INPUT_MIN_HEIGHT),b.hasDummyInput=!0;null===b.align&&(b.align=a.align)}shouldStartNewRow_(a,b){return b?b instanceof EndRowInput$$module$build$src$core$inputs$end_row_input||a instanceof StatementInput$$module$build$src$core$inputs$statement_input||b instanceof StatementInput$$module$build$src$core$inputs$statement_input? +a instanceof EndRowInput$$module$build$src$core$inputs$end_row_input)b.minHeight=Math.max(b.minHeight,a.getSourceBlock()&&a.getSourceBlock().isShadow()?this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT:this.constants_.DUMMY_INPUT_MIN_HEIGHT),b.hasDummyInput=!0;b.align===null&&(b.align=a.align)}shouldStartNewRow_(a,b){return b?b instanceof EndRowInput$$module$build$src$core$inputs$end_row_input||a instanceof StatementInput$$module$build$src$core$inputs$statement_input||b instanceof StatementInput$$module$build$src$core$inputs$statement_input? !0:a instanceof $.ValueInput$$module$build$src$core$inputs$value_input||a instanceof DummyInput$$module$build$src$core$inputs$dummy_input||b instanceof $.ValueInput$$module$build$src$core$inputs$value_input?!this.isInline:!1:!1}addElemSpacing_(){for(let a=0,b;b=this.rows[a];a++){const c=b.elements;b.elements=[];b.startsWithElemSpacer()&&b.elements.push(new InRowSpacer$$module$build$src$core$renderers$measurables$in_row_spacer(this.constants_,this.getInRowSpacing_(null,c[0])));if(c.length){for(let d= 0;da.disposeInternal());this.inputList.forEach(a=>a.dispose());this.inputList.length=0;this.getConnections_(!0).forEach(a=>a.dispose());this.disposed=!0}isDeadOrDying(){return this.disposing||this.disposed}initModel(){if(!this.initialized){for(const a of this.inputList)a.initModel();this.initialized=!0}}unplug(a){this.outputConnection&&this.unplugFromRow(a);this.previousConnection&&this.unplugFromStack(a)}unplugFromRow(a){let b=null,c;if(null==(c=this.outputConnection)?0: -c.isConnected())b=this.outputConnection.targetConnection,this.outputConnection.disconnect();b&&a&&(a=this.getOnlyValueConnection())&&a.isConnected()&&!a.targetBlock().isShadow()&&(a=a.targetConnection,null==a||a.disconnect(),this.workspace.connectionChecker.canConnect(a,b,!1)?b.connect(a):null==a||a.onFailedConnect(b))}getOnlyValueConnection(){let a=null;for(let b=0;b{d=d+("("===c||")"===e?"":" ")+e;c=e[e.length-1];return d},"");b=b.trim()||"???";a&&b.length>a&&(b=b.substring(0,a-3)+"...");return b}toTokens(a="?"){const b=[];for(const d of this.inputList)if(d.name!=COLLAPSED_INPUT_NAME$$module$build$src$core$constants){for(const e of d.fieldRow)b.push(e.getText()); -if(d.connection){const e=d.connection.targetBlock();if(e){var c=d.connection;let f=c.getCheck();!f&&c.targetConnection&&(f=c.targetConnection.getCheck());(c=!!f&&(f.includes("Boolean")||f.includes("Number")))&&b.push("(");b.push(...e.toTokens(a));c&&b.push(")")}else b.push(a)}}return b}appendValueInput(a){return this.appendInput(new $.ValueInput$$module$build$src$core$inputs$value_input(a,this))}appendStatementInput(a){this.statementInputCount++;return this.appendInput(new StatementInput$$module$build$src$core$inputs$statement_input(a, -this))}appendDummyInput(a=""){return this.appendInput(new DummyInput$$module$build$src$core$inputs$dummy_input(a,this))}appendEndRowInput(a=""){return this.appendInput(new EndRowInput$$module$build$src$core$inputs$end_row_input(a,this))}appendInput(a){this.inputList.push(a);return a}appendInputFromRegistry(a,b){return(a=getClass$$module$build$src$core$registry(Type$$module$build$src$core$registry.INPUT,a,!1))?this.appendInput(new a(b,this)):null}jsonInit(a){var b=a.type?'Block "'+a.type+'": ':""; -if(a.output&&a.previousStatement)throw Error(b+"Must not have both an output and a previousStatement.");for(var c=0;a["args"+c];){if(void 0===a["message"+c])throw Error(b+`args${c} must have a corresponding message (message${c}).`);c++}a.style&&a.style.hat&&(this.hat=a.style.hat,a.style=null);if(a.style&&a.colour)throw Error(b+"Must not have both a colour and a style.");a.style?this.jsonInitStyle(a,b):this.jsonInitColour(a,b);for(c=0;void 0!==a["message"+c];)this.interpolate(a["message"+c],a["args"+ -c]||[],a["implicitAlign"+c]||a["lastDummyAlign"+c],b),c++;void 0!==a.inputsInline&&($.disable$$module$build$src$core$events$utils(),this.setInputsInline(a.inputsInline),$.enable$$module$build$src$core$events$utils());void 0!==a.output&&this.setOutput(!0,a.output);void 0!==a.outputShape&&this.setOutputShape(a.outputShape);void 0!==a.previousStatement&&this.setPreviousStatement(!0,a.previousStatement);void 0!==a.nextStatement&&this.setNextStatement(!0,a.nextStatement);void 0!==a.tooltip&&(c=replaceMessageReferences$$module$build$src$core$utils$parsing(a.tooltip), -this.setTooltip(c));void 0!==a.enableContextMenu&&(this.contextMenu=!!a.enableContextMenu);void 0!==a.suppressPrefixSuffix&&(this.suppressPrefixSuffix=!!a.suppressPrefixSuffix);void 0!==a.helpUrl&&(c=replaceMessageReferences$$module$build$src$core$utils$parsing(a.helpUrl),this.setHelpUrl(c));"string"===typeof a.extensions&&(console.warn(b+"JSON attribute 'extensions' should be an array of strings. Found raw string in JSON for '"+a.type+"' block."),a.extensions=[a.extensions]);void 0!==a.mutator&& -apply$$module$build$src$core$extensions(a.mutator,this,!0);a=a.extensions;if(Array.isArray(a))for(b=0;bf||f>b)throw Error('Block "'+this.type+'": Message index %'+f+" out of range.");if(c[f])throw Error('Block "'+this.type+'": Message index %'+f+" duplicated.");c[f]=!0;d++}}if(d!==b)throw Error('Block "'+this.type+'": Message does not reference all '+b+" arg(s).");}interpolateArguments(a,b,c){const d=[];for(let f=0;f=this.inputList.length)throw RangeError("Input index "+a+" out of bounds.");if(b>this.inputList.length)throw RangeError("Reference input "+b+" out of bounds."); -const c=this.inputList[a];this.inputList.splice(a,1);ab.getWeight()-c.getWeight());return a}removeIcon(a){if(!this.hasIcon(a))return!1;let b;null==(b=this.getIcon(a))||b.dispose();this.icons=this.icons.filter(c=> -!c.getType().equals(a));return!0}hasIcon(a){return this.icons.some(b=>b.getType().equals(a))}getIcon(a){return a instanceof IconType$$module$build$src$core$icons$icon_types?this.icons.find(b=>b.getType().equals(a)):this.icons.find(b=>b.getType().toString()===a)}getIcons(){return[...this.icons]}getRelativeToSurfaceXY(){return this.xy}moveBy(a,b,c){if(this.parentBlock_)throw Error("Block has parent");const d=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_MOVE))(this); -c&&d.setReason(c);this.xy.translate(a,b);d.recordNew();fire$$module$build$src$core$events$utils(d)}makeConnection_(a){return new Connection$$module$build$src$core$connection(this,a)}allInputsFilled(a){void 0===a&&(a=!0);if(!a&&this.isShadow())return!1;for(let c=0,d;d=this.inputList[c];c++)if(d.connection){var b=d.connection.targetBlock();if(!b||!b.allInputsFilled(a))return!1}return(b=this.getNextBlock())?b.allInputsFilled(a):!0}toDevString(){let a=this.type?'"'+this.type+'" block':"Block";this.id&& -(a+=' (id="'+this.id+'")');return a}};Block$$module$build$src$core$block.COLLAPSED_INPUT_NAME=COLLAPSED_INPUT_NAME$$module$build$src$core$constants;Block$$module$build$src$core$block.COLLAPSED_FIELD_NAME=COLLAPSED_FIELD_NAME$$module$build$src$core$constants;var module$build$src$core$block={};module$build$src$core$block.Block=Block$$module$build$src$core$block;var FlyoutButton$$module$build$src$core$flyout_button=class{constructor(a,b,c,d){this.workspace=a;this.targetWorkspace=b;this.isFlyoutLabel=d;this.onMouseUpWrapper=null;this.height=this.width=0;this.cursorSvg=this.svgText=this.svgGroup=null;this.text=c.text;this.position=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.callbackKey=c.callbackKey||c.callbackkey;this.cssClass=c["web-class"]||null;this.info=c}createDom(){var a=this.isFlyoutLabel?"blocklyFlyoutLabel":"blocklyFlyoutButton"; -this.cssClass&&(a+=" "+this.cssClass);this.svgGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":a},this.workspace.getCanvas());let b;this.isFlyoutLabel||(b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyFlyoutButtonShadow",rx:FlyoutButton$$module$build$src$core$flyout_button.BORDER_RADIUS,ry:FlyoutButton$$module$build$src$core$flyout_button.BORDER_RADIUS,x:1,y:1},this.svgGroup));a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT, -{"class":this.isFlyoutLabel?"blocklyFlyoutLabelBackground":"blocklyFlyoutButtonBackground",rx:FlyoutButton$$module$build$src$core$flyout_button.BORDER_RADIUS,ry:FlyoutButton$$module$build$src$core$flyout_button.BORDER_RADIUS},this.svgGroup);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT,{"class":this.isFlyoutLabel?"blocklyFlyoutLabelText":"blocklyText",x:0,y:0,"text-anchor":"middle"},this.svgGroup);var d=replaceMessageReferences$$module$build$src$core$utils$parsing(this.text); -this.workspace.RTL&&(d+="\u200f");c.textContent=d;this.isFlyoutLabel&&(this.svgText=c,this.workspace.getThemeManager().subscribe(this.svgText,"flyoutForegroundColour","fill"));const e=getComputedStyle$$module$build$src$core$utils$style(c,"fontSize"),f=getComputedStyle$$module$build$src$core$utils$style(c,"fontWeight"),g=getComputedStyle$$module$build$src$core$utils$style(c,"fontFamily");this.width=getFastTextWidthWithSizeString$$module$build$src$core$utils$dom(c,e,f,g);d=measureFontMetrics$$module$build$src$core$utils$dom(d, -e,f,g);this.height=d.height;if(!this.isFlyoutLabel){this.width+=2*FlyoutButton$$module$build$src$core$flyout_button.TEXT_MARGIN_X;this.height+=2*FlyoutButton$$module$build$src$core$flyout_button.TEXT_MARGIN_Y;let h;null==(h=b)||h.setAttribute("width",String(this.width));let k;null==(k=b)||k.setAttribute("height",String(this.height))}a.setAttribute("width",String(this.width));a.setAttribute("height",String(this.height));c.setAttribute("x",String(this.width/2));c.setAttribute("y",String(this.height/ -2-d.height/2+d.baseline));this.updateTransform();this.onMouseUpWrapper=conditionalBind$$module$build$src$core$browser_events(this.svgGroup,"pointerup",this,this.onMouseUp);return this.svgGroup}show(){this.updateTransform();this.svgGroup.setAttribute("display","block")}updateTransform(){this.svgGroup.setAttribute("transform","translate("+this.position.x+","+this.position.y+")")}moveTo(a,b){this.position.x=a;this.position.y=b;this.updateTransform()}isLabel(){return this.isFlyoutLabel}getPosition(){return this.position}getButtonText(){return this.text}getTargetWorkspace(){return this.targetWorkspace}getWorkspace(){return this.workspace}dispose(){this.onMouseUpWrapper&& -unbind$$module$build$src$core$browser_events(this.onMouseUpWrapper);this.svgGroup&&removeNode$$module$build$src$core$utils$dom(this.svgGroup);this.svgText&&this.workspace.getThemeManager().unsubscribe(this.svgText)}setCursorSvg(a){a?this.svgGroup&&(this.svgGroup.appendChild(a),this.cursorSvg=a):this.cursorSvg=null}setMarkerSvg(){throw Error("Attempted to set a marker on a button.");}onMouseUp(a){(a=this.targetWorkspace.getGesture(a))&&a.cancel();this.isFlyoutLabel&&this.callbackKey?console.warn("Labels should not have callbacks. Label text: "+ -this.text):this.isFlyoutLabel||this.callbackKey&&this.targetWorkspace.getButtonCallback(this.callbackKey)?this.isFlyoutLabel||(a=this.targetWorkspace.getButtonCallback(this.callbackKey))&&a(this):console.warn("Buttons should have callbacks. Button text: "+this.text)}};FlyoutButton$$module$build$src$core$flyout_button.TEXT_MARGIN_X=5;FlyoutButton$$module$build$src$core$flyout_button.TEXT_MARGIN_Y=2;FlyoutButton$$module$build$src$core$flyout_button.BORDER_RADIUS=4;register$$module$build$src$core$css("\n.blocklyFlyoutButton {\n fill: #888;\n cursor: default;\n}\n\n.blocklyFlyoutButtonShadow {\n fill: #666;\n}\n\n.blocklyFlyoutButton:hover {\n fill: #aaa;\n}\n\n.blocklyFlyoutLabel {\n cursor: default;\n}\n\n.blocklyFlyoutLabelBackground {\n opacity: 0;\n}\n"); -var module$build$src$core$flyout_button={};module$build$src$core$flyout_button.FlyoutButton=FlyoutButton$$module$build$src$core$flyout_button;var ASTNode$$module$build$src$core$keyboard_nav$ast_node=class{constructor(a,b,c){this.wsCoordinate=null;if(!b)throw Error("Cannot create a node without a location.");this.type=a;this.isConnectionLocation=ASTNode$$module$build$src$core$keyboard_nav$ast_node.isConnectionType(a);this.location=b;this.processParams(c||null)}processParams(a){a&&a.wsCoordinate&&(this.wsCoordinate=a.wsCoordinate)}getLocation(){return this.location}getType(){return this.type}getWsCoordinate(){return this.wsCoordinate}isConnection(){return this.isConnectionLocation}findNextForInput(){var a= -this.location.getParentInput();const b=a.getSourceBlock();a=b.inputList.indexOf(a);for(a+=1;ab instanceof Block$$module$build$src$core$block&&e.block===b||b instanceof FlyoutButton$$module$build$src$core$flyout_button&&e.button===b?!0:!1);if(0>d)return null;c=c?d+1:d-1;return-1===c||c===a.length?null:a[c]}findTopASTNodeForBlock(a){const b=getParentConnection$$module$build$src$core$keyboard_nav$ast_node(a);return b?ASTNode$$module$build$src$core$keyboard_nav$ast_node.createConnectionNode(b): -ASTNode$$module$build$src$core$keyboard_nav$ast_node.createBlockNode(a)}getOutAstNodeForBlock(a){if(!a)return null;a=a.getTopStackBlock();const b=getParentConnection$$module$build$src$core$keyboard_nav$ast_node(a);return b&&b.targetConnection&&b.targetConnection.getParentInput()?ASTNode$$module$build$src$core$keyboard_nav$ast_node.createInputNode(b.targetConnection.getParentInput()):ASTNode$$module$build$src$core$keyboard_nav$ast_node.createStackNode(a)}findFirstFieldOrInput(a){a=a.inputList;for(let b= -0;b{connectionUiEffect$$module$build$src$core$block_animations(c.getSourceBlock());setTimeout(()=>{d.bringToFront()},0)})}}update(a,b){const c=this.getCandidate(a);if((this.wouldDeleteBlock=this.shouldDelete(!!c,b))||this.shouldUpdatePreviews(c,a))$.disable$$module$build$src$core$events$utils(),this.maybeHidePreview(c),this.maybeShowPreview(c),$.enable$$module$build$src$core$events$utils()}createMarkerBlock(a){$.disable$$module$build$src$core$events$utils(); -let b;try{const c=save$$module$build$src$core$serialization$blocks(a,{addCoordinates:!1,addInputBlocks:!1,addNextBlocks:!1,doFullSerialization:!1});if(!c)throw Error(`Failed to serialize source block. ${a.toDevString()}`);b=append$$module$build$src$core$serialization$blocks(c,this.workspace);for(const d of b.getDescendants(!1))d.setInsertionMarker(!0);b.initSvg();b.getSvgRoot().setAttribute("visibility","hidden")}finally{$.enable$$module$build$src$core$events$utils()}return b}initAvailableConnections(){const a= -this.topBlock.getConnections_(!1),b=this.topBlock.lastConnectionInStack(!0);b&&b!==this.topBlock.nextConnection&&(a.push(b),this.lastOnStack=b);return a}shouldUpdatePreviews(a,b){if(!a)return!!this.activeCandidate;if(!this.activeCandidate)return!0;const {local:c,closest:d}=this.activeCandidate;if(d===a.closest&&c===a.local)return!1;const e=c.x+b.x-d.x;b=c.y+b.y-d.y;return a.radius{let k;null==(k=d)||k.positionNearConnection(h,f,g);let l;null==(l=d)||l.getSvgRoot().setAttribute("visibility","visible")});this.markerConnection=e}hideInsertionMarker(){if(this.markerConnection){var a=this.markerConnection,b=a.getSourceBlock(),c=b.outputConnection,d;if((null==(d=b.previousConnection)?0:d.targetConnection)||(null==c?0:c.targetConnection))b.unplug(!0);else{let e;null==(e=a.targetBlock())||e.unplug(!1)}if(a.targetConnection)throw Error("markerConnection still connected at the end of disconnectInsertionMarker"); -this.markerConnection=null;(a=b.getSvgRoot())&&a.setAttribute("visibility","hidden")}}showInsertionInputOutline(a){a=a.closest;this.highlightedBlock=a.getSourceBlock();this.highlightedBlock.highlightShapeForInput(a,!0)}hideInsertionInputOutline(){if(this.highlightedBlock){if(!this.activeCandidate)throw Error("Cannot hide the insertion marker outline because there is no active candidate");this.highlightedBlock.highlightShapeForInput(this.activeCandidate.closest,!1);this.highlightedBlock=null}}showReplacementFade(a){this.fadedBlock= -a.closest.targetBlock();if(!this.fadedBlock)throw Error("Cannot show the replacement fade because the closest connection does not have a target block");this.fadedBlock.fadeForReplacement(!0)}hideReplacementFade(){this.fadedBlock&&(this.fadedBlock.fadeForReplacement(!1),this.fadedBlock=null)}getInsertionMarkers(){const a=[];this.firstMarker&&a.push(this.firstMarker);this.lastMarker&&a.push(this.lastMarker);return a}disposeInsertionMarker(a){if(a){$.disable$$module$build$src$core$events$utils();try{a.dispose()}finally{$.enable$$module$build$src$core$events$utils()}}}}; -(function(a){a=a.PREVIEW_TYPE||(a.PREVIEW_TYPE={});a[a.INSERTION_MARKER=0]="INSERTION_MARKER";a[a.INPUT_OUTLINE=1]="INPUT_OUTLINE";a[a.REPLACEMENT_FADE=2]="REPLACEMENT_FADE"})(InsertionMarkerManager$$module$build$src$core$insertion_marker_manager||(InsertionMarkerManager$$module$build$src$core$insertion_marker_manager={})); -var PreviewType$$module$build$src$core$insertion_marker_manager=InsertionMarkerManager$$module$build$src$core$insertion_marker_manager.PREVIEW_TYPE,module$build$src$core$insertion_marker_manager={};module$build$src$core$insertion_marker_manager.InsertionMarkerManager=InsertionMarkerManager$$module$build$src$core$insertion_marker_manager;module$build$src$core$insertion_marker_manager.PreviewType=PreviewType$$module$build$src$core$insertion_marker_manager;var Renderer$$module$build$src$core$renderers$common$renderer=class{constructor(a){this.overrides=null;this.name=a}getClassName(){return this.name+"-renderer"}init(a,b){this.constants_=this.makeConstants_();b&&(this.overrides=b,Object.assign(this.constants_,b));this.constants_.setTheme(a);this.constants_.init()}createDom(a,b){this.constants_.createDom(a,this.name+"-"+b.name,"."+this.getClassName()+"."+b.getClassName())}refreshDom(a,b){const c=this.getConstants();c.dispose();this.constants_=this.makeConstants_(); -this.overrides&&Object.assign(this.constants_,this.overrides);this.constants_.randomIdentifier=c.randomIdentifier;this.constants_.setTheme(b);this.constants_.init();this.createDom(a,b)}dispose(){this.constants_&&this.constants_.dispose()}makeConstants_(){return new ConstantProvider$$module$build$src$core$renderers$common$constants}makeRenderInfo_(a){return new RenderInfo$$module$build$src$core$renderers$common$info(this,a)}makeDrawer_(a,b){return new Drawer$$module$build$src$core$renderers$common$drawer(a, -b)}makeMarkerDrawer(a,b){return new MarkerSvg$$module$build$src$core$renderers$common$marker_svg(a,this.getConstants(),b)}makePathObject(a,b){return new PathObject$$module$build$src$core$renderers$common$path_object(a,b,this.constants_)}getConstants(){return this.constants_}shouldHighlightConnection(a){return!0}orphanCanConnectAtEnd(a,b,c){return!!Connection$$module$build$src$core$connection.getConnectionForOrphanedConnection(a,c===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE? -b.outputConnection:b.previousConnection)}getConnectionPreviewMethod(a,b,c){warn$$module$build$src$core$utils$deprecation("getConnectionPreviewMethod","v10","v12","an IConnectionPreviewer, if it fulfills your use case.");return b.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE||b.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT?!a.isConnected()||this.orphanCanConnectAtEnd(c,a.targetBlock(),b.type)?InsertionMarkerManager$$module$build$src$core$insertion_marker_manager.PREVIEW_TYPE.INSERTION_MARKER: -InsertionMarkerManager$$module$build$src$core$insertion_marker_manager.PREVIEW_TYPE.REPLACEMENT_FADE:InsertionMarkerManager$$module$build$src$core$insertion_marker_manager.PREVIEW_TYPE.INSERTION_MARKER}render(a){const b=this.makeRenderInfo_(a);b.measure();this.makeDrawer_(a,b).draw()}},module$build$src$core$renderers$common$renderer={};module$build$src$core$renderers$common$renderer.Renderer=Renderer$$module$build$src$core$renderers$common$renderer;var module$build$src$core$renderers$common$block_rendering={};module$build$src$core$renderers$common$block_rendering.BottomRow=BottomRow$$module$build$src$core$renderers$measurables$bottom_row;module$build$src$core$renderers$common$block_rendering.Connection=Connection$$module$build$src$core$renderers$measurables$connection;module$build$src$core$renderers$common$block_rendering.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$common$constants; +b&&(Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(b)||Types$$module$build$src$core$renderers$measurables$types.isNextConnection(b))?b.notchOffset:a&&Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(a)&&b&&(Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(b)||Types$$module$build$src$core$renderers$measurables$types.isNextConnection(b))?b.notchOffset-this.constants_.CORNER_RADIUS:a&&Types$$module$build$src$core$renderers$measurables$types.isField(a)&& +a.width===0?this.constants_.NO_PADDING:this.constants_.MEDIUM_PADDING}computeBounds_(){let a=0,b=0,c=0;for(let e=0,f;f=this.rows[e];e++){f.measure();b=Math.max(b,f.width);if(f.hasStatement){var d=f.getLastInput();let g,h;d=f.width-((h=(g=d)==null?void 0:g.width)!=null?h:0);a=Math.max(a,d)}c=Math.max(c,f.widthWithConnectedBlocks)}this.statementEdge=a;this.width=b;for(let e=0,f;f=this.rows[e];e++)f.hasStatement&&(f.statementEdge=this.statementEdge);this.widthWithChildren=Math.max(b,c);this.outputConnection&& +(this.startX=this.outputConnection.width,this.width+=this.outputConnection.width,this.widthWithChildren+=this.outputConnection.width)}alignRowElements_(){for(let b=0,c;c=this.rows[b];b++)if(c.hasStatement)this.alignStatementRow_(c);else{var a=c.width;a=this.getDesiredRowWidth_(c)-a;a>0&&this.addAlignmentPadding_(c,a);Types$$module$build$src$core$renderers$measurables$types.isTopOrBottomRow(c)&&(c.widthWithConnectedBlocks=c.width)}}getDesiredRowWidth_(a){return this.width-this.startX}addAlignmentPadding_(a, +b){const c=a.getFirstSpacer(),d=a.getLastSpacer();if(a.hasExternalInput||a.hasStatement)a.widthWithConnectedBlocks+=b;if(a.align===$.Align$$module$build$src$core$inputs$align.LEFT&&d)d.width+=b;else if(a.align===$.Align$$module$build$src$core$inputs$align.CENTRE&&c&&d)c.width+=b/2,d.width+=b/2;else if(a.align===$.Align$$module$build$src$core$inputs$align.RIGHT&&c)c.width+=b;else if(d)d.width+=b;else return;a.width+=b}alignStatementRow_(a){const b=a.getLastInput();if(b){var c=a.width-b.width,d=this.statementEdge; +c=d-c;c>0&&this.addAlignmentPadding_(a,c);c=a.width;d=this.getDesiredRowWidth_(a);b.width+=d-c;b.height=Math.max(b.height,a.height);a.width+=d-c;a.widthWithConnectedBlocks=Math.max(a.width,this.statementEdge+a.connectedBlockWidths)}}addRowSpacing_(){const a=this.rows;this.rows=[];for(let b=0;b=0;d--)c[d].element===a&&c.splice(d,1);c.length||this.componentDB.delete(b)}}dispose(){this.subscribedWorkspaces.length=0;this.componentDB.clear()}},module$build$src$core$theme_manager={};module$build$src$core$theme_manager.ThemeManager=ThemeManager$$module$build$src$core$theme_manager;var CATEGORY_NAME$$module$build$src$core$variables_dynamic="VARIABLE_DYNAMIC",onCreateVariableButtonClick_String$$module$build$src$core$variables_dynamic=stringButtonClickHandler$$module$build$src$core$variables_dynamic,onCreateVariableButtonClick_Number$$module$build$src$core$variables_dynamic=numberButtonClickHandler$$module$build$src$core$variables_dynamic,onCreateVariableButtonClick_Colour$$module$build$src$core$variables_dynamic=colourButtonClickHandler$$module$build$src$core$variables_dynamic, +module$build$src$core$variables_dynamic={CATEGORY_NAME:CATEGORY_NAME$$module$build$src$core$variables_dynamic};module$build$src$core$variables_dynamic.flyoutCategory=flyoutCategory$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.flyoutCategoryBlocks=flyoutCategoryBlocks$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.internalFlyoutCategory=internalFlyoutCategory$$module$build$src$core$variables_dynamic; +module$build$src$core$variables_dynamic.onCreateVariableButtonClick_Colour=colourButtonClickHandler$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.onCreateVariableButtonClick_Number=numberButtonClickHandler$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.onCreateVariableButtonClick_String=stringButtonClickHandler$$module$build$src$core$variables_dynamic;var ConnectionChecker$$module$build$src$core$connection_checker=class{canConnect(a,b,c,d){return this.canConnectWithReason(a,b,c,d)===Connection$$module$build$src$core$connection.CAN_CONNECT}canConnectWithReason(a,b,c,d){const e=this.doSafetyChecks(a,b);return e!==Connection$$module$build$src$core$connection.CAN_CONNECT?e:this.doTypeChecks(a,b)?c&&!this.doDragChecks(a,b,d||0)?Connection$$module$build$src$core$connection.REASON_DRAG_CHECKS_FAILED:Connection$$module$build$src$core$connection.CAN_CONNECT: Connection$$module$build$src$core$connection.REASON_CHECKS_FAILED}getErrorMessage(a,b,c){switch(a){case Connection$$module$build$src$core$connection.REASON_SELF_CONNECTION:return"Attempted to connect a block to itself.";case Connection$$module$build$src$core$connection.REASON_DIFFERENT_WORKSPACES:return"Blocks not on same workspace.";case Connection$$module$build$src$core$connection.REASON_WRONG_TYPE:return"Attempt to connect incompatible types.";case Connection$$module$build$src$core$connection.REASON_TARGET_NULL:return"Target connection is null."; case Connection$$module$build$src$core$connection.REASON_CHECKS_FAILED:return"Connection checks failed. "+(b+" expected "+b.getCheck()+", found "+c.getCheck());case Connection$$module$build$src$core$connection.REASON_SHADOW_PARENT:return"Connecting non-shadow to shadow block.";case Connection$$module$build$src$core$connection.REASON_DRAG_CHECKS_FAILED:return"Drag checks failed.";case Connection$$module$build$src$core$connection.REASON_PREVIOUS_AND_OUTPUT:return"Block would have an output and a previous connection."; default:return"Unknown connection failure: this should never happen!"}}doSafetyChecks(a,b){if(!a||!b)return Connection$$module$build$src$core$connection.REASON_TARGET_NULL;let c,d,e;a.isSuperior()?(c=a.getSourceBlock(),d=b.getSourceBlock(),e=b):(d=a.getSourceBlock(),c=b.getSourceBlock(),e=a,a=b);return c===d?Connection$$module$build$src$core$connection.REASON_SELF_CONNECTION:e.type!==OPPOSITE_TYPE$$module$build$src$core$internal_constants[a.type]?Connection$$module$build$src$core$connection.REASON_WRONG_TYPE: @@ -1134,431 +1329,351 @@ c.workspace!==d.workspace?Connection$$module$build$src$core$connection.REASON_DI Connection$$module$build$src$core$connection.CAN_CONNECT}doTypeChecks(a,b){a=a.getCheck();b=b.getCheck();if(!a||!b)return!0;for(let c=0;cc||b.getSourceBlock().isInsertionMarker())return!1;switch(b.type){case ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT:return this.canConnectToPrevious_(a,b);case ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE:if(b.isConnected()&& !b.targetBlock().isInsertionMarker()||a.isConnected())return!1;break;case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:if(b.isConnected()&&!b.targetBlock().isMovable()&&!b.targetBlock().isShadow())return!1;break;case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:if(b.isConnected()&&!a.getSourceBlock().nextConnection&&!b.targetBlock().isShadow()&&b.targetBlock().nextConnection||b.targetBlock()&&!b.targetBlock().isMovable()&&!b.targetBlock().isShadow())return!1; break;default:return!1}return draggingConnections$$module$build$src$core$common.includes(b)?!1:!0}canConnectToPrevious_(a,b){if(a.targetConnection||draggingConnections$$module$build$src$core$common.includes(b))return!1;if(!b.targetConnection)return!0;a=b.targetBlock();return a.isInsertionMarker()?!a.getPreviousBlock():!1}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.CONNECTION_CHECKER,DEFAULT$$module$build$src$core$registry,ConnectionChecker$$module$build$src$core$connection_checker); -var module$build$src$core$connection_checker={};module$build$src$core$connection_checker.ConnectionChecker=ConnectionChecker$$module$build$src$core$connection_checker;var VarDelete$$module$build$src$core$events$events_var_delete=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a){super(a);this.type=EventType$$module$build$src$core$events$type.VAR_DELETE;a&&(this.varType=a.type,this.varName=a.name)}toJson(){const a=super.toJson();if(void 0===this.varType)throw Error("The var type is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); -a.varType=this.varType;a.varName=this.varName;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new VarDelete$$module$build$src$core$events$events_var_delete);b.varType=a.varType;b.varName=a.varName;return b}run(a){const b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson");a?b.deleteVariableById(this.varId): -b.createVariable(this.varName,this.varType,this.varId)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VAR_DELETE,VarDelete$$module$build$src$core$events$events_var_delete);var module$build$src$core$events$events_var_delete={};module$build$src$core$events$events_var_delete.VarDelete=VarDelete$$module$build$src$core$events$events_var_delete;var VarRename$$module$build$src$core$events$events_var_rename=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a,b){super(a);this.type=EventType$$module$build$src$core$events$type.VAR_RENAME;a&&(this.oldName=a.name,this.newName="undefined"===typeof b?"":b)}toJson(){const a=super.toJson();if(!this.oldName)throw Error("The old var name is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.newName)throw Error("The new var name is undefined. Either pass a value to the constructor, or call fromJson"); -a.oldName=this.oldName;a.newName=this.newName;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new VarRename$$module$build$src$core$events$events_var_rename);b.oldName=a.oldName;b.newName=a.newName;return b}run(a){const b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.oldName)throw Error("The old var name is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.newName)throw Error("The new var name is undefined. Either pass a value to the constructor, or call fromJson"); -a?b.renameVariableById(this.varId,this.newName):b.renameVariableById(this.varId,this.oldName)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VAR_RENAME,VarRename$$module$build$src$core$events$events_var_rename);var module$build$src$core$events$events_var_rename={};module$build$src$core$events$events_var_rename.VarRename=VarRename$$module$build$src$core$events$events_var_rename;var VariableMap$$module$build$src$core$variable_map=class{constructor(a){this.workspace=a;this.variableMap=new Map}clear(){for(const a of this.variableMap.values())for(;0{e&&b&&this.deleteVariableInternal(b,d)})):this.deleteVariableInternal(b,d)}else console.warn("Can't delete non-existent variable: "+ -a)}deleteVariableInternal(a,b){const c=$.getGroup$$module$build$src$core$events$utils();c||$.setGroup$$module$build$src$core$events$utils(!0);try{for(let d=0;da.name)}getVariableUsesById(a){const b= -[],c=this.workspace.getAllBlocks(!1);for(let d=0;d!c.isInsertionMarker())}addTopComment(a){this.topComments.push(a);this.commentDB.has(a.id)&&console.warn('Overriding an existing comment on this workspace, with id "'+a.id+'"');this.commentDB.set(a.id,a)}removeTopComment(a){if(!removeElem$$module$build$src$core$utils$array(this.topComments,a))throw Error("Comment not present in workspace's list of top-most comments."); -this.commentDB.delete(a.id)}getTopComments(a=!1){const b=[].concat(this.topComments);a&&1!c.isInsertionMarker())}clear(){this.isClearing=!0;try{const a=$.getGroup$$module$build$src$core$events$utils();for(a||$.setGroup$$module$build$src$core$events$utils(!0);this.topBlocks.length;)this.topBlocks[0].dispose(!1); -for(;this.topComments.length;)this.topComments[this.topComments.length-1].dispose();$.setGroup$$module$build$src$core$events$utils(a);this.variableMap.clear();this.potentialVariableMap&&this.potentialVariableMap.clear()}finally{this.isClearing=!1}}renameVariableById(a,b){this.variableMap.renameVariableById(a,b)}createVariable(a,b,c){return this.variableMap.createVariable(a,b,c)}getVariableUsesById(a){return this.variableMap.getVariableUsesById(a)}deleteVariableById(a){this.variableMap.deleteVariableById(a)}getVariable(a, -b){return this.variableMap.getVariable(a,b)}getVariableById(a){return this.variableMap.getVariableById(a)}getVariablesOfType(a){return this.variableMap.getVariablesOfType(a)}getVariableTypes(){return this.variableMap.getVariableTypes(this)}getAllVariables(){return this.variableMap.getAllVariables()}getAllVariableNames(){return this.variableMap.getAllVariableNames()}getWidth(){return 0}newBlock(a,b){throw Error("The implementation of newBlock should be monkey-patched in by blockly.ts");}newComment(a){throw Error("The implementation of newComment should be monkey-patched in by blockly.ts"); -}remainingCapacity(){return isNaN(this.options.maxBlocks)?Infinity:this.options.maxBlocks-this.getAllBlocks(!1).length}remainingCapacityOfType(a){return this.options.maxInstances?(void 0!==this.options.maxInstances[a]?this.options.maxInstances[a]:Infinity)-this.getBlocksByType(a,!1).length:Infinity}isCapacityAvailable(a){if(!this.hasBlockLimits())return!0;let b=0;for(const c in a){if(a[c]>this.remainingCapacityOfType(c))return!1;b+=a[c]}return b>this.remainingCapacity()?!1:!0}hasBlockLimits(){return Infinity!== -this.options.maxBlocks||!!this.options.maxInstances}getUndoStack(){return this.undoStack_}getRedoStack(){return this.redoStack_}undo(a){var b=a?this.redoStack_:this.undoStack_,c=a?this.undoStack_:this.redoStack_;const d=b.pop();if(d){for(var e=[d];b.length&&d.group&&d.group===b[b.length-1].group;){const f=b.pop();f&&e.push(f)}for(b=0;bthis.MAX_UNDO&&0<=this.MAX_UNDO;)this.undoStack_.shift();for(let b=0;b({getBoundingRectangle:()=>{const e=d.getRelativeToSurfaceXY();return new Rect$$module$build$src$core$utils$rect(e.y,e.y,e.x,e.x)},moveBy:()=>{}});return this.sortByOrigin(c(a),c(b))}sortByOrigin(a,b){const c=Math.sin(toRadians$$module$build$src$core$utils$math(Workspace$$module$build$src$core$workspace.SCAN_ANGLE))* +(this.RTL?-1:1);a=a.getBoundingRectangle().getOrigin();b=b.getBoundingRectangle().getOrigin();return a.y+c*a.x-(b.y+c*b.x)}addTopBlock(a){this.topBlocks.push(a)}removeTopBlock(a){if(!removeElem$$module$build$src$core$utils$array(this.topBlocks,a))throw Error("Block not present in workspace's list of top-most blocks.");}getTopBlocks(a=!1){const b=[].concat(this.topBlocks);a&&b.length>1&&b.sort(this.sortObjects.bind(this));return b}addTypedBlock(a){this.typedBlocksDB.has(a.type)||this.typedBlocksDB.set(a.type, +[]);this.typedBlocksDB.get(a.type).push(a)}removeTypedBlock(a){removeElem$$module$build$src$core$utils$array(this.typedBlocksDB.get(a.type),a);this.typedBlocksDB.get(a.type).length||this.typedBlocksDB.delete(a.type)}getBlocksByType(a,b=!1){if(!this.typedBlocksDB.has(a))return[];a=this.typedBlocksDB.get(a).slice(0);b&&a&&a.length>1&&a.sort(this.sortObjects.bind(this));return a.filter(c=>!c.isInsertionMarker())}addTopComment(a){this.topComments.push(a);this.commentDB.has(a.id)&&console.warn('Overriding an existing comment on this workspace, with id "'+ +a.id+'"');this.commentDB.set(a.id,a)}removeTopComment(a){if(!removeElem$$module$build$src$core$utils$array(this.topComments,a))throw Error("Comment not present in workspace's list of top-most comments.");this.commentDB.delete(a.id)}getTopComments(a=!1){const b=[].concat(this.topComments);a&&b.length>1&&b.sort(this.sortObjects.bind(this));return b}getAllBlocks(a=!1){if(a){var b=this.getTopBlocks(!0);a=[];for(let c=0;c!c.isInsertionMarker())}clear(){this.isClearing=!0;try{const a=$.getGroup$$module$build$src$core$events$utils();for(a||$.setGroup$$module$build$src$core$events$utils(!0);this.topBlocks.length;)this.topBlocks[0].dispose(!1);for(;this.topComments.length;)this.topComments[this.topComments.length-1].dispose();$.setGroup$$module$build$src$core$events$utils(a);this.isFlyout||this.variableMap.clear();this.potentialVariableMap&&this.potentialVariableMap.clear()}finally{this.isClearing= +!1}}renameVariableById(a,b){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.renameVariableById","v12","v13","Blockly.Workspace.getVariableMap().renameVariable");(a=this.variableMap.getVariableById(a))&&this.variableMap.renameVariable(a,b)}createVariable(a,b,c){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.createVariable","v12","v13","Blockly.Workspace.getVariableMap().createVariable");return this.variableMap.createVariable(a,b!=null?b:void 0,c!=null?c:void 0)}getVariableUsesById(a){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.getVariableUsesById", +"v12","v13","Blockly.Variables.getVariableUsesById");return getVariableUsesById$$module$build$src$core$variables(this,a)}deleteVariableById(a){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.deleteVariableById","v12","v13","Blockly.Workspace.getVariableMap().deleteVariable");const b=this.variableMap.getVariableById(a);b?$.deleteVariable$$module$build$src$core$variables(this,b):console.warn(`Can't delete non-existent variable: ${a}`)}getVariable(a,b){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.getVariable", +"v12","v13","Blockly.Workspace.getVariableMap().getVariable");return this.variableMap.getVariable(a,b)}getVariableById(a){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.getVariableById","v12","v13","Blockly.Workspace.getVariableMap().getVariableById");return this.variableMap.getVariableById(a)}getVariablesOfType(a){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.getVariablesOfType","v12","v13","Blockly.Workspace.getVariableMap().getVariablesOfType");return this.variableMap.getVariablesOfType(a!= +null?a:"")}getAllVariables(){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.getAllVariables","v12","v13","Blockly.Workspace.getVariableMap().getAllVariables");return this.variableMap.getAllVariables()}getAllVariableNames(){warn$$module$build$src$core$utils$deprecation("Blockly.Workspace.getAllVariableNames","v12","v13","Blockly.Workspace.getVariableMap().getAllVariables");return this.variableMap.getAllVariables().map(a=>a.getName())}getWidth(){return 0}newBlock(a,b){throw Error("The implementation of newBlock should be monkey-patched in by blockly.ts"); +}newComment(a){throw Error("The implementation of newComment should be monkey-patched in by blockly.ts");}remainingCapacity(){return isNaN(this.options.maxBlocks)?Infinity:this.options.maxBlocks-this.getAllBlocks(!1).length}remainingCapacityOfType(a){return this.options.maxInstances?(this.options.maxInstances[a]!==void 0?this.options.maxInstances[a]:Infinity)-this.getBlocksByType(a,!1).length:Infinity}isCapacityAvailable(a){if(!this.hasBlockLimits())return!0;let b=0;for(const c in a){if(a[c]>this.remainingCapacityOfType(c))return!1; +b+=a[c]}return b>this.remainingCapacity()?!1:!0}hasBlockLimits(){return this.options.maxBlocks!==Infinity||!!this.options.maxInstances}getUndoStack(){return this.undoStack_}getRedoStack(){return this.redoStack_}undo(a){var b=a?this.redoStack_:this.undoStack_,c=a?this.undoStack_:this.redoStack_;const d=b.pop();if(d){for(var e=[d];b.length&&d.group&&d.group===b[b.length-1].group;){const f=b.pop();f&&e.push(f)}for(b=0;bthis.MAX_UNDO&&this.MAX_UNDO>= +0;)this.undoStack_.shift();for(let b=0;b{c.sounds.set(b,f)})}})}play(a,b){const c=this;return(0,$jscomp.asyncExecutePromiseGeneratorFunction)(function*(){if(!c.muted&&b!==0&&c.context){var d=c.sounds.get(a);if(d){const g=new Date;if(!(c.lastSound!==null&&g.getTime()-c.lastSound.getTime(){e.disconnect();f.disconnect()});e.start()}}else c.parentWorkspace&&c.parentWorkspace.getAudioManager().play(a,b)}})}setMuted(a){this.muted=a}getMuted(){return this.muted}},module$build$src$core$workspace_audio={};module$build$src$core$workspace_audio.WorkspaceAudio=WorkspaceAudio$$module$build$src$core$workspace_audio;var ZOOM_TO_FIT_MARGIN$$module$build$src$core$workspace_svg=20,WorkspaceSvg$$module$build$src$core$workspace_svg=class extends Workspace$$module$build$src$core$workspace{constructor(a){super(a);this.resizeHandlerWrapper=null;this.resizesEnabled=this.visible=this.rendered=!0;this.startScrollY=this.startScrollX=this.scrollY=this.scrollX=0;this.oldScale=this.scale=1;this.oldLeft=this.oldTop=0;this.inverseScreenCTM=this.targetWorkspace=this.dummyWheelListener=this.configureContextMenu=this.lastRecordedPageScroll= +this.injectionDiv=this.currentGesture_=this.toolbox=this.flyout=this.scrollbar=this.trashcan=null;this.inverseScreenCTMDirty=!0;this.highlightedBlocks=[];this.toolboxCategoryCallbacks=new Map;this.flyoutButtonCallbacks=new Map;this.cachedParentSvg=null;this.keyboardMoveInProgress=this.keyboardAccessibilityMode=!1;this.topBoundedElements=[];this.dragTargetAreas=[];this.zoomControls_=this.layerManager=null;this.navigator=new Navigator$$module$build$src$core$navigator;this.metricsManager=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.METRICS_MANAGER, a,!0))(this);this.getMetrics=a.getMetrics||this.metricsManager.getMetrics.bind(this.metricsManager);this.setMetrics=a.setMetrics||WorkspaceSvg$$module$build$src$core$workspace_svg.setTopLevelWorkspaceMetrics;this.componentManager=new ComponentManager$$module$build$src$core$component_manager;this.connectionDBList=ConnectionDB$$module$build$src$core$connection_db.init(this.connectionChecker);this.audioManager=new WorkspaceAudio$$module$build$src$core$workspace_audio(a.parentWorkspace);this.grid=this.options.gridPattern? -new Grid$$module$build$src$core$grid(this.options.gridPattern,a.gridOptions):null;this.markerManager=new MarkerManager$$module$build$src$core$marker_manager(this);module$build$src$core$variables&&flyoutCategory$$module$build$src$core$variables&&this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$variables,flyoutCategory$$module$build$src$core$variables);module$build$src$core$variables_dynamic&&flyoutCategory$$module$build$src$core$variables_dynamic&&this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$variables_dynamic, -flyoutCategory$$module$build$src$core$variables_dynamic);module$build$src$core$procedures&&flyoutCategory$$module$build$src$core$procedures&&(this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$procedures,flyoutCategory$$module$build$src$core$procedures),this.addChangeListener(mutatorOpenListener$$module$build$src$core$procedures));this.themeManager_=this.options.parentWorkspace?this.options.parentWorkspace.getThemeManager():new ThemeManager$$module$build$src$core$theme_manager(this, -this.options.theme||Classic$$module$build$src$core$theme$classic);this.themeManager_.subscribeWorkspace(this);let b;this.renderer=init$$module$build$src$core$renderers$common$block_rendering(this.options.renderer||"geras",this.getTheme(),null!=(b=this.options.rendererOverrides)?b:void 0);this.cachedParentSvgSize=new Size$$module$build$src$core$utils$size(0,0)}getMarkerManager(){return this.markerManager}getMetricsManager(){return this.metricsManager}setMetricsManager(a){this.metricsManager=a;this.getMetrics= -this.metricsManager.getMetrics.bind(this.metricsManager)}getComponentManager(){return this.componentManager}setCursorSvg(a){this.markerManager.setCursorSvg(a)}setMarkerSvg(a){this.markerManager.setMarkerSvg(a)}getMarker(a){return this.markerManager?this.markerManager.getMarker(a):null}getCursor(){return this.markerManager?this.markerManager.getCursor():null}getRenderer(){return this.renderer}getThemeManager(){return this.themeManager_}getTheme(){return this.themeManager_.getTheme()}setTheme(a){a|| -(a=Classic$$module$build$src$core$theme$classic);this.themeManager_.setTheme(a)}refreshTheme(){this.svgGroup_&&this.renderer.refreshDom(this.svgGroup_,this.getTheme());this.updateBlockStyles(this.getAllBlocks(!1).filter(b=>!!b.getStyleName()));this.refreshToolboxSelection();this.toolbox&&this.toolbox.refreshTheme();this.isVisible()&&this.setVisible(!0);const a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.THEME_CHANGE))(this.getTheme().name,this.id);fire$$module$build$src$core$events$utils(a)}updateBlockStyles(a){for(let b= -0,c;c=a[b];b++){const d=c.getStyleName();d&&c.setStyle(d)}}getInverseScreenCTM(){if(this.inverseScreenCTMDirty){const a=this.getParentSvg().getScreenCTM();a&&(this.inverseScreenCTM=a.inverse(),this.inverseScreenCTMDirty=!1)}return this.inverseScreenCTM}updateInverseScreenCTM(){this.inverseScreenCTMDirty=!0}isVisible(){return this.visible}getSvgXY(a){let b=0,c=0,d=1;if(this.getCanvas().contains(a)||this.getBubbleCanvas().contains(a))d=this.scale;do{const e=getRelativeXY$$module$build$src$core$utils$svg_math(a); -if(a===this.getCanvas()||a===this.getBubbleCanvas())d=1;b+=e.x*d;c+=e.y*d;a=a.parentNode}while(a&&a!==this.getParentSvg()&&a!==this.getInjectionDiv());return new Coordinate$$module$build$src$core$utils$coordinate(b,c)}getCachedParentSvgSize(){const a=this.cachedParentSvgSize;return new Size$$module$build$src$core$utils$size(a.width,a.height)}getOriginOffsetInPixels(){return getInjectionDivXY$$module$build$src$core$utils$svg_math(this.getCanvas())}getInjectionDiv(){if(!this.injectionDiv){let a=this.svgGroup_; -for(;a;){if((" "+(a.getAttribute("class")||"")+" ").includes(" injectionDiv ")){this.injectionDiv=a;break}a=a.parentNode}}return this.injectionDiv}getSvgGroup(){return this.svgGroup_}getBlockCanvas(){return this.getCanvas()}setResizeHandlerWrapper(a){this.resizeHandlerWrapper=a}createDom(a,b){this.injectionDiv||(this.injectionDiv=null!=b?b:null);this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyWorkspace"});a&&(this.svgBackground_= -createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{height:"100%",width:"100%","class":a},this.svgGroup_),"blocklyMainBackground"===a&&this.grid?this.svgBackground_.style.fill="url(#"+this.grid.getPatternId()+")":this.themeManager_.subscribe(this.svgBackground_,"workspaceBackgroundColour","fill"));this.layerManager=new LayerManager$$module$build$src$core$layer_manager(this);this.svgBlockCanvas_=this.layerManager.getBlockLayer();this.svgBubbleCanvas_=this.layerManager.getBubbleLayer(); -this.isFlyout||(conditionalBind$$module$build$src$core$browser_events(this.svgGroup_,"pointerdown",this,this.onMouseDown,!1),this.dummyWheelListener=()=>{},document.body.addEventListener("wheel",this.dummyWheelListener),conditionalBind$$module$build$src$core$browser_events(this.svgGroup_,"wheel",this,this.onMouseWheel));this.options.hasCategories&&(this.toolbox=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX,this.options,!0))(this));this.grid&& -this.grid.update(this.scale);this.recordDragTargets();(a=getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.CURSOR,this.options))&&this.markerManager.setCursor(new a);this.renderer.createDom(this.svgGroup_,this.getTheme());return this.svgGroup_}dispose(){this.rendered=!1;this.currentGesture_&&this.currentGesture_.cancel();this.svgGroup_&&removeNode$$module$build$src$core$utils$dom(this.svgGroup_);this.toolbox&&(this.toolbox.dispose(),this.toolbox=null);this.flyout&& -(this.flyout.dispose(),this.flyout=null);this.trashcan&&(this.trashcan.dispose(),this.trashcan=null);this.scrollbar&&(this.scrollbar.dispose(),this.scrollbar=null);this.zoomControls_&&this.zoomControls_.dispose();this.audioManager&&this.audioManager.dispose();this.grid&&(this.grid=null);this.renderer.dispose();this.markerManager&&this.markerManager.dispose();super.dispose();this.themeManager_&&(this.themeManager_.unsubscribeWorkspace(this),this.themeManager_.unsubscribe(this.svgBackground_),this.options.parentWorkspace|| -this.themeManager_.dispose());this.connectionDBList.length=0;this.toolboxCategoryCallbacks.clear();this.flyoutButtonCallbacks.clear();if(!this.options.parentWorkspace){const a=this.getParentSvg();a&&a.parentNode&&removeNode$$module$build$src$core$utils$dom(a.parentNode)}this.resizeHandlerWrapper&&(unbind$$module$build$src$core$browser_events(this.resizeHandlerWrapper),this.resizeHandlerWrapper=null);this.dummyWheelListener&&(document.body.removeEventListener("wheel",this.dummyWheelListener),this.dummyWheelListener= -null)}addTrashcan(){this.trashcan=WorkspaceSvg$$module$build$src$core$workspace_svg.newTrashcan(this);const a=this.trashcan.createDom();this.svgGroup_.insertBefore(a,this.getCanvas())}static newTrashcan(a){throw Error("The implementation of newTrashcan should be monkey-patched in by blockly.ts");}addZoomControls(){this.zoomControls_=new ZoomControls$$module$build$src$core$zoom_controls(this);const a=this.zoomControls_.createDom();this.svgGroup_.appendChild(a)}addFlyout(a){const b=new Options$$module$build$src$core$options({parentWorkspace:this, -rtl:this.RTL,oneBasedIndex:this.options.oneBasedIndex,horizontalLayout:this.horizontalLayout,renderer:this.options.renderer,rendererOverrides:this.options.rendererOverrides,move:{scrollbars:!0}});b.toolboxPosition=this.options.toolboxPosition;this.flyout=this.horizontalLayout?new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,this.options,!0))(b):new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX, -this.options,!0))(b);this.flyout.autoClose=!1;this.flyout.getWorkspace().setVisible(!0);return this.flyout.createDom(a)}getFlyout(a){return this.flyout||a?this.flyout:this.toolbox?this.toolbox.getFlyout():null}getToolbox(){return this.toolbox}updateScreenCalculations(){this.updateInverseScreenCTM();this.recordDragTargets()}resizeContents(){this.resizesEnabled&&this.rendered&&(this.scrollbar&&this.scrollbar.resize(),this.updateInverseScreenCTM())}resize(){this.toolbox&&this.toolbox.position();this.flyout&& +new Grid$$module$build$src$core$grid(this.options.gridPattern,a.gridOptions):null;this.markerManager=new MarkerManager$$module$build$src$core$marker_manager(this);module$build$src$core$variables&&internalFlyoutCategory$$module$build$src$core$variables&&this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$variables,internalFlyoutCategory$$module$build$src$core$variables);module$build$src$core$variables_dynamic&&internalFlyoutCategory$$module$build$src$core$variables_dynamic&&this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$variables_dynamic, +internalFlyoutCategory$$module$build$src$core$variables_dynamic);module$build$src$core$procedures&&internalFlyoutCategory$$module$build$src$core$procedures&&(this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$procedures,internalFlyoutCategory$$module$build$src$core$procedures),this.addChangeListener(mutatorOpenListener$$module$build$src$core$procedures));this.addChangeListener(this.variableChangeCallback.bind(this));this.themeManager_=this.options.parentWorkspace?this.options.parentWorkspace.getThemeManager(): +new ThemeManager$$module$build$src$core$theme_manager(this,this.options.theme||Classic$$module$build$src$core$theme$classic);this.themeManager_.subscribeWorkspace(this);let b;this.renderer=init$$module$build$src$core$renderers$common$block_rendering(this.options.renderer||"geras",this.getTheme(),(b=this.options.rendererOverrides)!=null?b:void 0);this.cachedParentSvgSize=new Size$$module$build$src$core$utils$size(0,0)}getMarkerManager(){return this.markerManager}getMetricsManager(){return this.metricsManager}setMetricsManager(a){this.metricsManager= +a;this.getMetrics=this.metricsManager.getMetrics.bind(this.metricsManager)}getComponentManager(){return this.componentManager}getMarker(a){return this.markerManager.getMarker(a)}getCursor(){return this.markerManager.getCursor()}getRenderer(){return this.renderer}getThemeManager(){return this.themeManager_}getTheme(){return this.themeManager_.getTheme()}setTheme(a){a||(a=Classic$$module$build$src$core$theme$classic);this.themeManager_.setTheme(a)}refreshTheme(){if(this.svgGroup_){var a=this.options.parentWorkspace=== +null;this.renderer.refreshDom(this.svgGroup_,this.getTheme(),a?this.getInjectionDiv():void 0)}this.updateBlockStyles(this.getAllBlocks(!1).filter(b=>!!b.getStyleName()));this.refreshToolboxSelection();this.toolbox&&this.toolbox.refreshTheme();this.isVisible()&&this.setVisible(!0);a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.THEME_CHANGE))(this.getTheme().name,this.id);fire$$module$build$src$core$events$utils(a)}updateBlockStyles(a){for(let b=0,c;c=a[b];b++){const d= +c.getStyleName();d&&c.setStyle(d)}}getInverseScreenCTM(){if(this.inverseScreenCTMDirty){const a=this.getParentSvg().getScreenCTM();a&&(this.inverseScreenCTM=a.inverse(),this.inverseScreenCTMDirty=!1)}return this.inverseScreenCTM}updateInverseScreenCTM(){this.inverseScreenCTMDirty=!0}isVisible(){return this.visible}getSvgXY(a){let b=0,c=0,d=1;if(this.getCanvas().contains(a)||this.getBubbleCanvas().contains(a))d=this.scale;do{const e=getRelativeXY$$module$build$src$core$utils$svg_math(a);if(a===this.getCanvas()|| +a===this.getBubbleCanvas())d=1;b+=e.x*d;c+=e.y*d;a=a.parentNode}while(a&&a!==this.getParentSvg()&&a!==this.getInjectionDiv());return new Coordinate$$module$build$src$core$utils$coordinate(b,c)}getCachedParentSvgSize(){const a=this.cachedParentSvgSize;return new Size$$module$build$src$core$utils$size(a.width,a.height)}getOriginOffsetInPixels(){return getInjectionDivXY$$module$build$src$core$utils$svg_math(this.getCanvas())}getInjectionDiv(){if(!this.injectionDiv){let a=this.svgGroup_;for(;a;){if((" "+ +(a.getAttribute("class")||"")+" ").includes(" injectionDiv ")){this.injectionDiv=a;break}a=a.parentNode}}return this.injectionDiv}getSvgGroup(){return this.svgGroup_}getBlockCanvas(){return this.getCanvas()}setResizeHandlerWrapper(a){this.resizeHandlerWrapper=a}createDom(a,b){this.injectionDiv||(this.injectionDiv=b!=null?b:null);this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyWorkspace",id:this.id});b&&setState$$module$build$src$core$utils$aria(this.svgGroup_, +State$$module$build$src$core$utils$aria.LABEL,$.Msg$$module$build$src$core$msg.WORKSPACE_ARIA_LABEL);a&&(this.svgBackground_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{height:"100%",width:"100%","class":a},this.svgGroup_),a==="blocklyMainBackground"&&this.grid?this.svgBackground_.style.fill="var(--blocklyGridPattern)":this.themeManager_.subscribe(this.svgBackground_,"workspaceBackgroundColour","fill"));this.layerManager=new LayerManager$$module$build$src$core$layer_manager(this); +this.svgBlockCanvas_=this.layerManager.getBlockLayer();this.svgBubbleCanvas_=this.layerManager.getBubbleLayer();this.isFlyout||(conditionalBind$$module$build$src$core$browser_events(this.svgGroup_,"pointerdown",this,this.onMouseDown,!1),this.dummyWheelListener=()=>{},document.body.addEventListener("wheel",this.dummyWheelListener,{passive:!0}),conditionalBind$$module$build$src$core$browser_events(this.svgGroup_,"wheel",this,this.onMouseWheel,!1,{passive:!1}));this.options.hasCategories&&(this.toolbox= +new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX,this.options,!0))(this));this.grid&&this.grid.update(this.scale);this.recordDragTargets();(a=getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.CURSOR,this.options))&&this.markerManager.setCursor(new a(this));a=this.options.parentWorkspace===null;this.renderer.createDom(this.svgGroup_,this.getTheme(),a?this.getInjectionDiv():void 0);$.getFocusManager$$module$build$src$core$focus_manager().registerTree(this, +!!this.injectionDiv||this.isFlyout);return this.svgGroup_}dispose(){this.rendered=!1;this.currentGesture_&&this.currentGesture_.cancel();this.svgGroup_&&removeNode$$module$build$src$core$utils$dom(this.svgGroup_);this.toolbox&&(this.toolbox.dispose(),this.toolbox=null);this.flyout&&(this.flyout.dispose(),this.flyout=null);this.trashcan&&(this.trashcan.dispose(),this.trashcan=null);this.scrollbar&&(this.scrollbar.dispose(),this.scrollbar=null);this.zoomControls_&&this.zoomControls_.dispose();this.audioManager&& +this.audioManager.dispose();this.grid&&(this.grid=null);this.renderer.dispose();this.markerManager.dispose();super.dispose();this.themeManager_&&(this.themeManager_.unsubscribeWorkspace(this),this.themeManager_.unsubscribe(this.svgBackground_),this.options.parentWorkspace||this.themeManager_.dispose());this.connectionDBList.length=0;this.toolboxCategoryCallbacks.clear();this.flyoutButtonCallbacks.clear();if(!this.options.parentWorkspace){const a=this.getParentSvg();a&&a.parentNode&&removeNode$$module$build$src$core$utils$dom(a.parentNode)}this.resizeHandlerWrapper&& +(unbind$$module$build$src$core$browser_events(this.resizeHandlerWrapper),this.resizeHandlerWrapper=null);this.dummyWheelListener&&(document.body.removeEventListener("wheel",this.dummyWheelListener),this.dummyWheelListener=null);$.getFocusManager$$module$build$src$core$focus_manager().isRegistered(this)&&$.getFocusManager$$module$build$src$core$focus_manager().unregisterTree(this)}addTrashcan(){this.trashcan=WorkspaceSvg$$module$build$src$core$workspace_svg.newTrashcan(this);const a=this.trashcan.createDom(); +this.svgGroup_.insertBefore(a,this.getCanvas())}static newTrashcan(a){throw Error("The implementation of newTrashcan should be monkey-patched in by blockly.ts");}addZoomControls(){this.zoomControls_=new ZoomControls$$module$build$src$core$zoom_controls(this);const a=this.zoomControls_.createDom();this.svgGroup_.appendChild(a)}copyOptionsForFlyout(){return new Options$$module$build$src$core$options({parentWorkspace:this,rtl:this.RTL,oneBasedIndex:this.options.oneBasedIndex,horizontalLayout:this.horizontalLayout, +renderer:this.options.renderer,rendererOverrides:this.options.rendererOverrides,plugins:this.options.plugins,modalInputs:this.options.modalInputs,move:{scrollbars:!0}})}addFlyout(a){const b=this.copyOptionsForFlyout();b.toolboxPosition=this.options.toolboxPosition;this.flyout=this.horizontalLayout?new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,this.options,!0))(b):new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX, +this.options,!0))(b);this.flyout.autoClose=!1;this.flyout.getWorkspace().setVisible(!0);return this.flyout.createDom(a)}getFlyout(a){return this.flyout||a?this.flyout:this.toolbox?this.toolbox.getFlyout():null}getToolbox(){return this.toolbox}updateScreenCalculations(){this.updateInverseScreenCTM();this.recordDragTargets()}resizeContents(){this.resizesEnabled&&this.rendered&&(this.scrollbar&&this.scrollbar.resize(),this.updateInverseScreenCTM())}resize(){this.toolbox?this.toolbox.position():this.flyout&& this.flyout.position();const a=this.componentManager.getComponents(ComponentManager$$module$build$src$core$component_manager.Capability.POSITIONABLE,!0),b=this.getMetricsManager().getUiMetrics(),c=[];for(let d=0,e;e=a[d];d++){e.position(b,c);const f=e.getBoundingRectangle();f&&c.push(f)}this.scrollbar&&this.scrollbar.resize();this.updateScreenCalculations()}updateScreenCalculationsIfScrolled(){const a=getDocumentScroll$$module$build$src$core$utils$svg_math();Coordinate$$module$build$src$core$utils$coordinate.equals(this.lastRecordedPageScroll, -a)||(this.lastRecordedPageScroll=a,this.updateScreenCalculations())}getLayerManager(){return this.layerManager}getCanvas(){return this.layerManager.getBlockLayer()}setCachedParentSvgSize(a,b){const c=this.getParentSvg();null!=a&&(this.cachedParentSvgSize.width=a,c.setAttribute("data-cached-width",`${a}`));null!=b&&(this.cachedParentSvgSize.height=b,c.setAttribute("data-cached-height",`${b}`))}getBubbleCanvas(){return this.layerManager.getBubbleLayer()}getParentSvg(){if(!this.cachedParentSvg){let a= -this.svgGroup_;for(;a;){if("svg"===a.tagName){this.cachedParentSvg=a;break}a=a.parentNode}}return this.cachedParentSvg}maybeFireViewportChangeEvent(){if(isEnabled$$module$build$src$core$events$utils()){var a=this.scale,b=-this.scrollY,c=-this.scrollX;if(!(a===this.oldScale&&1>Math.abs(b-this.oldTop)&&1>Math.abs(c-this.oldLeft))){var d=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.VIEWPORT_CHANGE))(b,c,a,this.id,this.oldScale);this.oldScale=a;this.oldTop= -b;this.oldLeft=c;fire$$module$build$src$core$events$utils(d)}}}translate(a,b){let c;null==(c=this.layerManager)||c.translateLayers(new Coordinate$$module$build$src$core$utils$coordinate(a,b),this.scale);let d;null==(d=this.grid)||d.moveTo(a,b);this.maybeFireViewportChangeEvent()}getWidth(){const a=this.getMetrics();return a?a.viewWidth/this.scale:0}setVisible(a){this.visible=a;this.svgGroup_&&(this.scrollbar&&this.scrollbar.setContainerVisible(a),this.getFlyout()&&this.getFlyout().setContainerVisible(a), -this.getParentSvg().style.display=a?"block":"none",this.toolbox&&this.toolbox.setVisible(a),a||this.hideChaff(!0))}render(){const a=this.getAllBlocks(!1);for(let b=a.length-1;0<=b;b--)a[b].queueRender();this.getTopBlocks().flatMap(b=>b.getDescendants(!1)).filter(b=>b.isInsertionMarker()).forEach(b=>b.queueRender());finishQueuedRenders$$module$build$src$core$render_management().then(()=>void this.markerManager.updateMarkers())}highlightBlock(a,b){if(void 0===b){for(let c=0,d;d=this.highlightedBlocks[c];c++)d.setHighlighted(!1); -this.highlightedBlocks.length=0}if(a=a?this.getBlockById(a):null)(b=void 0===b||b)?this.highlightedBlocks.includes(a)||this.highlightedBlocks.push(a):removeElem$$module$build$src$core$utils$array(this.highlightedBlocks,a),a.setHighlighted(b)}refreshToolboxSelection(){const a=this.isFlyout?this.targetWorkspace:this;a&&!a.currentGesture_&&a.toolbox&&a.toolbox.getFlyout()&&a.toolbox.refreshSelection()}renameVariableById(a,b){super.renameVariableById(a,b);this.refreshToolboxSelection()}deleteVariableById(a){super.deleteVariableById(a); -this.refreshToolboxSelection()}createVariable(a,b,c){a=super.createVariable(a,b,c);this.refreshToolboxSelection();return a}recordDragTargets(){const a=this.componentManager.getComponents(ComponentManager$$module$build$src$core$component_manager.Capability.DRAG_TARGET,!0);this.dragTargetAreas=[];for(let b=0,c;c=a[b];b++){const d=c.getClientRect();d&&this.dragTargetAreas.push({component:c,clientRect:d})}}newBlock(a,b){throw Error("The implementation of newBlock should be monkey-patched in by blockly.ts"); -}newComment(a){throw Error("The implementation of newComment should be monkey-patched in by blockly.ts");}getDragTarget(a){for(let b=0,c;c=this.dragTargetAreas[b];b++)if(c.clientRect.contains(a.clientX,a.clientY))return c.component;return null}onMouseDown(a){const b=this.getGesture(a);b&&b.handleWsStart(a,this)}startDrag(a,b){start$$module$build$src$core$utils$drag(this,a,b)}moveDrag(a){return move$$module$build$src$core$utils$drag(this,a)}isDragging(){return null!==this.currentGesture_&&this.currentGesture_.isDragging()}isDraggable(){return this.options.moveOptions&& -this.options.moveOptions.drag}isMovable(){return this.options.moveOptions&&!!this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch}isMovableHorizontally(){const a=!!this.scrollbar;return this.isMovable()&&(!a||a&&this.scrollbar.canScrollHorizontally())}isMovableVertically(){const a=!!this.scrollbar; -return this.isMovable()&&(!a||a&&this.scrollbar.canScrollVertically())}onMouseWheel(a){if(Gesture$$module$build$src$core$gesture.inProgress())a.preventDefault(),a.stopPropagation();else{var b=this.options.zoomOptions&&this.options.zoomOptions.wheel,c=this.options.moveOptions&&this.options.moveOptions.wheel;if(b||c){var d=getScrollDeltaPixels$$module$build$src$core$browser_events(a);if(MAC$$module$build$src$core$utils$useragent)var e=a.metaKey;b&&(a.ctrlKey||e||!c)?(d=-d.y/50,b=mouseToSvg$$module$build$src$core$browser_events(a, -this.getParentSvg(),this.getInverseScreenCTM()),this.zoom(b.x,b.y,d)):(b=this.scrollX-d.x,c=this.scrollY-d.y,a.shiftKey&&!d.x&&(b=this.scrollX-d.y,c=this.scrollY),this.scroll(b,c));a.preventDefault()}}}getBlocksBoundingBox(){const a=this.getTopBoundedElements();if(!a.length)return new Rect$$module$build$src$core$utils$rect(0,0,0,0);const b=a[0].getBoundingRectangle();for(let d=1;db.bottom&&(b.bottom=c.bottom),c.leftb.right&&(b.right=c.right))}return b}cleanUp(){this.setResizesEnabled(!1);$.setGroup$$module$build$src$core$events$utils(!0);var a=this.getTopBlocks(!0),b=a.filter(f=>f.isMovable());const c=a.filter(f=>!f.isMovable()).map(f=>f.getBoundingRectangle());a=function(f){for(const g of c)if(f.intersects(g))return g;return null};var d=0;const e=this.renderer.getConstants().MIN_BLOCK_HEIGHT;for(const f of b){b=f.getBoundingRectangle(); -f.moveBy(-b.left,d-b.top,["cleanup"]);f.snapToGrid();b=f.getBoundingRectangle();for(d=a(b);null!=d;)d=d.top+d.getHeight()+e,f.moveBy(0,d-b.top,["cleanup"]),f.snapToGrid(),b=f.getBoundingRectangle(),d=a(b);d=f.getRelativeToSurfaceXY().y+f.getHeightWidth().height+e}$.setGroup$$module$build$src$core$events$utils(!1);this.setResizesEnabled(!0)}showContextMenu(a){if(!this.options.readOnly&&!this.isFlyout){var b=ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.getContextMenuOptions(ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE, -{workspace:this});this.configureContextMenu&&this.configureContextMenu(b,a);show$$module$build$src$core$contextmenu(a,b,this.RTL,this)}}updateToolbox(a){if(a=convertToolboxDefToJson$$module$build$src$core$utils$toolbox(a)){if(!this.options.languageTree)throw Error("Existing toolbox is null. Can't create new toolbox.");if(hasCategories$$module$build$src$core$utils$toolbox(a)){if(!this.toolbox)throw Error("Existing toolbox has no categories. Can't change mode.");this.options.languageTree=a;this.toolbox.render(a)}else{if(!this.flyout)throw Error("Existing toolbox has categories. Can't change mode."); +a)||(this.lastRecordedPageScroll=a,this.updateScreenCalculations())}getLayerManager(){return this.layerManager}getCanvas(){return this.layerManager.getBlockLayer()}setCachedParentSvgSize(a,b){const c=this.getParentSvg();a!=null&&(this.cachedParentSvgSize.width=a,c.setAttribute("data-cached-width",`${a}`));b!=null&&(this.cachedParentSvgSize.height=b,c.setAttribute("data-cached-height",`${b}`))}getBubbleCanvas(){return this.layerManager.getBubbleLayer()}getParentSvg(){if(!this.cachedParentSvg){let a= +this.svgGroup_;for(;a;){if(a.tagName==="svg"){this.cachedParentSvg=a;break}a=a.parentNode}}return this.cachedParentSvg}maybeFireViewportChangeEvent(){if(isEnabled$$module$build$src$core$events$utils()){var a=this.scale,b=-this.scrollY,c=-this.scrollX;if(!(a===this.oldScale&&Math.abs(b-this.oldTop)<1&&Math.abs(c-this.oldLeft)<1)){var d=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.VIEWPORT_CHANGE))(b,c,a,this.id,this.oldScale);this.oldScale=a;this.oldTop= +b;this.oldLeft=c;fire$$module$build$src$core$events$utils(d)}}}translate(a,b){let c;(c=this.layerManager)==null||c.translateLayers(new Coordinate$$module$build$src$core$utils$coordinate(a,b),this.scale);let d;(d=this.grid)==null||d.moveTo(a,b);this.maybeFireViewportChangeEvent()}getWidth(){const a=this.getMetrics();return a?a.viewWidth/this.scale:0}setVisible(a){this.visible=a;this.svgGroup_&&(this.scrollbar&&this.scrollbar.setContainerVisible(a),this.getFlyout()&&this.getFlyout().setContainerVisible(a), +this.getParentSvg().style.display=a?"block":"none",this.toolbox&&this.toolbox.setVisible(a),a||this.hideChaff(!0))}render(){const a=this.getAllBlocks(!1);for(let b=a.length-1;b>=0;b--)a[b].queueRender();this.getTopBlocks().flatMap(b=>b.getDescendants(!1)).filter(b=>b.isInsertionMarker()).forEach(b=>b.queueRender())}highlightBlock(a,b){if(b===void 0){for(let c=0,d;d=this.highlightedBlocks[c];c++)d.setHighlighted(!1);this.highlightedBlocks.length=0}if(a=a?this.getBlockById(a):null)(b=b===void 0||b)? +this.highlightedBlocks.includes(a)||this.highlightedBlocks.push(a):removeElem$$module$build$src$core$utils$array(this.highlightedBlocks,a),a.setHighlighted(b)}variableChangeCallback(a){switch(a.type){case EventType$$module$build$src$core$events$type.VAR_CREATE:case EventType$$module$build$src$core$events$type.VAR_DELETE:case EventType$$module$build$src$core$events$type.VAR_RENAME:case EventType$$module$build$src$core$events$type.VAR_TYPE_CHANGE:this.refreshToolboxSelection()}}refreshToolboxSelection(){const a= +this.isFlyout?this.targetWorkspace:this;a&&!a.currentGesture_&&a.toolbox&&a.toolbox.getFlyout()&&a.toolbox.refreshSelection()}recordDragTargets(){const a=this.componentManager.getComponents(ComponentManager$$module$build$src$core$component_manager.Capability.DRAG_TARGET,!0);this.dragTargetAreas=[];for(let b=0,c;c=a[b];b++){const d=c.getClientRect();d&&this.dragTargetAreas.push({component:c,clientRect:d})}}newBlock(a,b){throw Error("The implementation of newBlock should be monkey-patched in by blockly.ts"); +}newComment(a){throw Error("The implementation of newComment should be monkey-patched in by blockly.ts");}getDragTarget(a){for(let b=0,c;c=this.dragTargetAreas[b];b++)if(c.clientRect.contains(a.clientX,a.clientY))return c.component;return null}onMouseDown(a){const b=this.getGesture(a);b&&b.handleWsStart(a,this)}startDrag(a,b){start$$module$build$src$core$utils$drag(this,a,b)}moveDrag(a){return move$$module$build$src$core$utils$drag(this,a)}setKeyboardMoveInProgress(a){this.keyboardMoveInProgress= +a}isDragging(){return this.keyboardMoveInProgress||this.currentGesture_!==null&&this.currentGesture_.isDragging()}isDraggable(){return this.options.moveOptions&&this.options.moveOptions.drag}isMovable(){return this.options.moveOptions&&!!this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch}isMovableHorizontally(){const a= +!!this.scrollbar;return this.isMovable()&&(!a||a&&this.scrollbar.canScrollHorizontally())}isMovableVertically(){const a=!!this.scrollbar;return this.isMovable()&&(!a||a&&this.scrollbar.canScrollVertically())}onMouseWheel(a){if(Gesture$$module$build$src$core$gesture.inProgress())a.preventDefault(),a.stopPropagation();else{var b=this.options.zoomOptions&&this.options.zoomOptions.wheel,c=this.options.moveOptions&&this.options.moveOptions.wheel;if(b||c){var d=getScrollDeltaPixels$$module$build$src$core$browser_events(a); +if(MAC$$module$build$src$core$utils$useragent)var e=a.metaKey;b&&(a.ctrlKey||e||!c)?(d=-d.y/50,b=mouseToSvg$$module$build$src$core$browser_events(a,this.getParentSvg(),this.getInverseScreenCTM()),this.zoom(b.x,b.y,d)):(b=this.scrollX-d.x,c=this.scrollY-d.y,a.shiftKey&&!d.x&&(b=this.scrollX-d.y,c=this.scrollY),this.scroll(b,c));a.preventDefault()}}}getBlocksBoundingBox(){const a=this.getTopBoundedElements();if(!a.length)return new Rect$$module$build$src$core$utils$rect(0,0,0,0);const b=a[0].getBoundingRectangle(); +for(let d=1;db.bottom&&(b.bottom=c.bottom),c.leftb.right&&(b.right=c.right))}return b}cleanUp(){this.setResizesEnabled(!1);const a=$.getGroup$$module$build$src$core$events$utils();a||$.setGroup$$module$build$src$core$events$utils(!0);var b=this.getTopBlocks(!0),c=b.filter(g=>g.isMovable());const d=b.filter(g=>!g.isMovable()).map(g=> +g.getBoundingRectangle());b=function(g){for(const h of d)if(g.intersects(h))return h;return null};var e=0;const f=this.renderer.getConstants().MIN_BLOCK_HEIGHT;for(const g of c){c=g.getBoundingRectangle();g.moveBy(-c.left,e-c.top,["cleanup"]);g.snapToGrid();c=g.getBoundingRectangle();for(e=b(c);e!=null;)e=e.top+e.getHeight()+f,g.moveBy(0,e-c.top,["cleanup"]),g.snapToGrid(),c=g.getBoundingRectangle(),e=b(c);e=g.getRelativeToSurfaceXY().y+g.getHeightWidth().height+f}$.setGroup$$module$build$src$core$events$utils(a); +this.setResizesEnabled(!0)}showContextMenu(a){if(!this.isReadOnly()&&!this.isFlyout){var b=ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.getContextMenuOptions({workspace:this,focusedNode:this},a);this.configureContextMenu&&this.configureContextMenu(b,a);var c=a instanceof PointerEvent?new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY):wsToScreenCoordinates$$module$build$src$core$utils$svg_math(this,new Coordinate$$module$build$src$core$utils$coordinate(5, +5));show$$module$build$src$core$contextmenu(a,b,this.RTL,this,c)}}updateToolbox(a){if(a=convertToolboxDefToJson$$module$build$src$core$utils$toolbox(a)){if(!this.options.languageTree)throw Error("Existing toolbox is null. Can't create new toolbox.");if(hasCategories$$module$build$src$core$utils$toolbox(a)){if(!this.toolbox)throw Error("Existing toolbox has no categories. Can't change mode.");this.options.languageTree=a;this.toolbox.render(a)}else{if(!this.flyout)throw Error("Existing toolbox has categories. Can't change mode."); this.options.languageTree=a;this.flyout.show(a)}}else if(this.options.languageTree)throw Error("Can't nullify an existing toolbox.");}markFocused(){this.options.parentWorkspace?this.options.parentWorkspace.markFocused():(setMainWorkspace$$module$build$src$core$common(this),this.getParentSvg().focus({preventScroll:!0}))}zoom(a,b,c){c=Math.pow(this.options.zoomOptions.scaleSpeed,c);const d=this.scale*c;if(this.scale!==d){d>this.options.zoomOptions.maxScale?c=this.options.zoomOptions.maxScale/this.scale: dthis.options.zoomOptions.maxScale?a=this.options.zoomOptions.maxScale:this.options.zoomOptions.minScale&&ab.autoHide(a))}static setTopLevelWorkspaceMetrics(a){const b=this.getMetrics();"number"===typeof a.x&&(this.scrollX=-(b.scrollLeft+(b.scrollWidth-b.viewWidth)*a.x));"number"===typeof a.y&&(this.scrollY=-(b.scrollTop+(b.scrollHeight-b.viewHeight)*a.y));this.translate(this.scrollX+b.absoluteLeft,this.scrollY+b.absoluteTop)}},module$build$src$core$workspace_svg={};module$build$src$core$workspace_svg.WorkspaceSvg=WorkspaceSvg$$module$build$src$core$workspace_svg; -module$build$src$core$workspace_svg.resizeSvgContents=resizeSvgContents$$module$build$src$core$workspace_svg;var Selected$$module$build$src$core$events$events_selected=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){super(c);this.type=EventType$$module$build$src$core$events$type.SELECTED;this.oldElementId=null!=a?a:void 0;this.newElementId=null!=b?b:void 0}toJson(){const a=super.toJson();a.oldElementId=this.oldElementId;a.newElementId=this.newElementId;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new Selected$$module$build$src$core$events$events_selected); -b.oldElementId=a.oldElementId;b.newElementId=a.newElementId;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.SELECTED,Selected$$module$build$src$core$events$events_selected);var module$build$src$core$events$events_selected={};module$build$src$core$events$events_selected.Selected=Selected$$module$build$src$core$events$events_selected;var BlockPaster$$module$build$src$core$clipboard$block_paster=class{paste(a,b,c){if(!b.isCapacityAvailable(a.typeCounts))return null;c&&(a.blockState.x=c.x,a.blockState.y=c.y);c=c||new Coordinate$$module$build$src$core$utils$coordinate(a.blockState.x||0,a.blockState.y||0);$.disable$$module$build$src$core$events$utils();let d;try{d=append$$module$build$src$core$serialization$blocks(a.blockState,b),moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster(d,c)}finally{$.enable$$module$build$src$core$events$utils()}if(!d)return d; -isEnabled$$module$build$src$core$events$utils()&&!d.isShadow()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CREATE))(d));$.setSelected$$module$build$src$core$common(d);return d}};BlockPaster$$module$build$src$core$clipboard$block_paster.TYPE="block";register$$module$build$src$core$clipboard$registry(BlockPaster$$module$build$src$core$clipboard$block_paster.TYPE,new BlockPaster$$module$build$src$core$clipboard$block_paster); -var module$build$src$core$clipboard$block_paster={};module$build$src$core$clipboard$block_paster.BlockPaster=BlockPaster$$module$build$src$core$clipboard$block_paster;module$build$src$core$clipboard$block_paster.moveBlockToNotConflict=moveBlockToNotConflict$$module$build$src$core$clipboard$block_paster;var bumpIntoBounds$$module$build$src$core$bump_objects=bumpObjectIntoBounds$$module$build$src$core$bump_objects,module$build$src$core$bump_objects={};module$build$src$core$bump_objects.bumpIntoBounds=bumpObjectIntoBounds$$module$build$src$core$bump_objects;module$build$src$core$bump_objects.bumpIntoBoundsHandler=bumpIntoBoundsHandler$$module$build$src$core$bump_objects;module$build$src$core$bump_objects.bumpTopObjectsIntoBounds=bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects;var BlockDragStrategy$$module$build$src$core$dragging$block_drag_strategy=class{constructor(a){this.block=a;this.connectionPreviewer=this.connectionCandidate=this.startLoc=this.startChildConn=this.startParentConn=null;this.dragging=!1;this.dragOffset=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.inGroup=!1;this.workspace=a.workspace}isMovable(){if(this.block.isShadow()){let a,b;return null!=(b=null==(a=this.block.getParent())?void 0:a.isMovable())?b:!1}return this.block.isOwnMovable()&& -!this.block.isDeadOrDying()&&!this.workspace.options.readOnly&&!this.block.isInFlyout}startDrag(a){if(this.block.isShadow())this.startDraggingShadow(a);else{this.dragging=!0;(this.inGroup=!!$.getGroup$$module$build$src$core$events$utils())||$.setGroup$$module$build$src$core$events$utils(!0);this.fireDragStartEvent();this.startLoc=this.block.getRelativeToSurfaceXY();this.connectionCandidate=null;this.connectionPreviewer=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.CONNECTION_PREVIEWER, -this.workspace.options))(this.block);startTextWidthCache$$module$build$src$core$utils$dom();this.workspace.setResizesEnabled(!1);disconnectUiStop$$module$build$src$core$block_animations();a=!!a&&(a.altKey||a.ctrlKey||a.metaKey);this.shouldDisconnect(a)&&this.disconnectBlock(a);this.block.setDragging(!0);var b;null==(b=this.workspace.getLayerManager())||b.moveToDragLayer(this.block)}}startDraggingShadow(a){const b=this.block.getParent();if(!b)throw Error("Tried to drag a shadow block with no parent. Shadow blocks should always have parents."); -this.dragOffset=Coordinate$$module$build$src$core$utils$coordinate.difference(b.getRelativeToSurfaceXY(),this.block.getRelativeToSurfaceXY());b.startDrag(a)}shouldDisconnect(a){return!!(this.block.getParent()||a&&this.block.nextConnection&&this.block.nextConnection.targetBlock())}disconnectBlock(a){let b,c,d;this.startParentConn=null!=(d=null==(b=this.block.outputConnection)?void 0:b.targetConnection)?d:null==(c=this.block.previousConnection)?void 0:c.targetConnection;if(a){let e;this.startChildConn= -null==(e=this.block.nextConnection)?void 0:e.targetConnection}this.block.unplug(a);disconnectUiEffect$$module$build$src$core$block_animations(this.block)}fireDragStartEvent(){const a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_DRAG))(this.block,!0,this.block.getDescendants(!1));fire$$module$build$src$core$events$utils(a)}fireDragEndEvent(){const a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_DRAG))(this.block, -!1,this.block.getDescendants(!1));fire$$module$build$src$core$events$utils(a)}fireMoveEvent(){if(!this.block.isDeadOrDying()){var a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_MOVE))(this.block);a.setReason(["drag"]);a.oldCoordinate=this.startLoc;a.recordNew();fire$$module$build$src$core$events$utils(a)}}drag(a){if(this.block.isShadow()){let b;null==(b=this.block.getParent())||b.drag(Coordinate$$module$build$src$core$utils$coordinate.sum(a,this.dragOffset))}else this.block.moveDuringDrag(a), -this.updateConnectionPreview(this.block,Coordinate$$module$build$src$core$utils$coordinate.difference(a,this.startLoc))}updateConnectionPreview(a,b){var c=this.connectionCandidate;const d=this.getConnectionCandidate(a,b);if(d){this.connectionCandidate=b=c&&this.currCandidateIsBetter(c,b,d)?c:d;var {local:e,neighbour:f}=b;b=e.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE||e.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT;c=f.isConnected()&& -!f.targetBlock().isInsertionMarker();b&&c&&!this.orphanCanConnectAtEnd(a,f.targetBlock(),e.type)?this.connectionPreviewer.previewReplacement(e,f,f.targetBlock()):this.connectionPreviewer.previewConnection(e,f)}else this.connectionPreviewer.hidePreview(),this.connectionCandidate=null}orphanCanConnectAtEnd(a,b,c){return!!Connection$$module$build$src$core$connection.getConnectionForOrphanedConnection(a,c===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE?b.outputConnection:b.previousConnection)}currCandidateIsBetter(a, -b,c){const {local:d,neighbour:e}=a;a=new Coordinate$$module$build$src$core$utils$coordinate(d.x,d.y);const f=new Coordinate$$module$build$src$core$utils$coordinate(e.x,e.y);b=Coordinate$$module$build$src$core$utils$coordinate.distance(Coordinate$$module$build$src$core$utils$coordinate.sum(a,b),f);return c.distance>b-$.config$$module$build$src$core$config.currentConnectionPreference}getConnectionCandidate(a,b){a=this.getLocalConnections(a);let c=this.connectionCandidate?$.config$$module$build$src$core$config.connectingSnapRadius: -$.config$$module$build$src$core$config.snapRadius,d=null;for(const e of a){const {connection:f,radius:g}=e.closest(c,b);f&&(d={local:e,neighbour:f,distance:g},c=g)}return d}getLocalConnections(a){const b=a.getConnections_(!1),c=a.lastConnectionInStack(!0);c&&c!==a.nextConnection&&b.push(c);return b}endDrag(a){if(this.block.isShadow()){let b;null==(b=this.block.getParent())||b.endDrag(a)}else{this.fireDragEndEvent();this.fireMoveEvent();stopTextWidthCache$$module$build$src$core$utils$dom();disconnectUiStop$$module$build$src$core$block_animations(); -this.connectionPreviewer.hidePreview();if(!this.block.isDeadOrDying()&&this.dragging){let b;null==(b=this.workspace.getLayerManager())||b.moveOffDragLayer(this.block,BLOCK$$module$build$src$core$layers);this.block.setDragging(!1)}this.connectionCandidate?(this.applyConnections(this.connectionCandidate),this.disposeStep()):this.block.queueRender().then(()=>this.disposeStep());this.inGroup||$.setGroup$$module$build$src$core$events$utils(!1)}}disposeStep(){this.block.snapToGrid();this.connectionPreviewer.dispose(); -this.workspace.setResizesEnabled(!0)}applyConnections(a){const {local:b,neighbour:c}=a;b.connect(c);const d=b.isSuperior()?c:b,e=this.block.getRootBlock();finishQueuedRenders$$module$build$src$core$render_management().then(()=>{connectionUiEffect$$module$build$src$core$block_animations(d.getSourceBlock());setTimeout(()=>{e.bringToFront()},0)})}revertDrag(){if(this.block.isShadow()){let b;null==(b=this.block.getParent())||b.revertDrag()}else{var a;null==(a=this.startChildConn)||a.connect(this.block.nextConnection); -if(this.startParentConn)switch(this.startParentConn.type){case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:this.startParentConn.connect(this.block.outputConnection);break;case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:this.startParentConn.connect(this.block.previousConnection)}else{this.block.moveTo(this.startLoc,["drag"]);let b;null==(b=this.workspace.getLayerManager())||b.moveOffDragLayer(this.block,BLOCK$$module$build$src$core$layers);bumpObjectIntoBounds$$module$build$src$core$bump_objects(this.workspace, -this.workspace.getMetricsManager().getScrollMetrics(!0),this.block)}this.startParentConn=this.startChildConn=null;this.connectionPreviewer.hidePreview();this.connectionCandidate=null;this.block.setDragging(!1);this.dragging=!1}}},module$build$src$core$dragging$block_drag_strategy={};module$build$src$core$dragging$block_drag_strategy.BlockDragStrategy=BlockDragStrategy$$module$build$src$core$dragging$block_drag_strategy;var Marker$$module$build$src$core$keyboard_nav$marker=class{constructor(){this.drawer=this.curNode=this.colour=null;this.type="marker"}setDrawer(a){this.drawer=a}getDrawer(){return this.drawer}getCurNode(){return this.curNode}setCurNode(a){const b=this.curNode;this.curNode=a;this.drawer&&this.drawer.draw(b,this.curNode)}draw(){this.drawer&&this.drawer.draw(this.curNode,this.curNode)}hide(){this.drawer&&this.drawer.hide()}dispose(){this.getDrawer()&&this.getDrawer().dispose()}},module$build$src$core$keyboard_nav$marker= -{};module$build$src$core$keyboard_nav$marker.Marker=Marker$$module$build$src$core$keyboard_nav$marker;var Cursor$$module$build$src$core$keyboard_nav$cursor=class extends Marker$$module$build$src$core$keyboard_nav$marker{constructor(){super();this.type="cursor"}next(){var a=this.getCurNode();if(!a)return null;for(a=a.next();a&&a.next()&&(a.getType()===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.NEXT||a.getType()===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.BLOCK);)a=a.next();a&&this.setCurNode(a);return a}in(){var a=this.getCurNode();if(!a)return null;if(a.getType()=== -ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.PREVIOUS||a.getType()===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.OUTPUT)a=a.next();let b,c;(a=null!=(c=null==(b=a)?void 0:b.in())?c:null)&&this.setCurNode(a);return a}prev(){var a=this.getCurNode();if(!a)return null;for(a=a.prev();a&&a.prev()&&(a.getType()===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.NEXT||a.getType()===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.BLOCK);)a=a.prev();a&&this.setCurNode(a); -return a}out(){var a=this.getCurNode();if(!a)return null;(a=a.out())&&a.getType()===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.BLOCK&&(a=a.prev()||a);a&&this.setCurNode(a);return a}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.CURSOR,DEFAULT$$module$build$src$core$registry,Cursor$$module$build$src$core$keyboard_nav$cursor);var module$build$src$core$keyboard_nav$cursor={};module$build$src$core$keyboard_nav$cursor.Cursor=Cursor$$module$build$src$core$keyboard_nav$cursor;var BasicCursor$$module$build$src$core$keyboard_nav$basic_cursor=class extends Cursor$$module$build$src$core$keyboard_nav$cursor{constructor(){super()}next(){var a=this.getCurNode();if(!a)return null;(a=this.getNextNode_(a,this.validNode_))&&this.setCurNode(a);return a}in(){return this.next()}prev(){var a=this.getCurNode();if(!a)return null;(a=this.getPreviousNode_(a,this.validNode_))&&this.setCurNode(a);return a}out(){return this.prev()}getNextNode_(a,b){if(!a)return null;const c=a.in()||a.next(); -if(b(c))return c;if(c)return this.getNextNode_(c,b);a=this.findSiblingOrParent(a.out());return b(a)?a:a?this.getNextNode_(a,b):null}getPreviousNode_(a,b){if(!a)return null;let c=a.prev();c=c?this.getRightMostChild(c):a.out();return b(c)?c:c?this.getPreviousNode_(c,b):null}validNode_(a){let b=!1;a=a&&a.getType();if(a===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.OUTPUT||a===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.INPUT||a===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.FIELD|| -a===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.NEXT||a===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.PREVIOUS||a===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.WORKSPACE)b=!0;return b}findSiblingOrParent(a){if(!a)return null;const b=a.next();return b?b:this.findSiblingOrParent(a.out())}getRightMostChild(a){if(!a.in())return a;for(a=a.in();a&&a.next();)a=a.next();return this.getRightMostChild(a)}}; -BasicCursor$$module$build$src$core$keyboard_nav$basic_cursor.registrationName="basicCursor";register$$module$build$src$core$registry(Type$$module$build$src$core$registry.CURSOR,BasicCursor$$module$build$src$core$keyboard_nav$basic_cursor.registrationName,BasicCursor$$module$build$src$core$keyboard_nav$basic_cursor);var module$build$src$core$keyboard_nav$basic_cursor={};module$build$src$core$keyboard_nav$basic_cursor.BasicCursor=BasicCursor$$module$build$src$core$keyboard_nav$basic_cursor;var TabNavigateCursor$$module$build$src$core$keyboard_nav$tab_navigate_cursor=class extends BasicCursor$$module$build$src$core$keyboard_nav$basic_cursor{validNode_(a){let b=!1;const c=a&&a.getType();a&&(a=a.getLocation(),c===ASTNode$$module$build$src$core$keyboard_nav$ast_node.types.FIELD&&a&&a.isTabNavigable()&&a.isClickable()&&(b=!0));return b}},module$build$src$core$keyboard_nav$tab_navigate_cursor={};module$build$src$core$keyboard_nav$tab_navigate_cursor.TabNavigateCursor=TabNavigateCursor$$module$build$src$core$keyboard_nav$tab_navigate_cursor;var BUMP_RANDOMNESS$$module$build$src$core$rendered_connection=10,RenderedConnection$$module$build$src$core$rendered_connection=class extends Connection$$module$build$src$core$connection{constructor(a,b){super(a,b);this.highlighted=!1;this.targetConnection=null;this.db=a.workspace.connectionDBList[b];this.dbOpposite=a.workspace.connectionDBList[OPPOSITE_TYPE$$module$build$src$core$internal_constants[b]];this.offsetInBlock=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.trackedState= -RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.WILL_TRACK}dispose(){super.dispose();this.trackedState===RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.TRACKED&&this.db.removeConnection(this,this.y);let a,b;null==(b=(a=this.sourceBlock_.pathObject).removeConnectionHighlight)||b.call(a,this)}getSourceBlock(){return super.getSourceBlock()}targetBlock(){return super.targetBlock()}distanceFrom(a){const b=this.x-a.x;a=this.y-a.y;return Math.sqrt(b* -b+a*a)}bumpAwayFrom(a,b=!1){if(!this.sourceBlock_.workspace.isDragging()){var c=$.config$$module$build$src$core$config.snapRadius+Math.floor(Math.random()*BUMP_RANDOMNESS$$module$build$src$core$rendered_connection),d=$.config$$module$build$src$core$config.snapRadius+Math.floor(Math.random()*BUMP_RANDOMNESS$$module$build$src$core$rendered_connection),e=a.sourceBlock_.getRootBlock(),f=this.sourceBlock_.getRootBlock();if(!e.isInFlyout&&!f.isInFlyout){var g=!0;if(f.isMovable())e.isMovable()&&b&&(d=-d); -else if(e.isMovable())g=!1,c=-c,d=-d;else return;b=g?a:this;a=g?this:a;e=g?f:e;(f=getSelected$$module$build$src$core$common()===e)||e.addSelect();e.RTL&&(c=-c);e.moveBy(b.x+c-a.x,b.y+d-a.y,["bump"]);f||e.removeSelect()}}}moveTo(a,b){let c=!1;this.trackedState===RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.WILL_TRACK?(this.db.addConnection(this,b),this.trackedState=RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.TRACKED,c=!0):this.trackedState=== -RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.TRACKED&&(this.db.removeConnection(this,this.y),this.db.addConnection(this,b),c=!0);this.x=a;this.y=b;return c}moveBy(a,b){return this.moveTo(this.x+a,this.y+b)}moveToOffset(a){return this.moveTo(a.x+this.offsetInBlock.x,a.y+this.offsetInBlock.y)}setOffsetInBlock(a,b){this.offsetInBlock.x=a;this.offsetInBlock.y=b}getOffsetInBlock(){return this.offsetInBlock}tightenEfficiently(){var a=this.targetConnection;const b=this.targetBlock(); -a&&b&&(a=Coordinate$$module$build$src$core$utils$coordinate.difference(this.offsetInBlock,a.offsetInBlock),b.translate(a.x,a.y))}closest(a,b){return this.dbOpposite.searchForClosest(this,a,b)}highlight(){this.highlighted=!0;this.getSourceBlock().queueRender()}unhighlight(){this.highlighted=!1;this.getSourceBlock().queueRender()}isHighlighted(){return this.highlighted}setTracking(a){a&&this.trackedState===RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.TRACKED||!a&&this.trackedState=== -RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.UNTRACKED||this.sourceBlock_.isInFlyout||(a?(this.db.addConnection(this,this.y),this.trackedState=RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.TRACKED):(this.trackedState===RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.TRACKED&&this.db.removeConnection(this,this.y),this.trackedState=RenderedConnection$$module$build$src$core$rendered_connection.TrackedState.UNTRACKED))}stopTrackingAll(){this.setTracking(!1); -if(this.targetConnection){const a=this.targetBlock().getDescendants(!1);for(let b=0;bclearTimeout(a));this.warningTextDb.clear();this.getIcons().forEach(a=>a.dispose())}checkAndDelete(){this.workspace.isFlyout||($.setGroup$$module$build$src$core$events$utils(!0),this.workspace.hideChaff(),this.outputConnection?this.dispose(!1,!0):this.dispose(!0,!0),$.setGroup$$module$build$src$core$events$utils(!1))}toCopyData(){return this.isInsertionMarker_? -null:{paster:BlockPaster$$module$build$src$core$clipboard$block_paster.TYPE,blockState:save$$module$build$src$core$serialization$blocks(this,{addCoordinates:!0,addNextBlocks:!1}),typeCounts:getBlockTypeCounts$$module$build$src$core$common(this,!0)}}applyColour(){this.pathObject.applyColour(this);const a=this.getIcons();for(let b=0;b{this.isDeadOrDying()||(this.warningTextDb.delete(b), -this.setWarningText(a,b))},100));else if(this.isInFlyout&&(a=null),c=this.getIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE),a){let d=this.getSurroundParent(),e=null;for(;d;)d.isCollapsed()&&(e=d),d=d.getSurroundParent();e&&e.setWarningText($.Msg$$module$build$src$core$msg.COLLAPSED_WARNINGS_WARNING,BlockSvg$$module$build$src$core$block_svg.COLLAPSED_WARNING_ID);c?c.addMessage(a,b):this.addIcon((new WarningIcon$$module$build$src$core$icons$warning_icon(this)).addMessage(a,b))}else c&& -(b?(c.addMessage("",b),c.getText()||this.removeIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE)):this.removeIcon(WarningIcon$$module$build$src$core$icons$warning_icon.TYPE))}setMutator(a){this.removeIcon($.MutatorIcon$$module$build$src$core$icons$mutator_icon.TYPE);a&&this.addIcon(a)}addIcon(a){super.addIcon(a);a instanceof $.MutatorIcon$$module$build$src$core$icons$mutator_icon&&(this.mutator=a);a.initView(this.createIconPointerDownListener(a));a.applyColour();a.updateEditable(); -this.queueRender();return a}createIconPointerDownListener(a){return b=>{this.isDeadOrDying()||(b=this.workspace.getGesture(b))&&b.setStartIcon(a)}}removeIcon(a){const b=super.removeIcon(a);a.equals($.MutatorIcon$$module$build$src$core$icons$mutator_icon.TYPE)&&(this.mutator=null);this.queueRender();return b}setEnabled(a){warn$$module$build$src$core$utils$deprecation("setEnabled","v11","v12","the setDisabledReason method of BlockSvg");const b=this.isEnabled();super.setEnabled(a);this.isEnabled()=== -b||this.getInheritedDisabled()||this.updateDisabled()}setDisabledReason(a,b){const c=this.isEnabled();super.setDisabledReason(a,b);this.isEnabled()===c||this.getInheritedDisabled()||this.updateDisabled()}setHighlighted(a){this.pathObject.updateHighlighted(a)}addSelect(){this.pathObject.updateSelected(!0)}removeSelect(){this.pathObject.updateSelected(!1)}setDeleteStyle(a){this.pathObject.updateDraggingDelete(a)}getColour(){return this.style.colourPrimary}setColour(a){super.setColour(a);a=this.workspace.getRenderer().getConstants().getBlockStyleForColour(this.colour_); -this.pathObject.setStyle(a.style);this.style=a.style;this.styleName_=a.name;this.applyColour()}setStyle(a){const b=this.workspace.getRenderer().getConstants().getBlockStyle(a);this.styleName_=a;if(b)this.hat=b.hat,this.pathObject.setStyle(b),this.colour_=b.colourPrimary,this.style=b,this.applyColour();else throw Error("Invalid style name: "+a);}getStyle(){return this.style}bringToFront(a=!1){let b=this;if(!b.isDeadOrDying()){do{const c=b.getSvgRoot(),d=c.parentNode,e=d.childNodes;e[e.length-1]!== -c&&d.appendChild(c);if(a)break;b=b.getParent()}while(b)}}setPreviousStatement(a,b){super.setPreviousStatement(a,b);this.queueRender()}setNextStatement(a,b){super.setNextStatement(a,b);this.queueRender()}setOutput(a,b){super.setOutput(a,b);this.queueRender()}setInputsInline(a){super.setInputsInline(a);this.queueRender()}removeInput(a,b){a=super.removeInput(a,b);this.queueRender();return a}moveNumberedInputBefore(a,b){super.moveNumberedInputBefore(a,b);this.queueRender()}appendInput(a){super.appendInput(a); -this.queueRender();return a}setConnectionTracking(a){this.previousConnection&&this.previousConnection.setTracking(a);this.outputConnection&&this.outputConnection.setTracking(a);if(this.nextConnection){this.nextConnection.setTracking(a);var b=this.nextConnection.targetBlock();b&&b.setConnectionTracking(a)}if(!this.collapsed_)for(b=0;b=this.workspace.options.maxTrashcanContents||(a=new Options$$module$build$src$core$options({scrollbars:!0,parentWorkspace:this.workspace,rtl:this.workspace.RTL,oneBasedIndex:this.workspace.options.oneBasedIndex, -renderer:this.workspace.options.renderer,rendererOverrides:this.workspace.options.rendererOverrides,move:{scrollbars:!0}}),this.workspace.horizontalLayout?(a.toolboxPosition=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.TOP?Position$$module$build$src$core$utils$toolbox.BOTTOM:Position$$module$build$src$core$utils$toolbox.TOP,this.flyout=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,this.workspace.options, -!0))(a)):(a.toolboxPosition=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.RIGHT?Position$$module$build$src$core$utils$toolbox.LEFT:Position$$module$build$src$core$utils$toolbox.RIGHT,this.flyout=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,this.workspace.options,!0))(a)),this.workspace.addChangeListener(this.onDelete.bind(this)))}createDom(){this.svgGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G, -{"class":"blocklyTrash"});let a;const b=String(Math.random()).substring(2);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH,{id:"blocklyTrashBodyClipPath"+b},this.svgGroup);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:WIDTH$$module$build$src$core$trashcan,height:BODY_HEIGHT$$module$build$src$core$trashcan,y:LID_HEIGHT$$module$build$src$core$trashcan},a);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE, -{width:SPRITE$$module$build$src$core$sprites.width,x:-SPRITE_LEFT$$module$build$src$core$trashcan,height:SPRITE$$module$build$src$core$sprites.height,y:-SPRITE_TOP$$module$build$src$core$trashcan,"clip-path":"url(#blocklyTrashBodyClipPath"+b+")"},this.svgGroup);c.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH, -{id:"blocklyTrashLidClipPath"+b},this.svgGroup);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:WIDTH$$module$build$src$core$trashcan,height:LID_HEIGHT$$module$build$src$core$trashcan},a);this.svgLid=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{width:SPRITE$$module$build$src$core$sprites.width,x:-SPRITE_LEFT$$module$build$src$core$trashcan,height:SPRITE$$module$build$src$core$sprites.height,y:-SPRITE_TOP$$module$build$src$core$trashcan, -"clip-path":"url(#blocklyTrashLidClipPath"+b+")"},this.svgGroup);this.svgLid.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);bind$$module$build$src$core$browser_events(this.svgGroup,"pointerdown",this,this.blockMouseDownWhenOpenable);bind$$module$build$src$core$browser_events(this.svgGroup,"pointerup",this,this.click);bind$$module$build$src$core$browser_events(c,"pointerover",this,this.mouseOver);bind$$module$build$src$core$browser_events(c, -"pointerout",this,this.mouseOut);this.animateLid();return this.svgGroup}init(){0{if(c.isFlyout){let d;const e=(d=c.targetWorkspace)==null?void 0:d.getFlyout();if(e instanceof Flyout$$module$build$src$core$flyout_base)return e.getFlyoutScale()}return c.getScale()},b=(c,d)=>c.options.parentWorkspace&&c.options.parentWorkspace.getSvgGroup().contains(c.getSvgGroup())?b(c.options.parentWorkspace,d*a(c)):d*a(c);return b(this,1)}scroll(a,b){this.hideChaff(!0); +const c=this.getMetrics();a=Math.min(a,-c.scrollLeft);b=Math.min(b,-c.scrollTop);const d=c.scrollTop+Math.max(0,c.scrollHeight-c.viewHeight);a=Math.max(a,-(c.scrollLeft+Math.max(0,c.scrollWidth-c.viewWidth)));b=Math.max(b,-d);this.scrollX=a;this.scrollY=b;this.scrollbar&&this.scrollbar.set(-(a+c.scrollLeft),-(b+c.scrollTop),!1);a+=c.absoluteLeft;b+=c.absoluteTop;this.translate(a,b)}getBlockById(a){return super.getBlockById(a)}getAllBlocks(a=!1){return super.getAllBlocks(a)}getTopBlocks(a=!1){return super.getTopBlocks(a)}addTopBlock(a){this.addTopBoundedElement(a); +super.addTopBlock(a)}removeTopBlock(a){this.removeTopBoundedElement(a);super.removeTopBlock(a)}addTopComment(a){this.addTopBoundedElement(a);super.addTopComment(a)}removeTopComment(a){this.removeTopBoundedElement(a);super.removeTopComment(a)}getTopComments(a=!1){return super.getTopComments(a)}getCommentById(a){return super.getCommentById(a)}getRootWorkspace(){return super.getRootWorkspace()}addTopBoundedElement(a){this.topBoundedElements.push(a)}removeTopBoundedElement(a){removeElem$$module$build$src$core$utils$array(this.topBoundedElements, +a)}getTopBoundedElements(a=!1){const b=[].concat(this.topBoundedElements);a&&b.sort(this.sortByOrigin.bind(this));return b}setResizesEnabled(a){const b=!this.resizesEnabled&&a;this.resizesEnabled=a;b&&this.resizeContents()}clear(){this.setResizesEnabled(!1);super.clear();this.topBoundedElements=[];this.setResizesEnabled(!0)}registerButtonCallback(a,b){if(typeof b!=="function")throw TypeError("Button callbacks must be functions.");this.flyoutButtonCallbacks.set(a,b)}getButtonCallback(a){let b;return(b= +this.flyoutButtonCallbacks.get(a))!=null?b:null}removeButtonCallback(a){this.flyoutButtonCallbacks.delete(a)}registerToolboxCategoryCallback(a,b){if(typeof b!=="function")throw TypeError("Toolbox category callbacks must be functions.");this.toolboxCategoryCallbacks.set(a,b)}getToolboxCategoryCallback(a){return this.toolboxCategoryCallbacks.get(a)||null}removeToolboxCategoryCallback(a){this.toolboxCategoryCallbacks.delete(a)}getGesture(a){if(this.keyboardMoveInProgress)return a==null||a.preventDefault(), +a==null||a.stopPropagation(),null;const b=(a==null?void 0:a.type)==="pointerdown";let c;b&&((c=this.currentGesture_)==null?0:c.hasStarted())&&(console.warn("Tried to start the same gesture twice."),this.currentGesture_.cancel());!this.currentGesture_&&b&&(this.currentGesture_=new Gesture$$module$build$src$core$gesture(a,this));return this.currentGesture_}clearGesture(){this.currentGesture_=null}cancelCurrentGesture(){this.currentGesture_&&this.currentGesture_.cancel()}getAudioManager(){return this.audioManager}getGrid(){return this.grid}hideChaff(a= +!1){hide$$module$build$src$core$tooltip();hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv(this);hideWithoutAnimation$$module$build$src$core$dropdowndiv();this.hideComponents(a)}hideComponents(a=!1){this.getComponentManager().getComponents(ComponentManager$$module$build$src$core$component_manager.Capability.AUTOHIDEABLE,!0).forEach(b=>b.autoHide(a))}static setTopLevelWorkspaceMetrics(a){const b=this.getMetrics();typeof a.x==="number"&&(this.scrollX=-(b.scrollLeft+(b.scrollWidth-b.viewWidth)* +a.x));typeof a.y==="number"&&(this.scrollY=-(b.scrollTop+(b.scrollHeight-b.viewHeight)*a.y));this.translate(this.scrollX+b.absoluteLeft,this.scrollY+b.absoluteTop)}addClass(a){this.injectionDiv&&addClass$$module$build$src$core$utils$dom(this.injectionDiv,a)}removeClass(a){this.injectionDiv&&removeClass$$module$build$src$core$utils$dom(this.injectionDiv,a)}setIsReadOnly(a){super.setIsReadOnly(a);a?this.addClass("blocklyReadOnly"):this.removeClass("blocklyReadOnly")}scrollBoundsIntoView(a,b=10){if(!Gesture$$module$build$src$core$gesture.inProgress()){var c= +this.getScale(),d=this.getMetricsManager().getViewMetrics(!0);d=new Rect$$module$build$src$core$utils$rect(d.top,d.top+d.height,d.left,d.left+d.width);if(!(a.left>=d.left&&a.top>=d.top&&a.right<=d.right&&a.bottom<=d.bottom)){a=a.clone();a.top-=b;a.bottom+=b;a.left-=b;a.right+=b;var e=b=0;a.leftd.right&&(b=this.RTL?d.right-a.right:Math.max(d.right-a.right,d.left-a.left));a.topd.bottom&&(e= +Math.max(d.bottom-a.bottom,d.top-a.top));this.scroll(this.scrollX+b*c,this.scrollY+e*c)}}}getFocusableElement(){return this.svgGroup_}getFocusableTree(){return this.isMutator&&this.options.parentWorkspace||this}onNodeFocus(){}onNodeBlur(){}canBeFocused(){return!0}getRootFocusableNode(){return this}getRestoredFocusableNode(a){if(a)return null;let b;a=(b=this.targetWorkspace)==null?void 0:b.getFlyout();if(this.isFlyout&&a){let d,e;return(e=(d=a.getContents().find(f=>{f=f.getElement();return isFocusableNode$$module$build$src$core$interfaces$i_focusable_node(f)&& +f.canBeFocused()}))==null?void 0:d.getElement())!=null?e:null}let c;return(c=this.getTopBlocks(!0)[0])!=null?c:null}getNestedTrees(){const a=this.getAllBlocks().map(c=>c.getIcons()).flat().filter(c=>c instanceof $.MutatorIcon$$module$build$src$core$icons$mutator_icon&&c.bubbleIsVisible()).map(c=>{let d;return(d=c.getBubble())==null?void 0:d.getWorkspace()}).filter(c=>!!c),b=this.getFlyout(!0);b&&a.push(b.getWorkspace());return a}searchForWorkspaceComment(a){for(const b of this.getTopComments())if(b instanceof +RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment&&b.canBeFocused()&&b.getFocusableElement().id===a)return b}lookUpFocusableNode(a){var b;const c=(b=this.targetWorkspace)==null?void 0:b.getFlyout();if(this.isFlyout&&c)for(var d of c.getContents())if(b=d.getElement(),isFocusableNode$$module$build$src$core$interfaces$i_focusable_node(b)&&b.canBeFocused()&&b.getFocusableElement().id===a)return b;d=a.indexOf("_field_");b=a.indexOf("_connection_");if(d!==-1){var e=a.substring(0, +d);if(e=this.getBlockById(e))for(var f of e.getFields())if(f.canBeFocused()&&f.getFocusableElement().id===a)return f;return null}if(b!==-1){e=a.substring(0,b);if(e=this.getBlockById(e))for(const h of e.getConnections_(!0))if(h.id===a)return h;return null}f=Math.max(a.indexOf(COMMENT_EDITOR_FOCUS_IDENTIFIER$$module$build$src$core$comments$comment_editor),a.indexOf(COMMENT_COLLAPSE_BAR_BUTTON_FOCUS_IDENTIFIER$$module$build$src$core$comments$collapse_comment_bar_button),a.indexOf(COMMENT_DELETE_BAR_BUTTON_FOCUS_IDENTIFIER$$module$build$src$core$comments$delete_comment_bar_button)); +if(f!==-1&&(f=a.substring(0,f),f=this.searchForWorkspaceComment(f))){if(a.indexOf(COMMENT_EDITOR_FOCUS_IDENTIFIER$$module$build$src$core$comments$comment_editor)>-1)return f.getEditorFocusableNode();var g;return(g=f.view.getCommentBarButtons().find(h=>h.getFocusableElement().id.includes(a)))!=null?g:null}if((g=this.getAllBlocks(!1).find(h=>h.getFocusableElement().id===a))||(g=this.searchForWorkspaceComment(a)))return g;g=this.getAllBlocks().map(h=>h.getIcons()).flat();for(e of g){if(e.canBeFocused()&& +e.getFocusableElement().id===a)return e;if(hasBubble$$module$build$src$core$interfaces$i_has_bubble(e)){if((g=e.getBubble())&&g.canBeFocused()&&g.getFocusableElement().id===a)return g;if(g instanceof TextInputBubble$$module$build$src$core$bubbles$textinput_bubble&&g.getEditor().getFocusableElement().id===a)return g.getEditor()}}return null}onTreeFocus(a,b){}onTreeBlur(a){if(this.isFlyout&&this.targetWorkspace&&!$.getFocusManager$$module$build$src$core$focus_manager().ephemeralFocusTaken()){var b= +this.targetWorkspace.getToolbox();b&&a===b||isAutoHideable$$module$build$src$core$interfaces$i_autohideable(b)&&b.autoHide(!1)}}getNavigator(){return this.navigator}setNavigator(a){this.navigator=a}},module$build$src$core$workspace_svg={};module$build$src$core$workspace_svg.WorkspaceSvg=WorkspaceSvg$$module$build$src$core$workspace_svg;module$build$src$core$workspace_svg.resizeSvgContents=resizeSvgContents$$module$build$src$core$workspace_svg;var VarBase$$module$build$src$core$events$events_var_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!0;this.isBlank=typeof a==="undefined";a&&(this.varId=a.getId(),this.workspaceId=a.getWorkspace().id)}toJson(){const a=super.toJson();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");a.varId=this.varId;return a}static fromJson(a,b,c){b=Abstract$$module$build$src$core$events$events_abstract.fromJson(a, +b,c!=null?c:new VarBase$$module$build$src$core$events$events_var_base);b.varId=a.varId;return b}},module$build$src$core$events$events_var_base={};module$build$src$core$events$events_var_base.VarBase=VarBase$$module$build$src$core$events$events_var_base;var VarCreate$$module$build$src$core$events$events_var_create=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a){super(a);this.type=EventType$$module$build$src$core$events$type.VAR_CREATE;a&&(this.varType=a.getType(),this.varName=a.getName())}toJson(){const a=super.toJson();if(this.varType===void 0)throw Error("The var type is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); +a.varType=this.varType;a.varName=this.varName;return a}static fromJson(a,b,c){b=VarBase$$module$build$src$core$events$events_var_base.fromJson(a,b,c!=null?c:new VarCreate$$module$build$src$core$events$events_var_create);b.varType=a.varType;b.varName=a.varName;return b}run(a){var b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); +b=b.getVariableMap();a?b.createVariable(this.varName,this.varType,this.varId):(a=b.getVariableById(this.varId))&&b.deleteVariable(a)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VAR_CREATE,VarCreate$$module$build$src$core$events$events_var_create);var module$build$src$core$events$events_var_create={};module$build$src$core$events$events_var_create.VarCreate=VarCreate$$module$build$src$core$events$events_var_create;var VariableModel$$module$build$src$core$variable_model=class{constructor(a,b,c,d){this.workspace=a;this.name=b;this.type=c||"";this.id=d||genUid$$module$build$src$core$utils$idgenerator()}getId(){return this.id}getName(){return this.name}setName(a){this.name=a;return this}getType(){return this.type}setType(a){this.type=a;return this}getWorkspace(){return this.workspace}save(){const a={name:this.getName(),id:this.getId()},b=this.getType();b&&(a.type=b);return a}static load(a,b){a=new this(b,a.name, +a.type,a.id);b.getVariableMap().addVariable(a);fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.VAR_CREATE))(a))}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.VARIABLE_MODEL,DEFAULT$$module$build$src$core$registry,VariableModel$$module$build$src$core$variable_model);var module$build$src$core$variable_model={};module$build$src$core$variable_model.VariableModel=VariableModel$$module$build$src$core$variable_model;var VarDelete$$module$build$src$core$events$events_var_delete=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a){super(a);this.type=EventType$$module$build$src$core$events$type.VAR_DELETE;a&&(this.varType=a.getType(),this.varName=a.getName())}toJson(){const a=super.toJson();if(this.varType===void 0)throw Error("The var type is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); +a.varType=this.varType;a.varName=this.varName;return a}static fromJson(a,b,c){b=VarBase$$module$build$src$core$events$events_var_base.fromJson(a,b,c!=null?c:new VarDelete$$module$build$src$core$events$events_var_delete);b.varType=a.varType;b.varName=a.varName;return b}run(a){var b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); +b=b.getVariableMap();a?(a=b.getVariableById(this.varId))&&b.deleteVariable(a):b.createVariable(this.varName,this.varType,this.varId)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VAR_DELETE,VarDelete$$module$build$src$core$events$events_var_delete);var module$build$src$core$events$events_var_delete={};module$build$src$core$events$events_var_delete.VarDelete=VarDelete$$module$build$src$core$events$events_var_delete;var VarRename$$module$build$src$core$events$events_var_rename=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a,b){super(a);this.type=EventType$$module$build$src$core$events$type.VAR_RENAME;a&&(this.oldName=a.getName(),this.newName=typeof b==="undefined"?"":b)}toJson(){const a=super.toJson();if(!this.oldName)throw Error("The old var name is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.newName)throw Error("The new var name is undefined. Either pass a value to the constructor, or call fromJson"); +a.oldName=this.oldName;a.newName=this.newName;return a}static fromJson(a,b,c){b=VarBase$$module$build$src$core$events$events_var_base.fromJson(a,b,c!=null?c:new VarRename$$module$build$src$core$events$events_var_rename);b.oldName=a.oldName;b.newName=a.newName;return b}run(a){var b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.oldName)throw Error("The old var name is undefined. Either pass a variable to the constructor, or call fromJson"); +if(!this.newName)throw Error("The new var name is undefined. Either pass a value to the constructor, or call fromJson");b=b.getVariableMap();const c=b.getVariableById(this.varId);a?c&&b.renameVariable(c,this.newName):c&&b.renameVariable(c,this.oldName)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.VAR_RENAME,VarRename$$module$build$src$core$events$events_var_rename); +var module$build$src$core$events$events_var_rename={};module$build$src$core$events$events_var_rename.VarRename=VarRename$$module$build$src$core$events$events_var_rename;var VariableMap$$module$build$src$core$variable_map=class{constructor(a,b=!1){this.workspace=a;this.potentialMap=b;this.variableMap=new Map}clear(){for(const a of this.variableMap.values())for(const b of a.values())this.deleteVariable(b);if(this.variableMap.size!==0)throw Error("Non-empty variable map");}renameVariable(a,b){if(a.getName()===b)return a;var c=a.getType();c=this.getVariable(b,c);const d=this.workspace.getAllBlocks(!1);let e="";this.potentialMap||(e=$.getGroup$$module$build$src$core$events$utils())|| +$.setGroup$$module$build$src$core$events$utils(!0);try{c&&c.getId()!==a.getId()?this.renameVariableWithConflict(a,b,c,d):this.renameVariableAndUses(a,b,d)}finally{this.potentialMap||$.setGroup$$module$build$src$core$events$utils(e)}return a}changeVariableType(a,b){const c=a.getType();if(c===b)return a;var d=this.variableMap.get(c);d==null||d.delete(a.getId());(d==null?void 0:d.size)===0&&this.variableMap.delete(c);a.setType(b);let e;d=(e=this.variableMap.get(b))!=null?e:new Map;d.set(a.getId(),a); +this.variableMap.has(b)||this.variableMap.set(b,d);fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.VAR_TYPE_CHANGE))(a,c,b));return a}renameVariableById(a,b){warn$$module$build$src$core$utils$deprecation("VariableMap.renameVariableById","v12","v13","VariableMap.renameVariable");const c=this.getVariableById(a);if(!c)throw Error("Tried to rename a variable that didn't exist. ID: "+a);this.renameVariable(c,b)}renameVariableAndUses(a, +b,c){this.potentialMap||fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.VAR_RENAME))(a,b));a.setName(b);for(b=0;b$.Names$$module$build$src$core$names.equals(d.getName(), +a)))!=null?c:null}getVariableById(a){for(const b of this.variableMap.values())if(b.has(a)){let c;return(c=b.get(a))!=null?c:null}return null}getVariablesOfType(a){return(a=this.variableMap.get(a||""))?[...a.values()]:[]}getTypes(){return[...this.variableMap.keys()]}getAllVariables(){let a=[];for(const b of this.variableMap.values())a=a.concat(...b.values());return a}getAllVariableNames(){warn$$module$build$src$core$utils$deprecation("VariableMap.getAllVariableNames","v12","v13","Blockly.Variables.getAllVariables"); +const a=[];for(const b of this.variableMap.values())for(const c of b.values())a.push(c.getName());return a}getVariableUsesById(a){warn$$module$build$src$core$utils$deprecation("VariableMap.getVariableUsesById","v12","v13","Blockly.Variables.getVariableUsesById");return getVariableUsesById$$module$build$src$core$variables(this.workspace,a)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.VARIABLE_MAP,DEFAULT$$module$build$src$core$registry,VariableMap$$module$build$src$core$variable_map); +var module$build$src$core$variable_map={};module$build$src$core$variable_map.VariableMap=VariableMap$$module$build$src$core$variable_map;var TrashcanOpen$$module$build$src$core$events$events_trashcan_open=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b){super(b);this.type=EventType$$module$build$src$core$events$type.TRASHCAN_OPEN;this.isOpen=a}toJson(){const a=super.toJson();if(this.isOpen===void 0)throw Error("Whether this is already open or not is undefined. Either pass a value to the constructor, or call fromJson");a.isOpen=this.isOpen;return a}static fromJson(a,b,c){b=UiBase$$module$build$src$core$events$events_ui_base.fromJson(a, +b,c!=null?c:new TrashcanOpen$$module$build$src$core$events$events_trashcan_open);b.isOpen=a.isOpen;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.TRASHCAN_OPEN,TrashcanOpen$$module$build$src$core$events$events_trashcan_open);var module$build$src$core$events$events_trashcan_open={};module$build$src$core$events$events_trashcan_open.TrashcanOpen=TrashcanOpen$$module$build$src$core$events$events_trashcan_open;var Trashcan$$module$build$src$core$trashcan=class extends DeleteArea$$module$build$src$core$delete_area{constructor(a){super();this.workspace=a;this.id="trashcan";this.contents=[];this.flyout=null;this.isLidOpen=!1;this.minOpenness=0;this.lidTask=this.svgLid=this.svgGroup=null;this.top=this.left=this.lidOpen=0;this.initialized=!1;this.workspace.options.maxTrashcanContents<=0||(a=this.workspace.copyOptionsForFlyout(),this.workspace.horizontalLayout?(a.toolboxPosition=this.workspace.toolboxPosition=== +Position$$module$build$src$core$utils$toolbox.TOP?Position$$module$build$src$core$utils$toolbox.BOTTOM:Position$$module$build$src$core$utils$toolbox.TOP,this.flyout=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,this.workspace.options,!0))(a)):(a.toolboxPosition=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.RIGHT?Position$$module$build$src$core$utils$toolbox.LEFT:Position$$module$build$src$core$utils$toolbox.RIGHT, +this.flyout=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,this.workspace.options,!0))(a)),this.workspace.addChangeListener(this.onDelete.bind(this)))}createDom(){this.svgGroup=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyTrash"});let a;const b=String(Math.random()).substring(2);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH, +{id:"blocklyTrashBodyClipPath"+b},this.svgGroup);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:WIDTH$$module$build$src$core$trashcan,height:BODY_HEIGHT$$module$build$src$core$trashcan,y:LID_HEIGHT$$module$build$src$core$trashcan},a);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{width:SPRITE$$module$build$src$core$sprites.width,x:-SPRITE_LEFT$$module$build$src$core$trashcan,height:SPRITE$$module$build$src$core$sprites.height, +y:-SPRITE_TOP$$module$build$src$core$trashcan,"clip-path":"url(#blocklyTrashBodyClipPath"+b+")"},this.svgGroup);c.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH,{id:"blocklyTrashLidClipPath"+b},this.svgGroup);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:WIDTH$$module$build$src$core$trashcan, +height:LID_HEIGHT$$module$build$src$core$trashcan},a);this.svgLid=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{width:SPRITE$$module$build$src$core$sprites.width,x:-SPRITE_LEFT$$module$build$src$core$trashcan,height:SPRITE$$module$build$src$core$sprites.height,y:-SPRITE_TOP$$module$build$src$core$trashcan,"clip-path":"url(#blocklyTrashLidClipPath"+b+")"},this.svgGroup);this.svgLid.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href", +this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);bind$$module$build$src$core$browser_events(this.svgGroup,"pointerdown",this,this.blockMouseDownWhenOpenable);bind$$module$build$src$core$browser_events(this.svgGroup,"pointerup",this,this.click);bind$$module$build$src$core$browser_events(c,"pointerover",this,this.mouseOver);bind$$module$build$src$core$browser_events(c,"pointerout",this,this.mouseOut);this.animateLid();return this.svgGroup}init(){if(this.workspace.options.maxTrashcanContents> +0){const a=this.flyout.createDom(Svg$$module$build$src$core$utils$svg.SVG);addClass$$module$build$src$core$utils$dom(a,"blocklyTrashcanFlyout");insertAfter$$module$build$src$core$utils$dom(a,this.workspace.getParentSvg());this.flyout.init(this.workspace)}this.workspace.getComponentManager().addComponent({component:this,weight:ComponentManager$$module$build$src$core$component_manager.ComponentWeight.TRASHCAN_WEIGHT,capabilities:[ComponentManager$$module$build$src$core$component_manager.Capability.AUTOHIDEABLE, ComponentManager$$module$build$src$core$component_manager.Capability.DELETE_AREA,ComponentManager$$module$build$src$core$component_manager.Capability.DRAG_TARGET,ComponentManager$$module$build$src$core$component_manager.Capability.POSITIONABLE]});this.initialized=!0;this.setLidOpen(!1)}dispose(){this.workspace.getComponentManager().removeComponent("trashcan");this.svgGroup&&removeNode$$module$build$src$core$utils$dom(this.svgGroup);this.lidTask&&clearTimeout(this.lidTask)}hasContents(){return!!this.contents.length}contentsIsOpen(){return!!this.flyout&& -this.flyout.isVisible()}openFlyout(){if(!this.contentsIsOpen()){var a=this.contents.map(function(c){return JSON.parse(c)}),b=this.workspace.getParentSvg().style;b.cursor="wait";setTimeout(()=>{let c;null==(c=this.flyout)||c.show(a);b.cursor="";let d;null==(d=this.workspace.scrollbar)||d.setVisible(!1)},10);this.fireUiEvent(!0)}}closeFlyout(){if(this.contentsIsOpen()){var a;null==(a=this.flyout)||a.hide();var b;null==(b=this.workspace.scrollbar)||b.setVisible(!0);this.fireUiEvent(!1);this.workspace.recordDragTargets()}}autoHide(a){!a&& +this.flyout.isVisible()}openFlyout(){if(!this.contentsIsOpen()){var a=this.contents.map(function(c){return JSON.parse(c)}),b=this.workspace.getParentSvg().style;b.cursor="wait";setTimeout(()=>{let c;(c=this.flyout)==null||c.show(a);b.cursor="";let d;(d=this.workspace.scrollbar)==null||d.setVisible(!1)},10);this.fireUiEvent(!0)}}closeFlyout(){if(this.contentsIsOpen()){var a;(a=this.flyout)==null||a.hide();var b;(b=this.workspace.scrollbar)==null||b.setVisible(!0);this.fireUiEvent(!1);this.workspace.recordDragTargets()}}autoHide(a){!a&& this.flyout&&this.closeFlyout()}emptyContents(){this.hasContents()&&(this.contents.length=0,this.setMinOpenness(0),this.closeFlyout())}position(a,b){if(this.initialized){var c=getCornerOppositeToolbox$$module$build$src$core$positionable_helpers(this.workspace,a);a=getStartPositionRect$$module$build$src$core$positionable_helpers(c,new Size$$module$build$src$core$utils$size(WIDTH$$module$build$src$core$trashcan,BODY_HEIGHT$$module$build$src$core$trashcan+LID_HEIGHT$$module$build$src$core$trashcan), -MARGIN_HORIZONTAL$$module$build$src$core$trashcan,MARGIN_VERTICAL$$module$build$src$core$trashcan,a,this.workspace);b=bumpPositionRect$$module$build$src$core$positionable_helpers(a,MARGIN_VERTICAL$$module$build$src$core$trashcan,c.vertical===verticalPosition$$module$build$src$core$positionable_helpers.TOP?bumpDirection$$module$build$src$core$positionable_helpers.DOWN:bumpDirection$$module$build$src$core$positionable_helpers.UP,b);this.top=b.top;this.left=b.left;var d;null==(d=this.svgGroup)||d.setAttribute("transform", -"translate("+this.left+","+this.top+")");var e;null==(e=this.flyout)||e.position()}}getBoundingRectangle(){return new Rect$$module$build$src$core$utils$rect(this.top,this.top+BODY_HEIGHT$$module$build$src$core$trashcan+LID_HEIGHT$$module$build$src$core$trashcan,this.left,this.left+WIDTH$$module$build$src$core$trashcan)}getClientRect(){if(!this.svgGroup)return null;var a=this.svgGroup.getBoundingClientRect();const b=a.top+SPRITE_TOP$$module$build$src$core$trashcan-MARGIN_HOTSPOT$$module$build$src$core$trashcan; +MARGIN_HORIZONTAL$$module$build$src$core$trashcan,MARGIN_VERTICAL$$module$build$src$core$trashcan,a,this.workspace);b=bumpPositionRect$$module$build$src$core$positionable_helpers(a,MARGIN_VERTICAL$$module$build$src$core$trashcan,c.vertical===verticalPosition$$module$build$src$core$positionable_helpers.TOP?bumpDirection$$module$build$src$core$positionable_helpers.DOWN:bumpDirection$$module$build$src$core$positionable_helpers.UP,b);this.top=b.top;this.left=b.left;var d;(d=this.svgGroup)==null||d.setAttribute("transform", +"translate("+this.left+","+this.top+")");var e;(e=this.flyout)==null||e.position()}}getBoundingRectangle(){return new Rect$$module$build$src$core$utils$rect(this.top,this.top+BODY_HEIGHT$$module$build$src$core$trashcan+LID_HEIGHT$$module$build$src$core$trashcan,this.left,this.left+WIDTH$$module$build$src$core$trashcan)}getClientRect(){if(!this.svgGroup)return null;var a=this.svgGroup.getBoundingClientRect();const b=a.top+SPRITE_TOP$$module$build$src$core$trashcan-MARGIN_HOTSPOT$$module$build$src$core$trashcan; a=a.left+SPRITE_LEFT$$module$build$src$core$trashcan-MARGIN_HOTSPOT$$module$build$src$core$trashcan;return new Rect$$module$build$src$core$utils$rect(b,b+LID_HEIGHT$$module$build$src$core$trashcan+BODY_HEIGHT$$module$build$src$core$trashcan+2*MARGIN_HOTSPOT$$module$build$src$core$trashcan,a,a+WIDTH$$module$build$src$core$trashcan+2*MARGIN_HOTSPOT$$module$build$src$core$trashcan)}onDragOver(a){this.setLidOpen(this.wouldDelete_)}onDragExit(a){this.setLidOpen(!1)}onDrop(a){setTimeout(this.setLidOpen.bind(this, !1),100)}setLidOpen(a){this.isLidOpen!==a&&(this.lidTask&&clearTimeout(this.lidTask),this.isLidOpen=a,this.animateLid())}animateLid(){const a=ANIMATION_FRAMES$$module$build$src$core$trashcan;var b=1/(a+1);this.lidOpen+=this.isLidOpen?b:-b;this.lidOpen=Math.min(Math.max(this.lidOpen,this.minOpenness),1);this.setLidAngle(this.lidOpen*MAX_LID_ANGLE$$module$build$src$core$trashcan);b=OPACITY_MIN$$module$build$src$core$trashcan+this.lidOpen*(OPACITY_MAX$$module$build$src$core$trashcan-OPACITY_MIN$$module$build$src$core$trashcan); -this.svgGroup&&(this.svgGroup.style.opacity=`${b}`);this.lidOpen>this.minOpenness&&1>this.lidOpen&&(this.lidTask=setTimeout(this.animateLid.bind(this),ANIMATION_LENGTH$$module$build$src$core$trashcan/a))}setLidAngle(a){const b=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.RIGHT||this.workspace.horizontalLayout&&this.workspace.RTL;let c;null==(c=this.svgLid)||c.setAttribute("transform","rotate("+(b?-a:a)+","+(b?4:WIDTH$$module$build$src$core$trashcan-4)+","+(LID_HEIGHT$$module$build$src$core$trashcan- +this.svgGroup&&(this.svgGroup.style.opacity=`${b}`);this.lidOpen>this.minOpenness&&this.lidOpen<1&&(this.lidTask=setTimeout(this.animateLid.bind(this),ANIMATION_LENGTH$$module$build$src$core$trashcan/a))}setLidAngle(a){const b=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.RIGHT||this.workspace.horizontalLayout&&this.workspace.RTL;let c;(c=this.svgLid)==null||c.setAttribute("transform","rotate("+(b?-a:a)+","+(b?4:WIDTH$$module$build$src$core$trashcan-4)+","+(LID_HEIGHT$$module$build$src$core$trashcan- 2)+")")}setMinOpenness(a){this.minOpenness=a;this.isLidOpen||this.setLidAngle(a*MAX_LID_ANGLE$$module$build$src$core$trashcan)}closeLid(){this.setLidOpen(!1)}click(){this.hasContents()&&!this.workspace.isDragging()&&this.openFlyout()}fireUiEvent(a){a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.TRASHCAN_OPEN))(a,this.workspace.id);fire$$module$build$src$core$events$utils(a)}blockMouseDownWhenOpenable(a){!this.contentsIsOpen()&&this.hasContents()&&a.stopPropagation()}mouseOver(){this.hasContents()&& -this.setLidOpen(!0)}mouseOut(){this.setLidOpen(!1)}onDelete(a){if(!(0>=this.workspace.options.maxTrashcanContents||!isBlockDelete$$module$build$src$core$events$predicates(a)||a.wasShadow)){if(!a.oldJson)throw Error("Encountered a delete event without proper oldJson");a=JSON.stringify(this.cleanBlockJson(a.oldJson));if(!this.contents.includes(a)){for(this.contents.unshift(a);this.contents.length>this.workspace.options.maxTrashcanContents;)this.contents.pop();this.setMinOpenness(HAS_BLOCKS_LID_ANGLE$$module$build$src$core$trashcan)}}}cleanBlockJson(a){function b(c){if(c){delete c.id; +this.setLidOpen(!0)}mouseOut(){this.setLidOpen(!1)}onDelete(a){if(!(this.workspace.options.maxTrashcanContents<=0||!isBlockDelete$$module$build$src$core$events$predicates(a)||a.wasShadow)){if(!a.oldJson)throw Error("Encountered a delete event without proper oldJson");a=JSON.stringify(this.cleanBlockJson(a.oldJson));if(!this.contents.includes(a)){for(this.contents.unshift(a);this.contents.length>this.workspace.options.maxTrashcanContents;)this.contents.pop();this.setMinOpenness(HAS_BLOCKS_LID_ANGLE$$module$build$src$core$trashcan)}}}cleanBlockJson(a){function b(c){if(c){delete c.id; delete c.x;delete c.y;delete c.enabled;delete c.disabledReasons;if(c.icons&&c.icons.comment){var d=c.icons.comment;delete d.height;delete d.width;delete d.pinned}d=c.inputs;for(var e in d){var f=d[e];const g=f.block;f=f.shadow;g&&b(g);f&&b(f)}c.next&&(e=c.next,c=e.block,e=e.shadow,c&&b(c),e&&b(e))}}a=JSON.parse(JSON.stringify(a));b(a);return Object.assign({},{kind:"BLOCK"},a)}},WIDTH$$module$build$src$core$trashcan=47,BODY_HEIGHT$$module$build$src$core$trashcan=44,LID_HEIGHT$$module$build$src$core$trashcan= 16,MARGIN_VERTICAL$$module$build$src$core$trashcan=20,MARGIN_HORIZONTAL$$module$build$src$core$trashcan=20,MARGIN_HOTSPOT$$module$build$src$core$trashcan=10,SPRITE_LEFT$$module$build$src$core$trashcan=0,SPRITE_TOP$$module$build$src$core$trashcan=32,HAS_BLOCKS_LID_ANGLE$$module$build$src$core$trashcan=.1,ANIMATION_LENGTH$$module$build$src$core$trashcan=80,ANIMATION_FRAMES$$module$build$src$core$trashcan=4,OPACITY_MIN$$module$build$src$core$trashcan=.4,OPACITY_MAX$$module$build$src$core$trashcan=.8, -MAX_LID_ANGLE$$module$build$src$core$trashcan=45,module$build$src$core$trashcan={};module$build$src$core$trashcan.Trashcan=Trashcan$$module$build$src$core$trashcan;var ShortcutRegistry$$module$build$src$core$shortcut_registry=class{constructor(){this.shortcuts=new Map;this.keyMap=new Map;this.reset()}reset(){this.shortcuts.clear();this.keyMap.clear()}register(a,b){if(this.shortcuts.get(a.name)&&!b)throw Error(`Shortcut named "${a.name}" already exists.`);this.shortcuts.set(a.name,a);b=a.keyCodes;if(null==b?0:b.length)for(const c of b)this.addKeyMapping(c,a.name,!!a.allowCollision)}unregister(a){if(!this.shortcuts.get(a))return console.warn(`Keyboard shortcut named "${a}" not found.`), -!1;this.removeAllKeyMappings(a);this.shortcuts.delete(a);return!0}addKeyMapping(a,b,c){a=`${a}`;const d=this.keyMap.get(a);if(d&&!c)throw Error(`Shortcut named "${b}" collides with shortcuts "${d}"`);d&&c?d.unshift(b):this.keyMap.set(a,[b])}removeKeyMapping(a,b,c){const d=this.keyMap.get(a);if(!d)return c||console.warn(`No keyboard shortcut named "${b}" registered with key code "${a}"`),!1;const e=d.indexOf(b);if(-1saveProcedure$$module$build$src$core$serialization$procedures(b));return a.length?a:null}load(a,b){const c=b.getProcedureMap();for(const d of a)c.add(loadProcedure$$module$build$src$core$serialization$procedures(this.procedureModelClass, -this.parameterModelClass,d,b))}clear(a){a.getProcedureMap().clear()}},module$build$src$core$serialization$procedures={};module$build$src$core$serialization$procedures.ProcedureSerializer=ProcedureSerializer$$module$build$src$core$serialization$procedures;module$build$src$core$serialization$procedures.loadProcedure=loadProcedure$$module$build$src$core$serialization$procedures;module$build$src$core$serialization$procedures.saveProcedure=saveProcedure$$module$build$src$core$serialization$procedures;var VariableSerializer$$module$build$src$core$serialization$variables=class{constructor(){this.priority=VARIABLES$$module$build$src$core$serialization$priorities}save(a){const b=[];for(const c of a.getAllVariables())a={name:c.name,id:c.getId()},c.type&&(a.type=c.type),b.push(a);return b.length?b:null}load(a,b){for(const c of a)b.createVariable(c.name,c.type,c.id)}clear(a){a.getVariableMap().clear()}};register$$module$build$src$core$serialization$registry("variables",new VariableSerializer$$module$build$src$core$serialization$variables); -var module$build$src$core$serialization$variables={};module$build$src$core$serialization$variables.VariableSerializer=VariableSerializer$$module$build$src$core$serialization$variables;var module$build$src$core$serialization$workspaces={};module$build$src$core$serialization$workspaces.load=load$$module$build$src$core$serialization$workspaces;module$build$src$core$serialization$workspaces.save=save$$module$build$src$core$serialization$workspaces;var module$build$src$core$serialization={blocks:module$build$src$core$serialization$blocks,exceptions:module$build$src$core$serialization$exceptions,priorities:module$build$src$core$serialization$priorities,procedures:module$build$src$core$serialization$procedures,registry:module$build$src$core$serialization$registry,variables:module$build$src$core$serialization$variables,workspaceComments:module$build$src$core$serialization$workspace_comments,workspaces:module$build$src$core$serialization$workspaces};var ScrollbarPair$$module$build$src$core$scrollbar_pair=class{constructor(a,b,c,d,e){this.workspace=a;this.oldHostMetrics=this.corner_=this.vScroll=this.hScroll=null;b=void 0===b?!0:b;c=void 0===c?!0:c;const f=b&&c;b&&(this.hScroll=new Scrollbar$$module$build$src$core$scrollbar(a,!0,f,d,e));c&&(this.vScroll=new Scrollbar$$module$build$src$core$scrollbar(a,!1,f,d,e));f&&(this.corner_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{height:Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness, -width:Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness,"class":"blocklyScrollbarBackground"}),insertAfter$$module$build$src$core$utils$dom(this.corner_,a.getBubbleCanvas()))}dispose(){removeNode$$module$build$src$core$utils$dom(this.corner_);this.oldHostMetrics=this.corner_=null;this.hScroll&&(this.hScroll.dispose(),this.hScroll=null);this.vScroll&&(this.vScroll.dispose(),this.vScroll=null)}resize(){const a=this.workspace.getMetrics();if(a){var b=!1,c=!1;this.oldHostMetrics&&this.oldHostMetrics.viewWidth=== -a.viewWidth&&this.oldHostMetrics.viewHeight===a.viewHeight&&this.oldHostMetrics.absoluteTop===a.absoluteTop&&this.oldHostMetrics.absoluteLeft===a.absoluteLeft?(this.oldHostMetrics&&this.oldHostMetrics.scrollWidth===a.scrollWidth&&this.oldHostMetrics.viewLeft===a.viewLeft&&this.oldHostMetrics.scrollLeft===a.scrollLeft||(b=!0),this.oldHostMetrics&&this.oldHostMetrics.scrollHeight===a.scrollHeight&&this.oldHostMetrics.viewTop===a.viewTop&&this.oldHostMetrics.scrollTop===a.scrollTop||(c=!0)):c=b=!0;if(b|| -c){try{$.disable$$module$build$src$core$events$utils(),this.hScroll&&b&&this.hScroll.resize(a),this.vScroll&&c&&this.vScroll.resize(a)}finally{$.enable$$module$build$src$core$events$utils()}this.workspace.maybeFireViewportChangeEvent()}if(this.hScroll&&this.vScroll){if(!this.oldHostMetrics||this.oldHostMetrics.viewWidth!==a.viewWidth||this.oldHostMetrics.absoluteLeft!==a.absoluteLeft){let d;null==(d=this.corner_)||d.setAttribute("x",String(this.vScroll.position.x))}if(!this.oldHostMetrics||this.oldHostMetrics.viewHeight!== -a.viewHeight||this.oldHostMetrics.absoluteTop!==a.absoluteTop){let d;null==(d=this.corner_)||d.setAttribute("y",String(this.hScroll.position.y))}}this.oldHostMetrics=a}}canScrollHorizontally(){return!!this.hScroll}canScrollVertically(){return!!this.vScroll}setOrigin(a,b){this.hScroll&&this.hScroll.setOrigin(a,b);this.vScroll&&this.vScroll.setOrigin(a,b)}set(a,b,c){this.hScroll&&this.hScroll.set(a,!1);this.vScroll&&this.vScroll.set(b,!1);if(c||void 0===c)a={},this.hScroll&&(a.x=this.hScroll.getRatio_()), -this.vScroll&&(a.y=this.vScroll.getRatio_()),this.workspace.setMetrics(a)}setX(a){this.hScroll&&this.hScroll.set(a,!0)}setY(a){this.vScroll&&this.vScroll.set(a,!0)}setContainerVisible(a){this.hScroll&&this.hScroll.setContainerVisible(a);this.vScroll&&this.vScroll.setContainerVisible(a)}isVisible(){let a=!1;this.hScroll&&(a=this.hScroll.isVisible());this.vScroll&&(a=a||this.vScroll.isVisible());return a}setVisible(a){this.hScroll&&this.hScroll.setVisibleInternal(a);this.vScroll&&this.vScroll.setVisibleInternal(a)}resizeContent(a){this.hScroll&& -this.hScroll.resizeContentHorizontal(a);this.vScroll&&this.vScroll.resizeContentVertical(a)}resizeView(a){this.hScroll&&this.hScroll.resizeViewHorizontal(a);this.vScroll&&this.vScroll.resizeViewVertical(a)}},module$build$src$core$scrollbar_pair={};module$build$src$core$scrollbar_pair.ScrollbarPair=ScrollbarPair$$module$build$src$core$scrollbar_pair;var MetricsManager$$module$build$src$core$metrics_manager=class{constructor(a){this.workspace_=a}getDimensionsPx_(a){let b=0,c=0;a&&(b=a.getWidth(),c=a.getHeight());return new Size$$module$build$src$core$utils$size(b,c)}getFlyoutMetrics(a){a=this.getDimensionsPx_(this.workspace_.getFlyout(a));return{width:a.width,height:a.height,position:this.workspace_.toolboxPosition}}getToolboxMetrics(){const a=this.getDimensionsPx_(this.workspace_.getToolbox());return{width:a.width,height:a.height,position:this.workspace_.toolboxPosition}}getSvgMetrics(){return this.workspace_.getCachedParentSvgSize()}getAbsoluteMetrics(){let a= -0,b=0;const c=this.getToolboxMetrics(),d=this.getFlyoutMetrics(),e=!!this.workspace_.getToolbox();var f;const g=!(null==(f=this.workspace_.getFlyout())?0:f.autoClose);f=e?c.position:d.position;const h=f===Position$$module$build$src$core$utils$toolbox.TOP;f===Position$$module$build$src$core$utils$toolbox.LEFT&&(e&&(a+=c.width),g&&(a+=d.width));h&&(e&&(b+=c.height),g&&(b+=d.height));return{top:b,left:a}}getViewMetrics(a){a=a?this.workspace_.scale:1;const b=this.getSvgMetrics(),c=this.getToolboxMetrics(), -d=this.getFlyoutMetrics(),e=!!this.workspace_.getToolbox();var f;const g=!(null==(f=this.workspace_.getFlyout())?0:f.autoClose);f=e?c.position:d.position;const h=f===Position$$module$build$src$core$utils$toolbox.LEFT||f===Position$$module$build$src$core$utils$toolbox.RIGHT;if(f===Position$$module$build$src$core$utils$toolbox.TOP||f===Position$$module$build$src$core$utils$toolbox.BOTTOM)e&&(b.height-=c.height),g&&(b.height-=d.height);h&&(e&&(b.width-=c.width),g&&(b.width-=d.width));return{height:b.height/ -a,width:b.width/a,top:-this.workspace_.scrollY/a,left:-this.workspace_.scrollX/a}}getContentMetrics(a){a=a?1:this.workspace_.scale;const b=this.workspace_.getBlocksBoundingBox();return{height:(b.bottom-b.top)*a,width:(b.right-b.left)*a,top:b.top*a,left:b.left*a}}hasFixedEdges(){return!this.workspace_.isMovableHorizontally()||!this.workspace_.isMovableVertically()}getComputedFixedEdges_(a){if(!this.hasFixedEdges())return{};const b=this.workspace_.isMovableHorizontally(),c=this.workspace_.isMovableVertically(); -a=a||this.getViewMetrics(!1);const d={};c||(d.top=a.top,d.bottom=a.top+a.height);b||(d.left=a.left,d.right=a.left+a.width);return d}getPaddedContent_(a,b){const c=b.top+b.height,d=b.left+b.width,e=a.width;a=a.height;const f=e/2,g=a/2;return{top:Math.min(b.top-g,c-a),bottom:Math.max(c+g,b.top+a),left:Math.min(b.left-f,d-e),right:Math.max(d+f,b.left+e)}}getScrollMetrics(a,b,c){a=a?this.workspace_.scale:1;b=b||this.getViewMetrics(!1);var d=c||this.getContentMetrics();c=this.getComputedFixedEdges_(b); -b=this.getPaddedContent_(b,d);d=void 0!==c.top?c.top:b.top;const e=void 0!==c.left?c.left:b.left;return{top:d/a,left:e/a,width:((void 0!==c.right?c.right:b.right)-e)/a,height:((void 0!==c.bottom?c.bottom:b.bottom)-d)/a}}getUiMetrics(){return{viewMetrics:this.getViewMetrics(),absoluteMetrics:this.getAbsoluteMetrics(),toolboxMetrics:this.getToolboxMetrics()}}getMetrics(){const a=this.getToolboxMetrics(),b=this.getFlyoutMetrics(!0),c=this.getSvgMetrics(),d=this.getAbsoluteMetrics(),e=this.getViewMetrics(), -f=this.getContentMetrics(),g=this.getScrollMetrics(!1,e,f);return{contentHeight:f.height,contentWidth:f.width,contentTop:f.top,contentLeft:f.left,scrollHeight:g.height,scrollWidth:g.width,scrollTop:g.top,scrollLeft:g.left,viewHeight:e.height,viewWidth:e.width,viewTop:e.top,viewLeft:e.left,absoluteTop:d.top,absoluteLeft:d.left,svgHeight:c.height,svgWidth:c.width,toolboxWidth:a.width,toolboxHeight:a.height,toolboxPosition:a.position,flyoutWidth:b.width,flyoutHeight:b.height}}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.METRICS_MANAGER,DEFAULT$$module$build$src$core$registry,MetricsManager$$module$build$src$core$metrics_manager);var module$build$src$core$metrics_manager={};module$build$src$core$metrics_manager.MetricsManager=MetricsManager$$module$build$src$core$metrics_manager;"Blockly"in globalThis||(globalThis.Blockly={Msg:module$build$src$core$msg});var module$build$src$core$main={};var ConstantProvider$$module$build$src$core$renderers$zelos$constants=class extends ConstantProvider$$module$build$src$core$renderers$common$constants{constructor(){super();this.GRID_UNIT=4;this.CURSOR_COLOUR="#ffa200";this.CURSOR_RADIUS=5;this.JAGGED_TEETH_WIDTH=this.JAGGED_TEETH_HEIGHT=0;this.START_HAT_HEIGHT=22;this.START_HAT_WIDTH=96;this.SHAPES={HEXAGONAL:1,ROUND:2,SQUARE:3,PUZZLE:4,NOTCH:5};this.SHAPE_IN_SHAPE_PADDING={1:{0:5*this.GRID_UNIT,1:2*this.GRID_UNIT,2:5*this.GRID_UNIT,3:5*this.GRID_UNIT}, +MAX_LID_ANGLE$$module$build$src$core$trashcan=45,module$build$src$core$trashcan={};module$build$src$core$trashcan.Trashcan=Trashcan$$module$build$src$core$trashcan;var stashedCopyData$$module$build$src$core$clipboard=null,stashedWorkspace$$module$build$src$core$clipboard=null,stashedCoordinates$$module$build$src$core$clipboard=void 0,module$build$src$core$clipboard={};module$build$src$core$clipboard.BlockPaster=BlockPaster$$module$build$src$core$clipboard$block_paster;module$build$src$core$clipboard.copy=copy$$module$build$src$core$clipboard;module$build$src$core$clipboard.getLastCopiedData=getLastCopiedData$$module$build$src$core$clipboard; +module$build$src$core$clipboard.getLastCopiedLocation=getLastCopiedLocation$$module$build$src$core$clipboard;module$build$src$core$clipboard.getLastCopiedWorkspace=getLastCopiedWorkspace$$module$build$src$core$clipboard;module$build$src$core$clipboard.paste=paste$$module$build$src$core$clipboard;module$build$src$core$clipboard.registry=module$build$src$core$clipboard$registry;module$build$src$core$clipboard.setLastCopiedData=setLastCopiedData$$module$build$src$core$clipboard; +module$build$src$core$clipboard.setLastCopiedLocation=setLastCopiedLocation$$module$build$src$core$clipboard;module$build$src$core$clipboard.setLastCopiedWorkspace=setLastCopiedWorkspace$$module$build$src$core$clipboard;var module$build$src$core$comments={};module$build$src$core$comments.CollapseCommentBarButton=CollapseCommentBarButton$$module$build$src$core$comments$collapse_comment_bar_button;module$build$src$core$comments.CommentBarButton=CommentBarButton$$module$build$src$core$comments$comment_bar_button;module$build$src$core$comments.CommentEditor=CommentEditor$$module$build$src$core$comments$comment_editor;module$build$src$core$comments.CommentView=CommentView$$module$build$src$core$comments$comment_view; +module$build$src$core$comments.DeleteCommentBarButton=DeleteCommentBarButton$$module$build$src$core$comments$delete_comment_bar_button;module$build$src$core$comments.RenderedWorkspaceComment=RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment;module$build$src$core$comments.WorkspaceComment=WorkspaceComment$$module$build$src$core$comments$workspace_comment;var module$build$src$core$interfaces$i_copyable={};module$build$src$core$interfaces$i_copyable.isCopyable=isCopyable$$module$build$src$core$interfaces$i_copyable;var names$$module$build$src$core$shortcut_items;(function(a){a.ESCAPE="escape";a.DELETE="delete";a.COPY="copy";a.CUT="cut";a.PASTE="paste";a.UNDO="undo";a.REDO="redo";a.MENU="menu"})(names$$module$build$src$core$shortcut_items||(names$$module$build$src$core$shortcut_items={}));registerDefaultShortcuts$$module$build$src$core$shortcut_items();var module$build$src$core$shortcut_items={};module$build$src$core$shortcut_items.names=names$$module$build$src$core$shortcut_items; +module$build$src$core$shortcut_items.registerCopy=registerCopy$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerCut=registerCut$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerDefaultShortcuts=registerDefaultShortcuts$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerDelete=registerDelete$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerEscape=registerEscape$$module$build$src$core$shortcut_items; +module$build$src$core$shortcut_items.registerPaste=registerPaste$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerRedo=registerRedo$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerShowContextMenu=registerShowContextMenu$$module$build$src$core$shortcut_items;module$build$src$core$shortcut_items.registerUndo=registerUndo$$module$build$src$core$shortcut_items;var ProcedureSerializer$$module$build$src$core$serialization$procedures=class{constructor(a,b){this.procedureModelClass=a;this.parameterModelClass=b;this.priority=PROCEDURES$$module$build$src$core$serialization$priorities}save(a){a=a.getProcedureMap().getProcedures().map(b=>saveProcedure$$module$build$src$core$serialization$procedures(b));return a.length?a:null}load(a,b){const c=b.getProcedureMap();for(const d of a)c.add(loadProcedure$$module$build$src$core$serialization$procedures(this.procedureModelClass, +this.parameterModelClass,d,b))}clear(a){a.getProcedureMap().clear()}},module$build$src$core$serialization$procedures={};module$build$src$core$serialization$procedures.ProcedureSerializer=ProcedureSerializer$$module$build$src$core$serialization$procedures;module$build$src$core$serialization$procedures.loadProcedure=loadProcedure$$module$build$src$core$serialization$procedures;module$build$src$core$serialization$procedures.saveProcedure=saveProcedure$$module$build$src$core$serialization$procedures;var VariableSerializer$$module$build$src$core$serialization$variables=class{constructor(){this.priority=VARIABLES$$module$build$src$core$serialization$priorities}save(a){a=a.getVariableMap().getAllVariables().map(b=>b.save());return a.length?a:null}load(a,b){const c=getObject$$module$build$src$core$registry(Type$$module$build$src$core$registry.VARIABLE_MODEL,DEFAULT$$module$build$src$core$registry);a.forEach(d=>{c==null||c.load(d,b)})}clear(a){a.getVariableMap().clear()}}; +register$$module$build$src$core$serialization$registry("variables",new VariableSerializer$$module$build$src$core$serialization$variables);var module$build$src$core$serialization$variables={};module$build$src$core$serialization$variables.VariableSerializer=VariableSerializer$$module$build$src$core$serialization$variables;var module$build$src$core$serialization$workspaces={};module$build$src$core$serialization$workspaces.load=load$$module$build$src$core$serialization$workspaces;module$build$src$core$serialization$workspaces.save=save$$module$build$src$core$serialization$workspaces;var module$build$src$core$serialization={blocks:module$build$src$core$serialization$blocks,exceptions:module$build$src$core$serialization$exceptions,priorities:module$build$src$core$serialization$priorities,procedures:module$build$src$core$serialization$procedures,registry:module$build$src$core$serialization$registry,variables:module$build$src$core$serialization$variables,workspaceComments:module$build$src$core$serialization$workspace_comments,workspaces:module$build$src$core$serialization$workspaces};"Blockly"in globalThis||(globalThis.Blockly={Msg:module$build$src$core$msg});var module$build$src$core$main={};var LABEL_TYPE$$module$build$src$core$label_flyout_inflater="label",LabelFlyoutInflater$$module$build$src$core$label_flyout_inflater=class{load(a,b){a=new FlyoutButton$$module$build$src$core$flyout_button(b.getWorkspace(),b.targetWorkspace,a,!0);a.show();return new FlyoutItem$$module$build$src$core$flyout_item(a,LABEL_TYPE$$module$build$src$core$label_flyout_inflater)}gapForItem(a,b){return b}disposeItem(a){a=a.getElement();a instanceof FlyoutButton$$module$build$src$core$flyout_button&&a.dispose()}getType(){return LABEL_TYPE$$module$build$src$core$label_flyout_inflater}}; +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUT_INFLATER,LABEL_TYPE$$module$build$src$core$label_flyout_inflater,LabelFlyoutInflater$$module$build$src$core$label_flyout_inflater);var module$build$src$core$label_flyout_inflater={};module$build$src$core$label_flyout_inflater.LabelFlyoutInflater=LabelFlyoutInflater$$module$build$src$core$label_flyout_inflater;var ConstantProvider$$module$build$src$core$renderers$zelos$constants=class extends ConstantProvider$$module$build$src$core$renderers$common$constants{constructor(a){super();this.GRID_UNIT=4;this.CURSOR_COLOUR="#ffa200";this.CURSOR_RADIUS=5;this.JAGGED_TEETH_WIDTH=this.JAGGED_TEETH_HEIGHT=0;this.START_HAT_HEIGHT=22;this.START_HAT_WIDTH=96;this.SHAPES={HEXAGONAL:1,ROUND:2,SQUARE:3,PUZZLE:4,NOTCH:5};this.SHAPE_IN_SHAPE_PADDING={1:{0:5*this.GRID_UNIT,1:2*this.GRID_UNIT,2:5*this.GRID_UNIT,3:5*this.GRID_UNIT}, 2:{0:3*this.GRID_UNIT,1:3*this.GRID_UNIT,2:1*this.GRID_UNIT,3:2*this.GRID_UNIT},3:{0:2*this.GRID_UNIT,1:2*this.GRID_UNIT,2:2*this.GRID_UNIT,3:2*this.GRID_UNIT}};this.FULL_BLOCK_FIELDS=!0;this.FIELD_TEXT_FONTWEIGHT="bold";this.FIELD_TEXT_FONTFAMILY='"Helvetica Neue", "Segoe UI", Helvetica, sans-serif';this.FIELD_COLOUR_FULL_BLOCK=this.FIELD_TEXTINPUT_BOX_SHADOW=this.FIELD_DROPDOWN_SVG_ARROW=this.FIELD_DROPDOWN_COLOURED_DIV=this.FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW=!0;this.SELECTED_GLOW_COLOUR="#fff200"; -this.SELECTED_GLOW_SIZE=.5;this.REPLACEMENT_GLOW_COLOUR="#fff200";this.REPLACEMENT_GLOW_SIZE=2;this.selectedGlowFilterId="";this.selectedGlowFilter=null;this.replacementGlowFilterId="";this.SQUARED=this.ROUNDED=this.HEXAGONAL=this.replacementGlowFilter=null;this.SMALL_PADDING=this.GRID_UNIT;this.MEDIUM_PADDING=2*this.GRID_UNIT;this.MEDIUM_LARGE_PADDING=3*this.GRID_UNIT;this.LARGE_PADDING=4*this.GRID_UNIT;this.CORNER_RADIUS=1*this.GRID_UNIT;this.NOTCH_WIDTH=9*this.GRID_UNIT;this.NOTCH_HEIGHT=2*this.GRID_UNIT; -this.STATEMENT_INPUT_NOTCH_OFFSET=this.NOTCH_OFFSET_LEFT=3*this.GRID_UNIT;this.MIN_BLOCK_WIDTH=2*this.GRID_UNIT;this.MIN_BLOCK_HEIGHT=12*this.GRID_UNIT;this.EMPTY_STATEMENT_INPUT_HEIGHT=6*this.GRID_UNIT;this.TOP_ROW_MIN_HEIGHT=this.CORNER_RADIUS;this.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT=this.LARGE_PADDING;this.BOTTOM_ROW_MIN_HEIGHT=this.CORNER_RADIUS;this.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT=6*this.GRID_UNIT;this.STATEMENT_BOTTOM_SPACER=-this.NOTCH_HEIGHT;this.STATEMENT_INPUT_SPACER_MIN_WIDTH=40* -this.GRID_UNIT;this.STATEMENT_INPUT_PADDING_LEFT=4*this.GRID_UNIT;this.EMPTY_INLINE_INPUT_PADDING=4*this.GRID_UNIT;this.EMPTY_INLINE_INPUT_HEIGHT=8*this.GRID_UNIT;this.DUMMY_INPUT_MIN_HEIGHT=8*this.GRID_UNIT;this.DUMMY_INPUT_SHADOW_MIN_HEIGHT=6*this.GRID_UNIT;this.CURSOR_WS_WIDTH=20*this.GRID_UNIT;this.FIELD_TEXT_FONTSIZE=3*this.GRID_UNIT;this.FIELD_BORDER_RECT_RADIUS=this.CORNER_RADIUS;this.FIELD_BORDER_RECT_X_PADDING=2*this.GRID_UNIT;this.FIELD_BORDER_RECT_Y_PADDING=1.625*this.GRID_UNIT;this.FIELD_BORDER_RECT_HEIGHT= -8*this.GRID_UNIT;this.FIELD_DROPDOWN_BORDER_RECT_HEIGHT=8*this.GRID_UNIT;this.FIELD_DROPDOWN_SVG_ARROW_PADDING=this.FIELD_BORDER_RECT_X_PADDING;this.FIELD_COLOUR_DEFAULT_WIDTH=6*this.GRID_UNIT;this.FIELD_COLOUR_DEFAULT_HEIGHT=8*this.GRID_UNIT;this.FIELD_CHECKBOX_X_OFFSET=1*this.GRID_UNIT;this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH=12*this.GRID_UNIT}setFontConstants_(a){super.setFontConstants_(a);this.FIELD_DROPDOWN_BORDER_RECT_HEIGHT=this.FIELD_BORDER_RECT_HEIGHT=this.FIELD_TEXT_HEIGHT+2*this.FIELD_BORDER_RECT_Y_PADDING}init(){super.init(); -this.HEXAGONAL=this.makeHexagonal();this.ROUNDED=this.makeRounded();this.SQUARED=this.makeSquared();this.STATEMENT_INPUT_NOTCH_OFFSET=this.NOTCH_OFFSET_LEFT+this.INSIDE_CORNERS.rightWidth}setDynamicProperties_(a){super.setDynamicProperties_(a);this.SELECTED_GLOW_COLOUR=a.getComponentStyle("selectedGlowColour")||this.SELECTED_GLOW_COLOUR;const b=Number(a.getComponentStyle("selectedGlowSize"));this.SELECTED_GLOW_SIZE=b&&!isNaN(b)?b:this.SELECTED_GLOW_SIZE;this.REPLACEMENT_GLOW_COLOUR=a.getComponentStyle("replacementGlowColour")|| -this.REPLACEMENT_GLOW_COLOUR;this.REPLACEMENT_GLOW_SIZE=(a=Number(a.getComponentStyle("replacementGlowSize")))&&!isNaN(a)?a:this.REPLACEMENT_GLOW_SIZE}dispose(){super.dispose();this.selectedGlowFilter&&removeNode$$module$build$src$core$utils$dom(this.selectedGlowFilter);this.replacementGlowFilter&&removeNode$$module$build$src$core$utils$dom(this.replacementGlowFilter)}makeStartHat(){const a=this.START_HAT_HEIGHT,b=this.START_HAT_WIDTH,c=curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(25, --a),point$$module$build$src$core$utils$svg_paths(71,-a),point$$module$build$src$core$utils$svg_paths(b,0)]);return{height:a,width:b,path:c}}makeHexagonal(){function a(c,d,e){var f=c/2;f=f>b?b:f;e=e?-1:1;c=(d?-1:1)*c/2;return lineTo$$module$build$src$core$utils$svg_paths(-e*f,c)+lineTo$$module$build$src$core$utils$svg_paths(e*f,c)}const b=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;return{type:this.SHAPES.HEXAGONAL,isDynamic:!0,width(c){c/=2;return c>b?b:c},height(c){return c},connectionOffsetY(c){return c/ -2},connectionOffsetX(c){return-c},pathDown(c){return a(c,!1,!1)},pathUp(c){return a(c,!0,!1)},pathRightDown(c){return a(c,!1,!0)},pathRightUp(c){return a(c,!1,!0)}}}makeRounded(){function a(d,e,f){const g=d>c?d-c:0;d=(d>c?c:d)/2;const h=f===e?"0":"1";return arc$$module$build$src$core$utils$svg_paths("a","0 0,"+h,d,point$$module$build$src$core$utils$svg_paths((f?1:-1)*d,(e?-1:1)*d))+lineOnAxis$$module$build$src$core$utils$svg_paths("v",(e?-1:1)*g)+arc$$module$build$src$core$utils$svg_paths("a","0 0,"+ -h,d,point$$module$build$src$core$utils$svg_paths((f?-1:1)*d,(e?-1:1)*d))}const b=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,c=2*b;return{type:this.SHAPES.ROUND,isDynamic:!0,width(d){d/=2;return d>b?b:d},height(d){return d},connectionOffsetY(d){return d/2},connectionOffsetX(d){return-d},pathDown(d){return a(d,!1,!1)},pathUp(d){return a(d,!0,!1)},pathRightDown(d){return a(d,!1,!0)},pathRightUp(d){return a(d,!1,!0)}}}makeSquared(){function a(c,d,e){c-=2*b;const f=e===d?"0":"1";return arc$$module$build$src$core$utils$svg_paths("a", -"0 0,"+f,b,point$$module$build$src$core$utils$svg_paths((e?1:-1)*b,(d?-1:1)*b))+lineOnAxis$$module$build$src$core$utils$svg_paths("v",(d?-1:1)*c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,"+f,b,point$$module$build$src$core$utils$svg_paths((e?-1:1)*b,(d?-1:1)*b))}const b=this.CORNER_RADIUS;return{type:this.SHAPES.SQUARE,isDynamic:!0,width(c){return b},height(c){return c},connectionOffsetY(c){return c/2},connectionOffsetX(c){return-c},pathDown(c){return a(c,!1,!1)},pathUp(c){return a(c,!0, -!1)},pathRightDown(c){return a(c,!1,!0)},pathRightUp(c){return a(c,!1,!0)}}}shapeFor(a){let b=a.getCheck();!b&&a.targetConnection&&(b=a.targetConnection.getCheck());switch(a.type){case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:case ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE:a=a.getSourceBlock().getOutputShape();if(null!==a)switch(a){case this.SHAPES.HEXAGONAL:return this.HEXAGONAL;case this.SHAPES.ROUND:return this.ROUNDED;case this.SHAPES.SQUARE:return this.SQUARED}if(b&& -b.includes("Boolean"))return this.HEXAGONAL;if(b&&b.includes("Number"))return this.ROUNDED;b&&b.includes("String");return this.ROUNDED;case ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT:case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:return this.NOTCH;default:throw Error("Unknown type");}}makeNotch(){function a(l){return curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/2,0),point$$module$build$src$core$utils$svg_paths(l* -e*3/4,g/2),point$$module$build$src$core$utils$svg_paths(l*e,g)])+line$$module$build$src$core$utils$svg_paths([point$$module$build$src$core$utils$svg_paths(l*e,f)])+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/4,g/2),point$$module$build$src$core$utils$svg_paths(l*e/2,g),point$$module$build$src$core$utils$svg_paths(l*e,g)])+lineOnAxis$$module$build$src$core$utils$svg_paths("h",l*d)+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l* -e/2,0),point$$module$build$src$core$utils$svg_paths(l*e*3/4,-(g/2)),point$$module$build$src$core$utils$svg_paths(l*e,-g)])+line$$module$build$src$core$utils$svg_paths([point$$module$build$src$core$utils$svg_paths(l*e,-f)])+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/4,-(g/2)),point$$module$build$src$core$utils$svg_paths(l*e/2,-g),point$$module$build$src$core$utils$svg_paths(l*e,-g)])}const b=this.NOTCH_WIDTH,c=this.NOTCH_HEIGHT,d=b/3,e=d/3,f= -c/2,g=f/2,h=a(1),k=a(-1);return{type:this.SHAPES.NOTCH,width:b,height:c,pathLeft:h,pathRight:k}}makeInsideCorners(){const a=this.CORNER_RADIUS,b=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(-a,a)),c=arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a,point$$module$build$src$core$utils$svg_paths(-a,a)),d=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(a,a)),e=arc$$module$build$src$core$utils$svg_paths("a", -"0 0,1",a,point$$module$build$src$core$utils$svg_paths(a,a));return{width:a,height:a,pathTop:b,pathBottom:d,rightWidth:a,rightHeight:a,pathTopRight:c,pathBottomRight:e}}generateSecondaryColour_(a){return blend$$module$build$src$core$utils$colour("#000",a,.15)||a}generateTertiaryColour_(a){return blend$$module$build$src$core$utils$colour("#000",a,.25)||a}createDom(a,b,c){super.createDom(a,b,c);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.DEFS,{},a);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER, -{id:"blocklySelectedGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR,{"in":"SourceGraphic",stdDeviation:this.SELECTED_GLOW_SIZE},b);c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER,{result:"outBlur"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table", -tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},c);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":this.SELECTED_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in",result:"outGlow"},b);this.selectedGlowFilterId=b.id;this.selectedGlowFilter=b;a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER, -{id:"blocklyReplacementGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR,{"in":"SourceGraphic",stdDeviation:this.REPLACEMENT_GLOW_SIZE},a);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER,{result:"outBlur"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table", -tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":this.REPLACEMENT_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in",result:"outGlow"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"SourceGraphic", -in2:"outGlow",operator:"over"},a);this.replacementGlowFilterId=a.id;this.replacementGlowFilter=a}getCSS_(a){return[`${a} .blocklyText,`,`${a} .blocklyFlyoutLabelText {`,`font: ${this.FIELD_TEXT_FONTWEIGHT} ${this.FIELD_TEXT_FONTSIZE}`+`pt ${this.FIELD_TEXT_FONTFAMILY};`,"}",`${a} .blocklyTextInputBubble textarea {`,"font-weight: normal;","}",`${a} .blocklyText {`,"fill: #fff;","}",`${a} .blocklyNonEditableText>rect:not(.blocklyDropdownRect),`,`${a} .blocklyEditableText>rect:not(.blocklyDropdownRect) {`, -`fill: ${this.FIELD_BORDER_RECT_COLOUR};`,"}",`${a} .blocklyNonEditableText>text,`,`${a} .blocklyEditableText>text,`,`${a} .blocklyNonEditableText>g>text,`,`${a} .blocklyEditableText>g>text {`,"fill: #575E75;","}",`${a} .blocklyFlyoutLabelText {`,"fill: #575E75;","}",`${a} .blocklyText.blocklyBubbleText {`,"fill: #575E75;","}",`${a} .blocklyDraggable:not(.blocklyDisabled)`," .blocklyEditableText:not(.editing):hover>rect,",`${a} .blocklyDraggable:not(.blocklyDisabled)`," .blocklyEditableText:not(.editing):hover>.blocklyPath {", -"stroke: #fff;","stroke-width: 2;","}",`${a} .blocklyHtmlInput {`,`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,`font-weight: ${this.FIELD_TEXT_FONTWEIGHT};`,"color: #575E75;","}",`${a} .blocklyDropdownText {`,"fill: #fff !important;","}",`${a}.blocklyWidgetDiv .blocklyMenuItem,`,`${a}.blocklyDropDownDiv .blocklyMenuItem {`,`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,"}",`${a}.blocklyDropDownDiv .blocklyMenuItemContent {`,"color: #fff;","}",`${a} .blocklyHighlightedConnectionPath {`,`stroke: ${this.SELECTED_GLOW_COLOUR};`, -"}",`${a} .blocklyDisabled > .blocklyOutlinePath {`,`fill: url(#blocklyDisabledPattern${this.randomIdentifier})`,"}",`${a} .blocklyInsertionMarker>.blocklyPath {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;","}"]}},module$build$src$core$renderers$zelos$constants={};module$build$src$core$renderers$zelos$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$zelos$constants;var Drawer$$module$build$src$core$renderers$zelos$drawer=class extends Drawer$$module$build$src$core$renderers$common$drawer{constructor(a,b){super(a,b)}draw(){const a=this.block_.pathObject;a.beginDrawing();this.drawOutline_();this.drawInternals_();this.updateConnectionHighlights();a.setPath(this.outlinePath_+"\n"+this.inlinePath_);this.info_.RTL&&a.flipRTL();this.recordSizeOnBlock_();this.info_.outputConnection&&(a.outputShapeType=this.info_.outputConnection.shape.type);a.endDrawing()}drawOutline_(){this.info_.outputConnection&& -this.info_.outputConnection.isDynamicShape&&!this.info_.hasStatementInput&&!this.info_.bottomRow.hasNextConnection?(this.drawFlatTop_(),this.drawRightDynamicConnection_(),this.drawFlatBottom_(),this.drawLeftDynamicConnection_()):super.drawOutline_()}drawLeft_(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape?this.drawLeftDynamicConnection_():super.drawLeft_()}drawRightSideRow_(a){if(!(0>=a.height)){if(Types$$module$build$src$core$renderers$measurables$types.isSpacer(a)){const d= -a.precedesStatement;var b=a.followsStatement;if(d||b){const e=this.constants_.INSIDE_CORNERS;var c=e.rightHeight;c=a.height-(d?c:0);b=b?e.pathBottomRight:"";a=0b?b:f;e=e?-1:1;c=(d?-1:1)*c/2;return lineTo$$module$build$src$core$utils$svg_paths(-e*f,c)+lineTo$$module$build$src$core$utils$svg_paths(e*f,c)}const b=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;return{type:this.SHAPES.HEXAGONAL,isDynamic:!0,width(c){c/=2;return c> +b?b:c},height(c){return c},connectionOffsetY(c){return c/2},connectionOffsetX(c){return-c},pathDown(c){return a(c,!1,!1)},pathUp(c){return a(c,!0,!1)},pathRightDown(c){return a(c,!1,!0)},pathRightUp(c){return a(c,!1,!0)}}}makeRounded(){function a(d,e,f){const g=d>c?d-c:0;d=(d>c?c:d)/2;const h=f===e?"0":"1";return arc$$module$build$src$core$utils$svg_paths("a","0 0,"+h,d,point$$module$build$src$core$utils$svg_paths((f?1:-1)*d,(e?-1:1)*d))+lineOnAxis$$module$build$src$core$utils$svg_paths("v",(e?-1: +1)*g)+arc$$module$build$src$core$utils$svg_paths("a","0 0,"+h,d,point$$module$build$src$core$utils$svg_paths((f?-1:1)*d,(e?-1:1)*d))}const b=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,c=b*2;return{type:this.SHAPES.ROUND,isDynamic:!0,width(d){d/=2;return d>b?b:d},height(d){return d},connectionOffsetY(d){return d/2},connectionOffsetX(d){return-d},pathDown(d){return a(d,!1,!1)},pathUp(d){return a(d,!0,!1)},pathRightDown(d){return a(d,!1,!0)},pathRightUp(d){return a(d,!1,!0)}}}makeSquared(){function a(c, +d,e){c-=b*2;const f=e===d?"0":"1";return arc$$module$build$src$core$utils$svg_paths("a","0 0,"+f,b,point$$module$build$src$core$utils$svg_paths((e?1:-1)*b,(d?-1:1)*b))+lineOnAxis$$module$build$src$core$utils$svg_paths("v",(d?-1:1)*c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,"+f,b,point$$module$build$src$core$utils$svg_paths((e?-1:1)*b,(d?-1:1)*b))}const b=this.CORNER_RADIUS;return{type:this.SHAPES.SQUARE,isDynamic:!0,width(c){return b},height(c){return c},connectionOffsetY(c){return c/ +2},connectionOffsetX(c){return-c},pathDown(c){return a(c,!1,!1)},pathUp(c){return a(c,!0,!1)},pathRightDown(c){return a(c,!1,!0)},pathRightUp(c){return a(c,!1,!0)}}}shapeFor(a){let b=a.getCheck();!b&&a.targetConnection&&(b=a.targetConnection.getCheck());switch(a.type){case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:case ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE:a=a.getSourceBlock().getOutputShape();if(a!==null)switch(a){case this.SHAPES.HEXAGONAL:return this.HEXAGONAL; +case this.SHAPES.ROUND:return this.ROUNDED;case this.SHAPES.SQUARE:return this.SQUARED}if(b&&b.includes("Boolean"))return this.HEXAGONAL;if(b&&b.includes("Number"))return this.ROUNDED;b&&b.includes("String");return this.ROUNDED;case ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT:case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:return this.NOTCH;default:throw Error("Unknown type");}}makeNotch(){function a(l){return curve$$module$build$src$core$utils$svg_paths("c", +[point$$module$build$src$core$utils$svg_paths(l*e/2,0),point$$module$build$src$core$utils$svg_paths(l*e*3/4,g/2),point$$module$build$src$core$utils$svg_paths(l*e,g)])+line$$module$build$src$core$utils$svg_paths([point$$module$build$src$core$utils$svg_paths(l*e,f)])+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/4,g/2),point$$module$build$src$core$utils$svg_paths(l*e/2,g),point$$module$build$src$core$utils$svg_paths(l*e,g)])+lineOnAxis$$module$build$src$core$utils$svg_paths("h", +l*d)+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/2,0),point$$module$build$src$core$utils$svg_paths(l*e*3/4,-(g/2)),point$$module$build$src$core$utils$svg_paths(l*e,-g)])+line$$module$build$src$core$utils$svg_paths([point$$module$build$src$core$utils$svg_paths(l*e,-f)])+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/4,-(g/2)),point$$module$build$src$core$utils$svg_paths(l*e/2,-g),point$$module$build$src$core$utils$svg_paths(l* +e,-g)])}const b=this.NOTCH_WIDTH,c=this.NOTCH_HEIGHT,d=b/3,e=d/3,f=c/2,g=f/2,h=a(1),k=a(-1);return{type:this.SHAPES.NOTCH,width:b,height:c,pathLeft:h,pathRight:k}}makeInsideCorners(){const a=this.CORNER_RADIUS,b=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(-a,a)),c=arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a,point$$module$build$src$core$utils$svg_paths(-a,a)),d=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(a, +a)),e=arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a,point$$module$build$src$core$utils$svg_paths(a,a));return{width:a,height:a,pathTop:b,pathBottom:d,rightWidth:a,rightHeight:a,pathTopRight:c,pathBottomRight:e}}generateSecondaryColour_(a){return blend$$module$build$src$core$utils$colour("#000",a,.15)||a}generateTertiaryColour_(a){return blend$$module$build$src$core$utils$colour("#000",a,.25)||a}createDom(a,b,c,d){super.createDom(a,b,c,d);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.DEFS, +{},a);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER,{id:"blocklySelectedGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR,{"in":"SourceGraphic",stdDeviation:this.SELECTED_GLOW_SIZE},b);c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER,{result:"outBlur"},b); +createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},c);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":this.SELECTED_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in",result:"outGlow"},b); +this.selectedGlowFilterId=b.id;this.selectedGlowFilter=b;a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER,{id:"blocklyReplacementGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR,{"in":"SourceGraphic",stdDeviation:this.REPLACEMENT_GLOW_SIZE},a);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER, +{result:"outBlur"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":this.REPLACEMENT_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in", +result:"outGlow"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"SourceGraphic",in2:"outGlow",operator:"over"},a);this.replacementGlowFilterId=a.id;this.replacementGlowFilter=a;d&&(d.style.setProperty("--blocklySelectedGlowFilter",`url(#${this.selectedGlowFilterId})`),d.style.setProperty("--blocklyReplacementGlowFilter",`url(#${this.replacementGlowFilterId})`))}getCSS_(a){return[`${a} .blocklyText,`,`${a} .blocklyFlyoutLabelText {`,`font: ${this.FIELD_TEXT_FONTWEIGHT} ${this.FIELD_TEXT_FONTSIZE}pt ${this.FIELD_TEXT_FONTFAMILY};`, +"}",`${a} .blocklyTextInputBubble textarea {`,"font-weight: normal;","}",`${a} .blocklyText {`,"fill: #fff;","}",`${a} .blocklyNonEditableField>rect:not(.blocklyDropdownRect),`,`${a} .blocklyEditableField>rect:not(.blocklyDropdownRect) {`,`fill: ${this.FIELD_BORDER_RECT_COLOUR};`,"}",`${a} .blocklyNonEditableField>text,`,`${a} .blocklyEditableField>text,`,`${a} .blocklyNonEditableField>g>text,`,`${a} .blocklyEditableField>g>text {`,"fill: #575E75;","}",`${a} .blocklyFlyoutLabelText {`,"fill: #575E75;", +"}",`${a} .blocklyText.blocklyBubbleText {`,"fill: #575E75;","}",`${a} .blocklyDraggable:not(.blocklyDisabled)`," .blocklyEditableField:not(.blocklyEditing):hover>rect,",`${a} .blocklyDraggable:not(.blocklyDisabled)`," .blocklyEditableField:not(.blocklyEditing):hover>.blocklyPath {","stroke: #fff;","stroke-width: 2;","}",`${a} .blocklyHtmlInput {`,`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,`font-weight: ${this.FIELD_TEXT_FONTWEIGHT};`,"color: #575E75;","}",`${a} .blocklyDropdownText {`,"fill: #fff !important;", +"}",`${a}.blocklyWidgetDiv .blocklyMenuItem,`,`${a}.blocklyDropDownDiv .blocklyMenuItem {`,`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,"}",`${a}.blocklyDropDownDiv .blocklyMenuItemContent {`,"color: #fff;","}",`${a} .blocklyHighlightedConnectionPath {`,`stroke: ${this.SELECTED_GLOW_COLOUR};`,"}",`${a} .blocklyDisabledPattern > .blocklyOutlinePath {`,"fill: var(--blocklyDisabledPattern)","}",`${a} .blocklyInsertionMarker>.blocklyPath {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;", +"}",`${a} .blocklySelected>.blocklyPath.blocklyPathSelected {`,"fill: none;","filter: var(--blocklySelectedGlowFilter);","}",`${a} .blocklyReplaceable>.blocklyPath {`,"filter: var(--blocklyReplacementGlowFilter);","}"]}},module$build$src$core$renderers$zelos$constants={};module$build$src$core$renderers$zelos$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$zelos$constants;var Drawer$$module$build$src$core$renderers$zelos$drawer=class extends Drawer$$module$build$src$core$renderers$common$drawer{constructor(a,b){super(a,b)}draw(){const a=this.block_.pathObject;a.beginDrawing();this.drawOutline_();this.drawInternals_();this.updateConnectionHighlights();a.setPath(this.outlinePath_+"\n"+this.inlinePath_);this.info_.RTL&&a.flipRTL();this.recordSizeOnBlock_();this.info_.outputConnection&&(a.outputShapeType=this.info_.outputConnection.shape.type);a.endDrawing()}drawOutline_(){this.info_.outputConnection&& +this.info_.outputConnection.isDynamicShape&&!this.info_.hasStatementInput&&!this.info_.bottomRow.hasNextConnection?(this.drawFlatTop_(),this.drawRightDynamicConnection_(),this.drawFlatBottom_(),this.drawLeftDynamicConnection_()):super.drawOutline_()}drawLeft_(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape?this.drawLeftDynamicConnection_():super.drawLeft_()}drawRightSideRow_(a){if(!(a.height<=0)){if(Types$$module$build$src$core$renderers$measurables$types.isSpacer(a)){const d= +a.precedesStatement;var b=a.followsStatement;if(d||b){const e=this.constants_.INSIDE_CORNERS;var c=e.rightHeight;c=a.height-(d?c:0);b=b?e.pathBottomRight:"";a=c>0?lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.yPos+c):"";this.outlinePath_+=b+a+(d?e.pathTopRight:"");return}}this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.yPos+a.height)}}drawRightDynamicConnection_(){if(!this.info_.outputConnection)throw Error("Cannot draw the output connection of a block that doesn't have one"); this.outlinePath_+=this.info_.outputConnection.shape.pathRightDown(this.info_.outputConnection.height)}drawLeftDynamicConnection_(){if(!this.info_.outputConnection)throw Error("Cannot draw the output connection of a block that doesn't have one");this.positionOutputConnection_();this.outlinePath_+=this.info_.outputConnection.shape.pathUp(this.info_.outputConnection.height);this.outlinePath_+="z"}drawFlatTop_(){const a=this.info_.topRow;this.positionPreviousConnection_();this.outlinePath_+=moveBy$$module$build$src$core$utils$svg_paths(a.xPos, this.info_.startY);this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("h",a.width)}drawFlatBottom_(){const a=this.info_.bottomRow;this.positionNextConnection_();this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.baseline);this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("h",-a.width)}drawInlineInput_(a){this.positionInlineInputConnection_(a);const b=a.input.name;a.connectedBlock||this.info_.isInsertionMarker||(a=moveTo$$module$build$src$core$utils$svg_paths(a.xPos+ -a.connectionWidth,a.centerline-a.height/2)+this.getInlineInputPath(a),this.block_.pathObject.setOutlinePath(b,a))}getInlineInputPath(a){const b=a.width-2*a.connectionWidth,c=a.height;return lineOnAxis$$module$build$src$core$utils$svg_paths("h",b)+a.shape.pathRightDown(c)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",-b)+a.shape.pathUp(c)+"z"}drawStatementInput_(a){var b=a.getLastInput();const c=b.xPos+b.notchOffset+b.shape.width,d=this.constants_.INSIDE_CORNERS,e=b.shape.pathRight+lineOnAxis$$module$build$src$core$utils$svg_paths("h", +a.connectionWidth,a.centerline-a.height/2)+this.getInlineInputPath(a),this.block_.pathObject.setOutlinePath(b,a))}getInlineInputPath(a){const b=a.width-a.connectionWidth*2,c=a.height;return lineOnAxis$$module$build$src$core$utils$svg_paths("h",b)+a.shape.pathRightDown(c)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",-b)+a.shape.pathUp(c)+"z"}drawStatementInput_(a){var b=a.getLastInput();const c=b.xPos+b.notchOffset+b.shape.width,d=this.constants_.INSIDE_CORNERS,e=b.shape.pathRight+lineOnAxis$$module$build$src$core$utils$svg_paths("h", -(b.notchOffset-d.width))+d.pathTop,f=a.height-2*d.height;b=d.pathBottom+lineOnAxis$$module$build$src$core$utils$svg_paths("h",b.notchOffset-d.width)+(b.connectedBottomNextConnection?"":b.shape.pathLeft);this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",c)+e+lineOnAxis$$module$build$src$core$utils$svg_paths("v",f)+b+lineOnAxis$$module$build$src$core$utils$svg_paths("H",a.xPos+a.width);this.positionStatementInputConnection_(a)}drawConnectionHighlightPath(a){const b=a.connectionModel; -if(b.type===ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT||b.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT||b.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE&&!a.isDynamicShape)super.drawConnectionHighlightPath(a);else{a=b.type===ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE?moveTo$$module$build$src$core$utils$svg_paths(a.connectionWidth,-a.height/2)+this.getInlineInputPath(a):moveTo$$module$build$src$core$utils$svg_paths(a.width, --a.height/2)+a.shape.pathDown(a.height);var c=b.getSourceBlock(),d,e;null==(e=(d=c.pathObject).addConnectionHighlight)||e.call(d,b,a,b.getOffsetInBlock(),c.RTL)}}},module$build$src$core$renderers$zelos$drawer={};module$build$src$core$renderers$zelos$drawer.Drawer=Drawer$$module$build$src$core$renderers$zelos$drawer;var FieldImage$$module$build$src$core$field_image=class extends Field$$module$build$src$core$field{constructor(a,b,c,d,e,f,g){super(Field$$module$build$src$core$field.SKIP_SETUP);this.imageElement=this.clickHandler=null;this.flipRtl=this.isDirty_=this.EDITABLE=!1;this.altText="";c=Number(replaceMessageReferences$$module$build$src$core$utils$parsing(c));b=Number(replaceMessageReferences$$module$build$src$core$utils$parsing(b));if(isNaN(c)||isNaN(b))throw Error("Height and width values of an image field must cast to numbers."); -if(0>=c||0>=b)throw Error("Height and width values of an image field must be greater than 0.");this.size_=new Size$$module$build$src$core$utils$size(b,c+FieldImage$$module$build$src$core$field_image.Y_PADDING);this.imageHeight=c;"function"===typeof e&&(this.clickHandler=e);a!==Field$$module$build$src$core$field.SKIP_SETUP&&(g?this.configure_(g):(this.flipRtl=!!f,this.altText=replaceMessageReferences$$module$build$src$core$utils$parsing(d)||""),this.setValue(replaceMessageReferences$$module$build$src$core$utils$parsing(a)))}configure_(a){super.configure_(a); -a.flipRtl&&(this.flipRtl=a.flipRtl);a.alt&&(this.altText=replaceMessageReferences$$module$build$src$core$utils$parsing(a.alt))}initView(){this.imageElement=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{height:this.imageHeight+"px",width:this.size_.width+"px",alt:this.altText},this.fieldGroup_);this.imageElement.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.value_);this.clickHandler&&(this.imageElement.style.cursor="pointer")}updateSize_(){}doClassValidation_(a){return"string"!== -typeof a?null:a}doValueUpdate_(a){this.value_=a;this.imageElement&&this.imageElement.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.value_)}getFlipRtl(){return this.flipRtl}setAlt(a){a!==this.altText&&(this.altText=a||"",this.imageElement&&this.imageElement.setAttribute("alt",this.altText))}showEditor_(){this.clickHandler&&this.clickHandler(this)}setOnClickHandler(a){this.clickHandler=a}getText_(){return this.altText}static fromJson(a){if(!a.src||!a.width||!a.height)throw Error("src, width, and height values for an image field arerequired. The width and height must be non-zero."); -return new this(a.src,a.width,a.height,void 0,void 0,void 0,a)}};FieldImage$$module$build$src$core$field_image.Y_PADDING=1;register$$module$build$src$core$field_registry("field_image",FieldImage$$module$build$src$core$field_image);FieldImage$$module$build$src$core$field_image.prototype.DEFAULT_VALUE="";var module$build$src$core$field_image={};module$build$src$core$field_image.FieldImage=FieldImage$$module$build$src$core$field_image;var FieldInput$$module$build$src$core$field_input=class extends Field$$module$build$src$core$field{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.spellcheck_=!0;this.htmlInput_=null;this.isTextValid_=this.isBeingEdited_=!1;this.onKeyInputWrapper=this.onKeyDownWrapper=this.valueWhenEditorWasOpened_=null;this.fullBlockClickTarget_=!1;this.workspace_=null;this.SERIALIZABLE=!0;this.CURSOR="text";a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a), -b&&this.setValidator(b))}configure_(a){super.configure_(a);void 0!==a.spellcheck&&(this.spellcheck_=a.spellcheck)}initView(){if(!this.getSourceBlock())throw new UnattachedFieldError$$module$build$src$core$field;super.initView();this.isFullBlockField()&&(this.clickTarget_=this.sourceBlock_.getSvgRoot())}isFullBlockField(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;let b;return this.fullBlockClickTarget_=!(null==(b=this.getConstants())||!b.FULL_BLOCK_FIELDS)&& -a.isSimpleReporter()}doValueInvalid_(a,b=!0){this.isBeingEdited_&&(this.isDirty_=!0,this.isTextValid_=!1,a=this.value_,this.value_=this.valueWhenEditorWasOpened_,this.sourceBlock_&&isEnabled$$module$build$src$core$events$utils()&&this.value_!==a&&b&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock_,"field",this.name||null,a,this.value_)))}doValueUpdate_(a){this.isTextValid_=this.isDirty_= -!0;this.value_=a}applyColour(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;this.getConstants().FULL_BLOCK_FIELDS&&this.fieldGroup_&&(!this.isFullBlockField()&&this.borderRect_?(this.borderRect_.style.display="block",this.borderRect_.setAttribute("stroke",a.getColourTertiary())):(this.borderRect_.style.display="none",a.pathObject.svgPath.setAttribute("fill",this.getConstants().FIELD_BORDER_RECT_COLOUR)))}getSize(){let a;if(null==(a=this.getConstants())? -0:a.FULL_BLOCK_FIELDS)this.render_(),this.isDirty_=!1;return super.getSize()}onLocationChange(){this.isBeingEdited_&&this.resizeEditor_()}render_(){super.render_();if(this.isBeingEdited_){var a=this.htmlInput_;this.isTextValid_?(removeClass$$module$build$src$core$utils$dom(a,"blocklyInvalidInput"),setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.INVALID,!1)):(addClass$$module$build$src$core$utils$dom(a,"blocklyInvalidInput"),setState$$module$build$src$core$utils$aria(a, -State$$module$build$src$core$utils$aria.INVALID,!0))}a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;this.getConstants().FULL_BLOCK_FIELDS&&a.applyColour()}setSpellcheck(a){a!==this.spellcheck_&&(this.spellcheck_=a,this.htmlInput_&&this.htmlInput_.setAttribute("spellcheck",this.spellcheck_))}showEditor_(a,b=!1){this.workspace_=this.sourceBlock_.workspace;!b&&this.workspace_.options.modalInputs&&(MOBILE$$module$build$src$core$utils$useragent||ANDROID$$module$build$src$core$utils$useragent|| -IPAD$$module$build$src$core$utils$useragent)?this.showPromptEditor():this.showInlineEditor(b)}showPromptEditor(){prompt$$module$build$src$core$dialog($.Msg$$module$build$src$core$msg.CHANGE_VALUE_TITLE,this.getText(),a=>{null!==a&&this.setValue(this.getValueFromEditorText_(a));this.onFinishEditing_(this.value_)})}showInlineEditor(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;show$$module$build$src$core$widgetdiv(this,b.RTL,this.widgetDispose_.bind(this), -this.workspace_);this.htmlInput_=this.widgetCreate_();this.isBeingEdited_=!0;this.valueWhenEditorWasOpened_=this.value_;a||(this.htmlInput_.focus({preventScroll:!0}),this.htmlInput_.select())}widgetCreate_(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;$.setGroup$$module$build$src$core$events$utils(!0);const b=getDiv$$module$build$src$core$widgetdiv();var c=this.getClickTarget_();if(!c)throw Error("A click target has not been set.");addClass$$module$build$src$core$utils$dom(c, -"editing");c=document.createElement("input");c.className="blocklyHtmlInput";c.setAttribute("spellcheck",this.spellcheck_);const d=this.workspace_.getScale();var e=this.getConstants().FIELD_TEXT_FONTSIZE*d+"pt";b.style.fontSize=e;c.style.fontSize=e;e=FieldInput$$module$build$src$core$field_input.BORDERRADIUS*d+"px";this.isFullBlockField()&&(e=this.getScaledBBox(),e=(e.bottom-e.top)/2+"px",a=a.getParent()?a.getParent().getColourTertiary():this.sourceBlock_.getColourTertiary(),c.style.border=1*d+"px solid "+ -a,b.style.borderRadius=e,b.style.transition="box-shadow 0.25s ease 0s",this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW&&(b.style.boxShadow="rgba(255, 255, 255, 0.3) 0 0 0 "+4*d+"px"));c.style.borderRadius=e;b.appendChild(c);c.value=c.defaultValue=this.getEditorText_(this.value_);c.setAttribute("data-untyped-default-value",String(this.value_));this.resizeEditor_();this.bindInputEvents_(c);return c}widgetDispose_(){this.isBeingEdited_=!1;this.isTextValid_=!0;this.forceRerender();this.onFinishEditing_(this.value_); -this.sourceBlock_&&isEnabled$$module$build$src$core$events$utils()&&null!==this.valueWhenEditorWasOpened_&&this.valueWhenEditorWasOpened_!==this.value_&&(fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock_,"field",this.name||null,this.valueWhenEditorWasOpened_,this.value_)),this.valueWhenEditorWasOpened_=null);$.setGroup$$module$build$src$core$events$utils(!1);this.unbindInputEvents_(); -var a=getDiv$$module$build$src$core$widgetdiv().style;a.width="auto";a.height="auto";a.fontSize="";a.transition="";a.boxShadow="";this.htmlInput_=null;a=this.getClickTarget_();if(!a)throw Error("A click target has not been set.");removeClass$$module$build$src$core$utils$dom(a,"editing")}onFinishEditing_(a){}bindInputEvents_(a){this.onKeyDownWrapper=conditionalBind$$module$build$src$core$browser_events(a,"keydown",this,this.onHtmlInputKeyDown_);this.onKeyInputWrapper=conditionalBind$$module$build$src$core$browser_events(a, -"input",this,this.onHtmlInputChange)}unbindInputEvents_(){this.onKeyDownWrapper&&(unbind$$module$build$src$core$browser_events(this.onKeyDownWrapper),this.onKeyDownWrapper=null);this.onKeyInputWrapper&&(unbind$$module$build$src$core$browser_events(this.onKeyInputWrapper),this.onKeyInputWrapper=null)}onHtmlInputKeyDown_(a){"Enter"===a.key?(hideIfOwner$$module$build$src$core$widgetdiv(this),hideWithoutAnimation$$module$build$src$core$dropdowndiv()):"Escape"===a.key?(this.setValue(this.htmlInput_.getAttribute("data-untyped-default-value"), -!1),hideIfOwner$$module$build$src$core$widgetdiv(this),hideWithoutAnimation$$module$build$src$core$dropdowndiv()):"Tab"===a.key&&(hideIfOwner$$module$build$src$core$widgetdiv(this),hideWithoutAnimation$$module$build$src$core$dropdowndiv(),this.sourceBlock_.tab(this,!a.shiftKey),a.preventDefault())}onHtmlInputChange(a){a=this.value_;this.setValue(this.getValueFromEditorText_(this.htmlInput_.value),!1);this.sourceBlock_&&isEnabled$$module$build$src$core$events$utils()&&this.value_!==a&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_FIELD_INTERMEDIATE_CHANGE))(this.sourceBlock_, +if(b.type===ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT||b.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT||b.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE&&!a.isDynamicShape)return super.drawConnectionHighlightPath(a);a=b.type===ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE?moveTo$$module$build$src$core$utils$svg_paths(a.connectionWidth,-a.height/2)+this.getInlineInputPath(a):moveTo$$module$build$src$core$utils$svg_paths(a.width, +-a.height/2)+a.shape.pathDown(a.height);const c=b.getSourceBlock();let d,e;return(e=(d=c.pathObject).addConnectionHighlight)==null?void 0:e.call(d,b,a,b.getOffsetInBlock(),c.RTL)}},module$build$src$core$renderers$zelos$drawer={};module$build$src$core$renderers$zelos$drawer.Drawer=Drawer$$module$build$src$core$renderers$zelos$drawer;var FieldImage$$module$build$src$core$field_image=class extends Field$$module$build$src$core$field{constructor(a,b,c,d,e,f,g){super(Field$$module$build$src$core$field.SKIP_SETUP);this.imageElement=this.clickHandler=null;this.flipRtl=this.isDirty_=this.EDITABLE=!1;this.altText="";c=Number(replaceMessageReferences$$module$build$src$core$utils$parsing(c));b=Number(replaceMessageReferences$$module$build$src$core$utils$parsing(b));if(isNaN(c)||isNaN(b))throw Error("Height and width values of an image field must cast to numbers."); +if(c<=0||b<=0)throw Error("Height and width values of an image field must be greater than 0.");this.size_=new Size$$module$build$src$core$utils$size(b,c+FieldImage$$module$build$src$core$field_image.Y_PADDING);this.imageHeight=c;typeof e==="function"&&(this.clickHandler=e);a!==Field$$module$build$src$core$field.SKIP_SETUP&&(g?this.configure_(g):(this.flipRtl=!!f,this.altText=replaceMessageReferences$$module$build$src$core$utils$parsing(d)||""),this.setValue(replaceMessageReferences$$module$build$src$core$utils$parsing(a)))}configure_(a){super.configure_(a); +a.flipRtl&&(this.flipRtl=a.flipRtl);a.alt&&(this.altText=replaceMessageReferences$$module$build$src$core$utils$parsing(a.alt))}initView(){this.imageElement=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{height:this.imageHeight+"px",width:this.size_.width+"px",alt:this.altText},this.fieldGroup_);this.imageElement.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.value_);this.fieldGroup_&&addClass$$module$build$src$core$utils$dom(this.fieldGroup_, +"blocklyImageField");this.clickHandler&&(this.imageElement.style.cursor="pointer")}updateSize_(){}doClassValidation_(a){return typeof a!=="string"?null:a}doValueUpdate_(a){this.value_=a;this.imageElement&&this.imageElement.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.value_)}getFlipRtl(){return this.flipRtl}setAlt(a){a!==this.altText&&(this.altText=a||"",this.imageElement&&this.imageElement.setAttribute("alt",this.altText))}isClickable(){return super.isClickable()&&!!this.clickHandler}showEditor_(){this.clickHandler&& +this.clickHandler(this)}setOnClickHandler(a){this.clickHandler=a}getText_(){return this.altText}static fromJson(a){if(!a.src||!a.width||!a.height)throw Error("src, width, and height values for an image field arerequired. The width and height must be non-zero.");return new this(a.src,a.width,a.height,void 0,void 0,void 0,a)}};FieldImage$$module$build$src$core$field_image.Y_PADDING=1;register$$module$build$src$core$field_registry("field_image",FieldImage$$module$build$src$core$field_image); +FieldImage$$module$build$src$core$field_image.prototype.DEFAULT_VALUE="";var module$build$src$core$field_image={};module$build$src$core$field_image.FieldImage=FieldImage$$module$build$src$core$field_image;var MINIMUM_WIDTH$$module$build$src$core$field_input=14,FieldInput$$module$build$src$core$field_input=class extends Field$$module$build$src$core$field{set size_(a){super.size_=a}get size_(){const a=super.size_;a.width{a!==null&&this.setValue(this.getValueFromEditorText_(a));this.onFinishEditing_(this.value_)})}showInlineEditor(a,b){const c=this.getSourceBlock();if(!c)throw new UnattachedFieldError$$module$build$src$core$field;show$$module$build$src$core$widgetdiv(this,c.RTL,this.widgetDispose_.bind(this),this.workspace_,b);this.htmlInput_=this.widgetCreate_();this.isBeingEdited_=!0;this.valueWhenEditorWasOpened_=this.value_;a||(this.htmlInput_.focus({preventScroll:!0}),this.htmlInput_.select())}widgetCreate_(){var a= +this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;$.setGroup$$module$build$src$core$events$utils(!0);const b=getDiv$$module$build$src$core$widgetdiv();var c=this.getClickTarget_();if(!c)throw Error("A click target has not been set.");addClass$$module$build$src$core$utils$dom(c,"blocklyEditing");c=document.createElement("input");c.className="blocklyHtmlInput";c.setAttribute("spellcheck",this.spellcheck_);const d=this.workspace_.getAbsoluteScale();var e=this.getConstants().FIELD_TEXT_FONTSIZE* +d+"pt";b.style.fontSize=e;c.style.fontSize=e;e=FieldInput$$module$build$src$core$field_input.BORDERRADIUS*d+"px";this.isFullBlockField()&&(e=this.getScaledBBox(),e=(e.bottom-e.top)/2+"px",a=a.getParent()?a.getParent().getColourTertiary():this.sourceBlock_.getColourTertiary(),c.style.border=1*d+"px solid "+a,b.style.borderRadius=e,b.style.transition="box-shadow 0.25s ease 0s",this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW&&(b.style.boxShadow="rgba(255, 255, 255, 0.3) 0 0 0 "+4*d+"px"));c.style.borderRadius= +e;b.appendChild(c);c.value=c.defaultValue=this.getEditorText_(this.value_);c.setAttribute("data-untyped-default-value",String(this.value_));this.resizeEditor_();this.bindInputEvents_(c);return c}widgetDispose_(){this.isBeingEdited_=!1;this.isTextValid_=!0;this.forceRerender();this.onFinishEditing_(this.value_);this.sourceBlock_&&isEnabled$$module$build$src$core$events$utils()&&this.valueWhenEditorWasOpened_!==null&&this.valueWhenEditorWasOpened_!==this.value_&&(fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_CHANGE))(this.sourceBlock_, +"field",this.name||null,this.valueWhenEditorWasOpened_,this.value_)),this.valueWhenEditorWasOpened_=null);$.setGroup$$module$build$src$core$events$utils(!1);this.unbindInputEvents_();var a=getDiv$$module$build$src$core$widgetdiv().style;a.width="auto";a.height="auto";a.fontSize="";a.transition="";a.boxShadow="";this.htmlInput_=null;a=this.getClickTarget_();if(!a)throw Error("A click target has not been set.");removeClass$$module$build$src$core$utils$dom(a,"blocklyEditing")}onFinishEditing_(a){}bindInputEvents_(a){this.onKeyDownWrapper= +conditionalBind$$module$build$src$core$browser_events(a,"keydown",this,this.onHtmlInputKeyDown_);this.onInputWrapper=conditionalBind$$module$build$src$core$browser_events(a,"input",this,this.onHtmlInputChange)}unbindInputEvents_(){this.onKeyDownWrapper&&(unbind$$module$build$src$core$browser_events(this.onKeyDownWrapper),this.onKeyDownWrapper=null);this.onInputWrapper&&(unbind$$module$build$src$core$browser_events(this.onInputWrapper),this.onInputWrapper=null)}onHtmlInputKeyDown_(a){if(a.key==="Enter")hideIfOwner$$module$build$src$core$widgetdiv(this), +hideWithoutAnimation$$module$build$src$core$dropdowndiv();else if(a.key==="Escape")this.setValue(this.htmlInput_.getAttribute("data-untyped-default-value"),!1),hideIfOwner$$module$build$src$core$widgetdiv(this),hideWithoutAnimation$$module$build$src$core$dropdowndiv();else if(a.key==="Tab"){a.preventDefault();var b,c=(b=this.workspace_)==null?void 0:b.getCursor();b=d=>(d instanceof FieldInput$$module$build$src$core$field_input||d instanceof BlockSvg$$module$build$src$core$block_svg&&d.isSimpleReporter())&& +d!==this.getSourceBlock();a=a.shiftKey?c==null?void 0:c.getPreviousNode(this,b,!1):c==null?void 0:c.getNextNode(this,b,!1);a=a instanceof BlockSvg$$module$build$src$core$block_svg&&a.isSimpleReporter()?a.getFields().next().value:a;a instanceof FieldInput$$module$build$src$core$field_input&&(hideIfOwner$$module$build$src$core$widgetdiv(this),hideWithoutAnimation$$module$build$src$core$dropdowndiv(),c=a.getSourceBlock(),a.isFullBlockField()&&c&&c instanceof BlockSvg$$module$build$src$core$block_svg? +$.getFocusManager$$module$build$src$core$focus_manager().focusNode(c):$.getFocusManager$$module$build$src$core$focus_manager().focusNode(a),a.showEditor())}}onHtmlInputChange(a){a=this.value_;this.setValue(this.getValueFromEditorText_(this.htmlInput_.value),!1);this.sourceBlock_&&isEnabled$$module$build$src$core$events$utils()&&this.value_!==a&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.BLOCK_FIELD_INTERMEDIATE_CHANGE))(this.sourceBlock_, this.name||null,a,this.value_))}setEditorValue_(a,b=!0){this.isDirty_=!0;this.isBeingEdited_&&(this.htmlInput_.value=this.getEditorText_(a));this.setValue(a,b)}resizeEditor_(){finishQueuedRenders$$module$build$src$core$render_management().then(()=>{const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;const b=getDiv$$module$build$src$core$widgetdiv(),c=this.getScaledBBox();b.style.width=c.right-c.left+"px";b.style.height=c.bottom-c.top+"px";const d=c.top; -b.style.left=`${a.RTL?c.right-b.offsetWidth:c.left}px`;b.style.top=`${d}px`})}repositionForWindowResize(){let a;const b=null==(a=this.getSourceBlock())?void 0:a.getRootBlock();if(!(b instanceof BlockSvg$$module$build$src$core$block_svg))return!1;bumpObjectIntoBounds$$module$build$src$core$bump_objects(this.workspace_,this.workspace_.getMetricsManager().getViewMetrics(!0),b)||this.resizeEditor_();return!0}isTabNavigable(){return!0}getText_(){return this.isBeingEdited_&&this.htmlInput_?this.htmlInput_.value: -null}getEditorText_(a){return`${a}`}getValueFromEditorText_(a){return a}};FieldInput$$module$build$src$core$field_input.BORDERRADIUS=4;var module$build$src$core$field_input={};module$build$src$core$field_input.FieldInput=FieldInput$$module$build$src$core$field_input;var FieldTextInput$$module$build$src$core$field_textinput=class extends FieldInput$$module$build$src$core$field_input{constructor(a,b,c){super(a,b,c)}doClassValidation_(a){return void 0===a?null:`${a}`}static fromJson(a){return new this(replaceMessageReferences$$module$build$src$core$utils$parsing(a.text),void 0,a)}};register$$module$build$src$core$field_registry("field_input",FieldTextInput$$module$build$src$core$field_textinput); -FieldTextInput$$module$build$src$core$field_textinput.prototype.DEFAULT_VALUE="";var module$build$src$core$field_textinput={};module$build$src$core$field_textinput.FieldTextInput=FieldTextInput$$module$build$src$core$field_textinput;var BottomRow$$module$build$src$core$renderers$zelos$measurables$bottom_row=class extends BottomRow$$module$build$src$core$renderers$measurables$bottom_row{constructor(a){super(a)}endsWithElemSpacer(){return!1}hasLeftSquareCorner(a){return!!a.outputConnection}hasRightSquareCorner(a){return!!a.outputConnection&&!a.statementInputCount&&!a.nextConnection}},module$build$src$core$renderers$zelos$measurables$bottom_row={};module$build$src$core$renderers$zelos$measurables$bottom_row.BottomRow=BottomRow$$module$build$src$core$renderers$zelos$measurables$bottom_row;var StatementInput$$module$build$src$core$renderers$zelos$measurables$inputs=class extends StatementInput$$module$build$src$core$renderers$measurables$statement_input{constructor(a,b){super(a,b);this.connectedBottomNextConnection=!1;if(this.connectedBlock){for(a=this.connectedBlock;b=a.getNextBlock();)a=b;a.nextConnection||(this.height=this.connectedBlockHeight,this.connectedBottomNextConnection=!0)}}},module$build$src$core$renderers$zelos$measurables$inputs={}; -module$build$src$core$renderers$zelos$measurables$inputs.StatementInput=StatementInput$$module$build$src$core$renderers$zelos$measurables$inputs;var RightConnectionShape$$module$build$src$core$renderers$zelos$measurables$row_elements=class extends Measurable$$module$build$src$core$renderers$measurables$base{constructor(a){super(a);this.width=this.height=0;this.type|=Types$$module$build$src$core$renderers$measurables$types.getType("RIGHT_CONNECTION")}},module$build$src$core$renderers$zelos$measurables$row_elements={};module$build$src$core$renderers$zelos$measurables$row_elements.RightConnectionShape=RightConnectionShape$$module$build$src$core$renderers$zelos$measurables$row_elements;var TopRow$$module$build$src$core$renderers$zelos$measurables$top_row=class extends TopRow$$module$build$src$core$renderers$measurables$top_row{constructor(a){super(a)}endsWithElemSpacer(){return!1}hasLeftSquareCorner(a){const b=(a.hat?"cap"===a.hat:this.constants_.ADD_START_HATS)&&!a.outputConnection&&!a.previousConnection;return!!a.outputConnection||b}hasRightSquareCorner(a){return!!a.outputConnection&&!a.statementInputCount&&!a.nextConnection}},module$build$src$core$renderers$zelos$measurables$top_row= +b.style.left=`${a.RTL?c.right-b.offsetWidth:c.left}px`;b.style.top=`${d}px`})}repositionForWindowResize(){let a;const b=(a=this.getSourceBlock())==null?void 0:a.getRootBlock();if(!(b instanceof BlockSvg$$module$build$src$core$block_svg))return!1;bumpObjectIntoBounds$$module$build$src$core$bump_objects(this.workspace_,this.workspace_.getMetricsManager().getViewMetrics(!0),b)||this.resizeEditor_();return!0}positionTextElement_(a,b){const c=a*2+b;super.positionTextElement_(a+(c0;this.rightSide=this.outputConnection?new RightConnectionShape$$module$build$src$core$renderers$zelos$measurables$row_elements(this.constants_):null;this.rightAlignedDummyInputs=new WeakMap}getRenderer(){return this.renderer_}measure(){this.createRows_();this.addElemSpacing_();this.addRowSpacing_();this.adjustXPosition_();this.computeBounds_();this.alignRowElements_();this.finalize_()}shouldStartNewRow_(a,b){return b?b instanceof EndRowInput$$module$build$src$core$inputs$end_row_input|| a instanceof StatementInput$$module$build$src$core$inputs$statement_input||b instanceof StatementInput$$module$build$src$core$inputs$statement_input?!0:a instanceof $.ValueInput$$module$build$src$core$inputs$value_input||a instanceof DummyInput$$module$build$src$core$inputs$dummy_input||a instanceof EndRowInput$$module$build$src$core$inputs$end_row_input?!this.isInline||this.isMultiRow:!1:!1}getDesiredRowWidth_(a){return a.hasStatement?this.width-this.startX-(this.constants_.INSIDE_CORNERS.rightWidth|| 0):super.getDesiredRowWidth_(a)}getInRowSpacing_(a,b){return a&&b||!this.outputConnection||!this.outputConnection.isDynamicShape||this.hasStatementInput||this.bottomRow.hasNextConnection?!a&&b&&Types$$module$build$src$core$renderers$measurables$types.isStatementInput(b)?this.constants_.STATEMENT_INPUT_PADDING_LEFT:a&&Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(a)&&b&&(Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(b)||Types$$module$build$src$core$renderers$measurables$types.isNextConnection(b))? -b.notchOffset-this.constants_.CORNER_RADIUS:a&&Types$$module$build$src$core$renderers$measurables$types.isLeftSquareCorner(a)&&b&&Types$$module$build$src$core$renderers$measurables$types.isHat(b)?this.constants_.NO_PADDING:this.constants_.MEDIUM_PADDING:this.constants_.NO_PADDING}getSpacerRowHeight_(a,b){if(Types$$module$build$src$core$renderers$measurables$types.isTopRow(a)&&Types$$module$build$src$core$renderers$measurables$types.isBottomRow(b))return this.constants_.EMPTY_BLOCK_SPACER_HEIGHT;const c= -Types$$module$build$src$core$renderers$measurables$types.isInputRow(a)&&a.hasStatement,d=Types$$module$build$src$core$renderers$measurables$types.isInputRow(b)&&b.hasStatement;return d||c?(a=Math.max(this.constants_.NOTCH_HEIGHT,this.constants_.INSIDE_CORNERS.rightHeight||0),d&&c?Math.max(a,this.constants_.DUMMY_INPUT_MIN_HEIGHT):a):Types$$module$build$src$core$renderers$measurables$types.isTopRow(a)?a.hasPreviousConnection||this.outputConnection&&!this.hasStatementInput?this.constants_.NO_PADDING: +b.notchOffset-this.constants_.CORNER_RADIUS:a&&Types$$module$build$src$core$renderers$measurables$types.isLeftSquareCorner(a)&&b&&Types$$module$build$src$core$renderers$measurables$types.isHat(b)||a&&Types$$module$build$src$core$renderers$measurables$types.isField(a)&&a.width===0?this.constants_.NO_PADDING:this.constants_.MEDIUM_PADDING:this.constants_.NO_PADDING}getSpacerRowHeight_(a,b){if(Types$$module$build$src$core$renderers$measurables$types.isTopRow(a)&&Types$$module$build$src$core$renderers$measurables$types.isBottomRow(b))return this.constants_.EMPTY_BLOCK_SPACER_HEIGHT; +const c=Types$$module$build$src$core$renderers$measurables$types.isInputRow(a)&&a.hasStatement,d=Types$$module$build$src$core$renderers$measurables$types.isInputRow(b)&&b.hasStatement;return d||c?(a=Math.max(this.constants_.NOTCH_HEIGHT,this.constants_.INSIDE_CORNERS.rightHeight||0),d&&c?Math.max(a,this.constants_.DUMMY_INPUT_MIN_HEIGHT):a):Types$$module$build$src$core$renderers$measurables$types.isTopRow(a)?a.hasPreviousConnection||this.outputConnection&&!this.hasStatementInput?this.constants_.NO_PADDING: Math.abs(this.constants_.NOTCH_HEIGHT-this.constants_.CORNER_RADIUS):Types$$module$build$src$core$renderers$measurables$types.isBottomRow(b)?this.outputConnection?!b.hasNextConnection&&this.hasStatementInput?Math.abs(this.constants_.NOTCH_HEIGHT-this.constants_.CORNER_RADIUS):this.constants_.NO_PADDING:Math.max(this.topRow.minHeight,Math.max(this.constants_.NOTCH_HEIGHT,this.constants_.CORNER_RADIUS))-this.constants_.CORNER_RADIUS:this.constants_.MEDIUM_PADDING}getSpacerRowWidth_(a,b){const c=this.width- this.startX;return Types$$module$build$src$core$renderers$measurables$types.isInputRow(a)&&a.hasStatement||Types$$module$build$src$core$renderers$measurables$types.isInputRow(b)&&b.hasStatement?Math.max(c,this.constants_.STATEMENT_INPUT_SPACER_MIN_WIDTH):c}getElemCenterline_(a,b){if(a.hasStatement&&!Types$$module$build$src$core$renderers$measurables$types.isSpacer(b)&&!Types$$module$build$src$core$renderers$measurables$types.isStatementInput(b))return a.yPos+this.constants_.EMPTY_STATEMENT_INPUT_HEIGHT/ -2;if(Types$$module$build$src$core$renderers$measurables$types.isInlineInput(b)&&b instanceof InputConnection$$module$build$src$core$renderers$measurables$input_connection){const c=b.connectedBlock;if(c&&c.outputConnection&&c.nextConnection)return a.yPos+c.height/2}return super.getElemCenterline_(a,b)}addInput_(a,b){if((a instanceof DummyInput$$module$build$src$core$inputs$dummy_input||a instanceof EndRowInput$$module$build$src$core$inputs$end_row_input)&&b.hasDummyInput&&b.align===$.Align$$module$build$src$core$inputs$align.LEFT&& -a.align===$.Align$$module$build$src$core$inputs$align.RIGHT)this.rightAlignedDummyInputs.set(b,a);else if(a instanceof StatementInput$$module$build$src$core$inputs$statement_input){b.elements.push(new StatementInput$$module$build$src$core$renderers$zelos$measurables$inputs(this.constants_,a));b.hasStatement=!0;null===b.align&&(b.align=a.align);return}super.addInput_(a,b)}addAlignmentPadding_(a,b){if(this.rightAlignedDummyInputs.get(a)){let c;for(let d=0;d=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!d.precedesStatement;if(Types$$module$build$src$core$renderers$measurables$types.isInputRow(f)&&f.hasStatement){f.measure();let g,h;b=f.width-(null!=(h=null==(g=f.getLastInput())?void 0:g.width)?h:0)+a}else if(c&&(2===e||d)&&Types$$module$build$src$core$renderers$measurables$types.isInputRow(f)&&!f.hasStatement){d=f.xPos;c=null;for(let g= -0;gc?c:this.height/2,b-c*(1-Math.sin(Math.acos((c-this.constants_.SMALL_PADDING)/c)));default:return 0}if(Types$$module$build$src$core$renderers$measurables$types.isInlineInput(a)&&a instanceof InputConnection$$module$build$src$core$renderers$measurables$input_connection){const e=a.connectedBlock;a=e?e.pathObject.outputShapeType:a.shape.type;return null==a||e&&e.outputConnection&&(e.statementInputCount||e.nextConnection)||c===d.SHAPES.HEXAGONAL&&c!==a?0:b-this.constants_.SHAPE_IN_SHAPE_PADDING[c][a]}return Types$$module$build$src$core$renderers$measurables$types.isField(a)&& -a instanceof Field$$module$build$src$core$renderers$measurables$field?c===d.SHAPES.ROUND&&a.field instanceof FieldTextInput$$module$build$src$core$field_textinput?b-2.75*d.GRID_UNIT:b-this.constants_.SHAPE_IN_SHAPE_PADDING[c][0]:Types$$module$build$src$core$renderers$measurables$types.isIcon(a)?this.constants_.SMALL_PADDING:0}finalizeVerticalAlignment_(){if(!this.outputConnection)for(let d=2;d=this.rows.length- -1?!!this.bottomRow.hasNextConnection:!!g.precedesStatement;if(a?this.topRow.hasPreviousConnection:e.followsStatement){var c=f.elements[1];c=3===f.elements.length&&c instanceof Field$$module$build$src$core$renderers$measurables$field&&(c.field instanceof FieldLabel$$module$build$src$core$field_label||c.field instanceof FieldImage$$module$build$src$core$field_image);if(!a&&c)e.height-=this.constants_.SMALL_PADDING,g.height-=this.constants_.SMALL_PADDING,f.height-=this.constants_.MEDIUM_PADDING;else if(!a&& -!b)e.height+=this.constants_.SMALL_PADDING;else if(b){a=!1;for(b=0;b=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!d.precedesStatement;if(Types$$module$build$src$core$renderers$measurables$types.isInputRow(f)&& +f.hasStatement){f.measure();let g,h;b=f.width-((h=(g=f.getLastInput())==null?void 0:g.width)!=null?h:0)+a}else if(c&&(e===2||d)&&Types$$module$build$src$core$renderers$measurables$types.isInputRow(f)&&!f.hasStatement){d=f.xPos;c=null;for(let g=0;g1)switch(c){case d.SHAPES.ROUND:return c=this.constants_.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,c=this.height/2>c?c:this.height/2,b-c*(1-Math.sin(Math.acos((c-this.constants_.SMALL_PADDING)/c)));default:return 0}if(Types$$module$build$src$core$renderers$measurables$types.isInlineInput(a)){const e=a.connectedBlock;a= +e?e.pathObject.outputShapeType:a.shape.type;return a==null||e&&e.outputConnection&&(e.statementInputCount||e.nextConnection)||c===d.SHAPES.HEXAGONAL&&c!==a?0:b-this.constants_.SHAPE_IN_SHAPE_PADDING[c][a]}return Types$$module$build$src$core$renderers$measurables$types.isField(a)?c===d.SHAPES.ROUND&&a.field instanceof $.FieldTextInput$$module$build$src$core$field_textinput?b-2.75*d.GRID_UNIT:b-this.constants_.SHAPE_IN_SHAPE_PADDING[c][0]:Types$$module$build$src$core$renderers$measurables$types.isIcon(a)? +this.constants_.SMALL_PADDING:0}finalizeVerticalAlignment_(){if(!this.outputConnection)for(let d=2;d=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!g.precedesStatement;if(a?this.topRow.hasPreviousConnection:e.followsStatement){var c=f.elements[1];c=f.elements.length===3&&c instanceof Field$$module$build$src$core$renderers$measurables$field&&(c.field instanceof FieldLabel$$module$build$src$core$field_label|| +c.field instanceof FieldImage$$module$build$src$core$field_image);if(!a&&c)e.height-=this.constants_.SMALL_PADDING,g.height-=this.constants_.SMALL_PADDING,f.height-=this.constants_.MEDIUM_PADDING;else if(!a&&!b)e.height+=this.constants_.SMALL_PADDING;else if(b){a=!1;for(b=0;b=40){a=!0;break}a&& +(e.height-=this.constants_.SMALL_PADDING,g.height-=this.constants_.SMALL_PADDING)}}}}finalize_(){this.finalizeOutputConnection_();this.finalizeHorizontalAlignment_();this.finalizeVerticalAlignment_();super.finalize_();this.rightSide&&(this.widthWithChildren+=this.rightSide.width)}},module$build$src$core$renderers$zelos$info={};module$build$src$core$renderers$zelos$info.RenderInfo=RenderInfo$$module$build$src$core$renderers$zelos$info;var PathObject$$module$build$src$core$renderers$zelos$path_object=class extends PathObject$$module$build$src$core$renderers$common$path_object{constructor(a,b,c){super(a,b,c);this.svgPathSelected=null;this.outlines=new Map;this.remainingOutlines=new Set;this.outputShapeType=null;this.constants=c}setPath(a){super.setPath(a);this.svgPathSelected&&this.svgPathSelected.setAttribute("d",a)}applyColour(a){super.applyColour(a);const b=a.getParent();a.isShadow()&&b&&this.svgPath.setAttribute("stroke",b.getColourTertiary()); +for(const c of this.outlines.values())c.setAttribute("fill",this.style.colourTertiary)}flipRTL(){super.flipRTL();for(const a of this.outlines.values())a.setAttribute("transform","scale(-1 1)")}updateSelected(a){this.setClass_("blocklySelected",a);a?this.svgPathSelected||(this.svgPathSelected=this.svgPath.cloneNode(!0),this.svgPathSelected.classList.add("blocklyPathSelected"),removeClass$$module$build$src$core$utils$dom(this.svgPathSelected,FocusManager$$module$build$src$core$focus_manager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME), +removeClass$$module$build$src$core$utils$dom(this.svgPathSelected,FocusManager$$module$build$src$core$focus_manager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME),this.svgPathSelected.removeAttribute("tabindex"),this.svgPathSelected.removeAttribute("id"),this.svgRoot.appendChild(this.svgPathSelected)):this.svgPathSelected&&(this.svgRoot.removeChild(this.svgPathSelected),this.svgPathSelected=null)}updateReplacementFade(a){this.setClass_("blocklyReplaceable",a)}updateShapeForInputHighlight(a,b){a=a.getParentInput().name; +(a=this.getOutlinePath(a))&&(b?a.setAttribute("filter","url(#"+this.constants.replacementGlowFilterId+")"):a.removeAttribute("filter"))}beginDrawing(){this.remainingOutlines.clear();for(const a of this.outlines.keys())this.remainingOutlines.add(a)}endDrawing(){if(this.remainingOutlines.size)for(const a of this.remainingOutlines)this.removeOutlinePath(a);this.remainingOutlines.clear()}setOutlinePath(a,b){a=this.getOutlinePath(a);a.setAttribute("d",b);a.setAttribute("fill",this.style.colourTertiary)}getOutlinePath(a){this.outlines.has(a)|| +this.outlines.set(a,createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyOutlinePath",d:""},this.svgRoot));this.remainingOutlines.delete(a);return this.outlines.get(a)}removeOutlinePath(a){let b,c;(b=this.outlines.get(a))==null||(c=b.parentNode)==null||c.removeChild(this.outlines.get(a));this.outlines.delete(a)}},module$build$src$core$renderers$zelos$path_object={};module$build$src$core$renderers$zelos$path_object.PathObject=PathObject$$module$build$src$core$renderers$zelos$path_object;var Renderer$$module$build$src$core$renderers$zelos$renderer=class extends Renderer$$module$build$src$core$renderers$common$renderer{constructor(a){super(a)}makeConstants_(){return new ConstantProvider$$module$build$src$core$renderers$zelos$constants}makeRenderInfo_(a){return new RenderInfo$$module$build$src$core$renderers$zelos$info(this,a)}makeDrawer_(a,b){return new Drawer$$module$build$src$core$renderers$zelos$drawer(a,b)}makePathObject(a,b){return new PathObject$$module$build$src$core$renderers$zelos$path_object(a, +b,this.getConstants())}getConstants(){return this.constants_}};register$$module$build$src$core$renderers$common$block_rendering("zelos",Renderer$$module$build$src$core$renderers$zelos$renderer);var module$build$src$core$renderers$zelos$renderer={};module$build$src$core$renderers$zelos$renderer.Renderer=Renderer$$module$build$src$core$renderers$zelos$renderer;var InsertionMarkerPreviewer$$module$build$src$core$insertion_marker_previewer=class{constructor(a){this.staticConn=this.draggedConn=this.markerConn=this.fadedBlock=null;this.workspace=a.workspace}previewReplacement(a,b,c){$.disable$$module$build$src$core$events$utils();try{this.hidePreview(),this.fadedBlock=c,c.fadeForReplacement(!0),this.workspace.getRenderer().shouldHighlightConnection(b)&&(b.highlight(),this.staticConn=b)}finally{$.enable$$module$build$src$core$events$utils()}}previewConnection(a, b){if(a!==this.draggedConn||b!==this.staticConn){$.disable$$module$build$src$core$events$utils();try{this.hidePreview(),this.shouldUseMarkerPreview(a,b)&&(this.markerConn=this.previewMarker(a,b)),this.workspace.getRenderer().shouldHighlightConnection(b)&&b.highlight(),this.draggedConn=a,this.staticConn=b}finally{$.enable$$module$build$src$core$events$utils()}}}shouldUseMarkerPreview(a,b){return b.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT||b.type===ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT|| !(this.workspace.getRenderer()instanceof Renderer$$module$build$src$core$renderers$zelos$renderer)}previewMarker(a,b){const c=a.getSourceBlock(),d=this.createInsertionMarker(c),e=this.getMatchingConnection(c,d,a);if(!e)return null;d.queueRender();triggerQueuedRenders$$module$build$src$core$render_management();e.connect(b);const f={x:b.x-e.x,y:b.y-e.y},g=e.getOffsetInBlock().clone();finishQueuedRenders$$module$build$src$core$render_management().then(()=>{if(!d.isDeadOrDying()){$.disable$$module$build$src$core$events$utils(); -try{null==d||d.positionNearConnection(e,f,g),null==d||d.getSvgRoot().setAttribute("visibility","visible")}finally{$.enable$$module$build$src$core$events$utils()}}});return e}createInsertionMarker(a){const b=save$$module$build$src$core$serialization$blocks(a,{addCoordinates:!1,addInputBlocks:!1,addNextBlocks:!1,doFullSerialization:!1});if(!b)throw Error(`Failed to serialize source block. ${a.toDevString()}`);a=append$$module$build$src$core$serialization$blocks(b,this.workspace);for(const c of a.getDescendants(!1))c.setInsertionMarker(!0); -a.initSvg();a.getSvgRoot().setAttribute("visibility","hidden");return a}getMatchingConnection(a,b,c){a=a.getConnections_(!0);b=b.getConnections_(!0);if(a.length!==b.length)return null;for(let d=0;d{this.targetWorkspace.isDragging()||b.addSelect()}));this.listeners.push(bind$$module$build$src$core$browser_events(a, -"pointerleave",b,()=>{this.targetWorkspace.isDragging()||b.removeSelect()}));this.listeners.push(bind$$module$build$src$core$browser_events(c,"pointerenter",b,()=>{this.targetWorkspace.isDragging()||b.addSelect()}));this.listeners.push(bind$$module$build$src$core$browser_events(c,"pointerleave",b,()=>{this.targetWorkspace.isDragging()||b.removeSelect()}))}blockMouseDown(a){return b=>{const c=this.targetWorkspace.getGesture(b);c&&(c.setStartBlock(a),c.handleFlyoutStart(b,this))}}onMouseDown(a){const b= -this.targetWorkspace.getGesture(a);b&&b.handleFlyoutStart(a,this)}isBlockCreatable(a){return a.isEnabled()}createBlock(a){let b=null;$.disable$$module$build$src$core$events$utils();var c=this.targetWorkspace.getAllVariables();this.targetWorkspace.setResizesEnabled(!1);try{b=this.placeNewBlock(a)}finally{$.enable$$module$build$src$core$events$utils()}this.targetWorkspace.hideChaff();a=getAddedVariables$$module$build$src$core$variables(this.targetWorkspace,c);if(isEnabled$$module$build$src$core$events$utils()){$.setGroup$$module$build$src$core$events$utils(!0); -for(c=0;c-b||a<-180+b||a>180-b?!0:!1}getClientRect(){if(!this.svgGroup_||this.autoClose||!this.isVisible())return null;const a= -this.svgGroup_.getBoundingClientRect(),b=a.left;return this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.LEFT?new Rect$$module$build$src$core$utils$rect(-1E9,1E9,-1E9,b+a.width):new Rect$$module$build$src$core$utils$rect(-1E9,1E9,b,1E9)}reflowInternal_(){this.workspace_.scale=this.getFlyoutScale();let a=0;var b=this.workspace_.getTopBlocks(!1);for(let d=0,e;e=b[d];d++){var c=e.getHeightWidth().width;e.outputConnection&&(c-=this.tabWidth_);a=Math.max(a,c)}for(let d=0,e;e=this.buttons_[d];d++)a= -Math.max(a,e.width);a+=1.5*this.MARGIN+this.tabWidth_;a*=this.workspace_.scale;a+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness;if(this.width_!==a){for(let d=0,e;e=b[d];d++){if(this.RTL){c=e.getRelativeToSurfaceXY().x;let f=a/this.workspace_.scale-this.MARGIN;e.outputConnection||(f-=this.tabWidth_);e.moveBy(f-c,0)}this.rectMap_.has(e)&&this.moveRectToBlock_(this.rectMap_.get(e),e)}if(this.RTL)for(let d=0,e;e=this.buttons_[d];d++)b=e.getPosition().y,e.moveTo(a/this.workspace_.scale- -e.width-this.MARGIN-this.tabWidth_,b);this.targetWorkspace.scrollbar||this.autoClose||this.targetWorkspace.getFlyout()!==this||this.toolboxPosition_!==Position$$module$build$src$core$utils$toolbox.LEFT||this.targetWorkspace.translate(this.targetWorkspace.scrollX+a,this.targetWorkspace.scrollY);this.width_=a;this.position();this.targetWorkspace.resizeContents();this.targetWorkspace.recordDragTargets()}}};VerticalFlyout$$module$build$src$core$flyout_vertical.registryName="verticalFlyout"; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,DEFAULT$$module$build$src$core$registry,VerticalFlyout$$module$build$src$core$flyout_vertical);var module$build$src$core$flyout_vertical={};module$build$src$core$flyout_vertical.VerticalFlyout=VerticalFlyout$$module$build$src$core$flyout_vertical;var HorizontalFlyout$$module$build$src$core$flyout_horizontal=class extends Flyout$$module$build$src$core$flyout_base{constructor(a){super(a);this.horizontalLayout=!0}setMetrics_(a){if(this.isVisible()){var b=this.workspace_.getMetricsManager(),c=b.getScrollMetrics(),d=b.getViewMetrics();b=b.getAbsoluteMetrics();"number"===typeof a.x&&(this.workspace_.scrollX=-(c.left+(c.width-d.width)*a.x));this.workspace_.translate(this.workspace_.scrollX+b.left,this.workspace_.scrollY+b.top)}}getX(){return 0}getY(){if(!this.isVisible())return 0; -var a=this.targetWorkspace.getMetricsManager();const b=a.getAbsoluteMetrics(),c=a.getViewMetrics();a=a.getToolboxMetrics();const d=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP;return this.targetWorkspace.toolboxPosition===this.toolboxPosition_?this.targetWorkspace.getToolbox()?d?a.height:c.height-this.height_:d?0:c.height:d?0:c.height+b.top-this.height_}position(){if(this.isVisible()&&this.targetWorkspace.isVisible()){var a=this.targetWorkspace.getMetricsManager().getViewMetrics(); -this.width_=a.width;this.setBackgroundPath(a.width-2*this.CORNER_RADIUS,this.height_-this.CORNER_RADIUS);a=this.getX();var b=this.getY();this.positionAt_(this.width_,this.height_,a,b)}}setBackgroundPath(a,b){const c=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP,d=["M 0,"+(c?0:this.CORNER_RADIUS)];c?(d.push("h",a+2*this.CORNER_RADIUS),d.push("v",b),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("h",-a),d.push("a",this.CORNER_RADIUS, -this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,-this.CORNER_RADIUS)):(d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,-this.CORNER_RADIUS),d.push("h",a),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("v",b),d.push("h",-a-2*this.CORNER_RADIUS));d.push("z");this.svgBackground_.setAttribute("d",d.join(" "))}scrollToStart(){let a;null==(a=this.workspace_.scrollbar)||a.setX(this.RTL?Infinity:0)}wheel_(a){var b=getScrollDeltaPixels$$module$build$src$core$browser_events(a); -if(b=b.x||b.y){const c=this.workspace_.getMetricsManager(),d=c.getScrollMetrics();b=c.getViewMetrics().left-d.left+b;let e;null==(e=this.workspace_.scrollbar)||e.setX(b);hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv(this.workspace_);hideWithoutAnimation$$module$build$src$core$dropdowndiv()}a.preventDefault();a.stopPropagation()}layout_(a,b){this.workspace_.scale=this.targetWorkspace.scale;const c=this.MARGIN;let d=c+this.tabWidth_;this.RTL&&(a=a.reverse());for(let h=0,k;k=a[h];h++)if("block"=== -k.type){var e=k.block;if(void 0===e||null===e)continue;var f=e.getDescendants(!1);for(let m=0,n;n=f[m];m++)n.isInFlyout=!0;f=e.getSvgRoot();const l=e.getHeightWidth();var g=e.outputConnection?this.tabWidth_:0;g=this.RTL?d+l.width:d-g;e.moveBy(g,c);g=this.createRect_(e,g,c,l,h);d+=l.width+b[h];this.addBlockListeners_(f,e,g)}else"button"===k.type&&(e=k.button,this.initFlyoutButton_(e,d,c),d+=e.width+b[h])}isDragTowardWorkspace(a){a=Math.atan2(a.y,a.x)/Math.PI*180;const b=this.dragAngleRange_;return a< -90+b&&a>90-b||a>-90-b&&a<-90+b?!0:!1}getClientRect(){if(!this.svgGroup_||this.autoClose||!this.isVisible())return null;const a=this.svgGroup_.getBoundingClientRect(),b=a.top;return this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP?new Rect$$module$build$src$core$utils$rect(-1E9,b+a.height,-1E9,1E9):new Rect$$module$build$src$core$utils$rect(b,1E9,-1E9,1E9)}reflowInternal_(){this.workspace_.scale=this.getFlyoutScale();let a=0;const b=this.workspace_.getTopBlocks(!1);for(let d= -0,e;e=b[d];d++)a=Math.max(a,e.getHeightWidth().height);const c=this.buttons_;for(let d=0,e;e=c[d];d++)a=Math.max(a,e.height);a+=1.5*this.MARGIN;a*=this.workspace_.scale;a+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness;if(this.height_!==a){for(let d=0,e;e=b[d];d++)this.rectMap_.has(e)&&this.moveRectToBlock_(this.rectMap_.get(e),e);this.targetWorkspace.scrollbar||this.autoClose||this.targetWorkspace.getFlyout()!==this||this.toolboxPosition_!==Position$$module$build$src$core$utils$toolbox.TOP|| -this.targetWorkspace.translate(this.targetWorkspace.scrollX,this.targetWorkspace.scrollY+a);this.height_=a;this.position();this.targetWorkspace.resizeContents();this.targetWorkspace.recordDragTargets()}}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,DEFAULT$$module$build$src$core$registry,HorizontalFlyout$$module$build$src$core$flyout_horizontal);var module$build$src$core$flyout_horizontal={}; -module$build$src$core$flyout_horizontal.HorizontalFlyout=HorizontalFlyout$$module$build$src$core$flyout_horizontal;var FieldVariable$$module$build$src$core$field_variable=class extends FieldDropdown$$module$build$src$core$field_dropdown{constructor(a,b,c,d,e){super(Field$$module$build$src$core$field.SKIP_SETUP);this.defaultType="";this.variableTypes=[];this.variable=null;this.SERIALIZABLE=!0;this.menuGenerator_=FieldVariable$$module$build$src$core$field_variable.dropdownCreate;this.defaultVariableName="string"===typeof a?a:"";this.size_=new Size$$module$build$src$core$utils$size(0,0);a!==Field$$module$build$src$core$field.SKIP_SETUP&& -(e?this.configure_(e):this.setTypes(c,d),b&&this.setValidator(b))}configure_(a){super.configure_(a);this.setTypes(a.variableTypes,a.defaultType)}initModel(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;this.variable||(a=$.getOrCreateVariablePackage$$module$build$src$core$variables(a.workspace,null,this.defaultVariableName,this.defaultType),this.doValueUpdate_(a.getId()))}shouldAddBorderRect_(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field; -return super.shouldAddBorderRect_()&&(!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||"variables_get"!==a.type)}fromXml(a){var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;const c=a.getAttribute("id"),d=a.textContent,e=a.getAttribute("variabletype")||a.getAttribute("variableType")||"";b=$.getOrCreateVariablePackage$$module$build$src$core$variables(b.workspace,c,d,e);if(null!==e&&e!==b.type)throw Error("Serialized variable type with id '"+b.getId()+ -"' had type "+b.type+", and does not match variable field that references it: "+domToText$$module$build$src$core$xml(a)+".");this.setValue(b.getId())}toXml(a){this.initModel();a.id=this.variable.getId();a.textContent=this.variable.name;this.variable.type&&a.setAttribute("variabletype",this.variable.type);return a}saveState(a){var b=this.saveLegacyState(FieldVariable$$module$build$src$core$field_variable);if(null!==b)return b;this.initModel();b={id:this.variable.getId()};a&&(b.name=this.variable.name, -b.type=this.variable.type);return b}loadState(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.loadLegacyState(FieldVariable$$module$build$src$core$field_variable,a)||(a=$.getOrCreateVariablePackage$$module$build$src$core$variables(b.workspace,a.id||null,a.name,a.type||""),this.setValue(a.getId()))}setSourceBlock(a){if(a.isShadow())throw Error("Variable fields are not allowed to exist on shadow blocks.");super.setSourceBlock(a)}getValue(){return this.variable? -this.variable.getId():null}getText(){return this.variable?this.variable.name:""}getVariable(){return this.variable}getValidator(){return this.variable?this.validator_:null}doClassValidation_(a){if(null===a)return null;var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;b=$.getVariable$$module$build$src$core$variables(b.workspace,a);if(!b)return console.warn("Variable id doesn't point to a real variable! ID was "+a),null;b=b.type;return this.typeIsAllowed(b)? -a:(console.warn("Variable type doesn't match this field! Type was "+b),null)}doValueUpdate_(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.variable=$.getVariable$$module$build$src$core$variables(b.workspace,a);super.doValueUpdate_(a)}typeIsAllowed(a){const b=this.getVariableTypes();if(!b)return!0;for(let c=0;cthis.max_&&(a.max=`${this.max_}`,setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.VALUEMAX, -this.max_));return a}static fromJson(a){return new this(a.value,void 0,void 0,void 0,void 0,a)}};register$$module$build$src$core$field_registry("field_number",FieldNumber$$module$build$src$core$field_number);FieldNumber$$module$build$src$core$field_number.prototype.DEFAULT_VALUE=0;var module$build$src$core$field_number={};module$build$src$core$field_number.FieldNumber=FieldNumber$$module$build$src$core$field_number;var FieldLabelSerializable$$module$build$src$core$field_label_serializable=class extends FieldLabel$$module$build$src$core$field_label{constructor(a,b,c){super(String(null!=a?a:""),b,c);this.EDITABLE=!1;this.SERIALIZABLE=!0}static fromJson(a){return new this(replaceMessageReferences$$module$build$src$core$utils$parsing(a.text),void 0,a)}};register$$module$build$src$core$field_registry("field_label_serializable",FieldLabelSerializable$$module$build$src$core$field_label_serializable); -var module$build$src$core$field_label_serializable={};module$build$src$core$field_label_serializable.FieldLabelSerializable=FieldLabelSerializable$$module$build$src$core$field_label_serializable;var FieldCheckbox$$module$build$src$core$field_checkbox=class extends Field$$module$build$src$core$field{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.SERIALIZABLE=!0;this.CURSOR="default";this.value_=this.value_;this.checkChar=FieldCheckbox$$module$build$src$core$field_checkbox.CHECK_CHAR;a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){super.configure_(a);a.checkCharacter&&(this.checkChar= -a.checkCharacter)}saveState(){const a=this.saveLegacyState(FieldCheckbox$$module$build$src$core$field_checkbox);return null!==a?a:this.getValueBoolean()}initView(){super.initView();const a=this.getTextElement();addClass$$module$build$src$core$utils$dom(a,"blocklyCheckbox");a.style.display=this.value_?"block":"none"}render_(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_());this.updateSize_(this.getConstants().FIELD_CHECKBOX_X_OFFSET)}getDisplayText_(){return this.checkChar}setCheckCharacter(a){this.checkChar= -a||FieldCheckbox$$module$build$src$core$field_checkbox.CHECK_CHAR;this.forceRerender()}showEditor_(){this.setValue(!this.value_)}doClassValidation_(a){return!0===a||"TRUE"===a?"TRUE":!1===a||"FALSE"===a?"FALSE":null}doValueUpdate_(a){this.value_=this.convertValueToBool(a);this.textElement_&&(this.textElement_.style.display=this.value_?"block":"none")}getValue(){return this.value_?"TRUE":"FALSE"}getValueBoolean(){return this.value_}getText(){return String(this.convertValueToBool(this.value_))}convertValueToBool(a){return"string"=== -typeof a?"TRUE"===a:!!a}static fromJson(a){return new this(a.checked,void 0,a)}};FieldCheckbox$$module$build$src$core$field_checkbox.CHECK_CHAR="\u2713";register$$module$build$src$core$field_registry("field_checkbox",FieldCheckbox$$module$build$src$core$field_checkbox);FieldCheckbox$$module$build$src$core$field_checkbox.prototype.DEFAULT_VALUE=!1;var module$build$src$core$field_checkbox={};module$build$src$core$field_checkbox.FieldCheckbox=FieldCheckbox$$module$build$src$core$field_checkbox;var Dragger$$module$build$src$core$dragging$dragger=class{constructor(a,b){this.draggable=a;this.workspace=b;this.dragTarget=null;this.startLoc=a.getRelativeToSurfaceXY()}onDragStart(a){this.draggable.startDrag(a)}onDrag(a,b){this.moveDraggable(a,b);b=this.getRoot(this.draggable);isDeletable$$module$build$src$core$interfaces$i_deletable(b)&&b.setDeleteStyle(this.wouldDeleteDraggable(a,b));this.updateDragTarget(a)}updateDragTarget(a){a=this.workspace.getDragTarget(a);const b=this.getRoot(this.draggable); -if(this.dragTarget!==a){let c;null==(c=this.dragTarget)||c.onDragExit(b);null==a||a.onDragEnter(b)}null==a||a.onDragOver(b);this.dragTarget=a}moveDraggable(a,b){b=this.pixelsToWorkspaceUnits(b);b=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startLoc,b);this.draggable.drag(b,a)}wouldDeleteDraggable(a,b){return(a=this.workspace.getDragTarget(a))&&this.workspace.getComponentManager().hasCapability(a.id,ComponentManager$$module$build$src$core$component_manager.Capability.DELETE_AREA)?a.wouldDelete(b): -!1}onDragEnd(a){const b=$.getGroup$$module$build$src$core$events$utils();var c=this.workspace.getDragTarget(a);const d=this.getRoot(this.draggable);if(c){let e;null==(e=this.dragTarget)||e.onDrop(d)}this.shouldReturnToStart(a,d)&&this.draggable.revertDrag();(c=isDeletable$$module$build$src$core$interfaces$i_deletable(d)&&this.wouldDeleteDraggable(a,d))&&this.draggable instanceof BlockSvg$$module$build$src$core$block_svg&&disposeUiEffect$$module$build$src$core$block_animations(this.draggable.getRootBlock()); -this.draggable.endDrag(a);c&&isDeletable$$module$build$src$core$interfaces$i_deletable(d)&&(a=$.getGroup$$module$build$src$core$events$utils(),$.setGroup$$module$build$src$core$events$utils(b),d.dispose(),$.setGroup$$module$build$src$core$events$utils(a))}getRoot(a){return a instanceof BlockSvg$$module$build$src$core$block_svg?a.getRootBlock():a}shouldReturnToStart(a,b){return(a=this.workspace.getDragTarget(a))?a.shouldPreventMove(b):!1}pixelsToWorkspaceUnits(a){a=new Coordinate$$module$build$src$core$utils$coordinate(a.x/ -this.workspace.scale,a.y/this.workspace.scale);this.workspace.isMutator&&a.scale(1/this.workspace.options.parentWorkspace.scale);return a}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.BLOCK_DRAGGER,DEFAULT$$module$build$src$core$registry,Dragger$$module$build$src$core$dragging$dragger);var module$build$src$core$dragging$dragger={};module$build$src$core$dragging$dragger.Dragger=Dragger$$module$build$src$core$dragging$dragger;var module$build$src$core$dragging={};module$build$src$core$dragging.BlockDragStrategy=BlockDragStrategy$$module$build$src$core$dragging$block_drag_strategy;module$build$src$core$dragging.BubbleDragStrategy=BubbleDragStrategy$$module$build$src$core$dragging$bubble_drag_strategy;module$build$src$core$dragging.CommentDragStrategy=CommentDragStrategy$$module$build$src$core$dragging$comment_drag_strategy;module$build$src$core$dragging.Dragger=Dragger$$module$build$src$core$dragging$dragger;var BlockDrag$$module$build$src$core$events$events_block_drag=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){super(a?a.workspace.id:void 0);this.type=EventType$$module$build$src$core$events$type.BLOCK_DRAG;a&&(this.blockId=a.id,this.isStart=b,this.blocks=c)}toJson(){const a=super.toJson();if(void 0===this.isStart)throw Error("Whether this event is the start of a drag is undefined. Either pass the value to the constructor, or call fromJson");if(void 0===this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson"); -a.isStart=this.isStart;a.blockId=this.blockId;a.blocks=this.blocks;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new BlockDrag$$module$build$src$core$events$events_block_drag);b.isStart=a.isStart;b.blockId=a.blockId;b.blocks=a.blocks;return b}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,EventType$$module$build$src$core$events$type.BLOCK_DRAG,BlockDrag$$module$build$src$core$events$events_block_drag); -var module$build$src$core$events$events_block_drag={};module$build$src$core$events$events_block_drag.BlockDrag=BlockDrag$$module$build$src$core$events$events_block_drag;var BlockFieldIntermediateChange$$module$build$src$core$events$events_block_field_intermediate_change=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a,b,c,d){super(a);this.type=EventType$$module$build$src$core$events$type.BLOCK_FIELD_INTERMEDIATE_CHANGE;this.recordUndo=!1;a&&(this.name=b,this.oldValue=c,this.newValue=d)}toJson(){const a=super.toJson();if(!this.name)throw Error("The changed field name is undefined. Either pass a name to the constructor, or call fromJson."); -a.name=this.name;a.oldValue=this.oldValue;a.newValue=this.newValue;return a}static fromJson(a,b,c){b=super.fromJson(a,b,null!=c?c:new BlockFieldIntermediateChange$$module$build$src$core$events$events_block_field_intermediate_change);b.name=a.name;b.oldValue=a.oldValue;b.newValue=a.newValue;return b}isNull(){return this.oldValue===this.newValue}run(a){var b=this.getEventWorkspace_();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson"); +b,c){return b}finish(a){this.definitions_=Object.create(null);this.functionNames_=Object.create(null);return a}scrubNakedValue(a){return a}};module$build$src$core$generator={};module$build$src$core$generator.CodeGenerator=$.CodeGenerator$$module$build$src$core$generator;var VerticalFlyout$$module$build$src$core$flyout_vertical=class extends Flyout$$module$build$src$core$flyout_base{constructor(a){super(a)}setMetrics_(a){if(this.isVisible()){var b=this.workspace_.getMetricsManager(),c=b.getScrollMetrics(),d=b.getViewMetrics();b=b.getAbsoluteMetrics();typeof a.y==="number"&&(this.workspace_.scrollY=-(c.top+(c.height-d.height)*a.y));this.workspace_.translate(this.workspace_.scrollX+b.left,this.workspace_.scrollY+b.top)}}getX(){if(!this.isVisible())return 0;var a=this.targetWorkspace.getMetricsManager(); +const b=a.getAbsoluteMetrics(),c=a.getViewMetrics();a=a.getToolboxMetrics();return this.targetWorkspace.toolboxPosition===this.toolboxPosition_?this.targetWorkspace.getToolbox()?this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.LEFT?a.width:c.width-this.getWidth():this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.LEFT?0:c.width:this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.LEFT?0:c.width+b.left-this.getWidth()}getY(){return 0}position(){if(this.isVisible()&& +this.targetWorkspace.isVisible()){var a=this.targetWorkspace.getMetricsManager().getViewMetrics();this.height_=a.height;var b=this.getWidth()-this.CORNER_RADIUS;this.setBackgroundPath(b,a.height-2*this.CORNER_RADIUS);a=this.getX();b=this.getY();this.positionAt_(this.getWidth(),this.getHeight(),a,b)}}setBackgroundPath(a,b){const c=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.RIGHT;var d=a+this.CORNER_RADIUS;d=["M "+(c?d:0)+",0"];d.push("h",c?-a:a);d.push("a",this.CORNER_RADIUS, +this.CORNER_RADIUS,0,0,c?0:1,c?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("v",Math.max(0,b));d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("h",c?a:-a);d.push("z");this.svgBackground_.setAttribute("d",d.join(" "))}scrollToStart(){let a;(a=this.workspace_.scrollbar)==null||a.setY(0)}wheel_(a){var b=getScrollDeltaPixels$$module$build$src$core$browser_events(a);if(b.y){const c=this.workspace_.getMetricsManager(), +d=c.getScrollMetrics();b=c.getViewMetrics().top-d.top+b.y;let e;(e=this.workspace_.scrollbar)==null||e.setY(b);hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv(this.workspace_);hideWithoutAnimation$$module$build$src$core$dropdowndiv()}a.preventDefault();a.stopPropagation()}layout_(a){this.workspace_.scale=this.targetWorkspace.scale;var b=this.MARGIN;const c=this.RTL?b:b+this.tabWidth_;for(const d of a)d.getElement().moveBy(c,b),b+=d.getElement().getBoundingRectangle().getHeight()}isDragTowardWorkspace(a){a= +Math.atan2(a.y,a.x)/Math.PI*180;const b=this.dragAngleRange_;return a-b||a<-180+b||a>180-b?!0:!1}getClientRect(){if(!this.svgGroup_||this.autoClose||!this.isVisible())return null;const a=this.svgGroup_.getBoundingClientRect(),b=a.left;return this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.LEFT?new Rect$$module$build$src$core$utils$rect(-1E9,1E9,-1E9,b+a.width):new Rect$$module$build$src$core$utils$rect(-1E9,1E9,b,1E9)}reflowInternal_(){this.workspace_.scale=this.getFlyoutScale(); +let a=this.getContents().reduce((b,c)=>Math.max(b,c.getElement().getBoundingRectangle().getWidth()),0);a+=this.MARGIN*1.5+this.tabWidth_;a*=this.workspace_.scale;a+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness;if(this.getWidth()!==a){if(this.RTL)for(const b of this.getContents()){const c=b.getElement().getBoundingRectangle().left,d=a/this.workspace_.scale-b.getElement().getBoundingRectangle().getWidth()-this.MARGIN-this.tabWidth_;b.getElement().moveBy(d-c,0)}this.targetWorkspace.scrollbar|| +this.autoClose||this.targetWorkspace.getFlyout()!==this||this.toolboxPosition_!==Position$$module$build$src$core$utils$toolbox.LEFT||this.targetWorkspace.translate(this.targetWorkspace.scrollX+a,this.targetWorkspace.scrollY);this.width_=a;this.position();this.targetWorkspace.resizeContents();this.targetWorkspace.recordDragTargets()}}};VerticalFlyout$$module$build$src$core$flyout_vertical.registryName="verticalFlyout"; +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,DEFAULT$$module$build$src$core$registry,VerticalFlyout$$module$build$src$core$flyout_vertical);var module$build$src$core$flyout_vertical={};module$build$src$core$flyout_vertical.VerticalFlyout=VerticalFlyout$$module$build$src$core$flyout_vertical;var HorizontalFlyout$$module$build$src$core$flyout_horizontal=class extends Flyout$$module$build$src$core$flyout_base{constructor(a){super(a);this.horizontalLayout=!0}setMetrics_(a){if(this.isVisible()){var b=this.workspace_.getMetricsManager(),c=b.getScrollMetrics(),d=b.getViewMetrics();b=b.getAbsoluteMetrics();typeof a.x==="number"&&(this.workspace_.scrollX=-(c.left+(c.width-d.width)*a.x));this.workspace_.translate(this.workspace_.scrollX+b.left,this.workspace_.scrollY+b.top)}}getX(){return 0}getY(){if(!this.isVisible())return 0; +var a=this.targetWorkspace.getMetricsManager();const b=a.getAbsoluteMetrics(),c=a.getViewMetrics();a=a.getToolboxMetrics();const d=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP;return this.targetWorkspace.toolboxPosition===this.toolboxPosition_?this.targetWorkspace.getToolbox()?d?a.height:c.height-this.getHeight():d?0:c.height:d?0:c.height+b.top-this.getHeight()}position(){if(this.isVisible()&&this.targetWorkspace.isVisible()){var a=this.targetWorkspace.getMetricsManager().getViewMetrics(); +this.width_=a.width;a=a.width-2*this.CORNER_RADIUS;var b=this.getHeight()-this.CORNER_RADIUS;this.setBackgroundPath(a,b);a=this.getX();b=this.getY();this.positionAt_(this.getWidth(),this.getHeight(),a,b)}}setBackgroundPath(a,b){const c=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP,d=["M 0,"+(c?0:this.CORNER_RADIUS)];c?(d.push("h",a+2*this.CORNER_RADIUS),d.push("v",b),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("h", +-a),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,-this.CORNER_RADIUS)):(d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,-this.CORNER_RADIUS),d.push("h",a),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("v",b),d.push("h",-a-2*this.CORNER_RADIUS));d.push("z");this.svgBackground_.setAttribute("d",d.join(" "))}scrollToStart(){let a;(a=this.workspace_.scrollbar)==null||a.setX(this.RTL?Infinity: +0)}wheel_(a){var b=getScrollDeltaPixels$$module$build$src$core$browser_events(a);if(b=b.x||b.y){const c=this.workspace_.getMetricsManager(),d=c.getScrollMetrics();b=c.getViewMetrics().left-d.left+b;let e;(e=this.workspace_.scrollbar)==null||e.setX(b);hideIfOwnerIsInWorkspace$$module$build$src$core$widgetdiv(this.workspace_);hideWithoutAnimation$$module$build$src$core$dropdowndiv()}a.preventDefault();a.stopPropagation()}layout_(a){this.workspace_.scale=this.targetWorkspace.scale;const b=this.MARGIN; +let c=b+this.tabWidth_;this.RTL&&(a=a.reverse());for(const d of a)a=d.getElement().getBoundingRectangle(),a=this.RTL?c+a.getWidth():c,d.getElement().moveBy(a,b),c+=d.getElement().getBoundingRectangle().getWidth()}isDragTowardWorkspace(a){a=Math.atan2(a.y,a.x)/Math.PI*180;const b=this.dragAngleRange_;return a<90+b&&a>90-b||a>-90-b&&a<-90+b?!0:!1}getClientRect(){if(!this.svgGroup_||this.autoClose||!this.isVisible())return null;const a=this.svgGroup_.getBoundingClientRect(),b=a.top;return this.toolboxPosition_=== +Position$$module$build$src$core$utils$toolbox.TOP?new Rect$$module$build$src$core$utils$rect(-1E9,b+a.height,-1E9,1E9):new Rect$$module$build$src$core$utils$rect(b,1E9,-1E9,1E9)}reflowInternal_(){this.workspace_.scale=this.getFlyoutScale();let a=this.getContents().reduce((b,c)=>Math.max(b,c.getElement().getBoundingRectangle().getHeight()),0);a+=this.MARGIN*1.5;a*=this.workspace_.scale;a+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness;this.getHeight()!==a&&(this.targetWorkspace.scrollbar|| +this.autoClose||this.targetWorkspace.getFlyout()!==this||this.toolboxPosition_!==Position$$module$build$src$core$utils$toolbox.TOP||this.targetWorkspace.translate(this.targetWorkspace.scrollX,this.targetWorkspace.scrollY+a),this.height_=a,this.position(),this.targetWorkspace.resizeContents(),this.targetWorkspace.recordDragTargets())}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,DEFAULT$$module$build$src$core$registry,HorizontalFlyout$$module$build$src$core$flyout_horizontal); +var module$build$src$core$flyout_horizontal={};module$build$src$core$flyout_horizontal.HorizontalFlyout=HorizontalFlyout$$module$build$src$core$flyout_horizontal;var FieldVariable$$module$build$src$core$field_variable=class extends FieldDropdown$$module$build$src$core$field_dropdown{constructor(a,b,c,d,e){super(Field$$module$build$src$core$field.SKIP_SETUP);this.defaultType="";this.variableTypes=[];this.variable=null;this.SERIALIZABLE=!0;this.menuGenerator_=FieldVariable$$module$build$src$core$field_variable.dropdownCreate;this.defaultVariableName=typeof a==="string"?a:"";this.size_=new Size$$module$build$src$core$utils$size(0,0);a!==Field$$module$build$src$core$field.SKIP_SETUP&& +(e?this.configure_(e):this.setTypes(c,d),b&&this.setValidator(b))}configure_(a){super.configure_(a);this.setTypes(a.variableTypes,a.defaultType)}initModel(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;this.variable||(a=$.getOrCreateVariablePackage$$module$build$src$core$variables(a.workspace,null,this.defaultVariableName,this.defaultType),this.doValueUpdate_(a.getId()))}initView(){super.initView();addClass$$module$build$src$core$utils$dom(this.fieldGroup_, +"blocklyVariableField")}shouldAddBorderRect_(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;return super.shouldAddBorderRect_()&&(!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||a.type!=="variables_get")}fromXml(a){var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;const c=a.getAttribute("id"),d=a.textContent,e=a.getAttribute("variabletype")||a.getAttribute("variableType")||"";b=$.getOrCreateVariablePackage$$module$build$src$core$variables(b.workspace, +c,d,e);if(e!==null&&e!==b.getType())throw Error("Serialized variable type with id '"+b.getId()+"' had type "+b.getType()+", and does not match variable field that references it: "+domToText$$module$build$src$core$xml(a)+".");this.setValue(b.getId())}toXml(a){this.initModel();a.id=this.variable.getId();a.textContent=this.variable.getName();this.variable.getType()&&a.setAttribute("variabletype",this.variable.getType());return a}saveState(a){var b=this.saveLegacyState(FieldVariable$$module$build$src$core$field_variable); +if(b!==null)return b;this.initModel();b={id:this.variable.getId()};a&&(b.name=this.variable.getName(),b.type=this.variable.getType());return b}loadState(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.loadLegacyState(FieldVariable$$module$build$src$core$field_variable,a)||(a=$.getOrCreateVariablePackage$$module$build$src$core$variables(b.workspace,a.id||null,a.name,a.type||""),this.setValue(a.getId()))}setSourceBlock(a){if(a.isShadow())throw Error("Variable fields are not allowed to exist on shadow blocks."); +super.setSourceBlock(a)}getValue(){return this.variable?this.variable.getId():null}getText(){return this.variable?this.variable.getName():""}getVariable(){return this.variable}getDefaultType(){return this.defaultType}getValidator(){return this.variable?this.validator_:null}doClassValidation_(a){if(a===null)return null;var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;b=$.getVariable$$module$build$src$core$variables(b.workspace,a);if(!b)return console.warn("Variable id doesn't point to a real variable! ID was "+ +a),null;b=b.getType();return this.typeIsAllowed(b)?a:(console.warn("Variable type doesn't match this field! Type was "+b),null)}doValueUpdate_(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.variable=$.getVariable$$module$build$src$core$variables(b.workspace,a);super.doValueUpdate_(a)}typeIsAllowed(a){const b=this.getVariableTypes();if(!b)return!0;for(let c=0;c-Infinity&&(a.min=`${this.min_}`,setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.VALUEMIN,this.min_));this.max_.blocklyPathLight,`,`${a} .blocklyInsertionMarker>.blocklyPathDark {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;", +module$build$src$core$contextmenu_items.registerInline=registerInline$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerRedo=registerRedo$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerUndo=registerUndo$$module$build$src$core$contextmenu_items;var BUTTON_TYPE$$module$build$src$core$button_flyout_inflater="button",ButtonFlyoutInflater$$module$build$src$core$button_flyout_inflater=class{load(a,b){a=new FlyoutButton$$module$build$src$core$flyout_button(b.getWorkspace(),b.targetWorkspace,a,!1);a.show();return new FlyoutItem$$module$build$src$core$flyout_item(a,BUTTON_TYPE$$module$build$src$core$button_flyout_inflater)}gapForItem(a,b){return b}disposeItem(a){a=a.getElement();a instanceof FlyoutButton$$module$build$src$core$flyout_button&&a.dispose()}getType(){return BUTTON_TYPE$$module$build$src$core$button_flyout_inflater}}; +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUT_INFLATER,BUTTON_TYPE$$module$build$src$core$button_flyout_inflater,ButtonFlyoutInflater$$module$build$src$core$button_flyout_inflater);var module$build$src$core$button_flyout_inflater={};module$build$src$core$button_flyout_inflater.ButtonFlyoutInflater=ButtonFlyoutInflater$$module$build$src$core$button_flyout_inflater;var module$build$src$core$bubbles={};module$build$src$core$bubbles.Bubble=Bubble$$module$build$src$core$bubbles$bubble;module$build$src$core$bubbles.MiniWorkspaceBubble=MiniWorkspaceBubble$$module$build$src$core$bubbles$mini_workspace_bubble;module$build$src$core$bubbles.TextBubble=TextBubble$$module$build$src$core$bubbles$text_bubble;module$build$src$core$bubbles.TextInputBubble=TextInputBubble$$module$build$src$core$bubbles$textinput_bubble;var module$build$src$core$blockly_options={};var WORKSPACE_AT_BLOCK_CAPACITY_DISABLED_REASON$$module$build$src$core$block_flyout_inflater="WORKSPACE_AT_BLOCK_CAPACITY",BLOCK_TYPE$$module$build$src$core$block_flyout_inflater="block",BlockFlyoutInflater$$module$build$src$core$block_flyout_inflater=class{constructor(){this.permanentlyDisabledBlocks=new Set;this.listeners=new Map;this.capacityWrapper=this.filterFlyoutBasedOnCapacity.bind(this)}load(a,b){this.setFlyout(b);a=this.createBlock(a,b.getWorkspace());a.isEnabled()?this.updateStateBasedOnCapacity(a): +this.permanentlyDisabledBlocks.add(a);a.getDescendants(!1).forEach(c=>c.isInFlyout=!0);this.addBlockListeners(a);return new FlyoutItem$$module$build$src$core$flyout_item(a,BLOCK_TYPE$$module$build$src$core$block_flyout_inflater)}createBlock(a,b){a.blockxml?(a=typeof a.blockxml==="string"?$.textToDom$$module$build$src$core$utils$xml(a.blockxml):a.blockxml,b=domToBlockInternal$$module$build$src$core$xml(a,b)):(a.enabled===void 0&&(a.enabled=a.disabled!=="true"&&a.disabled!==!0),a.disabledReasons=== +void 0&&a.enabled===!1&&(a.disabledReasons=[MANUALLY_DISABLED$$module$build$src$core$constants]),"x"in a&&delete a.x,"y"in a&&delete a.y,b=appendInternal$$module$build$src$core$serialization$blocks(a,b));return b}gapForItem(a,b){let c;a.gap?c=parseInt(String(a.gap)):a.blockxml&&(a=typeof a.blockxml==="string"?$.textToDom$$module$build$src$core$utils$xml(a.blockxml):a.blockxml,c=parseInt(a.getAttribute("gap")));return!c||isNaN(c)?b:c}disposeItem(a){a=a.getElement();a instanceof BlockSvg$$module$build$src$core$block_svg&& +(this.removeListeners(a.id),a.dispose(!1,!1))}removeListeners(a){let b;((b=this.listeners.get(a))!=null?b:[]).forEach(c=>unbind$$module$build$src$core$browser_events(c));this.listeners.delete(a)}setFlyout(a){if(this.flyout!==a){if(this.flyout){let c;(c=this.flyout.targetWorkspace)==null||c.removeChangeListener(this.capacityWrapper)}this.flyout=a;var b;(b=this.flyout.targetWorkspace)==null||b.addChangeListener(this.capacityWrapper)}}updateStateBasedOnCapacity(a){let b,c;const d=(b=this.flyout)==null? +void 0:(c=b.targetWorkspace)==null?void 0:c.isCapacityAvailable(getBlockTypeCounts$$module$build$src$core$common(a));for(;a;)a.setDisabledReason(!d,WORKSPACE_AT_BLOCK_CAPACITY_DISABLED_REASON$$module$build$src$core$block_flyout_inflater),a=a.getNextBlock()}addBlockListeners(a){const b=[];b.push(conditionalBind$$module$build$src$core$browser_events(a.getSvgRoot(),"pointerdown",a,c=>{let d,e;const f=(d=this.flyout)==null?void 0:(e=d.targetWorkspace)==null?void 0:e.getGesture(c);f&&this.flyout&&(f.setStartBlock(a), +f.handleFlyoutStart(c,this.flyout))}));b.push(bind$$module$build$src$core$browser_events(a.getSvgRoot(),"pointermove",null,()=>{let c,d;((c=this.flyout)==null?0:(d=c.targetWorkspace)==null?0:d.isDragging())||a.addSelect()}));b.push(bind$$module$build$src$core$browser_events(a.getSvgRoot(),"pointerleave",null,()=>{let c,d;((c=this.flyout)==null?0:(d=c.targetWorkspace)==null?0:d.isDragging())||a.removeSelect()}));this.listeners.set(a.id,b)}filterFlyoutBasedOnCapacity(a){!this.flyout||a&&a.type!==EventType$$module$build$src$core$events$type.BLOCK_CREATE&& +a.type!==EventType$$module$build$src$core$events$type.BLOCK_DELETE||this.flyout.getWorkspace().getTopBlocks(!1).forEach(b=>{this.permanentlyDisabledBlocks.has(b)||this.updateStateBasedOnCapacity(b)})}getType(){return BLOCK_TYPE$$module$build$src$core$block_flyout_inflater}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUT_INFLATER,BLOCK_TYPE$$module$build$src$core$block_flyout_inflater,BlockFlyoutInflater$$module$build$src$core$block_flyout_inflater); +var module$build$src$core$block_flyout_inflater={};module$build$src$core$block_flyout_inflater.BlockFlyoutInflater=BlockFlyoutInflater$$module$build$src$core$block_flyout_inflater;var module$build$src$core$interfaces$i_paster={};module$build$src$core$interfaces$i_paster.isPaster=isPaster$$module$build$src$core$interfaces$i_paster;var module$build$src$core$interfaces$i_rendered_element={};module$build$src$core$interfaces$i_rendered_element.isRenderedElement=isRenderedElement$$module$build$src$core$interfaces$i_rendered_element;var ConstantProvider$$module$build$src$core$renderers$geras$constants=class extends ConstantProvider$$module$build$src$core$renderers$common$constants{constructor(){super();this.FIELD_TEXT_BASELINE_CENTER=!1;this.DARK_PATH_OFFSET=1;this.MAX_BOTTOM_WIDTH=30;this.STATEMENT_BOTTOM_SPACER=-this.NOTCH_HEIGHT/2}getCSS_(a){return super.getCSS_(a).concat([`${a} .blocklyInsertionMarker>.blocklyPathLight,`,`${a} .blocklyInsertionMarker>.blocklyPathDark {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;", "}"])}},module$build$src$core$renderers$geras$constants={};module$build$src$core$renderers$geras$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$geras$constants;var Highlighter$$module$build$src$core$renderers$geras$highlighter=class{constructor(a){this.inlineSteps_=this.steps_="";this.info_=a;this.RTL_=this.info_.RTL;a=a.getRenderer();this.constants_=a.getConstants();this.highlightConstants_=a.getHighlightConstants();this.highlightOffset=this.highlightConstants_.OFFSET;this.outsideCornerPaths_=this.highlightConstants_.OUTSIDE_CORNER;this.insideCornerPaths_=this.highlightConstants_.INSIDE_CORNER;this.puzzleTabPaths_=this.highlightConstants_.PUZZLE_TAB;this.notchPaths_= this.highlightConstants_.NOTCH;this.startPaths_=this.highlightConstants_.START_HAT;this.jaggedTeethPaths_=this.highlightConstants_.JAGGED_TEETH}getPath(){return this.steps_+"\n"+this.inlineSteps_}drawTopCorner(a){this.steps_+=moveBy$$module$build$src$core$utils$svg_paths(a.xPos,this.info_.startY);for(let b=0,c;c=a.elements[b];b++)Types$$module$build$src$core$renderers$measurables$types.isLeftSquareCorner(c)?this.steps_+=this.highlightConstants_.START_POINT:Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(c)? -this.steps_+=this.outsideCornerPaths_.topLeft(this.RTL_):Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(c)?this.steps_+=this.notchPaths_.pathLeft:Types$$module$build$src$core$renderers$measurables$types.isHat(c)?this.steps_+=this.startPaths_.path(this.RTL_):Types$$module$build$src$core$renderers$measurables$types.isSpacer(c)&&0!==c.width&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",c.xPos+c.width-this.highlightOffset));this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H", +this.steps_+=this.outsideCornerPaths_.topLeft(this.RTL_):Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(c)?this.steps_+=this.notchPaths_.pathLeft:Types$$module$build$src$core$renderers$measurables$types.isHat(c)?this.steps_+=this.startPaths_.path(this.RTL_):Types$$module$build$src$core$renderers$measurables$types.isSpacer(c)&&c.width!==0&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",c.xPos+c.width-this.highlightOffset));this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H", a.xPos+a.width-this.highlightOffset)}drawJaggedEdge_(a){this.info_.RTL&&(this.steps_+=this.jaggedTeethPaths_.pathLeft+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height-this.jaggedTeethPaths_.height-this.highlightOffset))}drawValueInput(a){const b=a.getLastInput();if(this.RTL_){const c=a.height-b.connectionHeight;this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos+b.width-this.highlightOffset,a.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)+lineOnAxis$$module$build$src$core$utils$svg_paths("v", c)}else this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos+b.width,a.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)}drawStatementInput(a){const b=a.getLastInput();if(b)if(this.RTL_){const c=a.height-2*this.insideCornerPaths_.height;this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos,a.yPos)+this.insideCornerPaths_.pathTop(this.RTL_)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",c)+this.insideCornerPaths_.pathBottom(this.RTL_)+lineTo$$module$build$src$core$utils$svg_paths(a.width- b.xPos-this.insideCornerPaths_.width,0)}else this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos,a.yPos+a.height)+this.insideCornerPaths_.pathBottom(this.RTL_)+lineTo$$module$build$src$core$utils$svg_paths(a.width-b.xPos-this.insideCornerPaths_.width,0)}drawRightSideRow(a){const b=a.xPos+a.width-this.highlightOffset;a instanceof SpacerRow$$module$build$src$core$renderers$measurables$spacer_row&&a.followsStatement&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",b)); @@ -1569,134 +1684,139 @@ this.highlightOffset,c=a.xPos+a.connectionWidth;var d=a.centerline-a.height/2;co moveTo$$module$build$src$core$utils$svg_paths(a.xPos+a.width+b,f)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",-e)+moveTo$$module$build$src$core$utils$svg_paths(c,d+a.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)}},module$build$src$core$renderers$geras$highlighter={};module$build$src$core$renderers$geras$highlighter.Highlighter=Highlighter$$module$build$src$core$renderers$geras$highlighter;var Drawer$$module$build$src$core$renderers$geras$drawer=class extends Drawer$$module$build$src$core$renderers$common$drawer{constructor(a,b){super(a,b);this.highlighter_=new Highlighter$$module$build$src$core$renderers$geras$highlighter(b)}draw(){this.drawOutline_();this.drawInternals_();this.updateConnectionHighlights();const a=this.block_.pathObject;a.setPath(this.outlinePath_+"\n"+this.inlinePath_);a.setHighlightPath(this.highlighter_.getPath());this.info_.RTL&&a.flipRTL();this.recordSizeOnBlock_()}drawTop_(){this.highlighter_.drawTopCorner(this.info_.topRow); this.highlighter_.drawRightSideRow(this.info_.topRow);super.drawTop_()}drawJaggedEdge_(a){this.highlighter_.drawJaggedEdge_(a);super.drawJaggedEdge_(a)}drawValueInput_(a){this.highlighter_.drawValueInput(a);super.drawValueInput_(a)}drawStatementInput_(a){this.highlighter_.drawStatementInput(a);super.drawStatementInput_(a)}drawRightSideRow_(a){this.highlighter_.drawRightSideRow(a);this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",a.xPos+a.width)+lineOnAxis$$module$build$src$core$utils$svg_paths("V", a.yPos+a.height)}drawBottom_(){this.highlighter_.drawBottomRow(this.info_.bottomRow);super.drawBottom_()}drawLeft_(){this.highlighter_.drawLeft();super.drawLeft_()}drawInlineInput_(a){this.highlighter_.drawInlineInput(a);super.drawInlineInput_(a)}positionInlineInputConnection_(a){const b=a.centerline-a.height/2;if(a.connectionModel){let c=a.xPos+a.connectionWidth+this.constants_.DARK_PATH_OFFSET;this.info_.RTL&&(c*=-1);a.connectionModel.setOffsetInBlock(c,b+a.connectionOffsetY+this.constants_.DARK_PATH_OFFSET)}}positionStatementInputConnection_(a){const b= -a.getLastInput();if(null==b?0:b.connectionModel){let c=a.xPos+a.statementEdge+b.notchOffset;c=this.info_.RTL?-1*c:c+this.constants_.DARK_PATH_OFFSET;b.connectionModel.setOffsetInBlock(c,a.yPos+this.constants_.DARK_PATH_OFFSET)}}positionExternalValueConnection_(a){const b=a.getLastInput();if(b&&b.connectionModel){let c=a.xPos+a.width+this.constants_.DARK_PATH_OFFSET;this.info_.RTL&&(c*=-1);b.connectionModel.setOffsetInBlock(c,a.yPos)}}positionNextConnection_(){const a=this.info_.bottomRow;if(a.connection){const b= +a.getLastInput();if(b==null?0:b.connectionModel){let c=a.xPos+a.statementEdge+b.notchOffset;c=this.info_.RTL?c*-1:c+this.constants_.DARK_PATH_OFFSET;b.connectionModel.setOffsetInBlock(c,a.yPos+this.constants_.DARK_PATH_OFFSET)}}positionExternalValueConnection_(a){const b=a.getLastInput();if(b&&b.connectionModel){let c=a.xPos+a.width+this.constants_.DARK_PATH_OFFSET;this.info_.RTL&&(c*=-1);b.connectionModel.setOffsetInBlock(c,a.yPos)}}positionNextConnection_(){const a=this.info_.bottomRow;if(a.connection){const b= a.connection,c=b.xPos;b.connectionModel.setOffsetInBlock((this.info_.RTL?-c:c)+this.constants_.DARK_PATH_OFFSET/2,a.baseline+this.constants_.DARK_PATH_OFFSET)}}},module$build$src$core$renderers$geras$drawer={};module$build$src$core$renderers$geras$drawer.Drawer=Drawer$$module$build$src$core$renderers$geras$drawer;var HighlightConstantProvider$$module$build$src$core$renderers$geras$highlight_constants=class{constructor(a){this.OFFSET=.5;this.constantProvider=a;this.START_POINT=moveBy$$module$build$src$core$utils$svg_paths(this.OFFSET,this.OFFSET)}init(){this.INSIDE_CORNER=this.makeInsideCorner();this.OUTSIDE_CORNER=this.makeOutsideCorner();this.PUZZLE_TAB=this.makePuzzleTab();this.NOTCH=this.makeNotch();this.JAGGED_TEETH=this.makeJaggedTeeth();this.START_HAT=this.makeStartHat()}makeInsideCorner(){const a=this.constantProvider.CORNER_RADIUS, b=this.OFFSET,c=(1-Math.SQRT1_2)*(a+b)-b,d=moveBy$$module$build$src$core$utils$svg_paths(c,c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(-c-b,a-c)),e=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a+b,point$$module$build$src$core$utils$svg_paths(a+b,a+b)),f=moveBy$$module$build$src$core$utils$svg_paths(c,-c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a+b,point$$module$build$src$core$utils$svg_paths(a-c,c+b));return{width:a+ b,height:a,pathTop(g){return g?d:""},pathBottom(g){return g?e:f}}}makeOutsideCorner(){const a=this.constantProvider.CORNER_RADIUS,b=this.OFFSET,c=(1-Math.SQRT1_2)*(a-b)+b,d=moveBy$$module$build$src$core$utils$svg_paths(c,c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(a-c,-c+b)),e=moveBy$$module$build$src$core$utils$svg_paths(b,a)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(a,-a+ -b)),f=-c,g=moveBy$$module$build$src$core$utils$svg_paths(c,f)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(-c+b,-f-a));return{height:a,topLeft(h){return h?d:e},bottomLeft(){return g}}}makePuzzleTab(){const a=this.constantProvider.TAB_WIDTH,b=this.constantProvider.TAB_HEIGHT,c=moveBy$$module$build$src$core$utils$svg_paths(-2,-b+3.4)+lineTo$$module$build$src$core$utils$svg_paths(-.45*a,-2.1),d=lineOnAxis$$module$build$src$core$utils$svg_paths("v", -2.5)+moveBy$$module$build$src$core$utils$svg_paths(.97*-a,2.5)+curve$$module$build$src$core$utils$svg_paths("q",[point$$module$build$src$core$utils$svg_paths(.05*-a,10),point$$module$build$src$core$utils$svg_paths(.3*a,9.5)])+moveBy$$module$build$src$core$utils$svg_paths(.67*a,-1.9)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",2.5),e=lineOnAxis$$module$build$src$core$utils$svg_paths("v",-1.5)+moveBy$$module$build$src$core$utils$svg_paths(-.92*a,-.5)+curve$$module$build$src$core$utils$svg_paths("q", -[point$$module$build$src$core$utils$svg_paths(-.19*a,-5.5),point$$module$build$src$core$utils$svg_paths(0,-11)])+moveBy$$module$build$src$core$utils$svg_paths(.92*a,1),f=moveBy$$module$build$src$core$utils$svg_paths(-5,b-.7)+lineTo$$module$build$src$core$utils$svg_paths(.46*a,-2.1);return{width:a,height:b,pathUp(g){return g?c:e},pathDown(g){return g?d:f}}}makeNotch(){return{pathLeft:lineOnAxis$$module$build$src$core$utils$svg_paths("h",this.OFFSET)+this.constantProvider.NOTCH.pathLeft}}makeJaggedTeeth(){return{pathLeft:lineTo$$module$build$src$core$utils$svg_paths(5.1, +b)),f=-c,g=moveBy$$module$build$src$core$utils$svg_paths(c,f)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(-c+b,-f-a));return{height:a,topLeft(h){return h?d:e},bottomLeft(){return g}}}makePuzzleTab(){const a=this.constantProvider.TAB_WIDTH,b=this.constantProvider.TAB_HEIGHT,c=moveBy$$module$build$src$core$utils$svg_paths(-2,-b+2.5+.9)+lineTo$$module$build$src$core$utils$svg_paths(a*-.45,-2.1),d=lineOnAxis$$module$build$src$core$utils$svg_paths("v", +2.5)+moveBy$$module$build$src$core$utils$svg_paths(-a*.97,2.5)+curve$$module$build$src$core$utils$svg_paths("q",[point$$module$build$src$core$utils$svg_paths(-a*.05,10),point$$module$build$src$core$utils$svg_paths(a*.3,9.5)])+moveBy$$module$build$src$core$utils$svg_paths(a*.67,-1.9)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",2.5),e=lineOnAxis$$module$build$src$core$utils$svg_paths("v",-1.5)+moveBy$$module$build$src$core$utils$svg_paths(a*-.92,-.5)+curve$$module$build$src$core$utils$svg_paths("q", +[point$$module$build$src$core$utils$svg_paths(a*-.19,-5.5),point$$module$build$src$core$utils$svg_paths(0,-11)])+moveBy$$module$build$src$core$utils$svg_paths(a*.92,1),f=moveBy$$module$build$src$core$utils$svg_paths(-5,b-.7)+lineTo$$module$build$src$core$utils$svg_paths(a*.46,-2.1);return{width:a,height:b,pathUp(g){return g?c:e},pathDown(g){return g?d:f}}}makeNotch(){return{pathLeft:lineOnAxis$$module$build$src$core$utils$svg_paths("h",this.OFFSET)+this.constantProvider.NOTCH.pathLeft}}makeJaggedTeeth(){return{pathLeft:lineTo$$module$build$src$core$utils$svg_paths(5.1, 2.6)+moveBy$$module$build$src$core$utils$svg_paths(-10.2,6.8)+lineTo$$module$build$src$core$utils$svg_paths(5.1,2.6),height:12,width:10.2}}makeStartHat(){const a=this.constantProvider.START_HAT.height,b=moveBy$$module$build$src$core$utils$svg_paths(25,-8.7)+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(29.7,-6.2),point$$module$build$src$core$utils$svg_paths(57.2,-.5),point$$module$build$src$core$utils$svg_paths(75,8.7)]),c=curve$$module$build$src$core$utils$svg_paths("c", [point$$module$build$src$core$utils$svg_paths(17.8,-9.2),point$$module$build$src$core$utils$svg_paths(45.3,-14.9),point$$module$build$src$core$utils$svg_paths(75,-8.7)])+moveTo$$module$build$src$core$utils$svg_paths(100.5,a+.5);return{path(d){return d?b:c}}}},module$build$src$core$renderers$geras$highlight_constants={};module$build$src$core$renderers$geras$highlight_constants.HighlightConstantProvider=HighlightConstantProvider$$module$build$src$core$renderers$geras$highlight_constants;var InlineInput$$module$build$src$core$renderers$geras$measurables$inline_input=class extends InlineInput$$module$build$src$core$renderers$measurables$inline_input{constructor(a,b){super(a,b);this.constants_=a;this.connectedBlock&&(this.width+=this.constants_.DARK_PATH_OFFSET,this.height+=this.constants_.DARK_PATH_OFFSET)}},module$build$src$core$renderers$geras$measurables$inline_input={};module$build$src$core$renderers$geras$measurables$inline_input.InlineInput=InlineInput$$module$build$src$core$renderers$geras$measurables$inline_input;var StatementInput$$module$build$src$core$renderers$geras$measurables$statement_input=class extends StatementInput$$module$build$src$core$renderers$measurables$statement_input{constructor(a,b){super(a,b);this.constants_=a;this.connectedBlock&&(this.height+=this.constants_.DARK_PATH_OFFSET)}},module$build$src$core$renderers$geras$measurables$statement_input={};module$build$src$core$renderers$geras$measurables$statement_input.StatementInput=StatementInput$$module$build$src$core$renderers$geras$measurables$statement_input;var RenderInfo$$module$build$src$core$renderers$geras$info=class extends RenderInfo$$module$build$src$core$renderers$common$info{constructor(a,b){super(a,b);this.renderer_=a}getRenderer(){return this.renderer_}populateBottomRow_(){super.populateBottomRow_();this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1]instanceof StatementInput$$module$build$src$core$inputs$statement_input||(this.bottomRow.minHeight=this.constants_.MEDIUM_PADDING-this.constants_.DARK_PATH_OFFSET)}addInput_(a, b){if(this.isInline&&a instanceof $.ValueInput$$module$build$src$core$inputs$value_input)b.elements.push(new InlineInput$$module$build$src$core$renderers$geras$measurables$inline_input(this.constants_,a)),b.hasInlineInput=!0;else if(a instanceof StatementInput$$module$build$src$core$inputs$statement_input)b.elements.push(new StatementInput$$module$build$src$core$renderers$geras$measurables$statement_input(this.constants_,a)),b.hasStatement=!0;else if(a instanceof $.ValueInput$$module$build$src$core$inputs$value_input)b.elements.push(new ExternalValueInput$$module$build$src$core$renderers$measurables$external_value_input(this.constants_, -a)),b.hasExternalInput=!0;else if(a instanceof DummyInput$$module$build$src$core$inputs$dummy_input||a instanceof EndRowInput$$module$build$src$core$inputs$end_row_input)b.minHeight=Math.max(b.minHeight,this.constants_.DUMMY_INPUT_MIN_HEIGHT),b.hasDummyInput=!0;this.isInline||null!==b.align||(b.align=a.align)}addElemSpacing_(){let a=!1;for(let c=0,d;d=this.rows[c];c++)d.hasExternalInput&&(a=!0);for(let c=0,d;d=this.rows[c];c++){var b=d.elements;d.elements=[];d.startsWithElemSpacer()&&d.elements.push(new InRowSpacer$$module$build$src$core$renderers$measurables$in_row_spacer(this.constants_, +a)),b.hasExternalInput=!0;else if(a instanceof DummyInput$$module$build$src$core$inputs$dummy_input||a instanceof EndRowInput$$module$build$src$core$inputs$end_row_input)b.minHeight=Math.max(b.minHeight,this.constants_.DUMMY_INPUT_MIN_HEIGHT),b.hasDummyInput=!0;this.isInline||b.align!==null||(b.align=a.align)}addElemSpacing_(){let a=!1;for(let c=0,d;d=this.rows[c];c++)d.hasExternalInput&&(a=!0);for(let c=0,d;d=this.rows[c];c++){var b=d.elements;d.elements=[];d.startsWithElemSpacer()&&d.elements.push(new InRowSpacer$$module$build$src$core$renderers$measurables$in_row_spacer(this.constants_, this.getInRowSpacing_(null,b[0])));if(b.length){for(let e=0;e0&&this.addAlignmentPadding_(e,a),a=e.width)}else super.alignRowElements_()}getDesiredRowWidth_(a){return this.isInline&&a.hasStatement?this.statementEdge+ +this.constants_.MAX_BOTTOM_WIDTH+this.startX:super.getDesiredRowWidth_(a)}finalize_(){let a=0,b=0;for(let d=0,e;e=this.rows[d];d++){e.yPos=b;e.xPos=this.startX;b+=e.height;a=Math.max(a,e.widthWithConnectedBlocks);var c=b-this.topRow.ascenderHeight;e===this.bottomRow&&c>>/sprites.png);\n height: 16px;\n vertical-align: middle;\n visibility: hidden;\n width: 16px;\n}\n\n.blocklyTreeIconClosed {\n background-position: -32px -1px;\n}\n\n.blocklyToolboxDiv[dir="RTL"] .blocklyTreeIconClosed {\n background-position: 0 -1px;\n}\n\n.blocklyTreeSelected>.blocklyTreeIconClosed {\n background-position: -32px -17px;\n}\n\n.blocklyToolboxDiv[dir="RTL"] .blocklyTreeSelected>.blocklyTreeIconClosed {\n background-position: 0 -17px;\n}\n\n.blocklyTreeIconOpen {\n background-position: -16px -1px;\n}\n\n.blocklyTreeSelected>.blocklyTreeIconOpen {\n background-position: -16px -17px;\n}\n\n.blocklyTreeLabel {\n cursor: default;\n font: 16px sans-serif;\n padding: 0 3px;\n vertical-align: middle;\n}\n\n.blocklyToolboxDelete .blocklyTreeLabel {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyTreeSelected .blocklyTreeLabel {\n color: #fff;\n}\n'); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX_ITEM,ToolboxCategory$$module$build$src$core$toolbox$category.registrationName,ToolboxCategory$$module$build$src$core$toolbox$category);var module$build$src$core$toolbox$category={};module$build$src$core$toolbox$category.ToolboxCategory=ToolboxCategory$$module$build$src$core$toolbox$category;var ToolboxSeparator$$module$build$src$core$toolbox$separator=class extends ToolboxItem$$module$build$src$core$toolbox$toolbox_item{constructor(a,b){super(a,b);this.cssConfig_={container:"blocklyTreeSeparator"};this.htmlDiv=null;Object.assign(this.cssConfig_,a.cssconfig||a.cssConfig)}init(){this.createDom_()}createDom_(){const a=document.createElement("div"),b=this.cssConfig_.container;b&&addClass$$module$build$src$core$utils$dom(a,b);return this.htmlDiv=a}getDiv(){return this.htmlDiv}dispose(){removeNode$$module$build$src$core$utils$dom(this.htmlDiv)}}; -ToolboxSeparator$$module$build$src$core$toolbox$separator.registrationName="sep";register$$module$build$src$core$css('\n.blocklyTreeSeparator {\n border-bottom: solid #e5e5e5 1px;\n height: 0;\n margin: 5px 0;\n}\n\n.blocklyToolboxDiv[layout="h"] .blocklyTreeSeparator {\n border-right: solid #e5e5e5 1px;\n border-bottom: none;\n height: auto;\n margin: 0 5px 0 5px;\n padding: 5px 0;\n width: 0;\n}\n'); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX_ITEM,ToolboxSeparator$$module$build$src$core$toolbox$separator.registrationName,ToolboxSeparator$$module$build$src$core$toolbox$separator);var module$build$src$core$toolbox$separator={};module$build$src$core$toolbox$separator.ToolboxSeparator=ToolboxSeparator$$module$build$src$core$toolbox$separator;var CollapsibleToolboxCategory$$module$build$src$core$toolbox$collapsible_category=class extends ToolboxCategory$$module$build$src$core$toolbox$category{constructor(a,b,c){super(a,b,c);this.subcategoriesDiv_=null;this.expanded_=!1;this.toolboxItems_=[]}makeDefaultCssConfig_(){const a=super.makeDefaultCssConfig_();a.contents="blocklyToolboxContents";return a}parseContents_(a){if("custom"in a)this.flyoutItems_=a.custom;else{const b=a.contents;if(b){this.flyoutItems_=[];a=!0;for(let c=0;c>>/sprites.png);\n height: 16px;\n vertical-align: middle;\n visibility: hidden;\n width: 16px;\n}\n\n.blocklyToolboxCategoryIconClosed {\n background-position: -32px -1px;\n}\n\n.blocklyToolbox[dir="RTL"] .blocklyToolboxCategoryIconClosed {\n background-position: 0 -1px;\n}\n\n.blocklyToolboxSelected>.blocklyToolboxCategoryIconClosed {\n background-position: -32px -17px;\n}\n\n.blocklyToolbox[dir="RTL"] .blocklyToolboxSelected>.blocklyToolboxCategoryIconClosed {\n background-position: 0 -17px;\n}\n\n.blocklyToolboxCategoryIconOpen {\n background-position: -16px -1px;\n}\n\n.blocklyToolboxSelected>.blocklyToolboxCategoryIconOpen {\n background-position: -16px -17px;\n}\n\n.blocklyToolboxCategoryLabel {\n cursor: default;\n font: 16px sans-serif;\n padding: 0 3px;\n vertical-align: middle;\n}\n\n.blocklyToolboxDelete .blocklyToolboxCategoryLabel {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyToolboxSelected .blocklyToolboxCategoryLabel {\n color: #fff;\n}\n'); +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX_ITEM,ToolboxCategory$$module$build$src$core$toolbox$category.registrationName,ToolboxCategory$$module$build$src$core$toolbox$category);var module$build$src$core$toolbox$category={};module$build$src$core$toolbox$category.ToolboxCategory=ToolboxCategory$$module$build$src$core$toolbox$category;var ToolboxSeparator$$module$build$src$core$toolbox$separator=class extends ToolboxItem$$module$build$src$core$toolbox$toolbox_item{constructor(a,b){super(a,b);this.cssConfig_={container:"blocklyTreeSeparator"};this.htmlDiv=null;Object.assign(this.cssConfig_,a.cssconfig||a.cssConfig)}init(){this.createDom_()}createDom_(){const a=document.createElement("div");a.tabIndex=-1;a.id=this.getId();const b=this.cssConfig_.container;b&&addClass$$module$build$src$core$utils$dom(a,b);return this.htmlDiv=a}getDiv(){return this.htmlDiv}dispose(){removeNode$$module$build$src$core$utils$dom(this.htmlDiv)}}; +ToolboxSeparator$$module$build$src$core$toolbox$separator.registrationName="sep";register$$module$build$src$core$css('\n.blocklyTreeSeparator {\n border-bottom: solid #e5e5e5 1px;\n height: 0;\n margin: 5px 0;\n}\n\n.blocklyToolbox[layout="h"] .blocklyTreeSeparator {\n border-right: solid #e5e5e5 1px;\n border-bottom: none;\n height: auto;\n margin: 0 5px 0 5px;\n padding: 5px 0;\n width: 0;\n}\n'); +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX_ITEM,ToolboxSeparator$$module$build$src$core$toolbox$separator.registrationName,ToolboxSeparator$$module$build$src$core$toolbox$separator);var module$build$src$core$toolbox$separator={};module$build$src$core$toolbox$separator.ToolboxSeparator=ToolboxSeparator$$module$build$src$core$toolbox$separator;var CollapsibleToolboxCategory$$module$build$src$core$toolbox$collapsible_category=class extends ToolboxCategory$$module$build$src$core$toolbox$category{constructor(a,b,c){super(a,b,c);this.subcategoriesDiv_=null;this.expanded_=!1;this.toolboxItems_=[]}makeDefaultCssConfig_(){const a=super.makeDefaultCssConfig_();a.contents="blocklyToolboxCategoryGroup";return a}parseContents_(a){if("custom"in a)this.flyoutItems_=a.custom;else{const b=a.contents;if(b){this.flyoutItems_=[];a=!0;for(let c=0;c>>/handdelete.cur"), auto;\n}\n\n.blocklyToolboxGrab {\n cursor: url("<<>>/handclosed.cur"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n/* Category tree in Toolbox. */\n.blocklyToolboxDiv {\n background-color: #ddd;\n overflow-x: visible;\n overflow-y: auto;\n padding: 4px 0 4px 0;\n position: absolute;\n z-index: 70; /* so blocks go under toolbox when dragging */\n -webkit-tap-highlight-color: transparent; /* issue #1345 */\n}\n\n.blocklyToolboxContents {\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n}\n\n.blocklyToolboxContents:focus {\n outline: none;\n}\n'); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX,DEFAULT$$module$build$src$core$registry,Toolbox$$module$build$src$core$toolbox$toolbox);var module$build$src$core$toolbox$toolbox={};module$build$src$core$toolbox$toolbox.Toolbox=Toolbox$$module$build$src$core$toolbox$toolbox;var VERSION$$module$build$src$core$blockly="11.2.2",INPUT_VALUE$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE,OUTPUT_VALUE$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE,NEXT_STATEMENT$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT,PREVIOUS_STATEMENT$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT, +module$build$src$core$toolbox$collapsible_category.CollapsibleToolboxCategory=CollapsibleToolboxCategory$$module$build$src$core$toolbox$collapsible_category;var module$build$src$core$interfaces$i_selectable_toolbox_item={};module$build$src$core$interfaces$i_selectable_toolbox_item.isSelectableToolboxItem=isSelectableToolboxItem$$module$build$src$core$interfaces$i_selectable_toolbox_item;var Toolbox$$module$build$src$core$toolbox$toolbox=class extends DeleteArea$$module$build$src$core$delete_area{constructor(a){super();this.id="toolbox";this.contentsDiv_=this.HtmlDiv=null;this.isVisible_=!1;this.height_=this.width_=0;this.flyout=null;this.contents=new Map;this.previouslySelectedItem_=this.selectedItem_=null;this.boundEvents_=[];this.mouseDown=!1;this.workspace_=a;this.toolboxDef_=a.options.languageTree||{contents:[]};this.horizontalLayout=a.options.horizontalLayout;this.RTL=a.options.RTL; +this.toolboxPosition=a.options.toolboxPosition}onShortcut(a){return!1}init(){var a=this.workspace_;const b=a.getParentSvg();this.flyout=this.createFlyout_();this.HtmlDiv=this.createDom_(this.workspace_);const c=this.flyout.createDom("svg");addClass$$module$build$src$core$utils$dom(c,"blocklyToolboxFlyout");insertAfter$$module$build$src$core$utils$dom(c,b);this.setVisible(!0);this.flyout.init(a);this.render(this.toolboxDef_);a=a.getThemeManager();a.subscribe(this.HtmlDiv,"toolboxBackgroundColour", +"background-color");a.subscribe(this.HtmlDiv,"toolboxForegroundColour","color");this.workspace_.getComponentManager().addComponent({component:this,weight:ComponentManager$$module$build$src$core$component_manager.ComponentWeight.TOOLBOX_WEIGHT,capabilities:[ComponentManager$$module$build$src$core$component_manager.Capability.AUTOHIDEABLE,ComponentManager$$module$build$src$core$component_manager.Capability.DELETE_AREA,ComponentManager$$module$build$src$core$component_manager.Capability.DRAG_TARGET]}); +$.getFocusManager$$module$build$src$core$focus_manager().registerTree(this,!0)}createDom_(a){a=a.getParentSvg();const b=this.createContainer_();b.id=getNextUniqueId$$module$build$src$core$utils$idgenerator();this.contentsDiv_=this.createContentsContainer_();setRole$$module$build$src$core$utils$aria(this.contentsDiv_,Role$$module$build$src$core$utils$aria.TREE);b.appendChild(this.contentsDiv_);let c;(c=a.parentNode)==null||c.insertBefore(b,a);this.attachEvents_(b,this.contentsDiv_);return b}createContainer_(){const a= +document.createElement("div");a.setAttribute("layout",this.isHorizontal()?"h":"v");addClass$$module$build$src$core$utils$dom(a,"blocklyToolbox");a.setAttribute("dir",this.RTL?"RTL":"LTR");return a}createContentsContainer_(){const a=document.createElement("div");addClass$$module$build$src$core$utils$dom(a,"blocklyToolboxCategoryGroup");this.isHorizontal()&&(a.style.flexDirection="row");return a}attachEvents_(a,b){const c=conditionalBind$$module$build$src$core$browser_events(a,"pointerdown",this,this.onClick_, +!1);this.boundEvents_.push(c);a=bind$$module$build$src$core$browser_events(a,"pointerup",this,()=>{this.mouseDown=!1});this.boundEvents_.push(a);b=conditionalBind$$module$build$src$core$browser_events(b,"keydown",this,this.onKeyDown_,!1);this.boundEvents_.push(b)}onClick_(a){this.mouseDown=!0;if(isRightButton$$module$build$src$core$browser_events(a)||a.target===this.HtmlDiv)getMainWorkspace$$module$build$src$core$common().hideChaff(!1);else{var b=a.target.getAttribute("id");b&&(b=this.getToolboxItemById(b), +b==null?0:b.isSelectable())&&(this.setSelectedItem(b),b.onClick(a));getMainWorkspace$$module$build$src$core$common().hideChaff(!0)}clearTouchIdentifier$$module$build$src$core$touch()}onKeyDown_(a){let b=!1;switch(a.key){case "ArrowDown":b=this.selectNext();break;case "ArrowUp":b=this.selectPrevious();break;case "ArrowLeft":b=this.selectParent();break;case "ArrowRight":b=this.selectChild();break;case "Enter":case " ":this.selectedItem_&&this.selectedItem_.isCollapsible()&&(this.selectedItem_.toggleExpanded(), +b=!0);break;default:b=!1}!b&&this.selectedItem_&&this.selectedItem_.onKeyDown&&(b=this.selectedItem_.onKeyDown(a));b&&a.preventDefault()}createFlyout_(){const a=this.workspace_,b=a.copyOptionsForFlyout();b.toolboxPosition=a.options.toolboxPosition;return new (a.horizontalLayout?getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,a.options,!0):getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX, +a.options,!0))(b)}render(a){this.toolboxDef_=a;this.contents.forEach(b=>b.dispose());this.contents.clear();this.renderContents_(a.contents);this.position();this.handleToolboxItemResize()}renderContents_(a){const b=document.createDocumentFragment();for(let d=0;d +{a.refreshTheme&&a.refreshTheme()})}refreshSelection(){if(this.selectedItem_&&this.selectedItem_.isSelectable()&&this.selectedItem_.getContents().length){let a;(a=this.flyout)==null||a.show(this.selectedItem_.getContents())}}setVisible(a){this.isVisible_!==a&&(this.HtmlDiv&&(this.HtmlDiv.style.display=a?"block":"none"),this.isVisible_=a,this.workspace_.recordDragTargets())}autoHide(a){!a&&this.flyout&&this.flyout.autoClose&&this.clearSelection()}setSelectedItem(a){const b=this.selectedItem_;!a&&!b|| +a&&!isSelectableToolboxItem$$module$build$src$core$interfaces$i_selectable_toolbox_item(a)||(this.shouldDeselectItem_(b,a)&&b!==null&&this.deselectItem_(b),this.shouldSelectItem_(b,a)&&a!==null&&this.selectItem_(b,a),this.updateFlyout_(b,a),this.fireSelectEvent(b,a))}shouldDeselectItem_(a,b){return a!==null&&(!a.isCollapsible()||a!==b)}shouldSelectItem_(a,b){return b!==null&&b!==a}deselectItem_(a){this.selectedItem_=null;this.previouslySelectedItem_=a;a.setSelected(!1);setState$$module$build$src$core$utils$aria(this.contentsDiv_, +State$$module$build$src$core$utils$aria.ACTIVEDESCENDANT,"")}selectItem_(a,b){this.selectedItem_=b;this.previouslySelectedItem_=a;b.setSelected(!0);setState$$module$build$src$core$utils$aria(this.contentsDiv_,State$$module$build$src$core$utils$aria.ACTIVEDESCENDANT,b.getId())}selectItemByPosition(a){(a=this.getToolboxItems()[a])&&this.setSelectedItem(a)}updateFlyout_(a,b){if(b&&(a!==b||b.isCollapsible())&&b.getContents().length){let c;(c=this.flyout)==null||c.show(b.getContents());let d;(d=this.flyout)== +null||d.scrollToStart()}else{let c;(c=this.flyout)==null||c.hide()}}fireSelectEvent(a,b){const c=a&&a.getName();let d=b&&b.getName();a===b&&(d=null);a=new (get$$module$build$src$core$events$utils(EventType$$module$build$src$core$events$type.TOOLBOX_ITEM_SELECT))(c,d,this.workspace_.id);fire$$module$build$src$core$events$utils(a)}selectParent(){if(!this.selectedItem_)return!1;if(this.selectedItem_.isCollapsible()&&this.selectedItem_.isExpanded())return this.selectedItem_.toggleExpanded(),!0;let a; +return((a=this.selectedItem_.getParent())==null?0:a.isSelectable())?(this.setSelectedItem(this.selectedItem_.getParent()),!0):!1}selectChild(){if(!this.selectedItem_||!this.selectedItem_.isCollapsible())return!1;const a=this.selectedItem_;a.isExpanded()?this.selectNext():a.toggleExpanded();return!0}selectNext(){if(!this.selectedItem_)return!1;const a=[...this.contents.values()];let b=a.indexOf(this.selectedItem_)+1;if(b>-1&&b-1&&bb.dispose());for(a=0;ac.isSelectable()))!=null?b:null}return null}getNestedTrees(){return[]}lookUpFocusableNode(a){return this.getToolboxItemById(a)}onTreeFocus(a,b){a!==this?this.getSelectedItem()===a||this.mouseDown||this.setSelectedItem(a):this.clearSelection()}onTreeBlur(a){let b;a&&a===((b=this.flyout)==null?void 0:b.getWorkspace())||this.autoHide(!1)}};register$$module$build$src$core$css('\n.blocklyToolboxDelete {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyToolboxGrab {\n cursor: url("<<>>/handclosed.cur"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n/* Category tree in Toolbox. */\n.blocklyToolbox {\n box-sizing: border-box;\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n background-color: #ddd;\n overflow-x: visible;\n overflow-y: auto;\n padding: 4px 0 4px 0;\n position: absolute;\n z-index: 70; /* so blocks go under toolbox when dragging */\n -webkit-tap-highlight-color: transparent; /* issue #1345 */\n}\n\n.blocklyToolboxCategoryGroup {\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n}\n\n.blocklyToolboxCategoryGroup:focus {\n outline: none;\n}\n'); +register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX,DEFAULT$$module$build$src$core$registry,Toolbox$$module$build$src$core$toolbox$toolbox);var module$build$src$core$toolbox$toolbox={};module$build$src$core$toolbox$toolbox.Toolbox=Toolbox$$module$build$src$core$toolbox$toolbox;var module$build$src$core$interfaces$i_navigation_policy={};var VERSION$$module$build$src$core$blockly="12.5.1",INPUT_VALUE$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE,OUTPUT_VALUE$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE,NEXT_STATEMENT$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT,PREVIOUS_STATEMENT$$module$build$src$core$blockly=ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT, TOOLBOX_AT_TOP$$module$build$src$core$blockly=Position$$module$build$src$core$utils$toolbox.TOP,TOOLBOX_AT_BOTTOM$$module$build$src$core$blockly=Position$$module$build$src$core$utils$toolbox.BOTTOM,TOOLBOX_AT_LEFT$$module$build$src$core$blockly=Position$$module$build$src$core$utils$toolbox.LEFT,TOOLBOX_AT_RIGHT$$module$build$src$core$blockly=Position$$module$build$src$core$utils$toolbox.RIGHT,svgResize$$module$build$src$core$blockly=svgResize$$module$build$src$core$common,getMainWorkspace$$module$build$src$core$blockly= getMainWorkspace$$module$build$src$core$common,getSelected$$module$build$src$core$blockly=getSelected$$module$build$src$core$common,defineBlocksWithJsonArray$$module$build$src$core$blockly=defineBlocksWithJsonArray$$module$build$src$core$common,setParentContainer$$module$build$src$core$blockly=setParentContainer$$module$build$src$core$common,COLLAPSE_CHARS$$module$build$src$core$blockly=COLLAPSE_CHARS$$module$build$src$core$internal_constants,OPPOSITE_TYPE$$module$build$src$core$blockly=OPPOSITE_TYPE$$module$build$src$core$internal_constants, RENAME_VARIABLE_ID$$module$build$src$core$blockly=RENAME_VARIABLE_ID$$module$build$src$core$internal_constants,DELETE_VARIABLE_ID$$module$build$src$core$blockly=DELETE_VARIABLE_ID$$module$build$src$core$internal_constants,COLLAPSED_INPUT_NAME$$module$build$src$core$blockly=COLLAPSED_INPUT_NAME$$module$build$src$core$constants,COLLAPSED_FIELD_NAME$$module$build$src$core$blockly=COLLAPSED_FIELD_NAME$$module$build$src$core$constants,VARIABLE_CATEGORY_NAME$$module$build$src$core$blockly=CATEGORY_NAME$$module$build$src$core$variables, VARIABLE_DYNAMIC_CATEGORY_NAME$$module$build$src$core$blockly=CATEGORY_NAME$$module$build$src$core$variables_dynamic,PROCEDURE_CATEGORY_NAME$$module$build$src$core$blockly=CATEGORY_NAME$$module$build$src$core$procedures;Workspace$$module$build$src$core$workspace.prototype.newBlock=function(a,b){return new Block$$module$build$src$core$block(this,a,b)};WorkspaceSvg$$module$build$src$core$workspace_svg.prototype.newBlock=function(a,b){return new BlockSvg$$module$build$src$core$block_svg(this,a,b)}; Workspace$$module$build$src$core$workspace.prototype.newComment=function(a){return new WorkspaceComment$$module$build$src$core$comments$workspace_comment(this,a)};WorkspaceSvg$$module$build$src$core$workspace_svg.prototype.newComment=function(a){return new RenderedWorkspaceComment$$module$build$src$core$comments$rendered_workspace_comment(this,a)};WorkspaceSvg$$module$build$src$core$workspace_svg.newTrashcan=function(a){return new Trashcan$$module$build$src$core$trashcan(a)}; MiniWorkspaceBubble$$module$build$src$core$bubbles$mini_workspace_bubble.prototype.newWorkspaceSvg=function(a){return new WorkspaceSvg$$module$build$src$core$workspace_svg(a)};$.Names$$module$build$src$core$names.prototype.populateProcedures=function(a){a=allProcedures$$module$build$src$core$procedures(a);a=a[0].concat(a[1]);for(let b=0;bS4T_I;7qX~&LkdY!roq9>%9EDy)D25XYk`Pxlv((8**}U z#o1|alvoJoq=LU(L2_mm9Gfpr$-seG>w~#rfncfM67Ukt;WA^nfwB3?l1y>FC>IQc zMzh&r?{Z@UV{>GZ6j1=YH9tQ$V9lCs+qSLF6-skt*+S{+97)<5Gr1<$tZ#FsShzVS z75tg>ZI+_?V0MmBoGKOx;pA)~ED>di-v_i{I~<;qla?uhnb|3;F^kM*A|au17zhh? zK#zj;MPt=G2qHkx78k^}HkFB}70qtj8x#>JrS~dtP?YOQDV21?uN~|obbufWsK^ah z)jGpWA7P}CT&pBa4Dq}E$6>3An0pM|UUfK=9WdBSh^3Q|5Q0U;mm%#95+KTK77P^uGokQ9MCKXd&>8ZzahK@t zJYwv9$Jd6%a@joa$dcjqkyK}B2>85OY zs&IPhz~*J8e+1TVnFE2Ok(+W-A*iJHtBT(Z!I=a6Yv$w;`wx+?9&(B7a$!$+T>H)^ z`l-*jeOQbSJJum-+(CBTQ55T!blq2UohOR|R`d6)D*0?0pyt%zTtz4-&eDsl~#rhAKv$f)QL&fp3irKO%xAJ;% zxl((fC3CQIzW4vO-!dm$;sP4ToG^*YYngM2P7Vdx)aAi`YPKoAo5T93;sexmRj|$F_D#%({#bDASwJxmR74-3 zUm;0Gm{*(DkI->P6ax%bb?pQb@vJAUMX2p|DGyYw6U?h^3Q}ankv6-OavfL%S%Kf; z=CNuAOb`)*1bB`$Qlj9DAT!mRLHa{7hs8LqiXCBKSI7tHmPd*Sh?*Qbg7lN+!@&<# z#bd#45CmVsfM1B4k1z}(xI*`GT}EqtB8k*U`>;`>Xv&^FRp)cf$2W${8?xt3a(QH3F_|s=jcu zF)OLzl_)mRB+8FB)#DqJ&x_%S61cpC0#U+qUc9j|5^!VLw;Xu99^S2IS-kqf`}w@2 zc+suryadNxiBl!_e<-|9LM2a4$^bXnC`vvjn|2c`#px|4v`ROvR-^67(st?+TjsPa z+QF_gZD+?|*Qt}8ne%|#c|zOeq1Aev?CN--^_cHDq3zWTcAakQJUQR<&Eh_f`QBV@ zXXnYTCn&d9H*d(B@AcZ*jtsS*eB7()?aiL=%^U8?BDZQEe@Yv=e0s3!oB7@~XJwQa zp6sq7=|McOBWv@vqlwQ;y0ZTIneN3P5HRsC#%K=t0$BD@_8VZ#@YMb7WdAC4niA|( zt83JrobSqZ@9UTkiQyF{)rqFpB_%A&o?cg#ICY>!`?!}j^eIq8|H6<%{@9D0bjJ@c zj&$i37p4q6$Bky(G331nc<_U)^%Nf0e-K~;gJQ#eFsPa0zM#k-16fjLiLnHl9?mCl z9>Z;1x+O*WE=x~VY+$8R6gOxFm|MjhP}SP8wjzoNj#aaI11qChVdP|-X}=-(2i)e! z5_>8p_~{zM4Swa)6oU6`n{b4QQ=df{K-6qgn{5b7-A0ULdBzO`Ah%8gM`+sYVwsw5 zAWGfl7|Ejd5EHZMMlx8@W|zoB48+(hPlIxm0S2P3qRLG=9yTa|sKdoIES9dWhBK_H zMMV`?v6x6t4J!)lip4rp!r^DqjVey2FW40jRl~~kH1HFnx@83ZV$-g4-EkS|Is;Hn zRg)rFXSy9TvgtF+Sz;ZkT%&hPtOCkoGkn{P=_n&HE6}KvvUJ89oCAQ7l67%Xx#OE( zEf=JF8jJ!Rs+@MFt_CQdxy`R+C?*6zR1K#RtVqnf&|aSo7)s9m?wQ-tOy3`F@HCpG*v^l>Od!G8h+ zXk_{p5CE(U{7{xozcHheqBaUTe5U}2yJwUcEWpUPb^(IESY!pAUie0spDPJR^AVbi zD1w0-E9s>~K?QwQ6^cdl4WPzpC!wVW_{gI5M`bpInXiiU2J`D{HT&ASP=X);J|LqNeAZzpheM;P>(Qg* z2A|~#WLr_yMov1=5`a~oy@9H_861JAjr{$dAmv!#RZ!_$$^ldKHw7K^wh0c%Pf|(; zNFaU&*m{O1(rpw}b_4%|6T&Fi?`z~QhVEtOLPZg$^GfU5KDs=9&lGD4D7HgP-bOD5 z91x2p6fKnXEPyH$BNRCZgLzC|{o5EJVAc#R0H|5>JjI3(6ST0+U<_FSK;~wmsDQ$m z3pf)P<#wQyQvk{4F@+t_VJhzw92AkjH7LUbRTG7ypzbnFrkK~FwIG1#Li7|~HRsYg z=$z?u|MJ2OTL)NB5gvl_Zl=#8#sOHblGjJdt0e@%>ZP0tM)(;~gp-~$si3Qgv7C%K zm7p>v`bY|k-q)dsW4RsLJ0a=lE*J*4Ulye}(Z z|4`ZVZ%wcniLe7ykR&P;Xa?3ye`rmfS;o8fNIphV@Yd>1J*zERk$4~57Gpga z<=6cB);VnYXJ`C7J-0We)Xha7T8y`ysj?3xx%%H^I3gFj%U+UniJ@KJCqCS5y>rni zlFjm)`(_I{MUkWvtD~$=xYzDuC9nF6h4|+M%XODn%|A6R!(={t4+r&aqtvTDTR6wt z(E0g6;iC!CUn5Q=F;lNCeU$BW|GOmSroE}z?jKvqe=MMt#x1$K^JVRVO9UB`AAH+?lzm%p z1{*OoyDC~2yvA{|wBY%m$HfoEr(eFDn~YrWN#O44%&c#(*VYUW8=}3SZR50+b&>qM zxcCR>eP4+5OETUHu=zUuse4@FjUC3L8u14ODJ0uU>gIE|zX`wiY2M#!by-+9-^KoO zeJ}QBQO_Ma+Ub;B>A9{pn|5Hj_BxTTyL(j`e$?g0&p8<2ox_Kd!;juM{mwD$hBLOe zpWo-*oe_@yVnOE*4^^(d)lrW|-?kAh+P0$SyGn*^ho|&;Rtx^% p7k4FIZ@TV#xbK&J-v%`HU5P#@S^9X{;VrAfeySU))r708{sTaExM%T7p^9ndf_EzHQ$3of#W9Y}f@)fC>4I3RdDtcslIgiiG%1X;f4SFXnB`9;I9I~b- zrOyo-my?z}N3M(>n_!iz#^ofOdL$jp?qnQ1dpf|4>)g67Yd zo3=>Kr!NkQ&CEjjXKl#}$p10a$V5G(8wK{$@Ms5jfg zCMe65Y!=5R8M|9{nFh1f@H+X0fT(NEuDtzh(?&i5>(uCyEx*a`2A+3pL=ew zJ;KpB)FYwl-`5+95B~h*a_z&Jrol5SE z-;;|EuE1x(hOgb1e_IE^OgtylbCY zHRnb2i_FR}+fJr>1^K76a(Sj2^0oKv2kc&&AKhjx@rw0f?kicf>yL)OnlGz^8~eG2 zQcp{r+coQU!8lQOvE6HY^eW1E5Br+j-A}tOu*9=pwSzXlrnKh2oXHq(EVX{` zcEdcJUE&>G>m1WvLjRr&R92fzrWfo4&eEMm1o@yqaN){Q6##71+Ch)r6M;odo>7B(Sh^KSdF7}Ad zC2b)MCt@-N;5Na;dwi+x(!SMKidoQuzF^tP0OM^X(ojRjpk3dr4bn=qX?!3ag9&6a z`HGAow_yN0!3G=wV<8;Ma2<9*1J;Ws@mTmtyBB#z+R~rNDDnXeMn$yZEA(W2vp$il zq7$j3UmH|qq;Z7eqE;Bj!?Z{>MV+OodNMAj;YzOYnsSUaLO=0X>#Ca7f%*;ngT7

~Kv18<{tYx#Fqpj22d0W|!J;axGqUq#0ju4-7Dk3onMvxkUB#{h-^Wq$Law|@T zTjT~s$)xQh1`32P|6H%s-{y2? z_zgDUY5W{1L_!tr!|j-cFGYb^B7T)S4#5+$lYUEIkaO@co)BZjFmXa;;#?R{@<|!k z(I2OaFmY7WVH%l7f1?Ewy@#=zn8%m$5HVJs*ll`@g|nrkBYN_y+6HZr?khsTm-b+N z*<17=grh|aF{vBq}uRHE|4vv3C@q1S-IW zz(q7lE@gZ=Cb}_ivVOk6sB0&$=iZvUr zfOK}x;4sv%U1YD&w0yNptx*O+O++NDtP^aEmRb@jykc?xh#&UBn$6MB?Z+%IF1{jzh&xewMElNAM{;Cb@Ja zEh4Ao+3&`AScG9P3;MuKoPb@i6~2v+Fb^JsfwUuCNqbTXn_(hkLjlZ%1{{jdM3tC= ze_{x%g6pscJfJH^i4s0Zyos&gZ@5Sn(oMAdpWP6KE5t&HxVu;igdUalOJp`wix>Pj zZ!J7A7p(Lxmd9RWA=E^CAqH2AY2u=oj5o0Z^acwY#HkpI^YNHO=R`OG=OG?;V7SaQ z0XJedh#)QKWLifCla=s`#6^in!fo(18A6xQN%RcaC)L5hyYpz?z@1_cY#|HiT56;n zNEdihYSS9whR<;`G(j1hg++i86#=M=R=5z$a0nDbAF_d5AU}~j(vo~6kytEOjF;s>G4Z4zHB$AZF3aG{5cv2*Z@#2m+j76}YMADvgCpiU6aiB=%akA#s_&S+J|EBxt zJ#ts}KTq7}ErdUwgIL;zxv|;wJ<=cIFkd3MS(M0H9MD}>w+-SkSS;lmc@L2&QJh4- zV1KbT>L_(u27`{*l-j0l8I!zL`qj!jRP^c36+(IVK>r?eQJwlY>C*&l3joqSuO5a^DRfLOl;fn$#^QEG!CUx+Z zRJ@xaTTBtXL{BkND%pGJC(%VncX^|PlJ})r4#knU8Vj)sBVj9?gY^>WQJ5r(`A%NV zFNj(UBtbO4X?WAt=1SWwJGURPZ?&Ja?{Q30?c!af$}P?N8y`RKjUL%FY+jdf>6iFU-b(BWZMZ8II+)C%5-x*G>roK}NdiRF$dR#`+p!ce|n z>#eEUSG>Dq9-;9p$?&#PqI{-g84~GAJf`?QN+xa9Gse_&oB3VU_Wg@wn2J z-NPsPZZ*o4=z6J+=SSc-!&LJR)&*{Zt-a*?KLFFT66az^f@81q4J}zT5sOk`++zwf zX@;{TR9sS{oZTGZjv!}ywO(%vomif7z<5r+WzMo}vI2cYF2BN0i&6|GGwE1%i*060 zs0TTXlSHFlqlIZ)&DYlGcX% diff --git a/appinventor/lib/blockly/media/delete.ogg b/appinventor/lib/blockly/media/delete.ogg deleted file mode 100644 index 67f84ac19a05075a52de49829b3a2bc17af9e29c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5731 zcmai12~<UMQkbya=Ux7sx%#2s1z zeSLnbQ<2iDyGCVU8(<01Y(^MI!h<=~eVuXuCMB-GTqP_2dL%0)9N*9zRD^ix|2aBlfNoisNpYyS00CJUftSg$j*} zi?K2>IdI^>mY5(;bbM40XG=6Y#AKN?VMIr>{H4M{AHwAL2XHvi>^No+iV__Z790kM zfT$o8n;98)5YUW6s9n*~ArVXzDJpOaOm5jKw4J>N3{nK@aV{uf(m)O!f)Eh2UmvZU z7feF)d1Xe23VBWvN@$u<$jcBS1G8|VKRXmY2$(DjB^klF6%(ZJK4J*ckjpM5hV8bj zMk!>vJte|#&20*ds%oiXMfIT#6jyu8K_Fx{PP%F8R7uA;p_`5b-H+PrPTlGf_Dal! z(&H=5I#DSuW^XFmDGe*C`i~auUBLX` z%_g)H1K9vy-ig(|6RYn?)xX0wR*-tQ69O@{p&AR>_+1?Q9nSZl?TT~g;Ow5$nCI8pWzRWwla;Vx0R=v8TrdhyWB3|g__)tbU$X#^wsv|fN%qPx!sOV11x zar#I~Mf_#zkZQ3)ea#>k)0!+%7HI{5d0~S^3N>S1V6FE+(Zq$T>VV4N6&to*r7g?* z3X7V3C4D!E&%la|2gR(ba6dqO3MzSb7cLq5Cwy!`+yX|CqO-?QiClSxx^9(j-iEkS z%6X-@PITplZ0=5SP0AjsmLWgxxYTkK1f?RRDE_mPLU|d*mARRiZlg=RWS>kB=mdk7WC=P5&pb z{>mH(Bu%O`CwYu4+?|q?-FEQh0RNdevFdkDYj>U2cW&0F3>x449q;-9e^1TP4Nq~` z@VloGKcvZYx9}SxFo)>O;RNPb8`Jl4qIcWZgjr6T@sap%GDngkdPMFEr(D^;GpE#u z``nVdk(8_NoxAB!K}beX&6#s=YRXssBXdGCs|z!$Ph?J>;2LEVgk=;7u9io1H%zzx z&-Pd5>|*PK1~SKyt^ZBt+`wtugKTOxrhHho(fS^6Xq@BPZvy~9H*%DmrRRtn6+28N z3{$amn)QFr7{DFIQ-<)svH1|B1wk7@kW&$v>>Rr&YcECIguYxEQNHXpGPN3Eu0&j| z7nfseXniG@*rD{{Db+~B!6hZzU@I53`c~Cm(kn|vaO}xKZV;4&>%`qgvinF~r4D^K z_*q^j(U6}vNJ3)^kmhKED%HRjB^86Du1X%#IrD6#YG6h^SOh76cU9Ryjt0y|9fBB2 z)RpKo9<>iWkwfjqz0#(ViPa_UeMCi_)NY*o*%SntukGH4zN4MmYx}AsWx&=5f>1YL z;I%Wt2RT9rL+ELYet#a`S>3={&9PsdIif}x$;aQt6WnO@9yR(fjs8%RLT@vms8J}h zG`gB2U4uSUK%uur_T!mjH2Pyr`fwZbq2>>s1@YtN6mRe;2Hg0Of<%9Dq+j7zQ51El zC=2>X8^JA(?nY;N)9Bs_Oz(NRr#R6WaNQ|m8gzOaeQYk0UXb`Kj_&8l9Gj2{NrcwIMo{9~Tq3r}E2 zr2m0)zVm6#k=uT$U+e|~1{a9^(b`wRvP)6x!IumO``L#^AUOn38&Buf}1uRE#kj=%^}aR}-Zs*;A2*X8Uc z3$=NB$l!yhe22 zCrc#|VK!MA)JKBzTOP$*5nOvWrOYJSmlZZ;;l1b>c zT(S$;6`6c7jp`GD6PHjU2w+!0R4zFJEAsJmX^ltttdj1kzSV;jUM~X54fsfB^2Jt7 zRupbx9XYICqP#|^>B|Mm-C2Yxakzxx8)+>r;*jgb_o>-{5g2)Wxai2Qe_GB6$BM*^ zdWmw(#r#~LeByym7Lhl|0HSiKSzv{4#MP>TaKI>{o@||Xz=b@i$y4K?#OHLktqYnO7%d59v=zf!dDLj zzD07B?J!z_eYQsE)IDSjIt@W48Sp{9y;2+0a}fhPFKw`)<#S}e5<>}>j*6q1VN_CG z$c8n^z@zo?01A9zuTOY=%czZFeVW+J*#JNxxc+vb&t?dE3pVstdX5-CISP;svI6KO zh9DTd#Mjz*a58GADq}+-=M%4nja@& z@Te;x2onP;q9(T>&hgWw;LKbB9g>`xWTHYDZzo!W;^k6-I$%-_TM771=pkY7eBPn} zG$IHI2mmXQk3G3w=*4Q#<%=10gb@JZ)`=n(88BFPuR_oxIR&UmX1$|@Arg+k2T6@c zLIF2s;nLL^nYhUkdquRc5Y#wTNJ;4dezKDKBMUIVrwA~JliHH5gv0&2F!`GTH;Df* zq6XAiDjwi(EkdqWT&~J@s!BftBfb{th0CAc)a-v(@BfYRWz_@7ecM4czpPY%mK4@| z?6O3!TV*V<5dp3;$c{p=V|ks_boA@WR1lsrdot0;0H6eo2JitH&GR9j;ZUg<1Ac+z z=(z7g#sb+227EC!9B8pp{TYsUQr?W2rfRjUlWim!Sm!HMu;Gx5rKjEyXf0hSmWfGm=sU zfPyan^XA)Pew_GLlnx z<7@qjZoLTnvs*HILOaP&k`e^Pj)qU8#hoZ&Nos*}Y7QI0*rGzsB<{M%bkY(chj}=@ zx;vHix`dJC=6W`ejO(c5d611xA0K4bwI=j}%PvY0GDYZ`C)>c(k)1$Msw^5RZMrdl z+bb*kQq^pw(#kujoWU>|2$9;UbozvslB${@xtw7IdF|cbsgR_Uo!xSB)oZgGa(<8E zQK=|d-4jBXdQMV`TGYYkt6i_$gj+fCm6z}4FlYk=<*r8Q=@k*V%BR-kAWo~~s^+Qj z0DK|nDJ*FXl%y|r;>3wyZbion8GVPK)XLj0WeuckNvEi|d{vQ^($c%T>_L@fw&dv~HI5XBh^yWBcWoiLfIa%=r^ zMtlX?5`SnuEBy^|;8NX((LLF5;R}{0pV{XH^G3$MpSXmCf?$oi&fH|KP}pW8`{Qc4 zKhBaKmG_R8-8A>WTp~XuGZ{3k?x|h{;qU%1NJ-1zb^S^!EqiW@j7{480+_18@$Z+8 zJ$@X$-6}sUoP7CRXTlE)Ew9%oRX1G9d;gqgc(-tNH&+P?(rTO=jXr*6h0AvZUf;KU z3GTzs-{trJ`*42RcW(T;&!s;`E*;b^{@!OpxU%Nj^9nnlW`g!^Erlvsn?>?_YU(Ga zT|HR%eXpPQGE-3k#5ziLcS*(7kHe2p2R;X1IC{?F{IjLGCHE@jMw2r)m&ShowDfA` z!g@O!?P-mhad);|_<`^IT~5jwn|CiZ973eyVII|iinxMJr~Yvi z3iI1ku@<7uG;Fm&466?IxD>)hnr4b?-(Q&Br*lrL=l2cAYhq`Zf;WE@-*ic6fFfWA z;Hpq|$|r2Hi*eSLi6IxyH=Gu=^Hx9k&YHxTKHl{2ExAzXug8V6mMV7_KOd71l54b0 z+N`x3ckiTJH&J7K-<*lxSYKP@sdu*8F^yh#aDCdHp@_sxh;kjz55v2zh(^AKr5U$cjWPrn9VL<_N63e zLT`BwArth|^Zmou^xorHnjF<#o_kN@Kh2H77Zjcygp9xZaAT$`h){=jl)te`bCGQx z>sIrU9Qx(M==|)b7T(~ovys;jN)>W(F#l&RR=Fwa$vNU%dMeP0p6s@vu7CoUZUaK~ z%~+WaBUgHIw>>QQf_Y>gc5DUhOT#Yf&Z5oP&8N}kHhO~bd5v{?N)Z9h1Bf~GSGQ-lb|*aYS|sWn=WgpR+|J*m zLA;Bw5k$>x8|RwBA>Qg9*)=A0E6Znw?b<&lCodU~CH^w{pzFD-!Gn>hsN0dT@`vaP zC(YHCtZQaBQ9?Xe-@$InIinOsvJRDv+q*TE)?b?YZI8vX>fHui$JlEhZs~Yvv5>Ma z$Ho4|wZrh*=zg8=s8HNYgX7yhL8Qh+JDHvA7eS`tX4180(lPl%OKaZ8`!41jM7!)z zs)e#vH?FW>Rh8iIc;D)7!FB5<;!j21#ls=^GEew#6``wK_s4opB6}aUB|26q?LU0P z_q8k(r_m^r5M+K;4d1}JXQNPCz_7-0F)n7KUX*#thF=Jrvx0SY`ARwp@wW%J9x!{G z_@JCD2OWhs+Rm6Bc5^BVRy(fsc1Ll~k&Lj@tZf!PqJ0a!T0bkJJpB->6@Pm7qw-!A z|C5BAG)46DlMq$N+SlXe#G5}Hyxt{uUz+CwLJ=arw{@GUiq;MoPsRVVd@jnKJDb6N zJNC{!%Itixz-0Fyi%tJj#)YfU`$$#-1uyocuBTLo{Bg0$<5d3%wyK}{qo_r!>P*?%2`8@z*%I5vsfd(Ix~S`4B4u7p z_2+r)Y&=Zxk4wLa+d;UzP(6R#z3%8E)djT*1LZEK^FyCTC-D$Zr_pAcv2KdVmo}R> z!zTOMCJ62cUoH<#e{}c=uZg++gvy;U9-ZjOhqDd|?VosUhwxgBhUc6xTyGYZg(9C~ z-d`-562E+s{(8vL>Bu9iGMi(6eBb0bfTbPdTz?C{?f7P!ucGnl9+{uMI6WTV{rou; vR`?Wo(2Qg0ZT{g!$8~yn$d@jH=kr;w_lFKSxWQO2W1GLb6Jt_4yA%39fAVYV diff --git a/appinventor/lib/blockly/media/delete.wav b/appinventor/lib/blockly/media/delete.wav deleted file mode 100644 index 18debcf96d6f76e36f295feb6de2f09dffaec1f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9164 zcmXAu2Yip$_s7qDzDa}-Dr%Jc>{XkXr6@AY+M`sB5G#loTWQP)MXjn$P^v{yVr#9^ z+N<`agpf$`eeU_c_5bRtvcAuK?mg#oKA+Dyw@pN7=+WXL9UFFN(r3`{BDqAw@L%H} zMW%N$;z%xO9?`a4BEOGl8QLnMWy2QlKhr2?#GoMq`$hLHGNi|l$QX%e*ruI7zi&G{ za!6EX zIe74Z?*FaCzkMTzb?-53*x;Dqk-dww7~H#GpMHGPBf58yn8-o>M)Q5o*dk$r2lpKq zStKI5S4DQ#s7+%(-d448l`0~=dkpW9Tuh{>Jk==s!uFI);v+-#qW&OvYgSyeKvfpSiNzigSQ0M7e{Yr*QV;L-YOb2tp95aXHv^Lgknr@%!TS*lw z*QBk~kf}0K{wJSGQPbP`)A4ckn_f;a&l}G`pPQZ!JTuJ;ov7BXaED|jW{mcJ@~P**n7iD4&>l^4i4v4E2rl+2d*CRFKE&wH@8Z-binV_pG<4+t8NL4jQ9DQpp54 zo6Iz+Wwtw)ozNTz2U%T3Qn1dkHtS zq?s*YE9*^ZWq#H{BdMr~uGkYc!8WuN?R`5{HW`o8*IDH>acYo@w7d(Tdn7ADmkH_OaX zGt%sl-V$W0nY8Yr9bfWARQ!Qq@nrFERaK5T4(96GTd}AyCj+%?6kk= z6Md$;^m83AwVjd1N2}Q{^tfD?cbceob*}hJG3}>6Ykx8)a+UXfVID}PmN2!PeUgnc z6_9Z02)=JvuidGiXq5Jpn>tvtkc}{1poOKB+yEJQrJMP{SeU0Uft3kR|m-$TU z6T_ieU2;oR>7?E4HG4pxNupfUe7x(n{I2nuF1<`ka~7QKkqIC#FFPA;3YqJ=&34jo zlW0z`pCOt_L`txuS$f8PrDvo#NZux;rMW)U?J`cfa;ioWDq%882ieV3X*E+@M91)s zmHM{~6xYV+J&88|>O?zC|BwZ;fxo?w2y;YcOI~RpIb}2TAEG<;kk*zeri}cif9ra( z^&7FQDAOf7Yd*J++$y$<+$CdKar(`=G0WazepI47Mz&jO#e zeg)pSPs1}x_(f>e)C(yGeRg~h?OQqRSw^(~S6N%AefLS`K2I;tK0V|4!E8?}oH|pp zd1~98Qp0zK^FQL6!&6u;xy^K-xo>8g+S=AT-u+E-m<;>MK9GabTKC!#`i{6pNqf`P z6ftq2X_F>M4>Q%glBJph45hdS>?~cZr|cR%4wto&6=tDnAiH(Bd?!_;EN7es&&`#7 zri$4BgKX05ve=Y0t#q;twta1V-jH2x>r3;k$8l!rY5OaYnr|cB!aB}uGds1s_F

  • byd!2eCa;2SN@P6|j{ouc39DL8n)mgA(AWS*wl45GVAr)vfIR$9pc?M5}O&^(~N zfh;A;or!ZS{MQ7wZKH=|s);w{q_+N}&1D5RD0h}U-As$X)#MC~r;skk$>Br#f6exRbd+r@BI7dUahejtyfj@e=6NM-SuH!@2GX$8He4YZRTWVeFF zSlJ|H%r%LXHs&vK5p23^FHN(TZA<i-D;w@mL2>c)157QM<~Q@C?1L8Ob@lE*3w6MPC~%mcN!)q*~uK)E#u{H z>Zcb^{YeD`$T=OWS*e*F)Yo;Md2MU!J@P)AoGj&;cI;^@NZAiA9_TdPt|RaZvFOJW zbl|w2QGY&>$lv|&MPubSPO7DFR{ans^2n|M^_B`Mp`oC$l-6a(=QO{345~)3&M)$p zgvdQT0#;J&c+Dz@rJ(r-U0AD2bq^eSjoqhlo_#t~e9UcjwTRDzkuQ-`c(>f>Y-4$( z)pU(smSN_hG?PUA*DkT4HpJG|1F-Wt&Cqr1`&ShFA$56F%dx^jy=7n8u~b|;YGprJ zZOI9mngPT!D{g4H#!&|$=stJ?{T|68KVgGgOB*rfCVOnIcWo$poTtOll5U(n8C(Q{ z+a6%*y-Ft8idqw0ze!I1C40rGfR!*#R;h^+9OT^RsqW=+5ijM3?rj9ajqm~w;g#H= zZ7)vp0_a<)|C5vYJr!RJp4@Jm5Sw0lAI0lMh0cThuBjt&8cY>mKoe6mCo%aQwI7DB z8Ni#KQXvyzvLqX;pGhP>_H+3PO!Q{Oi=1I7?Eg2s+d>|qABV~Ra4=dOHoOE<)^omv zI)a=;aLUnAjrPThTm6Kf5_|B3z$hmGe`0|hv5 z3^h{sKXy3CnI@3kDY_QS^p^^-W<2?iB3cWnivY=Be`R<_brALv2IvPDU4WzS^0}Qv zdlI@4MEsZ0sf;0G6^Z?3*z_A%c9mAql3G?<;n?P&bT3h?nQ-MaIJ&sZB@&4`AAi^Z zHtSAQ{vq#??7k_r9}CN`CwBKZOPD^ihrwQ^twU`jNFzB*2AkmER>3usi1i4W$f{4# zv-#{~2`uK-H^lERd&(Bm_nG=vM~k2NgF2`qgQ$$o)LC&!lP}~`IA$$)JB~^ngnRJRzo`34TD zLpGYDJrh8Db25?0ySGr!xlo=}ct5zWN0@y{8Ls%u{*lDSMu$ z=j>g&gz0Lv8YqjR=Iij}E8>8P$cN-FT&_?zd-ONiPfgt;DnWRga8%}JG_NW=Fw>h~ z%K3%*TrdeXTUz7vl1^KnzD|t!)9g26G|t^*Q&n`jx4$=+Gu`*O`P%+qbD_A~^s>{z zGtkVEv-UeT%%+3fCmKed*2tE1*Vu<>#}Y6!7%nR%bETY_fO5ArkM&zB<~e#C0|VrN zb6??CLS&7UGP&eOs;IDBu!*)c`ASDyHpzXMHcGz(vE5*!^YjNt@MJ&J8*Zi2qv^4C z@U@xDu$$aW>*1VBLBTNdt;u5?F<^Bu?rW%IGjo{-r0P`8ZE*r!aDg{KhFIc>)KnT5HlQ*B8d z{N9&?ybodh12Ezqay$?&86bsCLGxa#eTn=?J!*qF$sF|Mt}P;taV6MnHKXWF`_XZJ z3a(30y@$xdVcbYwyi881iWc7E`IWHQGrGwHobMGPw*b%jf{JNJ?G}KYtC5TQptm;f zjis)8;9uX^C~7#C3V225_B-|V3D^&(hMyAW#pLA#vGJAiOgoanP$0RBLziY!eYNRJ zr=f1OiDgMN{x9mbJzgl9xUYvh>dPZoVvl_ULN3@boa|p}X%3n+*tWPyM!UP< zmv-ZN66p8W!1*ECl`6lCcfKff&G)cYR`lVj&R~-D2aI>!Ueo+$qy&(q1S+;L9dSE+ z%tjoxrKY=rfl_#g>+~FZ;n63W#@ZeMf!FZiMg>*1G1@a`!P zUlZSRgSo~IdfPyFpoYrq1$@ghs*Yj`TB`~&)YVB!6! zXDvBm^P!4mrLhLs(Y6X6WjMXi2BstH!Xz8^%uLymdDREq}m4Kjm|T->W4mb7Cz~u z@>C33-V4o5(rnAE}3+U|DX$w7Khr)&5v$G_on7Jib zgYa5;%_q#-8p2VN>3oezCpZ16y~BK_s+_j(+!=NvRa?Z~VD_{K^gXxDsMOA8x)bf` z;*@4qx6S;|Ow`@3x&g3wJ3Z@8f)`ez%ke1fNNocLOr|CxaL%J70F~I!wDbu~JHY05 zqueRXj*GH#d3djr*T24-gZr4T^rUCcLX8LG^aJ2%MN10dUPjAH z+f7@UerBr9v@O^{s13JmI7jJ6jL+>B@k#A;J$8WNG z+B@I&V>YnYFh?-zoSE@duA{J{KeZb=_~W&^Z6{9XZnvjS$z z1a&vy;M%zAn!47V;+Dn3Ez&|%@PM1pU~4_$MoltRFmkjGA@K zIP`L;*@iP~Nv~9z&xYXEpV{h~kKWzaUb16!G~Rl?4WXwUKv#Ye9bjsw88*9}2BU*POpNJ~$FjxB?t@)y8(CZ6Oy;7RQ&l(L%T();;8AWj^yOs{ahO zZ*M=dLr|Jv(;Dn`r2Ah(C${CiZ$`hTagH&X(-yKR_8tBqQn#YdAxv_7wlzbY?oL4yrq?;gY5NymegpR>b2)8My=dp-FnZx+ zWAGw7@GA#k{&ecSIXZQS9_W$`Wy)X36X!fM<(aRinNym@7I7PU_j+4{fM8|`+27AN z#Mk(nV|vFust4jo7?T^ek3cMIZhvmw^eZgO`U(t zBOKEh9QjckxkrxKNp>fluOGjgq}7?0ZY1wv`Z@O;8$il_CL)JXkz35@SL4t9sie>7 z4uXuYv|#2Qhl^V0F82Oli{p}}+8#DVMw(O!z#lYo=6Q}fFPT9WWG1l-%qHpg(i|m9 z(98B~cZfULR*{iTYy4QK47KZ+-G+I5oL1asv~w&Kjly^DM*D{9WYf@DWu7>P%v_Y~FB$5b)l+VL`PM9v)wZX5+RbzmnY3JU^Vl?2 zsb_wbFPW+yq`&G6zll@abhp{v^)?I)uSPfG$>n<7%3S)mA@KHG3394>R&sMOgjd=K(Y;nLce0bC;9y zAr5OCRh2~d(_Z4W3s`>%oBU1pKZEJ^D{V`>(m~@bdW=JE6L!DRv^UeuR!_9&oE)Yy z#-XN1xLX>8#}1VXrk_*P$!Ct@FDs&*SLKXd?md@r(3`AXL1Ra)Z6DbEFve?rB0FK| ztf>DdPB}B0-ZCCcZKu;+&TO!j1UdzsmSz-n*2Vlzzxy@n6pjaS;f55AK%JMEf2lm! z7pMF{o|{c(f@X&y9>FjfoHD^Kb>mR6_xxWsP72yS>9 zp{l==$#Gi3cE%?k!#k(RBPYyxNSC+=Y}F&n=}h?M;@I;TW0LI?ZyYy+HQ=$~@J5dR zX8r}xl(9_g{)b|{;r1|)c&%qjc7jM`Fkk!*=UJ0USbkV*6P^Asy5pKQ*?Yx)VdA9= z{@dTFZ+h9S?rrWAv*8q1aI3oDGtB?0|FkSu{GxqhOtAghdo#U%+P=4*)Ub?J>f_nzyVtL--(8=9o@tK1 zr>@!Tje7Uf+mv@p^i!XY{eJS?*DKy5nT2gpIcVlPYvrVka9g^oaRIlTvi|4%Lyeo- z=j|KsN$0X>0v>3ytjBwF@Z5CTn?8EbUFS}*nQ-V`Rr>|J58B1nEvts)6kL3(4w?16YQE=pF8XzCTQWN zy(6A#p2Pt< zLwY%_q2vu5?z8g2#wU@v8{}`0`tu($D(z z_O!`d=l#&*>mTUzJabp(0R0vgy_UO)8E@m zQ_Mb1wBx<+xIGJUm)dbA$tmG<#3_|9xjkb|2dU}IaF)qo@0yHl?tYlFpDp8ty8U&P z>Fg8eyUBA_1HE;;HZwUrN5&vG5%*g~AG(FCzkFeGJHtH#oEqfErAN<7$HCnoY`fLx zwBH2ZV4p%hA2^Y2hm0i|MVPyEC z{mNwF7PcoH?Kr%aKet9-FvnbDb90kh-i*Z~*5&?W1-DFlZ6Q|a%XHG^etQ@`Yyth- zCH;#Ia-;oOe_`7HObR%?ogTP@OS+JIpJ*z-4Nui}DsqnyV=mBp1j%b|4N6E!4YYgQ zDcsvk<}S4zJR6Kog^Rz9&m5Y0*3I$X)U<|t!@d1BywU^i49l4?(?*Ws-8<`MTbQ~T zi(0%gskp;oOkzebkqTt(W9&JPd1-Q)bhti=X~uFpL3i7ywlV!yb?M9$rLfsezq!;t zgzHR1&Xi(+2WfY1I) R6c)kuZMgU8%=~+f{2#xTwtoNs diff --git a/appinventor/lib/blockly/media/disconnect.ogg b/appinventor/lib/blockly/media/disconnect.ogg deleted file mode 100644 index 467b527b4d0515046b43198c2e0ea0d558d77bfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4404 zcmai14_H%2w!bKU5=0syU}&S?4U&Z$K?w#m?Bgw`?(45zdVWj|ks@h9nmi z%S)9qm8`fNbA{=F@Q4NCr1+^mv3csb-{sYrRKuq0QWCzs`-*~Pi2QdT5?9s1IJ z==PG5{6ZNjD9%~u;^tHui`$awf>2-w+$7XmHPt9V5E_EK7KC{p$rE5EU3#yVk8dU8&-?e~lrL#vY_9vP49 zh1BJcBxd-IZ;wU8hI;^Wj z39OuIp-2^|iEKYi7o4GAKEu3nEhzcR&=lXuYa8N4Vxa_zI&)WrY_>u@TTz+TQj>AM zGVOd##?6|{r#0D(+Gq7|m3N+!)uB4-g0!vSH_u@mfiHJ_!tYqBsqI;UUOSub@|cd~naH!J^Ckp_lu;98(Y%m_n8|xxVY4YF=8i>|fWIJ!2ds25dQ6#vCmR ziYJ0bm7yLE3y&e-(-X#mgxPCe*dxNA*+s zCs+91`Uh>@^yAk*s23j(9_ns6?(ksYWWXHw5*t5eZ96ulS4|4M^d@I-pU-g*OZPO4 z1uPi6Z2{RZPd=^p=)ScZ)}~GA=T8pNp;xav9y~B4cJg}$i|*eVCO_ccgBA539ajud zGokmtxrWcLP|2~M!zTv(mVJ|9Yu%4lYTc!DRu}8Y>hia|kF;^eFyrb&+HH7u^-dxn z*i^pXp*e~m8kz&e&l?AnohUXo9pH?IygLzbIh1UAMkb>c`$lM6ytshk&`3b>p@I2# zRK5HJg=xT^zSg88aLnY4C~zv8+ZgK};0Ti17Uej00;1wY$NhKE)fKC*y-=_I4>QGw z4fR??m}o<^L@e1=QIz(!`u4e+%$w>vvz2#d4`r>a{W-9Hj2r}lM&pP{owR{FYN*~3 zM|C>*dE}JQM-MYE9S%zD4-!s?Uip%j{DgPSH$H_Y6!~Rd^HX26tGi>h6s$Ym4GDHIT+PQ=#*PkM%EkygtX6+h5Q&3vdul63z2hy z%iIFd)E_E*;?yzv8W^-Ze&ve}K#&WKUWtx#B!vi@AtGmpFo`(&mm>zKGd$sS9vJp0 zf&?JQ8gR0Pc0kz}R~)^Y!krItYv;SSf5_0Bpl$HtFApqlj17)H-^3sBdUBTt@!OhI zeTcnDi!Q&|^{U{(W(pj8u1E@kRB^|+A2O7af=g{%C%M#C-55XEbYxn9g*7uaVC*iR zoH;}1wBV9a$4ETTYV^sex4@n60_@P31iX$$5504b*JAEc=}L zPKaDDFX%XF)`ytQ-R8j}bFU?%yg?(G@xKYgmVa1p4zC(Zq#W^?GN{+@5m zp^Jkj&BK=Q{=VbArxpjlST+*6I9zJ(?LF21DM=l+EZWKzhr{3K!Y+56dOX}cJY2ju zTsARS#OyRb{xj$D#lG?WFBXT_pH;I`Bdi%;(lx^Vg50knR$C75L){!%PMomo>H$WZrjSfjhg#L-Fe!JI{Fr1 z!-d3#?|4i*YweP%%`S*LYk@AJaja-Ljd+Y2#awrmY6os*>UQDI> z_#R9*O?b4McH)Y5ot;pe>AE5P3^n@W@-W?WdO^4CMtZ}F99qPJF?UixHJv31z-pn* z=pBcfjPyi2EOi2a+&LYa&~5Y)3AzV>mC5Lzh;s+&8O2;X6IK{~G6a~7E-DJM>DSm$ zV0DQU?vU}IMF*^oRX5?dS`_kf}S`yF#nONF!Gxl={=;3MEFCf-WvKk6;7S1rASN_Rn|rxA!OLb))A8eIZZji z=TPG&_`%)Eq&N(dOvF;y1Cx9Vv)cI-w#h${6J||SU>Il-26=}gY~6+RRu|9ZX;fq@ zM6nHpbH_cv#HgNP80k5*KobM}Vxs4OZ5b->I8H#$WNZkg*@<(o8X7KOn;Aok4R(#6!I(| zwxmPu{V8ndQ^z^NMjAbk7)B?^<>%9+6a0rv9-NF!jW@?;sP>Md_`x>dUp2vph870| z$oJZ-p)u*ENdkdCLSYOum6HS=;fWv|NU|w?DY>fshuh%HT!QQ)&rF=}(XQKu*-%{* z0pdWVZlxF4&YDURbm^a>0FA=P3L3!5mc9kISa&OWSth%*Cvp}*JTR|U;6PAZ8A6bc z-8_)KrLV+q3}#R{yj+J8RVbLTfm=(L9^ft*woou@3*4E&<@k;9U&DhJ!LP;HI-jL{xw7`ztS7~aohei#!r+o{~4`BmJFbv=W z5v@zdkEsZP!!|XON5_qHJPdeyuuXQN0Hj1wOlNP9qHe|}U?zL|!7vCp96qHDk+lR& zvEG#SaE;Rh#3v)C2LdQv0b5suVFPw)!vNSHP6)g7V5B{L8FII{6sbz+E2}+feD~tD zyAEHoAlZ&{Sev{U5a5e85-qH)IG~Ee2ulNQaE@sje;lJlEjXbCfLd_Q)9s9NK#S52 zW7sMHS%{;@h91?Kz&XIE@qtuM2b`T_IvuB~7|+1#y7C{fsOj zz{;4>aZPj)p?GMJHl!rC=HT3s9$hLPa(Mr=vS*-T0`9^n1qr9IHoO_*LT8MDAdM@A zwDnz>;=bzYdfz9))5~*Iqneg4MQEBaufuh_y?lJlZ+1wdklnAoHs(>~b?DI9gUcR9 zTyV?$SdD5>S5}?Xh2B_I?OXi%C(D!1e?X0jH+eg+?k>n`1Zi511_tW+TJN`BYNQ=r z(d2W)R|oJ#kh?BbFCkSyZgq8adD_mAxuro{b2Y{f@4K=cWU`@9oL3cBN8fR^ckOfD z^bzuEPm1|>w_|Q@ksEjs-21DtM9a4bw(lQ$T^5vpsgAwh$FP0t|NZ&Yx3dg=Q~&Yn zAJV=b)&A*9)ZZKS*yVrF=6&{$>m@zWSvjBG{`^Ul@w@NlT+MCQ{&bV^hr2tr{ZT$- zSggN2;y3yIn$b~* zgNLCjQ~p{Ichf39wd%K1kN#Tqj|ZNc_CGQ$_ga3M+4TDSjg^T-Pu*T?{o>qrZ{M0< jxIK41^keCb2kVdh=ifJXu}>c?xOZB5^2z7YcaZ-Bex2=H diff --git a/appinventor/lib/blockly/media/disconnect.wav b/appinventor/lib/blockly/media/disconnect.wav deleted file mode 100644 index af5c25447cad1a7ebd705e0f28ffbc4ebec01f49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1492 zcmcgse@v8R9Djbiciaz^Ls1l@Ugwr2@*^}OGz~%I%0mZ-QkeuC2WQ9K0Y~UYx-47F z)a7)e;WE=P*TBL;@<+^7&eSBAzbaP~Jp?=m9rug(eV^y)IZjqvTYvVv`@Y}L_vh#P zJbT`^z?hr+qY8laS?g9>tKFgj008-u(+0r%#SkE10G3jBX{^8l;|l`D!a0onTPVYT zjz`0Yj0@sb5eq%430ME^iCE#-BZ5a!g$cYvq&iah&z=$Xi8(0Go0ux%n|SX7C&5lI z1!S^vdX^j{_sLm0#1i2gv|}`Hbic39e>I>4+5-Cmoq=NAm z757*5CG~X=Y#yd*dUkOB!04bbG7y*ptMvU-d*g)o z!*Q2mzS1Uuxxu#{T=!<*Upp*}PL;ag*HIUB8G1$YxZt2Kj_vVx_!yUOFg$qe#jha@$x#a7rNLuL`C~edGzGQDJ zRU_KN(#R1xLssM#vWV>l80F&%Ay;)rwO>^ul%Ym;TuGPC1qb|zeybk^)zT&6ga?G} z>K=86Y5~5=?kESO7sfV>d8I<~1^7;|YT9($^qIP)QOogcW|eP;wgiiUheJv7Myfz2 zJXE(tiBV(18JJAZNlQb?!SrBaXpS_j#DjTwi>h6HQr)HM#t!%{GtdTdo}8k+Y(6YU zX554K;?2kaJK3xBfif(o$g=mx9@%UCg$$znP}Z?ij~6^7tvkbrhpLYI>LN{doRHqqlu1AVXr?L-a~hdzSS z;Z}aT%h)j*P0x{5a)s2;Z4AR^^d(mC+c*Q|gH&o)n&ci?Anmjn%tLwjV?2ts!y(p5 zLqtn2(W@*LO0X66pbtfY)IQ>;>Iy84W0v%08u@{7HWWJJIJ@E1bYyKDmz_ zrFY3`VxX7lT}Hqle2=pip__04KZ|~5;S9O-8tEoU)K9->UEmm8Z7ejO;vcRtKX;8W zKg;wO$7`J~m(5WruC`f3r", - "lastupdated": "2024-04-16 23:19:53.668551", + "lastupdated": "2026-01-08 08:39:56.707280", "locale": "en", "messagedocumentation" : "qqq" }, @@ -18,6 +18,7 @@ "DELETE_X_BLOCKS": "Delete %1 Blocks", "DELETE_ALL_BLOCKS": "Delete all %1 blocks?", "CLEAN_UP": "Clean up Blocks", + "CLOSE": "Close", "COLLAPSE_BLOCK": "Collapse Block", "COLLAPSE_ALL": "Collapse Blocks", "EXPAND_BLOCK": "Expand Block", @@ -63,24 +64,24 @@ "CONTROLS_REPEAT_TITLE": "repeat %1 times", "CONTROLS_REPEAT_INPUT_DO": "do", "CONTROLS_REPEAT_TOOLTIP": "Do some statements several times.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", + "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Loops#repeat", "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeat while", "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeat until", "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "While a value is true, then do some statements.", "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "While a value is false, then do some statements.", - "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", + "CONTROLS_FOR_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Loops#count-with", "CONTROLS_FOR_TOOLTIP": "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.", "CONTROLS_FOR_TITLE": "count with %1 from %2 to %3 by %4", - "CONTROLS_FOREACH_HELPURL": "https://github.com/google/blockly/wiki/Loops#for-each", + "CONTROLS_FOREACH_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Loops#for-each", "CONTROLS_FOREACH_TITLE": "for each item %1 in list %2", "CONTROLS_FOREACH_TOOLTIP": "For each item in a list, set the variable '%1' to the item, and then do some statements.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks", + "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Loops#loop-termination-blocks", "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "break out of loop", "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continue with next iteration of loop", "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Break out of the containing loop.", "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Skip the rest of this loop, and continue with the next iteration.", "CONTROLS_FLOW_STATEMENTS_WARNING": "Warning: This block may only be used within a loop.", - "CONTROLS_IF_HELPURL": "https://github.com/google/blockly/wiki/IfElse", + "CONTROLS_IF_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/IfElse", "CONTROLS_IF_TOOLTIP_1": "If a value is true, then do some statements.", "CONTROLS_IF_TOOLTIP_2": "If a value is true, then do the first block of statements. Otherwise, do the second block of statements.", "CONTROLS_IF_TOOLTIP_3": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.", @@ -98,15 +99,15 @@ "LOGIC_COMPARE_TOOLTIP_LTE": "Return true if the first input is smaller than or equal to the second input.", "LOGIC_COMPARE_TOOLTIP_GT": "Return true if the first input is greater than the second input.", "LOGIC_COMPARE_TOOLTIP_GTE": "Return true if the first input is greater than or equal to the second input.", - "LOGIC_OPERATION_HELPURL": "https://github.com/google/blockly/wiki/Logic#logical-operations", + "LOGIC_OPERATION_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Logic#logical-operations", "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", "LOGIC_OPERATION_AND": "and", "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", "LOGIC_OPERATION_OR": "or", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", + "LOGIC_NEGATE_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Logic#not", "LOGIC_NEGATE_TITLE": "not %1", "LOGIC_NEGATE_TOOLTIP": "Returns true if the input is false. Returns false if the input is true.", - "LOGIC_BOOLEAN_HELPURL": "https://github.com/google/blockly/wiki/Logic#values", + "LOGIC_BOOLEAN_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Logic#values", "LOGIC_BOOLEAN_TRUE": "true", "LOGIC_BOOLEAN_FALSE": "false", "LOGIC_BOOLEAN_TOOLTIP": "Returns either true or false.", @@ -206,27 +207,27 @@ "MATH_ATAN2_TOOLTIP": "Return the arctangent of point (X, Y) in degrees from -180 to 180.", "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", "TEXT_TEXT_TOOLTIP": "A letter, word, or line of text.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", + "TEXT_JOIN_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#text-creation", "TEXT_JOIN_TITLE_CREATEWITH": "create text with", "TEXT_JOIN_TOOLTIP": "Create a piece of text by joining together any number of items.", "TEXT_CREATE_JOIN_TITLE_JOIN": "join", "TEXT_CREATE_JOIN_TOOLTIP": "Add, remove, or reorder sections to reconfigure this text block.", "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Add an item to the text.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", + "TEXT_APPEND_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#text-modification", "TEXT_APPEND_TITLE": "to %1 append text %2", "TEXT_APPEND_TOOLTIP": "Append some text to variable '%1'.", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", + "TEXT_LENGTH_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#text-modification", "TEXT_LENGTH_TITLE": "length of %1", "TEXT_LENGTH_TOOLTIP": "Returns the number of letters (including spaces) in the provided text.", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", + "TEXT_ISEMPTY_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#checking-for-empty-text", "TEXT_ISEMPTY_TITLE": "%1 is empty", "TEXT_ISEMPTY_TOOLTIP": "Returns true if the provided text is empty.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", + "TEXT_INDEXOF_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#finding-text", "TEXT_INDEXOF_TOOLTIP": "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found.", "TEXT_INDEXOF_TITLE": "in text %1 %2 %3", "TEXT_INDEXOF_OPERATOR_FIRST": "find first occurrence of text", "TEXT_INDEXOF_OPERATOR_LAST": "find last occurrence of text", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", + "TEXT_CHARAT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#extracting-text", "TEXT_CHARAT_TITLE": "in text %1 %2", "TEXT_CHARAT_FROM_START": "get letter #", "TEXT_CHARAT_FROM_END": "get letter # from end", @@ -236,7 +237,7 @@ "TEXT_CHARAT_TAIL": "", "TEXT_CHARAT_TOOLTIP": "Returns the letter at the specified position.", "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", + "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#extracting-a-region-of-text", "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in text", "TEXT_GET_SUBSTRING_START_FROM_START": "get substring from letter #", "TEXT_GET_SUBSTRING_START_FROM_END": "get substring from letter # from end", @@ -245,57 +246,57 @@ "TEXT_GET_SUBSTRING_END_FROM_END": "to letter # from end", "TEXT_GET_SUBSTRING_END_LAST": "to last letter", "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", + "TEXT_CHANGECASE_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#adjusting-text-case", "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "to UPPER CASE", "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "to lower case", "TEXT_CHANGECASE_OPERATOR_TITLECASE": "to Title Case", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", + "TEXT_TRIM_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#trimming-removing-spaces", "TEXT_TRIM_TOOLTIP": "Return a copy of the text with spaces removed from one or both ends.", "TEXT_TRIM_OPERATOR_BOTH": "trim spaces from both sides of", "TEXT_TRIM_OPERATOR_LEFT": "trim spaces from left side of", "TEXT_TRIM_OPERATOR_RIGHT": "trim spaces from right side of", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", + "TEXT_PRINT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#printing-text", "TEXT_PRINT_TITLE": "print %1", "TEXT_PRINT_TOOLTIP": "Print the specified text, number or other value.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", + "TEXT_PROMPT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#getting-input-from-the-user", "TEXT_PROMPT_TYPE_TEXT": "prompt for text with message", "TEXT_PROMPT_TYPE_NUMBER": "prompt for number with message", "TEXT_PROMPT_TOOLTIP_NUMBER": "Prompt for user for a number.", "TEXT_PROMPT_TOOLTIP_TEXT": "Prompt for user for some text.", "TEXT_COUNT_MESSAGE0": "count %1 in %2", - "TEXT_COUNT_HELPURL": "https://github.com/google/blockly/wiki/Text#counting-substrings", + "TEXT_COUNT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#counting-substrings", "TEXT_COUNT_TOOLTIP": "Count how many times some text occurs within some other text.", "TEXT_REPLACE_MESSAGE0": "replace %1 with %2 in %3", - "TEXT_REPLACE_HELPURL": "https://github.com/google/blockly/wiki/Text#replacing-substrings", + "TEXT_REPLACE_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#replacing-substrings", "TEXT_REPLACE_TOOLTIP": "Replace all occurances of some text within some other text.", "TEXT_REVERSE_MESSAGE0": "reverse %1", - "TEXT_REVERSE_HELPURL": "https://github.com/google/blockly/wiki/Text#reversing-text", + "TEXT_REVERSE_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Text#reversing-text", "TEXT_REVERSE_TOOLTIP": "Reverses the order of the characters in the text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", + "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#create-empty-list", "LISTS_CREATE_EMPTY_TITLE": "create empty list", "LISTS_CREATE_EMPTY_TOOLTIP": "Returns a list, of length 0, containing no data records", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", + "LISTS_CREATE_WITH_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#create-list-with", "LISTS_CREATE_WITH_TOOLTIP": "Create a list with any number of items.", "LISTS_CREATE_WITH_INPUT_WITH": "create list with", "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "list", "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Add, remove, or reorder sections to reconfigure this list block.", "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Add an item to the list.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", + "LISTS_REPEAT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#create-list-with", "LISTS_REPEAT_TOOLTIP": "Creates a list consisting of the given value repeated the specified number of times.", "LISTS_REPEAT_TITLE": "create list with item %1 repeated %2 times", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", + "LISTS_LENGTH_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#length-of", "LISTS_LENGTH_TITLE": "length of %1", "LISTS_LENGTH_TOOLTIP": "Returns the length of a list.", - "LISTS_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#is-empty", + "LISTS_ISEMPTY_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#is-empty", "LISTS_ISEMPTY_TITLE": "%1 is empty", "LISTS_ISEMPTY_TOOLTIP": "Returns true if the list is empty.", "LISTS_INLIST": "in list", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list", + "LISTS_INDEX_OF_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#finding-items-in-a-list", "LISTS_INDEX_OF_FIRST": "find first occurrence of item", "LISTS_INDEX_OF_LAST": "find last occurrence of item", "LISTS_INDEX_OF_TOOLTIP": "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found.", - "LISTS_GET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", + "LISTS_GET_INDEX_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#getting-items-from-a-list", "LISTS_GET_INDEX_GET": "get", "LISTS_GET_INDEX_GET_REMOVE": "get and remove", "LISTS_GET_INDEX_REMOVE": "remove", @@ -319,7 +320,7 @@ "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Removes the first item in a list.", "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Removes the last item in a list.", "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Removes a random item in a list.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", + "LISTS_SET_INDEX_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#in-list--set", "LISTS_SET_INDEX_SET": "set", "LISTS_SET_INDEX_INSERT": "insert at", "LISTS_SET_INDEX_INPUT_TO": "as", @@ -331,7 +332,7 @@ "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserts the item at the start of a list.", "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Append the item to the end of a list.", "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserts the item randomly in a list.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", + "LISTS_GET_SUBLIST_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#getting-a-sublist", "LISTS_GET_SUBLIST_START_FROM_START": "get sub-list from #", "LISTS_GET_SUBLIST_START_FROM_END": "get sub-list from # from end", "LISTS_GET_SUBLIST_START_FIRST": "get sub-list from first", @@ -340,7 +341,7 @@ "LISTS_GET_SUBLIST_END_LAST": "to last", "LISTS_GET_SUBLIST_TAIL": "", "LISTS_GET_SUBLIST_TOOLTIP": "Creates a copy of the specified portion of a list.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", + "LISTS_SORT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#sorting-a-list", "LISTS_SORT_TITLE": "sort %1 %2 %3", "LISTS_SORT_TOOLTIP": "Sort a copy of a list.", "LISTS_SORT_ORDER_ASCENDING": "ascending", @@ -348,20 +349,20 @@ "LISTS_SORT_TYPE_NUMERIC": "numeric", "LISTS_SORT_TYPE_TEXT": "alphabetic", "LISTS_SORT_TYPE_IGNORECASE": "alphabetic, ignore case", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", + "LISTS_SPLIT_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#splitting-strings-and-joining-lists", "LISTS_SPLIT_LIST_FROM_TEXT": "make list from text", "LISTS_SPLIT_TEXT_FROM_LIST": "make text from list", "LISTS_SPLIT_WITH_DELIMITER": "with delimiter", "LISTS_SPLIT_TOOLTIP_SPLIT": "Split text into a list of texts, breaking at each delimiter.", "LISTS_SPLIT_TOOLTIP_JOIN": "Join a list of texts into one text, separated by a delimiter.", - "LISTS_REVERSE_HELPURL": "https://github.com/google/blockly/wiki/Lists#reversing-a-list", + "LISTS_REVERSE_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Lists#reversing-a-list", "LISTS_REVERSE_MESSAGE0": "reverse %1", "LISTS_REVERSE_TOOLTIP": "Reverse a copy of a list.", "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_HELPURL": "https://github.com/google/blockly/wiki/Variables#get", + "VARIABLES_GET_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Variables#get", "VARIABLES_GET_TOOLTIP": "Returns the value of this variable.", "VARIABLES_GET_CREATE_SET": "Create 'set %1'", - "VARIABLES_SET_HELPURL": "https://github.com/google/blockly/wiki/Variables#set", + "VARIABLES_SET_HELPURL": "https://github.com/RaspberryPiFoundation/blockly/wiki/Variables#set", "VARIABLES_SET": "set %1 to %2", "VARIABLES_SET_TOOLTIP": "Sets this variable to be equal to the input.", "VARIABLES_SET_CREATE_GET": "Create 'get %1'", @@ -396,5 +397,27 @@ "WORKSPACE_ARIA_LABEL": "Blockly Workspace", "COLLAPSED_WARNINGS_WARNING": "Collapsed blocks contain warnings.", "DIALOG_OK": "OK", - "DIALOG_CANCEL": "Cancel" + "DIALOG_CANCEL": "Cancel", + "EDIT_BLOCK_CONTENTS": "Edit Block contents", + "MOVE_BLOCK": "Move Block", + "WINDOWS": "Windows", + "MAC_OS": "macOS", + "CHROME_OS": "ChromeOS", + "LINUX": "Linux", + "UNKNOWN": "Unknown", + "CONTROL_KEY": "Ctrl", + "COMMAND_KEY": "⌘ Command", + "OPTION_KEY": "⌥ Option", + "ALT_KEY": "Alt", + "CUT_SHORTCUT": "Cut", + "COPY_SHORTCUT": "Copy", + "PASTE_SHORTCUT": "Paste", + "HELP_PROMPT": "Press %1 for help on keyboard controls", + "SHORTCUTS_GENERAL": "General", + "SHORTCUTS_EDITING": "Editing", + "SHORTCUTS_CODE_NAVIGATION": "Code navigation", + "KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT": "Hold %1 and use arrow keys to move freely, then %2 to accept the position", + "KEYBOARD_NAV_CONSTRAINED_MOVE_HINT": "Use the arrow keys to move, then %1 to accept the position", + "KEYBOARD_NAV_COPIED_HINT": "Copied. Press %1 to paste.", + "KEYBOARD_NAV_CUT_HINT": "Cut. Press %1 to paste." } From 74c4c457e4628e7ed3bfb4ca8a34725dc10453e6 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Fri, 9 Jan 2026 19:10:11 -0800 Subject: [PATCH 02/32] Blockly 12 renamed setEnabled to setDisabledReason --- appinventor/blocklyeditor/src/blocklyeditor.js | 4 ++-- appinventor/blocklyeditor/src/blocks/components.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/appinventor/blocklyeditor/src/blocklyeditor.js b/appinventor/blocklyeditor/src/blocklyeditor.js index f9d7da29df4..d2e46755171 100644 --- a/appinventor/blocklyeditor/src/blocklyeditor.js +++ b/appinventor/blocklyeditor/src/blocklyeditor.js @@ -693,7 +693,7 @@ AI.Blockly.ContextMenuItems.registerEnableDisableAllBlocksOption = function() { let allBlocks = scope.workspace.getAllBlocks(); try { Blockly.Events.setGroup(true); - allBlocks.forEach(block => block.setEnabled(true)); + allBlocks.forEach(block => block.setDisabledReason(false, Blockly.constants.MANUALLY_DISABLED)); } finally { Blockly.Events.setGroup(false); } @@ -714,7 +714,7 @@ AI.Blockly.ContextMenuItems.registerEnableDisableAllBlocksOption = function() { let allBlocks = scope.workspace.getAllBlocks(); try { Blockly.Events.setGroup(true); - allBlocks.forEach(block => block.setEnabled(false)); + allBlocks.forEach(block => block.setDisabledReason(true, Blockly.constants.MANUALLY_DISABLED)); } finally { Blockly.Events.setGroup(false); } diff --git a/appinventor/blocklyeditor/src/blocks/components.js b/appinventor/blocklyeditor/src/blocks/components.js index c5954c0a11c..b4056fe881e 100644 --- a/appinventor/blocklyeditor/src/blocks/components.js +++ b/appinventor/blocklyeditor/src/blocks/components.js @@ -216,7 +216,7 @@ Blockly.ComponentBlock.addGenericOption = function(block, options) { */ Blockly.ComponentBlock.checkDeprecated = function(block, data) { if (data && data.deprecated && block.workspace == Blockly.common.getMainWorkspace()) { - block.setEnabled(false); + block.setDisabledReason(true, 'DEPRECATED'); } } From 045ed3349e4a327f22d31eeb67f8260ec8551742 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Wed, 8 Apr 2026 15:43:06 -0700 Subject: [PATCH 03/32] Blockly 12 dropped Ctrl shortcut key on Mac https://github.com/RaspberryPiFoundation/blockly/commit/3b14950a36ed5cb452c72d53d8bb0e71605aacd9 --- .../com/google/appinventor/blocklyeditor/typeblock_tests.js | 6 +++--- appinventor/blocklyeditor/tests/testCommon.js | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js index bdb2a4f09ae..fc281aec21f 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js @@ -281,7 +281,7 @@ suite('TypeBlock', function() { test('undo create number block', async function() { await act(() => input('42')); - await act(() => ctrl('z')); + await act(() => cmdOrCtrl('z')); chai.assert.equal(workspace.getAllBlocks().length, 0); }); @@ -292,7 +292,7 @@ suite('TypeBlock', function() { await act(() => Blockly.common.setSelected(ifBlock)); await act(() => input('true')); - await act(() => ctrl('z')); + await act(() => cmdOrCtrl('z')); chai.assert.isNull(ifBlock.getInput('IF0').connection.targetBlock()); }); @@ -308,7 +308,7 @@ suite('TypeBlock', function() { await act(() => Blockly.common.setSelected(setBlock)); await act(() => input('if')); - await act(() => ctrl('z')); + await act(() => cmdOrCtrl('z')); chai.assert.isNull(setBlock.nextConnection.targetBlock()); }); }); diff --git a/appinventor/blocklyeditor/tests/testCommon.js b/appinventor/blocklyeditor/tests/testCommon.js index 669637a3141..015c7d8804d 100644 --- a/appinventor/blocklyeditor/tests/testCommon.js +++ b/appinventor/blocklyeditor/tests/testCommon.js @@ -302,10 +302,11 @@ function getPropertyBlockPresentedName(block) { } } -function ctrl(key) { +function cmdOrCtrl(key) { const workspace = Blockly.common.getMainWorkspace(); const keyCode = key.toUpperCase().charCodeAt(0); - const options = { key: key, keyCode: keyCode, ctrlKey: true, bubbles: true }; + const modKey = Blockly.utils.userAgent.MAC ? 'metaKey' : 'ctrlKey'; + const options = { key: key, keyCode: keyCode, [modKey]: true, bubbles: true }; workspace.getCanvas().dispatchEvent(new KeyboardEvent('keydown', options)); workspace.getCanvas().dispatchEvent(new KeyboardEvent('keyup', options)); } From c210adc638ec11870dee0e0bb6096b5577c44302 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sat, 10 Jan 2026 07:40:51 -0800 Subject: [PATCH 04/32] Remove duplicate blockly[Non]EditableText CSS https://github.com/RaspberryPiFoundation/blockly/commit/59fab944f4ba61bb2e6e3685053ae467ccdb8056 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L217-L219 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/renderers/common/constants.ts#L254 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/renderers/common/constants.ts#L1166-L1171 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/renderers/common/constants.ts#L1172-L1175 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/renderers/common/constants.ts#L1187-L1191 --- appinventor/blocklyeditor/media/blockly.css | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/appinventor/blocklyeditor/media/blockly.css b/appinventor/blocklyeditor/media/blockly.css index bb1e4f44705..9ed10692037 100644 --- a/appinventor/blocklyeditor/media/blockly.css +++ b/appinventor/blocklyeditor/media/blockly.css @@ -58,23 +58,9 @@ font-size: 11pt; fill: #fff; } -.blocklyNonEditableText>text { - pointer-events: none; -} -.blocklyNonEditableText>rect, .blocklyEditableText>rect { - fill: #fff; - fill-opacity: .6; -} -.blocklyNonEditableText>text, .blocklyEditableText>text { - fill: #000; -} .blocklyMultilineText { fill: #000; } -.blocklyEditableText:hover>rect { - stroke-width: 2; - stroke: #fff; -} .blocklySvg text { -moz-user-select: none; -webkit-user-select: none; From a9e692eb75060637049c2695bf348de2a330c32f Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sat, 10 Jan 2026 08:56:39 -0800 Subject: [PATCH 05/32] Remove duplicate blocklyScrollbarKnob CSS https://github.com/google/blockly/commit/06b9bb68e6762934fb5e7e1c004bb33dac1f1e0e https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L325-L332 --- appinventor/blocklyeditor/media/blockly.css | 6 ------ 1 file changed, 6 deletions(-) diff --git a/appinventor/blocklyeditor/media/blockly.css b/appinventor/blocklyeditor/media/blockly.css index 9ed10692037..108ae47a268 100644 --- a/appinventor/blocklyeditor/media/blockly.css +++ b/appinventor/blocklyeditor/media/blockly.css @@ -168,12 +168,6 @@ stroke-width: 1; stroke: #e4e4e4; } -.blocklyScrollbarKnob { - fill: #ccc; -} -.blocklyScrollbarBackground:hover+.blocklyScrollbarKnob, .blocklyScrollbarKnob:hover { - fill: #bbb; -} .blocklyInvalidInput { background: #faa; } From 24b37e753b67516f2962447a4fd9a2926124d8c3 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sat, 10 Jan 2026 09:04:21 -0800 Subject: [PATCH 06/32] Remove duplicate CSS https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L148-L152 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L160-L162 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L189-L193 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L195-L197 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L205-L208 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L234-L239 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L301-L304 https://github.com/RaspberryPiFoundation/blockly/blob/blockly-v12.5.1/packages/blockly/core/css.ts#L345-L347 --- appinventor/blocklyeditor/media/blockly.css | 31 --------------------- 1 file changed, 31 deletions(-) diff --git a/appinventor/blocklyeditor/media/blockly.css b/appinventor/blocklyeditor/media/blockly.css index 108ae47a268..c4c526a0110 100644 --- a/appinventor/blocklyeditor/media/blockly.css +++ b/appinventor/blocklyeditor/media/blockly.css @@ -21,11 +21,6 @@ stroke-width: 1; stroke: #888; } -.blocklyHighlightedConnectionPath { - stroke-width: 4px; - stroke: #fc3; - fill: none; -} .blocklyPathLight { fill: none; stroke-width: 2; @@ -35,23 +30,10 @@ stroke-width: 3px; stroke: #fc3; } -.blocklySelected>.blocklyPathLight { - display: none; -} -.blocklyDragging>.blocklyPath, .blocklyDragging>.blocklyPathLight { - fill-opacity: .8; - stroke-opacity: .8; -} -.blocklyDragging>.blocklyPathDark { - display: none; -} .blocklyDisabled>.blocklyPath { fill-opacity: .5; stroke-opacity: .5; } -.blocklyDisabled>.blocklyPathLight, .blocklyDisabled>.blocklyPathDark { - display: none; -} .blocklyText { cursor: default; font-family: sans-serif; @@ -61,12 +43,6 @@ .blocklyMultilineText { fill: #000; } -.blocklySvg text { - -moz-user-select: none; - -webkit-user-select: none; - user-select: none; - cursor: inherit; -} .blocklyHidden { display: none; } @@ -156,10 +132,6 @@ .blocklyToolboxBackground { fill: #ddd; } -.blocklyFlyoutBackground { - fill: #ddd; - fill-opacity: .8; -} .blocklyColourBackground { fill: #666; } @@ -168,9 +140,6 @@ stroke-width: 1; stroke: #e4e4e4; } -.blocklyInvalidInput { - background: #faa; -} .goog-palette { outline: none; cursor: default; From 3d7105c8a48901d869a1d3319d3df5af4741a0c4 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Fri, 9 Jan 2026 17:35:05 -0800 Subject: [PATCH 07/32] Remove unneeded setSelected(null) from tests --- .../google/appinventor/blocklyeditor/component_database_tests.js | 1 - .../google/appinventor/blocklyeditor/exportBlocksImage_tests.js | 1 - .../com/google/appinventor/blocklyeditor/procedures_tests.js | 1 - .../com/google/appinventor/blocklyeditor/typeblock_tests.js | 1 - .../com/google/appinventor/blocklyeditor/variables_tests.js | 1 - .../google/appinventor/blocklyeditor/xml_serialization_tests.js | 1 - .../tests/com/google/appinventor/blocklyeditor/yailgenerators.js | 1 - 7 files changed, 7 deletions(-) diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/component_database_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/component_database_tests.js index 416f6c93e9b..575ab625211 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/component_database_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/component_database_tests.js @@ -6,7 +6,6 @@ suite('Component Database Tests', function() { setup(function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', /*readonly*/ false, /*rtl*/ false)); - Blockly.common.setSelected(null); initComponentTypes(); }) test('TranslationTests', function() { diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/exportBlocksImage_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/exportBlocksImage_tests.js index 2066a34d366..a5a57ed4e88 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/exportBlocksImage_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/exportBlocksImage_tests.js @@ -4,7 +4,6 @@ suite('ExportBlocksImage', function() { setup(async function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', /*readonly*/ false, /*rtl*/ false)); workspace = Blockly.common.getMainWorkspace(); - await act(() => Blockly.common.setSelected(null)); }); test('export and import blocks png round-trip', async function() { diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/procedures_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/procedures_tests.js index 920806ab001..e0be50e6420 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/procedures_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/procedures_tests.js @@ -4,7 +4,6 @@ suite('Procedures', function() { setup(function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', /*readonly*/ false, /*rtl*/ false)); workspace = Blockly.common.getMainWorkspace(); - Blockly.common.setSelected(null); }); test('declared no-return procedure parameter in scope', function() { diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js index fc281aec21f..599277c6cd8 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/typeblock_tests.js @@ -4,7 +4,6 @@ suite('TypeBlock', function() { setup(async function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', /*readonly*/ false, /*rtl*/ false)); workspace = Blockly.common.getMainWorkspace(); - await act(() => Blockly.common.setSelected(null)); }); function input(text) { diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/variables_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/variables_tests.js index 2315292b0af..c9e6a733569 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/variables_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/variables_tests.js @@ -4,7 +4,6 @@ suite('Variables', function() { setup(function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', /*readonly*/ false, /*rtl*/ false)); workspace = Blockly.common.getMainWorkspace(); - Blockly.common.setSelected(null); }); test('declared global variable', function() { diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/xml_serialization_tests.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/xml_serialization_tests.js index 407a9ed8d70..7311022c4bb 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/xml_serialization_tests.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/xml_serialization_tests.js @@ -1,7 +1,6 @@ suite('XML Serialization Tests', function() { setup(function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', false, false)); - Blockly.common.setSelected(null); initComponentTypes(); }); diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/yailgenerators.js b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/yailgenerators.js index 24d4b84119d..2b8d7f8a660 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/yailgenerators.js +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/blocklyeditor/yailgenerators.js @@ -60,7 +60,6 @@ suite('Blockly Code Generator Tests', function() { setup(function() { Blockly.common.setMainWorkspace(Blockly.BlocklyEditor.create(document.body, '', /*readonly*/ false, /*rtl*/ false)); - Blockly.common.setSelected(null); }) suite('Control Blocks', function() { test('controls_eval_but_ignore', function() { From 35775b34522386d962147da8036b0bd37074f146 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sun, 11 Jan 2026 17:37:41 -0800 Subject: [PATCH 08/32] Update to @blockly/plugin-scroll-options 7.0.8 --- appinventor/appengine/war/index.jsp | 2 +- .../appengine/war/static/js/scroll-options-6.0.16.min.js | 3 --- .../appengine/war/static/js/scroll-options-7.0.8.min.js | 3 +++ .../tests/com/google/appinventor/mocha/index.html | 2 +- appinventor/karma.conf.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 appinventor/appengine/war/static/js/scroll-options-6.0.16.min.js create mode 100644 appinventor/appengine/war/static/js/scroll-options-7.0.8.min.js diff --git a/appinventor/appengine/war/index.jsp b/appinventor/appengine/war/index.jsp index fd54c8548b2..50c8eab2c84 100644 --- a/appinventor/appengine/war/index.jsp +++ b/appinventor/appengine/war/index.jsp @@ -120,7 +120,7 @@ - + diff --git a/appinventor/appengine/war/static/js/scroll-options-6.0.16.min.js b/appinventor/appengine/war/static/js/scroll-options-6.0.16.min.js deleted file mode 100644 index 197606fe66e..00000000000 --- a/appinventor/appengine/war/static/js/scroll-options-6.0.16.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see index.js.LICENSE.txt */ -!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var o="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var s in o)("object"==typeof exports?exports:t)[s]=o[s]}}(this,(t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},o={};function s(t){var i=o[t];if(void 0!==i)return i.exports;var r=o[t]={exports:{}};return e[t](r,r.exports,s),r.exports}s.d=(t,e)=>{for(var o in e)s.o(e,o)&&!s.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),s.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};s.r(i),s.d(i,{ScrollBlockDragger:()=>d,ScrollMetricsManager:()=>l,ScrollOptions:()=>p,isAutoScrollable:()=>h,isCacheable:()=>n});var r=s(370);class l extends r.MetricsManager{constructor(){super(...arguments),this.useCachedContentMetrics=!1,this.contentMetrics=null}getContentMetrics(){return this.useCachedContentMetrics&&this.contentMetrics||(this.contentMetrics=super.getContentMetrics()),this.contentMetrics}}function n(t){return void 0!==t.useCachedContentMetrics}const c=t=>{const e=t.svgBlockCanvas_.getAttribute("transform");if(!e)throw new Error("svgBlockCanvas has no attribute 'transform'");const o=e.split(","),s=Number(o[0].split("(")[1]),i=Number(o[1].split(")")[0]);return new r.utils.Coordinate(s,i)};class a{constructor(t,e){this.activeScrollVector_=new r.utils.Coordinate(0,0),this.animationFrameId_=0,this.lastTime_=Date.now(),this.shouldAnimate_=!1,this.workspace_=t,this.dragger=e}stopAndDestroy(){this.activeScrollVector_=new r.utils.Coordinate(0,0),this.shouldAnimate_=!1,cancelAnimationFrame(this.animationFrameId_),this.animationFrameId_=0}nextAnimationStep_(t){if(this.shouldAnimate_){const e=t-this.lastTime_;this.lastTime_=t,e>0&&this.scrollTick_(e),this.animationFrameId_=requestAnimationFrame((t=>this.nextAnimationStep_(t)))}}scrollTick_(t){const e=this.activeScrollVector_.x*t,o=this.activeScrollVector_.y*t;this.scrollWorkspaceWithBlock(e,o)}scrollWorkspaceWithBlock(t,e){const o=c(this.workspace_),s=this.workspace_.getMetricsManager();if(!n(s))return void console.warn("MetricsManager must be able to cache metrics in order to use AutoScroll");s.useCachedContentMetrics=!0;const i=this.workspace_.scrollX+t,r=this.workspace_.scrollY+e;this.workspace_.scroll(i,r),s.useCachedContentMetrics=!1;const l=c(this.workspace_),a=l.x-o.x,h=l.y-o.y;(a||h)&&this.dragger.moveBlockWhileDragging(a,h)}updateProperties(t){this.activeScrollVector_=t,this.shouldAnimate_=!0,0==this.animationFrameId_&&(this.lastTime_=Date.now(),this.nextAnimationStep_(this.lastTime_))}}function h(t){return"function"==typeof t.getBoundingRectangle}const u={slowBlockSpeed:.28,fastBlockSpeed:1.4,slowBlockStartDistance:0,fastBlockStartDistance:50,oversizeBlockThreshold:.85,oversizeBlockMargin:15,slowMouseSpeed:.5,fastMouseSpeed:1.6,slowMouseStartDistance:0,fastMouseStartDistance:35};class d extends r.dragging.Dragger{constructor(){super(...arguments),this.scrollDelta_=new r.utils.Coordinate(0,0),this.dragDelta_=new r.utils.Coordinate(0,0),this.scrollDirections_=["top","bottom","left","right"],this.SCROLL_DIRECTION_VECTORS_={top:new r.utils.Coordinate(0,1),bottom:new r.utils.Coordinate(0,-1),left:new r.utils.Coordinate(1,0),right:new r.utils.Coordinate(-1,0)},this.activeAutoScroll_=null}moveBlockWhileDragging(t,e){if(!h(this.draggable))return;this.scrollDelta_.x-=t,this.scrollDelta_.y-=e;const o=r.utils.Coordinate.sum(this.scrollDelta_,this.dragDelta_),s=this.pixelsToWorkspaceUnits(o),i=r.utils.Coordinate.sum(this.startLoc,s);this.draggable.drag(i)}onDrag(t,e){const o=r.utils.Coordinate.sum(this.scrollDelta_,e);super.onDrag(t,o),this.dragDelta_=e,d.edgeScrollEnabled&&this.scrollWorkspaceWhileDragging_(t)}onDragEnd(t){super.onDragEnd(t),this.stopAutoScrolling()}scrollWorkspaceWhileDragging_(t){if(!h(this.draggable))return;const e=r.utils.svgMath.screenToWsCoordinates(this.workspace,new r.utils.Coordinate(t.clientX,t.clientY)),o={top:[],bottom:[],left:[],right:[]},s=this.workspace.getMetricsManager().getViewMetrics(!0);this.computeBlockCandidateScrolls_(o,s,e),this.computeMouseCandidateScrolls_(o,s,e);const i=this.getOverallScrollVector_(o);r.utils.Coordinate.equals(i,new r.utils.Coordinate(0,0))?this.stopAutoScrolling():(this.activeAutoScroll_=this.activeAutoScroll_||new a(this.workspace,this),this.activeAutoScroll_.updateProperties(i))}getOverallScrollVector_(t){let e=new r.utils.Coordinate(0,0);for(const o of this.scrollDirections_){const s=t[o].reduce(((t,e)=>t&&r.utils.Coordinate.magnitude(t)>r.utils.Coordinate.magnitude(e)?t:e),new r.utils.Coordinate(0,0));e=r.utils.Coordinate.sum(e,s)}return e}computeBlockCandidateScrolls_(t,e,o){const s=this.getBlockBoundsOverflows_(e,o);for(const e of this.scrollDirections_){const o=s[e];if(o>d.options.slowBlockStartDistance){const s=o>d.options.fastBlockStartDistance?d.options.fastBlockSpeed:d.options.slowBlockSpeed,i=this.SCROLL_DIRECTION_VECTORS_[e].clone().scale(s);t[e].push(i)}}}computeMouseCandidateScrolls_(t,e,o){const s=this.getMouseOverflows_(e,o);for(const e of this.scrollDirections_){const o=s[e];if(o>d.options.slowMouseStartDistance){const s=o>d.options.fastMouseStartDistance?d.options.fastMouseSpeed:d.options.slowMouseSpeed,i=this.SCROLL_DIRECTION_VECTORS_[e].clone().scale(s);t[e].push(i)}}}getBlockBoundsOverflows_(t,e){if(!h(this.draggable))return{top:0,bottom:0,left:0,right:0};const o=this.draggable.getBoundingRectangle();return o.bottom-o.top>t.height*d.options.oversizeBlockThreshold&&(o.top=Math.max(o.top,e.y-d.options.oversizeBlockMargin),o.bottom=Math.min(o.bottom,e.y+d.options.oversizeBlockMargin)),o.right-o.left>t.width*d.options.oversizeBlockThreshold&&(o.left=Math.max(o.left,e.x-d.options.oversizeBlockMargin),o.right=Math.min(o.right,e.x+d.options.oversizeBlockMargin)),{top:t.top-o.top,bottom:-(t.top+t.height-o.bottom),left:t.left-o.left,right:-(t.left+t.width-o.right)}}getMouseOverflows_(t,e){return{top:t.top-e.y,bottom:-(t.top+t.height-e.y),left:t.left-e.x,right:-(t.left+t.width-e.x)}}stopAutoScrolling(){this.activeAutoScroll_&&this.activeAutoScroll_.stopAndDestroy(),this.activeAutoScroll_=null}}d.edgeScrollEnabled=!0,d.options=u,d.updateOptions=function(t){d.options=Object.assign(Object.assign({},d.options),t)},d.resetOptions=function(){d.options=u},r.registry.register(r.registry.Type.BLOCK_DRAGGER,"ScrollBlockDragger",d);class p{constructor(t){this.wheelEvent_=null,this.workspace_=t}init({enableWheelScroll:t=!0,enableEdgeScroll:e=!0,edgeScrollOptions:o}={enableWheelScroll:!0,enableEdgeScroll:!0,edgeScrollOptions:void 0}){t?this.enableWheelScroll():this.disableWheelScroll(),d.edgeScrollEnabled=e,o&&d.updateOptions(o)}enableWheelScroll(){if(this.wheelEvent_)return;const t=this.workspace_.getInjectionDiv().getElementsByClassName("blocklyBlockDragSurface")[0];if(!t)throw new Error("Can't attach wheel listener to nonexistent drag surface");this.wheelEvent_=r.browserEvents.conditionalBind(t,"wheel",this,this.onMouseWheel_)}disableWheelScroll(){this.wheelEvent_&&(r.browserEvents.unbind(this.wheelEvent_),this.wheelEvent_=null)}enableEdgeScroll(){d.edgeScrollEnabled=!0}disableEdgeScroll(){d.edgeScrollEnabled=!1}updateEdgeScrollOptions(t){d.updateOptions(t)}onMouseWheel_(t){const e=this.workspace_.options.moveOptions&&this.workspace_.options.moveOptions.wheel,o=this.workspace_.getGesture(t),s=this.workspace_.getMetricsManager();if(!n(s))return void console.warn("MetricsManager must be able to cache metrics in order to use AutoScroll");const i=null==o?void 0:o.getCurrentDragger();if(!(e&&o&&i instanceof d))return;const l=r.browserEvents.getScrollDeltaPixels(t);if(t.shiftKey){const t=l.x;l.x=l.y,l.y=t}const a=this.workspace_.scrollX-l.x,h=this.workspace_.scrollY-l.y,u=c(this.workspace_);s.useCachedContentMetrics=!0,this.workspace_.scroll(a,h),s.useCachedContentMetrics=!1;const p=c(this.workspace_),g=p.x-u.x,_=p.y-u.y;(g||_)&&(i.moveBlockWhileDragging(g,_),t.preventDefault())}}return i})())); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/appinventor/appengine/war/static/js/scroll-options-7.0.8.min.js b/appinventor/appengine/war/static/js/scroll-options-7.0.8.min.js new file mode 100644 index 00000000000..94828c8dd32 --- /dev/null +++ b/appinventor/appengine/war/static/js/scroll-options-7.0.8.min.js @@ -0,0 +1,3 @@ +/*! For license information please see index.js.LICENSE.txt */ +!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var o="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var s in o)("object"==typeof exports?exports:t)[s]=o[s]}}(this,t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},o={};function s(t){var i=o[t];if(void 0!==i)return i.exports;var r=o[t]={exports:{}};return e[t](r,r.exports,s),r.exports}s.d=(t,e)=>{for(var o in e)s.o(e,o)&&!s.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),s.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};s.r(i),s.d(i,{ScrollBlockDragger:()=>d,ScrollMetricsManager:()=>l,ScrollOptions:()=>p,isAutoScrollable:()=>h,isCacheable:()=>n});var r=s(370);class l extends r.MetricsManager{constructor(){super(...arguments),this.useCachedContentMetrics=!1,this.contentMetrics=null}getContentMetrics(){return this.useCachedContentMetrics&&this.contentMetrics||(this.contentMetrics=super.getContentMetrics()),this.contentMetrics}}function n(t){return void 0!==t.useCachedContentMetrics}const c=t=>{const e=t.svgBlockCanvas_.getAttribute("transform");if(!e)throw new Error("svgBlockCanvas has no attribute 'transform'");const o=e.split(","),s=Number(o[0].split("(")[1]),i=Number(o[1].split(")")[0]);return new r.utils.Coordinate(s,i)};class a{constructor(t,e){this.activeScrollVector_=new r.utils.Coordinate(0,0),this.animationFrameId_=0,this.lastTime_=Date.now(),this.shouldAnimate_=!1,this.workspace_=t,this.dragger=e}stopAndDestroy(){this.activeScrollVector_=new r.utils.Coordinate(0,0),this.shouldAnimate_=!1,cancelAnimationFrame(this.animationFrameId_),this.animationFrameId_=0}nextAnimationStep_(t){if(this.shouldAnimate_){const e=t-this.lastTime_;this.lastTime_=t,e>0&&this.scrollTick_(e),this.animationFrameId_=requestAnimationFrame(t=>this.nextAnimationStep_(t))}}scrollTick_(t){const e=this.activeScrollVector_.x*t,o=this.activeScrollVector_.y*t;this.scrollWorkspaceWithBlock(e,o)}scrollWorkspaceWithBlock(t,e){const o=c(this.workspace_),s=this.workspace_.getMetricsManager();if(!n(s))return void console.warn("MetricsManager must be able to cache metrics in order to use AutoScroll");s.useCachedContentMetrics=!0;const i=this.workspace_.scrollX+t,r=this.workspace_.scrollY+e;this.workspace_.scroll(i,r),s.useCachedContentMetrics=!1;const l=c(this.workspace_),a=l.x-o.x,h=l.y-o.y;(a||h)&&this.dragger.moveBlockWhileDragging(a,h)}updateProperties(t){this.activeScrollVector_=t,this.shouldAnimate_=!0,0==this.animationFrameId_&&(this.lastTime_=Date.now(),this.nextAnimationStep_(this.lastTime_))}}function h(t){return"function"==typeof t.getBoundingRectangle}const u={slowBlockSpeed:.28,fastBlockSpeed:1.4,slowBlockStartDistance:0,fastBlockStartDistance:50,oversizeBlockThreshold:.85,oversizeBlockMargin:15,slowMouseSpeed:.5,fastMouseSpeed:1.6,slowMouseStartDistance:0,fastMouseStartDistance:35};class d extends r.dragging.Dragger{constructor(){super(...arguments),this.scrollDelta_=new r.utils.Coordinate(0,0),this.dragDelta_=new r.utils.Coordinate(0,0),this.scrollDirections_=["top","bottom","left","right"],this.SCROLL_DIRECTION_VECTORS_={top:new r.utils.Coordinate(0,1),bottom:new r.utils.Coordinate(0,-1),left:new r.utils.Coordinate(1,0),right:new r.utils.Coordinate(-1,0)},this.activeAutoScroll_=null}moveBlockWhileDragging(t,e){if(!h(this.draggable))return;this.scrollDelta_.x-=t,this.scrollDelta_.y-=e;const o=r.utils.Coordinate.sum(this.scrollDelta_,this.dragDelta_),s=this.pixelsToWorkspaceUnits(o),i=r.utils.Coordinate.sum(this.startLoc,s);this.draggable.drag(i)}onDrag(t,e){const o=r.utils.Coordinate.sum(this.scrollDelta_,e);super.onDrag(t,o),this.dragDelta_=e,d.edgeScrollEnabled&&this.scrollWorkspaceWhileDragging_(t)}onDragEnd(t){super.onDragEnd(t),this.stopAutoScrolling()}scrollWorkspaceWhileDragging_(t){if(!h(this.draggable))return;const e=r.utils.svgMath.screenToWsCoordinates(this.workspace,new r.utils.Coordinate(t.clientX,t.clientY)),o={top:[],bottom:[],left:[],right:[]},s=this.workspace.getMetricsManager().getViewMetrics(!0);this.computeBlockCandidateScrolls_(o,s,e),this.computeMouseCandidateScrolls_(o,s,e);const i=this.getOverallScrollVector_(o);r.utils.Coordinate.equals(i,new r.utils.Coordinate(0,0))?this.stopAutoScrolling():(this.activeAutoScroll_=this.activeAutoScroll_||new a(this.workspace,this),this.activeAutoScroll_.updateProperties(i))}getOverallScrollVector_(t){let e=new r.utils.Coordinate(0,0);for(const o of this.scrollDirections_){const s=t[o].reduce((t,e)=>t&&r.utils.Coordinate.magnitude(t)>r.utils.Coordinate.magnitude(e)?t:e,new r.utils.Coordinate(0,0));e=r.utils.Coordinate.sum(e,s)}return e}computeBlockCandidateScrolls_(t,e,o){const s=this.getBlockBoundsOverflows_(e,o);for(const e of this.scrollDirections_){const o=s[e];if(o>d.options.slowBlockStartDistance){const s=o>d.options.fastBlockStartDistance?d.options.fastBlockSpeed:d.options.slowBlockSpeed,i=this.SCROLL_DIRECTION_VECTORS_[e].clone().scale(s);t[e].push(i)}}}computeMouseCandidateScrolls_(t,e,o){const s=this.getMouseOverflows_(e,o);for(const e of this.scrollDirections_){const o=s[e];if(o>d.options.slowMouseStartDistance){const s=o>d.options.fastMouseStartDistance?d.options.fastMouseSpeed:d.options.slowMouseSpeed,i=this.SCROLL_DIRECTION_VECTORS_[e].clone().scale(s);t[e].push(i)}}}getBlockBoundsOverflows_(t,e){if(!h(this.draggable))return{top:0,bottom:0,left:0,right:0};const o=this.draggable.getBoundingRectangle();return o.bottom-o.top>t.height*d.options.oversizeBlockThreshold&&(o.top=Math.max(o.top,e.y-d.options.oversizeBlockMargin),o.bottom=Math.min(o.bottom,e.y+d.options.oversizeBlockMargin)),o.right-o.left>t.width*d.options.oversizeBlockThreshold&&(o.left=Math.max(o.left,e.x-d.options.oversizeBlockMargin),o.right=Math.min(o.right,e.x+d.options.oversizeBlockMargin)),{top:t.top-o.top,bottom:-(t.top+t.height-o.bottom),left:t.left-o.left,right:-(t.left+t.width-o.right)}}getMouseOverflows_(t,e){return{top:t.top-e.y,bottom:-(t.top+t.height-e.y),left:t.left-e.x,right:-(t.left+t.width-e.x)}}stopAutoScrolling(){this.activeAutoScroll_&&this.activeAutoScroll_.stopAndDestroy(),this.activeAutoScroll_=null}}d.edgeScrollEnabled=!0,d.options=u,d.updateOptions=function(t){d.options=Object.assign(Object.assign({},d.options),t)},d.resetOptions=function(){d.options=u},r.registry.register(r.registry.Type.BLOCK_DRAGGER,"ScrollBlockDragger",d);class p{constructor(t){this.wheelEvent_=null,this.workspace_=t}init({enableWheelScroll:t=!0,enableEdgeScroll:e=!0,edgeScrollOptions:o}={enableWheelScroll:!0,enableEdgeScroll:!0,edgeScrollOptions:void 0}){t?this.enableWheelScroll():this.disableWheelScroll(),d.edgeScrollEnabled=e,o&&d.updateOptions(o)}enableWheelScroll(){if(this.wheelEvent_)return;const t=this.workspace_.getInjectionDiv().getElementsByClassName("blocklyBlockDragSurface")[0];if(!t)throw new Error("Can't attach wheel listener to nonexistent drag surface");this.wheelEvent_=r.browserEvents.conditionalBind(t,"wheel",this,this.onMouseWheel_)}disableWheelScroll(){this.wheelEvent_&&(r.browserEvents.unbind(this.wheelEvent_),this.wheelEvent_=null)}enableEdgeScroll(){d.edgeScrollEnabled=!0}disableEdgeScroll(){d.edgeScrollEnabled=!1}updateEdgeScrollOptions(t){d.updateOptions(t)}onMouseWheel_(t){const e=this.workspace_.options.moveOptions&&this.workspace_.options.moveOptions.wheel,o=this.workspace_.getGesture(t),s=this.workspace_.getMetricsManager();if(!n(s))return void console.warn("MetricsManager must be able to cache metrics in order to use AutoScroll");const i=null==o?void 0:o.getCurrentDragger();if(!(e&&o&&i instanceof d))return;const l=r.browserEvents.getScrollDeltaPixels(t);if(t.shiftKey){const t=l.x;l.x=l.y,l.y=t}const a=this.workspace_.scrollX-l.x,h=this.workspace_.scrollY-l.y,u=c(this.workspace_);s.useCachedContentMetrics=!0,this.workspace_.scroll(a,h),s.useCachedContentMetrics=!1;const p=c(this.workspace_),g=p.x-u.x,_=p.y-u.y;(g||_)&&(i.moveBlockWhileDragging(g,_),t.preventDefault())}}return i})()); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html b/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html index d759029a76f..0fa72540732 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html @@ -10,7 +10,7 @@ - + diff --git a/appinventor/karma.conf.js b/appinventor/karma.conf.js index ad81367b900..f3899f5932b 100644 --- a/appinventor/karma.conf.js +++ b/appinventor/karma.conf.js @@ -20,7 +20,7 @@ module.exports = function(config) { 'lib/closure-compiler/base.js', 'build/blocklyeditor/blockly-all.js', 'build/blocklyeditor/component-types.js', - 'appengine/war/static/js/scroll-options-6.0.16.min.js', + 'appengine/war/static/js/scroll-options-7.0.8.min.js', 'appengine/war/static/js/workspace-search-9.1.10.min.js', 'appengine/war/static/js/block-dynamic-connection-0.7.16.min.js', 'appengine/war/static/js/blockly-field-colour-5.0.19.min.js', From 21cb8f258c06b5160757f8eed07cc4070b673e97 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sun, 11 Jan 2026 17:39:58 -0800 Subject: [PATCH 09/32] Update to @blockly/plugin-workspace-search 10.1.7 --- appinventor/appengine/war/index.jsp | 2 +- .../appengine/war/static/js/workspace-search-10.1.7.min.js | 3 +++ .../appengine/war/static/js/workspace-search-9.1.10.min.js | 3 --- .../tests/com/google/appinventor/mocha/index.html | 2 +- appinventor/karma.conf.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 appinventor/appengine/war/static/js/workspace-search-10.1.7.min.js delete mode 100644 appinventor/appengine/war/static/js/workspace-search-9.1.10.min.js diff --git a/appinventor/appengine/war/index.jsp b/appinventor/appengine/war/index.jsp index 50c8eab2c84..15992ad5bb7 100644 --- a/appinventor/appengine/war/index.jsp +++ b/appinventor/appengine/war/index.jsp @@ -121,7 +121,7 @@ - + diff --git a/appinventor/appengine/war/static/js/workspace-search-10.1.7.min.js b/appinventor/appengine/war/static/js/workspace-search-10.1.7.min.js new file mode 100644 index 00000000000..134991f6cee --- /dev/null +++ b/appinventor/appengine/war/static/js/workspace-search-10.1.7.min.js @@ -0,0 +1,3 @@ +/*! For license information please see index.js.LICENSE.txt */ +!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var s="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in s)("object"==typeof exports?exports:t)[i]=s[i]}}(this,t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},s={};function i(t){var n=s[t];if(void 0!==n)return n.exports;var l=s[t]={exports:{}};return e[t](l,l.exports,i),l.exports}i.d=(t,e)=>{for(var s in e)i.o(e,s)&&!i.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:e[s]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};i.r(n),i.d(n,{WorkspaceSearch:()=>h});var l=i(370);const o=function(){let t=!1;return function(){if(t)return;t=!0;const e=document.createElement("style");e.id="blockly-ws-search-style";const s=document.createTextNode("path.blocklyPath.blockly-ws-search-highlight {\n fill: #000;\n }\n path.blocklyPath.blockly-ws-search-highlight.blockly-ws-search-current {\n fill: grey;\n }\n .blockly-ws-search-close-btn {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE0Ij48cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=) no-repeat top left;\n }\n .blockly-ws-search-next-btn {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE0Ij48cGF0aCBkPSJNNy40MSA4LjU5TDEyIDEzLjE3bDQuNTktNC41OEwxOCAxMGwtNiA2LTYtNiAxLjQxLTEuNDF6Ii8+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PC9zdmc+) no-repeat top left;\n }\n .blockly-ws-search-previous-btn {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE0Ij48cGF0aCBkPSJNNy40MSAxNS40MUwxMiAxMC44M2w0LjU5IDQuNThMMTggMTRsLTYtNi02IDZ6Ii8+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==) no-repeat top left;\n }\n .blockly-ws-search {\n background: #fff;\n border: solid lightgrey 0.5px;\n box-shadow: 0px 10px 20px grey;\n justify-content: center;\n padding: 0.25em;\n position: absolute;\n z-index: 70;\n }\n .blockly-ws-search-input input {\n border: none;\n }\n .blockly-ws-search button {\n border: none;\n padding-left: 6px;\n padding-right: 6px;\n }\n .blockly-ws-search-actions {\n display: flex;\n }\n .blockly-ws-search-container {\n display: flex;\n }\n .blockly-ws-search-content {\n display: flex;\n }");e.appendChild(s),document.head.insertBefore(e,document.head.firstChild)}}();class h{constructor(t){this.workspace=t,this.id="workspaceSearch",this.htmlDiv=null,this.actionDiv=null,this.inputElement=null,this.textInputPlaceholder="Search",this.blocks=[],this.lastHighlighted=null,this.currentBlockIndex=-1,this.searchText="",this.searchOnInput=!0,this.caseSensitive=!1,this.preserveSelected=!0,this.boundEvents=[]}init(){this.workspace.getComponentManager().addComponent({component:this,weight:0,capabilities:[l.ComponentManager.Capability.POSITIONABLE]}),o(),this.createDom(),this.setVisible(!1),this.workspace.resize()}dispose(){for(const t of this.boundEvents)l.browserEvents.unbind(t);this.boundEvents.length=0,this.htmlDiv&&(this.htmlDiv.remove(),this.htmlDiv=null),this.actionDiv=null,this.inputElement=null}createDom(){const t=this.workspace.getInjectionDiv();this.addEvent(t,"keydown",this,t=>this.onWorkspaceKeyDown(t)),this.htmlDiv=document.createElement("div"),l.utils.dom.addClass(this.htmlDiv,"blockly-ws-search");const e=document.createElement("div");l.utils.dom.addClass(e,"blockly-ws-search-container");const s=document.createElement("div");l.utils.dom.addClass(s,"blockly-ws-search-content"),e.appendChild(s);const i=document.createElement("div");l.utils.dom.addClass(i,"blockly-ws-search-input"),this.inputElement=this.createTextInput(),this.addEvent(this.inputElement,"keydown",this,t=>this.onKeyDown(t)),this.addEvent(this.inputElement,"input",this,()=>this.onInput()),this.addEvent(this.inputElement,"click",this,()=>{var t;this.searchAndHighlight(this.searchText,this.preserveSelected),null===(t=this.inputElement)||void 0===t||t.select()}),i.appendChild(this.inputElement),s.appendChild(i),this.actionDiv=document.createElement("div"),l.utils.dom.addClass(this.actionDiv,"blockly-ws-search-actions"),s.appendChild(this.actionDiv);const n=this.createNextBtn();n&&this.addActionBtn(n,()=>this.next());const o=this.createPreviousBtn();o&&this.addActionBtn(o,()=>this.previous());const h=this.createCloseBtn();h&&(this.addBtnListener(h,()=>this.close()),e.appendChild(h)),this.htmlDiv.appendChild(e),t.insertBefore(this.htmlDiv,this.workspace.getParentSvg())}addEvent(t,e,s,i){const n=l.browserEvents.conditionalBind(t,e,s,i);this.boundEvents.push(n)}addActionBtn(t,e){var s;this.addBtnListener(t,e),null===(s=this.actionDiv)||void 0===s||s.appendChild(t)}createTextInput(){const t=document.createElement("input");return t.type="text",t.setAttribute("placeholder",this.textInputPlaceholder),t}createNextBtn(){return this.createBtn("blockly-ws-search-next-btn","Find next")}createPreviousBtn(){return this.createBtn("blockly-ws-search-previous-btn","Find previous")}createCloseBtn(){return this.createBtn("blockly-ws-search-close-btn","Close search bar")}createBtn(t,e){const s=document.createElement("button");return l.utils.dom.addClass(s,t),s.setAttribute("aria-label",e),s}addBtnListener(t,e){this.addEvent(t,"click",this,e),this.addEvent(t,"keydown",this,t=>{"Enter"===t.key?(e(t),t.preventDefault()):"Escape"===t.key&&this.close(),t.stopPropagation()})}getBoundingRectangle(){return null}position(t,e){this.htmlDiv&&(this.workspace.RTL?this.htmlDiv.style.left=t.absoluteMetrics.left+"px":t.toolboxMetrics.position===l.TOOLBOX_AT_RIGHT?this.htmlDiv.style.right=t.toolboxMetrics.width+"px":this.htmlDiv.style.right="0",this.htmlDiv.style.top=t.absoluteMetrics.top+"px")}onInput(){if(this.searchOnInput&&this.inputElement){const t=this.inputElement.value.trim();t!==this.searchText&&this.searchAndHighlight(t,this.preserveSelected)}}onKeyDown(t){if("Escape"===t.key)this.close();else if("Enter"===t.key)if(this.searchOnInput)t.shiftKey?this.previous():this.next();else{if(!this.inputElement)return;const t=this.inputElement.value.trim();t!==this.searchText&&this.searchAndHighlight(t,this.preserveSelected)}}onWorkspaceKeyDown(t){(t.ctrlKey||t.metaKey)&&"f"===t.key&&(this.open(),t.preventDefault(),t.stopPropagation())}previous(){this.setCurrentBlock(this.currentBlockIndex-1)}next(){this.setCurrentBlock(this.currentBlockIndex+1)}setSearchPlaceholder(t){this.textInputPlaceholder=t,this.inputElement&&this.inputElement.setAttribute("placeholder",this.textInputPlaceholder)}setCurrentBlock(t){if(!this.blocks.length)return;let e=this.blocks[this.currentBlockIndex];e&&this.unhighlightCurrentSelection(e),this.currentBlockIndex=(t%this.blocks.length+this.blocks.length)%this.blocks.length,e=this.blocks[this.currentBlockIndex],this.highlightCurrentSelection(e),this.workspace.centerOnBlock(e.id,!1),this.lastHighlighted=e}open(){var t,e;this.setVisible(!0),null===(t=this.inputElement)||void 0===t||t.focus(),null===(e=this.inputElement)||void 0===e||e.select(),this.searchText&&this.searchAndHighlight(this.searchText)}close(){this.setVisible(!1);const t=l.FocusManager.getFocusManager();this.lastHighlighted&&!this.lastHighlighted.isDisposed()?t.focusNode(this.lastHighlighted):t.focusTree(this.workspace),this.clearBlocks(),this.lastHighlighted=null}setVisible(t){this.htmlDiv&&(this.htmlDiv.style.display=t?"flex":"none")}searchAndHighlight(t,e){const s=this.blocks[this.currentBlockIndex];this.searchText=t.trim(),this.clearBlocks(),this.blocks=this.getMatchingBlocks(this.workspace,this.searchText,this.caseSensitive),this.highlightSearchGroup(this.blocks);let i=0;e&&(i=this.blocks.indexOf(s),i=i>-1?i:0),this.setCurrentBlock(i)}getSearchPool(t){return t.getAllBlocks(!0).filter(t=>{const e=t.getSurroundParent();return!e||!e.isCollapsed()})}isBlockMatch(t,e,s){let i="";if(t.isCollapsed())i=t.toString();else{const e=[];t.inputList.forEach(t=>{t.fieldRow.forEach(t=>{e.push(t.getText())})}),i=e.join(" ").trim()}return s||(i=i.toLowerCase()),i.indexOf(e)>-1}getMatchingBlocks(t,e,s){return e?(this.caseSensitive||(e=e.toLowerCase()),this.getSearchPool(t).filter(t=>this.isBlockMatch(t,e,s))):[]}clearBlocks(){this.unhighlightSearchGroup(this.blocks);const t=this.blocks[this.currentBlockIndex];t&&this.unhighlightCurrentSelection(t),this.currentBlockIndex=-1,this.blocks=[]}highlightCurrentSelection(t){const e=t.pathObject.svgPath;l.utils.dom.addClass(e,"blockly-ws-search-current")}unhighlightCurrentSelection(t){const e=t.pathObject.svgPath;l.utils.dom.removeClass(e,"blockly-ws-search-current")}highlightSearchGroup(t){t.forEach(t=>{const e=t.pathObject.svgPath;l.utils.dom.addClass(e,"blockly-ws-search-highlight")})}unhighlightSearchGroup(t){t.forEach(t=>{const e=t.pathObject.svgPath;l.utils.dom.removeClass(e,"blockly-ws-search-highlight")})}}return n})()); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/appinventor/appengine/war/static/js/workspace-search-9.1.10.min.js b/appinventor/appengine/war/static/js/workspace-search-9.1.10.min.js deleted file mode 100644 index 6bc4c0bad9c..00000000000 --- a/appinventor/appengine/war/static/js/workspace-search-9.1.10.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see index.js.LICENSE.txt */ -!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var s="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in s)("object"==typeof exports?exports:t)[i]=s[i]}}(this,(t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},s={};function i(t){var n=s[t];if(void 0!==n)return n.exports;var o=s[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var s in e)i.o(e,s)&&!i.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:e[s]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};i.r(n),i.d(n,{WorkspaceSearch:()=>h});var o=i(370);const l=function(){let t=!1;return function(){if(t)return;t=!0;const e=document.createElement("style");e.id="blockly-ws-search-style";const s=document.createTextNode("path.blocklyPath.blockly-ws-search-highlight {\n fill: #000;\n }\n path.blocklyPath.blockly-ws-search-highlight.blockly-ws-search-current {\n fill: grey;\n }\n .blockly-ws-search-close-btn {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE0Ij48cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=) no-repeat top left;\n }\n .blockly-ws-search-next-btn {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE0Ij48cGF0aCBkPSJNNy40MSA4LjU5TDEyIDEzLjE3bDQuNTktNC41OEwxOCAxMGwtNiA2LTYtNiAxLjQxLTEuNDF6Ii8+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PC9zdmc+) no-repeat top left;\n }\n .blockly-ws-search-previous-btn {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE0Ij48cGF0aCBkPSJNNy40MSAxNS40MUwxMiAxMC44M2w0LjU5IDQuNThMMTggMTRsLTYtNi02IDZ6Ii8+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==) no-repeat top left;\n }\n .blockly-ws-search {\n background: #fff;\n border: solid lightgrey 0.5px;\n box-shadow: 0px 10px 20px grey;\n justify-content: center;\n padding: 0.25em;\n position: absolute;\n z-index: 70;\n }\n .blockly-ws-search-input input {\n border: none;\n }\n .blockly-ws-search button {\n border: none;\n padding-left: 6px;\n padding-right: 6px;\n }\n .blockly-ws-search-actions {\n display: flex;\n }\n .blockly-ws-search-container {\n display: flex;\n }\n .blockly-ws-search-content {\n display: flex;\n }");e.appendChild(s),document.head.insertBefore(e,document.head.firstChild)}}();class h{constructor(t){this.workspace=t,this.id="workspaceSearch",this.htmlDiv=null,this.actionDiv=null,this.inputElement=null,this.textInputPlaceholder="Search",this.blocks=[],this.currentBlockIndex=-1,this.searchText="",this.searchOnInput=!0,this.caseSensitive=!1,this.preserveSelected=!0,this.boundEvents=[]}init(){this.workspace.getComponentManager().addComponent({component:this,weight:0,capabilities:[o.ComponentManager.Capability.POSITIONABLE]}),l(),this.createDom(),this.setVisible(!1),this.workspace.resize()}dispose(){for(const t of this.boundEvents)o.browserEvents.unbind(t);this.boundEvents.length=0,this.htmlDiv&&(this.htmlDiv.remove(),this.htmlDiv=null),this.actionDiv=null,this.inputElement=null}createDom(){const t=this.workspace.getInjectionDiv();this.addEvent(t,"keydown",this,(t=>this.onWorkspaceKeyDown(t))),this.htmlDiv=document.createElement("div"),o.utils.dom.addClass(this.htmlDiv,"blockly-ws-search");const e=document.createElement("div");o.utils.dom.addClass(e,"blockly-ws-search-container");const s=document.createElement("div");o.utils.dom.addClass(s,"blockly-ws-search-content"),e.appendChild(s);const i=document.createElement("div");o.utils.dom.addClass(i,"blockly-ws-search-input"),this.inputElement=this.createTextInput(),this.addEvent(this.inputElement,"keydown",this,(t=>this.onKeyDown(t))),this.addEvent(this.inputElement,"input",this,(()=>this.onInput())),this.addEvent(this.inputElement,"click",this,(()=>{var t;this.searchAndHighlight(this.searchText,this.preserveSelected),null===(t=this.inputElement)||void 0===t||t.select()})),i.appendChild(this.inputElement),s.appendChild(i),this.actionDiv=document.createElement("div"),o.utils.dom.addClass(this.actionDiv,"blockly-ws-search-actions"),s.appendChild(this.actionDiv);const n=this.createNextBtn();n&&this.addActionBtn(n,(()=>this.next()));const l=this.createPreviousBtn();l&&this.addActionBtn(l,(()=>this.previous()));const h=this.createCloseBtn();h&&(this.addBtnListener(h,(()=>this.close())),e.appendChild(h)),this.htmlDiv.appendChild(e),t.insertBefore(this.htmlDiv,this.workspace.getParentSvg())}addEvent(t,e,s,i){const n=o.browserEvents.conditionalBind(t,e,s,i);this.boundEvents.push(n)}addActionBtn(t,e){var s;this.addBtnListener(t,e),null===(s=this.actionDiv)||void 0===s||s.appendChild(t)}createTextInput(){const t=document.createElement("input");return t.type="text",t.setAttribute("placeholder",this.textInputPlaceholder),t}createNextBtn(){return this.createBtn("blockly-ws-search-next-btn","Find next")}createPreviousBtn(){return this.createBtn("blockly-ws-search-previous-btn","Find previous")}createCloseBtn(){return this.createBtn("blockly-ws-search-close-btn","Close search bar")}createBtn(t,e){const s=document.createElement("button");return o.utils.dom.addClass(s,t),s.setAttribute("aria-label",e),s}addBtnListener(t,e){this.addEvent(t,"click",this,e),this.addEvent(t,"keydown",this,(t=>{"Enter"===t.key?(e(t),t.preventDefault()):"Escape"===t.key&&this.close(),t.stopPropagation()}))}getBoundingRectangle(){return null}position(t,e){this.htmlDiv&&(this.workspace.RTL?this.htmlDiv.style.left=t.absoluteMetrics.left+"px":t.toolboxMetrics.position===o.TOOLBOX_AT_RIGHT?this.htmlDiv.style.right=t.toolboxMetrics.width+"px":this.htmlDiv.style.right="0",this.htmlDiv.style.top=t.absoluteMetrics.top+"px")}onInput(){if(this.searchOnInput&&this.inputElement){const t=this.inputElement.value.trim();t!==this.searchText&&this.searchAndHighlight(t,this.preserveSelected)}}onKeyDown(t){if("Escape"===t.key)this.close();else if("Enter"===t.key)if(this.searchOnInput)t.shiftKey?this.previous():this.next();else{if(!this.inputElement)return;const t=this.inputElement.value.trim();t!==this.searchText&&this.searchAndHighlight(t,this.preserveSelected)}}onWorkspaceKeyDown(t){(t.ctrlKey||t.metaKey)&&"f"===t.key&&(this.open(),t.preventDefault(),t.stopPropagation())}previous(){this.setCurrentBlock(this.currentBlockIndex-1)}next(){this.setCurrentBlock(this.currentBlockIndex+1)}setSearchPlaceholder(t){this.textInputPlaceholder=t,this.inputElement&&this.inputElement.setAttribute("placeholder",this.textInputPlaceholder)}setCurrentBlock(t){if(!this.blocks.length)return;let e=this.blocks[this.currentBlockIndex];e&&this.unhighlightCurrentSelection(e),this.currentBlockIndex=(t%this.blocks.length+this.blocks.length)%this.blocks.length,e=this.blocks[this.currentBlockIndex],this.highlightCurrentSelection(e),this.workspace.centerOnBlock(e.id,!1)}open(){var t,e;this.setVisible(!0),null===(t=this.inputElement)||void 0===t||t.focus(),null===(e=this.inputElement)||void 0===e||e.select(),this.searchText&&this.searchAndHighlight(this.searchText)}close(){this.setVisible(!1),this.workspace.markFocused(),this.clearBlocks()}setVisible(t){this.htmlDiv&&(this.htmlDiv.style.display=t?"flex":"none")}searchAndHighlight(t,e){const s=this.blocks[this.currentBlockIndex];this.searchText=t.trim(),this.clearBlocks(),this.blocks=this.getMatchingBlocks(this.workspace,this.searchText,this.caseSensitive),this.highlightSearchGroup(this.blocks);let i=0;e&&(i=this.blocks.indexOf(s),i=i>-1?i:0),this.setCurrentBlock(i)}getSearchPool(t){return t.getAllBlocks(!0).filter((t=>{const e=t.getSurroundParent();return!e||!e.isCollapsed()}))}isBlockMatch(t,e,s){let i="";if(t.isCollapsed())i=t.toString();else{const e=[];t.inputList.forEach((t=>{t.fieldRow.forEach((t=>{e.push(t.getText())}))})),i=e.join(" ").trim()}return s||(i=i.toLowerCase()),i.indexOf(e)>-1}getMatchingBlocks(t,e,s){return e?(this.caseSensitive||(e=e.toLowerCase()),this.getSearchPool(t).filter((t=>this.isBlockMatch(t,e,s)))):[]}clearBlocks(){this.unhighlightSearchGroup(this.blocks);const t=this.blocks[this.currentBlockIndex];t&&this.unhighlightCurrentSelection(t),this.currentBlockIndex=-1,this.blocks=[]}highlightCurrentSelection(t){const e=t.pathObject.svgPath;o.utils.dom.addClass(e,"blockly-ws-search-current")}unhighlightCurrentSelection(t){const e=t.pathObject.svgPath;o.utils.dom.removeClass(e,"blockly-ws-search-current")}highlightSearchGroup(t){t.forEach((t=>{const e=t.pathObject.svgPath;o.utils.dom.addClass(e,"blockly-ws-search-highlight")}))}unhighlightSearchGroup(t){t.forEach((t=>{const e=t.pathObject.svgPath;o.utils.dom.removeClass(e,"blockly-ws-search-highlight")}))}}return n})())); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html b/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html index 0fa72540732..56a24dab3ef 100644 --- a/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html +++ b/appinventor/blocklyeditor/tests/com/google/appinventor/mocha/index.html @@ -11,7 +11,7 @@ - + diff --git a/appinventor/karma.conf.js b/appinventor/karma.conf.js index f3899f5932b..fd0cfd5862c 100644 --- a/appinventor/karma.conf.js +++ b/appinventor/karma.conf.js @@ -21,7 +21,7 @@ module.exports = function(config) { 'build/blocklyeditor/blockly-all.js', 'build/blocklyeditor/component-types.js', 'appengine/war/static/js/scroll-options-7.0.8.min.js', - 'appengine/war/static/js/workspace-search-9.1.10.min.js', + 'appengine/war/static/js/workspace-search-10.1.7.min.js', 'appengine/war/static/js/block-dynamic-connection-0.7.16.min.js', 'appengine/war/static/js/blockly-field-colour-5.0.19.min.js', 'appengine/war/static/js/workspace-multiselect-pr135-edf5dd2.min.js', From 29a26b54dd4e371fe5f368f3b1dbb59a1bd7c662 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sun, 11 Jan 2026 17:41:58 -0800 Subject: [PATCH 10/32] Update to @blockly/block-dynamic-connection 0.8.8 --- appinventor/appengine/war/index.jsp | 2 +- .../war/static/js/block-dynamic-connection-0.7.16.min.js | 3 --- .../war/static/js/block-dynamic-connection-0.8.8.min.js | 3 +++ .../tests/com/google/appinventor/mocha/index.html | 2 +- appinventor/karma.conf.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 appinventor/appengine/war/static/js/block-dynamic-connection-0.7.16.min.js create mode 100644 appinventor/appengine/war/static/js/block-dynamic-connection-0.8.8.min.js diff --git a/appinventor/appengine/war/index.jsp b/appinventor/appengine/war/index.jsp index 15992ad5bb7..2c78bca306e 100644 --- a/appinventor/appengine/war/index.jsp +++ b/appinventor/appengine/war/index.jsp @@ -122,7 +122,7 @@ - + diff --git a/appinventor/appengine/war/static/js/block-dynamic-connection-0.7.16.min.js b/appinventor/appengine/war/static/js/block-dynamic-connection-0.7.16.min.js deleted file mode 100644 index 406e142a853..00000000000 --- a/appinventor/appengine/war/static/js/block-dynamic-connection-0.7.16.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see index.js.LICENSE.txt */ -!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in n)("object"==typeof exports?exports:t)[i]=n[i]}}(this,(t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},n={};function i(t){var s=n[t];if(void 0!==s)return s.exports;var o=n[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};i.r(s),i.d(s,{blockIsDynamic:()=>a,decoratePreviewer:()=>p,finalizeConnections:()=>c,overrideOldBlockDefinitions:()=>h});var o=i(370);const l={minInputs:1,elseifCount:0,elseCount:0,init(){this.setHelpUrl(o.Msg.CONTROLS_IF_HELPURL),this.setStyle("logic_blocks"),this.addFirstCase(),this.setNextStatement(!0),this.setPreviousStatement(!0),this.setTooltip(o.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){if(this.isDeadOrDying()||(o.Events.disable(),this.finalizeConnections(),this instanceof o.BlockSvg&&this.initSvg(),o.Events.enable()),!this.elseifCount&&!this.elseCount)return null;const t=o.utils.xml.createElement("mutation");return this.elseifCount&&t.setAttribute("elseif",`${this.elseifCount}`),this.elseCount&&t.setAttribute("else","1"),t},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(t){const e=t.getAttribute("inputs");if(e){const t=e.split(",");this.getInput("IF0")&&this.removeInput("IF0"),this.getInput("DO0")&&this.removeInput("DO0");const n=t[0];this.appendValueInput("IF"+n).setCheck("Boolean").appendField(o.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO"+n).appendField(o.Msg.CONTROLS_IF_MSG_THEN);for(let e=1;e=0;t--)this.removeInput(this.inputList[t].name)},addCaseInputs(t){var e,n;for(let i=0;ithis.appendValueInput(t))),this.inputList[0].appendField(o.Msg.TEXT_JOIN_TITLE_CREATEWITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection})));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;ethis.appendValueInput(t))),this.inputList[0].appendField(o.Msg.LISTS_CREATE_WITH_INPUT_WITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection})));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;e(()=>{"use strict";var e={370:e=>{e.exports=t}},n={};function i(t){var s=n[t];if(void 0!==s)return s.exports;var o=n[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};i.r(s),i.d(s,{blockIsDynamic:()=>a,decoratePreviewer:()=>p,finalizeConnections:()=>c,overrideOldBlockDefinitions:()=>h});var o=i(370);const l={minInputs:1,elseifCount:0,elseCount:0,init(){this.setHelpUrl(o.Msg.CONTROLS_IF_HELPURL),this.setStyle("logic_blocks"),this.addFirstCase(),this.setNextStatement(!0),this.setPreviousStatement(!0),this.setTooltip(o.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){if(this.isDeadOrDying()||(o.Events.disable(),this.finalizeConnections(),this instanceof o.BlockSvg&&this.initSvg(),o.Events.enable()),!this.elseifCount&&!this.elseCount)return null;const t=o.utils.xml.createElement("mutation");return this.elseifCount&&t.setAttribute("elseif",`${this.elseifCount}`),this.elseCount&&t.setAttribute("else","1"),t},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(t){const e=t.getAttribute("inputs");if(e){const t=e.split(",");this.getInput("IF0")&&this.removeInput("IF0"),this.getInput("DO0")&&this.removeInput("DO0");const n=t[0];this.appendValueInput("IF"+n).setCheck("Boolean").appendField(o.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO"+n).appendField(o.Msg.CONTROLS_IF_MSG_THEN);for(let e=1;e=0;t--)this.removeInput(this.inputList[t].name)},addCaseInputs(t){var e,n;for(let i=0;ithis.appendValueInput(t)),this.inputList[0].appendField(o.Msg.TEXT_JOIN_TITLE_CREATEWITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection}));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;ethis.appendValueInput(t)),this.inputList[0].appendField(o.Msg.LISTS_CREATE_WITH_INPUT_WITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection}));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;e - + diff --git a/appinventor/karma.conf.js b/appinventor/karma.conf.js index fd0cfd5862c..b7665d595a3 100644 --- a/appinventor/karma.conf.js +++ b/appinventor/karma.conf.js @@ -22,7 +22,7 @@ module.exports = function(config) { 'build/blocklyeditor/component-types.js', 'appengine/war/static/js/scroll-options-7.0.8.min.js', 'appengine/war/static/js/workspace-search-10.1.7.min.js', - 'appengine/war/static/js/block-dynamic-connection-0.7.16.min.js', + 'appengine/war/static/js/block-dynamic-connection-0.8.8.min.js', 'appengine/war/static/js/blockly-field-colour-5.0.19.min.js', 'appengine/war/static/js/workspace-multiselect-pr135-edf5dd2.min.js', 'blocklyeditor/tests/testCommon.js', From 7a5c12a47b52e19fffa811421e22e1d6e01ed9aa Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sun, 11 Jan 2026 17:44:37 -0800 Subject: [PATCH 11/32] Update to @blockly/field-colour 6.0.11 --- appinventor/appengine/war/index.jsp | 2 +- .../appengine/war/static/js/blockly-field-colour-5.0.19.min.js | 3 --- .../appengine/war/static/js/blockly-field-colour-6.0.11.min.js | 3 +++ .../tests/com/google/appinventor/mocha/index.html | 2 +- appinventor/karma.conf.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 appinventor/appengine/war/static/js/blockly-field-colour-5.0.19.min.js create mode 100644 appinventor/appengine/war/static/js/blockly-field-colour-6.0.11.min.js diff --git a/appinventor/appengine/war/index.jsp b/appinventor/appengine/war/index.jsp index 2c78bca306e..4b5b2b6c9a7 100644 --- a/appinventor/appengine/war/index.jsp +++ b/appinventor/appengine/war/index.jsp @@ -129,7 +129,7 @@ - + - + diff --git a/appinventor/karma.conf.js b/appinventor/karma.conf.js index b7665d595a3..710592a36df 100644 --- a/appinventor/karma.conf.js +++ b/appinventor/karma.conf.js @@ -23,7 +23,7 @@ module.exports = function(config) { 'appengine/war/static/js/scroll-options-7.0.8.min.js', 'appengine/war/static/js/workspace-search-10.1.7.min.js', 'appengine/war/static/js/block-dynamic-connection-0.8.8.min.js', - 'appengine/war/static/js/blockly-field-colour-5.0.19.min.js', + 'appengine/war/static/js/blockly-field-colour-6.0.11.min.js', 'appengine/war/static/js/workspace-multiselect-pr135-edf5dd2.min.js', 'blocklyeditor/tests/testCommon.js', 'blocklyeditor/tests/com/google/appinventor/mocha/*.js', From b9b6de75241b8d140ae9ea2147f4ac601ef4da1a Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Tue, 13 Jan 2026 13:04:23 -0800 Subject: [PATCH 12/32] Update typeblocking to josmas-pr5-414bba9 --- appinventor/blocklyeditor/build.xml | 2 +- .../lib/blockly-plugins/typeblocking-josmas-pr4-cb783e3.min.js | 3 --- .../lib/blockly-plugins/typeblocking-josmas-pr5-414bba9.min.js | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 appinventor/lib/blockly-plugins/typeblocking-josmas-pr4-cb783e3.min.js create mode 100644 appinventor/lib/blockly-plugins/typeblocking-josmas-pr5-414bba9.min.js diff --git a/appinventor/blocklyeditor/build.xml b/appinventor/blocklyeditor/build.xml index d4b580581a2..2938a71a463 100644 --- a/appinventor/blocklyeditor/build.xml +++ b/appinventor/blocklyeditor/build.xml @@ -136,7 +136,7 @@ - + diff --git a/appinventor/lib/blockly-plugins/typeblocking-josmas-pr4-cb783e3.min.js b/appinventor/lib/blockly-plugins/typeblocking-josmas-pr4-cb783e3.min.js deleted file mode 100644 index b10836dbb9b..00000000000 --- a/appinventor/lib/blockly-plugins/typeblocking-josmas-pr4-cb783e3.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see index.js.LICENSE.txt */ -!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var o in n)("object"==typeof exports?exports:t)[o]=n[o]}}(this,(t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},n={};function o(t){var s=n[t];if(void 0!==s)return s.exports;var i=n[t]={exports:{}};return e[t](i,i.exports,o),i.exports}o.d=(t,e)=>{for(var n in e)o.o(e,n)&&!o.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};o.r(s),o.d(s,{TypeBlocking:()=>L});var i=o(370);const r="floatInput";function c(t){return t.replace(/_/g," ")}class a{constructor(t){this.workspace=t}setScopeAnalyzer(t){this.scopeAnalyzer=t}generateOptions(){const t=[];t.push(...this.getBuiltinBlockOptions()),t.push(...this.getVariableOptions()),t.push(...this.getProcedureOptions());const e=new Set;return t.filter((t=>{const n=`${t.blockType}:${t.displayText}`;return!e.has(n)&&(e.add(n),!0)}))}getVariableOptions(){const t=[],e=this.workspace.getVariablesOfType("");for(const n of e){const e=n.name;t.push({blockType:`get ${e}`,displayText:`get ${e}`}),t.push({blockType:`set ${e} to`,displayText:`set ${e} to`})}if(this.scopeAnalyzer){const e=this.scopeAnalyzer.getLocalVariablesInScope();console.log("Local variables in scope:",e);for(const n of e)t.push({blockType:`get ${n}`,displayText:`get ${n}`}),t.push({blockType:`set ${n} to`,displayText:`set ${n} to`})}return t}getProcedureOptions(){const t=[],e=this.workspace.getAllBlocks(!1);for(const n of e)if("procedures_defnoreturn"===n.type||"procedures_defreturn"===n.type){const e=n.getField("NAME");if(e){const o=e.getValue();if(o&&o.trim()){t.push({blockType:o,displayText:o});const e=this.getProcedureParameters(n);if(e.length>0){const n=`${o}(${e.join(", ")})`;t.push({blockType:n,displayText:n})}}}}return t}getBuiltinBlockOptions(){const t=[];for(const e in i.Blocks){const n=i.Blocks[e];this.shouldSkipBlock(e)||(n.typeblock?t.push({blockType:e,displayText:n.typeblock}):this.isValidBuiltinBlock(e)&&t.push({blockType:e,displayText:c(e)}))}return t}getProcedureParameters(t){const e=[];if(t.getVars){const n=t.getVars();e.push(...n)}return e}shouldSkipBlock(t){return[/^procedures_/,/^variables_get$/,/^variables_set$/,/^_/].some((e=>e.test(t)))}isValidBuiltinBlock(t){return i.Blocks[t]}}class l{constructor(t={}){var e,n,o,s,i,r,c,a;this.patterns=[],this.detectionCache=new Map,this.config={enableNumberDetection:null===(e=t.enableNumberDetection)||void 0===e||e,enableTextDetection:null===(n=t.enableTextDetection)||void 0===n||n,enableBooleanDetection:null===(o=t.enableBooleanDetection)||void 0===o||o,enableMathExpressions:null===(s=t.enableMathExpressions)||void 0===s||s,enableVariableAssignments:null===(i=t.enableVariableAssignments)||void 0===i||i,customPatterns:null!==(r=t.customPatterns)&&void 0!==r?r:[],patternPriorities:null!==(c=t.patternPriorities)&&void 0!==c?c:{},confidenceThreshold:null!==(a=t.confidenceThreshold)&&void 0!==a?a:.7},this.initializePatterns()}initializePatterns(){this.patterns.push(...this.config.customPatterns),this.sortPatterns()}registerBuiltinPatterns(t){const e=t.filter((t=>this.isPatternEnabled(t)));e.forEach((t=>{this.config.patternPriorities[t.name]&&(t.priority=this.config.patternPriorities[t.name])})),this.patterns.push(...e),this.sortPatterns()}isPatternEnabled(t){switch(t.name){case"number":return this.config.enableNumberDetection;case"text":return this.config.enableTextDetection;case"boolean":return this.config.enableBooleanDetection;case"math_expression":return this.config.enableMathExpressions;case"variable_assignment":return this.config.enableVariableAssignments;default:return!0}}sortPatterns(){this.patterns.sort(((t,e)=>e.priority-t.priority))}detectPattern(t){if(this.detectionCache.has(t))return this.detectionCache.get(t);let e=null;for(const n of this.patterns){const o=t.match(n.pattern);if(o){const s=this.calculateConfidence(n,o,t);if(s>=this.config.confidenceThreshold){const i={pattern:n,match:o,confidence:s};if(s>=.95)return this.detectionCache.set(t,i),i;(!e||s>e.confidence)&&(e=i)}}}return this.detectionCache.set(t,e),e}calculateConfidence(t,e,n){let o=.8;return e[0]===n.trim()&&(o+=.15),t.isComplete&&t.isComplete(n)&&(o+=.05),o+=t.priority/1e3,Math.min(o,1)}getBlockInstructions(t){const e=this.detectPattern(t);if(!e)return null;try{const n=e.pattern.parseInput(e.match);return n&&console.debug(`Generated block instruction using pattern: ${e.pattern.name}`,{input:t,confidence:e.confidence,blockType:n.blockType}),n}catch(t){return console.error(`Failed to generate instruction using pattern ${e.pattern.name}:`,t),null}}getSuggestions(t){const e=[];for(const n of this.patterns){if(n.generateSuggestions){const o=t.match(n.pattern);if(o){const t=n.generateSuggestions(o);e.push(...t.map((t=>({text:t,description:n.description,example:this.getPatternExample(n),patternName:n.name}))))}}this.isPartialMatch(t,n)&&e.push({text:this.getPatternExample(n),description:`${n.description} (example)`,example:this.getPatternExample(n),patternName:n.name})}return e}isPartialMatch(t,e){const n=t.trim();if(0===n.length)return!1;const o=["","0","1","true","false",'"',")"];for(const t of o){const o=n+t;if(e.pattern.test(o))return!0}return!1}getPatternExample(t){switch(t.name){case"number":return"42";case"text":return'"hello world"';case"boolean":return"true";case"math_expression":return"2 + 3";case"variable_assignment":return"set x to 5";default:return"example"}}isPatternMatch(t){return null!==this.detectPattern(t)}getPatterns(){return[...this.patterns]}clearCache(){this.detectionCache.clear()}updateConfig(t){this.config=Object.assign(Object.assign({},this.config),t),this.patterns=[],this.clearCache(),this.initializePatterns()}}class u{isComplete(t){return this.pattern.test(t.trim())}}class p extends u{constructor(){super(...arguments),this.name="number",this.pattern=/^-?\d*\.?\d+$/,this.priority=100,this.description="Create number block from numeric input"}parseInput(t){const e=t[0],n=parseFloat(e);return isNaN(n)?null:{blockType:"math_number",fieldValues:{NUM:e}}}generateSuggestions(t){const e=t[0],n=[e],o=parseFloat(e);return isNaN(o)||n.push(String(o+1),String(o-1),String(10*o),String(Math.abs(o))),n}}class h extends u{constructor(){super(...arguments),this.name="text",this.pattern=/^["'](.*)["']$/,this.priority=95,this.description="Create text block from quoted string"}parseInput(t){return{blockType:"text",fieldValues:{TEXT:t[1]}}}generateSuggestions(t){const e=t[1];return[`"${e}"`,`'${e}'`,'"hello world"','"example text"']}}class d extends u{constructor(){super(...arguments),this.name="boolean",this.pattern=/^(true|false)$/i,this.priority=90,this.description="Create boolean block from true/false"}parseInput(t){return{blockType:"logic_boolean",fieldValues:{BOOL:"true"===t[1].toLowerCase()?"TRUE":"FALSE"}}}generateSuggestions(){return["true","false"]}}class g extends u{constructor(){super(...arguments),this.name="math_expression",this.pattern=/^(\d+(?:\.\d+)?)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/,this.priority=80,this.description="Create arithmetic block from math expression",this.operatorMap={"+":"ADD","-":"MINUS","*":"MULTIPLY","/":"DIVIDE"}}parseInput(t){const[,e,n,o]=t;return this.operatorMap[n]?{blockType:"math_arithmetic",fieldValues:{OP:this.operatorMap[n]},children:[{input:"A",instruction:{blockType:"math_number",fieldValues:{NUM:e}}},{input:"B",instruction:{blockType:"math_number",fieldValues:{NUM:o}}}]}:null}generateSuggestions(t){const[,e,n,o]=t,s=parseFloat(e),i=parseFloat(o),r=[t[0]];for(const t of["+","-","*","/"])t!==n&&r.push(`${e} ${t} ${o}`);return r.push(`${s+1} ${n} ${o}`,`${e} ${n} ${i+1}`,`${10*s} ${n} ${o}`),r}}class f extends u{constructor(){super(...arguments),this.name="variable_assignment",this.pattern=/^set\s+(\w+)\s+to\s+(.+)$/i,this.priority=85,this.description='Create variable assignment from "set var to value" syntax'}parseInput(t){const[,e,n]=t,o=this.parseValueInstruction(n.trim());return o?{blockType:"variables_set",fieldValues:{VAR:e},children:[{input:"VALUE",instruction:o}]}:null}parseValueInstruction(t){if(/^-?\d*\.?\d+$/.test(t))return{blockType:"math_number",fieldValues:{NUM:t}};const e=t.match(/^["'](.*)["']$/);return e?{blockType:"text",fieldValues:{TEXT:e[1]}}:/^(true|false)$/i.test(t)?{blockType:"logic_boolean",fieldValues:{BOOL:"true"===t.toLowerCase()?"TRUE":"FALSE"}}:/^\w+$/.test(t)?{blockType:"variables_get",fieldValues:{VAR:t}}:null}generateSuggestions(t){const[,e,n]=t;return[`set ${e} to ${n}`,`set ${e} to 0`,`set ${e} to "text"`,`set ${e} to true`,"set myVar to 42","set count to 0"]}}function m(){return[new p,new h,new d,new g,new f]}function k(t){return{blockType:t,displayText:t}}class b extends a{constructor(t,e){super(t),this.lastInput="",this.lastSuggestions=[],this.patternManager=new l(e),this.patternManager.registerBuiltinPatterns(m())}generateOptionsForInput(t){if(t===this.lastInput&&this.lastSuggestions.length>0)return this.lastSuggestions;const e=t.trim(),n=this.generateOptions(),o=this.getPatternSuggestions(e),s=this.filterAndRankOptions(n,e),i=this.combineOptions(o,s,e);return this.lastInput=t,this.lastSuggestions=i,i}getPatternSuggestions(t){if(!t)return[];const e=[],n=this.patternManager.detectPattern(t);console.debug("SmartOptionGenerator: Pattern detection for",t,":",n),n&&(e.push(k(t)),console.debug("SmartOptionGenerator: Added pattern input as suggestion:",t));const o=this.patternManager.getSuggestions(t);if(console.debug("SmartOptionGenerator: Pattern manager suggestions:",o),e.push(...o.map((t=>k(t.text)))),this.isPartialPatternInput(t)){const n=this.getPatternExamples(t);console.debug("SmartOptionGenerator: Pattern examples:",n),e.push(...n.map((t=>k(t))))}console.debug("SmartOptionGenerator: Final pattern suggestions:",e);const s=new Set;return e.filter((t=>{const e=`${t.blockType}:${t.displayText}`;return!s.has(e)&&(s.add(e),!0)}))}isPartialPatternInput(t){return 0!==t.length&&[/^\d+$/,/^["']/,/^(true|false)$/i,/^\d+\s*[+\-*/]/,/^set\s+\w*/,/^get\s+/,/^when\s+/].some((e=>e.test(t)))}getPatternExamples(t){const e=[];if(/^\d/.test(t)&&e.push("42","3.14",`${t} + 1`,`${t} * 2`),/^["']/.test(t)&&e.push('"hello world"',"'example text'"),/^(t|f)/i.test(t)&&e.push("true","false"),/^set/i.test(t)&&e.push("set x to 5",'set name to "hello"',"set flag to true"),/^get/i.test(t)){const t=this.workspace.getVariablesOfType("");e.push(...t.map((t=>`get ${t.name}`)))}return e}filterAndRankOptions(t,e){return e?t.map((t=>({option:t,score:this.calculateRelevanceScore(t.displayText,e)}))).filter((t=>t.score>0)).sort(((t,e)=>e.score-t.score)).map((t=>t.option)):t}calculateRelevanceScore(t,e){const n=t.toLowerCase(),o=e.toLowerCase();let s=0;return n===o?100:(n.startsWith(o)&&(s+=50),n.includes(o)&&(s+=25),s+=this.getContextualBonus(t,e),e.length<3&&t.length>20&&(s-=10),Math.max(0,s))}getContextualBonus(t,e){let n=0;return/^\d/.test(e)&&/math|number|arithmetic|calculate/.test(t.toLowerCase())&&(n+=15),/^["']/.test(e)&&/text|string|concat|join/.test(t.toLowerCase())&&(n+=15),/^(true|false)/i.test(e)&&/logic|boolean|compare|if/.test(t.toLowerCase())&&(n+=15),/set|get|var/i.test(e)&&/variable|var|get|set/.test(t.toLowerCase())&&(n+=15),n}combineOptions(t,e,n){const o=[],s=new Set;for(const e of t){const t=`${e.blockType}:${e.displayText}`;s.has(t)||(o.push(e),s.add(t))}const i=Math.max(10,20-t.length);for(const t of e.slice(0,i)){const e=`${t.blockType}:${t.displayText}`;s.has(e)||(o.push(t),s.add(e))}if(o.length<5&&n.length<3){const t=["if","repeat","set variable","math","text","true","false"];for(const e of t){const t=k(e),n=`${t.blockType}:${t.displayText}`;!s.has(n)&&o.length<10&&(o.push(t),s.add(n))}}return o}setScopeAnalyzer(t){super.setScopeAnalyzer(t)}}class y{constructor(t){this.workspace=t,this._needsReload=!0,this.eventListeners=[],this.setupEventListeners()}get needsReload(){return this._needsReload}invalidate(t){this._needsReload||(console.debug(`TypeBlocking options invalidated: ${t}`),this._needsReload=!0)}markReloaded(){this._needsReload=!1}dispose(){this.eventListeners.forEach((t=>t())),this.eventListeners=[]}setupEventListeners(){this.addEventHandler(i.Events.VAR_CREATE,"variable created"),this.addEventHandler(i.Events.VAR_DELETE,"variable deleted"),this.addEventHandler(i.Events.VAR_RENAME,"variable renamed"),this.addEventHandler(i.Events.BLOCK_CREATE,(t=>{this.handleBlockEvent(t)})),this.addEventHandler(i.Events.BLOCK_DELETE,(t=>{this.handleBlockEvent(t)})),this.addEventHandler(i.Events.BLOCK_CHANGE,(t=>{this.handleBlockChangeEvent(t)})),this.addEventHandler(i.Events.FINISHED_LOADING,"workspace loaded"),this.addWorkspaceChangeListener()}addEventHandler(t,e){const n=t=>{t.workspaceId===this.workspace.id&&("string"==typeof e?this.invalidate(e):e(t))};this.workspace.addChangeListener(n),this.eventListeners.push((()=>{this.workspace.removeChangeListener(n)}))}handleBlockEvent(t){const e=t.type;e&&this.isProcedureBlock(e)&&this.invalidate(`procedure block ${e}`)}handleBlockChangeEvent(t){const e=this.workspace.getBlockById(t.blockId);e&&this.isProcedureBlock(e.type)&&"field"===t.element&&"NAME"===t.name&&this.invalidate(`procedure name changed from ${t.oldValue} to ${t.newValue}`)}addWorkspaceChangeListener(){let t=null;const e=e=>{e.workspaceId===this.workspace.id&&(t&&clearTimeout(t),t=setTimeout((()=>{this.shouldInvalidateForGeneralChange(e)&&this.invalidate("workspace change"),t=null}),100))};this.workspace.addChangeListener(e),this.eventListeners.push((()=>{this.workspace.removeChangeListener(e),t&&clearTimeout(t)}))}isProcedureBlock(t){return"procedures_defnoreturn"===t||"procedures_defreturn"===t||"procedures_callnoreturn"===t||"procedures_callreturn"===t}shouldInvalidateForGeneralChange(t){return!["selected","click","theme_change","viewport_change"].includes(t.type)}}class v{constructor(t){this.workspace=t}getLocalVariablesInScope(){const t=this.getLocalVariablesFromSelection();return t.length>0?(console.log("Using selection context for local variables:",t),t):(console.log("No selection context available, falling back to all procedure parameters."),this.getAllProcedureParameters())}getLocalVariablesFromSelection(){const t=this.getEnclosingProcedureFromSelection();return t?this.getProcedureParameters(t):[]}getAllProcedureParameters(){const t=[],e=this.workspace.getAllBlocks(!1);for(const n of e)this.isProcedureDefinition(n)&&t.push(...this.getProcedureParameters(n));return[...new Set(t)]}getEnclosingProcedureFromSelection(){const t=i.common.getSelected();return t&&t instanceof i.BlockSvg?this.findEnclosingProcedure(t):null}findEnclosingProcedure(t){let e=t;for(;e;){if(this.isProcedureDefinition(e))return e;const t=e.getParent();if(t&&this.isProcedureDefinition(t))return t;e=t}return null}getProcedureParameters(t){const e=[];if(this.isProcedureDefinition(t)){if(t.getVars){const n=t.getVars();Array.isArray(n)&&e.push(...n)}const n=t.inputList;for(const t of n)for(const n of t.fieldRow)if(n.name&&n.name.startsWith("ARG")){const t=n.getValue();t&&"string"==typeof t&&t.trim()&&e.push(t.trim())}}return e}isProcedureDefinition(t){return"procedures_defnoreturn"===t.type||"procedures_defreturn"===t.type}}const C=(t,e)=>{const n=e.trim().toLowerCase();return n?t.filter((t=>t.displayText.toLowerCase().includes(n))):t};class w{constructor(t,e=""){this.highlighted=-1,this.suggestions=[],this.root=document.createElement("div"),this.root.innerHTML='\n \n \n ',this.input=this.root.querySelector(".fi-input"),this.list=this.root.querySelector(".fi-list"),this.input.value=e,this.list.addEventListener("mousemove",(t=>{const e=t.target.closest("li");if(e){const t=parseInt(e.dataset.idx,10);t!==this.highlighted&&this.updateHighlight(t)}})),this.list.addEventListener("mousedown",(e=>{e.preventDefault();const n=e.target.closest("li");if(n){const e=parseInt(n.dataset.idx,10);t(this.suggestions[e])}}))}focus(){this.input.focus();const t=this.input.value.length;this.input.setSelectionRange(t,t)}setSuggestions(t){this.suggestions=t,this.list.innerHTML="",t.forEach(((t,e)=>{const n=document.createElement("li");n.dataset.idx=e.toString(),n.textContent=t.displayText,this.list.appendChild(n)})),t.length>0?this.updateHighlight(0):this.highlighted=-1,this.list.hidden=0===t.length}onKey(t,e){const n=()=>this.highlighted>=0&&this.highlighted=0&&e[this.highlighted].classList.remove("fi-hl"),this.highlighted=t,this.highlighted>=0&&(e[this.highlighted].classList.add("fi-hl"),e[this.highlighted].scrollIntoView({block:"nearest"}))}}class T{constructor(t){this.workspace=t}createBlock(t,e,n){let o=this.createSpecialBlock(t);if(o)return o;let s=t;if(!i.Blocks[s])for(const e in i.Blocks)if(i.Blocks[e].typeblock===t){s=e;break}if(!i.Blocks[s])return void console.warn(`No block registered for "${t}"`);const r={type:s};if(e&&(r.extraState=e),n){r.fields={};for(const[t,e]of Object.entries(n))r.fields[t]=e}return i.serialization.blocks.append(r,this.workspace,{recordUndo:!0})}createBlockFromInstruction(t){try{const e=this.workspace.newBlock(t.blockType);if(t.fieldValues)for(const[n,o]of Object.entries(t.fieldValues)){const t=e.getField(n);if(t)if("VAR"!==n||"variables_set"!==e.type&&"variables_get"!==e.type)t.setValue(o);else{let e=this.workspace.getVariable(o);e||(e=this.workspace.createVariable(o)),t.setValue(e.getId())}}if(e.initSvg(),e.render(),t.children)for(const n of t.children){const t=this.createBlockFromInstruction(n.instruction);if(t){const o=e.getInput(n.input);o&&t.outputConnection&&t.outputConnection.connect(o.connection)}}return e}catch(t){return void console.warn("Failed to create block from instruction:",t)}}createSpecialBlock(t){const e=t.match(/^get\s+(.+)$/);if(e)return this.createVariableGetter(e[1]);const n=t.match(/^set\s+(.+?)\s+to$/);if(n)return this.createVariableSetter(n[1]);const o=t.match(/^([^(]+)(?:\([^)]*\))?$/);return o&&this.isProcedureName(o[1].trim())?this.createProcedureCall(o[1].trim()):void 0}createVariableGetter(t){var e;const n=this.workspace.getVariable(t);if(!n)return void console.warn(`Variable "${t}" not found`);const o=this.workspace.newBlock("variables_get");return null===(e=o.getField("VAR"))||void 0===e||e.setValue(n.getId()),o.initSvg(),o.render(),o}createVariableSetter(t){var e;const n=this.workspace.getVariable(t);if(!n)return void console.warn(`Variable "${t}" not found`);const o=this.workspace.newBlock("variables_set");return null===(e=o.getField("VAR"))||void 0===e||e.setValue(n.getId()),o.initSvg(),o.render(),o}createProcedureCall(t){var e,n;const o=this.workspace.getAllBlocks(!1);let s=!1;for(const n of o)if(("procedures_defnoreturn"===n.type||"procedures_defreturn"===n.type)&&(null===(e=n.getField("NAME"))||void 0===e?void 0:e.getValue())===t){s="procedures_defreturn"===n.type;break}const i=s?"procedures_callreturn":"procedures_callnoreturn",r=this.workspace.newBlock(i);return null===(n=r.getField("NAME"))||void 0===n||n.setValue(t),r.initSvg(),r.render(),r}isProcedureName(t){var e;const n=this.workspace.getAllBlocks(!1);for(const o of n)if(("procedures_defnoreturn"===o.type||"procedures_defreturn"===o.type)&&(null===(e=o.getField("NAME"))||void 0===e?void 0:e.getValue())===t)return!0;return!1}}class x{constructor(t){this.workspace=t,this.offsetCount=0}positionBlock(t,e,n){const o=this.workspace.getMetrics(),s=this.workspace.getInjectionDiv().getBoundingClientRect(),i=null!=e?e:s.left+s.width/2,r=null!=n?n:s.top+s.height/2;let c=(i-s.left)/this.workspace.scale+o.viewLeft,a=(r-s.top)/this.workspace.scale+o.viewTop;if(this.lastCreationX===i&&this.lastCreationY===r){this.offsetCount++;const t=this.offsetCount*x.OFFSET_STEP/this.workspace.scale;c+=t,a+=t}else this.offsetCount=0,this.lastCreationX=i,this.lastCreationY=r;t.moveBy(c,a)}}x.OFFSET_STEP=30;class P{areTypesCompatible(t,e){if(!t||!e)return!1;const n=t.getCheck(),o=e.getCheck();return!n||!o||n.some((t=>o.includes(t)))}isConnectionAvailable(t){return t&&!t.isConnected()}getWorkspaceScale(t){return t.scale||1}calculateDistance(t,e){const n=t.x-e.x,o=t.y-e.y;return Math.sqrt(n*n+o*o)}}class S extends P{constructor(){super(...arguments),this.priority=90,this.name="StatementSequence"}canConnect(t,e){const n=t.previousConnection;if(!n)return!1;const o=e.nextConnection;return!(!o||o.isConnected())&&this.areTypesCompatible(n,o)}connect(t,e){const n=t.previousConnection,o=e.nextConnection;if(!this.canConnect(t,e))return{success:!1,reason:"Blocks not compatible for statement sequence connection"};try{return n.connect(o),{success:!0,connectionType:"statement_sequence",targetConnection:o}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}}class B extends P{constructor(){super(...arguments),this.priority=80,this.name="ValueInput"}canConnect(t,e){return!!t.outputConnection&&null!==this.findCompatibleInput(t,e)}connect(t,e){const n=t.outputConnection;if(!n)return{success:!1,reason:"New block has no output connection"};const o=this.findCompatibleInput(t,e);if(!o)return{success:!1,reason:"No compatible input connection found"};try{return n.connect(o),{success:!0,connectionType:"value_input",targetConnection:o}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}findCompatibleInput(t,e){const n=t.outputConnection;if(!n)return null;for(const t of e.inputList)if(t.connection&&this.isConnectionAvailable(t.connection)&&this.areTypesCompatible(n,t.connection))return t.connection;return null}}class E extends P{constructor(){super(...arguments),this.priority=70,this.name="StatementInsertion"}canConnect(t,e){const n=t.nextConnection,o=t.previousConnection;if(!n||!o)return!1;const s=e.previousConnection;return!!s&&this.areTypesCompatible(n,s)&&this.areTypesCompatible(o,s)}connect(t,e){const n=t.nextConnection,o=t.previousConnection,s=e.previousConnection;if(!this.canConnect(t,e))return{success:!1,reason:"Blocks not compatible for statement insertion"};try{const t=s.targetConnection;return t&&(s.disconnect(),o.connect(t)),n.connect(s),{success:!0,connectionType:"statement_insertion",targetConnection:s}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}}class $ extends P{constructor(){super(...arguments),this.priority=60,this.name="Wrapper"}canConnect(t,e){const n=this.getStatementInputs(t);if(0===n.length)return!1;const o=e.previousConnection;return!!o&&this.areTypesCompatible(o,n[0])}connect(t,e){const n=this.getStatementInputs(t),o=e.previousConnection;if(!this.canConnect(t,e))return{success:!1,reason:"Blocks not compatible for wrapping"};try{const e=o.targetConnection;if(e){o.disconnect();const n=t.previousConnection;n&&this.areTypesCompatible(n,e)&&n.connect(e)}return o.connect(n[0]),{success:!0,connectionType:"wrapper",targetConnection:n[0]}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}getStatementInputs(t){const e=[];for(const n of t.inputList)n.type===i.inputs.inputTypes.STATEMENT&&n.connection&&e.push(n.connection);return e}}class I{constructor(t,e={}){var n,o,s,i;this.workspace=t,this.config={enableAutoConnection:null===(n=e.enableAutoConnection)||void 0===n||n,connectionRadius:null!==(o=e.connectionRadius)&&void 0!==o?o:200,maxNearbyBlocks:null!==(s=e.maxNearbyBlocks)&&void 0!==s?s:10,strategies:null!==(i=e.strategies)&&void 0!==i?i:this.getDefaultStrategies()},this.connectionStrategies=this.config.strategies.sort(((t,e)=>e.priority-t.priority))}getDefaultStrategies(){return[new S,new B,new E,new $]}attemptConnection(t,e,n,o){if(!this.config.enableAutoConnection)return null;const s=this.buildConnectionContext(t,e,n,o);return this.findAndMakeConnection(t,s)}buildConnectionContext(t,e,n,o){const s=Object.assign({},o);if(!s.selectedBlock){const t=i.common.getSelected();t&&t instanceof i.BlockSvg&&(s.selectedBlock=t)}return void 0!==e&&void 0!==n&&(s.cursorPosition={x:e,y:n}),s.nearbyBlocks||(s.nearbyBlocks=this.findNearbyBlocks(t,s.cursorPosition)),s}findAndMakeConnection(t,e){const n=this.getPriorizedTargetBlocks(t,e);for(const o of n)for(const n of this.connectionStrategies)if(n.canConnect(t,o,e)){console.debug(`Attempting connection with strategy: ${n.name}`);const s=n.connect(t,o,e);if(s.success)return console.debug(`Successfully connected using strategy: ${n.name}`),s;console.debug(`Connection failed with strategy ${n.name}: ${s.reason}`)}return console.debug("No suitable connection found for new block"),null}getPriorizedTargetBlocks(t,e){const n=[];if(e.selectedBlock&&n.push(e.selectedBlock),e.nearbyBlocks){const o=e.nearbyBlocks.filter((t=>t!==e.selectedBlock)).sort(((n,o)=>{const s=this.connectionStrategies.find((t=>"ValueInput"===t.name));if(!s)return 0;const i=s.canConnect(t,n,e),r=s.canConnect(t,o,e);if(i&&!r)return-1;if(!i&&r)return 1;if(i&&r){const t=this.countConnectedInputs(n),e=this.countConnectedInputs(o);if(t!==e)return t-e}return 0}));n.push(...o)}return[...new Set(n)]}findNearbyBlocks(t,e){const n=t.getRelativeToSurfaceXY(),o=e?this.clientToWorkspaceCoordinates(e.x,e.y):n,s=this.workspace.getAllBlocks(!1),i=[];for(const e of s){if(e===t)continue;const n=e.getRelativeToSurfaceXY(),s=this.calculateDistance(o,n);s<=this.config.connectionRadius&&i.push({block:e,distance:s})}return i.sort(((t,e)=>t.distance-e.distance)),i.slice(0,this.config.maxNearbyBlocks).map((t=>t.block))}clientToWorkspaceCoordinates(t,e){const n=this.workspace.getMetrics(),o=this.workspace.getInjectionDiv().getBoundingClientRect();return{x:(t-o.left)/this.workspace.scale+n.viewLeft,y:(e-o.top)/this.workspace.scale+n.viewTop}}calculateDistance(t,e){const n=t.x-e.x,o=t.y-e.y;return Math.sqrt(n*n+o*o)}getBlockDistance(t,e){const n=t.getRelativeToSurfaceXY(),o=e.cursorPosition?this.clientToWorkspaceCoordinates(e.cursorPosition.x,e.cursorPosition.y):n;return this.calculateDistance(o,n)}hasAvailableInputConnections(t){for(const e of t.inputList)if(e.connection&&!e.connection.isConnected())return!0;return!1}countConnectedInputs(t){let e=0;for(const n of t.inputList)n.connection&&n.connection.isConnected()&&e++;return e}setConfig(t){this.config=Object.assign(Object.assign({},this.config),t),t.strategies&&(this.connectionStrategies=t.strategies.sort(((t,e)=>e.priority-t.priority)))}getConfig(){return Object.assign({},this.config)}}class O{constructor(t,e){var n,o,s,i,r;this.ws=t,this.lastX=0,this.lastY=0,this.pointerMoveListener=t=>{this.lastX=t.x,this.lastY=t.y},this.ws=t,this.options=e.options,this.matcher=null!==(n=e.matcher)&&void 0!==n?n:C,this.optionGenerator=e.optionGenerator,this.inputPositioning={mode:null!==(s=null===(o=e.inputPositioning)||void 0===o?void 0:o.mode)&&void 0!==s?s:"mouse",fixedPosition:null!==(r=null===(i=e.inputPositioning)||void 0===i?void 0:i.fixedPosition)&&void 0!==r?r:{x:100,y:10}},this.blockFactory=new T(t),this.blockPositioner=new x(t),!1!==e.enablePatternRecognition&&(this.patternManager=new l(e.patternConfig),this.patternManager.registerBuiltinPatterns(m())),!1!==e.enableSmartConnection&&(this.connectionManager=new I(t,e.connectionConfig)),t.getInjectionDiv().addEventListener("pointermove",this.pointerMoveListener)}dispose(){this.ws.getInjectionDiv().removeEventListener("pointermove",this.pointerMoveListener)}show(t=""){i.WidgetDiv.show({},this.ws.RTL,(()=>this.ws.getInjectionDiv().focus()),this.ws);const e=new w((t=>this.choose(t)),t);i.WidgetDiv.getDiv().appendChild(e.root),this.positionWidgetDiv();const n=()=>{let t=this.options;this.optionGenerator instanceof b?(console.debug("TypeBlocking: Using smart option generation for query:",e.query),t=this.optionGenerator.generateOptionsForInput(e.query),console.debug("TypeBlocking: Generated",t.length,"options:",t.slice(0,5))):console.debug("TypeBlocking: Using static options, generator type:",typeof this.optionGenerator);const n=this.matcher(t,e.query);console.debug("TypeBlocking: After matching, got",n.length,"options:",n.slice(0,5)),e.setSuggestions(n)};e.inputEl.addEventListener("input",n),n(),e.inputEl.addEventListener("keydown",(t=>{e.onKey(t.key,(t=>this.choose(t)))?t.preventDefault():"Escape"===t.key&&i.WidgetDiv.hide(),t.stopPropagation()})),e.inputEl.addEventListener("blur",(()=>i.WidgetDiv.hide())),setTimeout((()=>e.focus()))}choose(t){let e;console.debug("TypeBlocking: Choosing option:",t),i.Events.setGroup(!0);try{if(this.patternManager){console.debug("TypeBlocking: Trying pattern recognition for:",t.blockType);const n=this.patternManager.getBlockInstructions(t.blockType);n&&(console.debug("TypeBlocking: Found pattern instruction:",n),e=this.blockFactory.createBlockFromInstruction(n),e&&console.debug("TypeBlocking: Created block using pattern recognition:",e.type))}e||(console.debug("TypeBlocking: Falling back to regular block creation"),e=this.blockFactory.createBlock(t.blockType,t.extraState,t.fieldValues),e&&console.debug("TypeBlocking: Created block using regular method:",e.type)),e?(this.blockPositioner.positionBlock(e,this.lastX,this.lastY),this.connectionManager&&this.connectionManager.attemptConnection(e,this.lastX,this.lastY),i.common.setSelected(e)):console.warn("TypeBlocking: Failed to create block for option:",t)}finally{i.Events.setGroup(!1)}i.WidgetDiv.hide()}positionWidgetDiv(){const t=i.WidgetDiv.getDiv();let e,n;if("fixed"===this.inputPositioning.mode){const t=this.ws.getInjectionDiv().getBoundingClientRect();e=t.left+this.inputPositioning.fixedPosition.x,n=t.top+this.inputPositioning.fixedPosition.y}else if(e=this.lastX,n=this.lastY,!e&&!n){const t=this.ws.getInjectionDiv().getBoundingClientRect();e=t.left+t.width/2,n=t.top+t.height/2}Object.assign(t.style,{position:"fixed",left:`${e}px`,top:`${n}px`})}}class V extends O{constructor(t,e){var n;super(t,{options:e.options,matcher:null!==(n=e.matcher)&&void 0!==n?n:C,enableSmartConnection:e.enableSmartConnection,connectionConfig:e.connectionConfig,enablePatternRecognition:e.enablePatternRecognition,patternConfig:e.patternConfig,optionGenerator:e.optionGenerator,inputPositioning:e.inputPositioning}),this.staticOptions=e.options,this.dynamicOptionGenerator=e.optionGenerator,this.stateTracker=e.stateTracker}getCurrentOptions(){return this.dynamicOptionGenerator&&this.stateTracker?(!this.stateTracker.needsReload&&this.cachedOptions||this.lazyLoadOptions(),this.cachedOptions||this.staticOptions):this.staticOptions}lazyLoadOptions(){if(!this.dynamicOptionGenerator||!this.stateTracker)return;console.debug("TypeBlocking: Regenerating options...");const t=performance.now();try{this.cachedOptions=this.dynamicOptionGenerator.generateOptions(),"markReloaded"in this.stateTracker&&this.stateTracker.markReloaded();const e=performance.now()-t;console.debug(`TypeBlocking: Generated ${this.cachedOptions.length} options in ${e.toFixed(2)}ms`)}catch(t){console.error("TypeBlocking: Error generating options:",t),this.cachedOptions=this.staticOptions}}show(t=""){const e=this.getCurrentOptions();this.options=e,super.show(t)}dispose(){this.cachedOptions=void 0,this.dynamicOptionGenerator=void 0,this.stateTracker=void 0,super.dispose()}}class L{constructor(t){this.workspace=t}init(t={}){const e=!1!==t.enableDynamicOptions;console.log("what am I enabling?",e),e?this.setupDynamicOptions(t):this.setupStaticOptions(t),console.info("Typeblocking initialized on workspace:",this.workspace.id)}setupDynamicOptions(t){var e;if(!1!==t.enablePatternRecognition?this.optionGenerator=t.optionGenerator||new b(this.workspace,t.patternConfig):this.optionGenerator=t.optionGenerator||new a(this.workspace),this.optionGenerator instanceof a){const t=new v(this.workspace);this.optionGenerator.setScopeAnalyzer(t)}this.stateTracker=null!==(e=t.workspaceStateTracker)&&void 0!==e?e:new y(this.workspace),this.installFloatingInput({options:[],matcher:t.matcher,enableSmartConnection:t.enableSmartConnection,connectionConfig:t.connectionConfig,enablePatternRecognition:t.enablePatternRecognition,patternConfig:t.patternConfig,inputPositioning:t.inputPositioning})}setupStaticOptions(t){const e=t.options||this.generateLegacyOptions();this.installFloatingInput({options:e,matcher:t.matcher,enableSmartConnection:t.enableSmartConnection,connectionConfig:t.connectionConfig,enablePatternRecognition:t.enablePatternRecognition,patternConfig:t.patternConfig,inputPositioning:t.inputPositioning})}generateLegacyOptions(){const t=[];i.Blocks.controls_if.typeblock=i.Msg.CONTROLS_IF_MSG_IF;for(const e in i.Blocks)e.split("_").length>1&&(i.Blocks[e].typeblock||(i.Blocks[e].typeblock=e),t.push(i.Blocks[e].typeblock));return t}dispose(){if(!this.workspace)return;const t=this.workspace.id;L.instancesByWorkspaceId.delete(t),this.stateTracker&&(this.stateTracker.dispose(),this.stateTracker=void 0),this.controller&&(this.controller.dispose(),this.controller=void 0),L.instancesByWorkspaceId.size||i.ShortcutRegistry.registry.unregister(r),i.DropDownDiv.hideWithoutAnimation(),this.optionGenerator=void 0,this.workspace=null,console.info(`Typeblocking disposed from workspace ${t}`)}installFloatingInput({options:t=[],matcher:e,enableSmartConnection:n,connectionConfig:o,enablePatternRecognition:s,patternConfig:c,inputPositioning:a}){if(this.controller=new V(this.workspace,{options:t,matcher:e,optionGenerator:this.optionGenerator,stateTracker:this.stateTracker,enableSmartConnection:n,connectionConfig:o,enablePatternRecognition:s,patternConfig:c,inputPositioning:a}),L.instancesByWorkspaceId.set(this.workspace.id,this),!i.ShortcutRegistry.registry.getRegistry()[r]){const t=t=>1===t.key.length&&!t.ctrlKey&&!t.metaKey&&!t.altKey;i.ShortcutRegistry.registry.register({name:r,preconditionFn:t=>L.instancesByWorkspaceId.has(t.id)&&!i.FieldTextInput.activeField&&!i.WidgetDiv.isVisible(),callback:(e,n)=>{const o=n;return L.instancesByWorkspaceId.get(e.id).controller.show(t(o)?o.key:""),!0}},!0);const e=new Set([8,9,13,16,17,18,19,20,27,33,34,35,36,37,38,39,40,45,46,91,112,113,114,115,116,117,118,119,120,121,122,123]);for(let t=0;t<=222;++t)e.has(t)||(i.ShortcutRegistry.registry.addKeyMapping(t,r,!0),i.ShortcutRegistry.registry.addKeyMapping(i.ShortcutRegistry.registry.createSerializedKey(t,[i.utils.KeyCodes.SHIFT]),r,!0))}}}return L.instancesByWorkspaceId=new Map,s})())); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/appinventor/lib/blockly-plugins/typeblocking-josmas-pr5-414bba9.min.js b/appinventor/lib/blockly-plugins/typeblocking-josmas-pr5-414bba9.min.js new file mode 100644 index 00000000000..2940b04ab43 --- /dev/null +++ b/appinventor/lib/blockly-plugins/typeblocking-josmas-pr5-414bba9.min.js @@ -0,0 +1,3 @@ +/*! For license information please see index.js.LICENSE.txt */ +!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var o in n)("object"==typeof exports?exports:t)[o]=n[o]}}(this,t=>(()=>{"use strict";var e={370(e){e.exports=t}},n={};function o(t){var s=n[t];if(void 0!==s)return s.exports;var i=n[t]={exports:{}};return e[t](i,i.exports,o),i.exports}o.d=(t,e)=>{for(var n in e)o.o(e,n)&&!o.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};o.r(s),o.d(s,{TypeBlocking:()=>L});var i=o(370);const r="floatInput";function c(t){return t.replace(/_/g," ")}class a{constructor(t){this.workspace=t}setScopeAnalyzer(t){this.scopeAnalyzer=t}generateOptions(){const t=[];t.push(...this.getBuiltinBlockOptions()),t.push(...this.getVariableOptions()),t.push(...this.getProcedureOptions());const e=new Set;return t.filter(t=>{const n=`${t.blockType}:${t.displayText}`;return!e.has(n)&&(e.add(n),!0)})}getVariableOptions(){const t=[],e=this.workspace.getVariablesOfType("");for(const n of e){const e=n.getName();t.push({blockType:`get ${e}`,displayText:`get ${e}`}),t.push({blockType:`set ${e} to`,displayText:`set ${e} to`})}if(this.scopeAnalyzer){const e=this.scopeAnalyzer.getLocalVariablesInScope();console.log("Local variables in scope:",e);for(const n of e)t.push({blockType:`get ${n}`,displayText:`get ${n}`}),t.push({blockType:`set ${n} to`,displayText:`set ${n} to`})}return t}getProcedureOptions(){const t=[],e=this.workspace.getAllBlocks(!1);for(const n of e)if("procedures_defnoreturn"===n.type||"procedures_defreturn"===n.type){const e=n.getField("NAME");if(e){const o=e.getValue();if(o&&o.trim()){t.push({blockType:o,displayText:o});const e=this.getProcedureParameters(n);if(e.length>0){const n=`${o}(${e.join(", ")})`;t.push({blockType:n,displayText:n})}}}}return t}getBuiltinBlockOptions(){const t=[];for(const e in i.Blocks){const n=i.Blocks[e];this.shouldSkipBlock(e)||(n.typeblock?t.push({blockType:e,displayText:n.typeblock}):this.isValidBuiltinBlock(e)&&t.push({blockType:e,displayText:c(e)}))}return t}getProcedureParameters(t){const e=[];if(t.getVars){const n=t.getVars();e.push(...n)}return e}shouldSkipBlock(t){return[/^procedures_/,/^variables_get$/,/^variables_set$/,/^_/].some(e=>e.test(t))}isValidBuiltinBlock(t){return i.Blocks[t]}}class l{constructor(t={}){var e,n,o,s,i,r,c,a;this.patterns=[],this.detectionCache=new Map,this.config={enableNumberDetection:null===(e=t.enableNumberDetection)||void 0===e||e,enableTextDetection:null===(n=t.enableTextDetection)||void 0===n||n,enableBooleanDetection:null===(o=t.enableBooleanDetection)||void 0===o||o,enableMathExpressions:null===(s=t.enableMathExpressions)||void 0===s||s,enableVariableAssignments:null===(i=t.enableVariableAssignments)||void 0===i||i,customPatterns:null!==(r=t.customPatterns)&&void 0!==r?r:[],patternPriorities:null!==(c=t.patternPriorities)&&void 0!==c?c:{},confidenceThreshold:null!==(a=t.confidenceThreshold)&&void 0!==a?a:.7},this.initializePatterns()}initializePatterns(){this.patterns.push(...this.config.customPatterns),this.sortPatterns()}registerBuiltinPatterns(t){const e=t.filter(t=>this.isPatternEnabled(t));e.forEach(t=>{this.config.patternPriorities[t.name]&&(t.priority=this.config.patternPriorities[t.name])}),this.patterns.push(...e),this.sortPatterns()}isPatternEnabled(t){switch(t.name){case"number":return this.config.enableNumberDetection;case"text":return this.config.enableTextDetection;case"boolean":return this.config.enableBooleanDetection;case"math_expression":return this.config.enableMathExpressions;case"variable_assignment":return this.config.enableVariableAssignments;default:return!0}}sortPatterns(){this.patterns.sort((t,e)=>e.priority-t.priority)}detectPattern(t){if(this.detectionCache.has(t))return this.detectionCache.get(t);let e=null;for(const n of this.patterns){const o=t.match(n.pattern);if(o){const s=this.calculateConfidence(n,o,t);if(s>=this.config.confidenceThreshold){const i={pattern:n,match:o,confidence:s};if(s>=.95)return this.detectionCache.set(t,i),i;(!e||s>e.confidence)&&(e=i)}}}return this.detectionCache.set(t,e),e}calculateConfidence(t,e,n){let o=.8;return e[0]===n.trim()&&(o+=.15),t.isComplete&&t.isComplete(n)&&(o+=.05),o+=t.priority/1e3,Math.min(o,1)}getBlockInstructions(t){const e=this.detectPattern(t);if(!e)return null;try{const n=e.pattern.parseInput(e.match);return n&&console.debug(`Generated block instruction using pattern: ${e.pattern.name}`,{input:t,confidence:e.confidence,blockType:n.blockType}),n}catch(t){return console.error(`Failed to generate instruction using pattern ${e.pattern.name}:`,t),null}}getSuggestions(t){const e=[];for(const n of this.patterns){if(n.generateSuggestions){const o=t.match(n.pattern);if(o){const t=n.generateSuggestions(o);e.push(...t.map(t=>({text:t,description:n.description,example:this.getPatternExample(n),patternName:n.name})))}}this.isPartialMatch(t,n)&&e.push({text:this.getPatternExample(n),description:`${n.description} (example)`,example:this.getPatternExample(n),patternName:n.name})}return e}isPartialMatch(t,e){const n=t.trim();if(0===n.length)return!1;const o=["","0","1","true","false",'"',")"];for(const t of o){const o=n+t;if(e.pattern.test(o))return!0}return!1}getPatternExample(t){switch(t.name){case"number":return"42";case"text":return'"hello world"';case"boolean":return"true";case"math_expression":return"2 + 3";case"variable_assignment":return"set x to 5";default:return"example"}}isPatternMatch(t){return null!==this.detectPattern(t)}getPatterns(){return[...this.patterns]}clearCache(){this.detectionCache.clear()}updateConfig(t){this.config=Object.assign(Object.assign({},this.config),t),this.patterns=[],this.clearCache(),this.initializePatterns()}}class u{isComplete(t){return this.pattern.test(t.trim())}}class p extends u{constructor(){super(...arguments),this.name="number",this.pattern=/^-?\d*\.?\d+$/,this.priority=100,this.description="Create number block from numeric input"}parseInput(t){const e=t[0],n=parseFloat(e);return isNaN(n)?null:{blockType:"math_number",fieldValues:{NUM:e}}}generateSuggestions(t){const e=t[0],n=[e],o=parseFloat(e);return isNaN(o)||n.push(String(o+1),String(o-1),String(10*o),String(Math.abs(o))),n}}class h extends u{constructor(){super(...arguments),this.name="text",this.pattern=/^["'](.*)["']$/,this.priority=95,this.description="Create text block from quoted string"}parseInput(t){return{blockType:"text",fieldValues:{TEXT:t[1]}}}generateSuggestions(t){const e=t[1];return[`"${e}"`,`'${e}'`,'"hello world"','"example text"']}}class d extends u{constructor(){super(...arguments),this.name="boolean",this.pattern=/^(true|false)$/i,this.priority=90,this.description="Create boolean block from true/false"}parseInput(t){return{blockType:"logic_boolean",fieldValues:{BOOL:"true"===t[1].toLowerCase()?"TRUE":"FALSE"}}}generateSuggestions(){return["true","false"]}}class g extends u{constructor(){super(...arguments),this.name="math_expression",this.pattern=/^(\d+(?:\.\d+)?)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/,this.priority=80,this.description="Create arithmetic block from math expression",this.operatorMap={"+":"ADD","-":"MINUS","*":"MULTIPLY","/":"DIVIDE"}}parseInput(t){const[,e,n,o]=t;return this.operatorMap[n]?{blockType:"math_arithmetic",fieldValues:{OP:this.operatorMap[n]},children:[{input:"A",instruction:{blockType:"math_number",fieldValues:{NUM:e}}},{input:"B",instruction:{blockType:"math_number",fieldValues:{NUM:o}}}]}:null}generateSuggestions(t){const[,e,n,o]=t,s=parseFloat(e),i=parseFloat(o),r=[t[0]];for(const t of["+","-","*","/"])t!==n&&r.push(`${e} ${t} ${o}`);return r.push(`${s+1} ${n} ${o}`,`${e} ${n} ${i+1}`,`${10*s} ${n} ${o}`),r}}class f extends u{constructor(){super(...arguments),this.name="variable_assignment",this.pattern=/^set\s+(\w+)\s+to\s+(.+)$/i,this.priority=85,this.description='Create variable assignment from "set var to value" syntax'}parseInput(t){const[,e,n]=t,o=this.parseValueInstruction(n.trim());return o?{blockType:"variables_set",fieldValues:{VAR:e},children:[{input:"VALUE",instruction:o}]}:null}parseValueInstruction(t){if(/^-?\d*\.?\d+$/.test(t))return{blockType:"math_number",fieldValues:{NUM:t}};const e=t.match(/^["'](.*)["']$/);return e?{blockType:"text",fieldValues:{TEXT:e[1]}}:/^(true|false)$/i.test(t)?{blockType:"logic_boolean",fieldValues:{BOOL:"true"===t.toLowerCase()?"TRUE":"FALSE"}}:/^\w+$/.test(t)?{blockType:"variables_get",fieldValues:{VAR:t}}:null}generateSuggestions(t){const[,e,n]=t;return[`set ${e} to ${n}`,`set ${e} to 0`,`set ${e} to "text"`,`set ${e} to true`,"set myVar to 42","set count to 0"]}}function m(){return[new p,new h,new d,new g,new f]}function k(t){return{blockType:t,displayText:t}}class b extends a{constructor(t,e){super(t),this.lastInput="",this.lastSuggestions=[],this.patternManager=new l(e),this.patternManager.registerBuiltinPatterns(m())}generateOptionsForInput(t){if(t===this.lastInput&&this.lastSuggestions.length>0)return this.lastSuggestions;const e=t.trim(),n=this.generateOptions(),o=this.getPatternSuggestions(e),s=this.filterAndRankOptions(n,e),i=this.combineOptions(o,s,e);return this.lastInput=t,this.lastSuggestions=i,i}getPatternSuggestions(t){if(!t)return[];const e=[],n=this.patternManager.detectPattern(t);console.debug("SmartOptionGenerator: Pattern detection for",t,":",n),n&&(e.push(k(t)),console.debug("SmartOptionGenerator: Added pattern input as suggestion:",t));const o=this.patternManager.getSuggestions(t);if(console.debug("SmartOptionGenerator: Pattern manager suggestions:",o),e.push(...o.map(t=>k(t.text))),this.isPartialPatternInput(t)){const n=this.getPatternExamples(t);console.debug("SmartOptionGenerator: Pattern examples:",n),e.push(...n.map(t=>k(t)))}console.debug("SmartOptionGenerator: Final pattern suggestions:",e);const s=new Set;return e.filter(t=>{const e=`${t.blockType}:${t.displayText}`;return!s.has(e)&&(s.add(e),!0)})}isPartialPatternInput(t){return 0!==t.length&&[/^\d+$/,/^["']/,/^(true|false)$/i,/^\d+\s*[+\-*/]/,/^set\s+\w*/,/^get\s+/,/^when\s+/].some(e=>e.test(t))}getPatternExamples(t){const e=[];if(/^\d/.test(t)&&e.push("42","3.14",`${t} + 1`,`${t} * 2`),/^["']/.test(t)&&e.push('"hello world"',"'example text'"),/^(t|f)/i.test(t)&&e.push("true","false"),/^set/i.test(t)&&e.push("set x to 5",'set name to "hello"',"set flag to true"),/^get/i.test(t)){const t=this.workspace.getVariablesOfType("");e.push(...t.map(t=>`get ${t.getName()}`))}return e}filterAndRankOptions(t,e){return e?t.map(t=>({option:t,score:this.calculateRelevanceScore(t.displayText,e)})).filter(t=>t.score>0).sort((t,e)=>e.score-t.score).map(t=>t.option):t}calculateRelevanceScore(t,e){const n=t.toLowerCase(),o=e.toLowerCase();let s=0;return n===o?100:(n.startsWith(o)&&(s+=50),n.includes(o)&&(s+=25),s+=this.getContextualBonus(t,e),e.length<3&&t.length>20&&(s-=10),Math.max(0,s))}getContextualBonus(t,e){let n=0;return/^\d/.test(e)&&/math|number|arithmetic|calculate/.test(t.toLowerCase())&&(n+=15),/^["']/.test(e)&&/text|string|concat|join/.test(t.toLowerCase())&&(n+=15),/^(true|false)/i.test(e)&&/logic|boolean|compare|if/.test(t.toLowerCase())&&(n+=15),/set|get|var/i.test(e)&&/variable|var|get|set/.test(t.toLowerCase())&&(n+=15),n}combineOptions(t,e,n){const o=[],s=new Set;for(const e of t){const t=`${e.blockType}:${e.displayText}`;s.has(t)||(o.push(e),s.add(t))}const i=Math.max(10,20-t.length);for(const t of e.slice(0,i)){const e=`${t.blockType}:${t.displayText}`;s.has(e)||(o.push(t),s.add(e))}if(o.length<5&&n.length<3){const t=["if","repeat","set variable","math","text","true","false"];for(const e of t){const t=k(e),n=`${t.blockType}:${t.displayText}`;!s.has(n)&&o.length<10&&(o.push(t),s.add(n))}}return o}setScopeAnalyzer(t){super.setScopeAnalyzer(t)}}class y{constructor(t){this.workspace=t,this._needsReload=!0,this.eventListeners=[],this.setupEventListeners()}get needsReload(){return this._needsReload}invalidate(t){this._needsReload||(console.debug(`TypeBlocking options invalidated: ${t}`),this._needsReload=!0)}markReloaded(){this._needsReload=!1}dispose(){this.eventListeners.forEach(t=>t()),this.eventListeners=[]}setupEventListeners(){this.addEventHandler(i.Events.VAR_CREATE,"variable created"),this.addEventHandler(i.Events.VAR_DELETE,"variable deleted"),this.addEventHandler(i.Events.VAR_RENAME,"variable renamed"),this.addEventHandler(i.Events.BLOCK_CREATE,t=>{this.handleBlockEvent(t)}),this.addEventHandler(i.Events.BLOCK_DELETE,t=>{this.handleBlockEvent(t)}),this.addEventHandler(i.Events.BLOCK_CHANGE,t=>{this.handleBlockChangeEvent(t)}),this.addEventHandler(i.Events.FINISHED_LOADING,"workspace loaded"),this.addWorkspaceChangeListener()}addEventHandler(t,e){const n=t=>{t.workspaceId===this.workspace.id&&("string"==typeof e?this.invalidate(e):e(t))};this.workspace.addChangeListener(n),this.eventListeners.push(()=>{this.workspace.removeChangeListener(n)})}handleBlockEvent(t){const e=t.type;e&&this.isProcedureBlock(e)&&this.invalidate(`procedure block ${e}`)}handleBlockChangeEvent(t){const e=this.workspace.getBlockById(t.blockId);e&&this.isProcedureBlock(e.type)&&"field"===t.element&&"NAME"===t.name&&this.invalidate(`procedure name changed from ${t.oldValue} to ${t.newValue}`)}addWorkspaceChangeListener(){let t=null;const e=e=>{e.workspaceId===this.workspace.id&&(t&&clearTimeout(t),t=setTimeout(()=>{this.shouldInvalidateForGeneralChange(e)&&this.invalidate("workspace change"),t=null},100))};this.workspace.addChangeListener(e),this.eventListeners.push(()=>{this.workspace.removeChangeListener(e),t&&clearTimeout(t)})}isProcedureBlock(t){return"procedures_defnoreturn"===t||"procedures_defreturn"===t||"procedures_callnoreturn"===t||"procedures_callreturn"===t}shouldInvalidateForGeneralChange(t){return!["selected","click","theme_change","viewport_change"].includes(t.type)}}class v{constructor(t){this.workspace=t}getLocalVariablesInScope(){const t=this.getLocalVariablesFromSelection();return t.length>0?(console.log("Using selection context for local variables:",t),t):(console.log("No selection context available, falling back to all procedure parameters."),this.getAllProcedureParameters())}getLocalVariablesFromSelection(){const t=this.getEnclosingProcedureFromSelection();return t?this.getProcedureParameters(t):[]}getAllProcedureParameters(){const t=[],e=this.workspace.getAllBlocks(!1);for(const n of e)this.isProcedureDefinition(n)&&t.push(...this.getProcedureParameters(n));return[...new Set(t)]}getEnclosingProcedureFromSelection(){const t=i.common.getSelected();return t&&t instanceof i.BlockSvg?this.findEnclosingProcedure(t):null}findEnclosingProcedure(t){let e=t;for(;e;){if(this.isProcedureDefinition(e))return e;const t=e.getParent();if(t&&this.isProcedureDefinition(t))return t;e=t}return null}getProcedureParameters(t){const e=[];if(this.isProcedureDefinition(t)){if(t.getVars){const n=t.getVars();Array.isArray(n)&&e.push(...n)}const n=t.inputList;for(const t of n)for(const n of t.fieldRow)if(n.name&&n.name.startsWith("ARG")){const t=n.getValue();t&&"string"==typeof t&&t.trim()&&e.push(t.trim())}}return e}isProcedureDefinition(t){return"procedures_defnoreturn"===t.type||"procedures_defreturn"===t.type}}const C=(t,e)=>{const n=e.trim().toLowerCase();return n?t.filter(t=>t.displayText.toLowerCase().includes(n)):t};class w{constructor(t,e=""){this.highlighted=-1,this.suggestions=[],this.root=document.createElement("div"),this.root.innerHTML='\n \n \n ',this.input=this.root.querySelector(".fi-input"),this.list=this.root.querySelector(".fi-list"),this.input.value=e,this.list.addEventListener("mousemove",t=>{const e=t.target.closest("li");if(e){const t=parseInt(e.dataset.idx,10);t!==this.highlighted&&this.updateHighlight(t)}}),this.list.addEventListener("mousedown",e=>{e.preventDefault();const n=e.target.closest("li");if(n){const e=parseInt(n.dataset.idx,10);t(this.suggestions[e])}})}focus(){this.input.focus();const t=this.input.value.length;this.input.setSelectionRange(t,t)}setSuggestions(t){this.suggestions=t,this.list.innerHTML="",t.forEach((t,e)=>{const n=document.createElement("li");n.dataset.idx=e.toString(),n.textContent=t.displayText,this.list.appendChild(n)}),t.length>0?this.updateHighlight(0):this.highlighted=-1,this.list.hidden=0===t.length}onKey(t,e){const n=()=>this.highlighted>=0&&this.highlighted=0&&e[this.highlighted].classList.remove("fi-hl"),this.highlighted=t,this.highlighted>=0&&(e[this.highlighted].classList.add("fi-hl"),e[this.highlighted].scrollIntoView({block:"nearest"}))}}class T{constructor(t){this.workspace=t}createBlock(t,e,n){let o=this.createSpecialBlock(t);if(o)return o;let s=t;if(!i.Blocks[s])for(const e in i.Blocks)if(i.Blocks[e].typeblock===t){s=e;break}if(!i.Blocks[s])return void console.warn(`No block registered for "${t}"`);const r={type:s};if(e&&(r.extraState=e),n){r.fields={};for(const[t,e]of Object.entries(n))r.fields[t]=e}return i.serialization.blocks.append(r,this.workspace,{recordUndo:!0})}createBlockFromInstruction(t){try{const e=this.workspace.newBlock(t.blockType);if(t.fieldValues)for(const[n,o]of Object.entries(t.fieldValues)){const t=e.getField(n);if(t)if("VAR"!==n||"variables_set"!==e.type&&"variables_get"!==e.type)t.setValue(o);else{let e=this.workspace.getVariable(o);e||(e=this.workspace.createVariable(o)),t.setValue(e.getId())}}if(e.initSvg(),e.render(),t.children)for(const n of t.children){const t=this.createBlockFromInstruction(n.instruction);if(t){const o=e.getInput(n.input);o&&t.outputConnection&&t.outputConnection.connect(o.connection)}}return e}catch(t){return void console.warn("Failed to create block from instruction:",t)}}createSpecialBlock(t){const e=t.match(/^get\s+(.+)$/);if(e)return this.createVariableGetter(e[1]);const n=t.match(/^set\s+(.+?)\s+to$/);if(n)return this.createVariableSetter(n[1]);const o=t.match(/^([^(]+)(?:\([^)]*\))?$/);return o&&this.isProcedureName(o[1].trim())?this.createProcedureCall(o[1].trim()):void 0}createVariableGetter(t){var e;const n=this.workspace.getVariable(t);if(!n)return void console.warn(`Variable "${t}" not found`);const o=this.workspace.newBlock("variables_get");return null===(e=o.getField("VAR"))||void 0===e||e.setValue(n.getId()),o.initSvg(),o.render(),o}createVariableSetter(t){var e;const n=this.workspace.getVariable(t);if(!n)return void console.warn(`Variable "${t}" not found`);const o=this.workspace.newBlock("variables_set");return null===(e=o.getField("VAR"))||void 0===e||e.setValue(n.getId()),o.initSvg(),o.render(),o}createProcedureCall(t){var e,n;const o=this.workspace.getAllBlocks(!1);let s=!1;for(const n of o)if(("procedures_defnoreturn"===n.type||"procedures_defreturn"===n.type)&&(null===(e=n.getField("NAME"))||void 0===e?void 0:e.getValue())===t){s="procedures_defreturn"===n.type;break}const i=s?"procedures_callreturn":"procedures_callnoreturn",r=this.workspace.newBlock(i);return null===(n=r.getField("NAME"))||void 0===n||n.setValue(t),r.initSvg(),r.render(),r}isProcedureName(t){var e;const n=this.workspace.getAllBlocks(!1);for(const o of n)if(("procedures_defnoreturn"===o.type||"procedures_defreturn"===o.type)&&(null===(e=o.getField("NAME"))||void 0===e?void 0:e.getValue())===t)return!0;return!1}}class x{constructor(t){this.workspace=t,this.offsetCount=0}positionBlock(t,e,n){const o=this.workspace.getMetrics(),s=this.workspace.getInjectionDiv().getBoundingClientRect(),i=null!=e?e:s.left+s.width/2,r=null!=n?n:s.top+s.height/2;let c=(i-s.left)/this.workspace.scale+o.viewLeft,a=(r-s.top)/this.workspace.scale+o.viewTop;if(this.lastCreationX===i&&this.lastCreationY===r){this.offsetCount++;const t=this.offsetCount*x.OFFSET_STEP/this.workspace.scale;c+=t,a+=t}else this.offsetCount=0,this.lastCreationX=i,this.lastCreationY=r;t.moveBy(c,a)}}x.OFFSET_STEP=30;class P{areTypesCompatible(t,e){if(!t||!e)return!1;const n=t.getCheck(),o=e.getCheck();return!n||!o||n.some(t=>o.includes(t))}isConnectionAvailable(t){return t&&!t.isConnected()}getWorkspaceScale(t){return t.scale||1}calculateDistance(t,e){const n=t.x-e.x,o=t.y-e.y;return Math.sqrt(n*n+o*o)}}class S extends P{constructor(){super(...arguments),this.priority=90,this.name="StatementSequence"}canConnect(t,e){const n=t.previousConnection;if(!n)return!1;const o=e.nextConnection;return!(!o||o.isConnected())&&this.areTypesCompatible(n,o)}connect(t,e){const n=t.previousConnection,o=e.nextConnection;if(!this.canConnect(t,e))return{success:!1,reason:"Blocks not compatible for statement sequence connection"};try{return n.connect(o),{success:!0,connectionType:"statement_sequence",targetConnection:o}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}}class B extends P{constructor(){super(...arguments),this.priority=80,this.name="ValueInput"}canConnect(t,e){return!!t.outputConnection&&null!==this.findCompatibleInput(t,e)}connect(t,e){const n=t.outputConnection;if(!n)return{success:!1,reason:"New block has no output connection"};const o=this.findCompatibleInput(t,e);if(!o)return{success:!1,reason:"No compatible input connection found"};try{return n.connect(o),{success:!0,connectionType:"value_input",targetConnection:o}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}findCompatibleInput(t,e){const n=t.outputConnection;if(!n)return null;for(const t of e.inputList)if(t.connection&&this.isConnectionAvailable(t.connection)&&this.areTypesCompatible(n,t.connection))return t.connection;return null}}class E extends P{constructor(){super(...arguments),this.priority=70,this.name="StatementInsertion"}canConnect(t,e){const n=t.nextConnection,o=t.previousConnection;if(!n||!o)return!1;const s=e.previousConnection;return!!s&&this.areTypesCompatible(n,s)&&this.areTypesCompatible(o,s)}connect(t,e){const n=t.nextConnection,o=t.previousConnection,s=e.previousConnection;if(!this.canConnect(t,e))return{success:!1,reason:"Blocks not compatible for statement insertion"};try{const t=s.targetConnection;return t&&(s.disconnect(),o.connect(t)),n.connect(s),{success:!0,connectionType:"statement_insertion",targetConnection:s}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}}class $ extends P{constructor(){super(...arguments),this.priority=60,this.name="Wrapper"}canConnect(t,e){const n=this.getStatementInputs(t);if(0===n.length)return!1;const o=e.previousConnection;return!!o&&this.areTypesCompatible(o,n[0])}connect(t,e){const n=this.getStatementInputs(t),o=e.previousConnection;if(!this.canConnect(t,e))return{success:!1,reason:"Blocks not compatible for wrapping"};try{const e=o.targetConnection;if(e){o.disconnect();const n=t.previousConnection;n&&this.areTypesCompatible(n,e)&&n.connect(e)}return o.connect(n[0]),{success:!0,connectionType:"wrapper",targetConnection:n[0]}}catch(t){return{success:!1,reason:`Connection failed: ${t}`}}}getStatementInputs(t){const e=[];for(const n of t.inputList)n.type===i.inputs.inputTypes.STATEMENT&&n.connection&&e.push(n.connection);return e}}class I{constructor(t,e={}){var n,o,s,i;this.workspace=t,this.config={enableAutoConnection:null===(n=e.enableAutoConnection)||void 0===n||n,connectionRadius:null!==(o=e.connectionRadius)&&void 0!==o?o:200,maxNearbyBlocks:null!==(s=e.maxNearbyBlocks)&&void 0!==s?s:10,strategies:null!==(i=e.strategies)&&void 0!==i?i:this.getDefaultStrategies()},this.connectionStrategies=this.config.strategies.sort((t,e)=>e.priority-t.priority)}getDefaultStrategies(){return[new S,new B,new E,new $]}attemptConnection(t,e,n,o){if(!this.config.enableAutoConnection)return null;const s=this.buildConnectionContext(t,e,n,o);return this.findAndMakeConnection(t,s)}buildConnectionContext(t,e,n,o){const s=Object.assign({},o);if(!s.selectedBlock){const t=i.common.getSelected();t&&t instanceof i.BlockSvg&&(s.selectedBlock=t)}return void 0!==e&&void 0!==n&&(s.cursorPosition={x:e,y:n}),s.nearbyBlocks||(s.nearbyBlocks=this.findNearbyBlocks(t,s.cursorPosition)),s}findAndMakeConnection(t,e){const n=this.getPriorizedTargetBlocks(t,e);for(const o of n)for(const n of this.connectionStrategies)if(n.canConnect(t,o,e)){console.debug(`Attempting connection with strategy: ${n.name}`);const s=n.connect(t,o,e);if(s.success)return console.debug(`Successfully connected using strategy: ${n.name}`),s;console.debug(`Connection failed with strategy ${n.name}: ${s.reason}`)}return console.debug("No suitable connection found for new block"),null}getPriorizedTargetBlocks(t,e){const n=[];if(e.selectedBlock&&n.push(e.selectedBlock),e.nearbyBlocks){const o=e.nearbyBlocks.filter(t=>t!==e.selectedBlock).sort((n,o)=>{const s=this.connectionStrategies.find(t=>"ValueInput"===t.name);if(!s)return 0;const i=s.canConnect(t,n,e),r=s.canConnect(t,o,e);if(i&&!r)return-1;if(!i&&r)return 1;if(i&&r){const t=this.countConnectedInputs(n),e=this.countConnectedInputs(o);if(t!==e)return t-e}return 0});n.push(...o)}return[...new Set(n)]}findNearbyBlocks(t,e){const n=t.getRelativeToSurfaceXY(),o=e?this.clientToWorkspaceCoordinates(e.x,e.y):n,s=this.workspace.getAllBlocks(!1),i=[];for(const e of s){if(e===t)continue;const n=e.getRelativeToSurfaceXY(),s=this.calculateDistance(o,n);s<=this.config.connectionRadius&&i.push({block:e,distance:s})}return i.sort((t,e)=>t.distance-e.distance),i.slice(0,this.config.maxNearbyBlocks).map(t=>t.block)}clientToWorkspaceCoordinates(t,e){const n=this.workspace.getMetrics(),o=this.workspace.getInjectionDiv().getBoundingClientRect();return{x:(t-o.left)/this.workspace.scale+n.viewLeft,y:(e-o.top)/this.workspace.scale+n.viewTop}}calculateDistance(t,e){const n=t.x-e.x,o=t.y-e.y;return Math.sqrt(n*n+o*o)}getBlockDistance(t,e){const n=t.getRelativeToSurfaceXY(),o=e.cursorPosition?this.clientToWorkspaceCoordinates(e.cursorPosition.x,e.cursorPosition.y):n;return this.calculateDistance(o,n)}hasAvailableInputConnections(t){for(const e of t.inputList)if(e.connection&&!e.connection.isConnected())return!0;return!1}countConnectedInputs(t){let e=0;for(const n of t.inputList)n.connection&&n.connection.isConnected()&&e++;return e}setConfig(t){this.config=Object.assign(Object.assign({},this.config),t),t.strategies&&(this.connectionStrategies=t.strategies.sort((t,e)=>e.priority-t.priority))}getConfig(){return Object.assign({},this.config)}}class O{constructor(t,e){var n,o,s,i,r;this.ws=t,this.lastX=0,this.lastY=0,this.pointerMoveListener=t=>{this.lastX=t.x,this.lastY=t.y},this.ws=t,this.options=e.options,this.matcher=null!==(n=e.matcher)&&void 0!==n?n:C,this.optionGenerator=e.optionGenerator,this.inputPositioning={mode:null!==(s=null===(o=e.inputPositioning)||void 0===o?void 0:o.mode)&&void 0!==s?s:"mouse",fixedPosition:null!==(r=null===(i=e.inputPositioning)||void 0===i?void 0:i.fixedPosition)&&void 0!==r?r:{x:100,y:10}},this.blockFactory=new T(t),this.blockPositioner=new x(t),!1!==e.enablePatternRecognition&&(this.patternManager=new l(e.patternConfig),this.patternManager.registerBuiltinPatterns(m())),!1!==e.enableSmartConnection&&(this.connectionManager=new I(t,e.connectionConfig)),t.getInjectionDiv().addEventListener("pointermove",this.pointerMoveListener)}dispose(){this.ws.getInjectionDiv().removeEventListener("pointermove",this.pointerMoveListener)}show(t=""){i.WidgetDiv.show({},this.ws.RTL,()=>this.ws.getInjectionDiv().focus(),this.ws,!0);const e=new w(t=>this.choose(t),t);i.WidgetDiv.getDiv().appendChild(e.root),this.positionWidgetDiv();const n=()=>{let t=this.options;this.optionGenerator instanceof b?(console.debug("TypeBlocking: Using smart option generation for query:",e.query),t=this.optionGenerator.generateOptionsForInput(e.query),console.debug("TypeBlocking: Generated",t.length,"options:",t.slice(0,5))):console.debug("TypeBlocking: Using static options, generator type:",typeof this.optionGenerator);const n=this.matcher(t,e.query);console.debug("TypeBlocking: After matching, got",n.length,"options:",n.slice(0,5)),e.setSuggestions(n)};e.inputEl.addEventListener("input",n),n(),e.inputEl.addEventListener("keydown",t=>{e.onKey(t.key,t=>this.choose(t))?t.preventDefault():"Escape"===t.key&&i.WidgetDiv.hide(),t.stopPropagation()}),e.inputEl.addEventListener("blur",()=>i.WidgetDiv.hide()),setTimeout(()=>e.focus())}choose(t){let e;console.debug("TypeBlocking: Choosing option:",t),i.Events.setGroup(!0);try{if(this.patternManager){console.debug("TypeBlocking: Trying pattern recognition for:",t.blockType);const n=this.patternManager.getBlockInstructions(t.blockType);n&&(console.debug("TypeBlocking: Found pattern instruction:",n),e=this.blockFactory.createBlockFromInstruction(n),e&&console.debug("TypeBlocking: Created block using pattern recognition:",e.type))}e||(console.debug("TypeBlocking: Falling back to regular block creation"),e=this.blockFactory.createBlock(t.blockType,t.extraState,t.fieldValues),e&&console.debug("TypeBlocking: Created block using regular method:",e.type)),e?(this.blockPositioner.positionBlock(e,this.lastX,this.lastY),this.connectionManager&&this.connectionManager.attemptConnection(e,this.lastX,this.lastY),i.common.setSelected(e)):console.warn("TypeBlocking: Failed to create block for option:",t)}finally{i.Events.setGroup(!1)}i.WidgetDiv.hide()}positionWidgetDiv(){const t=i.WidgetDiv.getDiv();let e,n;if("fixed"===this.inputPositioning.mode){const t=this.ws.getInjectionDiv().getBoundingClientRect();e=t.left+this.inputPositioning.fixedPosition.x,n=t.top+this.inputPositioning.fixedPosition.y}else if(e=this.lastX,n=this.lastY,!e&&!n){const t=this.ws.getInjectionDiv().getBoundingClientRect();e=t.left+t.width/2,n=t.top+t.height/2}Object.assign(t.style,{position:"fixed",left:`${e}px`,top:`${n}px`})}}class V extends O{constructor(t,e){var n;super(t,{options:e.options,matcher:null!==(n=e.matcher)&&void 0!==n?n:C,enableSmartConnection:e.enableSmartConnection,connectionConfig:e.connectionConfig,enablePatternRecognition:e.enablePatternRecognition,patternConfig:e.patternConfig,optionGenerator:e.optionGenerator,inputPositioning:e.inputPositioning}),this.staticOptions=e.options,this.dynamicOptionGenerator=e.optionGenerator,this.stateTracker=e.stateTracker}getCurrentOptions(){return this.dynamicOptionGenerator&&this.stateTracker?(!this.stateTracker.needsReload&&this.cachedOptions||this.lazyLoadOptions(),this.cachedOptions||this.staticOptions):this.staticOptions}lazyLoadOptions(){if(!this.dynamicOptionGenerator||!this.stateTracker)return;console.debug("TypeBlocking: Regenerating options...");const t=performance.now();try{this.cachedOptions=this.dynamicOptionGenerator.generateOptions(),"markReloaded"in this.stateTracker&&this.stateTracker.markReloaded();const e=performance.now()-t;console.debug(`TypeBlocking: Generated ${this.cachedOptions.length} options in ${e.toFixed(2)}ms`)}catch(t){console.error("TypeBlocking: Error generating options:",t),this.cachedOptions=this.staticOptions}}show(t=""){const e=this.getCurrentOptions();this.options=e,super.show(t)}dispose(){this.cachedOptions=void 0,this.dynamicOptionGenerator=void 0,this.stateTracker=void 0,super.dispose()}}class L{constructor(t){this.workspace=t}init(t={}){const e=!1!==t.enableDynamicOptions;console.log("what am I enabling?",e),e?this.setupDynamicOptions(t):this.setupStaticOptions(t),console.info("Typeblocking initialized on workspace:",this.workspace.id)}setupDynamicOptions(t){var e;if(!1!==t.enablePatternRecognition?this.optionGenerator=t.optionGenerator||new b(this.workspace,t.patternConfig):this.optionGenerator=t.optionGenerator||new a(this.workspace),this.optionGenerator instanceof a){const t=new v(this.workspace);this.optionGenerator.setScopeAnalyzer(t)}this.stateTracker=null!==(e=t.workspaceStateTracker)&&void 0!==e?e:new y(this.workspace),this.installFloatingInput({options:[],matcher:t.matcher,enableSmartConnection:t.enableSmartConnection,connectionConfig:t.connectionConfig,enablePatternRecognition:t.enablePatternRecognition,patternConfig:t.patternConfig,inputPositioning:t.inputPositioning})}setupStaticOptions(t){const e=t.options||this.generateLegacyOptions();this.installFloatingInput({options:e,matcher:t.matcher,enableSmartConnection:t.enableSmartConnection,connectionConfig:t.connectionConfig,enablePatternRecognition:t.enablePatternRecognition,patternConfig:t.patternConfig,inputPositioning:t.inputPositioning})}generateLegacyOptions(){const t=[];i.Blocks.controls_if.typeblock=i.Msg.CONTROLS_IF_MSG_IF;for(const e in i.Blocks)e.split("_").length>1&&(i.Blocks[e].typeblock||(i.Blocks[e].typeblock=e),t.push(i.Blocks[e].typeblock));return t}dispose(){if(!this.workspace)return;const t=this.workspace.id;L.instancesByWorkspaceId.delete(t),this.stateTracker&&(this.stateTracker.dispose(),this.stateTracker=void 0),this.controller&&(this.controller.dispose(),this.controller=void 0),L.instancesByWorkspaceId.size||i.ShortcutRegistry.registry.unregister(r),i.DropDownDiv.hideWithoutAnimation(),this.optionGenerator=void 0,this.workspace=null,console.info(`Typeblocking disposed from workspace ${t}`)}installFloatingInput({options:t=[],matcher:e,enableSmartConnection:n,connectionConfig:o,enablePatternRecognition:s,patternConfig:c,inputPositioning:a}){if(this.controller=new V(this.workspace,{options:t,matcher:e,optionGenerator:this.optionGenerator,stateTracker:this.stateTracker,enableSmartConnection:n,connectionConfig:o,enablePatternRecognition:s,patternConfig:c,inputPositioning:a}),L.instancesByWorkspaceId.set(this.workspace.id,this),!i.ShortcutRegistry.registry.getRegistry()[r]){const t=t=>1===t.key.length&&!t.ctrlKey&&!t.metaKey&&!t.altKey;i.ShortcutRegistry.registry.register({name:r,preconditionFn:t=>L.instancesByWorkspaceId.has(t.id)&&!i.FieldTextInput.activeField&&!i.WidgetDiv.isVisible(),callback:(e,n)=>{const o=n;return L.instancesByWorkspaceId.get(e.id).controller.show(t(o)?o.key:""),!0}},!0);const e=new Set([8,9,13,16,17,18,19,20,27,33,34,35,36,37,38,39,40,45,46,91,112,113,114,115,116,117,118,119,120,121,122,123]);for(let t=0;t<=222;++t)e.has(t)||(i.ShortcutRegistry.registry.addKeyMapping(t,r,!0),i.ShortcutRegistry.registry.addKeyMapping(i.ShortcutRegistry.registry.createSerializedKey(t,[i.utils.KeyCodes.SHIFT]),r,!0))}}}return L.instancesByWorkspaceId=new Map,s})()); +//# sourceMappingURL=index.js.map \ No newline at end of file From 2698ce0a820ffd3dcf3b39eb3b9d8ce1df85cd35 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Wed, 18 Feb 2026 08:02:41 -0800 Subject: [PATCH 13/32] Update block-lexical-variables to pr68-db9c159 --- appinventor/blocklyeditor/build.xml | 2 +- .../block-lexical-variables-core-62b3583.min.js | 3 --- .../block-lexical-variables-core-pr68-db9c159.min.js | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 appinventor/lib/blockly-plugins/block-lexical-variables-core-62b3583.min.js create mode 100644 appinventor/lib/blockly-plugins/block-lexical-variables-core-pr68-db9c159.min.js diff --git a/appinventor/blocklyeditor/build.xml b/appinventor/blocklyeditor/build.xml index 2938a71a463..c5dee3ae5b9 100644 --- a/appinventor/blocklyeditor/build.xml +++ b/appinventor/blocklyeditor/build.xml @@ -135,7 +135,7 @@ - + diff --git a/appinventor/lib/blockly-plugins/block-lexical-variables-core-62b3583.min.js b/appinventor/lib/blockly-plugins/block-lexical-variables-core-62b3583.min.js deleted file mode 100644 index e8c37f9f0b3..00000000000 --- a/appinventor/lib/blockly-plugins/block-lexical-variables-core-62b3583.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see index.js.LICENSE.txt */ -!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],t);else{var n="object"==typeof exports?t(require("blockly/core")):t(e.Blockly);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(this,(e=>(()=>{"use strict";var t={573:t=>{t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var s=n[e]={exports:{}};return t[e](s,s.exports,r),s.exports}r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};return(()=>{r.r(o),r.d(o,{LexicalVariablesPlugin:()=>Y});var e={};r.r(e),r.d(e,{GLOBAL_KEYWORD:()=>c,handlerParameterPrefix:()=>d,localNamePrefix:()=>_,loopParameterPrefix:()=>p,loopRangeParameterPrefix:()=>g,menuSeparator:()=>h,possiblyPrefixGeneratedVarName:()=>E,possiblyPrefixMenuNameWith:()=>A,prefixGlobalMenuName:()=>R,prefixSeparator:()=>f,procedureParameterPrefix:()=>u,showPrefixToUser:()=>a,unprefixName:()=>L,usePrefixInCode:()=>l});const t=document.createElement("style");document.head.appendChild(t);var n=r(573);n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TITLE_INIT="initialize global",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_NAME="name",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TO="to",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_COLLAPSED_TEXT="global",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TOOLTIP="Creates a global variable and gives it the value of the attached blocks.",n.Msg.LANG_VARIABLES_GLOBAL_PREFIX="global",n.Msg.LANG_VARIABLES_GET_TITLE_GET="get",n.Msg.LANG_VARIABLES_GET_COLLAPSED_TEXT="get",n.Msg.LANG_VARIABLES_GET_TOOLTIP="Returns the value of this variable.",n.Msg.LANG_VARIABLES_SET_TITLE_SET="set",n.Msg.LANG_VARIABLES_SET_TITLE_TO="to",n.Msg.LANG_VARIABLES_SET_COLLAPSED_TEXT="set",n.Msg.LANG_VARIABLES_SET_TOOLTIP="Sets this variable to be equal to the input.",n.Msg.LANG_VARIABLES_VARIABLE=" variable",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_TITLE_INIT="initialize local",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_DEFAULT_NAME="name",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_INPUT_TO="to",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_IN_DO="in",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_COLLAPSED_TEXT="local",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_TOOLTIP="Allows you to create variables that are only accessible in the do part of this block.",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_TRANSLATED_NAME="initialize local in do",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_IN_RETURN="in",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_COLLAPSED_TEXT="local",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_TOOLTIP="Allows you to create variables that are only accessible in the return part of this block.",n.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_TRANSLATED_NAME="initialize local in return",n.Msg.LANG_VARIABLES_LOCAL_MUTATOR_CONTAINER_TITLE_LOCAL_NAMES="local names",n.Msg.LANG_VARIABLES_LOCAL_MUTATOR_CONTAINER_TOOLTIP="",n.Msg.LANG_VARIABLES_LOCAL_MUTATOR_ARG_TITLE_NAME="name",n.Msg.LANG_VARIABLES_LOCAL_MUTATOR_ARG_DEFAULT_VARIABLE="x",n.Msg.LANG_PROCEDURES_DEFNORETURN_DEFINE="to",n.Msg.LANG_PROCEDURES_DEFNORETURN_PROCEDURE="procedure",n.Msg.LANG_PROCEDURES_DEFNORETURN_DO="do",n.Msg.LANG_PROCEDURES_DEFNORETURN_COLLAPSED_PREFIX="to ",n.Msg.LANG_PROCEDURES_DEFNORETURN_TOOLTIP="A procedure that does not return a value.",n.Msg.LANG_PROCEDURES_DOTHENRETURN_THEN_RETURN="result",n.Msg.LANG_PROCEDURES_DOTHENRETURN_DO="do",n.Msg.LANG_PROCEDURES_DOTHENRETURN_RETURN="result",n.Msg.LANG_PROCEDURES_DOTHENRETURN_TOOLTIP="Runs the blocks in 'do' and returns a statement. Useful if you need to run a procedure before returning a value to a variable.",n.Msg.LANG_PROCEDURES_DOTHENRETURN_COLLAPSED_TEXT="do/result",n.Msg.LANG_PROCEDURES_DEFRETURN_DEFINE="to",n.Msg.LANG_PROCEDURES_DEFRETURN_PROCEDURE="procedure",n.Msg.LANG_PROCEDURES_DEFRETURN_RETURN="result",n.Msg.LANG_PROCEDURES_DEFRETURN_COLLAPSED_PREFIX="to ",n.Msg.LANG_PROCEDURES_DEFRETURN_TOOLTIP="A procedure returning a result value.",n.Msg.LANG_PROCEDURES_DEF_DUPLICATE_WARNING="Warning:\nThis procedure has\nduplicate inputs.",n.Msg.LANG_PROCEDURES_CALLNORETURN_CALL="call ",n.Msg.LANG_PROCEDURES_CALLNORETURN_PROCEDURE="procedure",n.Msg.LANG_PROCEDURES_CALLNORETURN_COLLAPSED_PREFIX="call ",n.Msg.LANG_PROCEDURES_CALLNORETURN_TOOLTIP="Call a procedure with no return value.",n.Msg.LANG_PROCEDURES_CALLNORETURN_TRANSLATED_NAME="call no return",n.Msg.LANG_PROCEDURES_CALLRETURN_CALL="call ",n.Msg.LANG_PROCEDURES_CALLRETURN_PROCEDURE="procedure",n.Msg.LANG_PROCEDURES_CALLRETURN_COLLAPSED_PREFIX="call ",n.Msg.LANG_PROCEDURES_CALLRETURN_TOOLTIP="Call a procedure with a return value.",n.Msg.LANG_PROCEDURES_CALLRETURN_TRANSLATED_NAME="call return",n.Msg.LANG_PROCEDURES_MUTATORCONTAINER_TITLE="inputs",n.Msg.LANG_PROCEDURES_MUTATORARG_TITLE="input:",n.Msg.LANG_PROCEDURES_HIGHLIGHT_DEF="Highlight Procedure",n.Msg.LANG_PROCEDURES_MUTATORCONTAINER_TOOLTIP="",n.Msg.LANG_PROCEDURES_MUTATORARG_TOOLTIP="",n.Msg.LANG_CONTROLS_FOR_INPUT_WITH="count with",n.Msg.LANG_CONTROLS_FOR_INPUT_VAR="x",n.Msg.LANG_CONTROLS_FOR_INPUT_FROM="from",n.Msg.LANG_CONTROLS_FOR_INPUT_TO="to",n.Msg.LANG_CONTROLS_FOR_INPUT_DO="do",n.Msg.LANG_CONTROLS_FOR_TOOLTIP="Count from a start number to an end number.\nFor each count, set the current count number to\nvariable '%1', and then do some statements.",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_ITEM="for each",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_VAR="number",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_START="from",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_END="to",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_STEP="by",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_DO="do",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_COLLAPSED_TEXT="for number in range",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_COLLAPSED_PREFIX="for",n.Msg.LANG_CONTROLS_FORRANGE_INPUT_COLLAPSED_SUFFIX=" in range",n.Msg.LANG_CONTROLS_FORRANGE_TOOLTIP="Runs the blocks in the 'do' section for each numeric value in the range from start to end, stepping the value each time. Use the given variable name to refer to the current value.",n.Msg.LANG_CONTROLS_FOREACH_INPUT_ITEM="for each",n.Msg.LANG_CONTROLS_FOREACH_INPUT_VAR="item",n.Msg.LANG_CONTROLS_FOREACH_INPUT_INLIST="in list",n.Msg.LANG_CONTROLS_FOREACH_INPUT_DO="do",n.Msg.LANG_CONTROLS_FOREACH_INPUT_COLLAPSED_TEXT="for item in list",n.Msg.LANG_CONTROLS_FOREACH_INPUT_COLLAPSED_PREFIX="for ",n.Msg.LANG_CONTROLS_FOREACH_INPUT_COLLAPSED_SUFFIX=" in list",n.Msg.LANG_CONTROLS_FOREACH_TOOLTIP="Runs the blocks in the 'do' section for each item in the list. Use the given variable name to refer to the current list item.",n.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT="for each %1 with %2 in dictionary %3",n.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT_DO="do",n.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT_KEY="key",n.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT_VALUE="value",n.Msg.LANG_CONTROLS_FOREACH_DICT_TITLE="for each in dictionary",n.Msg.LANG_CONTROLS_FOREACH_DICT_TOOLTIP="Runs the blocks in the 'do' section for each key-value entry in the dictionary. Use the given variable names to refer to the key/value of the current dictionary item.",n.Msg.ERROR_SELECT_VALID_ITEM_FROM_DROPDOWN="Select a valid item in the drop down.",n.Msg.ERROR_BLOCK_CANNOT_BE_IN_DEFINITION="This block cannot be in a definition",n.Msg.HORIZONTAL_PARAMETERS="Arrange Parameters Horizontally",n.Msg.VERTICAL_PARAMETERS="Arrange Parameters Vertically",n.Msg.LANG_CONTROLS_DO_THEN_RETURN_INPUT_DO="do",n.Msg.LANG_CONTROLS_DO_THEN_RETURN_INPUT_RETURN="result",n.Msg.LANG_CONTROLS_DO_THEN_RETURN_TOOLTIP="Runs the blocks in 'do' and returns a statement. Useful if you need to run a procedure before returning a value to a variable.",n.Msg.LANG_CONTROLS_DO_THEN_RETURN_COLLAPSED_TEXT="do/result",n.Msg.LANG_CONTROLS_DO_THEN_RETURN_TITLE="do result",n.Msg.PROCEDURES_DEFNORETURN_PROCEDURE=n.Msg.LANG_PROCEDURES_DEFNORETURN_PROCEDURE,n.Msg.PROCEDURES_DEFRETURN_PROCEDURE=n.Msg.LANG_PROCEDURES_DEFRETURN_PROCEDURE,n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_WARNING="Global declarations must be inside of a initialize global block.",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TITLE_INIT="initialize global variables",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TO_DO="to",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TOOLTIP="Allows you to create global variables that are accessible everywhere",n.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_BLOCK_CHECK="Only global_declaration_entry blocks are allowed here.";class s{checkErrors(e){if(e.getSvgRoot&&!e.getSvgRoot()||e.readOnly)return e.hasWarning&&(e.hasWarning=!1),void(e.hasError&&(e.hasError=!1));e.errors||(e.errors=[]),e.warnings||(e.warnings=[]);const t=e.errors,n=e.warnings;for(let n=0;n{s(e,t,n,r)})),o=r,r=r.getParent();return I.sortAndRemoveDuplicates(t)},O.dropdownCreate=function(){const e=this.getNamesInScope();return e.length>0?e:this.translatedName?[[this.translatedName,this.varname]]:[[" "," "]]},O.prototype.doValueUpdate_=function(e){if(Object.getPrototypeOf(n.FieldDropdown).prototype.doValueUpdate_.call(this,e),e&&" "!==e){const t=e.split(" ");2==t.length&&"global"!==t[0]&&(e="global "+t[1])}this.value_=e;const t=this.getOptions(!0,[[(r=e,r.startsWith("global ")?r.replace("global ",n.Msg.LANG_VARIABLES_GLOBAL_PREFIX+" "):r),e]]);var r;for(let e,n=0;e=t[n];n++)if(e[1]==this.value_){this.selectedOption=e;break}this.updateMutation(),this.forceRerender()},O.prototype.updateMutation=function(){const e=this.getText();if(this.getSourceBlock()&&this.getSourceBlock().getParent()){if(this.getSourceBlock().eventparam=void 0,0===e.indexOf(n.Msg.LANG_VARIABLES_GLOBAL_PREFIX+" "))return this.getSourceBlock().eventparam=null,this.translatedName=void 0,void(this.varname=void 0);let t,r=this.getSourceBlock().getParent();for(;r;){const n=r.declaredVariables?r.declaredVariables():[];for(t=0;t=<`'\"#:;,\\\\*+.()|{}[\\] ][^-!&%^/>=<'\"#:;,\\\\*+.()|{}[\\] ]*$");return{isLegal:0==t.search(n),transformed:t}},makeLegalIdentifier:function(e){const t=I.checkIdentifier(e);return t.isLegal?t.transformed:""===t.transformed?"_":"name"},referenceResult:function(e,t,n,r){if(!e)return[[],[]];const o=e.referenceResults?e.referenceResults(t,n,r):e.getChildren().map((function(e){return I.referenceResult(e,t,n,r)}));let s=[],i=[];for(let e=0;e{if("string"==typeof e&&"string"==typeof t)return e.localeCompare(t);if(Array.isArray(e)&&Array.isArray(t))return e[1].localeCompare(t[1]);throw Error("LexicalVariable.sortAndRemoveDuplicates: arguments must be strings or arrays of strings")})),n=[];if(e.length>=1){let e=t[0];n.push(e);for(let r=1;r1&&o.splice(0,1),o},P=function(e){if(this.getSourceBlock()&&this.getSourceBlock().isInFlyout)return e;const t=this.oldName_||this.getValue(),n=e;e=I.makeLegalIdentifier(e);const r=function(e){const t=e.workspace.getTopBlocks(!1),n=[];for(let r=0;r'+e+''+e+""},w.fromJson=function(e){const t=n.utils.replaceMessageReferences(e.name);return new w(t)},n.fieldRegistry.register("field_global_flydown",w);class v extends n.FieldDropdown{constructor(...e){super(...e)}}v.prototype.doClassValidation_=function(e){let t=!1;const n=this.getOptions(!0);for(let r,o=0;r=n[o];o++)if(r[1]===e){t=!0;break}return t||this.generatedOptions.push([e,e]),e},v.fromJson=function(e){return new v(e.options,void 0,e)},n.fieldRegistry.register("field_nocheck_dropdown",v);class M extends D{constructor(e,t,n,r){super(e,t,n,(function(e){if(!M.changeHandlerEnabled)return e;const t=I.renameParam.call(this,e);return r&&r.call(this,t),t}))}referencesVariables(){return!0}}M.prototype.fieldCSSClassName="blocklyFieldParameter",M.prototype.flyoutCSSClassName="blocklyFieldParameterFlydown",M.changeHandlerEnabled=!0,M.withChangeHanderDisabled=function(e){const t=M.changeHandlerEnabled;M.changeHandlerEnabled=!1;try{e()}finally{M.changeHandlerEnabled=t}},M.prototype.flydownBlocksXML_=function(){const e=this.getText();return''+e+''+e+""},M.addHorizontalVerticalOption=function(e,t){let r=0;if(e.getParameters&&(r=e.getParameters().length),e.isCollapsed()||r<=0)return;const o={enabled:!0,text:e.horizontalParameters?n.Msg.VERTICAL_PARAMETERS:n.Msg.HORIZONTAL_PARAMETERS,callback:function(){e.setParameterOrientation(!e.horizontalParameters)}};let s=0;for(let e;(e=t[s])&&e.text!=n.Msg.COLLAPSE_BLOCK;s++);t.splice(s,0,o);for(let e,r=0;e=t[r];r++)if(e.text==n.Msg.INLINE_INPUTS){t.splice(r,1);break}},M.fromJson=function(e){const t=n.utils.replaceMessageReferences(e.name);return new M(t,e.is_editable)},n.fieldRegistry.register("field_parameter_flydown",M);class V extends n.FieldTextInput{constructor(e){super(e,P)}setValue(e){const t=this.getValue();if(this.oldName_=t,this.doValueUpdate_(e),super.setValue(e),!this.getSourceBlock()||!this.getSourceBlock().isInFlyout){if("string"==typeof(e=this.getValue())&&this.getSourceBlock()){const n=this.getSourceBlock().workspace.getProcedureDatabase();n&&(n.getProcedure(this.getSourceBlock().id)?n.renameProcedure(this.getSourceBlock().id,t,e):n.addProcedure(e,this.getSourceBlock()))}this.oldName_=void 0}}}V.fromJson=function(e){const t=n.utils.replaceMessageReferences(e.name);return new V(t)},n.fieldRegistry.register("field_procedurename",V);class F extends n.blockRendering.ExternalValueInput{constructor(e,t){super(e,t),this.connectedBlock?this.height=this.connectedBlockHeight:this.height=this.constants_.EMPTY_STATEMENT_INPUT_HEIGHT}}class G extends n.geras.Highlighter{constructor(e){super(e)}drawIndentedInput(e){const t=e.getLastInput();if(this.RTL_){const r=e.height-t.connectionHeight-t.connectionOffsetY;this.steps_+=n.utils.svgPaths.moveTo(t.xPos+this.highlightOffset+t.connectionWidth-1,e.yPos)+n.utils.svgPaths.lineOnAxis("v",t.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)+n.utils.svgPaths.lineOnAxis("v",r)}else this.steps_+=n.utils.svgPaths.moveTo(t.xPos+t.connectionWidth,e.yPos+t.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)+n.utils.svgPaths.moveTo(t.xPos+t.connectionWidth+1,e.yPos+t.height)}}class B extends n.geras.Drawer{constructor(e,t){super(e,t),this.highlighter_=new G(t)}drawOutline_(){this.drawTop_();for(let e=1;e{if(l){const n=r.getFieldValue(e);return A(t)(n)}return r.getFieldValue(e)})),s=n.concat(o),i=r.inputList.map((o=>I.referenceResult(r.getInputTargetBlock(o.name),e,t,o.name===r.getScopedInputName()?s:n)));return r.nextConnection&&i.push(I.referenceResult(r.getNextBlock(),e,t,n)),i},withLexicalVarsAndPrefix:function(e,t){const n=this;e&&n.getInputTargetBlock(n.getScopedInputName())===e&&n.getDeclaredVarFieldNamesAndPrefixes().forEach((([e,r])=>{const o=n.getFieldValue(e);t(o,r)}))},getDeclaredVars:function(){const e=this;return e.getDeclaredVarFieldNames().map((t=>e.getFieldValue(t)))},blocksInScope:function(){const e=this.getInputTargetBlock(this.getScopedInputName());return e&&[e]||[]},declaredNames:function(){return this.getDeclaredVars()},renameVar:function(e,t){if(this.renameVars)this.renameVars(m.simpleSubstitution(e,t));else{const r=this;r.getDeclaredVarFieldNames().forEach((o=>{n.Names.equals(e,r.getFieldValue(o))&&r.setFieldValue(t,o)}))}},renameBound:function(e,t){const n=this;let r=t;if(n.inputList.forEach((o=>{o.name===n.getScopedInputName()?(n.getDeclaredVarFieldNames().forEach((o=>{const s=n.getFieldValue(o),i=e.apply(s);if(i!==s){n.renameVar(s,i);const e=m.simpleSubstitution(s,i);r=t.extend(e)}else r=t.remove([s])})),I.renameFree(n.getInputTargetBlock(n.getScopedInputName()),r)):I.renameFree(n.getInputTargetBlock(o.name),t)})),n.nextConnection){const e=n.nextConnection.targetBlock();I.renameFree(e,t)}},renameFree:function(e){const t=this,n=I.freeVariables(t.getInputTargetBlock(t.getScopedInputName())),r=new m;t.getDeclaredVarFieldNames().forEach((o=>{const s=t.getFieldValue(o);n.deleteName(s);const i=n.renamed(e);if(i.isMember(s)){const e=O.nameNotIn(s,i.toList()),t=m.simpleSubstitution(s,e);r.extend(t)}})),t.renameBound(r,e)},freeVariables:function(){const e=this,t=I.freeVariables(e.getInputTargetBlock(e.getScopedInputName()));if(e.getDeclaredVarFieldNames().forEach((n=>{t.deleteName(e.getFieldValue(n))})),e.inputList.forEach((n=>{n.name!==e.getScopedInputName()&&t.unite(I.freeVariables(e.getInputTargetBlock(n.name)))})),e.nextConnection){var n=e.nextConnection.targetBlock();t.unite(I.freeVariables(n))}return t}},H={...W,getDeclaredVarFieldNamesAndPrefixes:function(){return this.getDeclaredVarFieldNames().map((e=>[e,void 0]))}},X={...W,getDeclaredVarFieldNames:function(){return this.getDeclaredVarFieldNamesAndPrefixes().map((([e,t])=>e))}};n.Extensions.registerMixin("lexical_variable_scope_mixin",H),n.Extensions.registerMixin("prefixed_lexical_variable_scope_mixin",X);class Y{static init(e,r){var o;o=`.${e.getRenderer().getClassName()}.${e.getTheme().getClassName()}`,t.textContent=`\n ${o} .blocklyFieldParameter>rect {\n fill: rgb(222, 143, 108);\n fill-opacity: 1.0;\n stroke-width: 2;\n stroke: rgb(231, 175, 150);\n }\n ${o} .blocklyFieldParameter>text {\n stroke-width: 1;\n fill: #000;\n }\n ${o} .blocklyFieldParameter:hover>rect {\n stroke-width: 2;\n stroke: rgb(231,175,150);\n fill: rgb(231,175,150);\n fill-opacity: 1.0;\n }\n /*\n * [lyn, 10/08/13] Control flydown with the getter/setter blocks.\n */\n ${o} .blocklyFieldParameterFlydown {\n fill: rgb(231,175,150);\n fill-opacity: 0.8;\n }\n /*\n * [lyn, 10/08/13] Control parameter fields with flydown procedure\n * caller block.\n */\n ${o} .blocklyFieldProcedure>rect {\n fill: rgb(215,203,218);\n fill-opacity: 1.0;\n stroke-width: 0;\n stroke: #000;\n }\n ${o} .blocklyFieldProcedure>text {\n fill: #000;\n }\n ${o} .blocklyFieldProcedure:hover>rect {\n stroke-width: 2;\n stroke: #fff;\n fill: rgb(215,203,218);\n fill-opacity: 1.0;\n }\n /*\n * [lyn, 10/08/13] Control flydown with the procedure caller block.\n */\n ${o} .blocklyFieldProcedureFlydown {\n fill: rgb(215,203,218);\n fill-opacity: 0.8;\n }`;const s=new k(new n.Options({scrollbars:!1,rtl:e.RTL,renderer:e.options.renderer,rendererOverrides:e.options.rendererOverrides,parentWorkspace:e}));e.flydown_=s,n.utils.dom.insertAfter(s.createDom("g"),e.svgBubbleCanvas_),s.init(e),s.autoClose=!0,e.disableInvalidBlocks=r?.disableInvalidBlocks||!1}static Flydown=k;static FieldFlydown=D;static FieldGlobalFlydown=w;static FieldParameterFlydown=M;static lexicalVariableScopeMixin=H;static LexicalVariable=I;static FieldLexicalVariable=O;static FieldProcedureName=V;static FieldNoCheckDropdown=v;static NameSet=N;static Shared=e;static Substitution=m}n.blockRendering.register("geras2_renderer",U)})(),o})())); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/appinventor/lib/blockly-plugins/block-lexical-variables-core-pr68-db9c159.min.js b/appinventor/lib/blockly-plugins/block-lexical-variables-core-pr68-db9c159.min.js new file mode 100644 index 00000000000..132a295e1b1 --- /dev/null +++ b/appinventor/lib/blockly-plugins/block-lexical-variables-core-pr68-db9c159.min.js @@ -0,0 +1,3 @@ +/*! For license information please see index.js.LICENSE.txt */ +!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],t);else{var n="object"==typeof exports?t(require("blockly/core")):t(e.Blockly);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(this,e=>(()=>{"use strict";var t={370(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var s=n[e]={exports:{}};return t[e](s,s.exports,r),s.exports}r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};r.r(o),r.d(o,{LexicalVariablesPlugin:()=>$});var s={};r.r(s),r.d(s,{GLOBAL_KEYWORD:()=>_,handlerParameterPrefix:()=>g,localNamePrefix:()=>h,loopParameterPrefix:()=>f,loopRangeParameterPrefix:()=>A,menuSeparator:()=>R,possiblyPrefixGeneratedVarName:()=>O,possiblyPrefixMenuNameWith:()=>E,prefixGlobalMenuName:()=>N,prefixSeparator:()=>L,procedureParameterPrefix:()=>p,showPrefixToUser:()=>u,unprefixName:()=>m,usePrefixInCode:()=>d});const i=document.createElement("style");document.head.appendChild(i);var a=r(370);a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TITLE_INIT="initialize global",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_NAME="name",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TO="to",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_COLLAPSED_TEXT="global",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TOOLTIP="Creates a global variable and gives it the value of the attached blocks.",a.Msg.LANG_VARIABLES_GLOBAL_PREFIX="global",a.Msg.LANG_VARIABLES_GET_TITLE_GET="get",a.Msg.LANG_VARIABLES_GET_COLLAPSED_TEXT="get",a.Msg.LANG_VARIABLES_GET_TOOLTIP="Returns the value of this variable.",a.Msg.LANG_VARIABLES_SET_TITLE_SET="set",a.Msg.LANG_VARIABLES_SET_TITLE_TO="to",a.Msg.LANG_VARIABLES_SET_COLLAPSED_TEXT="set",a.Msg.LANG_VARIABLES_SET_TOOLTIP="Sets this variable to be equal to the input.",a.Msg.LANG_VARIABLES_VARIABLE=" variable",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_TITLE_INIT="initialize local",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_DEFAULT_NAME="name",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_INPUT_TO="to",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_IN_DO="in",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_COLLAPSED_TEXT="local",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_TOOLTIP="Allows you to create variables that are only accessible in the do part of this block.",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_TRANSLATED_NAME="initialize local in do",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_IN_RETURN="in",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_COLLAPSED_TEXT="local",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_TOOLTIP="Allows you to create variables that are only accessible in the return part of this block.",a.Msg.LANG_VARIABLES_LOCAL_DECLARATION_EXPRESSION_TRANSLATED_NAME="initialize local in return",a.Msg.LANG_VARIABLES_LOCAL_MUTATOR_CONTAINER_TITLE_LOCAL_NAMES="local names",a.Msg.LANG_VARIABLES_LOCAL_MUTATOR_CONTAINER_TOOLTIP="",a.Msg.LANG_VARIABLES_LOCAL_MUTATOR_ARG_TITLE_NAME="name",a.Msg.LANG_VARIABLES_LOCAL_MUTATOR_ARG_DEFAULT_VARIABLE="x",a.Msg.LANG_PROCEDURES_DEFNORETURN_DEFINE="to",a.Msg.LANG_PROCEDURES_DEFNORETURN_PROCEDURE="procedure",a.Msg.LANG_PROCEDURES_DEFNORETURN_DO="do",a.Msg.LANG_PROCEDURES_DEFNORETURN_COLLAPSED_PREFIX="to ",a.Msg.LANG_PROCEDURES_DEFNORETURN_TOOLTIP="A procedure that does not return a value.",a.Msg.LANG_PROCEDURES_DOTHENRETURN_THEN_RETURN="result",a.Msg.LANG_PROCEDURES_DOTHENRETURN_DO="do",a.Msg.LANG_PROCEDURES_DOTHENRETURN_RETURN="result",a.Msg.LANG_PROCEDURES_DOTHENRETURN_TOOLTIP="Runs the blocks in 'do' and returns a statement. Useful if you need to run a procedure before returning a value to a variable.",a.Msg.LANG_PROCEDURES_DOTHENRETURN_COLLAPSED_TEXT="do/result",a.Msg.LANG_PROCEDURES_DEFRETURN_DEFINE="to",a.Msg.LANG_PROCEDURES_DEFRETURN_PROCEDURE="procedure",a.Msg.LANG_PROCEDURES_DEFRETURN_RETURN="result",a.Msg.LANG_PROCEDURES_DEFRETURN_COLLAPSED_PREFIX="to ",a.Msg.LANG_PROCEDURES_DEFRETURN_TOOLTIP="A procedure returning a result value.",a.Msg.LANG_PROCEDURES_DEF_DUPLICATE_WARNING="Warning:\nThis procedure has\nduplicate inputs.",a.Msg.LANG_PROCEDURES_CALLNORETURN_CALL="call ",a.Msg.LANG_PROCEDURES_CALLNORETURN_PROCEDURE="procedure",a.Msg.LANG_PROCEDURES_CALLNORETURN_COLLAPSED_PREFIX="call ",a.Msg.LANG_PROCEDURES_CALLNORETURN_TOOLTIP="Call a procedure with no return value.",a.Msg.LANG_PROCEDURES_CALLNORETURN_TRANSLATED_NAME="call no return",a.Msg.LANG_PROCEDURES_CALLRETURN_CALL="call ",a.Msg.LANG_PROCEDURES_CALLRETURN_PROCEDURE="procedure",a.Msg.LANG_PROCEDURES_CALLRETURN_COLLAPSED_PREFIX="call ",a.Msg.LANG_PROCEDURES_CALLRETURN_TOOLTIP="Call a procedure with a return value.",a.Msg.LANG_PROCEDURES_CALLRETURN_TRANSLATED_NAME="call return",a.Msg.LANG_PROCEDURES_MUTATORCONTAINER_TITLE="inputs",a.Msg.LANG_PROCEDURES_MUTATORARG_TITLE="input:",a.Msg.LANG_PROCEDURES_HIGHLIGHT_DEF="Highlight Procedure",a.Msg.LANG_PROCEDURES_MUTATORCONTAINER_TOOLTIP="",a.Msg.LANG_PROCEDURES_MUTATORARG_TOOLTIP="",a.Msg.LANG_CONTROLS_FOR_INPUT_WITH="count with",a.Msg.LANG_CONTROLS_FOR_INPUT_VAR="x",a.Msg.LANG_CONTROLS_FOR_INPUT_FROM="from",a.Msg.LANG_CONTROLS_FOR_INPUT_TO="to",a.Msg.LANG_CONTROLS_FOR_INPUT_DO="do",a.Msg.LANG_CONTROLS_FOR_TOOLTIP="Count from a start number to an end number.\nFor each count, set the current count number to\nvariable '%1', and then do some statements.",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_ITEM="for each",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_VAR="number",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_START="from",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_END="to",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_STEP="by",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_DO="do",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_COLLAPSED_TEXT="for number in range",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_COLLAPSED_PREFIX="for",a.Msg.LANG_CONTROLS_FORRANGE_INPUT_COLLAPSED_SUFFIX=" in range",a.Msg.LANG_CONTROLS_FORRANGE_TOOLTIP="Runs the blocks in the 'do' section for each numeric value in the range from start to end, stepping the value each time. Use the given variable name to refer to the current value.",a.Msg.LANG_CONTROLS_FOREACH_INPUT_ITEM="for each",a.Msg.LANG_CONTROLS_FOREACH_INPUT_VAR="item",a.Msg.LANG_CONTROLS_FOREACH_INPUT_INLIST="in list",a.Msg.LANG_CONTROLS_FOREACH_INPUT_DO="do",a.Msg.LANG_CONTROLS_FOREACH_INPUT_COLLAPSED_TEXT="for item in list",a.Msg.LANG_CONTROLS_FOREACH_INPUT_COLLAPSED_PREFIX="for ",a.Msg.LANG_CONTROLS_FOREACH_INPUT_COLLAPSED_SUFFIX=" in list",a.Msg.LANG_CONTROLS_FOREACH_TOOLTIP="Runs the blocks in the 'do' section for each item in the list. Use the given variable name to refer to the current list item.",a.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT="for each %1 with %2 in dictionary %3",a.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT_DO="do",a.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT_KEY="key",a.Msg.LANG_CONTROLS_FOREACH_DICT_INPUT_VALUE="value",a.Msg.LANG_CONTROLS_FOREACH_DICT_TITLE="for each in dictionary",a.Msg.LANG_CONTROLS_FOREACH_DICT_TOOLTIP="Runs the blocks in the 'do' section for each key-value entry in the dictionary. Use the given variable names to refer to the key/value of the current dictionary item.",a.Msg.ERROR_SELECT_VALID_ITEM_FROM_DROPDOWN="Select a valid item in the drop down.",a.Msg.ERROR_BLOCK_CANNOT_BE_IN_DEFINITION="This block cannot be in a definition",a.Msg.HORIZONTAL_PARAMETERS="Arrange Parameters Horizontally",a.Msg.VERTICAL_PARAMETERS="Arrange Parameters Vertically",a.Msg.LANG_CONTROLS_DO_THEN_RETURN_INPUT_DO="do",a.Msg.LANG_CONTROLS_DO_THEN_RETURN_INPUT_RETURN="result",a.Msg.LANG_CONTROLS_DO_THEN_RETURN_TOOLTIP="Runs the blocks in 'do' and returns a statement. Useful if you need to run a procedure before returning a value to a variable.",a.Msg.LANG_CONTROLS_DO_THEN_RETURN_COLLAPSED_TEXT="do/result",a.Msg.LANG_CONTROLS_DO_THEN_RETURN_TITLE="do result",a.Msg.PROCEDURES_DEFNORETURN_PROCEDURE=a.Msg.LANG_PROCEDURES_DEFNORETURN_PROCEDURE,a.Msg.PROCEDURES_DEFRETURN_PROCEDURE=a.Msg.LANG_PROCEDURES_DEFRETURN_PROCEDURE,a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_WARNING="Global declarations must be inside of a initialize global block.",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TITLE_INIT="initialize global variables",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TO_DO="to",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_TOOLTIP="Allows you to create global variables that are accessible everywhere",a.Msg.LANG_VARIABLES_GLOBAL_DECLARATION_BLOCK_CHECK="Only global_declaration_entry blocks are allowed here.";class l{checkErrors(e){if(e.getSvgRoot&&!e.getSvgRoot()||e.readOnly)return e.hasWarning&&(e.hasWarning=!1),void(e.hasError&&(e.hasError=!1));e.errors||(e.errors=[]),e.warnings||(e.warnings=[]);const t=e.errors,n=e.warnings;for(let n=0;n{s(e,t,n,r)}),o=r,r=r.getParent();return P.sortAndRemoveDuplicates(t)},y.dropdownCreate=function(){const e=this.getNamesInScope();return e.length>0?e:this.translatedName?[[this.translatedName,this.varname]]:[[" "," "]]},y.prototype.doValueUpdate_=function(e){if(Object.getPrototypeOf(a.FieldDropdown).prototype.doValueUpdate_.call(this,e),e&&" "!==e){const t=e.split(" ");2==t.length&&"global"!==t[0]&&(e="global "+t[1])}this.value_=e;const t=this.getOptions(!0,[[(n=e,n.startsWith("global ")?n.replace("global ",a.Msg.LANG_VARIABLES_GLOBAL_PREFIX+" "):n),e]]);var n;for(let e,n=0;e=t[n];n++)if(e[1]==this.value_){this.selectedOption=e;break}this.updateMutation(),this.forceRerender()},y.prototype.updateMutation=function(){const e=this.getText();if(this.getSourceBlock()&&this.getSourceBlock().getParent()){if(this.getSourceBlock().eventparam=void 0,0===e.indexOf(a.Msg.LANG_VARIABLES_GLOBAL_PREFIX+" "))return this.getSourceBlock().eventparam=null,this.translatedName=void 0,void(this.varname=void 0);let t,n=this.getSourceBlock().getParent();for(;n;){const r=n.declaredVariables?n.declaredVariables():[];for(t=0;t=<`'\"#:;,\\\\*+.()|{}[\\] ][^-!&%^/>=<'\"#:;,\\\\*+.()|{}[\\] ]*$");return{isLegal:0==t.search(n),transformed:t}},makeLegalIdentifier:function(e){const t=P.checkIdentifier(e);return t.isLegal?t.transformed:""===t.transformed?"_":"name"},referenceResult:function(e,t,n,r){if(!e)return[[],[]];const o=e.referenceResults?e.referenceResults(t,n,r):e.getChildren().map(function(e){return P.referenceResult(e,t,n,r)});let s=[],i=[];for(let e=0;e{if("string"==typeof e&&"string"==typeof t)return e.localeCompare(t);if(Array.isArray(e)&&Array.isArray(t))return e[1].localeCompare(t[1]);throw Error("LexicalVariable.sortAndRemoveDuplicates: arguments must be strings or arrays of strings")}),n=[];if(e.length>=1){let e=t[0];n.push(e);for(let r=1;r1&&r.splice(0,1),r},D=function(e){if(this.getSourceBlock()&&this.getSourceBlock().isInFlyout)return e;const t=this.oldName_||this.getValue(),n=e;e=P.makeLegalIdentifier(e);const r=function(e){const t=e.workspace.getTopBlocks(!1),n=[];for(let r=0;r'+e+''+e+""},V.fromJson=function(e){const t=a.utils.replaceMessageReferences(e.name);return new V(t)},a.fieldRegistry.register("field_global_flydown",V);class F extends a.FieldDropdown{constructor(...e){super(...e)}}F.prototype.doClassValidation_=function(e){let t=!1;const n=this.getOptions(!0);for(let r,o=0;r=n[o];o++)if(r[1]===e){t=!0;break}return t||this.generatedOptions.push([e,e]),e},F.fromJson=function(e){return new F(e.options,void 0,e)},a.fieldRegistry.register("field_nocheck_dropdown",F);class G extends v{constructor(e,t,n,r){super(e,t,n,function(e){if(!G.changeHandlerEnabled)return e;const t=P.renameParam.call(this,e);return r&&r.call(this,t),t})}referencesVariables(){return!0}}G.prototype.fieldCSSClassName="blocklyFieldParameter",G.prototype.flyoutCSSClassName="blocklyFieldParameterFlydown",G.changeHandlerEnabled=!0,G.withChangeHanderDisabled=function(e){const t=G.changeHandlerEnabled;G.changeHandlerEnabled=!1;try{e()}finally{G.changeHandlerEnabled=t}},G.prototype.flydownBlocksXML_=function(){const e=this.getText();return''+e+''+e+""},G.addHorizontalVerticalOption=function(e,t){let n=0;if(e.getParameters&&(n=e.getParameters().length),e.isCollapsed()||n<=0)return;const r={enabled:!0,text:e.horizontalParameters?a.Msg.VERTICAL_PARAMETERS:a.Msg.HORIZONTAL_PARAMETERS,callback:function(){e.setParameterOrientation(!e.horizontalParameters)}};let o=0;for(let e;(e=t[o])&&e.text!=a.Msg.COLLAPSE_BLOCK;o++);t.splice(o,0,r);for(let e,n=0;e=t[n];n++)if(e.text==a.Msg.INLINE_INPUTS){t.splice(n,1);break}},G.fromJson=function(e){const t=a.utils.replaceMessageReferences(e.name);return new G(t,e.is_editable)},a.fieldRegistry.register("field_parameter_flydown",G);class B extends a.FieldTextInput{constructor(e){super(e,D)}setValue(e){const t=this.getValue();if(this.oldName_=t,this.doValueUpdate_(e),super.setValue(e),!this.getSourceBlock()||!this.getSourceBlock().isInFlyout){if("string"==typeof(e=this.getValue())&&this.getSourceBlock()){const n=this.getSourceBlock().workspace.getProcedureDatabase();n&&(n.getProcedure(this.getSourceBlock().id)?n.renameProcedure(this.getSourceBlock().id,t,e):n.addProcedure(e,this.getSourceBlock()))}this.oldName_=void 0}}}B.fromJson=function(e){const t=a.utils.replaceMessageReferences(e.name);return new B(t)},a.fieldRegistry.register("field_procedurename",B);class x extends a.blockRendering.ExternalValueInput{constructor(e,t){super(e,t),this.connectedBlock?this.height=this.connectedBlockHeight:this.height=this.constants_.EMPTY_STATEMENT_INPUT_HEIGHT}}class U extends a.geras.Highlighter{constructor(e){super(e)}drawIndentedInput(e){const t=e.getLastInput();if(this.RTL_){const n=e.height-t.connectionHeight-t.connectionOffsetY;this.steps_+=a.utils.svgPaths.moveTo(t.xPos+this.highlightOffset+t.connectionWidth-1,e.yPos)+a.utils.svgPaths.lineOnAxis("v",t.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)+a.utils.svgPaths.lineOnAxis("v",n)}else this.steps_+=a.utils.svgPaths.moveTo(t.xPos+t.connectionWidth,e.yPos+t.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)+a.utils.svgPaths.moveTo(t.xPos+t.connectionWidth+1,e.yPos+t.height)}}class W extends a.geras.Drawer{constructor(e,t){super(e,t),this.highlighter_=new U(t)}drawOutline_(){this.drawTop_();for(let e=1;e{if(d){const n=r.getFieldValue(e);return E(t)(n)}return r.getFieldValue(e)}),s=n.concat(o),i=r.inputList.map(o=>P.referenceResult(r.getInputTargetBlock(o.name),e,t,o.name===r.getScopedInputName()?s:n));return r.nextConnection&&i.push(P.referenceResult(r.getNextBlock(),e,t,n)),i},withLexicalVarsAndPrefix:function(e,t){const n=this;e&&n.getInputTargetBlock(n.getScopedInputName())===e&&n.getDeclaredVarFieldNamesAndPrefixes().forEach(([e,r])=>{const o=n.getFieldValue(e);t(o,r)})},getDeclaredVars:function(){const e=this;return e.getDeclaredVarFieldNames().map(t=>e.getFieldValue(t))},blocksInScope:function(){const e=this.getInputTargetBlock(this.getScopedInputName());return e&&[e]||[]},declaredNames:function(){return this.getDeclaredVars()},renameVar:function(e,t){if(this.renameVars)this.renameVars(I.simpleSubstitution(e,t));else{const n=this;n.getDeclaredVarFieldNames().forEach(r=>{a.Names.equals(e,n.getFieldValue(r))&&n.setFieldValue(t,r)})}},renameBound:function(e,t){const n=this;let r=t;if(n.inputList.forEach(o=>{o.name===n.getScopedInputName()?(n.getDeclaredVarFieldNames().forEach(o=>{const s=n.getFieldValue(o),i=e.apply(s);if(i!==s){n.renameVar(s,i);const e=I.simpleSubstitution(s,i);r=t.extend(e)}else r=t.remove([s])}),P.renameFree(n.getInputTargetBlock(n.getScopedInputName()),r)):P.renameFree(n.getInputTargetBlock(o.name),t)}),n.nextConnection){const e=n.nextConnection.targetBlock();P.renameFree(e,t)}},renameFree:function(e){const t=this,n=P.freeVariables(t.getInputTargetBlock(t.getScopedInputName())),r=new I;t.getDeclaredVarFieldNames().forEach(o=>{const s=t.getFieldValue(o);n.deleteName(s);const i=n.renamed(e);if(i.isMember(s)){const e=y.nameNotIn(s,i.toList()),t=I.simpleSubstitution(s,e);r.extend(t)}}),t.renameBound(r,e)},freeVariables:function(){const e=this,t=P.freeVariables(e.getInputTargetBlock(e.getScopedInputName()));if(e.getDeclaredVarFieldNames().forEach(n=>{t.deleteName(e.getFieldValue(n))}),e.inputList.forEach(n=>{n.name!==e.getScopedInputName()&&t.unite(P.freeVariables(e.getInputTargetBlock(n.name)))}),e.nextConnection){var n=e.nextConnection.targetBlock();t.unite(P.freeVariables(n))}return t}},j={...Y,getDeclaredVarFieldNamesAndPrefixes:function(){return this.getDeclaredVarFieldNames().map(e=>[e,void 0])}},z={...Y,getDeclaredVarFieldNames:function(){return this.getDeclaredVarFieldNamesAndPrefixes().map(([e,t])=>e)}};a.Extensions.registerMixin("lexical_variable_scope_mixin",j),a.Extensions.registerMixin("prefixed_lexical_variable_scope_mixin",z);class ${static init(e,t){var n;n=`.${e.getRenderer().getClassName()}.${e.getTheme().getClassName()}`,i.textContent=`\n ${n} .blocklyFieldParameter>rect {\n fill: rgb(222, 143, 108);\n fill-opacity: 1.0;\n stroke-width: 2;\n stroke: rgb(231, 175, 150);\n }\n ${n} .blocklyFieldParameter>text {\n stroke-width: 1;\n fill: #000;\n }\n ${n} .blocklyFieldParameter:hover>rect {\n stroke-width: 2;\n stroke: rgb(231,175,150);\n fill: rgb(231,175,150);\n fill-opacity: 1.0;\n }\n /*\n * [lyn, 10/08/13] Control flydown with the getter/setter blocks.\n */\n ${n} .blocklyFieldParameterFlydown {\n fill: rgb(231,175,150);\n fill-opacity: 0.8;\n }\n /*\n * [lyn, 10/08/13] Control parameter fields with flydown procedure\n * caller block.\n */\n ${n} .blocklyFieldProcedure>rect {\n fill: rgb(215,203,218);\n fill-opacity: 1.0;\n stroke-width: 0;\n stroke: #000;\n }\n ${n} .blocklyFieldProcedure>text {\n fill: #000;\n }\n ${n} .blocklyFieldProcedure:hover>rect {\n stroke-width: 2;\n stroke: #fff;\n fill: rgb(215,203,218);\n fill-opacity: 1.0;\n }\n /*\n * [lyn, 10/08/13] Control flydown with the procedure caller block.\n */\n ${n} .blocklyFieldProcedureFlydown {\n fill: rgb(215,203,218);\n fill-opacity: 0.8;\n }`;const r=new M(new a.Options({scrollbars:!1,rtl:e.RTL,renderer:e.options.renderer,rendererOverrides:e.options.rendererOverrides,parentWorkspace:e}));e.flydown_=r,a.utils.dom.insertAfter(r.createDom("g"),e.svgBubbleCanvas_),r.init(e),r.autoClose=!0,e.disableInvalidBlocks=t?.disableInvalidBlocks||!1}static Flydown=M;static FieldFlydown=v;static FieldGlobalFlydown=V;static FieldParameterFlydown=G;static lexicalVariableScopeMixin=j;static LexicalVariable=P;static FieldLexicalVariable=y;static FieldProcedureName=B;static FieldNoCheckDropdown=F;static NameSet=T;static Shared=s;static Substitution=I}return a.blockRendering.register("geras2_renderer",X),o})()); +//# sourceMappingURL=index.js.map \ No newline at end of file From ac2f5f3b23994f057bda4c1a44e6445b265493b2 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Sun, 19 Apr 2026 21:43:22 -0700 Subject: [PATCH 14/32] Update keyboard-navigation to 3.0.5 --- appinventor/appengine/war/index.jsp | 3 ++- .../js/keyboard-navigation-0.7.0.min.js | 3 --- .../js/keyboard-navigation-3.0.5.min.js | 3 +++ .../blocklyeditor/src/blocklyeditor.js | 25 +++++++++++++------ .../com/google/appinventor/mocha/index.html | 1 + appinventor/karma.conf.js | 1 + 6 files changed, 24 insertions(+), 12 deletions(-) delete mode 100644 appinventor/appengine/war/static/js/keyboard-navigation-0.7.0.min.js create mode 100644 appinventor/appengine/war/static/js/keyboard-navigation-3.0.5.min.js diff --git a/appinventor/appengine/war/index.jsp b/appinventor/appengine/war/index.jsp index 4b5b2b6c9a7..d95ecb1eed3 100644 --- a/appinventor/appengine/war/index.jsp +++ b/appinventor/appengine/war/index.jsp @@ -89,6 +89,7 @@ +