@opentripplanner/core-utils 4.11.6-alpha.1 → 5.0.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.
Files changed (70) hide show
  1. package/esm/deprecated-with-types.js +47 -0
  2. package/esm/deprecated-with-types.js.map +1 -0
  3. package/esm/index.js +0 -4
  4. package/esm/index.js.map +1 -1
  5. package/esm/itinerary.js +1 -1
  6. package/esm/itinerary.js.map +1 -1
  7. package/esm/map.js +4 -9
  8. package/esm/map.js.map +1 -1
  9. package/esm/route.js +5 -3
  10. package/esm/route.js.map +1 -1
  11. package/esm/storage.js +1 -0
  12. package/esm/storage.js.map +1 -1
  13. package/esm/time.js +6 -36
  14. package/esm/time.js.map +1 -1
  15. package/esm/ui.js +1 -1
  16. package/esm/ui.js.map +1 -1
  17. package/lib/deprecated-with-types.d.ts +23 -0
  18. package/lib/deprecated-with-types.d.ts.map +1 -0
  19. package/lib/deprecated-with-types.js +61 -0
  20. package/lib/deprecated-with-types.js.map +1 -0
  21. package/lib/index.d.ts +19 -0
  22. package/lib/index.d.ts.map +1 -0
  23. package/lib/index.js +0 -6
  24. package/lib/index.js.map +1 -1
  25. package/lib/itinerary.d.ts +113 -0
  26. package/lib/itinerary.d.ts.map +1 -0
  27. package/lib/itinerary.js +2 -1
  28. package/lib/itinerary.js.map +1 -1
  29. package/lib/map.d.ts +30 -0
  30. package/lib/map.d.ts.map +1 -0
  31. package/lib/map.js +3 -8
  32. package/lib/map.js.map +1 -1
  33. package/lib/route.d.ts +98 -0
  34. package/lib/route.d.ts.map +1 -0
  35. package/lib/route.js +5 -3
  36. package/lib/route.js.map +1 -1
  37. package/lib/storage.d.ts +19 -0
  38. package/lib/storage.d.ts.map +1 -0
  39. package/lib/storage.js +2 -0
  40. package/lib/storage.js.map +1 -1
  41. package/lib/time.d.ts +65 -0
  42. package/lib/time.d.ts.map +1 -0
  43. package/lib/time.js +22 -39
  44. package/lib/time.js.map +1 -1
  45. package/lib/ui.d.ts +13 -0
  46. package/lib/ui.d.ts.map +1 -0
  47. package/lib/ui.js +1 -1
  48. package/lib/ui.js.map +1 -1
  49. package/package.json +4 -1
  50. package/src/__tests__/__snapshots__/route.js.snap +30 -30
  51. package/src/deprecated-with-types.ts +62 -0
  52. package/src/{index.js → index.ts} +0 -4
  53. package/src/{itinerary.js → itinerary.ts} +70 -36
  54. package/src/{map.js → map.ts} +43 -31
  55. package/src/{route.js → route.ts} +52 -28
  56. package/src/{storage.js → storage.ts} +6 -5
  57. package/src/{time.js → time.ts} +28 -46
  58. package/src/{ui.js → ui.ts} +8 -8
  59. package/tsconfig.json +15 -0
  60. package/tsconfig.tsbuildinfo +4921 -0
  61. package/esm/messages.js +0 -25
  62. package/esm/messages.js.map +0 -1
  63. package/esm/types.js +0 -560
  64. package/esm/types.js.map +0 -1
  65. package/lib/messages.js +0 -29
  66. package/lib/messages.js.map +0 -1
  67. package/lib/types.js +0 -661
  68. package/lib/types.js.map +0 -1
  69. package/src/messages.js +0 -20
  70. package/src/types.js +0 -605
package/lib/time.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/time.js"],"names":["OTP_API_DATE_FORMAT","OTP_API_DATE_FORMAT_DATE_FNS","OTP_API_TIME_FORMAT","formatDurationLikeMoment","seconds","showSeconds","localize","enabled","code","hours","Math","floor","minutes","secondsLeftOver","specLookup","xHours","xMinutes","xSeconds","locale","formatDistance","spec","val","undefined","format","toHoursMinutesSeconds","getTimeFormat","config","dateTime","timeFormat","getDateFormat","dateFormat","getLongDateFormat","longDateFormat","formatDuration","formatDurationWithSeconds","region","offsetTime","ms","options","offset","formatTime","formatSecondsAfterMidnight","time","Date","getUserTimezone","fallbackTimezone","process","env","NODE_ENV","TZ","Intl","DateTimeFormat","resolvedOptions","timeZone","getCurrentTime","timezone","now","getCurrentDate"],"mappings":"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","sourcesContent":["import {\n startOfDay,\n add,\n format,\n formatDuration as dateFnsFormatDuration\n} from \"date-fns\";\nimport { utcToZonedTime } from \"date-fns-tz\";\n\n// special constants for making sure the following date format is always sent to\n// OTP regardless of whatever the user has configured as the display format\nexport const OTP_API_DATE_FORMAT = \"YYYY-MM-DD\";\n// Date-Fns uses a different string format than moment.js\n// see https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\nexport const OTP_API_DATE_FORMAT_DATE_FNS = \"yyyy-MM-dd\";\nexport const OTP_API_TIME_FORMAT = \"HH:mm\";\n\n/**\n * To ease the transition away from moment.js, this method uses date-fns to format durations\n * the way moment.js did.\n * @param {number} seconds The number of seconds to format\n * @param {boolean} showSeconds Whether to render seconds or not\n * @param {boolean} localize If true, will create output like moment.js using date-fns locale.\n * Otherwise, uses date-fns default\n * @returns Formatted duration\n */\nfunction formatDurationLikeMoment(\n seconds,\n showSeconds,\n localize = { enabled: true, code: \"en-US\" }\n) {\n // date-fns doesn't do this automatically\n if ((!showSeconds && seconds < 60) || seconds === 0) {\n return \"0 min\";\n }\n\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds - hours * 3600) / 60);\n const secondsLeftOver = showSeconds\n ? seconds - hours * 3600 - minutes * 60\n : 0;\n const specLookup = {\n xHours: \"hr\",\n xMinutes: \"min\",\n xSeconds: \"sec\"\n };\n const locale = localize\n ? {\n // Maintain backwards compatibility when called with localize=true\n code: localize?.code || \"en-US\",\n formatDistance: (spec, val) => {\n return `${val} ${specLookup[spec]}`;\n }\n }\n : undefined;\n\n return dateFnsFormatDuration(\n {\n hours,\n minutes,\n seconds: secondsLeftOver\n },\n {\n format: [\"hours\", \"minutes\", \"seconds\"],\n locale\n }\n );\n}\n\n/**\n * Breaks up a duration in seconds into hours, minutes, and seconds.\n * @param {number} seconds The number of seconds to break up\n * @returns an object with fields with the corresponding, hours, minutes, seconds.\n */\nexport function toHoursMinutesSeconds(seconds) {\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds - hours * 3600) / 60);\n return {\n hours,\n minutes,\n seconds: seconds - hours * 3600 - minutes * 60\n };\n}\n\n/**\n * @param {[type]} config the OTP config object found in store\n * @return {string} the config-defined time formatter or HH:mm (24-hr time)\n */\nexport function getTimeFormat(config) {\n return config?.dateTime?.timeFormat || OTP_API_TIME_FORMAT;\n}\n\nexport function getDateFormat(config) {\n return config?.dateTime?.dateFormat || OTP_API_DATE_FORMAT;\n}\n\nexport function getLongDateFormat(config) {\n return config?.dateTime?.longDateFormat || \"D MMMM YYYY\";\n}\n\n/**\n * Formats an elapsed time duration for display in narrative.\n * TODO: internationalization\n * @param {number} seconds duration in seconds\n * @returns {string} formatted text representation\n */\nexport function formatDuration(seconds) {\n return formatDurationLikeMoment(seconds, false);\n}\n\n/**\n * Formats an elapsed time in seconds, minutes, hours duration for display in narrative\n * @param {number} seconds duration in seconds\n * @param {object} region an object that allows internationalization of the time\n * @returns {string} formatted text representation\n */\nexport function formatDurationWithSeconds(seconds, region) {\n return formatDurationLikeMoment(seconds, { enabled: true, code: region });\n}\n\n/**\n * Offsets a time according to the provided time options\n * and returns the result.\n */\nexport function offsetTime(ms, options) {\n return ms + (options?.offset || 0);\n}\n\n/**\n * Formats a time value for display in narrative\n * TODO: internationalization/timezone\n * @param {number} ms epoch time value in milliseconds\n * @returns {string} formatted text representation\n */\nexport function formatTime(ms, options) {\n return format(\n offsetTime(ms, options),\n options?.format || OTP_API_TIME_FORMAT\n );\n}\n\n/**\n * Formats a seconds after midnight value for display in narrative\n * @param {number} seconds time since midnight in seconds\n * @param {string} timeFormat A valid date-fns time format\n * @return {string} formatted text representation\n */\nexport function formatSecondsAfterMidnight(seconds, timeFormat) {\n const time = add(startOfDay(new Date()), { seconds });\n return format(time, timeFormat);\n}\n\n/**\n * Uses Intl.DateTimeFormat() api to get the user's time zone. In a test\n * environment, pulls timezone information from an env variable. Default to\n * GMT+0 if the Intl API is unavailable.\n */\nexport function getUserTimezone(fallbackTimezone = \"Etc/Greenwich\") {\n if (process.env.NODE_ENV === \"test\") return process.env.TZ;\n return Intl?.DateTimeFormat().resolvedOptions().timeZone || fallbackTimezone;\n}\n\n/**\n * Formats current time for use in OTP query\n * The conversion to the user's timezone is needed for testing purposes.\n */\nexport function getCurrentTime(timezone = getUserTimezone()) {\n return format(utcToZonedTime(Date.now(), timezone), OTP_API_TIME_FORMAT);\n}\n\n/**\n * Formats current date for use in OTP query\n * The conversion to the user's timezone is needed for testing purposes.\n */\nexport function getCurrentDate(timezone = getUserTimezone()) {\n return format(\n utcToZonedTime(Date.now(), timezone),\n OTP_API_DATE_FORMAT_DATE_FNS\n );\n}\n"],"file":"time.js"}
1
+ {"version":3,"sources":["../src/time.ts"],"names":["OTP_API_DATE_FORMAT","OTP_API_DATE_FORMAT_DATE_FNS","OTP_API_TIME_FORMAT","formatDurationLikeMoment","seconds","showSeconds","localize","enabled","code","hours","Math","floor","minutes","secondsLeftOver","specLookup","xHours","xMinutes","xSeconds","locale","formatDistance","spec","val","undefined","format","toHoursMinutesSeconds","getTimeFormat","config","dateTime","timeFormat","getDateFormat","dateFormat","getLongDateFormat","longDateFormat","offsetTime","ms","options","offset","formatSecondsAfterMidnight","time","Date","getUserTimezone","fallbackTimezone","process","env","NODE_ENV","TZ","Intl","DateTimeFormat","resolvedOptions","timeZone","getCurrentTime","timezone","now","getCurrentDate"],"mappings":"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","sourcesContent":["import { Config } from \"@opentripplanner/types\";\nimport {\n startOfDay,\n add,\n format,\n formatDuration as dateFnsFormatDuration\n} from \"date-fns\";\nimport { utcToZonedTime } from \"date-fns-tz\";\n\n/* eslint-disable import/no-cycle */\nimport {\n formatTime,\n formatDurationWithSeconds,\n formatDuration\n} from \"./deprecated-with-types\";\n\nexport { formatTime, formatDuration, formatDurationWithSeconds };\n\n// special constants for making sure the following date format is always sent to\n// OTP regardless of whatever the user has configured as the display format\nexport const OTP_API_DATE_FORMAT = \"YYYY-MM-DD\";\n// Date-Fns uses a different string format than moment.js\n// see https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\nexport const OTP_API_DATE_FORMAT_DATE_FNS = \"yyyy-MM-dd\";\nexport const OTP_API_TIME_FORMAT = \"HH:mm\";\n\n/**\n * To ease the transition away from moment.js, this method uses date-fns to format durations\n * the way moment.js did.\n * @param {number} seconds The number of seconds to format\n * @param {boolean} showSeconds Whether to render seconds or not\n * @param {boolean} localize If true, will create output like moment.js using date-fns locale.\n * Otherwise, uses date-fns default\n * @returns Formatted duration\n */\nexport function formatDurationLikeMoment(\n seconds: number,\n showSeconds: boolean,\n localize: { enabled: boolean; code: string } = {\n enabled: true,\n code: \"en-US\"\n }\n): string {\n // date-fns doesn't do this automatically\n if ((!showSeconds && seconds < 60) || seconds === 0) {\n return \"0 min\";\n }\n\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds - hours * 3600) / 60);\n const secondsLeftOver = showSeconds\n ? seconds - hours * 3600 - minutes * 60\n : 0;\n const specLookup = {\n xHours: \"hr\",\n xMinutes: \"min\",\n xSeconds: \"sec\"\n };\n const locale = localize\n ? {\n // Maintain backwards compatibility when called with localize=true\n code: localize?.code || \"en-US\",\n formatDistance: (spec, val) => {\n return `${val} ${specLookup[spec]}`;\n }\n }\n : undefined;\n\n return dateFnsFormatDuration(\n {\n hours,\n minutes,\n seconds: secondsLeftOver\n },\n {\n format: [\"hours\", \"minutes\", \"seconds\"],\n locale\n }\n );\n}\n\n/**\n * Breaks up a duration in seconds into hours, minutes, and seconds.\n * @param {number} seconds The number of seconds to break up\n * @returns an object with fields with the corresponding, hours, minutes, seconds.\n */\nexport function toHoursMinutesSeconds(seconds) {\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds - hours * 3600) / 60);\n return {\n hours,\n minutes,\n seconds: seconds - hours * 3600 - minutes * 60\n };\n}\n\n/**\n * @param {[type]} config the OTP config object found in store\n * @return {string} the config-defined time formatter or HH:mm (24-hr time)\n */\nexport function getTimeFormat(config: Config): string {\n return config?.dateTime?.timeFormat || OTP_API_TIME_FORMAT;\n}\n\nexport function getDateFormat(config: Config): string {\n return config?.dateTime?.dateFormat || OTP_API_DATE_FORMAT;\n}\n\nexport function getLongDateFormat(config: Config): string {\n return config?.dateTime?.longDateFormat || \"D MMMM YYYY\";\n}\n/**\n * Offsets a time according to the provided time options\n * and returns the result.\n */\nexport function offsetTime(ms, options) {\n return ms + (options?.offset || 0);\n}\n\n/**\n * Formats a seconds after midnight value for display in narrative\n * @param {number} seconds time since midnight in seconds\n * @param {string} timeFormat A valid date-fns time format\n * @return {string} formatted text representation\n */\nexport function formatSecondsAfterMidnight(\n seconds: number,\n timeFormat: string\n): string {\n const time = add(startOfDay(new Date()), { seconds });\n return format(time, timeFormat);\n}\n\n/**\n * Uses Intl.DateTimeFormat() api to get the user's time zone. In a test\n * environment, pulls timezone information from an env variable. Default to\n * GMT+0 if the Intl API is unavailable.\n */\nexport function getUserTimezone(fallbackTimezone = \"Etc/Greenwich\"): string {\n if (process.env.NODE_ENV === \"test\") return process.env.TZ;\n return Intl?.DateTimeFormat().resolvedOptions().timeZone || fallbackTimezone;\n}\n\n/**\n * Formats current time for use in OTP query\n * The conversion to the user's timezone is needed for testing purposes.\n */\nexport function getCurrentTime(timezone = getUserTimezone()): string {\n return format(utcToZonedTime(Date.now(), timezone), OTP_API_TIME_FORMAT);\n}\n\n/**\n * Formats current date for use in OTP query\n * The conversion to the user's timezone is needed for testing purposes.\n */\nexport function getCurrentDate(timezone = getUserTimezone()): string {\n return format(\n utcToZonedTime(Date.now(), timezone),\n OTP_API_DATE_FORMAT_DATE_FNS\n );\n}\n"],"file":"time.js"}
package/lib/ui.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export declare function isMobile(): boolean;
2
+ /**
3
+ * Returns true if the user is using a [redacted] browser
4
+ */
5
+ export declare function isIE(): boolean;
6
+ /**
7
+ * Enables scrolling for a specified selector, while disabling scrolling for all
8
+ * other targets. This is adapted from https://stackoverflow.com/a/41601290/915811
9
+ * and intended to fix issues with iOS elastic scrolling, e.g.,
10
+ * https://github.com/conveyal/trimet-mod-otp/issues/92.
11
+ */
12
+ export declare function enableScrollForSelector(selector: string): void;
13
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,IAAI,OAAO,CAKlC;AAED;;GAEG;AACH,wBAAgB,IAAI,IAAI,OAAO,CAE9B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CA4C9D"}
package/lib/ui.js CHANGED
@@ -21,7 +21,7 @@ function isMobile() {
21
21
 
22
22
 
23
23
  function isIE() {
24
- return _bowser.default.name === "Internet Explorer";
24
+ return _bowser.default.parse(navigator.userAgent).browser === "Internet Explorer";
25
25
  }
26
26
  /**
27
27
  * Enables scrolling for a specified selector, while disabling scrolling for all
package/lib/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ui.js"],"names":["isMobile","test","navigator","userAgent","isIE","bowser","name","enableScrollForSelector","selector","overlay","document","querySelector","clientY","isOverlayTotallyScrolled","scrollHeight","scrollTop","clientHeight","disableRubberBand","event","clientYDelta","targetTouches","preventDefault","addEventListener","length"],"mappings":";;;;;;;;;;;AAAA;;AAEO,SAASA,QAAT,GAAoB;AACzB;AACA,SAAO,iEAAiEC,IAAjE,CACLC,SAAS,CAACC,SADL,CAAP;AAGD;AAED;AACA;AACA;;;AACO,SAASC,IAAT,GAAgB;AACrB,SAAOC,gBAAOC,IAAP,KAAgB,mBAAvB;AACD;AAED;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASC,uBAAT,CAAiCC,QAAjC,EAA2C;AAChD,QAAMC,OAAO,GAAGC,QAAQ,CAACC,aAAT,CAAuBH,QAAvB,CAAhB;AACA,MAAII,OAAO,GAAG,IAAd,CAFgD,CAE5B;;AAEpB,WAASC,wBAAT,GAAoC;AAClC;AACA,WAAOJ,OAAO,CAACK,YAAR,GAAuBL,OAAO,CAACM,SAA/B,IAA4CN,OAAO,CAACO,YAA3D;AACD;;AAED,WAASC,iBAAT,CAA2BC,KAA3B,EAAkC;AAChC,UAAMC,YAAY,GAAGD,KAAK,CAACE,aAAN,CAAoB,CAApB,EAAuBR,OAAvB,GAAiCA,OAAtD;;AAEA,QAAIH,OAAO,CAACM,SAAR,KAAsB,CAAtB,IAA2BI,YAAY,GAAG,CAA9C,EAAiD;AAC/C;AACAD,MAAAA,KAAK,CAACG,cAAN;AACD;;AAED,QAAIR,wBAAwB,MAAMM,YAAY,GAAG,CAAjD,EAAoD;AAClD;AACAD,MAAAA,KAAK,CAACG,cAAN;AACD;AACF;;AAEDZ,EAAAA,OAAO,CAACa,gBAAR,CACE,YADF,EAEE,UAASJ,KAAT,EAAgB;AACd,QAAIA,KAAK,CAACE,aAAN,CAAoBG,MAApB,KAA+B,CAAnC,EAAsC;AACpC;AACAX,MAAAA,OAAO,GAAGM,KAAK,CAACE,aAAN,CAAoB,CAApB,EAAuBR,OAAjC;AACD;AACF,GAPH,EAQE,KARF;AAWAH,EAAAA,OAAO,CAACa,gBAAR,CACE,WADF,EAEE,UAASJ,KAAT,EAAgB;AACd,QAAIA,KAAK,CAACE,aAAN,CAAoBG,MAApB,KAA+B,CAAnC,EAAsC;AACpC;AACAN,MAAAA,iBAAiB,CAACC,KAAD,CAAjB;AACD;AACF,GAPH,EAQE,KARF;AAUD","sourcesContent":["import bowser from \"bowser\";\n\nexport function isMobile() {\n // TODO: consider using 3rd-party library?\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent\n );\n}\n\n/**\n * Returns true if the user is using a [redacted] browser\n */\nexport function isIE() {\n return bowser.name === \"Internet Explorer\";\n}\n\n/**\n * Enables scrolling for a specified selector, while disabling scrolling for all\n * other targets. This is adapted from https://stackoverflow.com/a/41601290/915811\n * and intended to fix issues with iOS elastic scrolling, e.g.,\n * https://github.com/conveyal/trimet-mod-otp/issues/92.\n */\nexport function enableScrollForSelector(selector) {\n const overlay = document.querySelector(selector);\n let clientY = null; // remember Y position on touch start\n\n function isOverlayTotallyScrolled() {\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\n return overlay.scrollHeight - overlay.scrollTop <= overlay.clientHeight;\n }\n\n function disableRubberBand(event) {\n const clientYDelta = event.targetTouches[0].clientY - clientY;\n\n if (overlay.scrollTop === 0 && clientYDelta > 0) {\n // element is at the top of its scroll\n event.preventDefault();\n }\n\n if (isOverlayTotallyScrolled() && clientYDelta < 0) {\n // element is at the top of its scroll\n event.preventDefault();\n }\n }\n\n overlay.addEventListener(\n \"touchstart\",\n function(event) {\n if (event.targetTouches.length === 1) {\n // detect single touch\n clientY = event.targetTouches[0].clientY;\n }\n },\n false\n );\n\n overlay.addEventListener(\n \"touchmove\",\n function(event) {\n if (event.targetTouches.length === 1) {\n // detect single touch\n disableRubberBand(event);\n }\n },\n false\n );\n}\n"],"file":"ui.js"}
1
+ {"version":3,"sources":["../src/ui.ts"],"names":["isMobile","test","navigator","userAgent","isIE","bowser","parse","browser","enableScrollForSelector","selector","overlay","document","querySelector","clientY","isOverlayTotallyScrolled","scrollHeight","scrollTop","clientHeight","disableRubberBand","event","clientYDelta","targetTouches","preventDefault","addEventListener","length"],"mappings":";;;;;;;;;;;AAAA;;AAEO,SAASA,QAAT,GAA6B;AAClC;AACA,SAAO,iEAAiEC,IAAjE,CACLC,SAAS,CAACC,SADL,CAAP;AAGD;AAED;AACA;AACA;;;AACO,SAASC,IAAT,GAAyB;AAC9B,SAAOC,gBAAOC,KAAP,CAAaJ,SAAS,CAACC,SAAvB,EAAkCI,OAAlC,KAA8C,mBAArD;AACD;AAED;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASC,uBAAT,CAAiCC,QAAjC,EAAyD;AAC9D,QAAMC,OAAO,GAAGC,QAAQ,CAACC,aAAT,CAAuBH,QAAvB,CAAhB;AACA,MAAII,OAAO,GAAG,IAAd,CAF8D,CAE1C;;AAEpB,WAASC,wBAAT,GAA6C;AAC3C;AACA,WAAOJ,OAAO,CAACK,YAAR,GAAuBL,OAAO,CAACM,SAA/B,IAA4CN,OAAO,CAACO,YAA3D;AACD;;AAED,WAASC,iBAAT,CAA2BC,KAA3B,EAA8C;AAC5C,UAAMC,YAAY,GAAGD,KAAK,CAACE,aAAN,CAAoB,CAApB,EAAuBR,OAAvB,GAAiCA,OAAtD;;AAEA,QAAIH,OAAO,CAACM,SAAR,KAAsB,CAAtB,IAA2BI,YAAY,GAAG,CAA9C,EAAiD;AAC/C;AACAD,MAAAA,KAAK,CAACG,cAAN;AACD;;AAED,QAAIR,wBAAwB,MAAMM,YAAY,GAAG,CAAjD,EAAoD;AAClD;AACAD,MAAAA,KAAK,CAACG,cAAN;AACD;AACF;;AAEDZ,EAAAA,OAAO,CAACa,gBAAR,CACE,YADF,EAEE,UAASJ,KAAT,EAA4B;AAC1B,QAAIA,KAAK,CAACE,aAAN,CAAoBG,MAApB,KAA+B,CAAnC,EAAsC;AACpC;AACAX,MAAAA,OAAO,GAAGM,KAAK,CAACE,aAAN,CAAoB,CAApB,EAAuBR,OAAjC;AACD;AACF,GAPH,EAQE,KARF;AAWAH,EAAAA,OAAO,CAACa,gBAAR,CACE,WADF,EAEE,UAASJ,KAAT,EAA4B;AAC1B,QAAIA,KAAK,CAACE,aAAN,CAAoBG,MAApB,KAA+B,CAAnC,EAAsC;AACpC;AACAN,MAAAA,iBAAiB,CAACC,KAAD,CAAjB;AACD;AACF,GAPH,EAQE,KARF;AAUD","sourcesContent":["import bowser from \"bowser\";\n\nexport function isMobile(): boolean {\n // TODO: consider using 3rd-party library?\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent\n );\n}\n\n/**\n * Returns true if the user is using a [redacted] browser\n */\nexport function isIE(): boolean {\n return bowser.parse(navigator.userAgent).browser === \"Internet Explorer\";\n}\n\n/**\n * Enables scrolling for a specified selector, while disabling scrolling for all\n * other targets. This is adapted from https://stackoverflow.com/a/41601290/915811\n * and intended to fix issues with iOS elastic scrolling, e.g.,\n * https://github.com/conveyal/trimet-mod-otp/issues/92.\n */\nexport function enableScrollForSelector(selector: string): void {\n const overlay = document.querySelector(selector);\n let clientY = null; // remember Y position on touch start\n\n function isOverlayTotallyScrolled(): boolean {\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\n return overlay.scrollHeight - overlay.scrollTop <= overlay.clientHeight;\n }\n\n function disableRubberBand(event: TouchEvent) {\n const clientYDelta = event.targetTouches[0].clientY - clientY;\n\n if (overlay.scrollTop === 0 && clientYDelta > 0) {\n // element is at the top of its scroll\n event.preventDefault();\n }\n\n if (isOverlayTotallyScrolled() && clientYDelta < 0) {\n // element is at the top of its scroll\n event.preventDefault();\n }\n }\n\n overlay.addEventListener(\n \"touchstart\",\n function(event: TouchEvent) {\n if (event.targetTouches.length === 1) {\n // detect single touch\n clientY = event.targetTouches[0].clientY;\n }\n },\n false\n );\n\n overlay.addEventListener(\n \"touchmove\",\n function(event: TouchEvent) {\n if (event.targetTouches.length === 1) {\n // detect single touch\n disableRubberBand(event);\n }\n },\n false\n );\n}\n"],"file":"ui.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentripplanner/core-utils",
3
- "version": "4.11.6-alpha.1",
3
+ "version": "5.0.0",
4
4
  "description": "Core functionality that is shared among numerous UI components",
5
5
  "engines": {
6
6
  "node": ">=13"
@@ -26,5 +26,8 @@
26
26
  "qs": "^6.9.1"
27
27
  },
28
28
  "gitHead": "0af1b7cda60bd4252b219dcf893e01c2acb2ed5d",
29
+ "scripts": {
30
+ "tsc": "tsc"
31
+ },
29
32
  "devDependencies": {}
30
33
  }
@@ -35,18 +35,18 @@ Array [
35
35
 
36
36
  exports[`util > route routeComparator should prioritize routes with valid sortOrder 1`] = `
37
37
  Array [
38
- Object {
39
- "longName": "Around town",
40
- "mode": "BUS",
41
- "shortName": "20",
42
- "sortOrder": 2,
43
- },
44
38
  Object {
45
39
  "longName": "Around another town",
46
40
  "shortName": "3",
47
41
  "sortOrder": -999,
48
42
  "type": 3,
49
43
  },
44
+ Object {
45
+ "longName": "Around town",
46
+ "mode": "BUS",
47
+ "shortName": "20",
48
+ "sortOrder": 2,
49
+ },
50
50
  ]
51
51
  `;
52
52
 
@@ -191,6 +191,30 @@ Array [
191
191
  "shortName": "IC",
192
192
  "sortOrder": 2,
193
193
  },
194
+ Object {
195
+ "longName": "A-line",
196
+ "mode": "BUS",
197
+ "shortName": "A",
198
+ "sortOrder": -999,
199
+ },
200
+ Object {
201
+ "longName": "B-line",
202
+ "mode": "BUS",
203
+ "shortName": "B",
204
+ "sortOrder": -999,
205
+ },
206
+ Object {
207
+ "longName": "Loop route",
208
+ "mode": "BUS",
209
+ "shortName": "2",
210
+ "sortOrder": -999,
211
+ },
212
+ Object {
213
+ "longName": "Around another town",
214
+ "shortName": "3",
215
+ "sortOrder": -999,
216
+ "type": 3,
217
+ },
194
218
  Object {
195
219
  "longName": "Local route",
196
220
  "mode": "BUS",
@@ -239,30 +263,6 @@ Array [
239
263
  "shortName": "10",
240
264
  "sortOrder": 10,
241
265
  },
242
- Object {
243
- "longName": "A-line",
244
- "mode": "BUS",
245
- "shortName": "A",
246
- "sortOrder": -999,
247
- },
248
- Object {
249
- "longName": "B-line",
250
- "mode": "BUS",
251
- "shortName": "B",
252
- "sortOrder": -999,
253
- },
254
- Object {
255
- "longName": "Loop route",
256
- "mode": "BUS",
257
- "shortName": "2",
258
- "sortOrder": -999,
259
- },
260
- Object {
261
- "longName": "Around another town",
262
- "shortName": "3",
263
- "sortOrder": -999,
264
- "type": 3,
265
- },
266
266
  Object {
267
267
  "longName": "A meandering route",
268
268
  "mode": "BUS",
@@ -0,0 +1,62 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import { TimeOptions } from "@opentripplanner/types";
3
+ import { format } from "date-fns";
4
+
5
+ import { logDeprecationWarning } from "./deprecated";
6
+ import {
7
+ formatDurationLikeMoment,
8
+ offsetTime,
9
+ OTP_API_TIME_FORMAT
10
+ } from "./time";
11
+
12
+ // time.ts
13
+
14
+ /**
15
+ * Formats a time value for display in narrative
16
+ * TODO: internationalization/timezone
17
+ * @param {number} ms epoch time value in milliseconds
18
+ * @returns {string} formatted text representation
19
+ */
20
+ export function formatTime(ms: number, options: TimeOptions): string {
21
+ logDeprecationWarning("formatTime", "formatjs");
22
+
23
+ return format(
24
+ offsetTime(ms, options),
25
+ options?.format || OTP_API_TIME_FORMAT
26
+ );
27
+ }
28
+
29
+ /**
30
+ * Formats an elapsed time duration for display in narrative.
31
+ * TODO: internationalization
32
+ * @param {number} seconds duration in seconds
33
+ * @returns {string} formatted text representation
34
+ */
35
+ // TS TODO: region as type?
36
+ export function formatDuration(seconds: number, region: string): string {
37
+ logDeprecationWarning("formatDuration", "formatjs");
38
+
39
+ return formatDurationLikeMoment(seconds, false, {
40
+ enabled: true,
41
+ code: region
42
+ });
43
+ }
44
+
45
+ /**
46
+ * Formats an elapsed time in seconds, minutes, hours duration for display in narrative
47
+ * @param {number} seconds duration in seconds
48
+ * @param {object} region an object that allows internationalization of the time
49
+ * @returns {string} formatted text representation
50
+ */
51
+ // TS TODO: region as type?
52
+ export function formatDurationWithSeconds(
53
+ seconds: number,
54
+ region: string
55
+ ): string {
56
+ logDeprecationWarning("formatDurationWithSeconds", "formatjs");
57
+
58
+ return formatDurationLikeMoment(seconds, true, {
59
+ enabled: true,
60
+ code: region
61
+ });
62
+ }
@@ -1,26 +1,22 @@
1
1
  import * as itinerary from "./itinerary";
2
2
  import * as map from "./map";
3
- import * as messages from "./messages";
4
3
  import * as profile from "./profile";
5
4
  import * as query from "./query";
6
5
  import * as queryParams from "./query-params";
7
6
  import * as route from "./route";
8
7
  import * as storage from "./storage";
9
8
  import * as time from "./time";
10
- import * as types from "./types";
11
9
  import * as ui from "./ui";
12
10
 
13
11
  const core = {
14
12
  itinerary,
15
13
  map,
16
- messages,
17
14
  profile,
18
15
  query,
19
16
  queryParams,
20
17
  route,
21
18
  storage,
22
19
  time,
23
- types,
24
20
  ui
25
21
  };
26
22
 
@@ -1,4 +1,14 @@
1
1
  import polyline from "@mapbox/polyline";
2
+ import {
3
+ Company,
4
+ Config,
5
+ ElevationProfile,
6
+ FlexBookingInfo,
7
+ Itinerary,
8
+ LatLngArray,
9
+ Leg,
10
+ Step
11
+ } from "@opentripplanner/types";
2
12
  import turfAlong from "@turf/along";
3
13
 
4
14
  import {
@@ -40,13 +50,16 @@ export const transitModes = [
40
50
  * @return {Array} List of all transit modes defined in config; otherwise default mode list
41
51
  */
42
52
 
43
- export function getTransitModes(config) {
53
+ export function getTransitModes(config: Config): string[] {
44
54
  if (!config || !config.modes || !config.modes.transitModes)
45
55
  return transitModes;
46
- return config.modes.transitModes.map(tm => tm.mode);
56
+
57
+ return config.modes.transitModes.map(tm =>
58
+ typeof tm !== "string" ? tm.mode : tm
59
+ );
47
60
  }
48
61
 
49
- export function isTransit(mode) {
62
+ export function isTransit(mode: string): boolean {
50
63
  return transitModes.includes(mode) || mode === "TRANSIT";
51
64
  }
52
65
 
@@ -55,7 +68,7 @@ export function isTransit(mode) {
55
68
  * calling ahead for the service to run. "mustPhone" is the only
56
69
  * property of boardRule which encodes this info.
57
70
  */
58
- export function isReservationRequired(leg) {
71
+ export function isReservationRequired(leg: Leg): boolean {
59
72
  return leg.boardRule === "mustPhone";
60
73
  }
61
74
  /**
@@ -63,53 +76,53 @@ export function isReservationRequired(leg) {
63
76
  * asking the driver to let the user off. "coordinateWithDriver" is the only
64
77
  * property of alightRule which encodes this info.
65
78
  */
66
- export function isContinuousDropoff(leg) {
79
+ export function isContinuousDropoff(leg: Leg): boolean {
67
80
  return leg.alightRule === "coordinateWithDriver";
68
81
  }
69
82
  /**
70
83
  * The two rules checked by the above two functions are the only values
71
84
  * returned by OTP when a leg is a flex leg.
72
85
  */
73
- export function isFlex(leg) {
86
+ export function isFlex(leg: Leg): boolean {
74
87
  return isReservationRequired(leg) || isContinuousDropoff(leg);
75
88
  }
76
89
 
77
- export function isAdvanceBookingRequired(info) {
90
+ export function isAdvanceBookingRequired(info: FlexBookingInfo): boolean {
78
91
  return info?.latestBookingTime?.daysPrior > 0;
79
92
  }
80
- export function legDropoffRequiresAdvanceBooking(leg) {
93
+ export function legDropoffRequiresAdvanceBooking(leg: Leg): boolean {
81
94
  return isAdvanceBookingRequired(leg.dropOffBookingInfo);
82
95
  }
83
96
 
84
- export function isWalk(mode) {
97
+ export function isWalk(mode: string): boolean {
85
98
  if (!mode) return false;
86
99
 
87
100
  return mode === "WALK";
88
101
  }
89
102
 
90
- export function isBicycle(mode) {
103
+ export function isBicycle(mode: string): boolean {
91
104
  if (!mode) return false;
92
105
 
93
106
  return mode === "BICYCLE";
94
107
  }
95
108
 
96
- export function isBicycleRent(mode) {
109
+ export function isBicycleRent(mode: string): boolean {
97
110
  if (!mode) return false;
98
111
 
99
112
  return mode === "BICYCLE_RENT";
100
113
  }
101
114
 
102
- export function isCar(mode) {
115
+ export function isCar(mode: string): boolean {
103
116
  if (!mode) return false;
104
117
  return mode.startsWith("CAR");
105
118
  }
106
119
 
107
- export function isMicromobility(mode) {
120
+ export function isMicromobility(mode: string): boolean {
108
121
  if (!mode) return false;
109
122
  return mode.startsWith("MICROMOBILITY") || mode.startsWith("SCOOTER");
110
123
  }
111
124
 
112
- export function isAccessMode(mode) {
125
+ export function isAccessMode(mode: string): boolean {
113
126
  return (
114
127
  isWalk(mode) ||
115
128
  isBicycle(mode) ||
@@ -123,7 +136,7 @@ export function isAccessMode(mode) {
123
136
  * @param {string} modesStr a comma-separated list of OTP modes
124
137
  * @return {boolean} whether any of the modes are transit modes
125
138
  */
126
- export function hasTransit(modesStr) {
139
+ export function hasTransit(modesStr: string): boolean {
127
140
  return modesStr.split(",").some(mode => isTransit(mode));
128
141
  }
129
142
 
@@ -131,7 +144,7 @@ export function hasTransit(modesStr) {
131
144
  * @param {string} modesStr a comma-separated list of OTP modes
132
145
  * @return {boolean} whether any of the modes are car-based modes
133
146
  */
134
- export function hasCar(modesStr) {
147
+ export function hasCar(modesStr: string): boolean {
135
148
  return modesStr.split(",").some(mode => isCar(mode));
136
149
  }
137
150
 
@@ -139,7 +152,7 @@ export function hasCar(modesStr) {
139
152
  * @param {string} modesStr a comma-separated list of OTP modes
140
153
  * @return {boolean} whether any of the modes are bicycle-based modes
141
154
  */
142
- export function hasBike(modesStr) {
155
+ export function hasBike(modesStr: string): boolean {
143
156
  return modesStr
144
157
  .split(",")
145
158
  .some(mode => isBicycle(mode) || isBicycleRent(mode));
@@ -149,7 +162,7 @@ export function hasBike(modesStr) {
149
162
  * @param {string} modesStr a comma-separated list of OTP modes
150
163
  * @return {boolean} whether any of the modes are micromobility-based modes
151
164
  */
152
- export function hasMicromobility(modesStr) {
165
+ export function hasMicromobility(modesStr: string): boolean {
153
166
  return modesStr.split(",").some(mode => isMicromobility(mode));
154
167
  }
155
168
 
@@ -157,7 +170,7 @@ export function hasMicromobility(modesStr) {
157
170
  * @param {string} modesStr a comma-separated list of OTP modes
158
171
  * @return {boolean} whether any of the modes is a hailing mode
159
172
  */
160
- export function hasHail(modesStr) {
173
+ export function hasHail(modesStr: string): boolean {
161
174
  return modesStr.split(",").some(mode => mode.indexOf("_HAIL") > -1);
162
175
  }
163
176
 
@@ -165,11 +178,11 @@ export function hasHail(modesStr) {
165
178
  * @param {string} modesStr a comma-separated list of OTP modes
166
179
  * @return {boolean} whether any of the modes is a rental mode
167
180
  */
168
- export function hasRental(modesStr) {
181
+ export function hasRental(modesStr: string): boolean {
169
182
  return modesStr.split(",").some(mode => mode.indexOf("_RENT") > -1);
170
183
  }
171
184
 
172
- export function getMapColor(mode) {
185
+ export function getMapColor(mode: string): string {
173
186
  mode = mode || this.get("mode");
174
187
  if (mode === "WALK") return "#444";
175
188
  if (mode === "BICYCLE") return "#0073e5";
@@ -183,7 +196,7 @@ export function getMapColor(mode) {
183
196
  return "#aaa";
184
197
  }
185
198
 
186
- export function toSentenceCase(str) {
199
+ export function toSentenceCase(str: string): string {
187
200
  if (str == null) {
188
201
  return "";
189
202
  }
@@ -194,7 +207,7 @@ export function toSentenceCase(str) {
194
207
  /**
195
208
  * Derive the company string based on mode and network associated with leg.
196
209
  */
197
- export function getCompanyFromLeg(leg) {
210
+ export function getCompanyFromLeg(leg: Leg): string {
198
211
  if (!leg) return null;
199
212
  const { from, mode, rentedBike, rentedCar, rentedVehicle, tncData } = leg;
200
213
  if (mode === "CAR" && rentedCar) {
@@ -216,12 +229,12 @@ export function getCompanyFromLeg(leg) {
216
229
  return null;
217
230
  }
218
231
 
219
- export function getItineraryBounds(itinerary) {
232
+ export function getItineraryBounds(itinerary: Itinerary): LatLngArray[] {
220
233
  let coords = [];
221
234
  itinerary.legs.forEach(leg => {
222
235
  const legCoords = polyline
223
236
  .toGeoJSON(leg.legGeometry.points)
224
- .coordinates.map(c => [c[1], c[0]]);
237
+ .coordinates.map((c: number[]) => [c[1], c[0]]);
225
238
  coords = [...coords, ...legCoords];
226
239
  });
227
240
  return coords;
@@ -230,7 +243,7 @@ export function getItineraryBounds(itinerary) {
230
243
  /**
231
244
  * Return a coords object that encloses the given leg's geometry.
232
245
  */
233
- export function getLegBounds(leg) {
246
+ export function getLegBounds(leg: Leg): number[] {
234
247
  const coords = polyline
235
248
  .toGeoJSON(leg.legGeometry.points)
236
249
  .coordinates.map(c => [c[1], c[0]]);
@@ -246,7 +259,7 @@ export function getLegBounds(leg) {
246
259
 
247
260
  /* Returns an interpolated lat-lon at a specified distance along a leg */
248
261
 
249
- export function legLocationAtDistance(leg, distance) {
262
+ export function legLocationAtDistance(leg: Leg, distance: number): number[] {
250
263
  if (!leg.legGeometry) return null;
251
264
 
252
265
  try {
@@ -264,7 +277,10 @@ export function legLocationAtDistance(leg, distance) {
264
277
 
265
278
  /* Returns an interpolated elevation at a specified distance along a leg */
266
279
 
267
- export function legElevationAtDistance(points, distance) {
280
+ export function legElevationAtDistance(
281
+ points: number[][],
282
+ distance: number
283
+ ): number {
268
284
  // Iterate through the combined elevation profile
269
285
  let traversed = 0;
270
286
  // If first point distance is not zero, insert starting point at zero with
@@ -302,7 +318,10 @@ export function legElevationAtDistance(points, distance) {
302
318
 
303
319
  // Iterate through the steps, building the array of elevation points and
304
320
  // keeping track of the minimum and maximum elevations reached
305
- export function getElevationProfile(steps, unitConversion = 1) {
321
+ export function getElevationProfile(
322
+ steps: Step[],
323
+ unitConversion = 1
324
+ ): ElevationProfile {
306
325
  let minElev = 100000;
307
326
  let maxElev = -100000;
308
327
  let traversed = 0;
@@ -349,11 +368,14 @@ export function getElevationProfile(steps, unitConversion = 1) {
349
368
  *
350
369
  * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
351
370
  */
352
- export function getTextWidth(text, font = "22px Arial") {
371
+ export function getTextWidth(text: string, font = "22px Arial"): number {
372
+ // Create custom type for function including re-used canvas object
373
+ type GetTextWidth = typeof getTextWidth & { canvas: HTMLCanvasElement };
374
+
353
375
  // re-use canvas object for better performance
354
376
  const canvas =
355
- getTextWidth.canvas ||
356
- (getTextWidth.canvas = document.createElement("canvas"));
377
+ (getTextWidth as GetTextWidth).canvas ||
378
+ ((getTextWidth as GetTextWidth).canvas = document.createElement("canvas"));
357
379
  const context = canvas.getContext("2d");
358
380
  context.font = font;
359
381
  const metrics = context.measureText(text);
@@ -364,7 +386,10 @@ export function getTextWidth(text, font = "22px Arial") {
364
386
  * Get the configured company object for the given network string if the company
365
387
  * has been defined in the provided companies array config.
366
388
  */
367
- export function getCompanyForNetwork(networkString, companies = []) {
389
+ export function getCompanyForNetwork(
390
+ networkString: string,
391
+ companies: Company[] = []
392
+ ): Company {
368
393
  const company = companies.find(co => co.id === networkString);
369
394
  if (!company) {
370
395
  console.warn(
@@ -382,7 +407,10 @@ export function getCompanyForNetwork(networkString, companies = []) {
382
407
  * @param {Array<object>} [companies=[]] An optional list of the companies config.
383
408
  * @return {string} A label for use in presentation on a website.
384
409
  */
385
- export function getCompaniesLabelFromNetworks(networks, companies = []) {
410
+ export function getCompaniesLabelFromNetworks(
411
+ networks: string[],
412
+ companies: Company[] = []
413
+ ): string {
386
414
  return networks
387
415
  .map(network => getCompanyForNetwork(network, companies))
388
416
  .filter(co => !!co)
@@ -390,12 +418,18 @@ export function getCompaniesLabelFromNetworks(networks, companies = []) {
390
418
  .join("/");
391
419
  }
392
420
 
393
- export function getTNCLocation(leg, type) {
421
+ export function getTNCLocation(leg: Leg, type: string): string {
394
422
  const location = leg[type];
395
423
  return `${location.lat.toFixed(5)},${location.lon.toFixed(5)}`;
396
424
  }
397
425
 
398
- export function calculatePhysicalActivity(itinerary) {
426
+ export function calculatePhysicalActivity(
427
+ itinerary: Itinerary
428
+ ): {
429
+ bikeDuration: number;
430
+ caloriesBurned: number;
431
+ walkDuration: number;
432
+ } {
399
433
  let walkDuration = 0;
400
434
  let bikeDuration = 0;
401
435
  itinerary.legs.forEach(leg => {