@lugg/maps 0.2.0-alpha.9 → 1.0.0-beta.0

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 (173) hide show
  1. package/README.md +20 -19
  2. package/android/src/main/java/com/luggmaps/LuggMapView.kt +290 -0
  3. package/android/src/main/java/com/luggmaps/{LuggGoogleMapViewManager.kt → LuggMapViewManager.kt} +99 -36
  4. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +13 -5
  5. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +157 -13
  6. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +28 -0
  7. package/android/src/main/java/com/luggmaps/LuggPackage.kt +1 -4
  8. package/android/src/main/java/com/luggmaps/LuggPolygonView.kt +85 -0
  9. package/android/src/main/java/com/luggmaps/LuggPolygonViewManager.kt +100 -0
  10. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
  11. package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
  12. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +698 -0
  13. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +60 -0
  14. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +89 -24
  15. package/android/src/main/java/com/luggmaps/events/LongPressEvent.kt +29 -0
  16. package/android/src/main/java/com/luggmaps/events/MarkerDragEvent.kt +41 -0
  17. package/android/src/main/java/com/luggmaps/events/MarkerPressEvent.kt +34 -0
  18. package/android/src/main/java/com/luggmaps/events/PolygonPressEvent.kt +12 -0
  19. package/android/src/main/java/com/luggmaps/events/PressEvent.kt +29 -0
  20. package/ios/LuggMapView.h +9 -0
  21. package/ios/LuggMapView.mm +343 -0
  22. package/ios/LuggMarkerView.h +13 -0
  23. package/ios/LuggMarkerView.mm +119 -0
  24. package/ios/LuggPolygonView.h +31 -0
  25. package/ios/LuggPolygonView.mm +151 -0
  26. package/ios/LuggPolylineView.h +4 -0
  27. package/ios/LuggPolylineView.mm +23 -0
  28. package/ios/core/AppleMapProvider.h +15 -0
  29. package/ios/core/AppleMapProvider.mm +1029 -0
  30. package/ios/core/GMSPolylineAnimator.h +3 -0
  31. package/ios/core/GMSPolylineAnimator.m +101 -15
  32. package/ios/core/GoogleMapProvider.h +13 -0
  33. package/ios/core/GoogleMapProvider.mm +689 -0
  34. package/ios/core/MKPolylineAnimator.h +4 -0
  35. package/ios/core/MKPolylineAnimator.m +167 -42
  36. package/ios/core/MapProviderDelegate.h +84 -0
  37. package/ios/core/PolylineAnimatorBase.h +24 -1
  38. package/ios/core/PolylineAnimatorBase.m +82 -19
  39. package/ios/events/LongPressEvent.h +29 -0
  40. package/ios/events/MarkerDragEvent.h +69 -0
  41. package/ios/events/MarkerPressEvent.h +29 -0
  42. package/ios/events/PolygonPressEvent.h +20 -0
  43. package/ios/events/PressEvent.h +29 -0
  44. package/ios/extensions/MKMapView+Zoom.h +2 -0
  45. package/ios/extensions/MKMapView+Zoom.m +14 -4
  46. package/lib/module/MapProvider.js +2 -4
  47. package/lib/module/MapProvider.js.map +1 -1
  48. package/lib/module/MapProvider.web.js +12 -7
  49. package/lib/module/MapProvider.web.js.map +1 -1
  50. package/lib/module/MapView.js +33 -16
  51. package/lib/module/MapView.js.map +1 -1
  52. package/lib/module/MapView.web.js +283 -181
  53. package/lib/module/MapView.web.js.map +1 -1
  54. package/lib/module/components/GeoJson.js +159 -0
  55. package/lib/module/components/GeoJson.js.map +1 -0
  56. package/lib/module/components/GeoJson.types.js +4 -0
  57. package/lib/module/components/GeoJson.types.js.map +1 -0
  58. package/lib/module/components/Marker.js +28 -4
  59. package/lib/module/components/Marker.js.map +1 -1
  60. package/lib/module/components/Marker.types.js +4 -0
  61. package/lib/module/components/Marker.types.js.map +1 -0
  62. package/lib/module/components/Marker.web.js +98 -27
  63. package/lib/module/components/Marker.web.js.map +1 -1
  64. package/lib/module/components/Polygon.js +46 -0
  65. package/lib/module/components/Polygon.js.map +1 -0
  66. package/lib/module/components/Polygon.types.js +4 -0
  67. package/lib/module/components/Polygon.types.js.map +1 -0
  68. package/lib/module/components/Polygon.web.js +87 -0
  69. package/lib/module/components/Polygon.web.js.map +1 -0
  70. package/lib/module/components/Polyline.js +17 -4
  71. package/lib/module/components/Polyline.js.map +1 -1
  72. package/lib/module/components/Polyline.types.js +4 -0
  73. package/lib/module/components/Polyline.types.js.map +1 -0
  74. package/lib/module/components/Polyline.web.js +108 -31
  75. package/lib/module/components/Polyline.web.js.map +1 -1
  76. package/lib/module/components/index.js +4 -2
  77. package/lib/module/components/index.js.map +1 -1
  78. package/lib/module/components/index.web.js +2 -0
  79. package/lib/module/components/index.web.js.map +1 -1
  80. package/lib/module/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
  81. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +49 -1
  82. package/lib/module/fabric/LuggPolygonViewNativeComponent.ts +25 -0
  83. package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  84. package/lib/module/index.js +4 -1
  85. package/lib/module/index.js.map +1 -1
  86. package/lib/module/index.web.js +4 -1
  87. package/lib/module/index.web.js.map +1 -1
  88. package/lib/typescript/src/MapProvider.d.ts +1 -1
  89. package/lib/typescript/src/MapProvider.d.ts.map +1 -1
  90. package/lib/typescript/src/MapProvider.web.d.ts +17 -1
  91. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
  92. package/lib/typescript/src/MapView.d.ts +4 -4
  93. package/lib/typescript/src/MapView.d.ts.map +1 -1
  94. package/lib/typescript/src/MapView.types.d.ts +35 -9
  95. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  96. package/lib/typescript/src/MapView.web.d.ts +2 -11
  97. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  98. package/lib/typescript/src/components/GeoJson.d.ts +4 -0
  99. package/lib/typescript/src/components/GeoJson.d.ts.map +1 -0
  100. package/lib/typescript/src/components/GeoJson.types.d.ts +79 -0
  101. package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -0
  102. package/lib/typescript/src/components/Marker.d.ts +6 -33
  103. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  104. package/lib/typescript/src/components/Marker.types.d.ts +74 -0
  105. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -0
  106. package/lib/typescript/src/components/Marker.web.d.ts +2 -5
  107. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  108. package/lib/typescript/src/components/Polygon.d.ts +10 -0
  109. package/lib/typescript/src/components/Polygon.d.ts.map +1 -0
  110. package/lib/typescript/src/components/Polygon.types.d.ts +33 -0
  111. package/lib/typescript/src/components/Polygon.types.d.ts.map +1 -0
  112. package/lib/typescript/src/components/Polygon.web.d.ts +3 -0
  113. package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -0
  114. package/lib/typescript/src/components/Polyline.d.ts +6 -21
  115. package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
  116. package/lib/typescript/src/components/Polyline.types.d.ts +53 -0
  117. package/lib/typescript/src/components/Polyline.types.d.ts.map +1 -0
  118. package/lib/typescript/src/components/Polyline.web.d.ts +2 -5
  119. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
  120. package/lib/typescript/src/components/index.d.ts +8 -2
  121. package/lib/typescript/src/components/index.d.ts.map +1 -1
  122. package/lib/typescript/src/components/index.web.d.ts +6 -2
  123. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  124. package/lib/typescript/src/fabric/{LuggGoogleMapViewNativeComponent.d.ts → LuggMapViewNativeComponent.d.ts} +30 -4
  125. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -0
  126. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +45 -1
  127. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  128. package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts +18 -0
  129. package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts.map +1 -0
  130. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
  131. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
  132. package/lib/typescript/src/index.d.ts +11 -3
  133. package/lib/typescript/src/index.d.ts.map +1 -1
  134. package/lib/typescript/src/index.web.d.ts +9 -1
  135. package/lib/typescript/src/index.web.d.ts.map +1 -1
  136. package/lib/typescript/src/types.d.ts +11 -0
  137. package/lib/typescript/src/types.d.ts.map +1 -1
  138. package/package.json +10 -9
  139. package/src/MapProvider.tsx +1 -3
  140. package/src/MapProvider.web.tsx +12 -3
  141. package/src/MapView.tsx +32 -26
  142. package/src/MapView.types.ts +43 -9
  143. package/src/MapView.web.tsx +345 -211
  144. package/src/components/GeoJson.tsx +221 -0
  145. package/src/components/GeoJson.types.ts +107 -0
  146. package/src/components/Marker.tsx +45 -36
  147. package/src/components/Marker.types.ts +75 -0
  148. package/src/components/Marker.web.tsx +116 -28
  149. package/src/components/Polygon.tsx +52 -0
  150. package/src/components/Polygon.types.ts +33 -0
  151. package/src/components/Polygon.web.tsx +104 -0
  152. package/src/components/Polyline.tsx +23 -22
  153. package/src/components/Polyline.types.ts +55 -0
  154. package/src/components/Polyline.web.tsx +151 -37
  155. package/src/components/index.ts +16 -2
  156. package/src/components/index.web.ts +6 -2
  157. package/src/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
  158. package/src/fabric/LuggMarkerViewNativeComponent.ts +49 -1
  159. package/src/fabric/LuggPolygonViewNativeComponent.ts +25 -0
  160. package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  161. package/src/index.ts +28 -1
  162. package/src/index.web.ts +15 -1
  163. package/src/types.ts +13 -0
  164. package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +0 -511
  165. package/ios/LuggAppleMapView.h +0 -16
  166. package/ios/LuggAppleMapView.mm +0 -592
  167. package/ios/LuggGoogleMapView.h +0 -13
  168. package/ios/LuggGoogleMapView.mm +0 -455
  169. package/lib/module/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
  170. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts +0 -54
  171. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +0 -1
  172. package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +0 -1
  173. package/src/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
@@ -0,0 +1,221 @@
1
+ import React, { useMemo, type ReactElement } from 'react';
2
+ import type {
3
+ Feature,
4
+ FeatureCollection,
5
+ GeoJSON,
6
+ Geometry,
7
+ Position,
8
+ } from './GeoJson.types';
9
+ import type { Coordinate } from '../types';
10
+ import type { GeoJsonProps } from './GeoJson.types';
11
+ import { Marker } from './Marker';
12
+ import type { MarkerProps } from './Marker.types';
13
+ import { Polygon } from './Polygon';
14
+ import type { PolygonProps } from './Polygon.types';
15
+ import { Polyline } from './Polyline';
16
+ import type { PolylineProps } from './Polyline.types';
17
+
18
+ export type { GeoJsonProps } from './GeoJson.types';
19
+
20
+ const toCoordinate = (position: Position): Coordinate => ({
21
+ latitude: position[1],
22
+ longitude: position[0],
23
+ });
24
+
25
+ const toCoordinates = (positions: Position[]): Coordinate[] =>
26
+ positions.map(toCoordinate);
27
+
28
+ const normalizeFeatures = (geojson: GeoJSON): Feature[] => {
29
+ switch (geojson.type) {
30
+ case 'FeatureCollection':
31
+ return (geojson as FeatureCollection).features;
32
+ case 'Feature':
33
+ return [geojson as Feature];
34
+ default:
35
+ return [
36
+ { type: 'Feature', geometry: geojson as Geometry, properties: null },
37
+ ];
38
+ }
39
+ };
40
+
41
+ const renderGeometry = (
42
+ geometry: Geometry,
43
+ feature: Feature,
44
+ props: GeoJsonProps,
45
+ keyPrefix: string
46
+ ): ReactElement[] => {
47
+ const elements: ReactElement[] = [];
48
+
49
+ switch (geometry.type) {
50
+ case 'Point': {
51
+ const markerProps: MarkerProps = {
52
+ coordinate: toCoordinate(geometry.coordinates),
53
+ title: feature.properties?.title,
54
+ description: feature.properties?.description,
55
+ zIndex: props.zIndex,
56
+ };
57
+ elements.push(
58
+ props.renderMarker ? (
59
+ props.renderMarker(markerProps, feature) ?? (
60
+ <React.Fragment key={keyPrefix} />
61
+ )
62
+ ) : (
63
+ <Marker key={keyPrefix} {...markerProps} />
64
+ )
65
+ );
66
+ break;
67
+ }
68
+ case 'MultiPoint': {
69
+ for (let i = 0; i < geometry.coordinates.length; i++) {
70
+ const markerProps: MarkerProps = {
71
+ coordinate: toCoordinate(geometry.coordinates[i]!),
72
+ title: feature.properties?.title,
73
+ description: feature.properties?.description,
74
+ zIndex: props.zIndex,
75
+ };
76
+ const key = `${keyPrefix}-${i}`;
77
+ elements.push(
78
+ props.renderMarker ? (
79
+ props.renderMarker(markerProps, feature) ?? (
80
+ <React.Fragment key={key} />
81
+ )
82
+ ) : (
83
+ <Marker key={key} {...markerProps} />
84
+ )
85
+ );
86
+ }
87
+ break;
88
+ }
89
+ case 'LineString': {
90
+ const p = feature.properties;
91
+ const polylineProps: PolylineProps = {
92
+ coordinates: toCoordinates(geometry.coordinates),
93
+ strokeColors: p?.stroke ? [p.stroke] : undefined,
94
+ strokeWidth: p?.['stroke-width'],
95
+ zIndex: props.zIndex,
96
+ };
97
+ elements.push(
98
+ props.renderPolyline ? (
99
+ props.renderPolyline(polylineProps, feature) ?? (
100
+ <React.Fragment key={keyPrefix} />
101
+ )
102
+ ) : (
103
+ <Polyline key={keyPrefix} {...polylineProps} />
104
+ )
105
+ );
106
+ break;
107
+ }
108
+ case 'MultiLineString': {
109
+ const p = feature.properties;
110
+ for (let i = 0; i < geometry.coordinates.length; i++) {
111
+ const polylineProps: PolylineProps = {
112
+ coordinates: toCoordinates(geometry.coordinates[i]!),
113
+ strokeColors: p?.stroke ? [p.stroke] : undefined,
114
+ strokeWidth: p?.['stroke-width'],
115
+ zIndex: props.zIndex,
116
+ };
117
+ const key = `${keyPrefix}-${i}`;
118
+ elements.push(
119
+ props.renderPolyline ? (
120
+ props.renderPolyline(polylineProps, feature) ?? (
121
+ <React.Fragment key={key} />
122
+ )
123
+ ) : (
124
+ <Polyline key={key} {...polylineProps} />
125
+ )
126
+ );
127
+ }
128
+ break;
129
+ }
130
+ case 'Polygon': {
131
+ const outer = toCoordinates(geometry.coordinates[0]!);
132
+ const holes =
133
+ geometry.coordinates.length > 1
134
+ ? geometry.coordinates.slice(1).map(toCoordinates)
135
+ : undefined;
136
+ const p = feature.properties;
137
+ const polygonProps: PolygonProps = {
138
+ coordinates: outer,
139
+ holes,
140
+ fillColor: p?.fill,
141
+ strokeColor: p?.stroke,
142
+ strokeWidth: p?.['stroke-width'],
143
+ zIndex: props.zIndex,
144
+ };
145
+ elements.push(
146
+ props.renderPolygon ? (
147
+ props.renderPolygon(polygonProps, feature) ?? (
148
+ <React.Fragment key={keyPrefix} />
149
+ )
150
+ ) : (
151
+ <Polygon key={keyPrefix} {...polygonProps} />
152
+ )
153
+ );
154
+ break;
155
+ }
156
+ case 'MultiPolygon': {
157
+ const p = feature.properties;
158
+ for (let i = 0; i < geometry.coordinates.length; i++) {
159
+ const rings = geometry.coordinates[i]!;
160
+ const outer = toCoordinates(rings[0]!);
161
+ const holes =
162
+ rings.length > 1 ? rings.slice(1).map(toCoordinates) : undefined;
163
+ const polygonProps: PolygonProps = {
164
+ coordinates: outer,
165
+ holes,
166
+ fillColor: p?.fill,
167
+ strokeColor: p?.stroke,
168
+ strokeWidth: p?.['stroke-width'],
169
+ zIndex: props.zIndex,
170
+ };
171
+ const key = `${keyPrefix}-${i}`;
172
+ elements.push(
173
+ props.renderPolygon ? (
174
+ props.renderPolygon(polygonProps, feature) ?? (
175
+ <React.Fragment key={key} />
176
+ )
177
+ ) : (
178
+ <Polygon key={key} {...polygonProps} />
179
+ )
180
+ );
181
+ }
182
+ break;
183
+ }
184
+ case 'GeometryCollection': {
185
+ for (let i = 0; i < geometry.geometries.length; i++) {
186
+ elements.push(
187
+ ...renderGeometry(
188
+ geometry.geometries[i]!,
189
+ feature,
190
+ props,
191
+ `${keyPrefix}-${i}`
192
+ )
193
+ );
194
+ }
195
+ break;
196
+ }
197
+ }
198
+
199
+ return elements;
200
+ };
201
+
202
+ export const GeoJson = (props: GeoJsonProps) => {
203
+ const { geojson } = props;
204
+
205
+ const elements = useMemo(() => {
206
+ const features = normalizeFeatures(geojson);
207
+ const result: ReactElement[] = [];
208
+
209
+ for (let i = 0; i < features.length; i++) {
210
+ const feature = features[i]!;
211
+ if (!feature.geometry) continue;
212
+
213
+ const key = feature.id != null ? String(feature.id) : String(i);
214
+ result.push(...renderGeometry(feature.geometry, feature, props, key));
215
+ }
216
+
217
+ return result;
218
+ }, [geojson, props]);
219
+
220
+ return <>{elements}</>;
221
+ };
@@ -0,0 +1,107 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { MarkerProps } from './Marker.types';
3
+ import type { PolygonProps } from './Polygon.types';
4
+ import type { PolylineProps } from './Polyline.types';
5
+
6
+ /**
7
+ * GeoJSON types per RFC 7946
8
+ * Note: GeoJSON positions use [longitude, latitude] order
9
+ */
10
+
11
+ export type Position =
12
+ | [longitude: number, latitude: number]
13
+ | [longitude: number, latitude: number, altitude: number];
14
+
15
+ export interface Point {
16
+ type: 'Point';
17
+ coordinates: Position;
18
+ }
19
+
20
+ export interface MultiPoint {
21
+ type: 'MultiPoint';
22
+ coordinates: Position[];
23
+ }
24
+
25
+ export interface LineString {
26
+ type: 'LineString';
27
+ coordinates: Position[];
28
+ }
29
+
30
+ export interface MultiLineString {
31
+ type: 'MultiLineString';
32
+ coordinates: Position[][];
33
+ }
34
+
35
+ export interface Polygon {
36
+ type: 'Polygon';
37
+ coordinates: Position[][];
38
+ }
39
+
40
+ export interface MultiPolygon {
41
+ type: 'MultiPolygon';
42
+ coordinates: Position[][][];
43
+ }
44
+
45
+ export interface GeometryCollection {
46
+ type: 'GeometryCollection';
47
+ geometries: Geometry[];
48
+ }
49
+
50
+ export type Geometry =
51
+ | Point
52
+ | MultiPoint
53
+ | LineString
54
+ | MultiLineString
55
+ | Polygon
56
+ | MultiPolygon
57
+ | GeometryCollection;
58
+
59
+ export interface Feature<G extends Geometry = Geometry> {
60
+ type: 'Feature';
61
+ id?: string | number;
62
+ geometry: G;
63
+ properties: Record<string, any> | null;
64
+ }
65
+
66
+ export interface FeatureCollection<G extends Geometry = Geometry> {
67
+ type: 'FeatureCollection';
68
+ features: Feature<G>[];
69
+ }
70
+
71
+ export type GeoJSON = Geometry | Feature | FeatureCollection;
72
+
73
+ export interface GeoJsonProps {
74
+ /**
75
+ * GeoJSON data to render.
76
+ * Accepts a `FeatureCollection`, `Feature`, or bare `Geometry`.
77
+ */
78
+ geojson: GeoJSON;
79
+ /**
80
+ * Z-index for all rendered features.
81
+ */
82
+ zIndex?: number;
83
+ /**
84
+ * Custom render function for `Point`/`MultiPoint` features.
85
+ * @param props - Default `MarkerProps` derived from the geometry.
86
+ * @param feature - The source GeoJSON `Feature`.
87
+ */
88
+ renderMarker?: (props: MarkerProps, feature: Feature) => ReactElement | null;
89
+ /**
90
+ * Custom render function for `LineString`/`MultiLineString` features.
91
+ * @param props - Default `PolylineProps` derived from the geometry.
92
+ * @param feature - The source GeoJSON `Feature`.
93
+ */
94
+ renderPolyline?: (
95
+ props: PolylineProps,
96
+ feature: Feature
97
+ ) => ReactElement | null;
98
+ /**
99
+ * Custom render function for `Polygon`/`MultiPolygon` features.
100
+ * @param props - Default `PolygonProps` derived from the geometry.
101
+ * @param feature - The source GeoJSON `Feature`.
102
+ */
103
+ renderPolygon?: (
104
+ props: PolygonProps,
105
+ feature: Feature
106
+ ) => ReactElement | null;
107
+ }
@@ -1,53 +1,62 @@
1
1
  import React from 'react';
2
- import type { ReactNode } from 'react';
3
2
  import { StyleSheet } from 'react-native';
4
3
  import LuggMarkerViewNativeComponent from '../fabric/LuggMarkerViewNativeComponent';
5
- import type { Coordinate, Point } from '../types';
4
+ import type { MarkerProps } from './Marker.types';
6
5
 
7
- export interface MarkerProps {
8
- /**
9
- * Name used for debugging purposes
10
- */
11
- name?: string;
12
- /**
13
- * Marker position
14
- */
15
- coordinate: Coordinate;
16
- /**
17
- * Callout title
18
- */
19
- title?: string;
20
- /**
21
- * Callout description
22
- */
23
- description?: string;
24
- /**
25
- * Anchor point for custom marker views
26
- */
27
- anchor?: Point;
28
- /**
29
- * Z-index for marker ordering. Higher values render on top.
30
- */
31
- zIndex?: number;
32
- /**
33
- * Custom marker view
34
- */
35
- children?: ReactNode;
36
- }
6
+ export type {
7
+ MarkerProps,
8
+ MarkerPressEvent,
9
+ MarkerDragEvent,
10
+ } from './Marker.types';
11
+
12
+ export class Marker extends React.PureComponent<MarkerProps> {
13
+ private getStyle(zIndex: number | undefined) {
14
+ if (zIndex == null) return styles.marker;
15
+ if (zIndex !== this._cachedZIndex) {
16
+ this._cachedZIndex = zIndex;
17
+ this._cachedStyle = [{ zIndex }, styles.marker];
18
+ }
19
+ return this._cachedStyle!;
20
+ }
21
+
22
+ private _cachedZIndex: number | undefined;
23
+ private _cachedStyle: any;
37
24
 
38
- export class Marker extends React.Component<MarkerProps> {
39
25
  render() {
40
- const { name, coordinate, title, description, anchor, zIndex, children } =
41
- this.props;
26
+ const {
27
+ name,
28
+ coordinate,
29
+ title,
30
+ description,
31
+ anchor,
32
+ zIndex,
33
+ rotate = 0,
34
+ scale = 1,
35
+ rasterize = true,
36
+ draggable = false,
37
+ onPress,
38
+ onDragStart,
39
+ onDragChange,
40
+ onDragEnd,
41
+ children,
42
+ } = this.props;
42
43
 
43
44
  return (
44
45
  <LuggMarkerViewNativeComponent
45
- style={[{ zIndex }, styles.marker]}
46
+ style={this.getStyle(zIndex)}
46
47
  name={name}
47
48
  coordinate={coordinate}
48
49
  title={title}
49
50
  description={description}
50
51
  anchor={anchor}
52
+ rotate={rotate}
53
+ scale={scale}
54
+ rasterize={rasterize}
55
+ draggable={draggable}
56
+ onMarkerPress={onPress}
57
+ onMarkerDragStart={onDragStart}
58
+ onMarkerDragChange={onDragChange}
59
+ onMarkerDragEnd={onDragEnd}
51
60
  >
52
61
  {children}
53
62
  </LuggMarkerViewNativeComponent>
@@ -0,0 +1,75 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { NativeSyntheticEvent } from 'react-native';
3
+ import type { Coordinate, Point, PressEventPayload } from '../types';
4
+
5
+ export type MarkerPressEvent = NativeSyntheticEvent<PressEventPayload>;
6
+ export type MarkerDragEvent = NativeSyntheticEvent<PressEventPayload>;
7
+
8
+ export interface MarkerProps {
9
+ /**
10
+ * Name used for debugging purposes
11
+ */
12
+ name?: string;
13
+ /**
14
+ * Marker position
15
+ */
16
+ coordinate: Coordinate;
17
+ /**
18
+ * Callout title
19
+ */
20
+ title?: string;
21
+ /**
22
+ * Callout description
23
+ */
24
+ description?: string;
25
+ /**
26
+ * Anchor point for custom marker views
27
+ */
28
+ anchor?: Point;
29
+ /**
30
+ * Z-index for marker ordering. Higher values render on top.
31
+ */
32
+ zIndex?: number;
33
+ /**
34
+ * Rotation angle in degrees clockwise from north.
35
+ * @default 0
36
+ */
37
+ rotate?: number;
38
+ /**
39
+ * Scale factor for the marker.
40
+ * @default 1
41
+ */
42
+ scale?: number;
43
+ /**
44
+ * Rasterize custom marker view to bitmap for better performance.
45
+ * Set to false if you need live view updates (e.g., animations).
46
+ * @platform ios, android
47
+ * @default true
48
+ */
49
+ rasterize?: boolean;
50
+ /**
51
+ * Whether the marker can be dragged by the user.
52
+ * @default false
53
+ */
54
+ draggable?: boolean;
55
+ /**
56
+ * Called when the marker is pressed
57
+ */
58
+ onPress?: (event: MarkerPressEvent) => void;
59
+ /**
60
+ * Called when marker drag starts
61
+ */
62
+ onDragStart?: (event: MarkerDragEvent) => void;
63
+ /**
64
+ * Called continuously as the marker is dragged
65
+ */
66
+ onDragChange?: (event: MarkerDragEvent) => void;
67
+ /**
68
+ * Called when marker drag ends
69
+ */
70
+ onDragEnd?: (event: MarkerDragEvent) => void;
71
+ /**
72
+ * Custom marker view
73
+ */
74
+ children?: ReactNode;
75
+ }
@@ -1,32 +1,120 @@
1
- import React from 'react';
1
+ import { useCallback, useEffect, useRef } from 'react';
2
2
  import { AdvancedMarker } from '@vis.gl/react-google-maps';
3
- import type { MarkerProps } from './Marker';
3
+ import { useMapContext } from '../MapProvider.web';
4
+ import type { MarkerProps } from './Marker.types';
4
5
 
5
- /**
6
- * Converts point to % anchor for web.
7
- * e.g. `0.5` to `-50%`
8
- */
9
6
  const toWebAnchor = (value: number) => `-${value * 100}%`;
10
7
 
11
- export class Marker extends React.Component<MarkerProps> {
12
- render() {
13
- const { coordinate, title, anchor, zIndex, children } = this.props;
14
-
15
- const position = {
16
- lat: coordinate.latitude,
17
- lng: coordinate.longitude,
18
- };
19
-
20
- return (
21
- <AdvancedMarker
22
- position={position}
23
- title={title}
24
- zIndex={zIndex}
25
- anchorLeft={anchor ? toWebAnchor(anchor.x) : undefined}
26
- anchorTop={anchor ? toWebAnchor(anchor.y) : undefined}
27
- >
28
- {children}
29
- </AdvancedMarker>
30
- );
31
- }
32
- }
8
+ const createEvent = (
9
+ e: google.maps.MapMouseEvent,
10
+ coordinate: MarkerProps['coordinate']
11
+ ) =>
12
+ ({
13
+ nativeEvent: {
14
+ coordinate: {
15
+ latitude: e.latLng?.lat() ?? coordinate.latitude,
16
+ longitude: e.latLng?.lng() ?? coordinate.longitude,
17
+ },
18
+ point: {
19
+ x: (e.domEvent as MouseEvent)?.clientX ?? 0,
20
+ y: (e.domEvent as MouseEvent)?.clientY ?? 0,
21
+ },
22
+ },
23
+ } as any);
24
+
25
+ export const Marker = ({
26
+ coordinate,
27
+ title,
28
+ anchor,
29
+ zIndex,
30
+ rotate,
31
+ scale,
32
+ draggable,
33
+ onPress,
34
+ onDragStart,
35
+ onDragChange,
36
+ onDragEnd,
37
+ children,
38
+ }: MarkerProps) => {
39
+ const { moveCamera } = useMapContext();
40
+ const dragPositionRef = useRef<google.maps.LatLngLiteral | null>(null);
41
+
42
+ const transforms: string[] = [];
43
+ if (rotate) transforms.push(`rotate(${rotate}deg)`);
44
+ if (scale && scale !== 1) transforms.push(`scale(${scale})`);
45
+
46
+ const handleClick = useCallback(
47
+ (e: google.maps.MapMouseEvent) => {
48
+ const pos = dragPositionRef.current;
49
+ const coord = pos
50
+ ? { latitude: pos.lat, longitude: pos.lng }
51
+ : coordinate;
52
+ moveCamera(coord);
53
+ onPress?.(createEvent(e, coordinate));
54
+ },
55
+ [moveCamera, onPress, coordinate]
56
+ );
57
+
58
+ const handleDragStart = useCallback(
59
+ (e: google.maps.MapMouseEvent) => {
60
+ const latLng = e.latLng;
61
+ if (latLng) {
62
+ dragPositionRef.current = { lat: latLng.lat(), lng: latLng.lng() };
63
+ }
64
+ onDragStart?.(createEvent(e, coordinate));
65
+ },
66
+ [onDragStart, coordinate]
67
+ );
68
+
69
+ const handleDrag = useCallback(
70
+ (e: google.maps.MapMouseEvent) => {
71
+ const latLng = e.latLng;
72
+ if (latLng) {
73
+ dragPositionRef.current = { lat: latLng.lat(), lng: latLng.lng() };
74
+ }
75
+ onDragChange?.(createEvent(e, coordinate));
76
+ },
77
+ [onDragChange, coordinate]
78
+ );
79
+
80
+ const handleDragEnd = useCallback(
81
+ (e: google.maps.MapMouseEvent) => {
82
+ const latLng = e.latLng;
83
+ if (latLng) {
84
+ dragPositionRef.current = { lat: latLng.lat(), lng: latLng.lng() };
85
+ }
86
+ onDragEnd?.(createEvent(e, coordinate));
87
+ },
88
+ [onDragEnd, coordinate]
89
+ );
90
+
91
+ useEffect(() => {
92
+ dragPositionRef.current = null;
93
+ }, [coordinate.latitude, coordinate.longitude]);
94
+
95
+ const position = dragPositionRef.current ?? {
96
+ lat: coordinate.latitude,
97
+ lng: coordinate.longitude,
98
+ };
99
+
100
+ return (
101
+ <AdvancedMarker
102
+ position={position}
103
+ title={title}
104
+ zIndex={zIndex}
105
+ anchorLeft={anchor ? toWebAnchor(anchor.x) : undefined}
106
+ anchorTop={anchor ? toWebAnchor(anchor.y) : undefined}
107
+ clickable
108
+ draggable={draggable}
109
+ onClick={handleClick}
110
+ onDragStart={handleDragStart}
111
+ onDrag={handleDrag}
112
+ onDragEnd={handleDragEnd}
113
+ style={
114
+ transforms.length > 0 ? { transform: transforms.join(' ') } : undefined
115
+ }
116
+ >
117
+ {children}
118
+ </AdvancedMarker>
119
+ );
120
+ };
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { StyleSheet } from 'react-native';
3
+ import LuggPolygonViewNativeComponent from '../fabric/LuggPolygonViewNativeComponent';
4
+ import type { PolygonProps } from './Polygon.types';
5
+
6
+ export type { PolygonProps } from './Polygon.types';
7
+
8
+ export class Polygon extends React.PureComponent<PolygonProps> {
9
+ private _cachedZIndex: number | undefined;
10
+ private _cachedStyle: any;
11
+
12
+ private getStyle(zIndex: number | undefined) {
13
+ if (zIndex == null) return styles.polygon;
14
+ if (zIndex !== this._cachedZIndex) {
15
+ this._cachedZIndex = zIndex;
16
+ this._cachedStyle = [{ zIndex }, styles.polygon];
17
+ }
18
+ return this._cachedStyle!;
19
+ }
20
+
21
+ render() {
22
+ const {
23
+ coordinates,
24
+ holes,
25
+ strokeColor,
26
+ strokeWidth,
27
+ fillColor,
28
+ zIndex,
29
+ onPress,
30
+ } = this.props;
31
+
32
+ return (
33
+ <LuggPolygonViewNativeComponent
34
+ style={this.getStyle(zIndex)}
35
+ coordinates={coordinates}
36
+ holes={holes}
37
+ strokeColor={strokeColor}
38
+ strokeWidth={strokeWidth}
39
+ fillColor={fillColor}
40
+ tappable={!!onPress}
41
+ onPolygonPress={onPress}
42
+ />
43
+ );
44
+ }
45
+ }
46
+
47
+ const styles = StyleSheet.create({
48
+ polygon: {
49
+ position: 'absolute',
50
+ pointerEvents: 'none',
51
+ },
52
+ });