@lugg/maps 0.2.0-alpha.6 → 0.2.0-alpha.8

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 (49) hide show
  1. package/README.md +17 -4
  2. package/lib/module/MapProvider.js +13 -0
  3. package/lib/module/MapProvider.js.map +1 -0
  4. package/lib/module/MapProvider.types.js +4 -0
  5. package/lib/module/MapProvider.types.js.map +1 -0
  6. package/lib/module/MapProvider.web.js +14 -0
  7. package/lib/module/MapProvider.web.js.map +1 -0
  8. package/lib/module/MapView.web.js +264 -0
  9. package/lib/module/MapView.web.js.map +1 -0
  10. package/lib/module/components/Marker.web.js +34 -0
  11. package/lib/module/components/Marker.web.js.map +1 -0
  12. package/lib/module/components/Polyline.web.js +171 -0
  13. package/lib/module/components/Polyline.web.js.map +1 -0
  14. package/lib/module/components/index.js +2 -2
  15. package/lib/module/components/index.js.map +1 -1
  16. package/lib/module/components/index.web.js +5 -0
  17. package/lib/module/components/index.web.js.map +1 -0
  18. package/lib/module/index.js +3 -2
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/index.web.js +6 -0
  21. package/lib/module/index.web.js.map +1 -0
  22. package/lib/typescript/src/MapProvider.d.ts +8 -0
  23. package/lib/typescript/src/MapProvider.d.ts.map +1 -0
  24. package/lib/typescript/src/MapProvider.types.d.ts +16 -0
  25. package/lib/typescript/src/MapProvider.types.d.ts.map +1 -0
  26. package/lib/typescript/src/MapProvider.web.d.ts +3 -0
  27. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -0
  28. package/lib/typescript/src/MapView.web.d.ts +12 -0
  29. package/lib/typescript/src/MapView.web.d.ts.map +1 -0
  30. package/lib/typescript/src/components/Marker.web.d.ts +6 -0
  31. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -0
  32. package/lib/typescript/src/components/Polyline.web.d.ts +6 -0
  33. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -0
  34. package/lib/typescript/src/components/index.web.d.ts +5 -0
  35. package/lib/typescript/src/components/index.web.d.ts.map +1 -0
  36. package/lib/typescript/src/index.d.ts +3 -1
  37. package/lib/typescript/src/index.d.ts.map +1 -1
  38. package/lib/typescript/src/index.web.d.ts +7 -0
  39. package/lib/typescript/src/index.web.d.ts.map +1 -0
  40. package/package.json +13 -1
  41. package/src/MapProvider.tsx +10 -0
  42. package/src/MapProvider.types.ts +16 -0
  43. package/src/MapProvider.web.tsx +6 -0
  44. package/src/MapView.web.tsx +317 -0
  45. package/src/components/Marker.web.tsx +32 -0
  46. package/src/components/Polyline.web.tsx +206 -0
  47. package/src/components/index.web.ts +4 -0
  48. package/src/index.ts +8 -1
  49. package/src/index.web.ts +17 -0
@@ -0,0 +1,206 @@
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 {
15
+ const hex = (c: string) => parseInt(c, 16);
16
+ const r1 = hex(color1.slice(1, 3));
17
+ const g1 = hex(color1.slice(3, 5));
18
+ const b1 = hex(color1.slice(5, 7));
19
+ const r2 = hex(color2.slice(1, 3));
20
+ const g2 = hex(color2.slice(3, 5));
21
+ const b2 = hex(color2.slice(5, 7));
22
+
23
+ const r = Math.round(r1 + (r2 - r1) * t);
24
+ const g = Math.round(g1 + (g2 - g1) * t);
25
+ const b = Math.round(b1 + (b2 - b1) * t);
26
+
27
+ return `#${r.toString(16).padStart(2, '0')}${g
28
+ .toString(16)
29
+ .padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
30
+ }
31
+
32
+ function getGradientColor(colors: string[], position: number): string {
33
+ if (colors.length === 0) return '#000000';
34
+ if (colors.length === 1 || position <= 0) return colors[0]!;
35
+ if (position >= 1) return colors[colors.length - 1]!;
36
+
37
+ const scaledPos = position * (colors.length - 1);
38
+ const index = Math.floor(scaledPos);
39
+ const t = scaledPos - index;
40
+
41
+ return interpolateColor(colors[index]!, colors[index + 1]!, t);
42
+ }
43
+
44
+ function PolylineImpl({
45
+ coordinates,
46
+ strokeColors,
47
+ strokeWidth = 1,
48
+ animated,
49
+ }: PolylineProps) {
50
+ const map = useMap();
51
+ const polylinesRef = useRef<google.maps.Polyline[]>([]);
52
+ const animationRef = useRef<number>(0);
53
+
54
+ const colors = useMemo(
55
+ () =>
56
+ strokeColors && strokeColors.length > 0
57
+ ? (strokeColors as string[])
58
+ : ['#000000'],
59
+ [strokeColors]
60
+ );
61
+
62
+ const hasGradient = colors.length > 1;
63
+
64
+ // Refs for animation loop access
65
+ const propsRef = useRef({ map, colors, strokeWidth, hasGradient });
66
+ const [mapReady, setMapReady] = useState(!!map);
67
+
68
+ useEffect(() => {
69
+ propsRef.current = { map, colors, strokeWidth, hasGradient };
70
+ if (map && !mapReady) setMapReady(true);
71
+ }, [map, colors, strokeWidth, hasGradient, mapReady]);
72
+
73
+ const updatePath = useCallback((path: google.maps.LatLngLiteral[]) => {
74
+ const {
75
+ map: currentMap,
76
+ colors: currentColors,
77
+ strokeWidth: currentStrokeWidth,
78
+ hasGradient: currentHasGradient,
79
+ } = propsRef.current;
80
+ if (!currentMap || path.length < 2) return;
81
+
82
+ const neededSegments = currentHasGradient ? path.length - 1 : 1;
83
+ const existing = polylinesRef.current;
84
+
85
+ // Update or create segments
86
+ for (let i = 0; i < neededSegments; i++) {
87
+ const segmentPath = currentHasGradient ? [path[i]!, path[i + 1]!] : path;
88
+ const color = currentHasGradient
89
+ ? getGradientColor(currentColors, i / (path.length - 1))
90
+ : currentColors[0]!;
91
+
92
+ const segment = existing[i];
93
+ if (segment) {
94
+ segment.setPath(segmentPath);
95
+ segment.setOptions({ strokeColor: color });
96
+ } else {
97
+ existing.push(
98
+ new google.maps.Polyline({
99
+ path: segmentPath,
100
+ strokeColor: color,
101
+ strokeWeight: currentStrokeWidth,
102
+ strokeOpacity: 1,
103
+ map: currentMap,
104
+ })
105
+ );
106
+ }
107
+ }
108
+
109
+ // Remove extra segments
110
+ for (let i = neededSegments; i < existing.length; i++) {
111
+ existing[i]?.setMap(null);
112
+ }
113
+ existing.length = neededSegments;
114
+ }, []);
115
+
116
+ // Cleanup on unmount
117
+ useEffect(() => {
118
+ const polylines = polylinesRef.current;
119
+ return () => {
120
+ cancelAnimationFrame(animationRef.current);
121
+ polylines.forEach((p) => p.setMap(null));
122
+ };
123
+ }, []);
124
+
125
+ // Main effect
126
+ useEffect(() => {
127
+ if (!propsRef.current.map || coordinates.length === 0) return;
128
+
129
+ const fullPath = coordinates.map((c) => ({
130
+ lat: c.latitude,
131
+ lng: c.longitude,
132
+ }));
133
+
134
+ cancelAnimationFrame(animationRef.current);
135
+
136
+ if (!animated) {
137
+ updatePath(fullPath);
138
+ return;
139
+ }
140
+
141
+ const totalPoints = fullPath.length;
142
+ const cycleDuration = ANIMATION_DURATION * 2;
143
+
144
+ 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;
148
+
149
+ const partialPath: google.maps.LatLngLiteral[] = [];
150
+ const startFloor = Math.floor(startIdx);
151
+ const endFloor = Math.floor(endIdx);
152
+
153
+ // Start point (interpolated)
154
+ if (startFloor < totalPoints) {
155
+ const frac = startIdx - startFloor;
156
+ const from = fullPath[startFloor]!;
157
+ const to = fullPath[Math.min(startFloor + 1, totalPoints - 1)]!;
158
+ partialPath.push(
159
+ frac > 0
160
+ ? {
161
+ lat: from.lat + (to.lat - from.lat) * frac,
162
+ lng: from.lng + (to.lng - from.lng) * frac,
163
+ }
164
+ : from
165
+ );
166
+ }
167
+
168
+ // Middle points
169
+ for (
170
+ let i = startFloor + 1;
171
+ i <= Math.min(endFloor, totalPoints - 1);
172
+ i++
173
+ ) {
174
+ partialPath.push(fullPath[i]!);
175
+ }
176
+
177
+ // End point (interpolated)
178
+ if (endFloor < totalPoints - 1) {
179
+ const frac = endIdx - endFloor;
180
+ const from = fullPath[endFloor]!;
181
+ const to = fullPath[endFloor + 1]!;
182
+ if (frac > 0) {
183
+ partialPath.push({
184
+ lat: from.lat + (to.lat - from.lat) * frac,
185
+ lng: from.lng + (to.lng - from.lng) * frac,
186
+ });
187
+ }
188
+ }
189
+
190
+ updatePath(partialPath);
191
+ animationRef.current = requestAnimationFrame(animate);
192
+ };
193
+
194
+ animationRef.current = requestAnimationFrame(animate);
195
+
196
+ return () => cancelAnimationFrame(animationRef.current);
197
+ }, [coordinates, animated, hasGradient, updatePath, mapReady]);
198
+
199
+ return null;
200
+ }
201
+
202
+ export class Polyline extends Component<PolylineProps> {
203
+ render() {
204
+ return <PolylineImpl {...this.props} />;
205
+ }
206
+ }
@@ -0,0 +1,4 @@
1
+ export { Marker } from './Marker.web';
2
+ export { Polyline } from './Polyline.web';
3
+ export type { MarkerProps } from './Marker';
4
+ export type { PolylineProps } from './Polyline';
package/src/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { MapView } from './MapView';
2
+ export { MapProvider } from './MapProvider';
3
+ export type { MapProviderProps } from './MapProvider.types';
2
4
  export * from './components';
3
5
  export type {
4
6
  MapViewProps,
@@ -7,4 +9,9 @@ export type {
7
9
  FitCoordinatesOptions,
8
10
  CameraEventPayload,
9
11
  } from './MapView.types';
10
- export type { MapProvider, Coordinate, Point, EdgeInsets } from './types';
12
+ export type {
13
+ MapProvider as MapProviderType,
14
+ Coordinate,
15
+ Point,
16
+ EdgeInsets,
17
+ } from './types';
@@ -0,0 +1,17 @@
1
+ export { MapView } from './MapView.web';
2
+ export { MapProvider } from './MapProvider.web';
3
+ export type { MapProviderProps } from './MapProvider.types';
4
+ export * from './components/index.web';
5
+ export type {
6
+ MapViewProps,
7
+ MapViewRef,
8
+ MoveCameraOptions,
9
+ FitCoordinatesOptions,
10
+ CameraEventPayload,
11
+ } from './MapView.types';
12
+ export type {
13
+ MapProvider as MapProviderType,
14
+ Coordinate,
15
+ Point,
16
+ EdgeInsets,
17
+ } from './types';