@granite-js/react-native 3.0.5 → 3.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @granite-js/react-native
2
2
 
3
+ ## 3.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - dcd6832: Handle iOS accessibility escape gestures through the router's registered back handlers and expose `accessibilityEscape` as a back event source.
8
+ - @granite-js/blur-view@3.0.7
9
+ - @granite-js/brownfield-module@3.0.7
10
+ - @granite-js/cli@3.0.7
11
+ - @granite-js/config@3.0.7
12
+ - @granite-js/jest@3.0.7
13
+ - @granite-js/mpack@3.0.7
14
+ - @granite-js/style-utils@3.0.7
15
+ - @granite-js/video@3.0.7
16
+
17
+ ## 3.0.6
18
+
19
+ ### Patch Changes
20
+
21
+ - @granite-js/blur-view@3.0.6
22
+ - @granite-js/brownfield-module@3.0.6
23
+ - @granite-js/cli@3.0.6
24
+ - @granite-js/config@3.0.6
25
+ - @granite-js/jest@3.0.6
26
+ - @granite-js/mpack@3.0.6
27
+ - @granite-js/style-utils@3.0.6
28
+ - @granite-js/video@3.0.6
29
+
3
30
  ## 3.0.5
4
31
 
5
32
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { type PrivateBackEventControls } from './BackEventContext';
3
- export type BackEventSource = 'backButton' | 'iosSwipeGesture' | 'androidHardwareBackPress';
3
+ export type BackEventSource = 'backButton' | 'iosSwipeGesture' | 'androidHardwareBackPress' | 'accessibilityEscape';
4
4
  export interface BackEvent {
5
5
  source: BackEventSource;
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@granite-js/react-native",
3
- "version": "3.0.5",
3
+ "version": "3.0.7",
4
4
  "description": "The Granite Framework",
5
5
  "bin": {
6
6
  "granite": "./bin/cli.mjs"
@@ -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": "3.0.5",
95
- "@granite-js/vitest": "3.0.5",
94
+ "@granite-js/native": "3.0.7",
95
+ "@granite-js/vitest": "3.0.7",
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": "3.0.5",
125
- "@granite-js/brownfield-module": "3.0.5",
126
- "@granite-js/cli": "3.0.5",
127
- "@granite-js/config": "3.0.5",
128
- "@granite-js/jest": "3.0.5",
129
- "@granite-js/mpack": "3.0.5",
130
- "@granite-js/style-utils": "3.0.5",
131
- "@granite-js/video": "3.0.5",
124
+ "@granite-js/blur-view": "3.0.7",
125
+ "@granite-js/brownfield-module": "3.0.7",
126
+ "@granite-js/cli": "3.0.7",
127
+ "@granite-js/config": "3.0.7",
128
+ "@granite-js/jest": "3.0.7",
129
+ "@granite-js/mpack": "3.0.7",
130
+ "@granite-js/style-utils": "3.0.7",
131
+ "@granite-js/video": "3.0.7",
132
132
  "@standard-schema/spec": "^1.0.0",
133
133
  "es-toolkit": "^1.39.8",
134
134
  "react-native-url-polyfill": "3.0.0"
@@ -1,5 +1,5 @@
1
- import { render } from '@testing-library/react';
2
- import { BackHandler, Platform } from 'react-native';
1
+ import { render, renderHook } from '@testing-library/react';
2
+ import { BackHandler, Platform, View } from 'react-native';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
  import { CanGoBackGuard } from './CanGoBackGuard';
5
5
 
@@ -16,6 +16,74 @@ describe('CanGoBackGuard', () => {
16
16
  vi.restoreAllMocks();
17
17
  });
18
18
 
19
+ it('passes accessibility escape events to onBack while back events exist', () => {
20
+ mockPlatformOS('ios');
21
+
22
+ const onBack = vi.fn();
23
+ const children = <div />;
24
+ const { result } = renderHook(() =>
25
+ CanGoBackGuard({
26
+ canGoBack: false,
27
+ hasBackEvent: true,
28
+ isInitialScreen: true,
29
+ onBack,
30
+ children,
31
+ })
32
+ );
33
+
34
+ expect(result.current.type).toBe(View);
35
+ expect(result.current.props.collapsable).toBe(false);
36
+ expect(result.current.props.children).toBe(children);
37
+
38
+ result.current.props.onAccessibilityEscape();
39
+
40
+ expect(onBack).toHaveBeenCalledExactlyOnceWith({ source: 'accessibilityEscape' });
41
+ });
42
+
43
+ it('registers the accessibility escape handler only while back events exist', () => {
44
+ mockPlatformOS('ios');
45
+
46
+ const onBack = vi.fn();
47
+ const { result, rerender } = renderHook(
48
+ ({ hasBackEvent }) =>
49
+ CanGoBackGuard({
50
+ canGoBack: !hasBackEvent,
51
+ hasBackEvent,
52
+ isInitialScreen: true,
53
+ onBack,
54
+ children: <div />,
55
+ }),
56
+ { initialProps: { hasBackEvent: false } }
57
+ );
58
+
59
+ expect(result.current.props.onAccessibilityEscape).toBeUndefined();
60
+
61
+ rerender({ hasBackEvent: true });
62
+
63
+ result.current.props.onAccessibilityEscape();
64
+
65
+ expect(onBack).toHaveBeenCalledExactlyOnceWith({ source: 'accessibilityEscape' });
66
+
67
+ rerender({ hasBackEvent: false });
68
+
69
+ expect(result.current.props.onAccessibilityEscape).toBeUndefined();
70
+ });
71
+
72
+ it('does not register an accessibility escape handler when onBack is absent', () => {
73
+ mockPlatformOS('ios');
74
+
75
+ const { result } = renderHook(() =>
76
+ CanGoBackGuard({
77
+ canGoBack: false,
78
+ hasBackEvent: true,
79
+ isInitialScreen: true,
80
+ children: <div />,
81
+ })
82
+ );
83
+
84
+ expect(result.current.props.onAccessibilityEscape).toBeUndefined();
85
+ });
86
+
19
87
  it('passes Android hardware back events to onBack and consumes the native event', () => {
20
88
  mockPlatformOS('android');
21
89
 
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, useEffect } from 'react';
2
- import { BackHandler, Platform } from 'react-native';
2
+ import { BackHandler, Platform, View } from 'react-native';
3
3
  import type { BackEvent } from '../../use-back-event';
4
4
 
5
5
  type SetIosSwipeGestureEnabled = ({ isEnabled }: { isEnabled: boolean }) => Promise<void> | void;
@@ -86,5 +86,13 @@ export function CanGoBackGuard({
86
86
  };
87
87
  }, [hasBackEvent, onBack, setiOSBackPressHandler]);
88
88
 
89
- return <>{children}</>;
89
+ return (
90
+ <View
91
+ style={{ flex: 1 }}
92
+ collapsable={false}
93
+ onAccessibilityEscape={hasBackEvent && onBack ? () => onBack({ source: 'accessibilityEscape' }) : undefined}
94
+ >
95
+ {children}
96
+ </View>
97
+ );
90
98
  }
@@ -10,7 +10,7 @@ import {
10
10
  import { useBackEventActionsContext } from './useBackEventActionsContext';
11
11
  import type { BackHandlerCallback } from './useBackHandler';
12
12
 
13
- export type BackEventSource = 'backButton' | 'iosSwipeGesture' | 'androidHardwareBackPress';
13
+ export type BackEventSource = 'backButton' | 'iosSwipeGesture' | 'androidHardwareBackPress' | 'accessibilityEscape';
14
14
 
15
15
  export interface BackEvent {
16
16
  source: BackEventSource;