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

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 +31 -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 +62 -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
@@ -0,0 +1,51 @@
1
+ import { memo } from "preact/compat";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ import ArrowRight from "../icons/ArrowRight";
5
+ import Button from "../ui/Button";
6
+ import useLayerConfig from "../utils/hooks/useLayerConfig";
7
+
8
+ import type { Feature } from "ol";
9
+ import type BaseLayer from "ol/layer/Base";
10
+ import type { HTMLAttributes, PreactDOMAttributes } from "preact";
11
+
12
+ export type OverlayDetailsFooterProps = {
13
+ className?: string;
14
+ feature?: Feature;
15
+ layer?: BaseLayer;
16
+ } & HTMLAttributes<HTMLDivElement> &
17
+ PreactDOMAttributes;
18
+
19
+ function OverlayDetailsFooter({
20
+ className,
21
+ feature,
22
+ layer,
23
+ ...props
24
+ }: OverlayDetailsFooterProps) {
25
+ const layerConfig = useLayerConfig(layer?.get("name"));
26
+
27
+ if (!layerConfig?.link || layerConfig?.link?.show === false) {
28
+ return null;
29
+ }
30
+
31
+ let id = feature?.get("id");
32
+ const situation = feature?.get("situation");
33
+ if (situation) {
34
+ const situationParsed = JSON.parse(situation);
35
+ id = situationParsed?.id || id;
36
+ }
37
+ return (
38
+ <div {...props} className={twMerge("flex flex-row p-4", className)}>
39
+ <Button
40
+ href={layerConfig.link.href.replace("{{id}}", id)}
41
+ target="_blank"
42
+ theme="primary"
43
+ >
44
+ <span>{layerConfig.link.text || "Mehr erfahren"}</span>
45
+ <ArrowRight />
46
+ </Button>
47
+ </div>
48
+ );
49
+ }
50
+
51
+ export default memo(OverlayDetailsFooter);
@@ -0,0 +1 @@
1
+ export { default } from "./OverlayDetailsFooter";
@@ -0,0 +1,35 @@
1
+ import { memo, useMemo } from "preact/compat";
2
+
3
+ import OverlayHeader from "../OverlayHeader";
4
+ import { LAYERS_NAMES, LAYERS_TITLES } from "../utils/constants";
5
+
6
+ import type { Feature } from "ol";
7
+ import type BaseLayer from "ol/layer/Base";
8
+
9
+ import type { OverlayHeaderProps } from "../OverlayHeader/OverlayHeader";
10
+
11
+ export type OverlayDetailsHeaderProps = {
12
+ feature?: Feature;
13
+ layer?: BaseLayer;
14
+ } & OverlayHeaderProps;
15
+
16
+ function OverlayDetailsHeader({
17
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
+ feature,
19
+ layer,
20
+ ...props
21
+ }: OverlayDetailsHeaderProps) {
22
+ const title = useMemo(() => {
23
+ let ttle = layer?.get("title");
24
+ if (!ttle) {
25
+ const key = Object.keys(LAYERS_TITLES).find((titleKey) => {
26
+ return LAYERS_NAMES[titleKey] === layer?.get("name");
27
+ });
28
+ ttle = LAYERS_TITLES[key];
29
+ }
30
+ return ttle || layer?.get("name") || "Details";
31
+ }, [layer]);
32
+
33
+ return <OverlayHeader title={title} {...props}></OverlayHeader>;
34
+ }
35
+ export default memo(OverlayDetailsHeader);
@@ -0,0 +1 @@
1
+ export { default } from "./OverlayDetailsHeader";
@@ -0,0 +1,41 @@
1
+ import { memo } from "preact/compat";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ import Cancel from "../icons/Cancel";
5
+ import IconButton from "../ui/IconButton";
6
+
7
+ import type { HTMLAttributes, PreactDOMAttributes } from "preact";
8
+
9
+ export type RvfOverlayHeaderProps = {
10
+ onClose?: () => void;
11
+ title?: React.ReactNode;
12
+ } & HTMLAttributes<HTMLDivElement> &
13
+ PreactDOMAttributes;
14
+
15
+ function OverlayFooter({
16
+ children,
17
+ className,
18
+ onClose,
19
+ title,
20
+ ...props
21
+ }: RvfOverlayHeaderProps) {
22
+ return (
23
+ <div
24
+ {...props}
25
+ className={twMerge(
26
+ `flex flex-row items-center justify-between gap-2 border-b p-2 pl-4`,
27
+ className,
28
+ )}
29
+ >
30
+ {/* We set text-base so the clamp works on overlay container, not main */}
31
+ {children || <span className={"text-base font-bold"}>{title}</span>}
32
+ {onClose && (
33
+ <IconButton className={"!size-[32px] border-none"} onClick={onClose}>
34
+ <Cancel />
35
+ </IconButton>
36
+ )}
37
+ </div>
38
+ );
39
+ }
40
+
41
+ export default memo(OverlayFooter);
@@ -0,0 +1 @@
1
+ export { default } from "./OverlayFooter";
@@ -0,0 +1,44 @@
1
+ import { memo } from "preact/compat";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ import Cancel from "../icons/Cancel";
5
+ import IconButton from "../ui/IconButton";
6
+
7
+ import type { HTMLAttributes, PreactDOMAttributes } from "preact";
8
+
9
+ export type OverlayHeaderProps = {
10
+ onClose?: () => void;
11
+ title?: React.ReactNode;
12
+ } & HTMLAttributes<HTMLDivElement> &
13
+ PreactDOMAttributes;
14
+
15
+ function OverlayHeader({
16
+ children,
17
+ className,
18
+ onClose,
19
+ title,
20
+ ...props
21
+ }: OverlayHeaderProps) {
22
+ return (
23
+ <div
24
+ {...props}
25
+ className={twMerge(
26
+ `flex flex-row items-center justify-between gap-2 border-b p-2 pl-4`,
27
+ className,
28
+ )}
29
+ >
30
+ {/* We set text-base so the clamp works on overlay container, not main */}
31
+ {children || <span className={"text-base font-bold"}>{title}</span>}
32
+ {onClose && (
33
+ <IconButton
34
+ className={"!size-[32px] border-none shadow-none"}
35
+ onClick={onClose}
36
+ >
37
+ <Cancel />
38
+ </IconButton>
39
+ )}
40
+ </div>
41
+ );
42
+ }
43
+
44
+ export default memo(OverlayHeader);
@@ -0,0 +1 @@
1
+ export { default } from "./OverlayHeader";
@@ -0,0 +1,28 @@
1
+ import InputCopy from "../ui/InputCopy";
2
+
3
+ import type { HTMLAttributes, PreactDOMAttributes } from "preact";
4
+
5
+ import type { InputCopyProps } from "../ui/InputCopy/InputCopy";
6
+
7
+ export type PermalinkInputProps = {
8
+ inputProps?: InputCopyProps;
9
+ } & HTMLAttributes<HTMLDivElement> &
10
+ PreactDOMAttributes;
11
+
12
+ const emptyProps = {}; // avoid re-rendering
13
+
14
+ function PermalinkInput({
15
+ inputProps = emptyProps,
16
+ ...props
17
+ }: PermalinkInputProps) {
18
+ return (
19
+ <div {...props}>
20
+ <InputCopy value={window?.location.href} {...inputProps} />
21
+ <p className="py-2">
22
+ Sie können auch den Link aus der Adresszeile des Browsers kopieren.
23
+ </p>
24
+ </div>
25
+ );
26
+ }
27
+
28
+ export default PermalinkInput;
@@ -0,0 +1 @@
1
+ export { default } from "./PermalinkInput";
@@ -1,9 +1,11 @@
1
1
  import { memo } from "preact/compat";
2
2
  import { useEffect, useRef } from "preact/hooks";
3
+ import { twMerge } from "tailwind-merge";
3
4
 
4
5
  import RouteScheduleFooter from "../RouteScheduleFooter";
5
6
  import RouteScheduleHeader from "../RouteScheduleHeader";
6
7
  import RouteStop from "../RouteStop";
8
+ import ShadowOverflow from "../ShadowOverflow";
7
9
  import useMapContext from "../utils/hooks/useMapContext";
8
10
 
9
11
  import type { RealtimeStop } from "mobility-toolbox-js/types";
@@ -25,7 +27,7 @@ function RouteSchedule(props: RouteScheduleProps) {
25
27
  const nextStation = elt.querySelector("[data-station-passed=false]");
26
28
  if (nextStation) {
27
29
  // We use scrollTo avoid scrolling the entire window.
28
- (nextStation.parentNode as Element).scrollTo({
30
+ (nextStation.parentNode.parentNode as Element).scrollTo({
29
31
  behavior: "smooth",
30
32
  top: (nextStation as HTMLElement).offsetTop || 0,
31
33
  });
@@ -47,23 +49,25 @@ function RouteSchedule(props: RouteScheduleProps) {
47
49
  return (
48
50
  <>
49
51
  <RouteScheduleHeader />
50
- <div className={className} ref={ref}>
51
- {stopSequence.stations.map((stop: RealtimeStop, index: number) => {
52
- const { arrivalTime, departureTime, stationId, stationName } = stop;
53
- return (
54
- <RouteStop
55
- // Train line can go in circle so begin and end have the same id,
56
- index={index}
57
- // using the time in the key should fix the issue.
58
- key={
59
- (`${stationId}` || stationName) + arrivalTime + departureTime
60
- }
61
- stop={stop}
62
- />
63
- );
64
- })}
65
- <RouteScheduleFooter />
66
- </div>
52
+ <ShadowOverflow>
53
+ <div className={twMerge("text-base", className)} ref={ref}>
54
+ {stopSequence.stations.map((stop: RealtimeStop, index: number) => {
55
+ const { arrivalTime, departureTime, stationId, stationName } = stop;
56
+ return (
57
+ <RouteStop
58
+ // Train line can go in circle so begin and end have the same id,
59
+ index={index}
60
+ // using the time in the key should fix the issue.
61
+ key={
62
+ (`${stationId}` || stationName) + arrivalTime + departureTime
63
+ }
64
+ stop={stop}
65
+ />
66
+ );
67
+ })}
68
+ <RouteScheduleFooter />
69
+ </div>
70
+ </ShadowOverflow>
67
71
  </>
68
72
  );
69
73
  }
@@ -1,16 +1,11 @@
1
1
  import { memo } from "preact/compat";
2
2
 
3
- import useRvfContext from "../utils/hooks/useRvfContext";
3
+ import FeatureDetails from "../FeatureDetails/FeatureDetails";
4
4
 
5
- import RvfLineNetworkDetails from "./RvfLineNetworkDetails/RvfLineNetworkDetails";
6
- import RvfNotificationDetails from "./RvfNotificationDetails";
7
5
  import RvfSellingPointDetails from "./RvfSellingPointDetails";
8
6
  import RvfSharedMobilityDetails from "./RvfSharedMobilityDetail";
9
7
 
10
- import type { JSX, PreactDOMAttributes } from "preact";
11
-
12
- export type RvfFeatureDetailsProps = JSX.HTMLAttributes<HTMLDivElement> &
13
- PreactDOMAttributes;
8
+ import type { FeatureDetailsProps } from "../FeatureDetails/FeatureDetails";
14
9
 
15
10
  const getIsSharedMobility = (selectedFeature): boolean => {
16
11
  if (
@@ -22,51 +17,28 @@ const getIsSharedMobility = (selectedFeature): boolean => {
22
17
  }
23
18
  };
24
19
 
25
- function RvfFeatureDetails(props: RvfFeatureDetailsProps) {
26
- const { selectedFeature, selectedFeatures } = useRvfContext();
27
- const isSharedMobility = getIsSharedMobility(selectedFeature);
28
- const isSellingPoint = !!selectedFeature.get("tickets");
29
- const isNotification = !!selectedFeature.get("situation");
30
- const isLineNetwork = !!selectedFeature.get("original_line_id");
31
-
32
- const showDefaultData = () => {
33
- return Object.entries(selectedFeature.getProperties()).map(
34
- ([key, value]) => {
35
- return (
36
- <div className="flex gap-2" key={key}>
37
- <span>
38
- <b>{key}:</b>
39
- </span>
40
- <div>{value}</div>
41
- </div>
42
- );
43
- },
44
- );
45
- };
20
+ function RvfFeatureDetails({
21
+ feature,
22
+ featuresInfo,
23
+ layer,
24
+ }: FeatureDetailsProps) {
25
+ const isSharedMobility = getIsSharedMobility(feature);
26
+ const isSellingPoint = !!feature.get("tickets");
46
27
 
47
28
  return (
48
- <div {...props}>
49
- <div className="p-4 pb-0">
50
- {isSellingPoint && <RvfSellingPointDetails feature={selectedFeature} />}
51
- {isSharedMobility && (
52
- <RvfSharedMobilityDetails selectedFeature={selectedFeature} />
53
- )}
54
- {isNotification && <RvfNotificationDetails feature={selectedFeature} />}
55
- {isLineNetwork && (
56
- <RvfLineNetworkDetails
57
- feature={selectedFeature}
58
- features={selectedFeatures}
59
- />
60
- )}
61
- {!isLineNetwork &&
62
- !isNotification &&
63
- !isSharedMobility &&
64
- !isSellingPoint &&
65
- showDefaultData()}
66
- </div>
67
- {/* TODO find why -1px is necessary */}
68
- <div className="pointer-events-none sticky bottom-[-1px] h-6 w-full bg-gradient-to-b from-transparent to-white" />
69
- </div>
29
+ <>
30
+ <FeatureDetails
31
+ feature={feature}
32
+ featuresInfo={featuresInfo}
33
+ layer={layer}
34
+ />
35
+ {(isSellingPoint || isSharedMobility) && (
36
+ <div className="p-4 text-base">
37
+ {isSellingPoint && <RvfSellingPointDetails feature={feature} />}
38
+ {isSharedMobility && <RvfSharedMobilityDetails feature={feature} />}
39
+ </div>
40
+ )}
41
+ </>
70
42
  );
71
43
  }
72
44
 
@@ -1,10 +1,13 @@
1
1
  import { useEffect, useMemo, useState } from "preact/hooks";
2
+ import { twMerge } from "tailwind-merge";
2
3
 
3
4
  import RouteIcon from "../../RouteIcon";
5
+ import ShadowOverflow from "../../ShadowOverflow";
4
6
  import useMapContext from "../../utils/hooks/useMapContext";
5
7
 
6
8
  import type { RealtimeLine } from "mobility-toolbox-js/types";
7
9
  import type { Feature } from "ol";
10
+ import type { PreactDOMAttributes } from "preact";
8
11
 
9
12
  let cacheLineInfosById = null;
10
13
  let cacheStopInfosById = null;
@@ -35,13 +38,11 @@ const LNP_MD_STOPS = "geops.lnp.stops";
35
38
  const RUNS_PROP = "runs";
36
39
  const ORIGINAL_LINE_ID_PROP = "original_line_id";
37
40
 
38
- function RvfLineNetworkDetails({
39
- feature,
41
+ function LinesNetworkPlanDetails({
42
+ className,
40
43
  features,
41
- }: {
42
- feature: Feature;
43
- features: Feature[];
44
- }) {
44
+ ...props
45
+ }: { className?: string; features: Feature[] } & PreactDOMAttributes) {
45
46
  const { baseLayer } = useMapContext();
46
47
  const [lineInfos, setLineInfos] = useState<LineInfo[]>(null);
47
48
  const [stopInfos, setStopInfos] = useState<StopInfo[]>(null);
@@ -65,9 +66,7 @@ function RvfLineNetworkDetails({
65
66
  setLineInfos(cacheLineInfosById);
66
67
  setStopInfos(cacheStopInfosById);
67
68
  };
68
- // @ts-expect-error --- IGNORE ---
69
69
  if (source?.url) {
70
- // @ts-expect-error --- IGNORE ---git as
71
70
  void fetchInfos(source?.url);
72
71
  }
73
72
  return () => {
@@ -129,107 +128,111 @@ function RvfLineNetworkDetails({
129
128
  return byLineId;
130
129
  }, [features]);
131
130
 
132
- if (!feature || !lineInfos) {
131
+ if (!features?.length || !lineInfos) {
133
132
  return null;
134
133
  }
135
134
 
136
135
  return (
137
- <div className="space-y-4">
138
- {Object.entries(lineInfosByOperator)
139
- .sort(([operatorNameA], [operatorNameB]) => {
140
- return lineInfosByOperator[operatorNameA].runs <
141
- lineInfosByOperator[operatorNameB].runs
142
- ? 1
143
- : -1;
144
- })
145
- .map(([operatorName, linesInfos]) => {
146
- return (
147
- <div className={"flex flex-col gap-2"} key={operatorName}>
148
- <div>{operatorName}</div>
149
- <div className="flex flex-wrap gap-2">
150
- {linesInfos
151
- .sort((a, b) => {
152
- return a.runs < b.runs ? 1 : -1;
153
- })
154
- .map((lineInfo) => {
155
- const {
156
- color: backgroundColor,
157
- // color,
158
- // external_id,
159
- long_name,
160
- mot,
161
- runs,
162
- short_name: shortName,
163
- text_color: textColor,
164
- } = lineInfo;
165
- let longName = long_name;
136
+ <ShadowOverflow {...props} className={twMerge("px-4 text-base", className)}>
137
+ <div className="space-y-4">
138
+ {Object.entries(lineInfosByOperator)
139
+ .sort(([operatorNameA], [operatorNameB]) => {
140
+ return lineInfosByOperator[operatorNameA].runs <
141
+ lineInfosByOperator[operatorNameB].runs
142
+ ? 1
143
+ : -1;
144
+ })
145
+ .map(([operatorName, linesInfos]) => {
146
+ return (
147
+ <div className={"flex flex-col gap-2"} key={operatorName}>
148
+ <div>{operatorName}</div>
149
+ <div className="flex flex-wrap gap-2">
150
+ {linesInfos
151
+ .sort((a, b) => {
152
+ return a.runs < b.runs ? 1 : -1;
153
+ })
154
+ .map((lineInfo) => {
155
+ const {
156
+ color: backgroundColor,
157
+ // color,
158
+ // external_id,
159
+ long_name,
160
+ mot,
161
+ runs,
162
+ short_name: shortName,
163
+ text_color: textColor,
164
+ } = lineInfo;
165
+ let longName = long_name;
166
166
 
167
- let stops = null;
168
- //stopInfoIdsByLineId?.[id] || null;
169
- if (!stops?.length) {
170
- stops = null;
171
- }
167
+ let stops = null;
168
+ //stopInfoIdsByLineId?.[id] || null;
169
+ if (!stops?.length) {
170
+ stops = null;
171
+ }
172
172
 
173
- if (!longName && stops) {
174
- const names = stops.map((stopId) => {
175
- return stopInfos[stopId].short_name;
176
- });
173
+ if (!longName && stops) {
174
+ const names = stops.map((stopId) => {
175
+ return stopInfos[stopId].short_name;
176
+ });
177
177
 
178
- longName = [
179
- ...new Set([names[0], names[names.length - 1]]),
180
- ].join(" - ");
181
- }
178
+ longName = [
179
+ ...new Set([names[0], names[names.length - 1]]),
180
+ ].join(" - ");
181
+ }
182
182
 
183
- // Build a line object
184
- const line: { type: string } & RealtimeLine = {
185
- color: null,
186
- id: null,
187
- name: shortName,
188
- stroke: null,
189
- text_color: null,
190
- type: mot,
191
- };
183
+ // Build a line object
184
+ const line: { type: string } & RealtimeLine = {
185
+ color: null,
186
+ id: null,
187
+ name: shortName,
188
+ stroke: null,
189
+ text_color: null,
190
+ type: mot,
191
+ };
192
192
 
193
- if (textColor) {
194
- line.text_color = textColor.startsWith("#")
195
- ? textColor
196
- : `#${textColor}`;
197
- }
193
+ if (textColor) {
194
+ line.text_color = textColor.startsWith("#")
195
+ ? textColor
196
+ : `#${textColor}`;
197
+ }
198
198
 
199
- if (backgroundColor) {
200
- line.color = backgroundColor.startsWith("#")
201
- ? backgroundColor
202
- : `#${backgroundColor}`;
203
- }
199
+ if (backgroundColor) {
200
+ line.color = backgroundColor.startsWith("#")
201
+ ? backgroundColor
202
+ : `#${backgroundColor}`;
203
+ }
204
204
 
205
- return (
206
- <div className={longName ? "w-full" : ""} key={shortName}>
205
+ return (
207
206
  <div
208
- className={"flex justify-between gap-2"}
209
- // onClick={() => {
210
- // setStopInfosOpenId(stopInfosOpenId === id ? null : id);
211
- // }}
207
+ className={longName ? "w-full" : ""}
208
+ key={shortName}
212
209
  >
213
- <div>
214
- <RouteIcon line={line}></RouteIcon>
215
- </div>
216
- {!!longName && (
217
- <div
218
- className={
219
- "flex-1 text-left *:before:content-['_–'] *:first:font-semibold *:first:before:!content-[_p] *:last:font-semibold *:last:before:!content-[_p]"
220
- }
221
- >
222
- {longName.split("-").map((name) => {
223
- return <div key={name}>{name}</div>;
224
- })}
210
+ <div
211
+ className={"flex justify-between gap-2"}
212
+ // onClick={() => {
213
+ // setStopInfosOpenId(stopInfosOpenId === id ? null : id);
214
+ // }}
215
+ >
216
+ <div>
217
+ <RouteIcon line={line}></RouteIcon>
225
218
  </div>
226
- )}
227
- {isRunsDisplay && (
228
- <div className={"text-xs"}>{runs}</div>
229
- )}
219
+ {!!longName && (
220
+ <div
221
+ className={
222
+ "flex-1 text-left *:before:content-['_–'] *:first:font-semibold *:first:before:!content-[_p] *:last:font-semibold *:last:before:!content-[_p]"
223
+ }
224
+ >
225
+ {longName.split("-").map((name) => {
226
+ return <div key={name}>{name}</div>;
227
+ })}
228
+ </div>
229
+ )}
230
+ {isRunsDisplay && (
231
+ <div className={"text-xs"}>{runs}</div>
232
+ )}
230
233
 
231
- {/* We deactivate the list of stopsfor now */}
232
- {/* {!!stops && (
234
+ {/* We deactivate the list of stopsfor now */}
235
+ {/* {!!stops && (
233
236
  <button className={"shrink-0"}>
234
237
  {stopInfosOpenId === id ? (
235
238
  <ArrowUp />
@@ -238,8 +241,8 @@ function RvfLineNetworkDetails({
238
241
  )}
239
242
  </button>
240
243
  )} */}
241
- </div>
242
- {/* {!!stops && (
244
+ </div>
245
+ {/* {!!stops && (
243
246
  <div
244
247
  className={`${stopInfosOpenId === id ? "" : "hidden"}`}
245
248
  >
@@ -274,15 +277,16 @@ function RvfLineNetworkDetails({
274
277
  })}
275
278
  </div>
276
279
  )} */}
277
- </div>
278
- );
279
- })}
280
+ </div>
281
+ );
282
+ })}
283
+ </div>
280
284
  </div>
281
- </div>
282
- );
283
- })}
284
- </div>
285
+ );
286
+ })}
287
+ </div>
288
+ </ShadowOverflow>
285
289
  );
286
290
  }
287
291
 
288
- export default RvfLineNetworkDetails;
292
+ export default LinesNetworkPlanDetails;