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.
Files changed (51) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +91 -0
  3. package/lib/module/classes/blockly.js +24 -0
  4. package/lib/module/classes/blockly.js.map +1 -0
  5. package/lib/module/classes/blocklyViewConfig.js +39 -0
  6. package/lib/module/classes/blocklyViewConfig.js.map +1 -0
  7. package/lib/module/index.js +60 -0
  8. package/lib/module/index.js.map +1 -0
  9. package/lib/module/package.json +1 -0
  10. package/lib/module/parsers/parseToString.js +86 -0
  11. package/lib/module/parsers/parseToString.js.map +1 -0
  12. package/lib/module/parsers/stringToBlockly.js +87 -0
  13. package/lib/module/parsers/stringToBlockly.js.map +1 -0
  14. package/lib/module/types/blockly-types.d.js +4 -0
  15. package/lib/module/types/blockly-types.d.js.map +1 -0
  16. package/lib/module/types/blockly-view-types.d.js +4 -0
  17. package/lib/module/types/blockly-view-types.d.js.map +1 -0
  18. package/lib/module/utils/blocklyConstants.js +36 -0
  19. package/lib/module/utils/blocklyConstants.js.map +1 -0
  20. package/lib/module/utils/defaults.js +20 -0
  21. package/lib/module/utils/defaults.js.map +1 -0
  22. package/lib/module/utils/showWarnings.js +75 -0
  23. package/lib/module/utils/showWarnings.js.map +1 -0
  24. package/lib/typescript/package.json +1 -0
  25. package/lib/typescript/src/classes/blockly.d.ts +16 -0
  26. package/lib/typescript/src/classes/blockly.d.ts.map +1 -0
  27. package/lib/typescript/src/classes/blocklyViewConfig.d.ts +14 -0
  28. package/lib/typescript/src/classes/blocklyViewConfig.d.ts.map +1 -0
  29. package/lib/typescript/src/index.d.ts +16 -0
  30. package/lib/typescript/src/index.d.ts.map +1 -0
  31. package/lib/typescript/src/parsers/parseToString.d.ts +47 -0
  32. package/lib/typescript/src/parsers/parseToString.d.ts.map +1 -0
  33. package/lib/typescript/src/parsers/stringToBlockly.d.ts +14 -0
  34. package/lib/typescript/src/parsers/stringToBlockly.d.ts.map +1 -0
  35. package/lib/typescript/src/utils/blocklyConstants.d.ts +17 -0
  36. package/lib/typescript/src/utils/blocklyConstants.d.ts.map +1 -0
  37. package/lib/typescript/src/utils/defaults.d.ts +10 -0
  38. package/lib/typescript/src/utils/defaults.d.ts.map +1 -0
  39. package/lib/typescript/src/utils/showWarnings.d.ts +15 -0
  40. package/lib/typescript/src/utils/showWarnings.d.ts.map +1 -0
  41. package/package.json +155 -0
  42. package/src/classes/blockly.ts +25 -0
  43. package/src/classes/blocklyViewConfig.ts +36 -0
  44. package/src/index.tsx +65 -0
  45. package/src/parsers/parseToString.ts +92 -0
  46. package/src/parsers/stringToBlockly.ts +89 -0
  47. package/src/types/blockly-types.d.ts +28 -0
  48. package/src/types/blockly-view-types.d.ts +89 -0
  49. package/src/utils/blocklyConstants.ts +92 -0
  50. package/src/utils/defaults.ts +19 -0
  51. 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
+ };