Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
SunLxy committed May 17, 2023
2 parents 75e2a2f + 2a8ed59 commit cf1d62c
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 10 deletions.
8 changes: 8 additions & 0 deletions example/examples/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,12 @@ export const stackPageData: Routes[] = [
description: '图片头部组件',
},
},
{
name: 'Skeleton',
component: require('./routes/Skeleton').default,
params: {
title: 'Skeleton 骨架屏组件',
description: '骨架屏组件',
},
},
];
86 changes: 86 additions & 0 deletions example/examples/src/routes/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {Skeleton} from '@uiw/react-native';
import React, {useState, useEffect} from 'react';
import {StyleSheet, View, Text, TouchableOpacity} from 'react-native';
import Layout, {Container} from '../../Layout';

const {Header, Body, Card, Footer} = Layout;

const App = (props: any) => {
const [loading, setLoading] = useState(true);
const [data, setData] = useState<string[]>(['', '', '']);
useEffect(() => {
fetchData();
}, []);

const fetchData = () => {
setLoading(true);
setTimeout(() => {
setData(['项目1', '项目2', '项目3']);
setLoading(false);
}, 3000);
};
const {route} = props;
const description = route.params.description;
const title = route.params.title;

const skeletonStyles = [styles.item, styles.item, styles.item];

return (
<Container>
<Layout>
<Header title={title} description={description} />
<Body style={{paddingLeft: 16, paddingRight: 16}}>
<Card title="基础实例">
<View style={styles.container}>
{loading ? (
<Skeleton loading={loading} styles={skeletonStyles} duration={1200} containerStyle={styles.list} />
) : (
<View style={styles.list}>
{data.map((item, index) => (
<Text key={index} style={styles.item}>
{item}
</Text>
))}
</View>
)}
<TouchableOpacity style={styles.button} onPress={fetchData}>
<Text style={styles.buttonText}>重新加载</Text>
</TouchableOpacity>
</View>
</Card>
</Body>
<Footer />
</Layout>
</Container>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
list: {
width: '100%',
},
item: {
backgroundColor: '#E1E9EE',
height: 30,
marginBottom: 10,
justifyContent: 'center',
alignItems: 'center',
},
button: {
backgroundColor: '#007AFF',
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 5,
},
buttonText: {
color: '#FFF',
fontSize: 16,
},
});

export default App;
2 changes: 1 addition & 1 deletion example/examples/src/routes/VerificationCode/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const VerificationCodeDemo: React.FC<VerificationCodeProps> = ({route}) => {
<Card title="发验证码之前的回调">
<VerificationCode value={value} count={3} onChange={(text: string) => onChange(text)} onBefore={onBefore} outerStyle={{borderColor: '#ccc'}} />
</Card>
<Card title="发送验证码">
<Card title="发验证码时的回调">
<VerificationCode value={value} count={3} onChange={(text: string) => onChange(text)} onSend={onSend} outerStyle={{borderColor: '#ccc'}} />
</Card>
<Card title="倒计时结束后的回调">
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/Form/comps/input.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React from 'react';
import { TextInput, TextInputProps } from 'react-native';
import { useTheme } from "@shopify/restyle"
import { Theme } from '../../theme'
import { Platform, TextInput, TextInputProps } from 'react-native';
import { useTheme } from '@shopify/restyle';
import { Theme } from '../../theme';

const Input = ({ value, onChange, ...others }: TextInputProps & { onChange?: (value: string) => void }) => {
const theme = useTheme<Theme>()
const theme = useTheme<Theme>();
const isIOS = Platform.OS === 'ios';
return (
<TextInput
value={value}
onChangeText={(value) => {
onChange?.(value);
}}
style={{ color: theme.colors.text }}
style={{ paddingVertical: isIOS ? 5 : -5, color: theme.colors.text }}
{...others}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/Form/comps/label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const styles = StyleSheet.create({
width: 'auto',
fontSize: 16,
fontWeight: '500',
marginBottom: 10,
marginBottom: 5,
},
});

Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/Form/comps/tip.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import { Context } from '../hooks/context';
import { FormItemsProps } from '../types';
import { Text } from 'react-native';
import { View, Text } from 'react-native';

const Tip = ({ v }: { v: Partial<FormItemsProps> & { field: string } }) => {
const {
Expand All @@ -11,7 +11,11 @@ const Tip = ({ v }: { v: Partial<FormItemsProps> & { field: string } }) => {
const content = validator.message(v.field, store[v.field], {
validate: v?.validate,
});
return <Text style={{ color: 'red', marginBottom: content && 10, marginTop: content && 10 }}>{content}</Text>;
return (
<View style={{ marginTop: 5 }}>
{content && <Text style={{ color: 'red', marginBottom: content && 5 }}>{content}</Text>}
</View>
);
};

export default Tip;
2 changes: 1 addition & 1 deletion packages/core/src/Form/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const styles = StyleSheet.create({
},
form_items: {
textAlign: 'center',
margin: 10,
margin: 5,
borderBottomWidth: 0.5,
borderBottomColor: '#ccc',
},
Expand Down
103 changes: 103 additions & 0 deletions packages/core/src/Skeleton/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
Skeleton 骨架屏
---

在需要等待加载内容的位置提供一个占位图形组合。

### 基础示例

```jsx mdx:preview&background=#bebebe29
import { Skeleton } from '@uiw/react-native';
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';

const Demo = () => {
const [loading, setLoading] = useState(true);
const [data, setData] = useState(['', '', '']);
useEffect(() => {
fetchData();
}, []);

const fetchData = () => {
setLoading(true);
setTimeout(() => {
setData(['项目1', '项目2', '项目3']);
setLoading(false);
}, 3000);
};

const skeletonStyles = [
styles.item,
styles.item,
styles.item,
];

return (
<View style={styles.container}>
{loading ? (
<Skeleton
loading={loading}
styles={skeletonStyles}
duration={1200}
containerStyle={styles.list}
/>
) : (
<View style={styles.list}>
{data.map((item, index) => (
<Text key={index} style={styles.item}>
{item}
</Text>
))}
</View>
)}
<TouchableOpacity style={styles.button} onPress={fetchData}>
<Text style={styles.buttonText}>重新加载</Text>
</TouchableOpacity>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
list: {
width: '100%',
paddingHorizontal: 20,
},
item: {
backgroundColor: '#E1E9EE',
height: 30,
marginBottom: 10,
justifyContent: 'center',
alignItems: 'center',
},
button: {
backgroundColor: '#007AFF',
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 5,
},
buttonText: {
color: '#FFF',
fontSize: 16,
},
});

export default Demo;

```

### Props

| 参数 | 必填 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- | --- |
| loading | `false` | 是否正在加载 | `boolean` | `true` |
| styles | `true` | 骨架屏的样式 | `ViewStyle[]` | |
| duration | `false` | 动画的执行速度 | `number` | `1200` |
| easing | `false` | 动画的执行方式 | `Animated.EasingFunction` | `Easing.bezierFn(0.5, 0, 0.25, 1)` |
| containerStyle | `false` | 容器样式 | `StyleProp<ViewStyle>` | |
| animationType | `false` | 动画类型(条纹/脉搏/无) | `AnimationType` | `shiver` |
| boneColor | `false` | 基础颜色 | `string` | `#E1E9EE` |
| highlightColor | `false` | 高亮颜色 | `string` | `#F2F8FC` |
76 changes: 76 additions & 0 deletions packages/core/src/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import { View, Animated, EasingFunction, Easing, ViewStyle, StyleProp } from 'react-native';
type AnimationType = 'none' | 'stripe' | 'pulse';

interface SkeletonProps {
loading?: boolean;
styles: ViewStyle[];
duration?: number;
easing?: EasingFunction;
containerStyle?: StyleProp<ViewStyle>;
animationType?: AnimationType;
boneColor?: string;
highlightColor?: string;
}

const Skeleton: React.FC<SkeletonProps> = ({
loading = true,
styles,
duration = 1200,
easing = Easing.bezier(0.5, 0, 0.25, 1),
containerStyle,
animationType = 'stripe',
boneColor = '#E1E9EE',
highlightColor = '#F2F8FC',
}) => {
const animatedValue = React.useRef(new Animated.Value(0)).current;

const getInterpolatedColor = () => {
return animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [boneColor, highlightColor],
});
};
const getAnimationStyle = () => {
switch (animationType) {
case 'stripe':
return {
backgroundColor: getInterpolatedColor(),
};
case 'pulse':
return {
opacity: animatedValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0.5, 1, 0.5],
}),
};
default:
return {};
}
};

React.useEffect(() => {
if (loading) {
Animated.loop(
Animated.timing(animatedValue, {
toValue: 1,
duration,
easing: easing,
useNativeDriver: false,
}),
).start();
} else {
animatedValue.setValue(0);
}
}, [loading]);

return (
<View style={containerStyle}>
{styles.map((style, index) => (
<Animated.View key={index} style={[style, getAnimationStyle()]} />
))}
</View>
);
};

export default Skeleton;
2 changes: 2 additions & 0 deletions packages/core/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ export { default as LoginPage } from './LoginPage';
export * from './LoginPage';
export { default as ImageHeader } from './ImageHeader';
export * from './ImageHeader';
export { default as Skeleton } from './Skeleton';
export * from './Skeleton';
/**
* Typography
*/
Expand Down

0 comments on commit cf1d62c

Please sign in to comment.