react-native-maplibre-gl-js 1.0.0 → 1.0.1
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.
- package/README.md +7 -5
- package/package.json +19 -14
- package/src/communication/messages.types.ts +0 -121
- package/src/communication/messages.utils.ts +0 -58
- package/src/index.ts +0 -31
- package/src/react-native/components/Map/Map.tsx +0 -14
- package/src/react-native/components/Map/Map.types.ts +0 -149
- package/src/react-native/components/MapProvider/MapProvider.hooks.ts +0 -13
- package/src/react-native/components/MapProvider/MapProvider.tsx +0 -139
- package/src/react-native/components/MapProvider/MapProvider.types.ts +0 -12
- package/src/react-native/components/Marker/Marker.tsx +0 -14
- package/src/react-native/components/Marker/Marker.types.ts +0 -56
- package/src/react-native/components/Popup/Popup.tsx +0 -14
- package/src/react-native/components/Popup/Popup.types.ts +0 -43
- package/src/react-native/components-factory/createWebObjectAsComponent.ts +0 -33
- package/src/react-native/components-factory/createWebObjectAsComponent.types.ts +0 -176
- package/src/react-native/components-factory/hooks/useWebObjectMethodsProxy.ts +0 -61
- package/src/react-native/components-factory/hooks/useWebObjectMountOnLaunch.ts +0 -79
- package/src/react-native/components-factory/hooks/useWebObjectOptionsUpdater.ts +0 -29
- package/src/react-native/hooks/atoms/useMapAtoms.ts +0 -261
- package/src/react-native/hooks/atoms/useMapAtoms.utils.ts +0 -15
- package/src/react-native/logger/rn-logger.ts +0 -51
- package/src/typedoc.ts +0 -35
- package/src/web/bridge/ReactNativeBridge.ts +0 -44
- package/src/web/generated/index.html +0 -18
- package/src/web/generated/index.ts +0 -17
- package/src/web/generated/webview_static_html.ts +0 -23528
- package/src/web/logger/web-logger.ts +0 -36
- package/src/web/maplibre-gl-js/MapController.ts +0 -322
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { MessageFromWebToRN } from 'react-native-maplibre-gl-js/communication/messages.types'
|
|
2
|
-
|
|
3
|
-
// TODO how to disable in prod?
|
|
4
|
-
const __DEV__ = true
|
|
5
|
-
|
|
6
|
-
const createLoggerMethod = (level: 'debug' | 'info' | 'error') => {
|
|
7
|
-
if (!__DEV__) {
|
|
8
|
-
return () => {}
|
|
9
|
-
}
|
|
10
|
-
return (func: string, ...args: any[]) => {
|
|
11
|
-
// Send to React Native WebView if available.
|
|
12
|
-
try {
|
|
13
|
-
const message: MessageFromWebToRN = {
|
|
14
|
-
type: 'console',
|
|
15
|
-
payload: {
|
|
16
|
-
level,
|
|
17
|
-
args: [func, ...args],
|
|
18
|
-
},
|
|
19
|
-
}
|
|
20
|
-
// @ts-ignore
|
|
21
|
-
window.ReactNativeWebView?.postMessage(JSON.stringify(message))
|
|
22
|
-
} catch {}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Logger to be used from the Web world. Will post the log to the React Native
|
|
28
|
-
* world. Works only in __DEV__.
|
|
29
|
-
*/
|
|
30
|
-
const WebLogger = {
|
|
31
|
-
debug: createLoggerMethod('debug'),
|
|
32
|
-
info: createLoggerMethod('info'),
|
|
33
|
-
error: createLoggerMethod('error'),
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default WebLogger
|
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
import maplibregl, { type MapLayerEventType } from 'maplibre-gl'
|
|
2
|
-
import type ReactNativeBridge from 'react-native-maplibre-gl-js/web/bridge/ReactNativeBridge'
|
|
3
|
-
import {
|
|
4
|
-
type HTMLElementDescriptor,
|
|
5
|
-
type MessageFromRNToWeb,
|
|
6
|
-
type WebObjectClass,
|
|
7
|
-
} from 'react-native-maplibre-gl-js/communication/messages.types'
|
|
8
|
-
import WebLogger from 'react-native-maplibre-gl-js/web/logger/web-logger'
|
|
9
|
-
import {
|
|
10
|
-
isWebObjectListenerOnHTMLElement,
|
|
11
|
-
isWebObjectListenerOnMapLayer,
|
|
12
|
-
isWebObjectListenerOnObject,
|
|
13
|
-
} from 'react-native-maplibre-gl-js/communication/messages.utils'
|
|
14
|
-
import type {
|
|
15
|
-
WebObjectListenerOnMapLayer,
|
|
16
|
-
WebObjectListeners,
|
|
17
|
-
} from 'react-native-maplibre-gl-js/react-native/components-factory/createWebObjectAsComponent.types'
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Manage the MapLibre GL JS map and its objects. Receive messages from the
|
|
21
|
-
* React Native world and act accordingly.
|
|
22
|
-
*/
|
|
23
|
-
export default class MapController {
|
|
24
|
-
#reactNativeBridge?: ReactNativeBridge
|
|
25
|
-
#objects = new Map<string, WebObjectClass>()
|
|
26
|
-
#mapId: string | undefined
|
|
27
|
-
|
|
28
|
-
get reactNativeBridge(): ReactNativeBridge {
|
|
29
|
-
if (!this.#reactNativeBridge) {
|
|
30
|
-
throw new Error('React Native bridge not available')
|
|
31
|
-
}
|
|
32
|
-
return this.#reactNativeBridge
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
set reactNativeBridge(bridge: ReactNativeBridge) {
|
|
36
|
-
this.#reactNativeBridge = bridge
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get map(): maplibregl.Map {
|
|
40
|
-
const map = this.#objects.get(this.#mapId ?? '')
|
|
41
|
-
if (!map) {
|
|
42
|
-
throw new Error('Map not available')
|
|
43
|
-
}
|
|
44
|
-
return map as maplibregl.Map
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
handleMessage = (message: MessageFromRNToWeb) => {
|
|
48
|
-
WebLogger.info(this.handleMessage.name, message)
|
|
49
|
-
|
|
50
|
-
switch (message.type) {
|
|
51
|
-
case 'webObjectMount': {
|
|
52
|
-
this.#handleWebObjectMountMessage(message)
|
|
53
|
-
break
|
|
54
|
-
}
|
|
55
|
-
case 'webObjectUnmount': {
|
|
56
|
-
this.#handleWebObjectUnmountMessage(message)
|
|
57
|
-
break
|
|
58
|
-
}
|
|
59
|
-
case 'webObjectMethodCall': {
|
|
60
|
-
this.#handleWebObjectMethodCall(message).then()
|
|
61
|
-
break
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
#handleWebObjectMountMessage = (
|
|
67
|
-
message: Extract<MessageFromRNToWeb, { type: 'webObjectMount' }>,
|
|
68
|
-
) => {
|
|
69
|
-
switch (message.payload.objectType) {
|
|
70
|
-
case 'map': {
|
|
71
|
-
// 1) Create the MapLibre element.
|
|
72
|
-
const container = document.getElementById('app')!
|
|
73
|
-
const map = new maplibregl.Map({
|
|
74
|
-
...message.payload.options,
|
|
75
|
-
container,
|
|
76
|
-
})
|
|
77
|
-
this.#objects.set(message.payload.objectId, map)
|
|
78
|
-
this.#mapId = message.payload.objectId
|
|
79
|
-
// 2) Add listeners on the map and/or HTML element.
|
|
80
|
-
this.#setObjectListeners(
|
|
81
|
-
map,
|
|
82
|
-
message.payload.objectId,
|
|
83
|
-
message.payload.listeners,
|
|
84
|
-
)
|
|
85
|
-
break
|
|
86
|
-
}
|
|
87
|
-
case 'marker': {
|
|
88
|
-
// default marker element
|
|
89
|
-
const element = this.#buildHTMLElement(message.payload.options.element)
|
|
90
|
-
// 1) Create the MapLibre element.
|
|
91
|
-
const marker = new maplibregl.Marker({
|
|
92
|
-
...message.payload.options,
|
|
93
|
-
element,
|
|
94
|
-
})
|
|
95
|
-
// TODO setup default location (needed by default)
|
|
96
|
-
.setLngLat([0, 0])
|
|
97
|
-
.addTo(this.map)
|
|
98
|
-
this.#objects.set(message.payload.objectId, marker)
|
|
99
|
-
// 2) Add listeners on the map and/or HTML element.
|
|
100
|
-
this.#setObjectListeners(
|
|
101
|
-
marker,
|
|
102
|
-
message.payload.objectId,
|
|
103
|
-
message.payload.listeners,
|
|
104
|
-
)
|
|
105
|
-
break
|
|
106
|
-
}
|
|
107
|
-
case 'popup': {
|
|
108
|
-
// 1) Create the MapLibre element.
|
|
109
|
-
const popup = new maplibregl.Popup({
|
|
110
|
-
...message.payload.options,
|
|
111
|
-
})
|
|
112
|
-
//.addTo(this.map)
|
|
113
|
-
this.#objects.set(message.payload.objectId, popup)
|
|
114
|
-
// 2) Add listeners on the map and/or HTML element.
|
|
115
|
-
this.#setObjectListeners(
|
|
116
|
-
popup,
|
|
117
|
-
message.payload.objectId,
|
|
118
|
-
message.payload.listeners,
|
|
119
|
-
)
|
|
120
|
-
break
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
// TODO confirm its indeed mounted.
|
|
124
|
-
this.reactNativeBridge.postMessage({
|
|
125
|
-
type: 'webObjectListenerEvent',
|
|
126
|
-
payload: {
|
|
127
|
-
objectId: message.payload.objectId,
|
|
128
|
-
eventName: 'mount',
|
|
129
|
-
},
|
|
130
|
-
})
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
#handleWebObjectUnmountMessage = (
|
|
134
|
-
message: Extract<MessageFromRNToWeb, { type: 'webObjectUnmount' }>,
|
|
135
|
-
) => {
|
|
136
|
-
const object = this.#objects.get(message.payload.objectId)
|
|
137
|
-
if (!object) {
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
object.remove()
|
|
142
|
-
this.#objects.delete(message.payload.objectId)
|
|
143
|
-
|
|
144
|
-
this.reactNativeBridge.postMessage({
|
|
145
|
-
type: 'webObjectListenerEvent',
|
|
146
|
-
payload: {
|
|
147
|
-
objectId: message.payload.objectId,
|
|
148
|
-
eventName: 'unmount',
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
#handleWebObjectMethodCall = async (
|
|
154
|
-
message: Extract<MessageFromRNToWeb, { type: 'webObjectMethodCall' }>,
|
|
155
|
-
) => {
|
|
156
|
-
const object = this.#objects.get(message.payload.objectId)
|
|
157
|
-
|
|
158
|
-
if (!object) {
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
let result
|
|
163
|
-
|
|
164
|
-
if (!this.#runIfSpecialMethod(message, object)) {
|
|
165
|
-
result = await this.#runNormalMethod(message, object)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (!(object instanceof maplibregl.Map)) {
|
|
169
|
-
// Always add the object back to the map in case it was removed
|
|
170
|
-
// (e.g., Popup's setLngLat or setHTML methods remove it from the map).
|
|
171
|
-
object.addTo(this.map)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
this.reactNativeBridge.postMessage({
|
|
175
|
-
type: 'webObjectMethodResponse',
|
|
176
|
-
payload: { requestId: message.payload.requestId, result },
|
|
177
|
-
})
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
#runIfSpecialMethod = (
|
|
181
|
-
message: Extract<MessageFromRNToWeb, { type: 'webObjectMethodCall' }>,
|
|
182
|
-
object: WebObjectClass,
|
|
183
|
-
) => {
|
|
184
|
-
// Special cases for methods that have special parameters not compatible
|
|
185
|
-
// with RN (see RN component types definitions). These methods always return
|
|
186
|
-
// something. Return undefined if the method is not special.
|
|
187
|
-
|
|
188
|
-
if (object instanceof maplibregl.Marker) {
|
|
189
|
-
switch (message.payload.method) {
|
|
190
|
-
case 'addTo': {
|
|
191
|
-
object.addTo(this.map)
|
|
192
|
-
return true
|
|
193
|
-
}
|
|
194
|
-
case 'setEventedParent': {
|
|
195
|
-
const parentId = message.payload.args[0] as string
|
|
196
|
-
const parent = this.#objects.get(parentId) ?? null
|
|
197
|
-
if (parent) {
|
|
198
|
-
object.setEventedParent(parent)
|
|
199
|
-
}
|
|
200
|
-
return true
|
|
201
|
-
}
|
|
202
|
-
case 'setPopup': {
|
|
203
|
-
const popupId = message.payload.args[0] as string
|
|
204
|
-
const popup = this.#objects.get(popupId) ?? null
|
|
205
|
-
if (popup && popup instanceof maplibregl.Popup) {
|
|
206
|
-
object.setPopup(popup)
|
|
207
|
-
}
|
|
208
|
-
return true
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (object instanceof maplibregl.Popup) {
|
|
213
|
-
switch (message.payload.method) {
|
|
214
|
-
case 'addTo': {
|
|
215
|
-
object.addTo(this.map)
|
|
216
|
-
return true
|
|
217
|
-
}
|
|
218
|
-
case 'setEventedParent': {
|
|
219
|
-
const parentId = message.payload.args[0] as string
|
|
220
|
-
const parent = this.#objects.get(parentId) ?? null
|
|
221
|
-
if (parent) {
|
|
222
|
-
object.setEventedParent(parent)
|
|
223
|
-
}
|
|
224
|
-
return true
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return false
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
#runNormalMethod = async (
|
|
232
|
-
message: Extract<MessageFromRNToWeb, { type: 'webObjectMethodCall' }>,
|
|
233
|
-
object: WebObjectClass,
|
|
234
|
-
) => {
|
|
235
|
-
return await object[message.payload.method as keyof typeof object]?.(
|
|
236
|
-
...message.payload.args,
|
|
237
|
-
)
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
#buildHTMLElement = (
|
|
241
|
-
descriptor?: HTMLElementDescriptor,
|
|
242
|
-
): HTMLElement | undefined => {
|
|
243
|
-
// From a descriptor, build the corresponding HTMLElement.
|
|
244
|
-
if (!descriptor) {
|
|
245
|
-
return undefined
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const element = document.createElement(descriptor.tagName ?? 'div')
|
|
249
|
-
element.className = descriptor.className ?? ''
|
|
250
|
-
|
|
251
|
-
if (descriptor.attributes) {
|
|
252
|
-
for (const [name, value] of Object.entries(descriptor.attributes)) {
|
|
253
|
-
element.setAttribute(name, value)
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (descriptor.style) {
|
|
257
|
-
Object.assign(element.style, descriptor.style)
|
|
258
|
-
}
|
|
259
|
-
if (descriptor.dataset) {
|
|
260
|
-
for (const [name, value] of Object.entries(descriptor.dataset)) {
|
|
261
|
-
;(element.dataset as any)[name] = value
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
if (descriptor.innerHTML !== undefined) {
|
|
265
|
-
element.innerHTML = descriptor.innerHTML
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return element
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
#setObjectListeners = (
|
|
272
|
-
object: WebObjectClass,
|
|
273
|
-
objectId: string,
|
|
274
|
-
listeners?: WebObjectListeners,
|
|
275
|
-
) => {
|
|
276
|
-
if (!listeners) {
|
|
277
|
-
return
|
|
278
|
-
}
|
|
279
|
-
Object.entries(listeners).forEach(([eventName, listener]) => {
|
|
280
|
-
const sendEventToReactNative = (event: any) => {
|
|
281
|
-
// Remove circular references that cannot be serialized.
|
|
282
|
-
delete event.target
|
|
283
|
-
// Send the event to the React Native listener.
|
|
284
|
-
this.reactNativeBridge.postMessage({
|
|
285
|
-
type: 'webObjectListenerEvent',
|
|
286
|
-
payload: {
|
|
287
|
-
objectId,
|
|
288
|
-
eventName,
|
|
289
|
-
event,
|
|
290
|
-
},
|
|
291
|
-
})
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Attach the listener to the object.
|
|
295
|
-
if (isWebObjectListenerOnObject(listener)) {
|
|
296
|
-
object.on(eventName, sendEventToReactNative)
|
|
297
|
-
}
|
|
298
|
-
// Attach the listener to a map layer.
|
|
299
|
-
if (isWebObjectListenerOnMapLayer(listener)) {
|
|
300
|
-
// Listening to only one layer of the map is only possible on map
|
|
301
|
-
// events.
|
|
302
|
-
if (object instanceof maplibregl.Map) {
|
|
303
|
-
object.on(
|
|
304
|
-
eventName as keyof MapLayerEventType,
|
|
305
|
-
(listener as WebObjectListenerOnMapLayer<any>).layerId,
|
|
306
|
-
sendEventToReactNative,
|
|
307
|
-
)
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
// Attach the listener to the HTML element of the object
|
|
311
|
-
if (isWebObjectListenerOnHTMLElement(listener)) {
|
|
312
|
-
// Listening to the HTML element events is not possible on the map
|
|
313
|
-
// object.
|
|
314
|
-
if (!(object instanceof maplibregl.Map)) {
|
|
315
|
-
object
|
|
316
|
-
.getElement()
|
|
317
|
-
.addEventListener(eventName, sendEventToReactNative)
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
})
|
|
321
|
-
}
|
|
322
|
-
}
|