vue3-countdown
Version:
A simple countdown component for Vue3.x.
84 lines (73 loc) • 2.21 kB
text/typescript
/**
* Utils
*/
interface Unit {
symbol: string
value: number
}
type ResolvedCountdown = Record<string, string | number>
const units: Array<Unit> = [
{ symbol: 'D', value: 24 * 60 * 60 * 1000 },
{ symbol: 'H', value: 60 * 60 * 1000 },
{ symbol: 'm', value: 60 * 1000 },
{ symbol: 's', value: 1000 },
{ symbol: 'S', value: 100 }
]
function replaceAll(source: string, search: string, replace: string | number): string {
const escapeStr = '~' + search
if (source.indexOf(escapeStr) > -1) {
return source
.split(escapeStr)
.map(part => replaceAll(part, search, replace))
.join(escapeStr)
}
return source.replace(new RegExp(search, 'g'), String(replace))
}
// Decompose time into time units
export function resolveCountdown(
countdown: number,
format = 'HH:mm:ss'
): ResolvedCountdown {
const res: ResolvedCountdown = {}
if (format.indexOf('~') > -1) {
format = format.replace(/~[DHmsS]/g, '')
}
const thisUnits = units.filter(unit => format.indexOf(unit.symbol) > -1)
for (let i = 0, l = thisUnits.length; i < l; i++) {
const { symbol, value } = thisUnits[i]
// Use ceil method when only unit
const unitValue = (
l === 1
? Math.ceil(countdown / value)
: Math.floor(countdown / value)
)
res[symbol] = unitValue
res[symbol + symbol] = unitValue < 10 ? `0${unitValue}` : unitValue
countdown %= value
}
return res
}
// Format countdown
export function formatCountdown (
countdown: number | ResolvedCountdown,
format = 'HH:mm:ss'
): string {
// Check whether resolved
const time = (
typeof countdown === 'number'
? resolveCountdown(countdown, format)
: countdown
)
// Sort the keys from long to short to replace long placeholders first
// to prevent long placeholders from being replaced by short ones
const keys = Object.keys(time).sort((a, b) => b.length - a.length)
let rs = format
keys.forEach(key => {
rs = replaceAll(rs, key, time[key] as string)
})
// Remove escape char
if (rs.indexOf('~') > -1) {
rs = rs.replace(/~([DHmsS])/g, '$1')
}
return rs
}