@granite-js/react-native 0.0.0-dev-20250725013859
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/LICENSE +202 -0
- package/README.md +24 -0
- package/bin/cli.js +3 -0
- package/cli.d.ts +1 -0
- package/cli.js +4 -0
- package/config.d.ts +2 -0
- package/config.js +5 -0
- package/dist/app/App/index.android.d.ts +2 -0
- package/dist/app/App/index.ios.d.ts +6 -0
- package/dist/app/AppRoot.d.ts +1 -0
- package/dist/app/Granite.d.ts +61 -0
- package/dist/app/HostAppRoot.d.ts +1 -0
- package/dist/app/index.d.ts +2 -0
- package/dist/async-bridges.d.ts +2 -0
- package/dist/blur/BlurView.d.ts +78 -0
- package/dist/blur/ReactNativeBlurModule.d.ts +6 -0
- package/dist/blur/constants.d.ts +1 -0
- package/dist/blur/index.d.ts +1 -0
- package/dist/constant-bridges.d.ts +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/dev-entrypoint/index.d.ts +2 -0
- package/dist/event/abstract.d.ts +42 -0
- package/dist/event/index.d.ts +2 -0
- package/dist/event/useGraniteEvent.d.ts +14 -0
- package/dist/impression-area/ImpressionArea.d.ts +231 -0
- package/dist/impression-area/index.d.ts +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/initial-props/InitialProps.d.ts +92 -0
- package/dist/initial-props/index.d.ts +1 -0
- package/dist/intersection-observer/IOContext.d.ts +10 -0
- package/dist/intersection-observer/IOFlatList.d.ts +55 -0
- package/dist/intersection-observer/IOManager.d.ts +24 -0
- package/dist/intersection-observer/IOScrollView.d.ts +59 -0
- package/dist/intersection-observer/InView.d.ts +107 -0
- package/dist/intersection-observer/IntersectionObserver.d.ts +67 -0
- package/dist/intersection-observer/index.d.ts +8 -0
- package/dist/intersection-observer/withIO.d.ts +20 -0
- package/dist/jest/index.d.ts +1 -0
- package/dist/jest/index.js +32 -0
- package/dist/keyboard/KeyboardAboveView.d.ts +40 -0
- package/dist/keyboard/index.d.ts +2 -0
- package/dist/keyboard/useKeyboardAnimatedHeight.d.ts +20 -0
- package/dist/native-event-emitter/eventEmitters/index.d.ts +2 -0
- package/dist/native-event-emitter/eventEmitters/types.d.ts +4 -0
- package/dist/native-event-emitter/eventEmitters/visibilityChanged.d.ts +10 -0
- package/dist/native-event-emitter/index.d.ts +1 -0
- package/dist/native-event-emitter/nativeEventEmitter.d.ts +15 -0
- package/dist/native-modules/core/GraniteCoreModule.d.ts +8 -0
- package/dist/native-modules/index.d.ts +3 -0
- package/dist/native-modules/natives/GraniteModule.d.ts +7 -0
- package/dist/native-modules/natives/closeView.d.ts +21 -0
- package/dist/native-modules/natives/getSchemeUri.d.ts +23 -0
- package/dist/native-modules/natives/index.d.ts +3 -0
- package/dist/native-modules/natives/openURL.d.ts +36 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/useWaitForReturnNavigator.d.ts +39 -0
- package/dist/rn-polyfills/index.d.ts +1 -0
- package/dist/rn-polyfills/symbol-asynciterator/index.d.ts +9 -0
- package/dist/rn-polyfills/url/index.d.ts +1 -0
- package/dist/router/Router.d.ts +59 -0
- package/dist/router/components/BackButton.d.ts +7 -0
- package/dist/router/components/CanGoBackGuard.d.ts +6 -0
- package/dist/router/components/RouterBackButton.d.ts +9 -0
- package/dist/router/components/StackNavigator.d.ts +54 -0
- package/dist/router/constants.d.ts +2 -0
- package/dist/router/createRoute.d.ts +39 -0
- package/dist/router/createRoute.test-d.d.ts +9 -0
- package/dist/router/hooks/useInitialRouteName.d.ts +1 -0
- package/dist/router/hooks/useIsInitialScreen.d.ts +1 -0
- package/dist/router/hooks/useRouterControls.d.ts +11 -0
- package/dist/router/index.d.ts +3 -0
- package/dist/router/types/RequireContext.d.ts +7 -0
- package/dist/router/types/RouteScreen.d.ts +16 -0
- package/dist/router/types/Screen.d.ts +23 -0
- package/dist/router/types/index.d.ts +3 -0
- package/dist/router/types/screen-option.d.ts +4 -0
- package/dist/router/utils/createParentRouteScreenMap.d.ts +8 -0
- package/dist/router/utils/defaultParserParams.d.ts +9 -0
- package/dist/router/utils/index.d.ts +2 -0
- package/dist/router/utils/matchers.d.ts +2 -0
- package/dist/router/utils/mergeParentLayoutScreen.d.ts +18 -0
- package/dist/router/utils/path.d.ts +53 -0
- package/dist/router/utils/screen.d.ts +37 -0
- package/dist/scroll-view-inertial-background/ScrollViewInertialBackground.d.ts +49 -0
- package/dist/scroll-view-inertial-background/index.d.ts +1 -0
- package/dist/status-bar/StatusBar.android.d.ts +3 -0
- package/dist/status-bar/StatusBar.ios.d.ts +3 -0
- package/dist/status-bar/index.d.ts +2 -0
- package/dist/status-bar/types.d.ts +20 -0
- package/dist/status-bar/utils.d.ts +3 -0
- package/dist/types/global.d.ts +14 -0
- package/dist/use-back-event/index.d.ts +1 -0
- package/dist/use-back-event/useBackEvent.d.ts +135 -0
- package/dist/utils/noop.d.ts +1 -0
- package/dist/utils/usePreservedCallback.d.ts +1 -0
- package/dist/video/Video.d.ts +67 -0
- package/dist/video/index.d.ts +1 -0
- package/dist/video/instance.d.ts +9 -0
- package/dist/visibility/VisibilityProvider.d.ts +27 -0
- package/dist/visibility/index.d.ts +6 -0
- package/dist/visibility/react-navigation/index.d.ts +2 -0
- package/dist/visibility/react-navigation/useIsFocusedSafely.d.ts +20 -0
- package/dist/visibility/react-navigation/useNavigationSafely.d.ts +19 -0
- package/dist/visibility/useIsAppForeground.d.ts +39 -0
- package/dist/visibility/useVisibility.d.ts +35 -0
- package/dist/visibility/useVisibilityChange.d.ts +51 -0
- package/dist/visibility/useVisibilityChanged.d.ts +41 -0
- package/dist/visibility/utils/usePrevious.d.ts +15 -0
- package/jest.d.ts +1 -0
- package/package.json +94 -0
- package/presets.d.ts +1 -0
- package/src/app/App/index.android.tsx +6 -0
- package/src/app/App/index.d.ts +6 -0
- package/src/app/App/index.ios.tsx +13 -0
- package/src/app/AppRoot.tsx +39 -0
- package/src/app/Granite.tsx +128 -0
- package/src/app/HostAppRoot.tsx +19 -0
- package/src/app/index.ts +2 -0
- package/src/async-bridges.ts +2 -0
- package/src/blur/BlurView.tsx +103 -0
- package/src/blur/ReactNativeBlurModule.ts +19 -0
- package/src/blur/constants.ts +3 -0
- package/src/blur/index.ts +1 -0
- package/src/constant-bridges.ts +1 -0
- package/src/constants.ts +1 -0
- package/src/dev-entrypoint/index.tsx +17 -0
- package/src/event/abstract.ts +130 -0
- package/src/event/index.ts +2 -0
- package/src/event/useGraniteEvent.ts +34 -0
- package/src/impression-area/ImpressionArea.tsx +341 -0
- package/src/impression-area/index.ts +1 -0
- package/src/index.ts +24 -0
- package/src/initial-props/InitialProps.ts +95 -0
- package/src/initial-props/index.ts +1 -0
- package/src/intersection-observer/IOContext.ts +16 -0
- package/src/intersection-observer/IOFlatList.ts +72 -0
- package/src/intersection-observer/IOManager.ts +73 -0
- package/src/intersection-observer/IOScrollView.ts +69 -0
- package/src/intersection-observer/InView.tsx +205 -0
- package/src/intersection-observer/IntersectionObserver.ts +212 -0
- package/src/intersection-observer/index.ts +24 -0
- package/src/intersection-observer/withIO.tsx +151 -0
- package/src/jest/index.ts +1 -0
- package/src/keyboard/KeyboardAboveView.tsx +62 -0
- package/src/keyboard/index.ts +2 -0
- package/src/keyboard/useKeyboardAnimatedHeight.tsx +81 -0
- package/src/native-event-emitter/eventEmitters/index.ts +3 -0
- package/src/native-event-emitter/eventEmitters/types.ts +4 -0
- package/src/native-event-emitter/eventEmitters/visibilityChanged.ts +11 -0
- package/src/native-event-emitter/index.ts +1 -0
- package/src/native-event-emitter/nativeEventEmitter.ts +18 -0
- package/src/native-modules/core/GraniteCoreModule.ts +9 -0
- package/src/native-modules/index.ts +3 -0
- package/src/native-modules/natives/GraniteModule.ts +8 -0
- package/src/native-modules/natives/closeView.ts +25 -0
- package/src/native-modules/natives/getSchemeUri.ts +27 -0
- package/src/native-modules/natives/index.ts +3 -0
- package/src/native-modules/natives/openURL.ts +40 -0
- package/src/react/index.ts +1 -0
- package/src/react/useWaitForReturnNavigator.ts +75 -0
- package/src/rn-polyfills/index.ts +7 -0
- package/src/rn-polyfills/symbol-asynciterator/index.ts +15 -0
- package/src/rn-polyfills/url/index.ts +1 -0
- package/src/router/Router.tsx +164 -0
- package/src/router/components/BackButton.tsx +58 -0
- package/src/router/components/CanGoBackGuard.tsx +31 -0
- package/src/router/components/RouterBackButton.tsx +32 -0
- package/src/router/components/StackNavigator.tsx +12 -0
- package/src/router/constants.ts +3 -0
- package/src/router/createRoute.test-d.ts +52 -0
- package/src/router/createRoute.ts +161 -0
- package/src/router/hooks/useInitialRouteName.tsx +22 -0
- package/src/router/hooks/useIsInitialScreen.ts +7 -0
- package/src/router/hooks/useRouterControls.tsx +72 -0
- package/src/router/index.ts +3 -0
- package/src/router/types/RequireContext.ts +7 -0
- package/src/router/types/RouteScreen.ts +17 -0
- package/src/router/types/Screen.tsx +24 -0
- package/src/router/types/index.ts +3 -0
- package/src/router/types/screen-option.ts +23 -0
- package/src/router/utils/createParentRouteScreenMap.spec.ts +166 -0
- package/src/router/utils/createParentRouteScreenMap.ts +136 -0
- package/src/router/utils/defaultParserParams.spec.ts +46 -0
- package/src/router/utils/defaultParserParams.ts +19 -0
- package/src/router/utils/index.ts +2 -0
- package/src/router/utils/matchers.ts +5 -0
- package/src/router/utils/mergeParentLayoutScreen.spec.tsx +112 -0
- package/src/router/utils/mergeParentLayoutScreen.tsx +43 -0
- package/src/router/utils/path.spec.ts +135 -0
- package/src/router/utils/path.ts +105 -0
- package/src/router/utils/screen.tsx +95 -0
- package/src/scroll-view-inertial-background/ScrollViewInertialBackground.tsx +99 -0
- package/src/scroll-view-inertial-background/index.ts +1 -0
- package/src/status-bar/StatusBar.android.tsx +36 -0
- package/src/status-bar/StatusBar.d.ts +4 -0
- package/src/status-bar/StatusBar.ios.tsx +34 -0
- package/src/status-bar/index.ts +2 -0
- package/src/status-bar/types.ts +21 -0
- package/src/status-bar/utils.ts +20 -0
- package/src/types/global.ts +21 -0
- package/src/use-back-event/index.ts +1 -0
- package/src/use-back-event/useBackEvent.tsx +260 -0
- package/src/utils/noop.ts +1 -0
- package/src/utils/usePreservedCallback.ts +16 -0
- package/src/video/Video.tsx +104 -0
- package/src/video/index.ts +1 -0
- package/src/video/instance.tsx +28 -0
- package/src/visibility/VisibilityProvider.tsx +36 -0
- package/src/visibility/index.ts +6 -0
- package/src/visibility/react-navigation/index.ts +2 -0
- package/src/visibility/react-navigation/useIsFocusedSafely.tsx +58 -0
- package/src/visibility/react-navigation/useNavigationSafely.tsx +30 -0
- package/src/visibility/useIsAppForeground.tsx +73 -0
- package/src/visibility/useVisibility.tsx +54 -0
- package/src/visibility/useVisibilityChange.ts +69 -0
- package/src/visibility/useVisibilityChanged.tsx +69 -0
- package/src/visibility/utils/usePrevious.tsx +24 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String representing whether the screen is visible.
|
|
3
|
+
* @typedef {string} VisibilityState
|
|
4
|
+
* @property {'visible'} visible - The screen is visible.
|
|
5
|
+
* @property {'hidden'} hidden - The screen is not visible.
|
|
6
|
+
*/
|
|
7
|
+
export type VisibilityState = 'visible' | 'hidden';
|
|
8
|
+
/**
|
|
9
|
+
* @callback VisibilityCallback
|
|
10
|
+
* @param {VisibilityState} state - String representing the visibility state of the screen.
|
|
11
|
+
*/
|
|
12
|
+
export type VisibilityCallback = (state: VisibilityState) => void;
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
* @category Screen Control
|
|
16
|
+
* @name useVisibilityChange
|
|
17
|
+
* @kind function
|
|
18
|
+
* @description
|
|
19
|
+
* Calls a callback function with the visibility state when the screen's visibility changes.
|
|
20
|
+
* The callback function receives the return value from [useVisibility](/en/reference/react-native/Screen%20Control/useVisibility). If the return value is `true`, it passes 'visible', and if `false`, it passes 'hidden'.
|
|
21
|
+
*
|
|
22
|
+
* @param {VisibilityCallback} callback - Calls a callback function that receives visibility changes when the screen's visibility changes.
|
|
23
|
+
* @example
|
|
24
|
+
*
|
|
25
|
+
* ### Example of logging when screen visibility changes
|
|
26
|
+
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* import { useState } from 'react';
|
|
29
|
+
* import { Text, View } from 'react-native';
|
|
30
|
+
* import { useVisibilityChange, VisibilityState } from '@granite-js/react-native';
|
|
31
|
+
*
|
|
32
|
+
* export function UseVisibilityChangeExample() {
|
|
33
|
+
* const [visibilityHistory, setVisibilityHistory] = useState<VisibilityState[]>([]);
|
|
34
|
+
*
|
|
35
|
+
* useVisibilityChange((visibility) => {
|
|
36
|
+
* setVisibilityHistory((prev) => [...prev, visibility]);
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* return (
|
|
40
|
+
* <View>
|
|
41
|
+
* <Text>Logs are created when leaving and returning to the home screen.</Text>
|
|
42
|
+
*
|
|
43
|
+
* {visibilityHistory.map((visibility, index) => (
|
|
44
|
+
* <Text key={index}>{JSON.stringify(visibility)}</Text>
|
|
45
|
+
* ))}
|
|
46
|
+
* </View>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function useVisibilityChange(callback: VisibilityCallback): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PropsWithChildren, ReactElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @name VisibilityChangedProvider
|
|
4
|
+
* @kind function
|
|
5
|
+
* @description
|
|
6
|
+
* A Provider that manages whether a React Native screen is visible.
|
|
7
|
+
* It subscribes to the app's `visibilityChanged` event to detect and manage screen visibility.
|
|
8
|
+
*
|
|
9
|
+
* @param {ReactNode | undefined} children - Child components that check screen visibility.
|
|
10
|
+
* @param {boolean} isVisible - A boolean value indicating whether the screen is visible.
|
|
11
|
+
* @returns {ReactElement} - A React Provider component wrapped with `VisibilityChangedContext.Provider`.
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* export function VisibilityProvider({ isVisible, children }: Props) {
|
|
15
|
+
* return (
|
|
16
|
+
* <VisibilityChangedProvider isVisible={isVisible}>
|
|
17
|
+
* {children}
|
|
18
|
+
* </VisibilityChangedProvider>
|
|
19
|
+
* );
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function VisibilityChangedProvider({ children, isVisible, }: PropsWithChildren<{
|
|
24
|
+
isVisible: boolean;
|
|
25
|
+
}>): ReactElement;
|
|
26
|
+
/**
|
|
27
|
+
* @name useVisibilityChanged
|
|
28
|
+
* @category Hooks
|
|
29
|
+
* @kind function
|
|
30
|
+
* @description
|
|
31
|
+
* A Hook that returns whether a React Native screen is visible.
|
|
32
|
+
* @returns {boolean} - Returns whether the screen is visible.
|
|
33
|
+
* @throws {Error} Throws an error when not used within a `VisibilityChangedProvider`.
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const isVisible = useVisibilityChanged();
|
|
37
|
+
* console.log(isVisible);
|
|
38
|
+
* // true or false
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function useVisibilityChanged(): boolean;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name usePrevious
|
|
3
|
+
* @category Hooks
|
|
4
|
+
* @kind function
|
|
5
|
+
* @description
|
|
6
|
+
* A Hook that returns the previous value.
|
|
7
|
+
* @param {T} value - The value to return the previous value of.
|
|
8
|
+
* @returns {T} - Returns the previous value.
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const isVisible = useVisibility();
|
|
12
|
+
* const prevValue = usePrevious<boolean>(isVisible) ?? false;
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function usePrevious<T>(value: T): T;
|
package/jest.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/jest';
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@granite-js/react-native",
|
|
3
|
+
"version": "0.0.0-dev-20250725013859",
|
|
4
|
+
"description": "The Granite Framework",
|
|
5
|
+
"bin": {
|
|
6
|
+
"granite": "./bin/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"typecheck": "tsc --noEmit",
|
|
10
|
+
"test": "vitest --no-watch --coverage",
|
|
11
|
+
"lint": "eslint .",
|
|
12
|
+
"build": "tsup && tsc -p tsconfig.build.json",
|
|
13
|
+
"prepack": "yarn build"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./src/index.ts"
|
|
21
|
+
},
|
|
22
|
+
"./async-bridges": {
|
|
23
|
+
"types": "./src/async-bridges.ts",
|
|
24
|
+
"default": "./src/async-bridges.ts"
|
|
25
|
+
},
|
|
26
|
+
"./constant-bridges": {
|
|
27
|
+
"types": "./src/constant-bridges.ts",
|
|
28
|
+
"default": "./src/constant-bridges.ts"
|
|
29
|
+
},
|
|
30
|
+
"./jest": {
|
|
31
|
+
"types": "./dist/jest/index.d.ts",
|
|
32
|
+
"default": "./dist/jest/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./cli": {
|
|
35
|
+
"types": "./cli.d.ts",
|
|
36
|
+
"default": "./cli.js"
|
|
37
|
+
},
|
|
38
|
+
"./config": {
|
|
39
|
+
"types": "./config.d.ts",
|
|
40
|
+
"default": "./config.js"
|
|
41
|
+
},
|
|
42
|
+
"./types": {
|
|
43
|
+
"types": "./dist/types/global.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./package.json": "./package.json"
|
|
46
|
+
},
|
|
47
|
+
"files": [
|
|
48
|
+
"src",
|
|
49
|
+
"dist",
|
|
50
|
+
"bin",
|
|
51
|
+
"config.js",
|
|
52
|
+
"cli.js",
|
|
53
|
+
"*.d.ts"
|
|
54
|
+
],
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@babel/core": "^7.24.9",
|
|
57
|
+
"@babel/preset-env": "^7.24.8",
|
|
58
|
+
"@babel/preset-typescript": "^7.24.7",
|
|
59
|
+
"@granite-js/native": "workspace:*",
|
|
60
|
+
"@testing-library/dom": "^10.4.0",
|
|
61
|
+
"@testing-library/react": "^16.1.0",
|
|
62
|
+
"@types/babel__core": "^7",
|
|
63
|
+
"@types/babel__preset-env": "^7",
|
|
64
|
+
"@types/node": "^22.10.2",
|
|
65
|
+
"@types/react": "18.3.3",
|
|
66
|
+
"@types/react-dom": "^18",
|
|
67
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
68
|
+
"esbuild": "^0.25.4",
|
|
69
|
+
"eslint": "^9.7.0",
|
|
70
|
+
"jsdom": "^25.0.1",
|
|
71
|
+
"react": "18.2.0",
|
|
72
|
+
"react-dom": "18.2.0",
|
|
73
|
+
"react-native": "0.72.6",
|
|
74
|
+
"tsup": "^8.5.0",
|
|
75
|
+
"typescript": "5.8.3",
|
|
76
|
+
"vitest": "^2.1.8"
|
|
77
|
+
},
|
|
78
|
+
"peerDependencies": {
|
|
79
|
+
"@granite-js/native": "0.0.0-dev-20250725013859",
|
|
80
|
+
"@types/react": "*",
|
|
81
|
+
"react": "*",
|
|
82
|
+
"react-native": "*"
|
|
83
|
+
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"@granite-js/cli": "workspace:*",
|
|
86
|
+
"@granite-js/image": "workspace:*",
|
|
87
|
+
"@granite-js/jest": "workspace:*",
|
|
88
|
+
"@granite-js/lottie": "workspace:*",
|
|
89
|
+
"@granite-js/mpack": "workspace:*",
|
|
90
|
+
"@granite-js/style-utils": "workspace:*",
|
|
91
|
+
"es-toolkit": "^1.34.1",
|
|
92
|
+
"react-native-url-polyfill": "1.3.0"
|
|
93
|
+
}
|
|
94
|
+
}
|
package/presets.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/presets';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { VisibilityProvider } from '../../visibility';
|
|
3
|
+
import { Props } from '.';
|
|
4
|
+
|
|
5
|
+
type IOSInitialProps = Props & {
|
|
6
|
+
isVisible: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function App({ children, ...props }: IOSInitialProps) {
|
|
10
|
+
const { isVisible } = useMemo(() => props, [props]);
|
|
11
|
+
|
|
12
|
+
return <VisibilityProvider isVisible={isVisible}>{children}</VisibilityProvider>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SafeAreaProvider } from '@granite-js/native/react-native-safe-area-context';
|
|
2
|
+
import type { ComponentType, PropsWithChildren } from 'react';
|
|
3
|
+
import type { GraniteProps } from './Granite';
|
|
4
|
+
import type { InitialProps } from '../initial-props';
|
|
5
|
+
import { BackEventProvider, useBackEventState } from '../use-back-event';
|
|
6
|
+
import { App } from './App';
|
|
7
|
+
import { Router } from '../router';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
interface AppRootProps extends GraniteProps {
|
|
13
|
+
container: ComponentType<PropsWithChildren<InitialProps>>;
|
|
14
|
+
initialProps: InitialProps;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function AppRoot({ appName, context, container: Container, initialProps, router }: AppRootProps) {
|
|
18
|
+
const backEventState = useBackEventState();
|
|
19
|
+
const scheme = global.__granite.app.scheme;
|
|
20
|
+
const baseScheme = `${scheme}://${appName}`;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<App {...initialProps}>
|
|
24
|
+
<SafeAreaProvider>
|
|
25
|
+
<BackEventProvider backEvent={backEventState}>
|
|
26
|
+
<Router
|
|
27
|
+
context={context}
|
|
28
|
+
initialProps={initialProps}
|
|
29
|
+
container={Container}
|
|
30
|
+
canGoBack={!backEventState.hasBackEvent}
|
|
31
|
+
onBack={backEventState.onBack}
|
|
32
|
+
prefix={baseScheme}
|
|
33
|
+
{...router}
|
|
34
|
+
/>
|
|
35
|
+
</BackEventProvider>
|
|
36
|
+
</SafeAreaProvider>
|
|
37
|
+
</App>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { ComponentType, PropsWithChildren } from 'react';
|
|
2
|
+
import { AppRegistry } from 'react-native';
|
|
3
|
+
import { ENTRY_BUNDLE_NAME } from '../constants';
|
|
4
|
+
import type { InitialProps } from '../initial-props';
|
|
5
|
+
import type { RouterProps, RequireContext } from '../router';
|
|
6
|
+
import { AppRoot } from './AppRoot';
|
|
7
|
+
import { HostAppRoot } from './HostAppRoot';
|
|
8
|
+
|
|
9
|
+
export interface GraniteProps {
|
|
10
|
+
/**
|
|
11
|
+
* @description
|
|
12
|
+
* The name of the app.
|
|
13
|
+
*/
|
|
14
|
+
appName: string;
|
|
15
|
+
/**
|
|
16
|
+
* @description
|
|
17
|
+
* The context of the app.
|
|
18
|
+
*
|
|
19
|
+
* @TODO Hide context
|
|
20
|
+
*/
|
|
21
|
+
context: RequireContext;
|
|
22
|
+
/**
|
|
23
|
+
* @description
|
|
24
|
+
* Configuration object to be passed to the router.
|
|
25
|
+
*/
|
|
26
|
+
router?: RouterProps;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const createApp = () => {
|
|
30
|
+
let _appName: string | null = null;
|
|
31
|
+
|
|
32
|
+
function registerComponent(appKey: string, component: React.ComponentType<any>): string {
|
|
33
|
+
if (AppRegistry.getAppKeys().includes(appKey)) {
|
|
34
|
+
throw new Error(`App with key '${appKey}' already registered`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return AppRegistry.registerComponent(appKey, () => component);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
registerApp(
|
|
42
|
+
AppContainer: ComponentType<PropsWithChildren<InitialProps>>,
|
|
43
|
+
{ appName, context, router }: GraniteProps
|
|
44
|
+
): (initialProps: InitialProps) => JSX.Element {
|
|
45
|
+
if (appName === ENTRY_BUNDLE_NAME) {
|
|
46
|
+
throw new Error(`Reserved app name 'shared' cannot be used`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function Root(initialProps: InitialProps) {
|
|
50
|
+
return (
|
|
51
|
+
<AppRoot
|
|
52
|
+
container={AppContainer}
|
|
53
|
+
initialProps={initialProps}
|
|
54
|
+
appName={appName}
|
|
55
|
+
context={context}
|
|
56
|
+
router={router}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
registerComponent(appName, Root);
|
|
62
|
+
_appName = appName;
|
|
63
|
+
|
|
64
|
+
return Root;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
registerHostApp(
|
|
68
|
+
AppContainer: ComponentType<PropsWithChildren<InitialProps>>,
|
|
69
|
+
{ appName }: Pick<GraniteProps, 'appName'>
|
|
70
|
+
): (initialProps: InitialProps) => JSX.Element {
|
|
71
|
+
if (appName !== ENTRY_BUNDLE_NAME) {
|
|
72
|
+
throw new Error(`Host appName must be 'shared'`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function Root(initialProps: InitialProps) {
|
|
76
|
+
return <HostAppRoot container={AppContainer} initialProps={initialProps} />;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
registerComponent(appName, Root);
|
|
80
|
+
_appName = appName;
|
|
81
|
+
|
|
82
|
+
return Root;
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
get appName(): string {
|
|
86
|
+
if (_appName === null) {
|
|
87
|
+
throw new Error('Granite.appName can only be used after registerApp or registerHostApp has been called.');
|
|
88
|
+
}
|
|
89
|
+
return _appName;
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @public
|
|
96
|
+
* @category Core
|
|
97
|
+
* @name Granite
|
|
98
|
+
* @description
|
|
99
|
+
*
|
|
100
|
+
* @property {RegisterService} registerApp - This function sets up the basic environment for your service and helps you start service development quickly without needing complex configuration. By just passing `appName`, you can immediately use various features such as file-based routing, query parameter handling, and back navigation control.
|
|
101
|
+
*
|
|
102
|
+
* The features provided by the `Granite.registerApp` function are as follows:
|
|
103
|
+
* - Routing: URLs are automatically mapped according to file paths. It works similarly to Next.js's file-based routing. For example, the `/my-service/pages/index.ts` file can be accessed at `scheme://my-service`, and the `/my-service/pages/home.ts` file can be accessed at `scheme://my-service/home`.
|
|
104
|
+
* - Query Parameters: You can easily use query parameters received through URL schemes. For example, you can receive a `referrer` parameter and log it.
|
|
105
|
+
* - Back Navigation Control: You can control back navigation events. For example, when a user presses back on a screen, you can show a dialog or close the screen.
|
|
106
|
+
* - Screen Visibility: You can determine whether a screen is visible or hidden from the user. For example, you can use this value to handle specific actions when a user leaves for the home screen.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
*
|
|
110
|
+
* ### Example of creating with the `Granite` component
|
|
111
|
+
*
|
|
112
|
+
* ```tsx
|
|
113
|
+
* import { PropsWithChildren } from 'react';
|
|
114
|
+
* import { Granite, InitialProps } from '@granite-js/react-native';
|
|
115
|
+
* import { context } from '../require.context';
|
|
116
|
+
*
|
|
117
|
+
* function AppContainer({ children }: PropsWithChildren<InitialProps>) {
|
|
118
|
+
* return <>{children}</>;
|
|
119
|
+
* }
|
|
120
|
+
*
|
|
121
|
+
* export default Granite.registerApp(AppContainer, {
|
|
122
|
+
* appName: 'my-app',
|
|
123
|
+
* context,
|
|
124
|
+
* });
|
|
125
|
+
*
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export const Granite = createApp();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ComponentType, PropsWithChildren } from 'react';
|
|
2
|
+
import type { InitialProps } from '../initial-props';
|
|
3
|
+
import { App } from './App';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
interface HostAppRootProps {
|
|
9
|
+
container: ComponentType<PropsWithChildren<InitialProps>>;
|
|
10
|
+
initialProps: InitialProps;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function HostAppRoot({ container: Container, initialProps }: HostAppRootProps) {
|
|
14
|
+
return (
|
|
15
|
+
<App {...initialProps}>
|
|
16
|
+
<Container {...initialProps} />
|
|
17
|
+
</App>
|
|
18
|
+
);
|
|
19
|
+
}
|
package/src/app/index.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { BlurViewProps as InternalBlurViewProps } from '@granite-js/native/@react-native-community/blur';
|
|
2
|
+
import { View, ViewProps } from 'react-native';
|
|
3
|
+
import { ReactNativeBlurModule } from './ReactNativeBlurModule';
|
|
4
|
+
import { isBlurNativeModuleSupported } from './constants';
|
|
5
|
+
|
|
6
|
+
export type BlurType = InternalBlurViewProps['blurType'];
|
|
7
|
+
|
|
8
|
+
export interface BlurViewProps extends ViewProps {
|
|
9
|
+
blurType?: BlurType;
|
|
10
|
+
blurAmount?: number;
|
|
11
|
+
vibrancyEffect?: boolean;
|
|
12
|
+
reducedTransparencyFallbackColor?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @public
|
|
17
|
+
* @category UI
|
|
18
|
+
* @name BlurView
|
|
19
|
+
* @description
|
|
20
|
+
* `BlurView` adds a blurred background effect, primarily on iOS. It creates a visual blur on the background view.
|
|
21
|
+
*
|
|
22
|
+
* This component is supported only on iOS. On Android, it simply renders a regular [`View`](https://reactnative.dev/docs/0.72/view) without any blur effect.
|
|
23
|
+
*
|
|
24
|
+
* You can control the blur intensity and optionally enable the [vibrancy effect](https://developer.apple.com/documentation/uikit/uivibrancyeffect?language=objc), which enhances the visual impact of content displayed over a blurred background.
|
|
25
|
+
*
|
|
26
|
+
* If blur is not supported or doesn't render properly, you can use the `reducedTransparencyFallbackColor` prop to set a fallback background color.
|
|
27
|
+
*
|
|
28
|
+
* Use the `isSupported` property to check whether the current device supports blur. Blur is available on iOS from version 5.126.0 and not supported on Android.
|
|
29
|
+
*
|
|
30
|
+
* @param {BlurViewProps} [props] The props you can pass to `BlurView`. It extends `react-native`'s `ViewProps`, so you can use layout and style properties. The props align with those of [`@react-native-community/blur`](https://github.com/Kureev/react-native-blur/tree/v4.3.2?tab=readme-ov-file#blurview).
|
|
31
|
+
* @param {BlurType} [props.blurType] Type of blur to apply, such as `light`, `dark`, or `extraDark`.
|
|
32
|
+
* @param {number} [props.blurAmount=10] Intensity of the blur effect. Higher values make the blur stronger. Accepts values from `0` to `100`. Default is `10`.
|
|
33
|
+
* @param {boolean} [props.vibrancyEffect=false] Enables the vibrancy effect. This effect enhances content displayed on top of the blur. Only supported on iOS. Default is `false`.
|
|
34
|
+
* @param {string} [props.reducedTransparencyFallbackColor] Fallback background color used when blur cannot be applied due to system settings or device limitations.
|
|
35
|
+
*
|
|
36
|
+
* @returns {JSX.Element} On iOS, returns a blurred `BlurView` or `VibrancyView` component. On Android, returns a regular `View` without blur.
|
|
37
|
+
*
|
|
38
|
+
* ::: warning Note
|
|
39
|
+
* `BlurView` is only supported on iOS. On Android, it renders a regular `View` without any blur effect.
|
|
40
|
+
* :::
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
*
|
|
44
|
+
* ### Blurring background behind a text
|
|
45
|
+
*
|
|
46
|
+
* ```tsx
|
|
47
|
+
* import { BlurView } from '@granite-js/react-native';
|
|
48
|
+
* import { View, Text, StyleSheet } from 'react-native';
|
|
49
|
+
*
|
|
50
|
+
* export function BlurViewExample() {
|
|
51
|
+
* return (
|
|
52
|
+
* <View style={styles.container}>
|
|
53
|
+
* <Text style={styles.absolute}>Blurred Text</Text>
|
|
54
|
+
* <BlurView style={styles.absolute} blurType="light" blurAmount={1} />
|
|
55
|
+
* <Text>Non Blurred Text</Text>
|
|
56
|
+
* </View>
|
|
57
|
+
* );
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* const styles = StyleSheet.create({
|
|
61
|
+
* container: {
|
|
62
|
+
* justifyContent: 'center',
|
|
63
|
+
* alignItems: 'center',
|
|
64
|
+
* width: '100%',
|
|
65
|
+
* height: 300,
|
|
66
|
+
* },
|
|
67
|
+
* absolute: {
|
|
68
|
+
* position: 'absolute',
|
|
69
|
+
* top: 0,
|
|
70
|
+
* left: 0,
|
|
71
|
+
* bottom: 0,
|
|
72
|
+
* right: 0,
|
|
73
|
+
* },
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @see [iOS Vibrancy Effect Documentation](https://developer.apple.com/documentation/uikit/uivibrancyeffect)
|
|
78
|
+
* @see [Zeddios Blog Explanation](https://zeddios.tistory.com/1140)
|
|
79
|
+
*/
|
|
80
|
+
export function BlurView({
|
|
81
|
+
blurType,
|
|
82
|
+
blurAmount = 10,
|
|
83
|
+
reducedTransparencyFallbackColor,
|
|
84
|
+
vibrancyEffect = false,
|
|
85
|
+
...viewProps
|
|
86
|
+
}: BlurViewProps) {
|
|
87
|
+
if (!isBlurNativeModuleSupported || ReactNativeBlurModule == null) {
|
|
88
|
+
return <View {...viewProps} />;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const Component = vibrancyEffect ? ReactNativeBlurModule.VibrancyView : ReactNativeBlurModule.BlurView;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Component
|
|
95
|
+
blurAmount={blurAmount}
|
|
96
|
+
blurType={blurType}
|
|
97
|
+
reducedTransparencyFallbackColor={reducedTransparencyFallbackColor}
|
|
98
|
+
{...viewProps}
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
BlurView.isSupported = isBlurNativeModuleSupported;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BlurView, VibrancyView } from '@granite-js/native/@react-native-community/blur';
|
|
2
|
+
import { isBlurNativeModuleSupported } from './constants';
|
|
3
|
+
|
|
4
|
+
const ReactNativeBlurModule = (() => {
|
|
5
|
+
if (!isBlurNativeModuleSupported) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
return require('@granite-js/native/@react-native-community/blur') as {
|
|
11
|
+
BlurView: typeof BlurView;
|
|
12
|
+
VibrancyView: typeof VibrancyView;
|
|
13
|
+
};
|
|
14
|
+
} catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
})();
|
|
18
|
+
|
|
19
|
+
export { ReactNativeBlurModule };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './BlurView';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './native-modules/natives/getSchemeUri';
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ENTRY_BUNDLE_NAME = 'shared';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import { AppRegistry } from 'react-native';
|
|
3
|
+
import { ENTRY_BUNDLE_NAME } from '../constants';
|
|
4
|
+
import { setup } from '../rn-polyfills';
|
|
5
|
+
|
|
6
|
+
setup();
|
|
7
|
+
|
|
8
|
+
export function register(Component: ComponentType<any>) {
|
|
9
|
+
if (AppRegistry.getAppKeys().includes(ENTRY_BUNDLE_NAME)) {
|
|
10
|
+
console.warn('Granite entrypoint is already registered');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const component = (props: any) => <Component {...props} />;
|
|
15
|
+
|
|
16
|
+
AppRegistry.registerComponent(ENTRY_BUNDLE_NAME, () => component);
|
|
17
|
+
}
|