Skip to content
This repository was archived by the owner on Oct 13, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all 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
Binary file added packages/react-silk-docs/src/assets/chauchau1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/react-silk-docs/src/components/Anchors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export default () => (
<NavItem>
<Link to="/components/carousels">Carousels</Link>
</NavItem>
<NavItem>
<Link to="/components/masonry">Masonry</Link>
</NavItem>
<NavItem>
<Link to="/components/input_pins">Input Pins</Link>
</NavItem>
Expand Down
84 changes: 84 additions & 0 deletions packages/react-silk-docs/src/pages/components/masonry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import * as React from 'react'
import MyMom from '.'
import { Image, StyleSheet, Text, View } from 'react-native'
import { Masonry, Heading5, Modal } from 'react-silk-ui'

const images = [
'https://images.unsplash.com/photo-1542838077-7fb322b21b80?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550483135-4a6b4cbc6469?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550481585-67143479c9bd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550475966-70af27831597?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550456915-749f38312cbe?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550431703-109e2c9f3e3d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550433728-99a10e2bd20d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550434605-d1a3cb21158e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550411335-cab6040bb5b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
'https://images.unsplash.com/photo-1550359542-5c8b880dabdf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
]

const styles = StyleSheet.create({
heading: {
paddingTop: 15,
},
textDemo: {
paddingVertical: 12,
backgroundColor: '#282c34',
color: '#fff',
marginVertical: 12,
paddingLeft: 30,
borderRadius: 6,
},
})

export default class MasonryDemo extends React.Component {
state = {
toggle: false,
url: '',
width: 0,
height: 0,
}

setModalImg = (img: { url: string; height: number; width: number }) => {
this.setState({
toggle: !this.state.toggle,
...img,
})
}

render() {
const { toggle, url, width, height } = this.state
return (
<MyMom>
<View>
<Heading5 style={styles.heading}>Masonry default</Heading5>
<Text style={styles.textDemo}>{'<Masonry images={images} />'}</Text>
<Masonry images={images} />
<Heading5 style={styles.heading}>
Masonry with number of columns is set to 4
</Heading5>
<Text style={styles.textDemo}>
{'<Masonry images={images} col={4} />'}
</Text>
<Masonry images={images} col={4} />
<Heading5 style={styles.heading}>
Masonry with image gap is set to 30
</Heading5>
<Text style={styles.textDemo}>
{'<Masonry images={images} gap={30} />'}
</Text>
<Masonry images={images} gap={30} />
<Heading5 style={styles.heading}>Clickable Masonry</Heading5>
<Masonry images={images} onPress={this.setModalImg}>
<Modal
toggle={() => this.setState({ toggle: !toggle })}
isOpen={toggle}
style={{}}
>
<Image source={{ uri: url }} style={{ width, height }} />
</Modal>
</Masonry>
</View>
</MyMom>
)
}
}
133 changes: 133 additions & 0 deletions packages/react-silk-ui/src/components/Masonry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import * as React from 'react'
import { View, Image, TouchableWithoutFeedback, StyleSheet } from 'react-native'

export interface Props {
images: string[]
col?: number
gap?: number
onPress?: (arg0: { url: string; height: number; width: number }) => void
}

const defaultProps = {
col: 3,
gap: 10,
onPress: null,
}

interface State {
width: number
columns: {
height: number
images: { url: string; height: number; width: number }[]
}[]
}

const style = StyleSheet.create({
masonryWrapper: {
flexDirection: 'row',
},
column: {
flex: 1,
},
})

const COLUMN_WIDTH = 300 // on component didmount, layout wontbe loaded so it's width = 0, cannot get column width => define a value to calculate standard image height

export class Masonry extends React.Component<Props, State> {
static defaultProps = defaultProps

constructor(props: Props) {
super(props)
this.state = {
width: 0,
columns: [],
}
}

async componentDidMount() {
const columns = []
const col = this.props.col!
for (let i = 0; i < col; i++) {
columns.push({
height: 0,
images: [],
})
}
await this.setState({ columns })
await this.props.images.forEach(img => {
Image.getSize(
img,
(width, height) => {
const index = this.minColIndex()
const cols = this.state.columns
const imgHeight = (height * COLUMN_WIDTH) / width
cols[index].height = cols[index].height + imgHeight
cols[index].images.push({
url: img,
height: imgHeight,
width: COLUMN_WIDTH,
})
this.setState({ columns: cols })
},
err => console.log(err),
)
})
}

minColIndex() {
return this.state.columns.reduce(
(minIndex, current, index, arr) =>
current.height < arr[minIndex].height ? index : minIndex,
0,
)
}

onLayout = (event: any) => {
const { width } = event.nativeEvent.layout
this.setState({ width })
}

columnWidth() {
const col = this.props.col!
const gap = this.props.gap!
return this.state.width / col - gap
}

render() {
const onPress = this.props.onPress!
const gap = this.props.gap!
const colWidth = this.columnWidth()
return (
<View
onLayout={this.onLayout}
style={[style.masonryWrapper, { marginHorizontal: -gap / 2 }]}
>
{this.state.columns.map((col, index) => (
<View style={style.column} key={`column${index}`}>
{col.images.map((img, id) => {
const height = (img.height * colWidth) / COLUMN_WIDTH
return onPress !== null ? (
<TouchableWithoutFeedback
onPress={() => onPress(img)}
key={`col${index}_img${id}`}
>
<Image
source={{ uri: img.url }}
style={{ width: colWidth, height, margin: gap / 2 }}
/>
</TouchableWithoutFeedback>
) : (
<Image
source={{ uri: img.url }}
style={{ width: colWidth, height, margin: gap / 2 }}
key={`col${index}_img${id}`}
/>
)
})}
</View>
))}
{this.props.children}
</View>
)
}
}
3 changes: 3 additions & 0 deletions packages/react-silk-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { DropdownButton } from './components/Dropdown/Button'
import { DropdownItem } from './components/Dropdown/Item'
import { Carousel } from './components/Carousel'
import * as Colors from './components/Colors'
import { Masonry } from './components/Masonry'
import { InputPin } from './components/InputPin'

export {
Expand All @@ -37,6 +38,7 @@ export {
Dropdown,
DropdownButton,
DropdownItem,
Masonry,
Carousel,
InputPin,
}
Expand All @@ -59,6 +61,7 @@ export default {
Dropdown,
DropdownButton,
DropdownItem,
Masonry,
Carousel,
InputPin,
}
Loading