@granite-js/react-native 1.0.38 → 1.0.40
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 +30 -0
- package/dist/app/Granite.d.ts +5 -4
- package/dist/router/components/CanGoBackGuard.d.ts +9 -2
- package/dist/router/index.d.ts +1 -0
- package/package.json +12 -12
- package/src/app/AppRoot.tsx +2 -2
- package/src/app/Granite.tsx +5 -2
- package/src/router/Router.tsx +2 -2
- package/src/router/components/CanGoBackGuard.spec.tsx +66 -1
- package/src/router/components/CanGoBackGuard.tsx +10 -2
- package/src/router/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @granite-js/react-native
|
|
2
2
|
|
|
3
|
+
## 1.0.40
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c7e7fc9: fix(react-native): unset iOS back press handler on cleanup instead of re-registering
|
|
8
|
+
- @granite-js/blur-view@1.0.40
|
|
9
|
+
- @granite-js/brownfield-module@1.0.40
|
|
10
|
+
- @granite-js/cli@1.0.40
|
|
11
|
+
- @granite-js/jest@1.0.40
|
|
12
|
+
- @granite-js/mpack@1.0.40
|
|
13
|
+
- @granite-js/native@1.0.40
|
|
14
|
+
- @granite-js/plugin-core@1.0.40
|
|
15
|
+
- @granite-js/style-utils@1.0.40
|
|
16
|
+
- @granite-js/video@1.0.40
|
|
17
|
+
|
|
18
|
+
## 1.0.39
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [c790dbf]
|
|
23
|
+
- @granite-js/mpack@1.0.39
|
|
24
|
+
- @granite-js/cli@1.0.39
|
|
25
|
+
- @granite-js/blur-view@1.0.39
|
|
26
|
+
- @granite-js/brownfield-module@1.0.39
|
|
27
|
+
- @granite-js/jest@1.0.39
|
|
28
|
+
- @granite-js/native@1.0.39
|
|
29
|
+
- @granite-js/plugin-core@1.0.39
|
|
30
|
+
- @granite-js/style-utils@1.0.39
|
|
31
|
+
- @granite-js/video@1.0.39
|
|
32
|
+
|
|
3
33
|
## 1.0.38
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/app/Granite.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentType, type JSX, PropsWithChildren } from 'react';
|
|
2
2
|
import type { InitialProps } from '../initial-props';
|
|
3
|
-
import type { RouterProps, RequireContext } from '../router';
|
|
3
|
+
import type { RouterProps, RequireContext, SetIOSBackPressHandler } from '../router';
|
|
4
4
|
export interface GraniteProps {
|
|
5
5
|
/**
|
|
6
6
|
* @description
|
|
@@ -34,10 +34,11 @@ export interface GraniteProps {
|
|
|
34
34
|
/**
|
|
35
35
|
* @description
|
|
36
36
|
* The function to register a handler that runs when the iOS swipe back gesture is detected.
|
|
37
|
+
* Called with empty params (`{}`, no `handler`) when the handler should be unset — in
|
|
38
|
+
* that case the implementation must initialize the registered handler to `null`
|
|
39
|
+
* (e.g. call `unsetBackPressHandler()`), not keep an empty function registered.
|
|
37
40
|
*/
|
|
38
|
-
setiOSBackPressHandler?:
|
|
39
|
-
handler: () => void;
|
|
40
|
-
}) => Promise<void> | void;
|
|
41
|
+
setiOSBackPressHandler?: SetIOSBackPressHandler;
|
|
41
42
|
/**
|
|
42
43
|
* @description
|
|
43
44
|
* The function to provide the initial URL to router.
|
|
@@ -3,8 +3,15 @@ import type { BackEvent } from '../../use-back-event';
|
|
|
3
3
|
type SetIosSwipeGestureEnabled = ({ isEnabled }: {
|
|
4
4
|
isEnabled: boolean;
|
|
5
5
|
}) => Promise<void> | void;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Registers the iOS back press handler. Called with empty params (`{}`, no
|
|
8
|
+
* `handler`) to unset — mirroring `unsetBackPressHandler()`, which calls
|
|
9
|
+
* `setBackPressHandler` with empty params. In that case implementations should
|
|
10
|
+
* initialize the registered handler to `null`, not keep an empty function
|
|
11
|
+
* registered.
|
|
12
|
+
*/
|
|
13
|
+
export type SetIOSBackPressHandler = ({ handler }: {
|
|
14
|
+
handler?: () => void;
|
|
8
15
|
}) => Promise<void> | void;
|
|
9
16
|
export declare function CanGoBackGuard({ children, canGoBack, hasBackEvent, onBack, isInitialScreen, setIosSwipeGestureEnabled, setiOSBackPressHandler, }: {
|
|
10
17
|
canGoBack: boolean;
|
package/dist/router/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export * from './Router';
|
|
|
2
2
|
export { getRouteScreens, getScreenPathMapConfig, defaultParserParams } from './utils';
|
|
3
3
|
export * from './types';
|
|
4
4
|
export * from './components/BackButton';
|
|
5
|
+
export type { SetIOSBackPressHandler } from './components/CanGoBackGuard';
|
|
5
6
|
export * from './components/useRouterBackHandler';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@granite-js/react-native",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"description": "The Granite Framework",
|
|
5
5
|
"bin": {
|
|
6
6
|
"granite": "./bin/cli.js"
|
|
@@ -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": "1.0.
|
|
95
|
-
"@granite-js/vitest": "1.0.
|
|
94
|
+
"@granite-js/native": "1.0.40",
|
|
95
|
+
"@granite-js/vitest": "1.0.40",
|
|
96
96
|
"@testing-library/dom": "^10.4.0",
|
|
97
97
|
"@testing-library/react": "^16.1.0",
|
|
98
98
|
"@types/babel__core": "^7",
|
|
@@ -114,21 +114,21 @@
|
|
|
114
114
|
"zod": "^4.1.12"
|
|
115
115
|
},
|
|
116
116
|
"peerDependencies": {
|
|
117
|
-
"@granite-js/native": "1.0.
|
|
117
|
+
"@granite-js/native": "1.0.40",
|
|
118
118
|
"@types/react": "*",
|
|
119
119
|
"brick-module": "*",
|
|
120
120
|
"react": "*",
|
|
121
121
|
"react-native": "*"
|
|
122
122
|
},
|
|
123
123
|
"dependencies": {
|
|
124
|
-
"@granite-js/blur-view": "1.0.
|
|
125
|
-
"@granite-js/brownfield-module": "1.0.
|
|
126
|
-
"@granite-js/cli": "1.0.
|
|
127
|
-
"@granite-js/jest": "1.0.
|
|
128
|
-
"@granite-js/mpack": "1.0.
|
|
129
|
-
"@granite-js/plugin-core": "1.0.
|
|
130
|
-
"@granite-js/style-utils": "1.0.
|
|
131
|
-
"@granite-js/video": "1.0.
|
|
124
|
+
"@granite-js/blur-view": "1.0.40",
|
|
125
|
+
"@granite-js/brownfield-module": "1.0.40",
|
|
126
|
+
"@granite-js/cli": "1.0.40",
|
|
127
|
+
"@granite-js/jest": "1.0.40",
|
|
128
|
+
"@granite-js/mpack": "1.0.40",
|
|
129
|
+
"@granite-js/plugin-core": "1.0.40",
|
|
130
|
+
"@granite-js/style-utils": "1.0.40",
|
|
131
|
+
"@granite-js/video": "1.0.40",
|
|
132
132
|
"@standard-schema/spec": "^1.0.0",
|
|
133
133
|
"es-toolkit": "^1.39.8",
|
|
134
134
|
"react-native-url-polyfill": "3.0.0"
|
package/src/app/AppRoot.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SafeAreaProvider } from '@granite-js/native/react-native-safe-area-context';
|
|
2
2
|
import type { ComponentType, PropsWithChildren } from 'react';
|
|
3
3
|
import type { InitialProps } from '../initial-props';
|
|
4
|
-
import { Router, type InternalRouterProps } from '../router';
|
|
4
|
+
import { Router, type InternalRouterProps, type SetIOSBackPressHandler } from '../router';
|
|
5
5
|
import { BackEventProvider } from '../use-back-event';
|
|
6
6
|
import { App } from './App';
|
|
7
7
|
import type { GraniteProps } from './Granite';
|
|
@@ -16,7 +16,7 @@ interface AppRootProps extends GraniteProps {
|
|
|
16
16
|
initialProps: InitialProps;
|
|
17
17
|
initialScheme: string;
|
|
18
18
|
setIosSwipeGestureEnabled?: ({ isEnabled }: { isEnabled: boolean }) => void;
|
|
19
|
-
setiOSBackPressHandler?:
|
|
19
|
+
setiOSBackPressHandler?: SetIOSBackPressHandler;
|
|
20
20
|
getInitialUrl: InternalRouterProps['getInitialUrl'];
|
|
21
21
|
}
|
|
22
22
|
|
package/src/app/Granite.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { ComponentType, type JSX, PropsWithChildren } from 'react';
|
|
|
2
2
|
import { AppRegistry } from 'react-native';
|
|
3
3
|
import { ENTRY_BUNDLE_NAME } from '../constants';
|
|
4
4
|
import type { InitialProps } from '../initial-props';
|
|
5
|
-
import type { RouterProps, RequireContext } from '../router';
|
|
5
|
+
import type { RouterProps, RequireContext, SetIOSBackPressHandler } from '../router';
|
|
6
6
|
import { AppRoot } from './AppRoot';
|
|
7
7
|
import { HostAppRoot } from './HostAppRoot';
|
|
8
8
|
import { getSchemeUri } from '../constant-bridges';
|
|
@@ -42,8 +42,11 @@ export interface GraniteProps {
|
|
|
42
42
|
/**
|
|
43
43
|
* @description
|
|
44
44
|
* The function to register a handler that runs when the iOS swipe back gesture is detected.
|
|
45
|
+
* Called with empty params (`{}`, no `handler`) when the handler should be unset — in
|
|
46
|
+
* that case the implementation must initialize the registered handler to `null`
|
|
47
|
+
* (e.g. call `unsetBackPressHandler()`), not keep an empty function registered.
|
|
45
48
|
*/
|
|
46
|
-
setiOSBackPressHandler?:
|
|
49
|
+
setiOSBackPressHandler?: SetIOSBackPressHandler;
|
|
47
50
|
|
|
48
51
|
/**
|
|
49
52
|
* @description
|
package/src/router/Router.tsx
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { InitialProps } from '..';
|
|
21
21
|
import { closeView } from '../native-modules';
|
|
22
22
|
import { BackButton } from './components/BackButton';
|
|
23
|
-
import { CanGoBackGuard } from './components/CanGoBackGuard';
|
|
23
|
+
import { CanGoBackGuard, type SetIOSBackPressHandler } from './components/CanGoBackGuard';
|
|
24
24
|
import { StackNavigator } from './components/StackNavigator';
|
|
25
25
|
import { useInternalRouterBackHandler } from './components/useRouterBackHandler';
|
|
26
26
|
import { useRouterControls, type RouterControlsConfig } from './hooks/useRouterControls';
|
|
@@ -65,7 +65,7 @@ export interface InternalRouterProps {
|
|
|
65
65
|
initialProps: InitialProps;
|
|
66
66
|
initialScheme: string;
|
|
67
67
|
setIosSwipeGestureEnabled?: ({ isEnabled }: { isEnabled: boolean }) => Promise<void> | void;
|
|
68
|
-
setiOSBackPressHandler?:
|
|
68
|
+
setiOSBackPressHandler?: SetIOSBackPressHandler;
|
|
69
69
|
getInitialUrl?: RouterControlsConfig['getInitialUrl'];
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -73,7 +73,72 @@ describe('CanGoBackGuard', () => {
|
|
|
73
73
|
|
|
74
74
|
unmount();
|
|
75
75
|
|
|
76
|
-
expect(setiOSBackPressHandler).toHaveBeenLastCalledWith({
|
|
76
|
+
expect(setiOSBackPressHandler).toHaveBeenLastCalledWith({});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('unsets the iOS back press handler on unmount so the registered handler is initialized to null', () => {
|
|
80
|
+
mockPlatformOS('ios');
|
|
81
|
+
|
|
82
|
+
let registeredHandler: (() => void) | null = null;
|
|
83
|
+
// destructures params like legacy host implementations — must not crash on unset
|
|
84
|
+
const setiOSBackPressHandler = vi.fn(({ handler }: { handler?: () => void }) => {
|
|
85
|
+
registeredHandler = handler ?? null;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const { unmount } = render(
|
|
89
|
+
<CanGoBackGuard
|
|
90
|
+
canGoBack={true}
|
|
91
|
+
hasBackEvent={true}
|
|
92
|
+
isInitialScreen={true}
|
|
93
|
+
setiOSBackPressHandler={setiOSBackPressHandler}
|
|
94
|
+
>
|
|
95
|
+
<div />
|
|
96
|
+
</CanGoBackGuard>
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
expect(registeredHandler).toEqual(expect.any(Function));
|
|
100
|
+
|
|
101
|
+
unmount();
|
|
102
|
+
|
|
103
|
+
expect(setiOSBackPressHandler).toHaveBeenLastCalledWith({});
|
|
104
|
+
expect(registeredHandler).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('unsets the iOS back press handler when back events no longer exist', () => {
|
|
108
|
+
mockPlatformOS('ios');
|
|
109
|
+
|
|
110
|
+
let registeredHandler: (() => void) | null = null;
|
|
111
|
+
// destructures params like legacy host implementations — must not crash on unset
|
|
112
|
+
const setiOSBackPressHandler = vi.fn(({ handler }: { handler?: () => void }) => {
|
|
113
|
+
registeredHandler = handler ?? null;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const { rerender } = render(
|
|
117
|
+
<CanGoBackGuard
|
|
118
|
+
canGoBack={true}
|
|
119
|
+
hasBackEvent={true}
|
|
120
|
+
isInitialScreen={true}
|
|
121
|
+
setiOSBackPressHandler={setiOSBackPressHandler}
|
|
122
|
+
>
|
|
123
|
+
<div />
|
|
124
|
+
</CanGoBackGuard>
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
expect(registeredHandler).toEqual(expect.any(Function));
|
|
128
|
+
|
|
129
|
+
rerender(
|
|
130
|
+
<CanGoBackGuard
|
|
131
|
+
canGoBack={true}
|
|
132
|
+
hasBackEvent={false}
|
|
133
|
+
isInitialScreen={true}
|
|
134
|
+
setiOSBackPressHandler={setiOSBackPressHandler}
|
|
135
|
+
>
|
|
136
|
+
<div />
|
|
137
|
+
</CanGoBackGuard>
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
expect(setiOSBackPressHandler).toHaveBeenLastCalledWith({});
|
|
141
|
+
expect(registeredHandler).toBeNull();
|
|
77
142
|
});
|
|
78
143
|
|
|
79
144
|
it('disables iOS swipe when the current state should block default back navigation', () => {
|
|
@@ -3,7 +3,15 @@ import { BackHandler, Platform } from 'react-native';
|
|
|
3
3
|
import type { BackEvent } from '../../use-back-event';
|
|
4
4
|
|
|
5
5
|
type SetIosSwipeGestureEnabled = ({ isEnabled }: { isEnabled: boolean }) => Promise<void> | void;
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Registers the iOS back press handler. Called with empty params (`{}`, no
|
|
9
|
+
* `handler`) to unset — mirroring `unsetBackPressHandler()`, which calls
|
|
10
|
+
* `setBackPressHandler` with empty params. In that case implementations should
|
|
11
|
+
* initialize the registered handler to `null`, not keep an empty function
|
|
12
|
+
* registered.
|
|
13
|
+
*/
|
|
14
|
+
export type SetIOSBackPressHandler = ({ handler }: { handler?: () => void }) => Promise<void> | void;
|
|
7
15
|
|
|
8
16
|
export function CanGoBackGuard({
|
|
9
17
|
children,
|
|
@@ -74,7 +82,7 @@ export function CanGoBackGuard({
|
|
|
74
82
|
});
|
|
75
83
|
|
|
76
84
|
return () => {
|
|
77
|
-
setiOSBackPressHandler({
|
|
85
|
+
setiOSBackPressHandler?.({});
|
|
78
86
|
};
|
|
79
87
|
}, [hasBackEvent, onBack, setiOSBackPressHandler]);
|
|
80
88
|
|
package/src/router/index.ts
CHANGED
|
@@ -2,4 +2,5 @@ export * from './Router';
|
|
|
2
2
|
export { getRouteScreens, getScreenPathMapConfig, defaultParserParams } from './utils';
|
|
3
3
|
export * from './types';
|
|
4
4
|
export * from './components/BackButton';
|
|
5
|
+
export type { SetIOSBackPressHandler } from './components/CanGoBackGuard';
|
|
5
6
|
export * from './components/useRouterBackHandler';
|