Mixins / foldkit-mixins-ui

Timer

namespace · packages/mixins-ui/src/timer.ts:1

export * as Timer from './timer.js'

In the guides

Members

Timer.Action

const · packages/mixins-ui/src/timer.ts:49

const Action: Schema.Literals<
  readonly ['start', 'pause', 'resume', 'reset', 'restart']
>

Timer.init

function · packages/mixins-ui/src/timer.ts:77

function init(
  options: {
    readonly id: string
    readonly interval?: number | undefined
  } & (
    | {
        readonly countdown: true
        readonly duration: number
      }
    | {
        readonly countdown?: false | undefined
        readonly duration?: number | undefined
      }
  ),
): Model

A countdown from duration milliseconds, or a stopwatch (to duration, if given).

Timer.Message

const · packages/mixins-ui/src/timer.ts:92

const Message: MessageUnion<{
  readonly Pressed: {
    readonly action: Schema.Literals<
      readonly ['start', 'pause', 'resume', 'reset', 'restart']
    >
  }
  readonly Acted: {
    readonly action: Schema.Literals<
      readonly ['start', 'pause', 'resume', 'reset', 'restart']
    >
    readonly at: Schema.Number
  }
  readonly Ticked: { readonly turn: Schema.Number; readonly at: Schema.Number }
}>

Timer.Model

const · packages/mixins-ui/src/timer.ts:52

const Model: Schema.Struct<{
  readonly id: Schema.String
  readonly countdown: Schema.Boolean
  readonly duration: Schema.OptionFromNullOr<Schema.Number>
  readonly interval: Schema.Number
  readonly elapsed: Schema.Number
  readonly since: Schema.OptionFromNullOr<Schema.Number>
  readonly turn: Schema.Number
}>

Timer.partsOf

function · packages/mixins-ui/src/timer.ts:244

function partsOf(
  milliseconds: number,
  units: ReadonlyArray<Unit>,
  up?: boolean,
): ReadonlyArray<TimePart>

milliseconds in units, largest first: the largest holds what a larger unit left out would (90 minutes with no hours), and the smallest is rounded up when up (a countdown shows 1 second until the last one has run out).

Timer.Phase

const · packages/mixins-ui/src/timer.ts:102

const Phase: Schema.Literals<readonly ['idle', 'running', 'paused', 'done']>

Timer.phase

function · packages/mixins-ui/src/timer.ts:109

function phase(model: Model): Phase

Where the timer is: never started (or reset), counting, held, or at its duration.

Timer.shown

function · packages/mixins-ui/src/timer.ts:116

function shown(model: Model): number

The milliseconds the display shows: those left of a countdown, those counted of a stopwatch.

Timer.Stamp

const · packages/mixins-ui/src/timer.ts:122

const Stamp: Command.CommandDefinitionWithArgs<
  'Timer.Stamp',
  {
    action: Schema.Literals<
      readonly ['start', 'pause', 'resume', 'reset', 'restart']
    >
  },
  Effect.Effect<
    {
      readonly _tag: 'Acted'
      readonly action: 'reset' | 'start' | 'pause' | 'resume' | 'restart'
      readonly at: number
    },
    never,
    never
  >
>

Reads the clock for a press, so the time counted is the clock's from the moment it acts.

Timer.Tick

const · packages/mixins-ui/src/timer.ts:130

const Tick: Command.CommandDefinitionWithArgs<
  'Timer.Tick',
  { turn: Schema.Number; milliseconds: Schema.Number },
  Effect.Effect<
    { readonly _tag: 'Ticked'; readonly turn: number; readonly at: number },
    never,
    never
  >
>

Waits milliseconds, then says the clock's time for turn.

Timer.TimePart

interface · packages/mixins-ui/src/timer.ts:232

interface TimePart {
  readonly unit: Unit
  readonly value: number
  readonly text: string
}

Timer.TimerLabels

interface · packages/mixins-ui/src/timer.ts:262

interface TimerLabels {
  readonly start: string
  readonly pause: string
  readonly resume: string
  readonly reset: string
  readonly restart: string
}

The words a timer's presses say; each has an English default.

Timer.TimerSlots

const · packages/mixins-ui/src/timer.ts:32

const TimerSlots: Slots.Contract<{ readonly root: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly [Attr.AttrToken<"role">], readonly Slot.RequirementName[], boolean>; readonly label: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly area: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly [Attr.AttrToken<"role">], readonly Slot.RequirementName[], boolean>; readonly item: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly separator: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly controls: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<" …;

A timer after Zag's: a countdown from a duration, or a stopwatch counting up (to a duration if it has one), with start, pause, resume, reset and restart. The display is role="timer", its items the hours, minutes and seconds (or the units asked for), each in a Slot of its own.

button -> Pressed -> Stamp (reads the clock) -> Acted -> elapsed, since
                           Tick (waits, reads the clock) -> Ticked -> elapsed

The time counted is this Model, which the application keeps and folds with update; nothing ticks outside it. A press reads the clock in a Command before it acts, and each tick is a Command that waits for the display's next change and reads the clock again, so the time counted is the clock's, however late a tick lands, and a pause keeps every millisecond. The clock is Effect's, so a test drives a whole run with TestClock. Each start counts a new turn, and a tick of an older one is dropped.

The root carries data-state (idle, running, paused, done) and, with a duration, --fk-timer-progress: 0 to 1 of it counted.

Timer.TimerView

interface · packages/mixins-ui/src/timer.ts:278

interface TimerView<Message> {
  readonly model: Model
  readonly onMessage: (message: typeof Message.Type) => NoInfer<Message>
  readonly label: string
  readonly units?: ReadonlyArray<Unit> | undefined
  readonly separator?: string | undefined
  readonly controls?: boolean | undefined
  readonly labels?: Partial<TimerLabels> | undefined
  readonly style?: NamedStyle<typeof TimerSlots> | undefined
  readonly mixins?: MixinList<Message> | undefined
}

Timer.Unit

const · packages/mixins-ui/src/timer.ts:220

const Unit: Schema.Literals<
  readonly ['days', 'hours', 'minutes', 'seconds', 'milliseconds']
>

Timer.update

function · packages/mixins-ui/src/timer.ts:200

function update(model: Model, message: Message): Return<Model, Message>

The timer after message; the same Model when nothing changes.

Timer.view

function · packages/mixins-ui/src/timer.ts:305

function view<Outer>(options: TimerView<Outer>, h: HtmlBuilder<Outer>): Html