diff --git a/gulpfile.js b/gulpfile.js
index 42774aaecfc4..5c61c266df04 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -38,7 +38,6 @@ const pxtlib = () => compileTsProject("pxtlib");
const pxtcompiler = () => compileTsProject("pxtcompiler");
const pxtpy = () => compileTsProject("pxtpy");
const pxtsim = () => compileTsProject("pxtsim");
-const pxtblocks = () => compileTsProject("pxtblocks");
const pxtrunner = () => compileTsProject("pxtrunner", "built", true);
const pxteditor = () => compileTsProject("pxteditor", "built", true);
const pxtweb = () => compileTsProject("docfiles/pxtweb", "built/web");
@@ -46,16 +45,7 @@ const backendutils = () => compileTsProject("backendutils")
const cli = () => compileTsProject("cli", "built", true);
const webapp = () => compileTsProject("webapp", "built", true);
const reactCommon = () => compileTsProject("react-common", "built/react-common", true);
-
-const pxtblockly = () => gulp.src([
- "webapp/public/blockly/blockly_compressed.js",
- "webapp/public/blockly/blocks_compressed.js",
- "webapp/public/blockly/plugins.js",
- "webapp/public/blockly/msg/js/en.js",
- "built/pxtblocks.js"
-])
- .pipe(concat("pxtblockly.js"))
- .pipe(gulp.dest("built"));
+const pxtblocks = () => compileTsProject("pxtblocks", "built/pxtblocks", true);
const pxtapp = () => gulp.src([
"node_modules/lzma/src/lzma_worker-min.js",
@@ -86,7 +76,6 @@ const pxtembed = () => gulp.src([
"built/pxtlib.js",
"built/pxtcompiler.js",
"built/pxtpy.js",
- "built/pxtblockly.js",
"built/pxtsim.js",
"built/web/runnerembed.js"
])
@@ -121,8 +110,8 @@ function initWatch() {
const tasks = [
pxtlib,
gulp.parallel(pxtcompiler, pxtsim, backendutils),
- gulp.parallel(pxtpy, gulp.series(copyBlockly, pxtblocks, pxtblockly)),
- pxteditor,
+ pxtpy,
+ gulp.parallel(pxtblocks, pxteditor),
gulp.parallel(pxtrunner, cli, pxtcommon),
gulp.parallel(updatestrings, browserifyEmbed),
gulp.parallel(pxtjs, pxtdts, pxtapp, pxtworker, pxtembed),
@@ -142,7 +131,7 @@ function initWatch() {
gulp.watch("./backendutils/**/*", gulp.series(backendutils, ...tasks.slice(2)));
gulp.watch("./pxtpy/**/*", gulp.series(pxtpy, ...tasks.slice(3)));
- gulp.watch("./pxtblocks/**/*", gulp.series(gulp.series(copyBlockly, pxtblocks, pxtblockly), ...tasks.slice(3)));
+ gulp.watch("./pxtblocks/**/*", gulp.series(pxtblocks, ...tasks.slice(4)));
gulp.watch("./pxteditor/**/*", gulp.series(pxteditor, ...tasks.slice(4)));
@@ -162,7 +151,7 @@ function initWatchCli() {
const tasks = [
pxtlib,
gulp.parallel(pxtcompiler),
- gulp.parallel(pxtpy, gulp.series(pxtblocks, pxtblockly)),
+ pxtpy,
cli,
notifyBuildComplete
]
@@ -172,7 +161,6 @@ function initWatchCli() {
gulp.watch("./pxtcompiler/**/*", gulp.series(pxtcompiler, ...tasks.slice(2)));
gulp.watch("./pxtpy/**/*", gulp.series(pxtpy, ...tasks.slice(3)));
- gulp.watch("./pxtblockly/**/*", gulp.series(gulp.series(copyBlockly, pxtblocks, pxtblockly), ...tasks.slice(3)));
gulp.watch("./cli/**/*", gulp.series(cli, ...tasks.slice(5)));
}
@@ -388,8 +376,6 @@ const copyWebapp = () =>
"built/pxtlib.js",
"built/pxtcompiler.js",
"built/pxtpy.js",
- "built/pxtblocks.js",
- "built/pxtblockly.js",
"built/pxtsim.js",
"built/webapp/src/worker.js",
"built/webapp/src/serviceworker.js",
@@ -401,17 +387,16 @@ const copyWebapp = () =>
const copySemanticFonts = () => gulp.src("node_modules/semantic-ui-less/themes/default/assets/fonts/*")
.pipe(gulp.dest("built/web/fonts"))
-const browserifyWebapp = () => process.env.PXT_ENV == 'production' ?
- exec('node node_modules/browserify/bin/cmd ./built/webapp/src/app.js -g [ envify --NODE_ENV production ] -g uglifyify -o ./built/web/main.js') :
- exec('node node_modules/browserify/bin/cmd built/webapp/src/app.js -o built/web/main.js --debug')
+const execBrowserify = (entryPoint, outfile) => process.env.PXT_ENV == 'production' ?
+ exec(`node node_modules/browserify/bin/cmd ${entryPoint} -g [ envify --NODE_ENV production ] -g [ uglifyify --ignore '**/node_modules/@blockly/**' ] -o ${outfile}`) :
+ exec(`node node_modules/browserify/bin/cmd ${entryPoint} -o ${outfile} --debug`);
-const browserifyAssetEditor = () => process.env.PXT_ENV == 'production' ?
- exec('node node_modules/browserify/bin/cmd ./built/webapp/src/assetEditor.js -g [ envify --NODE_ENV production ] -g uglifyify -o ./built/web/pxtasseteditor.js') :
- exec('node node_modules/browserify/bin/cmd built/webapp/src/assetEditor.js -o built/web/pxtasseteditor.js --debug')
+const browserifyWebapp = () => execBrowserify("./built/webapp/src/app.js", "./built/web/main.js");
+
+const browserifyAssetEditor = () => execBrowserify("./built/webapp/src/assetEditor.js", "./built/web/pxtasseteditor.js");
+
+const browserifyEmbed = () => execBrowserify("./built/pxtrunner/embed.js", "./built/web/runnerembed.js");
-const browserifyEmbed = () => process.env.PXT_ENV == 'production' ?
- exec('node node_modules/browserify/bin/cmd ./built/pxtrunner/embed.js -g [ envify --NODE_ENV production ] -g uglifyify -o ./built/web/runnerembed.js') :
- exec('node node_modules/browserify/bin/cmd built/pxtrunner/embed.js -o built/web/runnerembed.js --debug')
const buildSVGIcons = () => {
let webfontsGenerator = require('@vusion/webfonts-generator')
@@ -534,37 +519,6 @@ const copyMonaco = gulp.series(
stripMonacoSourceMaps
);
-
-
-/********************************************************
- Blockly
-*********************************************************/
-
-const copyBlocklyCompressed = () => gulp.src([
- "node_modules/pxt-blockly/blocks_compressed.js",
- "node_modules/pxt-blockly/blockly_compressed.js"
-])
- .pipe(gulp.dest("webapp/public/blockly/"));
-
-const copyBlocklyExtensions = () => gulp.src("node_modules/@blockly/**/dist/index.js")
- .pipe(concat("plugins.js"))
- .pipe(gulp.dest("webapp/public/blockly/"));
-
-const copyBlocklyEnJs = () => gulp.src("node_modules/pxt-blockly/msg/js/en.js")
- .pipe(gulp.dest("webapp/public/blockly/msg/js/"));
-
-const copyBlocklyEnJson = () => gulp.src("node_modules/pxt-blockly/msg/json/en.json")
- .pipe(gulp.dest("webapp/public/blockly/msg/json/"));
-
-const copyBlocklyMedia = () => gulp.src("node_modules/pxt-blockly/media/*")
- .pipe(gulp.dest("webapp/public/blockly/media"))
-
-const copyBlocklyTypings = () => gulp.src("node_modules/pxt-blockly/typings/blockly.d.ts")
- .pipe(gulp.dest("localtypings/"))
-
-const copyBlockly = gulp.parallel(copyBlocklyCompressed, copyBlocklyExtensions, copyBlocklyEnJs, copyBlocklyEnJson, copyBlocklyMedia, copyBlocklyTypings);
-
-
/********************************************************
Skillmap
*********************************************************/
@@ -764,7 +718,10 @@ const testtutorials = testTask("tutorial-test", "tutorialrunner.js");
const testlanguageservice = testTask("language-service", "languageservicerunner.js");
const testpxteditor = pxtEditorTestTask();
-const buildKarmaRunner = () => compileTsProject("tests/blocklycompiler-test", "built/tests/", true);
+const buildKarmaRunner = () => compileTsProject("tests/blocklycompiler-test", "built/", true);
+const browserifyKarma = () =>
+ exec('node node_modules/browserify/bin/cmd built/tests/blocklycompiler-test/test.spec.js -o built/tests/karma-test-runner.js --debug');
+
const runKarma = () => {
let command;
if (isWin32) {
@@ -777,9 +734,11 @@ const runKarma = () => {
}
return exec(command, true);
}
-const karma = gulp.series(buildKarmaRunner, runKarma);
+const karma = gulp.series(buildKarmaRunner, browserifyKarma, runKarma);
-const buildBlocksTestRunner = () => compileTsProject("tests/blocks-test", "built/tests", true)
+const buildBlocksTestRunner = () => compileTsProject("tests/blocks-test", "built/", true);
+const browserifyBlocksTestRunner = () =>
+ exec('node node_modules/browserify/bin/cmd built/tests/blocks-test/blocksrunner.js -o built/tests/blocksrunner.js --debug');
const testAll = gulp.series(
testdecompiler,
@@ -849,11 +808,10 @@ const buildAll = gulp.series(
updatestrings,
maybeUpdateWebappStrings(),
copyTypescriptServices,
- copyBlocklyTypings,
gulp.parallel(pxtlib, pxtweb),
gulp.parallel(pxtcompiler, pxtsim, backendutils),
- gulp.parallel(pxtpy, gulp.series(copyBlockly, pxtblocks, pxtblockly)),
- pxteditor,
+ pxtpy,
+ gulp.parallel(pxteditor, pxtblocks),
gulp.parallel(pxtrunner, cli, pxtcommon),
browserifyEmbed,
gulp.parallel(pxtjs, pxtdts, pxtapp, pxtworker, pxtembed),
@@ -866,6 +824,7 @@ const buildAll = gulp.series(
browserifyAssetEditor,
gulp.parallel(semanticjs, copyJquery, copyWebapp, copySemanticFonts, copyMonaco),
buildBlocksTestRunner,
+ browserifyBlocksTestRunner,
runUglify
);
@@ -876,7 +835,7 @@ exports.clean = clean;
exports.build = buildAll;
exports.webapp = gulp.series(
- reactCommon,
+ gulp.parallel(reactCommon, pxtblocks, pxteditor),
webapp,
browserifyWebapp,
browserifyAssetEditor
@@ -884,7 +843,6 @@ exports.webapp = gulp.series(
exports.skillmapTest = testSkillmap;
exports.updatestrings = updatestrings;
-exports.updateblockly = copyBlockly;
exports.lint = lint
exports.testdecompiler = testdecompiler;
exports.testlang = testlang;
@@ -915,7 +873,7 @@ exports.testpxteditor = testpxteditor;
exports.cli = gulp.series(
gulp.parallel(pxtlib, pxtweb),
gulp.parallel(pxtcompiler, pxtsim, backendutils),
- gulp.parallel(pxtpy, gulp.series(copyBlockly, pxtblocks, pxtblockly)),
+ pxtpy,
pxteditor,
gulp.parallel(pxtrunner, cli, pxtcommon),
pxtjs
diff --git a/karma.conf.js b/karma.conf.js
index bd31a0a10dd1..812a0903b95c 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -21,9 +21,8 @@ module.exports = function(config) {
'built/web/typescript.js',
'webapp/public/blockly/**/*.js',
'built/pxtlib.js',
- 'built/pxtblocks.js',
'built/pxtcompiler.js',
- 'built/tests/tests.spec.js',
+ 'built/tests/karma-test-runner.js',
// test assets
{ pattern: 'tests/blocklycompiler-test/cases/*.blocks', watched: false, included: false, served: true, nocache: false },
diff --git a/localtypings/evaluation.d.ts b/localtypings/evaluation.d.ts
new file mode 100644
index 000000000000..a0630a704e9d
--- /dev/null
+++ b/localtypings/evaluation.d.ts
@@ -0,0 +1,5 @@
+namespace pxt.blocks {
+ export interface EvaluationResult {
+ result: boolean;
+ }
+}
\ No newline at end of file
diff --git a/localtypings/navigationController.d.ts b/localtypings/navigationController.d.ts
new file mode 100644
index 000000000000..549a7062b600
--- /dev/null
+++ b/localtypings/navigationController.d.ts
@@ -0,0 +1,19 @@
+type WorkspaceSvg = import("blockly").WorkspaceSvg;
+
+declare module '@blockly/keyboard-navigation' {
+ class NavigationController {
+ init(): void;
+ addWorkspace(workspace: WorkspaceSvg): void;
+ enable(workspace: WorkspaceSvg): void;
+ disable(workspace: WorkspaceSvg): void;
+ focusToolbox(workspace: WorkspaceSvg): void;
+ navigation: Navigation;
+ }
+
+ class Navigation {
+ resetFlyout(workspace: WorkspaceSvg, shouldHide: boolean): void;
+ setState(workspace: WorkspaceSvg, state: BlocklyNavigationState): void;
+ }
+
+ type BlocklyNavigationState = "workspace" | "toolbox" | "flyout";
+}
\ No newline at end of file
diff --git a/localtypings/pxtarget.d.ts b/localtypings/pxtarget.d.ts
index ce1888bcde92..d4d471eeb2ab 100644
--- a/localtypings/pxtarget.d.ts
+++ b/localtypings/pxtarget.d.ts
@@ -1,6 +1,5 @@
///
///
-///
///
declare namespace pxt {
@@ -356,7 +355,8 @@ declare namespace pxt {
invertedMonaco?: boolean; // if true: use the vs-dark monaco theme
invertedGitHub?: boolean; // inverted github view
lightToc?: boolean; // if true: do NOT use inverted style in docs toc
- blocklyOptions?: Blockly.BlocklyOptions; // Blockly options, see Configuration: https://developers.google.com/blockly/guides/get-started/web
+ // FIXME (riknoll): Can't use Blockly types here
+ blocklyOptions?: any; // Blockly options, see Configuration: https://developers.google.com/blockly/guides/get-started/web
hideFlyoutHeadings?: boolean; // Hide the flyout headings at the top of the flyout when on a mobile device.
monacoColors?: pxt.Map; // Monaco theme colors, see https://code.visualstudio.com/docs/getstarted/theme-color-reference
simAnimationEnter?: string; // Simulator enter animation
@@ -398,8 +398,8 @@ declare namespace pxt {
useUploadMessage?: boolean; // change "Download" text to "Upload"
downloadIcon?: string; // which icon io use for download
blockColors?: Map; // block namespace colors, used for build in categories
- blockIcons?: Map;
- blocklyColors?: Blockly.Colours; // Blockly workspace, flyout and other colors
+ blockIcons?: Map;
+ blocklyColors?: pxt.Map; // Overrides for the styles in the workspace Blockly.Theme.ComponentStyle
socialOptions?: SocialOptions; // show social icons in share dialog, options like twitter handle and org handle
noReloadOnUpdate?: boolean; // do not notify the user or reload the page when a new app cache is downloaded
appPathNames?: string[]; // Authorized URL paths in embedded apps, all other paths will display a warning banner
diff --git a/localtypings/pxtblockly.d.ts b/localtypings/pxtblockly.d.ts
index 836c58581514..fe5bebe8a69e 100644
--- a/localtypings/pxtblockly.d.ts
+++ b/localtypings/pxtblockly.d.ts
@@ -1,135 +1,16 @@
-///
-///
+import * as pxtblockly from "../built/pxtblocks/index";
+import * as Blockly from "blockly";
+type pxtblockly_ = typeof pxtblockly;
+type Blockly_ = typeof Blockly;
-declare namespace Blockly {
+declare global {
+ namespace pxt.blocks {
+ interface PxtBlockly extends pxtblockly_ {
- /**
- * Block Definitions
- */
-
- interface BlockDefinition {
- codeCard?: any;
- init: () => void;
- getVars?: () => any[];
- renameVar?: (oldName: string, newName: string) => void;
- customContextMenu?: any;
- getProcedureCall?: () => string;
- renameProcedure?: (oldName: string, newName: string) => void;
- defType_?: string;
- onchange?: (event: any) => void;
- mutationToDom?: () => Element;
- domToMutation?: (xmlElement: Element) => void;
- }
-
- const Blocks: {
- [index: string]: BlockDefinition;
- }
-
- // if type == controls_if
- class IfBlock extends Block {
- elseifCount_: number;
- elseCount_: number;
- }
-
- /**
- * Custom Fields
- */
-
- interface FieldCustomOptions {
- blocksInfo: any;
- colour?: string | number;
- label?: string;
- type?: string;
- }
-
- interface FieldCustomDropdownOptions extends FieldCustomOptions {
- data?: any;
- }
-
- interface FieldCustom extends Field {
- isFieldCustom_: boolean;
- saveOptions?(): pxt.Map;
- restoreOptions?(map: pxt.Map): void;
- }
-
- interface FieldCustomConstructor {
- new(text: string, options: FieldCustomOptions, validator?: Function): FieldCustom;
- }
-
- /**
- * Functions
- */
-
- namespace PXTBlockly {
- namespace FunctionUtils {
- let argumentIcons: {[typeName: string]: string};
- let argumentDefaultNames: {[typeName: string]: string};
- function createCustomArgumentReporter(typeName: string, ws: Blockly.Workspace): Blockly.Block;
- }
- }
-
- namespace Functions {
- interface ArgumentInfo {
- type: string;
- name: string;
- id: string;
}
- type ConfirmEditCallback = (mutation: Element) => void;
- }
- class FunctionBlockAbstract extends BlockSvg {
- getArguments: () => Functions.ArgumentInfo[];
- }
+ interface BlocklyModule extends Blockly_ {
- class FunctionDeclarationBlock extends FunctionBlockAbstract {
- updateFunctionSignature: () => void;
- addBooleanExternal(): void;
- addStringExternal(): void;
- addNumberExternal(): void;
- addArrayExternal(): void;
- addCustomExternal(typeName: string): void;
+ }
}
-
- class FunctionDefinitionBlock extends FunctionBlockAbstract { }
- class FunctionCallBlock extends FunctionBlockAbstract { }
-}
-
-/**
- * Blockly Keyboard Navigation plugin
- * Used for accessible blocks experiment
- */
-
-declare class NavigationController {
- init(): void;
- addWorkspace(workspace: Blockly.WorkspaceSvg): void;
- enable(workspace: Blockly.WorkspaceSvg): void;
- disable(workspace: Blockly.WorkspaceSvg): void;
- focusToolbox(workspace: Blockly.WorkspaceSvg): void;
- navigation: Navigation;
-}
-
-declare class Navigation {
- resetFlyout(workspace: Blockly.WorkspaceSvg, shouldHide: boolean): void;
- setState(workspace: Blockly.WorkspaceSvg, state: BlocklyNavigationState): void;
-}
-
-declare type BlocklyNavigationState = "workspace" | "toolbox" | "flyout";
-
-/**
- * Blockly Workspace Search plugin
- * Used for accessible blocks experiment
- */
-
-declare class WorkspaceSearch {
- constructor(workspace: Blockly.WorkspaceSvg);
- protected workspace_: Blockly.WorkspaceSvg;
- protected htmlDiv_: HTMLDivElement;
- protected inputElement_: HTMLInputElement;
- init(): void;
- protected createDom_(): void;
- protected addEvent_(node: Element, name: string, thisObject: Object, func: Function): void;
- open(): void;
- close(): void;
- previous(): void;
- next(): void;
}
\ No newline at end of file
diff --git a/localtypings/pxteditor.d.ts b/localtypings/pxteditor.d.ts
index a34eae36c407..ebba04fdd713 100644
--- a/localtypings/pxteditor.d.ts
+++ b/localtypings/pxteditor.d.ts
@@ -1,5 +1,4 @@
///
-///
///
///
@@ -292,7 +291,7 @@ declare namespace pxt.editor {
ts: string;
// rendering options
snippetMode?: boolean;
- layout?: pxt.blocks.BlockLayout;
+ layout?: BlockLayout;
}
export interface EditorMessageRunEvalRequest extends EditorMessageRequest {
@@ -593,6 +592,14 @@ declare namespace pxt.editor {
Disabled = 2
}
+ export const enum BlockLayout {
+ None = 0,
+ Align = 1,
+ // Shuffle deprecated
+ Clean = 3,
+ Flow = 4
+ }
+
export type EditorType = 'blocks' | 'ts';
export interface EditorEvent {
@@ -920,7 +927,10 @@ declare namespace pxt.editor {
blocksScreenshotAsync(pixelDensity?: number, encodeBlocks?: boolean): Promise;
renderBlocksAsync(req: pxt.editor.EditorMessageRenderBlocksRequest): Promise;
renderPythonAsync(req: pxt.editor.EditorMessageRenderPythonRequest): Promise;
- getBlocks(): Blockly.Block[];
+
+ // FIXME (riknoll) need to figure out how to type this better
+ // getBlocks(): Blockly.Block[];
+ getBlocks(): any[];
toggleHighContrast(): void;
setHighContrast(on: boolean): void;
@@ -1013,7 +1023,10 @@ declare namespace pxt.editor {
export interface IFieldCustomOptions {
selector: string;
- editor: Blockly.FieldCustomConstructor;
+ // FIXME (riknoll) need to figure out how to type this better. Also this type is from pxtblocks, but
+ // it uses types dervied from Blockly
+ // editor: Blockly.FieldCustomConstructor;
+ editor: any;
text?: string;
validator?: any;
}
diff --git a/package.json b/package.json
index 967f4b12cff6..ba00e7c7ad81 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "pxt-core",
- "version": "9.3.16",
+ "version": "10.0.0",
"description": "Microsoft MakeCode provides Blocks / JavaScript / Python tools and editors",
"keywords": [
"TypeScript",
@@ -66,13 +66,14 @@
"npm": ">=8.0.0"
},
"dependencies": {
- "@blockly/keyboard-navigation": "^0.1.18",
- "@blockly/plugin-workspace-search": "^4.0.10",
+ "@blockly/keyboard-navigation": "0.5.4",
+ "@blockly/plugin-workspace-search": "8.0.9",
"@fortawesome/fontawesome-free": "^5.15.4",
"@microsoft/applicationinsights-web": "^2.8.11",
"@microsoft/immersive-reader-sdk": "1.1.0",
"@types/diff-match-patch": "^1.0.32",
"@zip.js/zip.js": "2.4.20",
+ "blockly": "10.4.1",
"browserify": "16.2.3",
"chai": "^3.5.0",
"cssnano": "4.1.10",
@@ -110,7 +111,7 @@
"@types/highlight.js": "9.12.2",
"@types/jquery": "3.3.29",
"@types/marked": "0.3.0",
- "@types/mocha": "2.2.44",
+ "@types/mocha": "^2.2.44",
"@types/node": "10.14.2",
"@types/react": "17.0.50",
"@types/react-dom": "17.0.17",
@@ -141,7 +142,6 @@
"monaco-editor": "0.24.0",
"pouchdb": "7.2.1",
"pouchdb-adapter-memory": "7.2.1",
- "pxt-blockly": "4.0.15",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-modal": "3.15.1",
@@ -166,6 +166,7 @@
"test:lang": "gulp testlang",
"update": "gulp update",
"watch-streamer": "cd docs/static/streamer && tsc -t es6 --watch",
- "prepare": "bash scripts/npm-prepare.sh"
+ "prepare": "bash scripts/npm-prepare.sh",
+ "postinstall": "node ./scripts/patchUglifyify.js"
}
}
diff --git a/pxtblocks/blockDragger.ts b/pxtblocks/blockDragger.ts
new file mode 100644
index 000000000000..d95a8f8e165b
--- /dev/null
+++ b/pxtblocks/blockDragger.ts
@@ -0,0 +1,51 @@
+import * as Blockly from "blockly";
+import { DuplicateOnDragBlockDragger } from "./plugins/duplicateOnDrag";
+
+/**
+ * The following patch to blockly is to add the Trash icon on top of the toolbox,
+ * the trash icon should only show when a user drags a block that is already in the workspace.
+ */
+export class BlockDragger extends DuplicateOnDragBlockDragger {
+ drag(e: PointerEvent, currentDragDeltaXY: Blockly.utils.Coordinate): void {
+ const blocklyToolboxDiv = document.getElementsByClassName('blocklyToolboxDiv')[0] as HTMLElement;
+ const blocklyTreeRoot = document.getElementsByClassName('blocklyTreeRoot')[0] as HTMLElement
+ || document.getElementsByClassName('blocklyFlyout')[0] as HTMLElement;
+ const trashIcon = document.getElementById("blocklyTrashIcon");
+ if (blocklyTreeRoot && trashIcon) {
+ const distance = calculateDistance(blocklyTreeRoot.getBoundingClientRect(), e.clientX);
+ if (distance < 200) {
+ const opacity = distance / 200;
+ trashIcon.style.opacity = `${1 - opacity}`;
+ trashIcon.style.display = 'block';
+ if (blocklyToolboxDiv) {
+ blocklyTreeRoot.style.opacity = `${opacity}`;
+ if (distance < 50) {
+ pxt.BrowserUtils.addClass(blocklyToolboxDiv, 'blocklyToolboxDeleting');
+ }
+ }
+ } else {
+ trashIcon.style.display = 'none';
+ blocklyTreeRoot.style.opacity = '1';
+ if (blocklyToolboxDiv) pxt.BrowserUtils.removeClass(blocklyToolboxDiv, 'blocklyToolboxDeleting');
+ }
+ }
+ return super.drag(e, currentDragDeltaXY);
+ }
+
+ endDrag(e: PointerEvent, currentDragDeltaXY: Blockly.utils.Coordinate): void {
+ super.endDrag(e, currentDragDeltaXY);
+ const blocklyToolboxDiv = document.getElementsByClassName('blocklyToolboxDiv')[0] as HTMLElement;
+ const blocklyTreeRoot = document.getElementsByClassName('blocklyTreeRoot')[0] as HTMLElement
+ || document.getElementsByClassName('blocklyFlyout')[0] as HTMLElement;
+ const trashIcon = document.getElementById("blocklyTrashIcon");
+ if (trashIcon && blocklyTreeRoot) {
+ trashIcon.style.display = 'none';
+ blocklyTreeRoot.style.opacity = '1';
+ if (blocklyToolboxDiv) pxt.BrowserUtils.removeClass(blocklyToolboxDiv, 'blocklyToolboxDeleting');
+ }
+ }
+}
+
+function calculateDistance(elemBounds: DOMRect, mouseX: number) {
+ return Math.abs(mouseX - (elemBounds.left + (elemBounds.width / 2)));
+}
\ No newline at end of file
diff --git a/pxtblocks/blocklycompiler.ts b/pxtblocks/blocklycompiler.ts
deleted file mode 100644
index a6211ca397ee..000000000000
--- a/pxtblocks/blocklycompiler.ts
+++ /dev/null
@@ -1,2769 +0,0 @@
-///
-///
-
-let iface: pxt.worker.Iface
-
-namespace pxt.blocks {
- export function workerOpAsync(op: string, arg: pxtc.service.OpArg) {
- return pxt.worker.getWorker(pxt.webConfig.workerjs).opAsync(op, arg)
- }
-
- let placeholders: Map