@granite-js/micro-frontend 2.5.3 → 2.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @granite-js/micro-frontend
2
2
 
3
+ ## 2.5.5
4
+
5
+ ### Patch Changes
6
+
7
+ - @granite-js/utils@2.5.5
8
+
9
+ ## 2.5.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 271ef06: Put a detached portal source in the same measurement space React Native uses on Android.
14
+
15
+ A controller surface that is not attached to a window cannot read its own position, so the portal
16
+ offset was taken from the host origin and came out as zero. Fabric applies that offset as the
17
+ portal's transform, and that transform is what `measureInWindow` reports — the rendered position
18
+ comes from the host and never depended on it. The result was that a teleported subtree reported raw
19
+ screen coordinates while an ordinary window-attached surface reported coordinates relative to the
20
+ window's visible content area, the two disagreeing by the system bars inset. Anything consuming those
21
+ coordinates natively — an app bridge that draws at a measured rect, for one — landed a status bar
22
+ height off.
23
+
24
+ The detached branch now asks `RootViewUtil.getViewportOffset` about the host instead of deriving the
25
+ offset itself. That is the same call React Native makes to place a surface root, so the two stay in
26
+ one space without this package restating the rule. It also keeps them together as that function
27
+ changes: through 0.85 it subtracts the visible display frame, while 0.86 subtracts `WindowInsetsCompat`
28
+ status bar and cutout insets and skips the subtraction entirely under edge-to-edge.
29
+
30
+ Rendering and touch are unaffected. The teleported children are parented by the host, so they draw
31
+ where the host puts them, and the touch path that dispatches to them does not follow this offset.
32
+ - @granite-js/utils@2.5.4
33
+
3
34
  ## 2.5.3
4
35
 
5
36
  ### Patch Changes
@@ -1,7 +1,9 @@
1
1
  package com.teleport.portal
2
2
 
3
+ import android.graphics.Point
3
4
  import android.view.View
4
5
  import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.uimanager.RootViewUtil
5
7
  import com.facebook.react.uimanager.StateWrapper
6
8
  import com.teleport.extensions.dp
7
9
  import com.teleport.extensions.isDetached
@@ -61,22 +63,32 @@ internal class PortalLayoutStateController(
61
63
  }
62
64
 
63
65
  private fun createLayoutState(host: PortalHostView): PortalLayoutState {
64
- val hostLocation = host.screenLocation()
65
- // A detached controller surface has no Window coordinate space. Its children
66
- // are already physically parented by the destination host, so use the host
67
- // origin as the logical source origin and avoid applying a screen inset twice.
68
- val sourceLocation =
66
+ // This offset is what `PortalViewShadowNode.getTransform` translates by, and that transform is
67
+ // what `measureInWindow` reports. Neither what these nodes render nor what they receive touches
68
+ // on depends on it: the children are physically parented by the host, and `TouchTargetHelper`
69
+ // walks the real View tree. So it decides only where they say they are.
70
+ //
71
+ // A detached controller surface cannot measure itself: `getLocationOnScreen` returns (0, 0) for
72
+ // a view with no window, so an offset derived from it lands the teleported subtree in a
73
+ // different space than an ordinary, window-attached surface. React Native puts a surface root
74
+ // into that space with `RootViewUtil.getViewportOffset`; asking it about the host, which is the
75
+ // view these children are actually parented by, puts them there too. Delegating rather than
76
+ // repeating the arithmetic also means the two stay together when React Native changes what
77
+ // `getViewportOffset` does — 0.86 rewrote it around `WindowInsetsCompat`, for one.
78
+ val offset =
69
79
  if (sourceView.isDetached()) {
70
- hostLocation
80
+ RootViewUtil.getViewportOffset(host)
71
81
  } else {
72
- sourceView.screenLocation()
82
+ val hostLocation = host.screenLocation()
83
+ val sourceLocation = sourceView.screenLocation()
84
+ Point(hostLocation[0] - sourceLocation[0], hostLocation[1] - sourceLocation[1])
73
85
  }
74
86
 
75
87
  return PortalLayoutState(
76
88
  hostWidth = host.width.toFloat().dp,
77
89
  hostHeight = host.height.toFloat().dp,
78
- offsetX = (hostLocation[0] - sourceLocation[0]).toFloat().dp,
79
- offsetY = (hostLocation[1] - sourceLocation[1]).toFloat().dp,
90
+ offsetX = offset.x.toFloat().dp,
91
+ offsetY = offset.y.toFloat().dp,
80
92
  )
81
93
  }
82
94
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@granite-js/micro-frontend",
3
- "version": "2.5.3",
3
+ "version": "2.5.5",
4
4
  "description": "Micro-frontend build, runtime, session, and Portal contracts for Granite brownfield applications",
5
5
  "main": "./dist/module/index.js",
6
6
  "types": "./dist/typescript/index.d.ts",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "@babel/core": "7.28.5",
59
- "@granite-js/utils": "2.5.3",
59
+ "@granite-js/utils": "2.5.5",
60
60
  "@standard-schema/spec": "^1.0.0"
61
61
  },
62
62
  "peerDependencies": {
@@ -72,8 +72,8 @@
72
72
  },
73
73
  "devDependencies": {
74
74
  "@babel/types": "7.28.5",
75
- "@granite-js/plugin-core": "2.5.3",
76
- "@granite-js/react-native": "2.5.3",
75
+ "@granite-js/plugin-core": "2.5.5",
76
+ "@granite-js/react-native": "2.5.5",
77
77
  "@types/babel__core": "^7.20.5",
78
78
  "@types/node": "24.10.12",
79
79
  "@types/react": "19.2.0",