Events
Both embed mechanisms report readiness, state changes, and rejected writes. The iframe sends window messages; the inline embed exposes subscriptions on its handle.
The inline API additionally provides filter-specific changes, change sources, settlement promises, and image export.
Ready
window.addEventListener("message", (event) => {
if (event.source !== frame.contentWindow || event.origin !== ridgeOrigin) return;
if (event.data?.type === "ridge:ready") {
console.log("Dashboard ready", event.data.stateSchema);
}
});ridge.on("statechange", ({ state }) => console.log(state)); // safe before ready
await ridge.ready;
console.log("Dashboard ready", ridge.getStateSchema());Register an iframe message listener before loading the frame so its one-time ridge:ready message cannot be missed. The inline handle is stable as soon as the loader returns, so listeners can be attached before awaiting ready.
State changes
window.addEventListener("message", (event) => {
if (event.source !== frame.contentWindow || event.origin !== ridgeOrigin) return;
if (event.data?.type === "ridge:stateChange") {
syncMyControls(event.data.state);
}
});const unsubscribe = ridge.on("statechange", ({ state, changes, source, settled }) => {
if (source === "user") syncMyControls(state, changes);
});
// Later:
unsubscribe();The iframe reports the complete resulting state. The inline event also reports the delta, whether the change came from the user or API, and a promise that resolves after rendering.
Filter changes
// Filters arrive inside ridge:stateChange like any other state key.
const region = event.data.state["region-menu"]?.filter;ridge.on("filterchange", ({ filters, changes, source, settled }) => {
if (source === "user") syncFilterControls(filters, changes);
});Use { silent: true } when a host write should not trigger its own change notification.
Rejected writes
if (event.data?.type === "ridge:error") {
const { id, code, message } = event.data.error;
console.warn(code, id, message);
}ridge.on("stateerror", ({ id, code, message }) => {
console.warn(code, id, message);
});Branch on the machine-readable code, not the human-readable message. A batch may partially succeed even when one component rejects its value.
Wait for rendering
The iframe protocol does not expose render settlement or export. The inline handle does:
Not supported by the iframe message protocol.await ridge.whenSettled({ timeout: 10_000 });
const png = await ridge.exportImage("png");
const blob = await ridge.exportImage("blob");Await settlement before capturing an image so the exported dashboard matches its current state.