Skip to content

Instantly share code, notes, and snippets.

@asci
Created December 5, 2018 18:34
Show Gist options
  • Save asci/0e8dacad526c51b6de4dfc080eceadee to your computer and use it in GitHub Desktop.
Save asci/0e8dacad526c51b6de4dfc080eceadee to your computer and use it in GitHub Desktop.
Random Number component for Framer X
import * as React from "react";
import { PropertyControls, ControlType } from "framer";
import { FontWeightProperty, TextAlignProperty } from "csstype";
type FontWeight =
| "normal"
| "bold"
| "lighter"
| "bolder"
| "100"
| "200"
| "300"
| "400"
| "500"
| "600"
| "700"
| "800"
| "900"
| "1000";
// Define type of property
interface Props {
prefix: string;
color: string;
postfix: string;
precision: number;
min: number;
max: number;
updates: number;
round: boolean;
withTarget: boolean;
width: number;
height: number;
fontFamily: string;
textAlign: string;
fontWeight: FontWeight;
fontSize: number;
target: number;
belowTargetColor: string;
}
export class Nums extends React.Component<Props, { value: number }> {
static defaultProps = {
color: "#0055FF",
belowTargetColor: "#FF5500",
target: 50,
prefix: "",
postfix: "",
max: 100,
width: 36,
height: 16,
min: 0,
round: false,
withTarget: false,
precision: 2,
updates: 10000,
fontFamily: "'Helvetica', sans-serif",
fontWeight: "bold",
textAlign: "right",
fontSize: 14
};
// Items shown in property panel
static propertyControls: PropertyControls = {
textAlign: {
type: ControlType.SegmentedEnum,
title: "Align",
options: ["left", "center", "right"],
optionTitles: ["L", "C", "R"]
},
fontWeight: {
type: ControlType.Enum,
title: "Font Weight",
options: [
"normal",
"bold",
"lighter",
"bolder",
"100",
"200",
"300",
"400",
"500",
"600",
"700",
"800",
"900",
"1000"
],
optionTitles: [
"Normal",
"Bold",
"Lighter",
"Bolder",
"100",
"200",
"300",
"400",
"500",
"600",
"700",
"800",
"900",
"1000"
]
},
fontSize: {
type: ControlType.Number,
title: "Font Size",
min: 4,
max: 300
},
prefix: { type: ControlType.String, title: "Prefix" },
postfix: { type: ControlType.String, title: "Postfix" },
color: { type: ControlType.Color, title: "Color" },
withTarget: { type: ControlType.Boolean, title: "With Target" },
belowTargetColor: {
type: ControlType.Color,
title: "Below Target",
hidden(props) {
return !props.withTarget;
}
},
target: {
type: ControlType.Number,
title: "Target",
min: -10000000,
max: 10000000,
hidden(props) {
return !props.withTarget;
}
},
round: { type: ControlType.Boolean, title: "Round" },
precision: {
type: ControlType.Number,
title: "Float Digits",
max: 8,
min: 1,
hidden(props) {
return props.round;
}
},
min: {
type: ControlType.Number,
title: "Min",
min: -10000000,
max: 10000000
},
max: {
type: ControlType.Number,
title: "Max",
max: 10000000,
min: -10000000
},
updates: {
type: ControlType.Number,
title: "Updates",
max: 30000,
step: 100,
min: 0
}
};
interval: number;
constructor(props) {
super(props);
this.state = {
value: this.generateNumber()
};
}
componentDidUpdate(_, prevState) {
if (prevState.value !== this.state.value) return;
this.stop();
this.start();
}
stop() {
if (this.interval) clearInterval(this.interval);
}
start() {
if (this.props.updates > 0) {
this.interval = setInterval(() => {
this.updateNumber();
}, this.props.updates);
}
}
generateNumber() {
const number = +(
Math.random() * (this.props.max - this.props.min) +
this.props.min
).toFixed(this.props.precision);
return this.props.round ? Math.round(number) : number;
}
updateNumber() {
this.setState({
value: this.generateNumber()
});
}
componentDidMount() {
this.start();
}
render() {
const style: React.CSSProperties = {
color:
this.props.withTarget && this.state.value < this.props.target
? this.props.belowTargetColor
: this.props.color,
fontWeight: this.props.fontWeight as FontWeightProperty,
fontFamily: this.props.fontFamily,
textAlign: this.props.textAlign as TextAlignProperty,
fontSize: this.props.fontSize
};
const value = `${this.props.prefix}${this.state.value}${
this.props.postfix
}`;
return <div style={style}>{value}</div>;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment