@granite-js/react-native 0.1.23-next.13 → 0.1.23-next.14

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,20 @@
1
1
  # @granite-js/react-native
2
2
 
3
+ ## 0.1.23-next.14
4
+
5
+ ### Patch Changes
6
+
7
+ - fix
8
+ - Updated dependencies
9
+ - @granite-js/plugin-core@0.1.23-next.14
10
+ - @granite-js/style-utils@0.1.23-next.14
11
+ - @granite-js/lottie@0.1.23-next.14
12
+ - @granite-js/native@0.1.23-next.14
13
+ - @granite-js/image@0.1.23-next.14
14
+ - @granite-js/mpack@0.1.23-next.14
15
+ - @granite-js/jest@0.1.23-next.14
16
+ - @granite-js/cli@0.1.23-next.14
17
+
3
18
  ## 0.1.23-next.13
4
19
 
5
20
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@granite-js/react-native",
3
- "version": "0.1.23-next.13",
3
+ "version": "0.1.23-next.14",
4
4
  "description": "The Granite Framework",
5
5
  "bin": {
6
6
  "granite": "./bin/cli.js"
@@ -86,7 +86,7 @@
86
86
  "@babel/core": "^7.24.9",
87
87
  "@babel/preset-env": "^7.24.8",
88
88
  "@babel/preset-typescript": "^7.24.7",
89
- "@granite-js/native": "0.1.23-next.13",
89
+ "@granite-js/native": "0.1.23-next.14",
90
90
  "@testing-library/dom": "^10.4.0",
91
91
  "@testing-library/react": "^16.1.0",
92
92
  "@types/babel__core": "^7",
@@ -105,20 +105,20 @@
105
105
  "vitest": "^2.1.8"
106
106
  },
107
107
  "peerDependencies": {
108
- "@granite-js/native": "0.1.23-next.13",
108
+ "@granite-js/native": "0.1.23-next.14",
109
109
  "@types/react": "*",
110
110
  "brick-module": "*",
111
111
  "react": "*",
112
112
  "react-native": "*"
113
113
  },
114
114
  "dependencies": {
115
- "@granite-js/cli": "0.1.23-next.13",
116
- "@granite-js/image": "0.1.23-next.13",
117
- "@granite-js/jest": "0.1.23-next.13",
118
- "@granite-js/lottie": "0.1.23-next.13",
119
- "@granite-js/mpack": "0.1.23-next.13",
120
- "@granite-js/plugin-core": "0.1.23-next.13",
121
- "@granite-js/style-utils": "0.1.23-next.13",
115
+ "@granite-js/cli": "0.1.23-next.14",
116
+ "@granite-js/image": "0.1.23-next.14",
117
+ "@granite-js/jest": "0.1.23-next.14",
118
+ "@granite-js/lottie": "0.1.23-next.14",
119
+ "@granite-js/mpack": "0.1.23-next.14",
120
+ "@granite-js/plugin-core": "0.1.23-next.14",
121
+ "@granite-js/style-utils": "0.1.23-next.14",
122
122
  "es-toolkit": "^1.39.8",
123
123
  "react-native-url-polyfill": "1.3.0"
124
124
  }
@@ -1,5 +1,5 @@
1
1
  import { type ComponentProps, PureComponent, RefObject, createRef } from 'react';
2
- import { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, ScrollView } from 'react-native';
2
+ import { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, ScrollView, View } from 'react-native';
3
3
  import IOContext, { IOContextValue } from './IOContext';
4
4
  import IOManager from './IOManager';
5
5
  import { Root, RootMargin } from './IntersectionObserver';
@@ -40,6 +40,7 @@ function withIO<
40
40
  // eslint-disable-next-line @typescript-eslint/no-this-alias
41
41
  const self = this;
42
42
  this.scroller = createRef();
43
+ this.node = null;
43
44
  this.root = {
44
45
  get node() {
45
46
  return self.node;
@@ -81,10 +82,53 @@ function withIO<
81
82
  };
82
83
  }
83
84
 
85
+ // Private helpers to keep type-safety encapsulated
86
+ private isRefObject<T>(v: unknown): v is RefObject<T> {
87
+ return typeof v === 'object' && v !== null && 'current' in (v as Record<string, unknown>);
88
+ }
89
+
90
+ private toView(v: RefObject<View> | View | null | undefined): View | null {
91
+ if (!v) return null;
92
+ return this.isRefObject<View>(v) ? v.current ?? null : v;
93
+ }
94
+
95
+ private callIfFunction<T extends object, K extends string>(obj: T | null | undefined, key: K): unknown {
96
+ if (!obj) return null;
97
+ const rec = obj as unknown as Record<string, unknown>;
98
+ const fn = rec[String(key)];
99
+ if (typeof fn === 'function') {
100
+ return (fn as Function).call(obj);
101
+ }
102
+ return null;
103
+ }
104
+
105
+ protected resolveRootNode = (): View | null => {
106
+ const instance = this.scroller.current as unknown;
107
+
108
+ // 1) Prefer native scroll ref (FlatList/VirtualizedList on Fabric)
109
+ const viaNativeRef = this.callIfFunction(instance as object, 'getNativeScrollRef');
110
+ const nativeFromNativeRef = this.toView(viaNativeRef as RefObject<View> | View | null | undefined);
111
+ if (nativeFromNativeRef) return nativeFromNativeRef;
112
+
113
+ // 2) Fallback to getScrollRef
114
+ const viaScrollRef = this.callIfFunction(instance as object, 'getScrollRef');
115
+ const nativeFromScrollRef = this.toView(viaScrollRef as RefObject<View> | View | null | undefined);
116
+ if (nativeFromScrollRef) return nativeFromScrollRef;
117
+
118
+ // 3) Fallback to getScrollableNode (exclude numeric handles)
119
+ const scrollable = this.callIfFunction(instance as object, 'getScrollableNode');
120
+ if (scrollable && typeof scrollable !== 'number') {
121
+ return scrollable as View;
122
+ }
123
+
124
+ // 4) Lastly, treat the instance itself as a View or RefObject<View>
125
+ return this.toView(instance as RefObject<View> | View | null | undefined);
126
+ };
127
+
84
128
  componentDidMount() {
85
- // Use the host component ref directly for RN 0.81/React 19 compatibility.
86
- // This avoids relying on numeric node handles and works with Fabric.
87
- this.node = this.scroller.current;
129
+ // Prefer a native scroll ref (FlatList/VirtualizedList),
130
+ // otherwise fall back to the host ref (ScrollView).
131
+ this.node = this.resolveRootNode();
88
132
  methods.forEach((method) => {
89
133
  (this as any)[method] = (...args: any) => {
90
134
  this.scroller.current?.[method]?.(...args);