Parent window
Connecting…

Async return values

BroadcastChannelwindowId
The return-value pattern
Same return-value pattern as the postMessage demo, but the popup opens with noopener — it runs on its own event loop, so a long-running task in the parent never freezes the dialog. The real advantage of this transport is this thread isolation, not the call shape itself.
Last result
Whatever the child popup most recently returned.

// no result yet

Code
Both sides of the pattern. The parent awaits a typed value; the child turns user interaction into a procedure return.
parent.tsx
// Parent: open the popup and await a typed value.
// The BroadcastChannel transport opens the child with `noopener`, so
// the child runs on its OWN event loop — a busy parent does not freeze
// the dialog, and vice versa.
const child = await iwpc.open(`./child?kind=color`, {
  width: 520,
  height: 540
});

const hex = await child.invoke<void, string | null>(
  'PICK_COLOR',
  undefined,
  { timeout: 5 * 60 * 1000 } // generous, the user is in the loop
);

if (hex === null) {
  // user cancelled
} else {
  setColor(hex);
}
child.tsx
// Child: register BEFORE initialize() so the parent's invoke
// (which fires the moment open() resolves) finds the handler.
const instance = new IwpcWindow(window, {
  transport: 'broadcastChannel'
});

instance.register('PICK_COLOR', () =>
  new Promise<string | null>((resolve) => {
    setPending({ kind: 'color', resolve });
  })
);

instance.initialize();