@ingissa/navcore-react-native 1.0.7 → 1.0.9
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.
- package/dist/index.d.mts +131 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +233 -0
- package/dist/index.mjs +223 -0
- package/package.json +7 -15
- package/dist/core/src/NavCore.d.ts +0 -142
- package/dist/core/src/NavCore.d.ts.map +0 -1
- package/dist/core/src/NavCore.js +0 -390
- package/dist/core/src/bearing/BearingEngine.d.ts +0 -24
- package/dist/core/src/bearing/BearingEngine.d.ts.map +0 -1
- package/dist/core/src/bearing/BearingEngine.js +0 -50
- package/dist/core/src/constants.d.ts +0 -34
- package/dist/core/src/constants.d.ts.map +0 -1
- package/dist/core/src/constants.js +0 -41
- package/dist/core/src/corridor/DeviationDetector.d.ts +0 -33
- package/dist/core/src/corridor/DeviationDetector.d.ts.map +0 -1
- package/dist/core/src/corridor/DeviationDetector.js +0 -83
- package/dist/core/src/corridor/DynamicCorridor.d.ts +0 -13
- package/dist/core/src/corridor/DynamicCorridor.d.ts.map +0 -1
- package/dist/core/src/corridor/DynamicCorridor.js +0 -26
- package/dist/core/src/dead-reckoning/DeadReckoning.d.ts +0 -35
- package/dist/core/src/dead-reckoning/DeadReckoning.d.ts.map +0 -1
- package/dist/core/src/dead-reckoning/DeadReckoning.js +0 -49
- package/dist/core/src/directions/DirectionsProvider.d.ts +0 -70
- package/dist/core/src/directions/DirectionsProvider.d.ts.map +0 -1
- package/dist/core/src/directions/DirectionsProvider.js +0 -7
- package/dist/core/src/directions/OSRMDirectionsProvider.d.ts +0 -26
- package/dist/core/src/directions/OSRMDirectionsProvider.d.ts.map +0 -1
- package/dist/core/src/directions/OSRMDirectionsProvider.js +0 -90
- package/dist/core/src/directions/OpenRouteServiceProvider.d.ts +0 -30
- package/dist/core/src/directions/OpenRouteServiceProvider.d.ts.map +0 -1
- package/dist/core/src/directions/OpenRouteServiceProvider.js +0 -111
- package/dist/core/src/directions/ValhallaDirectionsProvider.d.ts +0 -33
- package/dist/core/src/directions/ValhallaDirectionsProvider.d.ts.map +0 -1
- package/dist/core/src/directions/ValhallaDirectionsProvider.js +0 -155
- package/dist/core/src/eta/ETAEngine.d.ts +0 -61
- package/dist/core/src/eta/ETAEngine.d.ts.map +0 -1
- package/dist/core/src/eta/ETAEngine.js +0 -74
- package/dist/core/src/features.d.ts +0 -76
- package/dist/core/src/features.d.ts.map +0 -1
- package/dist/core/src/features.js +0 -76
- package/dist/core/src/geo/bearing.d.ts +0 -11
- package/dist/core/src/geo/bearing.d.ts.map +0 -1
- package/dist/core/src/geo/bearing.js +0 -25
- package/dist/core/src/geo/cumulative.d.ts +0 -9
- package/dist/core/src/geo/cumulative.d.ts.map +0 -1
- package/dist/core/src/geo/cumulative.js +0 -20
- package/dist/core/src/geo/haversine.d.ts +0 -13
- package/dist/core/src/geo/haversine.d.ts.map +0 -1
- package/dist/core/src/geo/haversine.js +0 -39
- package/dist/core/src/geo/projection.d.ts +0 -7
- package/dist/core/src/geo/projection.d.ts.map +0 -1
- package/dist/core/src/geo/projection.js +0 -17
- package/dist/core/src/geofencing/GeofencingEngine.d.ts +0 -93
- package/dist/core/src/geofencing/GeofencingEngine.d.ts.map +0 -1
- package/dist/core/src/geofencing/GeofencingEngine.js +0 -154
- package/dist/core/src/index.d.ts +0 -66
- package/dist/core/src/index.d.ts.map +0 -1
- package/dist/core/src/index.js +0 -62
- package/dist/core/src/kalman/KalmanFilter2D.d.ts +0 -46
- package/dist/core/src/kalman/KalmanFilter2D.d.ts.map +0 -1
- package/dist/core/src/kalman/KalmanFilter2D.js +0 -77
- package/dist/core/src/license/LicenseManager.d.ts +0 -40
- package/dist/core/src/license/LicenseManager.d.ts.map +0 -1
- package/dist/core/src/license/LicenseManager.js +0 -119
- package/dist/core/src/license/verifyP256Signature.d.ts +0 -2
- package/dist/core/src/license/verifyP256Signature.d.ts.map +0 -1
- package/dist/core/src/license/verifyP256Signature.js +0 -26
- package/dist/core/src/off-route/NavigationFSM.d.ts +0 -42
- package/dist/core/src/off-route/NavigationFSM.d.ts.map +0 -1
- package/dist/core/src/off-route/NavigationFSM.js +0 -56
- package/dist/core/src/off-route/OffRouteFSM.d.ts +0 -70
- package/dist/core/src/off-route/OffRouteFSM.d.ts.map +0 -1
- package/dist/core/src/off-route/OffRouteFSM.js +0 -151
- package/dist/core/src/predictor/RouteOffsetPredictor.d.ts +0 -24
- package/dist/core/src/predictor/RouteOffsetPredictor.d.ts.map +0 -1
- package/dist/core/src/predictor/RouteOffsetPredictor.js +0 -55
- package/dist/core/src/progress/InstructionEditor.d.ts +0 -77
- package/dist/core/src/progress/InstructionEditor.d.ts.map +0 -1
- package/dist/core/src/progress/InstructionEditor.js +0 -151
- package/dist/core/src/progress/InstructionResolver.d.ts +0 -25
- package/dist/core/src/progress/InstructionResolver.d.ts.map +0 -1
- package/dist/core/src/progress/InstructionResolver.js +0 -78
- package/dist/core/src/progress/ProgressTracker.d.ts +0 -12
- package/dist/core/src/progress/ProgressTracker.d.ts.map +0 -1
- package/dist/core/src/progress/ProgressTracker.js +0 -22
- package/dist/core/src/renderer/MapRendererAdapter.d.ts +0 -72
- package/dist/core/src/renderer/MapRendererAdapter.d.ts.map +0 -1
- package/dist/core/src/renderer/MapRendererAdapter.js +0 -19
- package/dist/core/src/route-builder/CustomRouteBuilder.d.ts +0 -83
- package/dist/core/src/route-builder/CustomRouteBuilder.d.ts.map +0 -1
- package/dist/core/src/route-builder/CustomRouteBuilder.js +0 -160
- package/dist/core/src/route-plan/RoutePlan.d.ts +0 -38
- package/dist/core/src/route-plan/RoutePlan.d.ts.map +0 -1
- package/dist/core/src/route-plan/RoutePlan.js +0 -102
- package/dist/core/src/session/NavigationSession.d.ts +0 -81
- package/dist/core/src/session/NavigationSession.d.ts.map +0 -1
- package/dist/core/src/session/NavigationSession.js +0 -115
- package/dist/core/src/snapper/ParallelRoadResolver.d.ts +0 -86
- package/dist/core/src/snapper/ParallelRoadResolver.d.ts.map +0 -1
- package/dist/core/src/snapper/ParallelRoadResolver.js +0 -83
- package/dist/core/src/snapper/RouteSnapper.d.ts +0 -38
- package/dist/core/src/snapper/RouteSnapper.d.ts.map +0 -1
- package/dist/core/src/snapper/RouteSnapper.js +0 -80
- package/dist/core/src/voice/VoiceTriggerEngine.d.ts +0 -80
- package/dist/core/src/voice/VoiceTriggerEngine.d.ts.map +0 -1
- package/dist/core/src/voice/VoiceTriggerEngine.js +0 -108
- package/dist/react-native/src/NavCoreProvider.d.ts +0 -33
- package/dist/react-native/src/NavCoreProvider.d.ts.map +0 -1
- package/dist/react-native/src/NavCoreProvider.js +0 -41
- package/dist/react-native/src/index.d.ts +0 -10
- package/dist/react-native/src/index.d.ts.map +0 -1
- package/dist/react-native/src/index.js +0 -8
- package/dist/react-native/src/useNavCore.d.ts +0 -60
- package/dist/react-native/src/useNavCore.d.ts.map +0 -1
- package/dist/react-native/src/useNavCore.js +0 -119
- package/dist/react-native/src/useNavSelectors.d.ts +0 -42
- package/dist/react-native/src/useNavSelectors.d.ts.map +0 -1
- package/dist/react-native/src/useNavSelectors.js +0 -103
- package/src/NavCoreProvider.tsx +0 -59
- package/src/index.ts +0 -18
- package/src/useNavCore.ts +0 -208
- package/src/useNavSelectors.ts +0 -143
package/src/NavCoreProvider.tsx
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NavCoreProvider — React Context for shared NavCore engine access.
|
|
3
|
-
*
|
|
4
|
-
* Use when multiple components need access to the same engine instance
|
|
5
|
-
* (e.g. map view, instruction banner, debug panel).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createContext, useContext, useRef, useMemo, type ReactNode } from 'react';
|
|
9
|
-
import { NavCore, type NavCoreOptions } from '@ingissa/navcore-core';
|
|
10
|
-
|
|
11
|
-
interface NavCoreContextValue {
|
|
12
|
-
engine: NavCore;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const NavCoreContext = createContext<NavCoreContextValue | null>(null);
|
|
16
|
-
|
|
17
|
-
interface NavCoreProviderProps {
|
|
18
|
-
children: ReactNode;
|
|
19
|
-
options?: NavCoreOptions;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Wraps children with a shared NavCore engine instance.
|
|
24
|
-
*
|
|
25
|
-
* ```tsx
|
|
26
|
-
* <NavCoreProvider options={{ licenseKey: '...' }}>
|
|
27
|
-
* <MapScreen />
|
|
28
|
-
* <InstructionBanner />
|
|
29
|
-
* </NavCoreProvider>
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export function NavCoreProvider({ children, options }: NavCoreProviderProps) {
|
|
33
|
-
const engineRef = useRef<NavCore | null>(null);
|
|
34
|
-
if (!engineRef.current) {
|
|
35
|
-
engineRef.current = new NavCore(options);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const value = useMemo(() => ({
|
|
39
|
-
engine: engineRef.current!,
|
|
40
|
-
}), []);
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<NavCoreContext.Provider value={value}>
|
|
44
|
-
{children}
|
|
45
|
-
</NavCoreContext.Provider>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Access the shared NavCore engine from context.
|
|
51
|
-
* Must be used within a <NavCoreProvider>.
|
|
52
|
-
*/
|
|
53
|
-
export function useNavCoreContext(): NavCoreContextValue {
|
|
54
|
-
const ctx = useContext(NavCoreContext);
|
|
55
|
-
if (!ctx) {
|
|
56
|
-
throw new Error('useNavCoreContext must be used within a <NavCoreProvider>');
|
|
57
|
-
}
|
|
58
|
-
return ctx;
|
|
59
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @navcore/react-native — React Native bindings
|
|
3
|
-
*
|
|
4
|
-
* Provides hooks for integrating NavCore with React Native apps.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export { useNavCore } from './useNavCore';
|
|
8
|
-
export type { UseNavCoreProps, UseNavCoreReturn } from './useNavCore';
|
|
9
|
-
export { NavCoreProvider, useNavCoreContext } from './NavCoreProvider';
|
|
10
|
-
export {
|
|
11
|
-
useNavSelector,
|
|
12
|
-
useNavInstruction,
|
|
13
|
-
useNavAlert,
|
|
14
|
-
useNavProgress,
|
|
15
|
-
useNavIsOffRoute,
|
|
16
|
-
useNavSpeed,
|
|
17
|
-
type NavProgressInfo,
|
|
18
|
-
} from './useNavSelectors';
|
package/src/useNavCore.ts
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useNavCore — React hook for the NavCore navigation engine.
|
|
3
|
-
*
|
|
4
|
-
* Manages engine lifecycle, GPS → engine → state pipeline,
|
|
5
|
-
* event wiring, and optimized re-render batching.
|
|
6
|
-
*
|
|
7
|
-
* Drop-in replacement for the existing Go4Exams useNavCore hook.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
|
|
11
|
-
import {
|
|
12
|
-
NavCore,
|
|
13
|
-
type NavCoreOptions,
|
|
14
|
-
type NavGpsUpdate,
|
|
15
|
-
type NavCoreState,
|
|
16
|
-
type NavInstruction,
|
|
17
|
-
type Coordinate,
|
|
18
|
-
} from '@ingissa/navcore-core';
|
|
19
|
-
|
|
20
|
-
// ── Public types ──────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
export interface UseNavCoreProps {
|
|
23
|
-
/** Current GPS coordinate [lng, lat] */
|
|
24
|
-
gpsCoord: Coordinate | null;
|
|
25
|
-
/** GPS bearing in degrees */
|
|
26
|
-
gpsBearing?: number | null;
|
|
27
|
-
/** GPS accuracy in metres */
|
|
28
|
-
gpsAccuracy?: number | null;
|
|
29
|
-
/** GPS timestamp (ms since epoch) */
|
|
30
|
-
gpsTimestamp?: number | null;
|
|
31
|
-
/** Current speed in m/s */
|
|
32
|
-
speed: number;
|
|
33
|
-
/** Route geometry [lng, lat][] */
|
|
34
|
-
routeGeometry: Coordinate[] | null;
|
|
35
|
-
/** Navigation instructions */
|
|
36
|
-
instructions?: NavInstruction[];
|
|
37
|
-
/** Whether navigation has been started by the user */
|
|
38
|
-
isNavigating: boolean;
|
|
39
|
-
/** Engine configuration */
|
|
40
|
-
options?: NavCoreOptions;
|
|
41
|
-
/** Resume navigation at a specific route index (after rejoin) */
|
|
42
|
-
resumeAtIndex?: number | null;
|
|
43
|
-
/** Ref for external camera output (map camera integration) */
|
|
44
|
-
outputRef?: {
|
|
45
|
-
current: {
|
|
46
|
-
coord: Coordinate;
|
|
47
|
-
bearing: number;
|
|
48
|
-
speed: number;
|
|
49
|
-
} | null;
|
|
50
|
-
};
|
|
51
|
-
/** Called when deviation is confirmed */
|
|
52
|
-
onDeviation?: (event: { anchorIndex: number; ghostCoord: Coordinate }) => void;
|
|
53
|
-
/** Called when rejoin completes */
|
|
54
|
-
onRejoin?: (event: { resumeIndex: number }) => void;
|
|
55
|
-
/** Called when an instruction triggers */
|
|
56
|
-
onInstruction?: (instruction: NavInstruction) => void;
|
|
57
|
-
/** Called when arrival is detected */
|
|
58
|
-
onArrival?: () => void;
|
|
59
|
-
/** UI polling rate in Hz (default 30) */
|
|
60
|
-
pollRateHz?: number;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface UseNavCoreReturn extends NavCoreState {
|
|
64
|
-
/** The raw NavCore engine instance (for advanced usage) */
|
|
65
|
-
engine: NavCore;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ── Hook ──────────────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
export function useNavCore({
|
|
71
|
-
gpsCoord,
|
|
72
|
-
gpsBearing,
|
|
73
|
-
gpsAccuracy,
|
|
74
|
-
gpsTimestamp,
|
|
75
|
-
speed,
|
|
76
|
-
routeGeometry,
|
|
77
|
-
instructions,
|
|
78
|
-
isNavigating,
|
|
79
|
-
options,
|
|
80
|
-
resumeAtIndex,
|
|
81
|
-
outputRef,
|
|
82
|
-
onDeviation,
|
|
83
|
-
onRejoin,
|
|
84
|
-
onInstruction,
|
|
85
|
-
onArrival,
|
|
86
|
-
pollRateHz = 30,
|
|
87
|
-
}: UseNavCoreProps): UseNavCoreReturn {
|
|
88
|
-
|
|
89
|
-
// ── 1. Engine singleton ───────────────────────────────────────
|
|
90
|
-
const navRef = useRef<NavCore | null>(null);
|
|
91
|
-
if (!navRef.current) {
|
|
92
|
-
navRef.current = new NavCore(options);
|
|
93
|
-
}
|
|
94
|
-
const engine = navRef.current;
|
|
95
|
-
|
|
96
|
-
const [state, setState] = useState<NavCoreState>(() => engine.getState());
|
|
97
|
-
|
|
98
|
-
// ── 2. Event wiring ───────────────────────────────────────────
|
|
99
|
-
|
|
100
|
-
// 2a. Deviation
|
|
101
|
-
useEffect(() => {
|
|
102
|
-
if (!onDeviation) return;
|
|
103
|
-
const handler = (data: unknown) => onDeviation(data as { anchorIndex: number; ghostCoord: Coordinate });
|
|
104
|
-
engine.on('deviation', handler);
|
|
105
|
-
return () => { engine.off('deviation', handler); };
|
|
106
|
-
}, [engine, onDeviation]);
|
|
107
|
-
|
|
108
|
-
// 2b. Rejoin
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
if (!onRejoin) return;
|
|
111
|
-
const handler = (data: unknown) => onRejoin(data as { resumeIndex: number });
|
|
112
|
-
engine.on('rejoined', handler);
|
|
113
|
-
return () => { engine.off('rejoined', handler); };
|
|
114
|
-
}, [engine, onRejoin]);
|
|
115
|
-
|
|
116
|
-
// 2c. Instruction
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
if (!onInstruction) return;
|
|
119
|
-
const handler = (data: unknown) => onInstruction(data as NavInstruction);
|
|
120
|
-
engine.on('instruction', handler);
|
|
121
|
-
return () => { engine.off('instruction', handler); };
|
|
122
|
-
}, [engine, onInstruction]);
|
|
123
|
-
|
|
124
|
-
// 2d. Arrival
|
|
125
|
-
useEffect(() => {
|
|
126
|
-
if (!onArrival) return;
|
|
127
|
-
const handler = () => onArrival();
|
|
128
|
-
engine.on('arrival', handler);
|
|
129
|
-
return () => { engine.off('arrival', handler); };
|
|
130
|
-
}, [engine, onArrival]);
|
|
131
|
-
|
|
132
|
-
// ── 3. Route sync ────────────────────────────────────────────
|
|
133
|
-
useEffect(() => {
|
|
134
|
-
if (routeGeometry && routeGeometry.length >= 2) {
|
|
135
|
-
engine.setRoute(routeGeometry, instructions);
|
|
136
|
-
}
|
|
137
|
-
}, [engine, routeGeometry]);
|
|
138
|
-
|
|
139
|
-
// ── 4. Instructions sync (can change independently of route) ──
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
if (instructions && instructions.length > 0 && routeGeometry && routeGeometry.length >= 2) {
|
|
142
|
-
engine.setRoute(routeGeometry, instructions);
|
|
143
|
-
}
|
|
144
|
-
}, [engine, instructions]);
|
|
145
|
-
|
|
146
|
-
// ── 5. GPS → engine pipeline ──────────────────────────────────
|
|
147
|
-
useEffect(() => {
|
|
148
|
-
if (!gpsCoord || !isNavigating) return;
|
|
149
|
-
|
|
150
|
-
const gpsUpdate: NavGpsUpdate = {
|
|
151
|
-
coord: gpsCoord,
|
|
152
|
-
accuracy: gpsAccuracy ?? null,
|
|
153
|
-
bearing: gpsBearing ?? null,
|
|
154
|
-
speed,
|
|
155
|
-
timestamp: gpsTimestamp ?? Date.now(),
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const nextState = engine.update(gpsUpdate);
|
|
159
|
-
|
|
160
|
-
// Synchronous external camera/puck output with ZERO React re-renders
|
|
161
|
-
if (outputRef) {
|
|
162
|
-
outputRef.current = {
|
|
163
|
-
coord: nextState.snappedCoord ?? gpsCoord,
|
|
164
|
-
bearing: nextState.bearing,
|
|
165
|
-
speed: nextState.currentSpeed,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
}, [engine, gpsCoord, gpsAccuracy, gpsBearing, gpsTimestamp, speed, isNavigating, outputRef]);
|
|
169
|
-
|
|
170
|
-
// ── 6. Start navigation ───────────────────────────────────────
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
if (isNavigating) {
|
|
173
|
-
engine.startNavigation();
|
|
174
|
-
}
|
|
175
|
-
}, [engine, isNavigating]);
|
|
176
|
-
|
|
177
|
-
// ── 7. Push-based reactive state subscription ─────────────────
|
|
178
|
-
// Eliminates the 30 Hz setInterval loop. Updates state reactively
|
|
179
|
-
// only when new engine state is computed.
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
if (!isNavigating) return;
|
|
182
|
-
|
|
183
|
-
const handleUpdate = (updatedState: unknown) => {
|
|
184
|
-
setState(updatedState as NavCoreState);
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
engine.on('update', handleUpdate);
|
|
188
|
-
setState(engine.getState());
|
|
189
|
-
|
|
190
|
-
return () => {
|
|
191
|
-
engine.off('update', handleUpdate);
|
|
192
|
-
};
|
|
193
|
-
}, [engine, isNavigating]);
|
|
194
|
-
|
|
195
|
-
// ── 8. Cleanup ────────────────────────────────────────────────
|
|
196
|
-
useEffect(() => {
|
|
197
|
-
return () => {
|
|
198
|
-
engine.destroy();
|
|
199
|
-
navRef.current = null;
|
|
200
|
-
};
|
|
201
|
-
}, [engine]);
|
|
202
|
-
|
|
203
|
-
// ── 9. Stable return ──────────────────────────────────────────
|
|
204
|
-
return useMemo(() => ({
|
|
205
|
-
...state,
|
|
206
|
-
engine,
|
|
207
|
-
}), [state, engine]);
|
|
208
|
-
}
|
package/src/useNavSelectors.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Granular selector hooks for NavCore.
|
|
3
|
-
*
|
|
4
|
-
* Built with React 18 `useSyncExternalStore` for flicker-free, tearing-free
|
|
5
|
-
* state subscriptions. Components only re-render when the selected slice changes.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useSyncExternalStore, useRef, useCallback } from 'react';
|
|
9
|
-
import type { NavCore, NavCoreState, NavInstruction } from '@ingissa/navcore-core';
|
|
10
|
-
import { useNavCoreContext } from './NavCoreProvider';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Generic reactive selector subscribing to NavCore state updates.
|
|
14
|
-
* Only triggers re-renders when the selected value actually changes.
|
|
15
|
-
*/
|
|
16
|
-
export function useNavSelector<T>(
|
|
17
|
-
selector: (state: NavCoreState) => T,
|
|
18
|
-
customEngine?: NavCore,
|
|
19
|
-
isEqual: (a: T, b: T) => boolean = Object.is
|
|
20
|
-
): T {
|
|
21
|
-
let contextEngine: NavCore | undefined;
|
|
22
|
-
try {
|
|
23
|
-
contextEngine = useNavCoreContext().engine;
|
|
24
|
-
} catch {
|
|
25
|
-
contextEngine = undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const engine = customEngine ?? contextEngine;
|
|
29
|
-
if (!engine) {
|
|
30
|
-
throw new Error('useNavSelector must be provided an engine or used within a NavCoreProvider');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const lastSelectedRef = useRef<T | undefined>(undefined);
|
|
34
|
-
const lastStateRef = useRef<NavCoreState | undefined>(undefined);
|
|
35
|
-
|
|
36
|
-
const getSnapshot = useCallback(() => {
|
|
37
|
-
const currentState = engine.getState();
|
|
38
|
-
if (lastStateRef.current === currentState && lastSelectedRef.current !== undefined) {
|
|
39
|
-
return lastSelectedRef.current;
|
|
40
|
-
}
|
|
41
|
-
const nextSelected = selector(currentState);
|
|
42
|
-
if (lastSelectedRef.current !== undefined && isEqual(lastSelectedRef.current, nextSelected)) {
|
|
43
|
-
return lastSelectedRef.current;
|
|
44
|
-
}
|
|
45
|
-
lastStateRef.current = currentState;
|
|
46
|
-
lastSelectedRef.current = nextSelected;
|
|
47
|
-
return nextSelected;
|
|
48
|
-
}, [engine, selector, isEqual]);
|
|
49
|
-
|
|
50
|
-
const subscribe = useCallback((onStoreChange: () => void) => {
|
|
51
|
-
engine.on('update', onStoreChange);
|
|
52
|
-
return () => {
|
|
53
|
-
engine.off('update', onStoreChange);
|
|
54
|
-
};
|
|
55
|
-
}, [engine]);
|
|
56
|
-
|
|
57
|
-
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Hook to select the current upcoming turn-by-turn navigation instruction.
|
|
62
|
-
* Only re-renders when the instruction changes or triggers.
|
|
63
|
-
*/
|
|
64
|
-
export function useNavInstruction(customEngine?: NavCore): NavInstruction | null {
|
|
65
|
-
return useNavSelector(
|
|
66
|
-
(state) => {
|
|
67
|
-
if (state.nextInstructionIndex === null) return null;
|
|
68
|
-
let engine = customEngine;
|
|
69
|
-
if (!engine) {
|
|
70
|
-
try { engine = useNavCoreContext().engine; } catch { /* ignore */ }
|
|
71
|
-
}
|
|
72
|
-
if (!engine) return null;
|
|
73
|
-
const list = engine.getInstructions();
|
|
74
|
-
return list[state.nextInstructionIndex] ?? null;
|
|
75
|
-
},
|
|
76
|
-
customEngine,
|
|
77
|
-
(a, b) => a === b || (a?.geometryIndex === b?.geometryIndex && a?.instruction === b?.instruction)
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Hook to select current alert/deviation state ('NONE' | 'DEVIATING' | 'RECALCULATING' | 'REJOINING' | 'REJOINED').
|
|
83
|
-
* Only re-renders on alert state transitions.
|
|
84
|
-
*/
|
|
85
|
-
export function useNavAlert(customEngine?: NavCore): NavCoreState['alertState'] {
|
|
86
|
-
return useNavSelector(
|
|
87
|
-
(state) => state.alertState,
|
|
88
|
-
customEngine,
|
|
89
|
-
Object.is
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface NavProgressInfo {
|
|
94
|
-
distanceToDestination: number | null;
|
|
95
|
-
distanceToNextInstruction: number | null;
|
|
96
|
-
progressIndex: number;
|
|
97
|
-
routeIndex: number;
|
|
98
|
-
hasArrived: boolean;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Hook to select navigation progress and remaining distance metrics.
|
|
103
|
-
*/
|
|
104
|
-
export function useNavProgress(customEngine?: NavCore): NavProgressInfo {
|
|
105
|
-
return useNavSelector(
|
|
106
|
-
(state) => ({
|
|
107
|
-
distanceToDestination: state.distanceToDestination,
|
|
108
|
-
distanceToNextInstruction: state.distanceToNextInstruction,
|
|
109
|
-
progressIndex: state.progressIndex,
|
|
110
|
-
routeIndex: state.routeIndex,
|
|
111
|
-
hasArrived: state.hasArrived,
|
|
112
|
-
}),
|
|
113
|
-
customEngine,
|
|
114
|
-
(a, b) =>
|
|
115
|
-
a.distanceToDestination === b.distanceToDestination &&
|
|
116
|
-
a.distanceToNextInstruction === b.distanceToNextInstruction &&
|
|
117
|
-
a.progressIndex === b.progressIndex &&
|
|
118
|
-
a.routeIndex === b.routeIndex &&
|
|
119
|
-
a.hasArrived === b.hasArrived
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Hook to select whether the vehicle is currently off-route.
|
|
125
|
-
*/
|
|
126
|
-
export function useNavIsOffRoute(customEngine?: NavCore): boolean {
|
|
127
|
-
return useNavSelector(
|
|
128
|
-
(state) => state.isOffRoute,
|
|
129
|
-
customEngine,
|
|
130
|
-
Object.is
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Hook to select current speed in m/s.
|
|
136
|
-
*/
|
|
137
|
-
export function useNavSpeed(customEngine?: NavCore): number {
|
|
138
|
-
return useNavSelector(
|
|
139
|
-
(state) => state.currentSpeed,
|
|
140
|
-
customEngine,
|
|
141
|
-
Object.is
|
|
142
|
-
);
|
|
143
|
-
}
|