feat(hippy-react-web): fix web style issues (#2087)

* feat(hippy-react-web): fix web style issues

* feat(hippy-react-web): fix code magic number

* feat(hippy-react-web): fix pull header refresh distance

* feat(hippy-react-web): fix cr issues

Co-authored-by: Zoom Chan <zoom_chan@163.com>
This commit is contained in:
LittleCo
2022-07-25 13:09:01 +08:00
committed by zoomchan-cxj
co-authored by Zoom Chan
parent d648eda41f
commit e6d04161da
10 changed files with 170 additions and 96 deletions
@@ -28,7 +28,7 @@
}
#root {
min-height: 100vh;
height: 100vh;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
+7 -14
View File
@@ -31,17 +31,10 @@ module.exports = {
## Project progress
| Working | Not Working |
| ---------- | -------------- |
| View | RefreshWrapper |
| Text | Navigator |
| Animation | Modal |
| Image | NetInfo |
| ListView | |
| ScrollView | |
| TextInput | |
| ViewPager | |
| WebView | |
| VideoPlayer| |
| Slider | |
| TabHost | |
| Not Working |
| -------------- |
| Navigator |
| NetInfo |
| RippleViewAndorid |
| WaterFallView |
| VideoPlayer |
@@ -23,9 +23,9 @@ import { canUseDOM } from '../utils';
export const HIDE_SCROLLBAR_CLASS = '__hippy-react-hide-scrollbar';
const hideScrollbarKey = '__hippyReactHideScrollbarActive';
export const shouldHideScrollBar = (isHideScrollBar: boolean) => {
export const shouldHideScrollBar = (isShowScrollBar: boolean) => {
if (canUseDOM) {
if (isHideScrollBar && !window[hideScrollbarKey]) {
if (!isShowScrollBar && !window[hideScrollbarKey]) {
window[hideScrollbarKey] = true;
document.styleSheets[0].addRule(`.${HIDE_SCROLLBAR_CLASS}::-webkit-scrollbar`, 'display: none');
document.styleSheets[0].addRule(`.${HIDE_SCROLLBAR_CLASS}`, '-ms-overflow-style: none; scrollbar-width: none;');
@@ -27,6 +27,7 @@ import { formatWebStyle } from '../adapters/transfer';
import { canUseDOM, isFunc, noop } from '../utils';
import { HIDE_SCROLLBAR_CLASS, shouldHideScrollBar } from '../adapters/hide-scrollbar';
import { LayoutEvent } from '../types';
import { DEFAULT_DISTANCE_TO_REFRESH, REFRESH_DISTANCE_SCREEN_Y_OFFSET } from '../constants';
import View from './view';
interface ListViewItemProps {
@@ -80,7 +81,17 @@ const styles = StyleSheet.create({
listDefault: {
flex: 1,
},
container: {
display: 'flex',
flexDirection: 'column',
},
pullHeaderContainer: {
display: 'flex',
justifyContent: 'center',
alignContent: 'center',
},
});
let didWarn = !canUseDOM;
const setIntersectionObserve = (observeCallback: (entries: any[]) => void) => {
let observe: null | IntersectionObserver = null;
@@ -120,7 +131,7 @@ function ListViewItem(props: ListViewItemProps) {
}
}, [listItemRef]);
const liElementProps = { ...props, style: { ...formatWebStyle(style), ...itemStyle } };
const liElementProps = { ...props, style: { ...styles.container, ...formatWebStyle(style), ...itemStyle } };
delete liElementProps.observer;
delete liElementProps.height;
delete liElementProps.getRowKey;
@@ -132,6 +143,7 @@ function ListViewItem(props: ListViewItemProps) {
);
}
const ListView: React.FC<ListViewProps> = React.forwardRef((props, ref) => {
const {
getRowStyle = noop, rowShouldSticky, scrollEnabled = true, showScrollIndicator = true,
@@ -299,7 +311,7 @@ const ListView: React.FC<ListViewProps> = React.forwardRef((props, ref) => {
}
}, [pullHeaderRef]);
return (
<div ref={pullHeaderRef} style={{ visibility: headerVisibility.current, marginTop: `-${pullHeaderHeight.current}px` }}>
<div ref={pullHeaderRef} style={{ ...styles.pullHeaderContainer, visibility: headerVisibility.current, marginTop: `-${pullHeaderHeight.current}px` }}>
{renderPullHeader()}
</div>
);
@@ -337,7 +349,10 @@ const ListView: React.FC<ListViewProps> = React.forwardRef((props, ref) => {
refreshing={refreshing}
onRefresh={refresh}
indicator={pullIndicator}
distanceToRefresh={pullHeaderHeight.current || 100}
distanceToRefresh={
pullHeaderHeight.current
? pullHeaderHeight.current - REFRESH_DISTANCE_SCREEN_Y_OFFSET : DEFAULT_DISTANCE_TO_REFRESH
}
/>;
}
@@ -347,6 +362,7 @@ const ListView: React.FC<ListViewProps> = React.forwardRef((props, ref) => {
>
<MListView
{...listViewProps}
contentContainerStyle={{ position: 'relative' }}
ref={listRef}
className={(!showScrollIndicator && HIDE_SCROLLBAR_CLASS) || ''}
dataSource={getDataSource()}
@@ -24,6 +24,7 @@ import React, { useState } from 'react';
import MPullToRefresh from 'rmc-pull-to-refresh';
import { formatWebStyle } from '../adapters/transfer';
import { isFunc } from '../utils';
import { DEFAULT_CONTAINER_STYLE, DEFAULT_DISTANCE_TO_REFRESH, REFRESH_DISTANCE_SCREEN_Y_OFFSET } from '../constants';
export interface RefreshWrapperProps {
ref?: any;
@@ -33,6 +34,17 @@ export interface RefreshWrapperProps {
bounceTime?: number;
}
const styles = {
container: {
...DEFAULT_CONTAINER_STYLE,
},
pullHeaderContainer: {
display: 'flex',
justifyContent: 'center',
alignContent: 'center',
},
};
/**
* Simply to implement the drag down to refresh feature.
* @noInheritDoc
@@ -61,7 +73,7 @@ const RefreshWrapper: React.FC<RefreshWrapperProps> = React.forwardRef((props, r
}
}, [pullHeaderRef]);
return (
<div ref={pullHeaderRef} style={{ visibility: headerVisibility.current, marginTop: `-${pullHeaderHeight.current}px` }}>
<div ref={pullHeaderRef} style={{ ...styles.pullHeaderContainer, visibility: headerVisibility.current, marginTop: `-${pullHeaderHeight.current}px` }}>
{getRefresh()}
</div>
);
@@ -109,7 +121,10 @@ const RefreshWrapper: React.FC<RefreshWrapperProps> = React.forwardRef((props, r
refreshing={refreshing}
onRefresh={handleOnRefresh}
indicator={pullIndicator}
distanceToRefresh={pullHeaderHeight.current || 100}
distanceToRefresh={
pullHeaderHeight.current
? pullHeaderHeight.current - REFRESH_DISTANCE_SCREEN_Y_OFFSET : DEFAULT_DISTANCE_TO_REFRESH
}
/>,
});
@@ -119,7 +134,7 @@ const RefreshWrapper: React.FC<RefreshWrapperProps> = React.forwardRef((props, r
delete newProps.onRefresh;
return (
<div {...newProps} ref={wrapperRef}>
<div {...newProps} style={formatWebStyle({ ...styles.container, ...newProps.style })} ref={wrapperRef}>
{ newChildren }
</div>
);
@@ -264,7 +264,7 @@ const ScrollView: React.FC<ScrollViewProps> = React.forwardRef((props, ref) => {
onTouchDown={onTouchStart}
onTouchMove={onTouchMove}
onTouchEnd={onTouchEnd}
className={!showScrollIndicator && HIDE_SCROLLBAR_CLASS}
className={ !showScrollIndicator ? HIDE_SCROLLBAR_CLASS : ''}
ref={scrollRef}
style={[
directionStyle,
+102 -66
View File
@@ -19,42 +19,69 @@
*/
// @ts-nocheck
import React from 'react';
import React, { createContext, useRef } from 'react';
import { formatWebStyle } from '../adapters/transfer';
import View from './view';
import { LayoutEvent } from '../types';
import useResponderEvents from '../modules/use-responder-events';
import useElementLayout from '../modules/use-element-layout';
import { TouchEvent } from '../modules/use-responder-events/types';
import { DEFAULT_CONTAINER_STYLE } from '../constants';
const baseTextStyle = {
...DEFAULT_CONTAINER_STYLE,
backgroundColor: 'transparent',
border: '0 solid black',
boxSizing: 'border-box',
color: 'black',
font: '14px System',
listStyle: 'none',
margin: 0,
padding: 0,
textAlign: 'inherit',
textDecoration: 'none',
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
};
const styles = {
initial: {
borderWidth: 0,
boxSizing: 'border-box',
color: 'inherit',
fontFamily: 'System',
fontSize: 14,
fontStyle: 'inherit',
fontVariant: ['inherit'],
fontWeight: 'inherit',
lineHeight: 'inherit',
margin: 0,
padding: 0,
textDecorationLine: 'none',
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
text: {
...baseTextStyle,
},
isInAParentTextFontStyle: {
// inherit parent font styles
textHasParent: {
...baseTextStyle,
fontFamily: 'inherit',
fontSize: 'inherit',
whiteSpace: 'inherit',
},
singleLineStyle: {
singleText: {
maxWidth: '100%',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
display: 'block',
wordWrap: 'normal',
},
multiText: {
display: '-webkit-box',
maxWidth: '100%',
overflow: 'hidden',
textOverflow: 'ellipsis',
WebkitBoxOrient: 'vertical',
},
};
const TextAncestorContext = createContext(false);
interface TextProps {
style?: HippyTypes.Style | HippyTypes.Style[];
numberOfLines?: number;
opacity?: number;
ellipsizeMode?: 'clip' | 'ellipsis';
onLayout: (e: LayoutEvent) => void;
onTouchDown?: (e: TouchEvent) => void;
onTouchMove?: (e: TouchEvent) => void;
onTouchEnd?: (e: TouchEvent) => void;
onTouchCancel?: (e: TouchEvent) => void;
}
/**
* A React component for displaying text.
@@ -62,54 +89,63 @@ const styles = {
* `Text` doesn't support nesting.
* @noInheritDoc
*/
export class Text extends React.Component {
private static childContextTypes = {
isInAParentText: () => {},
};
const Text: React.FC<TextProps> = React.forwardRef((props: TextProps, ref) => {
const hasTextAncestor = React.useContext(TextAncestorContext);
const { style = {}, numberOfLines = 1, ellipsizeMode = 'ellipsis' } = props;
public constructor(props) {
super(props);
this.state = {};
const hostRef: any = useRef(null);
React.useImperativeHandle(ref, () => hostRef.current, [hostRef.current]);
const { onTouchDown, onTouchEnd, onTouchCancel, onTouchMove } = props;
useResponderEvents(hostRef, { onTouchDown, onTouchEnd, onTouchCancel, onTouchMove });
useElementLayout(hostRef, props.onLayout);
const newProps = { ...props };
let newStyle: HippyTypes.Style = {};
if (hasTextAncestor) {
newStyle = { ...newStyle, ...styles.textHasParent };
} else {
newStyle = { ...newStyle, ...styles.text };
}
public getChildContext() {
return { isInAParentText: true };
}
public render() {
let { style } = this.props;
const { isInAParentText } = this.context;
const { numberOfLines, ellipsizeMode } = this.props;
if (style) {
style = formatWebStyle(style);
}
const textOverflow = ellipsizeMode === 'clip' ? 'clip' : 'ellipsis';
const baseStyle = {
textOverflow,
overflow: 'hidden',
display: numberOfLines > 1 ? '-webkit-box' : 'inline',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: numberOfLines ? numberOfLines.toString() : '0',
if (numberOfLines === 1) {
newStyle = { ...newStyle, ...styles.singleText };
} else {
newStyle = {
...newStyle,
...styles.multiText,
WebkitLineClamp: numberOfLines > 1 ? numberOfLines : 1,
};
const newStyle = Object.assign({}, style, baseStyle);
const newProps = Object.assign({}, this.props, {
style: formatWebStyle([styles.initial,
isInAParentText === true && styles.isInAParentText,
newStyle,
numberOfLines === 1 && Object.assign({}, styles.singleLineStyle, { textOverflow }),
isInAParentText === true && { display: 'inline' },
]),
});
delete newProps.numberOfLines;
delete newProps.ellipsizeMode;
delete newProps.enableScale;
if (isInAParentText) return <View {...newProps} />;
return (
<View {...newProps} />
);
}
}
if (props.opacity) {
newStyle.opacity = props.opacity;
}
const composedStyle = Array.isArray(style) ? [newStyle, ...style] : { ...newStyle, ...style };
const formatedStyle = formatWebStyle(composedStyle);
newProps.style = formatWebStyle({ ...formatedStyle, textOverflow: ellipsizeMode });
// delete span unsupported props
delete newProps.ellipsizeMode;
delete newProps.numberOfLines;
delete newProps.onLayout;
delete newProps.onTouchDown;
delete newProps.onTouchMove;
delete newProps.onTouchEnd;
delete newProps.onTouchCancel;
delete newProps.enableScale;
return hasTextAncestor ? (
<span data-1={String(hasTextAncestor)} ref={hostRef} {...newProps} />
) : (
<TextAncestorContext.Provider value={true}>
<span ref={hostRef} data-1={String(hasTextAncestor)} {...newProps} />
</TextAncestorContext.Provider>
);
});
Text.displayName = 'Text';
export {
Text,
TextProps,
};
export default Text;
@@ -55,9 +55,15 @@ export const ViewPager: React.FC<ViewPagerProps> = React.forwardRef((props, ref)
const renderViewPagerItem = () => {
if (!children || (children as React.ReactNodeArray).length === 0) return null;
const swiperSlideStyle: React.CSSProperties = {
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
};
return children.map((item: any, index: number) => {
const keyParam = index;
return <SwiperSlide key={`ViewPager-${keyParam}`}>{item}</SwiperSlide>;
return <SwiperSlide style={swiperSlideStyle} key={`ViewPager-${keyParam}`}>{item}</SwiperSlide>;
});
};
@@ -24,17 +24,14 @@ import useElementLayout from '../modules/use-element-layout';
import { TouchEvent } from '../modules/use-responder-events/types';
import { LayoutEvent } from '../types';
import { warn } from '../utils';
import { DEFAULT_CONTAINER_STYLE } from '../constants';
const styles = {
root: {
alignItems: 'stretch',
...DEFAULT_CONTAINER_STYLE,
borderWidth: 0,
borderStyle: 'solid',
boxSizing: 'border-box',
display: 'flex',
flexBasis: 'auto',
flexDirection: 'column',
flexShrink: 0,
margin: 0,
padding: 0,
position: 'relative',
+11
View File
@@ -29,3 +29,14 @@ export const UNSUPPORTED_PROPS_MAP = {
webview: ['userAgent', 'method', 'onLoad', 'onLoadStart'],
view: ['nativeBackgroundAndroid'],
};
export const DEFAULT_CONTAINER_STYLE = {
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
flexBasis: 'auto',
flexShrink: 0,
};
export const DEFAULT_DISTANCE_TO_REFRESH = 50;
export const REFRESH_DISTANCE_SCREEN_Y_OFFSET = 1;