Skip to content
Destyler UI Destyler UI Destyler UI

Timer

The timer machine is used to record the time elapsed from zero or since a specified target time.

20
00
00
01
20
00
00
01
20
00
00
01
20
00
00
01

Features

Install

Install the component from your command line.

Terminal window
      
        
npm install @destyler/timer @destyler/vue
Terminal window
      
        
npm install @destyler/timer @destyler/react
Terminal window
      
        
npm install @destyler/timer @destyler/svelte
Terminal window
      
        
npm install @destyler/timer @destyler/solid

Anatomy

Import all parts and piece them together.

<script setup lang="ts">
import * as timer from '@destyler/timer'
import { normalizeProps, useMachine } from '@destyler/vue'
import { computed, useId } from 'vue'
const [state, send] = useMachine(
timer.machine({
id: useId(),
countdown: true,
autoStart: true,
startMs: timer.parse({ days: 20, seconds: 1 }),
}),
)
const api = computed(() => timer.connect(state.value, send, normalizeProps))
</script>
<template>
<div v-bind="api.getRootProps()">
<div v-bind="api.getAreaProps()" >
<div v-bind="api.getItemProps({ type: 'days' })" >
{{ api.formattedTime.days }}
</div>
<div v-bind="api.getSeparatorProps()" >
:
</div>
<div v-bind="api.getItemProps({ type: 'hours' })" >
{{ api.formattedTime.hours }}
</div>
<div v-bind="api.getSeparatorProps()" >
:
</div>
<div v-bind="api.getItemProps({ type: 'minutes' })" >
{{ api.formattedTime.minutes }}
</div>
<div v-bind="api.getSeparatorProps()" >
:
</div>
<div v-bind="api.getItemProps({ type: 'seconds' })" >
{{ api.formattedTime.seconds }}
</div>
</div>
<div v-bind="api.getControlProps()">
<button v-bind="api.getActionTriggerProps({ action: 'start' })">
Start
</button>
<button v-bind="api.getActionTriggerProps({ action: 'pause' })">
Pause
</button>
<button v-bind="api.getActionTriggerProps({ action: 'resume' })">
Resume
</button>
<button v-bind="api.getActionTriggerProps({ action: 'reset' })">
Reset
</button>
</div>
</div>
</template>
import { normalizeProps, useMachine } from '@destyler/react'
import * as timer from '@destyler/timer'
import { useId } from 'react'
export default function Timer() {
const [state, send] = useMachine(
timer.machine({
id: useId(),
countdown: true,
autoStart: true,
startMs: timer.parse({ days: 20, seconds: 1 }),
}),
)
const api = timer.connect(state, send, normalizeProps)
return (
<>
<div {...api.getRootProps()}>
<div {...api.getAreaProps()} >
<div {...api.getItemProps({ type: 'days' })} >
{api.formattedTime.days}
</div>
<div {...api.getSeparatorProps()} >
:
</div>
<div {...api.getItemProps({ type: 'hours' })} >
{api.formattedTime.hours}
</div>
<div {...api.getSeparatorProps()} >
:
</div>
<div {...api.getItemProps({ type: 'minutes' })} >
{api.formattedTime.minutes}
</div>
<div {...api.getSeparatorProps()} >
:
</div>
<div {...api.getItemProps({ type: 'seconds' })} >
{api.formattedTime.seconds}
</div>
</div>
<div {...api.getControlProps()}>
<button {...api.getActionTriggerProps({ action: "start" })}>
Start
</button>
<button {...api.getActionTriggerProps({ action: "pause" })}>
Pause
</button>
<button {...api.getActionTriggerProps({ action: "resume" })}>
Resume
</button>
<button {...api.getActionTriggerProps({ action: "reset" })}>
Reset
</button>
</div>
</div>
</>
)
}
<script lang="ts">
import * as timer from '@destyler/timer'
import { normalizeProps, useMachine } from '@destyler/svelte'
const id = $props.id()
const [state, send] = useMachine(
timer.machine({
id,
countdown: true,
autoStart: true,
startMs: timer.parse({ days: 20, seconds: 1 }),
})
)
const api = $derived(timer.connect(state, send, normalizeProps))
</script>
<div {...api.getRootProps()} >
<div {...api.getAreaProps()} >
<div {...api.getItemProps({ type: 'days' })} >
{api.formattedTime.days}
</div>
<div {...api.getSeparatorProps()} >
:
</div>
<div {...api.getItemProps({ type: 'hours' })} >
{api.formattedTime.hours}
</div>
<div {...api.getSeparatorProps()} >
:
</div>
<div {...api.getItemProps({ type: 'minutes' })} >
{api.formattedTime.minutes}
</div>
<div {...api.getSeparatorProps()} >
:
</div>
<div {...api.getItemProps({ type: 'seconds' })} >
{api.formattedTime.seconds}
</div>
</div>
<div {...api.getControlProps()}>
<button {...api.getActionTriggerProps({ action: "start" })}>
Start
</button>
<button {...api.getActionTriggerProps({ action: "pause" })}>
Pause
</button>
<button {...api.getActionTriggerProps({ action: "resume" })}>
Resume
</button>
<button {...api.getActionTriggerProps({ action: "reset" })}>
Reset
</button>
</div>
</div>
/** @jsxImportSource solid-js */
import { normalizeProps, useMachine } from '@destyler/solid'
import * as timer from '@destyler/timer'
import { createMemo, createUniqueId } from 'solid-js'
export default function Timer() {
const [state, send] = useMachine(
timer.machine({
id: createUniqueId(),
countdown: true,
autoStart: true,
startMs: timer.parse({ days: 20, seconds: 1 }),
}),
)
const api = createMemo(() => timer.connect(state, send, normalizeProps))
return (
<>
<div {...api().getRootProps()} >
<div {...api().getAreaProps()}>
<div {...api().getItemProps({ type: 'days' })} >
{api().formattedTime.days}
</div>
<div {...api().getSeparatorProps()} >
:
</div>
<div {...api().getItemProps({ type: 'hours' })} >
{api().formattedTime.hours}
</div>
<div {...api().getSeparatorProps()} >
:
</div>
<div {...api().getItemProps({ type: 'minutes' })} >
{api().formattedTime.minutes}
</div>
<div {...api().getSeparatorProps()} >
:
</div>
<div {...api().getItemProps({ type: 'seconds' })} >
{api().formattedTime.seconds}
</div>
</div>
<div {...api().getControlProps()}>
<button {...api().getActionTriggerProps({ action: "start" })}>
Start
</button>
<button {...api().getActionTriggerProps({ action: "pause" })}>
Pause
</button>
<button {...api().getActionTriggerProps({ action: "resume" })}>
Resume
</button>
<button {...api().getActionTriggerProps({ action: "reset" })}>
Reset
</button>
</div>
</div>
</>
)
}

Setting the start value

Set the startMs property to the timer machine’s context to set the start time in milliseconds.

const [state, send] = useMachine(
timer.machine({
startMs: 1000 * 60 * 60, // 1 hour
}),
)

Alternatively, you can also use the timer.parse function to convert a date time string or object into milliseconds

const [state, send] = useMachine(
timer.machine({
startMs: timer.parse("2021-01-01T12:00:00Z"),
// startMs: timer.parse({ hours: 12, minutes: 0, seconds: 0 }),
}),
)

Auto starting the timer

Set the autoStart property to true in the timer machine’s context to start the timer automatically when the component mounts.

const [state, send] = useMachine(
timer.machine({
autoStart: true,
}),
)

Usage as countdown timer

To use the timer as a countdown timer, set the countdown property to true in the timer machine’s context.

const [state, send] = useMachine(
timer.machine({
countdown: true,
}),
)

Setting the target value

To set the target value of the countdown timer, pass the targetMs property in the timer machine’s context. The timer stops automatically when the targetMs is reached.

When targetMs is set and countdown=true, the timer ticks down to zero from the specified target time.

const [state, send] = useMachine(
timer.machine({
countdown: true,
targetMs: 1000 * 60 * 60, // 1 hour
}),
)

When targetMs is set and countdown=false, the timer ticks up to the specified target time.

const [state, send] = useMachine(
timer.machine({
targetMs: 1000 * 60 * 60, // 1 hour
}),
)

Setting the tick interval

Set the interval property to the timer machine’s context to set the tick interval in milliseconds.

const [state, send] = useMachine(
timer.machine({
interval: 1000, // 1 second
}),
)

Listening to tick events

When the timer ticks, the onTick callback is invoke. You can listen to this event and update your UI accordingly.

const [state, send] = useMachine(
timer.machine({
onTick(details) {
// details => { value, segments }
console.log(details)
},
}),
)

Listening for completion events

When the timer reaches the target time, the onComplete callback is invoked.

const [state, send] = useMachine(
timer.machine({
countdown: true,
targetMs: 1000 * 60 * 60, // 1 hour
onComplete() {
console.log("Timer completed")
},
}),
)

Starting and Stopping the timer

To start the timer, send the api.start() callback

api.start()

To stop the timer, send the api.stop() callback

api.stop()

Pausing and Resuming the timer

To pause the timer, send the api.pause() callback

api.pause()

To resume the timer, send the api.resume() callback

api.resume()

Methods and Properties

Machine Context

The timer machine exposes the following context properties:

ids
Partial<{ root: string; area: string; }>
The ids of the timer parts
countdown
boolean
Whether the timer should countdown, decrementing the timer on each tick.
startMs
number
The total duration of the timer in milliseconds.
targetMs
number
The minimum count of the timer in milliseconds.
autoStart
boolean
Whether the timer should start automatically
interval
number
The interval in milliseconds to update the timer count.
onTick
(details: TickDetails) => void
Function invoked when the timer ticks
onComplete
() => void
Function invoked when the timer is completed
id
string
The unique identifier of the machine.
getRootNode
() => ShadowRoot | Node | Document
A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.

Machine API

The timer api exposes the following methods:

running
boolean
Whether the timer is running.
paused
boolean
Whether the timer is paused.
time
Time<number>
The formatted timer count value.
formattedTime
Time<string>
The formatted time parts of the timer count.
start
() => void
Function to start the timer.
pause
() => void
Function to pause the timer.
resume
() => void
Function to resume the timer.
reset
() => void
Function to reset the timer.
restart
() => void
Function to restart the timer.
progressPercent
number
The progress percentage of the timer.