Skip to content

Commit

Permalink
Merge pull request #588 from hy916/dev
Browse files Browse the repository at this point in the history
fix(Accordion)添加Accordion手风琴组件
  • Loading branch information
ChenlingasMx committed Apr 11, 2023
2 parents e4923c7 + c6bb251 commit 1a128a7
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 13 deletions.
14 changes: 6 additions & 8 deletions example/examples/lib2/ImagePicker/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import { View, Text, StyleSheet } from 'react-native';
const ImagePicker = () => {
return (
<View style={styles.tree}>
return <View style={styles.tree}>
<Text>ImagePicker</Text>
</View>
);
</View>;
};
const styles = StyleSheet.create({
tree: {
paddingHorizontal: 10,
paddingVertical: 5,
backgroundColor: '#fff',
},
backgroundColor: '#fff'
}
});
export default ImagePicker;
export default ImagePicker;
2 changes: 1 addition & 1 deletion example/examples/lib2/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {default as ImagePicker} from './ImagePicker';
export { default as ImagePicker } from './ImagePicker';
export * from './ImagePicker';
4 changes: 2 additions & 2 deletions example/examples/lib2/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {default as ImagePicker} from './ImagePicker';
export * from './ImagePicker';
export { default as ImagePicker } from './ImagePicker';
export * from './ImagePicker';
10 changes: 9 additions & 1 deletion example/examples/src/routes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {StackNavigationProp, StackNavigationOptions} from '@react-navigation/stack';
import { StackNavigationProp, StackNavigationOptions } from '@react-navigation/stack';

type ModalStackNavigation = StackNavigationProp<{}>;

Expand Down Expand Up @@ -498,4 +498,12 @@ export const stackPageData: Routes[] = [
description: '图片上传',
},
},
{
name: 'Accordion',
component: require('./routes/Accordion').default,
params: {
title: 'Accordion 手风琴',
description: '可以折叠/展开的内容区域。',
},
},
];
77 changes: 77 additions & 0 deletions example/examples/src/routes/Accordion/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { Component } from 'react';
import { View, Image } from 'react-native';
import { Accordion, Text } from '@uiw/react-native';
import Layout, { Container } from '../../Layout';
import { ComProps } from '../../routes';
const { Header, Body, Card, Footer } = Layout;

export interface Accordion extends ComProps { }

const contents = [
{
title: <Text>Section 1</Text>,
content: (
<View>
<Text>Content of section 1</Text>
<Image source={{ uri: 'https://wx3.sinaimg.cn/mw690/4718260ely1gt2cg7t5udj23dw1wkhdu.jpg' }} style={{ height: 180 }} />
</View>
),
},
{
title: <Text>Section 2</Text>,
content: (
<View>
<Text>Content of section 2</Text>
<Image source={{ uri: 'https://wx1.sinaimg.cn/mw690/4718260ely1gt2cg5r9zij22yo1o0x6p.jpg' }} style={{ height: 180 }} />
</View>
),
},
{
title: <Text>Section 3</Text>,
content: (
<View>
<Text>Content of section 3</Text>
<Image source={{ uri: 'https://iknow-pic.cdn.bcebos.com/810a19d8bc3eb135828572d2ab1ea8d3fd1f441d' }} style={{ height: 180 }} />
</View>
),
},
];
export default class MenuDropdownView extends Component<Accordion> {
state = {
expanded: false,
top: false,
};
render() {
const { route } = this.props;
const description = route.params.description;
const title = route.params.title;
return (
<Container>
<Layout>
<Header title={title} description={description} />
<Body>
<Card title="基础实例">
<Accordion sections={contents} />
</Card>
<Card title="是否可以展开多个.默认为是,当前为否">
<Accordion sections={contents} isMultiple={false} />
</Card>
<Card title="是否展示右侧图标,默认为是,当前为否">
<Accordion sections={contents} iconShow={false} />
</Card>
<Card title="设置右侧图标尺寸大小">
<Accordion sections={contents} iconSize={30} />
</Card>
<Card title="每行列表手风琴样式">
<Accordion sections={contents} accordionStyle={{ backgroundColor: '#3578e5' }} />
</Card>
<Card title="展开手风琴内容样式">
<Accordion sections={contents} contentStyle={{ backgroundColor: '#FFD21D' }} />
</Card>
</Body>
<Footer />
</Layout>
</Container>
);
}
}
61 changes: 61 additions & 0 deletions packages/core/src/Accordion/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Accordion 手风琴组件
---
可以折叠/展开的内容区域。

### 基础示例

```jsx mdx:preview&background=#bebebe29
import React,{ Component } from "react"
import { View, Text,Image,Card } from 'react-native';
import { Accordion } from '@uiw/react-native';

const contents = [
{
title: <Text>Section 1</Text>,
content: (
<View>
<Text>Content of section 1</Text>
<Image source={{ uri: 'https://wx3.sinaimg.cn/mw690/4718260ely1gt2cg7t5udj23dw1wkhdu.jpg' }} style={{ height: 180 }} />
</View>
),
},
{
title: <Text>Section 2</Text>,
content: (
<View>
<Text>Content of section 2</Text>
<Image source={{ uri: 'https://wx1.sinaimg.cn/mw690/4718260ely1gt2cg5r9zij22yo1o0x6p.jpg' }} style={{ height: 180 }} />
</View>
),
},
{
title: <Text>Section 3</Text>,
content: (
<View>
<Text>Content of section 3</Text>
<Image source={{ uri: 'https://iknow-pic.cdn.bcebos.com/810a19d8bc3eb135828572d2ab1ea8d3fd1f441d' }} style={{ height: 180 }} />
</View>
),
},
];

function Demo() {
return (
<View style={{ marginTop: 50 }}>
<Accordion sections={contents} />
</View>
);
}
```

### Props

| 参数 | 说明 | 类型 | 默认值 |
|------|------|-----|------|
| `sections` | 自定义手风琴列表,通过`title`参数设置标题,通过`content`参数设置展示内容,通过`isOnPress`参数设置是否禁用 | JSX.Element | - |
| `isMultiple` | 是否同时展示多个内容| boolean | true |
| `accordionStyle` | 手风琴每行列表样式 | ViewStyle | - |
| `contentStyle` | 点击展开内容样式 | ViewStyle | - |
| `iconShow` | 是否展示图标 | boolean | true |
| `iconSize` | 设置图标尺寸 | number | - |

119 changes: 119 additions & 0 deletions packages/core/src/Accordion/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { FC, useState, useRef } from 'react';
import { StyleSheet, View, TouchableOpacity, StyleProp, ViewStyle, LayoutAnimation, Animated } from 'react-native';
import { Theme } from '../theme';
import { useTheme } from '@shopify/restyle';
import Icon from '../Icon';

interface AccordionProps {
/** 自定义手风琴列表*/
sections: {
/** 列表标题内容*/
title: JSX.Element;
/** 展开内容*/
content: JSX.Element;
/** 是否可以点击,默认可以点击*/
isOnPress?: boolean;
}[];
/** 是否展示多个,默认展示多个*/
isMultiple?: boolean;
/** 手风琴每行列表样式 */
accordionStyle?: StyleProp<ViewStyle>;
/** 点击展开内容样式 */
contentStyle?: StyleProp<ViewStyle>;
/** 是否展示图标 */
iconShow?: boolean;
/** 图标源 */
customIcon?: string | JSX.Element;
/** 图标尺寸 */
iconSize?: number;
}

const Accordion: FC<AccordionProps> = (props) => {
const { sections, isMultiple = true, iconShow = true, iconSize = 18, accordionStyle, contentStyle } = props;
const [activeIndex, setActiveIndex] = useState<number[] | number>(isMultiple ? [] : -1);
const theme = useTheme<Theme>();
const styles = createStyles({
bgColor: theme.colors.mask,
headerColor: theme.colors.background,
borderColor: theme.colors.border,
});
const animatedController = useRef(new Animated.Value(0)).current;

const onPress = (index: number | never) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (isMultiple) {
const currentIndex = Array.isArray(activeIndex) ? activeIndex.indexOf(index) : -1;
if (currentIndex > -1) {
const newActiveIndex = Array.isArray(activeIndex) ? [...activeIndex] : [];
if (currentIndex > -1) {
newActiveIndex.splice(currentIndex, 1);
}
setActiveIndex(newActiveIndex);
} else {
setActiveIndex(Array.isArray(activeIndex) ? [...activeIndex, index] : [index]);
}
} else {
setActiveIndex(activeIndex === index ? -1 : index);
}
Animated.timing(animatedController, {
toValue: activeIndex === index ? 0 : 1,
duration: 500,
useNativeDriver: true,
}).start();
};

const rotateZ = animatedController.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '90deg'],
});

return (
<View>
{sections.map((item, index) => (
<View key={index}>
<TouchableOpacity disabled={item?.isOnPress || false} activeOpacity={0.8} onPress={() => onPress(index)} style={[styles.header, accordionStyle]}>
<View style={styles.titleBy} key={index}>
{item.title}
{iconShow &&
<Animated.View style={{ transform: [{ rotateZ: activeIndex === index || (Array.isArray(activeIndex) && activeIndex.indexOf(index) > -1) ? rotateZ : '0deg' }] }}>
<Icon name="right" size={iconSize} color={theme.colors.border} />
</Animated.View>}
</View>
</TouchableOpacity>
{(isMultiple && Array.isArray(activeIndex) && activeIndex.indexOf(index) > -1 || !isMultiple && activeIndex === index) && <View
style={[styles.content, contentStyle]}>
{item.content}
</View>}
</View>
))}
</View>
)
}

type CreStyle = {
bgColor: string;
headerColor: string;
borderColor: string;
};

function createStyles({ bgColor, borderColor, headerColor }: CreStyle) {
return StyleSheet.create({
titleBy: {
flexDirection: 'row',
justifyContent: 'space-between',
},
header: {
borderBottomWidth: 1,
borderBottomColor: borderColor,
padding: 15,
backgroundColor: headerColor,
},
content: {
padding: 15,
backgroundColor: bgColor,
},
});
}

export default Accordion;

3 changes: 2 additions & 1 deletion packages/core/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ export { default as ImageViewer } from './ImageViewer';
export * from './ImageViewer';
export { default as Form } from './Form';
export * from './Form';

export { default as Accordion } from './Accordion';
export * from './Accordion';
/**
* Typography
*/
Expand Down
6 changes: 6 additions & 0 deletions website/src/pages/components/accordion/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Preview from 'src/component/Preview';
import md from '@uiw/react-native/README.md';

const Demo = () => <Preview {...md} path="/packages/core/src/Accordion/README.md" />;

export default Demo;
1 change: 1 addition & 0 deletions website/src/routes/menus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const componentMenus: MenuData[] = [
{ path: '/components/swipeaction', name: 'SwipeAction 滑动操作组件' },
{ path: '/components/expandablesection', name: 'ExpandableSection 展开缩放组件' },
{ path: '/components/cardcollapse', name: 'CardCollapse 可折叠卡片列表' },
{ path: '/components/accordion', name: 'Accordion 可折叠/展开的内容区域' },
{ divider: true, name: 'Data Entry' },
{ path: '/components/form', name: 'Form 表单 🚧' },
{ path: '/components/checkbox', name: 'CheckBox 复选框' },
Expand Down
4 changes: 4 additions & 0 deletions website/src/routes/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ export const routeData = [
path: '/components/cardcollapse',
component: lazy(() => import('../pages/components/cardcollapse')),
},
{
path: '/components/accordion',
component: lazy(() => import('../pages/components/accordion')),
},
{
path: '/components/actionSheet',
component: lazy(() => import('../pages/components/actionSheet')),
Expand Down

0 comments on commit 1a128a7

Please sign in to comment.