npm package: @gmbl-games/webview-bridge
Description: A lightweight bridge for communication between React Native WebViews and web content.
Latest version: 1.0.0

# webview-bridge

A lightweight bridge for communication between React Native WebViews and web content.

## Installation

```bash
npm install @gmbl-games/webview-bridge
# or
yarn add @gmbl-games/webview-bridge
```

## Building

Run `nx build webview-bridge` to build the library.

## API Reference

### Core Functions

- **`parseWebViewMessage(event)`**: Parses a message received either from the JS game or React Native. Returns `null` if the message is invalid.
- **`sendMessageToApp(message)`**: Sends a message from the JS game to React Native.
- **`sendMessageToGame(message, webViewRef)`**: Sends a message from React Native to the JS game.
- **`createAppMessageEventListener()`**: Creates a listener manager for messages from React Native (use on the JS game). Returns `{ listenToAppMessage, destroyAppMessageListener }`.

### Types

- **`GameConfig`**: Configuration object for the game.
  ```typescript
  type GameConfig = {
    movingItemColor: string;
    staticItemColor: string;
  };
  ```
- **`MessageType`**: Enum of available message types.
- **`WebviewMessage`**: Typed message structure.

## How to use

### 📁 RN Component (GameScreen.tsx)

```tsx
import React, { useRef } from "react";
import { WebView } from "react-native-webview";
import {
  GameConfig,
  MessageType,
  parseWebViewMessage,
  sendMessageToGame,
} from "@gmbl-games/webview-bridge";

export default function GameScreen() {
  const webViewRef = useRef(null);

  const config: GameConfig = {
    movingItemColor: "#0f0",
    staticItemColor: "#f00",
  };

  const messageHandlers = {
    [MessageType.SESSION_STARTED]: () => console.log("🎮 Session started"),
    [MessageType.SESSION_ENDED]: () => console.log("🛑 Session ended"),
    [MessageType.SCORE_UPDATED]: (payload: { score: number }) =>
      console.log("📈 Score updated:", payload?.score),
    [MessageType.EXIT_GAME]: () => console.log("👋 Game exit requested"),
  };

  const handleMessage = (event: any) => {
    const message = parseWebViewMessage(event);
    if (!message) {
      return;
    }

    const handler = messageHandlers[message.type];
    if (handler) {
      handler(message.payload);
    }
  };

  const sendConfig = () => {
    sendMessageToGame(
      {
        type: MessageType.SEND_GAME_CONFIG,
        payload: config,
      },
      webViewRef
    );
  };

  return (
    <WebView
      ref={webViewRef}
      source={{ uri: "https://yourgame.com" }}
      onLoad={sendConfig} // send config when game loads
      onMessage={handleMessage} // handle messages from game
    />
  );
}
```

### 📁 Game (main.ts)

```ts
import {
  createAppMessageEventListener,
  sendMessageToApp,
  parseWebViewMessage,
  MessageType,
  GameConfig,
} from "@gmbl-games/webview-bridge";

// 1. Setup Listener
const { listenToAppMessage, destroyAppMessageListener } =
  createAppMessageEventListener();

listenToAppMessage((event) => {
  const message = parseWebViewMessage(event);
  if (!message) return;

  switch (message.type) {
    case MessageType.SEND_GAME_CONFIG:
      const config = message.payload as GameConfig;
      console.log("Received config:", config);
      // Initialize game with config...

      // Notify App that config is received
      sendMessageToApp({
        type: MessageType.GAME_CONFIG_RECEIVED,
        payload: config,
      });
      break;

    case MessageType.PAUSE_GAME:
      console.log("Pausing game...");
      sendMessageToApp({ type: MessageType.GAME_PAUSED });
      break;

    case MessageType.RESUME_GAME:
      console.log("Resuming game...");
      sendMessageToApp({ type: MessageType.GAME_RESUMED });
      break;
  }
});

// 2. Send messages to App
function updateScore(score: number) {
  sendMessageToApp({
    type: MessageType.SCORE_UPDATED,
    payload: { score },
  });
}

function exitGame() {
  sendMessageToApp({
    type: MessageType.EXIT_GAME,
  });
}

// Cleanup when needed
destroyAppMessageListener();
```