Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
4.3 kB · 180 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181import { Text, zero } from "@streamplace/components";import { fontFamilies } from "@streamplace/components/src/lib/theme/tokens";import * as chrono from "chrono-node";import { useEffect, useState } from "react";import { View, useWindowDimensions } from "react-native";
interface CountdownProps { from?: string; to?: string; small?: boolean;}
interface LabelBoxProps { children: React.ReactNode; small?: boolean;}
const LabelBox = ({ children, small }: LabelBoxProps) => { return ( <View style={[ { borderColor: "white", borderWidth: 0, borderTopWidth: small ? 2 : 4, borderStyle: "solid", }, ]} > <Text style={[ small ? { fontSize: 18 } : { fontSize: 24 }, small ? { lineHeight: 24 } : { lineHeight: 28 }, ]} > {children} </Text> </View> );};
export function Countdown({ from, to, small }: CountdownProps) { const [now, setNow] = useState(Date.now()); const [dest, setDest] = useState<number | null>(null); const { width, height } = useWindowDimensions();
useEffect(() => { if (from) { const fromDate = chrono.parseDate(from); if (fromDate === null) { throw new Error("could not parse from"); } setDest(fromDate.getTime()); } else if (to) { const toDate = chrono.parseDate(to); if (toDate === null) { throw new Error("could not parse to"); } setDest(toDate.getTime()); } else { throw new Error("must provide either from or to"); } }, [from, to]);
useEffect(() => { const tick = () => { if (!running) { return; } requestAnimationFrame(tick); setNow(Date.now()); }; let running = true; tick(); return () => { running = false; }; }, []);
if (dest === null) { return <View />; }
let diff = Math.abs(dest - now); if (to && now > dest) { diff = 0; } else if (from && now < dest) { diff = 0; } small = small ?? width <= 600; const [years, days, hrs, min, sec, ms] = toLabels(diff);
const unitStyle = [ zero.mx[small ? 2 : 4], zero.flex.values[0], { flexDirection: "column" }, ];
const timeTextStyle = [ { fontFamily: fontFamilies.monoRegular }, small ? { fontSize: 18 } : { fontSize: 128 }, small ? { lineHeight: 24 } : { lineHeight: 40 }, ];
return ( <View style={[ { flexDirection: "row" }, { alignSelf: small ? "auto" : "center" }, ]} > <View style={[{ flexDirection: "row" }, { justifyContent: "flex-end" }]}> <View style={unitStyle}> <Text style={timeTextStyle}>{years}</Text> <LabelBox small={small}>YEARS</LabelBox> </View> <View style={unitStyle}> <Text style={timeTextStyle}>{days}</Text> <LabelBox small={small}>DAYS</LabelBox> </View> <View style={unitStyle}> <Text style={timeTextStyle}>{hrs}</Text> <LabelBox small={small}>HRS</LabelBox> </View> </View> <View style={[{ flexDirection: "row" }, { justifyContent: "flex-end" }]}> <View style={unitStyle}> <Text style={timeTextStyle}>{min}</Text> <LabelBox small={small}>MIN</LabelBox> </View> <View style={unitStyle}> <Text style={timeTextStyle}>{sec}</Text> <LabelBox small={small}>SEC</LabelBox> </View> <View style={unitStyle}> <Text style={timeTextStyle}>{ms}</Text> <LabelBox small={small}>MS</LabelBox> </View> </View> </View> );}
const toLabels = ( now: number,): [string, string, string, string, string, string] => { const ms = now % 1000; now = Math.floor(now / 1000);
const sec = now % 60; now = Math.floor(now / 60);
const min = now % 60; now = Math.floor(now / 60);
const hrs = now % 24; now = Math.floor(now / 24);
const days = now % 365; now = Math.floor(now / 365);
const years = now;
return [ pad(years, 4), pad(days, 3), pad(hrs, 2), pad(min, 2), pad(sec, 2), pad(ms, 3), ];};
const pad = (num: number, n: number): string => { let str = `${num}`; while (str.length < n) { str = "0" + str; } return str;};