generated from chiffre-io/template-library
-
-
Notifications
You must be signed in to change notification settings - Fork 161
/
Copy pathcountdown.tsx
99 lines (92 loc) · 2.67 KB
/
countdown.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
'use client'
import NumberFlow, { NumberFlowGroup } from '@number-flow/react'
import { ComponentProps, ReactNode, useEffect, useState } from 'react'
import { cn } from '../lib/utils'
type CountdownProps = ComponentProps<'div'> & {
targetDate: Date
expiredMessage?: ReactNode
}
export function Countdown({
targetDate,
expiredMessage = null,
className,
...props
}: CountdownProps) {
const remaining = targetDate.getTime() - Date.now()
const [days, setDays] = useState(() =>
Math.floor(remaining / 1000 / 60 / 60 / 24)
)
const [hours, setHours] = useState(
() => Math.floor(remaining / 1000 / 60 / 60) % 24
)
const [minutes, setMinutes] = useState(
() => Math.floor(remaining / 1000 / 60) % 60
)
const [seconds, setSeconds] = useState(() =>
Math.floor((remaining / 1000) % 60)
)
useEffect(() => {
const timer = setInterval(() => {
const remaining = targetDate.getTime() - Date.now()
setDays(Math.floor(remaining / 1000 / 60 / 60 / 24))
setHours(Math.floor(remaining / 1000 / 60 / 60) % 24)
setMinutes(Math.floor(remaining / 1000 / 60) % 60)
setSeconds(Math.floor((remaining / 1000) % 60))
if (remaining <= 0) {
clearInterval(timer)
}
}, 500)
return () => clearInterval(timer)
}, [targetDate])
if (days <= 0 && hours <= 0 && minutes <= 0 && seconds <= 0) {
return expiredMessage
}
return (
<div
className={cn(
'flex items-baseline justify-center font-bold',
days > 0 ? 'gap-1 text-xl' : 'text-3xl',
className
)}
title={targetDate.toISOString()}
{...props}
>
<NumberFlowGroup>
{days > 0 && (
<NumberFlow
trend={-1}
value={days}
className="&::part(suffix):text-gray-400 tabular-nums"
suffix="d"
/>
)}
<NumberFlow
trend={-1}
value={hours}
className={'tabular-nums'}
suffix={days > 0 ? 'h' : undefined}
digits={{ 1: { max: 2 } }}
format={{ minimumIntegerDigits: 2 }}
/>
<NumberFlow
trend={-1}
value={minutes}
className="tabular-nums"
prefix={days > 0 ? undefined : ':'}
suffix={days > 0 ? 'm' : undefined}
digits={{ 1: { max: 5 } }}
format={{ minimumIntegerDigits: 2 }}
/>
<NumberFlow
trend={-1}
value={seconds}
className="tabular-nums"
prefix={days > 0 ? undefined : ':'}
suffix={days > 0 ? 's' : undefined}
digits={{ 1: { max: 5 } }}
format={{ minimumIntegerDigits: 2 }}
/>
</NumberFlowGroup>
</div>
)
}