@geops/rvf-mobility-web-component 0.1.56 → 0.1.57

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 (123) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/docutils.js +1 -1
  3. package/global.d.ts +1 -0
  4. package/iframe.html +15 -0
  5. package/index.html +2 -1
  6. package/index.js +278 -330
  7. package/package.json +16 -17
  8. package/src/{RvfExportMenu/RvfExportMenu.tsx → ExportMenu/ExportMenu.tsx} +11 -11
  9. package/src/ExportMenu/index.tsx +1 -0
  10. package/src/{RvfExportMenuButton/RvfExportMenuButton.tsx → ExportMenuButton/ExportMenuButton.tsx} +5 -5
  11. package/src/ExportMenuButton/index.tsx +1 -0
  12. package/src/FeatureDetails/FeatureDetails.tsx +57 -0
  13. package/src/FeatureDetails/index.ts +1 -0
  14. package/src/FeaturesInfosListener/FeaturesInfosListener.tsx +73 -0
  15. package/src/FeaturesInfosListener/index.tsx +1 -0
  16. package/src/GeolocationButton/GeolocationButton.tsx +0 -1
  17. package/src/LayerTree/LayerTree.tsx +58 -0
  18. package/src/LayerTree/TreeItem/TreeItem.tsx +151 -0
  19. package/src/LayerTree/TreeItem/index.tsx +1 -0
  20. package/src/LayerTree/index.tsx +1 -0
  21. package/src/LayerTree/layersTreeContext.ts +4 -0
  22. package/src/LayerTree/layersTreeReducer.ts +158 -0
  23. package/src/{RvfLayerTreeButton/RvfLayerTreeButton.tsx → LayerTreeButton/LayerTreeButton.tsx} +5 -5
  24. package/src/LayerTreeButton/index.tsx +1 -0
  25. package/src/{RvfTopics/RvfTopics.tsx → LayerTreeMenu/LayerTreeMenu.tsx} +17 -13
  26. package/src/LayerTreeMenu/index.tsx +1 -0
  27. package/src/LayoutState/LayoutState.tsx +277 -0
  28. package/src/LayoutState/index.tsx +1 -0
  29. package/src/LinesNetworkPlanDetails/LinesNetworkPlanDetails.tsx +292 -0
  30. package/src/LinesNetworkPlanDetails/index.tsx +1 -0
  31. package/src/{RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx → LinesNetworkPlanLayer/LinesNetworkPlanLayer.tsx} +7 -9
  32. package/src/LinesNetworkPlanLayer/index.tsx +1 -0
  33. package/src/MobilityMap/MobilityMap.tsx +274 -60
  34. package/src/MobilityMap/MobilityMapAttributes.ts +27 -43
  35. package/src/NotificationDetails/NotificationDetails.tsx +468 -0
  36. package/src/NotificationDetails/index.ts +1 -0
  37. package/src/{NotificationLayer/NotificationLayer.tsx → NotificationsLayer/NotificationsLayer.tsx} +9 -4
  38. package/src/NotificationsLayer/index.tsx +1 -0
  39. package/src/Overlay/Overlay.tsx +1 -6
  40. package/src/OverlayContent/OverlayContent.tsx +87 -0
  41. package/src/OverlayContent/index.ts +1 -0
  42. package/src/OverlayDetails/OverlayDetails.tsx +47 -0
  43. package/src/OverlayDetails/index.ts +1 -0
  44. package/src/OverlayDetailsFooter/OverlayDetailsFooter.tsx +51 -0
  45. package/src/OverlayDetailsFooter/index.tsx +1 -0
  46. package/src/OverlayDetailsHeader/OverlayDetailsHeader.tsx +35 -0
  47. package/src/OverlayDetailsHeader/index.ts +1 -0
  48. package/src/OverlayFooter/OverlayFooter.tsx +41 -0
  49. package/src/OverlayFooter/index.tsx +1 -0
  50. package/src/OverlayHeader/OverlayHeader.tsx +44 -0
  51. package/src/OverlayHeader/index.tsx +1 -0
  52. package/src/PermalinkInput/PermalinkInput.tsx +28 -0
  53. package/src/PermalinkInput/index.tsx +1 -0
  54. package/src/RouteSchedule/RouteSchedule.tsx +22 -18
  55. package/src/RvfFeatureDetails/RvfFeatureDetails.tsx +22 -50
  56. package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +108 -104
  57. package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +189 -154
  58. package/src/RvfFeatureDetails/RvfSharedMobilityDetail/RvfSharedMobilityDetails.tsx +12 -14
  59. package/src/RvfFeatureDetailsTitle/RvfFeatureDetailsTitle.tsx +5 -5
  60. package/src/RvfMainLinkButton/RvfMainLinkButton.tsx +65 -0
  61. package/src/RvfMainLinkButton/index.tsx +1 -0
  62. package/src/RvfMobilityMap/RvfMobilityMap.tsx +182 -394
  63. package/src/RvfOverlayContent/RvfOverlayContent.tsx +2 -2
  64. package/src/RvfPoisLayer/RvfPoisLayer.tsx +2 -2
  65. package/src/RvfSearch/RvfSearch.tsx +1 -1
  66. package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +2 -2
  67. package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +23 -23
  68. package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +2 -2
  69. package/src/Search/Search.tsx +11 -2
  70. package/src/{RvfSearchButton/RvfSearchButton.tsx → SearchButton/SearchButton.tsx} +5 -5
  71. package/src/SearchButton/index.tsx +1 -0
  72. package/src/ShadowOverflow/ShadowOverflow.tsx +20 -0
  73. package/src/ShadowOverflow/index.tsx +1 -0
  74. package/src/{RvfShare/RvfPermalinkButton/RvfPermalinkButton.tsx → ShareMenu/PermalinkButton/PermalinkButton.tsx} +4 -4
  75. package/src/ShareMenu/PermalinkButton/index.tsx +1 -0
  76. package/src/{RvfShare/RvfShare.tsx → ShareMenu/ShareMenu.tsx} +9 -11
  77. package/src/ShareMenu/index.tsx +1 -0
  78. package/src/{RvfShareMenuButton/RvfShareMenuButton.tsx → ShareMenuButton/ShareMenuButton.tsx} +6 -6
  79. package/src/ShareMenuButton/index.tsx +1 -0
  80. package/src/SingleClickListener/SingleClickListener.tsx +55 -113
  81. package/src/SingleClickListener/index.tsx +1 -1
  82. package/src/Station/Station.tsx +10 -3
  83. package/src/StationsLayer/StationsLayer.tsx +0 -1
  84. package/src/StopsSearch/StopsSearch.tsx +3 -4
  85. package/src/StopsSearch/index.tsx +2 -1
  86. package/src/WindowMessageListener/WindowMessageListener.tsx +7 -1
  87. package/src/{RvfZoomButtons/RvfZoomButtons.tsx → ZoomButtons/ZoomButtons.tsx} +9 -12
  88. package/src/ZoomButtons/index.tsx +1 -0
  89. package/src/icons/Geolocation/airport-14-svgrepo-com.svg +41 -0
  90. package/src/ui/Button/Button.tsx +9 -2
  91. package/src/ui/Checkbox/Checkbox.tsx +32 -0
  92. package/src/ui/Checkbox/index.tsx +1 -0
  93. package/src/ui/IconButton/IconButton.tsx +24 -4
  94. package/src/ui/Input/Input.tsx +17 -0
  95. package/src/ui/Input/index.tsx +1 -0
  96. package/src/ui/InputCopy/InputCopy.tsx +86 -0
  97. package/src/ui/InputCopy/index.tsx +1 -0
  98. package/src/ui/Select/Select.tsx +24 -0
  99. package/src/ui/Select/index.tsx +1 -0
  100. package/src/utils/constants.ts +43 -42
  101. package/src/utils/hooks/useInitialLayersVisiblity.tsx +1 -1
  102. package/src/utils/hooks/useLayerConfig.tsx +2 -2
  103. package/src/utils/hooks/useLayersConfig.tsx +3 -3
  104. package/src/utils/hooks/useMapContext.tsx +67 -8
  105. package/src/utils/hooks/useRvfContext.tsx +0 -44
  106. package/src/NotificationLayer/index.tsx +0 -1
  107. package/src/RvfEmbedNavigation/DragPanWarning.ts +0 -124
  108. package/src/RvfEmbedNavigation/RvfEmbedNavigation.tsx +0 -51
  109. package/src/RvfEmbedNavigation/index.js +0 -1
  110. package/src/RvfExportMenu/index.tsx +0 -1
  111. package/src/RvfExportMenuButton/index.tsx +0 -1
  112. package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +0 -44
  113. package/src/RvfFloatingMenu/index.tsx +0 -1
  114. package/src/RvfLayerTreeButton/index.tsx +0 -1
  115. package/src/RvfLineNetworkPlanLayer/index.tsx +0 -1
  116. package/src/RvfPermalink/RvfPermalink.tsx +0 -18
  117. package/src/RvfPermalink/index.tsx +0 -1
  118. package/src/RvfSearchButton/index.tsx +0 -1
  119. package/src/RvfShare/RvfPermalinkButton/index.tsx +0 -1
  120. package/src/RvfShare/index.tsx +0 -1
  121. package/src/RvfShareMenuButton/index.tsx +0 -1
  122. package/src/RvfTopics/index.tsx +0 -1
  123. package/src/RvfZoomButtons/index.tsx +0 -1
@@ -10,7 +10,7 @@ import RvfShare from "../RvfShare";
10
10
  import RvfTopics from "../RvfTopics";
11
11
  import Search from "../Search";
12
12
  import Station from "../Station";
13
- import { RVF_LAYERS_TITLES } from "../utils/constants";
13
+ import { LAYERS_TITLES } from "../utils/constants";
14
14
  import useMapContext from "../utils/hooks/useMapContext";
15
15
  import useRvfContext from "../utils/hooks/useRvfContext";
16
16
 
@@ -52,7 +52,7 @@ function RvfOverlayContent({
52
52
  onClose={() => {
53
53
  setTrainId(null);
54
54
  }}
55
- title={RVF_LAYERS_TITLES.echtzeit}
55
+ title={LAYERS_TITLES.echtzeit}
56
56
  ></RvfOverlayHeader>
57
57
  <RouteSchedule className={contentClassName} />
58
58
  </>
@@ -2,7 +2,7 @@ import { MaplibreStyleLayer } from "mobility-toolbox-js/ol";
2
2
  import { memo } from "preact/compat";
3
3
  import { useEffect, useMemo } from "preact/hooks";
4
4
 
5
- import { RVF_LAYERS_NAMES } from "../utils/constants";
5
+ import { LAYERS_NAMES } from "../utils/constants";
6
6
  import useMapContext from "../utils/hooks/useMapContext";
7
7
  import useRvfContext from "../utils/hooks/useRvfContext";
8
8
 
@@ -21,7 +21,7 @@ function RvfPoisLayer(props: MaplibreStyleLayerOptions) {
21
21
  return metadata?.["mapset.filter"] === "mapset_poi";
22
22
  },
23
23
  maplibreLayer: baseLayer,
24
- name: RVF_LAYERS_NAMES.pois,
24
+ name: LAYERS_NAMES.pois,
25
25
  visible: false,
26
26
  ...(props || {}),
27
27
  });
@@ -8,7 +8,7 @@ import useMapContext from "../utils/hooks/useMapContext";
8
8
 
9
9
  import type { StopsSearchProps } from "../StopsSearch/StopsSearch";
10
10
 
11
- function RvfSearch(props: StopsSearchProps) {
11
+ function RvfSearch(props: Partial<StopsSearchProps>) {
12
12
  const { apikey, map, stopsurl } = useMapContext();
13
13
 
14
14
  const onSelect = useCallback(
@@ -5,7 +5,7 @@ import { useEffect, useMemo } from "preact/hooks";
5
5
  import Automat from "../icons/Automat";
6
6
  import InPerson from "../icons/InPerson";
7
7
  import Video from "../icons/Video";
8
- import { RVF_LAYERS_NAMES } from "../utils/constants";
8
+ import { LAYERS_NAMES } from "../utils/constants";
9
9
  import useMapContext from "../utils/hooks/useMapContext";
10
10
  import useRvfContext from "../utils/hooks/useRvfContext";
11
11
 
@@ -26,7 +26,7 @@ function RvfSellingPointsLayer(props: MaplibreStyleLayerOptions) {
26
26
  return metadata?.["general.filter"] === "selling_points";
27
27
  },
28
28
  maplibreLayer: baseLayer,
29
- name: RVF_LAYERS_NAMES.verkaufsstellen,
29
+ name: LAYERS_NAMES.verkaufsstellen,
30
30
  ...(props || {}),
31
31
 
32
32
  title: (
@@ -15,8 +15,8 @@ import {
15
15
  CAR_FORM_FACTOR,
16
16
  CARGOBIKE_FORM_FACTOR,
17
17
  LAYER_PROP_IS_EXPORTING,
18
+ LAYERS_NAMES,
18
19
  RVF_EXTENT_4326,
19
- RVF_LAYERS_NAMES,
20
20
  SCOOTER_FORM_FACTOR,
21
21
  SOURCE_FREE_FLOAT_BIKE,
22
22
  SOURCE_FREE_FLOAT_CAR,
@@ -180,7 +180,7 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
180
180
  }, [map, updateData, mbMap]);
181
181
 
182
182
  useEffect(() => {
183
- if (!mbMap || !stationsData) {
183
+ if (!mbMap?.style || !stationsData) {
184
184
  return;
185
185
  }
186
186
  const source = mbMap.getSource(SOURCE_SHARING_STATIONS);
@@ -188,7 +188,7 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
188
188
  }, [stationsData, mbMap]);
189
189
 
190
190
  useEffect(() => {
191
- if (!mbMap || !bikeFreeFloatData) {
191
+ if (!mbMap?.style || !bikeFreeFloatData) {
192
192
  return;
193
193
  }
194
194
  const source = mbMap.getSource(SOURCE_FREE_FLOAT_BIKE);
@@ -196,7 +196,7 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
196
196
  }, [mbMap, bikeFreeFloatData]);
197
197
 
198
198
  useEffect(() => {
199
- if (!mbMap || !cargoBikeFreeFloatData) {
199
+ if (!mbMap?.style || !cargoBikeFreeFloatData) {
200
200
  return;
201
201
  }
202
202
  const source = mbMap.getSource(SOURCE_FREE_FLOAT_CARGO_BIKE);
@@ -204,7 +204,7 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
204
204
  }, [mbMap, cargoBikeFreeFloatData]);
205
205
 
206
206
  useEffect(() => {
207
- if (!mbMap || !carFreeFloatData) {
207
+ if (!mbMap?.style || !carFreeFloatData) {
208
208
  return;
209
209
  }
210
210
  const source = mbMap.getSource(SOURCE_FREE_FLOAT_CAR);
@@ -212,7 +212,7 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
212
212
  }, [mbMap, carFreeFloatData]);
213
213
 
214
214
  useEffect(() => {
215
- if (!mbMap || !scooterFreeFloatData) {
215
+ if (!mbMap?.style || !scooterFreeFloatData) {
216
216
  return;
217
217
  }
218
218
  const source = mbMap.getSource(SOURCE_FREE_FLOAT_SCOOTER);
@@ -235,7 +235,7 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
235
235
 
236
236
  const bikeFrelo = new MaplibreStyleLayer({
237
237
  maplibreLayer: baseLayer,
238
- name: RVF_LAYERS_NAMES.bikeFrelo,
238
+ name: LAYERS_NAMES.bikeFrelo,
239
239
  styleLayersFilter: ({ metadata }) => {
240
240
  return metadata?.["rvf.filter"] === "bike.frelo";
241
241
  },
@@ -251,13 +251,13 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
251
251
 
252
252
  const bikeOthers = new MaplibreStyleLayer({
253
253
  maplibreLayer: baseLayer,
254
- name: RVF_LAYERS_NAMES.bikeOthers,
254
+ name: LAYERS_NAMES.bikeOthers,
255
255
  styleLayersFilter: ({ metadata }) => {
256
256
  return metadata?.["rvf.filter"] === "bike.other";
257
257
  },
258
258
  title: (
259
259
  <div className="flex items-center justify-between gap-2">
260
- {layersConfig[RVF_LAYERS_NAMES.bikeOthers]?.title}
260
+ {layersConfig[LAYERS_NAMES.bikeOthers]?.title}
261
261
  <Bicycle />
262
262
  </div>
263
263
  ),
@@ -269,10 +269,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
269
269
  return metadata?.["rvf.filter"] === "cargo_bike.frelo";
270
270
  },
271
271
  maplibreLayer: baseLayer,
272
- name: RVF_LAYERS_NAMES.cargobikeFrelo,
272
+ name: LAYERS_NAMES.cargobikeFrelo,
273
273
  title: (
274
274
  <div className="flex items-center justify-between gap-2">
275
- {layersConfig[RVF_LAYERS_NAMES.cargobikeFrelo]?.title}
275
+ {layersConfig[LAYERS_NAMES.cargobikeFrelo]?.title}
276
276
  <CargoBike />
277
277
  </div>
278
278
  ),
@@ -284,10 +284,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
284
284
  return metadata?.["rvf.filter"] === "cargo_bike.other";
285
285
  },
286
286
  maplibreLayer: baseLayer,
287
- name: RVF_LAYERS_NAMES.cargobikeOthers,
287
+ name: LAYERS_NAMES.cargobikeOthers,
288
288
  title: (
289
289
  <div className="flex items-center justify-between gap-2">
290
- {layersConfig[RVF_LAYERS_NAMES.cargobikeOthers]?.title}
290
+ {layersConfig[LAYERS_NAMES.cargobikeOthers]?.title}
291
291
  <CargoBike />
292
292
  </div>
293
293
  ),
@@ -299,10 +299,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
299
299
  return metadata?.["rvf.filter"] === "car.grueneflotte";
300
300
  },
301
301
  maplibreLayer: baseLayer,
302
- name: RVF_LAYERS_NAMES.carGrf,
302
+ name: LAYERS_NAMES.carGrf,
303
303
  title: (
304
304
  <div className="flex items-center justify-between gap-2">
305
- {layersConfig[RVF_LAYERS_NAMES.carGrf]?.title}
305
+ {layersConfig[LAYERS_NAMES.carGrf]?.title}
306
306
  <Car />
307
307
  </div>
308
308
  ),
@@ -314,10 +314,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
314
314
  return metadata?.["rvf.filter"] === "car.naturenergy";
315
315
  },
316
316
  maplibreLayer: baseLayer,
317
- name: RVF_LAYERS_NAMES.carNatur,
317
+ name: LAYERS_NAMES.carNatur,
318
318
  title: (
319
319
  <div className="flex items-center justify-between gap-2">
320
- {layersConfig[RVF_LAYERS_NAMES.carNatur]?.title}
320
+ {layersConfig[LAYERS_NAMES.carNatur]?.title}
321
321
  <Car />
322
322
  </div>
323
323
  ),
@@ -329,10 +329,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
329
329
  return metadata?.["rvf.filter"] === "car.other";
330
330
  },
331
331
  maplibreLayer: baseLayer,
332
- name: RVF_LAYERS_NAMES.carOthers,
332
+ name: LAYERS_NAMES.carOthers,
333
333
  title: (
334
334
  <div className="flex items-center justify-between gap-2">
335
- {layersConfig[RVF_LAYERS_NAMES.carOthers]?.title}
335
+ {layersConfig[LAYERS_NAMES.carOthers]?.title}
336
336
  <Car />
337
337
  </div>
338
338
  ),
@@ -344,10 +344,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
344
344
  return metadata?.["rvf.filter"] === "scooter";
345
345
  },
346
346
  maplibreLayer: baseLayer,
347
- name: RVF_LAYERS_NAMES.eroller,
347
+ name: LAYERS_NAMES.eroller,
348
348
  title: (
349
349
  <div className="flex items-center justify-between gap-2">
350
- {layersConfig[RVF_LAYERS_NAMES.eroller]?.title}
350
+ {layersConfig[LAYERS_NAMES.eroller]?.title}
351
351
  <Scooter />
352
352
  </div>
353
353
  ),
@@ -359,10 +359,10 @@ function RvfSharedMobilityLayerGroup(props: GroupOptions) {
359
359
  return metadata?.["rvf.filter"] === "hitchhiking";
360
360
  },
361
361
  maplibreLayer: baseLayer,
362
- name: RVF_LAYERS_NAMES.mitfahrpunkte,
362
+ name: LAYERS_NAMES.mitfahrpunkte,
363
363
  title: (
364
364
  <div className="flex items-center justify-between gap-2">
365
- {layersConfig[RVF_LAYERS_NAMES.mitfahrpunkte]?.title}
365
+ {layersConfig[LAYERS_NAMES.mitfahrpunkte]?.title}
366
366
  <Ride />
367
367
  </div>
368
368
  ),
@@ -2,7 +2,7 @@ import { MaplibreStyleLayer } from "mobility-toolbox-js/ol";
2
2
  import { memo } from "preact/compat";
3
3
  import { useEffect, useMemo } from "preact/hooks";
4
4
 
5
- import { RVF_LAYERS_NAMES } from "../utils/constants";
5
+ import { LAYERS_NAMES } from "../utils/constants";
6
6
  import useMapContext from "../utils/hooks/useMapContext";
7
7
  import useRvfContext from "../utils/hooks/useRvfContext";
8
8
 
@@ -22,7 +22,7 @@ function RvfTarifZonenLayer(props: MaplibreStyleLayerOptions) {
22
22
  return metadata?.["rvf.filter"] === "zones";
23
23
  },
24
24
  maplibreLayer: baseLayer,
25
- name: RVF_LAYERS_NAMES.tarifzonen,
25
+ name: LAYERS_NAMES.tarifzonen,
26
26
  ...(props || {}),
27
27
  });
28
28
  }, [baseLayer, props]);
@@ -5,7 +5,9 @@ import StopsSearch from "../StopsSearch";
5
5
  import centerOnStation from "../utils/centerOnStation";
6
6
  import useMapContext from "../utils/hooks/useMapContext";
7
7
 
8
- function Search() {
8
+ import type { StopsSearchProps } from "../StopsSearch/StopsSearch";
9
+
10
+ function Search(props: StopsSearchProps) {
9
11
  const { apikey, map, stopsurl } = useMapContext();
10
12
 
11
13
  const onSelect = useCallback(
@@ -15,6 +17,13 @@ function Search() {
15
17
  [map],
16
18
  );
17
19
 
18
- return <StopsSearch apikey={apikey} onselect={onSelect} url={stopsurl} />;
20
+ return (
21
+ <StopsSearch
22
+ apikey={apikey}
23
+ onselect={onSelect}
24
+ url={stopsurl}
25
+ {...props}
26
+ />
27
+ );
19
28
  }
20
29
  export default memo(Search);
@@ -3,15 +3,15 @@ import { useCallback } from "preact/hooks";
3
3
 
4
4
  import Search from "../icons/Search";
5
5
  import IconButton from "../ui/IconButton";
6
- import useRvfContext from "../utils/hooks/useRvfContext";
6
+ import useMapContext from "../utils/hooks/useMapContext";
7
7
 
8
8
  import type { HTMLAttributes, PreactDOMAttributes } from "preact";
9
9
 
10
- export type RvfLayerTreeButtonProps = HTMLAttributes<HTMLButtonElement> &
10
+ export type SearchButtonProps = HTMLAttributes<HTMLButtonElement> &
11
11
  PreactDOMAttributes;
12
12
 
13
- function RvfSearchButton({ ...props }: RvfLayerTreeButtonProps) {
14
- const { isSearchOpen, setIsSearchOpen } = useRvfContext();
13
+ function SearchButton({ ...props }: SearchButtonProps) {
14
+ const { isSearchOpen, setIsSearchOpen } = useMapContext();
15
15
 
16
16
  const onClick = useCallback(() => {
17
17
  setIsSearchOpen(!isSearchOpen);
@@ -24,4 +24,4 @@ function RvfSearchButton({ ...props }: RvfLayerTreeButtonProps) {
24
24
  );
25
25
  }
26
26
 
27
- export default memo(RvfSearchButton);
27
+ export default memo(SearchButton);
@@ -0,0 +1 @@
1
+ export { default } from "./SearchButton";
@@ -0,0 +1,20 @@
1
+ import { memo } from "preact/compat";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ import type { PreactDOMAttributes } from "preact";
5
+
6
+ function ShadowOverflow({
7
+ children,
8
+ className,
9
+ ...props
10
+ }: { className?: string } & PreactDOMAttributes) {
11
+ return (
12
+ <div {...props} className={twMerge("relative overflow-y-auto", className)}>
13
+ <div className="pointer-events-none sticky top-0 right-0 left-0 h-4 bg-gradient-to-t from-transparent to-white"></div>
14
+ {children}
15
+ <div className="pointer-events-none sticky right-0 bottom-[-1px] left-0 h-4 bg-gradient-to-b from-transparent to-white"></div>
16
+ </div>
17
+ );
18
+ }
19
+
20
+ export default memo(ShadowOverflow);
@@ -0,0 +1 @@
1
+ export { default } from "./ShadowOverflow";
@@ -1,13 +1,13 @@
1
1
  import { useState } from "preact/hooks";
2
2
 
3
3
  import Cancel from "../../icons/Cancel";
4
- import Share from "../../icons/Share";
4
+ import ShareMenu from "../../icons/ShareMenu";
5
5
  import RvfInputCopy from "../../RvfInputCopy";
6
6
  import IconButton from "../../ui/IconButton";
7
7
 
8
8
  import type { ButtonHTMLAttributes, PreactDOMAttributes } from "preact";
9
9
 
10
- function RvfPermalinkButton({
10
+ function PermalinkButton({
11
11
  className,
12
12
  ...props
13
13
  }: { className?: string } & ButtonHTMLAttributes<HTMLButtonElement> &
@@ -28,7 +28,7 @@ function RvfPermalinkButton({
28
28
  selected={showTooltip}
29
29
  {...props}
30
30
  >
31
- <Share />
31
+ <ShareMenu />
32
32
  </IconButton>
33
33
 
34
34
  {showTooltip && positionTooltip && (
@@ -59,4 +59,4 @@ function RvfPermalinkButton({
59
59
  );
60
60
  }
61
61
 
62
- export default RvfPermalinkButton;
62
+ export default PermalinkButton;
@@ -0,0 +1 @@
1
+ export { default } from "./PermalinkButton";
@@ -3,13 +3,13 @@ import { twMerge } from "tailwind-merge";
3
3
 
4
4
  import Email from "../icons/Email";
5
5
  import Image from "../icons/Image";
6
- import RvfPermalink from "../RvfPermalink";
6
+ import PermalinkInput from "../PermalinkInput";
7
7
  import Button from "../ui/Button";
8
8
  import useMapContext from "../utils/hooks/useMapContext";
9
9
 
10
10
  import type { HTMLAttributes, PreactDOMAttributes } from "preact";
11
11
 
12
- function RvfShare({
12
+ function ShareMenu({
13
13
  className = "",
14
14
  ...props
15
15
  }: HTMLAttributes<HTMLDivElement> & PreactDOMAttributes) {
@@ -18,24 +18,22 @@ function RvfShare({
18
18
  return (
19
19
  // eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
20
20
  <div className={twMerge(`flex flex-col gap-4 ${className}`)} {...props}>
21
- <a
22
- className="flex items-center gap-2"
21
+ <Button
22
+ className="w-fit"
23
23
  href={`mailto:?subject=Karte&body=${window?.location.href}`}
24
24
  >
25
- <Button>
26
- <Email />
27
- <span>Email senden</span>
28
- </Button>
29
- </a>
25
+ <Email />
26
+ <span>Email senden</span>
27
+ </Button>
30
28
  <CanvasSaveButton map={map}>
31
29
  <Button className={"w-fit"}>
32
30
  <Image />
33
31
  <span>Bild speichern</span>
34
32
  </Button>
35
33
  </CanvasSaveButton>
36
- <RvfPermalink />
34
+ <PermalinkInput />
37
35
  </div>
38
36
  );
39
37
  }
40
38
 
41
- export default RvfShare;
39
+ export default ShareMenu;
@@ -0,0 +1 @@
1
+ export { default } from "./ShareMenu";
@@ -3,15 +3,15 @@ import { useCallback } from "preact/hooks";
3
3
 
4
4
  import Share from "../icons/Share";
5
5
  import IconButton from "../ui/IconButton";
6
- import useRvfContext from "../utils/hooks/useRvfContext";
6
+ import useMapContext from "../utils/hooks/useMapContext";
7
7
 
8
- import type { JSX, PreactDOMAttributes } from "preact";
8
+ import type { HTMLAttributes, PreactDOMAttributes } from "preact";
9
9
 
10
- export type RvfShareMenuButtonProps = JSX.HTMLAttributes<HTMLButtonElement> &
10
+ export type RvfShareMenuButtonProps = HTMLAttributes<HTMLButtonElement> &
11
11
  PreactDOMAttributes;
12
12
 
13
- function RvfShareMenuButton({ ...props }: RvfShareMenuButtonProps) {
14
- const { isShareMenuOpen, setIsShareMenuOpen } = useRvfContext();
13
+ function ShareMenuButton({ ...props }: RvfShareMenuButtonProps) {
14
+ const { isShareMenuOpen, setIsShareMenuOpen } = useMapContext();
15
15
 
16
16
  const onClick = useCallback(() => {
17
17
  setIsShareMenuOpen(!isShareMenuOpen);
@@ -24,4 +24,4 @@ function RvfShareMenuButton({ ...props }: RvfShareMenuButtonProps) {
24
24
  );
25
25
  }
26
26
 
27
- export default memo(RvfShareMenuButton);
27
+ export default memo(ShareMenuButton);
@@ -0,0 +1 @@
1
+ export { default } from "./ShareMenuButton";
@@ -1,130 +1,65 @@
1
+ import debounce from "lodash.debounce";
2
+ import { getFeatureInfoAtCoordinate } from "mobility-toolbox-js/ol";
1
3
  import { unByKey } from "ol/Observable";
2
4
  import { useCallback, useEffect } from "preact/hooks";
3
5
 
4
6
  import useMapContext from "../utils/hooks/useMapContext";
5
7
 
6
- import type { Feature, MapBrowserEvent } from "ol";
8
+ import type { DebounceSettings } from "lodash";
9
+ import type { MapBrowserEvent } from "ol";
10
+ import type { EventsKey } from "ol/events";
7
11
 
8
- function SingleClickListener() {
9
- const {
10
- map,
11
- // queryablelayers,
12
- realtimeLayer,
13
- setSelectedFeature,
14
- setSelectedFeatures,
15
- setStationId,
16
- setTrainId,
17
- stationId,
18
- stationsLayer,
19
- tenant,
20
- trainId,
21
- } = useMapContext();
22
-
23
- const onPointerMove = useCallback(
24
- (evt: MapBrowserEvent<PointerEvent>) => {
25
- const [realtimeFeature] = evt.map.getFeaturesAtPixel(evt.pixel, {
26
- hitTolerance: 5,
27
- layerFilter: (l) => {
28
- return l === realtimeLayer;
29
- },
30
- });
31
- realtimeLayer?.highlight(realtimeFeature as Feature);
12
+ export interface SingleClickListenerProps {
13
+ debounceOptions?: DebounceSettings;
14
+ debounceTimeout?: number;
15
+ hover?: boolean;
16
+ }
32
17
 
33
- const stationsFeatures = evt.map.getFeaturesAtPixel(evt.pixel, {
34
- layerFilter: (l) => {
35
- return l === stationsLayer;
36
- },
18
+ function SingleClickListener({
19
+ debounceOptions,
20
+ debounceTimeout = 0,
21
+ hover = true,
22
+ }: SingleClickListenerProps) {
23
+ const { map, queryablelayers, setFeaturesInfos, setFeaturesInfosHovered } =
24
+ useMapContext();
25
+
26
+ const getFeaturesInfosAtEvt = useCallback(
27
+ async (evt: MapBrowserEvent<PointerEvent>) => {
28
+ const queryableLayers = evt.map.getAllLayers().filter((l) => {
29
+ return queryablelayers.split(",").includes(l.get("name"));
37
30
  });
31
+ const featuresInfos = await getFeatureInfoAtCoordinate(
32
+ evt.coordinate,
33
+ queryableLayers,
34
+ 5,
35
+ true,
36
+ );
37
+ return featuresInfos;
38
+ },
39
+ [queryablelayers],
40
+ );
38
41
 
39
- const [stationFeature] = stationsFeatures.filter((feat) => {
40
- return feat.get("tralis_network")?.includes(tenant);
42
+ const onPointerMove = useCallback(
43
+ async (evt: MapBrowserEvent<PointerEvent>) => {
44
+ const featureInfos = await getFeaturesInfosAtEvt(evt);
45
+ setFeaturesInfosHovered(featureInfos);
46
+ const features = featureInfos.flatMap((featureInfo) => {
47
+ return featureInfo.features;
41
48
  });
42
49
 
43
- // Send all the features under the cursor
44
- const features = evt.map.getFeaturesAtPixel(evt.pixel, {
45
- layerFilter: (l) => {
46
- return l.get("isQueryable");
47
- },
48
- }) as Feature[];
49
-
50
- evt.map.getTargetElement().style.cursor =
51
- realtimeFeature || stationFeature || features?.length
52
- ? "pointer"
53
- : "default";
50
+ evt.map.getTargetElement().style.cursor = features?.length
51
+ ? "pointer"
52
+ : "default";
54
53
  },
55
- [realtimeLayer, stationsLayer, tenant],
54
+ [getFeaturesInfosAtEvt, setFeaturesInfosHovered],
56
55
  );
57
56
 
58
57
  const onSingleClick = useCallback(
59
- (evt: MapBrowserEvent<PointerEvent>) => {
60
- // const qeryableLayers = queryablelayers?.split(",");
61
- // const featuress = evt.map.getFeaturesAtPixel(evt.pixel, {
62
- // layerFilter: (l) => {
63
- // return qeryableLayers
64
- // ? queryablelayers.includes(l.get("name"))
65
- // : true;
66
- // },
67
- // });
68
- // console.log("featursss", featuress);
69
-
70
- const [realtimeFeature] = evt.map.getFeaturesAtPixel(evt.pixel, {
71
- hitTolerance: 5,
72
- layerFilter: (l) => {
73
- return l === realtimeLayer;
74
- },
75
- });
76
-
77
- const stationsFeatures = evt.map.getFeaturesAtPixel(evt.pixel, {
78
- layerFilter: (l) => {
79
- return l === stationsLayer;
80
- },
81
- });
82
- const [stationFeature] = stationsFeatures.filter((feat) => {
83
- return feat.get("tralis_network")?.includes(tenant);
84
- });
85
-
86
- const newStationId = stationFeature?.get("uid");
87
-
88
- const newTrainId = realtimeFeature?.get("train_id");
89
-
90
- if (newStationId && stationId !== newStationId) {
91
- setStationId(newStationId);
92
- setTrainId(null);
93
- } else if (newTrainId && newTrainId !== trainId) {
94
- setTrainId(realtimeFeature.get("train_id"));
95
- setStationId(null);
96
- } else {
97
- setTrainId(null);
98
- setStationId(null);
99
- }
100
-
101
- // Send all the features under the cursor
102
- const features = evt.map.getFeaturesAtPixel(evt.pixel, {
103
- layerFilter: (l) => {
104
- return l.get("isQueryable");
105
- },
106
- }) as Feature[];
107
-
108
- if (newStationId || newTrainId || !features.length) {
109
- setSelectedFeature(null);
110
- setSelectedFeatures([]);
111
- } else {
112
- setSelectedFeatures(features);
113
- setSelectedFeature(features[0]);
114
- }
58
+ async (evt: MapBrowserEvent<PointerEvent>) => {
59
+ const featuresInfos = await getFeaturesInfosAtEvt(evt);
60
+ setFeaturesInfos(featuresInfos);
115
61
  },
116
- [
117
- // queryablelayers,
118
- stationId,
119
- trainId,
120
- realtimeLayer,
121
- stationsLayer,
122
- tenant,
123
- setStationId,
124
- setTrainId,
125
- setSelectedFeature,
126
- setSelectedFeatures,
127
- ],
62
+ [getFeaturesInfosAtEvt, setFeaturesInfos],
128
63
  );
129
64
 
130
65
  useEffect(() => {
@@ -135,11 +70,18 @@ function SingleClickListener() {
135
70
  }, [map, onSingleClick]);
136
71
 
137
72
  useEffect(() => {
138
- const key = map?.on("pointermove", onPointerMove);
73
+ let key: EventsKey;
74
+ if (hover) {
75
+ let debounced = onPointerMove;
76
+ if (debounceTimeout) {
77
+ debounced = debounce(onPointerMove, debounceTimeout, debounceOptions);
78
+ }
79
+ key = map?.on("pointermove", debounced);
80
+ }
139
81
  return () => {
140
82
  unByKey(key);
141
83
  };
142
- }, [map, onPointerMove]);
84
+ }, [debounceOptions, debounceTimeout, hover, map, onPointerMove]);
143
85
 
144
86
  return null;
145
87
  }
@@ -1 +1 @@
1
- export { default } from "../RvfSingleClickListener";
1
+ export { default } from "./SingleClickListener";