Skip to content

Feat/with scroll enabler #807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions demo/src/screens/MenuStructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ export const navigationData = {
{title: 'StateScreen', tags: 'empty state screen', screen: 'unicorn.screens.EmptyStateScreen'},
{title: 'TabController', tags: 'tabbar controller native', screen: 'unicorn.components.TabControllerScreen'},
{title: 'TabBar', tags: 'tab bar', screen: 'unicorn.components.TabBarScreen'},
{
title: 'withScrollEnabler',
tags: 'scroll enabled withScrollEnabler',
screen: 'unicorn.components.WithScrollEnablerScreen'
},
{title: 'Wizard', tags: 'wizard', screen: 'unicorn.components.WizardScreen'}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import _ from 'lodash';
import React, {memo, useCallback} from 'react';
import {
FlatList,
FlatListProps,
StyleSheet,
LayoutChangeEvent
} from 'react-native';
import {
Colors,
Text,
View,
withScrollEnabler,
WithScrollEnablerProps
} from 'react-native-ui-lib';

export type AutoLockScrollViewProps = FlatListProps<number> & {
numberOfItems: number;
};

const AutoLockFlatList = (props: AutoLockScrollViewProps) => {
const numberOfItems = props.numberOfItems;

const WithScrollEnabler = withScrollEnabler(
useCallback(
(props: WithScrollEnablerProps) => {
const getData = useCallback(
(numberOfItems: number) => {
return [...Array(numberOfItems).keys()];
},
[numberOfItems]
);

const keyExtractor = useCallback((item: number) => {
return item.toString();
}, []);

const renderItem = useCallback(({index}: {index: number}) => {
return (
<View key={index} style={styles.item}>
<Text>{index + 1}</Text>
</View>
);
}, []);

const onContentSizeChange = useCallback(
(contentWidth: number, contentHeight: number) => {
_.invoke(props, 'onContentSizeChange', contentWidth, contentHeight);
_.invoke(
props,
'scrollEnablerProps.onContentSizeChange',
contentWidth,
contentHeight
);
},
[
props.onContentSizeChange,
props.scrollEnablerProps.onContentSizeChange
]
);

const onLayout = useCallback(
(nativeEvent: LayoutChangeEvent) => {
_.invoke(props, 'onLayout', nativeEvent);
_.invoke(props, 'scrollEnablerProps.onLayout', nativeEvent);
},
[props.onLayout, props.scrollEnablerProps.onLayout]
);

return (
<FlatList
{...props}
style={styles.flatList}
contentContainerStyle={styles.flatListContainer}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
data={getData(numberOfItems)}
renderItem={renderItem}
keyExtractor={keyExtractor}
onContentSizeChange={onContentSizeChange}
onLayout={onLayout}
scrollEnabled={props.scrollEnablerProps.scrollEnabled}
/>
);
},
[numberOfItems]
)
);

return <WithScrollEnabler {...props} />;
};

export default memo(AutoLockFlatList);

const styles = StyleSheet.create({
flatList: {
height: 240
},
flatListContainer: {
alignItems: 'center'
},
item: {
width: 100,
height: 100,
margin: 9,
backgroundColor: Colors.grey40,
alignItems: 'center',
justifyContent: 'center'
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import _ from 'lodash';
import React, {memo, useCallback} from 'react';
import {
ScrollView,
ScrollViewProps,
StyleSheet,
LayoutChangeEvent
} from 'react-native';
import {
Colors,
Text,
View,
withScrollEnabler,
WithScrollEnablerProps
} from 'react-native-ui-lib';

export type AutoLockScrollViewProps = ScrollViewProps & {
numberOfItems: number;
};

const AutoLockScrollView = (props: AutoLockScrollViewProps) => {
const numberOfItems = props.numberOfItems;

const WithScrollEnabler = withScrollEnabler(
useCallback(
(props: WithScrollEnablerProps) => {
const renderItem = useCallback((index: number) => {
return (
<View key={index} style={styles.item}>
<Text>{index + 1}</Text>
</View>
);
}, []);

const onContentSizeChange = useCallback(
(contentWidth: number, contentHeight: number) => {
_.invoke(props, 'onContentSizeChange', contentWidth, contentHeight);
_.invoke(
props,
'scrollEnablerProps.onContentSizeChange',
contentWidth,
contentHeight
);
},
[
props.onContentSizeChange,
props.scrollEnablerProps.onContentSizeChange
]
);

const onLayout = useCallback(
(nativeEvent: LayoutChangeEvent) => {
_.invoke(props, 'onLayout', nativeEvent);
_.invoke(props, 'scrollEnablerProps.onLayout', nativeEvent);
},
[props.onLayout, props.scrollEnablerProps.onLayout]
);

return (
<ScrollView
{...props}
style={styles.scrollView}
contentContainerStyle={styles.scrollViewContainer}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
onContentSizeChange={onContentSizeChange}
onLayout={onLayout}
scrollEnabled={props.scrollEnablerProps.scrollEnabled}
>
{_.times(numberOfItems, renderItem)}
</ScrollView>
);
},
[numberOfItems]
)
);

return <WithScrollEnabler {...props} />;
};

export default memo(AutoLockScrollView);

const styles = StyleSheet.create({
scrollView: {
height: 240
},
scrollViewContainer: {
alignItems: 'center'
},
item: {
width: 100,
height: 100,
margin: 9,
backgroundColor: Colors.grey40,
alignItems: 'center',
justifyContent: 'center'
}
});
116 changes: 116 additions & 0 deletions demo/src/screens/componentScreens/WithScrollEnablerScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, {Component} from 'react';
import {LayoutChangeEvent} from 'react-native';
import {Text, View} from 'react-native-ui-lib';
import {
renderHeader,
renderBooleanOption,
renderSliderOption
} from '../../ExampleScreenPresenter';
import AutoLockScrollView from './AutoLockScrollView';
import AutoLockFlatList from './AutoLockFlatList';

class WithScrollEnablerScreen extends Component {
state = {
isListView: false,
isHorizontal: false,
numberOfItems: 3,
contentWidth: undefined,
contentHeight: undefined,
layoutWidth: undefined,
layoutHeight: undefined
};

onContentSizeChange = (contentWidth: number, contentHeight: number) => {
const {
contentWidth: currentContentWidth,
contentHeight: currentContentHeight
} = this.state;
if (
currentContentWidth !== contentWidth ||
currentContentHeight !== contentHeight
) {
this.setState({contentWidth, contentHeight});
}
};

onLayout = ({
nativeEvent: {
layout: {width, height}
}
}: LayoutChangeEvent) => {
const {layoutWidth, layoutHeight} = this.state;
if (width !== layoutWidth || height !== layoutHeight) {
this.setState({layoutWidth: width, layoutHeight: height});
}
};

renderList = () => {
const {isListView, isHorizontal, numberOfItems} = this.state;
const Container = isListView ? AutoLockScrollView : AutoLockFlatList;

return (
// @ts-ignore
<Container
key={`${isHorizontal}`}
horizontal={isHorizontal}
numberOfItems={numberOfItems}
onContentSizeChange={this.onContentSizeChange}
onLayout={this.onLayout}
/>
);
};

renderData = () => {
const {contentWidth, contentHeight, layoutWidth, layoutHeight} = this.state;
const contentText = `Content {width, height}: ${contentWidth}, ${contentHeight}`;
const layoutText = `Layout {width, height}: ${layoutWidth}, ${layoutHeight}`;
return (
<>
<Text text70>{contentText}</Text>
<Text text70>{layoutText}</Text>
</>
);
};

renderOptions = () => {
const {isListView, isHorizontal} = this.state;
const orientationText = isHorizontal ? 'Horizontal' : 'Vertical';
const listTypeText = isListView ? 'ListView' : 'FlatList';
return (
<>
<View row>
<View flex marginR-10>
{renderBooleanOption.call(this, orientationText, 'isHorizontal')}
</View>
<View flex marginL-10>
{renderBooleanOption.call(this, listTypeText, 'isListView')}
</View>
</View>
{renderSliderOption.call(
this,
'Number of items shown',
'numberOfItems',
{
min: 1,
max: 5,
step: 1,
initial: 3
}
)}
</>
);
};

render() {
return (
<View margin-10>
{renderHeader('withScrollEnabler', {'marginB-10': true})}
{this.renderOptions()}
{this.renderData()}
{this.renderList()}
</View>
);
}
}

export default WithScrollEnablerScreen;
1 change: 1 addition & 0 deletions demo/src/screens/componentScreens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ export function registerScreens(registrar) {
registrar('unicorn.screens.EmptyStateScreen', () => require('./EmptyStateScreen').default);
registrar('unicorn.screens.LoadingScreen', () => require('./LoadingScreen').default);
registrar('unicorn.screens.ModalScreen', () => require('./ModalScreen').default);
registrar('unicorn.components.WithScrollEnablerScreen', () => require('./WithScrollEnablerScreen').default);
}

1 change: 1 addition & 0 deletions generatedTypes/commons/new.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as UIComponent } from './UIComponent';
export { default as asBaseComponent, BaseComponentInjectedProps } from './asBaseComponent';
export { default as forwardRef, ForwardRefInjectedProps } from './forwardRef';
export { default as withScrollEnabler } from './withScrollEnabler';
export { ContainerModifiers, MarginModifiers, TypographyModifiers, ColorsModifiers, BackgroundColorModifier } from './modifiers';
14 changes: 14 additions & 0 deletions generatedTypes/commons/withScrollEnabler.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { FlatListProps, ScrollViewProps, LayoutChangeEvent } from 'react-native';
export declare type ScrollEnablerProps = {
onContentSizeChange: (contentWidth: number, contentHeight: number) => void;
onLayout: (event: LayoutChangeEvent) => void;
scrollEnabled: boolean;
};
declare type SupportedViews = FlatListProps<any> | ScrollViewProps;
export declare type WithScrollEnablerProps = SupportedViews & {
scrollEnablerProps: ScrollEnablerProps;
ref?: any;
};
declare function withScrollEnabler<PROPS extends SupportedViews>(WrappedComponent: React.ComponentType<WithScrollEnablerProps>): React.ComponentType<PROPS>;
export default withScrollEnabler;
1 change: 1 addition & 0 deletions generatedTypes/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Please use this file for declaring all the exports, so they could be picked up by typescript's complier
*/
export * from './style';
export {withScrollEnabler} from './commons/new';
export {default as Card, CardPropTypes} from './components/card';
export {default as View, ViewPropTypes} from './components/view';
export {default as Text} from './components/text';
Expand Down
3 changes: 3 additions & 0 deletions src/commons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ module.exports = {
},
get forwardRef() {
return require('./forwardRef').default;
},
get withScrollEnabler() {
return require('./withScrollEnabler').default;
}
};
1 change: 1 addition & 0 deletions src/commons/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export {default as UIComponent} from './UIComponent';
export {default as asBaseComponent, BaseComponentInjectedProps} from './asBaseComponent';
export {default as forwardRef, ForwardRefInjectedProps} from './forwardRef';
export {default as withScrollEnabler} from './withScrollEnabler';
export {
ContainerModifiers,
MarginModifiers,
Expand Down
Loading