@aapicoits/powermap-web-sdk 1.1.0 → 1.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.
- package/README.md +229 -18
- package/dist/index.d.ts +13 -2
- package/dist/powermap-web-sdk.cjs.cjs +173 -32
- package/dist/powermap-web-sdk.js +5487 -2538
- package/dist/powermap-web-sdk.umd.cjs +173 -32
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -469,6 +469,31 @@ if (details) {
|
|
|
469
469
|
const summary = map.getRouteSummary(); // { distanceStr, durationStr }
|
|
470
470
|
```
|
|
471
471
|
|
|
472
|
+
### 9.1 Built-in Routing UI (Routing Panel)
|
|
473
|
+
|
|
474
|
+
The SDK provides a built-in outdoor routing panel that automatically handles searching, waypoint management, and turn-by-turn navigation UI.
|
|
475
|
+
|
|
476
|
+
```javascript
|
|
477
|
+
// Add the routing panel to the map
|
|
478
|
+
const routingControl = new PowerMap.RoutingPanelControl({
|
|
479
|
+
defaultProfile: 'driving', // 'driving', 'foot', 'bicycle', 'motorcycle'
|
|
480
|
+
onLocationSelect: (location) => {
|
|
481
|
+
console.log("Selected Location:", location);
|
|
482
|
+
},
|
|
483
|
+
onRouteCalculated: (routeResult) => {
|
|
484
|
+
console.log("Route calculated:", routeResult);
|
|
485
|
+
},
|
|
486
|
+
onClear: () => {
|
|
487
|
+
console.log("Route cleared");
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
map.addControl(routingControl);
|
|
492
|
+
|
|
493
|
+
// Programmatically clear the routing panel and map route
|
|
494
|
+
// routingControl.clear();
|
|
495
|
+
```
|
|
496
|
+
|
|
472
497
|
---
|
|
473
498
|
|
|
474
499
|
## 🏗️ 10. Map Layers Management
|
|
@@ -695,22 +720,60 @@ const map = new PowerMap({
|
|
|
695
720
|
|
|
696
721
|
## 12. 🔍 Search & Geocoding
|
|
697
722
|
|
|
698
|
-
The Web SDK provides built-in search capabilities using the PowerMap Search API.
|
|
723
|
+
The Web SDK provides built-in search capabilities using the PowerMap Search API with automatic script detection, smart field fallbacks, and cross-endpoint query handling.
|
|
699
724
|
|
|
700
725
|
### `search(query, options)`
|
|
701
726
|
|
|
702
727
|
Available options:
|
|
703
728
|
|
|
704
|
-
|
|
705
|
-
|
|
729
|
+
| Option | Type | Default | Description |
|
|
730
|
+
| :--- | :--- | :--- | :--- |
|
|
731
|
+
| `lang` | `string` | `'auto'` | Language mode: `'auto'`, `'th'`, or `'en'`. In `'auto'` mode, script type is detected automatically from Unicode ranges. |
|
|
732
|
+
| `location` | `[lat, lng]` | `-` | `[latitude, longitude]` coordinate pair to prioritize nearby search results. |
|
|
733
|
+
|
|
734
|
+
#### Automatic Script Detection & Fallbacks
|
|
735
|
+
- **`lang: 'auto'`**: Automatically inspects query characters. Thai queries (`[\u0E00-\u0E7F]`) select Thai search services, while English/Latin queries (`[a-zA-Z]`) select English search services.
|
|
736
|
+
- **Mixed Script Handling**: For mixed search terms (e.g. `"Central บางนา"` or `"BTS อโศก"`), if primary search yields no results or contains mixed scripts, the SDK automatically executes a cross-endpoint fallback search and merges unique results.
|
|
737
|
+
- **Smart Field Mapping**: `name` and `address` automatically default to the preferred query language with automatic fallback (`nameEn` -> `nameTh` -> `name` or `nameTh` -> `nameEn` -> `name`), ensuring titles and addresses are never returned as empty strings.
|
|
738
|
+
|
|
739
|
+
#### Returned `SearchResult` Properties
|
|
740
|
+
|
|
741
|
+
Each item in the returned array contains:
|
|
742
|
+
|
|
743
|
+
| Field | Type | Description |
|
|
744
|
+
| :--- | :--- | :--- |
|
|
745
|
+
| `id` / `gid` | `string` | Unique identifier for the POI. |
|
|
746
|
+
| `name` | `string` | Display name in the preferred language with automatic fallback. |
|
|
747
|
+
| `nameEn` | `string` | English name of the place (with Thai fallback). |
|
|
748
|
+
| `nameTh` | `string` | Thai name of the place (with English fallback). |
|
|
749
|
+
| `address` | `string` | Formatted address in the preferred language with fallback. |
|
|
750
|
+
| `addressEn` | `string` | Formatted English address string. |
|
|
751
|
+
| `addressTh` | `string` | Formatted Thai address string. |
|
|
752
|
+
| `position` | `[lat, lng]` | Coordinate pair `[latitude, longitude]` (compatible with Mobile SDK). |
|
|
753
|
+
| `positionLngLat` | `[lng, lat]` | Coordinate pair `[longitude, latitude]` for Web map view manipulation. |
|
|
754
|
+
| `province` / `amphoe` / `tambon` | `string` | Administrative boundary details. |
|
|
755
|
+
| `postCode` | `string` | Postal code if available. |
|
|
756
|
+
| `rawData` | `Object` | Raw Elasticsearch GeoJSON source payload. |
|
|
757
|
+
|
|
758
|
+
### Search Examples
|
|
706
759
|
|
|
707
760
|
```javascript
|
|
708
|
-
|
|
761
|
+
// 1. Auto language detection (Recommended)
|
|
762
|
+
const results = await map.search("Central World");
|
|
709
763
|
|
|
710
764
|
results.forEach(item => {
|
|
711
|
-
console.log(`${item.name}: ${item.address}`);
|
|
712
|
-
console.log(`Position
|
|
765
|
+
console.log(`${item.name} (${item.nameTh}): ${item.address}`);
|
|
766
|
+
console.log(`Position [lat, lng]:`, item.position);
|
|
713
767
|
});
|
|
768
|
+
|
|
769
|
+
// 2. Explicit English search with location prioritization
|
|
770
|
+
const enResults = await map.search("Siam Paragon", {
|
|
771
|
+
lang: 'en',
|
|
772
|
+
location: [13.746, 100.534] // [lat, lng]
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
// 3. Mixed query (Thai + English)
|
|
776
|
+
const mixedResults = await map.search("BTS อโศก", { lang: 'auto' });
|
|
714
777
|
```
|
|
715
778
|
|
|
716
779
|
---
|
|
@@ -1011,18 +1074,6 @@ const floors = map.indoor.getAvailableFloors();
|
|
|
1011
1074
|
// Returns: [1, 2, 3] or [] if no indoor data is found
|
|
1012
1075
|
```
|
|
1013
1076
|
|
|
1014
|
-
### 16.3 Visibility Control
|
|
1015
|
-
|
|
1016
|
-
Toggle the visibility of specific indoor data categories. These settings persist across floor changes.
|
|
1017
|
-
|
|
1018
|
-
```javascript
|
|
1019
|
-
// Toggle individual categories
|
|
1020
|
-
map.indoor.setCategoryVisible('poi', true); // Points of Interest
|
|
1021
|
-
map.indoor.setCategoryVisible('beacon', false); // Beacons/Sensors
|
|
1022
|
-
map.indoor.setCategoryVisible('walkway', true); // Navigation Paths
|
|
1023
|
-
map.indoor.setCategoryVisible('obstacle', true); // 3D Obstacles/Buildings
|
|
1024
|
-
```
|
|
1025
|
-
|
|
1026
1077
|
### 16.4 Indoor Data Kinds (IMDF Compliant)
|
|
1027
1078
|
|
|
1028
1079
|
The SDK categorizes indoor features using `user_kind` (or `kind`) mapped to OGC IMDF `feature_type`:
|
|
@@ -1099,6 +1150,117 @@ The SDK provides built-in productivity shortcuts whenever the geometry engine is
|
|
|
1099
1150
|
|
|
1100
1151
|
---
|
|
1101
1152
|
|
|
1153
|
+
## 17. 🏢 Indoor API & Mapping
|
|
1154
|
+
|
|
1155
|
+
The PowerMap SDK includes a dedicated `IndoorAPI` and UI controls to easily build indoor navigation and mapping applications. The indoor modules are initialized lazily and are available under `map.indoor`.
|
|
1156
|
+
|
|
1157
|
+
### 17.1 The `IndoorAPI`
|
|
1158
|
+
|
|
1159
|
+
The `IndoorAPI` automatically utilizes the SDK's `AuthManager` to handle authentication securely and allows you to fetch hierarchy data and perform searches within venues.
|
|
1160
|
+
|
|
1161
|
+
```javascript
|
|
1162
|
+
// Fetch all venues available for the user
|
|
1163
|
+
const venues = await map.indoor.api.getVenues();
|
|
1164
|
+
|
|
1165
|
+
// Fetch buildings in a specific venue
|
|
1166
|
+
const buildings = await map.indoor.api.getBuildings(venueId);
|
|
1167
|
+
|
|
1168
|
+
// Fetch floors in a specific building
|
|
1169
|
+
const floors = await map.indoor.api.getFloors(buildingId);
|
|
1170
|
+
|
|
1171
|
+
// Fetch raw GeoJSON for a specific floor to render on the map
|
|
1172
|
+
const geojson = await map.indoor.api.getFloorGeoJSON(floorId);
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
### 17.2 Indoor Search
|
|
1176
|
+
|
|
1177
|
+
You can search for Points of Interest (POIs) across your indoor map using the built-in search API. **Note: Searching requires a `buildingId` to ensure performance and accuracy.**
|
|
1178
|
+
|
|
1179
|
+
```javascript
|
|
1180
|
+
// Search within a specific building (buildingId is REQUIRED)
|
|
1181
|
+
const results = await map.indoor.api.search('coffee', { buildingId: 'bld-1234' });
|
|
1182
|
+
|
|
1183
|
+
// Search with a limit
|
|
1184
|
+
const limitedResults = await map.indoor.api.search('coffee', {
|
|
1185
|
+
buildingId: 'bld-1234',
|
|
1186
|
+
limit: 10
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
// Example output
|
|
1190
|
+
// [
|
|
1191
|
+
// {
|
|
1192
|
+
// id: 'poi-1', name: 'Starbucks', category: 'cafe',
|
|
1193
|
+
// x: 100.5, y: 13.7, floorId: 'fl-1', floorNumber: 'G'
|
|
1194
|
+
// }
|
|
1195
|
+
// ]
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
### 17.3 Indoor UI Controls
|
|
1199
|
+
|
|
1200
|
+
The SDK provides ready-to-use UI components such as the `IndoorFloorControl`, which renders a sleek, floating floor selector that automatically updates when you switch buildings.
|
|
1201
|
+
|
|
1202
|
+
```javascript
|
|
1203
|
+
import { IndoorFloorControl } from '@powermap/web-sdk';
|
|
1204
|
+
|
|
1205
|
+
// 1. Initialize the control
|
|
1206
|
+
const floorControl = new IndoorFloorControl({
|
|
1207
|
+
onChange: (floorId, floorInfo) => {
|
|
1208
|
+
console.log("Selected floor:", floorInfo.name);
|
|
1209
|
+
// Load the floor GeoJSON onto the map here...
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
// 2. Add to the map (top-right corner)
|
|
1214
|
+
map.mapManager.map.addControl(floorControl, 'top-right');
|
|
1215
|
+
|
|
1216
|
+
// 3. Feed it data from the IndoorAPI
|
|
1217
|
+
const floors = await map.indoor.api.getFloors('bld-1234');
|
|
1218
|
+
const formattedFloors = floors.map(f => ({
|
|
1219
|
+
id: f.id,
|
|
1220
|
+
name: f.floorNumber,
|
|
1221
|
+
score: parseInt(f.floorNumber) || 0
|
|
1222
|
+
}));
|
|
1223
|
+
|
|
1224
|
+
// Sort top to bottom, then pass to control
|
|
1225
|
+
formattedFloors.sort((a, b) => b.score - a.score);
|
|
1226
|
+
floorControl.setFloors(formattedFloors);
|
|
1227
|
+
|
|
1228
|
+
// 4. Update the active floor programmatically
|
|
1229
|
+
floorControl.setActiveFloor('fl-1');
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
### 17.4 Indoor Routing (Premium UI)
|
|
1233
|
+
|
|
1234
|
+
The SDK provides a built-in `IndoorRouter` and a complete `IndoorRoutingPanelControl` UI for searching POIs and calculating indoor paths across different floors.
|
|
1235
|
+
|
|
1236
|
+
The router integrates directly with the Indoor API and automatically manages multi-floor rendering, step-by-step instructions, and origin/destination markers.
|
|
1237
|
+
|
|
1238
|
+
```javascript
|
|
1239
|
+
import { IndoorRoutingPanelControl } from '@powermap/web-sdk';
|
|
1240
|
+
|
|
1241
|
+
// 1. Initialize the Routing Panel Control
|
|
1242
|
+
const routingPanel = new IndoorRoutingPanelControl({
|
|
1243
|
+
buildingId: 'bld-1234',
|
|
1244
|
+
router: map.indoor.router, // Provided automatically by the SDK
|
|
1245
|
+
onFloorChange: (floorId) => {
|
|
1246
|
+
// Automatically called when a user clicks a route step on a different floor
|
|
1247
|
+
// Use this callback to change your visual background maps or floor selector UI
|
|
1248
|
+
console.log("Routing requested switch to floor:", floorId);
|
|
1249
|
+
floorControl.setActiveFloor(floorId);
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1253
|
+
// 2. Add to the map (top-right corner, below the floor selector)
|
|
1254
|
+
map.mapManager.map.addControl(routingPanel, 'top-right');
|
|
1255
|
+
```
|
|
1256
|
+
|
|
1257
|
+
The `IndoorRoutingPanelControl` features:
|
|
1258
|
+
- **Built-in POI Search**: Users can type in the input fields to search for POIs via the backend.
|
|
1259
|
+
- **Auto-Switching Floors**: When a route is calculated, the SDK automatically switches to the origin floor and pans the camera.
|
|
1260
|
+
- **Layer Management**: The `IndoorRouter` handles drawing the route lines and rendering start/end markers on the correct floor.
|
|
1261
|
+
|
|
1262
|
+
---
|
|
1263
|
+
|
|
1102
1264
|
## 18. 🩺 Debug & Telemetry
|
|
1103
1265
|
|
|
1104
1266
|
Enable the Debug HUD during development to monitor performance and coordinates.
|
|
@@ -1151,6 +1313,55 @@ For contributors to the SDK core:
|
|
|
1151
1313
|
|
|
1152
1314
|
---
|
|
1153
1315
|
|
|
1316
|
+
## 16. 🏢 Indoor Map UI Controls
|
|
1317
|
+
|
|
1318
|
+
The SDK provides ready-to-use UI controls specifically designed for indoor mapping, ensuring a seamless user experience when navigating inside buildings.
|
|
1319
|
+
|
|
1320
|
+
### 16.1 Indoor Floor Selector (`IndoorFloorControl`)
|
|
1321
|
+
|
|
1322
|
+
A control that allows users to manually switch between floors in a building. It automatically updates its UI when `setFloors` or `setActiveFloor` is called.
|
|
1323
|
+
|
|
1324
|
+
```javascript
|
|
1325
|
+
const floorControl = new PowerMap.IndoorFloorControl({
|
|
1326
|
+
onChange: (floorId) => {
|
|
1327
|
+
console.log(`User changed to floor: ${floorId}`);
|
|
1328
|
+
// Your logic to switch the map's visible floor
|
|
1329
|
+
}
|
|
1330
|
+
});
|
|
1331
|
+
map.addControl(floorControl, 'bottom-right');
|
|
1332
|
+
|
|
1333
|
+
// Set available floors (e.g., from your venue data)
|
|
1334
|
+
floorControl.setFloors([
|
|
1335
|
+
{ id: '1', name: 'G' },
|
|
1336
|
+
{ id: '2', name: 'M' },
|
|
1337
|
+
{ id: '3', name: '1' }
|
|
1338
|
+
]);
|
|
1339
|
+
|
|
1340
|
+
// Set the active highlighted floor
|
|
1341
|
+
floorControl.setActiveFloor('1');
|
|
1342
|
+
```
|
|
1343
|
+
|
|
1344
|
+
### 16.2 Indoor Routing Panel (`IndoorRoutingPanelControl`)
|
|
1345
|
+
|
|
1346
|
+
A premium UI control for indoor navigation. It handles searching for indoor POIs, selecting start/end points within a building, and displaying turn-by-turn indoor directions (including elevators and escalators).
|
|
1347
|
+
|
|
1348
|
+
```javascript
|
|
1349
|
+
const indoorRoutingControl = new PowerMap.IndoorRoutingPanelControl({
|
|
1350
|
+
buildingId: 'bldg-12345',
|
|
1351
|
+
router: map.indoor.router, // Your IndoorRouter instance
|
|
1352
|
+
onLocationSelect: (location) => {
|
|
1353
|
+
console.log("Selected indoor location:", location);
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1356
|
+
|
|
1357
|
+
map.addControl(indoorRoutingControl, 'top-left');
|
|
1358
|
+
|
|
1359
|
+
// Programmatically clear the indoor routing panel
|
|
1360
|
+
// indoorRoutingControl.clear();
|
|
1361
|
+
```
|
|
1362
|
+
|
|
1363
|
+
---
|
|
1364
|
+
|
|
1154
1365
|
## 📌 Appendix A: Complete SDK Event List
|
|
1155
1366
|
|
|
1156
1367
|
The SDK emits the following events through its central `EventBus`. You can subscribe to them via `map.on(eventName, callback)`.
|
package/dist/index.d.ts
CHANGED
|
@@ -88,16 +88,27 @@ export interface RouteSummary {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
export interface SearchResult {
|
|
91
|
-
id
|
|
91
|
+
id?: string;
|
|
92
|
+
gid?: string;
|
|
92
93
|
name: string;
|
|
94
|
+
nameEn?: string;
|
|
95
|
+
nameTh?: string;
|
|
93
96
|
address?: string;
|
|
97
|
+
addressEn?: string;
|
|
98
|
+
addressTh?: string;
|
|
94
99
|
position: [number, number];
|
|
100
|
+
positionLngLat?: [number, number];
|
|
101
|
+
province?: string;
|
|
102
|
+
amphoe?: string;
|
|
103
|
+
tambon?: string;
|
|
104
|
+
postCode?: string;
|
|
105
|
+
rawData?: Record<string, unknown>;
|
|
95
106
|
[key: string]: unknown;
|
|
96
107
|
}
|
|
97
108
|
|
|
98
109
|
export interface SearchOptions {
|
|
99
110
|
location?: [number, number];
|
|
100
|
-
lang?: string;
|
|
111
|
+
lang?: 'th' | 'en' | 'auto' | string;
|
|
101
112
|
[key: string]: unknown;
|
|
102
113
|
}
|
|
103
114
|
|