@geops/rvf-mobility-web-component 0.1.11 → 0.1.13
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 +36 -0
- package/docutils.js +9 -9
- package/index.html +1 -1
- package/index.js +332 -263
- package/input.css +2 -8
- package/package.json +15 -15
- package/scripts/build.mjs +3 -3
- package/scripts/dev.mjs +3 -1
- package/src/BaseLayer/BaseLayer.tsx +20 -12
- package/src/RealtimeLayer/RealtimeLayer.tsx +1 -2
- package/src/RouteSchedule/RouteSchedule.tsx +3 -1
- package/src/RouteStop/RouteStop.tsx +1 -1
- package/src/RvfButton/RvfButton.tsx +2 -2
- package/src/RvfCheckbox/RvfCheckbox.tsx +25 -0
- package/src/RvfCheckbox/index.tsx +1 -0
- package/src/RvfExportMenu/RvfExportMenu.tsx +31 -11
- package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +44 -0
- package/src/RvfFloatingMenu/index.tsx +1 -0
- package/src/RvfIconButton/RvfIconButton.tsx +1 -1
- package/src/{LayerTree/LayerTree.tsx → RvfLayerTree/RvfLayerTree.tsx} +11 -18
- package/src/RvfLayerTree/TreeItem/TreeItem.tsx +130 -0
- package/src/RvfLayerTree/index.tsx +1 -0
- package/src/{LayerTree → RvfLayerTree}/layersTreeReducer.ts +1 -4
- package/src/RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx +49 -0
- package/src/RvfLineNetworkPlanLayer/index.tsx +1 -0
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +100 -35
- package/src/RvfPoisLayer/RvfPoisLayer.tsx +6 -0
- package/src/RvfRadioButton/RvfRadioButton.tsx +16 -0
- package/src/RvfRadioButton/index.tsx +1 -0
- package/src/RvfSelect/RvfSelect.tsx +22 -0
- package/src/RvfSelect/index.tsx +1 -0
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +45 -0
- package/src/RvfSellingPointsLayer/index.tsx +1 -0
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +93 -44
- package/src/RvfSingleClickListener/RvfSingleClickListener.tsx +20 -3
- package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +48 -0
- package/src/RvfTarifZonenLayer/index.tsx +1 -0
- package/src/RvfTopics/RvfTopics.tsx +44 -0
- package/src/RvfTopics/index.tsx +1 -0
- package/src/icons/ArrowDown/ArrowDown.tsx +22 -0
- package/src/icons/ArrowDown/down-open.svg +7 -0
- package/src/icons/ArrowDown/index.tsx +1 -0
- package/src/icons/ArrowUp/ArrowUp.tsx +22 -0
- package/src/icons/ArrowUp/index.tsx +1 -0
- package/src/icons/ArrowUp/up-open.svg +7 -0
- package/src/icons/Bicycle/verkehrstraeger-rad-2px-white.svg +19 -0
- package/src/icons/Car/verkehrstraeger-auto-2px-white.svg +14 -0
- package/src/icons/CargoBicycle/verkehrstraeger-lastenrad-2px-white.svg +27 -0
- package/src/icons/DownOpen/DownOpen.tsx +24 -0
- package/src/icons/DownOpen/down-open.svg +7 -0
- package/src/icons/DownOpen/index.tsx +1 -0
- package/src/icons/Ok/ok-grey.svg +7 -0
- package/src/icons/Ok/ok.svg +4 -0
- package/src/icons/Scooter/scooter.svg +10 -0
- package/src/utils/constants.ts +2 -0
- package/src/utils/createMobiDataBwWfsLayer.ts +31 -23
- package/src/utils/createSharedMobilityLayer.ts +176 -0
- package/src/utils/exportPdf.ts +20 -29
- package/src/utils/getAllLayers.ts +25 -0
- package/src/utils/hooks/useRvfContext.tsx +33 -0
- package/tailwind.config.mjs +31 -50
- package/src/LayerTree/TreeItem/TreeItem.tsx +0 -145
- package/src/LayerTree/TreeItemContainer/TreeItemContainer.tsx +0 -16
- package/src/LayerTree/TreeItemContainer/index.tsx +0 -1
- package/src/LayerTree/index.tsx +0 -1
- package/src/TopicMenu/TopicMenu.tsx +0 -143
- package/src/TopicMenu/index.tsx +0 -1
- /package/src/{LayerTree → RvfLayerTree}/TreeItem/index.tsx +0 -0
- /package/src/{LayerTree → RvfLayerTree}/layersTreeContext.ts +0 -0
package/src/utils/exportPdf.ts
CHANGED
|
@@ -26,7 +26,7 @@ let multilineCopyright = false;
|
|
|
26
26
|
const copyrightY = 0;
|
|
27
27
|
|
|
28
28
|
// Ensure the font size fita with the image width.
|
|
29
|
-
const decreaseFontSize = (destContext, maxWidth, copyright, scale) => {
|
|
29
|
+
const decreaseFontSize = (destContext, maxWidth, copyright, scale = 1) => {
|
|
30
30
|
const minFontSize = 8;
|
|
31
31
|
let sizeMatch;
|
|
32
32
|
let fontSize;
|
|
@@ -158,7 +158,6 @@ const drawText = (
|
|
|
158
158
|
textBaseline?: CanvasTextBaseline;
|
|
159
159
|
},
|
|
160
160
|
) => {
|
|
161
|
-
const scale = 1;
|
|
162
161
|
const canvas = document.createElement("canvas");
|
|
163
162
|
canvas.width = width;
|
|
164
163
|
canvas.height = height;
|
|
@@ -174,7 +173,7 @@ const drawText = (
|
|
|
174
173
|
|
|
175
174
|
ctx.fillStyle = fillStyle;
|
|
176
175
|
ctx.font = font;
|
|
177
|
-
ctx.font = decreaseFontSize(ctx, canvas.width, text
|
|
176
|
+
ctx.font = decreaseFontSize(ctx, canvas.width, text);
|
|
178
177
|
ctx.textAlign = textAlign;
|
|
179
178
|
ctx.textBaseline = textBaseline;
|
|
180
179
|
|
|
@@ -462,15 +461,6 @@ const createMapToExport = async (
|
|
|
462
461
|
const mapSize = size || map.getSize();
|
|
463
462
|
const extentToFit = extent;
|
|
464
463
|
|
|
465
|
-
// We apply preserveDrawingBuffer=true to be able to export the canvas.
|
|
466
|
-
// layers.forEach((layer) => {
|
|
467
|
-
// // @ts-expect-error - mapLibreMap is private
|
|
468
|
-
// if (layer?.mapLibreMap as MaplibreGlMap) {
|
|
469
|
-
// const opts = layer.get("mapLibreOptions");
|
|
470
|
-
// opts.preserveDrawingBuffer = true;
|
|
471
|
-
// }
|
|
472
|
-
// });
|
|
473
|
-
|
|
474
464
|
// We create a temporary map.
|
|
475
465
|
const div = document.createElement("div");
|
|
476
466
|
div.style.width = `${mapSize[0]}px`;
|
|
@@ -490,6 +480,7 @@ const createMapToExport = async (
|
|
|
490
480
|
projection: map.getView().getProjection(),
|
|
491
481
|
zoom: map.getView().getZoom(),
|
|
492
482
|
...viewOptions,
|
|
483
|
+
// extent: extentToFit,
|
|
493
484
|
}),
|
|
494
485
|
...mapOptions,
|
|
495
486
|
});
|
|
@@ -514,15 +505,6 @@ const createMapToExport = async (
|
|
|
514
505
|
});
|
|
515
506
|
});
|
|
516
507
|
|
|
517
|
-
// We apply preserveDrawingBuffer=true to be able to export the canvas.
|
|
518
|
-
// layers.forEach((layer) => {
|
|
519
|
-
// // @ts-expect-error - mapLibreMap is private
|
|
520
|
-
// if (layer?.mapLibreMap as MaplibreGlMap) {
|
|
521
|
-
// const opts = layer.get("mapLibreOptions");
|
|
522
|
-
// opts.preserveDrawingBuffer = false;
|
|
523
|
-
// }
|
|
524
|
-
// });
|
|
525
|
-
|
|
526
508
|
return await promise;
|
|
527
509
|
};
|
|
528
510
|
|
|
@@ -544,6 +526,8 @@ export interface CopyrightExportOptions {
|
|
|
544
526
|
|
|
545
527
|
export interface MapExportOptions {
|
|
546
528
|
copyrightOptions?: CopyrightExportOptions;
|
|
529
|
+
onAfter?: (map: Map, layers: BaseLayer[]) => void;
|
|
530
|
+
onBefore?: (map: Map, layers: BaseLayer[]) => void;
|
|
547
531
|
pixelRatio?: number;
|
|
548
532
|
text?: string;
|
|
549
533
|
useCopyright?: boolean;
|
|
@@ -557,13 +541,19 @@ async function exportPdf(
|
|
|
557
541
|
mapExportOptions: MapExportOptions = {},
|
|
558
542
|
): Promise<boolean> {
|
|
559
543
|
const {
|
|
544
|
+
onAfter,
|
|
545
|
+
onBefore,
|
|
560
546
|
pixelRatio = 3,
|
|
561
547
|
useCopyright = true,
|
|
562
548
|
useMaxExtent = false,
|
|
563
549
|
usePlaceholder = true,
|
|
564
550
|
} = mapExportOptions;
|
|
551
|
+
|
|
565
552
|
const format = formatOptions?.format || "A4";
|
|
566
|
-
const
|
|
553
|
+
const sizePt = sizesByFormat72Dpi[format as string] || (format as number[]);
|
|
554
|
+
const size = sizePt.map((n) => {
|
|
555
|
+
return (n * 96) / 72;
|
|
556
|
+
});
|
|
567
557
|
const extent = useMaxExtent
|
|
568
558
|
? RVF_EXTENT_3857
|
|
569
559
|
: map.getView().calculateExtent();
|
|
@@ -605,6 +595,9 @@ async function exportPdf(
|
|
|
605
595
|
|
|
606
596
|
map.getLayers().clear();
|
|
607
597
|
|
|
598
|
+
// Hide/show some layer before export
|
|
599
|
+
onBefore?.(map, layers);
|
|
600
|
+
|
|
608
601
|
// Creates a new map with proper size and extent
|
|
609
602
|
const mapToExport = await createMapToExport(map, layers, extent, size, {
|
|
610
603
|
pixelRatio: pixelRatio,
|
|
@@ -627,6 +620,9 @@ async function exportPdf(
|
|
|
627
620
|
|
|
628
621
|
document.body.style.overflow = "auto";
|
|
629
622
|
|
|
623
|
+
// Undo what you have done on onBefore
|
|
624
|
+
onAfter?.(map, layers);
|
|
625
|
+
|
|
630
626
|
// Reset map to previous state
|
|
631
627
|
map.setLayers(layers);
|
|
632
628
|
|
|
@@ -640,26 +636,21 @@ async function exportPdf(
|
|
|
640
636
|
if (useCopyright) {
|
|
641
637
|
drawCopyright(copyrightText, canvas, {
|
|
642
638
|
...(mapExportOptions?.copyrightOptions || {}),
|
|
643
|
-
|
|
644
|
-
scale: pixelRatio,
|
|
639
|
+
font: (pixelRatio * 12).toString() + "px Arial",
|
|
645
640
|
});
|
|
646
641
|
}
|
|
647
642
|
|
|
648
643
|
// Transform to PDF
|
|
649
644
|
if (/^A[0-9]{1,2}/.test(format as string) || format?.length === 2) {
|
|
650
645
|
try {
|
|
651
|
-
const size300Dpi = size.map((n) => {
|
|
652
|
-
return (n * 300) / 72;
|
|
653
|
-
});
|
|
654
646
|
const doc = new jsPDF({
|
|
655
647
|
orientation: "landscape",
|
|
656
648
|
unit: "pt",
|
|
657
649
|
...formatOptions,
|
|
658
|
-
format: size300Dpi,
|
|
659
650
|
});
|
|
660
651
|
|
|
661
652
|
// Add canvas to PDF
|
|
662
|
-
doc.addImage(canvas, "JPEG", 0, 0,
|
|
653
|
+
doc.addImage(canvas, "JPEG", 0, 0, sizePt[0], sizePt[1]);
|
|
663
654
|
|
|
664
655
|
// Download the pdf
|
|
665
656
|
doc.save(`rvf-${new Date().toISOString().slice(0, 10)}.pdf`);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Collection } from "ol";
|
|
2
|
+
import BaseLayer from "ol/layer/Base";
|
|
3
|
+
import Group from "ol/layer/Group";
|
|
4
|
+
|
|
5
|
+
const getAllLayers = (
|
|
6
|
+
layersOrLayerGroup: BaseLayer[] | Collection<BaseLayer> | Group,
|
|
7
|
+
) => {
|
|
8
|
+
const allLayers = [];
|
|
9
|
+
function addLayersFrom(layers: BaseLayer[] | Collection<BaseLayer>) {
|
|
10
|
+
layers.forEach(function (layer) {
|
|
11
|
+
if (layer instanceof Group) {
|
|
12
|
+
addLayersFrom((layer as Group).getLayers());
|
|
13
|
+
} else {
|
|
14
|
+
allLayers.push(layer);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
addLayersFrom(
|
|
19
|
+
(layersOrLayerGroup as Group)?.getLayers?.() ||
|
|
20
|
+
(layersOrLayerGroup as BaseLayer[] | Collection<BaseLayer>),
|
|
21
|
+
);
|
|
22
|
+
return allLayers;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default getAllLayers;
|
|
@@ -1,29 +1,62 @@
|
|
|
1
|
+
import { MaplibreStyleLayer } from "mobility-toolbox-js/ol";
|
|
1
2
|
import { Feature } from "ol";
|
|
3
|
+
import { Group } from "ol/layer";
|
|
2
4
|
import { createContext } from "preact";
|
|
3
5
|
import { useContext } from "preact/hooks";
|
|
4
6
|
|
|
5
7
|
export interface RvfContextType {
|
|
6
8
|
isExportMenuOpen: boolean;
|
|
9
|
+
lineNetworkPlanLayer: MaplibreStyleLayer;
|
|
10
|
+
poisLayer: MaplibreStyleLayer;
|
|
7
11
|
selectedFeature: Feature;
|
|
8
12
|
selectedFeatures: Feature[];
|
|
13
|
+
sellingPointsLayer: MaplibreStyleLayer;
|
|
9
14
|
setIsExportMenuOpen: (isOpen: boolean) => void;
|
|
15
|
+
setLineNetworkPlanLayer: (layer: MaplibreStyleLayer) => void;
|
|
16
|
+
setPoisLayer: (layer: MaplibreStyleLayer) => void;
|
|
10
17
|
setSelectedFeature: (feature: Feature) => void;
|
|
11
18
|
setSelectedFeatures: (features: Feature[]) => void;
|
|
19
|
+
setSellingPointsLayer: (layer: MaplibreStyleLayer) => void;
|
|
20
|
+
setSharedMobilityLayerGroup: (group: Group) => void;
|
|
21
|
+
setTarifZonenLayer: (layer: MaplibreStyleLayer) => void;
|
|
22
|
+
sharedMobilityLayerGroup: Group;
|
|
23
|
+
tarifZonenLayer: MaplibreStyleLayer;
|
|
12
24
|
}
|
|
13
25
|
|
|
14
26
|
export const RvfContext = createContext<RvfContextType>({
|
|
15
27
|
isExportMenuOpen: false,
|
|
28
|
+
lineNetworkPlanLayer: null,
|
|
29
|
+
poisLayer: null,
|
|
16
30
|
selectedFeature: null,
|
|
17
31
|
selectedFeatures: [],
|
|
32
|
+
sellingPointsLayer: null,
|
|
18
33
|
setIsExportMenuOpen: () => {
|
|
19
34
|
console.warn("setIsExportMenuOpen is not implemented");
|
|
20
35
|
},
|
|
36
|
+
setLineNetworkPlanLayer: () => {
|
|
37
|
+
console.warn("setLineNetworkPlanLayer is not implemented");
|
|
38
|
+
},
|
|
39
|
+
setPoisLayer: () => {
|
|
40
|
+
console.warn("setPoisLayer is not implemented");
|
|
41
|
+
},
|
|
42
|
+
|
|
21
43
|
setSelectedFeature: () => {
|
|
22
44
|
console.warn("setSelectedFeature is not implemented");
|
|
23
45
|
},
|
|
24
46
|
setSelectedFeatures: () => {
|
|
25
47
|
console.warn("setSelectedFeatures is not implemented");
|
|
26
48
|
},
|
|
49
|
+
setSellingPointsLayer: () => {
|
|
50
|
+
console.warn("setSellingPointsLayer is not implemented");
|
|
51
|
+
},
|
|
52
|
+
setSharedMobilityLayerGroup: () => {
|
|
53
|
+
console.warn("setSharedMobilityLayerGroup is not implemented");
|
|
54
|
+
},
|
|
55
|
+
setTarifZonenLayer: () => {
|
|
56
|
+
console.warn("setTarifZonenLayer is not implemented");
|
|
57
|
+
},
|
|
58
|
+
sharedMobilityLayerGroup: null,
|
|
59
|
+
tarifZonenLayer: null,
|
|
27
60
|
});
|
|
28
61
|
|
|
29
62
|
const useRvfContext = (): RvfContextType => {
|
package/tailwind.config.mjs
CHANGED
|
@@ -11,13 +11,13 @@ const getClamp = (min, max) => {
|
|
|
11
11
|
min +
|
|
12
12
|
"px + (" +
|
|
13
13
|
max +
|
|
14
|
-
"-" +
|
|
14
|
+
" - " +
|
|
15
15
|
min +
|
|
16
|
-
") * (
|
|
16
|
+
") * (100cqw - " +
|
|
17
17
|
minScreenSize +
|
|
18
|
-
"px)/( " +
|
|
18
|
+
"px) / ( " +
|
|
19
19
|
maxScreenSize +
|
|
20
|
-
"-" +
|
|
20
|
+
" - " +
|
|
21
21
|
minScreenSize +
|
|
22
22
|
")), " +
|
|
23
23
|
max +
|
|
@@ -25,6 +25,28 @@ const getClamp = (min, max) => {
|
|
|
25
25
|
);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
// const getClamp = (min, max) => {
|
|
29
|
+
// return (
|
|
30
|
+
// "clamp(" +
|
|
31
|
+
// min +
|
|
32
|
+
// "px, calc(" +
|
|
33
|
+
// min +
|
|
34
|
+
// "px + (" +
|
|
35
|
+
// max +
|
|
36
|
+
// "-" +
|
|
37
|
+
// min +
|
|
38
|
+
// ") * (100vw - " +
|
|
39
|
+
// minScreenSize +
|
|
40
|
+
// "px)/( " +
|
|
41
|
+
// maxScreenSize +
|
|
42
|
+
// "-" +
|
|
43
|
+
// minScreenSize +
|
|
44
|
+
// ")), " +
|
|
45
|
+
// max +
|
|
46
|
+
// "px )"
|
|
47
|
+
// );
|
|
48
|
+
// };
|
|
49
|
+
|
|
28
50
|
export default {
|
|
29
51
|
plugins: [containerQueries],
|
|
30
52
|
theme: {
|
|
@@ -39,14 +61,10 @@ export default {
|
|
|
39
61
|
ultradarkgray: "#2D2D2C", // another grey with no name
|
|
40
62
|
ultralightgrey: "#F5F5F5", // ultralight grey
|
|
41
63
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
button: "40px",
|
|
47
|
-
},
|
|
48
|
-
padding: {
|
|
49
|
-
1.75: "7px",
|
|
64
|
+
width: {
|
|
65
|
+
10: "40px", // for Route Schedule
|
|
66
|
+
8: "32px", // for Route Schedule
|
|
67
|
+
9: "36px", // for Route Schedule
|
|
50
68
|
},
|
|
51
69
|
},
|
|
52
70
|
fontFamily: {
|
|
@@ -65,44 +83,7 @@ export default {
|
|
|
65
83
|
lg: getClamp(19, 25), // H4
|
|
66
84
|
sm: getClamp(13, 15), // small
|
|
67
85
|
xl: getClamp(24, 31), // h3
|
|
86
|
+
xs: getClamp(13, 15), // small
|
|
68
87
|
},
|
|
69
|
-
extend: {
|
|
70
|
-
colors: {
|
|
71
|
-
darkgray: "#464646", // dark grey
|
|
72
|
-
grey: "#7C7C7C", // grey
|
|
73
|
-
lightgrey: "#D0D0D0", // light grey
|
|
74
|
-
red: "#E3000B", // rvf rot
|
|
75
|
-
ultradarkgray: "#2D2D2C", // another grey with no name
|
|
76
|
-
ultralightgrey: "#F5F5F5", // ultralight grey
|
|
77
|
-
},
|
|
78
|
-
width: {
|
|
79
|
-
'largeMenu': '350px',
|
|
80
|
-
'mediumMenu': '300px',
|
|
81
|
-
'inputControl': '20px',
|
|
82
|
-
'check': '6px',
|
|
83
|
-
'innerControl': '12px',
|
|
84
|
-
},
|
|
85
|
-
height: {
|
|
86
|
-
'inputControl': '20px',
|
|
87
|
-
'innerControl': '12px',
|
|
88
|
-
},
|
|
89
|
-
maxWidth: {
|
|
90
|
-
'button': '40px'
|
|
91
|
-
},
|
|
92
|
-
maxHeight: {
|
|
93
|
-
'button': '40px'
|
|
94
|
-
},
|
|
95
|
-
padding: {
|
|
96
|
-
'1.75': '7px'
|
|
97
|
-
},
|
|
98
|
-
margin: {
|
|
99
|
-
'4px': '4px',
|
|
100
|
-
'7px': '7px'
|
|
101
|
-
},
|
|
102
|
-
screens: {
|
|
103
|
-
'medium': '577px',
|
|
104
|
-
'large': '993px'
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
88
|
},
|
|
108
89
|
};
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
2
|
-
|
|
3
|
-
import BaseLayer from "ol/layer/Base";
|
|
4
|
-
import { SVGProps, useContext, useEffect, useState } from "preact/compat";
|
|
5
|
-
|
|
6
|
-
import { LayersTreeDispatchContext } from "../layersTreeContext";
|
|
7
|
-
import TreeItemContainer from "../TreeItemContainer";
|
|
8
|
-
|
|
9
|
-
export enum SelectionType {
|
|
10
|
-
CHECKBOX = "checkbox",
|
|
11
|
-
RADIO = "radio",
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type TreeItemProps = {
|
|
15
|
-
childItems: TreeItemProps[];
|
|
16
|
-
Icon?: (props: SVGProps<SVGSVGElement>) => preact.JSX.Element;
|
|
17
|
-
id: string;
|
|
18
|
-
isCollapsedOnControlClick?: boolean;
|
|
19
|
-
isControlChecked?: boolean;
|
|
20
|
-
layer?: BaseLayer;
|
|
21
|
-
onIconClick?: () => void;
|
|
22
|
-
selectionType: SelectionType;
|
|
23
|
-
title: string;
|
|
24
|
-
} & JSX.HTMLAttributes<HTMLButtonElement> &
|
|
25
|
-
PreactDOMAttributes;
|
|
26
|
-
|
|
27
|
-
function TreeItem({
|
|
28
|
-
childItems,
|
|
29
|
-
Icon,
|
|
30
|
-
isCollapsedOnControlClick,
|
|
31
|
-
isControlChecked,
|
|
32
|
-
layer,
|
|
33
|
-
onIconClick,
|
|
34
|
-
selectionType,
|
|
35
|
-
title,
|
|
36
|
-
}: TreeItemProps) {
|
|
37
|
-
const [isContainerVisible, setIsContainerVisible] = useState(true);
|
|
38
|
-
const dispatch = useContext(LayersTreeDispatchContext);
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
if (isCollapsedOnControlClick) {
|
|
42
|
-
setIsContainerVisible(isControlChecked);
|
|
43
|
-
}
|
|
44
|
-
}, [isControlChecked, isCollapsedOnControlClick]);
|
|
45
|
-
|
|
46
|
-
const handleItemClick = () => {
|
|
47
|
-
setIsContainerVisible(!isContainerVisible);
|
|
48
|
-
|
|
49
|
-
if (isCollapsedOnControlClick && !isContainerVisible) {
|
|
50
|
-
if (selectionType === SelectionType.RADIO) {
|
|
51
|
-
dispatch({
|
|
52
|
-
payload: {
|
|
53
|
-
...this["props"],
|
|
54
|
-
isControlChecked: true,
|
|
55
|
-
},
|
|
56
|
-
type: "SELECT_RADIO_ITEM",
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const handleSelectionChange = (event) => {
|
|
63
|
-
console.log("TREE LAYER", layer);
|
|
64
|
-
|
|
65
|
-
if (selectionType === SelectionType.RADIO) {
|
|
66
|
-
dispatch({
|
|
67
|
-
payload: {
|
|
68
|
-
...this["props"],
|
|
69
|
-
isControlChecked: event.target.checked,
|
|
70
|
-
},
|
|
71
|
-
type: "SELECT_RADIO_ITEM",
|
|
72
|
-
});
|
|
73
|
-
} else {
|
|
74
|
-
dispatch({
|
|
75
|
-
payload: {
|
|
76
|
-
...this["props"],
|
|
77
|
-
isControlChecked: event.target.checked,
|
|
78
|
-
},
|
|
79
|
-
type: "SELECT_ITEM",
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const arrowShowedClass = childItems.length > 0 ? "block" : "hidden";
|
|
85
|
-
const changeArrowClass = isContainerVisible
|
|
86
|
-
? "border-l border-t"
|
|
87
|
-
: "border-b border-r";
|
|
88
|
-
const radioButtonClass =
|
|
89
|
-
"appearance-none w-inputControl h-inputControl border-2 border-grey rounded-full mr-2 peer";
|
|
90
|
-
const checkboxClass =
|
|
91
|
-
"appearance-none w-inputControl h-inputControl border-2 border-grey rounded mr-2 peer";
|
|
92
|
-
|
|
93
|
-
const innerCircle = (
|
|
94
|
-
<span className="pointer-events-none absolute ml-4px h-innerControl w-innerControl rounded-full peer-checked:bg-red" />
|
|
95
|
-
);
|
|
96
|
-
const checkSign = (
|
|
97
|
-
<span className="pointer-events-none absolute mb-px ml-7px hidden h-innerControl w-check rotate-45 border-b-2 border-r-2 border-grey peer-checked:block" />
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const renderedLayers = childItems.map((item, idx) => {
|
|
101
|
-
return <TreeItem key={idx} {...item} />;
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<div className="flex flex-col pl-6">
|
|
106
|
-
<div className="flex h-8 cursor-pointer items-center">
|
|
107
|
-
<div className="relative flex items-center">
|
|
108
|
-
<input
|
|
109
|
-
checked={isControlChecked}
|
|
110
|
-
className={
|
|
111
|
-
selectionType === SelectionType.RADIO
|
|
112
|
-
? radioButtonClass
|
|
113
|
-
: checkboxClass
|
|
114
|
-
}
|
|
115
|
-
onChange={handleSelectionChange}
|
|
116
|
-
type={selectionType}
|
|
117
|
-
/>
|
|
118
|
-
{selectionType === SelectionType.RADIO ? innerCircle : checkSign}
|
|
119
|
-
</div>
|
|
120
|
-
<div
|
|
121
|
-
onClick={handleItemClick}
|
|
122
|
-
onKeyDown={handleItemClick}
|
|
123
|
-
role="button"
|
|
124
|
-
tabIndex={0}
|
|
125
|
-
>
|
|
126
|
-
<div className="flex items-center">
|
|
127
|
-
{title}
|
|
128
|
-
<div
|
|
129
|
-
className={`mb-0.5 ml-2 size-1.5 rotate-45 border-grey ${arrowShowedClass} ${changeArrowClass}`}
|
|
130
|
-
></div>
|
|
131
|
-
</div>
|
|
132
|
-
</div>
|
|
133
|
-
<span>{Icon ? <Icon onClick={onIconClick} /> : null}</span>
|
|
134
|
-
</div>
|
|
135
|
-
<TreeItemContainer
|
|
136
|
-
className={isContainerVisible ? "block" : "hidden"}
|
|
137
|
-
selectionType={childItems[0]?.selectionType}
|
|
138
|
-
>
|
|
139
|
-
{renderedLayers}
|
|
140
|
-
</TreeItemContainer>
|
|
141
|
-
</div>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export default TreeItem;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type JSX, type PreactDOMAttributes } from "preact";
|
|
2
|
-
|
|
3
|
-
import { SelectionType } from "../TreeItem/TreeItem";
|
|
4
|
-
|
|
5
|
-
export type TreeItemContainerProps = {
|
|
6
|
-
selectionType: SelectionType;
|
|
7
|
-
} & JSX.HTMLAttributes<HTMLButtonElement> &
|
|
8
|
-
PreactDOMAttributes;
|
|
9
|
-
|
|
10
|
-
function TreeItemContainer({ children, className }: TreeItemContainerProps) {
|
|
11
|
-
const classes = `flex flex-col ${className || ""}`;
|
|
12
|
-
|
|
13
|
-
return <div className={classes}>{children}</div>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default TreeItemContainer;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./TreeItemContainer";
|
package/src/LayerTree/index.tsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./LayerTree";
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { Map } from "ol";
|
|
2
|
-
import { Group } from "ol/layer";
|
|
3
|
-
|
|
4
|
-
import LayerTree from "../LayerTree";
|
|
5
|
-
import { SelectionType } from "../LayerTree/TreeItem/TreeItem";
|
|
6
|
-
|
|
7
|
-
function TopicMenu({ map }: { map: Map }) {
|
|
8
|
-
const layers = map
|
|
9
|
-
.getLayers()
|
|
10
|
-
.getArray()
|
|
11
|
-
.filter((layer) => {
|
|
12
|
-
return !layer.get("isNotInLayerTree");
|
|
13
|
-
})
|
|
14
|
-
.map((layer) => {
|
|
15
|
-
return {
|
|
16
|
-
childItems:
|
|
17
|
-
(layer as Group)
|
|
18
|
-
?.getLayers?.()
|
|
19
|
-
.getArray()
|
|
20
|
-
.map((subLayer) => {
|
|
21
|
-
return {
|
|
22
|
-
childItems: [],
|
|
23
|
-
id: (Math.random() + 1).toString(36).substring(7),
|
|
24
|
-
isControlChecked: subLayer.getVisible(),
|
|
25
|
-
layer: subLayer,
|
|
26
|
-
selectionType: SelectionType.CHECKBOX,
|
|
27
|
-
title: subLayer.get("title"),
|
|
28
|
-
};
|
|
29
|
-
}) || [],
|
|
30
|
-
id: (Math.random() + 1).toString(36).substring(7),
|
|
31
|
-
isControlChecked: layer.getVisible(),
|
|
32
|
-
layer,
|
|
33
|
-
selectionType: SelectionType.CHECKBOX,
|
|
34
|
-
title: layer.get("title"),
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// const readyLayers = [
|
|
39
|
-
// {
|
|
40
|
-
// childItems: layers.map((layer) => {
|
|
41
|
-
// return {
|
|
42
|
-
// ...layer,
|
|
43
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
44
|
-
// };
|
|
45
|
-
// }),
|
|
46
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
47
|
-
// isCollapsedOnControlClick: true,
|
|
48
|
-
// isControlChecked: true,
|
|
49
|
-
// selectionType: SelectionType.RADIO,
|
|
50
|
-
// title: "Topic 1",
|
|
51
|
-
// },
|
|
52
|
-
// {
|
|
53
|
-
// childItems: layers.map((layer) => {
|
|
54
|
-
// return {
|
|
55
|
-
// ...layer,
|
|
56
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
57
|
-
// };
|
|
58
|
-
// }),
|
|
59
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
60
|
-
// isCollapsedOnControlClick: true,
|
|
61
|
-
// selectionType: SelectionType.RADIO,
|
|
62
|
-
// title: "Topic 2",
|
|
63
|
-
// },
|
|
64
|
-
// {
|
|
65
|
-
// childItems: layers.map((layer) => {
|
|
66
|
-
// return {
|
|
67
|
-
// ...layer,
|
|
68
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
69
|
-
// isControlChecked: false,
|
|
70
|
-
// selectionType: SelectionType.RADIO,
|
|
71
|
-
// };
|
|
72
|
-
// }),
|
|
73
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
74
|
-
// isCollapsedOnControlClick: true,
|
|
75
|
-
// selectionType: SelectionType.RADIO,
|
|
76
|
-
// title: "Topic 3",
|
|
77
|
-
// },
|
|
78
|
-
// ];
|
|
79
|
-
|
|
80
|
-
// readyLayers[0].childItems[0].childItems = layers.map((layer, idx) => {
|
|
81
|
-
// return {
|
|
82
|
-
// ...layer,
|
|
83
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
84
|
-
// isControlChecked: idx === 0,
|
|
85
|
-
// selectionType: SelectionType.RADIO,
|
|
86
|
-
// };
|
|
87
|
-
// });
|
|
88
|
-
|
|
89
|
-
// readyLayers[1].childItems[0].childItems = layers.map((layer, idx) => {
|
|
90
|
-
// return {
|
|
91
|
-
// ...layer,
|
|
92
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
93
|
-
// isControlChecked: idx === 0,
|
|
94
|
-
// selectionType: SelectionType.RADIO,
|
|
95
|
-
// };
|
|
96
|
-
// });
|
|
97
|
-
|
|
98
|
-
// readyLayers[0].childItems[1].childItems = layers.map((layer) => {
|
|
99
|
-
// return {
|
|
100
|
-
// ...layer,
|
|
101
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
102
|
-
// selectionType: SelectionType.CHECKBOX,
|
|
103
|
-
// };
|
|
104
|
-
// });
|
|
105
|
-
|
|
106
|
-
// readyLayers[0].childItems[1].childItems[0].childItems = layers.map(
|
|
107
|
-
// (layer) => {
|
|
108
|
-
// return {
|
|
109
|
-
// ...layer,
|
|
110
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
111
|
-
// selectionType: SelectionType.CHECKBOX,
|
|
112
|
-
// };
|
|
113
|
-
// },
|
|
114
|
-
// );
|
|
115
|
-
|
|
116
|
-
// readyLayers[2].childItems[0].childItems = layers.map((layer) => {
|
|
117
|
-
// return {
|
|
118
|
-
// ...layer,
|
|
119
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
120
|
-
// isControlChecked: false,
|
|
121
|
-
// selectionType: SelectionType.RADIO,
|
|
122
|
-
// };
|
|
123
|
-
// });
|
|
124
|
-
|
|
125
|
-
// readyLayers[2].childItems[1].childItems = layers.map((layer) => {
|
|
126
|
-
// return {
|
|
127
|
-
// ...layer,
|
|
128
|
-
// id: (Math.random() + 1).toString(36).substring(7),
|
|
129
|
-
// isControlChecked: false,
|
|
130
|
-
// selectionType: SelectionType.RADIO,
|
|
131
|
-
// };
|
|
132
|
-
// });
|
|
133
|
-
|
|
134
|
-
// console.log("READY LAYERS", readyLayers);
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<div className="max-h-80 overflow-scroll bg-white medium:w-largeMenu large:w-mediumMenu">
|
|
138
|
-
<LayerTree layers={layers} />
|
|
139
|
-
</div>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export default TopicMenu;
|
package/src/TopicMenu/index.tsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./TopicMenu";
|
|
File without changes
|
|
File without changes
|