Primitives / Time
Start with one: a timer
ts
import { Schema } from 'effect'
import type { HtmlBuilder } from 'foldkit/html'
import { Bundle } from 'foldkit-bundle'
import { Timer, TimerMessage } from 'foldkit-primitives/time'
const Page = Bundle.compose({}).pipe(
Bundle.withChild('ticks', Timer, { args: { intervalMs: 1000 } }),
)
type Model = typeof Page.Model.Type
type Message = typeof Page.Message.Type
const { placements } = Page
const config = placements.complete({
init: () => placements.initial({}),
update: placements.update(model => ({ model })),
view: (model: Model, h: HtmlBuilder<Message>) =>
h.button(
[h.OnClick(Page.Message.GotTicksMessage({ message: TimerMessage.Started() }))],
[String(model.ticks.count)],
),
subscriptions: placements.subscriptions(),
})A timer starts stopped, and its stream is empty while stopped. Started runs
it; the first tick comes one interval later, and only Ticked advances the
count. Stopped pauses without resetting. An interval that is not positive
and finite is rejected at placement.
Interval is the wall-clock sibling: Ticked { at } is stamped from Effect's
clock and lastAt keeps it, for a view that renders a clock or an elapsed
time. Timer counts, Interval records when.