react-native-blockly 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +91 -0
- package/lib/module/classes/blockly.js +24 -0
- package/lib/module/classes/blockly.js.map +1 -0
- package/lib/module/classes/blocklyViewConfig.js +39 -0
- package/lib/module/classes/blocklyViewConfig.js.map +1 -0
- package/lib/module/index.js +60 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/parsers/parseToString.js +86 -0
- package/lib/module/parsers/parseToString.js.map +1 -0
- package/lib/module/parsers/stringToBlockly.js +87 -0
- package/lib/module/parsers/stringToBlockly.js.map +1 -0
- package/lib/module/types/blockly-types.d.js +4 -0
- package/lib/module/types/blockly-types.d.js.map +1 -0
- package/lib/module/types/blockly-view-types.d.js +4 -0
- package/lib/module/types/blockly-view-types.d.js.map +1 -0
- package/lib/module/utils/blocklyConstants.js +36 -0
- package/lib/module/utils/blocklyConstants.js.map +1 -0
- package/lib/module/utils/defaults.js +20 -0
- package/lib/module/utils/defaults.js.map +1 -0
- package/lib/module/utils/showWarnings.js +75 -0
- package/lib/module/utils/showWarnings.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/classes/blockly.d.ts +16 -0
- package/lib/typescript/src/classes/blockly.d.ts.map +1 -0
- package/lib/typescript/src/classes/blocklyViewConfig.d.ts +14 -0
- package/lib/typescript/src/classes/blocklyViewConfig.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +16 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/parsers/parseToString.d.ts +47 -0
- package/lib/typescript/src/parsers/parseToString.d.ts.map +1 -0
- package/lib/typescript/src/parsers/stringToBlockly.d.ts +14 -0
- package/lib/typescript/src/parsers/stringToBlockly.d.ts.map +1 -0
- package/lib/typescript/src/utils/blocklyConstants.d.ts +17 -0
- package/lib/typescript/src/utils/blocklyConstants.d.ts.map +1 -0
- package/lib/typescript/src/utils/defaults.d.ts +10 -0
- package/lib/typescript/src/utils/defaults.d.ts.map +1 -0
- package/lib/typescript/src/utils/showWarnings.d.ts +15 -0
- package/lib/typescript/src/utils/showWarnings.d.ts.map +1 -0
- package/package.json +155 -0
- package/src/classes/blockly.ts +25 -0
- package/src/classes/blocklyViewConfig.ts +36 -0
- package/src/index.tsx +65 -0
- package/src/parsers/parseToString.ts +92 -0
- package/src/parsers/stringToBlockly.ts +89 -0
- package/src/types/blockly-types.d.ts +28 -0
- package/src/types/blockly-view-types.d.ts +89 -0
- package/src/utils/blocklyConstants.ts +92 -0
- package/src/utils/defaults.ts +19 -0
- package/src/utils/showWarnings.ts +93 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BlocklyViewProps, ButtonConfig } from './types/blockly-view-types';
|
|
2
|
+
import { Blockly } from './classes/blockly';
|
|
3
|
+
import { BlocklyViewConfig } from './classes/blocklyViewConfig';
|
|
4
|
+
export { Blockly, BlocklyViewConfig };
|
|
5
|
+
export type { ButtonConfig };
|
|
6
|
+
/**
|
|
7
|
+
* BlocklyView wrapper for rendering the Blockly workspace.
|
|
8
|
+
*
|
|
9
|
+
* It takes an instance of the Blockly class, a BlocklyViewConfig instance, and an optional onMessage callback and
|
|
10
|
+
* parses the contents to generate an HTML and load it on the WebView.
|
|
11
|
+
*
|
|
12
|
+
* @param param0 - Props for the component
|
|
13
|
+
* @returns JSX.Element
|
|
14
|
+
*/
|
|
15
|
+
export default function BlocklyView({ Blockly, Config, onMessage, style, }: BlocklyViewProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,4BAA4B,CAAC;AAQpC,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAIhE,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,gBAAgB,2CA8BlB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Block, Toolbox, Workspace } from '../types/blockly-types';
|
|
2
|
+
import type { ButtonConfig } from '../types/blockly-view-types';
|
|
3
|
+
import type { CSSProperties } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Parses the blocks array to a string representation.
|
|
6
|
+
*
|
|
7
|
+
* If the block has a 'code' property, it uses that as the code generation logic.
|
|
8
|
+
* Otherwise, it defaults to returning a function call with the block type name.
|
|
9
|
+
* e.g. for a block of type 'moveForward', it will generate code: `return 'moveForward()\n'`; if
|
|
10
|
+
* no code property is provided.
|
|
11
|
+
*
|
|
12
|
+
* @param blocks - array of Block objects
|
|
13
|
+
* @returns a string representation of the blocks in JSON format
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseBlocksToString(blocks: Block[]): string;
|
|
16
|
+
/**
|
|
17
|
+
* Parses the toolbox object to a string representation.
|
|
18
|
+
*
|
|
19
|
+
* @param toolbox - toolbox object
|
|
20
|
+
* @returns a string representation of the toolbox in JSON format
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseToolboxToString(toolbox: Toolbox): string;
|
|
23
|
+
/**
|
|
24
|
+
* Parses the workspace object to a string representation.
|
|
25
|
+
*
|
|
26
|
+
* @param workspace - workspace object
|
|
27
|
+
* @returns a string representation of the workspace in JSON format
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseWorkspaceToString(workspace: Workspace): string;
|
|
30
|
+
/**
|
|
31
|
+
* Converts a CSSProperties object to an inline style string
|
|
32
|
+
*
|
|
33
|
+
* @param styles CSS properties object
|
|
34
|
+
* @returns inline style string
|
|
35
|
+
*/
|
|
36
|
+
export declare function cssObjectToString(styles: CSSProperties): string;
|
|
37
|
+
/**
|
|
38
|
+
* Parses the button configuration to string representation.
|
|
39
|
+
*
|
|
40
|
+
* @param buttonConfig - button configuration object
|
|
41
|
+
* @returns an object with text and style as strings
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseButtonConfigToString(buttonConfig: ButtonConfig): {
|
|
44
|
+
text: string;
|
|
45
|
+
style: string;
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=parseToString.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseToString.d.ts","sourceRoot":"","sources":["../../../../src/parsers/parseToString.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAsB3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAQ/D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,YAAY,GAAG;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAOA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main function to convert all of the characteristics of a Blockly instance into a string
|
|
3
|
+
*
|
|
4
|
+
* @param blocks blocks string
|
|
5
|
+
* @param toolbox toolbox string
|
|
6
|
+
* @param workspace workspace string (JSON stringified workspace configuration)
|
|
7
|
+
* @param buttonConfig parsed button configuration with text and style as strings
|
|
8
|
+
* @returns a complete HTML string ready to be loaded in the WebView
|
|
9
|
+
*/
|
|
10
|
+
export declare function stringToBlockly(blocks: string, toolbox: string, workspace: string, buttonConfig: {
|
|
11
|
+
text: string;
|
|
12
|
+
style: string;
|
|
13
|
+
}): string;
|
|
14
|
+
//# sourceMappingURL=stringToBlockly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stringToBlockly.d.ts","sourceRoot":"","sources":["../../../../src/parsers/stringToBlockly.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5C,MAAM,CAuER"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array of standard Blockly block types that are available by default.
|
|
3
|
+
* These blocks are built into the Blockly library and don't need to be
|
|
4
|
+
* defined in the custom blocks array.
|
|
5
|
+
*/
|
|
6
|
+
export declare const STANDARD_BLOCKLY_BLOCK_TYPES: readonly ["logic_compare", "logic_operation", "logic_negate", "logic_boolean", "logic_null", "logic_ternary", "controls_if", "controls_ifelse", "controls_repeat_ext", "controls_whileUntil", "controls_for", "controls_forEach", "controls_flow_statements", "math_number", "math_arithmetic", "math_single", "math_trig", "math_constant", "math_number_property", "math_round", "math_on_list", "math_modulo", "math_constrain", "math_random_int", "math_random_float", "math_atan2", "text", "text_multiline", "text_join", "text_append", "text_length", "text_isEmpty", "text_indexOf", "text_charAt", "text_getSubstring", "text_changeCase", "text_trim", "text_count", "text_replace", "text_reverse", "text_print", "text_prompt_ext", "lists_create_with", "lists_create_empty", "lists_repeat", "lists_length", "lists_isEmpty", "lists_indexOf", "lists_getIndex", "lists_setIndex", "lists_getSublist", "lists_split", "lists_sort", "lists_reverse", "colour_picker", "colour_random", "colour_rgb", "colour_blend", "variables_get", "variables_set", "procedures_defnoreturn", "procedures_defreturn", "procedures_callnoreturn", "procedures_callreturn", "procedures_ifreturn"];
|
|
7
|
+
/**
|
|
8
|
+
* Set of standard Blockly block types for efficient lookup.
|
|
9
|
+
* Used for runtime validation.
|
|
10
|
+
*/
|
|
11
|
+
export declare const STANDARD_BLOCKLY_BLOCKS: Set<"logic_compare" | "logic_operation" | "logic_negate" | "logic_boolean" | "logic_null" | "logic_ternary" | "controls_if" | "controls_ifelse" | "controls_repeat_ext" | "controls_whileUntil" | "controls_for" | "controls_forEach" | "controls_flow_statements" | "math_number" | "math_arithmetic" | "math_single" | "math_trig" | "math_constant" | "math_number_property" | "math_round" | "math_on_list" | "math_modulo" | "math_constrain" | "math_random_int" | "math_random_float" | "math_atan2" | "text" | "text_multiline" | "text_join" | "text_append" | "text_length" | "text_isEmpty" | "text_indexOf" | "text_charAt" | "text_getSubstring" | "text_changeCase" | "text_trim" | "text_count" | "text_replace" | "text_reverse" | "text_print" | "text_prompt_ext" | "lists_create_with" | "lists_create_empty" | "lists_repeat" | "lists_length" | "lists_isEmpty" | "lists_indexOf" | "lists_getIndex" | "lists_setIndex" | "lists_getSublist" | "lists_split" | "lists_sort" | "lists_reverse" | "colour_picker" | "colour_random" | "colour_rgb" | "colour_blend" | "variables_get" | "variables_set" | "procedures_defnoreturn" | "procedures_defreturn" | "procedures_callnoreturn" | "procedures_callreturn" | "procedures_ifreturn">;
|
|
12
|
+
/**
|
|
13
|
+
* Type representing all standard Blockly block types.
|
|
14
|
+
* Derived from the constant array to ensure type and runtime values stay in sync.
|
|
15
|
+
*/
|
|
16
|
+
export type StandardBlockType = (typeof STANDARD_BLOCKLY_BLOCK_TYPES)[number];
|
|
17
|
+
//# sourceMappingURL=blocklyConstants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocklyConstants.d.ts","sourceRoot":"","sources":["../../../../src/utils/blocklyConstants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,qoCA0E/B,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,uBAAuB,+rCAAwC,CAAC;AAE7E;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Default text for the run code button
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_BUTTON_TEXT = "Run Code";
|
|
6
|
+
/**
|
|
7
|
+
* Default CSS styles for the run code button
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_BUTTON_STYLE: CSSProperties;
|
|
10
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../../src/utils/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAQlC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Block, Toolbox } from '../types/blockly-types';
|
|
2
|
+
/**
|
|
3
|
+
* Validates if blocks and toolbox have matching pairs and shows warnings for mismatches
|
|
4
|
+
*
|
|
5
|
+
* @param blocks - Array of block definitions
|
|
6
|
+
* @param toolbox - Toolbox configuration
|
|
7
|
+
*/
|
|
8
|
+
export declare function blockInToolbox(blocks: Block[], toolbox: Toolbox | null): void;
|
|
9
|
+
/**
|
|
10
|
+
* Validates if blocks with custom code have a return statement and shows warnings for missing returns
|
|
11
|
+
*
|
|
12
|
+
* @param blocks - Array of block definitions
|
|
13
|
+
*/
|
|
14
|
+
export declare function noReturnStatement(blocks: Block[]): void;
|
|
15
|
+
//# sourceMappingURL=showWarnings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"showWarnings.d.ts","sourceRoot":"","sources":["../../../../src/utils/showWarnings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAM7D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAoD7E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAqBvD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-blockly",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Blockly implementation on react native using webview.",
|
|
5
|
+
"source": "./src/index.tsx",
|
|
6
|
+
"main": "./lib/module/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
10
|
+
"default": "./lib/module/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src",
|
|
16
|
+
"lib",
|
|
17
|
+
"android",
|
|
18
|
+
"ios",
|
|
19
|
+
"cpp",
|
|
20
|
+
"*.podspec",
|
|
21
|
+
"react-native.config.js",
|
|
22
|
+
"!ios/build",
|
|
23
|
+
"!android/build",
|
|
24
|
+
"!android/gradle",
|
|
25
|
+
"!android/gradlew",
|
|
26
|
+
"!android/gradlew.bat",
|
|
27
|
+
"!android/local.properties",
|
|
28
|
+
"!**/__tests__",
|
|
29
|
+
"!**/__fixtures__",
|
|
30
|
+
"!**/__mocks__",
|
|
31
|
+
"!**/.*"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"example": "yarn workspace react-native-blockly-example",
|
|
35
|
+
"test": "jest",
|
|
36
|
+
"typecheck": "tsc",
|
|
37
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
38
|
+
"clean": "del-cli lib",
|
|
39
|
+
"prepare": "bob build",
|
|
40
|
+
"release": "release-it"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"react-native",
|
|
44
|
+
"ios",
|
|
45
|
+
"android"
|
|
46
|
+
],
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/alanSilvaaa//react-native-blockly.git"
|
|
50
|
+
},
|
|
51
|
+
"author": "AlanSilvaaa <alanbsr4@gmail.com> (https://github.com/alanSilvaaa/)",
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/alanSilvaaa//react-native-blockly/issues"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/alanSilvaaa//react-native-blockly#readme",
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"registry": "https://registry.npmjs.org/"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@commitlint/config-conventional": "^19.6.0",
|
|
62
|
+
"@eslint/compat": "^1.2.7",
|
|
63
|
+
"@eslint/eslintrc": "^3.3.0",
|
|
64
|
+
"@eslint/js": "^9.22.0",
|
|
65
|
+
"@evilmartians/lefthook": "^1.5.0",
|
|
66
|
+
"@react-native/eslint-config": "^0.78.0",
|
|
67
|
+
"@release-it/conventional-changelog": "^9.0.2",
|
|
68
|
+
"@types/jest": "^29.5.5",
|
|
69
|
+
"@types/react": "^19.0.12",
|
|
70
|
+
"commitlint": "^19.6.1",
|
|
71
|
+
"del-cli": "^5.1.0",
|
|
72
|
+
"eslint": "^9.22.0",
|
|
73
|
+
"eslint-config-prettier": "^10.1.1",
|
|
74
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
75
|
+
"jest": "^29.7.0",
|
|
76
|
+
"prettier": "^3.0.3",
|
|
77
|
+
"react": "19.0.0",
|
|
78
|
+
"react-native": "0.79.5",
|
|
79
|
+
"react-native-builder-bob": "^0.38.3",
|
|
80
|
+
"release-it": "^17.10.0",
|
|
81
|
+
"typescript": "^5.2.2"
|
|
82
|
+
},
|
|
83
|
+
"peerDependencies": {
|
|
84
|
+
"react": "*",
|
|
85
|
+
"react-native": "*"
|
|
86
|
+
},
|
|
87
|
+
"workspaces": [
|
|
88
|
+
"example"
|
|
89
|
+
],
|
|
90
|
+
"packageManager": "yarn@3.6.1",
|
|
91
|
+
"jest": {
|
|
92
|
+
"preset": "react-native",
|
|
93
|
+
"modulePathIgnorePatterns": [
|
|
94
|
+
"<rootDir>/example/node_modules",
|
|
95
|
+
"<rootDir>/lib/"
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
"commitlint": {
|
|
99
|
+
"extends": [
|
|
100
|
+
"@commitlint/config-conventional"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
"release-it": {
|
|
104
|
+
"git": {
|
|
105
|
+
"commitMessage": "chore: release ${version}",
|
|
106
|
+
"tagName": "v${version}"
|
|
107
|
+
},
|
|
108
|
+
"npm": {
|
|
109
|
+
"publish": true
|
|
110
|
+
},
|
|
111
|
+
"github": {
|
|
112
|
+
"release": true
|
|
113
|
+
},
|
|
114
|
+
"plugins": {
|
|
115
|
+
"@release-it/conventional-changelog": {
|
|
116
|
+
"preset": {
|
|
117
|
+
"name": "angular"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"prettier": {
|
|
123
|
+
"quoteProps": "consistent",
|
|
124
|
+
"singleQuote": true,
|
|
125
|
+
"tabWidth": 2,
|
|
126
|
+
"trailingComma": "es5",
|
|
127
|
+
"useTabs": false
|
|
128
|
+
},
|
|
129
|
+
"react-native-builder-bob": {
|
|
130
|
+
"source": "src",
|
|
131
|
+
"output": "lib",
|
|
132
|
+
"targets": [
|
|
133
|
+
[
|
|
134
|
+
"module",
|
|
135
|
+
{
|
|
136
|
+
"esm": true
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
"typescript",
|
|
141
|
+
{
|
|
142
|
+
"project": "tsconfig.build.json"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
"create-react-native-library": {
|
|
148
|
+
"languages": "js",
|
|
149
|
+
"type": "library",
|
|
150
|
+
"version": "0.49.2"
|
|
151
|
+
},
|
|
152
|
+
"dependencies": {
|
|
153
|
+
"react-native-webview": "^13.15.0"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Block } from '../types/blockly-types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Blockly class to manage blockly configuration.
|
|
5
|
+
*/
|
|
6
|
+
export class Blockly {
|
|
7
|
+
blocks: Block[] = [];
|
|
8
|
+
|
|
9
|
+
createBlocks(blocks: Block[]): void {
|
|
10
|
+
this.blocks.push(...blocks);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a blockly block and add it to the blocks array.
|
|
15
|
+
*
|
|
16
|
+
* @param block - Block object to be added to the blocks array
|
|
17
|
+
*/
|
|
18
|
+
createBlock(block: Block): void {
|
|
19
|
+
this.blocks.push(block);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getBlocks(): Block[] {
|
|
23
|
+
return this.blocks;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Toolbox, Workspace } from '../types/blockly-types';
|
|
2
|
+
import type { ButtonConfig } from '../types/blockly-view-types';
|
|
3
|
+
import { DEFAULT_BUTTON_TEXT, DEFAULT_BUTTON_STYLE } from '../utils/defaults';
|
|
4
|
+
|
|
5
|
+
export class BlocklyViewConfig {
|
|
6
|
+
toolbox: Toolbox = { kind: '', contents: [] };
|
|
7
|
+
workspace: Workspace = { scrollbars: false, trashcan: false };
|
|
8
|
+
buttonConfig: ButtonConfig = {
|
|
9
|
+
text: DEFAULT_BUTTON_TEXT,
|
|
10
|
+
style: DEFAULT_BUTTON_STYLE,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
setToolbox(toolbox: Toolbox): void {
|
|
14
|
+
this.toolbox = toolbox;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getToolbox(): Toolbox {
|
|
18
|
+
return this.toolbox;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
setWorkspace(workspace: Workspace): void {
|
|
22
|
+
this.workspace = workspace;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getWorkspace(): Workspace {
|
|
26
|
+
return this.workspace;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setButtonConfig(buttonConfig: ButtonConfig): void {
|
|
30
|
+
this.buttonConfig = { ...this.buttonConfig, ...buttonConfig };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getButtonConfig(): ButtonConfig {
|
|
34
|
+
return this.buttonConfig;
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import WebView from 'react-native-webview';
|
|
2
|
+
import type {
|
|
3
|
+
BlocklyViewProps,
|
|
4
|
+
ButtonConfig,
|
|
5
|
+
} from './types/blockly-view-types';
|
|
6
|
+
import {
|
|
7
|
+
parseBlocksToString,
|
|
8
|
+
parseToolboxToString,
|
|
9
|
+
parseWorkspaceToString,
|
|
10
|
+
parseButtonConfigToString,
|
|
11
|
+
} from './parsers/parseToString';
|
|
12
|
+
import { stringToBlockly } from './parsers/stringToBlockly';
|
|
13
|
+
import { Blockly } from './classes/blockly';
|
|
14
|
+
import { BlocklyViewConfig } from './classes/blocklyViewConfig';
|
|
15
|
+
import { blockInToolbox, noReturnStatement } from './utils/showWarnings';
|
|
16
|
+
|
|
17
|
+
// Export both classes so they can be imported by users
|
|
18
|
+
export { Blockly, BlocklyViewConfig };
|
|
19
|
+
export type { ButtonConfig };
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* BlocklyView wrapper for rendering the Blockly workspace.
|
|
23
|
+
*
|
|
24
|
+
* It takes an instance of the Blockly class, a BlocklyViewConfig instance, and an optional onMessage callback and
|
|
25
|
+
* parses the contents to generate an HTML and load it on the WebView.
|
|
26
|
+
*
|
|
27
|
+
* @param param0 - Props for the component
|
|
28
|
+
* @returns JSX.Element
|
|
29
|
+
*/
|
|
30
|
+
export default function BlocklyView({
|
|
31
|
+
Blockly,
|
|
32
|
+
Config,
|
|
33
|
+
onMessage,
|
|
34
|
+
style,
|
|
35
|
+
}: BlocklyViewProps) {
|
|
36
|
+
/**
|
|
37
|
+
* parse the contents of the Blockly instance and Config to generate the HTML string
|
|
38
|
+
* that will be loaded in the WebView.
|
|
39
|
+
*/
|
|
40
|
+
const blocks = parseBlocksToString(Blockly.getBlocks());
|
|
41
|
+
const toolbox = parseToolboxToString(Config.getToolbox());
|
|
42
|
+
const workspace = parseWorkspaceToString(Config.getWorkspace());
|
|
43
|
+
const buttonConfig = parseButtonConfigToString(Config.getButtonConfig());
|
|
44
|
+
const blocklyHtml = stringToBlockly(blocks, toolbox, workspace, buttonConfig);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Show warnings
|
|
48
|
+
*/
|
|
49
|
+
blockInToolbox(Blockly.getBlocks(), Config.getToolbox());
|
|
50
|
+
noReturnStatement(Blockly.getBlocks());
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<WebView
|
|
54
|
+
originWhitelist={['*']}
|
|
55
|
+
source={{ html: blocklyHtml, baseUrl: 'file:///android_asset/' }}
|
|
56
|
+
style={style || { flex: 1 }}
|
|
57
|
+
onMessage={(event) => {
|
|
58
|
+
// console.log('Message received from webview:', event.nativeEvent.data);
|
|
59
|
+
if (onMessage) {
|
|
60
|
+
onMessage(event.nativeEvent.data); // Call the callback with the data
|
|
61
|
+
}
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Block, Toolbox, Workspace } from '../types/blockly-types';
|
|
2
|
+
import type { ButtonConfig } from '../types/blockly-view-types';
|
|
3
|
+
import type { CSSProperties } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses the blocks array to a string representation.
|
|
7
|
+
*
|
|
8
|
+
* If the block has a 'code' property, it uses that as the code generation logic.
|
|
9
|
+
* Otherwise, it defaults to returning a function call with the block type name.
|
|
10
|
+
* e.g. for a block of type 'moveForward', it will generate code: `return 'moveForward()\n'`; if
|
|
11
|
+
* no code property is provided.
|
|
12
|
+
*
|
|
13
|
+
* @param blocks - array of Block objects
|
|
14
|
+
* @returns a string representation of the blocks in JSON format
|
|
15
|
+
*/
|
|
16
|
+
export function parseBlocksToString(blocks: Block[]): string {
|
|
17
|
+
let htmlString = '';
|
|
18
|
+
blocks.forEach((block: Block) => {
|
|
19
|
+
htmlString += `
|
|
20
|
+
Blockly.defineBlocksWithJsonArray([
|
|
21
|
+
{
|
|
22
|
+
"type": "${block.type}",
|
|
23
|
+
"message0": "${block.message0}",
|
|
24
|
+
"colour": ${block.colour || 230},
|
|
25
|
+
"tooltip": "${block.tooltip || 'No tooltip'}",
|
|
26
|
+
"previousStatement": null,
|
|
27
|
+
"nextStatement": null,
|
|
28
|
+
"helpUrl": ""
|
|
29
|
+
}
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
javascript.javascriptGenerator.forBlock['${block.type}'] = function (block) {
|
|
33
|
+
${block.code ? block.code : `return '${block.type}()\\n'`};
|
|
34
|
+
};
|
|
35
|
+
`;
|
|
36
|
+
});
|
|
37
|
+
return htmlString;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parses the toolbox object to a string representation.
|
|
42
|
+
*
|
|
43
|
+
* @param toolbox - toolbox object
|
|
44
|
+
* @returns a string representation of the toolbox in JSON format
|
|
45
|
+
*/
|
|
46
|
+
export function parseToolboxToString(toolbox: Toolbox): string {
|
|
47
|
+
return JSON.stringify(toolbox);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parses the workspace object to a string representation.
|
|
52
|
+
*
|
|
53
|
+
* @param workspace - workspace object
|
|
54
|
+
* @returns a string representation of the workspace in JSON format
|
|
55
|
+
*/
|
|
56
|
+
export function parseWorkspaceToString(workspace: Workspace): string {
|
|
57
|
+
return JSON.stringify(workspace);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Converts a CSSProperties object to an inline style string
|
|
62
|
+
*
|
|
63
|
+
* @param styles CSS properties object
|
|
64
|
+
* @returns inline style string
|
|
65
|
+
*/
|
|
66
|
+
export function cssObjectToString(styles: CSSProperties): string {
|
|
67
|
+
return Object.entries(styles)
|
|
68
|
+
.map(([key, value]) => {
|
|
69
|
+
// Convert camelCase to kebab-case
|
|
70
|
+
const kebabKey = key.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
71
|
+
return `${kebabKey}: ${value}`;
|
|
72
|
+
})
|
|
73
|
+
.join('; ');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Parses the button configuration to string representation.
|
|
78
|
+
*
|
|
79
|
+
* @param buttonConfig - button configuration object
|
|
80
|
+
* @returns an object with text and style as strings
|
|
81
|
+
*/
|
|
82
|
+
export function parseButtonConfigToString(buttonConfig: ButtonConfig): {
|
|
83
|
+
text: string;
|
|
84
|
+
style: string;
|
|
85
|
+
} {
|
|
86
|
+
const text = buttonConfig?.text ?? '';
|
|
87
|
+
const style = buttonConfig?.style
|
|
88
|
+
? cssObjectToString(buttonConfig.style)
|
|
89
|
+
: '';
|
|
90
|
+
|
|
91
|
+
return { text, style };
|
|
92
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { DEFAULT_BUTTON_TEXT, DEFAULT_BUTTON_STYLE } from '../utils/defaults';
|
|
2
|
+
import { cssObjectToString } from './parseToString';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Main function to convert all of the characteristics of a Blockly instance into a string
|
|
6
|
+
*
|
|
7
|
+
* @param blocks blocks string
|
|
8
|
+
* @param toolbox toolbox string
|
|
9
|
+
* @param workspace workspace string (JSON stringified workspace configuration)
|
|
10
|
+
* @param buttonConfig parsed button configuration with text and style as strings
|
|
11
|
+
* @returns a complete HTML string ready to be loaded in the WebView
|
|
12
|
+
*/
|
|
13
|
+
export function stringToBlockly(
|
|
14
|
+
blocks: string,
|
|
15
|
+
toolbox: string,
|
|
16
|
+
workspace: string,
|
|
17
|
+
buttonConfig: { text: string; style: string }
|
|
18
|
+
): string {
|
|
19
|
+
return `
|
|
20
|
+
<!DOCTYPE html>
|
|
21
|
+
<html>
|
|
22
|
+
<head>
|
|
23
|
+
<meta charset="utf-8" />
|
|
24
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
25
|
+
<title>Custom Blockly Block</title>
|
|
26
|
+
<style>
|
|
27
|
+
html, body {
|
|
28
|
+
font-family: Arial, sans-serif;
|
|
29
|
+
margin: 0;
|
|
30
|
+
padding: 0;
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
}
|
|
35
|
+
body {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
}
|
|
39
|
+
#blocklyDiv {
|
|
40
|
+
flex: 1;
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
<div id="blocklyDiv"></div>
|
|
47
|
+
<button id="runCodeButton" style="${buttonConfig.style || cssObjectToString(DEFAULT_BUTTON_STYLE)}">${buttonConfig.text || DEFAULT_BUTTON_TEXT}</button>
|
|
48
|
+
|
|
49
|
+
<!-- Import required Blockly packages -->
|
|
50
|
+
<script src="https://unpkg.com/blockly/blockly_compressed.js"></script>
|
|
51
|
+
<script src="https://unpkg.com/blockly/blocks_compressed.js"></script>
|
|
52
|
+
<script src="https://unpkg.com/blockly/javascript_compressed.js"></script>
|
|
53
|
+
<script src="https://unpkg.com/blockly/msg/en.js"></script>
|
|
54
|
+
<script>
|
|
55
|
+
// Define the custom block using JSON
|
|
56
|
+
console.log('Blockly namespace:', typeof Blockly);
|
|
57
|
+
console.log('Blockly.JavaScript namespace:', typeof Blockly.JavaScript);
|
|
58
|
+
console.log('javascript.javascriptGenerator:', typeof javascript.javascriptGenerator);
|
|
59
|
+
|
|
60
|
+
${blocks ?? ''}
|
|
61
|
+
|
|
62
|
+
// Define the toolbox with the custom block
|
|
63
|
+
const toolbox = ${toolbox || `{}`};
|
|
64
|
+
|
|
65
|
+
// Parse workspace configuration
|
|
66
|
+
const workspaceConfig = ${workspace || `{}`};
|
|
67
|
+
|
|
68
|
+
// Inject Blockly into the workspace
|
|
69
|
+
const workspace = Blockly.inject('blocklyDiv', {
|
|
70
|
+
toolbox: toolbox,
|
|
71
|
+
...workspaceConfig,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Run the code when the button is clicked
|
|
75
|
+
document.getElementById('runCodeButton').addEventListener('click', () => {
|
|
76
|
+
const code = Blockly.JavaScript.workspaceToCode(workspace);
|
|
77
|
+
console.log('Generated Code:', code); // For debugging
|
|
78
|
+
try {
|
|
79
|
+
// eval(code); // Execute the code
|
|
80
|
+
window.ReactNativeWebView.postMessage(code); // Send the code to the app
|
|
81
|
+
} catch (error) {
|
|
82
|
+
alert('Error: ' + error.message);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
</body>
|
|
87
|
+
</html>
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { StandardBlockType } from '../utils/blocklyConstants';
|
|
2
|
+
|
|
3
|
+
export type { StandardBlockType };
|
|
4
|
+
|
|
5
|
+
export type Block = {
|
|
6
|
+
type: string | StandardBlockType;
|
|
7
|
+
message0?: string;
|
|
8
|
+
colour?: number;
|
|
9
|
+
tooltip?: string;
|
|
10
|
+
previousStatement?: null;
|
|
11
|
+
nextStatement?: null;
|
|
12
|
+
helpUrl?: string;
|
|
13
|
+
output?: boolean | null;
|
|
14
|
+
code?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type Toolbox = {
|
|
18
|
+
kind: string;
|
|
19
|
+
contents: Array<{
|
|
20
|
+
kind: string;
|
|
21
|
+
type: string | StandardBlockType;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type Workspace = {
|
|
26
|
+
scrollbars: boolean;
|
|
27
|
+
trashcan: boolean;
|
|
28
|
+
};
|