@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,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
+ }
@@ -1,17 +1,27 @@
1
- import {
2
- Component,
3
- useCallback,
4
- useEffect,
5
- useMemo,
6
- useRef,
7
- useState,
8
- } from 'react';
9
- import { useMap } from '@vis.gl/react-google-maps';
10
- import type { PolylineProps } from './Polyline';
11
-
12
- const ANIMATION_DURATION = 1500;
13
-
14
- function interpolateColor(color1: string, color2: string, t: number): string {
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useMapContext } from '../MapProvider.web';
3
+ import type { PolylineProps, PolylineEasing } from './Polyline.types';
4
+
5
+ const DEFAULT_DURATION = 2150;
6
+
7
+ const applyEasing = (t: number, easing: PolylineEasing = 'linear'): number => {
8
+ switch (easing) {
9
+ case 'easeIn':
10
+ return t * t;
11
+ case 'easeOut':
12
+ return t * (2 - t);
13
+ case 'easeInOut':
14
+ return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
15
+ default:
16
+ return t;
17
+ }
18
+ };
19
+
20
+ const interpolateColor = (
21
+ color1: string,
22
+ color2: string,
23
+ t: number
24
+ ): string => {
15
25
  const hex = (c: string) => parseInt(c, 16);
16
26
  const r1 = hex(color1.slice(1, 3));
17
27
  const g1 = hex(color1.slice(3, 5));
@@ -27,9 +37,9 @@ function interpolateColor(color1: string, color2: string, t: number): string {
27
37
  return `#${r.toString(16).padStart(2, '0')}${g
28
38
  .toString(16)
29
39
  .padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
30
- }
40
+ };
31
41
 
32
- function getGradientColor(colors: string[], position: number): string {
42
+ const getGradientColor = (colors: string[], position: number): string => {
33
43
  if (colors.length === 0) return '#000000';
34
44
  if (colors.length === 1 || position <= 0) return colors[0]!;
35
45
  if (position >= 1) return colors[colors.length - 1]!;
@@ -39,17 +49,39 @@ function getGradientColor(colors: string[], position: number): string {
39
49
  const t = scaledPos - index;
40
50
 
41
51
  return interpolateColor(colors[index]!, colors[index + 1]!, t);
42
- }
52
+ };
43
53
 
44
- function PolylineImpl({
54
+ export const Polyline = ({
45
55
  coordinates,
46
56
  strokeColors,
47
57
  strokeWidth = 1,
48
58
  animated,
49
- }: PolylineProps) {
50
- const map = useMap();
59
+ animatedOptions,
60
+ zIndex,
61
+ }: PolylineProps) => {
62
+ const resolvedZIndex = zIndex ?? (animated ? 1 : 0);
63
+ const { map, isDragging } = useMapContext();
64
+
65
+ const { duration, easing, trailLength, delay } = useMemo(
66
+ () => ({
67
+ duration: animatedOptions?.duration ?? DEFAULT_DURATION,
68
+ easing: animatedOptions?.easing ?? 'linear',
69
+ trailLength: Math.max(
70
+ 0.01,
71
+ Math.min(1, animatedOptions?.trailLength ?? 1)
72
+ ),
73
+ delay: animatedOptions?.delay ?? 0,
74
+ }),
75
+ [
76
+ animatedOptions?.duration,
77
+ animatedOptions?.easing,
78
+ animatedOptions?.trailLength,
79
+ animatedOptions?.delay,
80
+ ]
81
+ );
51
82
  const polylinesRef = useRef<google.maps.Polyline[]>([]);
52
83
  const animationRef = useRef<number>(0);
84
+ const isPausedRef = useRef(false);
53
85
 
54
86
  const colors = useMemo(
55
87
  () =>
@@ -62,13 +94,25 @@ function PolylineImpl({
62
94
  const hasGradient = colors.length > 1;
63
95
 
64
96
  // Refs for animation loop access
65
- const propsRef = useRef({ map, colors, strokeWidth, hasGradient });
97
+ const propsRef = useRef({
98
+ map,
99
+ colors,
100
+ strokeWidth,
101
+ hasGradient,
102
+ zIndex: resolvedZIndex,
103
+ });
66
104
  const [mapReady, setMapReady] = useState(!!map);
67
105
 
68
106
  useEffect(() => {
69
- propsRef.current = { map, colors, strokeWidth, hasGradient };
107
+ propsRef.current = {
108
+ map,
109
+ colors,
110
+ strokeWidth,
111
+ hasGradient,
112
+ zIndex: resolvedZIndex,
113
+ };
70
114
  if (map && !mapReady) setMapReady(true);
71
- }, [map, colors, strokeWidth, hasGradient, mapReady]);
115
+ }, [map, colors, strokeWidth, hasGradient, resolvedZIndex, mapReady]);
72
116
 
73
117
  const updatePath = useCallback((path: google.maps.LatLngLiteral[]) => {
74
118
  const {
@@ -76,11 +120,18 @@ function PolylineImpl({
76
120
  colors: currentColors,
77
121
  strokeWidth: currentStrokeWidth,
78
122
  hasGradient: currentHasGradient,
123
+ zIndex: currentZIndex,
79
124
  } = propsRef.current;
80
- if (!currentMap || path.length < 2) return;
125
+ const existing = polylinesRef.current;
126
+ if (!currentMap) return;
127
+
128
+ if (path.length < 2) {
129
+ existing.forEach((p) => p.setMap(null));
130
+ existing.length = 0;
131
+ return;
132
+ }
81
133
 
82
134
  const neededSegments = currentHasGradient ? path.length - 1 : 1;
83
- const existing = polylinesRef.current;
84
135
 
85
136
  // Update or create segments
86
137
  for (let i = 0; i < neededSegments; i++) {
@@ -100,6 +151,7 @@ function PolylineImpl({
100
151
  strokeColor: color,
101
152
  strokeWeight: currentStrokeWidth,
102
153
  strokeOpacity: 1,
154
+ zIndex: currentZIndex,
103
155
  map: currentMap,
104
156
  })
105
157
  );
@@ -122,6 +174,11 @@ function PolylineImpl({
122
174
  };
123
175
  }, []);
124
176
 
177
+ // Pause/resume animation during drag
178
+ useEffect(() => {
179
+ isPausedRef.current = isDragging;
180
+ }, [isDragging]);
181
+
125
182
  // Main effect
126
183
  useEffect(() => {
127
184
  if (!propsRef.current.map || coordinates.length === 0) return;
@@ -139,12 +196,65 @@ function PolylineImpl({
139
196
  }
140
197
 
141
198
  const totalPoints = fullPath.length;
142
- const cycleDuration = ANIMATION_DURATION * 2;
199
+ const useTrailMode = trailLength < 1;
200
+ const renderMax = useTrailMode ? 1 : 2;
201
+ const cycleMax = useTrailMode ? 1 : 2.15;
202
+
203
+ let startTime: number | null = null;
204
+ let delayRemaining = delay;
205
+
206
+ let pausedAt: number | null = null;
143
207
 
144
208
  const animate = (time: number) => {
145
- const progress = (time % cycleDuration) / ANIMATION_DURATION;
146
- const startIdx = progress <= 1 ? 0 : (progress - 1) * totalPoints;
147
- const endIdx = progress <= 1 ? progress * totalPoints : totalPoints;
209
+ if (isPausedRef.current) {
210
+ if (pausedAt === null) pausedAt = time;
211
+ animationRef.current = requestAnimationFrame(animate);
212
+ return;
213
+ }
214
+
215
+ if (pausedAt !== null) {
216
+ if (startTime !== null) {
217
+ startTime += time - pausedAt;
218
+ }
219
+ pausedAt = null;
220
+ }
221
+
222
+ if (startTime === null) {
223
+ startTime = time;
224
+ }
225
+
226
+ const elapsed = time - startTime;
227
+
228
+ if (delayRemaining > 0) {
229
+ if (elapsed < delayRemaining) {
230
+ animationRef.current = requestAnimationFrame(animate);
231
+ return;
232
+ }
233
+ startTime = time - (elapsed - delayRemaining);
234
+ delayRemaining = 0;
235
+ }
236
+
237
+ const rawProgress = (time - startTime) / duration;
238
+
239
+ if (rawProgress >= cycleMax) {
240
+ delayRemaining = delay;
241
+ startTime = time;
242
+ }
243
+
244
+ const clampedProgress = Math.min(rawProgress, renderMax);
245
+ const easedProgress =
246
+ applyEasing(clampedProgress / renderMax, easing) * renderMax;
247
+
248
+ let startIdx: number;
249
+ let endIdx: number;
250
+
251
+ if (useTrailMode) {
252
+ endIdx = easedProgress * totalPoints;
253
+ startIdx = Math.max(0, endIdx - trailLength * totalPoints);
254
+ } else {
255
+ startIdx = easedProgress <= 1 ? 0 : (easedProgress - 1) * totalPoints;
256
+ endIdx = easedProgress <= 1 ? easedProgress * totalPoints : totalPoints;
257
+ }
148
258
 
149
259
  const partialPath: google.maps.LatLngLiteral[] = [];
150
260
  const startFloor = Math.floor(startIdx);
@@ -194,13 +304,17 @@ function PolylineImpl({
194
304
  animationRef.current = requestAnimationFrame(animate);
195
305
 
196
306
  return () => cancelAnimationFrame(animationRef.current);
197
- }, [coordinates, animated, hasGradient, updatePath, mapReady]);
307
+ }, [
308
+ coordinates,
309
+ animated,
310
+ duration,
311
+ easing,
312
+ trailLength,
313
+ delay,
314
+ hasGradient,
315
+ updatePath,
316
+ mapReady,
317
+ ]);
198
318
 
199
319
  return null;
200
- }
201
-
202
- export class Polyline extends Component<PolylineProps> {
203
- render() {
204
- return <PolylineImpl {...this.props} />;
205
- }
206
- }
320
+ };
@@ -1,2 +1,16 @@
1
- export * from './Marker';
2
- export * from './Polyline';
1
+ export { Marker } from './Marker';
2
+ export type {
3
+ MarkerProps,
4
+ MarkerPressEvent,
5
+ MarkerDragEvent,
6
+ } from './Marker.types';
7
+ export { Polygon } from './Polygon';
8
+ export type { PolygonProps } from './Polygon.types';
9
+ export { Polyline } from './Polyline';
10
+ export type {
11
+ PolylineProps,
12
+ PolylineEasing,
13
+ PolylineAnimatedOptions,
14
+ } from './Polyline.types';
15
+ export { GeoJson } from './GeoJson';
16
+ export type { GeoJsonProps } from './GeoJson.types';
@@ -1,4 +1,8 @@
1
1
  export { Marker } from './Marker.web';
2
+ export { Polygon } from './Polygon.web';
2
3
  export { Polyline } from './Polyline.web';
3
- export type { MarkerProps } from './Marker';
4
- export type { PolylineProps } from './Polyline';
4
+ export type { MarkerProps } from './Marker.types';
5
+ export type { PolygonProps } from './Polygon.types';
6
+ export type { PolylineProps } from './Polyline.types';
7
+ export { GeoJson } from './GeoJson';
8
+ export type { GeoJsonProps } from './GeoJson.types';
@@ -2,6 +2,7 @@ import { codegenNativeComponent, codegenNativeCommands } from 'react-native';
2
2
  import type { ViewProps, HostComponent } from 'react-native';
3
3
  import type {
4
4
  Double,
5
+ WithDefault,
5
6
  DirectEventHandler,
6
7
  } from 'react-native/Libraries/Types/CodegenTypes';
7
8
 
@@ -35,9 +36,32 @@ export interface CameraIdleEvent {
35
36
  gesture: boolean;
36
37
  }
37
38
 
39
+ export interface PressEvent {
40
+ coordinate: {
41
+ latitude: Double;
42
+ longitude: Double;
43
+ };
44
+ point: {
45
+ x: Double;
46
+ y: Double;
47
+ };
48
+ }
49
+
50
+ export interface LongPressEvent {
51
+ coordinate: {
52
+ latitude: Double;
53
+ longitude: Double;
54
+ };
55
+ point: {
56
+ x: Double;
57
+ y: Double;
58
+ };
59
+ }
60
+
38
61
  export interface ReadyEvent {}
39
62
 
40
63
  export interface NativeProps extends ViewProps {
64
+ provider?: WithDefault<'google' | 'apple', 'google'>;
41
65
  mapId?: string;
42
66
  initialCoordinate?: Coordinate;
43
67
  initialZoom?: Double;
@@ -47,8 +71,12 @@ export interface NativeProps extends ViewProps {
47
71
  scrollEnabled?: boolean;
48
72
  rotateEnabled?: boolean;
49
73
  pitchEnabled?: boolean;
50
- padding?: EdgeInsets;
74
+ edgeInsets?: EdgeInsets;
51
75
  userLocationEnabled?: boolean;
76
+ userLocationButtonEnabled?: boolean;
77
+ theme?: WithDefault<'light' | 'dark' | 'system', 'system'>;
78
+ onMapPress?: DirectEventHandler<PressEvent>;
79
+ onMapLongPress?: DirectEventHandler<LongPressEvent>;
52
80
  onCameraMove?: DirectEventHandler<CameraMoveEvent>;
53
81
  onCameraIdle?: DirectEventHandler<CameraIdleEvent>;
54
82
  onReady?: DirectEventHandler<ReadyEvent>;
@@ -67,18 +95,26 @@ interface NativeCommands {
67
95
  fitCoordinates: (
68
96
  viewRef: React.ElementRef<ComponentType>,
69
97
  coordinates: Coordinate[],
70
- paddingTop: Double,
71
- paddingLeft: Double,
72
- paddingBottom: Double,
73
- paddingRight: Double,
98
+ edgeInsetsTop: Double,
99
+ edgeInsetsLeft: Double,
100
+ edgeInsetsBottom: Double,
101
+ edgeInsetsRight: Double,
102
+ duration: Double
103
+ ) => void;
104
+ setEdgeInsets: (
105
+ viewRef: React.ElementRef<ComponentType>,
106
+ top: Double,
107
+ left: Double,
108
+ bottom: Double,
109
+ right: Double,
74
110
  duration: Double
75
111
  ) => void;
76
112
  }
77
113
 
78
114
  export const Commands = codegenNativeCommands<NativeCommands>({
79
- supportedCommands: ['moveCamera', 'fitCoordinates'],
115
+ supportedCommands: ['moveCamera', 'fitCoordinates', 'setEdgeInsets'],
80
116
  });
81
117
 
82
118
  export default codegenNativeComponent<NativeProps>(
83
- 'LuggGoogleMapView'
119
+ 'LuggMapView'
84
120
  ) as ComponentType;