@mapslibvn/react-native 0.4.0 → 0.5.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.
package/README.md CHANGED
@@ -1,8 +1,100 @@
1
1
  # @mapslibvn/react-native
2
2
 
3
- Bọc `@maplibre/maplibre-react-native` để hiện bản đồ MapsLibVN trong app React Native (Expo hoặc bare),
4
- API bám `@mapslibvn/react`. Yêu cầu React ≥ 19.1, React Native ≥ 0.80, New Architecture, Expo ≥ 54
5
- (không chạy trên Expo Go). Hướng dẫn: trang "React Native" trong docs; app thử: `examples/embed-rn`.
3
+ [![npm version](https://img.shields.io/npm/v/@mapslibvn/react-native.svg)](https://www.npmjs.com/package/@mapslibvn/react-native)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@mapslibvn/react-native.svg)](https://www.npmjs.com/package/@mapslibvn/react-native)
5
+ [![license](https://img.shields.io/npm/l/@mapslibvn/react-native.svg)](https://www.npmjs.com/package/@mapslibvn/react-native)
6
+
7
+ **Native maps and voice-guided navigation for Vietnam, built for React Native.** `@mapslibvn/react-native` wraps `@maplibre/maplibre-react-native` behind the same API shape as [`@mapslibvn/react`](https://www.npmjs.com/package/@mapslibvn/react), so a team that already ships the web SDK can bring the exact same mental model to iOS and Android.
8
+
9
+ Works with Expo (bare or managed, not Expo Go) and bare React Native apps alike. Example app: `examples/embed-rn`.
10
+
11
+ ## Why teams pick it
12
+
13
+ - 📱 **Same API as the web SDK** — `<MapsLibVNMap>`, `<Marker>`, `useMap()`, `usePlaces()` — if your team already knows `@mapslibvn/react`, there's almost nothing new to learn.
14
+ - 🧭 **Turn-by-turn navigation that survives your app** — `createNavigationSession()` runs independently of any mounted map component. It keeps going across screen transitions, so you can pop up a full-screen navigation view on top of your existing app (ride-hailing style) without losing state.
15
+ - 🔊 **Voice guidance that keeps talking, even locked** — background location updates and Vietnamese TTS continue to work with the screen locked, verified on real hardware (not just a simulator).
16
+ - 🧩 **Opt-in Expo integration** — location, background task, speech, audio-session and keep-awake support ship through the `@mapslibvn/react-native/expo` entry point, as optional peer dependencies. Not using navigation? You don't install any of them. Building a bare app? Swap in your own GPS/audio source.
17
+ - 🔐 **Privacy-conscious by default** — only requests "When In Use" location permission, never "Always".
18
+ - 🚀 **New Architecture ready** — built and tested against React Native's New Architecture and current Expo SDKs.
19
+
20
+ ## Requirements
21
+
22
+ React ≥ 19.1, React Native ≥ 0.80, New Architecture, Expo ≥ 54 (does not run on Expo Go). Full guide: the "React Native" page in the docs.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ npm install @mapslibvn/react-native
28
+ npx expo install @maplibre/maplibre-react-native expo-application
29
+ ```
30
+
31
+ ## Quick start
32
+
33
+ ```tsx
34
+ import { MapsLibVNMap, Marker } from '@mapslibvn/react-native';
35
+
36
+ <MapsLibVNMap
37
+ apiKey="mlv_live_…"
38
+ apiBase="https://api.ai-solutions.io.vn"
39
+ bundleId="vn.example.app"
40
+ containerStyle={{ flex: 1 }}
41
+ >
42
+ <Marker lng={106.6981} lat={10.7725} />
43
+ </MapsLibVNMap>;
44
+ ```
45
+
46
+ Mobile keys must be scoped to your bundle/application id. Don't hide or disable attribution.
47
+
48
+ ## Turn-by-turn navigation
49
+
50
+ ```tsx
51
+ // index.ts — global scope, before registerRootComponent
52
+ import { defineNavigationTask } from '@mapslibvn/react-native/expo';
53
+ defineNavigationTask();
54
+ ```
55
+
56
+ ```tsx
57
+ import { MapsLibVNMap, createClient, createNavigationSession, useNavigation } from '@mapslibvn/react-native';
58
+ import { expoNavigation } from '@mapslibvn/react-native/expo';
59
+
60
+ const client = createClient({ apiKey, baseUrl: apiBase });
61
+ const session = createNavigationSession({ provider: client, ...expoNavigation() }); // lives outside the React tree
62
+
63
+ const response = await client.directions({ from: [10.7798, 106.699], to: [10.7725, 106.698], mode: 'motorbike' });
64
+ await session.start({ response }); // GPS even when locked, Vietnamese voice, auto-reroute on drift
65
+
66
+ <MapsLibVNMap {...props} navigation={session} /> // mounts to draw the route, puck and follow camera; unmounting doesn't stop the session
67
+ const { status, progress } = useNavigation(session); // usable anywhere
68
+ ```
69
+
70
+ You'll need `npx expo install expo-location expo-task-manager expo-speech expo-audio` plus the corresponding `app.json` plugin config (see docs). Have your own GPS pipeline? Pass your own `source` instead of `expoNavigation()`.
71
+
72
+ 📖 Docs: <https://mapslibvn-docs.pages.dev/react-native/> and <https://mapslibvn-docs.pages.dev/dan-duong-react-native/>
73
+
74
+ 📦 Part of the MapsLibVN SDK family: [`@mapslibvn/core`](https://www.npmjs.com/package/@mapslibvn/core) · [`@mapslibvn/web`](https://www.npmjs.com/package/@mapslibvn/web) · [`@mapslibvn/react`](https://www.npmjs.com/package/@mapslibvn/react)
75
+
76
+ Source license: MIT; see `THIRD_PARTY_NOTICES.md` for dependency and data licenses.
77
+
78
+ ---
79
+
80
+ ## Tiếng Việt
81
+
82
+ **Bản đồ native và dẫn đường có giọng nói cho Việt Nam, dành cho React Native.** `@mapslibvn/react-native` bọc `@maplibre/maplibre-react-native` theo đúng hình dạng API của [`@mapslibvn/react`](https://www.npmjs.com/package/@mapslibvn/react), nên một đội đã dùng SDK web có thể mang nguyên mô hình tư duy đó sang iOS và Android.
83
+
84
+ Dùng được với cả Expo (bare hoặc managed, không chạy trên Expo Go) và app React Native bare. App thử: `examples/embed-rn`.
85
+
86
+ ## Vì sao nên chọn
87
+
88
+ - 📱 **Cùng API với SDK web** — `<MapsLibVNMap>`, `<Marker>`, `useMap()`, `usePlaces()` — nếu đội đã quen `@mapslibvn/react` thì gần như không phải học gì mới.
89
+ - 🧭 **Dẫn đường sống độc lập với app** — `createNavigationSession()` chạy tách khỏi bất kỳ component bản đồ nào đang gắn. Phiên vẫn tiếp tục qua các lần chuyển màn hình, nên có thể bật một view dẫn đường toàn màn hình đè lên app hiện có (kiểu app gọi xe) mà không mất trạng thái.
90
+ - 🔊 **Giọng đọc không tắt kể cả khi khoá máy** — định vị nền và TTS tiếng Việt vẫn hoạt động khi khoá màn hình, đã xác nhận trên máy thật (không chỉ trên giả lập).
91
+ - 🧩 **Tích hợp Expo theo kiểu tuỳ chọn** — định vị, background task, giọng đọc, phiên âm thanh và giữ máy thức đi qua entry point `@mapslibvn/react-native/expo`, dưới dạng peer dependency tuỳ chọn. Không dùng dẫn đường? Không cần cài gói nào trong số đó. Làm app bare? Tự thay bằng nguồn GPS/âm thanh riêng.
92
+ - 🔐 **Tôn trọng quyền riêng tư mặc định** — chỉ xin quyền định vị "When In Use", không bao giờ xin "Always".
93
+ - 🚀 **Sẵn sàng cho New Architecture** — được build và kiểm thử trên New Architecture của React Native cùng các bản Expo SDK hiện hành.
94
+
95
+ ## Yêu cầu
96
+
97
+ React ≥ 19.1, React Native ≥ 0.80, New Architecture, Expo ≥ 54 (không chạy trên Expo Go). Hướng dẫn đầy đủ: trang "React Native" trong docs.
6
98
 
7
99
  ## Cài đặt
8
100
 
@@ -28,6 +120,32 @@ import { MapsLibVNMap, Marker } from '@mapslibvn/react-native';
28
120
 
29
121
  Khoá mobile phải giới hạn đúng bundle/application id. Không tắt hoặc che attribution.
30
122
 
31
- Tài liệu: <https://mapslibvn-docs.pages.dev/react-native/>
123
+ ## Dẫn đường
124
+
125
+ ```tsx
126
+ // index.ts — phạm vi toàn cục, trước registerRootComponent
127
+ import { defineNavigationTask } from '@mapslibvn/react-native/expo';
128
+ defineNavigationTask();
129
+ ```
130
+
131
+ ```tsx
132
+ import { MapsLibVNMap, createClient, createNavigationSession, useNavigation } from '@mapslibvn/react-native';
133
+ import { expoNavigation } from '@mapslibvn/react-native/expo';
134
+
135
+ const client = createClient({ apiKey, baseUrl: apiBase });
136
+ const session = createNavigationSession({ provider: client, ...expoNavigation() }); // sống ngoài cây React
137
+
138
+ const response = await client.directions({ from: [10.7798, 106.699], to: [10.7725, 106.698], mode: 'motorbike' });
139
+ await session.start({ response }); // GPS cả khi khoá máy, giọng Việt, tự tính lại khi lệch
140
+
141
+ <MapsLibVNMap {...props} navigation={session} /> // gắn để vẽ tuyến, puck, camera bám; unmount không dừng phiên
142
+ const { status, progress } = useNavigation(session); // dùng ở bất kỳ đâu
143
+ ```
144
+
145
+ Cần `npx expo install expo-location expo-task-manager expo-speech expo-audio` và plugin trong `app.json` (xem docs). App có luồng GPS riêng: truyền `source` của bạn thay `expoNavigation()`.
146
+
147
+ 📖 Tài liệu: <https://mapslibvn-docs.pages.dev/react-native/> và <https://mapslibvn-docs.pages.dev/dan-duong-react-native/>
148
+
149
+ 📦 Nằm trong họ SDK MapsLibVN: [`@mapslibvn/core`](https://www.npmjs.com/package/@mapslibvn/core) · [`@mapslibvn/web`](https://www.npmjs.com/package/@mapslibvn/web) · [`@mapslibvn/react`](https://www.npmjs.com/package/@mapslibvn/react)
32
150
 
33
151
  Giấy phép mã nguồn: MIT; xem `THIRD_PARTY_NOTICES.md` cho giấy phép phụ thuộc và dữ liệu.
@@ -9,7 +9,7 @@ MapsLibVN **không liên kết với, không được tài trợ hay chứng th
9
9
  nhãn hiệu của bên thứ ba; tên đó xuất hiện ở đây và trong tài liệu chỉ để mô tả nguồn gốc kỹ
10
10
  thuật của thư viện mà MapsLibVN sử dụng.
11
11
 
12
- Cập nhật: 04/09/2026.
12
+ Cập nhật: 12/09/2026.
13
13
 
14
14
  ## 1. Thư viện được đóng gói hoặc là peer dependency của SDK
15
15
 
@@ -20,6 +20,8 @@ Cập nhật: 04/09/2026.
20
20
  | react, react-dom | 18.3.1 (peer, chỉ `@mapslibvn/react`) | MIT | |
21
21
  | @maplibre/maplibre-react-native | 11.3.8 (peer, chỉ `@mapslibvn/react-native`) | MIT | bộ vẽ bản đồ native iOS/Android |
22
22
  | react, react-native | react ≥ 19.1, react-native ≥ 0.80 (peer, chỉ `@mapslibvn/react-native`) | MIT | |
23
+ | expo-location, expo-task-manager | 57.0.17 (peer **tuỳ chọn**, chỉ entry `@mapslibvn/react-native/expo`) | MIT | định vị tiền cảnh và nền cho dẫn đường |
24
+ | expo-speech, expo-audio, expo-keep-awake | 57.0.3 / 57.0.5 / 57.0.1 (peer **tuỳ chọn**, chỉ entry `@mapslibvn/react-native/expo`) | MIT | đọc câu chỉ dẫn, phiên âm thanh khi nền, giữ màn hình sáng |
23
25
 
24
26
  Nguyên văn giấy phép ở mục 4.
25
27
 
@@ -385,9 +387,38 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO
385
387
  Gói này nhúng MapLibre Native (Android, iOS) khi build app — xem thông báo giấy phép trong
386
388
  chính gói đó cho các thành phần native.
387
389
 
390
+ ### 4.9 expo-location, expo-task-manager, expo-speech, expo-audio, expo-keep-awake — MIT
391
+
392
+ ```
393
+ The MIT License (MIT)
394
+
395
+ Copyright (c) 2015-present 650 Industries, Inc. (aka Expo)
396
+
397
+ Permission is hereby granted, free of charge, to any person obtaining a copy
398
+ of this software and associated documentation files (the "Software"), to deal
399
+ in the Software without restriction, including without limitation the rights
400
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
401
+ copies of the Software, and to permit persons to whom the Software is
402
+ furnished to do so, subject to the following conditions:
403
+
404
+ The above copyright notice and this permission notice shall be included in all
405
+ copies or substantial portions of the Software.
406
+
407
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
408
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
409
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
410
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
411
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
412
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
413
+ SOFTWARE.
414
+ ```
415
+
416
+ Các gói này là peer dependency **tuỳ chọn**: chỉ app import `@mapslibvn/react-native/expo` (dẫn
417
+ đường) mới cài; SDK không đóng gói mã của chúng.
418
+
388
419
  ## 5. Công cụ phía máy chủ (không phân phối, liệt kê để minh bạch)
389
420
 
390
421
  Planetiler (Apache-2.0), tippecanoe (BSD-2-Clause), osmium-tool (GPL-3.0 — dùng như công cụ
391
422
  dòng lệnh, không liên kết mã), pyosmium (BSD-2-Clause), DuckDB (MIT), PostgreSQL
392
- (PostgreSQL License), PostGIS (GPL-2.0 — chạy như dịch vụ), Hono (MIT), cloudflared
423
+ (PostgreSQL License), PostGIS (GPL-2.0 — chạy như dịch vụ), Valhalla (MIT — engine chỉ đường, chạy như dịch vụ riêng trên máy chủ, không liên kết mã), Hono (MIT), cloudflared
393
424
  (Apache-2.0), Astro Starlight (MIT), Vitest (MIT), Playwright (Apache-2.0).
@@ -0,0 +1,7 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ export {
6
+ __publicField
7
+ };
@@ -0,0 +1,96 @@
1
+ import { A as AudioSession, K as KeepAwake, T as TravelMode, S as SessionPositionSource, G as GeoFix, a as Speaker, N as NavigationSessionOptions } from '../session-B7Fu_s_b.js';
2
+
3
+ /**
4
+ * Phiên âm thanh để giọng đọc phát khi khoá máy và làm nhỏ nhạc đang phát (spec C 6.3).
5
+ *
6
+ * Ba bước đều bắt buộc, xác nhận bằng thực địa trên máy thật 12/09/2026 (giọng đọc im lặng hoàn
7
+ * toàn ngay khi khoá màn hình cho tới khi vá đủ cả ba):
8
+ *
9
+ * 1. `setAudioModeAsync` chỉ đặt category AVAudioSession (iOS); nó KHÔNG gọi
10
+ * `AVAudioSession.setActive` (xác nhận trong mã nguồn expo-audio: `AudioModule.swift` hàm
11
+ * `setAudioMode` chỉ `session.setCategory`, `setActive` nằm ở hàm riêng `setIsAudioActive`) →
12
+ * phải gọi thêm `setIsAudioActiveAsync(true)`.
13
+ * 2. Chỉ kích hoạt phiên KHÔNG đủ: giữa hai câu chỉ dẫn (vài chục giây không có âm thanh nào thật
14
+ * sự phát ra), iOS coi app không còn dùng "audio" background mode một cách chính đáng và thu hồi
15
+ * quyền chạy nền. Phải phát một vòng lặp âm thanh (im lặng tuyệt đối, toàn mẫu 0) liên tục trong
16
+ * suốt lúc dẫn đường để giữ phiên "đang phát" thật sự.
17
+ * 3. Trên Android, `play()` một mình KHÔNG khiến hệ điều hành công nhận đây là phiên media đang
18
+ * hoạt động: xác nhận thực địa Android thật (Xiaomi/MIUI) 12/09/2026 — dù foreground service
19
+ * ĐỊNH VỊ vẫn còn nguyên (`serviceTypes` giữ cờ location suốt lúc khoá máy), JS/TTS vẫn đứng yên
20
+ * hoàn toàn. Phải gọi thêm `player.setActiveForLockScreen(true, …)` để có `MediaSessionService`
21
+ * — một foreground service RIÊNG, độc lập với foreground service định vị — giữ tiến trình sống.
22
+ * Đây là kỹ thuật chuẩn của app điều hướng/audiobook, đã ghi làm phương án dự phòng (a) trong
23
+ * spec C mục 11 rủi ro 1 (viết ban đầu cho iOS, hoá ra Android cũng cần bước tương đương).
24
+ */
25
+ declare function expoAudioSession(): AudioSession;
26
+ declare const KEEP_AWAKE_TAG = "mapslibvn-navigation";
27
+ declare function expoKeepAwake(): KeepAwake;
28
+
29
+ /** Tên task expo-task-manager nhận vị trí nền; một tên → một phiên nền tại một thời điểm. */
30
+ declare const NAVIGATION_TASK = "mapslibvn-navigation-location";
31
+ /** Độ chính xác của expo-location, đặt tên để không lộ enum của gói ra API công khai. */
32
+ type ExpoLocationAccuracy = 'balanced' | 'high' | 'highest' | 'bestForNavigation';
33
+ interface ExpoLocationSourceOptions {
34
+ /** Định vị cả khi khoá máy/chuyển app — mặc định true; cần app cấu hình plugin (docs). */
35
+ background?: boolean;
36
+ /** Mặc định 'bestForNavigation'. */
37
+ accuracy?: ExpoLocationAccuracy;
38
+ /** Mặc định 1000. */
39
+ timeInterval_ms?: number;
40
+ /** Thông báo foreground service Android. Mặc định "Đang dẫn đường" / "Chạm để mở ứng dụng". */
41
+ notification?: {
42
+ title?: string;
43
+ body?: string;
44
+ color?: string;
45
+ };
46
+ /** iOS: thanh trạng thái báo đang dùng vị trí nền — mặc định true. */
47
+ showsBackgroundLocationIndicator?: boolean;
48
+ /** iOS activityType và Android ưu tiên; mặc định 'motorbike', phiên ghi đè bằng `setMode` theo tuyến. */
49
+ mode?: TravelMode;
50
+ }
51
+ interface LocationObject {
52
+ coords: {
53
+ latitude: number;
54
+ longitude: number;
55
+ accuracy: number | null;
56
+ heading: number | null;
57
+ speed: number | null;
58
+ };
59
+ timestamp: number;
60
+ }
61
+ /** `LocationObject` của expo-location → `GeoFix` của core. iOS trả heading/speed âm khi không có. */
62
+ declare function toGeoFix(l: LocationObject): GeoFix;
63
+ /**
64
+ * Gọi ở PHẠM VI TOÀN CỤC của `index.ts`, trước `registerRootComponent` (yêu cầu của
65
+ * expo-task-manager). Gọi lại là no-op. Executor đẩy fix cho nguồn đang đăng ký; không ai nghe (app
66
+ * bị iOS đánh thức lại sau khi bị giết) thì tự dừng task để không thành task ma.
67
+ */
68
+ declare function defineNavigationTask(): void;
69
+ /**
70
+ * Nguồn vị trí Expo: một đường cho cả tiền cảnh lẫn nền (`startLocationUpdatesAsync` + task);
71
+ * điều kiện nền thiếu thì rơi về `watchPositionAsync` và báo `onBackgroundUnavailable` (spec C 6.1).
72
+ * Chỉ xin quyền When In Use — đã xác minh hai hệ không cần Always khi khởi động từ tiền cảnh.
73
+ */
74
+ declare function expoLocationSource(opts?: ExpoLocationSourceOptions): SessionPositionSource;
75
+
76
+ interface ExpoSpeechOptions {
77
+ /** 1 = tốc độ thường của hệ. */
78
+ rate?: number;
79
+ /** 0–1. */
80
+ volume?: number;
81
+ pitch?: number;
82
+ }
83
+ /**
84
+ * `Speaker` trên expo-speech. Android xếp hàng (`QUEUE_ADD`) và iOS cũng xếp hàng, nên muốn cắt câu
85
+ * phải `stop()` trước rồi mới `speak`. Theo dõi câu đang đọc bằng số thứ tự để callback của câu cũ
86
+ * đến muộn không xoá nhầm ưu tiên câu mới.
87
+ */
88
+ declare function expoSpeech(opts?: ExpoSpeechOptions): Speaker;
89
+
90
+ type ExpoNavigationOptions = ExpoLocationSourceOptions & {
91
+ speech?: ExpoSpeechOptions;
92
+ };
93
+ /** Bộ adapter Expo mặc định cho `createNavigationSession({ provider, ...expoNavigation() })`. */
94
+ declare function expoNavigation(opts?: ExpoNavigationOptions): Required<Pick<NavigationSessionOptions, 'source' | 'speech' | 'audio' | 'keepAwake'>>;
95
+
96
+ export { type ExpoLocationAccuracy, type ExpoLocationSourceOptions, type ExpoNavigationOptions, type ExpoSpeechOptions, KEEP_AWAKE_TAG, NAVIGATION_TASK, defineNavigationTask, expoAudioSession, expoKeepAwake, expoLocationSource, expoNavigation, expoSpeech, toGeoFix };