@metastringfoundation/map-list 0.1.0 → 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.
- package/dist/components/Handler/LayerCompareControl.d.ts +7 -0
- package/dist/components/Handler/LayerCompareControl.d.ts.map +1 -0
- package/dist/components/Handler/LayerCompareControl.js +18 -0
- package/dist/components/Handler/MapComparisonControl.d.ts +7 -0
- package/dist/components/Handler/MapComparisonControl.d.ts.map +1 -0
- package/dist/components/Handler/MapComparisonControl.js +8 -0
- package/dist/components/core/button.js +1 -1
- package/dist/components/core/input.d.ts.map +1 -1
- package/dist/components/core/input.js +1 -1
- package/dist/components/dualMap/MapLayerCard.d.ts +8 -0
- package/dist/components/dualMap/MapLayerCard.d.ts.map +1 -0
- package/dist/components/dualMap/MapLayerCard.js +68 -0
- package/dist/components/dualMap/index.d.ts +3 -0
- package/dist/components/dualMap/index.d.ts.map +1 -0
- package/dist/components/dualMap/index.js +277 -0
- package/dist/components/map/compare-sidebar.d.ts +2 -0
- package/dist/components/map/compare-sidebar.d.ts.map +1 -0
- package/dist/components/map/compare-sidebar.js +34 -0
- package/dist/components/map/compare.d.ts +2 -0
- package/dist/components/map/compare.d.ts.map +1 -0
- package/dist/components/map/compare.js +42 -0
- package/dist/components/map/index.d.ts.map +1 -1
- package/dist/components/map/index.js +14 -1
- package/dist/components/map/layers/grid/index.d.ts.map +1 -1
- package/dist/components/map/layers/grid/index.js +11 -1
- package/dist/components/map/layers/index.d.ts.map +1 -1
- package/dist/components/map/layers/index.js +17 -14
- package/dist/components/map/layers/raster/index.d.ts.map +1 -1
- package/dist/components/map/layers/raster/index.js +8 -8
- package/dist/components/map/layers/vector/index.d.ts.map +1 -1
- package/dist/components/map/layers/vector/index.js +25 -1
- package/dist/components/map/search.d.ts +2 -0
- package/dist/components/map/search.d.ts.map +1 -0
- package/dist/components/map/search.js +122 -0
- package/dist/components/map/split-map/SplitMapComparision.d.ts +2 -0
- package/dist/components/map/split-map/SplitMapComparision.d.ts.map +1 -0
- package/dist/components/map/split-map/SplitMapComparision.js +78 -0
- package/dist/components/map-comparison/attribute-selector.d.ts +11 -0
- package/dist/components/map-comparison/attribute-selector.d.ts.map +1 -0
- package/dist/components/map-comparison/attribute-selector.js +10 -0
- package/dist/components/map-comparison/comparison-panel.d.ts +2 -0
- package/dist/components/map-comparison/comparison-panel.d.ts.map +1 -0
- package/dist/components/map-comparison/comparison-panel.js +45 -0
- package/dist/components/map-comparison/comparison-stats.d.ts +2 -0
- package/dist/components/map-comparison/comparison-stats.d.ts.map +1 -0
- package/dist/components/map-comparison/comparison-stats.js +35 -0
- package/dist/components/map-comparison/comparison-view.d.ts +2 -0
- package/dist/components/map-comparison/comparison-view.d.ts.map +1 -0
- package/dist/components/map-comparison/comparison-view.js +152 -0
- package/dist/components/map-comparison/comparison-wrapper.d.ts +8 -0
- package/dist/components/map-comparison/comparison-wrapper.d.ts.map +1 -0
- package/dist/components/map-comparison/comparison-wrapper.js +26 -0
- package/dist/components/map-comparison/index.d.ts +3 -0
- package/dist/components/map-comparison/index.d.ts.map +1 -0
- package/dist/components/map-comparison/index.js +165 -0
- package/dist/components/map-comparison/types.d.ts +30 -0
- package/dist/components/map-comparison/types.d.ts.map +1 -0
- package/dist/components/map-comparison/types.js +2 -0
- package/dist/components/map-comparison/use-map-comparison.d.ts +18 -0
- package/dist/components/map-comparison/use-map-comparison.d.ts.map +1 -0
- package/dist/components/map-comparison/use-map-comparison.js +139 -0
- package/dist/components/sidebar/common/attribute-compare-addon.d.ts +7 -0
- package/dist/components/sidebar/common/attribute-compare-addon.d.ts.map +1 -0
- package/dist/components/sidebar/common/attribute-compare-addon.js +36 -0
- package/dist/components/sidebar/common/layer-compare-addon.d.ts +4 -0
- package/dist/components/sidebar/common/layer-compare-addon.d.ts.map +1 -0
- package/dist/components/sidebar/common/layer-compare-addon.js +17 -0
- package/dist/components/sidebar/common/layer-item-style.d.ts.map +1 -1
- package/dist/components/sidebar/common/layer-item-style.js +46 -1
- package/dist/components/sidebar/common/layer-item.d.ts.map +1 -1
- package/dist/components/sidebar/common/layer-item.js +1 -1
- package/dist/components/sidebar/common/opacity-handler-addon.d.ts +5 -2
- package/dist/components/sidebar/common/opacity-handler-addon.d.ts.map +1 -1
- package/dist/components/sidebar/common/opacity-handler-addon.js +101 -4
- package/dist/components/sidebar/common/style-legend.d.ts.map +1 -1
- package/dist/components/sidebar/common/style-legend.js +1 -2
- package/dist/components/sidebar/comparison/index.d.ts +4 -0
- package/dist/components/sidebar/comparison/index.d.ts.map +1 -0
- package/dist/components/sidebar/comparison/index.js +34 -0
- package/dist/components/sidebar/index.d.ts.map +1 -1
- package/dist/components/sidebar/search/attribute-comparison.d.ts +10 -0
- package/dist/components/sidebar/search/attribute-comparison.d.ts.map +1 -0
- package/dist/components/sidebar/search/attribute-comparison.js +137 -0
- package/dist/components/sidebar/search/index.d.ts +2 -0
- package/dist/components/sidebar/search/index.d.ts.map +1 -0
- package/dist/components/sidebar/search/index.js +29 -0
- package/dist/components/sidebar/selected/index.d.ts.map +1 -1
- package/dist/components/sidebar/selected/index.js +7 -4
- package/dist/components/sidebar/tabs.js +2 -2
- package/dist/hooks/use-layers.d.ts +10 -0
- package/dist/hooks/use-layers.d.ts.map +1 -1
- package/dist/hooks/use-layers.js +115 -5
- package/dist/hooks/use-polygon-data.d.ts +34 -0
- package/dist/hooks/use-polygon-data.d.ts.map +1 -0
- package/dist/hooks/use-polygon-data.js +74 -0
- package/dist/index.css +708 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/services/naksha.d.ts.map +1 -1
- package/dist/services/naksha.js +22 -158
- package/dist/services/polygon.d.ts +36 -0
- package/dist/services/polygon.d.ts.map +1 -0
- package/dist/services/polygon.js +67 -0
- package/dist/utils/naksha.d.ts.map +1 -1
- package/dist/utils/naksha.js +15 -6
- package/package.json +16 -15
|
@@ -0,0 +1,17 @@
|
|
|
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 = LayerCompareAddon;
|
|
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 LayerCompareAddon({ id }) {
|
|
11
|
+
const { layer } = (0, use_layers_1.default)();
|
|
12
|
+
const checked = Boolean(layer?.compareList?.includes(id));
|
|
13
|
+
const onToggle = () => {
|
|
14
|
+
layer.setCompareLayer(id, !checked);
|
|
15
|
+
};
|
|
16
|
+
return ((0, jsx_runtime_1.jsx)(core_1.Button, { children: (0, jsx_runtime_1.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer select-none", children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", className: "h-4 w-4 accent-green-700", checked: checked, onChange: onToggle }), (0, jsx_runtime_1.jsx)("span", { children: "Compare" })] }) }));
|
|
17
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-item-style.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/layer-item-style.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"layer-item-style.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/layer-item-style.tsx"],"names":[],"mappings":"AAQA,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,GAAG,CAAA;CAAE,kDA4H7D"}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.default = LayerItemStyle;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
// @ts-nocheck
|
|
9
|
+
const react_1 = require("react");
|
|
9
10
|
const use_layers_1 = __importDefault(require("../../../hooks/use-layers"));
|
|
10
11
|
const core_1 = require("../../core");
|
|
11
12
|
const moreless_1 = __importDefault(require("./moreless"));
|
|
@@ -14,8 +15,52 @@ function LayerItemStyle({ item }) {
|
|
|
14
15
|
if (!item.data?.styles)
|
|
15
16
|
return null;
|
|
16
17
|
const { layer } = (0, use_layers_1.default)();
|
|
18
|
+
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
19
|
+
const [selectedIndex, setSelectedIndex] = (0, react_1.useState)(0);
|
|
20
|
+
const dropdownRef = (0, react_1.useRef)(null);
|
|
21
|
+
// Close dropdown when clicking outside
|
|
22
|
+
(0, react_1.useEffect)(() => {
|
|
23
|
+
const handleClickOutside = (event) => {
|
|
24
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
25
|
+
setIsOpen(false);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
if (isOpen) {
|
|
29
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
30
|
+
}
|
|
31
|
+
return () => {
|
|
32
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
33
|
+
};
|
|
34
|
+
}, [isOpen]);
|
|
17
35
|
const onStyleChange = (e) => {
|
|
18
36
|
layer.updateStyle(item.id, Number(e.target.value));
|
|
37
|
+
setSelectedIndex(Number(e.target.value));
|
|
19
38
|
};
|
|
20
|
-
|
|
39
|
+
// Toggle checkbox for comparison (independent from dropdown selection)
|
|
40
|
+
const onCheckboxToggle = (styleIndex, event) => {
|
|
41
|
+
event.stopPropagation(); // Prevent dropdown item click
|
|
42
|
+
const attributeKey = `${item.id}-${styleIndex}`;
|
|
43
|
+
layer.toggleAttributeCompare(attributeKey);
|
|
44
|
+
};
|
|
45
|
+
const selectedStyle = item.data?.styles[selectedIndex];
|
|
46
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-4 pt-2", children: [item.layerType !== "RASTER" && ((0, jsx_runtime_1.jsxs)("div", { className: "relative", ref: dropdownRef, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setIsOpen(!isOpen), className: "block w-full px-4 py-2 mt-2 text-gray-700 border bg-white border-gray-200 rounded-md focus:outline-none focus:ring text-left flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { children: selectedStyle?.styleTitle || "Select attribute" }), (0, jsx_runtime_1.jsx)("svg", { className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), isOpen && ((0, jsx_runtime_1.jsx)("div", { className: "absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-md shadow-lg max-h-60 overflow-auto", children: item.data?.styles.map((opt, idx) => {
|
|
47
|
+
const attributeKey = `${item.id}-${idx}`;
|
|
48
|
+
const isChecked = layer.checkedAttributes.has(attributeKey);
|
|
49
|
+
const checkedCount = layer.getCheckedAttributesCount();
|
|
50
|
+
const isLimitReached = checkedCount >= 8 && !isChecked;
|
|
51
|
+
const isSelected = idx === selectedIndex;
|
|
52
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `flex items-center justify-between px-4 py-2 border-b border-gray-100 last:border-b-0 ${isSelected
|
|
53
|
+
? "bg-blue-50 hover:bg-blue-100"
|
|
54
|
+
: "hover:bg-gray-50"}`, children: [(0, jsx_runtime_1.jsx)("span", { className: "flex-1 text-gray-700 cursor-pointer", onClick: () => {
|
|
55
|
+
onStyleChange({ target: { value: idx } });
|
|
56
|
+
setIsOpen(false);
|
|
57
|
+
}, children: opt.styleTitle }), (0, jsx_runtime_1.jsx)("div", { onClick: (e) => {
|
|
58
|
+
if (isLimitReached) {
|
|
59
|
+
e.stopPropagation();
|
|
60
|
+
alert("Maximum 8 attributes can be compared at a time");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
onCheckboxToggle(idx, e);
|
|
64
|
+
}, className: isLimitReached ? "opacity-50 cursor-not-allowed" : "cursor-pointer", title: isLimitReached ? "Maximum 8 attributes can be compared at a time" : "", children: (0, jsx_runtime_1.jsx)(core_1.CheckboxInput, { name: `compare-${item.id}-${idx}`, checked: isChecked, disabled: isLimitReached, onChange: () => { } }) })] }, idx));
|
|
65
|
+
}) }))] })), (0, jsx_runtime_1.jsx)(moreless_1.default, { children: (0, jsx_runtime_1.jsx)(style_legend_1.StyleLegend, { item: item }) })] }));
|
|
21
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-item.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/layer-item.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAwBrD,UAAU,cAAc;IACtB,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,oDAAoD;IACpD,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,aAAa,CAAC,EAAE,GAAG,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"layer-item.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/layer-item.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAwBrD,UAAU,cAAc;IACtB,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,oDAAoD;IACpD,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,aAAa,CAAC,EAAE,GAAG,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,aAAa,GACd,EAAE,cAAc,2CAmIhB"}
|
|
@@ -55,5 +55,5 @@ function LayerItem({ item, extended, dragHandleProps, dragHandleRef, }) {
|
|
|
55
55
|
mp?.onLayerDownload(item.id);
|
|
56
56
|
};
|
|
57
57
|
const handleOnZoom = () => layer?.zoomToExtent(item?.id);
|
|
58
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "z-20 p-3 bg-white border-t border-gray-200", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-
|
|
58
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "z-20 p-3 bg-white border-t border-gray-200", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center shrink-0", children: [(0, jsx_runtime_1.jsx)(core_1.CheckboxInput, { name: item.id, checked: isAdded, onChange: onToggleLayer, isLoading: isLoading }), extended && ((0, jsx_runtime_1.jsx)("div", { ref: dragHandleRef, ...dragHandleProps, className: "mt-1 w-6 text-center cursor-move", children: (0, jsx_runtime_1.jsx)(core_1.GrabberIcon, {}) }))] }), (0, jsx_runtime_1.jsx)("img", { className: "flex shrink-0 overflow-hidden h-16 w-16 p-1 mb-2 object-cover border border-gray-200 rounded", src: item.thumbnail || constants_1.FALLBACK_THUMB }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { title: item.title, className: "mb-1 leading-tight", style: constants_1.overflowStyle, children: (0, jsx_runtime_1.jsx)(highlighter_1.Highlighted, { text: item.title, highlight: query.term }) }), (0, jsx_runtime_1.jsx)("p", { title: item.description, className: "text-gray-600 text-sm", style: constants_1.overflowStyle2, children: item.description })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "pb-3", children: extended && (0, jsx_runtime_1.jsx)(opacity_handler_addon_1.default, { layerId: item.id }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [!extended && ((0, jsx_runtime_1.jsxs)(core_1.Button, { onClick: onDownloadLayer, disabled: !item.isDownloadable, children: [(0, jsx_runtime_1.jsx)(core_1.DownloadIcon, {}), " Download"] })), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-3", children: [(0, jsx_runtime_1.jsx)(core_1.Button, { onClick: shareLayer, title: "Share", children: (0, jsx_runtime_1.jsx)(core_1.ShareIcon, {}) }), extended && ((0, jsx_runtime_1.jsx)(core_1.Button, { onClick: handleOnZoom, title: "Zoom To Extent", children: (0, jsx_runtime_1.jsx)(core_1.ZoomExtentIcon, {}) })), (0, jsx_runtime_1.jsx)(info_popover_1.PopoverWrapper, { item: item })] })] }), extended && (0, jsx_runtime_1.jsx)(layer_item_style_1.default, { item: item }), extended && item?.source?.type === "grid" && (0, jsx_runtime_1.jsx)(grid_legend_1.default, { item: item })] }));
|
|
59
59
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
interface OpacityHandlerProps {
|
|
2
|
+
layerId: string;
|
|
3
|
+
}
|
|
4
|
+
declare const OpacityHandler: ({ layerId }: OpacityHandlerProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default OpacityHandler;
|
|
3
6
|
//# sourceMappingURL=opacity-handler-addon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opacity-handler-addon.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/opacity-handler-addon.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"opacity-handler-addon.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/common/opacity-handler-addon.tsx"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,cAAc,GAAI,aAAa,mBAAmB,4CAgIvD,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -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
|
|
6
|
-
|
|
7
|
-
|
|
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 =
|
|
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,
|
|
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:
|
|
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 @@
|
|
|
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
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/sidebar/index.tsx"],"names":[],"mappings":"AAQA,MAAM,CAAC,OAAO,UAAU,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/sidebar/index.tsx"],"names":[],"mappings":"AAQA,MAAM,CAAC,OAAO,UAAU,OAAO,4CAuC9B"}
|
|
@@ -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 @@
|
|
|
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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/sidebar/selected/index.tsx"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,gBAAgB,4CA6CvC"}
|
|
@@ -11,10 +11,13 @@ const selected_item_list_1 = require("./selected-item-list");
|
|
|
11
11
|
const core_1 = require("../../core");
|
|
12
12
|
function SelectedTabPanel() {
|
|
13
13
|
const { layer } = (0, use_layers_1.default)();
|
|
14
|
-
const onSortEnd = ({ oldIndex, newIndex }) => {
|
|
14
|
+
const onSortEnd = ({ oldIndex, newIndex, }) => {
|
|
15
15
|
layer.setSelectedIds((0, array_move_1.arrayMoveImmutable)(layer.selectedIds, oldIndex, newIndex));
|
|
16
16
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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,
|
|
21
|
+
// @ts-ignore
|
|
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
|
|
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.
|
|
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
|
}
|
|
@@ -33,6 +33,16 @@ interface LayersContextProps {
|
|
|
33
33
|
zoomToExtent: (layerId: string) => void;
|
|
34
34
|
gridLegends: Record<string, any>;
|
|
35
35
|
setGridLegends: (g: Record<string, any>) => void;
|
|
36
|
+
compareList: string[];
|
|
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>;
|
|
36
46
|
};
|
|
37
47
|
query: {
|
|
38
48
|
term: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-layers.d.ts","sourceRoot":"","sources":["../../src/hooks/use-layers.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-layers.d.ts","sourceRoot":"","sources":["../../src/hooks/use-layers.tsx"],"names":[],"mappings":"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"}
|