How to copy react component and pass specific property value? - javascript

Text Component exists as below.
const Text = ({
color,
fontSize,
fontWeight,
children,
}: Props) => {
return (
<Root // styled-component
color={color}
fontSize={fontSize}
fontWeight={fontWeight}
>
{children}
</Root>
);
};
const Root = styled.div`
${props => `color: ${props.color};`}
${props => `font-size: ${props.fontSize};`}
${props => `font-weight: ${props.fontWeight};`}
`;
export default Text;
Color, fontSize, and fontWeight are externally managed in the form of objects.
export const color = {
purple: "#683CED",
light_purple: "#925CE9",
orange: "#F58229",
light_gray1: "#DDDDDD",
light_gray2: "#EEEEEE",
light_gray3: "#F9F9F9",
light_gray4: "#D9D9D9",
gray: "#666666",
dark_gray: "#999999",
black: "#000000",
white: "#FFFFFF",
};
export const font = {
size: {
menubar: "10px",
xs: "11px",
s: "12px",
m: "13px",
content: "14px",
title: "16px",
header: "18px",
},
weight: {
regular: "400",
bold: "700",
},
};
When using that component:
import { color, font } from "example-path"
<Text color={color.black} fontSize{font.size.s} fontWeight={font.weight.regular}>Example Text</Text>
This use seems to significantly increase the length of the code where the Text component is used. So, I would like to create in advance all cases of fontSize and fontWeight values that Text components can have and use them as follows.
<Text.T1 color={color.black}>T1</Text> // fontSize = xs and fontWeight = regular
<Text.T2 color={color.black}>T2</Text> // fontSize = s and fontWeight = regular
<Text.T3 color={color.black}>T3</Text> // fontSize = m and fontWeight = regular
....
When a Text component and a font object are given, is there a way to create all possible combinations of font values in advance and group them with the Text component as in the example above?

Related

paddingHorizontal: 0 not responding

Why is my paddingHorizontal not working in react native? I have used paddingHorizontal: 0 in the following code, But the buttons are not responding?
Not sure what I'm doing wrong.
import React from "react";
import { StyleSheet, TouchableOpacity, Text } from "react-native";
import PropTypes from "prop-types";
const Button = ({ title, varient }) => {
return (
<TouchableOpacity
style={[
styles.buttonContainer,
{
backgroundColor: varient === "primary" ? "black" : "transparent",
// paddingHorizontal: varient === "primary" ? 16 : 0,
},
]}
>
<Text
style={[
styles.buttonLabel,
{ color: varient === "primary" ? "white" : "black" },
]}
>
{title}
</Text>
</TouchableOpacity>
);
};
const { string } = PropTypes;
Button.propTypes = {
title: string,
varient: string,
};
const styles = StyleSheet.create({
buttonContainer: {
paddingVertical: 12,
paddingHorizontal: 0,
borderRadius: 6,
},
buttonLabel: {
fontSize: 18,
},
});
export default Button;
I have added the screen as following:

Input text label on border in react native

I want to create an input box like this:
But I designed it like this, and I don't know how to add the label on the input border
My Code is:
<InputBox label="Email" icon={true} keyboardType="email-address" defaultValue={emailId} onChangeText={text => setEmailId(text)} />
Input Component:
import React from 'react';
import {View, StyleSheet, TextInput, Text} from 'react-native';
import {COLORS} from '../constants/colors';
import {FONT_FAMILY} from '../constants/font-family';
export default function InputBox(props) {
return (
<View style={styles.container}>
<View style={{flex: 1}}>
<Text style={styles.label}>{props.label}</Text>
<TextInput
placeholder={props.placeholder}
placeholderTextColor="#9F9F9F"
style={styles.input}
keyboardType={props.keyboardType}
secureTextEntry={false}
defaultValue={props.defaultValue}
onChangeText={props.onChangeText}
editable={props.editable}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 20,
paddingTop: 7.5,
paddingHorizontal: 12.5,
paddingBottom: 2.5,
borderRadius: 5,
borderWidth: 0.75,
borderColor: COLORS.WHITE,
},
input: {
fontFamily: FONT_FAMILY.primaryMedium,
fontSize: 14,
height: 37,
color: COLORS.WHITE,
},
label: {
fontFamily: FONT_FAMILY.primary,
marginLeft: 5,
color: COLORS.WHITE,
fontSize: 12,
// marginTop: -30,
},
});
By using react-native-paper, when I add transparent background color it looks like this:
I was able to get this accomplished purely in React Native without any dependencies. The trick was to put the Text in a View with a background color the same as the screen's and position the Text absolutely. My example code hardcodes a lot of values, but if you want it to be responsive you'll need to come up with your own way of figuring those values out. The code:
import { View, Text, TextInput, StyleSheet } from "react-native";
const Input = () => {
return (
<View>
<View style={styles.labelContainer}>
<Text>Email Address</Text>
</View>
<View style={styles.inputContainer}>
<TextInput placeholder="Enter email address" />
</View>
</View>
);
}
const styles = StyleSheet.create({
labelContainer: {
backgroundColor: "white", // Same color as background
alignSelf: "flex-start", // Have View be same width as Text inside
paddingHorizontal: 3, // Amount of spacing between border and first/last letter
marginStart: 10, // How far right do you want the label to start
zIndex: 1, // Label must overlap border
elevation: 1, // Needed for android
shadowColor: "white", // Same as background color because elevation: 1 creates a shadow that we don't want
position: "absolute", // Needed to be able to precisely overlap label with border
top: -12, // Vertical position of label. Eyeball it to see where label intersects border.
},
inputContainer: {
borderWidth: 1, // Create border
borderRadius: 8, // Not needed. Just make it look nicer.
padding: 8, // Also used to make it look nicer
zIndex: 0, // Ensure border has z-index of 0
},
});
export default Input;
This is what it looks like on my device (Samsung Galaxy S10+):
If you have to use a material ui styled components you may wanna use reactnativepaper
hi there you cna use this code to achive
import React from 'react';
import {View, StyleSheet, Text} from 'react-native';
import { TextInput } from 'react-native-paper';
export default function InputBox(props) {
return (
<View style={styles.container}>
<TextInput
mode="outlined"
label="Email"
style={{width:'90%'}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
justifyContent:'center',alignItems:'center',
flex:1
// borderColor: COLORS.WHITE,
},
input: {
// fontFamily: FONT_FAMILY.primaryMedium,
fontSize: 14,
height: 37,
// color: COLORS.WHITE,
},
label: {
// fontFamily: FONT_FAMILY.primary,
marginLeft: 5,
// color: COLORS.WHITE,
fontSize: 12,
// marginTop: -30,
},
});
you can test it on Snack
Also you can read more about props here react-native-paper

Dimension isnt working in xiaomi phones? REACT-NATIVE

Im building a component that show some icons so the user can choose the color, the component is just a <View> and inside of it theres a flatlist showing the icons: heres the code:
class Color extends Component {
icons_config = {name: "square-full", size: 80, color: "black"};
show_hide_ = false;
options_array = [
{option_icon: <FontAwesome5 name = {this.icons_config.name} size = {this.icons_config.size} color = "red"/>, key: "red"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "blue"/>, key: "blue"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "green"/>, key: "green"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "yellow"/>, key: "yellow"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "purple"/>, key: "purple"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "black"/>, key: "rgba(0,0,0,0.7)"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "gray"/>, key: "gray"},
{option_icon: <FontAwesome5 name = {this.icons_config.name} size={this.icons_config.size} color = "orange"/>, key: "orange"},
{option_icon: <AntDesign name="closesquareo" size={80} color="black" />, key: ""}, //x icon for delete color
];
window_width = Dimensions.get("window").width;
window_height = Dimensions.get("window").height;
render() {
return (
<>
<View style = {this.styles.container}>
{this.options_array.map((option) => {
return (
<View key = {option.key} style = {this.styles.options}>
<TouchableOpacity style = {this.styles.touchable} onPress = {() => this.choose_color(option.key)}>
<Text>{option.option_icon}</Text>
</TouchableOpacity>
</View>
);
})}
</View>
</>
);
}
and the stylesheet code:
styles = StyleSheet.create({
container: {
position: "absolute",
justifyContent: "space-around",
width: Math.round(this.window_width) * 0.8,
height: Math.round(this.window_width) * 0.8,
flexWrap: "wrap",
flexDirection: "row",
alignSelf: "center",
//backgroundColor: "#DCDCDC",
backgroundColor: "red",
marginTop: 200,
},
options: {
paddingTop: Math.round(this.window_width) * 0.025,
justifyContent: "center",
}
});
the problem now, is that im using Dimensions.get("window").width in width and height to create a responsive square for all devices, the problem is that it isnt working in my xiaomi mi 9T, but it does in my one plus 7 pro and on my huawei p9 plus, here Im goint to post some captures so you can see it:
Xiaomi mi 9t:
One plus 7 pro:
Huawei p9 plus:
I guess it has something to do with the icons size, but for one plus and huawei theres no problem, how can I solve this?
You can get the screen width or height using window prop and set the card width and height.
Following example will help you,
import { StyleSheet, Dimensions } from 'react-native';
const window = Dimensions.get('window');
styles = StyleSheet.create({
container: {
width: (window.width) * 0.8,
height: (window.width) * 0.8
},
});

How to combine React default styles with a style prop?

I have the following ui-component:
...
import stylePropType from 'react-style-proptype';
const Heading = ({
...
marginBottom,
strong
}) => (
<Header
style={{
marginBottom,
fontWeight: strong ? 'bold' : 'normal',
}}
>....
</Header>
);
Heading.defaultProps = {
children: <div />,
marginBottom: 4,
strong: false,
style: {},
};
Heading.propTypes = {
children: PropTypes.node,
marginBottom: PropTypes.number,
strong: PropTypes.bool,
style: stylePropType,
};
How can I combine the current style logic (marginBottom and fontWeight) with optionally additional styles passed in as a prop? Is there a way to combine the two or merge them?
You can use the spread syntax (...) on your passed in styles:
<Header
style={{
marginBottom,
fontWeight: strong ? 'bold' : 'normal',
...this.props.style
}}
>....
</Header>

TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof ... renderIf"' has no compatible call signatures

Its base on https://github.com/react-native-training/reactxp-starter
Also I am new to TypeScript!
The renderIf is a regular js function, for some reason I got the error with type. I am not really clear where the type should have been to let the renderIf function run. Any thought or pointer will be great! Since ReactXP is really a thin wrapper above React Native.
Thanks!
/*
* This file demonstrates a basic ReactXP app.
*/
import RX = require('reactxp');
import renderIf = require('./util/renderIf');
//import { VirtualListView, VirtualListViewItemInfo } from 'virtuallistview';
const styles = {
container: RX.Styles.createViewStyle({
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#0a84c1'
}),
helloWorld: RX.Styles.createTextStyle({
color: 'white',
fontSize: 48,
fontWeight: 'bold',
marginBottom: 28
}),
welcome: RX.Styles.createTextStyle({
color: 'white',
fontSize: 32,
marginBottom: 12
}),
instructions: RX.Styles.createTextStyle({
fontSize: 16,
color: '#aaa',
marginBottom: 40
}),
docLink: RX.Styles.createLinkStyle({
fontSize: 16,
color: 'blue'
}),
emotionalInput: RX.Styles.createLinkStyle({
fontSize: 32,
height: 32,
}),
questionPage: RX.Styles.createTextStyle({
color: 'white',
fontSize: 48,
fontWeight: 'bold',
marginBottom: 28
}),
questionPageShow: RX.Styles.createTextStyle({
color: 'white',
fontSize: 48,
fontWeight: 'bold',
marginBottom: 28
}),
questionPageHide: RX.Styles.createTextStyle({
color: 'white',
fontSize: 48,
fontWeight: 'bold',
marginBottom: 28,
}),
};
// interface QuestionItem extends VirtualListViewItemInfo {
// text: string;
// }
interface QuestionProps {
}
interface QuestionState {
questionNow: number;
}
class App extends RX.Component<QuestionProps, QuestionState> {
private _translationValue: RX.Animated.Value;
private _translationValue2: RX.Animated.Value;
private _animatedStyle: RX.Types.AnimatedTextStyleRuleSet;
private _animatedStyleNextQuestion: RX.Types.AnimatedTextStyleRuleSet;
constructor() {
super();
this.state = {
questionNow: 1,
};
this._translationValue = new RX.Animated.Value(-100);
this._animatedStyle = RX.Styles.createAnimatedTextStyle({
transform: [
{
translateY: this._translationValue
}
]
});
this._translationValue2 = new RX.Animated.Value(-100);
this._animatedStyleNextQuestion = RX.Styles.createAnimatedTextStyle({
transform: [
{
translateY: this._translationValue2
}
]
});
}
componentDidMount() {
// let animation = RX.Animated.timing(this._translationValue, {
// toValue: 0,
// easing: RX.Animated.Easing.OutBack(),
// duration: 500
// }
// );
// animation.start();
let animationParalle = RX.Animated.parallel([
RX.Animated.timing(this._translationValue, {
toValue: 0,
easing: RX.Animated.Easing.OutBack(),
duration: 1000
}),
RX.Animated.timing(this._translationValue2, {
toValue: 0,
easing: RX.Animated.Easing.OutBack(),
duration: 3000
}),
]);
animationParalle.start();
}
guessResult(e: any) {
console.log(e);
}
pressAction(e: any) {
console.log(e);
}
goNext(event: any) {
console.log(event);
const newCount = this.state.questionNow + 1;
this.setState({
questionNow: newCount,
});
console.log(newCount);
}
render(): JSX.Element | null {
console.log(renderIf);
return (
<RX.View style={ styles.container }>
<RX.Animated.Text style={ [styles.helloWorld, this._animatedStyle] }>
Go Go Go
</RX.Animated.Text>
<RX.Animated.Text style={ [styles.questionPage, this._animatedStyleNextQuestion] }>
NEXT Question!
</RX.Animated.Text>
{renderIf(
this.state.questionNow === 1,
<RX.Text> New Stuff</RX.Text>
)}
{/*
Question 1
*/}
<RX.Text style={ styles.welcome }>
Question {this.state.questionNow}
How are you?
<RX.Button
style={ styles.welcome }
onPressOut={this.goNext.bind(this)}>
Great!
</RX.Button>
<RX.Button
style={ styles.welcome }
onPressOut={this.goNext.bind(this)}>
Great!
</RX.Button>
</RX.Text>
{/*
Question 2
*/}
<RX.Text style={ styles.welcome }>
Question {this.state.questionNow}
How are you?
<RX.Button
style={ styles.welcome }
onPressOut={this.goNext.bind(this)}>
Great!
</RX.Button>
<RX.Button
style={ styles.welcome }
onPressOut={this.goNext.bind(this)}>
Great!
</RX.Button>
</RX.Text>
<RX.TextInput style={ styles.emotionalInput } onChangeText={this.guessResult}/>
<RX.Text>Text</RX.Text>
</RX.View>
);
}
}
export = App;
error
ERROR in [at-loader] ./src/App.tsx:154:18
TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof "/Users/app/src/util/renderIf"' has no compatible call signatures.
renderIf.ts
export default function renderIf(condition: any, content: any) {
if (condition) {
return content;
} else {
return null;
}
}
Wow.... its crazy, actually its because I did not add .default when I call renderIf.... BUT I can't really even do import renderIf = require('./util/renderIf').default; so I have to do import renderIf = require('./util/renderIf');.. which is strange

Categories