@metastringfoundation/map-list 0.1.1 → 0.1.3

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
@@ -0,0 +1,7 @@
1
+ interface MapComparisonControlProps {
2
+ isActive: boolean;
3
+ onToggle: () => void;
4
+ }
5
+ export default function MapComparisonControl({ isActive, onToggle, }: MapComparisonControlProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=MapComparisonControl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapComparisonControl.d.ts","sourceRoot":"","sources":["../../../src/components/Handler/MapComparisonControl.tsx"],"names":[],"mappings":"AAIA,UAAU,yBAAyB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,QAAQ,EACR,QAAQ,GACT,EAAE,yBAAyB,2CAuD3B"}
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.default = MapComparisonControl;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ function MapComparisonControl({ isActive, onToggle, }) {
7
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "absolute bottom-4 right-4 z-50 flex gap-2", children: [!isActive && ((0, jsx_runtime_1.jsxs)("button", { onClick: onToggle, className: "px-4 py-2 bg-blue-600 hover:bg-blue-700 \n text-white rounded-lg shadow-md text-md flex items-center gap-2 font-semibold transition-colors", title: "Open Map Comparison", children: [(0, jsx_runtime_1.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" }), (0, jsx_runtime_1.jsx)("polyline", { points: "3.27 6.96 12 12.01 20.73 6.96" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "22.08", x2: "12", y2: "12" })] }), "Map Comparison"] })), isActive && ((0, jsx_runtime_1.jsxs)("button", { onClick: onToggle, className: "px-4 py-2 bg-blue-600 hover:bg-blue-700 \n text-white rounded-lg shadow-md text-md flex items-center gap-2 font-semibold transition-colors", title: "Close Map Comparison", children: [(0, jsx_runtime_1.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), (0, jsx_runtime_1.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }), "Close Comparison"] }))] }));
8
+ }
@@ -17,5 +17,5 @@ const CloseButton = (props) => ((0, jsx_runtime_1.jsx)("button", { className: "a
17
17
  exports.CloseButton = CloseButton;
18
18
  const LayersButton = (props) => ((0, jsx_runtime_1.jsx)("button", { className: "absolute top-4 left-4 rounded-lg z-10 h-10 w-10 bg-white cursor-pointer hover:bg-gray-100 text-gray-700 text-lg flex items-center justify-center", ...props, children: (0, jsx_runtime_1.jsx)(icons_1.LayersIcon, {}) }));
19
19
  exports.LayersButton = LayersButton;
20
- const InfobarButton = (props) => ((0, jsx_runtime_1.jsx)("button", { className: "absolute top-4 right-4 rounded-lg z-10 h-10 w-10 bg-white cursor-pointer hover:bg-gray-100 text-gray-700 text-lg flex items-center justify-center", ...props, children: (0, jsx_runtime_1.jsx)(icons_1.InfoIcon, {}) }));
20
+ const InfobarButton = (props) => ((0, jsx_runtime_1.jsx)("button", { className: "absolute top-4 right-11 rounded-lg z-10 h-10 w-10 bg-white cursor-pointer hover:bg-gray-100 text-gray-700 text-lg flex items-center justify-center", ...props, children: (0, jsx_runtime_1.jsx)(icons_1.InfoIcon, {}) }));
21
21
  exports.InfobarButton = InfobarButton;
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/core/input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,UACR,SAAQ,KAAK,CAAC,iBAAiB,CAC7B,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAC3C,gBAAgB,CACjB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,KAAK,GAAI,OAAO,UAAU,4CAetC,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,UAAU,4CAoB5C,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,UAAU,4CAW5C,CAAC;AAEF,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,GAAI,OAAO,kBAAkB,4CAuBpD,CAAC"}
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/core/input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,UACR,SAAQ,KAAK,CAAC,iBAAiB,CAC7B,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAC3C,gBAAgB,CACjB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,KAAK,GAAI,OAAO,UAAU,4CAetC,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,UAAU,4CAoB5C,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,UAAU,4CAW5C,CAAC;AAEF,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,GAAI,OAAO,kBAAkB,4CAwBpD,CAAC"}
@@ -14,5 +14,5 @@ const SelectInput = (props) => ((0, jsx_runtime_1.jsxs)("div", { children: [prop
14
14
  exports.SelectInput = SelectInput;
15
15
  const SearchInput = (props) => ((0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("span", { className: "absolute inset-y-0 left-0 flex items-center pl-3", children: (0, jsx_runtime_1.jsx)(icons_1.SearchIcon, {}) }), (0, jsx_runtime_1.jsx)("input", { type: "search", className: "w-full py-2 pl-10 pr-4 text-gray-700 bg-white border border-gray-300 text-base rounded-md focus:outline-none focus:ring", ...props })] }));
16
16
  exports.SearchInput = SearchInput;
17
- const CheckboxInput = (props) => props.isLoading ? ((0, jsx_runtime_1.jsx)("svg", { width: "20px", height: "20px", viewBox: "0 0 20 20", version: "1.1", className: "inline text-gray-200 animate-spin dark:text-gray-600", children: (0, jsx_runtime_1.jsx)("g", { stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd", children: (0, jsx_runtime_1.jsx)("g", { fill: "#212121", fillRule: "nonzero", children: (0, jsx_runtime_1.jsx)("path", { d: "M10,3 C6.13401,3 3,6.13401 3,10 C3,10.2761 2.77614,10.5 2.5,10.5 C2.22386,10.5 2,10.2761 2,10 C2,5.58172 5.58172,2 10,2 C14.4183,2 18,5.58172 18,10 C18,14.4183 14.4183,18 10,18 C9.72386,18 9.5,17.7761 9.5,17.5 C9.5,17.2239 9.72386,17 10,17 C13.866,17 17,13.866 17,10 C17,6.13401 13.866,3 10,3 Z" }) }) }) })) : ((0, jsx_runtime_1.jsx)("input", { type: "checkbox", className: "w-5 h-5 border-gray-100 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80", name: props.name, checked: props.checked, onChange: props.onChange }));
17
+ const CheckboxInput = (props) => props.isLoading ? ((0, jsx_runtime_1.jsx)("svg", { width: "20px", height: "20px", viewBox: "0 0 20 20", version: "1.1", className: "inline text-gray-200 animate-spin dark:text-gray-600", children: (0, jsx_runtime_1.jsx)("g", { stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd", children: (0, jsx_runtime_1.jsx)("g", { fill: "#212121", fillRule: "nonzero", children: (0, jsx_runtime_1.jsx)("path", { d: "M10,3 C6.13401,3 3,6.13401 3,10 C3,10.2761 2.77614,10.5 2.5,10.5 C2.22386,10.5 2,10.2761 2,10 C2,5.58172 5.58172,2 10,2 C14.4183,2 18,5.58172 18,10 C18,14.4183 14.4183,18 10,18 C9.72386,18 9.5,17.7761 9.5,17.5 C9.5,17.2239 9.72386,17 10,17 C13.866,17 17,13.866 17,10 C17,6.13401 13.866,3 10,3 Z" }) }) }) })) : ((0, jsx_runtime_1.jsx)("input", { type: "checkbox", className: "w-5 h-5 border-gray-100 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80 disabled:opacity-50 disabled:cursor-not-allowed", name: props.name, checked: props.checked, onChange: props.onChange, disabled: props.disabled }));
18
18
  exports.CheckboxInput = CheckboxInput;
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import { GeoserverLayer } from "../../interfaces";
3
+ interface MapLayerCardProps {
4
+ layer: GeoserverLayer;
5
+ }
6
+ export default function MapLayerCard({ layer, }: MapLayerCardProps): React.ReactElement;
7
+ export {};
8
+ //# sourceMappingURL=MapLayerCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapLayerCard.d.ts","sourceRoot":"","sources":["../../../src/components/dualMap/MapLayerCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIlD,UAAU,iBAAiB;IACzB,KAAK,EAAE,cAAc,CAAC;CACvB;AA2HD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,KAAK,GACN,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAwGxC"}
@@ -0,0 +1,68 @@
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 = MapLayerCard;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = require("react");
9
+ const core_1 = require("../core");
10
+ const use_layers_1 = __importDefault(require("../../hooks/use-layers"));
11
+ function LegendHeader({ isOpen, onToggle, }) {
12
+ return ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: onToggle, className: "flex w-fit items-center gap-1 rounded hover:bg-gray-100 py-0.5 px-1 transition-colors", "aria-expanded": isOpen, "aria-label": isOpen ? "Collapse legend" : "Expand legend", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[10px] font-semibold text-gray-700", children: "Legend" }), (0, jsx_runtime_1.jsx)("span", { className: "shrink-0 w-3 h-3 flex items-center justify-center text-gray-600", children: isOpen ? (0, jsx_runtime_1.jsx)(core_1.UpIcon, {}) : (0, jsx_runtime_1.jsx)(core_1.DownIcon, {}) })] }));
13
+ }
14
+ function CardLegend({ layer }) {
15
+ const { mp, layer: layerContext } = (0, use_layers_1.default)();
16
+ const [legendOpen, setLegendOpen] = (0, react_1.useState)(true);
17
+ const styleIndex = layer.data?.styleIndex;
18
+ const currentStyle = typeof styleIndex === "number" && layer.data?.styles
19
+ ? layer.data.styles[styleIndex]
20
+ : undefined;
21
+ const layerType = layer.source?.type;
22
+ const baseLayerId = layer.id.replace(/-style-\d+$/, "") || layer.id;
23
+ // Vector: legend from style stops (fill-color or circle-color)
24
+ const vectorStops = (0, react_1.useMemo)(() => currentStyle?.colors?.paint?.["fill-color"]?.stops ||
25
+ currentStyle?.colors?.paint?.["circle-color"]?.stops ||
26
+ [], [currentStyle]);
27
+ if (layerType === "grid") {
28
+ const legendInfo = layerContext.gridLegends?.[baseLayerId];
29
+ if (!legendInfo?.stops?.length)
30
+ return null;
31
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "mt-1.5 pt-1.5 border-t border-gray-200", children: [(0, jsx_runtime_1.jsx)(LegendHeader, { isOpen: legendOpen, onToggle: () => setLegendOpen((o) => !o) }), legendOpen && ((0, jsx_runtime_1.jsx)("div", { className: "max-h-32 overflow-y-auto mt-1", children: (0, jsx_runtime_1.jsxs)("ul", { className: "space-y-0.5 list-none p-0 m-0", children: [legendInfo.stops.map(([stop, color], index, stopsArr) => {
32
+ const prevStop = (stopsArr[index - 1] || [0])[0];
33
+ if (prevStop === stop)
34
+ return null;
35
+ return ((0, jsx_runtime_1.jsxs)("li", { className: "flex gap-1.5 items-center text-[10px]", children: [(0, jsx_runtime_1.jsx)("span", { className: "shrink-0 w-2.5 h-2.5 rounded-full border border-gray-300", style: { backgroundColor: color } }), (0, jsx_runtime_1.jsxs)("span", { className: "text-gray-700 truncate", children: [prevStop, " \u2013 ", stop] })] }, `${stop}-${color}`));
36
+ }), (0, jsx_runtime_1.jsxs)("li", { className: "text-[10px] text-gray-500 mt-0.5", children: ["1 sq = ", legendInfo.squareSize, "\u00D7", legendInfo.squareSize, " km"] })] }) }))] }));
37
+ }
38
+ if (layerType === "raster" && mp?.geoserver?.endpoint) {
39
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "mt-1.5 pt-1.5 border-t border-gray-200", children: [(0, jsx_runtime_1.jsx)(LegendHeader, { isOpen: legendOpen, onToggle: () => setLegendOpen((o) => !o) }), legendOpen && ((0, jsx_runtime_1.jsx)("div", { className: "max-h-32 overflow-y-auto mt-1", children: (0, jsx_runtime_1.jsx)("img", { className: "max-w-full h-auto max-h-16 object-contain", src: `${mp.geoserver.endpoint}/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&WIDTH=20&HEIGHT=20&STRICT=false&layer=biodiv:${baseLayerId}`, alt: "" }) }))] }));
40
+ }
41
+ if (vectorStops.length > 0) {
42
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "mt-1.5 pt-1.5 border-t border-gray-200", children: [(0, jsx_runtime_1.jsx)(LegendHeader, { isOpen: legendOpen, onToggle: () => setLegendOpen((o) => !o) }), legendOpen && ((0, jsx_runtime_1.jsx)("div", { className: "max-h-32 overflow-y-auto mt-1", children: (0, jsx_runtime_1.jsx)("ul", { className: "space-y-0.5 list-none p-0 m-0", children: vectorStops.map(([title, color]) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex gap-1.5 items-center text-[10px]", children: [(0, jsx_runtime_1.jsx)("span", { className: "shrink-0 w-2.5 h-2.5 rounded-full border border-gray-300", style: { backgroundColor: color } }), (0, jsx_runtime_1.jsx)("span", { className: "text-gray-700 truncate", children: String(title) })] }, String(color)))) }) }))] }));
43
+ }
44
+ return null;
45
+ }
46
+ function MapLayerCard({ layer, }) {
47
+ const [isCollapsed, setIsCollapsed] = (0, react_1.useState)(false);
48
+ const [showFullDesc, setShowFullDesc] = (0, react_1.useState)(false);
49
+ const styleIndex = layer.data?.styleIndex;
50
+ const currentStyle = typeof styleIndex === "number" && layer.data?.styles
51
+ ? layer.data.styles[styleIndex]
52
+ : undefined;
53
+ const attributeLabel = currentStyle?.styleTitle ||
54
+ currentStyle?.styleName;
55
+ return ((0, jsx_runtime_1.jsx)("div", { className: `absolute bottom-3 left-3 z-40 bg-white/95 rounded-md shadow border border-gray-200 overflow-hidden transition-all duration-200 ${isCollapsed ? "w-8 h-8" : "w-56 py-1.5 px-2"}`, children: isCollapsed ? ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "flex h-full w-full items-center justify-center hover:bg-gray-100", onClick: () => setIsCollapsed(false), "aria-label": "Expand layer info", children: (0, jsx_runtime_1.jsx)(core_1.UpIcon, {}) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col min-w-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-1 min-w-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col flex-1 min-w-0 space-y-0.5", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-[11px] text-gray-600 truncate", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-gray-800", children: "Layer:" }), " ", (0, jsx_runtime_1.jsx)("span", { className: "text-gray-900", children: layer.title })] }), attributeLabel && ((0, jsx_runtime_1.jsxs)("p", { className: "text-[11px] text-gray-600 truncate", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-gray-800", children: "Attribute:" }), " ", (0, jsx_runtime_1.jsx)("span", { className: "text-gray-900", children: attributeLabel })] }))] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "shrink-0 p-1 rounded hover:bg-gray-100 transition-colors", onClick: () => setIsCollapsed(true), "aria-label": "Collapse layer info", children: (0, jsx_runtime_1.jsx)(core_1.DownIcon, {}) })] }), (0, jsx_runtime_1.jsx)(CardLegend, { layer: layer }), (() => {
56
+ const raw = layer.description || "";
57
+ if (!raw) {
58
+ return null;
59
+ }
60
+ const maxPreviewChars = 60;
61
+ const isLong = raw.length > maxPreviewChars;
62
+ const fullText = raw;
63
+ const previewBody = isLong
64
+ ? fullText.slice(0, maxPreviewChars - 3)
65
+ : fullText;
66
+ return ((0, jsx_runtime_1.jsx)("p", { className: "mt-0.5 text-xs leading-snug text-gray-600", children: !isLong ? (fullText) : showFullDesc ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [fullText, " ", (0, jsx_runtime_1.jsx)("button", { type: "button", className: "inline text-[11px] text-blue-600 hover:underline", onClick: () => setShowFullDesc(false), "aria-label": "See less", children: "see less" })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [previewBody, " ", (0, jsx_runtime_1.jsx)("button", { type: "button", className: "inline text-[11px] text-blue-600 hover:underline", onClick: () => setShowFullDesc(true), "aria-label": "See more", children: "see more" })] })) }));
67
+ })()] })) }));
68
+ }
@@ -1,2 +1,3 @@
1
- export default function DualMap(): import("react/jsx-runtime").JSX.Element;
1
+ import { JSX } from "react";
2
+ export default function DualMap(): JSX.Element;
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/dualMap/index.tsx"],"names":[],"mappings":"AAeA,MAAM,CAAC,OAAO,UAAU,OAAO,4CA4H9B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/dualMap/index.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,GAAG,EAAgC,MAAM,OAAO,CAAC;AA4BjE,MAAM,CAAC,OAAO,UAAU,OAAO,IAAI,GAAG,CAAC,OAAO,CAkW7C"}
@@ -45,70 +45,233 @@ const map_common_1 = require("@metastringfoundation/map-common");
45
45
  const use_layers_1 = __importDefault(require("../../hooks/use-layers"));
46
46
  const infobar_1 = __importDefault(require("../infobar"));
47
47
  const layers_1 = require("../map/layers");
48
- const markers_list_1 = __importDefault(require("../map/markers-list"));
49
48
  const popup_1 = __importDefault(require("../map/popup"));
49
+ const MapLayerCard_1 = __importDefault(require("./MapLayerCard"));
50
50
  const NavControl = maplibre_1.NavigationControl;
51
51
  function DualMap() {
52
52
  const { mp, layer, hover, query } = (0, use_layers_1.default)();
53
- const viewState = (0, react_1.useMemo)(() => mp.defaultViewState || map_common_1.defaultViewState, [mp.defaultViewState]);
54
- const [coordsLeft, setCoordsLeft] = (0, react_1.useState)();
55
- const [coordsRight, setCoordsRight] = (0, react_1.useState)();
56
- // handlers
57
- // @ts-ignore
58
- const onLeftClick = (e) => query.setClickedLngLat(e.lngLat);
59
- // @ts-ignore
60
- const onRightClick = (e) => query.setClickedLngLat(e.lngLat);
61
- // @ts-ignore
62
- const onLeftMouseMove = (e) => {
63
- setCoordsLeft(e.lngLat);
53
+ const initialViewState = (0, react_1.useMemo)(() => mp.defaultViewState ?? map_common_1.defaultViewState, [mp.defaultViewState]);
54
+ // Fetch styles for all checked attributes when entering compare mode
55
+ (0, react_1.useEffect)(() => {
56
+ const checkedAttrs = layer.checkedAttributes;
57
+ if (!checkedAttrs || checkedAttrs.size === 0)
58
+ return;
59
+ const selectedIdsSet = new Set(layer.selectedLayers?.map((l) => l.id) || []);
60
+ // Fetch style for each checked attribute
61
+ for (const attrKey of checkedAttrs) {
62
+ const [layerId, styleIndexStr] = attrKey.split("-");
63
+ if (!layerId || !styleIndexStr) {
64
+ continue;
65
+ }
66
+ const styleIndex = parseInt(styleIndexStr, 10);
67
+ // Only fetch for currently selected layers
68
+ if (!selectedIdsSet.has(layerId)) {
69
+ continue;
70
+ }
71
+ // Find the layer
72
+ const baseLayer = layer.selectedLayers?.find(l => l.id === layerId);
73
+ if (!baseLayer)
74
+ continue;
75
+ // Check if style data is already loaded for this styleIndex
76
+ const styleData = baseLayer.data?.styles?.[styleIndex];
77
+ const hasColors = styleData?.colors;
78
+ // If style doesn't have colors loaded, fetch it without affecting main map
79
+ if (!hasColors) {
80
+ layer.fetchStyleForComparison(layerId, styleIndex);
81
+ }
82
+ }
83
+ }, [layer.checkedAttributes, layer.selectedLayers, layer.isCompareMode]);
84
+ /* --------------------------------------------------
85
+ * Panes (ALWAYS GeoserverLayer[])
86
+ * Uses checkedAttributes (format: "layerId-styleIndex") to create panes
87
+ * -------------------------------------------------- */
88
+ const panes = (0, react_1.useMemo)(() => {
89
+ // Use checkedAttributes if available, otherwise fallback to compareList or selectedLayers
90
+ const checkedAttrs = layer.checkedAttributes;
91
+ // If we have checked attributes, use them
92
+ if (checkedAttrs && checkedAttrs.size > 0) {
93
+ // Only use selected layers for comparison (not all layers)
94
+ const selectedIdsSet = new Set(layer.selectedLayers?.map((l) => l.id) || []);
95
+ // Build lookup from selected layers only
96
+ const byId = new Map();
97
+ for (const l of layer.selectedLayers || []) {
98
+ byId.set(l.id, l);
99
+ }
100
+ const result = [];
101
+ // Parse each checked attribute: "layerId-styleIndex"
102
+ for (const attrKey of checkedAttrs) {
103
+ const [layerId, styleIndexStr] = attrKey.split("-");
104
+ if (!layerId || !styleIndexStr) {
105
+ continue;
106
+ }
107
+ const styleIndex = parseInt(styleIndexStr, 10);
108
+ // Only include attributes from currently selected layers
109
+ if (!selectedIdsSet.has(layerId)) {
110
+ continue;
111
+ }
112
+ const baseLayer = byId.get(layerId);
113
+ if (baseLayer) {
114
+ // Check if style data exists for this styleIndex
115
+ const styleData = baseLayer.data?.styles?.[styleIndex];
116
+ // Create a copy of the layer with the specific style applied
117
+ // Use the latest layer data which should have the style loaded after updateLayerStyle
118
+ const layerWithStyle = {
119
+ ...baseLayer,
120
+ id: `${baseLayer.id}-style-${styleIndex}`, // Unique ID for this pane
121
+ data: {
122
+ ...baseLayer.data,
123
+ styleIndex: styleIndex,
124
+ // Ensure we're using the style data for this index
125
+ styles: baseLayer.data?.styles ? [...baseLayer.data.styles] : undefined,
126
+ },
127
+ };
128
+ result.push(layerWithStyle);
129
+ }
130
+ }
131
+ return result;
132
+ }
133
+ // Fallback to compareList or selectedLayers (original behavior)
134
+ if (!layer.selectedLayers || layer.selectedLayers.length === 0) {
135
+ return [];
136
+ }
137
+ const ids = layer.compareList && layer.compareList.length > 0
138
+ ? layer.compareList
139
+ : layer.selectedLayers.map((l) => l.id);
140
+ // build lookup
141
+ const byId = new Map();
142
+ for (const l of layer.selectedLayers) {
143
+ byId.set(l.id, l);
144
+ }
145
+ const result = [];
146
+ for (const id of ids) {
147
+ const found = byId.get(id);
148
+ if (found) {
149
+ result.push(found);
150
+ }
151
+ }
152
+ return result;
153
+ }, [layer.checkedAttributes, layer.compareList, layer.selectedLayers, layer.all]);
154
+ /* --------------------------------------------------
155
+ * Hover per pane
156
+ * -------------------------------------------------- */
157
+ const [coordsByPane, setCoordsByPane] = (0, react_1.useState)({});
158
+ const onMouseMove = (paneId) => (e) => {
159
+ if (!e.lngLat)
160
+ return;
161
+ setCoordsByPane((prev) => ({
162
+ ...prev,
163
+ [paneId]: e.lngLat,
164
+ }));
64
165
  hover.onHover(e);
65
166
  };
66
- // @ts-ignore
67
- const onRightMouseMove = (e) => {
68
- setCoordsRight(e.lngLat);
69
- hover.onHover(e);
167
+ const onClick = (e) => {
168
+ if (e.lngLat) {
169
+ query.setClickedLngLat(e.lngLat);
170
+ }
70
171
  };
71
- const compareList = layer?.compareList || [];
72
- const selectedLayers = layer?.selectedLayers || [];
73
- const [leftCompareId, rightCompareId] = (0, react_1.useMemo)(() => {
74
- if (compareList && compareList.length >= 2) {
75
- // most recent two (assumes newest at index 0)
76
- return [compareList[0], compareList[1]];
172
+ /* --------------------------------------------------
173
+ * Layout math
174
+ * -------------------------------------------------- */
175
+ const layout = (0, react_1.useMemo)(() => {
176
+ const count = panes.length;
177
+ if (count === 1)
178
+ return { cols: 1, rows: 1 };
179
+ if (count === 2)
180
+ return { cols: 2, rows: 1 };
181
+ if (count === 3)
182
+ return { cols: 2, rows: 2 };
183
+ return { cols: 2, rows: Math.ceil(count / 2) };
184
+ }, [panes.length]);
185
+ /* --------------------------------------------------
186
+ * Map renderer (pane is NEVER undefined)
187
+ * -------------------------------------------------- */
188
+ const renderMap = (pane) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(maplibre_1.default, { id: `map-${pane.id}`, initialViewState: initialViewState, style: { position: "absolute", inset: 0 }, mapStyle: layer.mapStyle, onClick: onClick, onMouseMove: onMouseMove(pane.id), children: [(0, jsx_runtime_1.jsx)(NavControl, { position: "top-right", showZoom: true, showCompass: true }), (0, jsx_runtime_1.jsx)(layers_1.MapLayer, { layer: pane }), (0, jsx_runtime_1.jsx)(popup_1.default, { coordinates: coordsByPane[pane.id] })] }), (0, jsx_runtime_1.jsx)(MapLayerCard_1.default, { layer: pane })] }));
189
+ /* --------------------------------------------------
190
+ * Pane rendering — 1–4 panes (grid layout)
191
+ * 2: [1 | 2] 3: 1 3 / 2 3 (3 full height right) 4: 1 3 / 2 4 (column-first)
192
+ * -------------------------------------------------- */
193
+ const renderPanes = () => {
194
+ const count = panes.length;
195
+ if (count === 3 && panes[0] && panes[1] && panes[2]) {
196
+ return [
197
+ (0, jsx_runtime_1.jsx)("div", { style: { gridColumn: 1, gridRow: 1, position: "relative" }, children: renderMap(panes[0]) }, panes[0].id),
198
+ (0, jsx_runtime_1.jsx)("div", { style: { gridColumn: 1, gridRow: 2, position: "relative" }, children: renderMap(panes[1]) }, panes[1].id),
199
+ (0, jsx_runtime_1.jsx)("div", { style: {
200
+ gridColumn: 2,
201
+ gridRow: "1 / -1",
202
+ position: "relative",
203
+ }, children: renderMap(panes[2]) }, panes[2].id),
204
+ ];
77
205
  }
78
- // fallback: take first two selectedLayers' ids (if any)
79
- const ids = selectedLayers.map((l) => l.id || null).filter(Boolean);
80
- return [ids[0] || null, ids[1] || null];
81
- }, [compareList, selectedLayers]);
82
- // Filter the full selectedLayers list to get the layer objects for each side.
83
- const leftLayersToRender = (0, react_1.useMemo)(() => {
84
- if (!leftCompareId)
85
- return [];
86
- return selectedLayers.filter((l) => l.id === leftCompareId);
87
- }, [selectedLayers, leftCompareId]);
88
- const rightLayersToRender = (0, react_1.useMemo)(() => {
89
- if (!rightCompareId)
206
+ return panes.map((pane) => ((0, jsx_runtime_1.jsx)("div", { style: { position: "relative" }, children: renderMap(pane) }, pane.id)));
207
+ };
208
+ /* --------------------------------------------------
209
+ * Layout mode: grid (1–4 panes) vs horizontal scroll (5+ panes)
210
+ * 5+ panes: first screen = 2×2 column-first (1 3 / 2 4); next screen(s) by chunk size.
211
+ * -------------------------------------------------- */
212
+ const useHorizontalScroll = panes.length > 4;
213
+ const PANES_PER_SCREEN = 4;
214
+ const paneChunks = (0, react_1.useMemo)(() => {
215
+ if (panes.length <= 4)
90
216
  return [];
91
- return selectedLayers.filter((l) => l.id === rightCompareId);
92
- }, [selectedLayers, rightCompareId]);
93
- return ((0, jsx_runtime_1.jsxs)("div", { style: {
94
- display: "grid",
95
- gridTemplateColumns: "1fr 1fr",
96
- width: "100%",
97
- height: "100vh", // fixed viewport height
98
- overflow: "hidden",
99
- }, children: [layer.selectedFeatures?.length > 0 && (0, jsx_runtime_1.jsx)(infobar_1.default, {}), (0, jsx_runtime_1.jsx)("div", { style: {
100
- width: "100%",
101
- height: "100%",
102
- position: "relative",
103
- minHeight: 0, // <-- critical for grid/flex children
104
- overflow: "hidden",
105
- }, children: (0, jsx_runtime_1.jsxs)(maplibre_1.default, { id: "map-left", cursor: "default", initialViewState: viewState,
106
- // render the map absolutely so it doesn't affect layout size
107
- style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }, mapStyle: layer.mapStyle, onClick: onLeftClick, onMouseMove: onLeftMouseMove, children: [(0, jsx_runtime_1.jsx)(NavControl, { position: "top-right", showZoom: true, showCompass: true }), (0, jsx_runtime_1.jsx)(markers_list_1.default, {}), leftLayersToRender?.[0] && ((0, jsx_runtime_1.jsx)(layers_1.MapLayer, { layer: leftLayersToRender[0], beforeId: undefined })), (0, jsx_runtime_1.jsx)(popup_1.default, { coordinates: coordsLeft }, "popup-left")] }) }), (0, jsx_runtime_1.jsx)("div", { style: {
217
+ const chunks = [];
218
+ chunks.push(panes.slice(0, 4));
219
+ for (let i = 4; i < panes.length; i += PANES_PER_SCREEN) {
220
+ chunks.push(panes.slice(i, i + PANES_PER_SCREEN));
221
+ }
222
+ return chunks;
223
+ }, [panes]);
224
+ /* --------------------------------------------------
225
+ * Render
226
+ * -------------------------------------------------- */
227
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { height: "100vh", overflow: "hidden", position: "relative" }, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => layer.setCompareMode(false), className: "absolute top-4 left-4 z-50 px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg shadow-md text-sm flex items-center gap-2 font-semibold", title: "", children: (0, jsx_runtime_1.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M18 6 6 18" }), (0, jsx_runtime_1.jsx)("path", { d: "m6 6 12 12" })] }) }), layer.selectedFeatures && layer.selectedFeatures.length > 0 && ((0, jsx_runtime_1.jsx)(infobar_1.default, {})), useHorizontalScroll ? ((0, jsx_runtime_1.jsx)("div", { style: {
228
+ display: "flex",
229
+ flexDirection: "row",
230
+ overflowX: "auto",
231
+ overflowY: "hidden",
232
+ height: "100vh",
108
233
  width: "100%",
109
- height: "100%",
110
- position: "relative",
111
- minHeight: 0, // <-- critical
112
- overflow: "hidden",
113
- }, children: (0, jsx_runtime_1.jsxs)(maplibre_1.default, { id: "map-right", cursor: "default", initialViewState: viewState, style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }, mapStyle: layer.mapStyle, onClick: onRightClick, onMouseMove: onRightMouseMove, children: [(0, jsx_runtime_1.jsx)(NavControl, { position: "top-right", showZoom: true, showCompass: true }), (0, jsx_runtime_1.jsx)(markers_list_1.default, {}), rightLayersToRender?.[0] && ((0, jsx_runtime_1.jsx)(layers_1.MapLayer, { layer: rightLayersToRender[0], beforeId: undefined })), (0, jsx_runtime_1.jsx)(popup_1.default, { coordinates: coordsRight }, "popup-right")] }) })] }));
234
+ }, children: paneChunks.map((chunk, chunkIndex) => {
235
+ const len = chunk.length;
236
+ const isFirstChunk = chunkIndex === 0;
237
+ const chunkWidthVw = len === 1 || len === 2 ? 50 : 100;
238
+ const gridStyle = {
239
+ flex: `0 0 ${chunkWidthVw}vw`,
240
+ minWidth: `${chunkWidthVw}vw`,
241
+ height: "100%",
242
+ display: "grid",
243
+ gridTemplateColumns: len === 1 || len === 2 ? "1fr" : "1fr 1fr",
244
+ gridTemplateRows: len === 2 ? "1fr 1fr" : len === 3 || len === 4 ? "1fr 1fr" : "1fr",
245
+ ...(len === 4 && isFirstChunk ? { gridAutoFlow: "column" } : {}),
246
+ };
247
+ const getPlacement = (paneIndex) => {
248
+ if (len === 1) {
249
+ return { gridColumn: 1, gridRow: "1 / -1" };
250
+ }
251
+ if (len === 2) {
252
+ return { gridColumn: 1, gridRow: paneIndex + 1 };
253
+ }
254
+ if (len === 3) {
255
+ if (paneIndex === 0)
256
+ return { gridColumn: 1, gridRow: 1 };
257
+ if (paneIndex === 1)
258
+ return { gridColumn: 1, gridRow: 2 };
259
+ return { gridColumn: 2, gridRow: "1 / -1" };
260
+ }
261
+ if (len === 4)
262
+ return {};
263
+ return {};
264
+ };
265
+ return ((0, jsx_runtime_1.jsx)("div", { style: gridStyle, children: chunk.map((pane, paneIndex) => ((0, jsx_runtime_1.jsx)("div", { style: {
266
+ position: "relative",
267
+ minHeight: 0,
268
+ ...getPlacement(paneIndex),
269
+ }, children: renderMap(pane) }, pane.id))) }, chunkIndex));
270
+ }) })) : ((0, jsx_runtime_1.jsx)("div", { style: {
271
+ display: "grid",
272
+ gridTemplateColumns: `repeat(${layout.cols}, 1fr)`,
273
+ gridTemplateRows: `repeat(${layout.rows}, ${100 / layout.rows}vh)`,
274
+ height: "100vh",
275
+ ...(panes.length === 4 ? { gridAutoFlow: "column" } : {}),
276
+ }, children: renderPanes() }))] }));
114
277
  }
@@ -0,0 +1,2 @@
1
+ export default function CompareSidebar(): import("react/jsx-runtime").JSX.Element | null;
2
+ //# sourceMappingURL=compare-sidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/map/compare-sidebar.tsx"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,UAAU,cAAc,mDAuJrC"}
@@ -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 = CompareSidebar;
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 core_1 = require("../core");
11
+ function CompareSidebar() {
12
+ const { layer } = (0, use_layers_1.default)();
13
+ const [isOpen, setIsOpen] = (0, react_1.useState)(false);
14
+ const compareList = layer?.compareList || [];
15
+ const handleRemoveFromComparison = (id) => {
16
+ layer.setCompareLayer(id, false);
17
+ };
18
+ const handleClearAll = () => {
19
+ compareList.forEach((id) => {
20
+ layer.setCompareLayer(id, false);
21
+ });
22
+ };
23
+ const toggleOpen = () => setIsOpen(!isOpen);
24
+ // Show button if there are any layers in comparison OR if sidebar is open
25
+ if (compareList.length === 0 && !isOpen) {
26
+ return null;
27
+ }
28
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: !isOpen ? ((0, jsx_runtime_1.jsxs)("button", { onClick: toggleOpen, type: "button", className: "absolute left-4 bg-white rounded-lg shadow-lg flex items-center gap-2 font-medium hover:bg-gray-50 transition-colors border border-gray-200 px-4 py-3", style: { top: '60px', zIndex: 60 }, children: [(0, jsx_runtime_1.jsxs)("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", className: "text-green-600", children: [(0, jsx_runtime_1.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "2", x2: "12", y2: "22" }), (0, jsx_runtime_1.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" })] }), (0, jsx_runtime_1.jsx)("span", { children: "Compare" }), (0, jsx_runtime_1.jsx)("span", { className: "bg-green-100 text-green-700 px-2 py-0.5 rounded text-sm font-semibold", children: compareList.length })] })) : ((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: toggleOpen }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col h-full", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-between p-4 border-b", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", className: "text-green-600", children: [(0, jsx_runtime_1.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "2", x2: "12", y2: "22" }), (0, jsx_runtime_1.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" })] }), (0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold text-gray-800", children: "Map Comparison" })] }) }), (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-3 p-4", children: compareList.length > 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-sm text-gray-600", 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 flex-col gap-2", 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
+ }) })] })) : ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-gray-400 mb-4", children: (0, jsx_runtime_1.jsxs)("svg", { width: "64", height: "64", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "2", x2: "12", y2: "22" }), (0, jsx_runtime_1.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" })] }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-semibold text-gray-700 mb-2", children: "No layers selected for comparison" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-500 max-w-sm", children: "Select layers from the layers tab and use the \"Compare\" option to add them here for comparison." })] })) }) })] })] })) }));
34
+ }
@@ -0,0 +1,2 @@
1
+ export default function MapCompare(): import("react/jsx-runtime").JSX.Element | null;
2
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/components/map/compare.tsx"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,UAAU,UAAU,mDAoHjC"}
@@ -0,0 +1,42 @@
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 = MapCompare;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = require("react");
9
+ const maplibre_1 = require("react-map-gl/maplibre");
10
+ const use_layers_1 = __importDefault(require("../../hooks/use-layers"));
11
+ const core_1 = require("../core");
12
+ function MapCompare() {
13
+ const { layer } = (0, use_layers_1.default)();
14
+ const { mapl } = (0, maplibre_1.useMap)();
15
+ const [isComparing, setIsComparing] = (0, react_1.useState)(false);
16
+ const compareList = layer?.compareList || [];
17
+ // Don't show if less than 2 layers in comparison
18
+ if (compareList.length < 2) {
19
+ return null;
20
+ }
21
+ const handleToggleCompare = () => {
22
+ setIsComparing(!isComparing);
23
+ // If starting comparison, sync view states
24
+ if (!isComparing && mapl) {
25
+ const mapInstance = Object.values(mapl).pop();
26
+ if (mapInstance) {
27
+ // Store current view state to sync later
28
+ const currentView = mapInstance.getCenter();
29
+ // You can add logic here to sync multiple map instances if needed
30
+ }
31
+ }
32
+ };
33
+ const handleExitCompare = () => {
34
+ setIsComparing(false);
35
+ };
36
+ return ((0, jsx_runtime_1.jsx)("div", { className: "absolute top-4 right-4 z-50 flex flex-col gap-2", style: { marginTop: '60px' }, children: !isComparing ? ((0, jsx_runtime_1.jsxs)("button", { onClick: handleToggleCompare, className: "px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-lg shadow-lg flex items-center gap-2 font-medium cursor-pointer", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "2", x2: "12", y2: "22" }), (0, jsx_runtime_1.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" })] }), (0, jsx_runtime_1.jsx)("span", { children: "Compare Maps" }), (0, jsx_runtime_1.jsx)("span", { className: "bg-white/20 px-2 py-0.5 rounded text-sm", children: compareList.length })] })) : ((0, jsx_runtime_1.jsxs)("div", { className: "bg-white rounded-lg shadow-lg p-3 border border-gray-200", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "16", height: "16", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", className: "text-green-600", children: [(0, jsx_runtime_1.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "2", x2: "12", y2: "22" }), (0, jsx_runtime_1.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" })] }), (0, jsx_runtime_1.jsxs)("span", { className: "font-semibold text-gray-800", children: ["Comparing ", compareList.length, " layers"] })] }), (0, jsx_runtime_1.jsx)(core_1.Button, { onClick: handleExitCompare, className: "text-gray-500 hover:text-gray-700 p-1", children: (0, jsx_runtime_1.jsx)("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-600 mb-2", children: "Use the DualMap view for side-by-side comparison" }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-1 max-h-40 overflow-y-auto", children: compareList.map((id) => {
37
+ const layerItem = layer.all.find((l) => l.id === id);
38
+ if (!layerItem)
39
+ return null;
40
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 px-2 py-1 bg-gray-50 rounded text-sm", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-2 h-2 rounded-full bg-green-500" }), (0, jsx_runtime_1.jsx)("span", { className: "text-gray-700 truncate", children: layerItem.title || id })] }, id));
41
+ }) })] })) }));
42
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/map/index.tsx"],"names":[],"mappings":"AAaA,MAAM,CAAC,OAAO,UAAU,GAAG,4CA2C1B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/map/index.tsx"],"names":[],"mappings":"AAcA,MAAM,CAAC,OAAO,UAAU,GAAG,4CAuD1B"}
@@ -41,6 +41,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
41
41
  const map_common_1 = require("@metastringfoundation/map-common");
42
42
  const react_1 = require("react");
43
43
  const maplibre_1 = __importStar(require("react-map-gl/maplibre"));
44
+ const map_draw_1 = require("@metastringfoundation/map-draw");
44
45
  const use_layers_1 = __importDefault(require("../../hooks/use-layers"));
45
46
  const infobar_1 = __importDefault(require("../infobar"));
46
47
  const sidebar_1 = __importDefault(require("../sidebar"));
@@ -50,6 +51,13 @@ const popup_1 = __importDefault(require("./popup"));
50
51
  const NavControl = maplibre_1.NavigationControl;
51
52
  function Map() {
52
53
  const { mp, layer, hover, query } = (0, use_layers_1.default)();
54
+ const [mapInstance, setMapInstance] = (0, react_1.useState)(null);
55
+ (0, map_draw_1.useMapDraw)({
56
+ map: mapInstance,
57
+ layer: {
58
+ selectedLayers: layer.selectedLayers,
59
+ },
60
+ });
53
61
  const [coordinates, setCoordinates] = (0, react_1.useState)();
54
62
  const viewState = (0, react_1.useMemo)(() => mp.defaultViewState || map_common_1.defaultViewState, [mp.defaultViewState]);
55
63
  // @ts-ignore
@@ -59,7 +67,12 @@ function Map() {
59
67
  setCoordinates(event.lngLat);
60
68
  hover.onHover(event);
61
69
  };
62
- return ((0, jsx_runtime_1.jsxs)("div", { className: "w-full h-screen overflow-hidden", children: [mp.loadToC && (0, jsx_runtime_1.jsx)(sidebar_1.default, {}), layer.selectedFeatures?.length > 0 && (0, jsx_runtime_1.jsx)(infobar_1.default, {}), (0, jsx_runtime_1.jsxs)(maplibre_1.default, { id: "mapl", cursor: "default", initialViewState: viewState, style: { width: "100%", height: "100%" }, mapStyle: layer.mapStyle, onClick: onMapClick, onMouseMove: handleOnMouseMove, children: [(0, jsx_runtime_1.jsx)(NavControl, { position: "top-right", showZoom: true, showCompass: true }), (0, jsx_runtime_1.jsx)(markers_list_1.default, {}), layer.selectedLayers.map((_l, index) => {
70
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "w-full h-screen overflow-hidden", children: [mp.loadToC && (0, jsx_runtime_1.jsx)(sidebar_1.default, {}), layer.selectedFeatures?.length > 0 && (0, jsx_runtime_1.jsx)(infobar_1.default, {}), (0, jsx_runtime_1.jsxs)(maplibre_1.default, { id: "mapl", cursor: "default", initialViewState: viewState, style: { width: "100%", height: "100%" }, mapStyle: layer.mapStyle, onClick: onMapClick, onMouseMove: handleOnMouseMove,
71
+ //@ts-ignore
72
+ onLoad: (e) => {
73
+ // ✅ e.target is the real MapLibre Map
74
+ setMapInstance(e.target);
75
+ }, children: [(0, jsx_runtime_1.jsx)(NavControl, { position: "top-right", showZoom: true, showCompass: true }), (0, jsx_runtime_1.jsx)(markers_list_1.default, {}), layer.selectedLayers.map((_l, index) => {
63
76
  const beforeId = index > 0 ? layer.selectedIds[index - 1] : undefined;
64
77
  return (0, jsx_runtime_1.jsx)(layers_1.MapLayer, { layer: _l, beforeId: beforeId }, _l.id);
65
78
  }), (0, jsx_runtime_1.jsx)(popup_1.default, { coordinates: coordinates }, "popup")] })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/map/layers/grid/index.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAC,MAAM,CAAA;CACjB,2CAoCA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/map/layers/grid/index.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAC,MAAM,CAAA;CACjB,2CAgDA"}