scratch-blocks 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -1
- package/commitlint.config.js +1 -1
- package/dist/main.mjs +1 -1
- package/dist/types/src/blocks/procedures.d.ts +1 -1
- package/dist/types/src/blocks/procedures.d.ts.map +1 -1
- package/dist/types/src/checkable_continuous_flyout.d.ts +1 -1
- package/dist/types/src/checkable_continuous_flyout.d.ts.map +1 -1
- package/dist/types/src/fields/field_colour_slider.d.ts +22 -0
- package/dist/types/src/fields/field_colour_slider.d.ts.map +1 -1
- package/dist/types/src/fields/field_note.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/recyclable_block_flyout_inflater.d.ts +1 -1
- package/dist/types/src/recyclable_block_flyout_inflater.d.ts.map +1 -1
- package/dist/types/src/renderer/path_object.d.ts.map +1 -1
- package/dist/types/src/scratch_continuous_category.d.ts +1 -1
- package/dist/types/src/scratch_continuous_category.d.ts.map +1 -1
- package/dist/types/src/scratch_continuous_toolbox.d.ts +1 -1
- package/dist/types/src/scratch_continuous_toolbox.d.ts.map +1 -1
- package/dist/types/src/scratch_dragger.d.ts +2 -2
- package/dist/types/src/scratch_dragger.d.ts.map +1 -1
- package/i18n/sync_tx_translations.js +1 -1
- package/i18n/test_scratch_msgs.js +2 -2
- package/package.json +10 -10
- package/src/blocks/procedures.ts +84 -24
- package/src/blocks/vertical_extensions.ts +34 -10
- package/src/checkable_continuous_flyout.ts +1 -1
- package/src/context_menu_items.ts +1 -1
- package/src/data_category.ts +3 -3
- package/src/fields/field_colour_slider.ts +1 -1
- package/src/fields/field_note.ts +3 -3
- package/src/fields/scratch_field_variable.ts +2 -2
- package/src/index.ts +1 -1
- package/src/procedures.ts +9 -9
- package/src/recyclable_block_flyout_inflater.ts +1 -1
- package/src/renderer/path_object.ts +9 -5
- package/src/renderer/render_info.ts +3 -3
- package/src/scratch_connection_checker.ts +16 -0
- package/src/scratch_continuous_category.ts +1 -1
- package/src/scratch_continuous_toolbox.ts +1 -1
- package/src/scratch_dragger.ts +15 -8
- package/src/scratch_variable_map.ts +1 -1
package/src/procedures.ts
CHANGED
|
@@ -32,8 +32,8 @@ import * as Constants from './constants'
|
|
|
32
32
|
function allProcedureMutations(root: Blockly.WorkspaceSvg): Element[] {
|
|
33
33
|
const blocks = root.getAllBlocks()
|
|
34
34
|
return blocks
|
|
35
|
-
.filter(b => b.type === Constants.PROCEDURES_PROTOTYPE_BLOCK_TYPE)
|
|
36
|
-
.map(b => b.mutationToDom!(/* opt_generateShadows */ true))
|
|
35
|
+
.filter((b) => b.type === Constants.PROCEDURES_PROTOTYPE_BLOCK_TYPE)
|
|
36
|
+
.map((b) => b.mutationToDom!(/* opt_generateShadows */ true))
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -118,7 +118,7 @@ export function getCallers(
|
|
|
118
118
|
definitionRoot: Blockly.BlockSvg,
|
|
119
119
|
allowRecursive: boolean,
|
|
120
120
|
): Blockly.BlockSvg[] {
|
|
121
|
-
return workspace.getTopBlocks().flatMap(block => {
|
|
121
|
+
return workspace.getTopBlocks().flatMap((block) => {
|
|
122
122
|
if (block.id === definitionRoot.id && !allowRecursive) {
|
|
123
123
|
return []
|
|
124
124
|
}
|
|
@@ -126,7 +126,7 @@ export function getCallers(
|
|
|
126
126
|
return block
|
|
127
127
|
.getDescendants(false)
|
|
128
128
|
.filter(
|
|
129
|
-
descendant =>
|
|
129
|
+
(descendant) =>
|
|
130
130
|
isProcedureBlock(descendant) &&
|
|
131
131
|
descendant.type === Constants.PROCEDURES_CALL_BLOCK_TYPE &&
|
|
132
132
|
descendant.getProcCode() === name,
|
|
@@ -151,7 +151,7 @@ function mutateCallersAndPrototype(name: string, workspace: Blockly.WorkspaceSvg
|
|
|
151
151
|
const callers = getCallers(name, defineBlock.workspace, defineBlock, true /* allowRecursive */)
|
|
152
152
|
callers.push(prototypeBlock)
|
|
153
153
|
Blockly.Events.setGroup(true)
|
|
154
|
-
callers.forEach(caller => {
|
|
154
|
+
callers.forEach((caller) => {
|
|
155
155
|
const oldMutationDom = caller.mutationToDom!()
|
|
156
156
|
const oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom)
|
|
157
157
|
caller.domToMutation!(mutation)
|
|
@@ -174,7 +174,7 @@ function mutateCallersAndPrototype(name: string, workspace: Blockly.WorkspaceSvg
|
|
|
174
174
|
*/
|
|
175
175
|
function getDefineBlock(procCode: string, workspace: Blockly.WorkspaceSvg): Blockly.BlockSvg | undefined {
|
|
176
176
|
// Assume that a procedure definition is a top block.
|
|
177
|
-
return workspace.getTopBlocks(false).find(block => {
|
|
177
|
+
return workspace.getTopBlocks(false).find((block) => {
|
|
178
178
|
if (block.type === Constants.PROCEDURES_DEFINITION_BLOCK_TYPE) {
|
|
179
179
|
const prototypeBlock = block.getInput('custom_block')!.connection!.targetBlock() as Blockly.BlockSvg
|
|
180
180
|
return isProcedureBlock(prototypeBlock) && prototypeBlock.getProcCode() === procCode
|
|
@@ -237,9 +237,9 @@ function createProcedureCallbackFactory(workspace: Blockly.WorkspaceSvg): (mutat
|
|
|
237
237
|
<xml>
|
|
238
238
|
<block type="procedures_definition">
|
|
239
239
|
<statement name="custom_block">
|
|
240
|
-
<
|
|
240
|
+
<block type="procedures_prototype">
|
|
241
241
|
${Blockly.Xml.domToText(mutation)}
|
|
242
|
-
</
|
|
242
|
+
</block>
|
|
243
243
|
</statement>
|
|
244
244
|
</block>
|
|
245
245
|
</xml>`
|
|
@@ -285,7 +285,7 @@ function editProcedureCallback(block: Blockly.BlockSvg) {
|
|
|
285
285
|
return
|
|
286
286
|
}
|
|
287
287
|
const innerBlock = conn.targetBlock()
|
|
288
|
-
if (
|
|
288
|
+
if (innerBlock?.type !== Constants.PROCEDURES_PROTOTYPE_BLOCK_TYPE) {
|
|
289
289
|
alert('Bad inner block') // TODO: Decide what to do about this.
|
|
290
290
|
return
|
|
291
291
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Copyright 2024 Google LLC
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import * as Blockly from 'blockly/core'
|
|
6
5
|
import { RecyclableBlockFlyoutInflater as BlocklyRecyclableBlockFlyoutInflater } from '@blockly/continuous-toolbox'
|
|
6
|
+
import * as Blockly from 'blockly/core'
|
|
7
7
|
import { CheckboxBubble } from './checkbox_bubble'
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -17,11 +17,15 @@ export class PathObject extends Blockly.zelos.PathObject {
|
|
|
17
17
|
override applyColour(block: Blockly.BlockSvg) {
|
|
18
18
|
super.applyColour(block)
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
// The prototype block is no longer a Blockly shadow, but it should still
|
|
21
|
+
// visually appear as one (using colourSecondary, the shadow fill colour).
|
|
22
|
+
if (block.type === 'procedures_prototype') {
|
|
23
|
+
this.svgPath.setAttribute('fill', this.style.colourSecondary)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Argument reporter blocks sit inside the prototype (which now renders with
|
|
27
|
+
// the shadow/secondary colour), so they need the full primary colour to
|
|
28
|
+
// stand out, just as they did when the prototype was a real shadow block.
|
|
25
29
|
if (block.type === 'argument_reporter_string_number' || block.type === 'argument_reporter_boolean') {
|
|
26
30
|
this.svgPath.setAttribute('fill', this.style.colourPrimary)
|
|
27
31
|
}
|
|
@@ -36,16 +36,16 @@ export class RenderInfo extends Blockly.zelos.RenderInfo {
|
|
|
36
36
|
// bowler hat block.
|
|
37
37
|
// Bowler hat blocks always have exactly one statement row and one input
|
|
38
38
|
// element, so these find() calls are guaranteed to succeed.
|
|
39
|
-
const statementRow = this.rows.find(r => r.hasStatement)!
|
|
39
|
+
const statementRow = this.rows.find((r) => r.hasStatement)!
|
|
40
40
|
this.width =
|
|
41
41
|
statementRow.widthWithConnectedBlocks -
|
|
42
|
-
statementRow.elements.find(e => Blockly.blockRendering.Types.isInput(e))!.width +
|
|
42
|
+
statementRow.elements.find((e) => Blockly.blockRendering.Types.isInput(e))!.width +
|
|
43
43
|
this.constants_.MEDIUM_PADDING
|
|
44
44
|
|
|
45
45
|
// The bowler hat's width is the same as the block's width, so it can't
|
|
46
46
|
// be derived from the constants like a normal hat and has to be set here.
|
|
47
47
|
// populateTopRow_ always adds a hat element for bowler hat blocks.
|
|
48
|
-
const hat = this.topRow.elements.find(e => Blockly.blockRendering.Types.isHat(e))!
|
|
48
|
+
const hat = this.topRow.elements.find((e) => Blockly.blockRendering.Types.isHat(e))!
|
|
49
49
|
hat.width = this.width
|
|
50
50
|
this.topRow.measure()
|
|
51
51
|
}
|
|
@@ -8,6 +8,22 @@ import * as Blockly from 'blockly/core'
|
|
|
8
8
|
* Custom connection checker to restrict which blocks can be connected.
|
|
9
9
|
*/
|
|
10
10
|
class ScratchConnectionChecker extends Blockly.ConnectionChecker {
|
|
11
|
+
override canConnectWithReason(
|
|
12
|
+
a: Blockly.Connection | null,
|
|
13
|
+
b: Blockly.Connection | null,
|
|
14
|
+
isDragging: boolean,
|
|
15
|
+
opt_distance?: number,
|
|
16
|
+
): number {
|
|
17
|
+
// The prototype's next connection is visual-only and should not accept any connections.
|
|
18
|
+
const isPrototypeNextConn = (c: Blockly.Connection | null) =>
|
|
19
|
+
c?.type === Blockly.ConnectionType.NEXT_STATEMENT &&
|
|
20
|
+
c.getSourceBlock().type === 'procedures_prototype'
|
|
21
|
+
if (isPrototypeNextConn(a) || isPrototypeNextConn(b)) {
|
|
22
|
+
return Blockly.Connection.REASON_CHECKS_FAILED
|
|
23
|
+
}
|
|
24
|
+
return super.canConnectWithReason(a, b, isDragging, opt_distance)
|
|
25
|
+
}
|
|
26
|
+
|
|
11
27
|
/**
|
|
12
28
|
* Returns whether or not the two connections should be allowed to connect.
|
|
13
29
|
* @param a One of the connections to check.
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Copyright 2024 Google LLC
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import * as Blockly from 'blockly/core'
|
|
6
5
|
import { ContinuousCategory } from '@blockly/continuous-toolbox'
|
|
6
|
+
import * as Blockly from 'blockly/core'
|
|
7
7
|
|
|
8
8
|
type StatusIndicatorCategoryInfo = Blockly.utils.toolbox.CategoryInfo & {
|
|
9
9
|
showStatusButton?: string
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Copyright 2024 Google LLC
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import * as Blockly from 'blockly/core'
|
|
6
5
|
import { ContinuousToolbox } from '@blockly/continuous-toolbox'
|
|
6
|
+
import * as Blockly from 'blockly/core'
|
|
7
7
|
import { ScratchContinuousCategory } from './scratch_continuous_category'
|
|
8
8
|
import { STATUS_INDICATOR_LABEL_TYPE } from './status_indicator_label_flyout_inflater'
|
|
9
9
|
|
package/src/scratch_dragger.ts
CHANGED
|
@@ -84,16 +84,20 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
|
|
|
84
84
|
* @param event The event that ended the drag.
|
|
85
85
|
*/
|
|
86
86
|
onDragEnd(event: PointerEvent) {
|
|
87
|
+
// When the prototype block is dragged (via its DelegateToParentDraggable
|
|
88
|
+
// strategy), this.draggable is the prototype, but getDragRoot returns the
|
|
89
|
+
// definition. Handle both cases for the "procedure is in use" check.
|
|
90
|
+
const dragRoot = this.getDragRoot(this.draggable)
|
|
87
91
|
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.wouldDeleteDraggable(event,
|
|
92
|
+
dragRoot instanceof Blockly.BlockSvg &&
|
|
93
|
+
dragRoot.type === 'procedures_definition' &&
|
|
94
|
+
this.wouldDeleteDraggable(event, dragRoot.getRootBlock())
|
|
91
95
|
) {
|
|
92
|
-
const prototype =
|
|
96
|
+
const prototype = dragRoot.getInput('custom_block')!.connection!.targetBlock()
|
|
93
97
|
const hasCaller =
|
|
94
98
|
prototype instanceof Blockly.BlockSvg &&
|
|
95
99
|
isProcedureBlock(prototype) &&
|
|
96
|
-
getCallers(prototype.getProcCode(),
|
|
100
|
+
getCallers(prototype.getProcCode(), dragRoot.workspace, dragRoot.getRootBlock(), false).length > 0
|
|
97
101
|
|
|
98
102
|
if (hasCaller) {
|
|
99
103
|
Blockly.dialog.alert(Blockly.Msg.PROCEDURE_USED)
|
|
@@ -140,8 +144,8 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
|
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
/**
|
|
143
|
-
* Returns the root element being dragged. For shadow blocks
|
|
144
|
-
* parent block.
|
|
147
|
+
* Returns the root element being dragged. For shadow blocks and the
|
|
148
|
+
* procedures_prototype block, this is the parent block.
|
|
145
149
|
* @param draggable The element being dragged directly.
|
|
146
150
|
* @returns The element being dragged, or its parent.
|
|
147
151
|
*/
|
|
@@ -149,7 +153,10 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
|
|
|
149
153
|
// We can't just use getRootBlock() here because, when blocks are detached
|
|
150
154
|
// from a stack via dragging, getRootBlock() still returns the root of that
|
|
151
155
|
// stack.
|
|
152
|
-
if (
|
|
156
|
+
if (
|
|
157
|
+
draggable instanceof Blockly.BlockSvg &&
|
|
158
|
+
(draggable.isShadow() || draggable.type === 'procedures_prototype')
|
|
159
|
+
) {
|
|
153
160
|
return draggable.getParent()
|
|
154
161
|
}
|
|
155
162
|
|
|
@@ -14,7 +14,7 @@ class ScratchVariableMap extends Blockly.VariableMap {
|
|
|
14
14
|
// is identical to the one requested.
|
|
15
15
|
const variables = this.getVariablesOfType(type ?? '')
|
|
16
16
|
if (!variables.length) return null
|
|
17
|
-
return variables.find(v => v.getName() === name) ?? null
|
|
17
|
+
return variables.find((v) => v.getName() === name) ?? null
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|