proximiio-js-library 1.15.0 → 1.15.2

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
@@ -139,8 +139,9 @@ const map = new Proximiio.Map({
139
139
  newFeatureModalEvent: 'click',
140
140
 
141
141
  // Optional, you'll receive turn-by-turn text navigation object in found route
142
- // listener response, default: true
143
- enableTBTNavigation: true,
142
+ // listener response, default: 'full'
143
+ // possible values: 'disabled', 'simple', 'simple-levelChangers', 'full', 'full-levelChangers', 'landmark', 'landmark-levelChangers';
144
+ stepsNavigation: 'full',
144
145
 
145
146
  // Optional, you can pass mapbox initial options like center or zoom here,
146
147
  // all options can be found at https://docs.mapbox.com/mapbox-gl-js/api/map/
package/lib/common.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import Feature from './models/feature';
2
2
  import { LngLatBoundsLike } from 'maplibre-gl';
3
+ import { FloorModel } from './models/floor';
3
4
  export declare const axios: import("axios").AxiosInstance;
4
5
  export declare const camelToKebab: (input: string) => string;
5
6
  export declare const kebabToCamel: (input: string) => string;
@@ -42,4 +43,8 @@ declare const shortenCoordinates: ({ coords, decimals }: {
42
43
  }) => any;
43
44
  declare const isLevelChanger: (poi: Feature) => boolean;
44
45
  declare const pointInBounds: (point: [number, number], bounds: LngLatBoundsLike) => boolean;
45
- export { calculateDimensions, convertToRTL, base64toBlob, throttle, filterByAmenity, validateLabelLine, optimizeFeatures, isLevelChanger, pointInBounds, shortenCoordinates, };
46
+ declare const getFloorName: ({ floor, language }: {
47
+ floor: FloorModel;
48
+ language: string;
49
+ }) => string;
50
+ export { calculateDimensions, convertToRTL, base64toBlob, throttle, filterByAmenity, validateLabelLine, optimizeFeatures, isLevelChanger, pointInBounds, shortenCoordinates, getFloorName, };
package/lib/common.js CHANGED
@@ -294,4 +294,15 @@ const pointInBounds = (point, bounds) => {
294
294
  const [lng, lat] = point;
295
295
  return lng >= minLng && lng <= maxLng && lat >= minLat && lat <= maxLat;
296
296
  };
297
- export { calculateDimensions, convertToRTL, base64toBlob, throttle, filterByAmenity, validateLabelLine, optimizeFeatures, isLevelChanger, pointInBounds, shortenCoordinates, };
297
+ const getFloorName = ({ floor, language }) => {
298
+ if (floor) {
299
+ if (floor.metadata && floor.metadata['title_' + language]) {
300
+ return floor.metadata['title_' + language];
301
+ }
302
+ if (floor.name.length === 1 && Number(parseInt(floor.name, 2))) {
303
+ return `L${floor.name}`;
304
+ }
305
+ return floor.name;
306
+ }
307
+ };
308
+ export { calculateDimensions, convertToRTL, base64toBlob, throttle, filterByAmenity, validateLabelLine, optimizeFeatures, isLevelChanger, pointInBounds, shortenCoordinates, getFloorName, };
@@ -1,26 +1,42 @@
1
1
  import Feature from '../../models/feature';
2
2
  import { GuidanceStep } from '../../models/wayfinding';
3
+ import { FloorModel } from '../../models/floor';
3
4
  export default class GuidanceStepsGenerator {
4
5
  points: Feature[];
5
6
  steps: GuidanceStep[];
6
7
  language: string;
7
- landMarkNav: boolean;
8
- simplifiedTBT: boolean;
8
+ stepsNavigation: 'disabled' | 'simple' | 'simple-levelChangers' | 'full' | 'full-levelChangers' | 'landmark' | 'landmark-levelChangers';
9
9
  pois?: Feature[];
10
10
  levelChangers?: Feature[];
11
11
  initialBearing: number;
12
- constructor({ points, language, landMarkNav, simplifiedTBT, pois, levelChangers, initialBearing, }: {
12
+ landmarkSteps: boolean;
13
+ fullSteps: boolean;
14
+ simpleSteps: boolean;
15
+ levelChangersSteps: boolean;
16
+ floors: FloorModel[];
17
+ currentFloor: FloorModel;
18
+ constructor({ points, language, stepsNavigation, pois, levelChangers, initialBearing, floors, currentFloor, }: {
13
19
  points: Feature[];
14
20
  language: string;
15
- landMarkNav: boolean;
16
- simplifiedTBT: boolean;
21
+ stepsNavigation: 'disabled' | 'simple' | 'simple-levelChangers' | 'full' | 'full-levelChangers' | 'landmark' | 'landmark-levelChangers';
17
22
  pois?: Feature[];
18
23
  levelChangers?: Feature[];
19
24
  initialBearing: number;
25
+ floors: FloorModel[];
26
+ currentFloor: FloorModel;
20
27
  });
21
28
  private capitalize;
22
29
  private generateStepsFromPoints;
23
30
  private generateInstruction;
31
+ private generateSimpleInstruction;
32
+ private generateFullInstruction;
33
+ private generateFullLevelChangerInstruction;
34
+ private generateLevelChangerStepInstruction;
35
+ private generateLandmarkInstruction;
36
+ private getLandmarkLevelChangerPrefix;
37
+ private getLandmarkInitialBearingPrefix;
38
+ private getLandmarkDistancePrefix;
39
+ private getLandmarkDirectionWithContext;
24
40
  private getDirectionInstruction;
25
41
  private getBearingFromLastStep;
26
42
  private getStepDirection;
@@ -4,6 +4,7 @@ import distance from '@turf/distance';
4
4
  import { lineString } from '@turf/helpers';
5
5
  import { translations } from './i18n';
6
6
  import nearestPoint from '@turf/nearest-point';
7
+ import { getFloorName } from '../../common';
7
8
  var Direction;
8
9
  (function (Direction) {
9
10
  Direction["Start"] = "START";
@@ -21,6 +22,11 @@ var Direction;
21
22
  Direction["ExitEscalator"] = "EXIT_ESCALATOR";
22
23
  Direction["ExitElevator"] = "EXIT_ELEVATOR";
23
24
  Direction["ExitRamp"] = "EXIT_RAMP";
25
+ Direction["At"] = "AT";
26
+ Direction["AtStaircase"] = "AT_STAIRS";
27
+ Direction["AtEscalator"] = "AT_ESCALATOR";
28
+ Direction["AtElevator"] = "AT_ELEVATOR";
29
+ Direction["AtRamp"] = "AT_RAMP";
24
30
  Direction["Up"] = "UP";
25
31
  Direction["Down"] = "DOWN";
26
32
  Direction["Left"] = "LEFT";
@@ -40,18 +46,36 @@ var LevelChangerTypes;
40
46
  LevelChangerTypes["ramp"] = "RAMP";
41
47
  })(LevelChangerTypes || (LevelChangerTypes = {}));
42
48
  export default class GuidanceStepsGenerator {
43
- constructor({ points, language, landMarkNav, simplifiedTBT, pois, levelChangers, initialBearing, }) {
49
+ constructor({ points, language, stepsNavigation, pois, levelChangers, initialBearing, floors, currentFloor, }) {
44
50
  this.capitalize = (s) => s && String(s[0]).toUpperCase() + String(s).slice(1);
45
51
  this.points = points;
46
52
  this.language = language;
47
- if (landMarkNav) {
48
- this.landMarkNav = landMarkNav;
53
+ this.stepsNavigation = stepsNavigation;
54
+ this.floors = floors;
55
+ this.currentFloor = currentFloor;
56
+ this.landmarkSteps = this.stepsNavigation === 'landmark' || this.stepsNavigation === 'landmark-levelChangers';
57
+ this.fullSteps = this.stepsNavigation === 'full' || this.stepsNavigation === 'full-levelChangers';
58
+ this.simpleSteps = this.stepsNavigation === 'simple' || this.stepsNavigation === 'simple-levelChangers';
59
+ this.levelChangersSteps =
60
+ this.stepsNavigation === 'simple-levelChangers' ||
61
+ this.stepsNavigation === 'full-levelChangers' ||
62
+ this.stepsNavigation === 'landmark-levelChangers';
63
+ if (this.landmarkSteps) {
49
64
  this.pois = pois;
50
65
  this.levelChangers = levelChangers;
51
66
  this.initialBearing = initialBearing;
52
67
  }
53
- this.simplifiedTBT = simplifiedTBT;
54
68
  if (this.points && this.points.length > 0) {
69
+ if (this.levelChangersSteps) {
70
+ this.points = this.points.flatMap((point, i) => {
71
+ const next = this.points[i + 1];
72
+ if (point.isLevelChanger && (next === null || next === void 0 ? void 0 : next.isLevelChanger) && point.properties.level !== next.properties.level) {
73
+ const transition = new Feature(Object.assign({}, point));
74
+ return [point, transition];
75
+ }
76
+ return [point];
77
+ });
78
+ }
55
79
  this.generateStepsFromPoints();
56
80
  }
57
81
  }
@@ -77,30 +101,35 @@ export default class GuidanceStepsGenerator {
77
101
  });
78
102
  const distanceFromLastStep = this.getDistanceFromLastStep(data);
79
103
  const extendedData = Object.assign(Object.assign({}, data), { direction, distanceFromLastStep });
80
- if (this.landMarkNav &&
104
+ if (this.stepsNavigation === 'landmark' &&
81
105
  (direction === Direction.Start ||
82
106
  (direction === Direction.Finish && currentPoint.isPoi) ||
83
107
  direction === Direction.TurnAround ||
84
- /*direction === `${Direction.Down}_${LevelChangerTypes[currentPoint.properties.type]}` ||
85
- direction === `${Direction.Up}_${LevelChangerTypes[currentPoint.properties.type]}` ||*/
86
108
  direction === `${Direction.Exit}_${LevelChangerTypes[currentPoint.properties.type]}` ||
87
109
  distanceFromLastStep === 0)) {
88
110
  return;
89
111
  }
90
- if (!this.simplifiedTBT &&
112
+ if (this.stepsNavigation === 'landmark-levelChangers' &&
91
113
  (direction === Direction.Start ||
92
114
  (direction === Direction.Finish && currentPoint.isPoi) ||
93
- direction === Direction.TurnAround) /*||
94
- direction === `${Direction.Down}_${LevelChangerTypes[currentPoint.properties.type]}` ||
95
- direction === `${Direction.Up}_${LevelChangerTypes[currentPoint.properties.type]}` ||
96
- direction === `${Direction.Exit}_${LevelChangerTypes[currentPoint.properties.type]}` ||
97
- distanceFromLastStep === 0*/) {
115
+ direction === Direction.TurnAround)) {
116
+ return;
117
+ }
118
+ if (this.stepsNavigation === 'full' &&
119
+ (direction === Direction.Start ||
120
+ direction === Direction.TurnAround ||
121
+ direction === `${Direction.Exit}_${LevelChangerTypes[currentPoint.properties.type]}` ||
122
+ distanceFromLastStep === 0)) {
98
123
  return;
99
124
  }
100
- return {
125
+ if (this.stepsNavigation === 'full-levelChangers' &&
126
+ (direction === Direction.Start || direction === Direction.TurnAround)) {
127
+ return;
128
+ }
129
+ const step = {
101
130
  bearingFromLastStep: this.getBearingFromLastStep(data),
102
131
  coordinates: [point.geometry.coordinates[0], point.geometry.coordinates[1]],
103
- direction: this.landMarkNav
132
+ direction: this.landmarkSteps
104
133
  ? nextStepDirection === Direction.Finish && (nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.isPoi)
105
134
  ? Direction.Finish
106
135
  : direction
@@ -114,72 +143,257 @@ export default class GuidanceStepsGenerator {
114
143
  ? nextPoint.properties.level
115
144
  : null,
116
145
  lineStringFeatureFromLastStep: this.getLineStringFeatureFromLastStep(data),
117
- instruction: this.generateInstruction(extendedData), // New attribute
118
146
  };
147
+ const destinationFloor = step.levelChangerDestinationLevel && this.floors.filter((f) => f.level === step.levelChangerDestinationLevel)
148
+ ? this.floors.filter((f) => f.level === step.levelChangerDestinationLevel)[0]
149
+ : this.currentFloor;
150
+ step.destinationFloor = destinationFloor;
151
+ return Object.assign(Object.assign({}, step), { instruction: this.generateInstruction(Object.assign(Object.assign({}, extendedData), { step })) });
119
152
  });
120
- }
121
- generateInstruction({ previousPoint, secondPreviousPoint, currentPoint, nextPoint, secondNextPoint, direction, distanceFromLastStep, }) {
122
- let instruction = '';
123
- if (this.landMarkNav && previousPoint.isLevelChanger) {
124
- const levelChangerFeature = this.levelChangers.find((f) => f.id === previousPoint.id);
125
- const levelChangeDirection = this.getStepDirection({
126
- previousPoint: levelChangerFeature,
127
- currentPoint: previousPoint,
128
- nextPoint: currentPoint,
129
- levelChangerDirection: true,
153
+ if (this.simpleSteps) {
154
+ let previousIndex = 0;
155
+ this.steps = this.steps
156
+ .filter((i, index, array) => {
157
+ // Get the first part of the direction string
158
+ const direction = i.direction.split('_')[0];
159
+ if (this.stepsNavigation === 'simple') {
160
+ // Check if the current step is a level changer and has a valid direction or is finish
161
+ if ((i.levelChangerId && (direction === 'UP' || direction === 'DOWN')) || i.direction === 'FINISH') {
162
+ i.stepsUntil = array.slice(previousIndex, index);
163
+ previousIndex = index + 1;
164
+ return i;
165
+ }
166
+ }
167
+ else {
168
+ if (i.levelChangerId) {
169
+ i.stepsUntil = array.slice(previousIndex, index);
170
+ previousIndex = index + 1;
171
+ return i;
172
+ }
173
+ if (i.direction === 'FINISH') {
174
+ i.stepsUntil = array.slice(previousIndex, index);
175
+ previousIndex = index + 1;
176
+ return i;
177
+ }
178
+ }
179
+ })
180
+ .map((step) => {
181
+ const stepsUntilDistance = step.stepsUntil && step.stepsUntil.length > 0
182
+ ? step.stepsUntil.reduce((total, item) => total + item.distanceFromLastStep, 0)
183
+ : 0;
184
+ const totalDistance = step.distanceFromLastStep + stepsUntilDistance;
185
+ const simplifiedStep = Object.assign(Object.assign({}, step), { totalDistance });
186
+ return Object.assign(Object.assign({}, simplifiedStep), { instruction: this.generateInstruction({ direction: simplifiedStep.direction, step: simplifiedStep }) });
130
187
  });
131
- instruction += `${this.capitalize(this.getDirectionInstruction(levelChangeDirection))} `;
132
188
  }
133
- if (this.landMarkNav && !secondPreviousPoint && this.initialBearing) {
134
- // if first step
135
- const bearingVar = bearing(previousPoint.geometry.coordinates, currentPoint.geometry.coordinates) - this.initialBearing;
136
- const dir = this.getDirectionFromBearing(bearingVar);
137
- instruction += `${this.getDirectionInstruction(dir)} `;
189
+ }
190
+ generateInstruction(params) {
191
+ if (this.simpleSteps)
192
+ return this.generateSimpleInstruction(params);
193
+ if (this.fullSteps)
194
+ return this.generateFullInstruction(params);
195
+ if (this.landmarkSteps)
196
+ return this.generateLandmarkInstruction(params);
197
+ return '';
198
+ }
199
+ // ─── Simple ───────────────────────────────────────────────────────────────────
200
+ generateSimpleInstruction({ step, direction }) {
201
+ var _a, _b, _c;
202
+ if (!(step === null || step === void 0 ? void 0 : step.totalDistance) && !this.levelChangersSteps)
203
+ return '';
204
+ const t = translations[this.language];
205
+ if (direction === 'FINISH') {
206
+ return [
207
+ this.capitalize(t.IN),
208
+ step.totalDistance ? step.totalDistance.toFixed(0) : 0,
209
+ t.METERS,
210
+ this.getDirectionInstruction(direction),
211
+ ].join(' ');
212
+ }
213
+ const floorName = ((_a = step.destinationFloor) === null || _a === void 0 ? void 0 : _a.name)
214
+ ? getFloorName({ floor: step.destinationFloor, language: this.language })
215
+ : String(step.destinationLevel);
216
+ if (this.levelChangersSteps && step.levelChangerId && !step.distanceFromLastStep) {
217
+ return this.generateLevelChangerStepInstruction({ step, t });
218
+ }
219
+ return [
220
+ this.capitalize(t.GO),
221
+ step.totalDistance ? step.totalDistance.toFixed(0) : 0,
222
+ t.METERS,
223
+ t.AND_TAKE_THE,
224
+ (_c = t[(_b = step.levelChangerType) === null || _b === void 0 ? void 0 : _b.toUpperCase()]) === null || _c === void 0 ? void 0 : _c.toLowerCase(),
225
+ t[step.levelChangerDirection],
226
+ t.TO,
227
+ floorName,
228
+ t.FLOOR + '.',
229
+ ].join(' ');
230
+ }
231
+ // ─── Full ─────────────────────────────────────────────────────────────────────
232
+ generateFullInstruction({ direction, distanceFromLastStep, step, currentPoint, }) {
233
+ const t = translations[this.language];
234
+ if ((currentPoint === null || currentPoint === void 0 ? void 0 : currentPoint.isLevelChanger) && step && step.distanceFromLastStep) {
235
+ return this.generateFullLevelChangerInstruction({ step, t });
236
+ }
237
+ if (direction === Direction.Start) {
238
+ return this.getDirectionInstruction(direction);
239
+ }
240
+ if (direction === Direction.Finish) {
241
+ return [
242
+ this.capitalize(t.IN),
243
+ distanceFromLastStep.toFixed(0),
244
+ t.METERS + ',',
245
+ this.getDirectionInstruction(direction),
246
+ ].join(' ');
138
247
  }
139
248
  if (distanceFromLastStep > 0) {
140
- instruction += `${this.capitalize(translations[this.language].IN)} ${distanceFromLastStep.toFixed(0)} ${translations[this.language].METERS} `;
249
+ return [
250
+ this.capitalize(t.IN),
251
+ distanceFromLastStep.toFixed(0),
252
+ t.METERS + ',',
253
+ this.getDirectionInstruction(direction),
254
+ ].join(' ');
141
255
  }
256
+ if (this.levelChangersSteps && step.levelChangerId) {
257
+ return this.generateLevelChangerStepInstruction({ step, t });
258
+ }
259
+ // Fallback: no distance yet (first step or distance not available)
260
+ return this.capitalize(this.getDirectionInstruction(direction));
261
+ }
262
+ generateFullLevelChangerInstruction({ step, t, }) {
263
+ var _a;
264
+ const floorName = ((_a = step.destinationFloor) === null || _a === void 0 ? void 0 : _a.name)
265
+ ? getFloorName({ floor: step.destinationFloor, language: this.language })
266
+ : String(step.destinationLevel);
267
+ return [
268
+ this.capitalize(t.IN),
269
+ step.distanceFromLastStep.toFixed(0),
270
+ t.METERS + ',',
271
+ t.TAKE_THE,
272
+ t[step.levelChangerType.toUpperCase()].toLowerCase(),
273
+ t[step.levelChangerDirection],
274
+ t.TO,
275
+ floorName,
276
+ t.FLOOR + '.',
277
+ ].join(' ');
278
+ }
279
+ generateLevelChangerStepInstruction({ step, t, }) {
280
+ var _a, _b, _c, _d, _e, _f, _g;
281
+ const floorName = ((_a = step.destinationFloor) === null || _a === void 0 ? void 0 : _a.name)
282
+ ? getFloorName({ floor: step.destinationFloor, language: this.language })
283
+ : String(step.destinationLevel);
284
+ const stepDirection = step.direction.split('_')[0];
285
+ // at level changer step
286
+ if (stepDirection === 'UP' || stepDirection === 'DOWN') {
287
+ return [
288
+ this.capitalize(t.YOU_ARE_AT_THE),
289
+ ((_c = t[(_b = step.levelChangerType) === null || _b === void 0 ? void 0 : _b.toUpperCase()]) === null || _c === void 0 ? void 0 : _c.toLowerCase()) + ',',
290
+ t.GO,
291
+ t[step.levelChangerDirection],
292
+ t.VIA,
293
+ (_e = t[(_d = step.levelChangerType) === null || _d === void 0 ? void 0 : _d.toUpperCase()]) === null || _e === void 0 ? void 0 : _e.toLowerCase(),
294
+ t.TO,
295
+ floorName,
296
+ t.FLOOR + '.',
297
+ ].join(' ');
298
+ }
299
+ // exit level changer step
300
+ if (stepDirection === 'EXIT') {
301
+ return [
302
+ this.capitalize(t.EXIT_THE),
303
+ ((_g = t[(_f = step.levelChangerType) === null || _f === void 0 ? void 0 : _f.toUpperCase()]) === null || _g === void 0 ? void 0 : _g.toLowerCase()) + ',',
304
+ t.YOU_ARE_AT.toLowerCase(),
305
+ floorName,
306
+ t.FLOOR + '.',
307
+ ].join(' ');
308
+ }
309
+ }
310
+ // ─── Landmark ────────────────────────────────────────────────────────────────
311
+ generateLandmarkInstruction(params) {
312
+ const parts = [];
313
+ parts.push(...this.getLandmarkLevelChangerPrefix(params));
314
+ parts.push(...this.getLandmarkInitialBearingPrefix(params));
315
+ parts.push(...this.getLandmarkDistancePrefix(params));
316
+ const { direction } = params;
142
317
  if (direction === Direction.TurnAround || direction === Direction.Start || direction === Direction.Finish) {
143
- instruction += this.getDirectionInstruction(direction);
144
- return instruction;
318
+ parts.push(this.getDirectionInstruction(direction));
319
+ return parts.join(' ');
145
320
  }
146
- if (this.landMarkNav) {
147
- const featureCollection = {
148
- type: 'FeatureCollection',
149
- features: this.pois.filter((f) => f.properties.level === currentPoint.properties.level),
150
- };
151
- const nextPointDirection = this.getStepDirection({
152
- previousPoint: currentPoint,
153
- currentPoint: nextPoint,
154
- nextPoint: secondNextPoint,
155
- });
156
- if (nextPointDirection === Direction.Finish && nextPoint.isPoi) {
157
- instruction += `${translations[this.language].DESTINATION} ${nextPoint.properties.title_i18n && nextPoint.properties.title_i18n[this.language]
158
- ? nextPoint.properties.title_i18n[this.language]
159
- : nextPoint.properties.title} ${translations[this.language].navInstructions[direction]}`;
160
- return instruction;
321
+ parts.push(...this.getLandmarkDirectionWithContext(params));
322
+ return parts.join(' ');
323
+ }
324
+ getLandmarkLevelChangerPrefix({ previousPoint, currentPoint, step }) {
325
+ if (!(previousPoint === null || previousPoint === void 0 ? void 0 : previousPoint.isLevelChanger))
326
+ return [];
327
+ if (this.levelChangersSteps && (step === null || step === void 0 ? void 0 : step.levelChangerId))
328
+ return [];
329
+ const levelChangerFeature = this.levelChangers.find((f) => f.id === previousPoint.id);
330
+ const levelChangeDirection = this.getStepDirection({
331
+ previousPoint: levelChangerFeature,
332
+ currentPoint: previousPoint,
333
+ nextPoint: currentPoint,
334
+ levelChangerDirection: true,
335
+ });
336
+ return [this.capitalize(this.getDirectionInstruction(levelChangeDirection))];
337
+ }
338
+ getLandmarkInitialBearingPrefix({ previousPoint, secondPreviousPoint, currentPoint, step, }) {
339
+ if (secondPreviousPoint || !this.initialBearing)
340
+ return [];
341
+ if (this.levelChangersSteps && (step === null || step === void 0 ? void 0 : step.levelChangerId))
342
+ return [];
343
+ const bearingVar = bearing(previousPoint.geometry.coordinates, currentPoint.geometry.coordinates) - this.initialBearing;
344
+ const dir = this.getDirectionFromBearing(bearingVar);
345
+ return [this.getDirectionInstruction(dir)];
346
+ }
347
+ getLandmarkDistancePrefix({ distanceFromLastStep, currentPoint, step }) {
348
+ if (!distanceFromLastStep || distanceFromLastStep <= 0)
349
+ return [];
350
+ if (this.levelChangersSteps && (currentPoint === null || currentPoint === void 0 ? void 0 : currentPoint.isLevelChanger))
351
+ return [];
352
+ if (this.levelChangersSteps && (step === null || step === void 0 ? void 0 : step.levelChangerId))
353
+ return [];
354
+ const t = translations[this.language];
355
+ return [this.capitalize(t.IN), distanceFromLastStep.toFixed(0), t.METERS];
356
+ }
357
+ getLandmarkDirectionWithContext({ currentPoint, nextPoint, secondNextPoint, direction, step, }) {
358
+ var _a, _b, _c, _d, _e;
359
+ const t = translations[this.language];
360
+ const nextPointDirection = this.getStepDirection({
361
+ previousPoint: currentPoint,
362
+ currentPoint: nextPoint,
363
+ nextPoint: secondNextPoint,
364
+ });
365
+ // Approaching a POI destination
366
+ if (nextPointDirection === Direction.Finish && (nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.isPoi)) {
367
+ const title = (_b = (_a = nextPoint.properties.title_i18n) === null || _a === void 0 ? void 0 : _a[this.language]) !== null && _b !== void 0 ? _b : nextPoint.properties.title;
368
+ return [t.DESTINATION, title, t.navInstructions[direction]];
369
+ }
370
+ const directionInstruction = this.getDirectionInstruction(direction);
371
+ // Exiting a level changer
372
+ if (currentPoint === null || currentPoint === void 0 ? void 0 : currentPoint.isLevelChanger) {
373
+ const floorName = ((_c = step.destinationFloor) === null || _c === void 0 ? void 0 : _c.name)
374
+ ? getFloorName({ floor: step.destinationFloor, language: this.language })
375
+ : String(step.destinationLevel);
376
+ if (this.levelChangersSteps) {
377
+ if (step.distanceFromLastStep > 0) {
378
+ return [this.generateFullLevelChangerInstruction({ step, t })];
379
+ }
380
+ else {
381
+ return [this.generateLevelChangerStepInstruction({ step, t })];
382
+ }
161
383
  }
162
- /*if (nextPoint.isLevelChanger) {
163
- instruction += `${this.getDirectionInstruction(nextPointDirection).slice(0, -1)} ${
164
- translations[this.language].TO_FLOOR
165
- } ${secondNextPoint.properties.level}`;
166
- return instruction;
167
- }*/
168
- instruction += this.getDirectionInstruction(direction);
169
- if (currentPoint.isLevelChanger) {
170
- instruction = instruction.slice(0, -1);
171
- instruction += ` ${translations[this.language].TO_FLOOR} ${nextPoint.properties.level}`;
172
- return instruction;
384
+ else {
385
+ // Trim trailing punctuation from direction instruction before appending floor
386
+ return [`${directionInstruction.replace(/[.,]$/, '')} ${t.TO} ${floorName} ${t.FLOOR}.`];
173
387
  }
174
- const nearestPoi = nearestPoint(currentPoint.geometry.coordinates, featureCollection);
175
- instruction = `${instruction.slice(0, -1)} ${translations[this.language].BY} ${nearestPoi.properties.title_i18n && nearestPoi.properties.title_i18n[this.language]
176
- ? nearestPoi.properties.title_i18n[this.language]
177
- : nearestPoi.properties.title}`;
178
- }
179
- else {
180
- instruction += this.getDirectionInstruction(direction);
181
388
  }
182
- return instruction;
389
+ // Standard landmark: direction + nearest POI
390
+ const floorPois = {
391
+ type: 'FeatureCollection',
392
+ features: this.pois.filter((f) => f.properties.level === currentPoint.properties.level),
393
+ };
394
+ const nearestPoi = nearestPoint(currentPoint.geometry.coordinates, floorPois);
395
+ const poiTitle = (_e = (_d = nearestPoi.properties.title_i18n) === null || _d === void 0 ? void 0 : _d[this.language]) !== null && _e !== void 0 ? _e : nearestPoi.properties.title;
396
+ return [`${directionInstruction.replace(/[.,]$/, '')} ${t.BY} ${poiTitle}`];
183
397
  }
184
398
  getDirectionInstruction(direction) {
185
399
  switch (direction) {
@@ -37,6 +37,14 @@ export declare const translations: {
37
37
  FLOOR: string;
38
38
  BY: string;
39
39
  IS_ON_YOUR: string;
40
+ GO: string;
41
+ AND_TAKE_THE: string;
42
+ WALK: string;
43
+ TAKE_THE: string;
44
+ YOU_ARE_AT: string;
45
+ YOU_ARE_AT_THE: string;
46
+ VIA: string;
47
+ EXIT_THE: string;
40
48
  navInstructions: {
41
49
  STRAIGHT: string;
42
50
  TURN_AROUND: string;
@@ -86,6 +94,14 @@ export declare const translations: {
86
94
  FLOOR: string;
87
95
  BY: string;
88
96
  IS_ON_YOUR: string;
97
+ GO: string;
98
+ AND_TAKE_THE: string;
99
+ WALK: string;
100
+ TAKE_THE: string;
101
+ YOU_ARE_AT: string;
102
+ YOU_ARE_AT_THE: string;
103
+ VIA: string;
104
+ EXIT_THE: string;
89
105
  navInstructions: {
90
106
  STRAIGHT: string;
91
107
  TURN_AROUND: string;
@@ -135,6 +151,14 @@ export declare const translations: {
135
151
  FLOOR: string;
136
152
  BY: string;
137
153
  IS_ON_YOUR: string;
154
+ GO: string;
155
+ AND_TAKE_THE: string;
156
+ WALK: string;
157
+ TAKE_THE: string;
158
+ YOU_ARE_AT: string;
159
+ YOU_ARE_AT_THE: string;
160
+ VIA: string;
161
+ EXIT_THE: string;
138
162
  navInstructions: {
139
163
  STRAIGHT: string;
140
164
  TURN_AROUND: string;
@@ -184,6 +208,14 @@ export declare const translations: {
184
208
  FLOOR: string;
185
209
  BY: string;
186
210
  IS_ON_YOUR: string;
211
+ GO: string;
212
+ AND_TAKE_THE: string;
213
+ WALK: string;
214
+ TAKE_THE: string;
215
+ YOU_ARE_AT: string;
216
+ YOU_ARE_AT_THE: string;
217
+ VIA: string;
218
+ EXIT_THE: string;
187
219
  navInstructions: {
188
220
  STRAIGHT: string;
189
221
  TURN_AROUND: string;
@@ -233,6 +265,14 @@ export declare const translations: {
233
265
  FLOOR: string;
234
266
  BY: string;
235
267
  IS_ON_YOUR: string;
268
+ GO: string;
269
+ AND_TAKE_THE: string;
270
+ WALK: string;
271
+ TAKE_THE: string;
272
+ YOU_ARE_AT: string;
273
+ YOU_ARE_AT_THE: string;
274
+ VIA: string;
275
+ EXIT_THE: string;
236
276
  navInstructions: {
237
277
  STRAIGHT: string;
238
278
  TURN_AROUND: string;
@@ -282,6 +322,14 @@ export declare const translations: {
282
322
  FLOOR: string;
283
323
  BY: string;
284
324
  IS_ON_YOUR: string;
325
+ GO: string;
326
+ AND_TAKE_THE: string;
327
+ WALK: string;
328
+ TAKE_THE: string;
329
+ YOU_ARE_AT: string;
330
+ YOU_ARE_AT_THE: string;
331
+ VIA: string;
332
+ EXIT_THE: string;
285
333
  navInstructions: {
286
334
  STRAIGHT: string;
287
335
  TURN_AROUND: string;
@@ -331,6 +379,14 @@ export declare const translations: {
331
379
  FLOOR: string;
332
380
  BY: string;
333
381
  IS_ON_YOUR: string;
382
+ GO: string;
383
+ AND_TAKE_THE: string;
384
+ WALK: string;
385
+ TAKE_THE: string;
386
+ YOU_ARE_AT: string;
387
+ YOU_ARE_AT_THE: string;
388
+ VIA: string;
389
+ EXIT_THE: string;
334
390
  navInstructions: {
335
391
  STRAIGHT: string;
336
392
  TURN_AROUND: string;