proximiio-js-library 1.14.55 → 1.15.1

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,5 +1,6 @@
1
1
  import { lineString, point } from '@turf/helpers';
2
2
  import pointToLineDistance from '@turf/point-to-line-distance';
3
+ import distance from '@turf/distance';
3
4
  /**
4
5
  * Find the most appropriate navigation step index based on user's current position.
5
6
  *
@@ -16,16 +17,22 @@ const getCurrentStepIndex = ({ userPosition, steps, lastKnownStepIndex = 0, thre
16
17
  // Only check steps ahead of current one to avoid regressions
17
18
  for (let i = lastKnownStepIndex; i < steps.length; i++) {
18
19
  const step = steps[i];
19
- if (step.navMode === 'mall' && !step.lineStringFeatureFromLastStep) {
20
+ const isStartOrLevelChanger = step.direction === 'START' || step.levelChangerId;
21
+ if (step.navMode === 'mall' && !step.lineStringFeatureFromLastStep && !isStartOrLevelChanger) {
20
22
  return;
21
23
  }
22
- const lineCoords = step.navMode === 'mall' ? step.lineStringFeatureFromLastStep.geometry.coordinates : step.geometry.coordinates;
23
- const line = lineString(lineCoords);
24
- // Calculate shortest distance from user to this step's path
25
- const distance = pointToLineDistance(userPoint, line, { units: 'meters' });
24
+ let pointDistance = 0;
25
+ if (isStartOrLevelChanger) {
26
+ pointDistance = distance(userPoint, point(step.coordinates), { units: 'meters' });
27
+ }
28
+ else {
29
+ const lineCoords = step.navMode === 'mall' ? step.lineStringFeatureFromLastStep.geometry.coordinates : step.geometry.coordinates;
30
+ const line = lineString(lineCoords);
31
+ pointDistance = pointToLineDistance(userPoint, line, { units: 'meters' });
32
+ }
26
33
  // If within threshold and closest so far, consider this as best candidate
27
- if (distance < thresholdMeters && distance < minDistance) {
28
- minDistance = distance;
34
+ if (pointDistance < thresholdMeters && pointDistance < minDistance) {
35
+ minDistance = pointDistance;
29
36
  closestStepIndex = i;
30
37
  }
31
38
  }
@@ -1,24 +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
+ stepsNavigation: 'disabled' | 'simple' | 'simple-levelChangers' | 'full' | 'full-levelChangers' | 'landmark' | 'landmark-levelChangers';
8
9
  pois?: Feature[];
9
10
  levelChangers?: Feature[];
10
11
  initialBearing: number;
11
- constructor({ points, language, landMarkNav, 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, }: {
12
19
  points: Feature[];
13
20
  language: string;
14
- landMarkNav: boolean;
21
+ stepsNavigation: 'disabled' | 'simple' | 'simple-levelChangers' | 'full' | 'full-levelChangers' | 'landmark' | 'landmark-levelChangers';
15
22
  pois?: Feature[];
16
23
  levelChangers?: Feature[];
17
24
  initialBearing: number;
25
+ floors: FloorModel[];
26
+ currentFloor: FloorModel;
18
27
  });
19
28
  private capitalize;
20
29
  private generateStepsFromPoints;
21
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;
22
40
  private getDirectionInstruction;
23
41
  private getBearingFromLastStep;
24
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,17 +46,36 @@ var LevelChangerTypes;
40
46
  LevelChangerTypes["ramp"] = "RAMP";
41
47
  })(LevelChangerTypes || (LevelChangerTypes = {}));
42
48
  export default class GuidanceStepsGenerator {
43
- constructor({ points, language, landMarkNav, 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
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
+ }
54
79
  this.generateStepsFromPoints();
55
80
  }
56
81
  }
@@ -76,20 +101,35 @@ export default class GuidanceStepsGenerator {
76
101
  });
77
102
  const distanceFromLastStep = this.getDistanceFromLastStep(data);
78
103
  const extendedData = Object.assign(Object.assign({}, data), { direction, distanceFromLastStep });
79
- if (this.landMarkNav &&
104
+ if (this.stepsNavigation === 'landmark' &&
80
105
  (direction === Direction.Start ||
81
106
  (direction === Direction.Finish && currentPoint.isPoi) ||
82
107
  direction === Direction.TurnAround ||
83
- /*direction === `${Direction.Down}_${LevelChangerTypes[currentPoint.properties.type]}` ||
84
- direction === `${Direction.Up}_${LevelChangerTypes[currentPoint.properties.type]}` ||*/
85
108
  direction === `${Direction.Exit}_${LevelChangerTypes[currentPoint.properties.type]}` ||
86
109
  distanceFromLastStep === 0)) {
87
110
  return;
88
111
  }
89
- return {
112
+ if (this.stepsNavigation === 'landmark-levelChangers' &&
113
+ (direction === Direction.Start ||
114
+ (direction === Direction.Finish && currentPoint.isPoi) ||
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)) {
123
+ return;
124
+ }
125
+ if (this.stepsNavigation === 'full-levelChangers' &&
126
+ (direction === Direction.Start || direction === Direction.TurnAround)) {
127
+ return;
128
+ }
129
+ const step = {
90
130
  bearingFromLastStep: this.getBearingFromLastStep(data),
91
131
  coordinates: [point.geometry.coordinates[0], point.geometry.coordinates[1]],
92
- direction: this.landMarkNav
132
+ direction: this.landmarkSteps
93
133
  ? nextStepDirection === Direction.Finish && (nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.isPoi)
94
134
  ? Direction.Finish
95
135
  : direction
@@ -103,72 +143,257 @@ export default class GuidanceStepsGenerator {
103
143
  ? nextPoint.properties.level
104
144
  : null,
105
145
  lineStringFeatureFromLastStep: this.getLineStringFeatureFromLastStep(data),
106
- instruction: this.generateInstruction(extendedData), // New attribute
107
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 })) });
108
152
  });
109
- }
110
- generateInstruction({ previousPoint, secondPreviousPoint, currentPoint, nextPoint, secondNextPoint, direction, distanceFromLastStep, }) {
111
- let instruction = '';
112
- if (this.landMarkNav && previousPoint.isLevelChanger) {
113
- const levelChangerFeature = this.levelChangers.find((f) => f.id === previousPoint.id);
114
- const levelChangeDirection = this.getStepDirection({
115
- previousPoint: levelChangerFeature,
116
- currentPoint: previousPoint,
117
- nextPoint: currentPoint,
118
- 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 }) });
119
187
  });
120
- instruction += `${this.capitalize(this.getDirectionInstruction(levelChangeDirection))} `;
121
188
  }
122
- if (this.landMarkNav && !secondPreviousPoint && this.initialBearing) {
123
- // if first step
124
- const bearingVar = bearing(previousPoint.geometry.coordinates, currentPoint.geometry.coordinates) - this.initialBearing;
125
- const dir = this.getDirectionFromBearing(bearingVar);
126
- 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(' ');
127
247
  }
128
248
  if (distanceFromLastStep > 0) {
129
- 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(' ');
130
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;
131
317
  if (direction === Direction.TurnAround || direction === Direction.Start || direction === Direction.Finish) {
132
- instruction += this.getDirectionInstruction(direction);
133
- return instruction;
318
+ parts.push(this.getDirectionInstruction(direction));
319
+ return parts.join(' ');
134
320
  }
135
- if (this.landMarkNav) {
136
- const featureCollection = {
137
- type: 'FeatureCollection',
138
- features: this.pois.filter((f) => f.properties.level === currentPoint.properties.level),
139
- };
140
- const nextPointDirection = this.getStepDirection({
141
- previousPoint: currentPoint,
142
- currentPoint: nextPoint,
143
- nextPoint: secondNextPoint,
144
- });
145
- if (nextPointDirection === Direction.Finish && nextPoint.isPoi) {
146
- instruction += `${translations[this.language].DESTINATION} ${nextPoint.properties.title_i18n && nextPoint.properties.title_i18n[this.language]
147
- ? nextPoint.properties.title_i18n[this.language]
148
- : nextPoint.properties.title} ${translations[this.language].navInstructions[direction]}`;
149
- 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
+ }
150
383
  }
151
- /*if (nextPoint.isLevelChanger) {
152
- instruction += `${this.getDirectionInstruction(nextPointDirection).slice(0, -1)} ${
153
- translations[this.language].TO_FLOOR
154
- } ${secondNextPoint.properties.level}`;
155
- return instruction;
156
- }*/
157
- instruction += this.getDirectionInstruction(direction);
158
- if (currentPoint.isLevelChanger) {
159
- instruction = instruction.slice(0, -1);
160
- instruction += ` ${translations[this.language].TO_FLOOR} ${nextPoint.properties.level}`;
161
- return instruction;
384
+ else {
385
+ // Trim trailing punctuation from direction instruction before appending floor
386
+ return [`${directionInstruction.replace(/[.,]$/, '')} ${t.TO} ${floorName} ${t.FLOOR}.`];
162
387
  }
163
- const nearestPoi = nearestPoint(currentPoint.geometry.coordinates, featureCollection);
164
- instruction = `${instruction.slice(0, -1)} ${translations[this.language].BY} ${nearestPoi.properties.title_i18n && nearestPoi.properties.title_i18n[this.language]
165
- ? nearestPoi.properties.title_i18n[this.language]
166
- : nearestPoi.properties.title}`;
167
- }
168
- else {
169
- instruction += this.getDirectionInstruction(direction);
170
388
  }
171
- 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}`];
172
397
  }
173
398
  getDirectionInstruction(direction) {
174
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;