@geops/rvf-mobility-web-component 0.1.46 → 0.1.47
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.
- package/.prettierrc.js +3 -1
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/doc/package.json +4 -3
- package/doc/postcss.config.mjs +1 -1
- package/doc/src/app/components/GeopsMobilityDoc.tsx +13 -224
- package/doc/src/app/components/GeopsMobilitySearchDoc.tsx +11 -107
- package/doc/src/app/components/WebComponentDoc.tsx +45 -56
- package/doc/src/app/geops-mobility/page.tsx +7 -2
- package/doc/src/app/geops-mobility-search/page.tsx +6 -2
- package/doc/src/app/globals.css +47 -27
- package/doc/src/app/layout.tsx +4 -2
- package/docutils.js +33 -17
- package/eslint.config.mjs +28 -34
- package/iframe.html +181 -207
- package/index.html +108 -88
- package/index.js +2345 -1976
- package/input.css +21 -3
- package/package.json +39 -41
- package/scripts/build.mjs +2 -2
- package/scripts/dev.mjs +3 -3
- package/search.html +70 -23
- package/src/BaseLayer/BaseLayer.tsx +2 -1
- package/src/Copyright/Copyright.tsx +4 -2
- package/src/DebugDeparture/DebugDeparture.tsx +16 -12
- package/src/DebugStop/DebugStop.tsx +2 -2
- package/src/Departure/Departure.tsx +2 -3
- package/src/EmbedNavigation/DragPanWarning.ts +125 -0
- package/src/EmbedNavigation/EmbedNavigation.tsx +52 -0
- package/src/EmbedNavigation/index.js +1 -0
- package/src/EmbedNavigation/index.tsx +1 -0
- package/src/GeolocationButton/GeolocationButton.tsx +11 -35
- package/src/GeolocationButton/index.tsx +1 -1
- package/src/Map/Map.tsx +5 -3
- package/src/MapDispatchEvents/MapDispatchEvents.tsx +78 -0
- package/src/MapDispatchEvents/index.tsx +1 -0
- package/src/MobilityMap/MobilityMap.tsx +117 -162
- package/src/MobilityMap/MobilityMapAttributes.test.ts +21 -0
- package/src/MobilityMap/MobilityMapAttributes.ts +252 -0
- package/src/MobilityMap/index.tsx +1 -0
- package/src/MobilitySearch/MobilitySearch.tsx +35 -0
- package/src/MobilitySearch/MobilitySearchAttributes.test.ts +21 -0
- package/src/MobilitySearch/MobilitySearchAttributes.ts +68 -0
- package/src/MobilitySearch/index.ts +2 -0
- package/src/NotificationLayer/NotificationLayer.tsx +36 -5
- package/src/Overlay/Overlay.tsx +24 -11
- package/src/Permalink/Permalink.tsx +77 -0
- package/src/Permalink/index.tsx +1 -0
- package/src/RealtimeLayer/RealtimeLayer.tsx +72 -33
- package/src/RouteDestination/RouteDestination.tsx +3 -3
- package/src/RouteIcon/RouteIcon.tsx +33 -25
- package/src/RouteIcon/index.tsx +1 -1
- package/src/RouteIdentifier/RouteIdentifer.tsx +6 -5
- package/src/RouteInfos/RouteInfos.tsx +7 -3
- package/src/RouteSchedule/RouteSchedule.tsx +3 -3
- package/src/RouteScheduleFooter/RouteScheduleFooter.tsx +1 -1
- package/src/RouteScheduleHeader/RouteScheduleHeader.tsx +7 -29
- package/src/RouteStop/RouteStop.tsx +8 -11
- package/src/RouteStopDelay/RouteStopDelay.tsx +2 -1
- package/src/RouteStopName/RouteStopName.tsx +2 -2
- package/src/RouteStopPlatform/RouteStopPlatform.tsx +2 -2
- package/src/RouteStopProgress/RouteStopProgress.tsx +2 -1
- package/src/RouteStopServices/RouteStopServices.tsx +2 -2
- package/src/RouteStopStation/RouteStopStation.tsx +8 -2
- package/src/RouteStopTime/RouteStopTime.tsx +2 -1
- package/src/RvfButton/RvfButton.tsx +14 -5
- package/src/RvfCheckbox/RvfCheckbox.tsx +8 -8
- package/src/RvfEmbedNavigation/DragPanWarning.ts +5 -5
- package/src/RvfEmbedNavigation/RvfEmbedNavigation.tsx +1 -0
- package/src/RvfExportMenu/RvfExportMenu.tsx +14 -12
- package/src/RvfExportMenuButton/RvfExportMenuButton.tsx +6 -7
- package/src/RvfFeatureDetails/RvfFeatureDetails.tsx +25 -21
- package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +131 -127
- package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +309 -111
- package/src/RvfFeatureDetails/RvfSellingPointDetails/RvfSellingPointDetails.tsx +2 -2
- package/src/RvfFeatureDetails/RvfSharedMobilityDetail/FloatingVehiclesDetails/FloatingVehiclesDetails.tsx +3 -3
- package/src/RvfFeatureDetails/RvfSharedMobilityDetail/RvfSharedMobilityDetails.tsx +8 -6
- package/src/RvfFeatureDetails/RvfSharedMobilityDetail/StationDetails/StationDetails.tsx +5 -4
- package/src/RvfFeatureDetailsFooter/RvfFeatureDetailsFooter.tsx +43 -0
- package/src/RvfFeatureDetailsFooter/index.tsx +1 -0
- package/src/RvfFeatureDetailsTitle/RvfFeatureDetailsTitle.tsx +81 -0
- package/src/RvfFeatureDetailsTitle/index.tsx +1 -0
- package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +4 -4
- package/src/RvfGeolocationButton/GeolocationButton.tsx +98 -0
- package/src/RvfGeolocationButton/index.tsx +1 -0
- package/src/RvfIconButton/RvfIconButton.tsx +20 -9
- package/src/RvfInputCopy/RvfInputCopy.tsx +8 -8
- package/src/RvfLayerTree/RvfLayerTree.tsx +5 -2
- package/src/RvfLayerTree/TreeItem/TreeItem.tsx +13 -16
- package/src/RvfLayerTree/layersTreeReducer.ts +23 -18
- package/src/RvfLayerTreeButton/RvfLayerTreeButton.tsx +6 -6
- package/src/RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx +2 -1
- package/src/RvfLink/RvfLink.tsx +4 -3
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +324 -320
- package/src/RvfModal/RvfModal.tsx +4 -3
- package/src/RvfOverlayContent/RvfOverlayContent.tsx +128 -0
- package/src/RvfOverlayContent/index.ts +0 -0
- package/src/RvfOverlayHeader/RvfOverlayHeader.tsx +13 -10
- package/src/RvfPermalink/RvfPermalink.tsx +2 -2
- package/src/RvfPoisLayer/RvfPoisLayer.tsx +2 -1
- package/src/RvfRadioButton/RvfRadioButton.tsx +1 -1
- package/src/RvfRouteIcon/RvfRouteIcon.tsx +10 -0
- package/src/RvfRouteIcon/index.tsx +1 -0
- package/src/RvfSearch/RvfSearch.tsx +4 -1
- package/src/RvfSearchButton/RvfSearchButton.tsx +27 -0
- package/src/RvfSearchButton/index.tsx +1 -0
- package/src/RvfSelect/RvfSelect.tsx +7 -5
- package/src/RvfSelectedFeatureHighlightLayer/RvfSelectedFeatureHighlightLayer.tsx +1 -2
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +2 -1
- package/src/RvfShare/RvfPermalinkButton/RvfPermalinkButton.tsx +13 -12
- package/src/RvfShare/RvfShare.tsx +11 -10
- package/src/RvfShareMenuButton/RvfShareMenuButton.tsx +5 -5
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +25 -22
- package/src/RvfSingleClickListener/RvfSingleClickListener.tsx +102 -67
- package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +2 -1
- package/src/RvfTopics/RvfTopics.tsx +6 -5
- package/src/RvfZoomButtons/RvfZoomButtons.tsx +3 -3
- package/src/ScaleLine/ScaleLine.tsx +5 -4
- package/src/ScrollableHandler/ScrollableHandler.tsx +2 -1
- package/src/ScrollableHandler/index.tsx +1 -1
- package/src/SingleClickListener/SingleClickListener.tsx +47 -4
- package/src/Station/Station.tsx +5 -5
- package/src/StationName/StationName.tsx +3 -3
- package/src/StationServices/StationServices.tsx +3 -3
- package/src/StationsLayer/StationsLayer.tsx +5 -4
- package/src/StopsSearch/StopsSearch.tsx +143 -88
- package/src/WindowMessageListener/WindowMessageListener.tsx +68 -0
- package/src/WindowMessageListener/index.tsx +1 -0
- package/src/icons/Airport/Airport.tsx +4 -4
- package/src/icons/ArrowDown/ArrowDown.tsx +1 -1
- package/src/icons/ArrowRight/ArrowRight.tsx +19 -0
- package/src/icons/ArrowRight/arrow-right.svg +16 -0
- package/src/icons/ArrowRight/index.tsx +1 -0
- package/src/icons/ArrowUp/ArrowUp.tsx +1 -1
- package/src/icons/ArrowUpRight/ArrowUpRight.tsx +1 -1
- package/src/icons/BarAndRestaurants/BarAndRestaurants.tsx +2 -2
- package/src/icons/Bathroom/Bathroom.tsx +1 -1
- package/src/icons/Copy/Copy.tsx +1 -1
- package/src/icons/Doc/Doc.tsx +1 -1
- package/src/icons/Email/Email.tsx +1 -1
- package/src/icons/FilePdf/FilePdf.tsx +1 -1
- package/src/icons/Geolocation/Geolocation.tsx +3 -5
- package/src/icons/Image/Image.tsx +1 -1
- package/src/icons/Menu/Menu.tsx +1 -1
- package/src/icons/Minus/Minus.tsx +1 -1
- package/src/icons/NoRealtime/NoRealtime.tsx +1 -1
- package/src/icons/Plus/Plus.tsx +1 -1
- package/src/icons/Police/Police.tsx +3 -3
- package/src/icons/Search/Search.tsx +0 -1
- package/src/icons/Share/Share.tsx +1 -1
- package/src/icons/Stack/Stack.tsx +1 -1
- package/src/icons/Tracking/Tracking.tsx +29 -0
- package/src/icons/Tracking/airport-14-svgrepo-com.svg +41 -0
- package/src/icons/Tracking/index.tsx +1 -0
- package/src/icons/WaitingAreas/WaitingAreas.tsx +1 -1
- package/src/icons/Warning/Warning.tsx +56 -0
- package/src/icons/Warning/index.tsx +1 -0
- package/src/icons/Warning/info-achtung-kreisrot-rot.svg +28 -0
- package/src/icons/WheelChair/WheelChair.tsx +1 -1
- package/src/index.tsx +8 -46
- package/src/indexDoc.ts +13 -0
- package/src/ui/Button/Button.tsx +57 -0
- package/src/ui/Button/index.tsx +1 -0
- package/src/ui/IconButton/IconButton.tsx +44 -0
- package/src/ui/IconButton/index.tsx +1 -0
- package/src/utils/MobilityEvent.ts +4 -3
- package/src/utils/applyInitialLayerVisibility.ts +3 -3
- package/src/utils/centerOnStation.ts +3 -2
- package/src/utils/centerOnVehicle.ts +5 -4
- package/src/utils/constants.ts +27 -3
- package/src/utils/exportPdf.ts +26 -20
- package/src/utils/fullTrajectoryStyle.ts +2 -2
- package/src/utils/getAllLayers.ts +4 -3
- package/src/utils/getDelayColor.test.ts +1 -0
- package/src/utils/getDelayColorForVehicle.test.ts +2 -0
- package/src/utils/getDelayString.test.ts +3 -0
- package/src/utils/getDelayTextForVehicle.test.ts +4 -0
- package/src/utils/getFullTrajectoryAndFit.ts +4 -3
- package/src/utils/getHoursAndMinutes.test.ts +1 -0
- package/src/utils/getLayersAsFlatArray.ts +2 -2
- package/src/utils/getLinkByDevice.ts +1 -1
- package/src/utils/getMainColorForVehicle.ts +3 -3
- package/src/utils/getPermalinkParameters.ts +2 -2
- package/src/utils/getStopStatus.test.ts +2 -1
- package/src/utils/getStopStatus.ts +1 -1
- package/src/utils/getTextForVehicle.ts +1 -1
- package/src/utils/hooks/useDeparture.tsx +6 -5
- package/src/utils/hooks/useI18n.tsx +6 -4
- package/src/utils/hooks/useInitialLayersVisiblity.tsx +2 -1
- package/src/utils/hooks/useLayerConfig.tsx +40 -0
- package/src/utils/hooks/useMapContext.tsx +30 -18
- package/src/utils/hooks/useRouteStop.tsx +3 -2
- package/src/utils/hooks/useRvfContext.tsx +11 -3
- package/src/utils/hooks/useStation.tsx +2 -1
- package/src/utils/hooks/useUpdatePermalink.tsx +25 -24
- package/src/utils/hooks/useZoom.tsx +4 -4
- package/src/utils/realtimeRVFStyle.ts +5 -4
- package/src/utils/sharingGraphqlUtils.ts +3 -2
- package/src/utils/sharingStylesUtils.ts +7 -7
- package/src/utils/sharingWFSUtils.ts +9 -15
- package/tailwind.config.mjs +1 -0
- package/tsconfig.json +1 -1
- package/doc/tailwind.config.ts +0 -20
- package/src/utils/getFeatureInformationTitle.tsx +0 -54
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { icons } from "../utils/addSourceAndLayers";
|
|
2
|
+
import {
|
|
3
|
+
RVF_LAYERS_NAMES,
|
|
4
|
+
RVF_LAYERS_TITLES,
|
|
5
|
+
TITLE_BY_CATEGORY,
|
|
6
|
+
TITLE_BY_FEED_ID,
|
|
7
|
+
} from "../utils/constants";
|
|
8
|
+
import useLayerConfig from "../utils/hooks/useLayerConfig";
|
|
9
|
+
|
|
10
|
+
import type { Feature } from "ol";
|
|
11
|
+
|
|
12
|
+
const defaultTitle = "Informations";
|
|
13
|
+
|
|
14
|
+
function RvfFeatureDetailsTitle({ feature }: { feature: Feature }) {
|
|
15
|
+
const features = feature.get("features");
|
|
16
|
+
const selectedFeature = features?.[0] || feature;
|
|
17
|
+
const {
|
|
18
|
+
category,
|
|
19
|
+
condition_group: conditionGroup,
|
|
20
|
+
disruption_type: disruptionType,
|
|
21
|
+
feed_id: feedId,
|
|
22
|
+
line_id: lineId,
|
|
23
|
+
tickets,
|
|
24
|
+
} = selectedFeature.getProperties();
|
|
25
|
+
const layerConfigLinienNetz = useLayerConfig(RVF_LAYERS_NAMES.liniennetz);
|
|
26
|
+
const layerConfigMeldungen = useLayerConfig(RVF_LAYERS_NAMES.meldungen);
|
|
27
|
+
|
|
28
|
+
// moco export v1
|
|
29
|
+
if (disruptionType) {
|
|
30
|
+
return (
|
|
31
|
+
<div className={"flex items-center gap-2 text-sm"}>
|
|
32
|
+
<div className="min-w-8 shrink-0 grow-0">
|
|
33
|
+
<img
|
|
34
|
+
alt={disruptionType}
|
|
35
|
+
className={"w-8"}
|
|
36
|
+
src={icons[disruptionType] || icons.warning}
|
|
37
|
+
></img>
|
|
38
|
+
</div>
|
|
39
|
+
<div className={"flex flex-col gap-2 text-base font-bold"}>
|
|
40
|
+
{layerConfigMeldungen.title}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// moco export v2
|
|
47
|
+
if (conditionGroup) {
|
|
48
|
+
return (
|
|
49
|
+
<div className={"flex items-center gap-2 text-sm"}>
|
|
50
|
+
{icons[conditionGroup] && (
|
|
51
|
+
<div className="min-w-8 shrink-0 grow-0">
|
|
52
|
+
<img
|
|
53
|
+
alt={conditionGroup}
|
|
54
|
+
className={"w-8"}
|
|
55
|
+
src={icons[conditionGroup] || icons.warning}
|
|
56
|
+
></img>
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
<div className={"flex flex-col gap-2 text-base font-bold"}>
|
|
60
|
+
{layerConfigMeldungen.title}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (category) {
|
|
66
|
+
return TITLE_BY_CATEGORY[category] || defaultTitle;
|
|
67
|
+
}
|
|
68
|
+
if (feedId) {
|
|
69
|
+
return TITLE_BY_FEED_ID[feedId] || defaultTitle;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (lineId) {
|
|
73
|
+
return layerConfigLinienNetz.title;
|
|
74
|
+
}
|
|
75
|
+
if (tickets) {
|
|
76
|
+
return RVF_LAYERS_TITLES.verkaufsstellen;
|
|
77
|
+
}
|
|
78
|
+
return defaultTitle;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default RvfFeatureDetailsTitle;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./RvfFeatureDetailsTitle";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
-
|
|
3
1
|
import ArrowDown from "../icons/ArrowDown";
|
|
4
2
|
import ArrowUp from "../icons/ArrowUp";
|
|
5
3
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
6
4
|
|
|
5
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
6
|
+
|
|
7
7
|
export type RvfFloatingMenuProps = {
|
|
8
8
|
isOpen: boolean;
|
|
9
9
|
onClick: () => void;
|
|
@@ -23,8 +23,8 @@ function RvfFloatingMenu({
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<div className="pointer-events-none absolute bottom-8 left-2
|
|
27
|
-
<div className="pointer-events-auto max-h-full w-48 rounded-lg border
|
|
26
|
+
<div className="pointer-events-none absolute top-2 bottom-8 left-2 z-10 flex flex-col overflow-hidden rounded-lg">
|
|
27
|
+
<div className="border-grey pointer-events-auto max-h-full w-48 rounded-lg border bg-white shadow-lg @lg/main:w-52">
|
|
28
28
|
<button
|
|
29
29
|
className="flex w-full items-center justify-between px-2 py-1.5 font-bold"
|
|
30
30
|
onClick={onClick}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Feature, Geolocation } from "ol";
|
|
2
|
+
import { Point } from "ol/geom";
|
|
3
|
+
import VectorLayer from "ol/layer/Vector";
|
|
4
|
+
import { unByKey } from "ol/Observable";
|
|
5
|
+
import { fromLonLat } from "ol/proj";
|
|
6
|
+
import VectorSource from "ol/source/Vector";
|
|
7
|
+
import { Icon, Style } from "ol/style";
|
|
8
|
+
import { memo } from "preact/compat";
|
|
9
|
+
import { useEffect, useMemo } from "preact/hooks";
|
|
10
|
+
|
|
11
|
+
import GeolocationIcon from "../icons/Geolocation";
|
|
12
|
+
import locationSvg from "../icons/Geolocation/location.svg";
|
|
13
|
+
import IconButton from "../ui/IconButton";
|
|
14
|
+
import useMapContext from "../utils/hooks/useMapContext";
|
|
15
|
+
|
|
16
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
17
|
+
|
|
18
|
+
const point = new Point([0, 0]);
|
|
19
|
+
const feature = new Feature(point);
|
|
20
|
+
const layer = new VectorLayer({
|
|
21
|
+
source: new VectorSource({ features: [feature] }),
|
|
22
|
+
style: new Style({
|
|
23
|
+
image: new Icon({
|
|
24
|
+
anchor: [0.5, 1],
|
|
25
|
+
src: locationSvg,
|
|
26
|
+
}),
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export type GeolocationButtonProps = JSX.HTMLAttributes<HTMLButtonElement> &
|
|
31
|
+
PreactDOMAttributes;
|
|
32
|
+
|
|
33
|
+
const TRACKING_ZOOM = 16;
|
|
34
|
+
|
|
35
|
+
function GeolocationButton({ ...props }: GeolocationButtonProps) {
|
|
36
|
+
const mapContext = useMapContext();
|
|
37
|
+
const { isTracking, map, setIsTracking } = mapContext;
|
|
38
|
+
|
|
39
|
+
const geolocation = useMemo(() => {
|
|
40
|
+
return new Geolocation();
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
let keys = [];
|
|
45
|
+
if (!map || !geolocation) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
keys = [
|
|
49
|
+
// First time we zoom and center on the position
|
|
50
|
+
geolocation.once("change:position", (evt) => {
|
|
51
|
+
const position = evt.target.getPosition();
|
|
52
|
+
if (evt.target.getPosition()) {
|
|
53
|
+
const coord = fromLonLat(position, "EPSG:3857");
|
|
54
|
+
map.getView().setZoom(TRACKING_ZOOM);
|
|
55
|
+
map.getView().setCenter(coord);
|
|
56
|
+
point.setCoordinates(coord);
|
|
57
|
+
}
|
|
58
|
+
}),
|
|
59
|
+
// then we only center the map.
|
|
60
|
+
geolocation.on("change:position", (evt) => {
|
|
61
|
+
const position = evt.target.getPosition();
|
|
62
|
+
if (evt.target.getPosition()) {
|
|
63
|
+
const coord = fromLonLat(position, "EPSG:3857");
|
|
64
|
+
map.getView().setCenter(coord);
|
|
65
|
+
point.setCoordinates(coord);
|
|
66
|
+
}
|
|
67
|
+
}),
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
unByKey(keys);
|
|
72
|
+
};
|
|
73
|
+
}, [map, geolocation]);
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
geolocation.setTracking(isTracking);
|
|
77
|
+
if (isTracking) {
|
|
78
|
+
layer.setMap(map);
|
|
79
|
+
}
|
|
80
|
+
return () => {
|
|
81
|
+
layer.setMap(null);
|
|
82
|
+
};
|
|
83
|
+
}, [map, geolocation, isTracking]);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<IconButton
|
|
87
|
+
onClick={() => {
|
|
88
|
+
setIsTracking(!isTracking);
|
|
89
|
+
}}
|
|
90
|
+
selected={isTracking}
|
|
91
|
+
{...props}
|
|
92
|
+
>
|
|
93
|
+
<GeolocationIcon className={isTracking ? "animate-pulse" : ""} />
|
|
94
|
+
</IconButton>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default memo(GeolocationButton);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./GeolocationButton";
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { memo, SVGProps, useMemo } from "preact/compat";
|
|
1
|
+
import { memo, useMemo } from "preact/compat";
|
|
4
2
|
import { twMerge } from "tailwind-merge";
|
|
5
3
|
|
|
6
|
-
import {
|
|
4
|
+
import { themes } from "../RvfButton/RvfButton";
|
|
5
|
+
|
|
6
|
+
import type { SVGProps } from "preact/compat";
|
|
7
|
+
|
|
8
|
+
import type { RvfButtonProps } from "../RvfButton/RvfButton";
|
|
7
9
|
|
|
8
10
|
export type RvfIconButtonProps = {
|
|
9
11
|
Icon?: (props: SVGProps<SVGSVGElement>) => preact.JSX.Element;
|
|
10
|
-
} &
|
|
11
|
-
PreactDOMAttributes &
|
|
12
|
-
RvfButtonProps;
|
|
12
|
+
} & RvfButtonProps;
|
|
13
13
|
|
|
14
14
|
const baseClasses =
|
|
15
|
-
"flex size-[32px] @sm/main:size-[36px] @md/main:size-[40px] p-[7px] items-center justify-center rounded-full border";
|
|
15
|
+
"flex size-[32px] @sm/main:size-[36px] @md/main:size-[40px] p-[7px] items-center justify-center rounded-full border cursor-pointer disabled:cursor-default";
|
|
16
16
|
|
|
17
17
|
function RvfIconButton({
|
|
18
18
|
children,
|
|
19
19
|
className,
|
|
20
|
+
href,
|
|
20
21
|
Icon,
|
|
21
22
|
selected = false,
|
|
22
23
|
theme = "secondary",
|
|
@@ -24,10 +25,20 @@ function RvfIconButton({
|
|
|
24
25
|
}: RvfIconButtonProps) {
|
|
25
26
|
const classes = useMemo(() => {
|
|
26
27
|
return twMerge(
|
|
27
|
-
|
|
28
|
+
baseClasses,
|
|
29
|
+
themes[theme].classes,
|
|
30
|
+
selected ? themes[theme].selectedClasses : "",
|
|
31
|
+
className,
|
|
28
32
|
);
|
|
29
33
|
}, [className, selected, theme]);
|
|
30
34
|
|
|
35
|
+
if (href) {
|
|
36
|
+
return (
|
|
37
|
+
<a className={classes} href={href} {...props}>
|
|
38
|
+
{children || <Icon height={"100%"} width={"100%"} />}
|
|
39
|
+
</a>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
31
42
|
return (
|
|
32
43
|
<button className={classes} {...props}>
|
|
33
44
|
{children || <Icon height={"100%"} width={"100%"} />}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
-
|
|
3
1
|
import { useRef, useState } from "preact/hooks";
|
|
4
2
|
|
|
5
3
|
import Copy from "../icons/Copy";
|
|
6
|
-
import
|
|
4
|
+
import IconButton from "../ui/IconButton";
|
|
5
|
+
|
|
6
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
7
7
|
|
|
8
8
|
function RvfInputCopy(props: JSX.InputHTMLAttributes & PreactDOMAttributes) {
|
|
9
9
|
const [positionTooltip, setPositionTooltip] = useState<DOMRect>();
|
|
@@ -12,7 +12,7 @@ function RvfInputCopy(props: JSX.InputHTMLAttributes & PreactDOMAttributes) {
|
|
|
12
12
|
|
|
13
13
|
const handleCopyClick = (event) => {
|
|
14
14
|
setPositionTooltip(event.currentTarget.getBoundingClientRect());
|
|
15
|
-
navigator.clipboard.writeText(window?.location.href).then(() => {
|
|
15
|
+
void navigator.clipboard.writeText(window?.location.href).then(() => {
|
|
16
16
|
setIsTooltipShowed(true);
|
|
17
17
|
setTimeout(() => {
|
|
18
18
|
setIsTooltipShowed(false);
|
|
@@ -26,7 +26,7 @@ function RvfInputCopy(props: JSX.InputHTMLAttributes & PreactDOMAttributes) {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<div className="flex items-center
|
|
29
|
+
<div className="text-grey flex items-center">
|
|
30
30
|
<input
|
|
31
31
|
className="h-7 w-full rounded-sm rounded-r-none border border-r-0 border-current p-1 leading-4 outline-none"
|
|
32
32
|
onFocus={handleInputFocus}
|
|
@@ -35,14 +35,14 @@ function RvfInputCopy(props: JSX.InputHTMLAttributes & PreactDOMAttributes) {
|
|
|
35
35
|
type="text"
|
|
36
36
|
{...props}
|
|
37
37
|
/>
|
|
38
|
-
<
|
|
38
|
+
<IconButton
|
|
39
39
|
className="!size-7 rounded-l-none rounded-r-sm border-current"
|
|
40
40
|
onClick={handleCopyClick}
|
|
41
41
|
>
|
|
42
42
|
<Copy />
|
|
43
|
-
</
|
|
43
|
+
</IconButton>
|
|
44
44
|
<div
|
|
45
|
-
className={`fixed rounded-md
|
|
45
|
+
className={`bg-grey fixed rounded-md p-1 text-sm text-white ${isTooptipShowed ? "block" : "hidden"}`}
|
|
46
46
|
style={{
|
|
47
47
|
left: positionTooltip?.left - 30,
|
|
48
48
|
top: positionTooltip?.top - 40,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { JSX, PreactDOMAttributes } from "preact";
|
|
2
1
|
import { memo } from "preact/compat";
|
|
3
2
|
import { useEffect, useReducer } from "preact/hooks";
|
|
4
3
|
|
|
@@ -7,7 +6,11 @@ import {
|
|
|
7
6
|
LayersTreeDispatchContext,
|
|
8
7
|
} from "./layersTreeContext";
|
|
9
8
|
import layersTreeReducer from "./layersTreeReducer";
|
|
10
|
-
import TreeItem
|
|
9
|
+
import TreeItem from "./TreeItem/TreeItem";
|
|
10
|
+
|
|
11
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
12
|
+
|
|
13
|
+
import type { TreeItemProps } from "./TreeItem/TreeItem";
|
|
11
14
|
|
|
12
15
|
export type RvfLayerTreeProps = {
|
|
13
16
|
layers: TreeItemProps[];
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import BaseLayer from "ol/layer/Base";
|
|
4
|
-
import {
|
|
5
|
-
SVGProps,
|
|
6
|
-
useContext,
|
|
7
|
-
useEffect,
|
|
8
|
-
useId,
|
|
9
|
-
useState,
|
|
10
|
-
} from "preact/compat";
|
|
1
|
+
import { useContext, useEffect, useId, useState } from "preact/compat";
|
|
11
2
|
|
|
12
3
|
import ArrowDown from "../../icons/ArrowDown";
|
|
13
4
|
import ArrowUp from "../../icons/ArrowUp";
|
|
14
5
|
import minusGrey from "../../icons/Minus/minus-grey.svg";
|
|
15
6
|
import RvfCheckbox from "../../RvfCheckbox";
|
|
16
7
|
import RvfRadioButton from "../../RvfRadioButton";
|
|
8
|
+
import useLayerConfig from "../../utils/hooks/useLayerConfig";
|
|
17
9
|
import { LayersTreeDispatchContext } from "../layersTreeContext";
|
|
18
10
|
|
|
11
|
+
import type BaseLayer from "ol/layer/Base";
|
|
12
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
13
|
+
import type { SVGProps } from "preact/compat";
|
|
14
|
+
|
|
19
15
|
export enum SelectionType {
|
|
20
16
|
CHECKBOX = "checkbox",
|
|
21
17
|
RADIO = "radio",
|
|
@@ -46,6 +42,7 @@ function TreeItem({
|
|
|
46
42
|
const dispatch = useContext(LayersTreeDispatchContext);
|
|
47
43
|
const inputId = useId();
|
|
48
44
|
const buttonId = useId();
|
|
45
|
+
const layerConfig = useLayerConfig(layer.get("name"));
|
|
49
46
|
|
|
50
47
|
useEffect(() => {
|
|
51
48
|
if (isCollapsedOnControlClick) {
|
|
@@ -59,7 +56,7 @@ function TreeItem({
|
|
|
59
56
|
if (isCollapsedOnControlClick && !isContainerVisible) {
|
|
60
57
|
dispatch({
|
|
61
58
|
payload: {
|
|
62
|
-
...this
|
|
59
|
+
...this.props,
|
|
63
60
|
isControlChecked: true,
|
|
64
61
|
},
|
|
65
62
|
type: "SELECT_ITEM",
|
|
@@ -70,7 +67,7 @@ function TreeItem({
|
|
|
70
67
|
const handleSelectionChange = (event) => {
|
|
71
68
|
dispatch({
|
|
72
69
|
payload: {
|
|
73
|
-
...this
|
|
70
|
+
...this.props,
|
|
74
71
|
isControlChecked: event.target.checked,
|
|
75
72
|
},
|
|
76
73
|
type: "SELECT_ITEM",
|
|
@@ -78,14 +75,14 @@ function TreeItem({
|
|
|
78
75
|
};
|
|
79
76
|
|
|
80
77
|
const renderedLayers = childItems
|
|
81
|
-
.filter(({ title }) => {
|
|
82
|
-
return !!
|
|
78
|
+
.filter(({ title: titlee }) => {
|
|
79
|
+
return !!titlee;
|
|
83
80
|
})
|
|
84
81
|
.map((item, idx) => {
|
|
85
82
|
return <TreeItem key={idx} {...item} />;
|
|
86
83
|
});
|
|
87
84
|
|
|
88
|
-
if (!title) {
|
|
85
|
+
if (!title && !layerConfig.title) {
|
|
89
86
|
return null;
|
|
90
87
|
}
|
|
91
88
|
|
|
@@ -128,7 +125,7 @@ function TreeItem({
|
|
|
128
125
|
className={`flex-1 cursor-pointer`}
|
|
129
126
|
htmlFor={renderedLayers.length > 0 ? buttonId : inputId}
|
|
130
127
|
>
|
|
131
|
-
{title}
|
|
128
|
+
{layerConfig.title || title}
|
|
132
129
|
</label>
|
|
133
130
|
{renderedLayers.length > 0 && (
|
|
134
131
|
<button
|
|
@@ -5,14 +5,6 @@ const ROOT = {
|
|
|
5
5
|
parent: null,
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
const initTree = (tree) => {
|
|
9
|
-
const initializedTree = { ...ROOT };
|
|
10
|
-
initializedTree.childItems = tree;
|
|
11
|
-
mapNode(initializedTree.childItems, initializedTree);
|
|
12
|
-
|
|
13
|
-
return initializedTree;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
8
|
const mapNode = (childItems, parent) => {
|
|
17
9
|
for (const child of childItems) {
|
|
18
10
|
child.parent = parent;
|
|
@@ -23,6 +15,14 @@ const mapNode = (childItems, parent) => {
|
|
|
23
15
|
}
|
|
24
16
|
};
|
|
25
17
|
|
|
18
|
+
const initTree = (tree) => {
|
|
19
|
+
const initializedTree = { ...ROOT };
|
|
20
|
+
initializedTree.childItems = tree;
|
|
21
|
+
mapNode(initializedTree.childItems, initializedTree);
|
|
22
|
+
|
|
23
|
+
return initializedTree;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
26
|
const findNodeInTree = (node, nodeToFind) => {
|
|
27
27
|
if (node.id === nodeToFind.id) {
|
|
28
28
|
return node;
|
|
@@ -38,16 +38,6 @@ const findNodeInTree = (node, nodeToFind) => {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
const setNewControlCheckedStatus = (tree, newItem) => {
|
|
42
|
-
const currentItem = findNodeInTree(tree, newItem);
|
|
43
|
-
|
|
44
|
-
if (currentItem) {
|
|
45
|
-
updateCheckedControlStatus(currentItem, newItem, false);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return { ...tree };
|
|
49
|
-
};
|
|
50
|
-
|
|
51
41
|
const updateCheckedControlStatus = (currentItem, newItem, isParentUpdate) => {
|
|
52
42
|
if (newItem.isControlChecked) {
|
|
53
43
|
if (newItem.selectionType === SelectionType.CHECKBOX) {
|
|
@@ -58,6 +48,7 @@ const updateCheckedControlStatus = (currentItem, newItem, isParentUpdate) => {
|
|
|
58
48
|
child.isControlChecked = child.id === currentItem.id;
|
|
59
49
|
|
|
60
50
|
if (!child.isControlChecked) {
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
61
52
|
updateRadioChildNodes(child);
|
|
62
53
|
}
|
|
63
54
|
}
|
|
@@ -71,17 +62,31 @@ const updateCheckedControlStatus = (currentItem, newItem, isParentUpdate) => {
|
|
|
71
62
|
|
|
72
63
|
// check all children
|
|
73
64
|
if (currentItem.childItems.length && !isParentUpdate) {
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
74
66
|
updateChildNodes(currentItem);
|
|
75
67
|
}
|
|
76
68
|
|
|
77
69
|
// check all parents
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
78
71
|
updateParentNodes(currentItem);
|
|
79
72
|
};
|
|
80
73
|
|
|
74
|
+
const setNewControlCheckedStatus = (tree, newItem) => {
|
|
75
|
+
const currentItem = findNodeInTree(tree, newItem);
|
|
76
|
+
|
|
77
|
+
if (currentItem) {
|
|
78
|
+
updateCheckedControlStatus(currentItem, newItem, false);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { ...tree };
|
|
82
|
+
};
|
|
83
|
+
|
|
81
84
|
const updateChildNodes = (node) => {
|
|
82
85
|
if (node.childItems[0].selectionType === SelectionType.RADIO) {
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
83
87
|
updateRadioChildNodes(node);
|
|
84
88
|
} else {
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
85
90
|
updateCheckboxChildNodes(node);
|
|
86
91
|
}
|
|
87
92
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
-
|
|
3
1
|
import { memo } from "preact/compat";
|
|
4
2
|
import { useCallback } from "preact/hooks";
|
|
5
3
|
|
|
6
4
|
import Stack from "../icons/Stack";
|
|
7
|
-
import
|
|
5
|
+
import IconButton from "../ui/IconButton";
|
|
8
6
|
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
import type { HTMLAttributes, PreactDOMAttributes } from "preact";
|
|
9
|
+
|
|
10
|
+
export type RvfLayerTreeButtonProps = HTMLAttributes<HTMLButtonElement> &
|
|
11
11
|
PreactDOMAttributes;
|
|
12
12
|
|
|
13
13
|
function RvfLayerTreeButton({ ...props }: RvfLayerTreeButtonProps) {
|
|
@@ -18,9 +18,9 @@ function RvfLayerTreeButton({ ...props }: RvfLayerTreeButtonProps) {
|
|
|
18
18
|
}, [isLayerTreeOpen, setIsLayerTreeOpen]);
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
|
-
<
|
|
21
|
+
<IconButton {...props} onClick={onClick} selected={isLayerTreeOpen}>
|
|
22
22
|
<Stack />
|
|
23
|
-
</
|
|
23
|
+
</IconButton>
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { MaplibreStyleLayer } from "mobility-toolbox-js/ol";
|
|
2
|
-
import { MaplibreStyleLayerOptions } from "mobility-toolbox-js/ol/layers/MaplibreStyleLayer";
|
|
3
2
|
import { memo } from "preact/compat";
|
|
4
3
|
import { useEffect, useMemo } from "preact/hooks";
|
|
5
4
|
|
|
@@ -7,6 +6,8 @@ import { RVF_LAYERS_NAMES } from "../utils/constants";
|
|
|
7
6
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
8
7
|
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
9
8
|
|
|
9
|
+
import type { MaplibreStyleLayerOptions } from "mobility-toolbox-js/ol/layers/MaplibreStyleLayer";
|
|
10
|
+
|
|
10
11
|
function RvfLineNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
|
|
11
12
|
const { baseLayer, map } = useMapContext();
|
|
12
13
|
const { setLineNetworkPlanLayer } = useRvfContext();
|
package/src/RvfLink/RvfLink.tsx
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
-
|
|
3
1
|
import { memo, useMemo } from "preact/compat";
|
|
4
2
|
import { twMerge } from "tailwind-merge";
|
|
5
3
|
|
|
6
4
|
import ArrowUpRight from "../icons/ArrowUpRight";
|
|
7
5
|
|
|
6
|
+
import type { AnchorHTMLAttributes, PreactDOMAttributes } from "preact";
|
|
7
|
+
|
|
8
8
|
export type RvfLinkProps = {
|
|
9
9
|
theme?: "primary" | "secondary";
|
|
10
|
-
} &
|
|
10
|
+
} & AnchorHTMLAttributes<HTMLAnchorElement> &
|
|
11
11
|
PreactDOMAttributes;
|
|
12
12
|
|
|
13
13
|
const baseClasses =
|
|
@@ -33,6 +33,7 @@ function RvfLink({
|
|
|
33
33
|
}: RvfLinkProps) {
|
|
34
34
|
const classes = useMemo(() => {
|
|
35
35
|
return twMerge(
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
|
|
36
37
|
`${baseClasses} ${themes[theme].classes} ${className || ""}`,
|
|
37
38
|
);
|
|
38
39
|
}, [className, theme]);
|