tooltip-timing.dhover×978all
#!/usr/bin/env dub
/+ dub.sdl:
    name "anchored_overlays_tooltip_timing"
    targetPath "build"
    dependency "sparkles:base" path="../../../.."
    dependency "sparkles:ui" path="../../../.."
    dflags "-preview=in" "-preview=dip1000"
    buildType "checked" {
        buildOptions "optimize" "inline" "debugInfo"
    }
+/
/**
 * The tooltip warm-up / cool-down machine, **composed from `Timeline` (`STM6`)**
 * and stepped over a scripted event list.
 *
 * Nine subjects in the survey implement the behaviour the field converged on —
 * the *first* tooltip in a group pays a warm-up delay, a *subsequent* one appears
 * instantly while the group is still warm, and the group goes cold again after a
 * cool-down (WPF's `BetweenShowDelay`, React Aria's `globalWarmedUp` +
 * `TOOLTIP_COOLDOWN`, Radix's `skipDelayDuration`, Ariakit's `skipTimeout`,
 * Base UI's `FloatingDelayGroup`, Qt, GTK, WinUI, Avalonia). They also converged
 * on its *shape*: **one shared arbiter holding two integers, with no per-widget
 * timer state.** This program is that machine, built the way `PRN8` demands —
 * the clock is the toolkit's existing $(REF Timeline, sparkles,ui,state), not a
 * second hand-rolled timer:
 *
 *   * `Timeline.Phase.fadeIn` **is** `warming` (the arm-to-deadline interval),
 *   * `Timeline.Phase.hold` **is** `shown`, pinned `holdUntilDismissed`,
 *   * the only genuinely new state is `DwellGroup` — `openId` plus one integer.
 *
 * Section 2 shows the three seams where `STM6`'s own semantics do *not* line up
 * with a warm-up, each demonstrated by running it: `visible()` is already true
 * in `fadeIn`, `dismissed()` from `fadeIn` plays a full-opacity fade-out, and a
 * backend with no frame clock never advances `stepped` at all. Composing
 * `Timeline` therefore means using it as the **counter**, and deriving
 * visibility from `phase == hold` rather than from `visible()`.
 *
 * The trace tables are the demonstration. The same scripted event list is run
 * through three targets, so the collapses are visible as *divergence in one
 * column* rather than as prose:
 *
 *   1. a pointer target (the full machine),
 *   2. a touch target — `caps.hover == false`, where the hover trigger is
 *      substituted rather than degraded,
 *   3. tier-0 static HTML — no script, **no timers at all**, where the warm-up
 *      survives as `transition-delay` and the group behaviour is honestly absent.
 *
 * Companion to [../proposal.md](../proposal.md) § 4.1 "Tooltip" and § 4.5
 * "The one genuinely new machine, and its `PRN8` justification"; the field
 * evidence it implements is in [../comparison.md](../comparison.md), dimension 6.
 *
 * Run with: dub run --single tooltip-timing.d
 *
 * Portability: pure computation over an injected `dtMs` — no clock, no display,
 * no terminal. Deterministic everywhere.
 */
module 
(module) anchored_overlays_tooltip_timing

The tooltip warm-up / cool-down machine, composed from Timeline (STM6) and stepped over a scripted event list.

Nine subjects in the survey implement the behaviour the field converged on — the first tooltip in a group pays a warm-up delay, a subsequent one appears instantly while the group is still warm, and the group goes cold again after a cool-down (WPF's BetweenShowDelay, React Aria's globalWarmedUp + TOOLTIP_COOLDOWN, Radix's skipDelayDuration, Ariakit's skipTimeout, Base UI's FloatingDelayGroup, Qt, GTK, WinUI, Avalonia). They also converged on its shape: one shared arbiter holding two integers, with no per-widget timer state. This program is that machine, built the way PRN8 demands — the clock is the toolkit's existing Timeline, not a second hand-rolled timer:

  • Timeline.Phase.fadeIn is warming (the arm-to-deadline interval),

  • Timeline.Phase.hold is shown, pinned holdUntilDismissed,

  • the only genuinely new state is DwellGroupopenId plus one integer.

Section 2 shows the three seams where STM6's own semantics do not line up with a warm-up, each demonstrated by running it: visible() is already true in fadeIn, dismissed() from fadeIn plays a full-opacity fade-out, and a backend with no frame clock never advances stepped at all. Composing Timeline therefore means using it as the counter, and deriving visibility from phase == hold rather than from visible().

The trace tables are the demonstration. The same scripted event list is run through three targets, so the collapses are visible as divergence in one column rather than as prose:

  1. a pointer target (the full machine),

  2. a touch target — caps.hover == false, where the hover trigger is substituted rather than degraded,

  3. tier-0 static HTML — no script, no timers at all, where the warm-up survives as transition-delay and the group behaviour is honestly absent.

Companion to ../proposal.md § 4.1 "Tooltip" and § 4.5 "The one genuinely new machine, and its PRN8 justification"; the field evidence it implements is in ../comparison.md, dimension 6.

Run with: dub run --single tooltip-timing.d

Portability

pure computation over an injected dtMs — no clock, no display, no terminal. Deterministic everywhere.

anchored_overlays_tooltip_timing
;
import
(package) std
std
.
(package) std.range
range
.
(module) std.range.primitives

This module is a submodule of std.range.

It defines the bidirectional and forward range primitives for arrays: empty, front, back, popFront, popBack and save.

It provides basic range functionality by defining several templates for testing whether a given object is a range, and what kind of range it is:

| isInputRange | Tests if something is an input range, defined to be something from which one can sequentially read data using the primitives front, popFront, and empty. | | isOutputRange | Tests if something is an output range, defined to be something to which one can sequentially write data using the put primitive. | | isForwardRange | Tests if something is a forward range, defined to be an input range with the additional capability that one can save one's current position with the save primitive, thus allowing one to iterate over the same range multiple times. | | isBidirectionalRange | Tests if something is a bidirectional range, that is, a forward range that allows reverse traversal using the primitives back and popBack. | | isRandomAccessRange | Tests if something is a random access range, which is a bidirectional range that also supports the array subscripting operation via the primitive opIndex. |

It also provides number of templates that test for various range capabilities:

| hasMobileElements | Tests if a given range's elements can be moved around using the primitives moveFront, moveBack, or moveAt. | | ElementType | Returns the element type of a given range. | | ElementEncodingType | Returns the encoding element type of a given range. | | hasSwappableElements | Tests if a range is a forward range with swappable elements. | | hasAssignableElements | Tests if a range is a forward range with mutable elements. | | hasLvalueElements | Tests if a range is a forward range with elements that can be passed by reference and have their address taken. | | hasLength | Tests if a given range has the length attribute. | | isInfinite | Tests if a given range is an infinite range. | | hasSlicing | Tests if a given range supports the array slicing operation R[x .. y]. |

Finally, it includes some convenience functions for manipulating ranges:

| popFrontN | Advances a given range by up to n elements. | | popBackN | Advances a given bidirectional range from the right by up to n elements. | | popFrontExactly | Advances a given range by up exactly n elements. | | popBackExactly | Advances a given bidirectional range from the right by exactly n elements. | | moveFront | Removes the front element of a range. | | moveBack | Removes the back element of a bidirectional range. | | moveAt | Removes the i'th element of a random-access range. | | walkLength | Computes the length of any range in O(n) time. | | put | Outputs element e to a range. |

Source

std/range/primitives.d

@licenseBoost License 1.0.@authorsAndrei Alexandrescu, David Simcha, and Jonathan M Davis. Credit for some of the ideas in building this module goes to Leonardo Maffi.
primitives
:
(alias template) anchored_overlays_tooltip_timing.put = std.range.primitives.put(R, E)(ref R r, E e)

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r.put(e) if R defines put, r.front = e if r is an input range (followed by r.popFront()), or r(e) otherwise.

Code Snippet
Scenario

| r.doPut(e); | R specifically accepts an E. |

| r.doPut([ e ]); | R specifically accepts an E[]. |

| r.putChar(e); | R accepts some form of string or character. put will transcode the character e accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r.put(e). Doing this may call R.put directly, by-passing any transformation feature provided by `Range.`put. ``put(r, e) is prefered.

put
;
import
(package) std
std
.
(module) std.stdio
Category Symbols
File handles _popen File isFileHandle openNetwork stderr stdin stdout
Reading chunks lines readf readfln readln
Writing toFile write writef writefln writeln
Misc KeepTerminator LockType StdioException

Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio is publically imported when importing std.stdio.

There are three layers of I/O:

  1. The lowest layer is the operating system layer. The two main schemes are Windows and Posix.

  2. C's stdio.h which unifies the two operating system schemes.

  3. std.stdio, this module, unifies the various stdio.h implementations into a high level package for D programs.

Source

std/stdio.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Alex Rønne Petersen
stdio
:
(alias template) anchored_overlays_tooltip_timing.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

Equivalent to writef(fmt, args, '\n').

writefln
,
(alias template) anchored_overlays_tooltip_timing.writeln = std.stdio.writeln(T...)(T args)

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
;
import
(package) sparkles
sparkles
.
(package) sparkles.base
base
.
(module) sparkles.base.smallbuffer

A @nogc container with Small Buffer Optimization (SBO).

Provides an append-only buffer that stores small amounts of data inline (avoiding heap allocation) and automatically switches to heap storage when capacity is exceeded.

Primary use case: appending elements in a temporary scope where GC allocation is not desired.

smallbuffer
:
(alias struct) anchored_overlays_tooltip_timing.SmallBuffer = sparkles.base.smallbuffer.SmallBuffer(T, ulong N = max(size_t(1), (T[]).sizeof / T.sizeof), bool unique = false)

A @nogc container with Small Buffer Optimization and copy-on-write.

Elements are stored inline up to N elements, then automatically allocated on the heap (via AffixAllocator!(Mallocator, ControlBlock), which keeps the reference count in an allocation prefix; the element capacity is the heap slice length) when capacity is exceeded. Heap blocks are managed with the std.experimental.allocator makeArray/expandArray/dispose helpers.

The buffer is copyable. Copying an inline buffer duplicates its elements (independent copies). Copying a heap buffer shares the allocation and bumps a reference count; the shared block is cloned copy-on-write the first time a mutable copy is written. This suits the common pattern of one producer building a buffer mutably, then handing out many const reader copies — read via const (e.g. through borrow) never clones. Mutating accessors on a shared mutable copy clone first, so a mutable slice/reference taken from a shared buffer and held across a later mutation may be invalidated (the usual copy-on-write caveat) — read through const to share without that risk.

Note

storage location is tied to length (data is inline whenever length <= N), so reserve pre-grows only once on the heap, and clear/popBack that drop the length back to <= N revert to inline storage.

@paramT Element type@paramN Number of elements stored inline. The default fills the slice-sized union exactly (max(1, (T[]).sizeof / T.sizeof)), so the struct stays three words (3 * size_t.sizeof) regardless of T — e.g. 16 for char, 4 for int, 2 for long.@paramunique When true, opt out of the copy-on-write machinery: the buffer becomes move-only (copy construction/assignment are @disabled), so it is a sole owner by construction. Mutation then never reads or bumps a reference count — the append/grow hot path skips the uniqueness check entirely. Hand a finished unique buffer to the shareable copy-on-write world with SmallBuffer`.toShared`, which consumes it and returns a SmallBuffer!(T, N) (heap storage transfers without a reallocation). The default, false, is the ordinary copy-on-write buffer described above.
SmallBuffer
;
import
(package) sparkles
sparkles
.
(package) sparkles.base
base
.
(package) sparkles.base.text
text
.
(module) sparkles.base.text.writers

@nogc-compatible text writing utilities for output ranges.

Provides functions for writing integers, floats, escaped characters/strings, and ANSI escape sequences to output ranges without GC allocation.

writers
:
(alias template) anchored_overlays_tooltip_timing.writeValue = sparkles.base.text.writers.writeValue(Writer, T)(ref Writer w, auto ref const T val)

Writes any value to an output range using best-effort @nogc conversion.

Dispatch order:

  1. bool — writes "true" or "false"

  2. Integral types — uses writeInteger

  3. Floating-point types — uses writeFloat

  4. char — writes the character directly

  5. String/char slices — writes directly via put

  6. User types with @nogc output range toString — calls t.toString(writer)

  7. User types with @nogc sink toString — calls with a forwarding delegate

  8. User types with @nogc toString() returning string — writes the result

  9. User types with @nogc string cast — writes cast(string) t

  10. Fallback — uses std.conv.to!string (GC-allocating)

writeValue
;
import
(package) sparkles
sparkles
.
(module) sparkles.input

sparkles:input`` — the abstract, capability-tiered input vocabulary shared by every sparkles:ui target (docs/specs/ui/input.md).

Interaction is the other half of "one definition, three targets": events are values in one vocabulary (sparkles.input.events), classified into capability tiers (sparkles.input.tier), in a package both the toolkit and the terminal library can depend on (sparkles:base only, plus sparkles:math import-only for the position type). Producers adapt their native input to it — the terminal decodes its wire formats straight into Event; a pixel backend synthesizes events from polled state.

input
:
(struct) sparkles.input.capability.InputCapabilities

A target's declared input affordances.

The defaults describe a mouse: the historical assumption, so a producer that has not thought about this yet keeps today's behavior rather than silently claiming a capability it lacks in the other direction.

Declare with one of the profiles below where one fits — mousePointer, touchPointer, cellPointer, staticPointer — so the vocabulary stays small and two targets that mean the same thing say it the same way.

InputCapabilities
;
import
(package) sparkles
sparkles
.
(package) sparkles.ui
ui
.
(module) sparkles.ui.state

The state level (STM) of sparkles.ui: presentation-free interaction state machines fed the shared sparkles:input events — pure logic over abstract input, producing state and derived geometry in abstract units, with no draw calls and no device units.

Machines are advanced by transformations and are intended to be Regular values. Scalar and immutable-payload machines meet that contract; DisclosureState's exposed slice still needs the ownership/copy policy tracked by UI-O1. They advance as state`.stepped(…) → `state (the caller assigns), never by mutating shared locals — so behavior can be snapshotted, replayed and diffed in tests. And every machine exists once: where behavior was written per backend it diverged (two scrollbar thumb formulas scrolling the same document differently; one copy affordance flashing on a timer while another held until the next event), which is precisely the "correctness does not compose" defect this level removes.

HoverState + hoverTargets — which element is hot (STM4) scrollbarThumb + ScrollState — one thumb formula (STM2) Selection — normalized anchor/focus, no -1 sentinel (STM3) DisclosureState — one opened/closed set for tree expansion and content folding (STM5) Timeline — transient effects as modes, not bare counters (STM6) FocusState — keyboard focus + deterministic traversal (STM7) SplitState — a draggable pane divider (STM8) PressState — press arms, release-over-the-same-target activates (STM10) CaptureState — press owns the drag; one affordance holds the pointer until release (STM11)

state
:
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
;
// --------------------------------------------------------------------------- // Configuration — the numbers live beside the other popup metrics, never inline // --------------------------------------------------------------------------- /** The two durations the whole dimension reduces to. Both belong in `Palette` beside `popupPadX`, exactly as WinUI puts them in the OS and Qt in `QStyle`; they are parameters here so the trace can name them. `skipMs == 0` must **statically disable** warmth rather than arm a zero-length timer — Radix shipped that bug (`#3873`: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. $(LREF DwellConfig.warmthEnabled) is that early return, expressed as a value. */ struct
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
{ int
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
= 500; /// the first tooltip in a cold group waits this long
int
(field) int anchored_overlays_tooltip_timing.DwellConfig.skipMs

the group stays warm this long after one closes

skipMs
= 300; /// the group stays warm this long after one closes
/// Warmth is a *feature*, switched on by a positive skip window. bool
bool anchored_overlays_tooltip_timing.DwellConfig.warmthEnabled() const pure nothrow @nogc @safe

Warmth is a feature, switched on by a positive skip window.

warmthEnabled
() const @safe pure nothrow @nogc =>
(field) int anchored_overlays_tooltip_timing.DwellConfig.skipMs

the group stays warm this long after one closes

skipMs
> 0;
} // --------------------------------------------------------------------------- // The machine: Timeline (STM6) as the clock + a two-integer group arbiter // --------------------------------------------------------------------------- /// The `Timeline` config a dwell arms with. `fadeInMs` is the *resolved* delay /// (0 when the group was warm), and `holdUntilDismissed` is pinned so a /// hover-triggered surface can never self-close — the WCAG 1.4.13 defaults trap /// that `Timeline.Config.holdMs = 1200` sets for an unwary caller.
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(struct) sparkles.ui.state.Timeline.Config

Phase durations. holdUntilDismissed is the event-scoped mode: hold persists until dismissed — a mode, not a magic duration.

Config
sparkles.ui.state.Timeline.Config anchored_overlays_tooltip_timing.lifeCfg(int resolvedDelayMs) pure nothrow @nogc @safe

The Timeline config a dwell arms with. fadeInMs is the resolved delay (0 when the group was warm), and holdUntilDismissed is pinned so a hover-triggered surface can never self-close — the WCAG 1.4.13 defaults trap that Timeline.Config.holdMs = 1200 sets for an unwary caller.

lifeCfg
(int
(parameter) int resolvedDelayMs
resolvedDelayMs
) @safe pure nothrow @nogc
=>
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(struct) sparkles.ui.state.Timeline.Config

Phase durations. holdUntilDismissed is the event-scoped mode: hold persists until dismissed — a mode, not a magic duration.

Config
(fadeInMs:
(parameter) int resolvedDelayMs
resolvedDelayMs
, holdUntilDismissed: true);
/// One tooltip's timing state: a composed `Timeline` plus the anchor it belongs /// to. `armedDelayMs` is stored because the deadline must be **absolute** — /// measured from the arm instant, never recomputed as `now + delay` — which /// `Timeline.stepped` gives for free as long as the config does not change /// under it. struct
(struct) anchored_overlays_tooltip_timing.TooltipDwell

One tooltip's timing state: a composed Timeline plus the anchor it belongs to. armedDelayMs is stored because the deadline must be absolute — measured from the arm instant, never recomputed as now + delay — which Timeline.stepped gives for free as long as the config does not change under it.

TooltipDwell
{
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
; /// `fadeIn` == warming, `hold` == shown
(alias) object.size_t = ulong
size_t
(field) ulong anchored_overlays_tooltip_timing.TooltipDwell.anchorId

0 == no anchor

anchorId
; /// 0 == no anchor
int
(field) int anchored_overlays_tooltip_timing.TooltipDwell.armedDelayMs

the delay resolved at arm time

armedDelayMs
; /// the delay resolved at arm time
@safe pure nothrow @nogc:
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(struct) sparkles.ui.state.Timeline.Config

Phase durations. holdUntilDismissed is the event-scoped mode: hold persists until dismissed — a mode, not a magic duration.

Config
sparkles.ui.state.Timeline.Config anchored_overlays_tooltip_timing.TooltipDwell.cfg() const pure nothrow @nogc @safe
cfg
() const =>
sparkles.ui.state.Timeline.Config anchored_overlays_tooltip_timing.lifeCfg(int resolvedDelayMs) pure nothrow @nogc @safe

The Timeline config a dwell arms with. fadeInMs is the resolved delay (0 when the group was warm), and holdUntilDismissed is pinned so a hover-triggered surface can never self-close — the WCAG 1.4.13 defaults trap that Timeline.Config.holdMs = 1200 sets for an unwary caller.

lifeCfg
(
(field) int anchored_overlays_tooltip_timing.TooltipDwell.armedDelayMs

the delay resolved at arm time

armedDelayMs
);
/// Counting down to the deadline, and **not** in the display or hit list. bool
bool anchored_overlays_tooltip_timing.TooltipDwell.warming() const pure nothrow @nogc @safe

Counting down to the deadline, and not in the display or hit list.

warming
() const =>
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
==
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(enum) sparkles.ui.state.Timeline.Phase

The phase of the effect.

Phase
.
(enum value) sparkles.ui.state.Timeline.Phase.fadeIn = 1

appearing

fadeIn
;
/// Painted. Note this is `phase == hold`, *not* `life.visible()` — see § 2. bool
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
() const =>
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
==
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(enum) sparkles.ui.state.Timeline.Phase

The phase of the effect.

Phase
.
(enum value) sparkles.ui.state.Timeline.Phase.hold = 2

fully visible

hold
;
} /// The whole cross-instance protocol: which anchor owns the open surface, and /// how much warmth is left once it closes. Nine independent lineages converged /// on exactly this much state. With an injected wall clock the second field is /// the absolute `warmUntilMs` the proposal specifies; this driver supplies /// `dtMs` (the shape `Timeline.stepped` already consumes), so it counts down. /// One integer either way. struct
(struct) anchored_overlays_tooltip_timing.DwellGroup

The whole cross-instance protocol: which anchor owns the open surface, and how much warmth is left once it closes. Nine independent lineages converged on exactly this much state. With an injected wall clock the second field is the absolute warmUntilMs the proposal specifies; this driver supplies dtMs (the shape Timeline.stepped already consumes), so it counts down. One integer either way.

DwellGroup
{
(alias) object.size_t = ulong
size_t
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
; /// the anchor currently showing, 0 == none
int
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
; /// > 0 ⇒ the next tooltip in the group opens instantly
} /// A group and its at-most-one live tooltip. One record suffices because /// opening closes every peer (React Aria's `closeOthers`), so a registry of /// per-instance timers — which is not expressible in `@safe pure` value code /// anyway — has nothing left to hold. struct
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
{
(struct) anchored_overlays_tooltip_timing.TooltipDwell

One tooltip's timing state: a composed Timeline plus the anchor it belongs to. armedDelayMs is stored because the deadline must be absolute — measured from the arm instant, never recomputed as now + delay — which Timeline.stepped gives for free as long as the config does not change under it.

TooltipDwell
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
;
(struct) anchored_overlays_tooltip_timing.DwellGroup

The whole cross-instance protocol: which anchor owns the open surface, and how much warmth is left once it closes. Nine independent lineages converged on exactly this much state. With an injected wall clock the second field is the absolute warmUntilMs the proposal specifies; this driver supplies dtMs (the shape Timeline.stepped already consumes), so it counts down. One integer either way.

DwellGroup
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
;
@safe pure nothrow @nogc: bool
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
() const =>
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
;
(alias) object.size_t = ulong
size_t
ulong anchored_overlays_tooltip_timing.Dwell.visibleId() const pure nothrow @nogc @safe
visibleId
() const =>
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
?
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) ulong anchored_overlays_tooltip_timing.TooltipDwell.anchorId

0 == no anchor

anchorId
: 0;
/// `true` while a *subsequent* tooltip would open with no delay. bool
bool anchored_overlays_tooltip_timing.Dwell.warm() const pure nothrow @nogc @safe

true while a subsequent tooltip would open with no delay.

warm
() const =>
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
!= 0 ||
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
> 0;
} /// Post-transition invariant: a shown tooltip **is** the group's open surface, /// and an open surface makes the countdown redundant (React Aria clears the /// pending cool-down on show).
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.settled(in anchored_overlays_tooltip_timing.Dwell s) pure nothrow @nogc @safe

Post-transition invariant: a shown tooltip is the group's open surface, and an open surface makes the countdown redundant (React Aria clears the pending cool-down on show).

settled
(in
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
) @safe pure nothrow @nogc
{
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
=
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
;
if (
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
)
{
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
=
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) ulong anchored_overlays_tooltip_timing.TooltipDwell.anchorId

0 == no anchor

anchorId
;
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
= 0;
} return
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
;
} /// Whatever was live yields the group. /// /// The cool-down is armed **only if something was actually shown** — abandoning /// a hover mid-warm-up leaves the group cold and the next hover pays full price /// (React Aria arms its cool-down inside `if (globalWarmedUp)`). And a cancelled /// warm-up resets to `Timeline.init`, never through `Timeline.dismissed` — § 2.b.
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.closedActive(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Whatever was live yields the group.

The cool-down is armed only if something was actually shown — abandoning a hover mid-warm-up leaves the group cold and the next hover pays full price (React Aria arms its cool-down inside if (globalWarmedUp)). And a cancelled warm-up resets to Timeline.init, never through Timeline.dismissed — § 2.b.

closedActive
(in
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
) @safe pure nothrow @nogc
{
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
=
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
;
const
(local variable) const(bool) wasShown
wasShown
=
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
;
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
=
(struct) anchored_overlays_tooltip_timing.TooltipDwell

One tooltip's timing state: a composed Timeline plus the anchor it belongs to. armedDelayMs is stored because the deadline must be absolute — measured from the arm instant, never recomputed as now + delay — which Timeline.stepped gives for free as long as the config does not change under it.

TooltipDwell
.
(constant) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.TooltipDwell.init = TooltipDwell(Timeline(Phase.idle, 0), 0LU, 0)
init
;
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
= 0;
if (
(local variable) const(bool) wasShown
wasShown
&&
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
.
bool anchored_overlays_tooltip_timing.DwellConfig.warmthEnabled() const pure nothrow @nogc @safe

Warmth is a feature, switched on by a positive skip window.

warmthEnabled
)
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
=
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.skipMs

the group stays warm this long after one closes

skipMs
;
return
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
;
} /// The pointer came to rest on an anchor.
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(in
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
,
(alias) object.size_t = ulong
size_t
(parameter) ulong id
id
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
) @safe pure nothrow @nogc
in (
(parameter) ulong id
id
!= 0, "anchor id 0 means 'no anchor'")
{ // Re-entry on the live anchor is a no-op, not a restart: a `retarget`, never // a close+open, or the surface flashes. if (
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) ulong anchored_overlays_tooltip_timing.TooltipDwell.anchorId

0 == no anchor

anchorId
==
(parameter) ulong id
id
&&
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
!=
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(enum) sparkles.ui.state.Timeline.Phase

The phase of the effect.

Phase
.
(enum value) sparkles.ui.state.Timeline.Phase.idle = cast(ubyte)0u

not showing

idle
)
return
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
;
// Read the group *before* the outgoing surface yields — the swap is instant // because a peer is open, which is the same warmth the cool-down preserves. const
(local variable) const(bool) instant
instant
=
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
.
bool anchored_overlays_tooltip_timing.DwellConfig.warmthEnabled() const pure nothrow @nogc @safe

Warmth is a feature, switched on by a positive skip window.

warmthEnabled
&&
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
.
bool anchored_overlays_tooltip_timing.Dwell.warm() const pure nothrow @nogc @safe

true while a subsequent tooltip would open with no delay.

warm
;
auto
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
=
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.closedActive(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Whatever was live yields the group.

The cool-down is armed only if something was actually shown — abandoning a hover mid-warm-up leaves the group cold and the next hover pays full price (React Aria arms its cool-down inside if (globalWarmedUp)). And a cancelled warm-up resets to Timeline.init, never through Timeline.dismissed — § 2.b.

closedActive
(
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
,
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
);
const
(local variable) const(int) delay
delay
=
(local variable) const(bool) instant
instant
? 0 :
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
;
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
=
(struct) anchored_overlays_tooltip_timing.TooltipDwell

One tooltip's timing state: a composed Timeline plus the anchor it belongs to. armedDelayMs is stored because the deadline must be absolute — measured from the arm instant, never recomputed as now + delay — which Timeline.stepped gives for free as long as the config does not change under it.

TooltipDwell
(
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.triggered(in sparkles.ui.state.Timeline.Config cfg) pure nothrow @nogc @safe

A freshly-triggered effect (restarts if already running).

triggered
(
sparkles.ui.state.Timeline.Config anchored_overlays_tooltip_timing.lifeCfg(int resolvedDelayMs) pure nothrow @nogc @safe

The Timeline config a dwell arms with. fadeInMs is the resolved delay (0 when the group was warm), and holdUntilDismissed is pinned so a hover-triggered surface can never self-close — the WCAG 1.4.13 defaults trap that Timeline.Config.holdMs = 1200 sets for an unwary caller.

lifeCfg
(
(local variable) const(int) delay
delay
)),
(parameter) ulong id
id
,
(local variable) const(int) delay
delay
);
return
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.settled(in anchored_overlays_tooltip_timing.Dwell s) pure nothrow @nogc @safe

Post-transition invariant: a shown tooltip is the group's open surface, and an open surface makes the countdown redundant (React Aria clears the pending cool-down on show).

settled
(
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
);
} /// The pointer left the anchor (and the group's region).
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.left(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer left the anchor (and the group's region).

left
(in
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
) @safe pure nothrow @nogc
=>
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.closedActive(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Whatever was live yields the group.

The cool-down is armed only if something was actually shown — abandoning a hover mid-warm-up leaves the group cold and the next hover pays full price (React Aria arms its cool-down inside if (globalWarmedUp)). And a cancelled warm-up resets to Timeline.init, never through Timeline.dismissed — § 2.b.

closedActive
(
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
,
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
);
/// A press, a key, or a scroll: closes the surface **and clears warmth**. /// /// Nothing in React Aria or Radix clears warmth except its own cool-down, so a /// click or a scroll leaves the next tooltip in instant mode; Ariakit patched /// exactly this symptom on `onBlur`. Warmth is a property of an uninterrupted /// hover context, so the interruption ends it.
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.interrupted(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

A press, a key, or a scroll: closes the surface and clears warmth.

Nothing in React Aria or Radix clears warmth except its own cool-down, so a click or a scroll leaves the next tooltip in instant mode; Ariakit patched exactly this symptom on onBlur. Warmth is a property of an uninterrupted hover context, so the interruption ends it.

interrupted
(in
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
) @safe pure nothrow @nogc
{ auto
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
=
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.closedActive(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Whatever was live yields the group.

The cool-down is armed only if something was actually shown — abandoning a hover mid-warm-up leaves the group cold and the next hover pays full price (React Aria arms its cool-down inside if (globalWarmedUp)). And a cancelled warm-up resets to Timeline.init, never through Timeline.dismissed — § 2.b.

closedActive
(
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
,
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
);
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
= 0;
return
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
;
} /// Advance by `dtMs`. The warm-up elapses inside `Timeline`; the cool-down is /// the one subtraction this machine adds.
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(in
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
, int
(parameter) int dtMs
dtMs
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
) @safe pure nothrow @nogc
{
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
=
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
;
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
=
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
.
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.stepped(int dtMs, in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Advanced by dtMs milliseconds.

stepped
(
(parameter) int dtMs
dtMs
,
(parameter) const(anchored_overlays_tooltip_timing.Dwell) s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
sparkles.ui.state.Timeline.Config anchored_overlays_tooltip_timing.TooltipDwell.cfg() const pure nothrow @nogc @safe
cfg
);
if (!
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
&&
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
== 0)
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
=
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
>
(parameter) int dtMs
dtMs
?
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
-
(parameter) int dtMs
dtMs
: 0;
return
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.settled(in anchored_overlays_tooltip_timing.Dwell s) pure nothrow @nogc @safe

Post-transition invariant: a shown tooltip is the group's open surface, and an open surface makes the countdown redundant (React Aria clears the pending cool-down on show).

settled
(
(local variable) anchored_overlays_tooltip_timing.Dwell n
n
);
} // --------------------------------------------------------------------------- // The scripted event list // --------------------------------------------------------------------------- /// What a target can deliver. `enter`/`leave` exist only where `caps.hover`. enum
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
: ubyte
{
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, /// time passes, nothing happens
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
, /// the pointer rests on an anchor
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
, /// the pointer leaves the group
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
, /// press+release on an anchor (or on 0 == outside)
(enum value) anchored_overlays_tooltip_timing.Ev.press = 4

a press elsewhere; also stands in for key/scroll

press
, /// a press elsewhere; also stands in for key/scroll
} /// One driver step: advance the clock by `dtMs`, then deliver `ev`. struct
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
{ int
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
;
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
;
(alias) object.size_t = ulong
size_t
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
;
(alias) object.string = string
string
(field) string anchored_overlays_tooltip_timing.Step.why

what the step is meant to prove

why
; /// what the step is meant to prove
}
(alias) object.string = string
string
string anchored_overlays_tooltip_timing.evName(anchored_overlays_tooltip_timing.Ev e) pure nothrow @nogc @safe
evName
(
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
(parameter) anchored_overlays_tooltip_timing.Ev e
e
) @safe pure nothrow @nogc
{ final switch (
(parameter) anchored_overlays_tooltip_timing.Ev e
e
) with (
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
)
{ case
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
: return "tick";
case
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
: return "enter";
case
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
: return "leave";
case
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
: return "tap";
case
(enum value) anchored_overlays_tooltip_timing.Ev.press = 4

a press elsewhere; also stands in for key/scroll

press
: return "press";
} }
(alias) object.string = string
string
string anchored_overlays_tooltip_timing.anchorLabel(ulong id) pure nothrow @nogc @safe
anchorLabel
(
(alias) object.size_t = ulong
size_t
(parameter) ulong id
id
) @safe pure nothrow @nogc
=>
(parameter) ulong id
id
== 0 ? "-" :
(parameter) ulong id
id
== 1 ? "A" :
(parameter) ulong id
id
== 2 ? "B" : "C";
/// `enter A`, `tick`, `tap outside` … — built through an output range, so the /// label costs no allocation even though `main` only prints it. void
void anchored_overlays_tooltip_timing.writeEvent!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.Step s) pure nothrow @nogc @safe

enter A, tick, tap outside … — built through an output range, so the label costs no allocation even though main only prints it.

writeEvent
(Writer)(ref
(alias) Writer = sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false)
Writer
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, in
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(parameter) const(anchored_overlays_tooltip_timing.Step) s
s
)
{
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
,
string anchored_overlays_tooltip_timing.evName(anchored_overlays_tooltip_timing.Ev e) pure nothrow @nogc @safe
evName
(
(parameter) const(anchored_overlays_tooltip_timing.Step) s
s
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
));
if (
(parameter) const(anchored_overlays_tooltip_timing.Step) s
s
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
!= 0)
{
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, " ");
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
,
string anchored_overlays_tooltip_timing.anchorLabel(ulong id) pure nothrow @nogc @safe
anchorLabel
(
(parameter) const(anchored_overlays_tooltip_timing.Step) s
s
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
));
} else if (
(parameter) const(anchored_overlays_tooltip_timing.Step) s
s
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
==
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
)
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, " outside");
} /// `cold` / `warm 180`. void
void anchored_overlays_tooltip_timing.writeGroup!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.DwellGroup g) pure nothrow @nogc @safe

cold / warm 180.

writeGroup
(Writer)(ref
(alias) Writer = sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false)
Writer
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, in
(struct) anchored_overlays_tooltip_timing.DwellGroup

The whole cross-instance protocol: which anchor owns the open surface, and how much warmth is left once it closes. Nine independent lineages converged on exactly this much state. With an injected wall clock the second field is the absolute warmUntilMs the proposal specifies; this driver supplies dtMs (the shape Timeline.stepped already consumes), so it counts down. One integer either way.

DwellGroup
(parameter) const(anchored_overlays_tooltip_timing.DwellGroup) g
g
)
{ if (
(parameter) const(anchored_overlays_tooltip_timing.DwellGroup) g
g
.
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
!= 0)
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, "open");
else if (
(parameter) const(anchored_overlays_tooltip_timing.DwellGroup) g
g
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
> 0)
{
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, "warm ");
void sparkles.base.text.writers.writeValue!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), int)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, ref const(int) val) pure nothrow @nogc @safe

Writes any value to an output range using best-effort @nogc conversion.

Dispatch order:

  1. bool — writes "true" or "false"

  2. Integral types — uses writeInteger

  3. Floating-point types — uses writeFloat

  4. char — writes the character directly

  5. String/char slices — writes directly via put

  6. User types with @nogc output range toString — calls t.toString(writer)

  7. User types with @nogc sink toString — calls with a forwarding delegate

  8. User types with @nogc toString() returning string — writes the result

  9. User types with @nogc string cast — writes cast(string) t

  10. Fallback — uses std.conv.to!string (GC-allocating)

writeValue
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
,
(parameter) const(anchored_overlays_tooltip_timing.DwellGroup) g
g
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
);
} else
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w
w
, "cold");
}
(alias) object.string = string
string
string anchored_overlays_tooltip_timing.dwellPhase(in anchored_overlays_tooltip_timing.TooltipDwell d) pure nothrow @nogc @safe
dwellPhase
(in
(struct) anchored_overlays_tooltip_timing.TooltipDwell

One tooltip's timing state: a composed Timeline plus the anchor it belongs to. armedDelayMs is stored because the deadline must be absolute — measured from the arm instant, never recomputed as now + delay — which Timeline.stepped gives for free as long as the config does not change under it.

TooltipDwell
(parameter) const(anchored_overlays_tooltip_timing.TooltipDwell) d
d
) @safe pure nothrow @nogc
=>
(parameter) const(anchored_overlays_tooltip_timing.TooltipDwell) d
d
.
bool anchored_overlays_tooltip_timing.TooltipDwell.warming() const pure nothrow @nogc @safe

Counting down to the deadline, and not in the display or hit list.

warming
? "warming" :
(parameter) const(anchored_overlays_tooltip_timing.TooltipDwell) d
d
.
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
? "shown" : "idle";
/// The hover script: A warms up and shows, B rides the warm group instantly, /// the cool-down expires before C, a press clears warmth, and an abandoned /// warm-up leaves the group cold. immutable
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
[]
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.hoverScript

The hover script: A warms up and shows, B rides the warm group instantly, the cool-down expires before C, a press clears warmth, and an abandoned warm-up leaves the group cold.

hoverScript
= [
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
, 1, "cold group: A pays the full warm-up"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(250,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "mid warm-up: armed, not painted"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(250,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "deadline reached: A is shown"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(700,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "holdUntilDismissed: no 1.2 s self-close"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
, 0, "A closes and arms the cool-down"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(120,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
, 2, "group still warm: B is INSTANT"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(300,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "B holds"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
, 0, "B closes, cool-down re-armed"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(400,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "cool-down expires: the group is cold"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
, 3, "C pays the full warm-up again"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(500,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "C is shown"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.press = 4

a press elsewhere; also stands in for key/scroll

press
, 3, "press closes AND clears warmth"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(50,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
, 1, "warmth was cleared: A warms up again"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(200,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
, 0, "abandoned mid-warm-up: no cool-down armed"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
, 2, "so B pays full price, not the skip window"),
]; /// The touch script: the substituted trigger, on the same three anchors. immutable
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
[]
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.tapScript

The touch script: the substituted trigger, on the same three anchors.

tapScript
= [
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
, 1, "tap pins A instantly (openMs is statically 0)"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(900,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
, 0, "pinned: no max-duration, no self-close"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
, 2, "tap B swaps the pinned surface"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
, 2, "tap the same anchor: triggerReactivate dismisses"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
, 3, "tap C pins C"),
(struct) anchored_overlays_tooltip_timing.Step

One driver step: advance the clock by dtMs, then deliver ev.

Step
(0,
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
, 0, "tap outside dismisses"),
]; // --------------------------------------------------------------------------- // Trigger resolution (the sketch from proposal.md § 3.5, reduced to what a // tooltip needs) // --------------------------------------------------------------------------- /// A declaration, not a behaviour: which triggers the component *wants*. struct
(struct) anchored_overlays_tooltip_timing.TriggerPolicy

A declaration, not a behaviour: which triggers the component wants.

TriggerPolicy
{ bool
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
,
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.activate
activate
,
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.longPress
longPress
;
} /// What the target can actually serve, and what it put in hover's place. struct
(struct) anchored_overlays_tooltip_timing.TriggerPlan

What the target can actually serve, and what it put in hover's place.

TriggerPlan
{
(struct) anchored_overlays_tooltip_timing.TriggerPolicy

A declaration, not a behaviour: which triggers the component wants.

TriggerPolicy
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
,
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.dropped
dropped
,
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.substituted
substituted
;
} /// `caps.hover == false` moves `hover` to `substituted` and lets `activate` /// (tap-to-pin) carry it — the only substitution expressible on all three live /// targets. Long press is **not** the default substitute: it exceeds the cell /// pointer's tier, and on Android it collides with text selection.
(struct) anchored_overlays_tooltip_timing.TriggerPlan

What the target can actually serve, and what it put in hover's place.

TriggerPlan
anchored_overlays_tooltip_timing.TriggerPlan anchored_overlays_tooltip_timing.resolveTriggers(in anchored_overlays_tooltip_timing.TriggerPolicy want, in sparkles.input.capability.InputCapabilities caps) pure nothrow @nogc @safe

``caps.hover == false moves hover to substituted and lets activate (tap-to-pin) carry it — the only substitution expressible on all three live targets. Long press is not the default substitute: it exceeds the cell pointer's tier, and on Android it collides with text selection.

resolveTriggers
(in
(struct) anchored_overlays_tooltip_timing.TriggerPolicy

A declaration, not a behaviour: which triggers the component wants.

TriggerPolicy
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
, in
(struct) sparkles.input.capability.InputCapabilities

A target's declared input affordances.

The defaults describe a mouse: the historical assumption, so a producer that has not thought about this yet keeps today's behavior rather than silently claiming a capability it lacks in the other direction.

Declare with one of the profiles below where one fits — mousePointer, touchPointer, cellPointer, staticPointer — so the vocabulary stays small and two targets that mean the same thing say it the same way.

InputCapabilities
(parameter) const(sparkles.input.capability.InputCapabilities) caps
caps
)
@safe pure nothrow @nogc {
(struct) anchored_overlays_tooltip_timing.TriggerPlan

What the target can actually serve, and what it put in hover's place.

TriggerPlan
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
;
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.activate
activate
=
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.activate
activate
;
if (
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
&&
(parameter) const(sparkles.input.capability.InputCapabilities) caps
caps
.
(field) bool sparkles.input.capability.InputCapabilities.hover

The pointer can rest on a target without pressing.

false on touch, and it is the one that changes component behavior most: everything hover-driven needs a second route, because on a touchscreen the "pointer position" between taps is simply the last place a finger left.

hover
)
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
= true;
else if (
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
&&
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.activate
activate
)
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.substituted
substituted
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
= true;
else if (
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
)
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.dropped
dropped
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
= true;
if (
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.longPress
longPress
&&
(parameter) const(sparkles.input.capability.InputCapabilities) caps
caps
.
(field) bool sparkles.input.capability.InputCapabilities.hover

The pointer can rest on a target without pressing.

false on touch, and it is the one that changes component behavior most: everything hover-driven needs a second route, because on a touchscreen the "pointer position" between taps is simply the last place a finger left.

hover
)
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.dropped
dropped
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.longPress
longPress
= true; // deliberate: never the default substitute
else
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.longPress
longPress
=
(parameter) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.longPress
longPress
;
return
(local variable) anchored_overlays_tooltip_timing.TriggerPlan p
p
;
} // --------------------------------------------------------------------------- // The tier-0 model: what `:hover` + `transition-delay` can and cannot express // --------------------------------------------------------------------------- /// Static HTML has no cross-element state, so *this is the entire machine*: how /// long one element has matched `:hover`. There is no group, no arbiter, and /// nothing to interrupt. struct
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
{
(alias) object.size_t = ulong
size_t
(field) ulong anchored_overlays_tooltip_timing.CssHover.hoveredId
hoveredId
;
int
(field) int anchored_overlays_tooltip_timing.CssHover.hoveredMs
hoveredMs
;
}
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
anchored_overlays_tooltip_timing.CssHover anchored_overlays_tooltip_timing.cssEntered(ulong id) pure nothrow @nogc @safe
cssEntered
(
(alias) object.size_t = ulong
size_t
(parameter) ulong id
id
) @safe pure nothrow @nogc =>
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
(
(parameter) ulong id
id
, 0);
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
anchored_overlays_tooltip_timing.CssHover anchored_overlays_tooltip_timing.cssLeft() pure nothrow @nogc @safe
cssLeft
() @safe pure nothrow @nogc =>
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
(0, 0);
/// Leaving reverts the property, so mid-delay cancellation is free — the one /// piece of the machine tier-0 gets right for nothing.
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
anchored_overlays_tooltip_timing.CssHover anchored_overlays_tooltip_timing.cssStepped(in anchored_overlays_tooltip_timing.CssHover s, int dtMs) pure nothrow @nogc @safe

Leaving reverts the property, so mid-delay cancellation is free — the one piece of the machine tier-0 gets right for nothing.

cssStepped
(in
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
, int
(parameter) int dtMs
dtMs
) @safe pure nothrow @nogc
=>
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
(
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
.
(field) ulong anchored_overlays_tooltip_timing.CssHover.hoveredId
hoveredId
,
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
.
(field) ulong anchored_overlays_tooltip_timing.CssHover.hoveredId
hoveredId
== 0 ? 0 :
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
.
(field) int anchored_overlays_tooltip_timing.CssHover.hoveredMs
hoveredMs
+
(parameter) int dtMs
dtMs
);
bool
bool anchored_overlays_tooltip_timing.cssVisible(in anchored_overlays_tooltip_timing.CssHover s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe
cssVisible
(in
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
) @safe pure nothrow @nogc
=>
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
.
(field) ulong anchored_overlays_tooltip_timing.CssHover.hoveredId
hoveredId
!= 0 &&
(parameter) const(anchored_overlays_tooltip_timing.CssHover) s
s
.
(field) int anchored_overlays_tooltip_timing.CssHover.hoveredMs
hoveredMs
>=
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
;
/// The rule pair a `DwellConfig` compiles to. It needs one change to /// `interp/html_semantic.d:57-58`: `display` is not transitionable, so the /// tier-0 reveal must switch to `visibility`/`opacity`. void
void anchored_overlays_tooltip_timing.writeTier0Css!(sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The rule pair a DwellConfig compiles to. It needs one change to interp/html_semantic.d:57-58: display is not transitionable, so the tier-0 reveal must switch to visibility/opacity.

writeTier0Css
(Writer)(ref
(alias) Writer = sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false)
Writer
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w
w
, in
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
)
{
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w
w
, ".spk-reveal{position:absolute;z-index:1;visibility:hidden;opacity:0;"
~ "transition:visibility 0s,opacity 0s;transition-delay:0ms}\n");
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w
w
, ".spk-hit:hover>.spk-reveal,.spk-hit:focus-visible>.spk-reveal{"
~ "visibility:visible;opacity:1;transition-delay:");
void sparkles.base.text.writers.writeValue!(sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false), int)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w, ref const(int) val) pure nothrow @nogc @safe

Writes any value to an output range using best-effort @nogc conversion.

Dispatch order:

  1. bool — writes "true" or "false"

  2. Integral types — uses writeInteger

  3. Floating-point types — uses writeFloat

  4. char — writes the character directly

  5. String/char slices — writes directly via put

  6. User types with @nogc output range toString — calls t.toString(writer)

  7. User types with @nogc sink toString — calls with a forwarding delegate

  8. User types with @nogc toString() returning string — writes the result

  9. User types with @nogc string cast — writes cast(string) t

  10. Fallback — uses std.conv.to!string (GC-allocating)

writeValue
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w
w
,
(parameter) const(anchored_overlays_tooltip_timing.DwellConfig) c
c
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
);
void std.range.primitives.put!(sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false), string)(ref sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) r, string e) pure nothrow @nogc @safe

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

In this table "doPut" is a method that places e into r, using the correct primitive: r`.`put`(`e`)` if `R` defines put, r.front = e if r is an input range (followed by r.popFront()), or ``r(e) otherwise.

Code Snippet
Scenario

| ``r.doPut(e); | R specifically accepts an E. |

| ``r.doPut([ e ]); | R specifically accepts an E[]. |

| r`.putChar(`e`);` | `R` accepts some form of string or character. `put` will transcode the character e`` accordingly. |

| for (; !e.empty; e.popFront()) put(r, e.front); | Copying range E into R. |

Tip

put should not be used "UFCS-style", e.g. r`.`put`(`e`)`. Doing this may call `R.`put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

Examples

When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.

import std.traits : isSomeChar;

static struct A
{
    string data;

    void put(C)(C c)
    if (isSomeChar!C)
    {
        data ~= c;
    }
}
static assert(isOutputRange!(A, char));

auto a = A();
put(a, "Hello");
assert(a.data == "Hello");

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

int[] a = [1, 2, 3], b = [10, 20];
auto c = a;
put(a, b);
assert(c == [10, 20, 3]);
// at this point, a was advanced twice, so it only contains
// its last element while c represents the whole array
assert(a == [3]);

It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.

Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a UTFException.

// the elements must be mutable, so using string or const(char)[]
// won't compile
char[] s1 = new char[13];
auto r1 = s1;
put(r1, "Hello, World!"w);
assert(s1 == "Hello, World!");
put
(
(parameter) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w
w
, "ms}\n");
} // --------------------------------------------------------------------------- void
void D main() @safe
main
() @safe
{ const
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
=
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
();
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("=== The tooltip timing machine, composed from Timeline (STM6) ===");
void std.stdio.writefln!("warm-up %d ms cool-down (skip window) %d ms warmth enabled: %s", const(int), const(int), bool)(const(int) __param_0, const(int) __param_1, bool __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"warm-up %d ms cool-down (skip window) %d ms warmth enabled: %s"(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.skipMs

the group stays warm this long after one closes

skipMs
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
.
bool anchored_overlays_tooltip_timing.DwellConfig.warmthEnabled() const pure nothrow @nogc @safe

Warmth is a feature, switched on by a positive skip window.

warmthEnabled
);
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("composition: Timeline.Config(fadeInMs: <resolved delay>, "
~ "holdUntilDismissed: true)");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" fadeIn == warming (not painted) hold == shown");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("new state: DwellGroup { openId, warmMsLeft } — two integers, "
~ "no per-widget timer"); // -- 1. the pointer trace ------------------------------------------------
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n=== 1. The hover script on a pointer target ===");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" t event dwell group shown why");
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
;
int
(local variable) int t
t
;
(alias) object.size_t = ulong
size_t
(local variable) ulong instantOpens
instantOpens
,
(local variable) ulong delayedOpens
delayedOpens
;
foreach (
(parameter) immutable(anchored_overlays_tooltip_timing.Step) st
st
;
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.hoverScript

The hover script: A warms up and shows, B rides the warm group instantly, the cool-down expires before C, a press clears warmth, and an abandoned warm-up leaves the group cold.

hoverScript
)
{
(local variable) int t
t
+=
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
;
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
=
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
const
(local variable) const(anchored_overlays_tooltip_timing.Dwell) before
before
=
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
;
final switch (
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
) with (
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
)
{ case
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
: break;
case
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
:
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
=
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
); break;
case
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
:
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
=
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.left(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer left the anchor (and the group's region).

left
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
); break;
case
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
:
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
=
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
); break;
case
(enum value) anchored_overlays_tooltip_timing.Ev.press = 4

a press elsewhere; also stands in for key/scroll

press
:
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
=
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.interrupted(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

A press, a key, or a scroll: closes the surface and clears warmth.

Nothing in React Aria or Radix clears warmth except its own cool-down, so a click or a scroll leaves the next tooltip in instant mode; Ariakit patched exactly this symptom on onBlur. Warmth is a property of an uninterrupted hover context, so the interruption ends it.

interrupted
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
); break;
} if (
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
==
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
)
{ if (
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) int anchored_overlays_tooltip_timing.TooltipDwell.armedDelayMs

the delay resolved at arm time

armedDelayMs
== 0)
++
(local variable) ulong instantOpens
instantOpens
;
else ++
(local variable) ulong delayedOpens
delayedOpens
;
} // The fade-out phase is unreachable here: fadeOutMs is 0 by // construction, so `shown` and `warming` partition every live state. assert(
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) sparkles.ui.state.Timeline anchored_overlays_tooltip_timing.TooltipDwell.life

fadeIn == warming, hold == shown

life
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
!=
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(enum) sparkles.ui.state.Timeline.Phase

The phase of the effect.

Phase
.
(enum value) sparkles.ui.state.Timeline.Phase.fadeOut = 3

disappearing

fadeOut
);
assert(
(local variable) const(anchored_overlays_tooltip_timing.Dwell) before
before
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
>= 0);
(struct) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false)

A @nogc container with Small Buffer Optimization and copy-on-write.

Elements are stored inline up to N elements, then automatically allocated on the heap (via AffixAllocator!(Mallocator, ControlBlock), which keeps the reference count in an allocation prefix; the element capacity is the heap slice length) when capacity is exceeded. Heap blocks are managed with the std.experimental.allocator makeArray/expandArray/dispose helpers.

The buffer is copyable. Copying an inline buffer duplicates its elements (independent copies). Copying a heap buffer shares the allocation and bumps a reference count; the shared block is cloned copy-on-write the first time a mutable copy is written. This suits the common pattern of one producer building a buffer mutably, then handing out many const reader copies — read via const (e.g. through borrow) never clones. Mutating accessors on a shared mutable copy clone first, so a mutable slice/reference taken from a shared buffer and held across a later mutation may be invalidated (the usual copy-on-write caveat) — read through const to share without that risk.

Note

storage location is tied to length (data is inline whenever length <= N), so reserve pre-grows only once on the heap, and clear/popBack that drop the length back to <= N revert to inline storage.

@paramT Element type@paramN Number of elements stored inline. The default fills the slice-sized union exactly (max(1, (T[]).sizeof / T.sizeof)), so the struct stays three words (3 * size_t.sizeof) regardless of T — e.g. 16 for char, 4 for int, 2 for long.@paramunique When true, opt out of the copy-on-write machinery: the buffer becomes move-only (copy construction/assignment are @disabled), so it is a sole owner by construction. Mutation then never reads or bumps a reference count — the append/grow hot path skips the uniqueness check entirely. Hand a finished unique buffer to the shareable copy-on-write world with SmallBuffer`.toShared`, which consumes it and returns a SmallBuffer!(T, N) (heap storage transfers without a reallocation). The default, false, is the ordinary copy-on-write buffer described above.
SmallBuffer
!(char, 32)
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
,
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) grp
grp
;
void anchored_overlays_tooltip_timing.writeEvent!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.Step s) pure nothrow @nogc @safe

enter A, tick, tap outside … — built through an output range, so the label costs no allocation even though main only prints it.

writeEvent
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
,
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
);
void anchored_overlays_tooltip_timing.writeGroup!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.DwellGroup g) pure nothrow @nogc @safe

cold / warm 180.

writeGroup
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) grp
grp
,
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
);
void std.stdio.writefln!("%5d %-9s %-8s %-9s %-5s %s", int, char[], string, char[], string, string)(int __param_0, char[] __param_1, string __param_2, char[] __param_3, string __param_4, string __param_5) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"%5d %-9s %-8s %-9s %-5s %s"(
(local variable) int t
t
,
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
[],
string anchored_overlays_tooltip_timing.dwellPhase(in anchored_overlays_tooltip_timing.TooltipDwell d) pure nothrow @nogc @safe
dwellPhase
(
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
),
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) grp
grp
[],
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
?
string anchored_overlays_tooltip_timing.anchorLabel(ulong id) pure nothrow @nogc @safe
anchorLabel
(
(local variable) anchored_overlays_tooltip_timing.Dwell s
s
.
ulong anchored_overlays_tooltip_timing.Dwell.visibleId() const pure nothrow @nogc @safe
visibleId
) : "-",
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) string anchored_overlays_tooltip_timing.Step.why

what the step is meant to prove

why
);
}
void std.stdio.writefln!("\nopens: %d paid the warm-up, %d opened instantly (one arbiter, zero per-widget timers)", ulong, ulong)(ulong __param_0, ulong __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!("\nopens: %d paid the warm-up, %d opened instantly "
~ "(one arbiter, zero per-widget timers)")(
(local variable) ulong delayedOpens
delayedOpens
,
(local variable) ulong instantOpens
instantOpens
);
assert(
(local variable) ulong instantOpens
instantOpens
== 1 &&
(local variable) ulong delayedOpens
delayedOpens
== 4);
// -- 2. the three STM6 seams --------------------------------------------
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n=== 2. Three Timeline seams the composition must not step on ===");
{ // (a) visible() is already true while warming. const
(local variable) const(sparkles.ui.state.Timeline.Config) warmingCfg
warmingCfg
=
sparkles.ui.state.Timeline.Config anchored_overlays_tooltip_timing.lifeCfg(int resolvedDelayMs) pure nothrow @nogc @safe

The Timeline config a dwell arms with. fadeInMs is the resolved delay (0 when the group was warm), and holdUntilDismissed is pinned so a hover-triggered surface can never self-close — the WCAG 1.4.13 defaults trap that Timeline.Config.holdMs = 1200 sets for an unwary caller.

lifeCfg
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
);
auto
(local variable) sparkles.ui.state.Timeline w
w
=
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.triggered(in sparkles.ui.state.Timeline.Config cfg) pure nothrow @nogc @safe

A freshly-triggered effect (restarts if already running).

triggered
(
(local variable) const(sparkles.ui.state.Timeline.Config) warmingCfg
warmingCfg
).
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.stepped(int dtMs, in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Advanced by dtMs milliseconds.

stepped
(250,
(local variable) const(sparkles.ui.state.Timeline.Config) warmingCfg
warmingCfg
);
void std.stdio.writefln!("a) warming at 250/%d ms: life.visible()=%s alpha=%d%% => paint on `phase == hold`, never on visible()", const(int), bool, int)(const(int) __param_0, bool __param_1, int __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!("a) warming at 250/%d ms: life.visible()=%s alpha=%d%% "
~ "=> paint on `phase == hold`, never on visible()")(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
,
(local variable) sparkles.ui.state.Timeline w
w
.
bool sparkles.ui.state.Timeline.visible() const pure nothrow @nogc @safe

true while anything should be painted.

visible
,
(local variable) sparkles.ui.state.Timeline w
w
.
int sparkles.ui.state.Timeline.alphaPercent(in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Opacity in percent (fades ramp linearly; hold is 100, idle 0).

alphaPercent
(
(local variable) const(sparkles.ui.state.Timeline.Config) warmingCfg
warmingCfg
));
assert(
(local variable) sparkles.ui.state.Timeline w
w
.
bool sparkles.ui.state.Timeline.visible() const pure nothrow @nogc @safe

true while anything should be painted.

visible
&&
(local variable) sparkles.ui.state.Timeline w
w
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
==
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(enum) sparkles.ui.state.Timeline.Phase

The phase of the effect.

Phase
.
(enum value) sparkles.ui.state.Timeline.Phase.fadeIn = 1

appearing

fadeIn
);
assert(!
(struct) anchored_overlays_tooltip_timing.TooltipDwell

One tooltip's timing state: a composed Timeline plus the anchor it belongs to. armedDelayMs is stored because the deadline must be absolute — measured from the arm instant, never recomputed as now + delay — which Timeline.stepped gives for free as long as the config does not change under it.

TooltipDwell
(
(local variable) sparkles.ui.state.Timeline w
w
, 1,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
).
bool anchored_overlays_tooltip_timing.TooltipDwell.shown() const pure nothrow @nogc @safe

Painted. Note this is phase == hold, not life.visible() — see § 2.

shown
);
// (b) dismissed() from fadeIn plays a full-opacity fade-out. const
(local variable) const(sparkles.ui.state.Timeline.Config) fading
fading
=
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(struct) sparkles.ui.state.Timeline.Config

Phase durations. holdUntilDismissed is the event-scoped mode: hold persists until dismissed — a mode, not a magic duration.

Config
(fadeInMs: 500, fadeOutMs: 150,
holdUntilDismissed: true); const
(local variable) const(sparkles.ui.state.Timeline) cancelled
cancelled
=
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.triggered(in sparkles.ui.state.Timeline.Config cfg) pure nothrow @nogc @safe

A freshly-triggered effect (restarts if already running).

triggered
(
(local variable) const(sparkles.ui.state.Timeline.Config) fading
fading
).
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.stepped(int dtMs, in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Advanced by dtMs milliseconds.

stepped
(250,
(local variable) const(sparkles.ui.state.Timeline.Config) fading
fading
)
.
sparkles.ui.state.Timeline sparkles.ui.state.Timeline.dismissed(in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Dismissed by an event (the no-frame-clock collapse): holding ends now.

dismissed
(
(local variable) const(sparkles.ui.state.Timeline.Config) fading
fading
);
void std.stdio.writefln!("b) dismissed() mid-warm-up: phase=%s alpha=%d%% \xe2\x80\x94 a cancelled warm-up must reset to idle, not dismiss", const(sparkles.ui.state.Timeline.Phase), int)(const(sparkles.ui.state.Timeline.Phase) __param_0, int __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!("b) dismissed() mid-warm-up: phase=%s alpha=%d%% — a cancelled "
~ "warm-up must reset to idle, not dismiss")(
(local variable) const(sparkles.ui.state.Timeline) cancelled
cancelled
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
,
(local variable) const(sparkles.ui.state.Timeline) cancelled
cancelled
.
int sparkles.ui.state.Timeline.alphaPercent(in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Opacity in percent (fades ramp linearly; hold is 100, idle 0).

alphaPercent
(
(local variable) const(sparkles.ui.state.Timeline.Config) fading
fading
));
assert(
(local variable) const(sparkles.ui.state.Timeline) cancelled
cancelled
.
(field) sparkles.ui.state.Timeline.Phase sparkles.ui.state.Timeline.phase
phase
==
(struct) sparkles.ui.state.Timeline

Transient-effect timing as a mode machine (STM6): idle → fadeIn → hold → fadeOut → idle, advanced by stepped(dtMs, config) — replacing the four hand-decremented float timers in the GUI. A backend with no frame clock (the event-driven TUI) collapses it without changing the caller: configure holdUntilDismissed and call ``Timeline.dismissed on the next event.

Timeline
.
(enum) sparkles.ui.state.Timeline.Phase

The phase of the effect.

Phase
.
(enum value) sparkles.ui.state.Timeline.Phase.fadeOut = 3

disappearing

fadeOut
&&
(local variable) const(sparkles.ui.state.Timeline) cancelled
cancelled
.
int sparkles.ui.state.Timeline.alphaPercent(in sparkles.ui.state.Timeline.Config cfg) const pure nothrow @nogc @safe

Opacity in percent (fades ramp linearly; hold is 100, idle 0).

alphaPercent
(
(local variable) const(sparkles.ui.state.Timeline.Config) fading
fading
) == 100);
// (c) a backend with no frame clock never advances `stepped`. auto
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
=
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
().
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(1,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
foreach (
(local variable) int _
_
; 0 .. 100)
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
=
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(0,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
); // TuiHost.frameSeconds() => 0
void std.stdio.writefln!("c) 100 frames at dt=0 (the TUI's frameSeconds): dwell=%s, shown=%s \xe2\x80\x94 a warm-up needs an injected clock", string, bool)(string __param_0, bool __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!("c) 100 frames at dt=0 (the TUI's frameSeconds): dwell=%s, "
~ "shown=%s — a warm-up needs an injected clock")(
string anchored_overlays_tooltip_timing.dwellPhase(in anchored_overlays_tooltip_timing.TooltipDwell d) pure nothrow @nogc @safe
dwellPhase
(
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
),
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
);
assert(
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.warming() const pure nothrow @nogc @safe

Counting down to the deadline, and not in the display or hit list.

warming
&& !
(local variable) anchored_overlays_tooltip_timing.Dwell frozen
frozen
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
);
} // -- 3. zero disables the feature, structurally --------------------------
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n=== 3. skipMs == 0 disables warmth; it never arms a 0 ms timer ===");
{ const
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) zero
zero
=
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(warmUpMs: 500, skipMs: 0);
auto
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
=
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
().
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(1,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) zero
zero
).
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(500,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) zero
zero
); // A shown
assert(
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
);
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
=
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.left(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer left the anchor (and the group's region).

left
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) zero
zero
);
void std.stdio.writefln!("after closing A with skipMs=0: group=%s, warmMsLeft=%d", string, int)(string __param_0, int __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"after closing A with skipMs=0: group=%s, warmMsLeft=%d"(
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
bool anchored_overlays_tooltip_timing.Dwell.warm() const pure nothrow @nogc @safe

true while a subsequent tooltip would open with no delay.

warm
? "warm" : "cold",
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
);
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
=
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(2,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) zero
zero
);
void std.stdio.writefln!("entering B: armed delay %d ms (not 0) \xe2\x80\x94 the WPF BetweenShowDelay==0 rule, and the fix for Radix #3873", int)(int __param_0) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!("entering B: armed delay %d ms (not 0) — the WPF "
~ "BetweenShowDelay==0 rule, and the fix for Radix #3873")(
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) int anchored_overlays_tooltip_timing.TooltipDwell.armedDelayMs

the delay resolved at arm time

armedDelayMs
);
assert(!
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
bool anchored_overlays_tooltip_timing.Dwell.warm() const pure nothrow @nogc @safe

true while a subsequent tooltip would open with no delay.

warm
&&
(local variable) anchored_overlays_tooltip_timing.Dwell z
z
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
(field) int anchored_overlays_tooltip_timing.TooltipDwell.armedDelayMs

the delay resolved at arm time

armedDelayMs
==
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) zero
zero
.
(field) int anchored_overlays_tooltip_timing.DwellConfig.warmUpMs

the first tooltip in a cold group waits this long

warmUpMs
);
} // -- 4. the touch collapse ----------------------------------------------
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n=== 4. The touch collapse (caps.hover == false) ===");
const
(local variable) const(sparkles.input.capability.InputCapabilities) touch
touch
=
(struct) sparkles.input.capability.InputCapabilities

A target's declared input affordances.

The defaults describe a mouse: the historical assumption, so a producer that has not thought about this yet keeps today's behavior rather than silently claiming a capability it lacks in the other direction.

Declare with one of the profiles below where one fits — mousePointer, touchPointer, cellPointer, staticPointer — so the vocabulary stays small and two targets that mean the same thing say it the same way.

InputCapabilities
(hover: false, precisePointer: false,
maxPointers: 5); const
(local variable) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
=
(struct) anchored_overlays_tooltip_timing.TriggerPolicy

A declaration, not a behaviour: which triggers the component wants.

TriggerPolicy
(hover: true, activate: true, longPress: false);
const
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
=
anchored_overlays_tooltip_timing.TriggerPlan anchored_overlays_tooltip_timing.resolveTriggers(in anchored_overlays_tooltip_timing.TriggerPolicy want, in sparkles.input.capability.InputCapabilities caps) pure nothrow @nogc @safe

``caps.hover == false moves hover to substituted and lets activate (tap-to-pin) carry it — the only substitution expressible on all three live targets. Long press is not the default substitute: it exceeds the cell pointer's tier, and on Android it collides with text selection.

resolveTriggers
(
(local variable) const(anchored_overlays_tooltip_timing.TriggerPolicy) want
want
,
(local variable) const(sparkles.input.capability.InputCapabilities) touch
touch
);
void std.stdio.writefln!("want: hover+activate caps.hover=%s", const(bool))(const(bool) __param_0) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"want: hover+activate caps.hover=%s"(
(local variable) const(sparkles.input.capability.InputCapabilities) touch
touch
.
(field) bool sparkles.input.capability.InputCapabilities.hover

The pointer can rest on a target without pressing.

false on touch, and it is the one that changes component behavior most: everything hover-driven needs a second route, because on a touchscreen the "pointer position" between taps is simply the last place a finger left.

hover
);
void std.stdio.writefln!(" served: hover=%s activate=%s", const(bool), const(bool))(const(bool) __param_0, const(bool) __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!" served: hover=%s activate=%s"(
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
,
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.activate
activate
);
void std.stdio.writefln!(" substituted: hover=%s -> tap-to-pin over PressState", const(bool))(const(bool) __param_0) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!" substituted: hover=%s -> tap-to-pin over PressState"(
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.substituted
substituted
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
);
void std.stdio.writefln!(" dropped: hover=%s", const(bool))(const(bool) __param_0) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!" dropped: hover=%s"(
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.dropped
dropped
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
);
assert(!
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.served
served
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
&&
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.substituted
substituted
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
&& !
(local variable) const(anchored_overlays_tooltip_timing.TriggerPlan) plan
plan
.
(field) anchored_overlays_tooltip_timing.TriggerPolicy anchored_overlays_tooltip_timing.TriggerPlan.dropped
dropped
.
(field) bool anchored_overlays_tooltip_timing.TriggerPolicy.hover
hover
);
// The same hover script, on a target that emits no hover events at all. {
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell h
h
;
int
(local variable) int delivered
delivered
,
(local variable) int shownSteps
shownSteps
;
foreach (
(parameter) immutable(anchored_overlays_tooltip_timing.Step) st
st
;
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.hoverScript

The hover script: A warms up and shows, B rides the warm group instantly, the cool-down expires before C, a press clears warmth, and an abandoned warm-up leaves the group cold.

hoverScript
)
{
(local variable) anchored_overlays_tooltip_timing.Dwell h
h
=
(local variable) anchored_overlays_tooltip_timing.Dwell h
h
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
if (
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
==
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
||
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
==
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
)
continue; // the target produces neither ++
(local variable) int delivered
delivered
;
if (
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
==
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.press = 4

a press elsewhere; also stands in for key/scroll

press
)
(local variable) anchored_overlays_tooltip_timing.Dwell h
h
=
(local variable) anchored_overlays_tooltip_timing.Dwell h
h
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.interrupted(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

A press, a key, or a scroll: closes the surface and clears warmth.

Nothing in React Aria or Radix clears warmth except its own cool-down, so a click or a scroll leaves the next tooltip in instant mode; Ariakit patched exactly this symptom on onBlur. Warmth is a property of an uninterrupted hover context, so the interruption ends it.

interrupted
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
if (
(local variable) anchored_overlays_tooltip_timing.Dwell h
h
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
)
++
(local variable) int shownSteps
shownSteps
;
}
void std.stdio.writefln!("\nreplaying the hover script here: %d of %d steps deliver an event, tooltip shown on %d \xe2\x80\x94 hover is unreachable, not slow", int, ulong, int)(int __param_0, ulong __param_1, int __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!("\nreplaying the hover script here: %d of %d steps deliver an "
~ "event, tooltip shown on %d — hover is unreachable, not slow")(
(local variable) int delivered
delivered
,
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.hoverScript

The hover script: A warms up and shows, B rides the warm group instantly, the cool-down expires before C, a press clears warmth, and an abandoned warm-up leaves the group cold.

hoverScript
.
(field) ulong immutable(anchored_overlays_tooltip_timing.Step[]).length
length
,
(local variable) int shownSteps
shownSteps
);
assert(
(local variable) int shownSteps
shownSteps
== 0);
} // The substituted trigger, driven by the same machine with openMs == 0. // `warming` and the cool-down are unreachable *by configuration*, not by a // runtime branch — a zero warm-up means `Timeline.triggered` lands in `hold`. const
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) touchCfg
touchCfg
=
(struct) anchored_overlays_tooltip_timing.DwellConfig

The two durations the whole dimension reduces to. Both belong in Palette beside popupPadX, exactly as WinUI puts them in the OS and Qt in QStyle; they are parameters here so the trace can name them.

skipMs == 0 must statically disable warmth rather than arm a zero-length timer — Radix shipped that bug (#3873: a zero-length timer left every tooltip instant forever) and fixed it with early returns in both provider callbacks. ``DwellConfig.warmthEnabled is that early return, expressed as a value.

DwellConfig
(warmUpMs: 0, skipMs: 0);
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\ntap-to-pin, warm-up statically 0, holdUntilDismissed pinned:");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" t event dwell group shown why");
{
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
;
int
(local variable) int tt
tt
;
foreach (
(parameter) immutable(anchored_overlays_tooltip_timing.Step) st
st
;
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.tapScript

The touch script: the substituted trigger, on the same three anchors.

tapScript
)
{
(local variable) int tt
tt
+=
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
;
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
=
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) touchCfg
touchCfg
);
if (
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
==
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
.
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
)
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
=
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
== 0 ||
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) ulong anchored_overlays_tooltip_timing.DwellGroup.openId

the anchor currently showing, 0 == none

openId
==
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
?
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.interrupted(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

A press, a key, or a scroll: closes the surface and clears warmth.

Nothing in React Aria or Radix clears warmth except its own cool-down, so a click or a scroll leaves the next tooltip in instant mode; Ariakit patched exactly this symptom on onBlur. Warmth is a property of an uninterrupted hover context, so the interruption ends it.

interrupted
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) touchCfg
touchCfg
) // outside / reactivate
:
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) touchCfg
touchCfg
); // pin
assert(!
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
.
bool anchored_overlays_tooltip_timing.TooltipDwell.warming() const pure nothrow @nogc @safe

Counting down to the deadline, and not in the display or hit list.

warming
, "warming is unreachable on touch");
assert(
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
.
(field) int anchored_overlays_tooltip_timing.DwellGroup.warmMsLeft

0 ⇒ the next tooltip in the group opens instantly

warmMsLeft
== 0, "the cool-down is unreachable too");
(struct) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false)

A @nogc container with Small Buffer Optimization and copy-on-write.

Elements are stored inline up to N elements, then automatically allocated on the heap (via AffixAllocator!(Mallocator, ControlBlock), which keeps the reference count in an allocation prefix; the element capacity is the heap slice length) when capacity is exceeded. Heap blocks are managed with the std.experimental.allocator makeArray/expandArray/dispose helpers.

The buffer is copyable. Copying an inline buffer duplicates its elements (independent copies). Copying a heap buffer shares the allocation and bumps a reference count; the shared block is cloned copy-on-write the first time a mutable copy is written. This suits the common pattern of one producer building a buffer mutably, then handing out many const reader copies — read via const (e.g. through borrow) never clones. Mutating accessors on a shared mutable copy clone first, so a mutable slice/reference taken from a shared buffer and held across a later mutation may be invalidated (the usual copy-on-write caveat) — read through const to share without that risk.

Note

storage location is tied to length (data is inline whenever length <= N), so reserve pre-grows only once on the heap, and clear/popBack that drop the length back to <= N revert to inline storage.

@paramT Element type@paramN Number of elements stored inline. The default fills the slice-sized union exactly (max(1, (T[]).sizeof / T.sizeof)), so the struct stays three words (3 * size_t.sizeof) regardless of T — e.g. 16 for char, 4 for int, 2 for long.@paramunique When true, opt out of the copy-on-write machinery: the buffer becomes move-only (copy construction/assignment are @disabled), so it is a sole owner by construction. Mutation then never reads or bumps a reference count — the append/grow hot path skips the uniqueness check entirely. Hand a finished unique buffer to the shareable copy-on-write world with SmallBuffer`.toShared`, which consumes it and returns a SmallBuffer!(T, N) (heap storage transfers without a reallocation). The default, false, is the ordinary copy-on-write buffer described above.
SmallBuffer
!(char, 32)
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
,
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) grp
grp
;
void anchored_overlays_tooltip_timing.writeEvent!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.Step s) pure nothrow @nogc @safe

enter A, tick, tap outside … — built through an output range, so the label costs no allocation even though main only prints it.

writeEvent
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
,
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
);
void anchored_overlays_tooltip_timing.writeGroup!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.DwellGroup g) pure nothrow @nogc @safe

cold / warm 180.

writeGroup
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) grp
grp
,
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
(field) anchored_overlays_tooltip_timing.DwellGroup anchored_overlays_tooltip_timing.Dwell.group
group
);
void std.stdio.writefln!("%5d %-11s %-8s %-9s %-5s %s", int, char[], string, char[], string, string)(int __param_0, char[] __param_1, string __param_2, char[] __param_3, string __param_4, string __param_5) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"%5d %-11s %-8s %-9s %-5s %s"(
(local variable) int tt
tt
,
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
[],
string anchored_overlays_tooltip_timing.dwellPhase(in anchored_overlays_tooltip_timing.TooltipDwell d) pure nothrow @nogc @safe
dwellPhase
(
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
(field) anchored_overlays_tooltip_timing.TooltipDwell anchored_overlays_tooltip_timing.Dwell.active
active
),
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) grp
grp
[],
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
?
string anchored_overlays_tooltip_timing.anchorLabel(ulong id) pure nothrow @nogc @safe
anchorLabel
(
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
ulong anchored_overlays_tooltip_timing.Dwell.visibleId() const pure nothrow @nogc @safe
visibleId
) : "-",
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) string anchored_overlays_tooltip_timing.Step.why

what the step is meant to prove

why
);
} assert(!
(local variable) anchored_overlays_tooltip_timing.Dwell p
p
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
);
}
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("unavailable rather than degraded: dwell intent (there is no rest "
~ "without hover),");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("the warm group, the cool-down. The substitution must be PUBLISHED "
~ "— as a readable");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("resolution value and an accessible description — or it is a silent "
~ "product hole."); // -- 5. the tier-0 collapse ---------------------------------------------
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n=== 5. The tier-0 collapse (static HTML: no script, no timers) ===");
{
(struct) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false)

A @nogc container with Small Buffer Optimization and copy-on-write.

Elements are stored inline up to N elements, then automatically allocated on the heap (via AffixAllocator!(Mallocator, ControlBlock), which keeps the reference count in an allocation prefix; the element capacity is the heap slice length) when capacity is exceeded. Heap blocks are managed with the std.experimental.allocator makeArray/expandArray/dispose helpers.

The buffer is copyable. Copying an inline buffer duplicates its elements (independent copies). Copying a heap buffer shares the allocation and bumps a reference count; the shared block is cloned copy-on-write the first time a mutable copy is written. This suits the common pattern of one producer building a buffer mutably, then handing out many const reader copies — read via const (e.g. through borrow) never clones. Mutating accessors on a shared mutable copy clone first, so a mutable slice/reference taken from a shared buffer and held across a later mutation may be invalidated (the usual copy-on-write caveat) — read through const to share without that risk.

Note

storage location is tied to length (data is inline whenever length <= N), so reserve pre-grows only once on the heap, and clear/popBack that drop the length back to <= N revert to inline storage.

@paramT Element type@paramN Number of elements stored inline. The default fills the slice-sized union exactly (max(1, (T[]).sizeof / T.sizeof)), so the struct stays three words (3 * size_t.sizeof) regardless of T — e.g. 16 for char, 4 for int, 2 for long.@paramunique When true, opt out of the copy-on-write machinery: the buffer becomes move-only (copy construction/assignment are @disabled), so it is a sole owner by construction. Mutation then never reads or bumps a reference count — the append/grow hot path skips the uniqueness check entirely. Hand a finished unique buffer to the shareable copy-on-write world with SmallBuffer`.toShared`, which consumes it and returns a SmallBuffer!(T, N) (heap storage transfers without a reallocation). The default, false, is the ordinary copy-on-write buffer described above.
SmallBuffer
!(char, 512)
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) css
css
;
void anchored_overlays_tooltip_timing.writeTier0Css!(sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) w, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The rule pair a DwellConfig compiles to. It needs one change to interp/html_semantic.d:57-58: display is not transitionable, so the tier-0 reveal must switch to visibility/opacity.

writeTier0Css
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) css
css
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
void std.stdio.writeln!(char[])(char[] __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 512LU, false) css
css
[]);
}
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("The same hover script, evaluated by those two rules alone:");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" t event machine tier-0 divergence");
{
(struct) anchored_overlays_tooltip_timing.Dwell

A group and its at-most-one live tooltip. One record suffices because opening closes every peer (React Aria's closeOthers), so a registry of per-instance timers — which is not expressible in @safe pure value code anyway — has nothing left to hold.

Dwell
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
;
(struct) anchored_overlays_tooltip_timing.CssHover

Static HTML has no cross-element state, so this is the entire machine: how long one element has matched :hover. There is no group, no arbiter, and nothing to interrupt.

CssHover
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
;
int
(local variable) int ct
ct
,
(local variable) int diverged
diverged
;
foreach (
(parameter) immutable(anchored_overlays_tooltip_timing.Step) st
st
;
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.hoverScript

The hover script: A warms up and shows, B rides the warm group instantly, the cool-down expires before C, a press clears warmth, and an abandoned warm-up leaves the group cold.

hoverScript
)
{
(local variable) int ct
ct
+=
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
;
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
=
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.stepped(in anchored_overlays_tooltip_timing.Dwell s, int dtMs, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

Advance by dtMs. The warm-up elapses inside Timeline; the cool-down is the one subtraction this machine adds.

stepped
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
=
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
.
anchored_overlays_tooltip_timing.CssHover anchored_overlays_tooltip_timing.cssStepped(in anchored_overlays_tooltip_timing.CssHover s, int dtMs) pure nothrow @nogc @safe

Leaving reverts the property, so mid-delay cancellation is free — the one piece of the machine tier-0 gets right for nothing.

cssStepped
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) int anchored_overlays_tooltip_timing.Step.dtMs
dtMs
);
final switch (
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) anchored_overlays_tooltip_timing.Ev anchored_overlays_tooltip_timing.Step.ev
ev
) with (
(enum) anchored_overlays_tooltip_timing.Ev

What a target can deliver. enter/leave exist only where caps.hover.

Ev
)
{ case
(enum value) anchored_overlays_tooltip_timing.Ev.tick = cast(ubyte)0u

time passes, nothing happens

tick
: break;
case
(enum value) anchored_overlays_tooltip_timing.Ev.enter = 1

the pointer rests on an anchor

enter
:
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
=
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
=
anchored_overlays_tooltip_timing.CssHover anchored_overlays_tooltip_timing.cssEntered(ulong id) pure nothrow @nogc @safe
cssEntered
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
);
break; case
(enum value) anchored_overlays_tooltip_timing.Ev.leave = 2

the pointer leaves the group

leave
:
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
=
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.left(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer left the anchor (and the group's region).

left
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
=
anchored_overlays_tooltip_timing.CssHover anchored_overlays_tooltip_timing.cssLeft() pure nothrow @nogc @safe
cssLeft
();
break; case
(enum value) anchored_overlays_tooltip_timing.Ev.tap = 3

press+release on an anchor (or on 0 == outside)

tap
:
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
=
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.entered(in anchored_overlays_tooltip_timing.Dwell s, ulong id, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

The pointer came to rest on an anchor.

entered
(
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
.
(field) ulong anchored_overlays_tooltip_timing.Step.anchor
anchor
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
break; case
(enum value) anchored_overlays_tooltip_timing.Ev.press = 4

a press elsewhere; also stands in for key/scroll

press
:
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
=
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
anchored_overlays_tooltip_timing.Dwell anchored_overlays_tooltip_timing.interrupted(in anchored_overlays_tooltip_timing.Dwell s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe

A press, a key, or a scroll: closes the surface and clears warmth.

Nothing in React Aria or Radix clears warmth except its own cool-down, so a click or a scroll leaves the next tooltip in instant mode; Ariakit patched exactly this symptom on onBlur. Warmth is a property of an uninterrupted hover context, so the interruption ends it.

interrupted
(
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
);
break; // no press channel at tier 0 } const
(local variable) const(string) mv
mv
=
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
bool anchored_overlays_tooltip_timing.Dwell.visible() const pure nothrow @nogc @safe
visible
?
string anchored_overlays_tooltip_timing.anchorLabel(ulong id) pure nothrow @nogc @safe
anchorLabel
(
(local variable) anchored_overlays_tooltip_timing.Dwell m
m
.
ulong anchored_overlays_tooltip_timing.Dwell.visibleId() const pure nothrow @nogc @safe
visibleId
) : "-";
const
(local variable) const(string) hv
hv
=
bool anchored_overlays_tooltip_timing.cssVisible(in anchored_overlays_tooltip_timing.CssHover s, in anchored_overlays_tooltip_timing.DwellConfig c) pure nothrow @nogc @safe
cssVisible
(
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
,
(local variable) const(anchored_overlays_tooltip_timing.DwellConfig) cfg
cfg
) ?
string anchored_overlays_tooltip_timing.anchorLabel(ulong id) pure nothrow @nogc @safe
anchorLabel
(
(local variable) anchored_overlays_tooltip_timing.CssHover h
h
.
(field) ulong anchored_overlays_tooltip_timing.CssHover.hoveredId
hoveredId
) : "-";
if (
(local variable) const(string) mv
mv
!=
(local variable) const(string) hv
hv
)
++
(local variable) int diverged
diverged
;
(struct) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false)

A @nogc container with Small Buffer Optimization and copy-on-write.

Elements are stored inline up to N elements, then automatically allocated on the heap (via AffixAllocator!(Mallocator, ControlBlock), which keeps the reference count in an allocation prefix; the element capacity is the heap slice length) when capacity is exceeded. Heap blocks are managed with the std.experimental.allocator makeArray/expandArray/dispose helpers.

The buffer is copyable. Copying an inline buffer duplicates its elements (independent copies). Copying a heap buffer shares the allocation and bumps a reference count; the shared block is cloned copy-on-write the first time a mutable copy is written. This suits the common pattern of one producer building a buffer mutably, then handing out many const reader copies — read via const (e.g. through borrow) never clones. Mutating accessors on a shared mutable copy clone first, so a mutable slice/reference taken from a shared buffer and held across a later mutation may be invalidated (the usual copy-on-write caveat) — read through const to share without that risk.

Note

storage location is tied to length (data is inline whenever length <= N), so reserve pre-grows only once on the heap, and clear/popBack that drop the length back to <= N revert to inline storage.

@paramT Element type@paramN Number of elements stored inline. The default fills the slice-sized union exactly (max(1, (T[]).sizeof / T.sizeof)), so the struct stays three words (3 * size_t.sizeof) regardless of T — e.g. 16 for char, 4 for int, 2 for long.@paramunique When true, opt out of the copy-on-write machinery: the buffer becomes move-only (copy construction/assignment are @disabled), so it is a sole owner by construction. Mutation then never reads or bumps a reference count — the append/grow hot path skips the uniqueness check entirely. Hand a finished unique buffer to the shareable copy-on-write world with SmallBuffer`.toShared`, which consumes it and returns a SmallBuffer!(T, N) (heap storage transfers without a reallocation). The default, false, is the ordinary copy-on-write buffer described above.
SmallBuffer
!(char, 32)
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
;
void anchored_overlays_tooltip_timing.writeEvent!(sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false))(ref sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) w, in anchored_overlays_tooltip_timing.Step s) pure nothrow @nogc @safe

enter A, tick, tap outside … — built through an output range, so the label costs no allocation even though main only prints it.

writeEvent
(
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
,
(local variable) immutable(anchored_overlays_tooltip_timing.Step) st
st
);
void std.stdio.writefln!("%5d %-9s %-9s %s", int, char[], string, string)(int __param_0, char[] __param_1, string __param_2, string __param_3) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"%5d %-9s %-9s %s"(
(local variable) int ct
ct
,
(local variable) sparkles.base.smallbuffer.SmallBuffer!(char, 32LU, false) ev
ev
[],
(local variable) const(string) mv
mv
,
(local variable) const(string) mv
mv
==
(local variable) const(string) hv
hv
?
(local variable) const(string) hv
hv
:
(local variable) const(string) hv
hv
~ " <-- differs");
}
void std.stdio.writefln!("\n%d of %d steps differ.", int, ulong)(int __param_0, ulong __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
!"\n%d of %d steps differ."(
(local variable) int diverged
diverged
,
(immutable global) immutable(anchored_overlays_tooltip_timing.Step[]) anchored_overlays_tooltip_timing.hoverScript

The hover script: A warms up and shows, B rides the warm group instantly, the cool-down expires before C, a press clears warmth, and an abandoned warm-up leaves the group cold.

hoverScript
.
(field) ulong immutable(anchored_overlays_tooltip_timing.Step[]).length
length
);
assert(
(local variable) int diverged
diverged
> 0);
}
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\nWhat tier 0 keeps, and what is simply not there:");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" warm-up delay -> transition-delay on the :hover rule");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" mid-delay cancellation -> free; the property reverts on unhover");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" hold until dismissed -> :hover holds as long as the pointer "
~ "stays");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" keyboard trigger -> the :focus-visible half of the same "
~ "rule");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" ABSENT: warm group / instant swap (no cross-element state)");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" ABSENT: cool-down, and the whole arbiter with it");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" ABSENT: rest (the id-stability gate needs a machine)");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" ABSENT: press / key / scroll clearing warmth (no channel)");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" ABSENT: the singleton — two nested .spk-hit elements both match "
~ ":hover");
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("These are honestly absent, not approximated, and are reported "
~ "under TGT5."); }