UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

761 lines (721 loc) 18.6 kB
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow * @format */ 'use strict'; const React = require('react'); const { Alert, Animated, I18nManager, Image, PixelRatio, Platform, StyleSheet, Text, TextInput, TouchableWithoutFeedback, Switch, View, Button, } = require('react-native'); type RTLToggleState = {isRTL: boolean, ...}; type AnimationState = { toggleStatus: any, linear: Object, windowWidth: number, ... }; const SCALE = PixelRatio.get(); const IMAGE_DIMENSION = 100 * SCALE; const IMAGE_SIZE = [IMAGE_DIMENSION, IMAGE_DIMENSION]; const IS_RTL = I18nManager.isRTL; function ListItem(props) { return ( <View style={styles.row}> <View style={styles.column1}> <Image source={props.imageSource} style={styles.icon} /> </View> <View style={styles.column2}> <View style={styles.textBox}> <Text>Text Text Text</Text> </View> </View> <View style={styles.column3}> <View style={styles.smallButton}> <Text style={styles.fontSizeSmall}>Button</Text> </View> </View> </View> ); } const TextAlignmentExample = withRTLState(({isRTL, setRTL, ...props}) => { return ( <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> <View style={directionStyle(isRTL)}> <Text style={props.style}> Left-to-Right language without text alignment. </Text> <Text style={props.style}> {'\u0645\u0646 \u0627\u0644\u064A\u0645\u064A\u0646 ' + '\u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631 ' + '\u0627\u0644\u0644\u063A\u0629 \u062F\u0648\u0646 ' + '\u0645\u062D\u0627\u0630\u0627\u0629 \u0627\u0644\u0646\u0635'} </Text> <Text style={props.style}> {'\u05DE\u05D9\u05DE\u05D9\u05DF \u05DC\u05E9\u05DE\u05D0\u05DC ' + '\u05D4\u05E9\u05E4\u05D4 \u05D1\u05DC\u05D9 ' + '\u05D9\u05D9\u05E9\u05D5\u05E8 \u05D8\u05E7\u05E1\u05D8'} </Text> </View> </View> ); }); const TextInputExample = withRTLState(({isRTL, setRTL, ...props}) => { return ( <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> <View style={directionStyle(isRTL)}> <Text style={props.style}>LRT or RTL TextInput.</Text> <TextInput style={props.style} /> </View> </View> ); }); const IconsExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> <View style={[styles.flexDirectionRow, directionStyle(isRTL)]}> <View> <Image source={require('../../assets/like.png')} style={styles.image} /> <Text style={styles.fontSizeExtraSmall}> Without directional meaning </Text> </View> <View style={styles.rightAlignStyle}> <Image source={require('../../assets/poke.png')} style={[styles.image, styles.withRTLStyle]} /> <Text style={styles.fontSizeExtraSmall}> With directional meaning </Text> </View> </View> </View> ); }); function AnimationBlock(props) { return ( <View style={styles.block}> <TouchableWithoutFeedback onPress={props.onPress}> <Animated.Image style={[styles.img, props.imgStyle]} source={require('../../assets/poke.png')} /> </TouchableWithoutFeedback> </View> ); } type RTLSwitcherComponentState = {| isRTL: boolean, |}; function withRTLState(Component) { return class extends React.Component<*, RTLSwitcherComponentState> { constructor(...args) { super(...args); this.state = { isRTL: IS_RTL, }; } render() { const setRTL = isRTL => this.setState({isRTL: isRTL}); return ( <Component isRTL={this.state.isRTL} setRTL={setRTL} {...this.props} /> ); } }; } const RTLToggler = ({isRTL, setRTL}) => { if (Platform.OS === 'android') { return <Text style={styles.rtlToggler}>{isRTL ? 'RTL' : 'LTR'}</Text>; } const toggleRTL = () => setRTL(!isRTL); return ( <Button onPress={toggleRTL} title={isRTL ? 'RTL' : 'LTR'} color="gray" accessibilityLabel="Change layout direction" /> ); }; class RTLToggleExample extends React.Component<any, RTLToggleState> { constructor(props: Object) { super(props); this.state = { isRTL: IS_RTL, }; } render() { return ( <View> <View style={styles.directionBox}> <Text style={styles.directionText}> {this.state.isRTL ? 'Right-to-Left' : 'Left-to-Right'} </Text> </View> <View style={styles.flexDirectionRow}> <Text style={styles.switchRowTextView}>forceRTL</Text> <View style={styles.switchRowSwitchView}> <Switch onValueChange={this._onDirectionChange} style={styles.rightAlignStyle} value={this.state.isRTL} /> </View> </View> </View> ); } _onDirectionChange = () => { I18nManager.forceRTL(!this.state.isRTL); this.setState({isRTL: !this.state.isRTL}); Alert.alert( 'Reload this page', 'Please reload this page to change the UI direction! ' + 'All examples in this app will be affected. ' + 'Check them out to see what they look like in RTL layout.', ); }; } const SimpleListItemExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> <View style={[styles.list, directionStyle(isRTL)]}> <ListItem imageSource={require('../../assets/like.png')} /> <ListItem imageSource={require('../../assets/poke.png')} /> </View> </View> ); }); const AnimationContainer = withRTLState(({isRTL, setRTL}) => { return <AnimationExample isRTL={isRTL} setRTL={setRTL} />; }); class AnimationExample extends React.Component<any, AnimationState> { constructor(props: Object) { super(props); this.state = { toggleStatus: {}, linear: new Animated.Value(0), windowWidth: 0, }; } render() { return ( <View> <RTLToggler setRTL={this.props.setRTL} isRTL={this.props.isRTL} /> <View style={styles.view} onLayout={this._onLayout}> <AnimationBlock onPress={this._linearTap} imgStyle={{ transform: [ {translateX: this.state.linear}, {scaleX: this.props.isRTL ? -1 : 1}, ], }} /> </View> </View> ); } _onLayout = (e: Object) => { this.setState({ windowWidth: e.nativeEvent.layout.width, }); }; _linearTap = (e: Object) => { this.setState({ toggleStatus: { ...this.state.toggleStatus, [e]: !this.state.toggleStatus[e], }, }); const offset = IMAGE_SIZE[0] / SCALE / 2 + 10; const toMaxDistance = (this.props.isRTL ? -1 : 1) * (this.state.windowWidth / 2 - offset); Animated.timing(this.state.linear, { toValue: this.state.toggleStatus[e] ? toMaxDistance : 0, duration: 2000, useNativeDriver: true, }).start(); }; } const PaddingExample = withRTLState(({isRTL, setRTL}) => { const color = 'teal'; return ( <View> <Text style={styles.bold}>Styles</Text> <Text>paddingStart: 50,</Text> <Text>paddingEnd: 10</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <Text>The {color} is padding.</Text> <View style={{ backgroundColor: color, paddingStart: 50, paddingEnd: 10, borderWidth: 1, borderColor: color, direction: isRTL ? 'rtl' : 'ltr', }}> <View style={{ backgroundColor: 'white', paddingTop: 5, paddingBottom: 5, borderLeftWidth: 1, borderRightWidth: 1, borderColor: 'gray', }}> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> ); }); const MarginExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <Text style={styles.bold}>Styles</Text> <Text>marginStart: 50,</Text> <Text>marginEnd: 10</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <Text>The green is margin.</Text> <View style={{ backgroundColor: 'green', borderWidth: 1, borderColor: 'green', direction: isRTL ? 'rtl' : 'ltr', }}> <View style={{ backgroundColor: 'white', paddingTop: 5, paddingBottom: 5, marginStart: 50, marginEnd: 10, borderLeftWidth: 1, borderRightWidth: 1, borderColor: 'gray', }}> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> ); }); const PositionExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <Text style={styles.bold}>Styles</Text> <Text>start: 50</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <Text>The orange is position.</Text> <View style={{ backgroundColor: 'orange', borderWidth: 1, borderColor: 'orange', direction: isRTL ? 'rtl' : 'ltr', }}> <View style={{ backgroundColor: 'white', start: 50, borderColor: 'gray', }}> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> <Text /> <Text style={styles.bold}>Styles</Text> <Text>end: 50</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <Text>The orange is position.</Text> <View style={{ backgroundColor: 'orange', borderWidth: 1, borderColor: 'orange', direction: isRTL ? 'rtl' : 'ltr', }}> <View style={{ backgroundColor: 'white', end: 50, borderColor: 'gray', }}> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> ); }); const BorderWidthExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <Text style={styles.bold}>Styles</Text> <Text>borderStartWidth: 10,</Text> <Text>borderEndWidth: 50</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <View style={directionStyle(isRTL)}> <View style={{ borderStartWidth: 10, borderEndWidth: 50, }}> <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> </View> ); }); const BorderColorExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <Text style={styles.bold}>Styles</Text> <Text>borderStartColor: 'red',</Text> <Text>borderEndColor: 'green',</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <View style={directionStyle(isRTL)}> <View style={{ borderStartColor: 'red', borderEndColor: 'green', borderLeftWidth: 20, borderRightWidth: 20, padding: 10, }}> <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> </View> ); }); const BorderRadiiExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <Text style={styles.bold}>Styles</Text> <Text>borderTopStartRadius: 10,</Text> <Text>borderTopEndRadius: 20,</Text> <Text>borderBottomStartRadius: 30,</Text> <Text>borderBottomEndRadius: 40</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <View style={directionStyle(isRTL)}> <View style={{ borderWidth: 10, borderTopStartRadius: 10, borderTopEndRadius: 20, borderBottomStartRadius: 30, borderBottomEndRadius: 40, padding: 10, }}> <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> </View> ); }); const BorderExample = withRTLState(({isRTL, setRTL}) => { return ( <View> <Text style={styles.bold}>Styles</Text> <Text>borderStartColor: 'red',</Text> <Text>borderEndColor: 'green',</Text> <Text>borderStartWidth: 10,</Text> <Text>borderEndWidth: 50,</Text> <Text>borderTopStartRadius: 10,</Text> <Text>borderTopEndRadius: 20,</Text> <Text>borderBottomStartRadius: 30,</Text> <Text>borderBottomEndRadius: 40</Text> <Text /> <Text style={styles.bold}>Demo: </Text> <View style={directionStyle(isRTL)}> <View style={{ borderStartColor: 'red', borderEndColor: 'green', borderStartWidth: 10, borderEndWidth: 50, borderTopStartRadius: 10, borderTopEndRadius: 20, borderBottomStartRadius: 30, borderBottomEndRadius: 40, padding: 10, }}> <View> <RTLToggler setRTL={setRTL} isRTL={isRTL} /> </View> </View> </View> </View> ); }); const directionStyle = isRTL => Platform.OS !== 'android' ? {direction: isRTL ? 'rtl' : 'ltr'} : null; const styles = StyleSheet.create({ container: { backgroundColor: '#e9eaed', paddingTop: 15, }, directionBox: { flex: 1, backgroundColor: '#f8f8f8', borderWidth: 0.5, borderColor: 'black', marginBottom: 15, }, directionText: { padding: 10, fontSize: 16, textAlign: 'center', fontWeight: 'bold', }, switchRowTextView: { flex: 1, marginBottom: 5, marginTop: 5, textAlign: 'center', }, switchRowSwitchView: { flex: 3, }, rightAlignStyle: { right: 10, position: 'absolute', }, list: { height: 120, marginBottom: 5, borderTopWidth: 0.5, borderLeftWidth: 0.5, borderRightWidth: 0.5, borderColor: '#e5e5e5', }, row: { height: 60, flexDirection: 'row', borderBottomWidth: 0.5, borderColor: '#e5e5e5', }, column1: { width: 60, }, column2: { flex: 2.5, padding: 6, }, column3: { flex: 1.5, }, icon: { width: 48, height: 48, margin: 6, borderWidth: 0.5, borderColor: '#e5e5e5', }, withRTLStyle: { transform: [{scaleX: IS_RTL ? -1 : 1}], }, image: { left: 30, width: 48, height: 48, }, img: { width: IMAGE_SIZE[0] / SCALE, height: IMAGE_SIZE[1] / SCALE, }, view: { flex: 1, }, block: { padding: 10, alignItems: 'center', }, smallButton: { top: 18, borderRadius: 5, height: 24, width: 64, backgroundColor: '#e5e5e5', justifyContent: 'center', alignItems: 'center', }, fontSizeSmall: { fontSize: 10, }, fontSizeExtraSmall: { fontSize: 8, }, textAlignLeft: { textAlign: 'left', }, textAlignRight: { textAlign: 'right', }, textBox: { width: 28, }, flexDirectionRow: { flexDirection: 'row', }, bold: { fontWeight: 'bold', }, rtlToggler: { color: 'gray', padding: 8, textAlign: 'center', fontWeight: '500', }, }); exports.title = 'RTLExample'; exports.category = 'UI'; exports.description = 'Examples to show how to apply components to RTL layout.'; exports.examples = [ { title: 'Current Layout Direction', render: function(): React.Element<any> { return <RTLToggleExample />; }, }, { title: 'A Simple List Item Layout', render: function(): React.Element<any> { return <SimpleListItemExample />; }, }, { title: 'Default Text Alignment', description: ('In iOS, it depends on active language. ' + 'In Android, it depends on the text content.': string), render: function(): React.Element<any> { return <TextAlignmentExample style={styles.fontSizeSmall} />; }, }, { title: "Using textAlign: 'left'", description: ('In iOS/Android, text alignment flips regardless of ' + 'languages or text content.': string), render: function(): React.Element<any> { return ( <TextAlignmentExample style={[styles.fontSizeSmall, styles.textAlignLeft]} /> ); }, }, { title: "Using textAlign: 'right'", description: ('In iOS/Android, text alignment flips regardless of ' + 'languages or text content.': string), render: function(): React.Element<any> { return ( <TextAlignmentExample style={[styles.fontSizeSmall, styles.textAlignRight]} /> ); }, }, { title: "Using textAlign: 'right' for TextInput", description: ('Flip TextInput direction to RTL': string), render: function(): React.Element<any> { return <TextInputExample style={[styles.textAlignRight]} />; }, }, { title: 'Working With Icons', render: function(): React.Element<any> { return <IconsExample />; }, }, { title: 'Controlling Animation', description: 'Animation direction according to layout', render: function(): React.Element<any> { return <AnimationContainer />; }, }, { title: 'Padding Start/End', render: function(): React.Element<any> { return <PaddingExample />; }, }, { title: 'Margin Start/End', render: function(): React.Element<any> { return <MarginExample />; }, }, { title: 'Position Start/End', render: function(): React.Element<any> { return <PositionExample />; }, }, { title: 'Border Width Start/End', render: function(): React.Element<any> { return <BorderWidthExample />; }, }, { title: 'Border Color Start/End', render: function(): React.Element<any> { return <BorderColorExample />; }, }, { title: 'Border Radii Start/End', render: function(): React.Element<any> { return <BorderRadiiExample />; }, }, { title: 'Border', render: function(): React.Element<any> { return <BorderExample />; }, }, ];