@lugg/maps 0.2.0-alpha.9 → 1.0.0-beta.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.
Files changed (184) hide show
  1. package/README.md +21 -20
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +74 -0
  4. package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +38 -0
  5. package/android/src/main/java/com/luggmaps/LuggMapView.kt +290 -0
  6. package/android/src/main/java/com/luggmaps/{LuggGoogleMapViewManager.kt → LuggMapViewManager.kt} +99 -36
  7. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +11 -14
  8. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +187 -21
  9. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +28 -0
  10. package/android/src/main/java/com/luggmaps/LuggPackage.kt +8 -4
  11. package/android/src/main/java/com/luggmaps/LuggPolygonView.kt +85 -0
  12. package/android/src/main/java/com/luggmaps/LuggPolygonViewManager.kt +100 -0
  13. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
  14. package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
  15. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +874 -0
  16. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +60 -0
  17. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +89 -24
  18. package/android/src/main/java/com/luggmaps/events/LongPressEvent.kt +29 -0
  19. package/android/src/main/java/com/luggmaps/events/MarkerDragEvent.kt +41 -0
  20. package/android/src/main/java/com/luggmaps/events/MarkerPressEvent.kt +34 -0
  21. package/android/src/main/java/com/luggmaps/events/PolygonPressEvent.kt +12 -0
  22. package/android/src/main/java/com/luggmaps/events/PressEvent.kt +29 -0
  23. package/ios/LuggCalloutView.h +23 -0
  24. package/ios/LuggCalloutView.mm +145 -0
  25. package/ios/LuggMapView.h +9 -0
  26. package/ios/LuggMapView.mm +343 -0
  27. package/ios/LuggMarkerView.h +15 -0
  28. package/ios/LuggMarkerView.mm +136 -2
  29. package/ios/LuggPolygonView.h +31 -0
  30. package/ios/LuggPolygonView.mm +151 -0
  31. package/ios/LuggPolylineView.h +4 -0
  32. package/ios/LuggPolylineView.mm +23 -0
  33. package/ios/core/AppleMapProvider.h +15 -0
  34. package/ios/core/AppleMapProvider.mm +1173 -0
  35. package/ios/core/GMSPolylineAnimator.h +3 -0
  36. package/ios/core/GMSPolylineAnimator.m +101 -15
  37. package/ios/core/GoogleMapProvider.h +13 -0
  38. package/ios/core/GoogleMapProvider.mm +798 -0
  39. package/ios/core/LuggAnnotationView.h +12 -0
  40. package/ios/core/LuggAnnotationView.mm +55 -0
  41. package/ios/core/MKPolylineAnimator.h +4 -0
  42. package/ios/core/MKPolylineAnimator.m +167 -42
  43. package/ios/core/MapProviderDelegate.h +84 -0
  44. package/ios/core/PolylineAnimatorBase.h +24 -1
  45. package/ios/core/PolylineAnimatorBase.m +82 -19
  46. package/ios/events/LongPressEvent.h +29 -0
  47. package/ios/events/MarkerDragEvent.h +69 -0
  48. package/ios/events/MarkerPressEvent.h +29 -0
  49. package/ios/events/PolygonPressEvent.h +20 -0
  50. package/ios/events/PressEvent.h +29 -0
  51. package/ios/extensions/MKMapView+Zoom.h +2 -0
  52. package/ios/extensions/MKMapView+Zoom.m +14 -4
  53. package/lib/module/MapProvider.js +2 -4
  54. package/lib/module/MapProvider.js.map +1 -1
  55. package/lib/module/MapProvider.web.js +14 -7
  56. package/lib/module/MapProvider.web.js.map +1 -1
  57. package/lib/module/MapView.js +33 -16
  58. package/lib/module/MapView.js.map +1 -1
  59. package/lib/module/MapView.web.js +296 -181
  60. package/lib/module/MapView.web.js.map +1 -1
  61. package/lib/module/components/GeoJson.js +159 -0
  62. package/lib/module/components/GeoJson.js.map +1 -0
  63. package/lib/module/components/GeoJson.types.js +4 -0
  64. package/lib/module/components/GeoJson.types.js.map +1 -0
  65. package/lib/module/components/Marker.js +49 -8
  66. package/lib/module/components/Marker.js.map +1 -1
  67. package/lib/module/components/Marker.types.js +4 -0
  68. package/lib/module/components/Marker.types.js.map +1 -0
  69. package/lib/module/components/Marker.web.js +159 -24
  70. package/lib/module/components/Marker.web.js.map +1 -1
  71. package/lib/module/components/Polygon.js +46 -0
  72. package/lib/module/components/Polygon.js.map +1 -0
  73. package/lib/module/components/Polygon.types.js +4 -0
  74. package/lib/module/components/Polygon.types.js.map +1 -0
  75. package/lib/module/components/Polygon.web.js +87 -0
  76. package/lib/module/components/Polygon.web.js.map +1 -0
  77. package/lib/module/components/Polyline.js +17 -4
  78. package/lib/module/components/Polyline.js.map +1 -1
  79. package/lib/module/components/Polyline.types.js +4 -0
  80. package/lib/module/components/Polyline.types.js.map +1 -0
  81. package/lib/module/components/Polyline.web.js +108 -31
  82. package/lib/module/components/Polyline.web.js.map +1 -1
  83. package/lib/module/components/index.js +4 -2
  84. package/lib/module/components/index.js.map +1 -1
  85. package/lib/module/components/index.web.js +2 -0
  86. package/lib/module/components/index.web.js.map +1 -1
  87. package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +20 -0
  88. package/lib/module/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
  89. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +49 -1
  90. package/lib/module/fabric/LuggPolygonViewNativeComponent.ts +25 -0
  91. package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  92. package/lib/module/index.js +4 -1
  93. package/lib/module/index.js.map +1 -1
  94. package/lib/module/index.web.js +4 -1
  95. package/lib/module/index.web.js.map +1 -1
  96. package/lib/typescript/src/MapProvider.d.ts +1 -1
  97. package/lib/typescript/src/MapProvider.d.ts.map +1 -1
  98. package/lib/typescript/src/MapProvider.web.d.ts +23 -1
  99. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
  100. package/lib/typescript/src/MapView.d.ts +4 -4
  101. package/lib/typescript/src/MapView.d.ts.map +1 -1
  102. package/lib/typescript/src/MapView.types.d.ts +35 -9
  103. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  104. package/lib/typescript/src/MapView.web.d.ts +2 -11
  105. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  106. package/lib/typescript/src/components/GeoJson.d.ts +4 -0
  107. package/lib/typescript/src/components/GeoJson.d.ts.map +1 -0
  108. package/lib/typescript/src/components/GeoJson.types.d.ts +89 -0
  109. package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -0
  110. package/lib/typescript/src/components/Marker.d.ts +6 -33
  111. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  112. package/lib/typescript/src/components/Marker.types.d.ts +100 -0
  113. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -0
  114. package/lib/typescript/src/components/Marker.web.d.ts +2 -5
  115. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  116. package/lib/typescript/src/components/Polygon.d.ts +10 -0
  117. package/lib/typescript/src/components/Polygon.d.ts.map +1 -0
  118. package/lib/typescript/src/components/Polygon.types.d.ts +33 -0
  119. package/lib/typescript/src/components/Polygon.types.d.ts.map +1 -0
  120. package/lib/typescript/src/components/Polygon.web.d.ts +3 -0
  121. package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -0
  122. package/lib/typescript/src/components/Polyline.d.ts +6 -21
  123. package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
  124. package/lib/typescript/src/components/Polyline.types.d.ts +53 -0
  125. package/lib/typescript/src/components/Polyline.types.d.ts.map +1 -0
  126. package/lib/typescript/src/components/Polyline.web.d.ts +2 -5
  127. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
  128. package/lib/typescript/src/components/index.d.ts +8 -2
  129. package/lib/typescript/src/components/index.d.ts.map +1 -1
  130. package/lib/typescript/src/components/index.web.d.ts +6 -2
  131. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  132. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +13 -0
  133. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts.map +1 -0
  134. package/lib/typescript/src/fabric/{LuggGoogleMapViewNativeComponent.d.ts → LuggMapViewNativeComponent.d.ts} +30 -4
  135. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -0
  136. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +45 -1
  137. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  138. package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts +18 -0
  139. package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts.map +1 -0
  140. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
  141. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
  142. package/lib/typescript/src/index.d.ts +11 -3
  143. package/lib/typescript/src/index.d.ts.map +1 -1
  144. package/lib/typescript/src/index.web.d.ts +9 -1
  145. package/lib/typescript/src/index.web.d.ts.map +1 -1
  146. package/lib/typescript/src/types.d.ts +11 -0
  147. package/lib/typescript/src/types.d.ts.map +1 -1
  148. package/package.json +11 -9
  149. package/src/MapProvider.tsx +1 -3
  150. package/src/MapProvider.web.tsx +22 -3
  151. package/src/MapView.tsx +32 -26
  152. package/src/MapView.types.ts +43 -9
  153. package/src/MapView.web.tsx +368 -210
  154. package/src/components/GeoJson.tsx +221 -0
  155. package/src/components/GeoJson.types.ts +118 -0
  156. package/src/components/Marker.tsx +75 -38
  157. package/src/components/Marker.types.ts +102 -0
  158. package/src/components/Marker.web.tsx +197 -19
  159. package/src/components/Polygon.tsx +52 -0
  160. package/src/components/Polygon.types.ts +33 -0
  161. package/src/components/Polygon.web.tsx +104 -0
  162. package/src/components/Polyline.tsx +23 -22
  163. package/src/components/Polyline.types.ts +55 -0
  164. package/src/components/Polyline.web.tsx +151 -37
  165. package/src/components/index.ts +17 -2
  166. package/src/components/index.web.ts +6 -2
  167. package/src/fabric/LuggCalloutViewNativeComponent.ts +20 -0
  168. package/src/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
  169. package/src/fabric/LuggMarkerViewNativeComponent.ts +49 -1
  170. package/src/fabric/LuggPolygonViewNativeComponent.ts +25 -0
  171. package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  172. package/src/index.ts +30 -1
  173. package/src/index.web.ts +16 -1
  174. package/src/types.ts +13 -0
  175. package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +0 -511
  176. package/ios/LuggAppleMapView.h +0 -16
  177. package/ios/LuggAppleMapView.mm +0 -592
  178. package/ios/LuggGoogleMapView.h +0 -13
  179. package/ios/LuggGoogleMapView.mm +0 -455
  180. package/lib/module/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
  181. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts +0 -54
  182. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +0 -1
  183. package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +0 -1
  184. package/src/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
@@ -1,32 +1,210 @@
1
- import React from 'react';
2
- import { AdvancedMarker } from '@vis.gl/react-google-maps';
3
- import type { MarkerProps } from './Marker';
4
-
5
- /**
6
- * Converts point to % anchor for web.
7
- * e.g. `0.5` to `-50%`
8
- */
1
+ import React, {
2
+ isValidElement,
3
+ useCallback,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
8
+ import {
9
+ AdvancedMarker,
10
+ InfoWindow,
11
+ useAdvancedMarkerRef,
12
+ } from '@vis.gl/react-google-maps';
13
+ import { useMapContext } from '../MapProvider.web';
14
+ import type { MarkerProps } from './Marker.types';
15
+
16
+ const CALLOUT_ARROW_HEIGHT = 12;
17
+ const UNBUBBLED_CLASS = 'rnm-callout-unbubbled';
18
+ const UNBUBBLED_STYLE_ID = 'rnm-callout-unbubbled-style';
19
+
20
+ function injectUnbubbledStyle() {
21
+ if (document.getElementById(UNBUBBLED_STYLE_ID)) return;
22
+ const style = document.createElement('style');
23
+ style.id = UNBUBBLED_STYLE_ID;
24
+ style.textContent = `
25
+ .gm-style-iw-c:has(.${UNBUBBLED_CLASS}) {
26
+ background: transparent !important;
27
+ box-shadow: none !important;
28
+ padding: 0 !important;
29
+ border-radius: 0 !important;
30
+ }
31
+ .gm-style-iw-d:has(.${UNBUBBLED_CLASS}) {
32
+ overflow: visible !important;
33
+ }
34
+ .gm-style-iw-t:has(.${UNBUBBLED_CLASS})::after,
35
+ .gm-style-iw-t:has(.${UNBUBBLED_CLASS}) .gm-style-iw-tc {
36
+ display: none !important;
37
+ }
38
+ `;
39
+ document.head.appendChild(style);
40
+ }
41
+
9
42
  const toWebAnchor = (value: number) => `-${value * 100}%`;
10
43
 
11
- export class Marker extends React.Component<MarkerProps> {
12
- render() {
13
- const { coordinate, title, anchor, zIndex, children } = this.props;
44
+ const createEvent = (
45
+ e: google.maps.MapMouseEvent,
46
+ coordinate: MarkerProps['coordinate']
47
+ ) =>
48
+ ({
49
+ nativeEvent: {
50
+ coordinate: {
51
+ latitude: e.latLng?.lat() ?? coordinate.latitude,
52
+ longitude: e.latLng?.lng() ?? coordinate.longitude,
53
+ },
54
+ point: {
55
+ x: (e.domEvent as MouseEvent)?.clientX ?? 0,
56
+ y: (e.domEvent as MouseEvent)?.clientY ?? 0,
57
+ },
58
+ },
59
+ } as any);
60
+
61
+ export const Marker = ({
62
+ coordinate,
63
+ title,
64
+ description,
65
+ anchor,
66
+ zIndex,
67
+ rotate,
68
+ scale,
69
+ draggable,
70
+ onPress,
71
+ onDragStart,
72
+ onDragChange,
73
+ onDragEnd,
74
+ callout,
75
+ calloutOptions,
76
+ children,
77
+ }: MarkerProps) => {
78
+ const { moveCamera, onCalloutClose, closeCallouts } = useMapContext();
79
+ const dragPositionRef = useRef<google.maps.LatLngLiteral | null>(null);
80
+ const [markerRef, markerElement] = useAdvancedMarkerRef();
81
+ const [infoWindowOpen, setInfoWindowOpen] = useState(false);
82
+ const calloutBubbled = calloutOptions?.bubbled ?? true;
83
+
84
+ const closeCallout = useCallback(() => setInfoWindowOpen(false), []);
85
+
86
+ useEffect(() => onCalloutClose(closeCallout), [onCalloutClose, closeCallout]);
87
+
88
+ useEffect(() => {
89
+ if (!calloutBubbled) injectUnbubbledStyle();
90
+ }, [calloutBubbled]);
91
+
92
+ const hasCallout = !!(callout || title);
14
93
 
15
- const position = {
16
- lat: coordinate.latitude,
17
- lng: coordinate.longitude,
18
- };
94
+ const calloutContent = callout
95
+ ? isValidElement(callout)
96
+ ? callout
97
+ : React.createElement(callout)
98
+ : title
99
+ ? React.createElement(
100
+ 'div',
101
+ { style: { fontSize: 14 } },
102
+ React.createElement('div', { style: { fontWeight: 500 } }, title),
103
+ description ? React.createElement('div', null, description) : null
104
+ )
105
+ : null;
19
106
 
20
- return (
107
+ const transforms: string[] = [];
108
+ if (rotate) transforms.push(`rotate(${rotate}deg)`);
109
+ if (scale && scale !== 1) transforms.push(`scale(${scale})`);
110
+
111
+ const handleClick = useCallback(
112
+ (e: google.maps.MapMouseEvent) => {
113
+ const pos = dragPositionRef.current;
114
+ const coord = pos
115
+ ? { latitude: pos.lat, longitude: pos.lng }
116
+ : coordinate;
117
+ moveCamera(coord);
118
+ onPress?.(createEvent(e, coordinate));
119
+ if (hasCallout) {
120
+ closeCallouts(closeCallout);
121
+ setInfoWindowOpen((prev) => !prev);
122
+ }
123
+ },
124
+ [moveCamera, onPress, coordinate, hasCallout, closeCallouts, closeCallout]
125
+ );
126
+
127
+ const handleDragStart = useCallback(
128
+ (e: google.maps.MapMouseEvent) => {
129
+ const latLng = e.latLng;
130
+ if (latLng) {
131
+ dragPositionRef.current = { lat: latLng.lat(), lng: latLng.lng() };
132
+ }
133
+ onDragStart?.(createEvent(e, coordinate));
134
+ },
135
+ [onDragStart, coordinate]
136
+ );
137
+
138
+ const handleDrag = useCallback(
139
+ (e: google.maps.MapMouseEvent) => {
140
+ const latLng = e.latLng;
141
+ if (latLng) {
142
+ dragPositionRef.current = { lat: latLng.lat(), lng: latLng.lng() };
143
+ }
144
+ onDragChange?.(createEvent(e, coordinate));
145
+ },
146
+ [onDragChange, coordinate]
147
+ );
148
+
149
+ const handleDragEnd = useCallback(
150
+ (e: google.maps.MapMouseEvent) => {
151
+ const latLng = e.latLng;
152
+ if (latLng) {
153
+ dragPositionRef.current = { lat: latLng.lat(), lng: latLng.lng() };
154
+ }
155
+ onDragEnd?.(createEvent(e, coordinate));
156
+ },
157
+ [onDragEnd, coordinate]
158
+ );
159
+
160
+ useEffect(() => {
161
+ dragPositionRef.current = null;
162
+ }, [coordinate.latitude, coordinate.longitude]);
163
+
164
+ const latLngPosition = {
165
+ lat: coordinate.latitude,
166
+ lng: coordinate.longitude,
167
+ };
168
+
169
+ const position = dragPositionRef.current ?? latLngPosition;
170
+
171
+ return (
172
+ <>
21
173
  <AdvancedMarker
174
+ ref={markerRef}
22
175
  position={position}
23
176
  title={title}
24
177
  zIndex={zIndex}
25
178
  anchorLeft={anchor ? toWebAnchor(anchor.x) : undefined}
26
179
  anchorTop={anchor ? toWebAnchor(anchor.y) : undefined}
180
+ clickable
181
+ draggable={draggable}
182
+ onClick={handleClick}
183
+ onDragStart={handleDragStart}
184
+ onDrag={handleDrag}
185
+ onDragEnd={handleDragEnd}
186
+ style={
187
+ transforms.length > 0
188
+ ? { transform: transforms.join(' ') }
189
+ : undefined
190
+ }
27
191
  >
28
192
  {children}
29
193
  </AdvancedMarker>
30
- );
31
- }
32
- }
194
+ {calloutContent && infoWindowOpen && markerElement && (
195
+ <InfoWindow
196
+ anchor={markerElement}
197
+ pixelOffset={!calloutBubbled ? [0, CALLOUT_ARROW_HEIGHT] : undefined}
198
+ headerDisabled
199
+ onClose={() => setInfoWindowOpen(false)}
200
+ >
201
+ {!calloutBubbled ? (
202
+ <div className={UNBUBBLED_CLASS}>{calloutContent}</div>
203
+ ) : (
204
+ calloutContent
205
+ )}
206
+ </InfoWindow>
207
+ )}
208
+ </>
209
+ );
210
+ };
@@ -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
+ });
@@ -0,0 +1,33 @@
1
+ import type { ColorValue } from 'react-native';
2
+ import type { Coordinate } from '../types';
3
+
4
+ export interface PolygonProps {
5
+ /**
6
+ * Array of coordinates forming the polygon boundary
7
+ */
8
+ coordinates: Coordinate[];
9
+ /**
10
+ * Array of coordinate arrays representing interior holes
11
+ */
12
+ holes?: Coordinate[][];
13
+ /**
14
+ * Stroke (outline) color
15
+ */
16
+ strokeColor?: ColorValue;
17
+ /**
18
+ * Stroke width in points
19
+ */
20
+ strokeWidth?: number;
21
+ /**
22
+ * Fill color of the polygon
23
+ */
24
+ fillColor?: ColorValue;
25
+ /**
26
+ * Z-index for layering
27
+ */
28
+ zIndex?: number;
29
+ /**
30
+ * Called when the polygon is tapped
31
+ */
32
+ onPress?: () => void;
33
+ }
@@ -0,0 +1,104 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ import { useMapContext } from '../MapProvider.web';
3
+ import type { PolygonProps } from './Polygon.types';
4
+
5
+ export const Polygon = ({
6
+ coordinates,
7
+ holes,
8
+ strokeColor = '#000000',
9
+ strokeWidth = 1,
10
+ fillColor = 'rgba(0, 0, 0, 0.3)',
11
+ zIndex = 0,
12
+ onPress,
13
+ }: PolygonProps) => {
14
+ const { map } = useMapContext();
15
+ const polygonRef = useRef<google.maps.Polygon | null>(null);
16
+ const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
17
+
18
+ const handleClick = useCallback(() => {
19
+ onPress?.();
20
+ }, [onPress]);
21
+
22
+ // Cleanup on unmount
23
+ useEffect(() => {
24
+ return () => {
25
+ listenersRef.current.forEach((l) => l.remove());
26
+ listenersRef.current = [];
27
+ polygonRef.current?.setMap(null);
28
+ polygonRef.current = null;
29
+ };
30
+ }, []);
31
+
32
+ // Sync listeners
33
+ useEffect(() => {
34
+ const polygon = polygonRef.current;
35
+ if (!polygon) return;
36
+
37
+ listenersRef.current.forEach((l) => l.remove());
38
+ listenersRef.current = [];
39
+
40
+ if (onPress) {
41
+ listenersRef.current.push(polygon.addListener('click', handleClick));
42
+ }
43
+ polygon.set('clickable', !!onPress);
44
+ }, [onPress, handleClick]);
45
+
46
+ // Sync polygon with props
47
+ useEffect(() => {
48
+ if (!map || coordinates.length === 0) {
49
+ polygonRef.current?.setMap(null);
50
+ return;
51
+ }
52
+
53
+ const outerPath = coordinates.map((c) => ({
54
+ lat: c.latitude,
55
+ lng: c.longitude,
56
+ }));
57
+
58
+ const paths = [
59
+ outerPath,
60
+ ...(holes ?? []).map((hole) =>
61
+ [...hole].reverse().map((c) => ({ lat: c.latitude, lng: c.longitude }))
62
+ ),
63
+ ];
64
+
65
+ if (polygonRef.current) {
66
+ polygonRef.current.setPaths(paths);
67
+ polygonRef.current.setOptions({
68
+ strokeColor: strokeColor as string,
69
+ strokeWeight: strokeWidth,
70
+ fillColor: fillColor as string,
71
+ zIndex,
72
+ });
73
+ } else {
74
+ const polygon = new google.maps.Polygon({
75
+ paths,
76
+ strokeColor: strokeColor as string,
77
+ strokeWeight: strokeWidth,
78
+ strokeOpacity: 1,
79
+ fillColor: fillColor as string,
80
+ fillOpacity: 1,
81
+ zIndex,
82
+ clickable: !!onPress,
83
+ map,
84
+ });
85
+ polygonRef.current = polygon;
86
+
87
+ if (onPress) {
88
+ listenersRef.current.push(polygon.addListener('click', handleClick));
89
+ }
90
+ }
91
+ }, [
92
+ map,
93
+ coordinates,
94
+ holes,
95
+ strokeColor,
96
+ strokeWidth,
97
+ fillColor,
98
+ zIndex,
99
+ onPress,
100
+ handleClick,
101
+ ]);
102
+
103
+ return null;
104
+ };
@@ -1,44 +1,45 @@
1
1
  import React from 'react';
2
- import type { ColorValue } from 'react-native';
3
2
  import { StyleSheet } from 'react-native';
4
3
  import LuggPolylineViewNativeComponent from '../fabric/LuggPolylineViewNativeComponent';
5
- import type { Coordinate } from '../types';
4
+ import type { PolylineProps } from './Polyline.types';
6
5
 
7
- export interface PolylineProps {
8
- /**
9
- * Array of coordinates forming the polyline
10
- */
11
- coordinates: Coordinate[];
12
- /**
13
- * Gradient colors along the polyline
14
- */
15
- strokeColors?: ColorValue[];
16
- /**
17
- * Line width in points
18
- */
19
- strokeWidth?: number;
20
- /**
21
- * Animate the polyline with a snake effect
22
- */
23
- animated?: boolean;
24
- }
6
+ export type {
7
+ PolylineProps,
8
+ PolylineEasing,
9
+ PolylineAnimatedOptions,
10
+ } from './Polyline.types';
11
+
12
+ export class Polyline extends React.PureComponent<PolylineProps> {
13
+ private getStyle(zIndex: number | undefined) {
14
+ if (zIndex == null) return styles.polyline;
15
+ if (zIndex !== this._cachedZIndex) {
16
+ this._cachedZIndex = zIndex;
17
+ this._cachedStyle = [{ zIndex }, styles.polyline];
18
+ }
19
+ return this._cachedStyle!;
20
+ }
21
+
22
+ private _cachedZIndex: number | undefined;
23
+ private _cachedStyle: any;
25
24
 
26
- export class Polyline extends React.Component<PolylineProps> {
27
25
  render() {
28
26
  const {
29
27
  coordinates,
30
28
  strokeColors,
31
29
  strokeWidth,
32
30
  animated = false,
31
+ animatedOptions,
32
+ zIndex,
33
33
  } = this.props;
34
34
 
35
35
  return (
36
36
  <LuggPolylineViewNativeComponent
37
- style={styles.polyline}
37
+ style={this.getStyle(zIndex)}
38
38
  coordinates={coordinates}
39
39
  strokeColors={strokeColors}
40
40
  strokeWidth={strokeWidth}
41
41
  animated={animated}
42
+ animatedOptions={animatedOptions}
42
43
  />
43
44
  );
44
45
  }
@@ -0,0 +1,55 @@
1
+ import type { ColorValue } from 'react-native';
2
+ import type { Coordinate } from '../types';
3
+
4
+ export type PolylineEasing = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';
5
+
6
+ export interface PolylineAnimatedOptions {
7
+ /**
8
+ * Animation duration in milliseconds
9
+ * @default 2150
10
+ */
11
+ duration?: number;
12
+ /**
13
+ * Easing function for the animation
14
+ * @default 'linear'
15
+ */
16
+ easing?: PolylineEasing;
17
+ /**
18
+ * Portion of the line visible as trail (0-1)
19
+ * 1.0 = full snake effect, 0.2 = short worm
20
+ * @default 1.0
21
+ */
22
+ trailLength?: number;
23
+ /**
24
+ * Delay before animation starts in milliseconds
25
+ * @default 0
26
+ */
27
+ delay?: number;
28
+ }
29
+
30
+ export interface PolylineProps {
31
+ /**
32
+ * Array of coordinates forming the polyline
33
+ */
34
+ coordinates: Coordinate[];
35
+ /**
36
+ * Gradient colors along the polyline
37
+ */
38
+ strokeColors?: ColorValue[];
39
+ /**
40
+ * Line width in points
41
+ */
42
+ strokeWidth?: number;
43
+ /**
44
+ * Animate the polyline with a snake effect
45
+ */
46
+ animated?: boolean;
47
+ /**
48
+ * Animation configuration options
49
+ */
50
+ animatedOptions?: PolylineAnimatedOptions;
51
+ /**
52
+ * Z-index for layering polylines
53
+ */
54
+ zIndex?: number;
55
+ }