venue-js 1.4.0-next.19 → 1.4.0-next.20

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/dist/index.mjs CHANGED
@@ -150,6 +150,119 @@ var defaultFeatureQueryOptionsMap = {
150
150
  model3d: {}
151
151
  };
152
152
 
153
+ // src/data/utils/geometry-validator.ts
154
+ var isValidCoordinate = (point2) => {
155
+ return point2.length === 2 && point2.every((coord) => typeof coord === "number");
156
+ };
157
+ function isValidLinearRingCoordinates(ring) {
158
+ if (ring.length < 4) {
159
+ return false;
160
+ }
161
+ return ring.every(isValidCoordinate) && ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1];
162
+ }
163
+ var isValidPolygonCoordinates = (polygon2) => {
164
+ if (Array.isArray(polygon2[0]) && (polygon2[0].length === 0 || typeof polygon2[0][0] === "number")) {
165
+ return isValidLinearRingCoordinates(polygon2);
166
+ }
167
+ if (Array.isArray(polygon2) && polygon2.length > 0 && Array.isArray(polygon2[0])) {
168
+ if (!isValidLinearRingCoordinates(polygon2[0])) {
169
+ return false;
170
+ }
171
+ for (let i = 1; i < polygon2.length; i++) {
172
+ if (!isValidLinearRingCoordinates(polygon2[i])) {
173
+ return false;
174
+ }
175
+ }
176
+ return true;
177
+ }
178
+ return false;
179
+ };
180
+ var isValidMultiPolygonCoordinates = (multipolygon) => {
181
+ return multipolygon.every(isValidPolygonCoordinates);
182
+ };
183
+ var isValidLineStringCoordinates = (lineString2) => {
184
+ if (!Array.isArray(lineString2) || lineString2.length < 2) {
185
+ return false;
186
+ }
187
+ const firstPoint = lineString2[0];
188
+ const lastPoint = lineString2[lineString2.length - 1];
189
+ if (firstPoint[0] === lastPoint[0] && firstPoint[1] === lastPoint[1]) {
190
+ return false;
191
+ }
192
+ return lineString2.every(isValidCoordinate);
193
+ };
194
+ var isValidMultiPolygon = (geometry) => {
195
+ const { type, coordinates } = geometry;
196
+ return type === "MultiPolygon" && isValidMultiPolygonCoordinates(coordinates);
197
+ };
198
+ var isValidPolygon = (geometry) => {
199
+ const { type, coordinates } = geometry;
200
+ return type === "Polygon" && isValidPolygonCoordinates(coordinates);
201
+ };
202
+ var isValidLineString = (geometry) => {
203
+ const { type, coordinates } = geometry;
204
+ return type === "LineString" && isValidLineStringCoordinates(coordinates);
205
+ };
206
+ var isValidPoint = (geometry) => {
207
+ const { type, coordinates } = geometry;
208
+ return type === "Point" && isValidCoordinate(coordinates);
209
+ };
210
+
211
+ // src/data/utils/match-filters.ts
212
+ function isInFilter(filter) {
213
+ return typeof filter === "object" && filter !== null && "$in" in filter && Array.isArray(filter.$in);
214
+ }
215
+ var someIntersect = (a, b) => a.some((v) => b.includes(v));
216
+ function matchFilter(value, filter) {
217
+ if (Array.isArray(value)) {
218
+ if (isInFilter(filter)) return someIntersect(value, filter.$in);
219
+ return value.includes(filter);
220
+ } else {
221
+ if (isInFilter(filter)) return filter.$in.includes(value);
222
+ return value === filter;
223
+ }
224
+ }
225
+ function matchFilters(item, filters) {
226
+ return Object.entries(filters).every(([key, filter]) => {
227
+ return matchFilter(item.properties[key], filter);
228
+ });
229
+ }
230
+
231
+ // src/data/utils/occupant-helper.ts
232
+ var occupant_helper_exports = {};
233
+ __export(occupant_helper_exports, {
234
+ getOccupantCorrelatedLocations: () => getOccupantCorrelatedLocations,
235
+ getOccupantMainLocation: () => getOccupantMainLocation,
236
+ getOccupantMarkerLocations: () => getOccupantMarkerLocations
237
+ });
238
+
239
+ // src/data/utils/lodash/compact.ts
240
+ var compact = (arr) => arr.filter((item) => Boolean(item));
241
+
242
+ // src/data/utils/occupant-helper.ts
243
+ var getOccupantMainLocation = (occupant) => {
244
+ return occupant.properties.kiosk || occupant.properties.unit;
245
+ };
246
+ var getOccupantCorrelatedLocations = (occupant) => {
247
+ const allCorrelatedLocations = [
248
+ ...occupant.properties.units,
249
+ ...occupant.properties.kiosks
250
+ ];
251
+ return compact(allCorrelatedLocations);
252
+ };
253
+ var getOccupantMarkerLocations = (occupant, options) => {
254
+ const placementType = options?.type ? options.type : occupant.properties.show_name_on_all_units ? "ALL_LOCATIONS" : "ONCE_PER_LEVEL";
255
+ const mainLocation = getOccupantMainLocation(occupant);
256
+ const mainLocationLevel = mainLocation?.properties?.level_id;
257
+ const allCorrelatedLocations = getOccupantCorrelatedLocations(occupant);
258
+ if (placementType === "ALL_LOCATIONS") {
259
+ return compact([mainLocation, ...allCorrelatedLocations]);
260
+ }
261
+ const otherLevelLocations = allCorrelatedLocations.filter((f) => f.properties.level_id !== mainLocationLevel);
262
+ const onePerLevelLocations = [...new Map(otherLevelLocations.map((loc) => [loc.properties.level_id, loc])).values()];
263
+ return compact([mainLocation, ...onePerLevelLocations]);
264
+ };
265
+
153
266
  // src/data/api/delivery-project.ts
154
267
  async function fetchDeliveryApi(projectId, apiKey, featureType, baseUrl = DEFAULT_BASE_URL) {
155
268
  switch (featureType) {
@@ -271,119 +384,6 @@ var safeFetchFeature = async (featureType, params) => {
271
384
  }
272
385
  };
273
386
 
274
- // src/data/utils/geometry-validator.ts
275
- var isValidCoordinate = (point2) => {
276
- return point2.length === 2 && point2.every((coord) => typeof coord === "number");
277
- };
278
- function isValidLinearRingCoordinates(ring) {
279
- if (ring.length < 4) {
280
- return false;
281
- }
282
- return ring.every(isValidCoordinate) && ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1];
283
- }
284
- var isValidPolygonCoordinates = (polygon2) => {
285
- if (Array.isArray(polygon2[0]) && (polygon2[0].length === 0 || typeof polygon2[0][0] === "number")) {
286
- return isValidLinearRingCoordinates(polygon2);
287
- }
288
- if (Array.isArray(polygon2) && polygon2.length > 0 && Array.isArray(polygon2[0])) {
289
- if (!isValidLinearRingCoordinates(polygon2[0])) {
290
- return false;
291
- }
292
- for (let i = 1; i < polygon2.length; i++) {
293
- if (!isValidLinearRingCoordinates(polygon2[i])) {
294
- return false;
295
- }
296
- }
297
- return true;
298
- }
299
- return false;
300
- };
301
- var isValidMultiPolygonCoordinates = (multipolygon) => {
302
- return multipolygon.every(isValidPolygonCoordinates);
303
- };
304
- var isValidLineStringCoordinates = (lineString2) => {
305
- if (!Array.isArray(lineString2) || lineString2.length < 2) {
306
- return false;
307
- }
308
- const firstPoint = lineString2[0];
309
- const lastPoint = lineString2[lineString2.length - 1];
310
- if (firstPoint[0] === lastPoint[0] && firstPoint[1] === lastPoint[1]) {
311
- return false;
312
- }
313
- return lineString2.every(isValidCoordinate);
314
- };
315
- var isValidMultiPolygon = (geometry) => {
316
- const { type, coordinates } = geometry;
317
- return type === "MultiPolygon" && isValidMultiPolygonCoordinates(coordinates);
318
- };
319
- var isValidPolygon = (geometry) => {
320
- const { type, coordinates } = geometry;
321
- return type === "Polygon" && isValidPolygonCoordinates(coordinates);
322
- };
323
- var isValidLineString = (geometry) => {
324
- const { type, coordinates } = geometry;
325
- return type === "LineString" && isValidLineStringCoordinates(coordinates);
326
- };
327
- var isValidPoint = (geometry) => {
328
- const { type, coordinates } = geometry;
329
- return type === "Point" && isValidCoordinate(coordinates);
330
- };
331
-
332
- // src/data/utils/match-filters.ts
333
- function isInFilter(filter) {
334
- return typeof filter === "object" && filter !== null && "$in" in filter && Array.isArray(filter.$in);
335
- }
336
- var someIntersect = (a, b) => a.some((v) => b.includes(v));
337
- function matchFilter(value, filter) {
338
- if (Array.isArray(value)) {
339
- if (isInFilter(filter)) return someIntersect(value, filter.$in);
340
- return value.includes(filter);
341
- } else {
342
- if (isInFilter(filter)) return filter.$in.includes(value);
343
- return value === filter;
344
- }
345
- }
346
- function matchFilters(item, filters) {
347
- return Object.entries(filters).every(([key, filter]) => {
348
- return matchFilter(item.properties[key], filter);
349
- });
350
- }
351
-
352
- // src/data/utils/occupant-helper.ts
353
- var occupant_helper_exports = {};
354
- __export(occupant_helper_exports, {
355
- getOccupantCorrelatedLocations: () => getOccupantCorrelatedLocations,
356
- getOccupantMainLocation: () => getOccupantMainLocation,
357
- getOccupantMarkerLocations: () => getOccupantMarkerLocations
358
- });
359
-
360
- // src/data/utils/lodash/compact.ts
361
- var compact = (arr) => arr.filter((item) => Boolean(item));
362
-
363
- // src/data/utils/occupant-helper.ts
364
- var getOccupantMainLocation = (occupant) => {
365
- return occupant.properties.kiosk || occupant.properties.unit;
366
- };
367
- var getOccupantCorrelatedLocations = (occupant) => {
368
- const allCorrelatedLocations = [
369
- ...occupant.properties.units,
370
- ...occupant.properties.kiosks
371
- ];
372
- return compact(allCorrelatedLocations);
373
- };
374
- var getOccupantMarkerLocations = (occupant, options) => {
375
- const placementType = options?.type ? options.type : occupant.properties.show_name_on_all_units ? "ALL_LOCATIONS" : "ONCE_PER_LEVEL";
376
- const mainLocation = getOccupantMainLocation(occupant);
377
- const mainLocationLevel = mainLocation?.properties?.level_id;
378
- const allCorrelatedLocations = getOccupantCorrelatedLocations(occupant);
379
- if (placementType === "ALL_LOCATIONS") {
380
- return compact([mainLocation, ...allCorrelatedLocations]);
381
- }
382
- const otherLevelLocations = allCorrelatedLocations.filter((f) => f.properties.level_id !== mainLocationLevel);
383
- const onePerLevelLocations = [...new Map(otherLevelLocations.map((loc) => [loc.properties.level_id, loc])).values()];
384
- return compact([mainLocation, ...onePerLevelLocations]);
385
- };
386
-
387
387
  // src/data/getDataClient.ts
388
388
  import {
389
389
  QueryClient,
@@ -791,7 +791,7 @@ var getDistanceOptions = (options, category) => {
791
791
 
792
792
  // src/data/utils/trace.ts
793
793
  var trace = (namespace, text, ms, color) => {
794
- console.log(`[${namespace}] %c${text.padEnd(90)} ${ms !== void 0 ? `${ms.toFixed(1).padStart(6)} ms` : ``}`, color ? `color: ${color}` : void 0);
794
+ if (process.env.NODE_ENV !== "test") console.log(`[${namespace}] %c${text.padEnd(90)} ${ms !== void 0 ? `${ms.toFixed(1).padStart(6)} ms` : ``}`, color ? `color: ${color}` : void 0);
795
795
  };
796
796
 
797
797
  // src/data/navigate/graph/nodemap/createTraversalNodeMap.ts
@@ -1202,7 +1202,6 @@ var prepareGraph = (options) => {
1202
1202
  // src/data/navigate/steps/createStepUtils.ts
1203
1203
  import { capitalize } from "lodash";
1204
1204
  import _intersectionBy from "lodash/intersectionBy";
1205
- import { center as center6 } from "@turf/center";
1206
1205
 
1207
1206
  // src/data/navigate/description/describe.ts
1208
1207
  var t = (template, locale, options) => {
@@ -1601,7 +1600,7 @@ function pruneSmallAngles(path, minDeg = 10) {
1601
1600
  if (path.length <= 2) return path;
1602
1601
  const out = [path[0]];
1603
1602
  for (let i = 1; i < path.length - 1; i++) {
1604
- const a = out[out.length - 1];
1603
+ const a = out.at(-1);
1605
1604
  const b = path[i];
1606
1605
  const c = path[i + 1];
1607
1606
  const abx = b[0] - a[0], aby = b[1] - a[1];
@@ -1612,7 +1611,7 @@ function pruneSmallAngles(path, minDeg = 10) {
1612
1611
  const angle = Math.acos(dot / (ab * bc)) * 180 / Math.PI;
1613
1612
  if (angle > minDeg) out.push(b);
1614
1613
  }
1615
- out.push(path[path.length - 1]);
1614
+ out.push(path.at(-1));
1616
1615
  return out;
1617
1616
  }
1618
1617
 
@@ -1620,7 +1619,7 @@ function pruneSmallAngles(path, minDeg = 10) {
1620
1619
  function pruneShortSegments(path, minLen = 5) {
1621
1620
  const out = [path[0]];
1622
1621
  for (let i = 1; i < path.length; i++) {
1623
- const [x0, y0] = out[out.length - 1];
1622
+ const [x0, y0] = out.at(-1);
1624
1623
  const [x1, y1] = path[i];
1625
1624
  if (Math.hypot(x1 - x0, y1 - y0) >= minLen) {
1626
1625
  out.push(path[i]);
@@ -1822,7 +1821,7 @@ var shortestPath_default = shortestPath;
1822
1821
  // src/data/navigate/steps/path/index.ts
1823
1822
  var createStepPathUtils = (options) => {
1824
1823
  const resolution = options.resolution ?? 88e-5;
1825
- const { units, kiosks, fixtures } = options.data;
1824
+ const { units = [], kiosks = [], fixtures = [] } = options.data;
1826
1825
  const possibleObstacleFeatures = [...units, ...kiosks, ...fixtures];
1827
1826
  const filterObstaclesByOrdinal = (levelId) => {
1828
1827
  return possibleObstacleFeatures.filter(({ feature_type, properties, geometry }) => {
@@ -1888,181 +1887,6 @@ var createStepPathUtils = (options) => {
1888
1887
  };
1889
1888
  };
1890
1889
 
1891
- // src/data/navigate/landmark/createLandmarkUtils.ts
1892
- import { center as center3 } from "@turf/center";
1893
- import distance4 from "@turf/distance";
1894
- var NEARBY_DISTANCE = 30;
1895
- var createLandmarkUtils = (options) => {
1896
- const { data, findByIdSync } = options;
1897
- const { occupants } = data;
1898
- const occupantToLandmark = (occupant) => {
1899
- const locationType = occupant.properties.unit_id ? "unit" : "kiosk";
1900
- const locationId = locationType === "unit" ? occupant.properties.unit_id : occupant.properties.kiosk_id;
1901
- const location = locationType === "unit" ? findByIdSync(locationId) : findByIdSync(locationId);
1902
- const level = findByIdSync(location.properties.level_id);
1903
- return {
1904
- name: occupant.properties.name,
1905
- point: center3(location.geometry).geometry.coordinates,
1906
- level_id: location.properties.level_id,
1907
- is_priority: occupant.properties.is_landmark,
1908
- ordinal: level.properties.ordinal
1909
- };
1910
- };
1911
- const landmarks = [
1912
- ...occupants.map(occupantToLandmark)
1913
- ];
1914
- const findNearbyLandmarks = (point2, levelId) => {
1915
- if (point2 === null || levelId === null) return [];
1916
- return landmarks.map((landmark) => {
1917
- const landmarkAndDistance = {
1918
- landmark,
1919
- d: distance4(point2, landmark.point, { units: "meters" })
1920
- };
1921
- return landmarkAndDistance;
1922
- }).filter(({ landmark, d }) => d <= NEARBY_DISTANCE && landmark.level_id === levelId).sort((a, b) => {
1923
- const aPriority = a.landmark.is_priority ? 0 : 1;
1924
- const bPriority = b.landmark.is_priority ? 0 : 1;
1925
- if (aPriority !== bPriority) return aPriority - bPriority;
1926
- return a.d - b.d;
1927
- }).map(({ landmark }) => landmark);
1928
- };
1929
- const findNearestLandmark = (point2, levelId) => {
1930
- const nearbyLandmarks = findNearbyLandmarks(point2, levelId);
1931
- const nearestLandmark = nearbyLandmarks.length > 0 ? nearbyLandmarks[0] : null;
1932
- return nearestLandmark;
1933
- };
1934
- return { findNearbyLandmarks, findNearestLandmark };
1935
- };
1936
-
1937
- // src/data/navigate/steps/utils/extractStartPoint.ts
1938
- import { center as center4 } from "@turf/center";
1939
-
1940
- // src/data/navigate/steps/utils/featureIdGuard.ts
1941
- var isOccupant = (id) => !!id && id.startsWith("occupant-");
1942
- var isUnit = (id) => !!id && id.startsWith("unit-");
1943
- var isKiosk = (id) => !!id && id.startsWith("kiosk-");
1944
- var isOpening = (id) => !!id && id.startsWith("opening-");
1945
-
1946
- // src/data/navigate/type-guard.ts
1947
- function isCoordinateOrdinalString(id) {
1948
- return /^-?\d+(\.\d+)?,-?\d+(\.\d+)?,-?\d+(\.\d+)?o$/.test(id);
1949
- }
1950
-
1951
- // src/data/navigate/steps/utils/extractStartPoint.ts
1952
- var extractStartPoint = (path, options) => {
1953
- const { findByIdSync } = options;
1954
- const [a, b, c] = path;
1955
- if (isOccupant(a) && isUnit(b) && isOpening(c)) {
1956
- const occ = findByIdSync(a);
1957
- const opening = findByIdSync(c);
1958
- const level = findByIdSync(opening.properties.level_id);
1959
- return [
1960
- {
1961
- id: occ.id,
1962
- type: "start",
1963
- name: occ.properties.name,
1964
- point: center4(opening).geometry.coordinates,
1965
- levelId: opening.properties.level_id,
1966
- ordinal: level.properties.ordinal,
1967
- source: { type: "opening", id: opening.id }
1968
- },
1969
- path.slice(3)
1970
- ];
1971
- }
1972
- if (isOccupant(a) && isKiosk(b)) {
1973
- const occ = findByIdSync(a);
1974
- const kiosk = findByIdSync(c);
1975
- const level = findByIdSync(kiosk.properties.level_id);
1976
- return [
1977
- {
1978
- id: occ.id,
1979
- type: "start",
1980
- name: occ.properties.name,
1981
- point: center4(kiosk).geometry.coordinates,
1982
- levelId: kiosk.properties.level_id,
1983
- ordinal: level.properties.ordinal,
1984
- source: { type: "kiosk", id: kiosk.id }
1985
- },
1986
- path.slice(2)
1987
- ];
1988
- }
1989
- if (isCoordinateOrdinalString(a) && isOpening(b)) {
1990
- const [lat, lng, ordinal] = parseOrdinalCoordinate(a);
1991
- const opening = findByIdSync(b);
1992
- return [
1993
- {
1994
- id: a,
1995
- type: "start",
1996
- name: { en: `Your location` },
1997
- point: [lng, lat],
1998
- levelId: opening.properties.level_id,
1999
- ordinal,
2000
- source: { type: "opening", id: opening.id }
2001
- },
2002
- path.slice(1)
2003
- ];
2004
- }
2005
- return [null, path];
2006
- };
2007
-
2008
- // src/data/navigate/steps/utils/extractEndPint.ts
2009
- import { center as center5 } from "@turf/center";
2010
- var extractEndPoint = (path, options) => {
2011
- const { findByIdSync } = options;
2012
- const [c, b, a] = path.slice(-3);
2013
- if (isOccupant(a) && isUnit(b) && isOpening(c)) {
2014
- const occ = findByIdSync(a);
2015
- const opening = findByIdSync(c);
2016
- const level = findByIdSync(opening.properties.level_id);
2017
- return [
2018
- {
2019
- id: occ.id,
2020
- type: "end",
2021
- name: occ.properties.name,
2022
- point: center5(opening).geometry.coordinates,
2023
- levelId: opening.properties.level_id,
2024
- ordinal: level.properties.ordinal,
2025
- source: { type: "opening", id: opening.id }
2026
- },
2027
- path.slice(0, -3)
2028
- ];
2029
- }
2030
- if (isOccupant(a) && isKiosk(b)) {
2031
- const occ = findByIdSync(a);
2032
- const kiosk = findByIdSync(c);
2033
- const level = findByIdSync(kiosk.properties.level_id);
2034
- return [
2035
- {
2036
- id: occ.id,
2037
- type: "end",
2038
- name: occ.properties.name,
2039
- point: center5(kiosk).geometry.coordinates,
2040
- levelId: kiosk.properties.level_id,
2041
- ordinal: level.properties.ordinal,
2042
- source: { type: "kiosk", id: kiosk.id }
2043
- },
2044
- path.slice(0, -2)
2045
- ];
2046
- }
2047
- if (isCoordinateOrdinalString(a)) {
2048
- const [lat, lng, ordinal] = parseOrdinalCoordinate(a);
2049
- const opening = findByIdSync(b);
2050
- return [
2051
- {
2052
- id: a,
2053
- type: "end",
2054
- name: { en: `Your location` },
2055
- point: [lng, lat],
2056
- levelId: opening.properties.level_id,
2057
- ordinal,
2058
- source: { type: "opening", id: opening.id }
2059
- },
2060
- path.slice(0, -2)
2061
- ];
2062
- }
2063
- return [null, path];
2064
- };
2065
-
2066
1890
  // src/data/navigate/steps/utils/combineWalkwaySteps.ts
2067
1891
  import uniq from "lodash/uniq";
2068
1892
  var combineWalkwaySteps = (steps) => {
@@ -2075,7 +1899,6 @@ var combineWalkwaySteps = (steps) => {
2075
1899
  }
2076
1900
  const nextStep = steps[i + 1];
2077
1901
  if (thisStep.intermediaryCategory === "walkway" && nextStep.intermediaryCategory === "walkway" && thisStep.from.source.type === "opening" && nextStep.from.source.type === "opening") {
2078
- console.log({ i, len: steps.length, thisStep, nextStep });
2079
1902
  result.push({
2080
1903
  from: thisStep.from,
2081
1904
  to: nextStep.to,
@@ -2099,15 +1922,14 @@ var combineWalkwaySteps = (steps) => {
2099
1922
  // src/data/navigate/steps/createStepUtils.ts
2100
1923
  var createStepUtils = (options) => {
2101
1924
  const { data: { units, relationships }, findByIdSync } = options;
2102
- const landmarkUtils = createLandmarkUtils(options);
2103
1925
  const stepPathUtils = createStepPathUtils({ ...options, resolution: 88e-5 });
2104
1926
  const findUnitBetweenOpenings = (originId, destinationId) => {
2105
1927
  const origin = findByIdSync(originId);
2106
1928
  const destination = findByIdSync(destinationId);
2107
1929
  const matchedOne = relationships.find((rel) => rel.properties.intermediary.map((int) => int.id).includes(origin.id));
2108
- const matchOneUnits = [matchedOne.properties.origin, matchedOne.properties.destination];
1930
+ const matchOneUnits = matchedOne ? [matchedOne.properties.origin, matchedOne.properties.destination] : [];
2109
1931
  const matchedTwo = relationships.find((rel) => rel.properties.intermediary.map((int) => int.id).includes(destination.id));
2110
- const matchTwoUnits = [matchedTwo.properties.origin, matchedTwo.properties.destination];
1932
+ const matchTwoUnits = matchedTwo ? [matchedTwo.properties.origin, matchedTwo.properties.destination] : [];
2111
1933
  const unitIds = _intersectionBy(matchOneUnits, matchTwoUnits, "id");
2112
1934
  return unitIds.map(({ id }) => findByIdSync(id));
2113
1935
  };
@@ -2134,7 +1956,7 @@ var createStepUtils = (options) => {
2134
1956
  const formatCategoryLabel = (category) => {
2135
1957
  return capitalize(category);
2136
1958
  };
2137
- const getToward = (from, to, intermediary) => {
1959
+ const getNextStepIntermediary = (from, to, intermediary) => {
2138
1960
  if (to.type === "end") return to.name;
2139
1961
  const intermediaryIds = intermediary.map((int) => int.id);
2140
1962
  const relationship = relationships.find((rel) => rel.properties.intermediary.map((int) => int.id).includes(to.source.id));
@@ -2145,32 +1967,11 @@ var createStepUtils = (options) => {
2145
1967
  const nextUnit = findByIdSync(nextUnitId);
2146
1968
  return { en: formatCategoryLabel(`${nextUnit.properties.category}`) };
2147
1969
  };
2148
- const toWaypoints = (path) => {
2149
- const [startPoint, middleAndEndPoints] = extractStartPoint(path, options);
2150
- const [endPoint, middlePoints] = extractEndPoint(middleAndEndPoints, options);
2151
- const waypoints = middlePoints.map((openingId) => {
2152
- const opening = findByIdSync(openingId);
2153
- const level = findByIdSync(opening.properties.level_id);
2154
- const coordinates = center6(opening).geometry.coordinates;
2155
- const landmark = landmarkUtils.findNearestLandmark(coordinates, opening.properties.level_id);
2156
- return {
2157
- id: `${opening.properties.level_id}:${openingId}`,
2158
- type: "between",
2159
- point: coordinates,
2160
- name: null,
2161
- levelId: opening.properties.level_id,
2162
- ordinal: level.properties.ordinal,
2163
- hint: landmark ? { kind: "landmark", name: landmark.name } : void 0,
2164
- source: { type: "opening", id: opening.id }
2165
- };
2166
- });
2167
- return [startPoint, ...waypoints, endPoint];
2168
- };
2169
1970
  const createHorizontalStep = (from, to) => {
2170
1971
  const intermediary = findHorizontalIntermediary(from, to);
2171
1972
  const intermediaryCategories = intermediary.map((unit) => unit.properties.category);
2172
1973
  const intermediaryCategory = intermediaryCategories.length > 0 ? intermediaryCategories[0] : "unspecified";
2173
- const toward = getToward(from, to, intermediary);
1974
+ const toward = getNextStepIntermediary(from, to, intermediary);
2174
1975
  const landmark = to.hint?.kind === "landmark" ? to.hint.name : null;
2175
1976
  const path = stepPathUtils.findStepPath(from.point, to.point, intermediary);
2176
1977
  const step = {
@@ -2227,8 +2028,6 @@ var createStepUtils = (options) => {
2227
2028
  return simplifySteps;
2228
2029
  };
2229
2030
  return {
2230
- // createSteps,
2231
- toWaypoints,
2232
2031
  toSteps
2233
2032
  };
2234
2033
  };
@@ -2249,6 +2048,11 @@ var calculateRoundedDistance = (distance5) => {
2249
2048
  return Math.round(distance5 - distance5 % 25);
2250
2049
  };
2251
2050
 
2051
+ // src/data/navigate/type-guard.ts
2052
+ function isCoordinateOrdinalString(id) {
2053
+ return /^-?\d+(\.\d+)?,-?\d+(\.\d+)?,-?\d+(\.\d+)?o$/.test(id);
2054
+ }
2055
+
2252
2056
  // src/data/navigate/utils/createFindByIdSync.ts
2253
2057
  var createFindByIdSync = (data) => {
2254
2058
  const { amenities = [], anchors = [], fixtures = [], levels = [], kiosks = [], relationships = [], occupants = [], openings = [], units } = data;
@@ -2271,6 +2075,207 @@ var createFindByIdSync = (data) => {
2271
2075
  return { findByIdSync };
2272
2076
  };
2273
2077
 
2078
+ // src/data/navigate/waypoint/createWaypointUtils.ts
2079
+ import { center as center6 } from "@turf/center";
2080
+
2081
+ // src/data/navigate/waypoint/extractEndWaypoint.ts
2082
+ import { center as center3 } from "@turf/center";
2083
+
2084
+ // src/data/navigate/waypoint/featureIdGuard.ts
2085
+ var isOccupant = (id) => !!id && id.startsWith("occupant-");
2086
+ var isUnit = (id) => !!id && id.startsWith("unit-");
2087
+ var isKiosk = (id) => !!id && id.startsWith("kiosk-");
2088
+ var isOpening = (id) => !!id && id.startsWith("opening-");
2089
+
2090
+ // src/data/navigate/waypoint/extractEndWaypoint.ts
2091
+ var extractEndPoint = (path, options) => {
2092
+ const { findByIdSync } = options;
2093
+ const [c, b, a] = path.slice(-3);
2094
+ if (isOccupant(a) && isUnit(b) && isOpening(c)) {
2095
+ const occ = findByIdSync(a);
2096
+ const opening = findByIdSync(c);
2097
+ const level = findByIdSync(opening.properties.level_id);
2098
+ return [
2099
+ {
2100
+ id: occ.id,
2101
+ type: "end",
2102
+ name: occ.properties.name,
2103
+ point: center3(opening).geometry.coordinates,
2104
+ levelId: opening.properties.level_id,
2105
+ ordinal: level.properties.ordinal,
2106
+ source: { type: "opening", id: opening.id }
2107
+ },
2108
+ path.slice(0, -3)
2109
+ ];
2110
+ }
2111
+ if (isOccupant(a) && isKiosk(b)) {
2112
+ const occ = findByIdSync(a);
2113
+ const kiosk = findByIdSync(b);
2114
+ const level = findByIdSync(kiosk.properties.level_id);
2115
+ return [
2116
+ {
2117
+ id: occ.id,
2118
+ type: "end",
2119
+ name: occ.properties.name,
2120
+ point: center3(kiosk).geometry.coordinates,
2121
+ levelId: kiosk.properties.level_id,
2122
+ ordinal: level.properties.ordinal,
2123
+ source: { type: "kiosk", id: kiosk.id }
2124
+ },
2125
+ path.slice(0, -2)
2126
+ ];
2127
+ }
2128
+ if (isCoordinateOrdinalString(a) && isOpening(b)) {
2129
+ const [lat, lng, ordinal] = parseOrdinalCoordinate(a);
2130
+ const opening = findByIdSync(b);
2131
+ return [
2132
+ {
2133
+ id: a,
2134
+ type: "end",
2135
+ name: { en: a },
2136
+ point: [lng, lat],
2137
+ levelId: opening.properties.level_id,
2138
+ ordinal,
2139
+ source: { type: "coordinate", raw: a }
2140
+ },
2141
+ path.slice(0, -1)
2142
+ ];
2143
+ }
2144
+ return [null, path];
2145
+ };
2146
+
2147
+ // src/data/navigate/waypoint/extractStartWaypoint.ts
2148
+ import { center as center4 } from "@turf/center";
2149
+ var extractStartPoint = (path, options) => {
2150
+ const { findByIdSync } = options;
2151
+ const [a, b, c] = path;
2152
+ if (isOccupant(a) && isUnit(b) && isOpening(c)) {
2153
+ const occ = findByIdSync(a);
2154
+ const opening = findByIdSync(c);
2155
+ const level = findByIdSync(opening.properties.level_id);
2156
+ return [
2157
+ {
2158
+ id: occ.id,
2159
+ type: "start",
2160
+ name: occ.properties.name,
2161
+ point: center4(opening).geometry.coordinates,
2162
+ levelId: opening.properties.level_id,
2163
+ ordinal: level.properties.ordinal,
2164
+ source: { type: "opening", id: opening.id }
2165
+ },
2166
+ path.slice(3)
2167
+ ];
2168
+ }
2169
+ if (isOccupant(a) && isKiosk(b)) {
2170
+ const occ = findByIdSync(a);
2171
+ const kiosk = findByIdSync(b);
2172
+ const level = findByIdSync(kiosk.properties.level_id);
2173
+ return [
2174
+ {
2175
+ id: occ.id,
2176
+ type: "start",
2177
+ name: occ.properties.name,
2178
+ point: center4(kiosk).geometry.coordinates,
2179
+ levelId: kiosk.properties.level_id,
2180
+ ordinal: level.properties.ordinal,
2181
+ source: { type: "kiosk", id: kiosk.id }
2182
+ },
2183
+ path.slice(2)
2184
+ ];
2185
+ }
2186
+ if (isCoordinateOrdinalString(a) && isOpening(b)) {
2187
+ const [lat, lng, ordinal] = parseOrdinalCoordinate(a);
2188
+ const opening = findByIdSync(b);
2189
+ return [
2190
+ {
2191
+ id: a,
2192
+ type: "start",
2193
+ name: { en: a },
2194
+ point: [lng, lat],
2195
+ levelId: opening.properties.level_id,
2196
+ ordinal,
2197
+ source: { type: "coordinate", raw: a }
2198
+ },
2199
+ path.slice(1)
2200
+ ];
2201
+ }
2202
+ return [null, path];
2203
+ };
2204
+
2205
+ // src/data/navigate/landmark/createLandmarkUtils.ts
2206
+ import { center as center5 } from "@turf/center";
2207
+ import distance4 from "@turf/distance";
2208
+ var NEARBY_DISTANCE = 30;
2209
+ var createLandmarkUtils = (options) => {
2210
+ const { data, findByIdSync } = options;
2211
+ const { occupants = [] } = data;
2212
+ const occupantToLandmark = (occupant) => {
2213
+ const locationType = occupant.properties.unit_id ? "unit" : "kiosk";
2214
+ const locationId = locationType === "unit" ? occupant.properties.unit_id : occupant.properties.kiosk_id;
2215
+ const location = locationType === "unit" ? findByIdSync(locationId) : findByIdSync(locationId);
2216
+ const level = findByIdSync(location.properties.level_id);
2217
+ return {
2218
+ name: occupant.properties.name,
2219
+ point: center5(location.geometry).geometry.coordinates,
2220
+ level_id: location.properties.level_id,
2221
+ is_priority: occupant.properties.is_landmark,
2222
+ ordinal: level.properties.ordinal
2223
+ };
2224
+ };
2225
+ const landmarks = [
2226
+ ...occupants.map(occupantToLandmark)
2227
+ ];
2228
+ const findNearbyLandmarks = (point2, levelId) => {
2229
+ if (point2 === null || levelId === null) return [];
2230
+ return landmarks.map((landmark) => {
2231
+ const landmarkAndDistance = {
2232
+ landmark,
2233
+ d: distance4(point2, landmark.point, { units: "meters" })
2234
+ };
2235
+ return landmarkAndDistance;
2236
+ }).filter(({ landmark, d }) => d <= NEARBY_DISTANCE && landmark.level_id === levelId).sort((a, b) => {
2237
+ const aPriority = a.landmark.is_priority ? 0 : 1;
2238
+ const bPriority = b.landmark.is_priority ? 0 : 1;
2239
+ if (aPriority !== bPriority) return aPriority - bPriority;
2240
+ return a.d - b.d;
2241
+ }).map(({ landmark }) => landmark);
2242
+ };
2243
+ const findNearestLandmark = (point2, levelId) => {
2244
+ const nearbyLandmarks = findNearbyLandmarks(point2, levelId);
2245
+ const nearestLandmark = nearbyLandmarks.length > 0 ? nearbyLandmarks[0] : null;
2246
+ return nearestLandmark;
2247
+ };
2248
+ return { findNearbyLandmarks, findNearestLandmark };
2249
+ };
2250
+
2251
+ // src/data/navigate/waypoint/createWaypointUtils.ts
2252
+ var createWaypointUtils = (options) => {
2253
+ const { findByIdSync } = options;
2254
+ const landmarkUtils = createLandmarkUtils(options);
2255
+ const toWaypoints = (path) => {
2256
+ const [startPoint, middleAndEndPoints] = extractStartPoint(path, options);
2257
+ const [endPoint, middlePoints] = extractEndPoint(middleAndEndPoints, options);
2258
+ const waypoints = middlePoints.map((openingId) => {
2259
+ const opening = findByIdSync(openingId);
2260
+ const level = findByIdSync(opening.properties.level_id);
2261
+ const coordinates = center6(opening).geometry.coordinates;
2262
+ const landmark = landmarkUtils.findNearestLandmark(coordinates, opening.properties.level_id);
2263
+ return {
2264
+ id: `${opening.properties.level_id}:${openingId}`,
2265
+ type: "between",
2266
+ point: coordinates,
2267
+ name: null,
2268
+ levelId: opening.properties.level_id,
2269
+ ordinal: level.properties.ordinal,
2270
+ hint: landmark ? { kind: "landmark", name: landmark.name } : void 0,
2271
+ source: { type: "opening", id: opening.id }
2272
+ };
2273
+ });
2274
+ return [startPoint, ...waypoints, endPoint];
2275
+ };
2276
+ return { toWaypoints };
2277
+ };
2278
+
2274
2279
  // src/data/navigate/getNavigateClient.ts
2275
2280
  var getNavigateClient = (options) => {
2276
2281
  const { data } = options;
@@ -2292,6 +2297,7 @@ var getNavigateClient = (options) => {
2292
2297
  return unit;
2293
2298
  };
2294
2299
  const stepUtils = createStepUtils({ ...options, findByIdSync });
2300
+ const waypointUtils = createWaypointUtils({ ...options, findByIdSync });
2295
2301
  const findRoute = async (routeOriginParam, routeDestinationParam, options2) => {
2296
2302
  if (!routeOriginParam || !routeDestinationParam) return null;
2297
2303
  const graph = options2?.mode === "accessible" ? accessibleGraph : defaultGraph;
@@ -2309,8 +2315,7 @@ var getNavigateClient = (options) => {
2309
2315
  const path = graph.path(routeOriginParam, routeDestinationParam);
2310
2316
  const t12 = performance.now();
2311
2317
  trace("nav", " \u251C\u2500 path (dijkstra)", t12 - t02);
2312
- const waypoints = stepUtils.toWaypoints(path);
2313
- console.log({ waypoints });
2318
+ const waypoints = waypointUtils.toWaypoints(path);
2314
2319
  const t22 = performance.now();
2315
2320
  trace("nav", " \u251C\u2500 toWaypoints", t22 - t12);
2316
2321
  trace("nav", " \u251C\u2500 toSteps", 0);
@@ -2322,9 +2327,6 @@ var getNavigateClient = (options) => {
2322
2327
  const t4 = performance.now();
2323
2328
  trace("nav", " \u2514\u2500 postProcess", t4 - t32);
2324
2329
  return {
2325
- // origin: routeOrigin,
2326
- // destination: routeDestination,
2327
- description: null,
2328
2330
  distance: roundedDistance,
2329
2331
  duration,
2330
2332
  steps
@@ -6561,6 +6563,7 @@ export {
6561
6563
  getLocationByFeature,
6562
6564
  getLocationByOccupant,
6563
6565
  getLocationIdByFeature,
6566
+ getNavigateClient,
6564
6567
  getOrdinalByLocationId,
6565
6568
  getRelatedLocationIdsByFeature,
6566
6569
  getRelatedLocationsByAmenity,