Skip to content

Commit a996b4a

Browse files
authored
feat: added web support (#1150)
* chore: updated dependencies * refactor: updated ReText view for web * chore: added cursor for handle container * chore: updated expo version for example project * feat: added scrollable component for web * feat: added gesture and scroll handler for web * chore: added getRefNativeTag for web * feat: rewrite gesture apis with gesture handler 2 (#1126) * chore: updated dependencies * feat: rewrite the gesture api with gh2 * fix(#1119): fixed race condition between onmount and keyboard animations * fix: update ref handler for web * chore: removed unused component * chore: updated expo * fix: detached example on web
1 parent a1ec74d commit a996b4a

24 files changed

+914
-112
lines changed

example/app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
"nanoid": "^3.3.3",
2121
"react": "17.0.2",
2222
"react-native": "0.68.1",
23-
"react-native-gesture-handler": "^2.5.0",
23+
"react-native-gesture-handler": "~2.8.0",
2424
"react-native-maps": "^0.30.1",
2525
"react-native-pager-view": "^5.4.24",
26-
"react-native-reanimated": "^2.9.1",
26+
"react-native-reanimated": "~2.12.0",
2727
"react-native-redash": "^16.0.11",
2828
"react-native-safe-area-context": "4.2.4",
2929
"react-native-screens": "^3.15.0",

example/app/src/components/contactList/styles.web.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ export const styles = StyleSheet.create({
99
sectionHeaderTitle: {
1010
fontSize: 16,
1111
textTransform: 'uppercase',
12+
color: 'black',
1213
},
1314
container: {
1415
flex: 1,
15-
paddingHorizontal: 16,
1616
},
1717
contentContainer: {
1818
paddingHorizontal: 16,

example/app/src/screens/modal/DetachedExample.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const DetachedExample = () => {
7676
snapPoints={animatedSnapPoints}
7777
handleHeight={animatedHandleHeight}
7878
contentHeight={animatedContentHeight}
79-
bottomInset={safeBottomArea + 34}
79+
bottomInset={safeBottomArea + 16}
8080
enablePanDownToClose={true}
8181
style={styles.sheetContainer}
8282
backgroundComponent={null}
@@ -118,7 +118,7 @@ const styles = StyleSheet.create({
118118
contentContainerStyle: {
119119
paddingTop: 12,
120120
paddingBottom: 12,
121-
paddingHorizontal: 16,
121+
paddingHorizontal: 12,
122122
},
123123
footer: {
124124
justifyContent: 'center',

example/bare/ios/Podfile.lock

+6-6
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ PODS:
306306
- React
307307
- react-native-maps (0.30.2):
308308
- React-Core
309-
- react-native-pager-view (5.4.24):
309+
- react-native-pager-view (5.4.25):
310310
- React-Core
311311
- react-native-safe-area-context (4.2.4):
312312
- RCT-Folly
@@ -382,7 +382,7 @@ PODS:
382382
- React-perflogger (= 0.69.4)
383383
- RNCMaskedView (0.1.11):
384384
- React
385-
- RNGestureHandler (2.6.2):
385+
- RNGestureHandler (2.7.0):
386386
- React-Core
387387
- RNReanimated (2.10.0):
388388
- DoubleConversion
@@ -411,7 +411,7 @@ PODS:
411411
- React-RCTText
412412
- ReactCommon/turbomodule/core
413413
- Yoga
414-
- RNScreens (3.15.0):
414+
- RNScreens (3.17.0):
415415
- React-Core
416416
- React-RCTImage
417417
- SocketRocket (0.6.0)
@@ -629,7 +629,7 @@ SPEC CHECKSUMS:
629629
React-logger: 1088859f145b8f6dd0d3ed051a647ef0e3e80fad
630630
react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
631631
react-native-maps: df7b9fca1b1c8d356fadbf5b8a63a5f8cf32fc73
632-
react-native-pager-view: 95d0418c3c74279840abec6926653d32447bafb6
632+
react-native-pager-view: da490aa1f902c9a5aeecf0909cc975ad0e92e53e
633633
react-native-safe-area-context: f98b0b16d1546d208fc293b4661e3f81a895afd9
634634
React-perflogger: cb386fd44c97ec7f8199c04c12b22066b0f2e1e0
635635
React-RCTActionSheet: f803a85e46cf5b4066c2ac5e122447f918e9c6e5
@@ -644,9 +644,9 @@ SPEC CHECKSUMS:
644644
React-runtimeexecutor: 61ee22a8cdf8b6bb2a7fb7b4ba2cc763e5285196
645645
ReactCommon: 8f67bd7e0a6afade0f20718f859dc8c2275f2e83
646646
RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489
647-
RNGestureHandler: 4defbd70b2faf3d6761b82fa7880285241762cb0
647+
RNGestureHandler: 7673697e7c0e9391adefae4faa087442bc04af33
648648
RNReanimated: 7faa787e8d4493fbc95fab2ad331fa7625828cfa
649-
RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7
649+
RNScreens: 0df01424e9e0ed7827200d6ed1087ddd06c493f9
650650
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
651651
Yoga: ff994563b2fd98c982ca58e8cd9db2cdaf4dda74
652652
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

example/expo/babel.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module.exports = function (api) {
1616
return {
1717
presets: ['babel-preset-expo'],
1818
plugins: [
19+
'@babel/plugin-proposal-export-namespace-from',
1920
'react-native-reanimated/plugin',
2021
[
2122
'module-resolver',

example/expo/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { registerRootComponent } from 'expo';
22

3+
import { enableExperimentalWebImplementation } from 'react-native-gesture-handler';
4+
enableExperimentalWebImplementation(true);
5+
36
import { enableScreens } from 'react-native-screens';
47
enableScreens(true);
58

example/expo/package.json

+20-19
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
"private": true,
66
"main": "./index.ts",
77
"scripts": {
8-
"start": "expo start",
9-
"android": "expo start --android",
10-
"ios": "expo start --ios",
11-
"web": "expo start --web",
12-
"eject": "expo eject"
8+
"start": "npx expo start",
9+
"android": "npx expo start --android",
10+
"ios": "npx expo start --ios",
11+
"web": "npx expo start --web"
1312
},
1413
"dependencies": {
14+
"@expo/webpack-config": "^0.17.2",
1515
"@gorhom/portal": "^1.0.13",
1616
"@gorhom/showcase-template": "^2.1.0",
1717
"@react-navigation/bottom-tabs": "^6.3.1",
@@ -20,28 +20,29 @@
2020
"@react-navigation/native": "^6.0.10",
2121
"@react-navigation/native-stack": "^6.6.2",
2222
"@react-navigation/stack": "^6.2.1",
23-
"expo": "^46.0.0",
24-
"expo-status-bar": "~1.4.0",
23+
"expo": "^47.0.0",
24+
"expo-status-bar": "~1.4.2",
2525
"faker": "^4.1.0",
2626
"nanoid": "^3.3.3",
27-
"react": "18.0.0",
28-
"react-dom": "18.0.0",
29-
"react-native": "0.69.4",
30-
"react-native-gesture-handler": "~2.5.0",
31-
"react-native-pager-view": "5.4.24",
32-
"react-native-reanimated": "~2.9.1",
27+
"react": "18.1.0",
28+
"react-dom": "18.1.0",
29+
"react-native": "0.70.5",
30+
"react-native-gesture-handler": "~2.8.0",
31+
"react-native-pager-view": "6.0.1",
32+
"react-native-reanimated": "~2.12.0",
3333
"react-native-redash": "^16.2.4",
34-
"react-native-safe-area-context": "4.3.1",
35-
"react-native-screens": "~3.15.0",
34+
"react-native-safe-area-context": "4.4.1",
35+
"react-native-screens": "~3.18.0",
3636
"react-native-tab-view": "^3.1.1",
3737
"react-native-web": "~0.18.7"
3838
},
3939
"devDependencies": {
40-
"@babel/core": "^7.18.6",
41-
"@types/react": "~18.0.0",
42-
"@types/react-native": "~0.69.1",
40+
"@babel/core": "^7.19.3",
41+
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
42+
"@types/react": "~18.0.24",
43+
"@types/react-native": "~0.70.6",
44+
"babel-loader": "^8.2.3",
4345
"babel-plugin-module-resolver": "^4.1.0",
44-
"expo-cli": "^6.0.2",
4546
"typescript": "^4.6.3"
4647
},
4748
"resolutions": {

example/expo/web/index.html

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<!DOCTYPE html>
2+
<html lang="%LANG_ISO_CODE%">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
6+
<!--
7+
This viewport works for phones with notches.
8+
It's optimized for gestures by disabling global zoom.
9+
-->
10+
<meta
11+
name="viewport"
12+
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover"
13+
/>
14+
<meta name="theme-color" content="#fff" media="(prefers-color-scheme: light)">
15+
<meta name="theme-color" content="#000" media="(prefers-color-scheme: dark)">
16+
<title>%WEB_TITLE%</title>
17+
<style>
18+
/**
19+
* Extend the react-native-web reset:
20+
* https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
21+
*/
22+
html,
23+
body,
24+
#root {
25+
width: 100%;
26+
/* To smooth any scrolling behavior */
27+
-webkit-overflow-scrolling: touch;
28+
margin: 0px;
29+
padding: 0px;
30+
/* Allows content to fill the viewport and go beyond the bottom */
31+
min-height: 100%;
32+
background-color: #000;
33+
}
34+
#root {
35+
flex-shrink: 0;
36+
flex-basis: auto;
37+
flex-grow: 1;
38+
display: flex;
39+
flex: 1;
40+
background-color: #000;
41+
}
42+
43+
html {
44+
scroll-behavior: smooth;
45+
/* Prevent text size change on orientation change https://gist.github.com/tfausak/2222823#file-ios-8-web-app-html-L138 */
46+
-webkit-text-size-adjust: 100%;
47+
height: calc(100% + env(safe-area-inset-top));
48+
}
49+
50+
body {
51+
display: flex;
52+
/* Allows you to scroll below the viewport; default value is visible */
53+
overflow-y: auto;
54+
overscroll-behavior-y: none;
55+
text-rendering: optimizeLegibility;
56+
-webkit-font-smoothing: antialiased;
57+
-moz-osx-font-smoothing: grayscale;
58+
-ms-overflow-style: scrollbar;
59+
}
60+
/* Enable for apps that support dark-theme */
61+
/*@media (prefers-color-scheme: dark) {
62+
body {
63+
background-color: black;
64+
}
65+
}*/
66+
</style>
67+
</head>
68+
69+
<body>
70+
<!--
71+
A generic no script element with a reload button and a message.
72+
Feel free to customize this however you'd like.
73+
-->
74+
<noscript>
75+
<form
76+
action=""
77+
style="
78+
background-color: #fff;
79+
position: fixed;
80+
top: 0;
81+
left: 0;
82+
right: 0;
83+
bottom: 0;
84+
z-index: 9999;
85+
"
86+
>
87+
<div
88+
style="
89+
font-size: 18px;
90+
font-family: Helvetica, sans-serif;
91+
line-height: 24px;
92+
margin: 10%;
93+
width: 80%;
94+
"
95+
>
96+
<p>Oh no! It looks like JavaScript is not enabled in your browser.</p>
97+
<p style="margin: 20px 0">
98+
<button
99+
type="submit"
100+
style="
101+
background-color: #4630eb;
102+
border-radius: 100px;
103+
border: none;
104+
box-shadow: none;
105+
color: #fff;
106+
cursor: pointer;
107+
font-weight: bold;
108+
line-height: 20px;
109+
padding: 6px 16px;
110+
"
111+
>
112+
Reload
113+
</button>
114+
</p>
115+
</div>
116+
</form>
117+
</noscript>
118+
<!-- The root element for your Expo app. -->
119+
<div id="root"></div>
120+
</body>
121+
</html>

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@
6969
"peerDependencies": {
7070
"react": "*",
7171
"react-native": "*",
72-
"react-native-gesture-handler": ">=2.5.0",
73-
"react-native-reanimated": ">=2.9.0"
72+
"react-native-gesture-handler": ">=2.6.0",
73+
"react-native-reanimated": ">=2.10.0"
7474
},
7575
"react-native-builder-bob": {
7676
"source": "src",

src/components/bottomSheet/BottomSheet.tsx

+9-6
Original file line numberDiff line numberDiff line change
@@ -1370,12 +1370,15 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
13701370
/**
13711371
* Calculate the keyboard height in the container.
13721372
*/
1373-
animatedKeyboardHeightInContainer.value = $modal
1374-
? Math.abs(
1375-
_keyboardHeight -
1376-
Math.abs(bottomInset - animatedContainerOffset.value.bottom)
1377-
)
1378-
: Math.abs(_keyboardHeight - animatedContainerOffset.value.bottom);
1373+
animatedKeyboardHeightInContainer.value =
1374+
_keyboardHeight === 0
1375+
? 0
1376+
: $modal
1377+
? Math.abs(
1378+
_keyboardHeight -
1379+
Math.abs(bottomInset - animatedContainerOffset.value.bottom)
1380+
)
1381+
: Math.abs(_keyboardHeight - animatedContainerOffset.value.bottom);
13791382

13801383
/**
13811384
* if keyboard state is equal to the previous state, then exit the method
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React, { useRef } from 'react';
2+
import { TextProps as RNTextProps, TextInput } from 'react-native';
3+
import Animated, {
4+
useAnimatedReaction,
5+
useDerivedValue,
6+
} from 'react-native-reanimated';
7+
8+
interface TextProps {
9+
text: string;
10+
value: Animated.SharedValue<number | boolean> | number;
11+
style?: Animated.AnimateProps<RNTextProps>['style'];
12+
}
13+
14+
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
15+
16+
const ReText = (props: TextProps) => {
17+
const { text, value: _providedValue, style } = { style: {}, ...props };
18+
const textRef = useRef<TextInput>(null);
19+
20+
const providedValue = useDerivedValue(() => {
21+
const value =
22+
typeof _providedValue === 'number'
23+
? _providedValue
24+
: typeof _providedValue.value === 'number'
25+
? _providedValue.value.toFixed(2)
26+
: _providedValue.value;
27+
28+
return `${text}: ${value}`;
29+
});
30+
31+
//region effects
32+
useAnimatedReaction(
33+
() => providedValue.value,
34+
result => {
35+
textRef.current?.setNativeProps({
36+
text: result,
37+
});
38+
}
39+
);
40+
//endregion
41+
42+
return (
43+
<AnimatedTextInput
44+
ref={textRef}
45+
underlineColorAndroid="transparent"
46+
editable={false}
47+
value={providedValue.value}
48+
style={style}
49+
/>
50+
);
51+
};
52+
53+
export default ReText;

0 commit comments

Comments
 (0)