@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.
- package/CHANGELOG.md +23 -0
- package/docutils.js +1 -1
- package/global.d.ts +1 -0
- package/iframe.html +15 -0
- package/index.html +2 -1
- package/index.js +278 -330
- package/package.json +16 -17
- package/src/{RvfExportMenu/RvfExportMenu.tsx → ExportMenu/ExportMenu.tsx} +11 -11
- package/src/ExportMenu/index.tsx +1 -0
- package/src/{RvfExportMenuButton/RvfExportMenuButton.tsx → ExportMenuButton/ExportMenuButton.tsx} +5 -5
- package/src/ExportMenuButton/index.tsx +1 -0
- package/src/FeatureDetails/FeatureDetails.tsx +57 -0
- package/src/FeatureDetails/index.ts +1 -0
- package/src/FeaturesInfosListener/FeaturesInfosListener.tsx +73 -0
- package/src/FeaturesInfosListener/index.tsx +1 -0
- package/src/GeolocationButton/GeolocationButton.tsx +0 -1
- package/src/LayerTree/LayerTree.tsx +58 -0
- package/src/LayerTree/TreeItem/TreeItem.tsx +151 -0
- package/src/LayerTree/TreeItem/index.tsx +1 -0
- package/src/LayerTree/index.tsx +1 -0
- package/src/LayerTree/layersTreeContext.ts +4 -0
- package/src/LayerTree/layersTreeReducer.ts +158 -0
- package/src/{RvfLayerTreeButton/RvfLayerTreeButton.tsx → LayerTreeButton/LayerTreeButton.tsx} +5 -5
- package/src/LayerTreeButton/index.tsx +1 -0
- package/src/{RvfTopics/RvfTopics.tsx → LayerTreeMenu/LayerTreeMenu.tsx} +17 -13
- package/src/LayerTreeMenu/index.tsx +1 -0
- package/src/LayoutState/LayoutState.tsx +277 -0
- package/src/LayoutState/index.tsx +1 -0
- package/src/LinesNetworkPlanDetails/LinesNetworkPlanDetails.tsx +292 -0
- package/src/LinesNetworkPlanDetails/index.tsx +1 -0
- package/src/{RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx → LinesNetworkPlanLayer/LinesNetworkPlanLayer.tsx} +7 -9
- package/src/LinesNetworkPlanLayer/index.tsx +1 -0
- package/src/MobilityMap/MobilityMap.tsx +274 -60
- package/src/MobilityMap/MobilityMapAttributes.ts +27 -43
- package/src/NotificationDetails/NotificationDetails.tsx +468 -0
- package/src/NotificationDetails/index.ts +1 -0
- package/src/{NotificationLayer/NotificationLayer.tsx → NotificationsLayer/NotificationsLayer.tsx} +9 -4
- package/src/NotificationsLayer/index.tsx +1 -0
- package/src/Overlay/Overlay.tsx +1 -6
- package/src/OverlayContent/OverlayContent.tsx +87 -0
- package/src/OverlayContent/index.ts +1 -0
- package/src/OverlayDetails/OverlayDetails.tsx +47 -0
- package/src/OverlayDetails/index.ts +1 -0
- package/src/OverlayDetailsFooter/OverlayDetailsFooter.tsx +51 -0
- package/src/OverlayDetailsFooter/index.tsx +1 -0
- package/src/OverlayDetailsHeader/OverlayDetailsHeader.tsx +35 -0
- package/src/OverlayDetailsHeader/index.ts +1 -0
- package/src/OverlayFooter/OverlayFooter.tsx +41 -0
- package/src/OverlayFooter/index.tsx +1 -0
- package/src/OverlayHeader/OverlayHeader.tsx +44 -0
- package/src/OverlayHeader/index.tsx +1 -0
- package/src/PermalinkInput/PermalinkInput.tsx +28 -0
- package/src/PermalinkInput/index.tsx +1 -0
- package/src/RouteSchedule/RouteSchedule.tsx +22 -18
- package/src/RvfFeatureDetails/RvfFeatureDetails.tsx +22 -50
- package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +108 -104
- package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +189 -154
- package/src/RvfFeatureDetails/RvfSharedMobilityDetail/RvfSharedMobilityDetails.tsx +12 -14
- package/src/RvfFeatureDetailsTitle/RvfFeatureDetailsTitle.tsx +5 -5
- package/src/RvfMainLinkButton/RvfMainLinkButton.tsx +65 -0
- package/src/RvfMainLinkButton/index.tsx +1 -0
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +182 -394
- package/src/RvfOverlayContent/RvfOverlayContent.tsx +2 -2
- package/src/RvfPoisLayer/RvfPoisLayer.tsx +2 -2
- package/src/RvfSearch/RvfSearch.tsx +1 -1
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +2 -2
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +23 -23
- package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +2 -2
- package/src/Search/Search.tsx +11 -2
- package/src/{RvfSearchButton/RvfSearchButton.tsx → SearchButton/SearchButton.tsx} +5 -5
- package/src/SearchButton/index.tsx +1 -0
- package/src/ShadowOverflow/ShadowOverflow.tsx +20 -0
- package/src/ShadowOverflow/index.tsx +1 -0
- package/src/{RvfShare/RvfPermalinkButton/RvfPermalinkButton.tsx → ShareMenu/PermalinkButton/PermalinkButton.tsx} +4 -4
- package/src/ShareMenu/PermalinkButton/index.tsx +1 -0
- package/src/{RvfShare/RvfShare.tsx → ShareMenu/ShareMenu.tsx} +9 -11
- package/src/ShareMenu/index.tsx +1 -0
- package/src/{RvfShareMenuButton/RvfShareMenuButton.tsx → ShareMenuButton/ShareMenuButton.tsx} +6 -6
- package/src/ShareMenuButton/index.tsx +1 -0
- package/src/SingleClickListener/SingleClickListener.tsx +55 -113
- package/src/SingleClickListener/index.tsx +1 -1
- package/src/Station/Station.tsx +10 -3
- package/src/StationsLayer/StationsLayer.tsx +0 -1
- package/src/StopsSearch/StopsSearch.tsx +3 -4
- package/src/StopsSearch/index.tsx +2 -1
- package/src/WindowMessageListener/WindowMessageListener.tsx +7 -1
- package/src/{RvfZoomButtons/RvfZoomButtons.tsx → ZoomButtons/ZoomButtons.tsx} +9 -12
- package/src/ZoomButtons/index.tsx +1 -0
- package/src/icons/Geolocation/airport-14-svgrepo-com.svg +41 -0
- package/src/ui/Button/Button.tsx +9 -2
- package/src/ui/Checkbox/Checkbox.tsx +32 -0
- package/src/ui/Checkbox/index.tsx +1 -0
- package/src/ui/IconButton/IconButton.tsx +24 -4
- package/src/ui/Input/Input.tsx +17 -0
- package/src/ui/Input/index.tsx +1 -0
- package/src/ui/InputCopy/InputCopy.tsx +86 -0
- package/src/ui/InputCopy/index.tsx +1 -0
- package/src/ui/Select/Select.tsx +24 -0
- package/src/ui/Select/index.tsx +1 -0
- package/src/utils/constants.ts +43 -42
- package/src/utils/hooks/useInitialLayersVisiblity.tsx +1 -1
- package/src/utils/hooks/useLayerConfig.tsx +2 -2
- package/src/utils/hooks/useLayersConfig.tsx +3 -3
- package/src/utils/hooks/useMapContext.tsx +67 -8
- package/src/utils/hooks/useRvfContext.tsx +0 -44
- package/src/NotificationLayer/index.tsx +0 -1
- package/src/RvfEmbedNavigation/DragPanWarning.ts +0 -124
- package/src/RvfEmbedNavigation/RvfEmbedNavigation.tsx +0 -51
- package/src/RvfEmbedNavigation/index.js +0 -1
- package/src/RvfExportMenu/index.tsx +0 -1
- package/src/RvfExportMenuButton/index.tsx +0 -1
- package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +0 -44
- package/src/RvfFloatingMenu/index.tsx +0 -1
- package/src/RvfLayerTreeButton/index.tsx +0 -1
- package/src/RvfLineNetworkPlanLayer/index.tsx +0 -1
- package/src/RvfPermalink/RvfPermalink.tsx +0 -18
- package/src/RvfPermalink/index.tsx +0 -1
- package/src/RvfSearchButton/index.tsx +0 -1
- package/src/RvfShare/RvfPermalinkButton/index.tsx +0 -1
- package/src/RvfShare/index.tsx +0 -1
- package/src/RvfShareMenuButton/index.tsx +0 -1
- package/src/RvfTopics/index.tsx +0 -1
- package/src/RvfZoomButtons/index.tsx +0 -1
package/src/Station/Station.tsx
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { debounceDeparturesMessages } from "mobility-toolbox-js/ol";
|
|
2
2
|
import { memo } from "preact/compat";
|
|
3
3
|
import { useEffect, useRef, useState } from "preact/hooks";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
4
5
|
|
|
5
6
|
import Departure from "../Departure";
|
|
6
7
|
import StationHeader from "../StationHeader";
|
|
7
8
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
8
9
|
|
|
9
10
|
import type { RealtimeDeparture } from "mobility-toolbox-js/types";
|
|
10
|
-
import type {
|
|
11
|
+
import type { HTMLAttributes, PreactDOMAttributes } from "preact";
|
|
11
12
|
|
|
12
|
-
export type StationProps =
|
|
13
|
+
export type StationProps = {
|
|
14
|
+
className?: string;
|
|
15
|
+
} & HTMLAttributes<HTMLDivElement> &
|
|
13
16
|
PreactDOMAttributes;
|
|
14
17
|
|
|
15
18
|
function Station(props: StationProps) {
|
|
@@ -48,7 +51,11 @@ function Station(props: StationProps) {
|
|
|
48
51
|
return (
|
|
49
52
|
<>
|
|
50
53
|
<StationHeader />
|
|
51
|
-
<div
|
|
54
|
+
<div
|
|
55
|
+
className={twMerge("flex flex-col p-2", className)}
|
|
56
|
+
ref={ref}
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
52
59
|
{(departures || [])
|
|
53
60
|
// .filter(hideDepartures)
|
|
54
61
|
.map((departure: RealtimeDeparture, index: number) => {
|
|
@@ -13,6 +13,7 @@ import { twMerge } from "tailwind-merge";
|
|
|
13
13
|
import Cancel from "../icons/Cancel";
|
|
14
14
|
import Search from "../icons/Search";
|
|
15
15
|
import IconButton from "../ui/IconButton";
|
|
16
|
+
import Input from "../ui/Input";
|
|
16
17
|
import useI18n from "../utils/hooks/useI18n";
|
|
17
18
|
import MobilityEvent from "../utils/MobilityEvent";
|
|
18
19
|
|
|
@@ -242,13 +243,12 @@ function StopsSearch({
|
|
|
242
243
|
inputContainerClassName,
|
|
243
244
|
)}
|
|
244
245
|
>
|
|
245
|
-
<
|
|
246
|
+
<Input
|
|
246
247
|
autoComplete="off"
|
|
247
248
|
className={twMerge(
|
|
248
|
-
"h-8
|
|
249
|
+
"h-8 w-1 grow overflow-hidden text-ellipsis placeholder:text-zinc-400",
|
|
249
250
|
inputClassName,
|
|
250
251
|
)}
|
|
251
|
-
id="searchfield"
|
|
252
252
|
onChange={(evt) => {
|
|
253
253
|
// @ts-expect-error target is missing
|
|
254
254
|
setQuery(evt.target.value);
|
|
@@ -333,7 +333,6 @@ function StopsSearch({
|
|
|
333
333
|
)}
|
|
334
334
|
</div>
|
|
335
335
|
)}
|
|
336
|
-
{/* </div> */}
|
|
337
336
|
</>
|
|
338
337
|
);
|
|
339
338
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { default
|
|
1
|
+
export { default } from "./StopsSearch";
|
|
2
|
+
export type { StopsFeature, StopsSearchProps } from "./StopsSearch";
|
|
@@ -25,7 +25,6 @@ function WindowMessageListener({ eventNode }: { eventNode: HTMLElement }) {
|
|
|
25
25
|
useEffect(() => {
|
|
26
26
|
const onMessage = (event) => {
|
|
27
27
|
if (event.data.situations) {
|
|
28
|
-
console.log("Setting preview situations", event.data.situations);
|
|
29
28
|
setPreviewNotifications(event.data.situations);
|
|
30
29
|
}
|
|
31
30
|
};
|
|
@@ -47,6 +46,13 @@ function WindowMessageListener({ eventNode }: { eventNode: HTMLElement }) {
|
|
|
47
46
|
// @ts-expect-error children is the react property
|
|
48
47
|
delete evt.data.children;
|
|
49
48
|
}
|
|
49
|
+
if (evt.type === "mwc:selectedfeature") {
|
|
50
|
+
// @ts-expect-error children is the react property
|
|
51
|
+
if (evt.data?.properties?.olGeometry) {
|
|
52
|
+
// @ts-expect-error children is the react property
|
|
53
|
+
delete evt.data.properties.olGeometry;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
50
56
|
window.parent?.postMessage({ data: evt.data, type: evt.type }, "*");
|
|
51
57
|
};
|
|
52
58
|
evtTypes.forEach((eventType) => {
|
|
@@ -7,7 +7,7 @@ import Plus from "../icons/Plus";
|
|
|
7
7
|
import IconButton from "../ui/IconButton";
|
|
8
8
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
9
9
|
|
|
10
|
-
function
|
|
10
|
+
function ZoomButtons() {
|
|
11
11
|
const { map } = useMapContext();
|
|
12
12
|
const [isZoomInDisabled, setIsZoomInDisabled] = useState(false);
|
|
13
13
|
const [isZoomOutDisabled, setIsZoomOutDisabled] = useState(false);
|
|
@@ -56,18 +56,15 @@ function RvfZoomButtons() {
|
|
|
56
56
|
|
|
57
57
|
return (
|
|
58
58
|
<>
|
|
59
|
-
<IconButton
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Icon={Minus}
|
|
67
|
-
onClick={handleZoomOut}
|
|
68
|
-
/>
|
|
59
|
+
<IconButton disabled={isZoomInDisabled} onClick={handleZoomIn}>
|
|
60
|
+
<Plus />
|
|
61
|
+
</IconButton>
|
|
62
|
+
|
|
63
|
+
<IconButton disabled={isZoomOutDisabled} onClick={handleZoomOut}>
|
|
64
|
+
<Minus />
|
|
65
|
+
</IconButton>
|
|
69
66
|
</>
|
|
70
67
|
);
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
export default memo(
|
|
70
|
+
export default memo(ZoomButtons);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./ZoomButtons";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
7
|
+
xmlns:cc="http://creativecommons.org/ns#"
|
|
8
|
+
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
9
|
+
xmlns:svg="http://www.w3.org/2000/svg"
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
version="1.1"
|
|
12
|
+
width="100%"
|
|
13
|
+
height="100%"
|
|
14
|
+
viewBox="0 0 14 14"
|
|
15
|
+
id="svg2">
|
|
16
|
+
<metadata
|
|
17
|
+
id="metadata8">
|
|
18
|
+
<rdf:RDF>
|
|
19
|
+
<cc:Work
|
|
20
|
+
rdf:about="">
|
|
21
|
+
<dc:format>image/svg+xml</dc:format>
|
|
22
|
+
<dc:type
|
|
23
|
+
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
24
|
+
<dc:title></dc:title>
|
|
25
|
+
</cc:Work>
|
|
26
|
+
</rdf:RDF>
|
|
27
|
+
</metadata>
|
|
28
|
+
<defs
|
|
29
|
+
id="defs6" />
|
|
30
|
+
<rect
|
|
31
|
+
width="14"
|
|
32
|
+
height="14"
|
|
33
|
+
x="0"
|
|
34
|
+
y="0"
|
|
35
|
+
id="canvas"
|
|
36
|
+
style="fill:none;stroke:none;visibility:hidden" />
|
|
37
|
+
<path
|
|
38
|
+
d="m 14,8 0,1 -6,-1 0,3 2,2 0,1 L 7,13 4,14 4,13 6,11 6,8 0,9 0,8 6,5 6,2 C 6,1 6.22222,0 7,0 7.77777,0 8,1 8,2 l 0,3 z"
|
|
39
|
+
id="airport"
|
|
40
|
+
style="fill:#000000;fill-opacity:1;stroke:none" />
|
|
41
|
+
</svg>
|
package/src/ui/Button/Button.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { memo, useMemo } from "preact/compat";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
2
3
|
|
|
3
4
|
import type {
|
|
4
5
|
AnchorHTMLAttributes,
|
|
@@ -14,7 +15,8 @@ export type ButtonProps = {
|
|
|
14
15
|
ButtonHTMLAttributes &
|
|
15
16
|
PreactDOMAttributes;
|
|
16
17
|
|
|
17
|
-
const baseClasses =
|
|
18
|
+
const baseClasses =
|
|
19
|
+
"flex gap-2 items-center px-4 py-2 rounded-2xl border hover:border-black hover:not-disabled:cursor-pointer";
|
|
18
20
|
|
|
19
21
|
export const themes = {
|
|
20
22
|
primary: {
|
|
@@ -36,7 +38,12 @@ function Button({
|
|
|
36
38
|
...props
|
|
37
39
|
}: ButtonProps) {
|
|
38
40
|
const classes = useMemo(() => {
|
|
39
|
-
return
|
|
41
|
+
return twMerge(
|
|
42
|
+
baseClasses,
|
|
43
|
+
themes[theme].classes,
|
|
44
|
+
selected ? themes[theme].selectedClasses : "",
|
|
45
|
+
className,
|
|
46
|
+
);
|
|
40
47
|
}, [className, selected, theme]);
|
|
41
48
|
|
|
42
49
|
if (href) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { memo } from "preact/compat";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
import ok from "../../icons/Ok/ok-grey.svg";
|
|
5
|
+
|
|
6
|
+
import type { InputHTMLAttributes } from "preact";
|
|
7
|
+
|
|
8
|
+
export type RvfCheckboxProps = {
|
|
9
|
+
checkedIconUrl?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
} & InputHTMLAttributes;
|
|
12
|
+
|
|
13
|
+
function Checkbox({ className, ...props }: RvfCheckboxProps) {
|
|
14
|
+
const checkedIconUrl = props.checkedIconUrl || ok;
|
|
15
|
+
return (
|
|
16
|
+
<input
|
|
17
|
+
checked={props.checked}
|
|
18
|
+
className={twMerge(
|
|
19
|
+
`border-grey text-grey disabled:border-lightgrey box-border size-[20px] flex-none cursor-pointer appearance-none rounded border-2 bg-white bg-contain bg-center disabled:cursor-default`,
|
|
20
|
+
className,
|
|
21
|
+
)}
|
|
22
|
+
style={{
|
|
23
|
+
backgroundImage:
|
|
24
|
+
props.checked && !props.disabled ? `url('${checkedIconUrl}')` : "",
|
|
25
|
+
}}
|
|
26
|
+
{...props}
|
|
27
|
+
type="checkbox"
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default memo(Checkbox);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "../../RvfCheckbox";
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { memo, useMemo } from "preact/compat";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
2
3
|
|
|
3
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
AnchorHTMLAttributes,
|
|
6
|
+
ButtonHTMLAttributes,
|
|
7
|
+
PreactDOMAttributes,
|
|
8
|
+
} from "preact";
|
|
4
9
|
|
|
5
10
|
export type IconButtonProps = {
|
|
6
11
|
className?: string;
|
|
7
12
|
selected?: boolean;
|
|
8
13
|
theme?: "primary" | "secondary";
|
|
9
|
-
} &
|
|
14
|
+
} & AnchorHTMLAttributes &
|
|
15
|
+
ButtonHTMLAttributes &
|
|
10
16
|
PreactDOMAttributes;
|
|
11
17
|
|
|
12
18
|
const baseClasses =
|
|
13
|
-
"flex size-9 items-center justify-center rounded-full bg-white p-1.5 shadow-lg";
|
|
19
|
+
"flex size-9 items-center justify-center rounded-full bg-white p-1.5 shadow-lg hover:not-disabled:cursor-pointer";
|
|
14
20
|
|
|
15
21
|
export const themes = {
|
|
16
22
|
primary: {
|
|
@@ -26,14 +32,28 @@ export const themes = {
|
|
|
26
32
|
function IconButton({
|
|
27
33
|
children,
|
|
28
34
|
className,
|
|
35
|
+
href,
|
|
29
36
|
selected = false,
|
|
30
37
|
theme = "secondary",
|
|
31
38
|
...props
|
|
32
39
|
}: IconButtonProps) {
|
|
33
40
|
const classes = useMemo(() => {
|
|
34
|
-
return
|
|
41
|
+
return twMerge(
|
|
42
|
+
baseClasses,
|
|
43
|
+
themes[theme].classes,
|
|
44
|
+
selected ? themes[theme].selectedClasses : "",
|
|
45
|
+
className,
|
|
46
|
+
);
|
|
35
47
|
}, [className, selected, theme]);
|
|
36
48
|
|
|
49
|
+
if (href) {
|
|
50
|
+
return (
|
|
51
|
+
<a className={classes} href={href} {...props}>
|
|
52
|
+
{children}
|
|
53
|
+
</a>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
37
57
|
return (
|
|
38
58
|
<button className={classes} {...props}>
|
|
39
59
|
{children}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { twMerge } from "tailwind-merge";
|
|
2
|
+
|
|
3
|
+
import type { InputHTMLAttributes, PreactDOMAttributes } from "preact";
|
|
4
|
+
|
|
5
|
+
export type InputProps = { className?: string } & InputHTMLAttributes &
|
|
6
|
+
PreactDOMAttributes;
|
|
7
|
+
|
|
8
|
+
function Input({ className, ...props }: InputProps) {
|
|
9
|
+
return (
|
|
10
|
+
<input
|
|
11
|
+
{...props}
|
|
12
|
+
className={twMerge("p-2 text-sm read-only:text-gray-400", className)}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default Input;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./Input";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { useId, useState } from "preact/hooks";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
import Copy from "../../icons/Copy";
|
|
5
|
+
import IconButton from "../IconButton";
|
|
6
|
+
import Input from "../Input";
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
HTMLAttributes,
|
|
10
|
+
InputHTMLAttributes,
|
|
11
|
+
PreactDOMAttributes,
|
|
12
|
+
} from "preact";
|
|
13
|
+
|
|
14
|
+
export type InputCopyProps = {
|
|
15
|
+
containerProps?: HTMLAttributes<HTMLDivElement> & PreactDOMAttributes;
|
|
16
|
+
tooltipProps?: HTMLAttributes<HTMLDivElement> & PreactDOMAttributes;
|
|
17
|
+
} & InputHTMLAttributes &
|
|
18
|
+
PreactDOMAttributes;
|
|
19
|
+
|
|
20
|
+
const emptyProps = {}; // avoid re-rendering
|
|
21
|
+
|
|
22
|
+
function InputCopy({
|
|
23
|
+
containerProps = emptyProps,
|
|
24
|
+
tooltipProps = emptyProps,
|
|
25
|
+
...props
|
|
26
|
+
}: InputCopyProps) {
|
|
27
|
+
const [positionTooltip, setPositionTooltip] = useState<DOMRect>();
|
|
28
|
+
const [isTooptipShowed, setIsTooltipShowed] = useState(false);
|
|
29
|
+
const inputId = useId();
|
|
30
|
+
|
|
31
|
+
const handleCopyClick = (event) => {
|
|
32
|
+
setPositionTooltip(event.currentTarget.getBoundingClientRect());
|
|
33
|
+
void navigator.clipboard.writeText(window?.location.href).then(() => {
|
|
34
|
+
setIsTooltipShowed(true);
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
setIsTooltipShowed(false);
|
|
37
|
+
}, 1000);
|
|
38
|
+
});
|
|
39
|
+
(document.getElementById(inputId) as HTMLInputElement | null)?.select();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleInputFocus = () => {
|
|
43
|
+
(document.getElementById(inputId) as HTMLInputElement | null)?.select();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
{...containerProps}
|
|
49
|
+
className={twMerge(
|
|
50
|
+
"relative flex items-center",
|
|
51
|
+
containerProps?.className,
|
|
52
|
+
)}
|
|
53
|
+
>
|
|
54
|
+
<Input
|
|
55
|
+
id={inputId}
|
|
56
|
+
onFocus={handleInputFocus}
|
|
57
|
+
readOnly
|
|
58
|
+
type="text"
|
|
59
|
+
{...props}
|
|
60
|
+
className={twMerge("h-full flex-1 border border-r-0", props?.className)}
|
|
61
|
+
/>
|
|
62
|
+
<IconButton
|
|
63
|
+
className="h-full rounded-none border p-2 shadow-none"
|
|
64
|
+
onClick={handleCopyClick}
|
|
65
|
+
>
|
|
66
|
+
<Copy />
|
|
67
|
+
</IconButton>
|
|
68
|
+
<div
|
|
69
|
+
{...tooltipProps}
|
|
70
|
+
className={twMerge(
|
|
71
|
+
`fixed hidden rounded bg-gray-600 p-1 text-sm text-white`,
|
|
72
|
+
isTooptipShowed && "block",
|
|
73
|
+
tooltipProps?.className,
|
|
74
|
+
)}
|
|
75
|
+
style={{
|
|
76
|
+
left: positionTooltip?.left - 30,
|
|
77
|
+
top: positionTooltip?.top - 30,
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
Kopiert!
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default InputCopy;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "../../RvfInputCopy";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import ArrowDown from "../../icons/ArrowDown";
|
|
2
|
+
|
|
3
|
+
import type { HTMLAttributes, PreactDOMAttributes } from "preact";
|
|
4
|
+
|
|
5
|
+
export type RvfSelectProps = {
|
|
6
|
+
className?: string;
|
|
7
|
+
} & HTMLAttributes<HTMLSelectElement> &
|
|
8
|
+
PreactDOMAttributes;
|
|
9
|
+
|
|
10
|
+
function Select({ children, className, onChange }: RvfSelectProps) {
|
|
11
|
+
return (
|
|
12
|
+
<div className="text-grey relative flex items-center">
|
|
13
|
+
<select
|
|
14
|
+
className={`h-[32px] cursor-pointer appearance-none rounded-[12px] border border-current bg-white px-[13px] text-[16px] leading-[22px] disabled:cursor-default @sm/main:h-[36px] @md/main:h-[40px] ${className}`}
|
|
15
|
+
onChange={onChange}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</select>
|
|
19
|
+
<ArrowDown className="pointer-events-none absolute right-[8px]" />
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default Select;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "../../RvfSelect";
|
package/src/utils/constants.ts
CHANGED
|
@@ -13,46 +13,49 @@ import type { FeatureCollection } from "geojson";
|
|
|
13
13
|
|
|
14
14
|
export const LAYER_NAME_REALTIME = "echtzeit";
|
|
15
15
|
export const LAYER_NAME_STATIONS = "haltestellen";
|
|
16
|
-
export const
|
|
16
|
+
export const LAYER_NAME_NOTIFICATIONS = "meldungen";
|
|
17
|
+
export const LAYER_NAME_LINESNETWORKPLAN = "liniennetz";
|
|
17
18
|
|
|
18
19
|
export const RVF_EXTENT_4326 = [7.5, 47.7, 8.45, 48.4];
|
|
19
20
|
|
|
20
|
-
export const
|
|
21
|
+
export const MAX_EXTENT = transformExtent(
|
|
21
22
|
RVF_EXTENT_4326,
|
|
22
23
|
"EPSG:4326",
|
|
23
24
|
"EPSG:3857",
|
|
24
25
|
);
|
|
25
26
|
|
|
27
|
+
export const RVF_EXTENT_3857 = MAX_EXTENT;
|
|
28
|
+
|
|
26
29
|
// @ts-expect-error - testsdsd sd
|
|
27
30
|
window.fromLonLat = fromLonLat;
|
|
28
31
|
// @ts-expect-error - testsdsd sd
|
|
29
32
|
window.toLonLat = toLonLat;
|
|
30
33
|
export const LAYER_PROP_IS_EXPORTING = "isExporting";
|
|
31
34
|
|
|
32
|
-
export const
|
|
35
|
+
export const LAYERS_TITLES = {
|
|
33
36
|
auto: "Auto",
|
|
34
37
|
autoandere: "Auto, andere Anbieter",
|
|
35
38
|
cargobike: "Cargobike",
|
|
36
39
|
cargobikeandere: "Lastenrad, andere Anbieter",
|
|
37
40
|
cargobikefrelo: "Lastenfrelo",
|
|
38
41
|
"e-roller": "E-Roller",
|
|
39
|
-
echtzeit: "Echtzeit",
|
|
40
42
|
eroller: "E-Roller",
|
|
41
43
|
fahrrad: "Fahrrad",
|
|
42
44
|
fahrradandere: "Fahrrad, andere Anbieter",
|
|
43
45
|
grueneflotte: "Grüne Flotte",
|
|
44
|
-
|
|
45
|
-
liniennetz: "Liniennetz",
|
|
46
|
-
meldungen: "Meldungen",
|
|
46
|
+
linesnetworkplan: "Liniennetz",
|
|
47
47
|
mitfahrpunkte: "Mitfahrpunkte",
|
|
48
48
|
naturenergie: "Naturenergie-Sharing",
|
|
49
|
+
notifications: "Meldungen",
|
|
49
50
|
pois: "POIs",
|
|
51
|
+
realtime: "Echtzeit",
|
|
50
52
|
sharedMobility: "Shared Mobility",
|
|
53
|
+
stations: "Haltestellen",
|
|
51
54
|
tarifzonen: "Tarifzonen",
|
|
52
55
|
verkaufsstellen: "Verkaufsstellen",
|
|
53
56
|
};
|
|
54
57
|
|
|
55
|
-
export const
|
|
58
|
+
export const LAYERS_NAMES = {
|
|
56
59
|
bikeFrelo: "fahrradfrelo",
|
|
57
60
|
bikeOthers: "fahrradandere",
|
|
58
61
|
cargobikeFrelo: "cargobikefrelo",
|
|
@@ -60,37 +63,35 @@ export const RVF_LAYERS_NAMES = {
|
|
|
60
63
|
carGrf: "grueneflotte",
|
|
61
64
|
carNatur: "naturenergie",
|
|
62
65
|
carOthers: "autoandere",
|
|
63
|
-
echtzeit: LAYER_NAME_REALTIME,
|
|
64
66
|
eroller: "e-roller",
|
|
65
|
-
|
|
66
|
-
liniennetz: "liniennetz",
|
|
67
|
-
meldungen: LAYER_NAME_NOTIFICATION,
|
|
67
|
+
linesnetworkplan: LAYER_NAME_LINESNETWORKPLAN,
|
|
68
68
|
mitfahrpunkte: "mitfahrpunkte",
|
|
69
|
+
notifications: LAYER_NAME_NOTIFICATIONS,
|
|
69
70
|
pois: "pois",
|
|
71
|
+
realtime: LAYER_NAME_REALTIME,
|
|
72
|
+
stations: LAYER_NAME_STATIONS,
|
|
70
73
|
tarifzonen: "tarifzonen",
|
|
71
74
|
verkaufsstellen: "verkaufsstellen",
|
|
72
75
|
};
|
|
73
76
|
|
|
74
|
-
export const DEFAULT_QUERYABLE_LAYERS = Object.values(
|
|
75
|
-
|
|
77
|
+
export const DEFAULT_QUERYABLE_LAYERS = Object.values(LAYERS_NAMES).filter(
|
|
78
|
+
(name) => {
|
|
76
79
|
return ![
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
LAYERS_NAMES.mitfahrpunkte,
|
|
81
|
+
LAYERS_NAMES.pois,
|
|
82
|
+
LAYERS_NAMES.stations,
|
|
83
|
+
LAYERS_NAMES.tarifzonen,
|
|
81
84
|
].includes(name);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
export const LAYERS_WITH_LINK = Object.values(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
})
|
|
93
|
-
.toString();
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
export const LAYERS_WITH_LINK = Object.values(LAYERS_NAMES).filter((name) => {
|
|
89
|
+
return (
|
|
90
|
+
name !== LAYERS_NAMES.tarifzonen &&
|
|
91
|
+
name !== LAYERS_NAMES.pois &&
|
|
92
|
+
name !== LAYERS_NAMES.realtime
|
|
93
|
+
);
|
|
94
|
+
});
|
|
94
95
|
|
|
95
96
|
export const WFS_CARGO_BIKE_TYPE = "sharing_stations_cargo_bicycle";
|
|
96
97
|
export const WFS_CAR_TYPE = "sharing_stations_car";
|
|
@@ -128,21 +129,21 @@ export const API_REQUEST_FEATURE_TYPE = {
|
|
|
128
129
|
};
|
|
129
130
|
|
|
130
131
|
export const TITLE_BY_FEED_ID = {
|
|
131
|
-
callabike_ice:
|
|
132
|
-
flinkster_carsharing:
|
|
133
|
-
"gruene-flotte_freiburg":
|
|
134
|
-
lastenvelo_fr:
|
|
135
|
-
naturenergie_sharing:
|
|
136
|
-
nextbike_df:
|
|
137
|
-
yoio_freiburg:
|
|
138
|
-
zeus_freiburg:
|
|
132
|
+
callabike_ice: LAYERS_TITLES.fahrrad,
|
|
133
|
+
flinkster_carsharing: LAYERS_TITLES.auto,
|
|
134
|
+
"gruene-flotte_freiburg": LAYERS_TITLES.auto,
|
|
135
|
+
lastenvelo_fr: LAYERS_TITLES.cargobike,
|
|
136
|
+
naturenergie_sharing: LAYERS_TITLES.auto,
|
|
137
|
+
nextbike_df: LAYERS_TITLES.fahrrad,
|
|
138
|
+
yoio_freiburg: LAYERS_TITLES.eroller,
|
|
139
|
+
zeus_freiburg: LAYERS_TITLES.eroller,
|
|
139
140
|
};
|
|
140
141
|
|
|
141
142
|
export const TITLE_BY_CATEGORY = {
|
|
142
|
-
"Bike Sharing":
|
|
143
|
-
"Cargo Bike Sharing":
|
|
144
|
-
"Car Sharing":
|
|
145
|
-
"E-Scooter":
|
|
143
|
+
"Bike Sharing": LAYERS_TITLES.fahrrad,
|
|
144
|
+
"Cargo Bike Sharing": LAYERS_TITLES.cargobike,
|
|
145
|
+
"Car Sharing": LAYERS_TITLES.auto,
|
|
146
|
+
"E-Scooter": LAYERS_TITLES.eroller,
|
|
146
147
|
};
|
|
147
148
|
|
|
148
149
|
export const PROVIDER_BY_FEED_ID = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { getLayersAsFlatArray } from "mobility-toolbox-js/ol";
|
|
1
2
|
import { unByKey } from "ol/Observable";
|
|
2
3
|
import { useEffect } from "preact/hooks";
|
|
3
4
|
|
|
4
5
|
import applyInitialLayerVisibility from "../applyInitialLayerVisibility";
|
|
5
|
-
import getLayersAsFlatArray from "../getLayersAsFlatArray";
|
|
6
6
|
|
|
7
7
|
import type { Map } from "ol";
|
|
8
8
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LAYERS_TITLES } from "../constants";
|
|
2
2
|
|
|
3
3
|
import useLayersConfig from "./useLayersConfig";
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ function useLayerConfig(layerName: string) {
|
|
|
10
10
|
// Set defaultstyle if not present in layersconfig
|
|
11
11
|
const layerConfig = layersConfig[layerName] || ({} as LayerConfig);
|
|
12
12
|
if (!layerConfig.title) {
|
|
13
|
-
layerConfig.title =
|
|
13
|
+
layerConfig.title = LAYERS_TITLES[layerName];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
return layerConfig;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useState } from "preact/hooks";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { LAYERS_NAMES, LAYERS_TITLES } from "../constants";
|
|
4
4
|
|
|
5
5
|
import useMapContext from "./useMapContext";
|
|
6
6
|
|
|
@@ -23,9 +23,9 @@ function useLayersConfig() {
|
|
|
23
23
|
const config = JSON.parse(layersconfig || "{}");
|
|
24
24
|
|
|
25
25
|
// Set the default title if not present in layersconfig
|
|
26
|
-
Object.values(
|
|
26
|
+
Object.values(LAYERS_NAMES).forEach((name) => {
|
|
27
27
|
config[name] = {
|
|
28
|
-
title:
|
|
28
|
+
title: LAYERS_TITLES[name],
|
|
29
29
|
...(config[name] || {}),
|
|
30
30
|
};
|
|
31
31
|
});
|