Skip to content

Commit 2db3b94

Browse files
authored
Merge pull request #46358 from software-mansion-labs/types/react-native-web
[NO QA] Move react-native-web styles to a separate package
2 parents 0ff1b98 + 70747ed commit 2db3b94

File tree

16 files changed

+70
-433
lines changed

16 files changed

+70
-433
lines changed

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@
245245
"@types/react-collapse": "^5.0.1",
246246
"@types/react-dom": "^18.2.4",
247247
"@types/react-is": "^18.3.0",
248+
"@types/react-native-web": "^0.0.0",
248249
"@types/react-test-renderer": "^18.0.0",
249250
"@types/semver": "^7.5.4",
250251
"@types/setimmediate": "^1.0.2",

src/components/BlockingViews/BlockingView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type {ImageContentFit} from 'expo-image';
22
import React, {useMemo} from 'react';
3-
import type {ImageSourcePropType, StyleProp, TextStyle, ViewStyle, WebStyle} from 'react-native';
3+
import type {ImageSourcePropType, StyleProp, TextStyle, ViewStyle} from 'react-native';
44
import {View} from 'react-native';
55
import type {SvgProps} from 'react-native-svg';
6+
import type {WebStyle} from 'react-native-web';
67
import type {MergeExclusive} from 'type-fest';
78
import AutoEmailLink from '@components/AutoEmailLink';
89
import Icon from '@components/Icon';

src/components/Composer/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {BaseSyntheticEvent, ForwardedRef} from 'react';
44
import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
55
import {flushSync} from 'react-dom';
66
// eslint-disable-next-line no-restricted-imports
7-
import type {DimensionValue, NativeSyntheticEvent, Text as RNText, TextInput, TextInputKeyPressEventData, TextInputSelectionChangeEventData, TextStyle} from 'react-native';
7+
import type {NativeSyntheticEvent, Text as RNText, TextInput, TextInputKeyPressEventData, TextInputSelectionChangeEventData, ViewStyle} from 'react-native';
88
import {DeviceEventEmitter, StyleSheet, View} from 'react-native';
99
import type {AnimatedMarkdownTextInputRef} from '@components/RNMarkdownTextInput';
1010
import RNMarkdownTextInput from '@components/RNMarkdownTextInput';
@@ -100,7 +100,7 @@ function Composer(
100100
});
101101
const [caretContent, setCaretContent] = useState('');
102102
const [valueBeforeCaret, setValueBeforeCaret] = useState('');
103-
const [textInputWidth, setTextInputWidth] = useState('');
103+
const [textInputWidth, setTextInputWidth] = useState<ViewStyle['width']>('');
104104
const [isRendered, setIsRendered] = useState(false);
105105
const isScrollBarVisible = useIsScrollBarVisible(textInput, value ?? '');
106106
const [prevScroll, setPrevScroll] = useState<number | undefined>();
@@ -352,7 +352,7 @@ function Composer(
352352
opacity: 0,
353353
}}
354354
>
355-
<Text style={[StyleSheet.flatten([style, styles.noSelect]), StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), {maxWidth: textInputWidth as DimensionValue}]}>
355+
<Text style={[StyleSheet.flatten([style, styles.noSelect]), StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), {maxWidth: textInputWidth}]}>
356356
{`${valueBeforeCaret} `}
357357
<Text
358358
numberOfLines={1}
@@ -378,7 +378,7 @@ function Composer(
378378
Browser.isMobileSafari() || Browser.isSafari() ? styles.rtlTextRenderForSafari : {},
379379
scrollStyleMemo,
380380
StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize),
381-
isComposerFullSize ? ({height: '100%', maxHeight: 'none' as DimensionValue} as TextStyle) : undefined,
381+
isComposerFullSize ? {height: '100%', maxHeight: 'none'} : undefined,
382382
textContainsOnlyEmojis ? styles.onlyEmojisTextLineHeight : {},
383383
],
384384

src/components/SafeAreaConsumer/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import type {DimensionValue} from 'react-native';
1+
import type {ViewStyle} from 'react-native';
22
import type {EdgeInsets} from 'react-native-safe-area-context';
33

44
type SafeAreaChildrenProps = {
5-
paddingTop?: DimensionValue;
6-
paddingBottom?: DimensionValue;
5+
paddingTop?: ViewStyle['paddingTop'];
6+
paddingBottom?: ViewStyle['paddingBottom'];
77
insets?: EdgeInsets;
88
safeAreaPaddingBottomStyle: {
9-
paddingBottom?: DimensionValue;
9+
paddingBottom?: ViewStyle['paddingBottom'];
1010
};
1111
};
1212

src/components/ScreenWrapper.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {useNavigation} from '@react-navigation/native';
22
import type {StackNavigationProp} from '@react-navigation/stack';
33
import type {ForwardedRef, ReactNode} from 'react';
44
import React, {createContext, forwardRef, useEffect, useMemo, useRef, useState} from 'react';
5-
import type {DimensionValue, StyleProp, ViewStyle} from 'react-native';
5+
import type {StyleProp, ViewStyle} from 'react-native';
66
import {Keyboard, PanResponder, View} from 'react-native';
77
import {PickerAvoidingView} from 'react-native-picker-select';
88
import type {EdgeInsets} from 'react-native-safe-area-context';
@@ -31,7 +31,7 @@ import withNavigationFallback from './withNavigationFallback';
3131
type ScreenWrapperChildrenProps = {
3232
insets: EdgeInsets;
3333
safeAreaPaddingBottomStyle?: {
34-
paddingBottom?: DimensionValue;
34+
paddingBottom?: ViewStyle['paddingBottom'];
3535
};
3636
didScreenTransitionEnd: boolean;
3737
};

src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import React, {memo, useEffect, useRef} from 'react';
22
import {InteractionManager} from 'react-native';
3-
import type {LayoutChangeEvent} from 'react-native';
3+
import type {LayoutRectangle, NativeSyntheticEvent} from 'react-native';
44
import GenericTooltip from '@components/Tooltip/GenericTooltip';
55
import type {EducationalTooltipProps} from '@components/Tooltip/types';
66
import CONST from '@src/CONST';
77

8+
type LayoutChangeEventWithTarget = NativeSyntheticEvent<{layout: LayoutRectangle; target: HTMLElement}>;
9+
810
/**
911
* A component used to wrap an element intended for displaying a tooltip.
1012
* This tooltip would show immediately without user's interaction and hide after 5 seconds.
@@ -45,7 +47,7 @@ function BaseEducationalTooltip({children, shouldAutoDismiss = false, ...props}:
4547
// eslint-disable-next-line react-compiler/react-compiler
4648
hideTooltipRef.current = hideTooltip;
4749
return React.cloneElement(children as React.ReactElement, {
48-
onLayout: (e: LayoutChangeEvent) => {
50+
onLayout: (e: LayoutChangeEventWithTarget) => {
4951
// e.target is specific to native, use e.nativeEvent.target on web instead
5052
const target = e.target || e.nativeEvent.target;
5153
// When tooltip is used inside an animated view (e.g. popover), we need to wait for the animation to finish before measuring content.

src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type {StackCardInterpolationProps, StackNavigationOptions} from '@react-navigation/stack';
2-
import type {ViewStyle} from 'react-native';
32
import type {ThemeStyles} from '@styles/index';
43
import type {StyleUtilsType} from '@styles/utils';
54
import variables from '@styles/variables';
@@ -61,8 +60,7 @@ const getRootNavigatorScreenOptions: GetRootNavigatorScreenOptions = (isSmallScr
6160
width: '100%',
6261
top: 0,
6362
left: 0,
64-
// We need to guarantee that it covers BottomTabBar on web, but fixed position is not supported in react native.
65-
position: 'fixed' as ViewStyle['position'],
63+
position: 'fixed',
6664
},
6765
}),
6866
leftModalNavigator: {

src/styles/utils/display.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,27 @@ export default {
2323
* Web-only style.
2424
*/
2525
dInline: {
26-
// NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
27-
display: 'inline' as ViewStyle['display'],
26+
display: 'inline',
2827
},
2928

3029
/**
3130
* Web-only style.
3231
*/
3332
dInlineFlex: {
34-
// NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
35-
display: 'inline-flex' as ViewStyle['display'],
33+
display: 'inline-flex',
3634
},
3735

3836
/**
3937
* Web-only style.
4038
*/
4139
dBlock: {
42-
// NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
43-
display: 'block' as ViewStyle['display'],
40+
display: 'block',
4441
},
4542

4643
/**
4744
* Web-only style.
4845
*/
4946
dGrid: {
50-
// NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
51-
display: 'grid' as ViewStyle['display'],
47+
display: 'grid',
5248
},
5349
} satisfies Record<string, ViewStyle>;

src/styles/utils/generators/ReportActionContextMenuStyleUtils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ const getMiniWrapperStyle = (theme: ThemeColors, styles: ThemeStyles): ViewStyle
2020
borderWidth: 1,
2121
borderColor: theme.border,
2222
// In Safari, when welcome messages use a code block (triple backticks), they would overlap the context menu below when there is no scrollbar without the transform style.
23-
// NOTE: asserting "transform" to a valid type, because it isn't possible to augment "transform".
24-
transform: 'translateZ(0)' as unknown as ViewStyle['transform'],
23+
transform: 'translateZ(0)',
2524
},
2625
];
2726

src/styles/utils/index.ts

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {StyleSheet} from 'react-native';
2-
import type {AnimatableNumericValue, Animated, ColorValue, DimensionValue, ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native';
2+
import type {AnimatableNumericValue, Animated, ColorValue, ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native';
33
import type {OnyxEntry} from 'react-native-onyx';
44
import type {EdgeInsets} from 'react-native-safe-area-context';
55
import type {ValueOf} from 'type-fest';
@@ -342,7 +342,6 @@ function getSafeAreaMargins(insets?: EdgeInsets): ViewStyle {
342342
return {marginBottom: (insets?.bottom ?? 0) * variables.safeInsertPercentage};
343343
}
344344

345-
// NOTE: asserting some web style properties to a valid type, because it isn't possible to augment them.
346345
function getZoomSizingStyle(
347346
isZoomed: boolean,
348347
imgWidth: number,
@@ -356,23 +355,23 @@ function getZoomSizingStyle(
356355
if (isLoading || imgWidth === 0 || imgHeight === 0) {
357356
return undefined;
358357
}
359-
const top = `${Math.max((containerHeight - imgHeight) / 2, 0)}px` as DimensionValue;
360-
const left = `${Math.max((containerWidth - imgWidth) / 2, 0)}px` as DimensionValue;
358+
const top = `${Math.max((containerHeight - imgHeight) / 2, 0)}px`;
359+
const left = `${Math.max((containerWidth - imgWidth) / 2, 0)}px`;
361360

362361
// Return different size and offset style based on zoomScale and isZoom.
363362
if (isZoomed) {
364363
// When both width and height are smaller than container(modal) size, set the height by multiplying zoomScale if it is zoomed in.
365364
if (zoomScale >= 1) {
366365
return {
367-
height: `${imgHeight * zoomScale}px` as DimensionValue,
368-
width: `${imgWidth * zoomScale}px` as DimensionValue,
366+
height: `${imgHeight * zoomScale}px`,
367+
width: `${imgWidth * zoomScale}px`,
369368
};
370369
}
371370

372371
// If image height and width are bigger than container size, display image with original size because original size is bigger and position absolute.
373372
return {
374-
height: `${imgHeight}px` as DimensionValue,
375-
width: `${imgWidth}px` as DimensionValue,
373+
height: `${imgHeight}px`,
374+
width: `${imgWidth}px`,
376375
top,
377376
left,
378377
};
@@ -381,20 +380,20 @@ function getZoomSizingStyle(
381380
// If image is not zoomed in and image size is smaller than container size, display with original size based on offset and position absolute.
382381
if (zoomScale > 1) {
383382
return {
384-
height: `${imgHeight}px` as DimensionValue,
385-
width: `${imgWidth}px` as DimensionValue,
383+
height: `${imgHeight}px`,
384+
width: `${imgWidth}px`,
386385
top,
387386
left,
388387
};
389388
}
390389

391390
// If image is bigger than container size, display full image in the screen with scaled size (fit by container size) and position absolute.
392391
// top, left offset should be different when displaying long or wide image.
393-
const scaledTop = `${Math.max((containerHeight - imgHeight * zoomScale) / 2, 0)}px` as DimensionValue;
394-
const scaledLeft = `${Math.max((containerWidth - imgWidth * zoomScale) / 2, 0)}px` as DimensionValue;
392+
const scaledTop = `${Math.max((containerHeight - imgHeight * zoomScale) / 2, 0)}px`;
393+
const scaledLeft = `${Math.max((containerWidth - imgWidth * zoomScale) / 2, 0)}px`;
395394
return {
396-
height: `${imgHeight * zoomScale}px` as DimensionValue,
397-
width: `${imgWidth * zoomScale}px` as DimensionValue,
395+
height: `${imgHeight * zoomScale}px`,
396+
width: `${imgWidth * zoomScale}px`,
398397
top: scaledTop,
399398
left: scaledLeft,
400399
};
@@ -538,17 +537,23 @@ function getButtonStyleWithIcon(
538537
}
539538
}
540539

540+
type MarginPaddingValue = ViewStyle['marginTop' | 'marginBottom' | 'paddingTop' | 'paddingBottom'];
541+
541542
/**
542543
* Combine margin/padding with safe area inset
543544
*
544545
* @param modalContainerValue - margin or padding value
545546
* @param safeAreaValue - safe area inset
546547
* @param shouldAddSafeAreaValue - indicator whether safe area inset should be applied
547548
*/
548-
function getCombinedSpacing(modalContainerValue: DimensionValue | undefined, safeAreaValue: number, shouldAddSafeAreaValue: boolean): number | DimensionValue | undefined {
549+
function getCombinedSpacing(modalContainerValue: MarginPaddingValue, safeAreaValue: number, shouldAddSafeAreaValue: boolean): MarginPaddingValue {
549550
// modalContainerValue can only be added to safe area inset if it's a number, otherwise it's returned as is
550-
if (typeof modalContainerValue === 'number' || !modalContainerValue) {
551-
return (modalContainerValue ?? 0) + (shouldAddSafeAreaValue ? safeAreaValue : 0);
551+
if (typeof modalContainerValue === 'number') {
552+
return modalContainerValue + (shouldAddSafeAreaValue ? safeAreaValue : 0);
553+
}
554+
555+
if (!modalContainerValue) {
556+
return shouldAddSafeAreaValue ? safeAreaValue : 0;
552557
}
553558

554559
return modalContainerValue;
@@ -563,10 +568,10 @@ type ModalPaddingStylesParams = {
563568
safeAreaPaddingBottom: number;
564569
safeAreaPaddingLeft: number;
565570
safeAreaPaddingRight: number;
566-
modalContainerStyleMarginTop: DimensionValue | undefined;
567-
modalContainerStyleMarginBottom: DimensionValue | undefined;
568-
modalContainerStylePaddingTop: DimensionValue | undefined;
569-
modalContainerStylePaddingBottom: DimensionValue | undefined;
571+
modalContainerStyleMarginTop: MarginPaddingValue;
572+
modalContainerStyleMarginBottom: MarginPaddingValue;
573+
modalContainerStylePaddingTop: MarginPaddingValue;
574+
modalContainerStylePaddingBottom: MarginPaddingValue;
570575
insets: EdgeInsets;
571576
};
572577

@@ -964,8 +969,7 @@ function getCheckboxPressableStyle(borderRadius = 6): ViewStyle {
964969
return {
965970
justifyContent: 'center',
966971
alignItems: 'center',
967-
// eslint-disable-next-line object-shorthand
968-
borderRadius: borderRadius,
972+
borderRadius,
969973
};
970974
}
971975

@@ -1311,8 +1315,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
13111315
borderWidth: 2,
13121316
justifyContent: 'center',
13131317
alignItems: 'center',
1314-
// eslint-disable-next-line object-shorthand
1315-
borderRadius: borderRadius,
1318+
borderRadius,
13161319
}),
13171320

13181321
/**
@@ -1338,13 +1341,13 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
13381341
/**
13391342
* Get the style for the AM and PM buttons in the TimePicker
13401343
*/
1341-
getStatusAMandPMButtonStyle: (amPmValue: string): {styleForAM: ViewStyle; styleForPM: ViewStyle} => {
1344+
getStatusAMandPMButtonStyle: (amPmValue: string): {styleForAM: StyleProp<ViewStyle>; styleForPM: StyleProp<ViewStyle>} => {
13421345
const computedStyleForAM: ViewStyle = amPmValue !== CONST.TIME_PERIOD.AM ? {backgroundColor: theme.componentBG} : {};
13431346
const computedStyleForPM: ViewStyle = amPmValue !== CONST.TIME_PERIOD.PM ? {backgroundColor: theme.componentBG} : {};
13441347

13451348
return {
1346-
styleForAM: [styles.timePickerWidth100, computedStyleForAM] as unknown as ViewStyle,
1347-
styleForPM: [styles.timePickerWidth100, computedStyleForPM] as unknown as ViewStyle,
1349+
styleForAM: [styles.timePickerWidth100, computedStyleForAM],
1350+
styleForPM: [styles.timePickerWidth100, computedStyleForPM],
13481351
};
13491352
},
13501353

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import type {ViewStyle} from 'react-native';
21
import type OverflowAutoStyles from './types';
32

43
/**
54
* Web-only style.
65
*/
76
const overflowAuto: OverflowAutoStyles = {
8-
// NOTE: asserting "overflow" to a valid type, because it isn't possible to augment "overflow".
9-
overflow: 'auto' as ViewStyle['overflow'],
7+
overflow: 'auto',
108
};
119

1210
export default overflowAuto;

src/styles/utils/positioning.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ export default {
1515
* Web-only style.
1616
*/
1717
pFixed: {
18-
// NOTE: asserting "position" to a valid type, because it isn't possible to augment "position".
19-
position: 'fixed' as ViewStyle['position'],
18+
position: 'fixed',
2019
},
2120

2221
t0: {

src/types/modules/react-native-web.d.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)