react-native-mapsforge-vtm-ext-grib 0.2.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +118 -0
  3. package/android/CMakeLists.txt +13 -0
  4. package/android/build.gradle +108 -0
  5. package/android/generated/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/NativeWeatherOverlaySpec.java +95 -0
  6. package/android/generated/jni/CMakeLists.txt +28 -0
  7. package/android/generated/jni/RNMapsforgeVtmExtGribSpec-generated.cpp +62 -0
  8. package/android/generated/jni/RNMapsforgeVtmExtGribSpec.h +31 -0
  9. package/android/generated/jni/react/renderer/components/RNMapsforgeVtmExtGribSpec/RNMapsforgeVtmExtGribSpecJSI.h +521 -0
  10. package/android/gradle.properties +5 -0
  11. package/android/src/main/AndroidManifest.xml +2 -0
  12. package/android/src/main/AndroidManifestNew.xml +2 -0
  13. package/android/src/main/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/ExtGribPackage.java +62 -0
  14. package/android/src/main/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/modules/WeatherOverlay.java +343 -0
  15. package/android/src/main/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/tiles/ColorRamp.java +165 -0
  16. package/android/src/main/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/tiles/WeatherGridData.java +103 -0
  17. package/android/src/main/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/tiles/WeatherTileDataSource.java +147 -0
  18. package/android/src/main/java/com/jhotadhari/reactnative/mapsforge/vtm/ext/grib/tiles/WeatherTileSource.java +80 -0
  19. package/lib/commonjs/NativeModules/NativeWeatherOverlay.js +9 -0
  20. package/lib/commonjs/NativeModules/NativeWeatherOverlay.js.map +1 -0
  21. package/lib/commonjs/components/WeatherOverlay.js +180 -0
  22. package/lib/commonjs/components/WeatherOverlay.js.map +1 -0
  23. package/lib/commonjs/index.js +21 -0
  24. package/lib/commonjs/index.js.map +1 -0
  25. package/lib/commonjs/package.json +1 -0
  26. package/lib/commonjs/reanimated/index.js +13 -0
  27. package/lib/commonjs/reanimated/index.js.map +1 -0
  28. package/lib/commonjs/reanimated/useWeatherAnimation.js +86 -0
  29. package/lib/commonjs/reanimated/useWeatherAnimation.js.map +1 -0
  30. package/lib/commonjs/reportNativeError.js +14 -0
  31. package/lib/commonjs/reportNativeError.js.map +1 -0
  32. package/lib/commonjs/types.js +2 -0
  33. package/lib/commonjs/types.js.map +1 -0
  34. package/lib/module/NativeModules/NativeWeatherOverlay.js +5 -0
  35. package/lib/module/NativeModules/NativeWeatherOverlay.js.map +1 -0
  36. package/lib/module/components/WeatherOverlay.js +174 -0
  37. package/lib/module/components/WeatherOverlay.js.map +1 -0
  38. package/lib/module/index.js +16 -0
  39. package/lib/module/index.js.map +1 -0
  40. package/lib/module/package.json +1 -0
  41. package/lib/module/reanimated/index.js +4 -0
  42. package/lib/module/reanimated/index.js.map +1 -0
  43. package/lib/module/reanimated/useWeatherAnimation.js +81 -0
  44. package/lib/module/reanimated/useWeatherAnimation.js.map +1 -0
  45. package/lib/module/reportNativeError.js +10 -0
  46. package/lib/module/reportNativeError.js.map +1 -0
  47. package/lib/module/types.js +2 -0
  48. package/lib/module/types.js.map +1 -0
  49. package/lib/typescript/commonjs/package.json +1 -0
  50. package/lib/typescript/commonjs/src/NativeModules/NativeWeatherOverlay.d.ts +63 -0
  51. package/lib/typescript/commonjs/src/NativeModules/NativeWeatherOverlay.d.ts.map +1 -0
  52. package/lib/typescript/commonjs/src/components/WeatherOverlay.d.ts +10 -0
  53. package/lib/typescript/commonjs/src/components/WeatherOverlay.d.ts.map +1 -0
  54. package/lib/typescript/commonjs/src/index.d.ts +11 -0
  55. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  56. package/lib/typescript/commonjs/src/reanimated/index.d.ts +3 -0
  57. package/lib/typescript/commonjs/src/reanimated/index.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/src/reanimated/useWeatherAnimation.d.ts +44 -0
  59. package/lib/typescript/commonjs/src/reanimated/useWeatherAnimation.d.ts.map +1 -0
  60. package/lib/typescript/commonjs/src/reportNativeError.d.ts +3 -0
  61. package/lib/typescript/commonjs/src/reportNativeError.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/src/types.d.ts +51 -0
  63. package/lib/typescript/commonjs/src/types.d.ts.map +1 -0
  64. package/lib/typescript/module/package.json +1 -0
  65. package/lib/typescript/module/src/NativeModules/NativeWeatherOverlay.d.ts +63 -0
  66. package/lib/typescript/module/src/NativeModules/NativeWeatherOverlay.d.ts.map +1 -0
  67. package/lib/typescript/module/src/components/WeatherOverlay.d.ts +10 -0
  68. package/lib/typescript/module/src/components/WeatherOverlay.d.ts.map +1 -0
  69. package/lib/typescript/module/src/index.d.ts +11 -0
  70. package/lib/typescript/module/src/index.d.ts.map +1 -0
  71. package/lib/typescript/module/src/reanimated/index.d.ts +3 -0
  72. package/lib/typescript/module/src/reanimated/index.d.ts.map +1 -0
  73. package/lib/typescript/module/src/reanimated/useWeatherAnimation.d.ts +44 -0
  74. package/lib/typescript/module/src/reanimated/useWeatherAnimation.d.ts.map +1 -0
  75. package/lib/typescript/module/src/reportNativeError.d.ts +3 -0
  76. package/lib/typescript/module/src/reportNativeError.d.ts.map +1 -0
  77. package/lib/typescript/module/src/types.d.ts +51 -0
  78. package/lib/typescript/module/src/types.d.ts.map +1 -0
  79. package/package.json +159 -0
  80. package/react-native.config.js +13 -0
  81. package/src/NativeModules/NativeWeatherOverlay.ts +73 -0
  82. package/src/components/WeatherOverlay.tsx +173 -0
  83. package/src/index.ts +22 -0
  84. package/src/reanimated/index.ts +2 -0
  85. package/src/reanimated/useWeatherAnimation.ts +118 -0
  86. package/src/reportNativeError.ts +15 -0
  87. package/src/types.ts +56 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * react-native-mapsforge-vtm-ext-grib
3
+ *
4
+ * Weather GRIB overlay extension for react-native-mapsforge-vtm.
5
+ */
6
+ export { default as WeatherOverlay } from './components/WeatherOverlay.js';
7
+ export type { WeatherOverlayProps } from './NativeModules/NativeWeatherOverlay.js';
8
+ export type { WeatherGrid, WeatherMetadata, ColorMapName, ResponseBase, ErrorBase, } from './types.js';
9
+ export { useWeatherAnimation } from './reanimated/useWeatherAnimation.js';
10
+ export type { WeatherAnimationControls } from './reanimated/useWeatherAnimation.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,gCAA6B,CAAC;AACxE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yCAAsC,CAAC;AAGhF,YAAY,EACX,WAAW,EACX,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,SAAS,GACT,MAAM,YAAS,CAAC;AAGjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAkC,CAAC;AACvE,YAAY,EAAE,wBAAwB,EAAE,MAAM,qCAAkC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { useWeatherAnimation } from './useWeatherAnimation.js';
2
+ export type { WeatherAnimationControls } from './useWeatherAnimation.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/reanimated/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAAuB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { type SharedValue } from 'react-native-reanimated';
2
+ export interface WeatherAnimationControls {
3
+ /** The current animation progress (0.0 to timeSteps.length - 1). */
4
+ progressSv: SharedValue<number>;
5
+ /** Start playing the animation. */
6
+ play: () => void;
7
+ /** Pause the animation. */
8
+ pause: () => void;
9
+ /** Reset to the first time step. */
10
+ reset: () => void;
11
+ /** Seek to a specific time step index (fractional for interpolation). */
12
+ seek: (timeIndex: number) => void;
13
+ }
14
+ /**
15
+ * Creates a reanimated shared value that drives smooth time-step animation
16
+ * for a weather overlay.
17
+ *
18
+ * The progress value ranges from 0.0 to (numTimeSteps - 1), where the
19
+ * fractional part represents the interpolation between adjacent time steps.
20
+ *
21
+ * Usage with WeatherOverlay:
22
+ * - Pass `Math.floor(progress.value)` as `timeIndex` to the "current" layer
23
+ * - Pass `Math.ceil(progress.value)` as `timeIndex` to the "next" layer
24
+ * - Set the "next" layer's opacity to `progress.value - Math.floor(progress.value)`
25
+ *
26
+ * @param numTimeSteps - Total number of forecast time steps available.
27
+ * @param durationMs - Duration of the full animation in milliseconds.
28
+ * @returns Animation controls including the progress shared value.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * const { progressSv, play, pause } = useWeatherAnimation(
33
+ * weatherData.timeSteps.length,
34
+ * 10000
35
+ * );
36
+ *
37
+ * // In a worklet or useDerivedValue:
38
+ * const currentIdx = Math.floor(progressSv.value);
39
+ * const nextAlpha = progressSv.value - currentIdx;
40
+ * ```
41
+ */
42
+ export declare function useWeatherAnimation(numTimeSteps: number, durationMs?: number): WeatherAnimationControls;
43
+ export default useWeatherAnimation;
44
+ //# sourceMappingURL=useWeatherAnimation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWeatherAnimation.d.ts","sourceRoot":"","sources":["../../../../../src/reanimated/useWeatherAnimation.ts"],"names":[],"mappings":"AACA,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,wBAAwB;IACxC,oEAAoE;IACpE,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,mCAAmC;IACnC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,oCAAoC;IACpC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yEAAyE;IACzE,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,mBAAmB,CAClC,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,MAAc,GACxB,wBAAwB,CAgE1B;AAED,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ErrorBase } from './types.js';
2
+ export default function reportNativeError(err: ErrorBase, onError?: null | ((err: ErrorBase) => void)): void;
3
+ //# sourceMappingURL=reportNativeError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reportNativeError.d.ts","sourceRoot":"","sources":["../../../../src/reportNativeError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAS,CAAC;AAEzC,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACxC,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC,GACzC,IAAI,CASN"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Base types shared across the ext-grib library.
3
+ *
4
+ * Mirrors the pattern from react-native-mapsforge-vtm's types.ts.
5
+ */
6
+ export interface ResponseBase {
7
+ uuid: string;
8
+ nativeNodeHandle: number;
9
+ }
10
+ export interface ErrorBase {
11
+ userInfo?: {
12
+ errorMsg?: string;
13
+ };
14
+ }
15
+ /**
16
+ * Represents one time step of gridded weather data.
17
+ * This is the format produced by server-side GRIB to JSON conversion
18
+ * (and later by on-device JGribX parsing).
19
+ */
20
+ export interface WeatherGrid {
21
+ /** UTC ISO timestamp e.g. "2026-07-03T00:00:00Z" */
22
+ validTime: string;
23
+ /** Minimum latitude of the grid (southern edge) */
24
+ minLat: number;
25
+ /** Maximum latitude of the grid (northern edge) */
26
+ maxLat: number;
27
+ /** Minimum longitude of the grid (western edge) */
28
+ minLng: number;
29
+ /** Maximum longitude of the grid (eastern edge) */
30
+ maxLng: number;
31
+ /** Number of grid points in the longitude direction */
32
+ ni: number;
33
+ /** Number of grid points in the latitude direction */
34
+ nj: number;
35
+ /** Row-major grid values, length = ni * nj. Missing values are NaN. */
36
+ values: number[];
37
+ }
38
+ /**
39
+ * Metadata for a weather data source (returned after loading).
40
+ */
41
+ export interface WeatherMetadata {
42
+ parameter: string;
43
+ levelType?: string;
44
+ unit: string;
45
+ timeSteps: WeatherGrid[];
46
+ }
47
+ /**
48
+ * Built-in color ramp identifiers.
49
+ */
50
+ export type ColorMapName = 'temperature' | 'wind' | 'pressure' | 'rainfall' | 'waves' | 'grayscale';
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC3B,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;IACX,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,WAAW,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACvB,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC"}
package/package.json ADDED
@@ -0,0 +1,159 @@
1
+ {
2
+ "name": "react-native-mapsforge-vtm-ext-grib",
3
+ "version": "0.2.0",
4
+ "description": "Weather GRIB overlay extension for react-native-mapsforge-vtm. Renders gridded weather data (wind, temperature, pressure, etc.) as colored overlays on offline vector maps. Android only.",
5
+ "source": "./src/index.ts",
6
+ "main": "./lib/commonjs/index.js",
7
+ "module": "./lib/module/index.js",
8
+ "types": "./lib/typescript/commonjs/src/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./lib/typescript/module/src/index.d.ts",
13
+ "default": "./lib/module/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./lib/typescript/commonjs/src/index.d.ts",
17
+ "default": "./lib/commonjs/index.js"
18
+ }
19
+ },
20
+ "./package.json": "./package.json",
21
+ "./reanimated": {
22
+ "import": {
23
+ "types": "./lib/typescript/module/src/reanimated/index.d.ts",
24
+ "default": "./lib/module/reanimated/index.js"
25
+ },
26
+ "require": {
27
+ "types": "./lib/typescript/commonjs/src/reanimated/index.d.ts",
28
+ "default": "./lib/commonjs/reanimated/index.js"
29
+ }
30
+ }
31
+ },
32
+ "files": [
33
+ "src",
34
+ "lib",
35
+ "android",
36
+ "react-native.config.js",
37
+ "!ios/build",
38
+ "!android/build",
39
+ "!android/gradle",
40
+ "!android/gradlew",
41
+ "!android/gradlew.bat",
42
+ "!android/local.properties",
43
+ "!**/__tests__",
44
+ "!**/__fixtures__",
45
+ "!**/__mocks__",
46
+ "!**/.*"
47
+ ],
48
+ "scripts": {
49
+ "example": "yarn workspace react-native-mapsforge-vtm-ext-grib-example",
50
+ "test": "jest",
51
+ "typecheck": "tsc",
52
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
53
+ "format": "prettier . --write",
54
+ "clean": "del-cli android/build example/android/build example/android/app/build lib",
55
+ "prepare": "bob build",
56
+ "postinstall": "node -e \"['react','react-native','react-native-mapsforge-vtm'].forEach(m=>{const t='node_modules/'+m,s='example/'+t;require('fs').existsSync(s)&&!require('fs').lstatSync(t).isSymbolicLink()&&(require('fs').rmSync(t,{recursive:true,force:true}),require('fs').symlinkSync(require('path').relative(require('path').dirname(t),require('path').resolve(s)),t,'dir'))})\"",
57
+ "release": "release-kit"
58
+ },
59
+ "keywords": [
60
+ "react-native",
61
+ "android",
62
+ "maps",
63
+ "offline",
64
+ "weather",
65
+ "grib",
66
+ "mapsforge",
67
+ "vtm"
68
+ ],
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "git+https://github.com/jhotadhari/react-native-mapsforge-vtm-ext-grib.git"
72
+ },
73
+ "author": "jhotadhari <tellme@waterproof-webdesign.de> (https://github.com/jhotadhari)",
74
+ "license": "MIT",
75
+ "publishConfig": {
76
+ "registry": "https://registry.npmjs.org/"
77
+ },
78
+ "devDependencies": {
79
+ "@eslint/compat": "^2.1.0",
80
+ "@eslint/eslintrc": "^3.3.5",
81
+ "@eslint/js": "^9.22.0",
82
+ "@evilmartians/lefthook": "^2.1.9",
83
+ "@jhotadhari/release-kit": "^0.0.6",
84
+ "@react-native/eslint-config": "^0.86.0",
85
+ "@types/jest": "^29.5.5",
86
+ "@types/react": "^19.2.17",
87
+ "del-cli": "^7.0.0",
88
+ "eslint": "^9.22.0",
89
+ "eslint-config-prettier": "^10.1.8",
90
+ "eslint-plugin-prettier": "^5.5.6",
91
+ "jest": "^29.7.0",
92
+ "prettier": "^3.8.4",
93
+ "prettier-plugin-embed": "^0.5.1",
94
+ "prettier-plugin-multiline-arrays": "^4.1.9",
95
+ "react": "19.2.7",
96
+ "react-native": "0.86.0",
97
+ "react-native-builder-bob": "^0.43.0",
98
+ "react-native-reanimated": ">=3.0.0",
99
+ "react-native-worklets": ">=0.1.0",
100
+ "typescript": "^6.0.3"
101
+ },
102
+ "peerDependencies": {
103
+ "react": "*",
104
+ "react-native": ">=0.80.0",
105
+ "react-native-mapsforge-vtm": "^0.9.0",
106
+ "react-native-reanimated": ">=3.0.0",
107
+ "react-native-worklets": ">=0.1.0"
108
+ },
109
+ "peerDependenciesMeta": {
110
+ "react-native-reanimated": {
111
+ "optional": true
112
+ },
113
+ "react-native-worklets": {
114
+ "optional": true
115
+ }
116
+ },
117
+ "workspaces": [
118
+ "example"
119
+ ],
120
+ "packageManager": "yarn@3.6.1",
121
+ "react-native-builder-bob": {
122
+ "source": "src",
123
+ "output": "lib",
124
+ "targets": [
125
+ "codegen",
126
+ [
127
+ "module",
128
+ {
129
+ "esm": true
130
+ }
131
+ ],
132
+ [
133
+ "commonjs",
134
+ {
135
+ "esm": true
136
+ }
137
+ ],
138
+ [
139
+ "typescript",
140
+ {
141
+ "project": "tsconfig.build.json"
142
+ }
143
+ ]
144
+ ]
145
+ },
146
+ "codegenConfig": {
147
+ "name": "RNMapsforgeVtmExtGribSpec",
148
+ "type": "modules",
149
+ "jsSrcsDir": "src",
150
+ "outputDir": {
151
+ "ios": "ios/generated",
152
+ "android": "android/generated"
153
+ },
154
+ "android": {
155
+ "javaPackageName": "com.jhotadhari.reactnative.mapsforge.vtm.ext.grib"
156
+ },
157
+ "includesGeneratedCode": true
158
+ }
159
+ }
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ dependency: {
3
+ platforms: {
4
+ android: {
5
+ sourceDir: './android',
6
+ cmakeListsPath: 'CMakeLists.txt',
7
+ packageImportPath:
8
+ 'import com.jhotadhari.reactnative.mapsforge.vtm.ext.grib.ExtGribPackage;',
9
+ packageInstance: 'new ExtGribPackage()',
10
+ },
11
+ },
12
+ },
13
+ };
@@ -0,0 +1,73 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+ import type { Double, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
4
+ import type { ErrorBase, ResponseBase } from '../types';
5
+
6
+ export interface ModuleParams {
7
+ dataUrl?: string;
8
+ parameter?: string;
9
+ timeIndex?: Int32;
10
+ colorMap?: string;
11
+ opacity?: Double;
12
+ zoomMin?: Int32;
13
+ zoomMax?: Int32;
14
+ enabledZoomMin?: Int32;
15
+ enabledZoomMax?: Int32;
16
+ }
17
+
18
+ interface CreateLayerParams extends ModuleParams {
19
+ nativeNodeHandle?: Int32;
20
+ }
21
+
22
+ interface RemoveLayerParams {
23
+ nativeNodeHandle: Int32;
24
+ uuid: string;
25
+ }
26
+
27
+ interface UpdateEnabledZoomMinMaxParams {
28
+ nativeNodeHandle: Int32;
29
+ uuid: string;
30
+ enabledZoomMin?: Int32;
31
+ enabledZoomMax?: Int32;
32
+ }
33
+
34
+ interface SetOpacityParams {
35
+ nativeNodeHandle: Int32;
36
+ uuid: string;
37
+ opacity?: Double;
38
+ }
39
+
40
+ interface SetTimeIndexParams {
41
+ nativeNodeHandle: Int32;
42
+ uuid: string;
43
+ timeIndex: Int32;
44
+ }
45
+
46
+ export type WeatherOverlayProps = {
47
+ dataUrl?: string;
48
+ parameter?: string;
49
+ timeIndex?: number;
50
+ colorMap?: string;
51
+ opacity?: number;
52
+ zoomMin?: number;
53
+ zoomMax?: number;
54
+ enabledZoomMin?: number;
55
+ enabledZoomMax?: number;
56
+ onCreate?: null | ((result: ResponseBase) => void);
57
+ onRemove?: null | ((result: ResponseBase) => void);
58
+ onChange?: null | ((result: ResponseBase) => void);
59
+ onError?: null | ((err: ErrorBase) => void);
60
+ };
61
+
62
+ export interface Spec extends TurboModule {
63
+ getConstants(): ModuleParams;
64
+ createLayer(params: CreateLayerParams): Promise<string>;
65
+ removeLayer(params: RemoveLayerParams): Promise<string>;
66
+ updateEnabledZoomMinMax(
67
+ params: UpdateEnabledZoomMinMaxParams
68
+ ): Promise<string>;
69
+ setOpacity(params: SetOpacityParams): Promise<string>;
70
+ setTimeIndex(params: SetTimeIndexParams): Promise<string>;
71
+ }
72
+
73
+ export default TurboModuleRegistry.getEnforcing<Spec>('WeatherOverlay');
@@ -0,0 +1,173 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { useContext, useEffect } from 'react';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import WeatherOverlayModule, {
10
+ type WeatherOverlayProps,
11
+ } from '../NativeModules/NativeWeatherOverlay';
12
+ import type { ErrorBase } from '../types';
13
+ import reportNativeError from '../reportNativeError';
14
+
15
+ /**
16
+ * Peer dependencies (from react-native-mapsforge-vtm)
17
+ */
18
+ import {
19
+ MapHandleContext,
20
+ useLayerAnchor,
21
+ useSceneUuidBinding,
22
+ useNativeLayerLifecycle,
23
+ } from 'react-native-mapsforge-vtm';
24
+
25
+ const WeatherOverlay = ({
26
+ dataUrl,
27
+ parameter,
28
+ timeIndex,
29
+ colorMap,
30
+ opacity,
31
+ zoomMin,
32
+ zoomMax,
33
+ enabledZoomMin,
34
+ enabledZoomMax,
35
+ onCreate,
36
+ onRemove,
37
+ onChange,
38
+ onError,
39
+ }: WeatherOverlayProps) => {
40
+ const { nativeNodeHandle } = useContext(MapHandleContext);
41
+
42
+ const { uid: anchorUid, element: anchorElement } = useLayerAnchor({
43
+ kind: 'layer',
44
+ });
45
+
46
+ const { uuid, triggerCreate, triggerRemove } = useNativeLayerLifecycle({
47
+ enabled: !!nativeNodeHandle && !!dataUrl,
48
+ create: ({ triggerOnCreate, triggerOnChange }) => {
49
+ if (!nativeNodeHandle) {
50
+ return Promise.reject<string>({
51
+ userInfo: { errorMsg: 'Missing nativeNodeHandle' },
52
+ } as ErrorBase);
53
+ }
54
+ return WeatherOverlayModule.createLayer({
55
+ nativeNodeHandle,
56
+ ...(dataUrl && { dataUrl }),
57
+ ...(parameter && { parameter }),
58
+ ...(timeIndex != null && { timeIndex: Math.round(timeIndex) }),
59
+ ...(colorMap && { colorMap }),
60
+ ...(opacity != null && { opacity }),
61
+ ...(zoomMin != null && { zoomMin: Math.round(zoomMin) }),
62
+ ...(zoomMax != null && { zoomMax: Math.round(zoomMax) }),
63
+ ...(enabledZoomMin != null && {
64
+ enabledZoomMin: Math.round(enabledZoomMin),
65
+ }),
66
+ ...(enabledZoomMax != null && {
67
+ enabledZoomMax: Math.round(enabledZoomMax),
68
+ }),
69
+ }).then((newUuid) => {
70
+ triggerOnCreate && onCreate
71
+ ? onCreate({ nativeNodeHandle, uuid: newUuid })
72
+ : null;
73
+ triggerOnChange && onChange
74
+ ? onChange({ nativeNodeHandle, uuid: newUuid })
75
+ : null;
76
+ return newUuid;
77
+ });
78
+ },
79
+ remove: (currentUuid, { triggerOnRemove }) => {
80
+ if (!nativeNodeHandle) {
81
+ return Promise.resolve(false);
82
+ }
83
+ return WeatherOverlayModule.removeLayer({
84
+ nativeNodeHandle,
85
+ uuid: currentUuid,
86
+ })
87
+ .then((removedUuid) => {
88
+ triggerOnRemove && onRemove
89
+ ? onRemove({ nativeNodeHandle, uuid: removedUuid })
90
+ : null;
91
+ return true;
92
+ })
93
+ .catch((err: ErrorBase) => {
94
+ reportNativeError(err, onError);
95
+ return false;
96
+ });
97
+ },
98
+ onError,
99
+ });
100
+
101
+ useSceneUuidBinding(anchorUid, uuid);
102
+
103
+ // Update enabledZoomMin/enabledZoomMax in place.
104
+ useEffect(() => {
105
+ if (nativeNodeHandle && uuid) {
106
+ WeatherOverlayModule.updateEnabledZoomMinMax({
107
+ nativeNodeHandle,
108
+ uuid,
109
+ ...(enabledZoomMin != null && {
110
+ enabledZoomMin: Math.round(enabledZoomMin),
111
+ }),
112
+ ...(enabledZoomMax != null && {
113
+ enabledZoomMax: Math.round(enabledZoomMax),
114
+ }),
115
+ }).catch((err: ErrorBase) => {
116
+ reportNativeError(err, onError);
117
+ });
118
+ }
119
+ }, [
120
+ enabledZoomMin,
121
+ enabledZoomMax,
122
+ nativeNodeHandle,
123
+ uuid,
124
+ onError,
125
+ ]);
126
+
127
+ // Update opacity in place.
128
+ useEffect(() => {
129
+ if (nativeNodeHandle && uuid && opacity != null) {
130
+ WeatherOverlayModule.setOpacity({
131
+ nativeNodeHandle,
132
+ uuid,
133
+ opacity,
134
+ }).catch((err: ErrorBase) => {
135
+ reportNativeError(err, onError);
136
+ });
137
+ }
138
+ }, [
139
+ opacity,
140
+ nativeNodeHandle,
141
+ uuid,
142
+ onError,
143
+ ]);
144
+
145
+ // Recreate on these prop changes (baked into native construction).
146
+ // timeIndex is included here because changing it requires a fresh data
147
+ // fetch and tile source — same as dataUrl or parameter changes.
148
+ useEffect(() => {
149
+ triggerRemove({ triggerOnRemove: false }).then((success) => {
150
+ if (success) {
151
+ triggerCreate({
152
+ triggerOnCreate: false,
153
+ triggerOnChange: true,
154
+ });
155
+ }
156
+ });
157
+ }, [
158
+ dataUrl,
159
+ parameter,
160
+ timeIndex,
161
+ colorMap,
162
+ zoomMin,
163
+ zoomMax,
164
+ triggerRemove,
165
+ triggerCreate,
166
+ ]);
167
+
168
+ return anchorElement;
169
+ };
170
+
171
+ WeatherOverlay.defaults = WeatherOverlayModule.getConstants();
172
+
173
+ export default WeatherOverlay;
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * react-native-mapsforge-vtm-ext-grib
3
+ *
4
+ * Weather GRIB overlay extension for react-native-mapsforge-vtm.
5
+ */
6
+
7
+ // Main component
8
+ export { default as WeatherOverlay } from './components/WeatherOverlay';
9
+ export type { WeatherOverlayProps } from './NativeModules/NativeWeatherOverlay';
10
+
11
+ // Shared types
12
+ export type {
13
+ WeatherGrid,
14
+ WeatherMetadata,
15
+ ColorMapName,
16
+ ResponseBase,
17
+ ErrorBase,
18
+ } from './types';
19
+
20
+ // Reanimated utilities (also available via /reanimated subpath export)
21
+ export { useWeatherAnimation } from './reanimated/useWeatherAnimation';
22
+ export type { WeatherAnimationControls } from './reanimated/useWeatherAnimation';
@@ -0,0 +1,2 @@
1
+ export { useWeatherAnimation } from './useWeatherAnimation';
2
+ export type { WeatherAnimationControls } from './useWeatherAnimation';