@granite-js/react-native 0.1.1 → 0.1.2

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
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - e1384cf: re-add previously excluded native module packages
8
+ - Updated dependencies [e1384cf]
9
+ - @granite-js/lottie@0.1.2
10
+ - @granite-js/native@0.1.2
11
+ - @granite-js/image@0.1.2
12
+ - @granite-js/jest@0.1.2
13
+ - @granite-js/style-utils@0.1.2
14
+ - @granite-js/cli@0.1.2
15
+ - @granite-js/mpack@0.1.2
16
+
3
17
  ## 0.1.1
4
18
 
5
19
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import './types/global';
2
2
  export { Granite } from './app';
3
3
  export * from '@granite-js/style-utils';
4
4
  export * from '@granite-js/image';
5
+ export * from '@granite-js/lottie';
5
6
  export * from './dev-entrypoint';
6
7
  export * from './native-modules/natives';
7
8
  export * from './visibility';
@@ -13,5 +14,6 @@ export * from './scroll-view-inertial-background';
13
14
  export * from './react';
14
15
  export * from './router/createRoute';
15
16
  export * from './event';
17
+ export * from './video';
16
18
  export type { InitialProps, ColorPreference } from './initial-props';
17
19
  export type { GraniteProps } from './app';
@@ -0,0 +1,67 @@
1
+ import type { default as VideoRef } from '@granite-js/native/react-native-video';
2
+ import { ComponentProps } from 'react';
3
+ import { Animated } from 'react-native';
4
+ import * as instance from './instance';
5
+ declare const AnimatedRNVideo: Animated.AnimatedComponent<import("react").ComponentType<instance.VideoNativeProps>>;
6
+ type VideoProps = ComponentProps<typeof AnimatedRNVideo>;
7
+ /**
8
+ * @public
9
+ * @name Video
10
+ * @category UI
11
+ * @description
12
+ * The Video component implements audio focus control logic to prevent the sandbox app from stopping music playing in other apps. It automatically plays or pauses based on the app's state. For example, when the app transitions to the background, the video automatically pauses.
13
+ *
14
+ * ::: warning
15
+ * The Video component uses [react-native-video version (6.0.0-alpha.6)](https://github.com/TheWidlarzGroup/react-native-video/tree/v6.0.0-alpha.6). Therefore, some types or features may not be compatible with the latest version.
16
+ * :::
17
+ *
18
+ * @property {boolean} [isAvailable] Value to check if the `Video` component can be used. You can check this value to determine if the user can render the video or if video functionality is unavailable due to environmental constraints (e.g., network connection issues, unsupported devices). If this value is `false`, you should handle it by not rendering the video or providing alternative content.
19
+ *
20
+ * @param {VideoProperties} [props] Properties provided by [`react-native-video`](https://github.com/TheWidlarzGroup/react-native-video/tree/v6.0.0-alpha.6).
21
+ * @param {string} [props.source.uri] Source of the video to play. Can be set to a file path or URL.
22
+ * @param {boolean} [props.muted=false] Controls the mute state of the video. If `true`, the video's audio is muted; if `false`, the audio plays. Default is `false`.
23
+ * @param {boolean} [props.paused=false] Property to control video playback. If `true`, the video is paused; if `false`, the video plays. Default is `false`, and it autoplays.
24
+ * @param {OnAudioFocusChanged} [props.onAudioFocusChanged] Callback function called when audio focus changes. Must be implemented when `muted` is `false`. For more details, see [OnAudioFocusChanged](/reference/react-native/Types/OnAudioFocusChanged.html).
25
+ * @param {Ref<VideoRef>} ref Reference object to access the video instance. Through this ref, you can access various methods of the video instance.
26
+ *
27
+ * @returns {JSX.Element} Returns a JSX element that renders the video. Uses `Animated` to provide smooth animation effects during video playback.
28
+ *
29
+ * @see [react-native-video] https://github.com/react-native-video/react-native-video
30
+ * For detailed properties of the video component, please refer to the official documentation.
31
+ * @see [react-native-video-6.0.0] https://github.com/TheWidlarzGroup/react-native-video/releases/tag/v6.0.0
32
+ * This is the source code of the version currently installed in the sandbox app.
33
+ *
34
+ * @example
35
+ *
36
+ * ### Video Autoplay Example
37
+ *
38
+ * ```tsx
39
+ * import { useRef } from 'react';
40
+ * import { View } from 'react-native';
41
+ * import { Video } from '@granite-js/react-native';
42
+ *
43
+ * export function VideoExample() {
44
+ * const videoRef = useRef(null);
45
+ *
46
+ * return (
47
+ * <View>
48
+ * <Video
49
+ * ref={videoRef}
50
+ * source={{ uri: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4' }}
51
+ * muted={true}
52
+ * paused={false}
53
+ * resizeMode="cover"
54
+ * style={{ width: 300, height: 200, borderWidth: 1 }}
55
+ * />
56
+ * </View>
57
+ * );
58
+ * }
59
+ * ```
60
+ */
61
+ declare const Video: import("react").ForwardRefExoticComponent<Omit<import("react-native-video").VideoProperties, "onAudioFocusChanged"> & {
62
+ onAudioFocusChanged?: (event: {
63
+ hasAudioFocus: boolean;
64
+ }) => void;
65
+ } & import("react").RefAttributes<VideoRef>>;
66
+ export { Video };
67
+ export type { VideoRef, VideoProps };
@@ -0,0 +1 @@
1
+ export * from './Video';
@@ -0,0 +1,9 @@
1
+ import type { VideoProperties } from '@granite-js/native/react-native-video';
2
+ import { type ComponentType } from 'react';
3
+ export type VideoNativeProps = Omit<VideoProperties, 'onAudioFocusChanged'> & {
4
+ onAudioFocusChanged?: (event: {
5
+ hasAudioFocus: boolean;
6
+ }) => void;
7
+ };
8
+ export declare const Component: ComponentType<VideoNativeProps>;
9
+ export declare const isAvailable: boolean;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@granite-js/react-native",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "The Granite Framework",
5
5
  "bin": {
6
6
  "granite": "./bin/cli.js"
7
7
  },
8
8
  "scripts": {
9
9
  "typecheck": "tsc --noEmit",
10
- "test": "vitest --no-watch",
10
+ "test": "vitest --no-watch --coverage",
11
11
  "lint": "eslint .",
12
12
  "build": "tsup && tsc -p tsconfig.build.json",
13
13
  "prepack": "yarn build"
@@ -56,7 +56,7 @@
56
56
  "@babel/core": "^7.24.9",
57
57
  "@babel/preset-env": "^7.24.8",
58
58
  "@babel/preset-typescript": "^7.24.7",
59
- "@granite-js/native": "0.1.1",
59
+ "@granite-js/native": "0.1.2",
60
60
  "@testing-library/dom": "^10.4.0",
61
61
  "@testing-library/react": "^16.1.0",
62
62
  "@types/babel__core": "^7",
@@ -64,6 +64,7 @@
64
64
  "@types/node": "^22.10.2",
65
65
  "@types/react": "18.3.3",
66
66
  "@types/react-dom": "^18",
67
+ "@vitest/coverage-v8": "^2.1.8",
67
68
  "esbuild": "^0.25.4",
68
69
  "eslint": "^9.7.0",
69
70
  "jsdom": "^25.0.1",
@@ -81,11 +82,12 @@
81
82
  "react-native": "*"
82
83
  },
83
84
  "dependencies": {
84
- "@granite-js/cli": "0.1.1",
85
- "@granite-js/image": "0.1.1",
86
- "@granite-js/jest": "0.1.1",
87
- "@granite-js/mpack": "0.1.1",
88
- "@granite-js/style-utils": "0.1.1",
85
+ "@granite-js/cli": "0.1.2",
86
+ "@granite-js/image": "0.1.2",
87
+ "@granite-js/jest": "0.1.2",
88
+ "@granite-js/lottie": "0.1.2",
89
+ "@granite-js/mpack": "0.1.2",
90
+ "@granite-js/style-utils": "0.1.2",
89
91
  "es-toolkit": "^1.34.1",
90
92
  "react-native-url-polyfill": "1.3.0"
91
93
  }
package/src/index.ts CHANGED
@@ -3,6 +3,8 @@ import './types/global';
3
3
  export { Granite } from './app';
4
4
  export * from '@granite-js/style-utils';
5
5
  export * from '@granite-js/image';
6
+ export * from '@granite-js/lottie';
7
+
6
8
  export * from './dev-entrypoint';
7
9
  export * from './native-modules/natives';
8
10
  export * from './visibility';
@@ -14,6 +16,7 @@ export * from './scroll-view-inertial-background';
14
16
  export * from './react';
15
17
  export * from './router/createRoute';
16
18
  export * from './event';
19
+ export * from './video';
17
20
 
18
21
  export type { InitialProps, ColorPreference } from './initial-props';
19
22
  export type { GraniteProps } from './app';
@@ -0,0 +1,104 @@
1
+ import type { default as VideoRef } from '@granite-js/native/react-native-video';
2
+ import { ComponentProps, forwardRef, useMemo, useState } from 'react';
3
+ import { Animated, Platform } from 'react-native';
4
+ import * as instance from './instance';
5
+ import { useVisibility } from '../visibility';
6
+
7
+ const AnimatedRNVideo = Animated.createAnimatedComponent(instance.Component);
8
+
9
+ type VideoProps = ComponentProps<typeof AnimatedRNVideo>;
10
+
11
+ /**
12
+ * @public
13
+ * @name Video
14
+ * @category UI
15
+ * @description
16
+ * The Video component implements audio focus control logic to prevent the sandbox app from stopping music playing in other apps. It automatically plays or pauses based on the app's state. For example, when the app transitions to the background, the video automatically pauses.
17
+ *
18
+ * ::: warning
19
+ * The Video component uses [react-native-video version (6.0.0-alpha.6)](https://github.com/TheWidlarzGroup/react-native-video/tree/v6.0.0-alpha.6). Therefore, some types or features may not be compatible with the latest version.
20
+ * :::
21
+ *
22
+ * @property {boolean} [isAvailable] Value to check if the `Video` component can be used. You can check this value to determine if the user can render the video or if video functionality is unavailable due to environmental constraints (e.g., network connection issues, unsupported devices). If this value is `false`, you should handle it by not rendering the video or providing alternative content.
23
+ *
24
+ * @param {VideoProperties} [props] Properties provided by [`react-native-video`](https://github.com/TheWidlarzGroup/react-native-video/tree/v6.0.0-alpha.6).
25
+ * @param {string} [props.source.uri] Source of the video to play. Can be set to a file path or URL.
26
+ * @param {boolean} [props.muted=false] Controls the mute state of the video. If `true`, the video's audio is muted; if `false`, the audio plays. Default is `false`.
27
+ * @param {boolean} [props.paused=false] Property to control video playback. If `true`, the video is paused; if `false`, the video plays. Default is `false`, and it autoplays.
28
+ * @param {OnAudioFocusChanged} [props.onAudioFocusChanged] Callback function called when audio focus changes. Must be implemented when `muted` is `false`. For more details, see [OnAudioFocusChanged](/reference/react-native/Types/OnAudioFocusChanged.html).
29
+ * @param {Ref<VideoRef>} ref Reference object to access the video instance. Through this ref, you can access various methods of the video instance.
30
+ *
31
+ * @returns {JSX.Element} Returns a JSX element that renders the video. Uses `Animated` to provide smooth animation effects during video playback.
32
+ *
33
+ * @see [react-native-video] https://github.com/react-native-video/react-native-video
34
+ * For detailed properties of the video component, please refer to the official documentation.
35
+ * @see [react-native-video-6.0.0] https://github.com/TheWidlarzGroup/react-native-video/releases/tag/v6.0.0
36
+ * This is the source code of the version currently installed in the sandbox app.
37
+ *
38
+ * @example
39
+ *
40
+ * ### Video Autoplay Example
41
+ *
42
+ * ```tsx
43
+ * import { useRef } from 'react';
44
+ * import { View } from 'react-native';
45
+ * import { Video } from '@granite-js/react-native';
46
+ *
47
+ * export function VideoExample() {
48
+ * const videoRef = useRef(null);
49
+ *
50
+ * return (
51
+ * <View>
52
+ * <Video
53
+ * ref={videoRef}
54
+ * source={{ uri: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4' }}
55
+ * muted={true}
56
+ * paused={false}
57
+ * resizeMode="cover"
58
+ * style={{ width: 300, height: 200, borderWidth: 1 }}
59
+ * />
60
+ * </View>
61
+ * );
62
+ * }
63
+ * ```
64
+ */
65
+ const Video = forwardRef<VideoRef, instance.VideoNativeProps>((props, ref) => {
66
+ const [isFocused, setIsFocused] = useState(props.muted || props.paused);
67
+ const visible = useVisibility();
68
+
69
+ // If focus state is not managed directly by the service through onAudioFocusChanged, control the paused value based on internal state.
70
+ const paused = useMemo(
71
+ () => !visible || props.paused || (!props.onAudioFocusChanged && !isFocused),
72
+ [props.onAudioFocusChanged, props.paused, visible, isFocused]
73
+ );
74
+
75
+ const disableFocus = props.muted || props.paused;
76
+ const mixWithOthers = props.muted ? 'mix' : undefined;
77
+
78
+ return (
79
+ <AnimatedRNVideo
80
+ ref={ref as any}
81
+ progressUpdateInterval={16}
82
+ disableFocus={Platform.OS === 'ios' ? false : disableFocus}
83
+ playWhenInactive
84
+ onAudioFocusChanged={(event: any) => {
85
+ setIsFocused(event.hasAudioFocus);
86
+ props.onAudioFocusChanged?.(event);
87
+ }}
88
+ {...props}
89
+ // Internal state is used to control the component's states.
90
+ paused={paused}
91
+ mixWithOthers={mixWithOthers}
92
+ />
93
+ );
94
+ });
95
+
96
+ Object.defineProperty(Video, 'isAvailable', {
97
+ value: instance.isAvailable,
98
+ enumerable: true,
99
+ writable: false,
100
+ configurable: false,
101
+ });
102
+
103
+ export { Video };
104
+ export type { VideoRef, VideoProps };
@@ -0,0 +1 @@
1
+ export * from './Video';
@@ -0,0 +1,28 @@
1
+ import type { VideoProperties } from '@granite-js/native/react-native-video';
2
+ import { Component as ReactComponent, forwardRef, type ComponentType, type ForwardedRef } from 'react';
3
+ import { View } from 'react-native';
4
+
5
+ export type VideoNativeProps = Omit<VideoProperties, 'onAudioFocusChanged'> & {
6
+ onAudioFocusChanged?: (event: { hasAudioFocus: boolean }) => void;
7
+ };
8
+
9
+ class FallbackComponent extends ReactComponent<VideoNativeProps & { innerRef: ForwardedRef<View> }> {
10
+ render() {
11
+ return <View ref={this.props.innerRef} />;
12
+ }
13
+ }
14
+
15
+ const ForwardedComponent = forwardRef<View, VideoNativeProps>((props: VideoNativeProps, ref) => (
16
+ <FallbackComponent {...props} innerRef={ref} />
17
+ ));
18
+
19
+ function getVideoComponent(): ComponentType<VideoNativeProps> {
20
+ try {
21
+ return require('@granite-js/native/react-native-video')?.default;
22
+ } catch {
23
+ return ForwardedComponent;
24
+ }
25
+ }
26
+
27
+ export const Component = getVideoComponent();
28
+ export const isAvailable = Component !== ForwardedComponent;