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

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 (85) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/main.js +1 -1
  3. package/dist/main.js.LICENSE.txt +0 -12
  4. package/package.json +4 -4
  5. package/src/{block_reporting.js → block_reporting.ts} +7 -5
  6. package/src/blocks/{colour.js → colour.ts} +6 -6
  7. package/src/blocks/{control.js → control.ts} +21 -54
  8. package/src/blocks/{data.js → data.ts} +134 -142
  9. package/src/blocks/{event.js → event.ts} +12 -33
  10. package/src/blocks/{looks.js → looks.ts} +24 -73
  11. package/src/blocks/{math.js → math.ts} +6 -11
  12. package/src/blocks/{matrix.js → matrix.ts} +2 -3
  13. package/src/blocks/{motion.js → motion.ts} +23 -70
  14. package/src/blocks/{note.js → note.ts} +2 -3
  15. package/src/blocks/{operators.js → operators.ts} +18 -55
  16. package/src/blocks/{procedures.js → procedures.ts} +418 -269
  17. package/src/blocks/{sensing.js → sensing.ts} +21 -61
  18. package/src/blocks/{sound.js → sound.ts} +9 -28
  19. package/src/blocks/{text.js → text.ts} +1 -2
  20. package/src/blocks/{vertical_extensions.js → vertical_extensions.ts} +63 -100
  21. package/src/checkable_continuous_flyout.ts +112 -0
  22. package/src/{checkbox_bubble.js → checkbox_bubble.ts} +40 -58
  23. package/src/{colours.js → colours.ts} +11 -4
  24. package/src/{constants.js → constants.ts} +13 -0
  25. package/src/{context_menu_items.js → context_menu_items.ts} +18 -12
  26. package/src/{css.js → css.ts} +13 -7
  27. package/src/{data_category.js → data_category.ts} +216 -150
  28. package/src/events/{events_block_comment_base.js → events_block_comment_base.ts} +23 -4
  29. package/src/events/{events_block_comment_change.js → events_block_comment_change.ts} +29 -5
  30. package/src/events/{events_block_comment_collapse.js → events_block_comment_collapse.ts} +24 -6
  31. package/src/events/{events_block_comment_create.js → events_block_comment_create.ts} +36 -10
  32. package/src/events/{events_block_comment_delete.js → events_block_comment_delete.ts} +6 -2
  33. package/src/events/{events_block_comment_move.js → events_block_comment_move.ts} +36 -6
  34. package/src/events/events_block_comment_resize.ts +88 -0
  35. package/src/events/events_block_drag_end.ts +49 -0
  36. package/src/events/events_block_drag_outside.ts +44 -0
  37. package/src/events/{events_scratch_variable_create.js → events_scratch_variable_create.ts} +28 -15
  38. package/src/fields/{field_colour_slider.js → field_colour_slider.ts} +117 -106
  39. package/src/fields/{field_matrix.js → field_matrix.ts} +189 -215
  40. package/src/fields/{field_note.js → field_note.ts} +227 -286
  41. package/src/fields/{field_textinput_removable.js → field_textinput_removable.ts} +17 -20
  42. package/src/fields/{field_variable_getter.js → field_variable_getter.ts} +28 -17
  43. package/src/fields/{field_vertical_separator.js → field_vertical_separator.ts} +14 -30
  44. package/src/fields/{field_angle.js → scratch_field_angle.ts} +124 -80
  45. package/src/fields/{field_dropdown.js → scratch_field_dropdown.ts} +9 -7
  46. package/src/fields/{field_number.js → scratch_field_number.ts} +60 -55
  47. package/src/fields/{field_variable.js → scratch_field_variable.ts} +46 -27
  48. package/src/{flyout_checkbox_icon.js → flyout_checkbox_icon.ts} +15 -19
  49. package/src/{glows.js → glows.ts} +29 -18
  50. package/src/index.ts +62 -63
  51. package/src/procedures.ts +462 -0
  52. package/src/recyclable_block_flyout_inflater.ts +51 -0
  53. package/src/renderer/{bowler_hat.js → bowler_hat.ts} +1 -1
  54. package/src/renderer/{constants.js → constants.ts} +26 -12
  55. package/src/renderer/{drawer.js → drawer.ts} +8 -3
  56. package/src/renderer/{path_object.js → path_object.ts} +2 -2
  57. package/src/renderer/{render_info.js → render_info.ts} +19 -7
  58. package/src/renderer/renderer.ts +76 -0
  59. package/src/{scratch_block_paster.js → scratch_block_paster.ts} +9 -7
  60. package/src/scratch_blocks_utils.ts +39 -0
  61. package/src/{scratch_comment_icon.js → scratch_comment_icon.ts} +43 -26
  62. package/src/scratch_connection_checker.ts +44 -0
  63. package/src/{scratch_continuous_category.js → scratch_continuous_category.ts} +20 -13
  64. package/src/scratch_continuous_toolbox.ts +70 -0
  65. package/src/{scratch_dragger.js → scratch_dragger.ts} +97 -28
  66. package/src/{scratch_variable_map.js → scratch_variable_map.ts} +4 -1
  67. package/src/scratch_variable_model.ts +30 -0
  68. package/src/{shadows.js → shadows.ts} +8 -4
  69. package/src/{status_indicator_label.js → status_indicator_label.ts} +24 -36
  70. package/src/{status_indicator_label_flyout_inflater.js → status_indicator_label_flyout_inflater.ts} +13 -9
  71. package/src/{variables.js → variables.ts} +153 -123
  72. package/tsconfig.json +5 -0
  73. package/src/categories.js +0 -15
  74. package/src/checkable_continuous_flyout.js +0 -138
  75. package/src/events/events_block_comment_resize.js +0 -52
  76. package/src/events/events_block_drag_end.js +0 -33
  77. package/src/events/events_block_drag_outside.js +0 -30
  78. package/src/procedures.js +0 -425
  79. package/src/recyclable_block_flyout_inflater.js +0 -194
  80. package/src/renderer/renderer.js +0 -74
  81. package/src/scratch_blocks_utils.js +0 -148
  82. package/src/scratch_connection_checker.js +0 -29
  83. package/src/scratch_continuous_toolbox.js +0 -78
  84. package/src/scratch_variable_model.js +0 -24
  85. /package/{continuous-toolbox.d.ts → types/continuous-toolbox.d.ts} +0 -0
@@ -36,124 +36,87 @@ import * as Blockly from "blockly/core";
36
36
  * @constructor
37
37
  */
38
38
  export class FieldNote extends Blockly.FieldTextInput {
39
- constructor(opt_value, opt_validator) {
40
- opt_value = opt_value && !isNaN(opt_value) ? String(opt_value) : "0";
41
- super(opt_value, opt_validator);
42
-
43
- /**
44
- * Width of the field. Computed when drawing it, and used for animation.
45
- * @type {number}
46
- * @private
47
- */
48
- this.fieldEditorWidth_ = 0;
49
-
50
- /**
51
- * Height of the field. Computed when drawing it.
52
- * @type {number}
53
- * @private
54
- */
55
- this.fieldEditorHeight_ = 0;
56
-
57
- /**
58
- * The piano SVG.
59
- * @type {SVGElement}
60
- * @private
61
- */
62
- this.pianoSVG_ = null;
39
+ /**
40
+ * Width of the field. Computed when drawing it, and used for animation.
41
+ */
42
+ private fieldEditorWidth_ = 0;
63
43
 
64
- /**
65
- * Array of SVG elements representing the clickable piano keys.
66
- * @type {!Array<SVGElement>}
67
- * @private
68
- */
69
- this.keySVGs_ = [];
44
+ /**
45
+ * Height of the field. Computed when drawing it.
46
+ */
47
+ private fieldEditorHeight_ = 0;
70
48
 
71
- /**
72
- * Note name indicator at the top of the field.
73
- * @type {SVGElement}
74
- * @private
75
- */
76
- this.noteNameText_ = null;
49
+ /**
50
+ * The piano SVG.
51
+ */
52
+ private pianoSVG_: SVGElement | null = null;
77
53
 
78
- /**
79
- * Note name indicator on the low C key.
80
- * @type {SVGElement}
81
- * @private
82
- */
83
- this.lowCText_ = null;
54
+ /**
55
+ * Array of SVG elements representing the clickable piano keys.
56
+ */
57
+ private keySVGs_: SVGElement[] = [];
84
58
 
85
- /**
86
- * Note name indicator on the low C key.
87
- * @type {SVGElement}
88
- * @private
89
- */
90
- this.highCText_ = null;
59
+ /**
60
+ * Note name indicator at the top of the field.
61
+ */
62
+ private noteNameText_: SVGElement | null = null;
91
63
 
92
- /**
93
- * Octave number of the currently displayed range of keys.
94
- * @type {number}
95
- * @private
96
- */
97
- this.displayedOctave_ = null;
98
-
99
- /**
100
- * Current animation position of the piano SVG, as it shifts left or right to
101
- * change octaves.
102
- * @type {number}
103
- * @private
104
- */
105
- this.animationPos_ = 0;
64
+ /**
65
+ * Note name indicator on the low C key.
66
+ */
67
+ private lowCText_: SVGElement | null = null;
106
68
 
107
- /**
108
- * Target position for the animation as the piano SVG shifts left or right.
109
- * @type {number}
110
- * @private
111
- */
112
- this.animationTarget_ = 0;
113
-
114
- /**
115
- * A flag indicating that the mouse is currently down. Used in combination with
116
- * mouse enter events to update the key selection while dragging.
117
- * @type {boolean}
118
- * @private
119
- */
120
- this.mouseIsDown_ = false;
69
+ /**
70
+ * Note name indicator on the low C key.
71
+ */
72
+ private highCText_: SVGElement | null = null;
121
73
 
122
- /**
123
- * An array of wrappers for mouse down events on piano keys.
124
- * @type {!Array.<!Array>}
125
- * @private
126
- */
127
- this.mouseDownWrappers_ = [];
128
-
129
- /**
130
- * A wrapper for the mouse up event.
131
- * @type {!Array.<!Array>}
132
- * @private
133
- */
134
- this.mouseUpWrapper_ = null;
74
+ /**
75
+ * Octave number of the currently displayed range of keys.
76
+ */
77
+ private displayedOctave_: number | null = null;
135
78
 
136
- /**
137
- * An array of wrappers for mouse enter events on piano keys.
138
- * @type {!Array.<!Array>}
139
- * @private
140
- */
141
- this.mouseEnterWrappers_ = [];
142
-
143
- /**
144
- * A wrapper for the mouse down event on the octave down button.
145
- * @type {!Array.<!Array>}
146
- * @private
147
- */
148
- this.octaveDownMouseDownWrapper_ = null;
149
-
150
- /**
151
- * A wrapper for the mouse down event on the octave up button.
152
- * @type {!Array.<!Array>}
153
- * @private
154
- */
155
- this.octaveUpMouseDownWrapper_ = null;
156
- }
79
+ /**
80
+ * Current animation position of the piano SVG, as it shifts left or right to
81
+ * change octaves.
82
+ */
83
+ private animationPos_ = 0;
84
+
85
+ /**
86
+ * Target position for the animation as the piano SVG shifts left or right.
87
+ */
88
+ private animationTarget_ = 0;
89
+
90
+ /**
91
+ * A flag indicating that the mouse is currently down. Used in combination with
92
+ * mouse enter events to update the key selection while dragging.
93
+ */
94
+ private mouseIsDown_ = false;
95
+
96
+ /**
97
+ * An array of wrappers for mouse down events on piano keys.
98
+ */
99
+ private mouseDownWrappers_: Blockly.browserEvents.Data[] = [];
100
+
101
+ /**
102
+ * A wrapper for the mouse up event.
103
+ */
104
+ private mouseUpWrapper_: Blockly.browserEvents.Data | null = null;
105
+
106
+ /**
107
+ * An array of wrappers for mouse enter events on piano keys.
108
+ */
109
+ private mouseEnterWrappers_: Blockly.browserEvents.Data[] = [];
110
+
111
+ /**
112
+ * A wrapper for the mouse down event on the octave down button.
113
+ */
114
+ private octaveDownMouseDownWrapper_: Blockly.browserEvents.Data | null = null;
115
+
116
+ /**
117
+ * A wrapper for the mouse down event on the octave up button.
118
+ */
119
+ private octaveUpMouseDownWrapper_: Blockly.browserEvents.Data | null = null;
157
120
 
158
121
  /**
159
122
  * Inset in pixels of content displayed in the field, caused by parent properties.
@@ -164,122 +127,88 @@ export class FieldNote extends Blockly.FieldTextInput {
164
127
 
165
128
  /**
166
129
  * Height of the top area of the field, in px.
167
- * @type {number}
168
- * @const
169
130
  */
170
- static TOP_MENU_HEIGHT = 32 - FieldNote.INSET;
131
+ static readonly TOP_MENU_HEIGHT = 32 - FieldNote.INSET;
171
132
 
172
133
  /**
173
134
  * Padding on the top and sides of the field, in px.
174
- * @type {number}
175
- * @const
176
135
  */
177
- static EDGE_PADDING = 1;
136
+ static readonly EDGE_PADDING = 1;
178
137
 
179
138
  /**
180
139
  * Height of the drop shadow on the piano, in px.
181
- * @type {number}
182
- * @const
183
140
  */
184
- static SHADOW_HEIGHT = 4;
141
+ static readonly SHADOW_HEIGHT = 4;
185
142
 
186
143
  /**
187
144
  * Color for the shadow on the piano.
188
- * @type {string}
189
- * @const
190
145
  */
191
- static SHADOW_COLOR = "#000";
146
+ static readonly SHADOW_COLOR = "#000";
192
147
 
193
148
  /**
194
149
  * Opacity for the shadow on the piano.
195
- * @type {string}
196
- * @const
197
150
  */
198
- static SHADOW_OPACITY = 0.2;
151
+ static readonly SHADOW_OPACITY = 0.2;
199
152
 
200
153
  /**
201
154
  * A color for the white piano keys.
202
- * @type {string}
203
- * @const
204
155
  */
205
- static WHITE_KEY_COLOR = "#FFFFFF";
156
+ static readonly WHITE_KEY_COLOR = "#FFFFFF";
206
157
 
207
158
  /**
208
159
  * A color for the black piano keys.
209
- * @type {string}
210
- * @const
211
160
  */
212
- static BLACK_KEY_COLOR = "#323133";
161
+ static readonly BLACK_KEY_COLOR = "#323133";
213
162
 
214
163
  /**
215
164
  * A color for stroke around black piano keys.
216
- * @type {string}
217
- * @const
218
165
  */
219
- static BLACK_KEY_STROKE = "#555555";
166
+ static readonly BLACK_KEY_STROKE = "#555555";
220
167
 
221
168
  /**
222
169
  * A color for the selected state of a piano key.
223
- * @type {string}
224
- * @const
225
170
  */
226
- static KEY_SELECTED_COLOR = "#b0d6ff";
171
+ static readonly KEY_SELECTED_COLOR = "#b0d6ff";
227
172
 
228
173
  /**
229
174
  * The number of white keys in one octave on the piano.
230
- * @type {number}
231
- * @const
232
175
  */
233
- static NUM_WHITE_KEYS = 8;
176
+ static readonly NUM_WHITE_KEYS = 8;
234
177
 
235
178
  /**
236
179
  * Height of a white piano key, in px.
237
- * @type {string}
238
- * @const
239
180
  */
240
- static WHITE_KEY_HEIGHT = 72;
181
+ static readonly WHITE_KEY_HEIGHT = 72;
241
182
 
242
183
  /**
243
184
  * Width of a white piano key, in px.
244
- * @type {string}
245
- * @const
246
185
  */
247
- static WHITE_KEY_WIDTH = 40;
186
+ static readonly WHITE_KEY_WIDTH = 40;
248
187
 
249
188
  /**
250
189
  * Height of a black piano key, in px.
251
- * @type {string}
252
- * @const
253
190
  */
254
- static BLACK_KEY_HEIGHT = 40;
191
+ static readonly BLACK_KEY_HEIGHT = 40;
255
192
 
256
193
  /**
257
194
  * Width of a black piano key, in px.
258
- * @type {string}
259
- * @const
260
195
  */
261
- static BLACK_KEY_WIDTH = 32;
196
+ static readonly BLACK_KEY_WIDTH = 32;
262
197
 
263
198
  /**
264
199
  * Radius of the curved bottom corner of a piano key, in px.
265
- * @type {string}
266
- * @const
267
200
  */
268
- static KEY_RADIUS = 6;
201
+ static readonly KEY_RADIUS = 6;
269
202
 
270
203
  /**
271
204
  * Bottom padding for the labels on C keys.
272
- * @type {string}
273
- * @const
274
205
  */
275
- static KEY_LABEL_PADDING = 8;
206
+ static readonly KEY_LABEL_PADDING = 8;
276
207
 
277
208
  /**
278
209
  * An array of objects with data describing the keys on the piano.
279
- * @type {Array.<{name: String, pitch: Number, isBlack: boolean}>}
280
- * @const
281
210
  */
282
- static KEY_INFO = [
211
+ static readonly KEY_INFO = [
283
212
  { name: "C", pitch: 0 },
284
213
  { name: "C♯", pitch: 1, isBlack: true },
285
214
  { name: "D", pitch: 2 },
@@ -297,48 +226,37 @@ export class FieldNote extends Blockly.FieldTextInput {
297
226
 
298
227
  /**
299
228
  * The MIDI note number of the highest note selectable on the piano.
300
- * @type {number}
301
- * @const
302
229
  */
303
- static MAX_NOTE = 130;
230
+ static readonly MAX_NOTE = 130;
304
231
 
305
232
  /**
306
233
  * The fraction of the distance to the target location to move the piano at each
307
234
  * step of the animation.
308
- * @type {number}
309
- * @const
310
235
  */
311
- static ANIMATION_FRACTION = 0.2;
236
+ static readonly ANIMATION_FRACTION = 0.2;
312
237
 
313
238
  /**
314
239
  * Path to the arrow svg icon, used on the octave buttons.
315
- * @type {string}
316
- * @const
317
240
  */
318
- static ARROW_SVG_PATH = "icons/arrow_button.svg";
241
+ static readonly ARROW_SVG_PATH = "icons/arrow_button.svg";
319
242
 
320
243
  /**
321
244
  * The size of the square octave buttons.
322
- * @type {number}
323
- * @const
324
245
  */
325
- static OCTAVE_BUTTON_SIZE = 32;
246
+ static readonly OCTAVE_BUTTON_SIZE = 32;
326
247
 
327
248
  /**
328
249
  * Construct a FieldNote from a JSON arg object.
329
- * @param {!Object} options A JSON object with options.
330
- * @returns {!Blockly.FieldNote} The new field instance.
331
- * @package
332
- * @nocollapse
250
+ *
251
+ * @param options A JSON object with options.
252
+ * @returns The new field instance.
333
253
  */
334
- static fromJson(options) {
254
+ static fromJson(options: FieldNoteJsonConfig): FieldNote {
335
255
  return new FieldNote(options["note"]);
336
256
  }
337
257
 
338
258
  /**
339
259
  * Clean up this FieldNote, as well as the inherited FieldTextInput.
340
- * @return {!Function} Closure to call on destruction of the WidgetDiv.
341
- * @private
342
260
  */
343
261
  dispose() {
344
262
  super.dispose();
@@ -366,13 +284,12 @@ export class FieldNote extends Blockly.FieldTextInput {
366
284
 
367
285
  /**
368
286
  * Show a field with piano keys.
369
- * @private
370
287
  */
371
- showEditor_(event, quietInput = false) {
288
+ showEditor_(event: PointerEvent, quietInput = false) {
372
289
  super.showEditor_(event, quietInput);
373
290
 
374
291
  // Build the SVG DOM.
375
- var div = Blockly.DropDownDiv.getContentDiv();
292
+ const div = Blockly.DropDownDiv.getContentDiv();
376
293
 
377
294
  this.fieldEditorWidth_ =
378
295
  FieldNote.NUM_WHITE_KEYS * FieldNote.WHITE_KEY_WIDTH +
@@ -382,7 +299,7 @@ export class FieldNote extends Blockly.FieldTextInput {
382
299
  FieldNote.WHITE_KEY_HEIGHT +
383
300
  FieldNote.EDGE_PADDING;
384
301
 
385
- var svg = Blockly.utils.dom.createSvgElement(
302
+ const svg = Blockly.utils.dom.createSvgElement(
386
303
  "svg",
387
304
  {
388
305
  xmlns: "http://www.w3.org/2000/svg",
@@ -399,12 +316,12 @@ export class FieldNote extends Blockly.FieldTextInput {
399
316
  // Since we are adding the keys from left to right in order, they need
400
317
  // to be in two groups in order to layer correctly.
401
318
  this.pianoSVG_ = Blockly.utils.dom.createSvgElement("g", {}, svg);
402
- var whiteKeyGroup = Blockly.utils.dom.createSvgElement(
319
+ const whiteKeyGroup = Blockly.utils.dom.createSvgElement(
403
320
  "g",
404
321
  {},
405
322
  this.pianoSVG_
406
323
  );
407
- var blackKeyGroup = Blockly.utils.dom.createSvgElement(
324
+ const blackKeyGroup = Blockly.utils.dom.createSvgElement(
408
325
  "g",
409
326
  {},
410
327
  this.pianoSVG_
@@ -441,9 +358,9 @@ export class FieldNote extends Blockly.FieldTextInput {
441
358
  );
442
359
 
443
360
  // Note names on the low and high C keys
444
- var lowCX = FieldNote.WHITE_KEY_WIDTH / 2;
361
+ const lowCX = FieldNote.WHITE_KEY_WIDTH / 2;
445
362
  this.lowCText_ = this.addCKeyLabel_(lowCX, svg);
446
- var highCX =
363
+ const highCX =
447
364
  lowCX + FieldNote.WHITE_KEY_WIDTH * (FieldNote.NUM_WHITE_KEYS - 1);
448
365
  this.highCText_ = this.addCKeyLabel_(highCX, svg);
449
366
 
@@ -451,7 +368,9 @@ export class FieldNote extends Blockly.FieldTextInput {
451
368
  Blockly.utils.dom.createSvgElement(
452
369
  "line",
453
370
  {
454
- stroke: this.sourceBlock_.parentBlock_.getColourTertiary(),
371
+ stroke: (
372
+ this.sourceBlock_.getParent() as Blockly.BlockSvg
373
+ ).getColourTertiary(),
455
374
  x1: 0,
456
375
  y1: FieldNote.TOP_MENU_HEIGHT,
457
376
  x2: this.fieldEditorWidth_,
@@ -475,8 +394,8 @@ export class FieldNote extends Blockly.FieldTextInput {
475
394
  );
476
395
 
477
396
  // Octave buttons
478
- this.octaveDownButton = this.addOctaveButton_(0, true, svg);
479
- this.octaveUpButton = this.addOctaveButton_(
397
+ const octaveDownButton = this.addOctaveButton_(0, true, svg);
398
+ const octaveUpButton = this.addOctaveButton_(
480
399
  this.fieldEditorWidth_ +
481
400
  FieldNote.INSET * 2 -
482
401
  FieldNote.OCTAVE_BUTTON_SIZE,
@@ -485,7 +404,7 @@ export class FieldNote extends Blockly.FieldTextInput {
485
404
  );
486
405
 
487
406
  this.octaveDownMouseDownWrapper_ = Blockly.browserEvents.bind(
488
- this.octaveDownButton,
407
+ octaveDownButton,
489
408
  "mousedown",
490
409
  this,
491
410
  function () {
@@ -493,34 +412,40 @@ export class FieldNote extends Blockly.FieldTextInput {
493
412
  }
494
413
  );
495
414
  this.octaveUpMouseDownWrapper_ = Blockly.browserEvents.bind(
496
- this.octaveUpButton,
415
+ octaveUpButton,
497
416
  "mousedown",
498
417
  this,
499
418
  function () {
500
419
  this.changeOctaveBy_(1);
501
420
  }
502
421
  );
422
+ const sourceBlock = this.getSourceBlock() as Blockly.BlockSvg;
503
423
  Blockly.DropDownDiv.setColour(
504
- this.sourceBlock_.parentBlock_.getColour(),
505
- this.sourceBlock_.parentBlock_.getColourTertiary()
424
+ sourceBlock.getParent().getColour(),
425
+ sourceBlock.getParent().getColourTertiary()
506
426
  );
507
- Blockly.DropDownDiv.showPositionedByBlock(this, this.sourceBlock_);
427
+ Blockly.DropDownDiv.showPositionedByBlock(this, sourceBlock);
508
428
 
509
429
  this.updateSelection_();
510
430
  }
511
431
 
512
432
  /**
513
433
  * Add one octave of piano keys drawn using SVG.
514
- * @param {number} x The x position of the left edge of this octave of keys.
515
- * @param {SVGElement} whiteKeyGroup The group for all white piano keys.
516
- * @param {SvgElement} blackKeyGroup The group for all black piano keys.
517
- * @param {!Array.<SvgElement>} keySVGarray An array containing all the key SVGs.
518
- * @private
519
- */
520
- addPianoOctave_(x, whiteKeyGroup, blackKeyGroup, keySVGarray) {
521
- var xIncrement, width, height, fill, stroke, group;
434
+ *
435
+ * @param x The x position of the left edge of this octave of keys.
436
+ * @param whiteKeyGroup The group for all white piano keys.
437
+ * @param blackKeyGroup The group for all black piano keys.
438
+ * @param keySVGarray An array containing all the key SVGs.
439
+ */
440
+ private addPianoOctave_(
441
+ x: number,
442
+ whiteKeyGroup: SVGElement,
443
+ blackKeyGroup: SVGElement,
444
+ keySVGarray: SVGElement[]
445
+ ) {
446
+ let xIncrement, width, height, fill, stroke, group;
522
447
  x += FieldNote.EDGE_PADDING / 2;
523
- var y = FieldNote.TOP_MENU_HEIGHT;
448
+ const y = FieldNote.TOP_MENU_HEIGHT;
524
449
  for (var i = 0; i < FieldNote.KEY_INFO.length; i++) {
525
450
  // Draw a black or white key
526
451
  if (FieldNote.KEY_INFO[i].isBlack) {
@@ -537,23 +462,25 @@ export class FieldNote extends Blockly.FieldTextInput {
537
462
  width = FieldNote.WHITE_KEY_WIDTH;
538
463
  height = FieldNote.WHITE_KEY_HEIGHT;
539
464
  fill = FieldNote.WHITE_KEY_COLOR;
540
- stroke = this.sourceBlock_.parentBlock_.getColourTertiary();
465
+ stroke = (
466
+ this.sourceBlock_.getParent() as Blockly.BlockSvg
467
+ ).getColourTertiary();
541
468
  group = whiteKeyGroup;
542
469
  }
543
- var attr = {
470
+ const attr = {
544
471
  d: this.getPianoKeyPath_(x, y, width, height),
545
472
  fill: fill,
546
473
  stroke: stroke,
547
474
  };
548
475
  x += xIncrement;
549
476
 
550
- var keySVG = Blockly.utils.dom.createSvgElement("path", attr, group);
477
+ const keySVG = Blockly.utils.dom.createSvgElement("path", attr, group);
551
478
 
552
479
  if (keySVGarray) {
553
480
  keySVGarray[i] = keySVG;
554
- keySVG.setAttribute("data-pitch", FieldNote.KEY_INFO[i].pitch);
555
- keySVG.setAttribute("data-name", FieldNote.KEY_INFO[i].name);
556
- keySVG.setAttribute("data-isBlack", FieldNote.KEY_INFO[i].isBlack);
481
+ keySVG.setAttribute("data-pitch", `${FieldNote.KEY_INFO[i].pitch}`);
482
+ keySVG.setAttribute("data-name", `${FieldNote.KEY_INFO[i].name}`);
483
+ keySVG.setAttribute("data-isBlack", `${FieldNote.KEY_INFO[i].isBlack}`);
557
484
 
558
485
  this.mouseDownWrappers_[i] = Blockly.browserEvents.bind(
559
486
  keySVG,
@@ -574,14 +501,19 @@ export class FieldNote extends Blockly.FieldTextInput {
574
501
  /**
575
502
  * Construct the SVG path string for a piano key shape: a rectangle with rounded
576
503
  * corners at the bottom.
577
- * @param {number} x the x position for the key.
578
- * @param {number} y the y position for the key.
579
- * @param {number} width the width of the key.
580
- * @param {number} height the height of the key.
581
- * @returns {string} the SVG path as a string.
582
- * @private
583
- */
584
- getPianoKeyPath_(x, y, width, height) {
504
+ *
505
+ * @param x the x position for the key.
506
+ * @param y the y position for the key.
507
+ * @param width the width of the key.
508
+ * @param height the height of the key.
509
+ * @returns the SVG path as a string.
510
+ */
511
+ private getPianoKeyPath_(
512
+ x: number,
513
+ y: number,
514
+ width: number,
515
+ height: number
516
+ ): string {
585
517
  return (
586
518
  "M" +
587
519
  x +
@@ -630,16 +562,20 @@ export class FieldNote extends Blockly.FieldTextInput {
630
562
 
631
563
  /**
632
564
  * Add a button for switching the displayed octave of the piano up or down.
633
- * @param {number} x The x position of the button.
634
- * @param {boolean} flipped If true, the icon should be flipped.
635
- * @param {SvgElement} svg The svg element to add the buttons to.
636
- * @returns {SvgElement} A group containing the button SVG elements.
637
- * @private
638
- */
639
- addOctaveButton_(x, flipped, svg) {
640
- var group = Blockly.utils.dom.createSvgElement("g", {}, svg);
641
- var imageSize = FieldNote.OCTAVE_BUTTON_SIZE;
642
- var arrow = Blockly.utils.dom.createSvgElement(
565
+ *
566
+ * @param x The x position of the button.
567
+ * @param flipped If true, the icon should be flipped.
568
+ * @param svg The svg element to add the buttons to.
569
+ * @returns A group containing the button SVG elements.
570
+ */
571
+ private addOctaveButton_(
572
+ x: number,
573
+ flipped: boolean,
574
+ svg: SVGElement
575
+ ): SVGElement {
576
+ const group = Blockly.utils.dom.createSvgElement("g", {}, svg);
577
+ const imageSize = FieldNote.OCTAVE_BUTTON_SIZE;
578
+ const arrow = Blockly.utils.dom.createSvgElement(
643
579
  "image",
644
580
  {
645
581
  width: imageSize,
@@ -657,7 +593,9 @@ export class FieldNote extends Blockly.FieldTextInput {
657
593
  Blockly.utils.dom.createSvgElement(
658
594
  "line",
659
595
  {
660
- stroke: this.sourceBlock_.parentBlock_.getColourTertiary(),
596
+ stroke: (
597
+ this.sourceBlock_.getParent() as Blockly.BlockSvg
598
+ ).getColourTertiary(),
661
599
  x1: x - FieldNote.INSET,
662
600
  y1: 0,
663
601
  x2: x - FieldNote.INSET,
@@ -666,7 +604,8 @@ export class FieldNote extends Blockly.FieldTextInput {
666
604
  group
667
605
  );
668
606
  if (flipped) {
669
- var translateX = -1 * FieldNote.OCTAVE_BUTTON_SIZE + FieldNote.INSET * 2;
607
+ const translateX =
608
+ -1 * FieldNote.OCTAVE_BUTTON_SIZE + FieldNote.INSET * 2;
670
609
  group.setAttribute(
671
610
  "transform",
672
611
  "scale(-1, 1) " + "translate(" + translateX + ", 0)"
@@ -677,12 +616,12 @@ export class FieldNote extends Blockly.FieldTextInput {
677
616
 
678
617
  /**
679
618
  * Add an SVG text label for display on the C keys of the piano.
680
- * @param {number} x The x position for the label.
681
- * @param {SvgElement} svg The SVG element to add the label to.
682
- * @returns {SvgElement} The SVG element containing the label.
683
- * @private
619
+ *
620
+ * @param x The x position for the label.
621
+ * @param svg The SVG element to add the label to.
622
+ * @returns The SVG element containing the label.
684
623
  */
685
- addCKeyLabel_(x, svg) {
624
+ private addCKeyLabel_(x: number, svg: SVGElement): SVGElement {
686
625
  return Blockly.utils.dom.createSvgElement(
687
626
  "text",
688
627
  {
@@ -700,10 +639,10 @@ export class FieldNote extends Blockly.FieldTextInput {
700
639
 
701
640
  /**
702
641
  * Set the visibility of the C key labels.
703
- * @param {boolean} visible If true, set labels to be visible.
704
- * @private
642
+ *
643
+ * @param visible If true, set labels to be visible.
705
644
  */
706
- setCKeyLabelsVisible_(visible) {
645
+ private setCKeyLabelsVisible_(visible: boolean) {
707
646
  if (visible) {
708
647
  this.fadeSvgToOpacity_(this.lowCText_, 1);
709
648
  this.fadeSvgToOpacity_(this.highCText_, 1);
@@ -715,11 +654,11 @@ export class FieldNote extends Blockly.FieldTextInput {
715
654
 
716
655
  /**
717
656
  * Animate an SVG to fade it in or out to a target opacity.
718
- * @param {SvgElement} svg The SVG element to apply the fade to.
719
- * @param {number} opacity The target opacity.
720
- * @private
657
+ *
658
+ * @param svg The SVG element to apply the fade to.
659
+ * @param opacity The target opacity.
721
660
  */
722
- fadeSvgToOpacity_(svg, opacity) {
661
+ private fadeSvgToOpacity_(svg: SVGElement, opacity: number) {
723
662
  svg.setAttribute(
724
663
  "style",
725
664
  "opacity: " + opacity + "; transition: opacity 0.1s;"
@@ -728,10 +667,10 @@ export class FieldNote extends Blockly.FieldTextInput {
728
667
 
729
668
  /**
730
669
  * Handle the mouse down event on a piano key.
731
- * @param {!Event} e Mouse down event.
732
- * @private
670
+ *
671
+ * @param e Mouse down event.
733
672
  */
734
- onMouseDownOnKey_(e) {
673
+ private onMouseDownOnKey_(e: PointerEvent) {
735
674
  this.mouseIsDown_ = true;
736
675
  this.mouseUpWrapper_ = Blockly.browserEvents.bind(
737
676
  document.body,
@@ -744,9 +683,8 @@ export class FieldNote extends Blockly.FieldTextInput {
744
683
 
745
684
  /**
746
685
  * Handle the mouse up event following a mouse down on a piano key.
747
- * @private
748
686
  */
749
- onMouseUp_() {
687
+ private onMouseUp_() {
750
688
  this.mouseIsDown_ = false;
751
689
  Blockly.browserEvents.unbind(this.mouseUpWrapper_);
752
690
  this.mouseUpWrapper_ = null;
@@ -754,10 +692,10 @@ export class FieldNote extends Blockly.FieldTextInput {
754
692
 
755
693
  /**
756
694
  * Handle the event when the mouse enters a piano key.
757
- * @param {!Event} e Mouse enter event.
758
- * @private
695
+ *
696
+ * @param e Mouse enter event.
759
697
  */
760
- onMouseEnter_(e) {
698
+ private onMouseEnter_(e: PointerEvent) {
761
699
  if (this.mouseIsDown_) {
762
700
  this.selectNoteWithMouseEvent_(e);
763
701
  }
@@ -765,21 +703,21 @@ export class FieldNote extends Blockly.FieldTextInput {
765
703
 
766
704
  /**
767
705
  * Use the data in a mouse event to select a new note, and play it.
768
- * @param {!Event} e Mouse event.
769
- * @private
706
+ *
707
+ * @param e Mouse event.
770
708
  */
771
- selectNoteWithMouseEvent_(e) {
772
- var newNoteNum =
773
- Number(e.target.getAttribute("data-pitch")) + this.displayedOctave_ * 12;
709
+ private selectNoteWithMouseEvent_(e: PointerEvent) {
710
+ const newNoteNum =
711
+ Number((e.target as HTMLElement).getAttribute("data-pitch")) +
712
+ this.displayedOctave_ * 12;
774
713
  this.setEditorValue_(newNoteNum);
775
714
  this.playNoteInternal_();
776
715
  }
777
716
 
778
717
  /**
779
718
  * Play a note, by calling the externally overriden play note function.
780
- * @private
781
719
  */
782
- playNoteInternal_() {
720
+ private playNoteInternal_() {
783
721
  if (FieldNote.playNote_) {
784
722
  FieldNote.playNote_(Number(this.getValue()), "Music");
785
723
  }
@@ -788,32 +726,32 @@ export class FieldNote extends Blockly.FieldTextInput {
788
726
  /**
789
727
  * Function to play a musical note corresponding to the key selected.
790
728
  * Overridden externally.
791
- * @param {number} noteNum the MIDI note number to play.
792
- * @param {string} id An id to select a scratch extension to play the note.
793
- * @private
729
+ *
730
+ * @param noteNum the MIDI note number to play.
731
+ * @param id An id to select a scratch extension to play the note.
794
732
  */
795
- static playNote_ = function (/* noteNum, id*/) {
733
+ static playNote_ = function (noteNum: number, id: string) {
796
734
  return;
797
735
  };
798
736
 
799
737
  /**
800
738
  * Change the selected note by a number of octaves, and start the animation.
801
- * @param {number} octaves The number of octaves to change by.
802
- * @private
739
+ *
740
+ * @param octaves The number of octaves to change by.
803
741
  */
804
- changeOctaveBy_(octaves) {
742
+ private changeOctaveBy_(octaves: number) {
805
743
  this.displayedOctave_ += octaves;
806
744
  if (this.displayedOctave_ < 0) {
807
745
  this.displayedOctave_ = 0;
808
746
  return;
809
747
  }
810
- var maxOctave = Math.floor(FieldNote.MAX_NOTE / 12);
748
+ const maxOctave = Math.floor(FieldNote.MAX_NOTE / 12);
811
749
  if (this.displayedOctave_ > maxOctave) {
812
750
  this.displayedOctave_ = maxOctave;
813
751
  return;
814
752
  }
815
753
 
816
- var newNote = Number(this.getText()) + octaves * 12;
754
+ const newNote = Number(this.getText()) + octaves * 12;
817
755
  this.setEditorValue_(newNote);
818
756
 
819
757
  this.animationTarget_ = this.fieldEditorWidth_ * octaves * -1;
@@ -824,10 +762,9 @@ export class FieldNote extends Blockly.FieldTextInput {
824
762
 
825
763
  /**
826
764
  * Animate the piano up or down an octave by sliding it to the left or right.
827
- * @private
828
765
  */
829
- stepOctaveAnimation_() {
830
- var absDiff = Math.abs(this.animationPos_ - this.animationTarget_);
766
+ private stepOctaveAnimation_() {
767
+ const absDiff = Math.abs(this.animationPos_ - this.animationTarget_);
831
768
  if (absDiff < 1) {
832
769
  this.pianoSVG_.setAttribute("transform", "translate(0, 0)");
833
770
  this.setCKeyLabelsVisible_(true);
@@ -844,7 +781,7 @@ export class FieldNote extends Blockly.FieldTextInput {
844
781
  requestAnimationFrame(this.stepOctaveAnimation_.bind(this));
845
782
  }
846
783
 
847
- doValueUpdate_(newValue) {
784
+ doValueUpdate_(newValue: string) {
848
785
  super.doValueUpdate_(newValue);
849
786
 
850
787
  if (!this.textElement_) {
@@ -857,20 +794,19 @@ export class FieldNote extends Blockly.FieldTextInput {
857
794
 
858
795
  /**
859
796
  * For a MIDI note number, find the index of the corresponding piano key.
860
- * @param {number} noteNum The note number.
861
- * @returns {number} The index of the piano key.
862
- * @private
797
+ *
798
+ * @param noteNum The note number.
799
+ * @returns The index of the piano key.
863
800
  */
864
- noteNumToKeyIndex_(noteNum) {
801
+ private noteNumToKeyIndex_(noteNum: number): number {
865
802
  return Math.floor(noteNum) - this.displayedOctave_ * 12;
866
803
  }
867
804
 
868
805
  /**
869
806
  * Update the selected note and labels on the field.
870
- * @private
871
807
  */
872
- updateSelection_() {
873
- var noteNum = Number(this.getText());
808
+ private updateSelection_() {
809
+ const noteNum = Number(this.getText());
874
810
 
875
811
  // If the note is outside the currently displayed octave, update it
876
812
  if (
@@ -881,11 +817,11 @@ export class FieldNote extends Blockly.FieldTextInput {
881
817
  this.displayedOctave_ = Math.floor(noteNum / 12);
882
818
  }
883
819
 
884
- var index = this.noteNumToKeyIndex_(noteNum);
820
+ const index = this.noteNumToKeyIndex_(noteNum);
885
821
 
886
822
  // Clear the highlight on all keys
887
823
  this.keySVGs_.forEach(function (svg) {
888
- var isBlack = svg.getAttribute("data-isBlack");
824
+ const isBlack = svg.getAttribute("data-isBlack");
889
825
  if (isBlack === "true") {
890
826
  svg.setAttribute("fill", FieldNote.BLACK_KEY_COLOR);
891
827
  } else {
@@ -896,11 +832,11 @@ export class FieldNote extends Blockly.FieldTextInput {
896
832
  if (this.keySVGs_[index]) {
897
833
  this.keySVGs_[index].setAttribute("fill", FieldNote.KEY_SELECTED_COLOR);
898
834
  // Update the note name text
899
- var noteName = FieldNote.KEY_INFO[index].name;
835
+ const noteName = FieldNote.KEY_INFO[index].name;
900
836
  this.noteNameText_.textContent =
901
837
  noteName + " (" + Math.floor(noteNum) + ")";
902
838
  // Update the low and high C note names
903
- var lowCNum = this.displayedOctave_ * 12;
839
+ const lowCNum = this.displayedOctave_ * 12;
904
840
  this.lowCText_.textContent = "C(" + lowCNum + ")";
905
841
  this.highCText_.textContent = "C(" + (lowCNum + 12) + ")";
906
842
  }
@@ -908,14 +844,15 @@ export class FieldNote extends Blockly.FieldTextInput {
908
844
 
909
845
  /**
910
846
  * Ensure that only a valid MIDI note number may be entered.
911
- * @param {string} text The user's text.
912
- * @return {?string} A string representing a valid note number, or null if invalid.
847
+ *
848
+ * @param text The user's text.
849
+ * @returns A string representing a valid note number, or null if invalid.
913
850
  */
914
- doClassValidation_(text) {
851
+ doClassValidation_(text: string): string | null {
915
852
  if (text === null) {
916
853
  return null;
917
854
  }
918
- var n = parseFloat(text || 0);
855
+ var n = parseFloat(text || "0");
919
856
  if (isNaN(n)) {
920
857
  return null;
921
858
  }
@@ -929,6 +866,10 @@ export class FieldNote extends Blockly.FieldTextInput {
929
866
  }
930
867
  }
931
868
 
869
+ interface FieldNoteJsonConfig extends Blockly.FieldTextInputFromJsonConfig {
870
+ note: string;
871
+ }
872
+
932
873
  /**
933
874
  * Register the field and any dependencies.
934
875
  */