Skip to content

Translated to TypeScript and added props #3

@gustavogenovese

Description

@gustavogenovese

Hey, I've translated your code to TypeScript and simplified it in the process.
I've also added a couple of extra Props: fontFamily, fontSize, switchMargin which was hardcoded to 6, btnBorderWidth which was hardcoded to 1 and btnBorderRadius which was hardcoded to switchBorderRadius.
Feel free to test it and/or merge it into your repo.
Thanks for your work!

import React, { Component } from "react";
import {
	View,
	Text,
	TouchableWithoutFeedback,
	StyleSheet,
	Animated,
} from "react-native";

type Props = {
	onValueChange: (activeSwitch: 1 | 2) => void;
	fontFamily?: string;
	fontSize?: number;
} & typeof SwitchButton.defaultProps;

interface State {
	offsetX: Animated.Value;
}

class SwitchButton extends Component<Props, State> {
	static defaultProps = {
		text1: "ON",
		text2: "OFF",

		activeSwitch: 1 as 1 | 2,

		switchWidth: 100,
		switchHeight: 44,
		switchMargin: 6,
		switchBorderRadius: 22,
		switchBorderColor: "#d4d4d4",
		switchBackgroundColor: "#fff",
		switchBorderWidth: 1,

		changeSpeed: 100,

		fontColor: "#b1b1b1",
		activeFontColor: "#fff",

		btnBorderColor: "#00a4b9",
		btnBorderWidth: 1,
		btnBorderRadius: 22,
		btnBackgroundColor: "#00bcd4",

		direction: "ltr" as "ltr" | "rtl",
	};

	constructor(props: Props) {
		super(props);
		this.state = {
			offsetX: new Animated.Value(
				this.props.activeSwitch === 1
					? this.getOffsetXFor1()
					: this.getOffsetXFor2()
			),
		};
	}

	componentWillReceiveProps = (nextProps: Props) => {
		if (this.props.activeSwitch !== nextProps.activeSwitch) {
			this.animate();
		}
	};

	getOffsetXFor1 = () => {
		return this.props.switchMargin;
	};

	getOffsetXFor2 = () => {
		const { switchWidth, switchMargin, direction } = this.props;
		let dirsign = 1;
		if (direction === "rtl") {
			dirsign = -1;
		}
		return (switchWidth / 2 + switchMargin) * dirsign;
	};

	switchThump = () => {
		const { onValueChange } = this.props;

		if (this.props.activeSwitch === 1) {
			onValueChange(2);
		} else {
			onValueChange(1);
		}
	};

	animate = () => {
		const { activeSwitch, changeSpeed } = this.props;
		if (activeSwitch === 1) {
			Animated.timing(this.state.offsetX, {
				toValue: this.getOffsetXFor2(),
				duration: changeSpeed,
			}).start();
		} else {
			Animated.timing(this.state.offsetX, {
				toValue: this.getOffsetXFor1(),
				duration: changeSpeed,
			}).start();
		}
	};

	render = () => (
		<TouchableWithoutFeedback onPress={this.switchThump}>
			<View
				style={{
					width: this.props.switchWidth,
					height: this.props.switchHeight,
					borderRadius: this.props.switchBorderRadius,
					borderWidth: this.props.switchBorderWidth,
					borderColor: this.props.switchBorderColor,
					backgroundColor: this.props.switchBackgroundColor,
				}}
			>
				<View
					style={
						this.props.direction === "ltr" ? switchStyles.ltr : switchStyles.rtl
					}
				>
					<Animated.View
						style={{
							transform: [{ translateX: this.state.offsetX }],
							top: this.props.switchMargin,
						}}
					>
						<View
							style={{
								width: this.props.switchWidth / 2 - 2 * this.props.switchMargin,
								height: this.props.switchHeight - 2 * this.props.switchMargin,
								borderWidth: this.props.btnBorderWidth,
								borderRadius: this.props.btnBorderRadius,
								borderColor: this.props.btnBorderColor,
								backgroundColor: this.props.btnBackgroundColor,
							}}
						/>
					</Animated.View>

					<View
						style={[
							switchStyles.textPos,
							{
								width: this.props.switchWidth / 2,
								height: this.props.switchHeight,
								left: 0,
							},
						]}
					>
						<Text
							style={{
								fontFamily: this.props.fontFamily,
								fontSize: this.props.fontSize,
								textAlign: "center",
								color:
									this.props.activeSwitch === 1
										? this.props.activeFontColor
										: this.props.fontColor,
							}}
						>
							{this.props.text1}
						</Text>
					</View>

					<View
						style={[
							switchStyles.textPos,
							{
								width: this.props.switchWidth / 2,
								height: this.props.switchHeight,
								right: 0,
							},
						]}
					>
						<Text
							style={{
								fontFamily: this.props.fontFamily,
								fontSize: this.props.fontSize,
								textAlign: "center",
								color:
									this.props.activeSwitch === 2
										? this.props.activeFontColor
										: this.props.fontColor,
							}}
						>
							{this.props.text2}
						</Text>
					</View>
				</View>
			</View>
		</TouchableWithoutFeedback>
	);
}

const switchStyles = StyleSheet.create({
	textPos: {
		position: "absolute",
		justifyContent: "center",
		alignItems: "center",
	},
	rtl: {
		flexDirection: "row-reverse",
	},
	ltr: {
		flexDirection: "row",
	},
});

export default SwitchButton;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions