# @mirrorapp/iframe-bridge

A tiny bridge to help you:

- Auto-initialize iframe resizing via `@open-iframe-resizer/core`
- Expose a global message handler so child iframes can request parent viewport info
- Use a simple API: `iFrameSetup(iframe: HTMLIFrameElement)`

UMD build exposes `window.IframeBridge.iFrameSetup` and also `window.iFrameSetup`.

## Installation

```bash
npm install @mirrorapp/iframe-bridge
```

Alternative:

```bash
yarn add @mirrorapp/iframe-bridge
```

```bash
pnpm add @mirrorapp/iframe-bridge
```

## Quick Start (ES Modules)

```ts
import { iFrameSetup } from "@mirrorapp/iframe-bridge";

const iframe = document.getElementById("my-iframe") as HTMLIFrameElement;

// If no id is present, the bridge assigns a unique one automatically.
iFrameSetup(iframe);
```

## Browser Usage (UMD, no bundler)

Load the UMD bundle and call the global API:

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>IframeBridge UMD</title>
  </head>
  <body>
    <iframe
      id="my-iframe"
      src="https://example.com"
      style="width:100%;border:0;"
    ></iframe>

    <script src="https://unpkg.com/@mirrorapp/iframe-bridge/dist/index.umd.js"></script>
    <script>
      const iframe = document.getElementById("my-iframe");

      // Either global object...
      window.IframeBridge.iFrameSetup(iframe);

      // ...or the convenience alias:
      // window.iFrameSetup(iframe);
    </script>
  </body>
</html>
```

## React Example

Initialize after mount using a `ref`:

```tsx
import { useEffect, useRef } from "react";
import { iFrameSetup } from "@mirrorapp/iframe-bridge";

export default function App() {
  const iframeRef = useRef<HTMLIFrameElement | null>(null);

  useEffect(() => {
    if (iframeRef.current) {
      iFrameSetup(iframeRef.current);
    }
  }, []);

  return (
    <iframe
      ref={iframeRef}
      id="my-iframe"
      src="https://example.com"
      style={{ width: "100%", border: 0 }}
    />
  );
}
```

## Communicating from Inside the Iframe

From the child iframe page, request viewport info from the parent:

```js
// Request parent viewport info
const requestId = "req-" + Date.now();
window.parent.postMessage(
  { type: "get_viewport_info", data: { requestId } },
  "*"
);

// Listen for the response
window.addEventListener("message", (event) => {
  if (
    event.data?.type === "viewport_info_response" &&
    event.data.requestId === requestId
  ) {
    const {
      iframeTopInViewport,
      iframeLeftInViewport,
      viewportHeight,
      viewportWidth,
      scrollTop,
      scrollLeft,
    } = event.data;

    console.log("Viewport info:", event.data);
  }
});
```

The parent responds with:

- `type: "viewport_info_response"`
- `iframeTopInViewport`, `iframeLeftInViewport` — iframe position within the parent viewport
- `viewportHeight`, `viewportWidth` — parent viewport dimensions
- `scrollTop`, `scrollLeft` — parent scroll positions
- `requestId` — echo from your request

## API

- `iFrameSetup(iframe: HTMLIFrameElement): void`
  - Ensures the iframe has an `id` (adds one if missing)
  - Initializes `@open-iframe-resizer/core` with `{ checkOrigin: false }` for that iframe
  - Registers a single global message handler for viewport info requests

UMD global:

- `window.IframeBridge.iFrameSetup(iframe)`
- Alias: `window.iFrameSetup(iframe)`

## Notes

- SSR: Call `iFrameSetup` only in the browser (client-side). The package checks for `window`.
- Security: Resizer uses `checkOrigin: false`. Ensure the parent and child iframe content are trusted. Prefer restricting `postMessage` target origins to a known domain instead of `"*"`.
- Types: TypeScript definitions are included in the package.

## Module Formats

Exports include:

- ESM: `dist/index.js` (default `import`)
- CJS: `dist/index.cjs` (`require`)
- UMD: `dist/index.umd.js` (global `IframeBridge`)

```js
// CommonJS example
const { iFrameSetup } = require("@mirrorapp/iframe-bridge");
```

## Development

```bash
npm ci
```

```bash
npm run build
```

Build outputs to `dist/` with `esm`, `cjs`, and `iife (UMD)` formats, source maps, and type declarations.
