Kumbatio

React

EnergyProvider, hooks, and headless components from @kumbatio/energy-system/react

import { EnergyProvider, useEnergyLevel, EnergyGate } from '@kumbatio/energy-system/react'

Requires the optional peer dependency react >= 19.2. All hooks must be used inside an EnergyProvider; they throw Error('Energy hooks must be used within an EnergyProvider') otherwise. State reads use useSyncExternalStore, so they are concurrent-rendering safe.

EnergyProvider

function EnergyProvider(props: EnergyProviderProps): React.ReactElement

Provides an EnergyEngine to the tree. Either pass a pre-created engine, or let the provider create and own one (it disposes its internal engine on unmount, and recreates it correctly under React StrictMode).

import { EnergyProvider } from '@kumbatio/energy-system/react'
import { localStoragePersistence } from '@kumbatio/energy-system/persistence'

export function App({ children }: { children: React.ReactNode }) {
  return (
    <EnergyProvider defaultLevel={75} persistence={localStoragePersistence()}>
      {children}
    </EnergyProvider>
  )
}

EnergyProviderProps

Prop

Type

/>

Hooks

useEnergyState

function useEnergyState(): EnergyState

Get the full energy state (level + timestamp + source + revision + origin).

useEnergyLevel

function useEnergyLevel(): [EnergyLevel, (level: EnergyLevel, source?: EnergySource) => void]

Read the current energy level and a setter (source defaults to 'manual').

const [level, setLevel] = useEnergyLevel()

useEnergyLevelCycler

function useEnergyLevelCycler(): () => void

Returns a stable function that cycles to the next energy level (100 -> 75 -> 50 -> 25 -> 0 -> 100).

useStrategy

function useStrategy<T>(strategy: AdaptationStrategy<T>): T

Resolve a strategy against the current energy level. Memoized on [strategy, level].

import { uiVisibilityStrategy } from '@kumbatio/energy-system'
import { useStrategy } from '@kumbatio/energy-system/react'

const ui = useStrategy(uiVisibilityStrategy)
if (!ui.sidebar) return null

useEnergyGate

function useEnergyGate(minLevel: EnergyLevel): boolean

Returns true if the current energy level meets or exceeds the given minimum.

useEnergyPresence

function useEnergyPresence(presence: EnergyPresenceMap): EnergyPresence

Resolve a presence map against the current energy level. Memoized on [presence, level] - keep the map referentially stable (module scope or useMemo).

EnergyGate

function EnergyGate(props: EnergyGateProps): React.ReactNode

Declarative energy gating for a subtree. Headless: renders no wrapper element of its own. When the resolved presence is 'hidden', fallback takes over visually.

Hidden subtrees keep their state by default. Energy moves up and down, so a gate that destroyed its children would throw away a half-written message every time capacity dipped. Hiding goes through React 19.2's <Activity>: component state, DOM and scroll position survive, effects are torn down while hidden and re-run on reveal, and hidden content is not server-rendered. Set whenHidden="unmount" for subtrees whose cost is worth reclaiming instead - media, canvases, live connections.

// Hide the AI chat at 50 and below:
<EnergyGate min={75}>
  <AiChatPanel />
</EnergyGate>

// Full presence map, muted state styled by the child:
<EnergyGate presence={aiChatPresence}>
  {(presence) => <AiChatPanel muted={presence === 'muted'} />}
</EnergyGate>

EnergyGateProps

Exactly one gating form must be used: a full presence map, min (optionally with max for band gating), or max alone. Passing none throws Error('EnergyGate requires a presence map or min/max level').

Prop

Type

/>

EnergyHiddenBehavior

type EnergyHiddenBehavior = 'preserve' | 'unmount'

The whenHidden vocabulary, exported for props that pass the choice through.

EnergyIndicator

function EnergyIndicator(props: EnergyIndicatorProps): React.ReactNode

Headless energy indicator - bring your own UI. Takes a single render-prop child.

<EnergyIndicator>
  {({ level, label, cycle }) => (
    <button onClick={cycle}>
      {label} ({level})
    </button>
  )}
</EnergyIndicator>

EnergyIndicatorProps

Prop

Type

/>

EnergyIndicatorRenderProps

Prop

Type

/>