From a1664927ced0436070f39e898a56e6f052610868 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 21 Oct 2015 17:57:01 -0700 Subject: [PATCH] [change] initial example with media queries --- examples/components/App.js | 198 +++++++++++++++++++++ examples/components/GridView.js | 67 +++++++ examples/components/Heading.js | 31 ++++ examples/components/MediaQueryWidget.js | 36 ++++ examples/index.js | 222 ++---------------------- package.json | 1 + 6 files changed, 350 insertions(+), 205 deletions(-) create mode 100644 examples/components/App.js create mode 100644 examples/components/GridView.js create mode 100644 examples/components/Heading.js create mode 100644 examples/components/MediaQueryWidget.js diff --git a/examples/components/App.js b/examples/components/App.js new file mode 100644 index 00000000..cefd87d7 --- /dev/null +++ b/examples/components/App.js @@ -0,0 +1,198 @@ +import GridView from './GridView' +import Heading from './Heading' +import MediaQueryWidget from './MediaQueryWidget' +import React, { Image, StyleSheet, Text, TextInput, Touchable, View } from '../../src' + +export default class App extends React.Component { + static propTypes = { + mediaQuery: React.PropTypes.object, + style: View.propTypes.style + } + + render() { + const { mediaQuery } = this.props + const rootStyles = { + ...(styles.root.common), + ...(mediaQuery.small.matches && styles.root.mqSmall), + ...(mediaQuery.large.matches && styles.root.mqLarge) + } + + return ( + + React Native for Web + React Native Web takes the core components from React + Native and brings them to the web. These components provide + simple building blocks – touch handling, flexbox layout, + scroll views – from which more complex components and apps can be + constructed. + + + + Image + Inner content} + defaultSource={{ + uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAIAAAAP3aGbAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wkGESkdPWMDggAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAD5UlEQVR42u3UMQ0AAAgEMcC/x7eCCgaSVsIN10kK4IORADAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAswLAkAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAALi04UQW9HF910gAAAABJRU5ErkJggg==' + }} + onError={(e) => { console.log('Image.onError', e) }} + onLoad={(e) => { console.log('Image.onLoad', e) }} + onLoadEnd={() => { console.log('Image.onLoadEnd') }} + onLoadStart={() => { console.log('Image.onLoadStart') }} + resizeMode={'contain'} + source={{ + height: 400, + uri: 'http://facebook.github.io/react/img/logo_og.png', + width: 400 + }} + style={{ + borderWidth: '5px' + }} + testID='Example.image' + /> + + Text + { console.log('Text.onPress', e) }} + testID={'Example.text'} + > + PRESS ME. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vel + lectus urna. Aliquam vitae justo porttitor, aliquam erat nec, + venenatis diam. Vivamus facilisis augue non urna mattis ultricies. + Suspendisse et vulputate enim, a maximus nulla. Vivamus imperdiet + hendrerit consequat. Aliquam lorem quam, elementum eget ex nec, + ultrices porttitor nibh. Nulla pellentesque urna leo, a aliquet elit + rhoncus a. Aenean ultricies, nunc a interdum dictum, dui odio + scelerisque mauris, a fringilla elit ligula vel sem. Sed vel aliquet + ipsum, sed rhoncus velit. Vivamus commodo pretium libero id placerat. + + + TRUNCATED after 1 line. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vel + lectus urna. Aliquam vitae justo porttitor, aliquam erat nec, + venenatis diam. Vivamus facilisis augue non urna mattis ultricies. + Suspendisse et vulputate enim, a maximus nulla. Vivamus imperdiet + hendrerit consequat. + + + TextInput + { console.log('TextInput.onBlur', e) }} + onChange={(e) => { console.log('TextInput.onChange', e) }} + onChangeText={(e) => { console.log('TextInput.onChangeText', e) }} + onFocus={(e) => { console.log('TextInput.onFocus', e) }} + onSelectionChange={(e) => { console.log('TextInput.onSelectionChange', e) }} + /> + + + + + + + + + Touchable + { console.log('Touchable.onLongPress', e) }} + onPress={(e) => { console.log('Touchable.onPress', e) }} + onPressIn={(e) => { console.log('Touchable.onPressIn', e) }} + onPressOut={(e) => { console.log('Touchable.onPressOut', e) }} + > + + Touchable area (press, long press) + + + + View + Default layout + + {[ 1, 2, 3, 4, 5, 6 ].map((item, i) => { + return ( + + {item} + + ) + })} + + + Row layout + + {[ 1, 2, 3, 4, 5, 6 ].map((item, i) => { + return ( + + {item} + + ) + })} + + + pointerEvents + + {['box-none', 'box-only', 'none'].map((value, i) => { + return ( + + ) + })} + + + ) + } +} + +const styles = StyleSheet.create({ + root: { + common: { + margin: '0 auto' + }, + mqSmall: { + maxWidth: '400px' + }, + mqLarge: { + maxWidth: '600px' + } + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap' + }, + box: { + alignItems: 'center', + flexGrow: 1, + justifyContent: 'center', + borderWidth: '1px' + }, + boxFull: { + width: '100%' + }, + pointerEventsBox: { + alignItems: 'center', + borderWidth: '1px', + flexGrow: 1, + height: '100px', + justifyContent: 'center' + }, + touchableArea: { + alignItems: 'center', + borderWidth: 1, + height: '200px', + justifyContent: 'center' + } +}) diff --git a/examples/components/GridView.js b/examples/components/GridView.js new file mode 100644 index 00000000..79ae086d --- /dev/null +++ b/examples/components/GridView.js @@ -0,0 +1,67 @@ +import React, { StyleSheet, View } from '../../src' + +const { Component, PropTypes } = React + +const styles = StyleSheet.create({ + root: { + overflow: 'hidden' + }, + contentContainer: { + flexDirection: 'row', + flexGrow: 1 + }, + // distribute all space (rather than extra space) + column: { + flexBasis: '0%' + } +}) + +export default class GridView extends Component { + static propTypes = { + alley: PropTypes.string, + children: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.arrayOf(PropTypes.element) + ]), + gutter: PropTypes.string, + style: PropTypes.object + } + + static defaultProps = { + alley: '0', + gutter: '0' + } + + render() { + const { alley, children, gutter, style, ...other } = this.props + + const rootStyle = { + ...style, + ...styles.root + } + + const contentContainerStyle = { + ...styles.contentContainer, + margin: `0 calc(-0.5 * ${alley})`, + padding: `0 ${gutter}` + } + + const newChildren = React.Children.map(children, (child) => { + return child && React.cloneElement(child, { + style: { + ...child.props.style, + ...styles.column, + margin: `0 calc(0.5 * ${alley})` + } + }) + }) + + return ( + + + {newChildren} + + + ) + } +} diff --git a/examples/components/Heading.js b/examples/components/Heading.js new file mode 100644 index 00000000..5571af2c --- /dev/null +++ b/examples/components/Heading.js @@ -0,0 +1,31 @@ +import React from 'react' +import { StyleSheet, Text } from '../../src' + +const headingStyles = StyleSheet.create({ + size: { + xlarge: { + fontSize: '2rem', + marginBottom: '1em' + }, + large: { + fontSize: '1.5rem', + marginBottom: '1em', + marginTop: '1em' + }, + normal: { + fontSize: '1.25rem', + marginBottom: '0.5em', + marginTop: '0.5em' + } + } +}) + +const Heading = ({ children, size = 'normal' }) => ( + +) + +export default Heading diff --git a/examples/components/MediaQueryWidget.js b/examples/components/MediaQueryWidget.js new file mode 100644 index 00000000..c7c057ff --- /dev/null +++ b/examples/components/MediaQueryWidget.js @@ -0,0 +1,36 @@ +import React, { StyleSheet, Text, View } from '../../src' + +const styles = StyleSheet.create({ + root: { + alignItems: 'center', + borderWidth: 1, + margin: '10px 0', + padding: 10, + textAlign: 'center' + }, + heading: { + fontWeight: 'bold', + padding: 5 + } +}) + +const MediaQueryWidget = ({ mediaQuery = {} }) => { + const active = Object.keys(mediaQuery).reduce((active, alias) => { + if (mediaQuery[alias].matches) { + active = { + alias, + mql: mediaQuery[alias] + } + } + return active + }, {}) + + return ( + + Active Media Query + {`"${active.alias}"`} {active.mql.media} + + ) +} + +export default MediaQueryWidget diff --git a/examples/index.js b/examples/index.js index 2f6ccf98..12f2d8e3 100644 --- a/examples/index.js +++ b/examples/index.js @@ -1,210 +1,22 @@ -import React, { Image, StyleSheet, Text, TextInput, Touchable, View } from '../src' +import { MediaProvider, matchMedia } from 'react-media-queries' +import App from './components/App' +import createGetter from 'react-media-queries/lib/createMediaQueryGetter' +import createListener from 'react-media-queries/lib/createMediaQueryListener' +import React, { StyleSheet } from '../src' import ReactDOM from 'react-dom' -const Heading = ({ children, size = 'normal' }) => ( - +const mediaQueries = { + small: '(min-width: 300px)', + medium: '(min-width: 400px)', + large: '(min-width: 500px)' +} +const ResponsiveApp = matchMedia()(App) + +ReactDOM.render( + + + , + document.getElementById('react-root') ) -const headingStyles = StyleSheet.create({ - size: { - xlarge: { - fontSize: '2rem', - marginBottom: '1em' - }, - large: { - fontSize: '1.5rem', - marginBottom: '1em', - marginTop: '1em' - }, - normal: { - fontSize: '1.25rem', - marginBottom: '0.5em', - marginTop: '0.5em' - } - } -}) - -class Example extends React.Component { - static propTypes = { - style: View.propTypes.style - } - - render() { - return ( - - React Native Web - React Native Web takes the core components from React - Native and brings them to the web. These components provide - simple building blocks – touch handling, flexbox layout, - scroll views – from which more complex components and apps can be - constructed. - - Image - Inner content} - defaultSource={{ - uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAIAAAAP3aGbAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wkGESkdPWMDggAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAD5UlEQVR42u3UMQ0AAAgEMcC/x7eCCgaSVsIN10kK4IORADAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAswLAkAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAADAvAsADDAjAsAMMCDAvAsAAMCzAsAMMCMCzAsAAMC8CwAMMCMCzAsAAMC8CwAMMCMCwAwwIMC8CwAAwLMCwAwwIwLMCwAAwLwLAAwwIwLADDAgwLwLAADAswLADDAjAswLAALi04UQW9HF910gAAAABJRU5ErkJggg==' - }} - onError={(e) => { console.log('Image.onError', e) }} - onLoad={(e) => { console.log('Image.onLoad', e) }} - onLoadEnd={() => { console.log('Image.onLoadEnd') }} - onLoadStart={() => { console.log('Image.onLoadStart') }} - resizeMode={'contain'} - source={{ - height: 400, - uri: 'http://facebook.github.io/react/img/logo_og.png', - width: 400 - }} - style={{ - borderWidth: '5px' - }} - testID='Example.image' - /> - - Text - { console.log('Text.onPress', e) }} - testID={'Example.text'} - > - PRESS ME. - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vel - lectus urna. Aliquam vitae justo porttitor, aliquam erat nec, - venenatis diam. Vivamus facilisis augue non urna mattis ultricies. - Suspendisse et vulputate enim, a maximus nulla. Vivamus imperdiet - hendrerit consequat. Aliquam lorem quam, elementum eget ex nec, - ultrices porttitor nibh. Nulla pellentesque urna leo, a aliquet elit - rhoncus a. Aenean ultricies, nunc a interdum dictum, dui odio - scelerisque mauris, a fringilla elit ligula vel sem. Sed vel aliquet - ipsum, sed rhoncus velit. Vivamus commodo pretium libero id placerat. - - - TRUNCATED after 1 line. - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vel - lectus urna. Aliquam vitae justo porttitor, aliquam erat nec, - venenatis diam. Vivamus facilisis augue non urna mattis ultricies. - Suspendisse et vulputate enim, a maximus nulla. Vivamus imperdiet - hendrerit consequat. - - - TextInput - { console.log('TextInput.onBlur', e) }} - onChange={(e) => { console.log('TextInput.onChange', e) }} - onChangeText={(e) => { console.log('TextInput.onChangeText', e) }} - onFocus={(e) => { console.log('TextInput.onFocus', e) }} - onSelectionChange={(e) => { console.log('TextInput.onSelectionChange', e) }} - /> - - - - - - - - - Touchable - { console.log('Touchable.onLongPress', e) }} - onPress={(e) => { console.log('Touchable.onPress', e) }} - onPressIn={(e) => { console.log('Touchable.onPressIn', e) }} - onPressOut={(e) => { console.log('Touchable.onPressOut', e) }} - > - - Touchable area (press, long press) - - - - View - Default layout - - {[ 1, 2, 3, 4, 5, 6 ].map((item, i) => { - return ( - - {item} - - ) - })} - - - Row layout - - {[ 1, 2, 3, 4, 5, 6 ].map((item, i) => { - return ( - - {item} - - ) - })} - - - pointerEvents - - {['box-none', 'box-only', 'none'].map((value, i) => { - return ( - - ) - })} - - - ) - } -} - -const styles = StyleSheet.create({ - root: { - maxWidth: '600px', - margin: '0 auto' - }, - row: { - flexDirection: 'row', - flexWrap: 'wrap' - }, - box: { - alignItems: 'center', - flexGrow: 1, - justifyContent: 'center', - borderWidth: '1px' - }, - boxFull: { - width: '100%' - }, - pointerEventsBox: { - alignItems: 'center', - borderWidth: '1px', - flexGrow: 1, - height: '100px', - justifyContent: 'center' - }, - touchableArea: { - alignItems: 'center', - borderWidth: 1, - height: '200px', - justifyContent: 'center' - } -}) - -ReactDOM.render(, document.getElementById('react-root')) - document.getElementById('react-stylesheet').textContent = StyleSheet.renderToString() diff --git a/package.json b/package.json index 1172907f..ac5be6ad 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "react": "^0.14.0", "react-addons-test-utils": "^0.14.0", "react-dom": "^0.14.0", + "react-media-queries": "^2.0.0", "webpack": "^1.12.2", "webpack-dev-server": "^1.12.1" },