@metastringfoundation/map-list 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/components/Handler/MapComparisonControl.d.ts +7 -0
  2. package/dist/components/Handler/MapComparisonControl.d.ts.map +1 -0
  3. package/dist/components/Handler/MapComparisonControl.js +8 -0
  4. package/dist/components/core/button.js +1 -1
  5. package/dist/components/core/input.d.ts.map +1 -1
  6. package/dist/components/core/input.js +1 -1
  7. package/dist/components/dualMap/MapLayerCard.d.ts +8 -0
  8. package/dist/components/dualMap/MapLayerCard.d.ts.map +1 -0
  9. package/dist/components/dualMap/MapLayerCard.js +68 -0
  10. package/dist/components/dualMap/index.d.ts +2 -1
  11. package/dist/components/dualMap/index.d.ts.map +1 -1
  12. package/dist/components/dualMap/index.js +219 -56
  13. package/dist/components/map/compare-sidebar.d.ts +2 -0
  14. package/dist/components/map/compare-sidebar.d.ts.map +1 -0
  15. package/dist/components/map/compare-sidebar.js +34 -0
  16. package/dist/components/map/compare.d.ts +2 -0
  17. package/dist/components/map/compare.d.ts.map +1 -0
  18. package/dist/components/map/compare.js +42 -0
  19. package/dist/components/map/index.d.ts.map +1 -1
  20. package/dist/components/map/index.js +14 -1
  21. package/dist/components/map/layers/grid/index.d.ts.map +1 -1
  22. package/dist/components/map/layers/grid/index.js +11 -1
  23. package/dist/components/map/layers/index.d.ts.map +1 -1
  24. package/dist/components/map/layers/index.js +0 -1
  25. package/dist/components/map/layers/raster/index.d.ts.map +1 -1
  26. package/dist/components/map/layers/raster/index.js +5 -3
  27. package/dist/components/map/layers/vector/index.d.ts.map +1 -1
  28. package/dist/components/map/layers/vector/index.js +25 -2
  29. package/dist/components/map/search.d.ts +2 -0
  30. package/dist/components/map/search.d.ts.map +1 -0
  31. package/dist/components/map/search.js +122 -0
  32. package/dist/components/map-comparison/attribute-selector.d.ts +11 -0
  33. package/dist/components/map-comparison/attribute-selector.d.ts.map +1 -0
  34. package/dist/components/map-comparison/attribute-selector.js +10 -0
  35. package/dist/components/map-comparison/comparison-panel.d.ts +2 -0
  36. package/dist/components/map-comparison/comparison-panel.d.ts.map +1 -0
  37. package/dist/components/map-comparison/comparison-panel.js +45 -0
  38. package/dist/components/map-comparison/comparison-stats.d.ts +2 -0
  39. package/dist/components/map-comparison/comparison-stats.d.ts.map +1 -0
  40. package/dist/components/map-comparison/comparison-stats.js +35 -0
  41. package/dist/components/map-comparison/comparison-view.d.ts +2 -0
  42. package/dist/components/map-comparison/comparison-view.d.ts.map +1 -0
  43. package/dist/components/map-comparison/comparison-view.js +152 -0
  44. package/dist/components/map-comparison/comparison-wrapper.d.ts +8 -0
  45. package/dist/components/map-comparison/comparison-wrapper.d.ts.map +1 -0
  46. package/dist/components/map-comparison/comparison-wrapper.js +26 -0
  47. package/dist/components/map-comparison/index.d.ts +3 -0
  48. package/dist/components/map-comparison/index.d.ts.map +1 -0
  49. package/dist/components/map-comparison/index.js +165 -0
  50. package/dist/components/map-comparison/types.d.ts +30 -0
  51. package/dist/components/map-comparison/types.d.ts.map +1 -0
  52. package/dist/components/map-comparison/types.js +2 -0
  53. package/dist/components/map-comparison/use-map-comparison.d.ts +18 -0
  54. package/dist/components/map-comparison/use-map-comparison.d.ts.map +1 -0
  55. package/dist/components/map-comparison/use-map-comparison.js +139 -0
  56. package/dist/components/sidebar/common/attribute-compare-addon.d.ts +7 -0
  57. package/dist/components/sidebar/common/attribute-compare-addon.d.ts.map +1 -0
  58. package/dist/components/sidebar/common/attribute-compare-addon.js +36 -0
  59. package/dist/components/sidebar/common/layer-item-style.d.ts.map +1 -1
  60. package/dist/components/sidebar/common/layer-item-style.js +46 -1
  61. package/dist/components/sidebar/common/layer-item.d.ts.map +1 -1
  62. package/dist/components/sidebar/common/layer-item.js +1 -2
  63. package/dist/components/sidebar/common/opacity-handler-addon.d.ts +5 -2
  64. package/dist/components/sidebar/common/opacity-handler-addon.d.ts.map +1 -1
  65. package/dist/components/sidebar/common/opacity-handler-addon.js +101 -4
  66. package/dist/components/sidebar/common/style-legend.d.ts.map +1 -1
  67. package/dist/components/sidebar/common/style-legend.js +1 -2
  68. package/dist/components/sidebar/comparison/index.d.ts +4 -0
  69. package/dist/components/sidebar/comparison/index.d.ts.map +1 -0
  70. package/dist/components/sidebar/comparison/index.js +34 -0
  71. package/dist/components/sidebar/search/attribute-comparison.d.ts +10 -0
  72. package/dist/components/sidebar/search/attribute-comparison.d.ts.map +1 -0
  73. package/dist/components/sidebar/search/attribute-comparison.js +137 -0
  74. package/dist/components/sidebar/search/index.d.ts +2 -0
  75. package/dist/components/sidebar/search/index.d.ts.map +1 -0
  76. package/dist/components/sidebar/search/index.js +29 -0
  77. package/dist/components/sidebar/selected/index.d.ts.map +1 -1
  78. package/dist/components/sidebar/selected/index.js +4 -1
  79. package/dist/components/sidebar/tabs.js +2 -2
  80. package/dist/hooks/use-layers.d.ts +8 -0
  81. package/dist/hooks/use-layers.d.ts.map +1 -1
  82. package/dist/hooks/use-layers.js +101 -1
  83. package/dist/hooks/use-polygon-data.d.ts +34 -0
  84. package/dist/hooks/use-polygon-data.d.ts.map +1 -0
  85. package/dist/hooks/use-polygon-data.js +74 -0
  86. package/dist/index.css +659 -30
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +9 -36
  89. package/dist/services/naksha.d.ts.map +1 -1
  90. package/dist/services/naksha.js +16 -158
  91. package/dist/services/polygon.d.ts +36 -0
  92. package/dist/services/polygon.d.ts.map +1 -0
  93. package/dist/services/polygon.js +67 -0
  94. package/dist/utils/naksha.d.ts.map +1 -1
  95. package/dist/utils/naksha.js +4 -2
  96. package/package.json +16 -15
@@ -1,9 +1,106 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const jsx_runtime_1 = require("react/jsx-runtime");
4
7
  const react_1 = require("react");
5
- const OpacitySlider = () => {
6
- const [opacity, setOpacity] = (0, react_1.useState)(1);
7
- return ((0, jsx_runtime_1.jsx)("div", { className: "max-w-sm space-y-4", children: (0, jsx_runtime_1.jsx)("input", { id: "opacity-slider", type: "range", min: "0", max: "1", step: "0.01", value: opacity, onChange: (e) => setOpacity(Number(e.target.value)), className: "\n w-full cursor-pointer text-2xl h-1\n " }) }));
8
+ const use_layers_1 = __importDefault(require("../../../hooks/use-layers"));
9
+ const OpacityHandler = ({ layerId }) => {
10
+ const { layer } = (0, use_layers_1.default)();
11
+ const contextOpacity = layer.getLayerOpacity(layerId);
12
+ // Local state for smooth slider interaction
13
+ const [localOpacity, setLocalOpacity] = (0, react_1.useState)(contextOpacity);
14
+ const isDraggingRef = (0, react_1.useRef)(false);
15
+ const rafRef = (0, react_1.useRef)(null);
16
+ // Sync local state with context when context changes externally (not during drag)
17
+ (0, react_1.useEffect)(() => {
18
+ if (!isDraggingRef.current) {
19
+ setLocalOpacity(contextOpacity);
20
+ }
21
+ }, [contextOpacity]);
22
+ // Use requestAnimationFrame for smooth updates
23
+ const updateOpacity = (0, react_1.useCallback)((value) => {
24
+ if (rafRef.current !== null) {
25
+ cancelAnimationFrame(rafRef.current);
26
+ }
27
+ rafRef.current = requestAnimationFrame(() => {
28
+ layer.setLayerOpacity(layerId, value);
29
+ });
30
+ }, [layer, layerId]);
31
+ const handleInput = (e) => {
32
+ const value = Number(e.target.value);
33
+ setLocalOpacity(value);
34
+ isDraggingRef.current = true;
35
+ updateOpacity(value);
36
+ };
37
+ const handleMouseUp = () => {
38
+ // Ensure final value is set
39
+ if (rafRef.current !== null) {
40
+ cancelAnimationFrame(rafRef.current);
41
+ }
42
+ layer.setLayerOpacity(layerId, localOpacity);
43
+ isDraggingRef.current = false;
44
+ };
45
+ // Cleanup on unmount
46
+ (0, react_1.useEffect)(() => {
47
+ return () => {
48
+ if (rafRef.current !== null) {
49
+ cancelAnimationFrame(rafRef.current);
50
+ }
51
+ };
52
+ }, []);
53
+ const percentage = Math.round(localOpacity * 100);
54
+ const opacityPercent = localOpacity * 100;
55
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 w-full", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 h-6 flex items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 h-2 rounded-lg pointer-events-none", style: {
56
+ background: `linear-gradient(to right, #3b82f6 0%, #3b82f6 ${opacityPercent}%, #e5e7eb ${opacityPercent}%, #e5e7eb 100%)`,
57
+ } }), (0, jsx_runtime_1.jsx)("input", { id: `opacity-slider-${layerId}`, type: "range", min: "0", max: "1", step: "0.01", value: localOpacity, onInput: handleInput, onChange: handleInput, onMouseUp: handleMouseUp, onTouchEnd: handleMouseUp, className: "relative w-full h-2 bg-transparent appearance-none cursor-pointer opacity-slider-input" })] }), (0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: {
58
+ __html: `
59
+ .opacity-slider-input::-webkit-slider-thumb {
60
+ appearance: none;
61
+ width: 18px;
62
+ height: 18px;
63
+ border-radius: 50%;
64
+ background: #3b82f6;
65
+ cursor: pointer;
66
+ border: 2px solid white;
67
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
68
+ margin-top: -5px;
69
+ }
70
+ .opacity-slider-input::-webkit-slider-thumb:hover {
71
+ transform: scale(1.1);
72
+ }
73
+ .opacity-slider-input::-webkit-slider-thumb:active {
74
+ transform: scale(1.2);
75
+ cursor: grabbing;
76
+ }
77
+ .opacity-slider-input::-webkit-slider-runnable-track {
78
+ height: 8px;
79
+ border-radius: 4px;
80
+ background: transparent;
81
+ }
82
+ .opacity-slider-input::-moz-range-thumb {
83
+ width: 18px;
84
+ height: 18px;
85
+ border-radius: 50%;
86
+ background: #3b82f6;
87
+ cursor: pointer;
88
+ border: 2px solid white;
89
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
90
+ }
91
+ .opacity-slider-input::-moz-range-thumb:hover {
92
+ transform: scale(1.1);
93
+ }
94
+ .opacity-slider-input::-moz-range-thumb:active {
95
+ transform: scale(1.2);
96
+ cursor: grabbing;
97
+ }
98
+ .opacity-slider-input::-moz-range-track {
99
+ height: 8px;
100
+ border-radius: 4px;
101
+ background: transparent;
102
+ }
103
+ `
104
+ } })] }));
8
105
  };
9
- exports.default = OpacitySlider;
106
+ exports.default = OpacityHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"style-legend.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/style-legend.tsx"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE;;CAAA,2CA4CnC"}
1
+ {"version":3,"file":"style-legend.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/style-legend.tsx"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE;;CAAA,2CA2CnC"}
@@ -11,7 +11,6 @@ const use_layers_1 = __importDefault(require("../../../hooks/use-layers"));
11
11
  function StyleLegend({ item }) {
12
12
  const [showImage, setShowImage] = (0, react_1.useState)(true);
13
13
  const { mp } = (0, use_layers_1.default)();
14
- const { t } = useT();
15
14
  const legendStyles = (0, react_1.useMemo)(() => item?.data?.styles?.[item.data.styleIndex]?.colors?.paint?.["fill-color"]
16
15
  ?.stops ||
17
16
  item?.data?.styles?.[item.data.styleIndex]?.colors?.paint?.["circle-color"]?.stops ||
@@ -19,5 +18,5 @@ function StyleLegend({ item }) {
19
18
  const vectorLegend = () => {
20
19
  return legendStyles.map(([title, color]) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex gap-2 items-center mb-1", children: [(0, jsx_runtime_1.jsx)("svg", { viewBox: "0 0 24 24", height: "14", width: "14", focusable: "false", children: (0, jsx_runtime_1.jsx)("circle", { cx: "12", fill: color, cy: "12", r: "12", stroke: "none" }) }), (0, jsx_runtime_1.jsx)("div", { children: title })] }, color)));
21
20
  };
22
- return ((0, jsx_runtime_1.jsx)("ul", { style: { margin: 0, padding: 0 }, children: item.layerType !== "RASTER" ? (vectorLegend()) : showImage ? ((0, jsx_runtime_1.jsx)("li", { children: (0, jsx_runtime_1.jsx)("img", { style: { margin: "5px" }, onError: () => setShowImage(false), src: `${mp?.geoserver?.endpoint}/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&WIDTH=20&HEIGHT=20&STRICT=false&layer=biodiv:${item.id}` }) })) : ((0, jsx_runtime_1.jsx)("div", { children: t("raster_style_not_found") })) }));
21
+ return ((0, jsx_runtime_1.jsx)("ul", { style: { margin: 0, padding: 0 }, children: item.layerType !== "RASTER" ? (vectorLegend()) : showImage ? ((0, jsx_runtime_1.jsx)("li", { children: (0, jsx_runtime_1.jsx)("img", { style: { margin: "5px" }, onError: () => setShowImage(false), src: `${mp?.geoserver?.endpoint}/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&WIDTH=20&HEIGHT=20&STRICT=false&layer=biodiv:${item.id}` }) })) : ((0, jsx_runtime_1.jsx)("div", { children: ("raster_style_not_found") })) }));
23
22
  }
@@ -0,0 +1,4 @@
1
+ export default function ComparisonSidebar({ onClose }: {
2
+ onClose?: () => void;
3
+ }): import("react/jsx-runtime").JSX.Element | null;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/comparison/index.tsx"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,kDAoE9E"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = ComparisonSidebar;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const use_layers_1 = __importDefault(require("../../../hooks/use-layers"));
9
+ const core_1 = require("../../core");
10
+ function ComparisonSidebar({ onClose }) {
11
+ const { layer } = (0, use_layers_1.default)();
12
+ const compareList = layer?.compareList || [];
13
+ const handleRemoveFromComparison = (id) => {
14
+ layer.setCompareLayer(id, false);
15
+ };
16
+ const handleClearAll = () => {
17
+ compareList.forEach((id) => {
18
+ layer.setCompareLayer(id, false);
19
+ });
20
+ };
21
+ // Don't show if no layers in comparison
22
+ if (compareList.length === 0) {
23
+ return null;
24
+ }
25
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "absolute md:left-4 md:bottom-4 md:max-w-sm w-full z-20 bg-white rounded-lg shadow-md overflow-hidden", style: {
26
+ maxHeight: "40vh",
27
+ height: "auto"
28
+ }, children: [onClose && (0, jsx_runtime_1.jsx)(core_1.CloseButton, { onClick: onClose }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col", style: { maxHeight: "40vh" }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between p-4 border-b shrink-0", children: [(0, jsx_runtime_1.jsxs)("h3", { className: "text-lg font-semibold text-gray-800", children: ["Comparing ", compareList.length, " ", compareList.length === 1 ? "layer" : "layers"] }), (0, jsx_runtime_1.jsx)(core_1.Button, { onClick: handleClearAll, className: "text-sm", children: "Clear All" })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 min-h-0 overflow-y-auto", children: (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-2 p-4", children: compareList.map((id) => {
29
+ const layerItem = layer.all.find((l) => l.id === id);
30
+ if (!layerItem)
31
+ return null;
32
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between p-3 bg-gray-50 rounded-md border border-gray-200 hover:bg-gray-100 transition-colors", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-medium text-gray-800", children: layerItem.title || layerItem.id }), layerItem.description && ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-500 mt-1", children: layerItem.description }))] }), (0, jsx_runtime_1.jsx)(core_1.Button, { onClick: () => handleRemoveFromComparison(id), className: "ml-2 text-red-600 hover:text-red-700", children: "Remove" })] }, id));
33
+ }) }) })] })] }));
34
+ }
@@ -0,0 +1,10 @@
1
+ interface AttributeComparisonProps {
2
+ attributeKey?: string;
3
+ clickedLngLat?: {
4
+ lng: number;
5
+ lat: number;
6
+ };
7
+ }
8
+ export default function AttributeComparison({ attributeKey: initialAttributeKey, clickedLngLat, }: AttributeComparisonProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=attribute-comparison.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-comparison.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/search/attribute-comparison.tsx"],"names":[],"mappings":"AAIA,UAAU,wBAAwB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,YAAY,EAAE,mBAA0B,EACxC,aAAa,GACd,EAAE,wBAAwB,2CAwT1B"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = AttributeComparison;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = require("react");
9
+ const use_layers_1 = __importDefault(require("../../../hooks/use-layers"));
10
+ const naksha_1 = require("../../../services/naksha");
11
+ function AttributeComparison({ attributeKey: initialAttributeKey = "-2", clickedLngLat, }) {
12
+ const { layer, mp, query } = (0, use_layers_1.default)();
13
+ const [attributeKey, setAttributeKey] = (0, react_1.useState)(initialAttributeKey);
14
+ const [comparisonData, setComparisonData] = (0, react_1.useState)([]);
15
+ const [loading, setLoading] = (0, react_1.useState)(false);
16
+ const [error, setError] = (0, react_1.useState)(null);
17
+ const compareLayers = (0, react_1.useMemo)(() => {
18
+ if (!layer.compareList || layer.compareList.length === 0) {
19
+ return layer.selectedLayers || [];
20
+ }
21
+ return (layer.selectedLayers?.filter((l) => layer.compareList.includes(l.id)) ||
22
+ []);
23
+ }, [layer.compareList, layer.selectedLayers]);
24
+ const fetchAttributeData = async () => {
25
+ if (compareLayers.length < 2) {
26
+ setComparisonData([]);
27
+ return;
28
+ }
29
+ setLoading(true);
30
+ setError(null);
31
+ try {
32
+ const lngLat = clickedLngLat || query.clickedLngLat;
33
+ if (!lngLat) {
34
+ setError("Please click on the map to select a location");
35
+ setLoading(false);
36
+ return;
37
+ }
38
+ const dataPromises = compareLayers.map(async (currentLayer) => {
39
+ let attributeValue = null;
40
+ let allProperties = [];
41
+ try {
42
+ if (currentLayer.layerType?.toLowerCase() === "raster") {
43
+ const { data } = await (0, naksha_1.axGexGetRasterInfoWithLonLat)(mp.geoserver?.endpoint, mp.geoserver?.workspace, {
44
+ bbox: `${lngLat.lng},${lngLat.lat},${lngLat.lng},${lngLat.lat}`,
45
+ query_layers: `${mp.geoserver?.workspace}:${currentLayer.id}`,
46
+ layers: `${mp.geoserver?.workspace}:${currentLayer.id}`,
47
+ });
48
+ if (data?.features?.[0]?.properties) {
49
+ const props = data.features[0].properties;
50
+ allProperties = Object.entries(props).map(([k, v]) => [k, v]);
51
+ // Try multiple strategies to find the attribute
52
+ // 1. Direct key match
53
+ if (props[attributeKey] !== undefined) {
54
+ attributeValue = props[attributeKey];
55
+ }
56
+ // 2. Try numeric index if attributeKey is "-2"
57
+ else if (attributeKey === "-2") {
58
+ const propKeys = Object.keys(props);
59
+ const index = propKeys.length - 2; // -2 means second from last
60
+ if (index >= 0 && index < propKeys.length) {
61
+ attributeValue = props[propKeys[index]];
62
+ }
63
+ }
64
+ // 3. Try to find by value match (case-insensitive)
65
+ else {
66
+ const foundKey = Object.keys(props).find((k) => k.toLowerCase() === attributeKey.toLowerCase());
67
+ if (foundKey) {
68
+ attributeValue = props[foundKey];
69
+ }
70
+ }
71
+ }
72
+ }
73
+ else {
74
+ // Vector layer
75
+ const propertyMap = currentLayer?.data?.propertyMap || {};
76
+ allProperties = Object.entries(propertyMap).map(([k, v]) => [
77
+ v,
78
+ null, // Value will be fetched from clicked feature
79
+ ]);
80
+ // Try multiple strategies to find the attribute
81
+ // 1. Direct key match in propertyMap values
82
+ let propertyKey = Object.keys(propertyMap).find((k) => propertyMap[k] === attributeKey);
83
+ // 2. Direct key match in propertyMap keys
84
+ if (!propertyKey && propertyMap[attributeKey]) {
85
+ propertyKey = attributeKey;
86
+ }
87
+ // 3. Try numeric index if attributeKey is "-2"
88
+ if (!propertyKey && attributeKey === "-2") {
89
+ const propertyKeys = Object.keys(propertyMap);
90
+ const index = propertyKeys.length - 2; // -2 means second from last
91
+ if (index >= 0 && index < propertyKeys.length) {
92
+ propertyKey = propertyKeys[index];
93
+ }
94
+ }
95
+ if (propertyKey && layer.selectedFeatures) {
96
+ const feature = layer.selectedFeatures.find((f) => f.sourceLayer === currentLayer.id);
97
+ if (feature?.properties?.[propertyKey] !== undefined) {
98
+ attributeValue = feature.properties[propertyKey];
99
+ }
100
+ }
101
+ }
102
+ }
103
+ catch (err) {
104
+ console.error(`Error fetching data for layer ${currentLayer.id}:`, err);
105
+ }
106
+ return {
107
+ layerId: currentLayer.id,
108
+ layerTitle: currentLayer.title,
109
+ attributeValue,
110
+ allProperties,
111
+ };
112
+ });
113
+ const results = await Promise.all(dataPromises);
114
+ setComparisonData(results);
115
+ }
116
+ catch (err) {
117
+ setError(err.message || "Failed to fetch comparison data");
118
+ }
119
+ finally {
120
+ setLoading(false);
121
+ }
122
+ };
123
+ (0, react_1.useEffect)(() => {
124
+ if (compareLayers.length >= 2 && (clickedLngLat || query.clickedLngLat)) {
125
+ fetchAttributeData();
126
+ }
127
+ else {
128
+ setComparisonData([]);
129
+ }
130
+ }, [compareLayers, clickedLngLat, query.clickedLngLat, attributeKey]);
131
+ if (compareLayers.length < 2) {
132
+ return ((0, jsx_runtime_1.jsx)("div", { className: "w-full p-4 flex flex-col gap-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center py-8 text-gray-500", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-lg font-semibold mb-2", children: "No Layers Selected for Comparison" }), (0, jsx_runtime_1.jsx)("div", { className: "text-sm", children: "Select at least 2 layers and enable comparison mode to compare attributes" })] }) }));
133
+ }
134
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "w-full p-4 flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3 mb-2", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-semibold text-gray-800", children: "Attribute Comparison" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-sm text-gray-600 whitespace-nowrap", children: "Attribute Key:" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: attributeKey, onChange: (e) => setAttributeKey(e.target.value), className: "flex-1 px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent font-mono", placeholder: "e.g., -2, name, id" })] })] }), loading && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center py-8", children: [(0, jsx_runtime_1.jsx)("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }), (0, jsx_runtime_1.jsx)("span", { className: "ml-3 text-gray-600", children: "Loading comparison data..." })] })), error && ((0, jsx_runtime_1.jsxs)("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 text-red-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold mb-1", children: "Error" }), (0, jsx_runtime_1.jsx)("div", { className: "text-sm", children: error })] })), !loading && !error && comparisonData.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-white border border-gray-200 rounded-lg overflow-hidden shadow-sm", children: (0, jsx_runtime_1.jsx)("div", { className: "overflow-x-auto", children: (0, jsx_runtime_1.jsxs)("table", { className: "w-full", children: [(0, jsx_runtime_1.jsx)("thead", { className: "bg-gray-50 border-b border-gray-200", children: (0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("th", { className: "px-4 py-3 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider", children: "Layer" }), (0, jsx_runtime_1.jsxs)("th", { className: "px-4 py-3 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider", children: [attributeKey, " Value"] })] }) }), (0, jsx_runtime_1.jsx)("tbody", { className: "bg-white divide-y divide-gray-200", children: comparisonData.map((item, index) => ((0, jsx_runtime_1.jsxs)("tr", { className: `hover:bg-gray-50 transition-colors ${index % 2 === 0 ? "bg-white" : "bg-gray-50"}`, children: [(0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 text-sm font-medium text-gray-900", children: item.layerTitle }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 text-sm text-gray-700", children: item.attributeValue !== null &&
135
+ item.attributeValue !== undefined ? ((0, jsx_runtime_1.jsx)("span", { className: "font-mono font-semibold text-blue-600", children: String(item.attributeValue) })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-gray-400 italic", children: "N/A" })) })] }, item.layerId))) })] }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: comparisonData.map((item) => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-gradient-to-br from-blue-50 to-indigo-50 border border-blue-200 rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between mb-3", children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-semibold text-gray-800 text-sm", children: item.layerTitle }), (0, jsx_runtime_1.jsx)("div", { className: "w-2 h-2 bg-blue-500 rounded-full" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600 uppercase tracking-wide", children: attributeKey }), (0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-blue-700", children: item.attributeValue !== null &&
136
+ item.attributeValue !== undefined ? (String(item.attributeValue)) : ((0, jsx_runtime_1.jsx)("span", { className: "text-gray-400 text-lg", children: "N/A" })) })] })] }, item.layerId))) }), comparisonData.some((d) => d.attributeValue !== null) && ((0, jsx_runtime_1.jsxs)("div", { className: "bg-gray-50 border border-gray-200 rounded-lg p-4", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Comparison Summary" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-4 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-gray-600", children: "Layers Compared" }), (0, jsx_runtime_1.jsx)("div", { className: "text-lg font-semibold text-gray-800", children: comparisonData.length })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-gray-600", children: "Valid Values" }), (0, jsx_runtime_1.jsx)("div", { className: "text-lg font-semibold text-green-600", children: comparisonData.filter((d) => d.attributeValue !== null).length })] })] })] }))] })), !loading && !error && comparisonData.length === 0 && ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-gray-500", children: (0, jsx_runtime_1.jsx)("div", { className: "text-sm mb-2", children: "Click on the map to compare attributes at that location" }) }))] }));
137
+ }
@@ -0,0 +1,2 @@
1
+ export default function SearchTabPanel(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/search/index.tsx"],"names":[],"mappings":"AAsBA,MAAM,CAAC,OAAO,UAAU,cAAc,4CAmDrC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SearchTabPanel;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const core_1 = require("../../core");
7
+ // Darker search icon component
8
+ const SearchIconDark = ({ disabled = false }) => ((0, jsx_runtime_1.jsx)("svg", { fill: "none", className: `w-5 h-5 ${disabled ? "text-blue-200" : "text-white"}`, width: "24", height: "24", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
9
+ function SearchTabPanel() {
10
+ const [searchTerm, setSearchTerm] = (0, react_1.useState)("");
11
+ const handleSearchChange = (e) => {
12
+ setSearchTerm(e.target.value);
13
+ };
14
+ const handleSearch = () => {
15
+ // TODO: Implement search functionality for data within drawn polygon
16
+ console.log("Searching for:", searchTerm);
17
+ // This will search data within the polygon boundaries
18
+ // You can integrate with the polygon data from useMapDraw hook here
19
+ };
20
+ const handleKeyPress = (e) => {
21
+ if (e.key === "Enter") {
22
+ handleSearch();
23
+ }
24
+ };
25
+ const isDisabled = !searchTerm.trim();
26
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `w-full p-4 flex flex-col gap-4`, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)(core_1.Input, { name: "polygon_search", label: "Search Data in Polygon", placeholder: "Enter search term...", value: searchTerm, onChange: handleSearchChange, onKeyPress: handleKeyPress }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleSearch, className: `w-full h-10 px-4 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 text-md flex align-middle items-center justify-center gap-2 font-medium transition-all duration-200 ${isDisabled
27
+ ? "bg-blue-500 text-blue-50 cursor-not-allowed focus:ring-blue-400"
28
+ : "bg-blue-600 hover:bg-blue-700 text-white cursor-pointer focus:ring-blue-500 hover:shadow-md"}`, disabled: isDisabled, children: [(0, jsx_runtime_1.jsx)(SearchIconDark, { disabled: isDisabled }), (0, jsx_runtime_1.jsx)("span", { children: "Search" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-sm text-gray-500 mt-2", children: "Draw a polygon on the map first, then search for data within it." })] }));
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/selected/index.tsx"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,gBAAgB,4CAgCvC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/selected/index.tsx"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,gBAAgB,4CA6CvC"}
@@ -14,7 +14,10 @@ function SelectedTabPanel() {
14
14
  const onSortEnd = ({ oldIndex, newIndex, }) => {
15
15
  layer.setSelectedIds((0, array_move_1.arrayMoveImmutable)(layer.selectedIds, oldIndex, newIndex));
16
16
  };
17
- return ((0, jsx_runtime_1.jsx)("div", { className: "flex-1 min-h-0 overflow-y-auto", children: (0, jsx_runtime_1.jsxs)("div", { className: `flex flex-col gap-3 w-full`, children: [layer.selectedIds.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: `p-3 pb-0`, children: (0, jsx_runtime_1.jsxs)(core_1.Button, { onClick: () => layer.clearAll(), children: ["\u2715 ", "clear"] }) })), (0, jsx_runtime_1.jsx)(selected_item_list_1.SelectedItemList, { layerList: layer.selectedLayers,
17
+ const checkedCount = layer.getCheckedAttributesCount();
18
+ return ((0, jsx_runtime_1.jsx)("div", { className: "flex-1 min-h-0 overflow-y-auto", children: (0, jsx_runtime_1.jsxs)("div", { className: `flex flex-col gap-3 w-full`, children: [layer.selectedIds.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: `p-3 pb-0 flex gap-2`, children: [(0, jsx_runtime_1.jsxs)(core_1.Button, { onClick: () => layer.clearAll(), children: ["\u2715 ", "clear"] }), checkedCount > 0 && ((0, jsx_runtime_1.jsxs)("button", { onClick: () => {
19
+ layer.setCompareMode(true);
20
+ }, className: "h-8 px-3 py-2 rounded-md focus:outline-none focus:ring cursor-pointer text-md flex align-middle items-center gap-1 bg-green-700 hover:bg-green-800 text-white", children: ["Compare", " ", (0, jsx_runtime_1.jsxs)("span", { children: ["(", checkedCount, ")"] })] }))] })), (0, jsx_runtime_1.jsx)(selected_item_list_1.SelectedItemList, { layerList: layer.selectedLayers,
18
21
  // @ts-ignore
19
22
  useDragHandle: true, onSortEnd: onSortEnd })] }) }));
20
23
  }
@@ -8,8 +8,8 @@ const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const core_1 = require("../core");
9
9
  const index_1 = __importDefault(require("./layers/index"));
10
10
  const selected_1 = __importDefault(require("./selected"));
11
- const settings_1 = __importDefault(require("./settings"));
11
+ const search_1 = __importDefault(require("./search"));
12
12
  // @ts-ignore
13
13
  function SidebarTabs({ onClose }) {
14
- return ((0, jsx_runtime_1.jsxs)("div", { className: "absolute top-0 right-0 bottom-0 left-0 md:right-auto md:top-4 md:left-4 md:bottom-4 bg-white rounded-lg shadow-md md:max-w-sm w-full z-20 overflow-hidden", children: [(0, jsx_runtime_1.jsx)(core_1.CloseButton, { onClick: onClose }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col h-full", children: (0, jsx_runtime_1.jsxs)(core_1.Tabs, { className: "flex flex-col h-full", children: [(0, jsx_runtime_1.jsxs)(core_1.TabHeader, { children: [(0, jsx_runtime_1.jsx)(core_1.IconTab, { icon: (0, jsx_runtime_1.jsx)(core_1.LayersIcon, {}), children: ("layers") }), (0, jsx_runtime_1.jsx)(core_1.IconTab, { icon: (0, jsx_runtime_1.jsx)(core_1.LayersIcon, {}), children: ("selected") }), (0, jsx_runtime_1.jsx)(core_1.IconTab, { icon: (0, jsx_runtime_1.jsx)(core_1.SlidersIcon, {}), children: ("settings") })] }), (0, jsx_runtime_1.jsx)(core_1.Panel, { children: (0, jsx_runtime_1.jsx)(index_1.default, {}) }), (0, jsx_runtime_1.jsx)(core_1.Panel, { children: (0, jsx_runtime_1.jsx)(selected_1.default, {}) }), (0, jsx_runtime_1.jsx)(core_1.Panel, { children: (0, jsx_runtime_1.jsx)(settings_1.default, {}) })] }) })] }));
14
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "absolute top-0 right-0 bottom-0 left-0 md:right-auto md:top-4 md:left-4 md:bottom-4 bg-white rounded-lg shadow-md md:max-w-sm w-full z-20 overflow-hidden", children: [(0, jsx_runtime_1.jsx)(core_1.CloseButton, { onClick: onClose }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col h-full", children: (0, jsx_runtime_1.jsxs)(core_1.Tabs, { className: "flex flex-col h-full", children: [(0, jsx_runtime_1.jsxs)(core_1.TabHeader, { children: [(0, jsx_runtime_1.jsx)(core_1.IconTab, { icon: (0, jsx_runtime_1.jsx)(core_1.LayersIcon, {}), children: ("layers") }), (0, jsx_runtime_1.jsx)(core_1.IconTab, { icon: (0, jsx_runtime_1.jsx)(core_1.LayersIcon, {}), children: ("selected") }), (0, jsx_runtime_1.jsx)(core_1.IconTab, { icon: (0, jsx_runtime_1.jsx)(core_1.SearchIcon, {}), children: ("search") })] }), (0, jsx_runtime_1.jsx)(core_1.Panel, { children: (0, jsx_runtime_1.jsx)(index_1.default, {}) }), (0, jsx_runtime_1.jsx)(core_1.Panel, { children: (0, jsx_runtime_1.jsx)(selected_1.default, {}) }), (0, jsx_runtime_1.jsx)(core_1.Panel, { children: (0, jsx_runtime_1.jsx)(search_1.default, {}) })] }) })] }));
15
15
  }
@@ -35,6 +35,14 @@ interface LayersContextProps {
35
35
  setGridLegends: (g: Record<string, any>) => void;
36
36
  compareList: string[];
37
37
  setCompareLayer: (layerId: string, checked: boolean) => void;
38
+ getLayerOpacity: (layerId: string) => number;
39
+ setLayerOpacity: (layerId: string, opacity: number) => void;
40
+ checkedAttributes: Set<string>;
41
+ toggleAttributeCompare: (attributeKey: string) => void;
42
+ getCheckedAttributesCount: () => number;
43
+ isCompareMode: boolean;
44
+ setCompareMode: (value: boolean) => void;
45
+ fetchStyleForComparison: (layerId: string, styleIndex: number) => Promise<void>;
38
46
  };
39
47
  query: {
40
48
  term: string;
@@ -1 +1 @@
1
- {"version":3,"file":"use-layers.d.ts","sourceRoot":"","sources":["../../src/hooks/use-layers.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-layers.d.ts","sourceRoot":"","sources":["../../src/hooks/use-layers.tsx"],"names":[],"mappings":"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"}
@@ -64,6 +64,12 @@ const LayersProvider = ({ mp: _mp, children }) => {
64
64
  const [hoverFeatures, setHoverFeatures] = (0, react_1.useState)();
65
65
  const [selectedFeatures, setSelectedFeatures] = (0, react_1.useState)();
66
66
  const [compareList, setCompareList] = (0, react_1.useState)((_mp && _mp.compareList) || []);
67
+ const [layerOpacities, setLayerOpacities] = (0, react_1.useState)({});
68
+ const [layerVisibilities, setLayerVisibilities] = (0, react_1.useState)({});
69
+ // State for tracking checked attributes for comparison (format: "layerId-styleIndex")
70
+ const [checkedAttributes, setCheckedAttributes] = (0, react_1.useState)(new Set());
71
+ // State for compare mode (showing dual map)
72
+ const [isCompareMode, setIsCompareMode] = (0, react_1.useState)(false);
67
73
  const setCompareLayer = (layerId, checked) => {
68
74
  setCompareList((prev) => {
69
75
  if (checked)
@@ -72,6 +78,36 @@ const LayersProvider = ({ mp: _mp, children }) => {
72
78
  });
73
79
  // optional: call mp.onCompareChange(layerId, checked) if you want callbacks
74
80
  };
81
+ const toggleAttributeCompare = (attributeKey) => {
82
+ setCheckedAttributes((prev) => {
83
+ const newSet = new Set(prev);
84
+ if (newSet.has(attributeKey)) {
85
+ // Removing - always allowed
86
+ newSet.delete(attributeKey);
87
+ }
88
+ else {
89
+ // Adding - check limit
90
+ if (newSet.size >= 8) {
91
+ alert("Maximum 8 attributes can be compared at a time");
92
+ return prev; // Don't add, return previous state
93
+ }
94
+ newSet.add(attributeKey);
95
+ }
96
+ return newSet;
97
+ });
98
+ };
99
+ const getCheckedAttributesCount = () => {
100
+ return checkedAttributes.size;
101
+ };
102
+ const getLayerOpacity = (layerId) => {
103
+ return layerOpacities[layerId] ?? 1;
104
+ };
105
+ const setLayerOpacity = (layerId, opacity) => {
106
+ setLayerOpacities((prev) => ({
107
+ ...prev,
108
+ [layerId]: Math.max(0, Math.min(1, opacity)), // Clamp between 0 and 1
109
+ }));
110
+ };
75
111
  const selectedFeaturesId = (0, react_1.useMemo)(() => {
76
112
  const meta = {};
77
113
  for (const qr of selectedFeatures || []) {
@@ -118,11 +154,35 @@ const LayersProvider = ({ mp: _mp, children }) => {
118
154
  const layerIndex = getLayerIndexById(layerId);
119
155
  toggleVectorLayer(layerIndex, styleIndex, false);
120
156
  };
157
+ // Fetch style data for comparison without changing the active styleIndex on main map
158
+ const fetchStyleForComparison = async (layerId, styleIndex) => {
159
+ const layerIndex = getLayerIndexById(layerId);
160
+ const layer = layers[layerIndex];
161
+ if (!layer)
162
+ return;
163
+ // Get the current active styleIndex to preserve it
164
+ const currentStyleIndex = layer.data?.styleIndex ?? 0;
165
+ // Fetch the style data
166
+ const layerData = await (0, naksha_2.getLayerStyle)(
167
+ // @ts-ignore
168
+ layer, styleIndex, mp.nakshaApiEndpoint, mp.geoserver);
169
+ // Update layer data but preserve the original styleIndex so main map doesn't change
170
+ updateLayerById(layer.id, {
171
+ data: {
172
+ ...layerData,
173
+ styleIndex: currentStyleIndex, // Keep the original active style
174
+ }
175
+ });
176
+ };
121
177
  const onMapHover = async (e) => {
122
178
  if (!selectedLayerIds.length || !mapl)
123
179
  return;
124
180
  try {
125
181
  const lastLayerId = selectedLayerIds[0];
182
+ // console.log(lastLayerId , "lastLayerId")
183
+ // added check
184
+ if (!mapl?.getLayer(lastLayerId))
185
+ return;
126
186
  const feats = mapl.queryRenderedFeatures(e.point, {
127
187
  layers: [lastLayerId],
128
188
  });
@@ -154,6 +214,16 @@ const LayersProvider = ({ mp: _mp, children }) => {
154
214
  const toggleLayer = async ({ layerId, add, styleIndex = 0, focus = true, }) => {
155
215
  if (!add) {
156
216
  setSelectedLayerIds(selectedLayerIds.filter((_lyrId) => layerId !== _lyrId));
217
+ // Remove all checked attributes for this layer when it's deselected
218
+ setCheckedAttributes((prev) => {
219
+ const newSet = new Set(prev);
220
+ for (const attrKey of prev) {
221
+ if (attrKey.startsWith(`${layerId}-`)) {
222
+ newSet.delete(attrKey);
223
+ }
224
+ }
225
+ return newSet;
226
+ });
157
227
  return;
158
228
  }
159
229
  const layerIndex = getLayerIndexById(layerId);
@@ -164,7 +234,11 @@ const LayersProvider = ({ mp: _mp, children }) => {
164
234
  return updated;
165
235
  });
166
236
  };
167
- const clearAllLayers = async () => setSelectedLayerIds([]);
237
+ const clearAllLayers = async () => {
238
+ setSelectedLayerIds([]);
239
+ // Clear all checked attributes when all layers are cleared
240
+ setCheckedAttributes(new Set());
241
+ };
168
242
  const updateMP = (key, value) => {
169
243
  setMP({ ...mp, [key]: value });
170
244
  };
@@ -259,6 +333,24 @@ const LayersProvider = ({ mp: _mp, children }) => {
259
333
  // if it takes more then 300 selection will be discarded
260
334
  setTimeout(featuresAtLatLng, 300);
261
335
  }, [clickedLngLat, selectionStyle, selectedLayerIds]);
336
+ // Sync checkedAttributes with selectedLayers - remove attributes for unselected layers
337
+ (0, react_1.useEffect)(() => {
338
+ setCheckedAttributes((prev) => {
339
+ const selectedIdsSet = new Set(selectedLayerIds);
340
+ const newSet = new Set();
341
+ for (const attrKey of prev) {
342
+ const [layerId] = attrKey.split("-");
343
+ if (!layerId) {
344
+ continue;
345
+ }
346
+ // Only keep attributes for layers that are currently selected
347
+ if (selectedIdsSet.has(layerId)) {
348
+ newSet.add(attrKey);
349
+ }
350
+ }
351
+ return newSet;
352
+ });
353
+ }, [selectedLayerIds]);
262
354
  return ((0, jsx_runtime_1.jsx)(LayersContext.Provider, { value: {
263
355
  mp,
264
356
  updateMP,
@@ -287,6 +379,14 @@ const LayersProvider = ({ mp: _mp, children }) => {
287
379
  setGridLegends,
288
380
  compareList: compareList,
289
381
  setCompareLayer: setCompareLayer,
382
+ getLayerOpacity,
383
+ setLayerOpacity,
384
+ checkedAttributes: checkedAttributes,
385
+ toggleAttributeCompare: toggleAttributeCompare,
386
+ getCheckedAttributesCount: getCheckedAttributesCount,
387
+ isCompareMode: isCompareMode,
388
+ setCompareMode: setIsCompareMode,
389
+ fetchStyleForComparison: fetchStyleForComparison,
290
390
  },
291
391
  query: {
292
392
  term: queryTermDebounced,
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ /** GeoJSON Feature from map-draw (polygon) */
3
+ export type PolygonShape = {
4
+ id: string;
5
+ type: "Feature";
6
+ geometry: {
7
+ type: string;
8
+ coordinates: unknown;
9
+ };
10
+ properties?: Record<string, unknown>;
11
+ };
12
+ interface PolygonDataContextValue {
13
+ /** Current drawn polygon features from map-draw */
14
+ shapes: PolygonShape[];
15
+ /** Fetch data from backend for current polygon(s). Call after user draws and hits Search. */
16
+ fetchPolygonData: (searchTerm?: string) => Promise<void>;
17
+ /** Response data from last successful fetch */
18
+ polygonData: unknown;
19
+ /** Loading state while fetch is in progress */
20
+ loading: boolean;
21
+ /** Error message from last failed fetch */
22
+ error: string | null;
23
+ /** Clear error (e.g. when user retries or draws again) */
24
+ clearError: () => void;
25
+ }
26
+ export interface PolygonProviderProps {
27
+ /** Drawn polygon features from useMapDraw().shapes */
28
+ shapes: PolygonShape[];
29
+ children: React.ReactNode;
30
+ }
31
+ export declare function PolygonProvider({ shapes, children }: PolygonProviderProps): import("react/jsx-runtime").JSX.Element;
32
+ export declare function usePolygonData(): PolygonDataContextValue;
33
+ export {};
34
+ //# sourceMappingURL=use-polygon-data.d.ts.map