@blorkfield/overlay-core 0.11.5 → 0.11.7

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/README.md CHANGED
@@ -215,9 +215,11 @@ scene.spawnObject({
215
215
  });
216
216
  ```
217
217
 
218
+ **Positioning convention:** overlay-core sets `position: absolute` on the element and owns `left`, `top`, and `transform` entirely via inline styles. Position is expressed as `left: x - width/2; top: y - height/2` (body centre → top-left corner). Rotation is applied via `transform: rotate(angle)`. Do not set `left`, `top`, or `transform` on the element yourself — they will be overwritten. To place the element before spawn, set it off-screen or hidden; overlay-core writes the correct position on `spawnObject` for both static and dynamic elements, so it is visible and correctly placed immediately after the call returns.
219
+
218
220
  When a DOM element collapses:
219
- - The element's CSS transform is updated each frame to follow physics
220
- - Shadow creates a cloned DOM element at the original position
221
+ - The element follows its physics body each frame via `left`/`top` updates
222
+ - If `shadow` is configured, a cloned DOM element is left at the original spawn position
221
223
 
222
224
  ```typescript
223
225
  // Get the shadow element after collapse (if shadow was configured)
@@ -555,7 +557,7 @@ const scene = new OverlayScene(canvas, {
555
557
  | `floorConfig.minIntegrity` | none | Minimum segments required, otherwise all collapse |
556
558
  | `floorConfig.segmentWidths` | none | Proportional widths for each segment (array that sums to 1.0) |
557
559
  | `despawnBelowFloor` | 1.0 | Distance below floor to despawn objects (as fraction of height) |
558
- | `recenterOnResize` | false | Translate all objects to stay centred when canvas dimensions change — useful for phone rotation and responsive layouts |
560
+ | `recenterOnResize` | false | Translate all objects to stay centred when canvas dimensions change — useful for phone rotation and responsive layouts. Applies to all object types including static DOM obstacles (their CSS `left`/`top` is updated immediately at resize time, not deferred to the next frame). |
559
561
 
560
562
  ### Background Configuration
561
563
 
package/dist/index.cjs CHANGED
@@ -1498,6 +1498,8 @@ var OverlayScene = class {
1498
1498
  this.pressureObstacleIds = /* @__PURE__ */ new Set();
1499
1499
  // Active collision pairs: id -> Set of ids currently colliding with it
1500
1500
  this.activeCollisions = /* @__PURE__ */ new Map();
1501
+ // DOM shadow elements whose parent entry has been removed (live body despawned after collapse)
1502
+ this.orphanedDOMShadows = /* @__PURE__ */ new Set();
1501
1503
  /** Handle mouse down - start grab via programmatic API */
1502
1504
  this.handleMouseDown = (event) => {
1503
1505
  const rect = this.canvas.getBoundingClientRect();
@@ -2052,9 +2054,9 @@ var OverlayScene = class {
2052
2054
  transform: entry.domElement.style.transform
2053
2055
  }
2054
2056
  });
2055
- shadowElement.style.setProperty("left", `${computedLeft}px`, "important");
2056
- shadowElement.style.setProperty("top", `${computedTop}px`, "important");
2057
- shadowElement.style.setProperty("transform", "rotate(0deg)", "important");
2057
+ shadowElement.style.left = `${computedLeft}px`;
2058
+ shadowElement.style.top = `${computedTop}px`;
2059
+ shadowElement.style.transform = "rotate(0deg)";
2058
2060
  entry.domElement.parentNode?.insertBefore(shadowElement, entry.domElement);
2059
2061
  entry.domShadowElement = shadowElement;
2060
2062
  return;
@@ -2169,6 +2171,7 @@ var OverlayScene = class {
2169
2171
  import_matter_js5.default.Events.off(this.engine, "collisionEnd", this.handleCollisionEnd);
2170
2172
  import_matter_js5.default.Engine.clear(this.engine);
2171
2173
  this.objects.clear();
2174
+ this.orphanedDOMShadows.clear();
2172
2175
  this.gravityOverrideEntries.clear();
2173
2176
  this.followWindowEntries.clear();
2174
2177
  this.pressureObstacleIds.clear();
@@ -2318,13 +2321,25 @@ var OverlayScene = class {
2318
2321
  y: entry.originalPosition.y + dy
2319
2322
  };
2320
2323
  }
2324
+ if (entry.domElement && entry.tags.includes("static")) {
2325
+ const currentLeft = parseFloat(entry.domElement.style.left) || 0;
2326
+ const currentTop = parseFloat(entry.domElement.style.top) || 0;
2327
+ entry.domElement.style.left = `${currentLeft + dx}px`;
2328
+ entry.domElement.style.top = `${currentTop + dy}px`;
2329
+ }
2321
2330
  if (entry.domShadowElement) {
2322
2331
  const currentLeft = parseFloat(entry.domShadowElement.style.left) || 0;
2323
2332
  const currentTop = parseFloat(entry.domShadowElement.style.top) || 0;
2324
- entry.domShadowElement.style.setProperty("left", `${currentLeft + dx}px`, "important");
2325
- entry.domShadowElement.style.setProperty("top", `${currentTop + dy}px`, "important");
2333
+ entry.domShadowElement.style.left = `${currentLeft + dx}px`;
2334
+ entry.domShadowElement.style.top = `${currentTop + dy}px`;
2326
2335
  }
2327
2336
  }
2337
+ for (const shadowEl of this.orphanedDOMShadows) {
2338
+ const currentLeft = parseFloat(shadowEl.style.left) || 0;
2339
+ const currentTop = parseFloat(shadowEl.style.top) || 0;
2340
+ shadowEl.style.left = `${currentLeft + dx}px`;
2341
+ shadowEl.style.top = `${currentTop + dy}px`;
2342
+ }
2328
2343
  }
2329
2344
  this.canvas.width = width;
2330
2345
  this.canvas.height = height;
@@ -2656,6 +2671,9 @@ var OverlayScene = class {
2656
2671
  }
2657
2672
  this.activeCollisions.delete(id);
2658
2673
  }
2674
+ if (entry.domShadowElement) {
2675
+ this.orphanedDOMShadows.add(entry.domShadowElement);
2676
+ }
2659
2677
  this.objects.delete(id);
2660
2678
  }
2661
2679
  removeObjects(ids) {
@@ -3785,9 +3803,9 @@ var OverlayScene = class {
3785
3803
  const angleDeg = angle * (180 / Math.PI);
3786
3804
  const width = entry.domElement.offsetWidth;
3787
3805
  const height = entry.domElement.offsetHeight;
3788
- entry.domElement.style.setProperty("left", `${x - width / 2}px`, "important");
3789
- entry.domElement.style.setProperty("top", `${y - height / 2}px`, "important");
3790
- entry.domElement.style.setProperty("transform", `rotate(${angleDeg}deg)`, "important");
3806
+ entry.domElement.style.left = `${x - width / 2}px`;
3807
+ entry.domElement.style.top = `${y - height / 2}px`;
3808
+ entry.domElement.style.transform = `rotate(${angleDeg}deg)`;
3791
3809
  }
3792
3810
  /** TTL expiration + below-floor despawn in a single O(N) pass */
3793
3811
  checkExpiration() {