JS-Specific Operators

These operators are only available in jsMain because they use browser APIs.

animTicker()

Emits a TickerFrame on every requestAnimationFrame callback (~60fps). Perfect for animations and frame-based game loops:

import io.peekandpoke.ultra.streams.ops.animTicker

val tick = animTicker()

val unsub = tick.subscribeToStream { frame ->
    // frame.count     — frames since start
    // frame.deltaTime — ms since last frame
    updateAnimation(frame.deltaTime)
}

unsub()  // stops requesting animation frames

Unlike ticker(intervalMs) (available on all platforms), animTicker() synchronizes with the browser's display refresh rate.

persistInLocalStorage()

Persists a stream's value in localStorage. On page reload, the stream initializes from storage:

import io.peekandpoke.ultra.streams.ops.persistInLocalStorage
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer

val theme = StreamSource("light")
    .persistInLocalStorage("app.theme", String.serializer())

@Serializable
data class Preferences(val fontSize: Int = 14, val darkMode: Boolean = false)

val prefs = StreamSource(Preferences())
    .persistInLocalStorage("app.prefs", Preferences.serializer())

Falls back to in-memory storage silently if localStorage is unavailable or the quota is exceeded. Accepts a custom StringFormat codec (defaults to JSON with ignoreUnknownKeys = true).

debouncedFunc() / debouncedFuncExceptFirst()

Standalone debounced function wrappers using browser setTimeout. Useful outside of streams:

import io.peekandpoke.ultra.streams.ops.debouncedFunc
import io.peekandpoke.ultra.streams.ops.debouncedFuncExceptFirst

val saveSearch = debouncedFunc(delayMs = 200) {
    performSearch(inputField.value)
}

inputField.onInput { saveSearch() }

// Execute first call immediately, debounce the rest
val autoSave = debouncedFuncExceptFirst(delayMs = 1000) {
    saveDraft()
}