@geops/rvf-mobility-web-component 0.1.13 → 0.1.14
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 +30 -0
- package/index.js +217 -112
- package/package.json +5 -3
- package/src/RvfButton/RvfButton.tsx +5 -2
- package/src/RvfCheckbox/RvfCheckbox.tsx +10 -4
- package/src/RvfExportMenu/RvfExportMenu.tsx +59 -77
- package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +1 -1
- package/src/RvfIconButton/RvfIconButton.tsx +4 -1
- package/src/RvfInputCopy/RvfInputCopy.tsx +57 -0
- package/src/RvfInputCopy/index.tsx +1 -0
- package/src/RvfLayerTree/TreeItem/TreeItem.tsx +20 -0
- package/src/RvfLayerTreeButton/RvfLayerTreeButton.tsx +27 -0
- package/src/RvfLayerTreeButton/index.tsx +1 -0
- package/src/RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx +2 -5
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +176 -18
- package/src/RvfOverlayHeader/RvfOverlayHeader.tsx +40 -0
- package/src/RvfOverlayHeader/index.tsx +1 -0
- package/src/RvfPermalink/RvfPermalink.tsx +18 -0
- package/src/RvfPermalink/index.tsx +1 -0
- package/src/RvfSelect/RvfSelect.tsx +2 -2
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +16 -1
- package/src/RvfShare/RvfPermalinkButton/RvfPermalinkButton.tsx +61 -0
- package/src/RvfShare/RvfPermalinkButton/index.tsx +1 -0
- package/src/RvfShare/RvfShare.tsx +40 -0
- package/src/RvfShare/index.tsx +1 -0
- package/src/RvfShareMenuButton/RvfShareMenuButton.tsx +27 -0
- package/src/RvfShareMenuButton/index.tsx +1 -0
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +64 -15
- package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +2 -5
- package/src/icons/Automat/Automat.tsx +8 -0
- package/src/icons/Automat/index.tsx +1 -0
- package/src/icons/Automat/rvf_automat.svg +15 -0
- package/src/icons/Bike/Bike.tsx +8 -0
- package/src/icons/Bike/index.tsx +1 -0
- package/src/icons/Bike/rvf_shared_bike.svg +15 -0
- package/src/icons/Car/Car.tsx +8 -0
- package/src/icons/Car/index.tsx +1 -0
- package/src/icons/Car/rvf_shared_car.svg +16 -0
- package/src/icons/CargoBike/CargoBike.tsx +8 -0
- package/src/icons/CargoBike/index.tsx +1 -0
- package/src/icons/CargoBike/rvf_shared_cargo_bike.svg +16 -0
- package/src/icons/Copy/Copy.tsx +25 -0
- package/src/icons/Copy/index.tsx +1 -0
- package/src/icons/Doc/Doc.tsx +19 -0
- package/src/icons/Doc/doc.svg +7 -0
- package/src/icons/Doc/index.tsx +1 -0
- package/src/icons/Ebike/Ebike.tsx +8 -0
- package/src/icons/Ebike/index.tsx +1 -0
- package/src/icons/Ebike/rvf_shared_e-bike.svg +15 -0
- package/src/icons/Email/Email.tsx +19 -0
- package/src/icons/Email/email.svg +7 -0
- package/src/icons/Email/index.tsx +1 -0
- package/src/icons/FilePdf/FilePdf.tsx +19 -0
- package/src/icons/FilePdf/file-pdf.svg +7 -0
- package/src/icons/FilePdf/index.tsx +1 -0
- package/src/icons/Image/Image.tsx +24 -0
- package/src/icons/Image/index.tsx +1 -0
- package/src/icons/InPerson/InPerson.tsx +8 -0
- package/src/icons/InPerson/index.tsx +1 -0
- package/src/icons/InPerson/rvf_persoenlich.svg +17 -0
- package/src/icons/Minus/minus-grey.svg +7 -0
- package/src/icons/Ride/Ride.tsx +8 -0
- package/src/icons/Ride/index.tsx +1 -0
- package/src/icons/Ride/rvf_shared_ride.svg +15 -0
- package/src/icons/Scooter/Scooter.tsx +8 -0
- package/src/icons/Scooter/index.tsx +1 -0
- package/src/icons/Scooter/rvf_shared_scooter.svg +15 -0
- package/src/icons/Share/Share.tsx +24 -0
- package/src/icons/Share/index.tsx +1 -0
- package/src/icons/Stack/Stack.tsx +24 -0
- package/src/icons/Stack/index.tsx +1 -0
- package/src/icons/Video/Video.tsx +8 -0
- package/src/icons/Video/index.tsx +1 -0
- package/src/icons/Video/rvf_video.svg +19 -0
- package/src/icons/rvf_shared_ride_2.svg +12 -0
- package/src/utils/createSharedMobilityLayer.ts +20 -20
- package/src/utils/hooks/useRvfContext.tsx +13 -1
- package/tailwind.config.mjs +3 -0
- package/src/icons/Bicycle/verkehrstraeger-rad-2px-white.svg +0 -19
- package/src/icons/Car/verkehrstraeger-auto-2px-white.svg +0 -14
- package/src/icons/CargoBicycle/verkehrstraeger-lastenrad-2px-white.svg +0 -27
- package/src/icons/Scooter/scooter.svg +0 -10
package/package.json
CHANGED
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
"name": "@geops/rvf-mobility-web-component",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
4
|
"description": "Web components for rvf in the domains of mobility and logistics.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.14",
|
|
6
6
|
"homepage": "https://rvf-mobility-web-component-geops.vercel.app/",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "index.js",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"jspdf": "^2.5.2",
|
|
11
11
|
"maplibre-gl": "^4.7.1",
|
|
12
|
-
"mobility-toolbox-js": "3.1.0",
|
|
12
|
+
"mobility-toolbox-js": "3.1.1-beta.0",
|
|
13
13
|
"ol": "^10.3.1",
|
|
14
14
|
"preact": "^10.25.4",
|
|
15
15
|
"preact-custom-element": "^4.3.0",
|
|
16
16
|
"react": "npm:@preact/compat@^18.3.1",
|
|
17
17
|
"react-dom": "npm:@preact/compat@^18.3.1",
|
|
18
18
|
"react-icons": "^5.4.0",
|
|
19
|
-
"
|
|
19
|
+
"react-spatial": "^1.12.2",
|
|
20
|
+
"rosetta": "^1.1.0",
|
|
21
|
+
"tailwind-merge": "^2.6.0"
|
|
20
22
|
},
|
|
21
23
|
"devDependencies": {
|
|
22
24
|
"@commitlint/cli": "^19.6.1",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
2
|
|
|
3
3
|
import { memo, useMemo } from "preact/compat";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
4
5
|
|
|
5
6
|
export type RvfButtonProps = {
|
|
6
7
|
selected?: boolean;
|
|
@@ -9,7 +10,7 @@ export type RvfButtonProps = {
|
|
|
9
10
|
PreactDOMAttributes;
|
|
10
11
|
|
|
11
12
|
const baseClasses =
|
|
12
|
-
"flex text-[14px] @sm/main:text-[16px] @md/main:text-[18px] h-[32px] @sm/main:h-[36px] @md/main:h-[40px] px-[22px] @sm/main:px-[22.5px] @md/main:px-[27.5px] pt-[7px] pb-[5px] @sm/main:pt-[8px] @sm/main:pb-[6px] @md/main:pt-[8.5px] @md/main:pb-[6.5px] items-center justify-
|
|
13
|
+
"flex gap-2 text-[14px] @sm/main:text-[16px] @md/main:text-[18px] h-[32px] @sm/main:h-[36px] @md/main:h-[40px] px-[22px] @sm/main:px-[22.5px] @md/main:px-[27.5px] pt-[7px] pb-[5px] @sm/main:pt-[8px] @sm/main:pb-[6px] @md/main:pt-[8.5px] @md/main:pb-[6.5px] items-center justify-left rounded-full border font-semibold text-button";
|
|
13
14
|
|
|
14
15
|
export const themes = {
|
|
15
16
|
primary: {
|
|
@@ -32,7 +33,9 @@ function RvfButton({
|
|
|
32
33
|
...props
|
|
33
34
|
}: RvfButtonProps) {
|
|
34
35
|
const classes = useMemo(() => {
|
|
35
|
-
return
|
|
36
|
+
return twMerge(
|
|
37
|
+
`${baseClasses} ${themes[theme].classes} ${selected ? themes[theme].selectedClasses : ""} ${className || ""}`,
|
|
38
|
+
);
|
|
36
39
|
}, [className, selected, theme]);
|
|
37
40
|
|
|
38
41
|
return (
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import type { JSX } from "preact";
|
|
2
2
|
|
|
3
3
|
import { memo } from "preact/compat";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
4
5
|
|
|
5
6
|
// @ts-expect-error - required for htm to resolve the JSX pragma
|
|
6
7
|
import ok from "../icons/Ok/ok-grey.svg";
|
|
7
8
|
|
|
8
|
-
export type RvfCheckboxProps = {
|
|
9
|
+
export type RvfCheckboxProps = {
|
|
10
|
+
checkedIconUrl?: string;
|
|
11
|
+
} & JSX.InputHTMLAttributes<HTMLInputElement>;
|
|
9
12
|
|
|
10
13
|
function RvfCheckbox({ className, ...props }: RvfCheckboxProps) {
|
|
14
|
+
const checkedIconUrl = props.checkedIconUrl || ok;
|
|
11
15
|
return (
|
|
12
16
|
<input
|
|
13
|
-
className={`
|
|
14
|
-
box-border size-[20px] flex-none cursor-pointer appearance-none rounded border-2 border-grey bg-white bg-contain bg-center text-grey disabled:cursor-default disabled:border-lightgrey ${className}`}
|
|
17
|
+
className={twMerge(`
|
|
18
|
+
box-border size-[20px] flex-none cursor-pointer appearance-none rounded border-2 border-grey bg-white bg-contain bg-center text-grey disabled:cursor-default disabled:border-lightgrey ${className}`)}
|
|
15
19
|
style={{
|
|
16
20
|
backgroundImage:
|
|
17
|
-
props.checked && !props.disabled
|
|
21
|
+
props.checked && !props.disabled
|
|
22
|
+
? `url('` + checkedIconUrl + `')`
|
|
23
|
+
: "",
|
|
18
24
|
}}
|
|
19
25
|
{...props}
|
|
20
26
|
type="checkbox"
|
|
@@ -2,16 +2,13 @@ import type { JSX, PreactDOMAttributes } from "preact";
|
|
|
2
2
|
|
|
3
3
|
import { memo, useId, useState } from "preact/compat";
|
|
4
4
|
|
|
5
|
-
import Cancel from "../icons/Cancel";
|
|
6
5
|
import RvfButton from "../RvfButton";
|
|
7
6
|
import RvfCheckbox from "../RvfCheckbox";
|
|
8
|
-
import RvfIconButton from "../RvfIconButton";
|
|
9
7
|
import RvfSelect from "../RvfSelect";
|
|
10
8
|
import { LAYER_PROP_IS_EXPORTING } from "../utils/constants";
|
|
11
9
|
import exportPdf from "../utils/exportPdf";
|
|
12
10
|
import getAllLayers from "../utils/getAllLayers";
|
|
13
11
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
14
|
-
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
15
12
|
|
|
16
13
|
export type RvfExportMenuButtonProps = JSX.HTMLAttributes<HTMLDivElement> &
|
|
17
14
|
PreactDOMAttributes;
|
|
@@ -19,7 +16,6 @@ export type RvfExportMenuButtonProps = JSX.HTMLAttributes<HTMLDivElement> &
|
|
|
19
16
|
const formats = ["A4", "A3", "A1", "A0"];
|
|
20
17
|
|
|
21
18
|
function RvfExportMenu({ ...props }: RvfExportMenuButtonProps) {
|
|
22
|
-
const { setIsExportMenuOpen } = useRvfContext();
|
|
23
19
|
const { map } = useMapContext();
|
|
24
20
|
const [useMaxExtent, setUseMaxExtent] = useState(false);
|
|
25
21
|
const [format, setFormat] = useState<string>(formats[0]);
|
|
@@ -29,85 +25,71 @@ function RvfExportMenu({ ...props }: RvfExportMenuButtonProps) {
|
|
|
29
25
|
const [isExportingError, setIsExportingError] = useState(false);
|
|
30
26
|
return (
|
|
31
27
|
<div {...props}>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<div className={"flex flex-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
{/* <!-- Content --> */}
|
|
29
|
+
<div className="flex flex-1 flex-col gap-2">
|
|
30
|
+
<div className={"flex flex-wrap items-center gap-2"}>
|
|
31
|
+
<RvfCheckbox
|
|
32
|
+
checked={useMaxExtent}
|
|
33
|
+
id={checkboxId}
|
|
34
|
+
onChange={() => {
|
|
35
|
+
return setUseMaxExtent(!useMaxExtent);
|
|
40
36
|
}}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
</RvfIconButton>
|
|
44
|
-
</div>
|
|
45
|
-
{/* <!-- Content --> */}
|
|
46
|
-
<div className="flex flex-1 flex-col gap-2">
|
|
47
|
-
<div className={"flex flex-wrap items-center gap-2"}>
|
|
48
|
-
<RvfCheckbox
|
|
49
|
-
checked={useMaxExtent}
|
|
50
|
-
id={checkboxId}
|
|
51
|
-
onChange={() => {
|
|
52
|
-
return setUseMaxExtent(!useMaxExtent);
|
|
53
|
-
}}
|
|
54
|
-
/>
|
|
55
|
-
<label htmlFor={checkboxId}>Ganze Region exportieren</label>
|
|
56
|
-
</div>
|
|
57
|
-
<div className={"flex flex-wrap items-center gap-2"}>
|
|
58
|
-
<label htmlFor={selectId}>Format:</label>
|
|
59
|
-
<RvfSelect
|
|
60
|
-
className={"w-24"}
|
|
61
|
-
id={selectId}
|
|
62
|
-
onChange={(evt) => {
|
|
63
|
-
setFormat((evt.target as HTMLSelectElement).value);
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
{formats.map((format) => {
|
|
67
|
-
return <option key={format}>{format}</option>;
|
|
68
|
-
})}
|
|
69
|
-
</RvfSelect>
|
|
70
|
-
</div>
|
|
37
|
+
/>
|
|
38
|
+
<label htmlFor={checkboxId}>Ganze Region exportieren</label>
|
|
71
39
|
</div>
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const result = await exportPdf(
|
|
80
|
-
map,
|
|
81
|
-
{ format },
|
|
82
|
-
{
|
|
83
|
-
onAfter: (map, layers) => {
|
|
84
|
-
getAllLayers(layers).forEach((layer) => {
|
|
85
|
-
layer.set(LAYER_PROP_IS_EXPORTING, false);
|
|
86
|
-
});
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
onBefore: (map, layers) => {
|
|
90
|
-
getAllLayers(layers).forEach((layer) => {
|
|
91
|
-
layer.set(LAYER_PROP_IS_EXPORTING, true);
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
useMaxExtent,
|
|
95
|
-
},
|
|
96
|
-
);
|
|
97
|
-
setTimeout(() => {
|
|
98
|
-
setIsExporting(false);
|
|
99
|
-
setIsExportingError(!result);
|
|
100
|
-
}, 1000);
|
|
40
|
+
<div className={"flex flex-wrap items-center gap-2"}>
|
|
41
|
+
<label htmlFor={selectId}>Format:</label>
|
|
42
|
+
<RvfSelect
|
|
43
|
+
className={"w-24"}
|
|
44
|
+
id={selectId}
|
|
45
|
+
onChange={(evt) => {
|
|
46
|
+
setFormat((evt.target as HTMLSelectElement).value);
|
|
101
47
|
}}
|
|
102
48
|
>
|
|
103
|
-
{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
: "Download"}
|
|
108
|
-
</RvfButton>
|
|
49
|
+
{formats.map((format) => {
|
|
50
|
+
return <option key={format}>{format}</option>;
|
|
51
|
+
})}
|
|
52
|
+
</RvfSelect>
|
|
109
53
|
</div>
|
|
110
54
|
</div>
|
|
55
|
+
{/* <!-- Footer --> */}
|
|
56
|
+
<div>
|
|
57
|
+
<RvfButton
|
|
58
|
+
disabled={isExporting}
|
|
59
|
+
onClick={async () => {
|
|
60
|
+
setIsExportingError(false);
|
|
61
|
+
setIsExporting(true);
|
|
62
|
+
const result = await exportPdf(
|
|
63
|
+
map,
|
|
64
|
+
{ format },
|
|
65
|
+
{
|
|
66
|
+
onAfter: (map, layers) => {
|
|
67
|
+
getAllLayers(layers).forEach((layer) => {
|
|
68
|
+
layer.set(LAYER_PROP_IS_EXPORTING, false);
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
onBefore: (map, layers) => {
|
|
73
|
+
getAllLayers(layers).forEach((layer) => {
|
|
74
|
+
layer.set(LAYER_PROP_IS_EXPORTING, true);
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
useMaxExtent,
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
setIsExporting(false);
|
|
82
|
+
setIsExportingError(!result);
|
|
83
|
+
}, 1000);
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
{isExporting
|
|
87
|
+
? "Exporting..."
|
|
88
|
+
: isExportingError
|
|
89
|
+
? "Error"
|
|
90
|
+
: "Download"}
|
|
91
|
+
</RvfButton>
|
|
92
|
+
</div>
|
|
111
93
|
</div>
|
|
112
94
|
);
|
|
113
95
|
}
|
|
@@ -32,7 +32,7 @@ function RvfFloatingMenu({
|
|
|
32
32
|
{title} {isOpen ? <ArrowDown /> : <ArrowUp />}
|
|
33
33
|
</button>
|
|
34
34
|
{!isOpen && (
|
|
35
|
-
<div className="flex h-[calc(100%-39px)] w-full flex-1 overflow-y-auto">
|
|
35
|
+
<div className="flex h-[calc(100%-39px)] w-full flex-1 flex-col overflow-y-auto">
|
|
36
36
|
{children}
|
|
37
37
|
</div>
|
|
38
38
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
2
|
|
|
3
3
|
import { memo, SVGProps, useMemo } from "preact/compat";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
4
5
|
|
|
5
6
|
import { RvfButtonProps, themes } from "../RvfButton/RvfButton";
|
|
6
7
|
|
|
@@ -22,7 +23,9 @@ function RvfIconButton({
|
|
|
22
23
|
...props
|
|
23
24
|
}: RvfIconButtonProps) {
|
|
24
25
|
const classes = useMemo(() => {
|
|
25
|
-
return
|
|
26
|
+
return twMerge(
|
|
27
|
+
`${baseClasses} ${themes[theme].classes} ${selected ? themes[theme].selectedClasses : ""} ${className || ""}`,
|
|
28
|
+
);
|
|
26
29
|
}, [className, selected, theme]);
|
|
27
30
|
|
|
28
31
|
return (
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
+
|
|
3
|
+
import { useRef, useState } from "preact/hooks";
|
|
4
|
+
|
|
5
|
+
import Copy from "../icons/Copy";
|
|
6
|
+
import RvfIconButton from "../RvfIconButton";
|
|
7
|
+
|
|
8
|
+
function RvfInputCopy(props: JSX.InputHTMLAttributes & PreactDOMAttributes) {
|
|
9
|
+
const [positionTooltip, setPositionTooltip] = useState<DOMRect>();
|
|
10
|
+
const [isTooptipShowed, setIsTooltipShowed] = useState(false);
|
|
11
|
+
const inputRef = useRef(null);
|
|
12
|
+
|
|
13
|
+
const handleCopyClick = (event) => {
|
|
14
|
+
setPositionTooltip(event.currentTarget.getBoundingClientRect());
|
|
15
|
+
navigator.clipboard.writeText(window?.location.href).then(() => {
|
|
16
|
+
setIsTooltipShowed(true);
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
setIsTooltipShowed(false);
|
|
19
|
+
}, 1000);
|
|
20
|
+
});
|
|
21
|
+
inputRef.current.select();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const handleInputFocus = () => {
|
|
25
|
+
inputRef.current.select();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="flex items-center text-grey">
|
|
30
|
+
<input
|
|
31
|
+
className="h-7 w-full rounded-sm rounded-r-none border border-r-0 border-current p-1 leading-4 outline-none"
|
|
32
|
+
onFocus={handleInputFocus}
|
|
33
|
+
readOnly
|
|
34
|
+
ref={inputRef}
|
|
35
|
+
type="text"
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
<RvfIconButton
|
|
39
|
+
className="!size-7 rounded-l-none rounded-r-sm border-current"
|
|
40
|
+
onClick={handleCopyClick}
|
|
41
|
+
>
|
|
42
|
+
<Copy />
|
|
43
|
+
</RvfIconButton>
|
|
44
|
+
<div
|
|
45
|
+
className={`fixed rounded-md bg-grey p-1 text-sm text-white ${isTooptipShowed ? "block" : "hidden"}`}
|
|
46
|
+
style={{
|
|
47
|
+
left: positionTooltip?.left - 30,
|
|
48
|
+
top: positionTooltip?.top - 40,
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
Link kopiert!
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default RvfInputCopy;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./RvfInputCopy";
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
|
|
12
12
|
import ArrowDown from "../../icons/ArrowDown";
|
|
13
13
|
import ArrowUp from "../../icons/ArrowUp";
|
|
14
|
+
import minusGrey from "../../icons/Minus/minus-grey.svg";
|
|
14
15
|
import RvfCheckbox from "../../RvfCheckbox";
|
|
15
16
|
import RvfRadioButton from "../../RvfRadioButton";
|
|
16
17
|
import { LayersTreeDispatchContext } from "../layersTreeContext";
|
|
@@ -88,6 +89,23 @@ function TreeItem({
|
|
|
88
89
|
return null;
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
const isMiddleState = () => {
|
|
93
|
+
if (childItems.length > 0) {
|
|
94
|
+
const checkedItems = childItems.filter((item) => {
|
|
95
|
+
return item.isControlChecked;
|
|
96
|
+
});
|
|
97
|
+
if (checkedItems.length === childItems.length) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return childItems.some((item) => {
|
|
102
|
+
return item.isControlChecked;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return false;
|
|
107
|
+
};
|
|
108
|
+
|
|
91
109
|
return (
|
|
92
110
|
<div>
|
|
93
111
|
<div className="flex items-center gap-2 border-b py-2 pr-1">
|
|
@@ -100,6 +118,8 @@ function TreeItem({
|
|
|
100
118
|
) : (
|
|
101
119
|
<RvfCheckbox
|
|
102
120
|
checked={isControlChecked}
|
|
121
|
+
checkedIconUrl={isMiddleState() ? minusGrey : null}
|
|
122
|
+
className={isMiddleState() ? "bg-[length:18px]" : ""}
|
|
103
123
|
id={inputId}
|
|
104
124
|
onChange={handleSelectionChange}
|
|
105
125
|
/>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
+
|
|
3
|
+
import { memo } from "preact/compat";
|
|
4
|
+
import { useCallback } from "preact/hooks";
|
|
5
|
+
|
|
6
|
+
import Stack from "../icons/Stack";
|
|
7
|
+
import RvfIconButton from "../RvfIconButton";
|
|
8
|
+
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
9
|
+
|
|
10
|
+
export type RvfLayerTreeButtonProps = JSX.HTMLAttributes<HTMLButtonElement> &
|
|
11
|
+
PreactDOMAttributes;
|
|
12
|
+
|
|
13
|
+
function RvfLayerTreeButton({ ...props }: RvfLayerTreeButtonProps) {
|
|
14
|
+
const { isLayerTreeOpen, setIsLayerTreeOpen } = useRvfContext();
|
|
15
|
+
|
|
16
|
+
const onClick = useCallback(() => {
|
|
17
|
+
setIsLayerTreeOpen(!isLayerTreeOpen);
|
|
18
|
+
}, [isLayerTreeOpen, setIsLayerTreeOpen]);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<RvfIconButton {...props} onClick={onClick} selected={isLayerTreeOpen}>
|
|
22
|
+
<Stack />
|
|
23
|
+
</RvfIconButton>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default memo(RvfLayerTreeButton);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./RvfLayerTreeButton";
|
|
@@ -16,11 +16,8 @@ function RvfLineNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
|
|
|
16
16
|
}
|
|
17
17
|
return new MaplibreStyleLayer({
|
|
18
18
|
isQueryable: true,
|
|
19
|
-
layersFilter: ({ metadata
|
|
20
|
-
return
|
|
21
|
-
metadata?.["rvf.filter"] === "netowrk_plans" ||
|
|
22
|
-
source === "network_plans"
|
|
23
|
-
);
|
|
19
|
+
layersFilter: ({ metadata }) => {
|
|
20
|
+
return metadata?.["rvf.filter"] === "netzplan_lines";
|
|
24
21
|
},
|
|
25
22
|
maplibreLayer: baseLayer,
|
|
26
23
|
minZoom: 10,
|