Param Panel

Serialization

Snapshot and restore panel state with getState() and setState(), keyed by stable control IDs.

Controls that have a stable id can participate in state serialization. This is the foundation for persistence and URL sharing.

Stable IDs

Give each control you want to serialize an id:

const threshold = pp.slider({
  id: "threshold",
  label: "Threshold",
  value: 128,
  min: 0,
  max: 255,
});

Controls inside folders get path-based keys built from the folder and control IDs:

advanced.edgeGain
advanced.diagnostics.showNormals

The path encoding is stable and documented, so saved state keeps working as your panel evolves — as long as the IDs stay the same.

getState()

const state = pp.getState();
interface PanelState {
  version: number;
  values: Record<string, unknown>;
  folders: Record<string, { expanded: boolean }>;
  tabs: Record<string, { activeIndex: number }>;
}

A snapshot looks like:

{
  "version": 1,
  "values": {
    "threshold": 128,
    "advanced.edgeGain": 2.5,
    "enabled": true
  },
  "folders": {
    "advanced": {
      "expanded": true
    }
  },
  "tabs": {
    "renderingMode": {
      "activeIndex": 1
    }
  }
}

setState()

pp.setState(savedState);
interface SetStateOptions {
  notify?: boolean;
  strict?: boolean;
}
pp.setState(savedState, {
  notify: true, // fire subscribers for changed values
  strict: false, // ignore unknown IDs instead of throwing
});

State application is safe and efficient:

  • Validated before anything is applied.
  • Applied as a single batch.
  • Notifies subscribers once per changed value.
  • In non-strict mode, unknown IDs are ignored; in strict mode they throw.

What is (and isn't) serialized

By default the snapshot includes only genuine user state:

  • Value-control values
  • Folder expanded/collapsed state
  • Tabs active index

It deliberately excludes configuration — labels, hints, min/max, styling, event listeners, canvas draw callbacks, and runtime DOM state. Those belong to how you built the panel, not to what the user changed. Rows have no state of their own — as a pure layout container, a row is never part of PanelState.

On this page