@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 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
- - `lang`: `'th'` (default) or `'en'`.
705
- - `location`: `[latitude, longitude]` to prioritize nearby results.
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
- const results = await map.search("Central World", { lang: 'en' });
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: ${item.position}`); // [lat, lng]
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: string;
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