@geops/rvf-mobility-web-component 0.1.8

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 (212) hide show
  1. package/.fixpackrc +21 -0
  2. package/.husky/commit-msg +1 -0
  3. package/.husky/post-checkout +1 -0
  4. package/.husky/post-merge +1 -0
  5. package/.husky/post-rebase +1 -0
  6. package/.husky/pre-commit +1 -0
  7. package/.lintstagedrc.js +12 -0
  8. package/.nvmrc +1 -0
  9. package/.prettierrc.js +1 -0
  10. package/CHANGELOG.md +183 -0
  11. package/Logo.svg +10 -0
  12. package/README.md +179 -0
  13. package/__mocks__/dataurl.js +11 -0
  14. package/__mocks__/mapbox-gl.js +19 -0
  15. package/commitlint.config.cjs +1 -0
  16. package/doc/.eslintrc.json +3 -0
  17. package/doc/.fixpackrc +21 -0
  18. package/doc/.prettierrc +1 -0
  19. package/doc/README.md +14 -0
  20. package/doc/declarations.d.ts +6 -0
  21. package/doc/next.config.mjs +4 -0
  22. package/doc/package.json +43 -0
  23. package/doc/postcss.config.mjs +8 -0
  24. package/doc/public/README.md +1 -0
  25. package/doc/src/app/components/GeopsAPIKeyLink.tsx +6 -0
  26. package/doc/src/app/components/GeopsAPIsLink.tsx +6 -0
  27. package/doc/src/app/components/GeopsMapsAPILink.tsx +8 -0
  28. package/doc/src/app/components/GeopsMobility.tsx +9 -0
  29. package/doc/src/app/components/GeopsMobilityDoc.tsx +231 -0
  30. package/doc/src/app/components/GeopsMobilitySearch.tsx +10 -0
  31. package/doc/src/app/components/GeopsMobilitySearchDoc.tsx +129 -0
  32. package/doc/src/app/components/GeopsRealtimeAPILink.tsx +10 -0
  33. package/doc/src/app/components/GeopsStopsAPILink.tsx +8 -0
  34. package/doc/src/app/components/Link.tsx +9 -0
  35. package/doc/src/app/components/WebComponentDoc.tsx +296 -0
  36. package/doc/src/app/favicon.ico +0 -0
  37. package/doc/src/app/geops-mobility/page.tsx +6 -0
  38. package/doc/src/app/geops-mobility-search/page.tsx +7 -0
  39. package/doc/src/app/globals.css +38 -0
  40. package/doc/src/app/hooks/useAttrFromUrlParams.ts +21 -0
  41. package/doc/src/app/hooks/useIsFullScreen.ts +14 -0
  42. package/doc/src/app/hooks/usePublicKey.ts +21 -0
  43. package/doc/src/app/layout.tsx +51 -0
  44. package/doc/src/app/page.tsx +86 -0
  45. package/doc/src/geops-ui.ts +3 -0
  46. package/doc/tailwind.config.ts +20 -0
  47. package/doc/tsconfig.json +40 -0
  48. package/eslint.config.mjs +40 -0
  49. package/favicon.ico +0 -0
  50. package/global.d.ts +4 -0
  51. package/iframe.html +34 -0
  52. package/index.html +276 -0
  53. package/index.js +2162 -0
  54. package/input.css +34 -0
  55. package/jest-setup.js +4 -0
  56. package/jest.config.js +17 -0
  57. package/package.json +80 -0
  58. package/scripts/build.mjs +16 -0
  59. package/scripts/dev.mjs +26 -0
  60. package/search.html +144 -0
  61. package/src/BaseLayer/BaseLayer.tsx +36 -0
  62. package/src/BaseLayer/index.tsx +1 -0
  63. package/src/Copyright/Copyright.tsx +54 -0
  64. package/src/Copyright/index.css +3 -0
  65. package/src/Copyright/index.tsx +1 -0
  66. package/src/DebugDeparture/DebugDeparture.tsx +116 -0
  67. package/src/DebugDeparture/index.tsx +1 -0
  68. package/src/DebugStop/DebugStop.tsx +47 -0
  69. package/src/DebugStop/index.tsx +1 -0
  70. package/src/Departure/Departure.tsx +55 -0
  71. package/src/Departure/index.tsx +1 -0
  72. package/src/GeolocationButton/GeolocationButton.tsx +81 -0
  73. package/src/GeolocationButton/index.tsx +1 -0
  74. package/src/Map/Map.tsx +89 -0
  75. package/src/Map/index.tsx +1 -0
  76. package/src/MobilityMap/MobilityMap.tsx +259 -0
  77. package/src/MobilityMap/index.css +13 -0
  78. package/src/MobilityMap/index.tsx +1 -0
  79. package/src/NotificationLayer/NotificationLayer.tsx +156 -0
  80. package/src/NotificationLayer/index.tsx +1 -0
  81. package/src/NotificationLayer/notificationUtils.ts +191 -0
  82. package/src/Overlay/Overlay.tsx +57 -0
  83. package/src/Overlay/index.tsx +1 -0
  84. package/src/RealtimeLayer/RealtimeLayer.tsx +230 -0
  85. package/src/RealtimeLayer/index.tsx +1 -0
  86. package/src/RouteDestination/RouteDestination.test.tsx +13 -0
  87. package/src/RouteDestination/RouteDestination.tsx +15 -0
  88. package/src/RouteDestination/index.tsx +1 -0
  89. package/src/RouteIcon/RouteIcon.tsx +66 -0
  90. package/src/RouteIcon/index.tsx +1 -0
  91. package/src/RouteIdentifier/RouteIdentifer.tsx +35 -0
  92. package/src/RouteIdentifier/index.tsx +1 -0
  93. package/src/RouteInfos/RouteInfos.tsx +22 -0
  94. package/src/RouteInfos/index.tsx +1 -0
  95. package/src/RouteSchedule/RouteSchedule.tsx +69 -0
  96. package/src/RouteSchedule/firstStation.png +0 -0
  97. package/src/RouteSchedule/index.tsx +1 -0
  98. package/src/RouteSchedule/lastStation.png +0 -0
  99. package/src/RouteSchedule/line.png +0 -0
  100. package/src/RouteSchedule/station.png +0 -0
  101. package/src/RouteScheduleFooter/RouteScheduleFooter.tsx +44 -0
  102. package/src/RouteScheduleFooter/index.tsx +1 -0
  103. package/src/RouteScheduleHeader/RouteScheduleHeader.tsx +58 -0
  104. package/src/RouteScheduleHeader/index.tsx +1 -0
  105. package/src/RouteStop/RouteStop.tsx +121 -0
  106. package/src/RouteStop/index.tsx +1 -0
  107. package/src/RouteStopDelay/RouteStopDelay.tsx +36 -0
  108. package/src/RouteStopDelay/index.tsx +1 -0
  109. package/src/RouteStopName/RouteStopName.tsx +24 -0
  110. package/src/RouteStopName/index.tsx +1 -0
  111. package/src/RouteStopPlatform/RouteStopPlatform.tsx +29 -0
  112. package/src/RouteStopPlatform/index.tsx +1 -0
  113. package/src/RouteStopProgress/RouteStopProgress.tsx +101 -0
  114. package/src/RouteStopProgress/index.tsx +1 -0
  115. package/src/RouteStopServices/RouteStopServices.tsx +26 -0
  116. package/src/RouteStopServices/index.tsx +1 -0
  117. package/src/RouteStopStation/RouteStopStation.tsx +32 -0
  118. package/src/RouteStopStation/index.tsx +1 -0
  119. package/src/RouteStopTime/RouteStopTime.tsx +34 -0
  120. package/src/RouteStopTime/index.tsx +1 -0
  121. package/src/RvfMobilityMap/RvfMobilityMap.tsx +245 -0
  122. package/src/RvfMobilityMap/index.css +13 -0
  123. package/src/RvfMobilityMap/index.tsx +1 -0
  124. package/src/ScaleLine/ScaleLine.tsx +51 -0
  125. package/src/ScaleLine/index.css +6 -0
  126. package/src/ScaleLine/index.tsx +1 -0
  127. package/src/ScrollableHandler/ScrollableHandler.tsx +65 -0
  128. package/src/ScrollableHandler/index.tsx +1 -0
  129. package/src/Search/Search.tsx +18 -0
  130. package/src/Search/index.tsx +1 -0
  131. package/src/SingleClickListener/SingleClickListener.tsx +103 -0
  132. package/src/SingleClickListener/index.tsx +1 -0
  133. package/src/Station/Station.tsx +68 -0
  134. package/src/Station/index.tsx +1 -0
  135. package/src/StationHeader/StationHeader.tsx +32 -0
  136. package/src/StationHeader/index.tsx +1 -0
  137. package/src/StationName/StationName.tsx +21 -0
  138. package/src/StationName/index.tsx +1 -0
  139. package/src/StationServices/StationServices.tsx +80 -0
  140. package/src/StationServices/index.tsx +1 -0
  141. package/src/StationsLayer/StationsLayer.tsx +41 -0
  142. package/src/StationsLayer/index.tsx +1 -0
  143. package/src/StopsSearch/StopsSearch.tsx +254 -0
  144. package/src/StopsSearch/index.tsx +1 -0
  145. package/src/icons/Airport/Airport.tsx +17 -0
  146. package/src/icons/Airport/airport-14-svgrepo-com.svg +41 -0
  147. package/src/icons/Airport/index.tsx +1 -0
  148. package/src/icons/BarAndRestaurants/BarAndRestaurants.tsx +17 -0
  149. package/src/icons/BarAndRestaurants/food-restaurant-svgrepo-com.svg +12 -0
  150. package/src/icons/BarAndRestaurants/index.tsx +1 -0
  151. package/src/icons/Bathroom/Bathroom.tsx +59 -0
  152. package/src/icons/Bathroom/bathroom-restroom-svgrepo-com.svg +38 -0
  153. package/src/icons/Bathroom/index.tsx +1 -0
  154. package/src/icons/BikeStorage/BikeStorage.tsx +17 -0
  155. package/src/icons/BikeStorage/index.tsx +1 -0
  156. package/src/icons/BikeStorage/parking-bicycle-14-svgrepo-com.svg +41 -0
  157. package/src/icons/Elevator/Elevator.tsx +16 -0
  158. package/src/icons/Elevator/elevator-svgrepo-com.svg +2 -0
  159. package/src/icons/Elevator/index.tsx +1 -0
  160. package/src/icons/Police/Police.tsx +20 -0
  161. package/src/icons/Police/index.tsx +1 -0
  162. package/src/icons/Police/polizia.png +0 -0
  163. package/src/icons/README.md +52 -0
  164. package/src/icons/WaitingAreas/WaitingAreas.tsx +16 -0
  165. package/src/icons/WaitingAreas/highway-rest-area-svgrepo-com.svg +5 -0
  166. package/src/icons/WaitingAreas/index.tsx +1 -0
  167. package/src/icons/WaitingAreas/wheelchair-svgrepo-com.svg +2 -0
  168. package/src/icons/WheelChair/WheelChair.tsx +16 -0
  169. package/src/icons/WheelChair/disabili.png +0 -0
  170. package/src/icons/WheelChair/index.tsx +1 -0
  171. package/src/icons/WheelChair/wheelchair-svgrepo-com.svg +2 -0
  172. package/src/index.tsx +50 -0
  173. package/src/utils/MobilityEvent.ts +21 -0
  174. package/src/utils/addSourceAndLayers.ts +62 -0
  175. package/src/utils/centerOnStation.ts +17 -0
  176. package/src/utils/centerOnVehicle.ts +50 -0
  177. package/src/utils/getBgColor.ts +3 -0
  178. package/src/utils/getDelayColor.test.ts +20 -0
  179. package/src/utils/getDelayColor.ts +23 -0
  180. package/src/utils/getDelayColorForVehicle.test.ts +28 -0
  181. package/src/utils/getDelayColorForVehicle.ts +25 -0
  182. package/src/utils/getDelayFontForVehicle.test.ts +7 -0
  183. package/src/utils/getDelayFontForVehicle.tsx +8 -0
  184. package/src/utils/getDelayString.test.ts +22 -0
  185. package/src/utils/getDelayString.ts +28 -0
  186. package/src/utils/getDelayTextForVehicle.test.ts +28 -0
  187. package/src/utils/getDelayTextForVehicle.ts +21 -0
  188. package/src/utils/getFullTrajectoryAndFit.ts +40 -0
  189. package/src/utils/getHoursAndMinutes.test.ts +14 -0
  190. package/src/utils/getHoursAndMinutes.ts +22 -0
  191. package/src/utils/getMainColorForVehicle.test.ts +27 -0
  192. package/src/utils/getMainColorForVehicle.ts +46 -0
  193. package/src/utils/getStopStatus.test.ts +104 -0
  194. package/src/utils/getStopStatus.ts +171 -0
  195. package/src/utils/getTextFontForVehicle.test.ts +7 -0
  196. package/src/utils/getTextFontForVehicle.tsx +9 -0
  197. package/src/utils/getTextForVehicle.test.ts +17 -0
  198. package/src/utils/getTextForVehicle.ts +19 -0
  199. package/src/utils/hooks/useDebug.tsx +11 -0
  200. package/src/utils/hooks/useDeparture.tsx +23 -0
  201. package/src/utils/hooks/useI18n.tsx +20 -0
  202. package/src/utils/hooks/useMapContext.tsx +74 -0
  203. package/src/utils/hooks/useParams.ts +5 -0
  204. package/src/utils/hooks/useRouteStop.tsx +33 -0
  205. package/src/utils/hooks/useStation.tsx +21 -0
  206. package/src/utils/hooks/useUpdatePermalink.tsx +33 -0
  207. package/src/utils/hooks/useZoom.tsx +32 -0
  208. package/src/utils/i18n.ts +16 -0
  209. package/src/utils/translations.ts +31 -0
  210. package/tailwind.config.mjs +56 -0
  211. package/testNotification.json +50653 -0
  212. package/tsconfig.json +12 -0
@@ -0,0 +1,20 @@
1
+ function Police({ ...props }) {
2
+ return (
3
+ <svg
4
+ fill="currentColor"
5
+ width="24px"
6
+ height="24px"
7
+ viewBox="0 0 15 15"
8
+ version="1.1"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ {...props}
11
+ >
12
+ <path
13
+ id="rect4718"
14
+ d="M5.5,1L6,2h5l0.5-1H5.5z M6,2.5v1.25c0,0,0,2.75,2.5,2.75S11,3.75,11,3.75V2.5H6z M1.9844,3.9863&#xA;&#x9;C1.4329,3.9949,0.9924,4.4485,1,5v4c-0.0001,0.6398,0.5922,1.1152,1.2168,0.9766L5,9.3574V14l5.8789-6.9297&#xA;&#x9;C10.7391,7.0294,10.5947,7,10.4414,7H6.5L3,7.7539V5C3.0077,4.4362,2.5481,3.9775,1.9844,3.9863z M11.748,7.7109L6.4121,14H12&#xA;&#x9;V8.5586C12,8.2451,11.9061,7.9548,11.748,7.7109z"
15
+ />
16
+ </svg>
17
+ );
18
+ }
19
+
20
+ export default Police;
@@ -0,0 +1 @@
1
+ export { default } from "./Police";
Binary file
@@ -0,0 +1,52 @@
1
+ # Icons
2
+
3
+ This folder contains icons used inside the web component.
4
+ Icons are preact components that display an SVG. No raster data (PNGs,JPEGs...).
5
+ Until we decide otherwise, we don't want to use automatic transformation from SVG to component like using SVGR.
6
+ So you must create and clean your component manually.
7
+
8
+ Icon must have their color defines with currentColor
9
+
10
+ You can let the original svg file in the corrsponding folder to keep track of them.
11
+
12
+ ## Guidelines
13
+
14
+ - Structure of folders follows the same rules as in normal components.
15
+
16
+ ```bash
17
+ MyIcon/index.tsx // only export the component
18
+ /MyIcon.tsx // the component containing the SVG
19
+ /icon.svg // the original SVG file
20
+ ```
21
+
22
+ - Set the width and height attribute to 24 pixels
23
+
24
+ - Propagate all the component props
25
+
26
+ - Set the fill attribute to `currentcColor`
27
+
28
+ - Clean all useless properties.
29
+
30
+ Here an example how it should look like:
31
+
32
+ ```js
33
+ function MyIcon({ ...props }) {
34
+ return (
35
+ <svg
36
+ xmlns="http://www.w3.org/2000/svg"
37
+ version="1.1"
38
+ width="24"
39
+ height="24"
40
+ fill="currentColor"
41
+ viewBox="0 0 14 14"
42
+ {...props}
43
+ >
44
+ </svg>
45
+ );
46
+ }
47
+
48
+ ```
49
+
50
+ ## Where to find icons
51
+
52
+ For now, if you need new icon, use <https://www.svgrepo.com/> and select only icons you are allowed to use and modify.
@@ -0,0 +1,16 @@
1
+ function WaitingAreas({ ...props }) {
2
+ return (
3
+ <svg
4
+ fill="currentColor"
5
+ width="24px"
6
+ height="24px"
7
+ viewBox="0 0 15 15"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ {...props}
10
+ >
11
+ <path d="M13.5,13h-3V9h3a.5.5,0,0,0,.4092-.7871L11.66,5h.84a.5.5,0,0,0,.3838-.82l-2.5-3a.5155.5155,0,0,0-.7676,0l-2.5,3A.5.5,0,0,0,7.5,5h.84L6.0908,8.2129A.5.5,0,0,0,6.5,9h3v4H4V11H5.5a.5.5,0,0,0,0-1h-4a.5.5,0,0,0,0,1H3v2H1.5a.5.5,0,0,0,0,1h12a.5.5,0,0,0,0-1Z" />
12
+ </svg>
13
+ );
14
+ }
15
+
16
+ export default WaitingAreas;
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
3
+ <svg fill="#000000" width="800px" height="800px" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg" id="highway-rest-area">
4
+ <path d="M13.5,13h-3V9h3a.5.5,0,0,0,.4092-.7871L11.66,5h.84a.5.5,0,0,0,.3838-.82l-2.5-3a.5155.5155,0,0,0-.7676,0l-2.5,3A.5.5,0,0,0,7.5,5h.84L6.0908,8.2129A.5.5,0,0,0,6.5,9h3v4H4V11H5.5a.5.5,0,0,0,0-1h-4a.5.5,0,0,0,0,1H3v2H1.5a.5.5,0,0,0,0,1h12a.5.5,0,0,0,0-1Z"/>
5
+ </svg>
@@ -0,0 +1 @@
1
+ export { default } from "./WaitingAreas";
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
2
+ <svg fill="inheritColor" width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="M12,6.5a2,2,0,1,0-2-2A2,2,0,0,0,12,6.5Zm7.5,14h-1v-5a1,1,0,0,0-1-1h-5v-2h5a1,1,0,0,0,0-2h-5v-2a1,1,0,0,0-2,0v7a1,1,0,0,0,1,1h5v5a1,1,0,0,0,1,1h2a1,1,0,0,0,0-2Zm-6.8-1.6a4,4,0,0,1-7.2-2.4,4,4,0,0,1,2.4-3.66A1,1,0,1,0,7.1,11a6,6,0,1,0,7.2,9.1,1,1,0,0,0-1.6-1.2Z"/></svg>
@@ -0,0 +1,16 @@
1
+ function WheelChair({ ...props }) {
2
+ return (
3
+ <svg
4
+ fill="currentColor"
5
+ width="24px"
6
+ height="24px"
7
+ viewBox="0 0 24 24"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ {...props}
10
+ >
11
+ <path d="M12,6.5a2,2,0,1,0-2-2A2,2,0,0,0,12,6.5Zm7.5,14h-1v-5a1,1,0,0,0-1-1h-5v-2h5a1,1,0,0,0,0-2h-5v-2a1,1,0,0,0-2,0v7a1,1,0,0,0,1,1h5v5a1,1,0,0,0,1,1h2a1,1,0,0,0,0-2Zm-6.8-1.6a4,4,0,0,1-7.2-2.4,4,4,0,0,1,2.4-3.66A1,1,0,1,0,7.1,11a6,6,0,1,0,7.2,9.1,1,1,0,0,0-1.6-1.2Z" />
12
+ </svg>
13
+ );
14
+ }
15
+
16
+ export default WheelChair;
@@ -0,0 +1 @@
1
+ export { default } from "./WheelChair";
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
2
+ <svg fill="inheritColor" width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="M12,6.5a2,2,0,1,0-2-2A2,2,0,0,0,12,6.5Zm7.5,14h-1v-5a1,1,0,0,0-1-1h-5v-2h5a1,1,0,0,0,0-2h-5v-2a1,1,0,0,0-2,0v7a1,1,0,0,0,1,1h5v5a1,1,0,0,0,1,1h2a1,1,0,0,0,0-2Zm-6.8-1.6a4,4,0,0,1-7.2-2.4,4,4,0,0,1,2.4-3.66A1,1,0,1,0,7.1,11a6,6,0,1,0,7.2,9.1,1,1,0,0,0-1.6-1.2Z"/></svg>
package/src/index.tsx ADDED
@@ -0,0 +1,50 @@
1
+ import register from "preact-custom-element";
2
+
3
+ import MobilityMap from "./MobilityMap";
4
+ import MobilitySearch from "./StopsSearch";
5
+
6
+ register(
7
+ MobilityMap,
8
+ "geops-mobility",
9
+ [
10
+ "apikey",
11
+ "baselayer",
12
+ "center",
13
+ "geolocation",
14
+ "mapsurl",
15
+ "mots",
16
+ "notification",
17
+ "notificationat",
18
+ "notificationurl",
19
+ "notificationbeforelayerid",
20
+ "realtime",
21
+ "realtimeUrl",
22
+ "search",
23
+ "tenant",
24
+ "zoom",
25
+ "permalink",
26
+ ],
27
+ { shadow: true },
28
+ );
29
+
30
+ register(
31
+ MobilitySearch,
32
+ "geops-mobility-search",
33
+ [
34
+ "apikey",
35
+ "bbox",
36
+ "countrycode",
37
+ "event",
38
+ "field",
39
+ "limit",
40
+ "mots",
41
+ "onselect",
42
+ "params",
43
+ "prefagencies",
44
+ "reflocation",
45
+ "url",
46
+ ],
47
+ {
48
+ shadow: true,
49
+ },
50
+ );
@@ -0,0 +1,21 @@
1
+ import type { MobilityMapProps } from "../MobilityMap/MobilityMap";
2
+
3
+ export type MobilityEventType =
4
+ | "mwc:attribute"
5
+ | "mwc:stopssearchselect"
6
+ | string;
7
+
8
+ class MobilityEvent<T> extends Event {
9
+ data: MobilityMapProps;
10
+
11
+ constructor(name: MobilityEventType, data: T, options: EventInit = {}) {
12
+ super(name, { ...options, composed: true });
13
+ this.data = data;
14
+ }
15
+
16
+ logImportantData() {
17
+ console.log(this.data);
18
+ }
19
+ }
20
+
21
+ export default MobilityEvent;
@@ -0,0 +1,62 @@
1
+ // Add a source and styleLayer using the id in parameter.
2
+ const addSourceAndLayers = (
3
+ mapboxLayer,
4
+ sourceId,
5
+ sourceData,
6
+ styleLayer,
7
+ beforeLayerId,
8
+ ) => {
9
+ if (!mapboxLayer.loaded) {
10
+ mapboxLayer.once("load", () => {
11
+ addSourceAndLayers(
12
+ mapboxLayer,
13
+ sourceId,
14
+ sourceData,
15
+ styleLayer,
16
+ beforeLayerId,
17
+ );
18
+ });
19
+ return;
20
+ }
21
+ const { mbMap } = mapboxLayer;
22
+
23
+ // Update source
24
+ if (sourceId && sourceData) {
25
+ const source = mbMap.getSource(sourceId);
26
+ if (source) {
27
+ source.setData(sourceData.data);
28
+ } else {
29
+ mbMap.addSource(sourceId, sourceData);
30
+ }
31
+ }
32
+
33
+ // Update layer
34
+ if (styleLayer) {
35
+ let layer = mbMap.getLayer(sourceId);
36
+ if (layer) {
37
+ mbMap.removeLayer(layer.id);
38
+ }
39
+
40
+ // styleLayer could be an array of styles to add.
41
+ let styleLayers = styleLayer;
42
+ if (!Array.isArray(styleLayer)) {
43
+ styleLayers = [styleLayer];
44
+ }
45
+ styleLayers.forEach((style) => {
46
+ if (mbMap.getSource(style.source)) {
47
+ layer = mbMap.getLayer(style.id);
48
+ if (layer) {
49
+ mbMap.removeLayer(layer.id);
50
+ }
51
+ mbMap.addLayer(style, beforeLayerId);
52
+ } else {
53
+ console.warn(
54
+ `The source ${style.source} doesn't exist. This layer can't be added`,
55
+ style,
56
+ );
57
+ }
58
+ });
59
+ }
60
+ };
61
+
62
+ export default addSourceAndLayers;
@@ -0,0 +1,17 @@
1
+ import { Map } from "ol";
2
+ import { fromLonLat } from "ol/proj";
3
+
4
+ import { StationFeature } from "../StopsSearch";
5
+
6
+ const centerOnStation = (selectedStation: StationFeature, map: Map) => {
7
+ const center = selectedStation?.geometry?.coordinates;
8
+ if (center) {
9
+ map?.getView()?.animate({
10
+ center: fromLonLat(center),
11
+ duration: 500,
12
+ zoom: 16,
13
+ });
14
+ }
15
+ };
16
+
17
+ export default centerOnStation;
@@ -0,0 +1,50 @@
1
+ import { getVehiclePosition } from "mobility-toolbox-js/ol";
2
+ import { RealtimeTrajectory } from "mobility-toolbox-js/types";
3
+ import { Map } from "ol";
4
+ import { linear } from "ol/easing";
5
+
6
+ const centerOnVehicle = async (
7
+ vehicle: RealtimeTrajectory,
8
+ map: Map,
9
+ targetZoom = 0,
10
+ ) => {
11
+ if (!vehicle) {
12
+ return Promise.reject();
13
+ }
14
+
15
+ const {
16
+ geometry,
17
+ properties: { coordinate },
18
+ } = vehicle;
19
+ const view = map.getView();
20
+ const zoom = targetZoom || view.getZoom();
21
+ const resolution = zoom > 0 ? view.getResolutionForZoom(zoom) : undefined;
22
+
23
+ let center = coordinate;
24
+ if (!center && geometry) {
25
+ const { coord } = getVehiclePosition(Date.now(), vehicle, true);
26
+ center = coord as [number, number];
27
+ }
28
+ if (!center) {
29
+ return Promise.reject();
30
+ }
31
+
32
+ view.cancelAnimations();
33
+
34
+ const promise = new Promise((resolve) => {
35
+ view.animate(
36
+ {
37
+ center,
38
+ duration: 1000,
39
+ easing: linear,
40
+ resolution,
41
+ },
42
+ (success) => {
43
+ resolve(success);
44
+ },
45
+ );
46
+ });
47
+ return promise;
48
+ };
49
+
50
+ export default centerOnVehicle;
@@ -0,0 +1,3 @@
1
+ import { realtimeConfig } from "mobility-toolbox-js/ol";
2
+
3
+ export default realtimeConfig.getBgColor;
@@ -0,0 +1,20 @@
1
+ import getDelayColor from "./getDelayColor";
2
+
3
+ describe("getDelayColor", () => {
4
+ it("returns green", () => {
5
+ expect(getDelayColor(0)).toBe("#16a34a");
6
+ expect(getDelayColor(2.49 * 60 * 1000)).toBe("#16a34a");
7
+ });
8
+ it("returns yellow", () => {
9
+ expect(getDelayColor(3 * 60 * 1000)).toBe("#ca8a04");
10
+ expect(getDelayColor(4.49 * 60 * 1000 - 1)).toBe("#ca8a04");
11
+ });
12
+ it("returns orange", () => {
13
+ expect(getDelayColor(5 * 60 * 1000)).toBe("#ea580c");
14
+ expect(getDelayColor(9.49 * 60 * 1000 - 1)).toBe("#ea580c");
15
+ });
16
+ it("returns red", () => {
17
+ expect(getDelayColor(10 * 60 * 1000)).toBe("#dc2626");
18
+ expect(getDelayColor(180 * 60 * 1000)).toBe("#dc2626");
19
+ });
20
+ });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Returns a color class to display the delay.
3
+ * @param {Number} time Delay time in milliseconds.
4
+ */
5
+ const getDelayColor = (timeInMs: number) => {
6
+ // we use rounded value to fit the getDelayString method.
7
+ const minutes = Math.round(timeInMs / 1000 / 60);
8
+ // if (minutes >= 60) {
9
+ // }
10
+ if (minutes >= 10) {
11
+ return "#dc2626"; // "text-red-600";
12
+ }
13
+ if (minutes >= 5) {
14
+ return "#ea580c"; // "text-orange-600";
15
+ // return "#d97706"; // "text-amber-600";
16
+ }
17
+ if (minutes >= 3) {
18
+ return "#ca8a04"; // "text-yellow-600";
19
+ }
20
+ return "#16a34a"; // "text-green-600";
21
+ };
22
+
23
+ export default getDelayColor;
@@ -0,0 +1,28 @@
1
+ import getDelayColorForVehicle from "./getDelayColorForVehicle";
2
+
3
+ describe("getDelayColorForVehicle", () => {
4
+ it("returns cancelled color", () => {
5
+ expect(getDelayColorForVehicle(0, true, true)).toBe("#dc2626");
6
+ expect(getDelayColorForVehicle(0, true, false)).toBe("#a0a0a0");
7
+ });
8
+ it("returns null delay (no realtime train) color", () => {
9
+ expect(getDelayColorForVehicle(null)).toBe("#a0a0a0");
10
+ });
11
+
12
+ it("returns green", () => {
13
+ expect(getDelayColorForVehicle(0)).toBe("#16a34a");
14
+ expect(getDelayColorForVehicle(2.49 * 60 * 1000)).toBe("#16a34a");
15
+ });
16
+ it("returns yellow", () => {
17
+ expect(getDelayColorForVehicle(3 * 60 * 1000)).toBe("#ca8a04");
18
+ expect(getDelayColorForVehicle(4.49 * 60 * 1000 - 1)).toBe("#ca8a04");
19
+ });
20
+ it("returns orange", () => {
21
+ expect(getDelayColorForVehicle(5 * 60 * 1000)).toBe("#ea580c");
22
+ expect(getDelayColorForVehicle(9.49 * 60 * 1000 - 1)).toBe("#ea580c");
23
+ });
24
+ it("returns red", () => {
25
+ expect(getDelayColorForVehicle(10 * 60 * 1000)).toBe("#dc2626");
26
+ expect(getDelayColorForVehicle(180 * 60 * 1000)).toBe("#dc2626");
27
+ });
28
+ });
@@ -0,0 +1,25 @@
1
+ import getDelayColor from "./getDelayColor";
2
+
3
+ /**
4
+ * @private
5
+ * @param {number} delayInMs Delay in milliseconds.
6
+ * @param {boolean} cancelled true if the journey is cancelled.
7
+ * @param {boolean} isDelayText true if the color is used for delay text of the symbol.
8
+ */
9
+ const getDelayColorForVehicle = (
10
+ delayInMs: null | number,
11
+ cancelled?: boolean,
12
+ isDelayText?: boolean,
13
+ ): string => {
14
+ if (cancelled) {
15
+ return isDelayText
16
+ ? "#dc2626" // "text-red-600";
17
+ : "#a0a0a0"; // gray
18
+ }
19
+ if (delayInMs === null) {
20
+ return "#a0a0a0";
21
+ }
22
+ return getDelayColor(delayInMs);
23
+ };
24
+
25
+ export default getDelayColorForVehicle;
@@ -0,0 +1,7 @@
1
+ import getDelayFontForVehicle from "./getDelayFontForVehicle";
2
+
3
+ describe("getDelayFontForVehicle", () => {
4
+ it("returns font that inherit", () => {
5
+ expect(getDelayFontForVehicle(12)).toBe("bold 12px arial");
6
+ });
7
+ });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Return the font for the delay text in the map.
3
+ */
4
+ const getDelayFontForVehicle = (fontSize: number) => {
5
+ return `bold ${fontSize}px arial`;
6
+ };
7
+
8
+ export default getDelayFontForVehicle;
@@ -0,0 +1,22 @@
1
+ import getDelayString from "./getDelayString";
2
+
3
+ describe("getDelayString", () => {
4
+ it("returns hours (floor)", () => {
5
+ expect(getDelayString(7200000)).toBe("2h");
6
+ expect(getDelayString(7255555)).toBe("2h1m");
7
+ });
8
+ it("returns minutes (round)", () => {
9
+ expect(getDelayString(120000)).toBe("2m");
10
+ expect(getDelayString(151000)).toBe("3m");
11
+ });
12
+ it("doesn't display seconds", () => {
13
+ expect(getDelayString(1000)).toBe("0");
14
+ expect(getDelayString(30000)).toBe("1m");
15
+ expect(getDelayString(7255555)).toBe("2h1m");
16
+ });
17
+ it("returns defsult 0 value", () => {
18
+ expect(getDelayString(0)).toBe("0");
19
+ expect(getDelayString(null)).toBe("0");
20
+ expect(getDelayString(undefined)).toBe("0");
21
+ });
22
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Returns a string representing a delay.
3
+ * @param {Number} timeInMs Delay time in milliseconds.
4
+ * @ignore
5
+ */
6
+ const getDelayString = (delayInMs: number) => {
7
+ let timeInMs = delayInMs;
8
+ if (timeInMs < 0) {
9
+ timeInMs = 0;
10
+ }
11
+ const h = Math.floor(timeInMs / 3600000);
12
+ const m = Math.round((timeInMs % 3600000) / 60000);
13
+ // const s = Math.floor(((timeInMs % 3600000) % 60000) / 1000);
14
+
15
+ let str = "";
16
+ if (h > 0) {
17
+ str += `${h}h`;
18
+ }
19
+ if (m > 0) {
20
+ str += `${m}m`;
21
+ }
22
+ // if (s > 0) {
23
+ // str += `${s}s`;
24
+ // }
25
+ return str || "0";
26
+ };
27
+
28
+ export default getDelayString;
@@ -0,0 +1,28 @@
1
+ import getDelayTextForVehicle from "./getDelayTextForVehicle";
2
+
3
+ describe("getDelayTextForVehicle", () => {
4
+ it("returns cancelled character", () => {
5
+ expect(getDelayTextForVehicle(7200000, true)).toBe(
6
+ String.fromCodePoint(0x00d7),
7
+ );
8
+ });
9
+ it("returns hours (floor)", () => {
10
+ expect(getDelayTextForVehicle(7200000)).toBe("+2h");
11
+ expect(getDelayTextForVehicle(7255555)).toBe("+2h1m");
12
+ });
13
+ it("returns minutes (round)", () => {
14
+ expect(getDelayTextForVehicle(120000)).toBe("+2m");
15
+ expect(getDelayTextForVehicle(151000)).toBe("+3m");
16
+ });
17
+ it("doesn't display seconds", () => {
18
+ expect(getDelayTextForVehicle(1000)).toBe("");
19
+ expect(getDelayTextForVehicle(30000)).toBe("+1m");
20
+ expect(getDelayTextForVehicle(7255555)).toBe("+2h1m");
21
+ });
22
+ it("returns empty value", () => {
23
+ expect(getDelayTextForVehicle(1000)).toBe("");
24
+ expect(getDelayTextForVehicle(null)).toBe("");
25
+ expect(getDelayTextForVehicle(undefined)).toBe("");
26
+ expect(getDelayTextForVehicle(0)).toBe("");
27
+ });
28
+ });
@@ -0,0 +1,21 @@
1
+ import getDelayString from "./getDelayString";
2
+
3
+ /**
4
+ * This function returns the text displays near the vehicle.
5
+ * We use getDelayString inside it to make sure that RouteSchedule and
6
+ * the map have the same values.
7
+ */
8
+ const getDelayTextForVehicle = (
9
+ delayInMs: number,
10
+ cancelled = false,
11
+ ): string => {
12
+ if (cancelled) {
13
+ return String.fromCodePoint(0x00d7);
14
+ }
15
+ const delayString = getDelayString(delayInMs);
16
+ if (delayString === "0") {
17
+ return "";
18
+ }
19
+ return `+${delayString}`;
20
+ };
21
+ export default getDelayTextForVehicle;
@@ -0,0 +1,40 @@
1
+ import { RealtimeLayer } from "mobility-toolbox-js/ol";
2
+ import { RealtimeTrainId } from "mobility-toolbox-js/types";
3
+ import { Map } from "ol";
4
+ import { GeoJSON } from "ol/format";
5
+ import { Vector } from "ol/source";
6
+
7
+ const getFullTrajectoryAndFit = async (
8
+ map: Map,
9
+ realtimeLayer: RealtimeLayer,
10
+ trainId: RealtimeTrainId,
11
+ targetZoom = 0,
12
+ ) => {
13
+ // TO IMPROVE:
14
+ // We should be able to get a trajectory directly but it does not work because the trajectory is outside the bbox
15
+ // see /BAHNMW-805 and TGSRVI-1126
16
+ // So we get the full trajectory then zoom on it.
17
+
18
+ const fullTrajectory = await realtimeLayer.api.getFullTrajectory(
19
+ trainId,
20
+ realtimeLayer.mode,
21
+ realtimeLayer.engine.generalizationLevelByZoom[targetZoom],
22
+ );
23
+ if (fullTrajectory?.content?.features?.length) {
24
+ const extent = new Vector({
25
+ features: new GeoJSON().readFeatures(fullTrajectory.content),
26
+ }).getExtent();
27
+
28
+ const promise = new Promise((resolve) => {
29
+ map.getView().fit(extent, {
30
+ callback: (success) => {
31
+ resolve(success);
32
+ },
33
+ });
34
+ });
35
+ return promise;
36
+ }
37
+ return Promise.resolve(false);
38
+ };
39
+
40
+ export default getFullTrajectoryAndFit;
@@ -0,0 +1,14 @@
1
+ import getHoursAndMinutes from "./getHoursAndMinutes";
2
+
3
+ describe("getHoursAndMinutes", () => {
4
+ it("returns hours and minutes", () => {
5
+ expect(getHoursAndMinutes(7200000)).toBe("02:00");
6
+ expect(getHoursAndMinutes(72999999)).toBe("20:16");
7
+ });
8
+ it("returns empty string", () => {
9
+ expect(getHoursAndMinutes(null)).toBe("");
10
+ expect(getHoursAndMinutes(undefined)).toBe("");
11
+ expect(getHoursAndMinutes(0)).toBe("");
12
+ expect(getHoursAndMinutes(-500000)).toBe("");
13
+ });
14
+ });
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Returns a string representation of a number, with a zero if the number is lower than 10.
3
+ * @ignore
4
+ */
5
+ const pad = (integer: number) => {
6
+ return integer < 10 ? `0${integer}` : integer;
7
+ };
8
+
9
+ /**
10
+ * Returns a 'hh:mm' string from a time in ms.
11
+ * @param {Number} timeInMs Time in milliseconds.
12
+ * @ignore
13
+ */
14
+ const getHoursAndMinutes = (timeInMs: number) => {
15
+ if (!timeInMs || timeInMs <= 0) {
16
+ return "";
17
+ }
18
+ const date = new Date(timeInMs);
19
+ return `${pad(date.getHours())}:${pad(date.getMinutes())}`;
20
+ };
21
+
22
+ export default getHoursAndMinutes;