scratch-blocks 2.0.0-spork.2 → 2.0.0-spork.3

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 (81) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/main.js +1 -1
  3. package/package.json +1 -1
  4. package/src/{block_reporting.js → block_reporting.ts} +7 -5
  5. package/src/blocks/{colour.js → colour.ts} +6 -6
  6. package/src/blocks/{control.js → control.ts} +21 -54
  7. package/src/blocks/{data.js → data.ts} +134 -142
  8. package/src/blocks/{event.js → event.ts} +12 -33
  9. package/src/blocks/{looks.js → looks.ts} +24 -73
  10. package/src/blocks/{math.js → math.ts} +6 -11
  11. package/src/blocks/{matrix.js → matrix.ts} +2 -3
  12. package/src/blocks/{motion.js → motion.ts} +23 -70
  13. package/src/blocks/{note.js → note.ts} +2 -3
  14. package/src/blocks/{operators.js → operators.ts} +18 -55
  15. package/src/blocks/{procedures.js → procedures.ts} +418 -269
  16. package/src/blocks/{sensing.js → sensing.ts} +21 -61
  17. package/src/blocks/{sound.js → sound.ts} +9 -28
  18. package/src/blocks/{text.js → text.ts} +1 -2
  19. package/src/blocks/{vertical_extensions.js → vertical_extensions.ts} +63 -100
  20. package/src/checkable_continuous_flyout.js +2 -2
  21. package/src/{checkbox_bubble.js → checkbox_bubble.ts} +36 -53
  22. package/src/{colours.js → colours.ts} +11 -4
  23. package/src/{constants.js → constants.ts} +13 -0
  24. package/src/{context_menu_items.js → context_menu_items.ts} +18 -12
  25. package/src/{data_category.js → data_category.ts} +216 -150
  26. package/src/events/{events_block_comment_base.js → events_block_comment_base.ts} +23 -4
  27. package/src/events/{events_block_comment_change.js → events_block_comment_change.ts} +29 -5
  28. package/src/events/{events_block_comment_collapse.js → events_block_comment_collapse.ts} +24 -6
  29. package/src/events/{events_block_comment_create.js → events_block_comment_create.ts} +36 -10
  30. package/src/events/{events_block_comment_delete.js → events_block_comment_delete.ts} +6 -2
  31. package/src/events/{events_block_comment_move.js → events_block_comment_move.ts} +36 -6
  32. package/src/events/events_block_comment_resize.ts +88 -0
  33. package/src/events/events_block_drag_end.ts +49 -0
  34. package/src/events/events_block_drag_outside.ts +44 -0
  35. package/src/events/{events_scratch_variable_create.js → events_scratch_variable_create.ts} +28 -15
  36. package/src/fields/{field_colour_slider.js → field_colour_slider.ts} +117 -106
  37. package/src/fields/{field_matrix.js → field_matrix.ts} +189 -215
  38. package/src/fields/{field_note.js → field_note.ts} +227 -286
  39. package/src/fields/{field_textinput_removable.js → field_textinput_removable.ts} +17 -20
  40. package/src/fields/{field_variable_getter.js → field_variable_getter.ts} +28 -17
  41. package/src/fields/{field_vertical_separator.js → field_vertical_separator.ts} +14 -30
  42. package/src/fields/{field_angle.js → scratch_field_angle.ts} +124 -80
  43. package/src/fields/{field_dropdown.js → scratch_field_dropdown.ts} +9 -7
  44. package/src/fields/{field_number.js → scratch_field_number.ts} +60 -55
  45. package/src/fields/{field_variable.js → scratch_field_variable.ts} +46 -27
  46. package/src/{flyout_checkbox_icon.js → flyout_checkbox_icon.ts} +15 -19
  47. package/src/{glows.js → glows.ts} +29 -18
  48. package/src/index.ts +59 -60
  49. package/src/procedures.ts +462 -0
  50. package/src/{recyclable_block_flyout_inflater.js → recyclable_block_flyout_inflater.ts} +35 -35
  51. package/src/renderer/{bowler_hat.js → bowler_hat.ts} +1 -1
  52. package/src/renderer/{constants.js → constants.ts} +26 -12
  53. package/src/renderer/{drawer.js → drawer.ts} +8 -3
  54. package/src/renderer/{path_object.js → path_object.ts} +2 -2
  55. package/src/renderer/{render_info.js → render_info.ts} +19 -7
  56. package/src/renderer/renderer.ts +76 -0
  57. package/src/{scratch_block_paster.js → scratch_block_paster.ts} +9 -7
  58. package/src/scratch_blocks_utils.ts +39 -0
  59. package/src/{scratch_comment_icon.js → scratch_comment_icon.ts} +43 -26
  60. package/src/scratch_connection_checker.ts +44 -0
  61. package/src/{scratch_continuous_category.js → scratch_continuous_category.ts} +20 -13
  62. package/src/{scratch_continuous_toolbox.js → scratch_continuous_toolbox.ts} +20 -18
  63. package/src/{scratch_dragger.js → scratch_dragger.ts} +97 -28
  64. package/src/{scratch_variable_map.js → scratch_variable_map.ts} +4 -1
  65. package/src/scratch_variable_model.ts +30 -0
  66. package/src/{shadows.js → shadows.ts} +8 -4
  67. package/src/{status_indicator_label.js → status_indicator_label.ts} +24 -36
  68. package/src/{status_indicator_label_flyout_inflater.js → status_indicator_label_flyout_inflater.ts} +9 -7
  69. package/src/{variables.js → variables.ts} +153 -123
  70. package/tsconfig.json +5 -0
  71. package/src/categories.js +0 -15
  72. package/src/events/events_block_comment_resize.js +0 -52
  73. package/src/events/events_block_drag_end.js +0 -33
  74. package/src/events/events_block_drag_outside.js +0 -30
  75. package/src/procedures.js +0 -425
  76. package/src/renderer/renderer.js +0 -74
  77. package/src/scratch_blocks_utils.js +0 -148
  78. package/src/scratch_connection_checker.js +0 -29
  79. package/src/scratch_variable_model.js +0 -24
  80. /package/src/{css.js → css.ts} +0 -0
  81. /package/{continuous-toolbox.d.ts → types/continuous-toolbox.d.ts} +0 -0
@@ -23,38 +23,78 @@
23
23
  */
24
24
 
25
25
  import * as Blockly from "blockly/core";
26
- import { FieldTextInputRemovable } from "../fields/field_textinput_removable.js";
26
+ import { FieldTextInputRemovable } from "../fields/field_textinput_removable";
27
+ import type { ScratchDragger } from "../scratch_dragger";
27
28
 
28
- class DuplicateOnDragDraggable {
29
- constructor(block) {
30
- this.block = block;
31
- }
29
+ /**
30
+ * An object mapping argument IDs to blocks and shadow DOMs.
31
+ */
32
+ type ConnectionMap = {
33
+ [key: string]: {
34
+ shadow: Element;
35
+ block: Blockly.BlockSvg;
36
+ };
37
+ };
38
+
39
+ /**
40
+ * Possible types for procedure arguments.
41
+ */
42
+ enum ArgumentType {
43
+ STRING = "s",
44
+ NUMBER = "n",
45
+ BOOLEAN = "b",
46
+ }
32
47
 
33
- isMovable() {
48
+ /**
49
+ * Class representing a draggable block that copies itself on drag.
50
+ */
51
+ class DuplicateOnDragDraggable implements Blockly.IDraggable {
52
+ /**
53
+ * The newly-created duplicate block.
54
+ */
55
+ private copy?: Blockly.BlockSvg;
56
+ constructor(private block: Blockly.BlockSvg) {}
57
+
58
+ /**
59
+ * Returns whether or not this draggable is movable. */
60
+ isMovable(): boolean {
34
61
  return true;
35
62
  }
36
63
 
37
- startDrag(e) {
64
+ /**
65
+ * Handles the start of a drag.
66
+ *
67
+ * @param e The event that triggered the drag.
68
+ */
69
+ startDrag(e: PointerEvent) {
38
70
  const data = this.block.toCopyData();
39
- this.copy = Blockly.clipboard.paste(data, this.block.workspace);
71
+ this.copy = Blockly.clipboard.paste(
72
+ data,
73
+ this.block.workspace
74
+ ) as Blockly.BlockSvg;
40
75
  this.copy.startDrag(e);
41
76
  }
42
77
 
43
- drag(e) {
44
- this.block.workspace
45
- .getGesture(e)
46
- .getCurrentDragger()
47
- .setDraggable(this.copy);
48
- this.copy.drag(e);
78
+ drag(newLoc: Blockly.utils.Coordinate, e?: PointerEvent) {
79
+ (
80
+ this.block.workspace.getGesture(e).getCurrentDragger() as ScratchDragger
81
+ ).setDraggable(this.copy);
82
+ this.copy.drag(newLoc, e);
49
83
  }
50
84
 
51
- endDrag(e) {
85
+ endDrag(e: PointerEvent) {
52
86
  this.copy?.endDrag(e);
53
87
  }
54
88
 
55
- revertDrag(e) {
89
+ revertDrag() {
56
90
  this.copy?.dispose();
57
91
  }
92
+
93
+ getRelativeToSurfaceXY() {
94
+ return this.copy
95
+ ? this.copy.getRelativeToSurfaceXY()
96
+ : this.block.getRelativeToSurfaceXY();
97
+ }
58
98
  }
59
99
 
60
100
  // Serialization and deserialization.
@@ -62,11 +102,11 @@ class DuplicateOnDragDraggable {
62
102
  /**
63
103
  * Create XML to represent the (non-editable) name and arguments of a procedure
64
104
  * call block.
65
- * @return {!Element} XML storage element.
66
- * @this Blockly.Block
105
+ *
106
+ * @returns XML storage element.
67
107
  */
68
- function callerMutationToDom() {
69
- var container = document.createElement("mutation");
108
+ function callerMutationToDom(this: ProcedureCallBlock): Element {
109
+ const container = document.createElement("mutation");
70
110
  container.setAttribute("proccode", this.procCode_);
71
111
  container.setAttribute("argumentids", JSON.stringify(this.argumentIds_));
72
112
  container.setAttribute("warp", JSON.stringify(this.warp_));
@@ -76,10 +116,10 @@ function callerMutationToDom() {
76
116
  /**
77
117
  * Parse XML to restore the (non-editable) name and arguments of a procedure
78
118
  * call block.
79
- * @param {!Element} xmlElement XML storage element.
80
- * @this Blockly.Block
119
+ *
120
+ * @param xmlElement XML storage element.
81
121
  */
82
- function callerDomToMutation(xmlElement) {
122
+ function callerDomToMutation(this: ProcedureCallBlock, xmlElement: Element) {
83
123
  this.procCode_ = xmlElement.getAttribute("proccode");
84
124
  this.generateShadows_ = JSON.parse(
85
125
  xmlElement.getAttribute("generateshadows")
@@ -92,16 +132,19 @@ function callerDomToMutation(xmlElement) {
92
132
  /**
93
133
  * Create XML to represent the (non-editable) name and arguments of a
94
134
  * procedures_prototype block or a procedures_declaration block.
95
- * @param {boolean=} opt_generateShadows Whether to include the generateshadows
96
- * flag in the generated XML. False if not provided.
97
- * @return {!Element} XML storage element.
98
- * @this Blockly.Block
135
+ *
136
+ * @param opt_generateShadows Whether to include the generateshadows flag in the
137
+ * generated XML. False if not provided.
138
+ * @returns XML storage element.
99
139
  */
100
- function definitionMutationToDom(opt_generateShadows) {
101
- var container = document.createElement("mutation");
140
+ function definitionMutationToDom(
141
+ this: ProcedurePrototypeBlock | ProcedureDeclarationBlock,
142
+ opt_generateShadows?: boolean
143
+ ): Element {
144
+ const container = document.createElement("mutation");
102
145
 
103
146
  if (opt_generateShadows) {
104
- container.setAttribute("generateshadows", true);
147
+ container.setAttribute("generateshadows", "true");
105
148
  }
106
149
  container.setAttribute("proccode", this.procCode_);
107
150
  container.setAttribute("argumentids", JSON.stringify(this.argumentIds_));
@@ -117,15 +160,18 @@ function definitionMutationToDom(opt_generateShadows) {
117
160
  /**
118
161
  * Parse XML to restore the (non-editable) name and arguments of a
119
162
  * procedures_prototype block or a procedures_declaration block.
120
- * @param {!Element} xmlElement XML storage element.
121
- * @this Blockly.Block
163
+ *
164
+ * @param xmlElement XML storage element.
122
165
  */
123
- function definitionDomToMutation(xmlElement) {
166
+ function definitionDomToMutation(
167
+ this: ProcedurePrototypeBlock | ProcedureDeclarationBlock,
168
+ xmlElement: Element
169
+ ) {
124
170
  this.procCode_ = xmlElement.getAttribute("proccode");
125
171
  this.warp_ = JSON.parse(xmlElement.getAttribute("warp"));
126
172
 
127
- var prevArgIds = this.argumentIds_;
128
- var prevDisplayNames = this.displayNames_;
173
+ const prevArgIds = this.argumentIds_;
174
+ const prevDisplayNames = this.displayNames_;
129
175
 
130
176
  this.argumentIds_ = JSON.parse(xmlElement.getAttribute("argumentids"));
131
177
  this.displayNames_ = JSON.parse(xmlElement.getAttribute("argumentnames"));
@@ -133,7 +179,7 @@ function definitionDomToMutation(xmlElement) {
133
179
  xmlElement.getAttribute("argumentdefaults")
134
180
  );
135
181
  this.updateDisplay_();
136
- if (this.updateArgumentReporterNames_) {
182
+ if ("updateArgumentReporterNames_" in this) {
137
183
  this.updateArgumentReporterNames_(prevArgIds, prevDisplayNames);
138
184
  }
139
185
  }
@@ -145,21 +191,19 @@ function definitionDomToMutation(xmlElement) {
145
191
  /**
146
192
  * Returns the name of the procedure this block calls, or the empty string if
147
193
  * it has not yet been set.
148
- * @return {string} Procedure name.
149
- * @this Blockly.Block
194
+ *
195
+ * @returns Procedure name.
150
196
  */
151
- function getProcCode() {
197
+ function getProcCode(this: ProcedureBlock): string {
152
198
  return this.procCode_;
153
199
  }
154
200
 
155
201
  /**
156
202
  * Update the block's structure and appearance to match the internally stored
157
203
  * mutation.
158
- * @private
159
- * @this Blockly.Block
160
204
  */
161
- function updateDisplay_() {
162
- var connectionMap = this.disconnectOldBlocks_();
205
+ function updateDisplay_(this: ProcedureBlock) {
206
+ const connectionMap = this.disconnectOldBlocks_();
163
207
  this.removeAllInputs_();
164
208
  this.createAllInputs_(connectionMap);
165
209
  this.deleteShadows_(connectionMap);
@@ -170,18 +214,16 @@ function updateDisplay_() {
170
214
  * in case they can be reattached later. Also save the shadow DOM if it exists.
171
215
  * The result is a map from argument ID to information that was associated with
172
216
  * that argument at the beginning of the mutation.
173
- * @return {!Object.<string, {shadow: Element, block: Blockly.Block}>} An object
174
- * mapping argument IDs to blocks and shadow DOMs.
175
- * @private
176
- * @this Blockly.Block
217
+ *
218
+ * @returns An object mapping argument IDs to blocks and shadow DOMs.
177
219
  */
178
- function disconnectOldBlocks_() {
220
+ function disconnectOldBlocks_(this: ProcedureBlock): ConnectionMap {
179
221
  // Remove old stuff
180
- var connectionMap = {};
181
- for (var i = 0, input; (input = this.inputList[i]); i++) {
222
+ const connectionMap: ConnectionMap = {};
223
+ for (const input of this.inputList) {
182
224
  if (input.connection) {
183
- var target = input.connection.targetBlock();
184
- var saveInfo = {
225
+ const target = input.connection.targetBlock() as Blockly.BlockSvg;
226
+ const saveInfo = {
185
227
  shadow: input.connection.getShadowDom(),
186
228
  block: target,
187
229
  };
@@ -198,40 +240,39 @@ function disconnectOldBlocks_() {
198
240
  /**
199
241
  * Remove all inputs on the block, including dummy inputs.
200
242
  * Assumes no input has shadow DOM set.
201
- * @private
202
- * @this Blockly.Block
203
243
  */
204
- function removeAllInputs_() {
244
+ function removeAllInputs_(this: ProcedureBlock) {
205
245
  // Delete inputs directly instead of with block.removeInput to avoid splicing
206
246
  // out of the input list at every index.
207
- for (var i = 0, input; (input = this.inputList[i]); i++) {
208
- input.dispose();
209
- }
247
+ this.inputList.forEach((input: Blockly.Input) => input.dispose());
210
248
  this.inputList = [];
211
249
  }
212
250
 
213
251
  /**
214
252
  * Create all inputs specified by the new procCode, and populate them with
215
253
  * shadow blocks or reconnected old blocks as appropriate.
216
- * @param {!Object.<string, {shadow: Element, block: Blockly.Block}>}
217
- * connectionMap An object mapping argument IDs to blocks and shadow DOMs.
218
- * @private
219
- * @this Blockly.Block
254
+ *
255
+ * @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
220
256
  */
221
- function createAllInputs_(connectionMap) {
257
+ function createAllInputs_(this: ProcedureBlock, connectionMap: ConnectionMap) {
222
258
  // Split the proc into components, by %n, %b, and %s (ignoring escaped).
223
- var procComponents = this.procCode_.split(/(?=[^\\]%[nbs])/);
224
- procComponents = procComponents.map(function (c) {
225
- return c.trim(); // Strip whitespace.
226
- });
259
+ const procComponents = this.procCode_
260
+ .split(/(?=[^\\]%[nbs])/)
261
+ .map(function (c: string) {
262
+ return c.trim(); // Strip whitespace.
263
+ });
227
264
  // Create arguments and labels as appropriate.
228
- var argumentCount = 0;
229
- for (var i = 0, component; (component = procComponents[i]); i++) {
230
- var labelText;
231
- if (component.substring(0, 1) == "%") {
232
- var argumentType = component.substring(1, 2);
265
+ let argumentCount = 0;
266
+ for (const component of procComponents) {
267
+ let labelText;
268
+ if (component.substring(0, 1) === "%") {
269
+ const argumentType = component.substring(1, 2);
233
270
  if (
234
- !(argumentType == "n" || argumentType == "b" || argumentType == "s")
271
+ !(
272
+ argumentType === ArgumentType.NUMBER ||
273
+ argumentType === ArgumentType.BOOLEAN ||
274
+ argumentType === ArgumentType.STRING
275
+ )
235
276
  ) {
236
277
  throw new Error(
237
278
  "Found an custom procedure with an invalid type: " + argumentType
@@ -239,10 +280,10 @@ function createAllInputs_(connectionMap) {
239
280
  }
240
281
  labelText = component.substring(2).trim();
241
282
 
242
- var id = this.argumentIds_[argumentCount];
283
+ const id = this.argumentIds_[argumentCount];
243
284
 
244
- var input = this.appendValueInput(id);
245
- if (argumentType == "b") {
285
+ const input = this.appendValueInput(id);
286
+ if (argumentType === ArgumentType.BOOLEAN) {
246
287
  input.setCheck("Boolean");
247
288
  }
248
289
  this.populateArgument_(
@@ -262,19 +303,17 @@ function createAllInputs_(connectionMap) {
262
303
 
263
304
  /**
264
305
  * Delete all shadow blocks in the given map.
265
- * @param {!Object.<string, Blockly.Block>} connectionMap An object mapping
266
- * argument IDs to the blocks that were connected to those IDs at the
267
- * beginning of the mutation.
268
- * @private
269
- * @this Blockly.Block
306
+ *
307
+ * @param connectionMap An object mapping argument IDs to the blocks that were
308
+ * connected to those IDs at the beginning of the mutation.
270
309
  */
271
- function deleteShadows_(connectionMap) {
310
+ function deleteShadows_(this: ProcedureBlock, connectionMap: ConnectionMap) {
272
311
  // Get rid of all of the old shadow blocks if they aren't connected.
273
312
  if (connectionMap) {
274
- for (var id in connectionMap) {
275
- var saveInfo = connectionMap[id];
313
+ for (const id in connectionMap) {
314
+ const saveInfo = connectionMap[id];
276
315
  if (saveInfo) {
277
- var block = saveInfo["block"];
316
+ const block = saveInfo["block"];
278
317
  if (block && block.isShadow()) {
279
318
  block.dispose();
280
319
  connectionMap[id] = null;
@@ -290,10 +329,13 @@ function deleteShadows_(connectionMap) {
290
329
  /**
291
330
  * Add a label field with the given text to a procedures_call or
292
331
  * procedures_prototype block.
293
- * @param {string} text The label text.
294
- * @private
332
+ *
333
+ * @param text The label text.
295
334
  */
296
- function addLabelField_(text) {
335
+ function addLabelField_(
336
+ this: ProcedureCallBlock | ProcedurePrototypeBlock,
337
+ text: string
338
+ ) {
297
339
  this.appendDummyInput().appendField(text);
298
340
  }
299
341
 
@@ -301,10 +343,10 @@ function addLabelField_(text) {
301
343
  * Add a label editor with the given text to a procedures_declaration
302
344
  * block. Editing the text in the label editor updates the text of the
303
345
  * corresponding label fields on function calls.
304
- * @param {string} text The label text.
305
- * @private
346
+ *
347
+ * @param text The label text.
306
348
  */
307
- function addLabelEditor_(text) {
349
+ function addLabelEditor_(this: ProcedureDeclarationBlock, text: string) {
308
350
  if (text) {
309
351
  this.appendDummyInput(Blockly.utils.idGenerator.genUid()).appendField(
310
352
  new FieldTextInputRemovable(text)
@@ -314,24 +356,25 @@ function addLabelEditor_(text) {
314
356
 
315
357
  /**
316
358
  * Build a DOM node representing a shadow block of the given type.
317
- * @param {string} type One of 's' (string) or 'n' (number).
318
- * @return {!Element} The DOM node representing the new shadow block.
319
- * @private
320
- * @this Blockly.Block
321
- */
322
- function buildShadowDom_(type) {
323
- var shadowDom = goog.dom.createDom("shadow");
324
- if (type == "n") {
325
- var shadowType = "math_number";
326
- var fieldName = "NUM";
327
- var fieldValue = "1";
359
+ *
360
+ * @param type One of 's' (string) or 'n' (number).
361
+ * @returns The DOM node representing the new shadow block.
362
+ */
363
+ function buildShadowDom_(type: ArgumentType): Element {
364
+ const shadowDom = document.createElement("shadow");
365
+ let shadowType, fieldName, fieldValue;
366
+ if (type === ArgumentType.NUMBER) {
367
+ shadowType = "math_number";
368
+ fieldName = "NUM";
369
+ fieldValue = "1";
328
370
  } else {
329
- var shadowType = "text";
330
- var fieldName = "TEXT";
331
- var fieldValue = "";
371
+ shadowType = "text";
372
+ fieldName = "TEXT";
373
+ fieldValue = "";
332
374
  }
333
375
  shadowDom.setAttribute("type", shadowType);
334
- var fieldDom = goog.dom.createDom("field", null, fieldValue);
376
+ const fieldDom = document.createElement("field");
377
+ fieldDom.textContent = fieldValue;
335
378
  fieldDom.setAttribute("name", fieldName);
336
379
  shadowDom.appendChild(fieldDom);
337
380
  return shadowDom;
@@ -339,19 +382,27 @@ function buildShadowDom_(type) {
339
382
 
340
383
  /**
341
384
  * Create a new shadow block and attach it to the given input.
342
- * @param {!Blockly.Input} input The value input to attach a block to.
343
- * @param {string} argumentType One of 'b' (boolean), 's' (string) or
385
+ *
386
+ * @param input The value input to attach a block to.
387
+ * @param argumentType One of 'b' (boolean), 's' (string) or
344
388
  * 'n' (number).
345
- * @private
346
- * @this Blockly.Block
347
389
  */
348
- function attachShadow_(input, argumentType) {
349
- if (argumentType == "n" || argumentType == "s") {
350
- var blockType = argumentType == "n" ? "math_number" : "text";
390
+ function attachShadow_(
391
+ this: ProcedureCallBlock,
392
+ input: Blockly.Input,
393
+ argumentType: ArgumentType
394
+ ) {
395
+ if (
396
+ argumentType === ArgumentType.NUMBER ||
397
+ argumentType === ArgumentType.STRING
398
+ ) {
399
+ const blockType =
400
+ argumentType === ArgumentType.NUMBER ? "math_number" : "text";
351
401
  Blockly.Events.disable();
402
+ let newBlock;
352
403
  try {
353
- var newBlock = this.workspace.newBlock(blockType);
354
- if (argumentType == "n") {
404
+ newBlock = this.workspace.newBlock(blockType);
405
+ if (argumentType === ArgumentType.NUMBER) {
355
406
  newBlock.setFieldValue("1", "NUM");
356
407
  } else {
357
408
  newBlock.setFieldValue("", "TEXT");
@@ -359,7 +410,7 @@ function attachShadow_(input, argumentType) {
359
410
  newBlock.setShadow(true);
360
411
  if (!this.isInsertionMarker()) {
361
412
  newBlock.initSvg();
362
- newBlock.render(false);
413
+ newBlock.render();
363
414
  }
364
415
  } finally {
365
416
  Blockly.Events.enable();
@@ -375,28 +426,36 @@ function attachShadow_(input, argumentType) {
375
426
 
376
427
  /**
377
428
  * Create a new argument reporter block.
378
- * @param {string} argumentType One of 'b' (boolean), 's' (string) or
429
+ *
430
+ * @param argumentType One of 'b' (boolean), 's' (string) or
379
431
  * 'n' (number).
380
- * @param {string} displayName The name of the argument as provided by the
432
+ * @param displayName The name of the argument as provided by the
381
433
  * user, which becomes the text of the label on the argument reporter block.
382
- * @return {!Blockly.BlockSvg} The newly created argument reporter block.
383
- * @private
384
- * @this Blockly.Block
434
+ * @returns The newly created argument reporter block.
385
435
  */
386
- function createArgumentReporter_(argumentType, displayName) {
387
- if (argumentType == "n" || argumentType == "s") {
388
- var blockType = "argument_reporter_string_number";
436
+ function createArgumentReporter_(
437
+ this: ProcedurePrototypeBlock,
438
+ argumentType: ArgumentType,
439
+ displayName: string
440
+ ): Blockly.BlockSvg {
441
+ let blockType;
442
+ if (
443
+ argumentType === ArgumentType.NUMBER ||
444
+ argumentType === ArgumentType.STRING
445
+ ) {
446
+ blockType = "argument_reporter_string_number";
389
447
  } else {
390
- var blockType = "argument_reporter_boolean";
448
+ blockType = "argument_reporter_boolean";
391
449
  }
392
450
  Blockly.Events.disable();
451
+ let newBlock;
393
452
  try {
394
- var newBlock = this.workspace.newBlock(blockType);
453
+ newBlock = this.workspace.newBlock(blockType);
395
454
  newBlock.setShadow(true);
396
455
  newBlock.setFieldValue(displayName, "VALUE");
397
456
  if (!this.isInsertionMarker()) {
398
457
  newBlock.initSvg();
399
- newBlock.render(false);
458
+ newBlock.render();
400
459
  }
401
460
  } finally {
402
461
  Blockly.Events.enable();
@@ -412,20 +471,25 @@ function createArgumentReporter_(argumentType, displayName) {
412
471
  /**
413
472
  * Populate the argument by attaching the correct child block or shadow to the
414
473
  * given input.
415
- * @param {string} type One of 'b' (boolean), 's' (string) or 'n' (number).
416
- * @param {number} index The index of this argument into the argument id array.
417
- * @param {!Object.<string, {shadow: Element, block: Blockly.Block}>}
418
- * connectionMap An object mapping argument IDs to blocks and shadow DOMs.
419
- * @param {string} id The ID of the input to populate.
420
- * @param {!Blockly.Input} input The newly created input to populate.
421
- * @private
422
- * @this Blockly.Block
423
- */
424
- function populateArgumentOnCaller_(type, index, connectionMap, id, input) {
425
- var oldBlock = null;
426
- var oldShadow = null;
474
+ *
475
+ * @param type One of 'b' (boolean), 's' (string) or 'n' (number).
476
+ * @param index The index of this argument into the argument id array.
477
+ * @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
478
+ * @param id The ID of the input to populate.
479
+ * @param input The newly created input to populate.
480
+ */
481
+ function populateArgumentOnCaller_(
482
+ this: ProcedureCallBlock,
483
+ type: ArgumentType,
484
+ index: number,
485
+ connectionMap: ConnectionMap,
486
+ id: string,
487
+ input: Blockly.Input
488
+ ) {
489
+ let oldBlock: Blockly.BlockSvg;
490
+ let oldShadow: Element;
427
491
  if (connectionMap && id in connectionMap) {
428
- var saveInfo = connectionMap[id];
492
+ const saveInfo = connectionMap[id];
429
493
  oldBlock = saveInfo["block"];
430
494
  oldShadow = saveInfo["shadow"];
431
495
  }
@@ -434,9 +498,8 @@ function populateArgumentOnCaller_(type, index, connectionMap, id, input) {
434
498
  // Reattach the old block and shadow DOM.
435
499
  connectionMap[input.name] = null;
436
500
  oldBlock.outputConnection.connect(input.connection);
437
- if (type != "b" && this.generateShadows_) {
438
- var shadowDom = oldShadow || this.buildShadowDom_(type);
439
- console.log("setting shadow dom: " + shadowDom);
501
+ if (type !== ArgumentType.BOOLEAN && this.generateShadows_) {
502
+ const shadowDom = oldShadow || this.buildShadowDom_(type);
440
503
  input.connection.setShadowDom(shadowDom);
441
504
  }
442
505
  } else if (this.generateShadows_) {
@@ -447,35 +510,41 @@ function populateArgumentOnCaller_(type, index, connectionMap, id, input) {
447
510
  /**
448
511
  * Populate the argument by attaching the correct argument reporter to the given
449
512
  * input.
450
- * @param {string} type One of 'b' (boolean), 's' (string) or 'n' (number).
451
- * @param {number} index The index of this argument into the argument ID and
513
+ *
514
+ * @param type One of 'b' (boolean), 's' (string) or 'n' (number).
515
+ * @param index The index of this argument into the argument ID and
452
516
  * argument display name arrays.
453
- * @param {!Object.<string, {shadow: Element, block: Blockly.Block}>}
454
- * connectionMap An object mapping argument IDs to blocks and shadow DOMs.
455
- * @param {string} id The ID of the input to populate.
456
- * @param {!Blockly.Input} input The newly created input to populate.
457
- * @private
458
- * @this Blockly.Block
459
- */
460
- function populateArgumentOnPrototype_(type, index, connectionMap, id, input) {
461
- var oldBlock = null;
517
+ * @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
518
+ * @param id The ID of the input to populate.
519
+ * @param input The newly created input to populate.
520
+ */
521
+ function populateArgumentOnPrototype_(
522
+ this: ProcedurePrototypeBlock,
523
+ type: ArgumentType,
524
+ index: number,
525
+ connectionMap: ConnectionMap,
526
+ id: string,
527
+ input: Blockly.Input
528
+ ) {
529
+ let oldBlock = null;
462
530
  if (connectionMap && id in connectionMap) {
463
- var saveInfo = connectionMap[id];
531
+ const saveInfo = connectionMap[id];
464
532
  oldBlock = saveInfo["block"];
465
533
  }
466
534
 
467
- var oldTypeMatches = checkOldTypeMatches_(oldBlock, type);
468
- var displayName = this.displayNames_[index];
535
+ const oldTypeMatches = checkOldTypeMatches_(oldBlock, type);
536
+ const displayName = this.displayNames_[index];
469
537
 
470
538
  // Decide which block to attach.
539
+ let argumentReporter: Blockly.BlockSvg;
471
540
  if (connectionMap && oldBlock && oldTypeMatches) {
472
541
  // Update the text if needed. The old argument reporter is the same type,
473
542
  // and on the same input, but the argument's display name may have changed.
474
- var argumentReporter = oldBlock;
543
+ argumentReporter = oldBlock;
475
544
  argumentReporter.setFieldValue(displayName, "VALUE");
476
545
  connectionMap[input.name] = null;
477
546
  } else {
478
- var argumentReporter = this.createArgumentReporter_(type, displayName);
547
+ argumentReporter = this.createArgumentReporter_(type, displayName);
479
548
  }
480
549
 
481
550
  // Attach the block.
@@ -485,36 +554,42 @@ function populateArgumentOnPrototype_(type, index, connectionMap, id, input) {
485
554
  /**
486
555
  * Populate the argument by attaching the correct argument editor to the given
487
556
  * input.
488
- * @param {string} type One of 'b' (boolean), 's' (string) or 'n' (number).
489
- * @param {number} index The index of this argument into the argument id and
490
- * argument display name arrays.
491
- * @param {!Object.<string, {shadow: Element, block: Blockly.Block}>}
492
- * connectionMap An object mapping argument IDs to blocks and shadow DOMs.
493
- * @param {string} id The ID of the input to populate.
494
- * @param {!Blockly.Input} input The newly created input to populate.
495
- * @private
496
- * @this Blockly.Block
497
- */
498
- function populateArgumentOnDeclaration_(type, index, connectionMap, id, input) {
499
- var oldBlock = null;
557
+ *
558
+ * @param type One of 'b' (boolean), 's' (string) or 'n' (number).
559
+ * @param index The index of this argument into the argument id and argument
560
+ * display name arrays.
561
+ * @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
562
+ * @param id The ID of the input to populate.
563
+ * @param input The newly created input to populate.
564
+ */
565
+ function populateArgumentOnDeclaration_(
566
+ this: ProcedureDeclarationBlock,
567
+ type: ArgumentType,
568
+ index: number,
569
+ connectionMap: ConnectionMap,
570
+ id: string,
571
+ input: Blockly.Input
572
+ ) {
573
+ let oldBlock = null;
500
574
  if (connectionMap && id in connectionMap) {
501
- var saveInfo = connectionMap[id];
575
+ const saveInfo = connectionMap[id];
502
576
  oldBlock = saveInfo["block"];
503
577
  }
504
578
 
505
579
  // TODO: This always returns false, because it checks for argument reporter
506
580
  // blocks instead of argument editor blocks. Create a new version for argument
507
581
  // editors.
508
- var oldTypeMatches = checkOldTypeMatches_(oldBlock, type);
509
- var displayName = this.displayNames_[index];
582
+ const oldTypeMatches = checkOldTypeMatches_(oldBlock, type);
583
+ const displayName = this.displayNames_[index];
510
584
 
511
585
  // Decide which block to attach.
586
+ let argumentEditor: Blockly.BlockSvg;
512
587
  if (oldBlock && oldTypeMatches) {
513
- var argumentEditor = oldBlock;
588
+ argumentEditor = oldBlock;
514
589
  oldBlock.setFieldValue(displayName, "TEXT");
515
590
  connectionMap[input.name] = null;
516
591
  } else {
517
- var argumentEditor = this.createArgumentEditor_(type, displayName);
592
+ argumentEditor = this.createArgumentEditor_(type, displayName);
518
593
  }
519
594
 
520
595
  // Attach the block.
@@ -524,21 +599,28 @@ function populateArgumentOnDeclaration_(type, index, connectionMap, id, input) {
524
599
  /**
525
600
  * Check whether the type of the old block corresponds to the given argument
526
601
  * type.
527
- * @param {Blockly.BlockSvg} oldBlock The old block to check.
528
- * @param {string} type The argument type. One of 'n', 'n', or 's'.
529
- * @return {boolean} True if the type matches, false otherwise.
602
+ *
603
+ * @param oldBlock The old block to check.
604
+ * @param type The argument type. One of 'n', 'n', or 's'.
605
+ * @returns True if the type matches, false otherwise.
530
606
  */
531
- function checkOldTypeMatches_(oldBlock, type) {
607
+ function checkOldTypeMatches_(
608
+ oldBlock: Blockly.BlockSvg | null,
609
+ type: string
610
+ ): boolean {
532
611
  if (!oldBlock) {
533
612
  return false;
534
613
  }
535
614
  if (
536
- (type == "n" || type == "s") &&
537
- oldBlock.type == "argument_reporter_string_number"
615
+ (type === ArgumentType.NUMBER || type === ArgumentType.STRING) &&
616
+ oldBlock.type === "argument_reporter_string_number"
538
617
  ) {
539
618
  return true;
540
619
  }
541
- if (type == "b" && oldBlock.type == "argument_reporter_boolean") {
620
+ if (
621
+ type === ArgumentType.BOOLEAN &&
622
+ oldBlock.type === "argument_reporter_boolean"
623
+ ) {
542
624
  return true;
543
625
  }
544
626
  return false;
@@ -548,21 +630,27 @@ function checkOldTypeMatches_(oldBlock, type) {
548
630
  * Create an argument editor.
549
631
  * An argument editor is a shadow block with a single text field, which is used
550
632
  * to set the display name of the argument.
551
- * @param {string} argumentType One of 'b' (boolean), 's' (string) or
552
- * 'n' (number).
553
- * @param {string} displayName The display name of this argument, which is the
554
- * text of the field on the shadow block.
555
- * @return {!Blockly.BlockSvg} The newly created argument editor block.
556
- * @private
557
- * @this Blockly.Block
633
+ *
634
+ * @param argumentType One of 'b' (boolean), 's' (string) or 'n' (number).
635
+ * @param displayName The display name of this argument, which is the text of
636
+ * the field on the shadow block.
637
+ * @returns The newly created argument editor block.
558
638
  */
559
- function createArgumentEditor_(argumentType, displayName) {
639
+ function createArgumentEditor_(
640
+ this: ProcedureDeclarationBlock,
641
+ argumentType: ArgumentType,
642
+ displayName: string
643
+ ): Blockly.BlockSvg {
560
644
  Blockly.Events.disable();
645
+ let newBlock;
561
646
  try {
562
- if (argumentType == "n" || argumentType == "s") {
563
- var newBlock = this.workspace.newBlock("argument_editor_string_number");
647
+ if (
648
+ argumentType === ArgumentType.NUMBER ||
649
+ argumentType === ArgumentType.STRING
650
+ ) {
651
+ newBlock = this.workspace.newBlock("argument_editor_string_number");
564
652
  } else {
565
- var newBlock = this.workspace.newBlock("argument_editor_boolean");
653
+ newBlock = this.workspace.newBlock("argument_editor_boolean");
566
654
  }
567
655
  newBlock.setFieldValue(displayName, "TEXT");
568
656
  newBlock.setShadow(true);
@@ -585,23 +673,23 @@ function createArgumentEditor_(argumentType, displayName) {
585
673
  * Update the serializable information on the block based on the existing inputs
586
674
  * and their text.
587
675
  */
588
- function updateDeclarationProcCode_() {
676
+ function updateDeclarationProcCode_(this: ProcedureDeclarationBlock) {
589
677
  this.procCode_ = "";
590
678
  this.displayNames_ = [];
591
679
  this.argumentIds_ = [];
592
- for (var i = 0; i < this.inputList.length; i++) {
593
- if (i != 0) {
680
+ for (let i = 0; i < this.inputList.length; i++) {
681
+ if (i !== 0) {
594
682
  this.procCode_ += " ";
595
683
  }
596
- var input = this.inputList[i];
597
- if (input.type == Blockly.inputs.inputTypes.DUMMY) {
684
+ const input = this.inputList[i];
685
+ if (input.type === Blockly.inputs.inputTypes.DUMMY) {
598
686
  this.procCode_ += input.fieldRow[0].getValue();
599
- } else if (input.type == Blockly.inputs.inputTypes.VALUE) {
687
+ } else if (input.type === Blockly.inputs.inputTypes.VALUE) {
600
688
  // Inspect the argument editor.
601
- var target = input.connection.targetBlock();
689
+ const target = input.connection.targetBlock();
602
690
  this.displayNames_.push(target.getFieldValue("TEXT"));
603
691
  this.argumentIds_.push(input.name);
604
- if (target.type == "argument_editor_boolean") {
692
+ if (target.type === "argument_editor_boolean") {
605
693
  this.procCode_ += "%b";
606
694
  } else {
607
695
  this.procCode_ += "%s";
@@ -616,27 +704,25 @@ function updateDeclarationProcCode_() {
616
704
 
617
705
  /**
618
706
  * Focus on the last argument editor or label editor on the block.
619
- * @private
620
707
  */
621
- function focusLastEditor_() {
708
+ function focusLastEditor_(this: ProcedureDeclarationBlock) {
622
709
  if (this.inputList.length > 0) {
623
- var newInput = this.inputList[this.inputList.length - 1];
624
- if (newInput.type == Blockly.inputs.inputTypes.DUMMY) {
625
- newInput.fieldRow[0].showEditor_();
626
- } else if (newInput.type == Blockly.inputs.inputTypes.VALUE) {
710
+ const newInput = this.inputList[this.inputList.length - 1];
711
+ if (newInput.type === Blockly.inputs.inputTypes.DUMMY) {
712
+ newInput.fieldRow[0].showEditor();
713
+ } else if (newInput.type === Blockly.inputs.inputTypes.VALUE) {
627
714
  // Inspect the argument editor.
628
- var target = newInput.connection.targetBlock();
629
- target.getField("TEXT").showEditor_();
715
+ const target = newInput.connection.targetBlock();
716
+ target.getField("TEXT").showEditor();
630
717
  }
631
718
  }
632
719
  }
633
720
 
634
721
  /**
635
722
  * Externally-visible function to add a label to the procedure declaration.
636
- * @public
637
723
  */
638
- function addLabelExternal() {
639
- Blockly.WidgetDiv.hide(true);
724
+ function addLabelExternal(this: ProcedureDeclarationBlock) {
725
+ Blockly.WidgetDiv.hide();
640
726
  this.procCode_ = this.procCode_ + " label text";
641
727
  this.updateDisplay_();
642
728
  this.focusLastEditor_();
@@ -645,10 +731,9 @@ function addLabelExternal() {
645
731
  /**
646
732
  * Externally-visible function to add a boolean argument to the procedure
647
733
  * declaration.
648
- * @public
649
734
  */
650
- function addBooleanExternal() {
651
- Blockly.WidgetDiv.hide(true);
735
+ function addBooleanExternal(this: ProcedureDeclarationBlock) {
736
+ Blockly.WidgetDiv.hide();
652
737
  this.procCode_ = this.procCode_ + " %b";
653
738
  this.displayNames_.push("boolean");
654
739
  this.argumentIds_.push(Blockly.utils.idGenerator.genUid());
@@ -660,10 +745,9 @@ function addBooleanExternal() {
660
745
  /**
661
746
  * Externally-visible function to add a string/number argument to the procedure
662
747
  * declaration.
663
- * @public
664
748
  */
665
- function addStringNumberExternal() {
666
- Blockly.WidgetDiv.hide(true);
749
+ function addStringNumberExternal(this: ProcedureDeclarationBlock) {
750
+ Blockly.WidgetDiv.hide();
667
751
  this.procCode_ = this.procCode_ + " %s";
668
752
  this.displayNames_.push("number or text");
669
753
  this.argumentIds_.push(Blockly.utils.idGenerator.genUid());
@@ -674,28 +758,31 @@ function addStringNumberExternal() {
674
758
 
675
759
  /**
676
760
  * Externally-visible function to get the warp on procedure declaration.
677
- * @return {boolean} The value of the warp_ property.
678
- * @public
761
+ *
762
+ * @returns The value of the warp_ property.
679
763
  */
680
- function getWarp() {
764
+ function getWarp(this: ProcedureDeclarationBlock): boolean {
681
765
  return this.warp_;
682
766
  }
683
767
 
684
768
  /**
685
769
  * Externally-visible function to set the warp on procedure declaration.
686
- * @param {boolean} warp The value of the warp_ property.
687
- * @public
770
+ *
771
+ * @param warp The value of the warp_ property.
688
772
  */
689
- function setWarp(warp) {
773
+ function setWarp(this: ProcedureDeclarationBlock, warp: boolean) {
690
774
  this.warp_ = warp;
691
775
  }
692
776
 
693
777
  /**
694
778
  * Callback to remove a field, only for the declaration block.
695
- * @param {Blockly.Field} field The field being removed.
696
- * @public
779
+ *
780
+ * @param field The field being removed.
697
781
  */
698
- function removeFieldCallback(field) {
782
+ function removeFieldCallback(
783
+ this: ProcedureDeclarationBlock,
784
+ field: Blockly.Field
785
+ ) {
699
786
  // Do not delete if there is only one input
700
787
  if (this.inputList.length === 1) {
701
788
  return;
@@ -705,19 +792,19 @@ function removeFieldCallback(field) {
705
792
  var input = this.inputList[n];
706
793
  if (input.connection) {
707
794
  var target = input.connection.targetBlock();
708
- if (field.name && target.getField(field.name) == field) {
795
+ if (field.name && target.getField(field.name) === field) {
709
796
  inputNameToRemove = input.name;
710
797
  }
711
798
  } else {
712
799
  for (var j = 0; j < input.fieldRow.length; j++) {
713
- if (input.fieldRow[j] == field) {
800
+ if (input.fieldRow[j] === field) {
714
801
  inputNameToRemove = input.name;
715
802
  }
716
803
  }
717
804
  }
718
805
  }
719
806
  if (inputNameToRemove) {
720
- Blockly.WidgetDiv.hide(true);
807
+ Blockly.WidgetDiv.hide();
721
808
  this.removeInput(inputNameToRemove);
722
809
  this.onChangeFn();
723
810
  this.updateDisplay_();
@@ -726,12 +813,16 @@ function removeFieldCallback(field) {
726
813
 
727
814
  /**
728
815
  * Callback to pass removeField up to the declaration block from arguments.
729
- * @param {Blockly.Field} field The field being removed.
730
- * @public
816
+ *
817
+ * @param field The field being removed.
731
818
  */
732
- function removeArgumentCallback_(field) {
733
- if (this.parentBlock_ && this.parentBlock_.removeFieldCallback) {
734
- this.parentBlock_.removeFieldCallback(field);
819
+ function removeArgumentCallback_(
820
+ this: ProcedureDeclarationBlock | ProcedureArgumentEditorBlock,
821
+ field: Blockly.Field
822
+ ) {
823
+ const parent = this.getParent();
824
+ if (parent && parent.removeFieldCallback) {
825
+ parent.removeFieldCallback(field);
735
826
  }
736
827
  }
737
828
 
@@ -744,20 +835,22 @@ function removeArgumentCallback_(field) {
744
835
  * Until there is a more explicit way of identifying argument reporter blocks using ids,
745
836
  * be conservative and only update argument reporters that are used in the
746
837
  * stack below the prototype, ie the definition.
747
- * @param {!Array<string>} prevArgIds The previous ordering of argument ids.
748
- * @param {!Array<string>} prevDisplayNames The previous argument names.
749
- * @this Blockly.Block
750
- */
751
- function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
752
- var nameChanges = [];
753
- var argReporters = [];
754
- var definitionBlock = this.getParent();
838
+ *
839
+ * @param prevArgIds The previous ordering of argument ids.
840
+ * @param prevDisplayNames The previous argument names.
841
+ */
842
+ function updateArgumentReporterNames_(
843
+ this: ProcedurePrototypeBlock,
844
+ prevArgIds: string[],
845
+ prevDisplayNames: string[]
846
+ ) {
847
+ const nameChanges: { newName: string; blocks: Blockly.BlockSvg[] }[] = [];
848
+ const argReporters: Blockly.BlockSvg[] = [];
849
+ const definitionBlock = this.getParent();
755
850
  if (!definitionBlock) return;
756
851
 
757
852
  // Create a list of argument reporters that are descendants of the definition stack (see above comment)
758
- var allBlocks = definitionBlock.getDescendants(false);
759
- for (var i = 0; i < allBlocks.length; i++) {
760
- var block = allBlocks[i];
853
+ definitionBlock.getDescendants(false).forEach((block: Blockly.BlockSvg) => {
761
854
  if (
762
855
  (block.type === "argument_reporter_string_number" ||
763
856
  block.type === "argument_reporter_boolean") &&
@@ -766,20 +859,20 @@ function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
766
859
  // Exclude arg reporters in the prototype block, which are shadows.
767
860
  argReporters.push(block);
768
861
  }
769
- }
862
+ });
770
863
 
771
864
  // Create a list of "name changes", including the new name and blocks matching the old name
772
865
  // Only search over the current set of argument ids, ignore args that have been removed
773
- for (var i = 0, id; (id = this.argumentIds_[i]); i++) {
866
+ for (let i = 0, id; (id = this.argumentIds_[i]); i++) {
774
867
  // Find the previous index of this argument id. Could be -1 if it is newly added.
775
- var prevIndex = prevArgIds.indexOf(id);
776
- if (prevIndex == -1) continue; // Newly added argument, no corresponding previous argument to update.
777
- var prevName = prevDisplayNames[prevIndex];
778
- if (prevName != this.displayNames_[i]) {
868
+ const prevIndex = prevArgIds.indexOf(id);
869
+ if (prevIndex === -1) continue; // Newly added argument, no corresponding previous argument to update.
870
+ const prevName = prevDisplayNames[prevIndex];
871
+ if (prevName !== this.displayNames_[i]) {
779
872
  nameChanges.push({
780
873
  newName: this.displayNames_[i],
781
- blocks: argReporters.filter(function (block) {
782
- return block.getFieldValue("VALUE") == prevName;
874
+ blocks: argReporters.filter((block) => {
875
+ return block.getFieldValue("VALUE") === prevName;
783
876
  }),
784
877
  });
785
878
  }
@@ -787,8 +880,8 @@ function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
787
880
 
788
881
  // Finally update the blocks for each name change.
789
882
  // Do this after creating the lists to avoid cycles of renaming.
790
- for (var j = 0, nameChange; (nameChange = nameChanges[j]); j++) {
791
- for (var k = 0, block; (block = nameChange.blocks[k]); k++) {
883
+ for (const nameChange of nameChanges) {
884
+ for (const block of nameChange.blocks) {
792
885
  block.setFieldValue(nameChange.newName, "VALUE");
793
886
  }
794
887
  }
@@ -797,9 +890,8 @@ function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
797
890
  Blockly.Blocks["procedures_definition"] = {
798
891
  /**
799
892
  * Block for defining a procedure with no return value.
800
- * @this Blockly.Block
801
893
  */
802
- init: function () {
894
+ init: function (this: Blockly.Block) {
803
895
  this.jsonInit({
804
896
  message0: Blockly.Msg.PROCEDURES_DEFINITION,
805
897
  args0: [
@@ -820,9 +912,8 @@ Blockly.Blocks["procedures_definition"] = {
820
912
  Blockly.Blocks["procedures_call"] = {
821
913
  /**
822
914
  * Block for calling a procedure with no return value.
823
- * @this Blockly.Block
824
915
  */
825
- init: function () {
916
+ init: function (this: ProcedureCallBlock) {
826
917
  this.jsonInit({
827
918
  extensions: [
828
919
  "colours_more",
@@ -858,9 +949,8 @@ Blockly.Blocks["procedures_prototype"] = {
858
949
  /**
859
950
  * Block for calling a procedure with no return value, for rendering inside
860
951
  * define block.
861
- * @this Blockly.Block
862
952
  */
863
- init: function () {
953
+ init: function (this: ProcedurePrototypeBlock) {
864
954
  this.jsonInit({
865
955
  extensions: ["colours_more", "shape_statement"],
866
956
  });
@@ -894,9 +984,8 @@ Blockly.Blocks["procedures_prototype"] = {
894
984
  Blockly.Blocks["procedures_declaration"] = {
895
985
  /**
896
986
  * The root block in the procedure declaration editor.
897
- * @this Blockly.Block
898
987
  */
899
- init: function () {
988
+ init: function (this: ProcedureDeclarationBlock) {
900
989
  this.jsonInit({
901
990
  extensions: ["colours_more", "shape_statement"],
902
991
  });
@@ -937,7 +1026,7 @@ Blockly.Blocks["procedures_declaration"] = {
937
1026
  };
938
1027
 
939
1028
  Blockly.Blocks["argument_reporter_boolean"] = {
940
- init: function () {
1029
+ init: function (this: Blockly.BlockSvg) {
941
1030
  this.jsonInit({
942
1031
  message0: " %1",
943
1032
  args0: [
@@ -954,7 +1043,7 @@ Blockly.Blocks["argument_reporter_boolean"] = {
954
1043
  };
955
1044
 
956
1045
  Blockly.Blocks["argument_reporter_string_number"] = {
957
- init: function () {
1046
+ init: function (this: Blockly.BlockSvg) {
958
1047
  this.jsonInit({
959
1048
  message0: " %1",
960
1049
  args0: [
@@ -971,7 +1060,7 @@ Blockly.Blocks["argument_reporter_string_number"] = {
971
1060
  };
972
1061
 
973
1062
  Blockly.Blocks["argument_editor_boolean"] = {
974
- init: function () {
1063
+ init: function (this: ProcedureArgumentEditorBlock) {
975
1064
  this.jsonInit({
976
1065
  message0: " %1",
977
1066
  args0: [
@@ -990,7 +1079,7 @@ Blockly.Blocks["argument_editor_boolean"] = {
990
1079
  };
991
1080
 
992
1081
  Blockly.Blocks["argument_editor_string_number"] = {
993
- init: function () {
1082
+ init: function (this: ProcedureArgumentEditorBlock) {
994
1083
  this.jsonInit({
995
1084
  message0: " %1",
996
1085
  args0: [
@@ -1007,3 +1096,63 @@ Blockly.Blocks["argument_editor_string_number"] = {
1007
1096
  this.removeFieldCallback = removeArgumentCallback_.bind(this);
1008
1097
  },
1009
1098
  };
1099
+
1100
+ interface ProcedureBlock extends Blockly.BlockSvg {
1101
+ procCode_: string;
1102
+ argumentIds_: string[];
1103
+ warp_: boolean;
1104
+ getProcCode: () => string;
1105
+ removeAllInputs_: () => void;
1106
+ disconnectOldBlocks_: () => ConnectionMap;
1107
+ deleteShadows_: (connectionMap: ConnectionMap) => void;
1108
+ createAllInputs_: (connectionMap: ConnectionMap) => void;
1109
+ updateDisplay_: () => void;
1110
+ populateArgument_: (
1111
+ type: ArgumentType,
1112
+ index: number,
1113
+ connectionMap: ConnectionMap,
1114
+ id: string,
1115
+ input: Blockly.Input
1116
+ ) => void;
1117
+ addProcedureLabel_: (text: string) => void;
1118
+ }
1119
+
1120
+ export interface ProcedureDeclarationBlock extends ProcedureBlock {
1121
+ displayNames_: string[];
1122
+ argumentDefaults_: string[];
1123
+ removeFieldCallback: (field: Blockly.Field) => void;
1124
+ createArgumentEditor_: (
1125
+ argumentType: ArgumentType,
1126
+ displayName: string
1127
+ ) => Blockly.BlockSvg;
1128
+ focusLastEditor_: () => void;
1129
+ getWarp: () => boolean;
1130
+ setWarp: (warp: boolean) => void;
1131
+ addLabelExternal: () => void;
1132
+ addBooleanExternal: () => void;
1133
+ addStringNumberExternal: () => void;
1134
+ onChangeFn: () => void;
1135
+ }
1136
+
1137
+ interface ProcedureCallBlock extends ProcedureBlock {
1138
+ generateShadows_: boolean;
1139
+ attachShadow_: (input: Blockly.Input, argumentType: ArgumentType) => void;
1140
+ buildShadowDom_: (type: ArgumentType) => Element;
1141
+ }
1142
+
1143
+ interface ProcedurePrototypeBlock extends ProcedureBlock {
1144
+ displayNames_: string[];
1145
+ argumentDefaults_: string[];
1146
+ createArgumentReporter_: (
1147
+ argumentType: ArgumentType,
1148
+ displayName: string
1149
+ ) => Blockly.BlockSvg;
1150
+ updateArgumentReporterNames_: (
1151
+ prevArgIds: string[],
1152
+ prevDisplayNames: string[]
1153
+ ) => void;
1154
+ }
1155
+
1156
+ interface ProcedureArgumentEditorBlock extends Blockly.BlockSvg {
1157
+ removeFieldCallback: (field: Blockly.Field) => void;
1158
+ }