Skip to content

Commit

Permalink
Add FlashList and List components
Browse files Browse the repository at this point in the history
  • Loading branch information
ntorionbearstudio committed Oct 20, 2023
1 parent 18945b2 commit 28523c3
Show file tree
Hide file tree
Showing 15 changed files with 829 additions and 19 deletions.
553 changes: 553 additions & 0 deletions docs/docs/Components/flashlist.md

Large diffs are not rendered by default.

14 changes: 3 additions & 11 deletions docs/docs/Components/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ sidebar_position: 9

import ExpoLayout from '../../src/components/ExpoLayout/index.js';

# List ⚡️
# List

Wrapper around `FlashList` component from `@shopify/flash-list`.
Wrapper around `FlatList` component from `react-native`.

https://shopify.github.io/flash-list/docs/

`FlashList` component is a more optimized list component from Shopify development team, it works as react native `FlatList` component.

So, `List` component accepts every props from react native `FlatList` component.
`List` component accepts every props from react native `FlatList` component.

## Import

Expand All @@ -24,10 +20,6 @@ import { List } from "react-native-ficus-ui";

<ExpoLayout id="list" />

## Performance demo ⚡️

<ExpoLayout id="list-perf" />

## Props

`renderItem`
Expand Down
43 changes: 43 additions & 0 deletions example/src/components/FlashList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable react-native/no-inline-styles */
import React from 'react';
import { SafeAreaView } from 'react-native';
import { Box, Flex, FlashList, Text } from 'react-native-ficus-ui';

const FlashListComponent = () => {
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
return (
<SafeAreaView style={{ flex: 1 }}>
<Text mx="xl" fontSize="4xl">
FlashList component
</Text>
<Flex mt="xl">
<FlashList
bg="gray.200"
p="xl"
data={DATA}
renderItem={({ item }) => (
<Box p="lg">
<Text>{item.title}</Text>
</Box>
)}
estimatedItemSize={200}
/>
</Flex>
</SafeAreaView>
);
};

export default FlashListComponent;
2 changes: 1 addition & 1 deletion example/src/components/List.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable react-native/no-inline-styles */
import React from 'react';
import { SafeAreaView } from 'react-native';
import { Box, Flex, List, Text } from 'react-native-ficus-ui';
Expand Down Expand Up @@ -32,7 +33,6 @@ const ListComponent = () => {
<Text>{item.title}</Text>
</Box>
)}
estimatedItemSize={200}
/>
</Flex>
</SafeAreaView>
Expand Down
6 changes: 6 additions & 0 deletions example/src/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import CheckboxComponent from './components/Checkbox';
import RadioComponent from './components/Radio';
import ToastHook from './components/Toast';
import ModalComponent from './components/Modal';
import FlashListComponent from './components/FlashList';

type ExampleComponentType = {
onScreenName: string;
Expand All @@ -43,6 +44,11 @@ export const components: ExampleComponentType[] = [
{ navigationPath: 'Flex', onScreenName: 'Flex', component: FlexComponent },
{ navigationPath: 'Stack', onScreenName: 'Stack', component: StackComponent },
{ navigationPath: 'List', onScreenName: 'List', component: ListComponent },
{
navigationPath: 'FlashList',
onScreenName: 'FlashList',
component: FlashListComponent,
},
{
navigationPath: 'SectionList',
onScreenName: 'SectionList',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-ficus-ui",
"version": "1.0.0-alpha11",
"version": "1.0.0-alpha12",
"description": "React Native UI library forked from Magnus UI and inspired by Chakra UI",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
92 changes: 92 additions & 0 deletions src/components/flashlist/flashlist.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as React from 'react';
import { View } from 'react-native';
import { FlashList as ShopifyFlashList } from '@shopify/flash-list';

import { getStyle } from './flashlist.style';
import type { FlashListProps } from './flashlist.type';
import { useTheme } from '../../theme/theme.hook';
import { useDefaultProps } from '../../utilities/useDefaultProps';

const FlashList: React.FunctionComponent<FlashListProps> = (incomingProps) => {
const props = useDefaultProps('FlashList', incomingProps, { flex: 1 });

const {
bg,
h,
w,
m,
mt,
mr,
mb,
ml,
ms,
p,
pr,
pt,
pb,
pl,
minH,
minW,
maxW,
maxH,
position,
style,
flexDirection,
direction,
borderRadius,
borderTopRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderLeftRadius,
borderRightRadius,
borderBottomRadius,
children,
alignItems,
align,
justifyContent,
justify,
borderColor,
borderBottomColor,
borderLeftColor,
borderTopColor,
borderRightColor,
borderWidth,
borderLeftWidth,
borderRightWidth,
borderBottomWidth,
borderTopWidth,
borderEndWidth,
flexWrap,
wrap,
flexGrow,
grow,
flexBasis,
basis,
flexShrink,
shrink,
shadow,
shadowColor,
opacity,
overflow,
top,
left,
right,
bottom,
zIndex,
...rest
} = props;
const { theme } = useTheme();
const computedStyle = getStyle(theme, props);

return (
<View style={computedStyle.list}>
<ShopifyFlashList {...rest} />
</View>
);
};

// FlashList.defaultProps = {};

export { FlashList };
28 changes: 28 additions & 0 deletions src/components/flashlist/flashlist.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { render } from '@testing-library/react-native';

import { Text } from '../text/text.component';
import { FlashList } from './flashlist.component';
import type { FlashListProps } from './flashlist.type';
import { ThemeProvider } from '../../theme/theme.provider';

jest.mock('react-native-toast-message', () => 'Toast');

describe('FlashList component', () => {
const TestList: React.FC<FlashListProps> = (props) => (
<ThemeProvider>
<FlashList {...props} />
</ThemeProvider>
);

it('should render component passed to children', () => {
render(
<TestList
data={[{ id: 0, text: 'I love Ficus UI (forked from Magnus UI)' }]}
renderItem={({ item }) => <Text>{item.text}</Text>}
keyExtractor={(item) => item.id}
estimatedItemSize={200}
/>
);
});
});
63 changes: 63 additions & 0 deletions src/components/flashlist/flashlist.style.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { StyleSheet } from 'react-native';

import {
createShadowStyles,
createPositionStyle,
createSpacingStyles,
createBorderWidthStyles,
createBorderColorStyles,
createBorderRadiusStyles,
getThemeColor,
} from '../../theme/theme.service';
import type { FlashListProps } from './flashlist.type';
import type { ThemeType } from '../../theme/type';

/**
* computed style
*
* @param theme
* @param props
*/
export const getStyle = (theme: ThemeType, props: FlashListProps) => {
const computedStyle: any = {};

computedStyle.list = {
flexDirection: props.direction ? props.direction : props.flexDirection,
flexWrap: props.wrap ? props.wrap : props.flexWrap,
alignItems: props.align ? props.align : props.alignItems,
justifyContent: props.justify ? props.justify : props.justifyContent,
flexBasis: props.basis ? props.basis : props.flexBasis,
flexGrow: props.grow ? props.grow : props.flexGrow,
flexShrink: props.shrink ? props.shrink : props.flexShrink,
height: props.h,
width: props.w,
minWidth: props.minW,
minHeight: props.minH,
alignSelf: props.alignSelf,
maxWidth: props.maxW,
maxHeight: props.maxH,
opacity: props.opacity,
overflow: props.overflow || 'hidden',
zIndex: props.zIndex,
borderStyle: props.borderStyle,
backgroundColor: getThemeColor(theme.colors, props.bg),
flex: props.flex,
...createPositionStyle(props),
...createShadowStyles(props, theme),
...createBorderWidthStyles(props),
...createSpacingStyles(props, theme.spacing),
...createBorderColorStyles(props, theme.colors),
...createBorderRadiusStyles(props, theme.borderRadius),
};

// merging custom style props to computed style
if (props.style) {
computedStyle.list = {
...computedStyle.list,
// @ts-ignore
...props.style,
};
}

return StyleSheet.create(computedStyle);
};
31 changes: 31 additions & 0 deletions src/components/flashlist/flashlist.type.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FlashListProps as ShopifyFlashListProps } from '@shopify/flash-list';

import type {
BorderPropsType,
SpacingPropsType,
BorderRadiusPropsType,
ShadowPropsType,
DimensionPropsType,
BackgroundPropsType,
FlexPropsType,
PositionPropsType,
ZIndexPropsType,
OverflowPropsType,
OpacityPropsType,
VariantPropsType,
} from '../../types';

export interface FlashListProps
extends ShopifyFlashListProps<any>,
BorderPropsType,
SpacingPropsType,
BorderRadiusPropsType,
ShadowPropsType,
DimensionPropsType,
BackgroundPropsType,
FlexPropsType,
PositionPropsType,
ZIndexPropsType,
OverflowPropsType,
OpacityPropsType,
VariantPropsType {}
2 changes: 2 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export { HStack } from './stack/hstack.component';
export { StackProps } from './stack/stack.type';
export { List } from './list/list.component';
export { ListProps } from './list/list.type';
export { FlashList } from './flashlist/flashlist.component';
export { FlashListProps } from './flashlist/flashlist.type';
export { SectionList } from './sectionlist/sectionlist.component';
export { SectionListProps } from './sectionlist/sectionlist.type';
export { Image } from './image/image.component';
Expand Down
5 changes: 2 additions & 3 deletions src/components/list/list.component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import { View } from 'react-native';
import { FlashList } from '@shopify/flash-list';
import { FlatList, View } from 'react-native';

import { getStyle } from './list.style';
import type { ListProps } from './list.type';
Expand Down Expand Up @@ -82,7 +81,7 @@ const List: React.FunctionComponent<ListProps> = (incomingProps) => {

return (
<View style={computedStyle.list}>
<FlashList {...rest} />
<FlatList {...rest} />
</View>
);
};
Expand Down
1 change: 0 additions & 1 deletion src/components/list/list.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ describe('List component', () => {
data={[{ id: 0, text: 'I love Ficus UI (forked from Magnus UI)' }]}
renderItem={({ item }) => <Text>{item.text}</Text>}
keyExtractor={(item) => item.id}
estimatedItemSize={200}
/>
);
});
Expand Down
4 changes: 2 additions & 2 deletions src/components/list/list.type.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FlashListProps } from '@shopify/flash-list';
import { FlatListProps } from 'react-native';

import type {
BorderPropsType,
Expand All @@ -16,7 +16,7 @@ import type {
} from '../../types';

export interface ListProps
extends FlashListProps<any>,
extends FlatListProps<any>,
BorderPropsType,
SpacingPropsType,
BorderRadiusPropsType,
Expand Down
2 changes: 2 additions & 0 deletions src/theme/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { TouchableHighlightProps } from 'components/touchable-highlight/tou
import type { TouchableWithoutFeedbackProps } from 'components/touchable-without-feedback/touchable-without-feedback.type';
import type { PressableProps } from 'components/pressable/pressable.type';
import type { SpinnerProps } from 'components/spinner/spinner.type';
import type { FlashListProps } from 'components/flashlist/flashlist.type';
import type { ListProps } from 'components/list/list.type';
import type { SectionListProps } from 'components/sectionlist/sectionlist.type';
import type { ImageProps } from 'components/image/image.type';
Expand Down Expand Up @@ -56,6 +57,7 @@ export interface ThemeType {
TouchableWithoutFeedback?: VariantType<TouchableWithoutFeedbackProps>;
Pressable?: VariantType<PressableProps>;
Spinner?: VariantType<SpinnerProps>;
FlashList?: VariantType<FlashListProps>;
List?: VariantType<ListProps>;
SectionList?: VariantType<SectionListProps>;
Image?: VariantType<ImageProps>;
Expand Down

0 comments on commit 28523c3

Please sign in to comment.