wovvmap-webview-bridge 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +213 -180
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,180 +1,213 @@
1
- # 📱 Native Integration Guide – wovvmap-webview-bridge
2
-
3
- This guide explains how to use the `wovvmap-webview-bridge` package **from the React Native side**. This package helps you send data to a WebView and listen for data coming from the WebView.
4
-
5
- ---
6
-
7
- ## Installation
8
-
9
- ```bash
10
- npm install wovvmap-webview-bridge
11
- # or
12
- yarn add wovvmap-webview-bridge
13
- ```
14
-
15
- ---
16
-
17
- ## 🔌 Setup WebView
18
-
19
- Import and use the `<WebViewScreen />` component provided by the package:
20
-
21
- ```tsx
22
- import React from 'react';
23
- import { View } from 'react-native';
24
- import { WebViewScreen } from 'wovvmap-webview-bridge';
25
-
26
- export default function App() {
27
- return (
28
- <View style={{ flex: 1 }}>
29
- <WebViewScreen url="http://localhost:5173/map" />
30
- </View>
31
- );
32
- }
33
- ```
34
-
35
- ---
36
-
37
- ## 📤 Send Data to WebView
38
-
39
- You can send navigation data (e.g. from, to, elevator, escalator) using `sendToWeb`:
40
-
41
- ```ts
42
- import { sendToWeb } from 'wovvmap-webview-bridge';
43
-
44
- sendToWeb({
45
- type: "setNavigationData",
46
- payload: {
47
- from: "store1",
48
- to: "store9",
49
- elevator: false,
50
- escalator: true,
51
- floor : 1
52
- },
53
- });
54
- ```
55
-
56
- ---
57
-
58
- ## 📥 Receive Events from WebView
59
-
60
- Use `registerBridgeHandler` to listen for events sent from the web:
61
-
62
- ```ts
63
- import { registerBridgeHandler } from 'wovvmap-webview-bridge';
64
-
65
- registerBridgeHandler("pathData", (points) => {
66
- console.log("📍 Received pathData:", points);
67
- });
68
-
69
- registerBridgeHandler("PathFindingResult", (result) => {
70
- console.log("🧭 Path result:", result);
71
- });
72
-
73
- registerBridgeHandler("changeFloor", (floor) => {
74
- console.log("🏢 Web requested floor change:", floor);
75
- });
76
- ```
77
-
78
- ---
79
-
80
- ## 🧠 Data Types
81
-
82
- The bridge handles these types safely:
83
-
84
- ```ts
85
- type SendToWebMessage = {
86
- type: "setNavigationData";
87
- payload: {
88
- from?: string;
89
- to?: string;
90
- elevator?: boolean;
91
- escalator?: boolean;
92
- floor?: boolean;
93
- };
94
- };
95
-
96
- type BridgeMessage =
97
- | { type: "event"; key: "floor"; value: number }
98
- | { type: "event"; key: "pathData"; value: NodePoint[] }
99
- | { type: "event"; key: "PathFindingResult"; value: PathFindingResult }
100
- | { type: "event"; key: "searchTextResult"; value: NodePoint[] }
101
- | { type: "event"; key: "shapeZoomAndSelect"; value: NodePoint | undefined }
102
- | { type: "event"; key: "searchablePoints"; value: NodePoint[] }
103
- | { type: "event"; key: "nodePoint"; value: {[key:string]: NodePointOuterFiled} }
104
- | { type: "event"; key: "nodeline"; value: {[key:string]: NodeLineOuterFiled} }
105
- | { type: "event"; key: "categoryList"; value: { [key: string]: NodePoint } }
106
- | {
107
- type: "event"; key: "floorInfo"; value: {
108
- floors: {
109
- index: number;
110
- shortName: string;
111
- fullName: string;
112
- floorNumber: number;
113
- }[],
114
- defaultFloorIndex: number
115
- }
116
- }
117
- | { type: "event"; key: "to"; value:string}
118
- | { type: "event"; key: "from"; value:string}
119
- | { type: "event"; key: "elevator"; value:"true" | "false"}
120
- | { type: "event"; key: "escalator"; value:"true" | "false"}
121
-
122
-
123
-
124
- type EventHandlerMap = {
125
- floor?: (floor: number) => void;
126
- pathData?: (val: NodePoint[]) => void;
127
- PathFindingResult?: (val: PathFindingResult) => void;
128
- searchTextResult?: (val: NodePoint[]) => void;
129
- shapeZoomAndSelect?: (val: NodePoint | undefined) => void;
130
- searchablePoints?: (val: NodePoint[]) => void;
131
- nodePoint?: (val: { [key: string]: NodePointOuterFiled }) => void;
132
- nodeline?: (val: { [key: string]: NodeLineOuterFiled }) => void;
133
- categoryList?: (val: { [key: string]: NodePoint }) => void;
134
- floorInfo?: (val: {
135
- floors: {
136
- index: number;
137
- shortName: string;
138
- fullName: string;
139
- floorNumber: number;
140
- }[];
141
- defaultFloorIndex: number;
142
- }) => void;
143
- to?: (val: string) => void;
144
- from?: (val: string) => void;
145
- elevator?: (val: "true" | "false") => void;
146
- escalator?: (val: "true" | "false") => void;
147
- };
148
-
149
- ```
150
-
151
- ---
152
-
153
- ## 💡 Tips
154
-
155
- - All bridge messages are serialized using `JSON.stringify`. Avoid non-serializable data like Maps or circular references.
156
- - WebView must have messaging enabled (already done in `<WebViewScreen />`).
157
- - You can directly access the `webviewRef` if needed.
158
-
159
- ```ts
160
- import { webviewRef } from 'wovvmap-webview-bridge';
161
- ```
162
-
163
- ---
164
-
165
- ## 📄 Summary of Exports (Native Side)
166
-
167
- ```ts
168
- import {
169
- WebViewScreen,
170
- sendToWeb,
171
- webviewRef,
172
- registerBridgeHandler,
173
- } from 'wovvmap-webview-bridge';
174
- ```
175
-
176
- ---
177
-
178
- ## 📘 Done!
179
-
180
- You're now ready to communicate seamlessly between React Native and your WebView 🎉
1
+
2
+ # React Native WebView Bridge
3
+
4
+ A tiny bridge layer to communicate between a React Native app (using `react-native-webview`) and a web page. It provides:
5
+
6
+ - A ready-to-use `<WebViewScreen />` wrapper
7
+ - A simple `sendToWeb(...)` API for posting messages to the webview
8
+ - Typed event handling for messages coming **from** the web page
9
+ - Lightweight in-app state storage (via `koshin`) to keep UI in sync with bridge events
10
+
11
+ > **Demo idea:** Your message referenced a Snack example. You can adapt this package to the same flow as in your Snack: https://snack.expo.dev/@krushnkant/react-native-webview
12
+
13
+ ---
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ # with npm
19
+ npm i react-native-webview
20
+
21
+ # or with yarn
22
+ yarn add react-native-webview
23
+
24
+ # or with pnpm
25
+ pnpm add react-native-webview
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Quick Start
31
+
32
+ 1) **Render the WebView and hook the bridge handler**
33
+
34
+ ```tsx
35
+ import React from "react";
36
+ import { WebViewScreen } from "<your-package-name>";
37
+ // If you want to register custom event callbacks:
38
+ import { registerBridgeHandler } from "<your-package-name>";
39
+
40
+ export default function App() {
41
+ React.useEffect(() => {
42
+ // Optional handlers for clicks coming from the web scene
43
+ registerBridgeHandler("isSceneClick", (evt) => {
44
+ console.log("Scene clicked:", evt);
45
+ });
46
+ registerBridgeHandler("isShapClick", (evt) => {
47
+ console.log("Shape clicked:", evt.value);
48
+ });
49
+ }, []);
50
+
51
+ return <WebViewScreen url={"https://your-web-app.example.com"} />;
52
+ }
53
+ ```
54
+
55
+ Under the hood, `<WebViewScreen />` wires `onMessage` to the bridge message handler so any `postMessage(...)` coming from your web page is typed and routed correctly. fileciteturn1file6
56
+
57
+ 2) **Send commands *to* the web app**
58
+
59
+ ```ts
60
+ import {
61
+ sendActiveFloorToBridge,
62
+ sendEndPointToBridge,
63
+ sendPathFinishBtnClick,
64
+ sendPathNextBtnClick,
65
+ sendPathPreBtnClick,
66
+ sendStartPointToBridge,
67
+ } from "<your-package-name>";
68
+
69
+ // examples:
70
+ sendStartPointToBridge("node_123");
71
+ sendEndPointToBridge("node_999");
72
+ sendActiveFloorToBridge(2);
73
+ sendPathNextBtnClick();
74
+ sendPathPreBtnClick();
75
+ sendPathFinishBtnClick();
76
+ ```
77
+
78
+ These helpers call the shared `sendToWeb(...)` which posts a JSON-serialized message to the underlying `WebView` instance. fileciteturn1file1 fileciteturn1file7
79
+
80
+ 3) **Keep UI in sync with bridge state (optional)**
81
+
82
+ ```ts
83
+ import { bridgeStorage } from "<your-package-name>";
84
+
85
+ bridgeStorage.subscribe((state) => {
86
+ // state includes: isBridgeLoaded, isMapLoaded, searchablePoints, activeFloor, etc.
87
+ console.log(state);
88
+ });
89
+ ```
90
+
91
+ Internally this uses a small `koshin` store with fields like `isBridgeLoaded`, `isMapLoaded`, `searchablePoints`, `activeFloor`, `floorImages`, `stapByStapList`, and `nextPreState`. fileciteturn1file0
92
+
93
+ ---
94
+
95
+ ## What the Web Page Should Send
96
+
97
+ Your web page (inside the WebView) should `postMessage(JSON.stringify(...))` with the following **Incoming** event shapes:
98
+
99
+ ```ts
100
+ type IncomingMessage =
101
+ | { type: "event"; key: "isConnection"; value: boolean; file: string }
102
+ | { type: "event"; key: "mapLoaded"; value: boolean; file: string }
103
+ | { type: "event"; key: "_searchablePoints"; value: NodePoint[]; file: string }
104
+ | { type: "event"; key: "Category"; value: Category[]; file: string }
105
+ | { type: "event"; key: "_activeFloor"; value: number; file: string }
106
+ | { type: "event"; key: "FloorImg"; value: FloorImage[]; file: string }
107
+ | { type: "event"; key: "isSceneClick"; file: string }
108
+ | { type: "event"; key: "isShapClick"; value: NodePoint; file: string }
109
+ | { type: "event"; key: "stapByStapList"; value: StepInstruction[]; file: string }
110
+ | { type: "event"; key: "pathNextPreState"; value: NavState; file: string };
111
+ ```
112
+ The built-in handler parses the message, updates store fields, and triggers any registered callbacks for `isSceneClick` / `isShapClick`. fileciteturn1file3 fileciteturn1file2
113
+
114
+ ---
115
+
116
+ ## What the App Sends to the Web Page
117
+
118
+ Outgoing commands you can dispatch from React Native:
119
+
120
+ ```ts
121
+ type OutgoingMessage =
122
+ | { type: "applyCSS"; selector: string; style: Partial<Record<string, string | number>> }
123
+ | { type: "event"; key: "ping"; value: boolean; file: string }
124
+ | { type: "event"; key: "setEndPoint"; value: string; file: string }
125
+ | { type: "event"; key: "setStartPoint"; value: string; file: string }
126
+ | { type: "event"; key: "setActiveFloor"; value: number; file: string }
127
+ | { type: "event"; key: "pathNextBtnClick"; file: string }
128
+ | { type: "event"; key: "pathPreBtnClick"; file: string }
129
+ | { type: "event"; key: "pathFinishBtnClick"; file: string };
130
+ ```
131
+ These go through `sendToWeb(...)` which uses a shared `webviewRef` to `postMessage(...)`. fileciteturn1file7
132
+
133
+ ---
134
+
135
+ ## API Reference
136
+
137
+ ### Components
138
+
139
+ #### `<WebViewScreen />`
140
+ A thin wrapper around `react-native-webview` that plugs in the bridge message handler.
141
+
142
+ **Props**
143
+ - `url: string` the URL to load inside the WebView.
144
+
145
+ fileciteturn1file6
146
+
147
+ ### Functions
148
+
149
+ - `registerBridgeHandler(type, handler)` — Register a callback for `"isSceneClick"` or `"isShapClick"` events. fileciteturn1file3
150
+ - `sendStartPointToBridge(pointId)` — Ask web map to set the start point. fileciteturn1file1
151
+ - `sendEndPointToBridge(pointId)` — Ask web map to set the end point. fileciteturn1file1
152
+ - `sendActiveFloorToBridge(floorIndex)` — Switch active floor on the web map. fileciteturn1file1
153
+ - `sendPathNextBtnClick()` / `sendPathPreBtnClick()` / `sendPathFinishBtnClick()` — Control path stepper on the web map. fileciteturn1file1
154
+ - `bridgeStorage` — Reactive store with connection and navigation-related state. fileciteturn1file0
155
+
156
+ ### Types (partial)
157
+ - `NodePoint`, `Category`, `FloorImage`, `StepInstruction`, `NavState`, `IncomingMessage`, `OutgoingMessage` TypeScript contracts shared across the bridge. fileciteturn1file5
158
+
159
+ ---
160
+
161
+ ## Minimal Web Side (Example)
162
+
163
+ Your web app should listen for messages and respond via `window.ReactNativeWebView.postMessage(...)`:
164
+
165
+ ```js
166
+ // inside the web page
167
+ window.addEventListener("message", (e) => {
168
+ try {
169
+ const msg = JSON.parse(e.data);
170
+ if (msg.type === "event" && msg.key === "setActiveFloor") {
171
+ // do something in the web app
172
+ console.log("Active floor requested:", msg.value);
173
+ // notify RN app that web is connected
174
+ window.ReactNativeWebView?.postMessage(JSON.stringify({
175
+ type: "event",
176
+ key: "isConnection",
177
+ value: true,
178
+ file: "web-app",
179
+ }));
180
+ }
181
+ } catch {}
182
+ });
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Project Structure (Library)
188
+
189
+ ```
190
+ src/
191
+ ├─ index.ts # package exports fileciteturn1file4
192
+ ├─ handlers/WebBridgeHandlers # incoming event router & registration fileciteturn1file3
193
+ ├─ webviewBridge/WebViewBridgeRef.ts # shared ref + sendToWeb fileciteturn1file7
194
+ ├─ webviewBridge/BridgeService.ts # convenience sending helpers fileciteturn1file1
195
+ ├─ webviewBridge/BridgeStorage.ts # tiny state store (koshin) fileciteturn1file0
196
+ ├─ webviewBridge/WebViewScreen.tsx # ready-to-use WebView wrapper fileciteturn1file6
197
+ ├─ types/types.ts # shared TS contracts fileciteturn1file5
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Requirements
203
+
204
+ - React Native
205
+ - [`react-native-webview`](https://github.com/react-native-webview/react-native-webview)
206
+ - [`koshin`](https://www.npmjs.com/package/koshin)
207
+ - TypeScript recommended
208
+
209
+ ---
210
+
211
+ ## License
212
+
213
+ MIT © Your Name
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wovvmap-webview-bridge",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [