@tempots/core
Core types and utilities for the multi-context Tempo framework. This package provides the foundational signal system, disposal management, and rendering primitives shared across all Tempo rendering contexts.
Installation
npm install @tempots/core
Features
- Signal System - Reactive state management with
Signal,Prop, andComputed - Disposal Scopes - Automatic resource lifecycle management
- Renderables - Type-safe renderable abstraction for multi-context rendering
- Providers - Dependency injection via
makeProviderMark - Signal Utilities - Rich set of derived signal operators
Signals
Signals are the reactive primitives that drive all state management in Tempo:
import { prop, computed, effect } from '@tempots/core'
// Prop: read-write signal
const count = prop(0)
// Computed: derived signal
const doubled = computed(() => count.value * 2)
// Effect: side-effect on signal changes
effect(() => console.log('Count:', count.value))
// Update triggers reactivity
count.set(5) // logs "Count: 5", doubled.value === 10
Signal Transformations
// Map, filter, flatMap
const label = count.map(n => `Count: ${n}`)
const positive = count.filter(n => n > 0)
// Async mapping
const data = count.mapAsync(async n => fetch(`/api/${n}`).then(r => r.json()))
// Feed into another prop
const target = prop('')
count.feedProp(target, n => String(n))
Signal Utilities
import { and, or, not, notNil, throttleSignal, distinctUntilChanged, accumulateSignal } from '@tempots/core'
// Boolean combinators
const canSubmit = and(isValid, isNotLoading)
const showWarning = or(hasError, isExpired)
const isHidden = not(isVisible)
// Throttle rapid updates
const throttled = throttleSignal(mouseMoveSignal, 16) // ~60fps
// Skip duplicate values
const unique = distinctUntilChanged(searchQuery)
// Accumulate values (scan/reduce)
const sum = accumulateSignal(valueSignal, (acc, val) => acc + val, 0)
Storage-Backed Props
import { localStorageProp, sessionStorageProp, storedProp } from '@tempots/core'
const theme = localStorageProp({ key: 'theme', defaultValue: 'light' })
const token = sessionStorageProp({ key: 'auth-token', defaultValue: '' })
History / Undo-Redo
import { prop, propHistory } from '@tempots/core'
const counter = prop(0)
const history = propHistory(counter)
counter.set(1); counter.set(2); counter.set(3)
history.undo() // counter.value === 2
history.redo() // counter.value === 3
history.go(0) // counter.value === 0
Disposal Scopes
Signals created within a DisposalScope are automatically tracked and disposed when the scope is disposed:
import { DisposalScope, prop, computed } from '@tempots/core'
const scope = new DisposalScope()
const count = scope.prop(0)
const doubled = scope.computed(() => count.value * 2)
// Later: disposes both signals
scope.dispose()
Core Types
Renderable
The universal rendering abstraction that all platform packages build upon:
import { createRenderable } from '@tempots/core'
const MY_TYPE = Symbol('MY_RENDERABLE')
const myComponent = createRenderable(MY_TYPE, (ctx) => {
// Render logic here
return (removeTree) => {
// Cleanup logic here
}
})
TNode
Represents any content that can be rendered — renderables, strings, signals of strings, arrays, or null:
type TNode<CTX, TType> = Renderable<CTX, TType> | Value<string> | null | undefined | Renderable<CTX, TType>[]
Value
A type that can be either a static value or a reactive signal:
type Value<T> = T | Signal<T>
Usage
@tempots/core is typically used indirectly through platform-specific packages like @tempots/dom or @tempots/native. Those packages re-export the signal system and provide higher-level APIs built on these core types.
For more information, see the Tempo documentation.