@applicaster/zapp-react-native-utils 14.0.17 → 14.0.18-alpha.5740764222

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "14.0.17",
3
+ "version": "14.0.18-alpha.5740764222",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/applicaster/quickbrick#readme",
29
29
  "dependencies": {
30
- "@applicaster/applicaster-types": "14.0.17",
30
+ "@applicaster/applicaster-types": "14.0.18-alpha.5740764222",
31
31
  "buffer": "^5.2.1",
32
32
  "camelize": "^1.0.0",
33
33
  "dayjs": "^1.11.10",
@@ -39,6 +39,7 @@ ReactNative.NativeModules.QuickBrickCommunicationModule =
39
39
 
40
40
  jest.mock("react-native-safe-area-context", () => ({
41
41
  useSafeAreaInsets: () => ({ top: 50 }),
42
+ useSafeAreaFrame: () => ({ x: 0, y: 0, width: 100, height: 100 }),
42
43
  }));
43
44
 
44
45
  jest.mock("../../../reactUtils", () => ({
@@ -49,6 +50,22 @@ jest.mock("../../../reactUtils", () => ({
49
50
 
50
51
  jest.mock("../../navigation", () => ({
51
52
  useIsScreenActive: () => true,
53
+ useRoute: () => ({
54
+ screenData: { general: { screen_orientation: "portrait" } },
55
+ }),
56
+ }));
57
+
58
+ jest.mock("../../screen", () => ({
59
+ useCurrentScreenData: () => null,
60
+ }));
61
+
62
+ jest.mock("../../device", () => ({
63
+ useIsTablet: () => false,
64
+ }));
65
+
66
+ jest.mock("../../../appUtils/orientationHelper", () => ({
67
+ getScreenOrientation: jest.fn(() => 1), // portrait
68
+ isOrientationCompatible: jest.fn(() => true),
52
69
  }));
53
70
 
54
71
  jest.mock("../../navigation/useNavigation");
@@ -22,6 +22,12 @@ export type Options = {
22
22
  rounded?: boolean;
23
23
  deviceInfo?: boolean;
24
24
  updateForInactiveScreens?: boolean;
25
+ /**
26
+ * When true, dimensions will only update when they match the screen's target orientation.
27
+ * Returns the last valid dimensions during orientation transitions.
28
+ * Requires updateForInactiveScreens: false to work properly.
29
+ */
30
+ waitForValidOrientation?: boolean;
25
31
  };
26
32
 
27
33
  export type Context = "window" | "screen";
@@ -19,6 +19,28 @@ jest.mock(
19
19
  })
20
20
  );
21
21
 
22
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
23
+ useCurrentScreenData: jest.fn().mockReturnValue(null),
24
+ }));
25
+
26
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
27
+ useRoute: jest.fn().mockReturnValue({
28
+ screenData: { general: { screen_orientation: "portrait" } },
29
+ }),
30
+ }));
31
+
32
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/device", () => ({
33
+ useIsTablet: jest.fn().mockReturnValue(false),
34
+ }));
35
+
36
+ jest.mock(
37
+ "@applicaster/zapp-react-native-utils/appUtils/orientationHelper",
38
+ () => ({
39
+ getScreenOrientation: jest.fn().mockReturnValue(1), // portrait
40
+ isOrientationCompatible: jest.fn().mockReturnValue(true),
41
+ })
42
+ );
43
+
22
44
  jest.doMock("../helpers", () => ({
23
45
  getInitialDimensions: jest
24
46
  .fn()
@@ -129,4 +151,20 @@ describe("useDimensions", () => {
129
151
 
130
152
  consoleWarnSpy.mockRestore();
131
153
  });
154
+
155
+ it("accepts waitForValidOrientation option", () => {
156
+ // Smoke test to verify the option is accepted without errors
157
+ const { result } = renderHook(() =>
158
+ useDimensions("screen", {
159
+ updateForInactiveScreens: false,
160
+ waitForValidOrientation: true,
161
+ })
162
+ );
163
+
164
+ expect(result.current).toMatchObject({
165
+ width: expect.any(Number),
166
+ height: expect.any(Number),
167
+ statusBarHeight: expect.any(Number),
168
+ });
169
+ });
132
170
  });
@@ -11,6 +11,13 @@ import { Options, UseDimensions } from "../types";
11
11
  import { getDeviceInfo } from "../getDeviceInfo";
12
12
  import { getInitialDimensions } from "./helpers";
13
13
  import { useIsScreenActive } from "../../navigation/useIsScreenActive";
14
+ import {
15
+ getScreenOrientation,
16
+ isOrientationCompatible,
17
+ } from "../../../appUtils/orientationHelper";
18
+ import { useCurrentScreenData } from "../../screen";
19
+ import { useRoute } from "../../navigation";
20
+ import { useIsTablet } from "../../device";
14
21
 
15
22
  function compensateForScaleIfNeeded(context) {
16
23
  return function () {
@@ -59,9 +66,43 @@ export const useDimensions: UseDimensions = (
59
66
  options.fullDimensions = false;
60
67
  }
61
68
 
69
+ if (options.waitForValidOrientation === undefined) {
70
+ options.waitForValidOrientation = false;
71
+ }
72
+
62
73
  const [dimensions, setDimensions] = useState(getInitialDimensions(context));
63
74
  const deviceInfo = useRef(getDeviceInfo(dimensions, appData));
64
75
 
76
+ // Orientation validation setup (only when waitForValidOrientation is enabled)
77
+ const currentScreenData = useCurrentScreenData();
78
+ const { screenData } = useRoute();
79
+ const isTablet = useIsTablet();
80
+ const isTabletPortrait = appData?.isTabletPortrait;
81
+
82
+ const targetScreenData =
83
+ currentScreenData || (screenData as any)?.targetScreen || screenData;
84
+
85
+ const orientation = options.waitForValidOrientation
86
+ ? getScreenOrientation({
87
+ screenData: targetScreenData,
88
+ layoutData: { isTablet, isTabletPortrait },
89
+ })
90
+ : null;
91
+
92
+ const isOrientationValid = options.waitForValidOrientation
93
+ ? isOrientationCompatible({
94
+ orientation,
95
+ layoutData: {
96
+ isTablet,
97
+ isTabletPortrait,
98
+ width: dimensions.width,
99
+ height: dimensions.height,
100
+ },
101
+ })
102
+ : true;
103
+
104
+ const lastValidDimensions = useRef(dimensions);
105
+
65
106
  const applyOptions = R.compose(
66
107
  R.when(() => options.deviceInfo, R.assoc("deviceInfo", deviceInfo.current)),
67
108
  R.when(
@@ -109,13 +150,29 @@ export const useDimensions: UseDimensions = (
109
150
  };
110
151
  }, [isActive]);
111
152
 
153
+ let dimensionsToUse;
154
+
155
+ // When waitForValidOrientation is enabled, freeze dimensions during invalid orientation
156
+ if (options.waitForValidOrientation) {
157
+ if (isOrientationValid) {
158
+ // Store last valid dimensions to return during orientation transitions
159
+ lastValidDimensions.current = dimensions;
160
+ dimensionsToUse = dimensions;
161
+ } else {
162
+ // Return last valid dimensions during orientation transitions
163
+ dimensionsToUse = lastValidDimensions.current;
164
+ }
165
+ } else {
166
+ dimensionsToUse = dimensions;
167
+ }
168
+
112
169
  const memoizedDimensions = useMemo(() => {
113
- return { ...applyOptions(dimensions), statusBarHeight };
170
+ return { ...applyOptions(dimensionsToUse), statusBarHeight };
114
171
  }, [
115
- dimensions.width,
116
- dimensions.height,
117
- dimensions.fontScale,
118
- dimensions.scale,
172
+ dimensionsToUse.width,
173
+ dimensionsToUse.height,
174
+ dimensionsToUse.fontScale,
175
+ dimensionsToUse.scale,
119
176
  ]);
120
177
 
121
178
  return memoizedDimensions;
@@ -1,10 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { cleanup, renderHook } from "@testing-library/react-hooks";
4
- import configureStore from "redux-mock-store";
5
- import { Provider } from "react-redux";
6
-
7
- const mockStore = configureStore([]);
3
+ import { cleanup } from "@testing-library/react-native";
4
+ import { renderWithProviders } from "../../../testUtils";
8
5
 
9
6
  const mock_rtl_flag = false;
10
7
 
@@ -46,12 +43,7 @@ describe("cellResolver", () => {
46
43
  },
47
44
  };
48
45
 
49
- const store = mockStore({ cellStyles, styles, plugins });
50
-
51
- // eslint-disable-next-line react/prop-types
52
- const wrapper = ({ children }) => (
53
- <Provider store={store}>{children}</Provider>
54
- );
46
+ const storeState = { cellStyles, styles, plugins };
55
47
 
56
48
  afterEach(() => {
57
49
  cleanup();
@@ -61,8 +53,14 @@ describe("cellResolver", () => {
61
53
  expect(useCellResolver).toBeDefined();
62
54
  });
63
55
 
64
- it("Resolves cell plugin", () => {
65
- renderHook(() => useCellResolver({ component }), { wrapper });
56
+ it("resolves cell plugin", () => {
57
+ const TestComponent = () => {
58
+ const resolvedCell = useCellResolver({ component });
59
+
60
+ return <>{resolvedCell}</>;
61
+ };
62
+
63
+ renderWithProviders(<TestComponent />, storeState);
66
64
 
67
65
  expect(testCellModule).toBeCalled();
68
66
  });
@@ -51,6 +51,7 @@ export function useCellResolver({
51
51
 
52
52
  const { width, height } = useDimensions("screen", {
53
53
  updateForInactiveScreens: false,
54
+ waitForValidOrientation: true,
54
55
  });
55
56
 
56
57
  const { plugins, cellStyles } = usePickFromState(["plugins", "cellStyles"]);