@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,292 @@
1
+ import { useEffect, useMemo, useState } from "preact/hooks";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ import RouteIcon from "../RouteIcon";
5
+ import ShadowOverflow from "../ShadowOverflow";
6
+ import useMapContext from "../utils/hooks/useMapContext";
7
+
8
+ import type { RealtimeLine } from "mobility-toolbox-js/types";
9
+ import type { Feature } from "ol";
10
+ import type { PreactDOMAttributes } from "preact";
11
+
12
+ let cacheLineInfosById = null;
13
+ let cacheStopInfosById = null;
14
+
15
+ interface LineInfo {
16
+ color: string;
17
+ external_id: string;
18
+ id: string;
19
+ long_name: string;
20
+ mot: string;
21
+ operator_name: string;
22
+ runs: number;
23
+ short_name: string;
24
+ text_color: string;
25
+ }
26
+
27
+ interface StopInfo {
28
+ external_id: string;
29
+ importance: number;
30
+ long_name: string;
31
+ short_name: string;
32
+ visibility_level: number;
33
+ }
34
+
35
+ const LNP_SOURCE_ID = "network_plans";
36
+ const LNP_MD_LINES = "geops.lnp.lines";
37
+ const LNP_MD_STOPS = "geops.lnp.stops";
38
+ const RUNS_PROP = "runs";
39
+ const ORIGINAL_LINE_ID_PROP = "original_line_id";
40
+
41
+ function LinesNetworkPlanDetails({
42
+ className,
43
+ features,
44
+ ...props
45
+ }: { className?: string; features: Feature[] } & PreactDOMAttributes) {
46
+ const { baseLayer } = useMapContext();
47
+ const [lineInfos, setLineInfos] = useState<LineInfo[]>(null);
48
+ const [stopInfos, setStopInfos] = useState<StopInfo[]>(null);
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
+ const [stopInfosOpenId, setStopInfosOpenId] = useState<string>(null);
51
+
52
+ const isRunsDisplay = useMemo(() => {
53
+ return new URLSearchParams(window.location.search).get("runs") === "true";
54
+ }, []);
55
+
56
+ useEffect(() => {
57
+ const source = baseLayer?.mapLibreMap?.getSource(LNP_SOURCE_ID);
58
+ const abortController = new AbortController();
59
+ const fetchInfos = async (url) => {
60
+ if (!cacheLineInfosById) {
61
+ const response = await fetch(url, { signal: abortController.signal });
62
+ const data = await response.json();
63
+ cacheLineInfosById = data[LNP_MD_LINES];
64
+ cacheStopInfosById = data[LNP_MD_STOPS];
65
+ }
66
+ setLineInfos(cacheLineInfosById);
67
+ setStopInfos(cacheStopInfosById);
68
+ };
69
+ if (source?.url) {
70
+ void fetchInfos(source?.url);
71
+ }
72
+ return () => {
73
+ abortController?.abort();
74
+ };
75
+ }, [baseLayer?.mapLibreMap]);
76
+
77
+ const lineInfosByOperator: Record<string, LineInfo[]> = useMemo(() => {
78
+ const byOperators = {};
79
+
80
+ [
81
+ ...new Set(
82
+ features.map((f) => {
83
+ return f.get(ORIGINAL_LINE_ID_PROP);
84
+ }),
85
+ ),
86
+ ]
87
+ .filter((id) => {
88
+ return !!id && !!lineInfos?.[id];
89
+ })
90
+ .forEach((id) => {
91
+ const { operator_name: operatorName } = lineInfos[id];
92
+ if (!byOperators[operatorName]) {
93
+ byOperators[operatorName] = [];
94
+ byOperators[operatorName].runs = 0;
95
+ }
96
+ lineInfos[id].id = id;
97
+
98
+ const runs = features
99
+ .filter((f) => {
100
+ return f.get(ORIGINAL_LINE_ID_PROP) === id;
101
+ })
102
+ .reduce((acc, featuree) => {
103
+ return acc + featuree.get(RUNS_PROP);
104
+ }, 0);
105
+ lineInfos[id].id = id;
106
+ lineInfos[id].runs = runs;
107
+ byOperators[operatorName].runs += runs;
108
+ byOperators[operatorName].push(lineInfos[id]);
109
+ });
110
+
111
+ return byOperators;
112
+ }, [features, lineInfos]);
113
+
114
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
115
+ const stopInfoIdsByLineId: Record<string, string[]> = useMemo(() => {
116
+ const byLineId = {};
117
+ features.forEach((f) => {
118
+ const lineId = f.get(ORIGINAL_LINE_ID_PROP);
119
+ if (lineId && !byLineId[lineId] && f.get("stop_ids")) {
120
+ try {
121
+ byLineId[lineId] = JSON.parse(f.get("stop_ids"));
122
+ } catch (e) {
123
+ console.log(e);
124
+ }
125
+ }
126
+ });
127
+
128
+ return byLineId;
129
+ }, [features]);
130
+
131
+ if (!features?.length || !lineInfos) {
132
+ return null;
133
+ }
134
+
135
+ return (
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
+
167
+ let stops = null;
168
+ //stopInfoIdsByLineId?.[id] || null;
169
+ if (!stops?.length) {
170
+ stops = null;
171
+ }
172
+
173
+ if (!longName && stops) {
174
+ const names = stops.map((stopId) => {
175
+ return stopInfos[stopId].short_name;
176
+ });
177
+
178
+ longName = [
179
+ ...new Set([names[0], names[names.length - 1]]),
180
+ ].join(" - ");
181
+ }
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
+ };
192
+
193
+ if (textColor) {
194
+ line.text_color = textColor.startsWith("#")
195
+ ? textColor
196
+ : `#${textColor}`;
197
+ }
198
+
199
+ if (backgroundColor) {
200
+ line.color = backgroundColor.startsWith("#")
201
+ ? backgroundColor
202
+ : `#${backgroundColor}`;
203
+ }
204
+
205
+ return (
206
+ <div
207
+ className={longName ? "w-full" : ""}
208
+ key={shortName}
209
+ >
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>
218
+ </div>
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
+ )}
233
+
234
+ {/* We deactivate the list of stopsfor now */}
235
+ {/* {!!stops && (
236
+ <button className={"shrink-0"}>
237
+ {stopInfosOpenId === id ? (
238
+ <ArrowUp />
239
+ ) : (
240
+ <ArrowDown />
241
+ )}
242
+ </button>
243
+ )} */}
244
+ </div>
245
+ {/* {!!stops && (
246
+ <div
247
+ className={`${stopInfosOpenId === id ? "" : "hidden"}`}
248
+ >
249
+ {stops?.map((stopId, index, arr) => {
250
+ const stop = stopInfos[stopId];
251
+ return (
252
+ <div
253
+ className={"flex items-center gap-2"}
254
+ key={stopId}
255
+ >
256
+ <RouteStopContext.Provider
257
+ value={{
258
+ index,
259
+ status: {
260
+ isFirst: !index,
261
+ isLast: index === arr.length - 1,
262
+ isLeft: false,
263
+ isPassed: false,
264
+ progress: !index ? 50 : 0,
265
+ },
266
+ stop,
267
+ }}
268
+ >
269
+ <RouteStopProgress
270
+ className="relative flex size-8 shrink-0 items-center justify-center"
271
+ lineColor={line.color}
272
+ />
273
+ <div>{stop.short_name}</div>
274
+ </RouteStopContext.Provider>
275
+ </div>
276
+ );
277
+ })}
278
+ </div>
279
+ )} */}
280
+ </div>
281
+ );
282
+ })}
283
+ </div>
284
+ </div>
285
+ );
286
+ })}
287
+ </div>
288
+ </ShadowOverflow>
289
+ );
290
+ }
291
+
292
+ export default LinesNetworkPlanDetails;
@@ -0,0 +1 @@
1
+ export { default } from "../RvfFeatureDetails/RvfLineNetworkDetails";
@@ -2,15 +2,13 @@ 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
- import useRvfContext from "../utils/hooks/useRvfContext";
8
7
 
9
8
  import type { MaplibreStyleLayerOptions } from "mobility-toolbox-js/ol/layers/MaplibreStyleLayer";
10
9
 
11
- function RvfLineNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
12
- const { baseLayer, map } = useMapContext();
13
- const { setLineNetworkPlanLayer } = useRvfContext();
10
+ function LinesNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
11
+ const { baseLayer, map, setLinesNetworkPlanLayer } = useMapContext();
14
12
 
15
13
  const layer = useMemo(() => {
16
14
  if (!baseLayer) {
@@ -24,7 +22,7 @@ function RvfLineNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
24
22
  );
25
23
  },
26
24
  maplibreLayer: baseLayer,
27
- name: RVF_LAYERS_NAMES.liniennetz,
25
+ name: LAYERS_NAMES.linesnetworkplan,
28
26
  queryRenderedLayersFilter: ({ metadata }) => {
29
27
  return metadata?.["rvf.filter"] === "netzplan_trips_info";
30
28
  },
@@ -33,8 +31,8 @@ function RvfLineNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
33
31
  }, [baseLayer, props]);
34
32
 
35
33
  useEffect(() => {
36
- setLineNetworkPlanLayer(layer);
37
- }, [layer, setLineNetworkPlanLayer]);
34
+ setLinesNetworkPlanLayer?.(layer);
35
+ }, [layer, setLinesNetworkPlanLayer]);
38
36
 
39
37
  useEffect(() => {
40
38
  if (!map || !layer) {
@@ -50,4 +48,4 @@ function RvfLineNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
50
48
  return null; // <RegisterForSelectFeaturesOnClick />;
51
49
  }
52
50
 
53
- export default memo(RvfLineNetworkPlanLayer);
51
+ export default memo(LinesNetworkPlanLayer);
@@ -0,0 +1 @@
1
+ export { default } from "./LinesNetworkPlanLayer";