-
Notifications
You must be signed in to change notification settings - Fork 734
GridListItem - horizontal alignment support #3001
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
Changes from 6 commits
d733687
cea1b7c
a8af708
27c3904
1732f94
d15a9ce
66b5067
3ab4789
7a6f366
896142e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,20 @@ | ||
import _ from 'lodash'; | ||
import React, {Component} from 'react'; | ||
import {StyleProp, StyleSheet, ViewStyle} from 'react-native'; | ||
import memoize from 'memoize-one'; | ||
import * as Modifiers from '../../commons/modifiers'; | ||
import {Colors, Spacings, Typography} from 'style'; | ||
import View, {ViewProps} from '../view'; | ||
import TouchableOpacity, {TouchableOpacityProps} from '../touchableOpacity'; | ||
import Text from '../text'; | ||
import Image, {ImageProps} from '../image'; | ||
|
||
export enum HorizontalAlignment { | ||
left = 'left', | ||
center = 'center', | ||
right = 'right' | ||
} | ||
|
||
export interface GridListItemProps { | ||
/** | ||
* Image props object for rendering an image item | ||
|
@@ -85,6 +92,10 @@ export interface GridListItemProps { | |
* Should content be align to start (default is center) | ||
*/ | ||
alignToStart?: boolean; | ||
/** | ||
* Content horizontal alignment (default is center) | ||
*/ | ||
horizontalAlignment?: HorizontalAlignment | `${HorizontalAlignment}`; | ||
/** | ||
* Custom container style | ||
*/ | ||
|
@@ -101,7 +112,7 @@ export interface GridListItemProps { | |
* Test ID for component | ||
*/ | ||
testID?: string; | ||
children?: React.ReactNode; | ||
children?: React.ReactElement; | ||
} | ||
|
||
interface RenderContentType { | ||
|
@@ -120,6 +131,8 @@ interface RenderContentType { | |
class GridListItem extends Component<GridListItemProps> { | ||
static displayName = 'GridListItem'; | ||
|
||
static horizontalAlignment = HorizontalAlignment; | ||
|
||
static defaultProps = { | ||
itemSize: 48 | ||
}; | ||
|
@@ -139,14 +152,35 @@ class GridListItem extends Component<GridListItemProps> { | |
return {width: itemSize as number, height: itemSize as number}; | ||
} | ||
|
||
getHorizontalAlignmentStyle = memoize(horizontalAlignment => { | ||
switch (horizontalAlignment) { | ||
case HorizontalAlignment.left: | ||
return {contentStyle: styles.contentAlignedToStart, containerStyle: styles.containerAlignedToStart}; | ||
case HorizontalAlignment.right: | ||
return {contentStyle: styles.contentAlignedToEnd, containerStyle: styles.containerAlignedToEnd}; | ||
case HorizontalAlignment.center: | ||
return {contentStyle: styles.contentAlignedToCenter, containerStyle: styles.containerAlignedToCenter}; | ||
default: | ||
undefined; | ||
} | ||
}); | ||
|
||
renderContent({text, typography, color, numberOfLines = 1, style, testID}: RenderContentType) { | ||
const {alignToStart} = this.props; | ||
const {alignToStart, horizontalAlignment} = this.props; | ||
const horizontalAlignmentStyle = this.getHorizontalAlignmentStyle(horizontalAlignment); | ||
if (text) { | ||
return ( | ||
<Text | ||
testID={testID} | ||
// @ts-ignore | ||
style={[style, Typography[typography], color && {color}, alignToStart && styles.contentAlignedToStart]} | ||
style={[ | ||
style, | ||
//@ts-ignore | ||
Typography[typography], | ||
color && {color}, | ||
alignToStart && styles.contentAlignedToStart, | ||
horizontalAlignmentStyle?.contentStyle | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. {textAlign: HorizontalAlignment} - can replace this object, just place it before this line: |
||
]} | ||
numberOfLines={numberOfLines} | ||
> | ||
{text} | ||
|
@@ -160,6 +194,7 @@ class GridListItem extends Component<GridListItemProps> { | |
testID, | ||
imageProps, | ||
alignToStart, | ||
horizontalAlignment, | ||
containerStyle, | ||
containerProps = {}, | ||
renderCustomItem, | ||
|
@@ -181,33 +216,33 @@ class GridListItem extends Component<GridListItemProps> { | |
onPress, | ||
renderOverlay | ||
} = this.props; | ||
const hasPress = _.isFunction(onPress); | ||
const hasOverlay = _.isFunction(renderOverlay); | ||
const Container = hasPress ? TouchableOpacity : View; | ||
const imageStyle = {...this.getItemSizeObj()}; | ||
const width = _.get(imageStyle, 'width'); | ||
const TextContainer = overlayText ? View : React.Fragment; | ||
const textContainerStyle = overlayText ? {style: [styles.overlayText, overlayTextContainerStyle]} : null; | ||
const imageBorderRadius = imageProps?.borderRadius; | ||
const Container = onPress ? TouchableOpacity : View; | ||
const itemSize = this.getItemSizeObj(); | ||
const {width} = itemSize; | ||
const horizontalAlignmentStyle = this.getHorizontalAlignmentStyle(horizontalAlignment); | ||
const textContainerStyle = overlayText && { | ||
style: [styles.overlayText, overlayTextContainerStyle] | ||
}; | ||
const {hitSlop, ...otherContainerProps} = containerProps; // eslint-disable-line | ||
|
||
return ( | ||
<Container | ||
style={[styles.container, alignToStart && styles.containerAlignedToStart, {width}, containerStyle]} | ||
style={[ | ||
styles.container, | ||
alignToStart && styles.containerAlignedToStart, | ||
horizontalAlignmentStyle?.containerStyle, | ||
{width}, | ||
containerStyle | ||
]} | ||
{...otherContainerProps} | ||
onPress={hasPress ? this.onItemPress : undefined} | ||
onPress={onPress && this.onItemPress} | ||
accessible={renderCustomItem ? true : undefined} | ||
{...Modifiers.extractAccessibilityProps(this.props)} | ||
> | ||
{imageProps && ( | ||
<View style={[{borderRadius: imageBorderRadius}, imageStyle]}> | ||
<Image {...imageProps} style={[imageStyle, imageProps?.style]}/> | ||
{children} | ||
</View> | ||
)} | ||
{imageProps && <Image style={itemSize} {...imageProps} customOverlayContent={children}/>} | ||
{!_.isNil(renderCustomItem) && <View style={{width}}>{renderCustomItem()}</View>} | ||
{hasOverlay && <View style={[styles.overlay, this.getItemSizeObj()]}>{renderOverlay?.()}</View>} | ||
<TextContainer {...textContainerStyle}> | ||
{renderOverlay && <View style={[styles.overlay, itemSize]}>{renderOverlay()}</View>} | ||
<View {...textContainerStyle}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You changed the TextContainer from View or Fragment to View. This can result in alignment issues (if you remember the Icon bug...). Why did you make this change? |
||
{this.renderContent({ | ||
testID: `${testID}.title`, | ||
text: title, | ||
|
@@ -232,7 +267,7 @@ class GridListItem extends Component<GridListItemProps> { | |
numberOfLines: descriptionLines, | ||
style: styles.description | ||
})} | ||
</TextContainer> | ||
</View> | ||
</Container> | ||
); | ||
} | ||
|
@@ -246,6 +281,12 @@ const styles = StyleSheet.create({ | |
containerAlignedToStart: { | ||
alignItems: 'flex-start' | ||
}, | ||
containerAlignedToCenter: { | ||
alignItems: 'center' | ||
}, | ||
containerAlignedToEnd: { | ||
alignItems: 'flex-end' | ||
}, | ||
title: { | ||
marginTop: Spacings.s1, | ||
textAlign: 'center', | ||
|
@@ -262,15 +303,21 @@ const styles = StyleSheet.create({ | |
contentAlignedToStart: { | ||
textAlign: 'left' | ||
}, | ||
contentAlignedToCenter: { | ||
textAlign: 'center' | ||
}, | ||
contentAlignedToEnd: { | ||
textAlign: 'right' | ||
}, | ||
overlay: { | ||
position: 'absolute', | ||
left: 0, | ||
top: 0 | ||
}, | ||
overlayText: { | ||
position: 'absolute', | ||
bottom: 10, | ||
left: 10 | ||
bottom: 0, | ||
padding: Spacings.s3 | ||
} | ||
}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,7 +73,7 @@ export type ImageProps = Omit<RNImageProps, 'source'> & | |
/** | ||
* Render an overlay with custom content | ||
*/ | ||
customOverlayContent?: JSX.Element; | ||
customOverlayContent?: React.ReactElement; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the children type change is relevant to this PR? |
||
/** | ||
* Default image source in case of an error | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be an array