@world-engines/blocks-editor 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 (76) hide show
  1. package/LICENSE +46 -0
  2. package/README.md +40 -0
  3. package/dist/adapters/trigger.d.ts +72 -0
  4. package/dist/adapters/trigger.js +206 -0
  5. package/dist/blockly-config.d.ts +3 -0
  6. package/dist/blockly-config.js +7 -0
  7. package/dist/blocks/ctx.d.ts +67 -0
  8. package/dist/blocks/ctx.js +96 -0
  9. package/dist/blocks/registry-taxonomy.d.ts +12 -0
  10. package/dist/blocks/registry-taxonomy.js +79 -0
  11. package/dist/blocks/registry.d.ts +39 -0
  12. package/dist/blocks/registry.js +1000 -0
  13. package/dist/blocks/time-fields.d.ts +16 -0
  14. package/dist/blocks/time-fields.js +45 -0
  15. package/dist/blocks/toolbox.d.ts +53 -0
  16. package/dist/blocks/toolbox.js +195 -0
  17. package/dist/fields/AttrPickerField.d.ts +13 -0
  18. package/dist/fields/AttrPickerField.js +48 -0
  19. package/dist/fields/EdgePickerField.d.ts +10 -0
  20. package/dist/fields/EdgePickerField.js +36 -0
  21. package/dist/fields/EntityPickerField.d.ts +10 -0
  22. package/dist/fields/EntityPickerField.js +36 -0
  23. package/dist/fields/StatePickerField.d.ts +13 -0
  24. package/dist/fields/StatePickerField.js +47 -0
  25. package/dist/fields/TimePickerField.d.ts +10 -0
  26. package/dist/fields/TimePickerField.js +81 -0
  27. package/dist/fields/picker-events.d.ts +21 -0
  28. package/dist/fields/picker-events.js +28 -0
  29. package/dist/fields/register.d.ts +6 -0
  30. package/dist/fields/register.js +22 -0
  31. package/dist/i18n/messages-zh.d.ts +6 -0
  32. package/dist/i18n/messages-zh.js +34 -0
  33. package/dist/index.d.ts +21 -0
  34. package/dist/index.js +11 -0
  35. package/dist/migration/index.d.ts +1 -0
  36. package/dist/migration/index.js +1 -0
  37. package/dist/migration/types.d.ts +91 -0
  38. package/dist/migration/types.js +1 -0
  39. package/dist/react/PickerHost.d.ts +6 -0
  40. package/dist/react/PickerHost.js +110 -0
  41. package/dist/sdk-to-block/index.d.ts +4 -0
  42. package/dist/sdk-to-block/index.js +4 -0
  43. package/dist/sdk-to-block/parser.d.ts +2 -0
  44. package/dist/sdk-to-block/parser.js +101 -0
  45. package/dist/sdk-to-block/register.d.ts +3 -0
  46. package/dist/sdk-to-block/register.js +27 -0
  47. package/dist/sdk-to-block/signature.d.ts +31 -0
  48. package/dist/sdk-to-block/signature.js +12 -0
  49. package/dist/sdk-to-block/to-block-def.d.ts +25 -0
  50. package/dist/sdk-to-block/to-block-def.js +71 -0
  51. package/dist/themes/index.d.ts +4 -0
  52. package/dist/themes/index.js +12 -0
  53. package/dist/themes/liquid-glass-dark.d.ts +57 -0
  54. package/dist/themes/liquid-glass-dark.js +187 -0
  55. package/dist/themes/liquid-glass.css +195 -0
  56. package/dist/view-to-block/index.d.ts +10 -0
  57. package/dist/view-to-block/index.js +67 -0
  58. package/dist/workspace.d.ts +33 -0
  59. package/dist/workspace.js +306 -0
  60. package/package.json +65 -0
  61. package/public/blockly-media/1x1.gif +0 -0
  62. package/public/blockly-media/click.mp3 +0 -0
  63. package/public/blockly-media/delete-icon.svg +1 -0
  64. package/public/blockly-media/delete.mp3 +0 -0
  65. package/public/blockly-media/disconnect.mp3 +0 -0
  66. package/public/blockly-media/drop.mp3 +0 -0
  67. package/public/blockly-media/dropdown-arrow.svg +1 -0
  68. package/public/blockly-media/foldout-icon.svg +1 -0
  69. package/public/blockly-media/handclosed.cur +0 -0
  70. package/public/blockly-media/handdelete.cur +0 -0
  71. package/public/blockly-media/handopen.cur +0 -0
  72. package/public/blockly-media/pilcrow.png +0 -0
  73. package/public/blockly-media/quote0.png +0 -0
  74. package/public/blockly-media/quote1.png +0 -0
  75. package/public/blockly-media/resize-handle.svg +3 -0
  76. package/public/blockly-media/sprites.svg +74 -0
@@ -0,0 +1,57 @@
1
+ import { Theme } from "blockly";
2
+ export declare const BLOCK_CATEGORY_PALETTE: {
3
+ readonly events: {
4
+ readonly primary: "#16c784";
5
+ readonly secondary: "#45d5a0";
6
+ readonly tertiary: "#109463";
7
+ };
8
+ readonly control: {
9
+ readonly primary: "#ff9f43";
10
+ readonly secondary: "#ffb76e";
11
+ readonly tertiary: "#c97831";
12
+ };
13
+ readonly sensing: {
14
+ readonly primary: "#20c4d9";
15
+ readonly secondary: "#55d2e1";
16
+ readonly tertiary: "#1894a4";
17
+ };
18
+ readonly operators: {
19
+ readonly primary: "#a970ff";
20
+ readonly secondary: "#bd91ff";
21
+ readonly tertiary: "#7d54bf";
22
+ };
23
+ readonly variables: {
24
+ readonly primary: "#f4c542";
25
+ readonly secondary: "#f7d36e";
26
+ readonly tertiary: "#b99431";
27
+ };
28
+ readonly sdkInterfaces: {
29
+ readonly primary: "#ff6680";
30
+ readonly secondary: "#ff8da0";
31
+ readonly tertiary: "#bf4d60";
32
+ };
33
+ readonly viewInterfaces: {
34
+ readonly primary: "#4c8dff";
35
+ readonly secondary: "#76a8ff";
36
+ readonly tertiary: "#396abf";
37
+ };
38
+ };
39
+ export declare const BLOCK_STYLE_KEYS: {
40
+ readonly boolean: "boolean_blocks";
41
+ readonly dataEvent: "data_event_blocks";
42
+ readonly dataAttr: "data_attr_blocks";
43
+ readonly time: "time_blocks";
44
+ readonly container: "container_blocks";
45
+ readonly control: "control_blocks";
46
+ readonly sensing: "sensing_blocks";
47
+ readonly operators: "operators_blocks";
48
+ readonly variables: "variables_blocks";
49
+ readonly myBlocks: "my_blocks_blocks";
50
+ readonly scenarioHat: "scenario_hat_blocks";
51
+ };
52
+ export type BlockStyleKey = (typeof BLOCK_STYLE_KEYS)[keyof typeof BLOCK_STYLE_KEYS];
53
+ export declare const GRID_COLOUR: "rgba(0, 200, 83, 0.14)";
54
+ export declare const liquidGlassDarkTheme: Theme;
55
+ export declare const LIQUID_GLASS_DARK_THEME_NAME: "liquid-glass-dark";
56
+ export declare const LIQUID_GLASS_BLOCK_STYLE_KEYS: readonly ["boolean_blocks", "data_event_blocks", "data_attr_blocks", "time_blocks", "container_blocks", "control_blocks", "sensing_blocks", "operators_blocks", "variables_blocks", "my_blocks_blocks", "scenario_hat_blocks"];
57
+ export type LiquidGlassBlockStyleKey = (typeof LIQUID_GLASS_BLOCK_STYLE_KEYS)[number];
@@ -0,0 +1,187 @@
1
+ import { Theme, Themes } from "blockly";
2
+ export const BLOCK_CATEGORY_PALETTE = {
3
+ events: { primary: "#16c784", secondary: "#45d5a0", tertiary: "#109463" },
4
+ control: { primary: "#ff9f43", secondary: "#ffb76e", tertiary: "#c97831" },
5
+ sensing: { primary: "#20c4d9", secondary: "#55d2e1", tertiary: "#1894a4" },
6
+ operators: { primary: "#a970ff", secondary: "#bd91ff", tertiary: "#7d54bf" },
7
+ variables: { primary: "#f4c542", secondary: "#f7d36e", tertiary: "#b99431" },
8
+ sdkInterfaces: { primary: "#ff6680", secondary: "#ff8da0", tertiary: "#bf4d60" },
9
+ viewInterfaces: { primary: "#4c8dff", secondary: "#76a8ff", tertiary: "#396abf" }
10
+ };
11
+ const COLOUR = {
12
+ booleanPrimary: "#00b8d4",
13
+ booleanSecondary: "#33c8de",
14
+ booleanTertiary: "#008fa3",
15
+ dataEventPrimary: "#00c853",
16
+ dataEventSecondary: "#33d475",
17
+ dataEventTertiary: "#009c40",
18
+ dataAttrPrimary: "#0bd48c",
19
+ dataAttrSecondary: "#3ddba4",
20
+ dataAttrTertiary: "#08a56d",
21
+ timePrimary: "#00e676",
22
+ timeSecondary: "#33eb91",
23
+ timeTertiary: "#00b25c",
24
+ containerPrimary: "#00a86b",
25
+ containerSecondary: "#33bd8a",
26
+ containerTertiary: "#008551",
27
+ controlPrimary: BLOCK_CATEGORY_PALETTE.control.primary,
28
+ controlSecondary: BLOCK_CATEGORY_PALETTE.control.secondary,
29
+ controlTertiary: BLOCK_CATEGORY_PALETTE.control.tertiary,
30
+ sensingPrimary: BLOCK_CATEGORY_PALETTE.sensing.primary,
31
+ sensingSecondary: BLOCK_CATEGORY_PALETTE.sensing.secondary,
32
+ sensingTertiary: BLOCK_CATEGORY_PALETTE.sensing.tertiary,
33
+ operatorsPrimary: BLOCK_CATEGORY_PALETTE.operators.primary,
34
+ operatorsSecondary: BLOCK_CATEGORY_PALETTE.operators.secondary,
35
+ operatorsTertiary: BLOCK_CATEGORY_PALETTE.operators.tertiary,
36
+ variablesPrimary: BLOCK_CATEGORY_PALETTE.variables.primary,
37
+ variablesSecondary: BLOCK_CATEGORY_PALETTE.variables.secondary,
38
+ variablesTertiary: BLOCK_CATEGORY_PALETTE.variables.tertiary,
39
+ myBlocksPrimary: "#00a8ff",
40
+ myBlocksSecondary: "#33baff",
41
+ myBlocksTertiary: "#0084cc",
42
+ scenarioHatPrimary: BLOCK_CATEGORY_PALETTE.events.primary,
43
+ scenarioHatSecondary: BLOCK_CATEGORY_PALETTE.events.secondary,
44
+ scenarioHatTertiary: BLOCK_CATEGORY_PALETTE.events.tertiary,
45
+ categoryControl: BLOCK_CATEGORY_PALETTE.control.primary,
46
+ categoryOperators: BLOCK_CATEGORY_PALETTE.operators.primary,
47
+ categoryVariables: BLOCK_CATEGORY_PALETTE.variables.primary,
48
+ categoryMotions: "#00a8ff",
49
+ categoryEvents: BLOCK_CATEGORY_PALETTE.events.primary,
50
+ categorySensing: BLOCK_CATEGORY_PALETTE.sensing.primary,
51
+ categoryMyBlocks: "#00a8ff"
52
+ };
53
+ const HAT = "";
54
+ const HAT_CAP = "cap";
55
+ export const BLOCK_STYLE_KEYS = {
56
+ boolean: "boolean_blocks",
57
+ dataEvent: "data_event_blocks",
58
+ dataAttr: "data_attr_blocks",
59
+ time: "time_blocks",
60
+ container: "container_blocks",
61
+ control: "control_blocks",
62
+ sensing: "sensing_blocks",
63
+ operators: "operators_blocks",
64
+ variables: "variables_blocks",
65
+ myBlocks: "my_blocks_blocks",
66
+ scenarioHat: "scenario_hat_blocks"
67
+ };
68
+ export const GRID_COLOUR = "rgba(0, 200, 83, 0.14)";
69
+ export const liquidGlassDarkTheme = Theme.defineTheme("liquid-glass-dark", {
70
+ name: "liquid-glass-dark",
71
+ base: Themes.Zelos,
72
+ blockStyles: {
73
+ [BLOCK_STYLE_KEYS.boolean]: {
74
+ colourPrimary: COLOUR.booleanPrimary,
75
+ colourSecondary: COLOUR.booleanSecondary,
76
+ colourTertiary: COLOUR.booleanTertiary,
77
+ hat: HAT
78
+ },
79
+ [BLOCK_STYLE_KEYS.dataEvent]: {
80
+ colourPrimary: COLOUR.dataEventPrimary,
81
+ colourSecondary: COLOUR.dataEventSecondary,
82
+ colourTertiary: COLOUR.dataEventTertiary,
83
+ hat: HAT
84
+ },
85
+ [BLOCK_STYLE_KEYS.dataAttr]: {
86
+ colourPrimary: COLOUR.dataAttrPrimary,
87
+ colourSecondary: COLOUR.dataAttrSecondary,
88
+ colourTertiary: COLOUR.dataAttrTertiary,
89
+ hat: HAT
90
+ },
91
+ [BLOCK_STYLE_KEYS.time]: {
92
+ colourPrimary: COLOUR.timePrimary,
93
+ colourSecondary: COLOUR.timeSecondary,
94
+ colourTertiary: COLOUR.timeTertiary,
95
+ hat: HAT
96
+ },
97
+ [BLOCK_STYLE_KEYS.container]: {
98
+ colourPrimary: COLOUR.containerPrimary,
99
+ colourSecondary: COLOUR.containerSecondary,
100
+ colourTertiary: COLOUR.containerTertiary,
101
+ hat: HAT
102
+ },
103
+ [BLOCK_STYLE_KEYS.control]: {
104
+ colourPrimary: COLOUR.controlPrimary,
105
+ colourSecondary: COLOUR.controlSecondary,
106
+ colourTertiary: COLOUR.controlTertiary,
107
+ hat: HAT
108
+ },
109
+ [BLOCK_STYLE_KEYS.sensing]: {
110
+ colourPrimary: COLOUR.sensingPrimary,
111
+ colourSecondary: COLOUR.sensingSecondary,
112
+ colourTertiary: COLOUR.sensingTertiary,
113
+ hat: HAT
114
+ },
115
+ [BLOCK_STYLE_KEYS.operators]: {
116
+ colourPrimary: COLOUR.operatorsPrimary,
117
+ colourSecondary: COLOUR.operatorsSecondary,
118
+ colourTertiary: COLOUR.operatorsTertiary,
119
+ hat: HAT
120
+ },
121
+ [BLOCK_STYLE_KEYS.variables]: {
122
+ colourPrimary: COLOUR.variablesPrimary,
123
+ colourSecondary: COLOUR.variablesSecondary,
124
+ colourTertiary: COLOUR.variablesTertiary,
125
+ hat: HAT
126
+ },
127
+ [BLOCK_STYLE_KEYS.myBlocks]: {
128
+ colourPrimary: COLOUR.myBlocksPrimary,
129
+ colourSecondary: COLOUR.myBlocksSecondary,
130
+ colourTertiary: COLOUR.myBlocksTertiary,
131
+ hat: HAT
132
+ },
133
+ [BLOCK_STYLE_KEYS.scenarioHat]: {
134
+ colourPrimary: COLOUR.scenarioHatPrimary,
135
+ colourSecondary: COLOUR.scenarioHatSecondary,
136
+ colourTertiary: COLOUR.scenarioHatTertiary,
137
+ hat: HAT_CAP
138
+ }
139
+ },
140
+ categoryStyles: {
141
+ control_category: { colour: COLOUR.categoryControl },
142
+ operators_category: { colour: COLOUR.categoryOperators },
143
+ variables_category: { colour: COLOUR.categoryVariables },
144
+ motions_category: { colour: COLOUR.categoryMotions },
145
+ events_category: { colour: COLOUR.categoryEvents },
146
+ sensing_category: { colour: COLOUR.categorySensing },
147
+ my_blocks_category: { colour: COLOUR.categoryMyBlocks },
148
+ sdk_interfaces_category: { colour: BLOCK_CATEGORY_PALETTE.sdkInterfaces.primary },
149
+ view_interfaces_category: { colour: BLOCK_CATEGORY_PALETTE.viewInterfaces.primary }
150
+ },
151
+ componentStyles: {
152
+ workspaceBackgroundColour: "transparent",
153
+ toolboxBackgroundColour: "rgba(6, 14, 10, 0.62)",
154
+ toolboxForegroundColour: "rgba(220, 246, 230, 0.9)",
155
+ flyoutBackgroundColour: "rgba(8, 16, 12, 0.66)",
156
+ flyoutForegroundColour: "rgba(220, 246, 230, 0.9)",
157
+ flyoutOpacity: 1,
158
+ scrollbarColour: "rgba(0, 200, 83, 0.32)",
159
+ scrollbarOpacity: 0.8,
160
+ insertionMarkerColour: "#00e676",
161
+ insertionMarkerOpacity: 0.5,
162
+ markerColour: "#00c853",
163
+ cursorColour: "#00c853",
164
+ selectedGlowColour: "#00e676",
165
+ selectedGlowOpacity: 0.55
166
+ },
167
+ fontStyle: {
168
+ family: "'Inter', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', system-ui, sans-serif",
169
+ weight: "500",
170
+ size: 12
171
+ },
172
+ startHats: false
173
+ });
174
+ export const LIQUID_GLASS_DARK_THEME_NAME = "liquid-glass-dark";
175
+ export const LIQUID_GLASS_BLOCK_STYLE_KEYS = [
176
+ BLOCK_STYLE_KEYS.boolean,
177
+ BLOCK_STYLE_KEYS.dataEvent,
178
+ BLOCK_STYLE_KEYS.dataAttr,
179
+ BLOCK_STYLE_KEYS.time,
180
+ BLOCK_STYLE_KEYS.container,
181
+ BLOCK_STYLE_KEYS.control,
182
+ BLOCK_STYLE_KEYS.sensing,
183
+ BLOCK_STYLE_KEYS.operators,
184
+ BLOCK_STYLE_KEYS.variables,
185
+ BLOCK_STYLE_KEYS.myBlocks,
186
+ BLOCK_STYLE_KEYS.scenarioHat
187
+ ];
@@ -0,0 +1,195 @@
1
+ .blocks-editor__blockly-host {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 100%;
5
+ }
6
+
7
+ .blocks-editor {
8
+ position: relative;
9
+ width: 100%;
10
+ height: 100%;
11
+ border: 1px solid rgba(0, 200, 83, 0.24);
12
+ border-radius: 0.5rem;
13
+ background: linear-gradient(
14
+ 135deg,
15
+ rgba(4, 10, 8, 0.82) 0%,
16
+ rgba(8, 18, 14, 0.76) 100%
17
+ );
18
+ background-clip: padding-box;
19
+ box-shadow:
20
+ 0 1.25rem 2.5rem rgba(0, 0, 0, 0.55),
21
+ inset 0 1px 0 rgba(0, 230, 118, 0.08);
22
+ backdrop-filter: blur(8px) saturate(140%);
23
+ -webkit-backdrop-filter: blur(8px) saturate(140%);
24
+ overflow: hidden;
25
+ }
26
+
27
+ .blocks-editor--liquid-glass-dark .blocklyMainBackground {
28
+ fill: transparent;
29
+ stroke: none;
30
+ }
31
+
32
+ .blocks-editor--liquid-glass-dark .blocklyToolboxDiv {
33
+ border-inline-end: 1px solid rgba(0, 200, 83, 0.22);
34
+ background: linear-gradient(
35
+ 180deg,
36
+ rgba(4, 10, 8, 0.78) 0%,
37
+ rgba(4, 12, 8, 0.72) 100%
38
+ );
39
+ backdrop-filter: blur(10px) saturate(140%);
40
+ -webkit-backdrop-filter: blur(10px) saturate(140%);
41
+ }
42
+
43
+ .blocks-editor--liquid-glass-dark .blocklyFlyout {
44
+ background: rgba(8, 16, 12, 0.62);
45
+ backdrop-filter: blur(12px) saturate(140%);
46
+ -webkit-backdrop-filter: blur(12px) saturate(140%);
47
+ }
48
+
49
+ .blocks-editor--liquid-glass-dark .blocklyFlyoutBackground {
50
+ fill: rgba(8, 16, 12, 0.62);
51
+ fill-opacity: 1;
52
+ }
53
+
54
+ .blocks-editor--liquid-glass-dark .blocklyTreeRow {
55
+ border-radius: 0.5rem;
56
+ margin: 0.125rem 0.375rem;
57
+ min-height: 2.25rem;
58
+ padding-block: 0.5rem;
59
+ color: rgba(220, 246, 230, 0.86);
60
+ transition: background-color 160ms ease, color 160ms ease;
61
+ }
62
+
63
+ .blocks-editor--liquid-glass-dark .blocklyTreeRow:hover {
64
+ background: rgba(0, 230, 118, 0.14);
65
+ color: rgba(240, 255, 245, 0.96);
66
+ }
67
+
68
+ .blocks-editor--liquid-glass-dark .blocklyTreeSelected {
69
+ background: rgba(0, 200, 83, 0.22);
70
+ color: rgba(240, 255, 245, 0.98);
71
+ }
72
+
73
+ .blocks-editor--liquid-glass-dark .blocklyTreeLabel {
74
+ color: inherit;
75
+ font-weight: 500;
76
+ }
77
+
78
+ .blocks-editor--liquid-glass-dark .blocklyDraggable .blocklyPath {
79
+ filter: drop-shadow(0 0.5rem 1rem rgba(0, 0, 0, 0.45));
80
+ }
81
+
82
+ .blocks-editor--liquid-glass-dark .blocklyText {
83
+ fill: rgba(240, 255, 245, 0.96);
84
+ font-weight: 500;
85
+ }
86
+
87
+ .blocks-editor--liquid-glass-dark .blocklyEditableText > rect {
88
+ fill: rgba(4, 12, 8, 0.6);
89
+ stroke: rgba(0, 230, 118, 0.32);
90
+ }
91
+
92
+ .blocks-editor--liquid-glass-dark .blocklyHtmlInput {
93
+ color: rgba(240, 255, 245, 0.96);
94
+ background: rgba(4, 12, 8, 0.85);
95
+ border: 1px solid rgba(0, 230, 118, 0.36);
96
+ border-radius: 0.375rem;
97
+ caret-color: hsl(140, 100%, 55%);
98
+ }
99
+
100
+ .blocks-editor--liquid-glass-dark .blocklyHtmlInput::placeholder {
101
+ color: rgba(170, 200, 180, 0.55);
102
+ }
103
+
104
+ .blocks-editor--liquid-glass-dark .blocklyDropdownText {
105
+ fill: rgba(240, 255, 245, 0.96);
106
+ }
107
+
108
+ .blocks-editor--liquid-glass-dark .blocklyWidgetDiv .goog-menu,
109
+ .blocks-editor--liquid-glass-dark .blocklyDropDownDiv {
110
+ background: rgba(4, 12, 8, 0.94);
111
+ border: 1px solid rgba(0, 230, 118, 0.32);
112
+ border-radius: 0.5rem;
113
+ box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.6);
114
+ backdrop-filter: blur(12px) saturate(140%);
115
+ -webkit-backdrop-filter: blur(12px) saturate(140%);
116
+ color: rgba(220, 246, 230, 0.94);
117
+ }
118
+
119
+ .blocks-editor--liquid-glass-dark .blocklyDropDownContent {
120
+ color: inherit;
121
+ }
122
+
123
+ .blocks-editor--liquid-glass-dark .blocklyMenuItem {
124
+ color: rgba(220, 246, 230, 0.94);
125
+ border-radius: 0.375rem;
126
+ padding-inline: 0.625rem;
127
+ }
128
+
129
+ .blocks-editor--liquid-glass-dark .blocklyMenuItemHighlight,
130
+ .blocks-editor--liquid-glass-dark .blocklyMenuItem:hover {
131
+ background: rgba(0, 230, 118, 0.18);
132
+ color: rgba(240, 255, 245, 0.98);
133
+ }
134
+
135
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarHandle {
136
+ fill: rgba(0, 200, 83, 0.4);
137
+ }
138
+
139
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarVertical,
140
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarVertical .blocklyScrollbarHandle {
141
+ width: 3px !important;
142
+ }
143
+
144
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarHorizontal,
145
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarHorizontal .blocklyScrollbarHandle {
146
+ height: 3px !important;
147
+ }
148
+
149
+ .blocks-editor--liquid-glass-dark .blocklyTrash,
150
+ .blocks-editor--liquid-glass-dark .blocklyZoom {
151
+ display: none !important;
152
+ }
153
+
154
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarHandle:hover,
155
+ .blocks-editor--liquid-glass-dark .blocklyScrollbarHandle.blocklyScrollbarHovered {
156
+ fill: rgba(0, 230, 118, 0.6);
157
+ }
158
+
159
+ .blocks-editor--liquid-glass-dark ::-webkit-scrollbar {
160
+ width: 3px;
161
+ height: 3px;
162
+ }
163
+
164
+ .blocks-editor--liquid-glass-dark ::-webkit-scrollbar-track {
165
+ background: transparent;
166
+ }
167
+
168
+ .blocks-editor--liquid-glass-dark ::-webkit-scrollbar-thumb {
169
+ background: rgba(0, 200, 83, 0.36);
170
+ border-radius: 999px;
171
+ }
172
+
173
+ .blocks-editor--liquid-glass-dark ::-webkit-scrollbar-thumb:hover {
174
+ background: rgba(0, 230, 118, 0.56);
175
+ }
176
+
177
+ .blocks-editor--liquid-glass-dark .blocklyTrash > image,
178
+ .blocks-editor--liquid-glass-dark .blocklyTrash > rect {
179
+ opacity: 0.78;
180
+ }
181
+
182
+ .blocks-editor--liquid-glass-dark .blocklyZoom > image,
183
+ .blocks-editor--liquid-glass-dark .blocklyZoom > rect {
184
+ opacity: 0.78;
185
+ }
186
+
187
+ .blocks-editor--liquid-glass-dark .blocklyContextMenu {
188
+ background: rgba(4, 12, 8, 0.94);
189
+ border: 1px solid rgba(0, 230, 118, 0.32);
190
+ border-radius: 0.5rem;
191
+ box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.6);
192
+ backdrop-filter: blur(10px);
193
+ -webkit-backdrop-filter: blur(10px);
194
+ color: rgba(220, 246, 230, 0.94);
195
+ }
@@ -0,0 +1,10 @@
1
+ import type { ViewExposureFunction } from "@world-engines/view-exposure";
2
+ export interface ViewBlockCatalog {
3
+ readonly manifestHash: string;
4
+ readonly manifestRevision: number;
5
+ readonly functions: ReadonlyArray<ViewExposureFunction>;
6
+ }
7
+ export declare const viewBlockType: (fn: ViewExposureFunction, hash: string) => string;
8
+ /** 只注册当前 manifest revision;旧 block 不创建 tombstone。 */
9
+ export declare const registerViewBlocks: (catalog: ViewBlockCatalog) => ReadonlyArray<string>;
10
+ export declare const isViewActionBlockType: (type: string) => boolean;
@@ -0,0 +1,67 @@
1
+ import * as Blockly from "blockly";
2
+ const VIEW_BLOCK_PREFIX = "view_action_";
3
+ const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;
4
+ const MANIFEST_HASH = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,127}$/;
5
+ const registered = new Set();
6
+ const manifestFingerprint = (hash) => hash.replace(/[^A-Za-z0-9]/g, "").slice(-16);
7
+ export const viewBlockType = (fn, hash) => `${VIEW_BLOCK_PREFIX}${fn.name}_${manifestFingerprint(hash)}`;
8
+ const blocklyCheckForSchema = (schema) => {
9
+ switch (schema.type) {
10
+ case "string": return "String";
11
+ case "number":
12
+ case "integer": return "Number";
13
+ case "boolean": return "Boolean";
14
+ case "array":
15
+ case "object": return undefined;
16
+ }
17
+ };
18
+ const authorizedTriggerFunctions = (catalog) => {
19
+ if (!MANIFEST_HASH.test(catalog.manifestHash)
20
+ || manifestFingerprint(catalog.manifestHash).length === 0) {
21
+ throw new Error("view_action_catalog_manifest_hash_invalid");
22
+ }
23
+ if (!Number.isSafeInteger(catalog.manifestRevision) || catalog.manifestRevision < 0) {
24
+ throw new Error("view_action_catalog_manifest_revision_invalid");
25
+ }
26
+ const functions = catalog.functions.filter((fn) => fn.target === "trigger" || fn.target === "both");
27
+ const ids = new Set();
28
+ const names = new Set();
29
+ const blockTypes = new Set();
30
+ for (const fn of functions) {
31
+ if (!IDENTIFIER.test(fn.name))
32
+ throw new Error(`view_action_name_invalid:${fn.name}`);
33
+ if (ids.has(fn.id))
34
+ throw new Error(`view_action_exposure_id_duplicate:${fn.id}`);
35
+ if (names.has(fn.name))
36
+ throw new Error(`view_action_name_duplicate:${fn.name}`);
37
+ const type = viewBlockType(fn, catalog.manifestHash);
38
+ if (blockTypes.has(type))
39
+ throw new Error(`view_action_block_type_collision:${type}`);
40
+ ids.add(fn.id);
41
+ names.add(fn.name);
42
+ blockTypes.add(type);
43
+ }
44
+ return functions;
45
+ };
46
+ /** 只注册当前 manifest revision;旧 block 不创建 tombstone。 */
47
+ export const registerViewBlocks = (catalog) => authorizedTriggerFunctions(catalog).map((fn) => {
48
+ const type = viewBlockType(fn, catalog.manifestHash);
49
+ if (!registered.has(type)) {
50
+ const args0 = Object.entries(fn.parameters.properties).map(([name, schema]) => {
51
+ const check = blocklyCheckForSchema(schema);
52
+ return { type: "input_value", name, ...(check === undefined ? {} : { check }) };
53
+ });
54
+ Blockly.common.defineBlocksWithJsonArray([{
55
+ type,
56
+ message0: `${fn.label}${args0.map((_, index) => ` %${index + 1}`).join("")}`,
57
+ args0,
58
+ previousStatement: null,
59
+ nextStatement: null,
60
+ colour: "#4c8dff",
61
+ tooltip: fn.description
62
+ }]);
63
+ registered.add(type);
64
+ }
65
+ return type;
66
+ });
67
+ export const isViewActionBlockType = (type) => type.startsWith(VIEW_BLOCK_PREFIX);
@@ -0,0 +1,33 @@
1
+ import * as Blockly from "blockly";
2
+ import { type CtxEdge, type CtxEntity, type CtxEvent, type CtxVariable } from "./blocks/ctx.js";
3
+ import type { WorldTimeBounds } from "./blocks/time-fields.js";
4
+ import { CATEGORY_IDS, type CategoryId } from "./blocks/toolbox.js";
5
+ import type { SdkCatalog } from "./sdk-to-block/signature.js";
6
+ import { type ViewBlockCatalog } from "./view-to-block/index.js";
7
+ export type BlocksWorkspaceSchema = "trigger-definition" | "trigger" | "tmw-condition-v3";
8
+ export interface BlocksWorkspaceTriggerCtx {
9
+ readonly event_list: ReadonlyArray<CtxEvent>;
10
+ readonly entity_list: ReadonlyArray<CtxEntity>;
11
+ readonly edge_list?: ReadonlyArray<CtxEdge>;
12
+ readonly variable_list?: ReadonlyArray<CtxVariable>;
13
+ readonly sdk_catalog?: SdkCatalog;
14
+ readonly worldTime?: WorldTimeBounds;
15
+ readonly view_catalog?: ViewBlockCatalog;
16
+ }
17
+ export interface BlocksWorkspaceHandle {
18
+ selectCategory(id: CategoryId): void;
19
+ getWorkspace(): Blockly.WorkspaceSvg | null;
20
+ }
21
+ export interface BlocksWorkspaceProps {
22
+ readonly schema: BlocksWorkspaceSchema;
23
+ readonly ownerKey: string;
24
+ /** Blockly serialization.workspaces.save 后 JSON.stringify 的产物 空 workspace 传 "" 或 `{"blocks":{"blocks":[]}}` */
25
+ readonly workspaceJson: string;
26
+ readonly ctx: BlocksWorkspaceTriggerCtx;
27
+ readonly onWorkspaceJsonChange: (nextJson: string) => void;
28
+ readonly className?: string;
29
+ readonly mediaBaseUrl?: string;
30
+ }
31
+ export declare const BlocksWorkspace: import("react").ForwardRefExoticComponent<BlocksWorkspaceProps & import("react").RefAttributes<BlocksWorkspaceHandle>>;
32
+ export { CATEGORY_IDS };
33
+ export type { CategoryId };