scratch-blocks 2.1.9 → 2.1.11

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.
@@ -41,6 +41,17 @@ export declare class ScratchDragger extends Blockly.dragging.Dragger {
41
41
  * @param event The event that ended the drag.
42
42
  */
43
43
  onDragEnd(event: PointerEvent): void;
44
+ /**
45
+ * Returns whether or not the dragged item would be deleted if dropped at
46
+ * the current location. When a block is dragged outside the workspace
47
+ * bounds (e.g. onto the backpack or a different sprite), the GUI handles
48
+ * the drop — the flyout should not delete the block even if the pointer
49
+ * happens to overlap the flyout's bounding rect.
50
+ * @param event The drag event that triggered this check.
51
+ * @param rootDraggable The topmost item being dragged.
52
+ * @returns True if the draggable would be deleted.
53
+ */
54
+ wouldDeleteDraggable(event: PointerEvent, rootDraggable: Blockly.IDraggable & Blockly.IDeletable): boolean;
44
55
  /**
45
56
  * Returns whether or not the dragged item should return to its starting
46
57
  * position.
@@ -1 +1 @@
1
- {"version":3,"file":"scratch_dragger.d.ts","sourceRoot":"","sources":["../../../src/scratch_dragger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAUvC;;GAEG;AACH,qBAAa,cAAe,SAAQ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAC1D;;OAEG;IACH,kBAAkB,UAAQ;IAE1B;;OAEG;IACH,oBAAoB,UAAQ;IAE5B;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU;IAI1C;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,YAAY;IAgB/B;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,UAAU;IAKhE;;;OAGG;IACH,sBAAsB,CAAC,KAAK,EAAE,YAAY;IAW1C;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,YAAY;IA8C7B;;;;;;OAMG;IACH,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU;IAO1E;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU;IAczC;;;;;OAKG;IACH,iBAAiB,CAAC,KAAK,EAAE,YAAY;CAKtC"}
1
+ {"version":3,"file":"scratch_dragger.d.ts","sourceRoot":"","sources":["../../../src/scratch_dragger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAUvC;;GAEG;AACH,qBAAa,cAAe,SAAQ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAC1D;;OAEG;IACH,kBAAkB,UAAQ;IAE1B;;OAEG;IACH,oBAAoB,UAAQ;IAE5B;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU;IAI1C;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,YAAY;IAgB/B;;;;OAIG;IACM,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,UAAU;IAQzE;;;OAGG;IACH,sBAAsB,CAAC,KAAK,EAAE,YAAY;IAW1C;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,YAAY;IAiD7B;;;;;;;;;OASG;IACM,oBAAoB,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU;IAKzG;;;;;;OAMG;IACH,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU;IAO1E;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU;IAczC;;;;;OAKG;IACH,iBAAiB,CAAC,KAAK,EAAE,YAAY;CAKtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../../../src/xml.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAGvC;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,YAAY,GAAG,MAAM,EAAE,CA6BpG"}
1
+ {"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../../../src/xml.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAGvC;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,YAAY,GAAG,MAAM,EAAE,CAkDpG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scratch-blocks",
3
- "version": "2.1.9",
3
+ "version": "2.1.11",
4
4
  "description": "Scratch Blocks is a library for building creative computing interfaces.",
5
5
  "author": "Massachusetts Institute of Technology",
6
6
  "license": "Apache-2.0",
@@ -38,20 +38,20 @@
38
38
  "devDependencies": {
39
39
  "@commitlint/cli": "20.5.0",
40
40
  "@commitlint/config-conventional": "20.5.0",
41
- "@vitest/browser": "4.1.2",
42
- "@vitest/browser-playwright": "4.1.2",
41
+ "@vitest/browser": "4.1.4",
42
+ "@vitest/browser-playwright": "4.1.4",
43
43
  "eslint": "9.39.4",
44
- "eslint-config-scratch": "14.1.4",
44
+ "eslint-config-scratch": "14.1.6",
45
45
  "husky": "9.1.7",
46
46
  "playwright": "1.59.1",
47
- "prettier": "3.8.1",
47
+ "prettier": "3.8.2",
48
48
  "scratch-semantic-release-config": "4.0.1",
49
49
  "semantic-release": "25.0.3",
50
50
  "source-map-loader": "5.0.0",
51
51
  "ts-loader": "9.5.7",
52
52
  "typescript": "5.9.3",
53
- "vitest": "4.1.2",
54
- "webpack": "5.105.4",
53
+ "vitest": "4.1.4",
54
+ "webpack": "5.106.1",
55
55
  "webpack-cli": "6.0.1",
56
56
  "webpack-dev-server": "5.2.3"
57
57
  },
package/src/css.ts CHANGED
@@ -1221,6 +1221,18 @@ const styles = `
1221
1221
  width: 100%;
1222
1222
  height: 100%;
1223
1223
  }
1224
+
1225
+ /* Prevent children of the drag surface from intercepting pointer
1226
+ events. Blockly's field elements set pointer-events:auto for
1227
+ click/edit interactions, but during a drag, Blockly's gesture
1228
+ handler binds pointermove/pointerup on document so the dragged
1229
+ block does not need to receive pointer events. Without this rule,
1230
+ the field elements steal hover and pointer events from elements
1231
+ underneath the dragged block (e.g. sprite selector tiles, the
1232
+ backpack drop target). */
1233
+ .blocklyBlockDragSurface * {
1234
+ pointer-events: none;
1235
+ }
1224
1236
  `
1225
1237
 
1226
1238
  Blockly.Css.register(styles)
@@ -59,9 +59,12 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
59
59
  * @param event The event that triggered this call.
60
60
  * @param totalDelta The change in pointer position since the last invocation.
61
61
  */
62
- onDrag(event: PointerEvent, totalDelta: Blockly.utils.Coordinate) {
63
- super.onDrag(event, totalDelta)
62
+ override onDrag(event: PointerEvent, totalDelta: Blockly.utils.Coordinate) {
63
+ // Update out-of-bounds state BEFORE the base onDrag so that
64
+ // wouldDeleteDraggable (called by super.onDrag to set the delete
65
+ // cursor) sees the current draggedOutOfBounds value.
64
66
  this.updateOutOfBoundsState(event)
67
+ super.onDrag(event, totalDelta)
65
68
  }
66
69
 
67
70
  /**
@@ -84,6 +87,11 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
84
87
  * @param event The event that ended the drag.
85
88
  */
86
89
  onDragEnd(event: PointerEvent) {
90
+ // Update out-of-bounds state BEFORE any wouldDeleteDraggable checks
91
+ // so the override sees the position from the pointerup event, not
92
+ // the last pointermove (which could be stale if the user moved fast).
93
+ this.updateOutOfBoundsState(event)
94
+
87
95
  // When the prototype block is dragged (via its DelegateToParentDraggable
88
96
  // strategy), this.draggable is the prototype, but getDragRoot returns the
89
97
  // definition. Handle both cases for the "procedure is in use" check.
@@ -108,8 +116,6 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
108
116
  }
109
117
 
110
118
  super.onDragEnd(event)
111
-
112
- this.updateOutOfBoundsState(event)
113
119
  if (this.draggable instanceof Blockly.BlockSvg) {
114
120
  const event = new BlockDragEnd(this.getDragRoot(this.draggable) as Blockly.BlockSvg, this.draggedOutOfBounds)
115
121
  Blockly.Events.fire(event)
@@ -129,6 +135,21 @@ export class ScratchDragger extends Blockly.dragging.Dragger {
129
135
  this.workspace.removeClass(BOUNDLESS_CLASS)
130
136
  }
131
137
 
138
+ /**
139
+ * Returns whether or not the dragged item would be deleted if dropped at
140
+ * the current location. When a block is dragged outside the workspace
141
+ * bounds (e.g. onto the backpack or a different sprite), the GUI handles
142
+ * the drop — the flyout should not delete the block even if the pointer
143
+ * happens to overlap the flyout's bounding rect.
144
+ * @param event The drag event that triggered this check.
145
+ * @param rootDraggable The topmost item being dragged.
146
+ * @returns True if the draggable would be deleted.
147
+ */
148
+ override wouldDeleteDraggable(event: PointerEvent, rootDraggable: Blockly.IDraggable & Blockly.IDeletable) {
149
+ if (this.draggedOutOfBounds) return false
150
+ return super.wouldDeleteDraggable(event, rootDraggable)
151
+ }
152
+
132
153
  /**
133
154
  * Returns whether or not the dragged item should return to its starting
134
155
  * position.
package/src/xml.ts CHANGED
@@ -36,8 +36,29 @@ export function clearWorkspaceAndLoadFromXml(xml: Element, workspace: Blockly.Wo
36
36
  xml.querySelector('variables')?.remove()
37
37
 
38
38
  // Defer to core for the rest of the deserialization.
39
- const blockIds = Blockly.Xml.domToWorkspace(xml, workspace)
39
+ let blockIds: string[]
40
+ try {
41
+ blockIds = Blockly.Xml.domToWorkspace(xml, workspace)
42
+ } catch (error) {
43
+ const context =
44
+ Array.from(xml.children)
45
+ .map((el) => {
46
+ const type = el.getAttribute('type')
47
+ const id = el.getAttribute('id')
48
+ const attrs = [...(type ? [`type=${type}`] : []), ...(id ? [`id=${id}`] : [])]
49
+ return attrs.length ? `${el.tagName}[${attrs.join(', ')}]` : el.tagName
50
+ })
51
+ .join(', ') || '(none)'
52
+ const message = error instanceof Error ? error.message : String(error)
53
+ const wrapped = new Error(
54
+ `Failed to load workspace XML (${message}). Top-level elements: ${context}`,
55
+ ) as Error & { cause?: unknown }
56
+ wrapped.cause = error
57
+ throw wrapped
58
+ } finally {
59
+ Blockly.Events.setGroup(false)
60
+ workspace.setResizesEnabled(true)
61
+ }
40
62
 
41
- workspace.setResizesEnabled(true)
42
63
  return blockIds
43
64
  }