### 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') } }) ```