@opentripplanner/vehicle-rental-overlay 1.4.2 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ import { Styled as BaseMapStyled } from "@opentripplanner/base-map";
2
+ import React from "react";
3
+ import FromToLocationPicker from "@opentripplanner/from-to-location-picker";
4
+ import coreUtils from "@opentripplanner/core-utils";
5
+ import { useIntl, FormattedMessage } from "react-intl";
6
+ import flatten from "flat"; // Load the default messages.
7
+ // @ts-expect-error why is this failing?
8
+
9
+ import defaultEnglishMessages from "../i18n/en-US.yml"; // HACK: We should flatten the messages loaded above because
10
+ // the YAML loaders behave differently between webpack and our version of jest:
11
+ // - the yaml loader for webpack returns a nested object,
12
+ // - the yaml loader for jest returns messages with flattened ids.
13
+
14
+ var defaultMessages = flatten(defaultEnglishMessages);
15
+
16
+ function makeDefaultGetStationName(intl) {
17
+ return function defaultGetStationName(configCompanies, station) {
18
+ var stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks((station === null || station === void 0 ? void 0 : station.networks) || [], configCompanies);
19
+ var stationName = station.name || station.id; // If the station name or id is a giant UUID (with more than 3 "-" characters)
20
+ // best not to show that at all and instead use the network name.
21
+
22
+ if ((stationName.match(/-/g) || []).length > 3) {
23
+ stationName = stationNetworks;
24
+ }
25
+
26
+ if (station.isFloatingBike) {
27
+ stationName = intl.formatMessage({
28
+ defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingBike"],
29
+ description: "Popup title for a free-floating bike",
30
+ id: "otpUi.VehicleRentalOverlay.floatingBike"
31
+ }, {
32
+ name: stationName
33
+ });
34
+ } else if (station.isFloatingCar) {
35
+ stationName = intl.formatMessage({
36
+ defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingCar"],
37
+ description: "Popup title for a free-floating car",
38
+ id: "otpUi.VehicleRentalOverlay.floatingCar"
39
+ }, {
40
+ company: stationNetworks,
41
+ name: stationName
42
+ });
43
+ } else if (station.isFloatingVehicle) {
44
+ // assumes that all floating vehicles are E-scooters
45
+ stationName = intl.formatMessage({
46
+ defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingEScooter"],
47
+ description: "Popup title for a free-floating e-scooter",
48
+ id: "otpUi.VehicleRentalOverlay.floatingEScooter"
49
+ }, {
50
+ company: stationNetworks
51
+ });
52
+ }
53
+
54
+ return stationName;
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Render some popup html for a station. This contains custom logic for
60
+ * displaying rental vehicles in the TriMet MOD website that might not be
61
+ * applicable to other regions.
62
+ */
63
+ var StationPopup = function StationPopup(props) {
64
+ var intl = useIntl();
65
+ var configCompanies = props.configCompanies,
66
+ getStationName = props.getStationName,
67
+ setLocation = props.setLocation,
68
+ station = props.station;
69
+ var stationIsHub = station.bikesAvailable !== undefined && !station.isFloatingBike;
70
+ var getStationNameFunc = getStationName || makeDefaultGetStationName(intl);
71
+ var stationName = getStationNameFunc(configCompanies, station);
72
+ var location = {
73
+ lat: station.y,
74
+ lon: station.x,
75
+ name: stationName
76
+ };
77
+ return /*#__PURE__*/React.createElement(BaseMapStyled.MapOverlayPopup, null, /*#__PURE__*/React.createElement(BaseMapStyled.PopupTitle, null, stationName), stationIsHub && /*#__PURE__*/React.createElement(BaseMapStyled.PopupRow, null, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(FormattedMessage, {
78
+ defaultMessage: defaultMessages["otpUi.VehicleRentalOverlay.availableBikes"],
79
+ description: "Label text for the number of bikes available",
80
+ id: "otpUi.VehicleRentalOverlay.availableBikes",
81
+ values: {
82
+ value: station.bikesAvailable
83
+ }
84
+ })), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(FormattedMessage, {
85
+ defaultMessage: defaultMessages["otpUi.VehicleRentalOverlay.availableDocks"],
86
+ description: "Label text for the number of docks available",
87
+ id: "otpUi.VehicleRentalOverlay.availableDocks",
88
+ values: {
89
+ value: station.spacesAvailable
90
+ }
91
+ }))), /*#__PURE__*/React.createElement(BaseMapStyled.PopupRow, null, /*#__PURE__*/React.createElement(FromToLocationPicker, {
92
+ label: true,
93
+ location: location,
94
+ setLocation: setLocation
95
+ })));
96
+ };
97
+
98
+ export default StationPopup;
99
+ //# sourceMappingURL=StationPopup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/StationPopup.tsx"],"names":["Styled","BaseMapStyled","React","FromToLocationPicker","coreUtils","useIntl","FormattedMessage","flatten","defaultEnglishMessages","defaultMessages","makeDefaultGetStationName","intl","defaultGetStationName","configCompanies","station","stationNetworks","itinerary","getCompaniesLabelFromNetworks","networks","stationName","name","id","match","length","isFloatingBike","formatMessage","defaultMessage","description","isFloatingCar","company","isFloatingVehicle","StationPopup","props","getStationName","setLocation","stationIsHub","bikesAvailable","undefined","getStationNameFunc","location","lat","y","lon","x","value","spacesAvailable"],"mappings":"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","sourcesContent":["import {\n Company,\n ConfiguredCompany,\n MapLocationActionArg,\n Station\n} from \"@opentripplanner/types\";\nimport { Styled as BaseMapStyled } from \"@opentripplanner/base-map\";\nimport React from \"react\";\nimport FromToLocationPicker from \"@opentripplanner/from-to-location-picker\";\nimport coreUtils from \"@opentripplanner/core-utils\";\nimport { IntlShape, useIntl, FormattedMessage } from \"react-intl\";\nimport flatten from \"flat\";\n\n// Load the default messages.\n// @ts-expect-error why is this failing?\nimport defaultEnglishMessages from \"../i18n/en-US.yml\";\n\n// HACK: We should flatten the messages loaded above because\n// the YAML loaders behave differently between webpack and our version of jest:\n// - the yaml loader for webpack returns a nested object,\n// - the yaml loader for jest returns messages with flattened ids.\nconst defaultMessages = flatten(defaultEnglishMessages);\n\nfunction makeDefaultGetStationName(intl: IntlShape) {\n return function defaultGetStationName(\n configCompanies: Company[],\n station: Station\n ) {\n const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(\n station?.networks || [],\n configCompanies\n );\n let stationName = station.name || station.id;\n // If the station name or id is a giant UUID (with more than 3 \"-\" characters)\n // best not to show that at all and instead use the network name.\n if ((stationName.match(/-/g) || []).length > 3) {\n stationName = stationNetworks;\n }\n\n if (station.isFloatingBike) {\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\"otpUi.VehicleRentalOverlay.floatingBike\"],\n description: \"Popup title for a free-floating bike\",\n id: \"otpUi.VehicleRentalOverlay.floatingBike\"\n },\n { name: stationName }\n );\n } else if (station.isFloatingCar) {\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\"otpUi.VehicleRentalOverlay.floatingCar\"],\n description: \"Popup title for a free-floating car\",\n id: \"otpUi.VehicleRentalOverlay.floatingCar\"\n },\n {\n company: stationNetworks,\n name: stationName\n }\n );\n } else if (station.isFloatingVehicle) {\n // assumes that all floating vehicles are E-scooters\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\n \"otpUi.VehicleRentalOverlay.floatingEScooter\"\n ],\n description: \"Popup title for a free-floating e-scooter\",\n id: \"otpUi.VehicleRentalOverlay.floatingEScooter\"\n },\n { company: stationNetworks }\n );\n }\n return stationName;\n };\n}\n\ntype Props = {\n station: Station;\n configCompanies: ConfiguredCompany[];\n getStationName: (configCompanies: Company[], station: Station) => string;\n setLocation: (arg: MapLocationActionArg) => void;\n};\n/**\n * Render some popup html for a station. This contains custom logic for\n * displaying rental vehicles in the TriMet MOD website that might not be\n * applicable to other regions.\n */\nconst StationPopup = (props: Props): JSX.Element => {\n const intl = useIntl();\n const { configCompanies, getStationName, setLocation, station } = props;\n const stationIsHub =\n station.bikesAvailable !== undefined && !station.isFloatingBike;\n const getStationNameFunc = getStationName || makeDefaultGetStationName(intl);\n const stationName = getStationNameFunc(configCompanies, station);\n const location = {\n lat: station.y,\n lon: station.x,\n name: stationName\n };\n return (\n <BaseMapStyled.MapOverlayPopup>\n <BaseMapStyled.PopupTitle>{stationName}</BaseMapStyled.PopupTitle>\n\n {/* render dock info if it is available */}\n {stationIsHub && (\n <BaseMapStyled.PopupRow>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableBikes\"]\n }\n description=\"Label text for the number of bikes available\"\n id=\"otpUi.VehicleRentalOverlay.availableBikes\"\n values={{ value: station.bikesAvailable }}\n />\n </div>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableDocks\"]\n }\n description=\"Label text for the number of docks available\"\n id=\"otpUi.VehicleRentalOverlay.availableDocks\"\n values={{ value: station.spacesAvailable }}\n />\n </div>\n </BaseMapStyled.PopupRow>\n )}\n\n {/* Set as from/to toolbar */}\n <BaseMapStyled.PopupRow>\n <FromToLocationPicker\n label\n location={location}\n setLocation={setLocation}\n />\n </BaseMapStyled.PopupRow>\n </BaseMapStyled.MapOverlayPopup>\n );\n};\n\nexport default StationPopup;\n"],"file":"StationPopup.js"}
package/esm/index.js CHANGED
@@ -1,373 +1,168 @@
1
- import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
- import _createClass from "@babel/runtime/helpers/createClass";
3
- import _inherits from "@babel/runtime/helpers/inherits";
4
- import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
5
- import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
6
3
 
7
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
4
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
8
5
 
9
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
6
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
10
7
 
11
- import flatten from "flat";
12
- import { Styled as BaseMapStyled } from "@opentripplanner/base-map";
13
- import coreUtils from "@opentripplanner/core-utils";
14
- import FromToLocationPicker from "@opentripplanner/from-to-location-picker";
15
- import ZoomBasedMarkers from "@opentripplanner/zoom-based-markers";
16
- import PropTypes from "prop-types";
17
- import React from "react";
18
- import { FormattedMessage, injectIntl } from "react-intl";
19
- import { FeatureGroup, MapLayer, Popup, withLeaflet } from "react-leaflet";
20
- import { GenericMarker, HubAndFloatingBike, SharedBikeCircle } from "./DefaultMarkers"; // Load the default messages.
8
+ import { Source, Layer, useMap, Popup } from "react-map-gl";
9
+ import React, { useEffect, useState } from "react";
10
+ import { MarkerWithPopup } from "@opentripplanner/base-map";
11
+ import StationPopup from "./StationPopup";
12
+ import { BaseBikeRentalIcon, StationMarker } from "./styled"; // TODO: Make configurable?
21
13
 
22
- import defaultEnglishMessages from "../i18n/en-US.yml"; // HACK: We should flatten the messages loaded above because
23
- // the YAML loaders behave differently between webpack and our version of jest:
24
- // - the yaml loader for webpack returns a nested object,
25
- // - the yaml loader for jest returns messages with flattened ids.
14
+ var DETAILED_MARKER_CUTOFF = 16;
26
15
 
27
- var defaultMessages = flatten(defaultEnglishMessages);
16
+ var getColorForStation = function getColorForStation(v) {
17
+ if (v.isFloatingCar) return "#009cde";
18
+ if (v.isFloatingVehicle) return "#f5a729"; // TODO: nicer color to match transitive
28
19
 
29
- function makeDefaultGetStationName(intl) {
30
- return function defaultGetStationName(configCompanies, station) {
31
- var stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(station.networks, configCompanies);
32
- var stationName = station.name || station.id;
20
+ if (v.bikesAvailable !== undefined || v.isFloatingBike) return "#f00";
21
+ return "gray";
22
+ };
33
23
 
34
- if (station.isFloatingBike) {
35
- stationName = intl.formatMessage({
36
- defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingBike"],
37
- description: "Popup title for a free-floating bike",
38
- id: "otpUi.VehicleRentalOverlay.floatingBike"
39
- }, {
40
- name: stationName
41
- });
42
- } else if (station.isFloatingCar) {
43
- stationName = intl.formatMessage({
44
- defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingCar"],
45
- description: "Popup title for a free-floating car",
46
- id: "otpUi.VehicleRentalOverlay.floatingCar"
47
- }, {
48
- company: stationNetworks,
49
- name: stationName
50
- });
51
- } else if (station.isFloatingVehicle) {
52
- // assumes that all floating vehicles are E-scooters
53
- stationName = intl.formatMessage({
54
- defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingEScooter"],
55
- description: "Popup title for a free-floating e-scooter",
56
- id: "otpUi.VehicleRentalOverlay.floatingEScooter"
57
- }, {
58
- company: stationNetworks
59
- });
60
- }
24
+ var checkIfPositionInViewport = function checkIfPositionInViewport(bounds, lat, lng) {
25
+ var PADDING = 0.001; // @ts-expect-error types appear to be wrong? version issue?
26
+ // eslint-disable-next-line no-underscore-dangle
27
+
28
+ var _ref = [bounds._sw, bounds._ne],
29
+ sw = _ref[0],
30
+ ne = _ref[1];
31
+ if (!sw || !ne) return false;
32
+ return lat >= sw.lat - PADDING && lat <= ne.lat + PADDING && lng >= sw.lng - PADDING && lng <= ne.lng + PADDING;
33
+ };
61
34
 
62
- return stationName;
63
- };
64
- }
65
35
  /**
66
36
  * This vehicle rental overlay can be used to render vehicle rentals of various
67
37
  * types. This layer can be configured to show different styles of markers at
68
38
  * different zoom levels.
69
39
  */
70
-
71
-
72
- var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
73
- _inherits(VehicleRentalOverlay, _MapLayer);
74
-
75
- var _super = _createSuper(VehicleRentalOverlay);
76
-
77
- function VehicleRentalOverlay(props) {
78
- var _this;
79
-
80
- _classCallCheck(this, VehicleRentalOverlay);
81
-
82
- _this = _super.call(this, props);
83
-
84
- _this.renderSymbolWithPopup = function (_Symbol) {
85
- var SymbolWrapper = function SymbolWrapper(_ref) {
86
- var station = _ref.entity,
87
- zoom = _ref.zoom;
88
- return /*#__PURE__*/React.createElement(_Symbol, {
89
- entity: station,
90
- zoom: zoom
91
- }, _this.renderPopupForStation(station, station.bikesAvailable !== undefined && !station.isFloatingBike));
92
- };
93
-
94
- SymbolWrapper.propTypes = {
95
- // entity: coreUtils.types.stationType.isRequired,
96
- zoom: PropTypes.number.isRequired
97
- };
98
- return SymbolWrapper;
99
- };
100
-
101
- _this.convertToZoomMarkerSymbols = function (mapSymbols) {
102
- return mapSymbols.map(function (mapSymbol) {
103
- // If mapSymbol uses zoomBasedSymbolType, use it as is.
104
- if (mapSymbol.symbol) {
105
- return mapSymbol;
106
- } // Otherwise, convert into zoomBasedType (no support for symbols by type).
107
-
108
-
109
- var symbol;
110
-
111
- switch (mapSymbol.type) {
112
- case "circle":
113
- symbol = SharedBikeCircle(mapSymbol);
114
- break;
115
-
116
- case "hubAndFloatingBike":
117
- symbol = HubAndFloatingBike;
118
- break;
119
-
120
- default:
121
- symbol = GenericMarker(mapSymbol);
122
- }
123
-
124
- return {
125
- minZoom: mapSymbol.minZoom,
126
- symbol: symbol
127
- };
128
- });
129
- };
130
-
131
- _this.onOverlayAdded = function () {
132
- _this.startRefreshing();
133
- };
134
-
135
- _this.onOverlayRemoved = function () {
136
- _this.stopRefreshing();
137
- };
138
-
139
- _this.onViewportChanged = function (viewport) {
140
- var newZoom = viewport.zoom;
141
-
142
- if (_this.state.zoom !== newZoom) {
143
- _this.setState({
144
- zoom: newZoom
145
- });
146
- }
147
- };
148
-
149
- _this.renderPopupForStation = function (station) {
150
- var stationIsHub = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
151
- var _this$props = _this.props,
152
- configCompanies = _this$props.configCompanies,
153
- getStationName = _this$props.getStationName,
154
- intl = _this$props.intl,
155
- setLocation = _this$props.setLocation;
156
- var getStationNameFunc = getStationName || makeDefaultGetStationName(intl);
157
- var stationName = getStationNameFunc(configCompanies, station);
158
- var location = {
159
- lat: station.y,
160
- lon: station.x,
161
- name: stationName
162
- };
163
- return /*#__PURE__*/React.createElement(Popup, null, /*#__PURE__*/React.createElement(BaseMapStyled.MapOverlayPopup, null, /*#__PURE__*/React.createElement(BaseMapStyled.PopupTitle, null, stationName), stationIsHub && /*#__PURE__*/React.createElement(BaseMapStyled.PopupRow, null, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(FormattedMessage, {
164
- defaultMessage: defaultMessages["otpUi.VehicleRentalOverlay.availableBikes"],
165
- description: "Label text for the number of bikes available",
166
- id: "otpUi.VehicleRentalOverlay.availableBikes",
167
- values: {
168
- value: station.bikesAvailable
169
- }
170
- })), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(FormattedMessage, {
171
- defaultMessage: defaultMessages["otpUi.VehicleRentalOverlay.availableDocks"],
172
- description: "Label text for the number of docks available",
173
- id: "otpUi.VehicleRentalOverlay.availableDocks",
174
- values: {
175
- value: station.spacesAvailable
176
- }
177
- }))), /*#__PURE__*/React.createElement(BaseMapStyled.PopupRow, null, /*#__PURE__*/React.createElement(FromToLocationPicker, {
178
- label: true,
179
- location: location,
180
- setLocation: setLocation
181
- }))));
182
- };
183
-
184
- _this.state = {
185
- zoom: null
186
- };
187
- return _this;
188
- }
189
- /**
190
- * This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.
191
- * It creates a component that inserts a popup
192
- * as a child of the specified symbol from the mapSymbols prop.
193
- */
194
-
195
-
196
- _createClass(VehicleRentalOverlay, [{
197
- key: "createLeafletElement",
198
- value: function createLeafletElement() {}
199
- }, {
200
- key: "updateLeafletElement",
201
- value: function updateLeafletElement() {}
202
- }, {
203
- key: "startRefreshing",
204
- value: function startRefreshing() {
205
- var refreshVehicles = this.props.refreshVehicles; // Create the timer only if refreshVehicles is a valid function.
206
-
207
- if (typeof refreshVehicles === "function") {
208
- // initial station retrieval
209
- refreshVehicles(); // set up timer to refresh stations periodically
210
-
211
- this.refreshTimer = setInterval(function () {
212
- refreshVehicles();
213
- }, 30000); // defaults to every 30 sec. TODO: make this configurable?
214
- }
40
+ var VehicleRentalOverlay = function VehicleRentalOverlay(props) {
41
+ var _useMap = useMap(),
42
+ mainMap = _useMap.mainMap;
43
+
44
+ var zoom = mainMap === null || mainMap === void 0 ? void 0 : mainMap.getZoom();
45
+ var bounds = mainMap === null || mainMap === void 0 ? void 0 : mainMap.getBounds();
46
+ var configCompanies = props.configCompanies,
47
+ companies = props.companies,
48
+ getStationName = props.getStationName,
49
+ id = props.id,
50
+ refreshVehicles = props.refreshVehicles,
51
+ _setLocation = props.setLocation,
52
+ stations = props.stations,
53
+ visible = props.visible;
54
+ var layerId = "rental-vehicles-".concat(id);
55
+
56
+ var _useState = useState(null),
57
+ _useState2 = _slicedToArray(_useState, 2),
58
+ clickedVehicle = _useState2[0],
59
+ setClickedVehicle = _useState2[1];
60
+
61
+ useEffect(function () {
62
+ // TODO: Make 30s configurable?
63
+ if (!refreshVehicles || typeof refreshVehicles !== "function") {
64
+ return;
215
65
  }
216
- }, {
217
- key: "stopRefreshing",
218
- value: function stopRefreshing() {
219
- if (this.refreshTimer) clearInterval(this.refreshTimer);
220
- }
221
- /**
222
- * When the layer is added (or toggled on, or its visibility becomes true),
223
- * start refreshing vehicle positions.
224
- */
225
66
 
226
- }, {
227
- key: "componentDidMount",
228
- value:
229
- /**
230
- * Upon mounting, see whether the vehicles should be fetched,
231
- * and also call the register overlay prop that the
232
- * @opentripplanner/base-map package has injected to listen to zoom/position changes.
233
- */
234
- function componentDidMount() {
235
- var _this$props2 = this.props,
236
- leaflet = _this$props2.leaflet,
237
- registerOverlay = _this$props2.registerOverlay,
238
- visible = _this$props2.visible;
239
- this.setState({
240
- zoom: leaflet.map.getZoom()
67
+ refreshVehicles();
68
+ setInterval(refreshVehicles, 30000);
69
+ }, [refreshVehicles]);
70
+ useEffect(function () {
71
+ var VEHICLE_LAYERS = [layerId];
72
+ VEHICLE_LAYERS.forEach(function (stopLayer) {
73
+ mainMap === null || mainMap === void 0 ? void 0 : mainMap.on("mouseenter", stopLayer, function () {
74
+ mainMap.getCanvas().style.cursor = "pointer";
241
75
  });
242
- if (visible) this.startRefreshing();
243
-
244
- if (typeof registerOverlay === "function") {
245
- registerOverlay(this);
246
- }
247
- }
248
- }, {
249
- key: "componentWillUnmount",
250
- value: function componentWillUnmount() {
251
- this.stopRefreshing();
252
- }
253
- /**
254
- * Render some popup html for a station. This contains custom logic for
255
- * displaying rental vehicles in the TriMet MOD website that might not be
256
- * applicable to other regions.
257
- */
258
-
259
- }, {
260
- key: "render",
261
- value: function render() {
262
- var _this$props3 = this.props,
263
- companies = _this$props3.companies,
264
- leaflet = _this$props3.leaflet,
265
- mapSymbols = _this$props3.mapSymbols,
266
- stations = _this$props3.stations;
267
- var _this$state$zoom = this.state.zoom,
268
- zoom = _this$state$zoom === void 0 ? leaflet.map.getZoom() : _this$state$zoom; // Render an empty FeatureGroup if the rental vehicles should not be visible
269
- // on the map. Otherwise previous stations may still be shown due to some
270
- // react-leaflet internals, maybe? Also, do not return null because that will
271
- // prevent the overlay from appearing in the layer controls.
272
-
273
- var filteredStations = stations;
274
-
275
- if (companies) {
276
- filteredStations = stations.filter(function (station) {
277
- return station.networks.filter(function (value) {
278
- return companies.includes(value);
279
- }).length > 0;
280
- });
281
- }
76
+ mainMap === null || mainMap === void 0 ? void 0 : mainMap.on("mouseleave", stopLayer, function () {
77
+ mainMap.getCanvas().style.cursor = "";
78
+ });
79
+ mainMap === null || mainMap === void 0 ? void 0 : mainMap.on("click", stopLayer, function (event) {
80
+ var _event$features;
282
81
 
283
- if (!filteredStations || filteredStations.length === 0) {
284
- return /*#__PURE__*/React.createElement(FeatureGroup, null);
285
- } // Convert map symbols for this overlay to zoomBasedSymbolType.
82
+ setClickedVehicle((_event$features = event.features) === null || _event$features === void 0 ? void 0 : _event$features[0].properties);
83
+ });
84
+ });
85
+ }, [mainMap]); // Don't render if no map or no stops are defined.
286
86
 
87
+ if (visible === false || !stations || stations.length === 0) {
88
+ return /*#__PURE__*/React.createElement(React.Fragment, null);
89
+ }
287
90
 
288
- var symbols = this.convertToZoomMarkerSymbols(mapSymbols);
289
- return /*#__PURE__*/React.createElement(FeatureGroup, null, /*#__PURE__*/React.createElement(ZoomBasedMarkers, {
290
- entities: filteredStations,
291
- symbols: symbols,
292
- symbolTransform: this.renderSymbolWithPopup,
293
- zoom: zoom
294
- }));
91
+ var vehiclesGeoJSON = {
92
+ type: "FeatureCollection",
93
+ features: stations.filter(function (vehicle) {
94
+ return (// Include specified companies only if companies is specified and network info is available
95
+ !companies || !vehicle.networks || companies.includes(vehicle.networks[0])
96
+ );
97
+ }).map(function (vehicle) {
98
+ return {
99
+ type: "Feature",
100
+ properties: _objectSpread(_objectSpread({}, vehicle), {}, {
101
+ networks: JSON.stringify(vehicle.networks),
102
+ "stroke-width": vehicle.isFloatingBike || vehicle.isFloatingVehicle ? 1 : 2,
103
+ color: getColorForStation(vehicle)
104
+ }),
105
+ geometry: {
106
+ type: "Point",
107
+ coordinates: [vehicle.x, vehicle.y]
108
+ }
109
+ };
110
+ })
111
+ };
112
+ return /*#__PURE__*/React.createElement(React.Fragment, null, zoom < DETAILED_MARKER_CUTOFF && /*#__PURE__*/React.createElement(Source, {
113
+ type: "geojson",
114
+ data: vehiclesGeoJSON
115
+ }, /*#__PURE__*/React.createElement(Layer, {
116
+ id: layerId,
117
+ type: "circle",
118
+ paint: {
119
+ "circle-color": ["get", "color"],
120
+ "circle-opacity": 0.9,
121
+ "circle-stroke-width": ["get", "stroke-width"],
122
+ "circle-stroke-color": "#333"
295
123
  }
296
- }]);
297
-
298
- return VehicleRentalOverlay;
299
- }(MapLayer);
300
-
301
- VehicleRentalOverlay.props = {
302
- /**
303
- * The entire companies config array.
304
- */
305
- // configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)
306
- // .isRequired,
307
-
308
- /**
309
- * A list of companies that are applicable to just this instance of the
310
- * overlay.
311
- */
312
- companies: PropTypes.arrayOf(PropTypes.string.isRequired),
313
-
314
- /**
315
- * An optional custom function to create a string name of a particular vehicle
316
- * rental station. This function takes two arguments of the configCompanies
317
- * prop and a vehicle rental station. The function must return a string.
318
- */
319
- getStationName: PropTypes.func,
320
-
321
- /**
322
- * A configuration of what map markers or symbols to show at various
323
- * zoom levels.
324
- */
325
- // mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
326
-
327
- /**
328
- * If specified, a function that will be triggered every 30 seconds whenever this layer is
329
- * visible.
330
- */
331
- refreshVehicles: PropTypes.func,
332
-
333
- /**
334
- * A callback for when a user clicks on setting this stop as either the from
335
- * or to location of a new search.
336
- *
337
- * This will be dispatched with the following argument:
338
- *
339
- * ```js
340
- * {
341
- * location: {
342
- * lat: number,
343
- * lon: number,
344
- * name: string
345
- * },
346
- * locationType: "from" or "to"
347
- * }
348
- * ```
349
- */
350
- setLocation: PropTypes.func.isRequired,
351
-
352
- /**
353
- * A list of the vehicle rental stations specific to this overlay instance.
354
- */
355
- // stations: PropTypes.arrayOf(coreUtils.types.stationType),
356
-
357
- /**
358
- * Whether the overlay is currently visible.
359
- */
360
- visible: PropTypes.bool
124
+ })), zoom >= DETAILED_MARKER_CUTOFF && stations.filter(function (station) {
125
+ return checkIfPositionInViewport(bounds, station.y, station.x);
126
+ }).map(function (station) {
127
+ return /*#__PURE__*/React.createElement(MarkerWithPopup, {
128
+ key: station.id,
129
+ position: [station.y, station.x],
130
+ popupContents: /*#__PURE__*/React.createElement(StationPopup, {
131
+ configCompanies: configCompanies,
132
+ setLocation: function setLocation(location) {
133
+ setClickedVehicle(null);
134
+
135
+ _setLocation(location);
136
+ },
137
+ getStationName: getStationName,
138
+ station: station
139
+ })
140
+ }, station.bikesAvailable !== undefined && !station.isFloatingBike && !station.isFloatingVehicle && station.spacesAvailable !== undefined ? /*#__PURE__*/React.createElement(BaseBikeRentalIcon, {
141
+ percent: (station === null || station === void 0 ? void 0 : station.bikesAvailable) / ((station === null || station === void 0 ? void 0 : station.bikesAvailable) + (station === null || station === void 0 ? void 0 : station.spacesAvailable))
142
+ }) : /*#__PURE__*/React.createElement(StationMarker, {
143
+ width: 12,
144
+ color: getColorForStation(station)
145
+ }));
146
+ }), clickedVehicle && /*#__PURE__*/React.createElement(Popup, {
147
+ onClose: function onClose() {
148
+ setClickedVehicle(null);
149
+ },
150
+ longitude: clickedVehicle.x,
151
+ latitude: clickedVehicle.y,
152
+ maxWidth: "100%"
153
+ }, /*#__PURE__*/React.createElement(StationPopup, {
154
+ configCompanies: configCompanies,
155
+ setLocation: function setLocation(location) {
156
+ setClickedVehicle(null);
157
+
158
+ _setLocation(location);
159
+ },
160
+ getStationName: getStationName,
161
+ station: _objectSpread(_objectSpread({}, clickedVehicle), {}, {
162
+ networks: JSON.parse(clickedVehicle.networks)
163
+ })
164
+ })));
361
165
  };
362
- VehicleRentalOverlay.defaultProps = {
363
- getStationName: null,
364
- mapSymbols: [{
365
- zoom: 0,
366
- symbol: GenericMarker
367
- }],
368
- refreshVehicles: null,
369
- stations: [],
370
- visible: false
371
- };
372
- export default withLeaflet(injectIntl(VehicleRentalOverlay));
166
+
167
+ export default VehicleRentalOverlay;
373
168
  //# sourceMappingURL=index.js.map