@granite-js/react-native 2.5.5 → 3.0.0

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,19 @@
1
1
  # @granite-js/react-native
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 586459d: feat(react-native): export InitialPropsProvider
8
+ - @granite-js/blur-view@3.0.0
9
+ - @granite-js/brownfield-module@3.0.0
10
+ - @granite-js/cli@3.0.0
11
+ - @granite-js/config@3.0.0
12
+ - @granite-js/jest@3.0.0
13
+ - @granite-js/mpack@3.0.0
14
+ - @granite-js/style-utils@3.0.0
15
+ - @granite-js/video@3.0.0
16
+
3
17
  ## 2.5.5
4
18
 
5
19
  ### Patch Changes
@@ -228,6 +242,57 @@
228
242
  - @granite-js/style-utils@2.0.0
229
243
  - @granite-js/video@2.0.0
230
244
 
245
+ ## 1.0.45
246
+
247
+ ### Patch Changes
248
+
249
+ - @granite-js/blur-view@1.0.45
250
+ - @granite-js/brownfield-module@1.0.45
251
+ - @granite-js/cli@1.0.45
252
+ - @granite-js/jest@1.0.45
253
+ - @granite-js/mpack@1.0.45
254
+ - @granite-js/plugin-core@1.0.45
255
+ - @granite-js/style-utils@1.0.45
256
+ - @granite-js/video@1.0.45
257
+
258
+ ## 1.0.44
259
+
260
+ ### Patch Changes
261
+
262
+ - e97fe95: Use an unrestricted native peer range instead of an exact workspace constraint, preventing compatible updates from causing an unintended major release.
263
+ - 23a710f: Read navigation focus through `useSyncExternalStore` so focus changes between rendering and subscription are not missed by `useIsFocusedSafely`, `useVisibility`, or visibility effects. Preserve the focused fallback when no navigation context is available.
264
+
265
+ Visibility effects follow committed visibility snapshots with React's effect setup and cleanup lifecycle.
266
+
267
+ - 92a23a8: Add `useVisibilityEffect` to run an effect while a screen is visible and clean it up when visibility is lost, the callback changes, or the component unmounts.
268
+
269
+ Deprecate `useVisibilityChange` without changing its behavior. Use `useVisibilityEffect` for effects with cleanup, or `useVisibility` with React's `useEffect` for explicit visibility change handling.
270
+
271
+ - Updated dependencies [e97fe95]
272
+ - @granite-js/blur-view@1.0.44
273
+ - @granite-js/jest@1.0.44
274
+ - @granite-js/brownfield-module@1.0.44
275
+ - @granite-js/cli@1.0.44
276
+ - @granite-js/mpack@1.0.44
277
+ - @granite-js/plugin-core@1.0.44
278
+ - @granite-js/style-utils@1.0.44
279
+ - @granite-js/video@1.0.44
280
+
281
+ ## 1.0.43
282
+
283
+ ### Patch Changes
284
+
285
+ - afd4e50: feat(react-native): export InitialPropsProvider
286
+ - @granite-js/blur-view@1.0.43
287
+ - @granite-js/brownfield-module@1.0.43
288
+ - @granite-js/cli@1.0.43
289
+ - @granite-js/jest@1.0.43
290
+ - @granite-js/mpack@1.0.43
291
+ - @granite-js/native@1.0.43
292
+ - @granite-js/plugin-core@1.0.43
293
+ - @granite-js/style-utils@1.0.43
294
+ - @granite-js/video@1.0.43
295
+
231
296
  ## 1.0.42
232
297
 
233
298
  ### Patch Changes
package/bin/cli.mjs ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { initialize } from '@granite-js/cli';
4
+
5
+ initialize();
@@ -86,7 +86,7 @@ export interface GraniteProps {
86
86
  * ```
87
87
  */
88
88
  export declare const Granite: {
89
- registerApp(AppContainer: ComponentType<PropsWithChildren<InitialProps>>, { appName, context, router, initialScheme, setIosSwipeGestureEnabled, setiOSBackPressHandler, getInitialUrl }: GraniteProps): (initialProps: RegisteredAppProps) => JSX.Element;
89
+ registerApp(AppContainer: ComponentType<PropsWithChildren<InitialProps>>, { appName, context, router, initialScheme, setIosSwipeGestureEnabled, setiOSBackPressHandler, getInitialUrl, }: GraniteProps): (initialProps: RegisteredAppProps) => JSX.Element;
90
90
  registerHostApp(AppContainer: ComponentType<PropsWithChildren<InitialProps>>, { appName }: Pick<GraniteProps, "appName">): (initialProps: InitialProps) => React.JSX.Element;
91
91
  readonly appName: string;
92
92
  };
@@ -1,6 +1,33 @@
1
1
  import { type PropsWithChildren } from 'react';
2
2
  import { InitialProps } from '../../initial-props';
3
3
  export declare const InitialPropsContext: import("react").Context<InitialProps | null>;
4
+ /**
5
+ * @public
6
+ * @name InitialPropsProvider
7
+ * @category Core
8
+ * @description Provides the initial data passed from the native platform (Android or iOS) to `useInitialProps` and `useInitialSearchParams`. `Granite.registerApp` already renders this provider, so you only need it when you register the root component yourself instead of going through the router.
9
+ * @param {InitialProps} initialProps - Initial data the native platform passed to the root component.
10
+ * @param {ReactNode | undefined} children - Child components that read the initial data.
11
+ * @returns {ReactElement} A React Provider component.
12
+ * @example
13
+ *
14
+ * ### Registering a root component without the router
15
+ *
16
+ * ```tsx
17
+ * import { AppRegistry } from 'react-native';
18
+ * import { InitialPropsProvider, type InitialProps } from '@granite-js/react-native';
19
+ *
20
+ * function App(initialProps: InitialProps) {
21
+ * return (
22
+ * <InitialPropsProvider initialProps={initialProps}>
23
+ * <MyApp />
24
+ * </InitialPropsProvider>
25
+ * );
26
+ * }
27
+ *
28
+ * AppRegistry.registerComponent('my-app', () => App);
29
+ * ```
30
+ */
4
31
  export declare function InitialPropsProvider({ children, initialProps }: PropsWithChildren<{
5
32
  initialProps: InitialProps;
6
33
  }>): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- export { useInitialProps } from './context/InitialPropsContext';
1
+ export { InitialPropsProvider, useInitialProps } from './context/InitialPropsContext';
2
2
  export { useInitialSearchParams } from './context/useInitialSearchParams';
3
3
  export { Granite } from './Granite';
4
4
  export type { GraniteProps } from './Granite';
package/dist/cli.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { initialize } from '@granite-js/cli';
2
- import '@granite-js/plugin-core';
2
+ import '@granite-js/config';
3
3
  import '@granite-js/jest';
package/dist/config.d.mts CHANGED
@@ -1 +1 @@
1
- export { defineConfig } from '@granite-js/plugin-core';
1
+ export { BuildPlatform, BundlerAdapter, BundlerAdapterContext, BundlerBuildOption, BundlerServerOptions, GraniteConfig, GraniteContext, defineConfig } from '@granite-js/config';
package/dist/config.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { defineConfig } from '@granite-js/plugin-core';
1
+ export { defineConfig } from '@granite-js/config';
2
+ export type { BundlerAdapter, BundlerAdapterContext, BundlerBuildOption, BundlerServerOptions, BuildPlatform, GraniteContext, GraniteConfig, } from '@granite-js/config';
package/dist/config.js CHANGED
@@ -20,10 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/config.ts
21
21
  var config_exports = {};
22
22
  __export(config_exports, {
23
- defineConfig: () => import_plugin_core.defineConfig
23
+ defineConfig: () => import_config.defineConfig
24
24
  });
25
25
  module.exports = __toCommonJS(config_exports);
26
- var import_plugin_core = require("@granite-js/plugin-core");
26
+ var import_config = require("@granite-js/config");
27
27
  // Annotate the CommonJS export names for ESM import in node:
28
28
  0 && (module.exports = {
29
29
  defineConfig
package/dist/config.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/config.ts
2
- import { defineConfig } from "@granite-js/plugin-core";
2
+ import { defineConfig } from "@granite-js/config";
3
3
  export {
4
4
  defineConfig
5
5
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import './types/global';
2
- export { Granite, useInitialSearchParams, useInitialProps } from './app';
2
+ export { Granite, InitialPropsProvider, useInitialSearchParams, useInitialProps } from './app';
3
3
  export * from '@granite-js/style-utils';
4
4
  export { type GraniteImageSource, type GraniteImageStatic, type ResizeMode, type CachePolicy, type Priority, type OnLoadEvent, type OnProgressEvent, } from '@granite-js/native/react-native-fast-image';
5
5
  export * from './image';
@@ -12,7 +12,11 @@ import { RequireContext, RouteScreen } from '../types';
12
12
  * ```tsx
13
13
  * import { getRouteScreens } from '@granite-js/react-native';
14
14
  *
15
- * const context = require.context('../pages');
15
+ * const pageModules = import.meta.glob('./**' + '/*.{js,jsx,ts,tsx}', { base: './pages', eager: true });
16
+ * const context = ((key: string) => pageModules[key]) as Parameters<typeof getRouteScreens>[0];
17
+ * context.keys = () => Object.keys(pageModules);
18
+ * context.resolve = (key: string) => key;
19
+ * context.id = 'import.meta.glob';
16
20
  * const screens = getRouteScreens(context);
17
21
  * ```
18
22
  */
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@granite-js/react-native",
3
- "version": "2.5.5",
3
+ "version": "3.0.0",
4
4
  "description": "The Granite Framework",
5
5
  "bin": {
6
- "granite": "./bin/cli.js"
6
+ "granite": "./bin/cli.mjs"
7
7
  },
8
8
  "scripts": {
9
9
  "typecheck": "tsc --noEmit",
@@ -91,8 +91,8 @@
91
91
  "@babel/core": "7.28.5",
92
92
  "@babel/preset-env": "7.28.5",
93
93
  "@babel/preset-typescript": "7.28.5",
94
- "@granite-js/native": "2.5.5",
95
- "@granite-js/vitest": "2.5.5",
94
+ "@granite-js/native": "3.0.0",
95
+ "@granite-js/vitest": "3.0.0",
96
96
  "@testing-library/dom": "^10.4.0",
97
97
  "@testing-library/react": "^16.1.0",
98
98
  "@types/babel__core": "^7",
@@ -121,14 +121,14 @@
121
121
  "react-native": "*"
122
122
  },
123
123
  "dependencies": {
124
- "@granite-js/blur-view": "2.5.5",
125
- "@granite-js/brownfield-module": "2.5.5",
126
- "@granite-js/cli": "2.5.5",
127
- "@granite-js/jest": "2.5.5",
128
- "@granite-js/mpack": "2.5.5",
129
- "@granite-js/plugin-core": "2.5.5",
130
- "@granite-js/style-utils": "2.5.5",
131
- "@granite-js/video": "2.5.5",
124
+ "@granite-js/blur-view": "3.0.0",
125
+ "@granite-js/brownfield-module": "3.0.0",
126
+ "@granite-js/cli": "3.0.0",
127
+ "@granite-js/config": "3.0.0",
128
+ "@granite-js/jest": "3.0.0",
129
+ "@granite-js/mpack": "3.0.0",
130
+ "@granite-js/style-utils": "3.0.0",
131
+ "@granite-js/video": "3.0.0",
132
132
  "@standard-schema/spec": "^1.0.0",
133
133
  "es-toolkit": "^1.39.8",
134
134
  "react-native-url-polyfill": "3.0.0"
@@ -65,9 +65,7 @@ describe('Granite.registerApp', () => {
65
65
  });
66
66
 
67
67
  // When
68
- render(
69
- <Root platform="android" initialColorPreference="light" presentationVisibility={false} />
70
- );
68
+ render(<Root platform="android" initialColorPreference="light" presentationVisibility={false} />);
71
69
 
72
70
  // Then
73
71
  expect(visibilityState.value).toBe(false);
@@ -79,16 +79,25 @@ const createApp = () => {
79
79
  }
80
80
 
81
81
  return {
82
- registerApp(
82
+ registerApp(
83
83
  AppContainer: ComponentType<PropsWithChildren<InitialProps>>,
84
- { appName, context, router, initialScheme, setIosSwipeGestureEnabled, setiOSBackPressHandler, getInitialUrl }: GraniteProps
84
+ {
85
+ appName,
86
+ context,
87
+ router,
88
+ initialScheme,
89
+ setIosSwipeGestureEnabled,
90
+ setiOSBackPressHandler,
91
+ getInitialUrl,
92
+ }: GraniteProps
85
93
  ): (initialProps: RegisteredAppProps) => JSX.Element {
86
94
  if (appName === ENTRY_BUNDLE_NAME) {
87
95
  throw new Error(`Reserved app name 'shared' cannot be used`);
88
96
  }
89
97
 
90
98
  function Root({ presentationVisibility = true, ...initialProps }: RegisteredAppProps) {
91
- const initialSchemeValue = (typeof initialScheme === 'function' ? initialScheme() : initialScheme) ?? getSchemeUri();
99
+ const initialSchemeValue =
100
+ (typeof initialScheme === 'function' ? initialScheme() : initialScheme) ?? getSchemeUri();
92
101
 
93
102
  return (
94
103
  <VisibilityChangedProvider isVisible={presentationVisibility}>
@@ -3,6 +3,33 @@ import { InitialProps } from '../../initial-props';
3
3
 
4
4
  export const InitialPropsContext = createContext<InitialProps | null>(null);
5
5
 
6
+ /**
7
+ * @public
8
+ * @name InitialPropsProvider
9
+ * @category Core
10
+ * @description Provides the initial data passed from the native platform (Android or iOS) to `useInitialProps` and `useInitialSearchParams`. `Granite.registerApp` already renders this provider, so you only need it when you register the root component yourself instead of going through the router.
11
+ * @param {InitialProps} initialProps - Initial data the native platform passed to the root component.
12
+ * @param {ReactNode | undefined} children - Child components that read the initial data.
13
+ * @returns {ReactElement} A React Provider component.
14
+ * @example
15
+ *
16
+ * ### Registering a root component without the router
17
+ *
18
+ * ```tsx
19
+ * import { AppRegistry } from 'react-native';
20
+ * import { InitialPropsProvider, type InitialProps } from '@granite-js/react-native';
21
+ *
22
+ * function App(initialProps: InitialProps) {
23
+ * return (
24
+ * <InitialPropsProvider initialProps={initialProps}>
25
+ * <MyApp />
26
+ * </InitialPropsProvider>
27
+ * );
28
+ * }
29
+ *
30
+ * AppRegistry.registerComponent('my-app', () => App);
31
+ * ```
32
+ */
6
33
  export function InitialPropsProvider({ children, initialProps }: PropsWithChildren<{ initialProps: InitialProps }>) {
7
34
  return <InitialPropsContext.Provider value={initialProps}>{children}</InitialPropsContext.Provider>;
8
35
  }
package/src/app/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { useInitialProps } from './context/InitialPropsContext';
1
+ export { InitialPropsProvider, useInitialProps } from './context/InitialPropsContext';
2
2
  export { useInitialSearchParams } from './context/useInitialSearchParams';
3
3
  export { Granite } from './Granite';
4
4
  export type { GraniteProps } from './Granite';
package/src/config.ts CHANGED
@@ -1 +1,10 @@
1
- export { defineConfig } from '@granite-js/plugin-core';
1
+ export { defineConfig } from '@granite-js/config';
2
+ export type {
3
+ BundlerAdapter,
4
+ BundlerAdapterContext,
5
+ BundlerBuildOption,
6
+ BundlerServerOptions,
7
+ BuildPlatform,
8
+ GraniteContext,
9
+ GraniteConfig,
10
+ } from '@granite-js/config';
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import './types/global';
2
2
 
3
- export { Granite, useInitialSearchParams, useInitialProps } from './app';
3
+ export { Granite, InitialPropsProvider, useInitialSearchParams, useInitialProps } from './app';
4
4
  export * from '@granite-js/style-utils';
5
5
  export {
6
6
  type GraniteImageSource,
@@ -16,7 +16,11 @@ import { validateRouteParams } from './validateRouteParams';
16
16
  * ```tsx
17
17
  * import { getRouteScreens } from '@granite-js/react-native';
18
18
  *
19
- * const context = require.context('../pages');
19
+ * const pageModules = import.meta.glob('./**' + '/*.{js,jsx,ts,tsx}', { base: './pages', eager: true });
20
+ * const context = ((key: string) => pageModules[key]) as Parameters<typeof getRouteScreens>[0];
21
+ * context.keys = () => Object.keys(pageModules);
22
+ * context.resolve = (key: string) => key;
23
+ * context.id = 'import.meta.glob';
20
24
  * const screens = getRouteScreens(context);
21
25
  * ```
22
26
  */
@@ -16,10 +16,10 @@ describe('getSchemePrefix', () => {
16
16
  const result = getSchemePrefix({
17
17
  scheme: 'myapp',
18
18
  appName: 'testapp',
19
- host: 'super',
19
+ host: 'example',
20
20
  });
21
21
 
22
- expect(result).toBe('myapp://super/testapp');
22
+ expect(result).toBe('myapp://example/testapp');
23
23
  });
24
24
 
25
25
  it('should handle different schemes', () => {
package/bin/cli.js DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- require('@granite-js/cli').initialize();