### Monorepo Structure Example
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Illustrates the monorepo setup using pnpm workspaces, tsup for bundling, and a single package.json with multiple export entry points.
```json
{
"version": "1.0.0-dev.18",
"exports": {
".": "...",
"./react": "...",
"./profiler": "..."
}
}
```
--------------------------------
### Complete React App with Tempus
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Demonstrates a full React application setup using Tempus for animations and integrating the profiler. Ensure 'react' and 'tempus/react' are installed.
```javascript
import { useState } from 'react'
import Tempus from 'tempus'
import { ReactTempus, useTempus } from 'tempus/react'
import { profiler } from 'tempus/profiler'
export default function App() {
const [showProfiler, setShowProfiler] = useState(false)
return (
<>
>
)
}
function Content({ showProfiler }) {
const [x, setX] = useState(0)
useTempus(({ time }) => {
setX(Math.sin(time / 500) * 100)
}, { label: 'animation' })
return (
Animated Content
{showProfiler && }
)
}
function Profiler() {
const [overlay] = useState(() => profiler())
return null // profiler handles its own DOM
}
```
--------------------------------
### Profiler Usage Example
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/types.md
Demonstrates how to initialize the profiler with options and later destroy the handle to unmount and clean up.
```javascript
const handle = profiler({ corner: 'top-right' })
// Later
handle.destroy() // unmount and cleanup
```
--------------------------------
### Install Tempus with npm
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Install the Tempus package using npm. This is the recommended method for project integration.
```bash
npm install tempus
```
--------------------------------
### Complete React App Example with Tempus
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/react-bindings.md
A comprehensive example demonstrating the integration of ReactTempus, useTempus, and the Tempus profiler within a React application. It includes components for scrolling, animation, and physics.
```javascript
import React, { useState, useRef, useEffect } from 'react'
import Tempus from 'tempus'
import { ReactTempus, useTempus } from 'tempus/react'
import { profiler } from 'tempus/profiler'
export default function App() {
const [showProfiler, setShowProfiler] = useState(false)
const profilerRef = useRef(null)
useEffect(() => {
if (showProfiler && !profilerRef.current) {
profilerRef.current = profiler({ corner: 'top-left' })
} else if (!showProfiler && profilerRef.current) {
profilerRef.current.destroy()
profilerRef.current = null
}
}, [showProfiler])
return (
<>
>
)
}
function ScrollComponent() {
const [scrollY, setScrollY] = useState(0)
useTempus(() => {
const y = window.scrollY
setScrollY(y)
}, { order: -1, label: 'scroll' })
return
Scroll: {scrollY}px
}
function AnimationComponent() {
const [rotation, setRotation] = useState(0)
useTempus(({ time }) => {
setRotation(time * 0.05)
}, { label: 'rotate' })
return (
)
}
function PhysicsComponent() {
const [position, setPosition] = useState({ x: 0, y: 0 })
const velocityRef = useRef({ x: 0.5, y: 0.3 })
useTempus(({ deltaTime }) => {
setPosition((p) => ({
x: p.x + velocityRef.current.x * deltaTime,
y: p.y + velocityRef.current.y * deltaTime,
}))
}, { fps: 30, order: 1, label: 'physics' })
return (
)
}
```
--------------------------------
### Direct Import Examples
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Illustrates how to import modules and types directly from the main Tempus package, the profiler, and the React exports.
```javascript
// From main package
import Tempus from 'tempus'
import type { TempusState } from 'tempus'
// From profiler
import { profiler } from 'tempus/profiler'
import type { ProfilerOptions } from 'tempus/profiler'
// From React
import { useTempus, ReactTempus } from 'tempus/react'
import type { TempusCallback } from 'tempus/react'
```
--------------------------------
### Usage Example: tempus/profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
How to import the profiler function and its types from the 'tempus/profiler' package.
```javascript
import { profiler } from 'tempus/profiler'
import type { ProfilerOptions, ProfilerHandle } from 'tempus/profiler'
```
--------------------------------
### Full Tempus Setup with Profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/profiler.md
Demonstrates integrating Tempus with callbacks and visualizing them using the profiler overlay. The profiler visualizes callback order, cost, and budget adherence.
```javascript
import Tempus from 'tempus'
import { profiler } from 'tempus/profiler'
// Add some callbacks
Tempus.add(() => {
updateScroll()
}, { order: -1, label: 'scroll' })
Tempus.add(() => {
updateAnimations()
}, { label: 'animate' })
Tempus.add(() => {
render()
}, { order: 1, label: 'render' })
// Mount the profiler to visualize
const overlay = profiler({ corner: 'top-right' })
// The overlay shows:
// - scroll (order -1) running first
// - animate (order 0) running second
// - render (order 1) running last
// - Total budget usage and per-frame FPS
// - If any callback exceeds the frame budget, that region shows in red
```
--------------------------------
### Usage Example: tempus
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
How to import the Tempus singleton and its associated types in JavaScript/TypeScript.
```javascript
import Tempus from 'tempus'
import type { TempusState, TempusCallback, TempusOptions } from 'tempus'
```
--------------------------------
### Usage Example for TempusCallbackInfo
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/types.md
Demonstrates how to iterate through TempusCallbackInfo objects to calculate and log average callback durations.
```javascript
const infos = Tempus.inspect()
for (const info of infos) {
const avgDuration = info.samples.reduce((a, b) => a + b, 0) / info.samples.length
console.log(`${info.label}: ${avgDuration.toFixed(2)}ms (${info.fps}fps)`)
}
```
--------------------------------
### Usage Example: tempus/react
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
How to import the useTempus hook, ReactTempus component, and types from the 'tempus/react' package.
```javascript
import { useTempus, ReactTempus } from 'tempus/react'
import type { TempusState, TempusCallback } from 'tempus/react'
```
--------------------------------
### Testing Callback Order
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Verify that Tempus callbacks execute in the specified order. This example uses explicit `order` options and suggests using `Tempus.inspect()` for verification.
```javascript
test('callbacks run in order', () => {
const log = []
Tempus.add(() => log.push('b'), { order: 0 })
Tempus.add(() => log.push('a'), { order: -1 })
Tempus.add(() => log.push('c'), { order: 1 })
// Wait for next frame (requires RAF mock or real RAF in test)
// In practice, use Tempus.inspect() and check order field
const info = Tempus.inspect()
expect(info.map(i => i.order)).toEqual([-1, 0, 1])
})
```
--------------------------------
### Basic ReactTempus Setup
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Set up ReactTempus by rendering the ReactTempus component in your application's root. This globally patches requestAnimationFrame and automatically unpatches on unmount. Use the useTempus hook within components to access frame data.
```javascript
import { ReactTempus, useTempus } from 'tempus/react'
export default function App() {
return (
<>
{/* Patch globally, unmounts = unpatch */}
>
)
}
function YourComponent() {
useTempus(({ time, deltaTime }) => {
// Called every frame
console.log('Frame delta:', deltaTime)
})
return
Your UI
}
```
--------------------------------
### Serialization Example
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/types.md
Demonstrates how to serialize a Tempus.inspect() result to JSON, noting that TempusState.budget is a function and not serializable.
```javascript
const info = Tempus.inspect()[0]
console.log(JSON.stringify(info))
// {"label":"animate","samples":[1.5,1.6,1.4],"order":0,"fps":60,"source":"add"}
```
--------------------------------
### Tempus.play()
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Starts or resumes the animation loop. The loop typically auto-starts on client-side import.
```APIDOC
## Tempus.play()
Starts (or resumes) the loop. The loop auto-starts on the client when Tempus is imported.
```
--------------------------------
### Add Callback at Relative Frame Rate
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Register a callback to run at a fraction of the system's frame rate, specified as a percentage. This example runs at 50% of the system FPS.
```javascript
Tempus.add(() => {
updateCollisions()
}, { fps: '50%' })
```
--------------------------------
### Integrating GSAP with Tempus
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Shows how to integrate Tempus with GSAP to leverage Tempus's requestAnimationFrame loop for GSAP animations. Requires 'gsap' to be installed.
```javascript
import Tempus from 'tempus'
import gsap from 'gsap'
Tempus.patch() // GSAP's internal RAF is absorbed
gsap.to('#element', { duration: 2, x: 100 }) // runs in Tempus loop
```
--------------------------------
### Mocking Frame Time for Testing
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Test animations that rely on `deltaTime` by mocking the frame time. This example shows how to add a callback and collect `deltaTime` values for assertion.
```javascript
import Tempus from 'tempus'
test('animation progresses with deltaTime', () => {
const deltas = []
Tempus.add(({ deltaTime }) => {
deltas.push(deltaTime)
})
// In a real test harness, you'd control frame timing
// Tempus will provide actual frame deltas from RAF
// After test
expect(deltas.length).toBeGreaterThan(0)
expect(deltas[0]).toBeGreaterThan(0)
})
```
--------------------------------
### Add Callbacks with Execution Ordering
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Register multiple callbacks with specific execution orders. Lower 'order' values execute earlier in the frame. This example ensures scroll updates run before animations, and rendering happens last.
```javascript
Tempus.add(updateScroll, { order: -1 })
Tempus.add(updateAnimations) // default order: 0
Tempus.add(renderFrame, { order: 1 })
```
--------------------------------
### Import Tempus in JavaScript
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Import the Tempus library into your JavaScript project after installation. This makes the Tempus API available for use.
```javascript
import Tempus from 'tempus'
```
--------------------------------
### Get Callback Timing Snapshot
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Retrieves a normalized timing snapshot of all active callbacks, including those added via Tempus.add() and those absorbed by Tempus.patch(). This data is used by the profiler overlay.
```javascript
Tempus.inspect()
// [{ label, samples, order, fps, source: 'add' | 'patch' }, ...]
```
--------------------------------
### Initialize and Use Live Profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Initializes the live profiler overlay to monitor frame composition, CPU usage, and callback costs. Call `destroy()` to unmount the overlay.
```javascript
import { profiler } from 'tempus/profiler'
const overlay = profiler({
corner: 'top-left', // corner position
fps: 5, // overlay refresh rate
container: document.body // mount target
})
// Shows real-time frame composition, CPU budget usage, per-callback cost
// Click header to collapse, drag to move, click play/pause to control loop
overlay.destroy() // unmount
```
--------------------------------
### Initialize Profiler Overlay
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Mounts a live, draggable overlay that visualizes the composition of a single frame. It displays all callbacks end-to-end on a timeline relative to the per-frame budget. The overlay can be configured with options like corner position, refresh rate, and mount target.
```javascript
import { profiler } from 'tempus/profiler'
const overlay = profiler({
corner: 'top-left', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
fps: 5, // overlay refresh rate (the measurements it shows are unaffected)
container: document.body, // mount target
})
```
--------------------------------
### Basic Profiler Usage
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/profiler.md
Mounts the profiler overlay with default settings. Remember to call destroy() later to clean up.
```javascript
import { profiler } from 'tempus/profiler'
const overlay = profiler()
// Later, remove the panel
overlay.destroy()
```
--------------------------------
### Mount ReactTempus Once
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/react-bindings.md
Mount ReactTempus near the app root to patch requestAnimationFrame globally. This is the typical setup for most applications.
```javascript
import { ReactTempus } from 'tempus/react'
function App() {
return (
<>
{/* Patches rAF globally */}
>
)
}
```
--------------------------------
### Tempus.add() with All Options
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Adds a callback with all available configuration options specified.
```javascript
// All options
Tempus.add(animate, {
order: 1,
fps: 30,
label: 'my-animation'
})
```
--------------------------------
### profiler(options)
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/types.md
Initializes and mounts a performance profiler overlay. It accepts an optional configuration object to customize its behavior and appearance.
```APIDOC
## profiler(options)
### Description
Initializes and mounts a performance profiler overlay. It accepts an optional configuration object to customize its behavior and appearance.
### Method
POST (or similar, conceptually)
### Endpoint
`/profiler` (conceptual, as this is an SDK function)
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **options** (ProfilerOptions) - Optional - Configuration object for the profiler.
- **fps** (number) - Optional - Overlay refresh rate in Hz. Defaults to 5.
- **corner** (ProfilerCorner) - Optional - Where to pin the panel. Accepts 'top-left', 'top-right', 'bottom-left', or 'bottom-right'. Defaults to 'top-left'.
- **container** (HTMLElement) - Optional - DOM element to mount the panel into. Defaults to `document.body`.
### Request Example
```javascript
profiler({
fps: 10,
corner: 'top-right',
container: document.getElementById('my-container')
})
```
### Response
#### Success Response (200)
- **ProfilerHandle** - An object used to control the profiler instance.
- **element** (HTMLElement) - The root DOM element of the profiler panel.
- **destroy** (() => void) - Function to unmount the panel and clean up.
#### Response Example
```json
{
"element": "
...
",
"destroy": "function"
}
```
```
--------------------------------
### profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Imports and mounts a live, draggable overlay that visualizes the composition of a single frame, showing all callbacks and their timing relative to the frame budget.
```APIDOC
### profiler({ corner, fps, container })
Mounts a live, draggable overlay that visualizes how a single frame is composed.
### Parameters
- `corner`: `'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'` (default: `'top-left'`) - The corner where the overlay will be positioned.
- `fps`: `number` (default: 5) - The refresh rate of the overlay itself (does not affect measurement accuracy).
- `container`: `HTMLElement` (default: `document.body`) - The DOM element to mount the overlay into.
### Returns
- `object` - An object with a `destroy()` method to remove the overlay.
- `destroy()`: `() => void` - Removes the overlay from the DOM.
```
--------------------------------
### profiler(options)
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Mounts the live frame-budget overlay and returns a `{ element, destroy }` handle. This function is imported from `tempus/profiler`.
```APIDOC
## profiler(options)
### Description
Mounts the live frame-budget overlay and returns a `{ element, destroy }` handle.
### Method
`profiler(options)`
### Endpoint
`import { profiler } from 'tempus/profiler'`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Parameters
- **options**: Object - Configuration options for the profiler.
- **corner**: `'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'` - Optional - Default: `'top-left'`. Specifies where to pin the panel.
- **fps**: `number` - Optional - Default: `5`. The overlay refresh rate.
- **container**: `HTMLElement` - Optional - Default: `document.body`. The mount target for the overlay.
```
--------------------------------
### Basic Animation Loop
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Set up a simple animation callback that logs frame information. Each callback receives a state object with time, deltaTime, frame, and budget.
```javascript
import Tempus from "tempus"
// Simple animation at maximum FPS.
// Every callback receives a single `state` object:
// { time, deltaTime, frame, budget }
function animate({ time, deltaTime, frame, budget }) {
console.log('frame', time, deltaTime)
}
Tempus.add(animate)
```
--------------------------------
### Registering Callbacks with Tempus and Profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/profiler.md
Register various callbacks with different orders, labels, and FPS throttling options. Mount the profiler to visualize their performance on the timeline.
```javascript
import Tempus from 'tempus'
import { profiler } from 'tempus/profiler'
// Register callbacks with labels
Tempus.add(updateInput, {
order: -2,
label: 'input',
fps: 'Infinity'
})
Tempus.add(updatePhysics, {
order: -1,
label: 'physics',
fps: 30 // throttle to 30 FPS
})
Tempus.add(updateAnimations, {
order: 0,
label: 'animations'
})
Tempus.add(render, {
order: 1,
label: 'render'
})
Tempus.add(updateDebug, {
order: 2,
label: 'debug',
fps: 10 // throttle for performance
})
// Mount profiler to see frame composition
const overlay = profiler({
corner: 'top-left',
fps: 5
})
// Now watch the timeline fill up. You'll see:
// - Blue segment for input (runs every frame)
// - Orange hatched segment for physics (30 FPS throttle)
// - Green segment for animations
// - Red segment for render
// - Purple segment for debug (10 FPS throttle, very small)
// If total > budget, the overflow turns red.
// If FPS drops, the header updates live.
```
--------------------------------
### tsup Build Outputs
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Shows the directory structure and file types generated by the tsup build configuration for the Tempus package.
```bash
dist/
├── tempus.mjs # Main package, ESM
├── tempus.d.ts # Main package, types
├── tempus-profiler.mjs # Profiler export, ESM
├── tempus-profiler.d.ts # Profiler export, types
├── tempus-react.mjs # React export, ESM
└── tempus-react.d.ts # React export, types
Each entry point (packages/core/index.ts, packages/core/profiler.ts, packages/react/index.ts) is compiled to its own .mjs and .d.ts pair.
```
--------------------------------
### Tempus Singleton Instance
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Demonstrates the singleton pattern used for the Tempus instance, ensuring all modules import and use the same instance.
```typescript
// packages/core/src/tempus.ts
class TempusImpl { /* ... */ }
const Tempus = new TempusImpl()
export { Tempus }
```
```typescript
// packages/core/profiler.ts
import Tempus from 'tempus' // The published package, not relative import
// ensures the profiler uses the host app's singleton, not a duplicate
```
```typescript
// packages/react/src/use-tempus.ts
import Tempus from 'tempus'
// All React components use the same Tempus instance
```
--------------------------------
### Monitoring Performance Metrics with inspect()
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Use Tempus.inspect() to gather performance data for each labeled task and log average, max, and percentage of frame budget used.
```javascript
function logPerformance() {
const info = Tempus.inspect()
for (const entry of info) {
if (entry.samples.length === 0) continue
const avg = entry.samples.reduce((a, b) => a + b, 0) / entry.samples.length
const max = Math.max(...entry.samples)
const pct = (avg / Tempus.frameBudget) * 100
console.log(`${entry.label}: ${avg.toFixed(2)}ms (max: ${max.toFixed(2)}ms, ${pct.toFixed(1)}%)`)
}
console.log(`FPS: ${Math.round(Tempus.fps)}, Usage: ${Math.round(Tempus.usage * 100)}%`)
}
Tempus.add(logPerformance, { fps: 1, label: 'profiling' })
```
--------------------------------
### useTempus with Options
Source: https://github.com/darkroomengineering/tempus/blob/main/packages/react/README.md
Configure the `useTempus` hook by passing options such as FPS, order, and label. These options are forwarded to `Tempus.add`.
```javascript
useTempus(() => {}, {
fps: 30, // Will run at 30 FPS (or a relative rate like '50%')
order: -1, // Will run before other animations (lower runs first)
label: 'my-effect', // Shown in tempus/profiler and Tempus.inspect()
})
```
--------------------------------
### Configure Profiler Overlay
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Initialize the Tempus profiler with options to control its refresh rate, corner position, and the DOM element it mounts to. Ensure the profiler is imported before configuration.
```typescript
import { profiler } from 'tempus/profiler'
profiler({
corner: 'top-left', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
fps: 5, // overlay refresh rate (measurements unaffected)
container: document.body // mount target
})
```
--------------------------------
### Set Max FPS (System Refresh Rate)
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Configure a callback to run on every frame at the system's refresh rate. This bypasses throttling and provides the true frame delta for calculations.
```javascript
Tempus.add(update) // default: Infinity
Tempus.add(update, { fps: Infinity }) // explicit: run every frame
Tempus.add(update, { fps: Number.POSITIVE_INFINITY }) // equivalent
```
--------------------------------
### Tempus.add() with Order Option
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Demonstrates using the 'order' option to control the execution sequence of callbacks, similar to CSS ordering.
```javascript
// Order only (CSS-like ordering)
Tempus.add(scrollUpdate, { order: -1 }) // runs first
Tempus.add(mainAnimation) // runs second (order 0)
Tempus.add(render, { order: 1 }) // runs third
```
--------------------------------
### Input Logic Render Pattern
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Organize callbacks into a common Input → Logic → Render pattern using the 'order' option. This ensures user input is processed first, followed by game logic, and finally rendering.
```javascript
// User input first (order -1)
Tempus.add(handleInput, { order: -1 })
// Game logic second (order 0, default)
Tempus.add(updateGame)
// Rendering last (order 1)
Tempus.add(render, { order: 1 })
```
--------------------------------
### profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/profiler.md
Mounts a live frame-budget profiler overlay to the DOM and returns a handle to control and destroy it. The overlay visualizes callback performance and frame budget usage in real-time.
```APIDOC
## profiler(options?)
### Description
Mounts a live frame-budget profiler overlay to the DOM and returns a handle to control and destroy it. It visualizes real-time measurements of active callbacks laid out end-to-end on a timeline.
### Signature
```typescript
function profiler(options?: ProfilerOptions): ProfilerHandle
```
### Parameters
#### options
- **Type**: `ProfilerOptions`
- **Required**: No
- **Default**: `{}`
- **Description**: Configuration for the overlay panel.
### ProfilerOptions Type
Configuration object for `profiler()`.
| Key | Type | Default | Description |
|---|---|---|---|
| corner | `ProfilerCorner` | `'top-left'` | Where to pin the panel: `'top-left'`, `'top-right'`, `'bottom-left'`, or `'bottom-right'`. |
| fps | `number` | `5` | Overlay refresh rate in Hz. The panel updates at this rate for performance; the measurements it shows (from `Tempus.inspect()`) are unaffected. |
| container | `HTMLElement` | `document.body` | DOM element to mount the panel into. |
### Return Value
**Type:** `ProfilerHandle`
Handle returned by `profiler()` for control and cleanup.
| Property | Type | Description |
|---|---|---|
| element | `HTMLElement` | The root DOM element of the profiler panel. |
| destroy | `() => void` | Function to unmount the panel, unsubscribe from Tempus, and clean up listeners. |
### Behavior
- The panel is SSR-safe: on the server, `profiler()` returns a no-op handle.
- The panel is draggable by its header, pinned to the specified corner initially.
- On first drag, the panel switches to `top`/`left` positioning so it can be freely moved within the viewport.
- Clicking the header (without dragging) toggles collapse/expand.
- The play/pause button starts and stops the entire Tempus loop.
- The panel displays live FPS and CPU budget usage (%), a timeline of callbacks, and a legend with execution details.
- Throttled callbacks are shown with diagonal hatching.
### Usage Examples
**Basic usage with defaults:**
```javascript
import { profiler } from 'tempus/profiler'
const overlay = profiler()
// Later, remove the panel
overlay.destroy()
```
**Pin to top-right, custom refresh rate:**
```javascript
const overlay = profiler({
corner: 'top-right',
fps: 10,
})
```
**Mount to a specific container:**
```javascript
const container = document.querySelector('#debug-zone')
const overlay = profiler({
corner: 'bottom-left',
container,
})
```
```
--------------------------------
### Callback Execution Ordering
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Demonstrates how to control the execution order of callbacks using the `order` option, similar to CSS z-index.
```javascript
Tempus.add(a, { order: -1 }) // runs first
Tempus.add(b, { order: 0 }) // runs second (default)
Tempus.add(c, { order: 1 }) // runs third
```
--------------------------------
### Profiler with Custom Options
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/profiler.md
Configures the profiler to pin to the top-right corner and update at 10Hz.
```javascript
const overlay = profiler({
corner: 'top-right',
fps: 10,
})
```
--------------------------------
### useTempus with Execution Ordering
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/react-bindings.md
Control the execution order of animation callbacks using the `order` option. Negative values run earlier, positive values run later.
```javascript
function ScrollComponent() {
useTempus(updateScroll, { order: -1 }) // run first
}
function AnimationComponent() {
useTempus(animate) // default order 0
}
function RenderComponent() {
useTempus(render, { order: 1 }) // run last
}
```
--------------------------------
### Import Main Tempus Class and Types
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Imports the singleton animation frame manager and its associated types from the main 'tempus' package.
```javascript
import Tempus from 'tempus'
import type {
TempusState,
TempusCallback,
TempusOptions,
TempusCallbackInfo
} from 'tempus'
```
--------------------------------
### Throttling Profiling/Logging
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Schedule performance metrics logging to run every 500ms (2 FPS) using the 'fps' option.
```javascript
Tempus.add(logMetrics, {
fps: 2, // 2 FPS, measure every 500ms
label: 'metrics'
})
```
--------------------------------
### Progressive Rendering with Time Deadline
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Implement progressive rendering by rendering batches of work within a calculated time deadline based on the frame budget.
```javascript
Tempus.add((state) => {
const deadline = state.time + state.budget()
while (state.time < deadline && hasMoreToRender()) {
renderNextBatch()
}
})
```
--------------------------------
### Set Target FPS and Monitor Frame Budget
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Adjusts the target frames per second, which recalculates the budget per frame. Logs the updated frame budget and adds a callback to check the budget.
```javascript
Tempus.targetFps = 120 // set budget to ~8.33ms per frame
console.log(Tempus.frameBudget) // 8.333...
Tempus.add(({ budget }) => {
if (budget() > 2) doWork()
})
```
--------------------------------
### Tempus.add() with FPS Variations
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Shows how to configure different frame rate throttling behaviors using the 'fps' option.
```javascript
// FPS variations
Tempus.add(expensive, { fps: 30 }) // fixed 30 FPS
Tempus.add(moderate, { fps: '50%' }) // half system FPS
Tempus.add(smooth, { fps: Infinity }) // system refresh rate (default)
```
--------------------------------
### Import Profiler Function and Types
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Imports the `profiler` function and related types for creating and managing the live performance overlay.
```javascript
import { profiler } from 'tempus/profiler'
import type {
ProfilerOptions,
ProfilerHandle,
ProfilerCorner
} from 'tempus/profiler'
```
--------------------------------
### package.json Exports Configuration
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Defines the package export conditions in package.json, mapping entry points to their respective build output files for different module systems and types.
```json
{
"exports": {
".": {
"types": "./dist/tempus.d.ts",
"default": "./dist/tempus.mjs"
},
"./react": {
"types": "./dist/tempus-react.d.ts",
"default": "./dist/tempus-react.mjs"
},
"./profiler": {
"types": "./dist/tempus-profiler.d.ts",
"default": "./dist/tempus-profiler.mjs"
}
}
}
```
--------------------------------
### Log CPU Usage
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Adds a callback that logs the CPU usage percentage based on Tempus's performance metrics.
```javascript
Tempus.add(() => {
console.log('CPU usage:', Math.round(Tempus.usage * 100) + '%')
})
```
--------------------------------
### Minimal Tempus.add() Usage
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Adds a callback with default options: order 0, maximum FPS, and no label.
```javascript
// Minimal: no options, defaults to order 0, max FPS, no label
Tempus.add(animate)
```
--------------------------------
### Frame Budget Gating
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Shows how to conditionally execute expensive work only if the remaining frame budget is sufficient, preventing performance degradation.
```javascript
Tempus.add(({ budget }) => {
if (budget() > 2) {
doExpensiveWork() // only if there's time left
}
})
```
--------------------------------
### Tempus Type Relationships
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/types.md
Illustrates the relationships between various Tempus types, showing how options are passed and what is returned.
```plaintext
TempusOptions
↓
Tempus.add(callback, options: TempusOptions)
↓
callback: TempusCallback
↓
receives: TempusState
Tempus.inspect()
↓
returns: TempusCallbackInfo[]
profiler(options: ProfilerOptions)
↓
returns: ProfilerHandle
ProfilerOptions.corner: ProfilerCorner
```
--------------------------------
### Custom RAF Loop with Budget
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Illustrates creating a custom requestAnimationFrame loop with Tempus that manages a processing budget. This is useful for batching work within a frame.
```javascript
Tempus.add((state) => {
const deadline = state.time + state.budget()
while (state.time < deadline && hasWorkQueued()) {
processWork()
}
}, { label: 'queue-processor' })
```
--------------------------------
### useTempus with Multiple Animations
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/react-bindings.md
Manage multiple animations within a single component by calling `useTempus` multiple times with different callbacks and options. Order and FPS can be specified for each.
```javascript
function ComplexComponent() {
const [data, setData] = useState({})
// Input processing (first)
useTempus(() => {
handleInput()
}, { order: -1 })
// State update (middle)
useTempus(({ time }) => {
setData(prev => ({
...prev,
animationTime: time
}))
}, { order: 0 })
// Expensive computation (last, throttled)
useTempus(() => {
updateComplexModel()
}, { order: 1, fps: 30 })
}
```
--------------------------------
### Frame Rate Throttling
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Illustrates setting a fixed frame rate for callbacks using the `fps` option, allowing independent control over update frequency.
```javascript
Tempus.add(update, { fps: 30 }) // fixed 30 FPS
Tempus.add(update, { fps: '50%' }) // half system FPS
Tempus.add(update, { fps: Infinity }) // system rate (default)
```
--------------------------------
### Inspect Callback Timings
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Retrieves a snapshot of timing information for all active Tempus callbacks and logs their average duration and target FPS.
```javascript
const snapshot = Tempus.inspect()
for (const cb of snapshot) {
const avg = cb.samples.reduce((a, b) => a + b, 0) / cb.samples.length
console.log(`${cb.label}: ${avg.toFixed(2)}ms (${cb.fps}fps)`)
}
```
--------------------------------
### Monitor Low FPS
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Adds a callback that logs a warning if the measured frames per second drops below 30.
```javascript
Tempus.add(() => {
if (Tempus.fps < 30) {
console.warn('Low FPS:', Tempus.fps)
}
})
```
--------------------------------
### Import Tempus React Bindings
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/react-bindings.md
Import the necessary hooks and components from the tempus/react library.
```typescript
import { useTempus, ReactTempus } from 'tempus/react'
```
--------------------------------
### Dependency-Based Ordering of Callbacks
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Define the execution order of callbacks based on their dependencies using the 'order' and 'label' options with Tempus.add().
```javascript
// Scroll position (lowest order, no dependencies)
Tempus.add(updateScrollPosition, {
order: -2,
label: 'scroll-position'
})
// Parallax (depends on scroll)
Tempus.add(updateParallax, {
order: -1,
label: 'parallax'
})
// General animation (independent)
Tempus.add(updateAnimations, {
order: 0,
label: 'animations'
})
// Physics (depends on time, order-independent)
Tempus.add(updatePhysics, {
order: 0.5,
label: 'physics'
})
// Rendering (depends on everything)
Tempus.add(render, {
order: 1,
label: 'render'
})
// Post-render logging/profiling (highest order)
Tempus.add(logMetrics, {
order: 2,
label: 'metrics'
})
```
--------------------------------
### useTempus with Frame Budget
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/react-bindings.md
Utilize the frame budget to ensure animations only run when there's sufficient time remaining in the current frame. The `budget()` function returns the available time.
```javascript
function HeavyComponent() {
useTempus(({ budget }) => {
// Only process if there's time left in the frame
if (budget() > 2) {
doExpensiveWork()
}
}, { label: 'heavy-work' })
}
```
--------------------------------
### Add Simple Animation Callback
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Register a callback to run on every animation frame. The callback receives frame, time, and delta time information.
```javascript
import Tempus from 'tempus'
Tempus.add(({ time, deltaTime, frame }) => {
console.log('Frame', frame, 'elapsed', time, 'ms, delta', deltaTime, 'ms')
})
```
--------------------------------
### Load Tempus using a script tag
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Include Tempus in your HTML using a script tag from a CDN. This is useful for quick integration or projects not using a package manager.
```html
```
--------------------------------
### Integrate Profiler with React Components
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Set up and manage a profiler within a React application using Tempus's React integration and hooks.
```javascript
import { useState, useEffect, useRef } from 'react'
import { ReactTempus, useTempus } from 'tempus/react'
import { profiler } from 'tempus/profiler'
export default function App() {
const [showProfiler, setShowProfiler] = useState(false)
const profilerRef = useRef(null)
useEffect(() => {
if (showProfiler) {
profilerRef.current = profiler({ corner: 'top-left' })
} else if (profilerRef.current) {
profilerRef.current.destroy()
profilerRef.current = null
}
}, [showProfiler])
return (
<>
>
)
}
```
--------------------------------
### Tempus Core and Profiler Type Imports
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/types.md
Shows how to import core Tempus types and specific types for the profiler module.
```typescript
// Core types
import type {
TempusState,
TempusCallback,
TempusOptions,
TempusCallbackInfo
} from 'tempus'
// Profiler types
import type {
ProfilerOptions,
ProfilerHandle,
ProfilerCorner
} from 'tempus/profiler'
// React types (re-exports core types)
import type {
TempusState,
TempusCallback,
TempusOptions
} from 'tempus/react'
```
--------------------------------
### React Integration with Tempus
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Demonstrates how to integrate Tempus with React applications using the `ReactTempus` component for global patching and the `useTempus` hook for component-scoped animations. The hook safely handles updates without needing `useCallback`.
```javascript
import { ReactTempus, useTempus } from 'tempus/react'
function App() {
return (
<>
{/* Patch globally */}
>
)
}
function Component() {
useTempus(({ time, budget }) => {
// Runs every frame; latest callback is used without re-subscribing
// Safe to close over component state (no useCallback needed)
updateAnimation(time)
})
}
```
--------------------------------
### Import React Hooks and Components
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Imports React-specific utilities, including the `useTempus` hook for component-lifetime callbacks and `ReactTempus` component for patching requestAnimationFrame.
```javascript
import { useTempus, ReactTempus } from 'tempus/react'
import type {
TempusState,
TempusCallback,
TempusOptions
} from 'tempus/react'
```
--------------------------------
### Budget Warning Callback
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Add a callback to warn when the frame budget is exceeded, indicating potential performance issues.
```javascript
Tempus.add(({ budget }) => {
if (budget() < 2) {
console.warn('Frame budget exceeded; performance impact likely')
}
})
```
--------------------------------
### Label Callbacks for Profiler Visibility
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Assign labels to callbacks using the 'label' option for clearer identification in the profiler. This improves readability and helps in pinpointing performance bottlenecks.
```javascript
Tempus.add(updateScroll, {
order: -1,
label: 'scroll',
fps: 'Infinity'
})
Tempus.add(updatePhysics, {
order: 0,
label: 'physics',
fps: 30
})
Tempus.add(render, {
order: 1,
label: 'render'
})
```
--------------------------------
### Relative Frame Rate Throttling (Percentage-Based)
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Configures a callback to run at a fraction of the system's current frame rate. This provides responsive throttling across different devices.
```javascript
Tempus.add(update, { fps: '50%' }) // Half system FPS
Tempus.add(update, { fps: '33.33%' }) // One-third system FPS
Tempus.add(update, { fps: '100%' }) // Full system FPS (equivalent to Infinity)
```
--------------------------------
### Scroll Synchronization Pattern
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Implement scroll synchronization by ordering callbacks appropriately. Scroll position updates should precede parallax calculations, which in turn should happen before general rendering.
```javascript
// Scroll must update before parallax (order -2)
Tempus.add(updateScrollPosition, { order: -2 })
// Parallax depends on scroll (order -1)
Tempus.add(updateParallax, { order: -1 })
// Animation (order 0)
Tempus.add(animate)
// Render uses all above data (order 1)
Tempus.add(render, { order: 1 })
```
--------------------------------
### Peer Dependencies Configuration
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Specifies peer dependencies for the Tempus package, indicating that React is optional and only required for the 'tempus/react' export.
```json
{
"peerDependencies": {
"react": ">=17.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
}
}
```
--------------------------------
### Throttling AI/Pathfinding Updates
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Limit AI or pathfinding calculations to 10 FPS using the 'fps' option, allowing for less frequent but consistent updates.
```javascript
Tempus.add(updateAI, {
fps: 10, // 10 FPS, 100ms updates
label: 'ai'
})
```
--------------------------------
### Tempus.inspect()
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Retrieves a detailed timing snapshot of all active callbacks, including those added via `Tempus.add` and those absorbed by `Tempus.patch`.
```APIDOC
## Tempus.inspect()
Returns a `TempusCallbackInfo[]` timing snapshot of every active callback (both `Tempus.add()` callbacks and loops absorbed by `patch()`):
### Parameters
None
### Returns
- `TempusCallbackInfo[]`: An array of objects, where each object contains:
- `label`: `string` - The label assigned to the callback.
- `samples`: `number[]` - An array of recent per-frame durations in milliseconds.
- `order`: `number` - The execution order of the callback.
- `fps`: `number | string` - The target frame rate for the callback.
- `source`: `'add' | 'patch'` - Indicates if the callback was added directly or absorbed via patching.
```
--------------------------------
### Import Profiler
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/profiler.md
Import the profiler function from the tempus/profiler module.
```typescript
import { profiler } from 'tempus/profiler'
```
--------------------------------
### Pause and Resume Animation Loop
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/core-tempus.md
Shows how to temporarily stop the Tempus animation loop using `pause()` and then restart it with `play()`. Callbacks will not execute while paused.
```javascript
Tempus.pause()
// No callbacks run now
Tempus.play() // resume
```
--------------------------------
### Ping-Pong Pattern with Two Callbacks
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/integration-patterns.md
Use two separate Tempus callbacks to implement a ping-pong pattern, ensuring work is done on alternating frames.
```javascript
Tempus.add(() => {
doWorkA()
}, { order: -1, label: 'work-a' })
Tempus.add(({ frame }) => {
if (frame % 2 === 0) {
doWorkB()
}
}, { order: 0, label: 'work-b' })
```
--------------------------------
### Tempus.restart()
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Resets the loop's elapsed time to zero and resumes its execution.
```APIDOC
## Tempus.restart()
Resets the clock's elapsed time to `0` and resumes the loop.
```
--------------------------------
### Inspect Tempus Performance
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/README.md
Allows inspection of the Tempus loop's performance metrics, including callback timing snapshots, live frame rate, and CPU usage.
```javascript
const info = Tempus.inspect() // array of callback timing snapshots
console.log(Tempus.fps) // live frame rate
console.log(Tempus.usage) // CPU usage (0–1)
```
--------------------------------
### Tempus Core Module Imports: tempus.ts
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Illustrates the imports used within the main 'tempus.ts' file, showing dependencies on local modules like './clock' and './types'.
```typescript
import Clock from './clock'
import type { TempusState, TempusCallback, TempusOptions, TempusCallbackInfo } from './types'
import { getUID } from './uid'
import { version } from '../../../package.json'
```
--------------------------------
### Main Package Exports: tempus
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/module-structure.md
Exports from the core 'tempus' package, including the default Tempus singleton and types. Used for general animation frame management.
```typescript
export { Tempus as default } from './src/tempus'
// Types
export * from './src/types'
```
--------------------------------
### Define Callback Execution Order
Source: https://github.com/darkroomengineering/tempus/blob/main/_autodocs/configuration.md
Callbacks are executed based on their 'order' values, with lower numbers running first. Callbacks with the same order execute in the sequence they were registered.
```typescript
order: -2 -1 0 1 2
↓ ↓ ↓ ↓ ↓
first scroll animate render last
```
--------------------------------
### Ping Pong Animation Technique
Source: https://github.com/darkroomengineering/tempus/blob/main/README.md
Implement alternating animations ('ping' and 'pong') that execute on different frames but never within the same frame.
```javascript
Tempus.add(({ frame }) => {
if (frame % 2 === 0) {
console.log('ping')
} else {
console.log('pong')
}
})
```