@macrostrat/map-interface 1.0.12 → 1.2.0

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 (134) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/container.72611900.js +134 -0
  3. package/dist/cjs/container.72611900.js.map +1 -0
  4. package/dist/cjs/context-panel.8c4b009c.js +88 -0
  5. package/dist/cjs/context-panel.8c4b009c.js.map +1 -0
  6. package/dist/cjs/controls.7ce3e95c.js +79 -0
  7. package/dist/cjs/controls.7ce3e95c.js.map +1 -0
  8. package/dist/cjs/dev.7499151f.js +33 -0
  9. package/dist/cjs/dev.7499151f.js.map +1 -0
  10. package/dist/cjs/expansion-panel.08532cee.js +134 -0
  11. package/dist/cjs/expansion-panel.08532cee.js.map +1 -0
  12. package/dist/cjs/hash-string.62e84f08.js +67 -0
  13. package/dist/cjs/hash-string.62e84f08.js.map +1 -0
  14. package/dist/cjs/header.58c5c012.js +104 -0
  15. package/dist/cjs/header.58c5c012.js.map +1 -0
  16. package/dist/cjs/headers.20eae5f7.js +29 -0
  17. package/dist/cjs/headers.20eae5f7.js.map +1 -0
  18. package/dist/cjs/helpers.0f72ddaf.js +190 -0
  19. package/dist/cjs/helpers.0f72ddaf.js.map +1 -0
  20. package/dist/cjs/index.js +51 -0
  21. package/dist/cjs/index.js.map +1 -0
  22. package/dist/cjs/location-info.92e70042.js +119 -0
  23. package/dist/cjs/location-info.92e70042.js.map +1 -0
  24. package/dist/cjs/location-panel.c95f5e96.js +66 -0
  25. package/dist/cjs/location-panel.c95f5e96.js.map +1 -0
  26. package/dist/cjs/main.module.02c4de16.css +86 -0
  27. package/dist/cjs/main.module.02c4de16.css.map +1 -0
  28. package/dist/cjs/main.module.3f2b7c9f.js +38 -0
  29. package/dist/cjs/main.module.3f2b7c9f.js.map +1 -0
  30. package/dist/cjs/main.module.4ecbaaa5.js +62 -0
  31. package/dist/cjs/main.module.4ecbaaa5.js.map +1 -0
  32. package/dist/cjs/main.module.62939ea7.js +167 -0
  33. package/dist/cjs/main.module.62939ea7.js.map +1 -0
  34. package/dist/cjs/main.module.92978d8b.css +52 -0
  35. package/dist/cjs/main.module.92978d8b.css.map +1 -0
  36. package/dist/cjs/main.module.becc2fe7.css +92 -0
  37. package/dist/cjs/main.module.becc2fe7.css.map +1 -0
  38. package/dist/cjs/main.module.ccec47df.js +50 -0
  39. package/dist/cjs/main.module.ccec47df.js.map +1 -0
  40. package/dist/cjs/main.module.e958948e.js +26 -0
  41. package/dist/cjs/main.module.e958948e.js.map +1 -0
  42. package/dist/{index.css → cjs/main.module.f085a193.css} +9 -397
  43. package/dist/cjs/main.module.f085a193.css.map +1 -0
  44. package/dist/cjs/main.module.ff1b1aca.css +179 -0
  45. package/dist/cjs/main.module.ff1b1aca.css.map +1 -0
  46. package/dist/cjs/map-page.190b6723.js +182 -0
  47. package/dist/cjs/map-page.190b6723.js.map +1 -0
  48. package/dist/cjs/map-view.93363b41.js +167 -0
  49. package/dist/cjs/map-view.93363b41.js.map +1 -0
  50. package/dist/cjs/terrain.90f76b4e.js +59 -0
  51. package/dist/cjs/terrain.90f76b4e.js.map +1 -0
  52. package/dist/cjs/tile-extent.06a4b2ed.js +51 -0
  53. package/dist/cjs/tile-extent.06a4b2ed.js.map +1 -0
  54. package/dist/cjs/utils.09cef979.js +36 -0
  55. package/dist/cjs/utils.09cef979.js.map +1 -0
  56. package/dist/cjs/utils.26f02633.js +46 -0
  57. package/dist/cjs/utils.26f02633.js.map +1 -0
  58. package/dist/cjs/vector-tile-features.456f887b.js +268 -0
  59. package/dist/cjs/vector-tile-features.456f887b.js.map +1 -0
  60. package/dist/cjs/xray.a23f8660.js +89 -0
  61. package/dist/cjs/xray.a23f8660.js.map +1 -0
  62. package/dist/esm/container.16bde261.js +126 -0
  63. package/dist/esm/container.16bde261.js.map +1 -0
  64. package/dist/esm/context-panel.c288c5cd.js +81 -0
  65. package/dist/esm/context-panel.c288c5cd.js.map +1 -0
  66. package/dist/esm/controls.f757ce16.js +74 -0
  67. package/dist/esm/controls.f757ce16.js.map +1 -0
  68. package/dist/esm/dev.ccb6e774.js +13 -0
  69. package/dist/esm/dev.ccb6e774.js.map +1 -0
  70. package/dist/esm/expansion-panel.feff0e62.js +123 -0
  71. package/dist/esm/expansion-panel.feff0e62.js.map +1 -0
  72. package/dist/esm/hash-string.836601b2.js +61 -0
  73. package/dist/esm/hash-string.836601b2.js.map +1 -0
  74. package/dist/esm/header.0f535ab1.js +99 -0
  75. package/dist/esm/header.0f535ab1.js.map +1 -0
  76. package/dist/esm/headers.b25ff414.js +24 -0
  77. package/dist/esm/headers.b25ff414.js.map +1 -0
  78. package/dist/esm/helpers.fb1d7227.js +176 -0
  79. package/dist/esm/helpers.fb1d7227.js.map +1 -0
  80. package/dist/{types.d.ts → esm/index.d.ts} +104 -52
  81. package/dist/esm/index.d.ts.map +1 -0
  82. package/dist/esm/index.js +25 -0
  83. package/dist/esm/index.js.map +1 -0
  84. package/dist/esm/location-info.5543bb05.js +89 -0
  85. package/dist/esm/location-info.5543bb05.js.map +1 -0
  86. package/dist/esm/location-panel.0b1f4ed2.js +58 -0
  87. package/dist/esm/location-panel.0b1f4ed2.js.map +1 -0
  88. package/dist/esm/main.module.5eb366de.js +52 -0
  89. package/dist/esm/main.module.5eb366de.js.map +1 -0
  90. package/dist/esm/main.module.67a908da.js +40 -0
  91. package/dist/esm/main.module.67a908da.js.map +1 -0
  92. package/dist/esm/main.module.89579666.js +64 -0
  93. package/dist/esm/main.module.89579666.js.map +1 -0
  94. package/dist/esm/main.module.9c57cc95.js +28 -0
  95. package/dist/esm/main.module.9c57cc95.js.map +1 -0
  96. package/dist/esm/main.module.f70e002b.js +169 -0
  97. package/dist/esm/main.module.f70e002b.js.map +1 -0
  98. package/dist/esm/map-page.b953c404.js +175 -0
  99. package/dist/esm/map-page.b953c404.js.map +1 -0
  100. package/dist/esm/map-view.a3fe6257.js +161 -0
  101. package/dist/esm/map-view.a3fe6257.js.map +1 -0
  102. package/dist/esm/terrain.f65cf7c5.js +54 -0
  103. package/dist/esm/terrain.f65cf7c5.js.map +1 -0
  104. package/dist/esm/tile-extent.ca526996.js +46 -0
  105. package/dist/esm/tile-extent.ca526996.js.map +1 -0
  106. package/dist/esm/utils.122d1f2d.js +28 -0
  107. package/dist/esm/utils.122d1f2d.js.map +1 -0
  108. package/dist/esm/utils.d40349f0.js +40 -0
  109. package/dist/esm/utils.d40349f0.js.map +1 -0
  110. package/dist/esm/vector-tile-features.e1a24df0.js +258 -0
  111. package/dist/esm/vector-tile-features.e1a24df0.js.map +1 -0
  112. package/dist/esm/xray.c0663c25.js +83 -0
  113. package/dist/esm/xray.c0663c25.js.map +1 -0
  114. package/package.json +19 -36
  115. package/src/container.ts +29 -21
  116. package/src/context-panel/index.ts +7 -8
  117. package/src/context-panel/main.module.sass +1 -1
  118. package/src/dev/main.module.sass +16 -0
  119. package/src/dev/map-page.ts +32 -11
  120. package/src/dev/vector-tile-features.ts +44 -13
  121. package/src/helpers.ts +15 -13
  122. package/src/location-panel/header.ts +27 -8
  123. package/src/location-panel/index.ts +4 -2
  124. package/src/location-panel/main.module.sass +7 -0
  125. package/src/main.module.sass +4 -1
  126. package/src/map-view/index.ts +28 -32
  127. package/dist/index.cjs.css +0 -961
  128. package/dist/index.cjs.css.map +0 -1
  129. package/dist/index.cjs.js +0 -1965
  130. package/dist/index.cjs.js.map +0 -1
  131. package/dist/index.css.map +0 -1
  132. package/dist/index.js +0 -1956
  133. package/dist/index.js.map +0 -1
  134. package/dist/types.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["packages/map-interface/src/dev/vector-tile-features.ts"],"sourcesContent":["import { Spinner, Switch, Button, Intent } from \"@blueprintjs/core\";\nimport { useMapRef, useMapStatus } from \"@macrostrat/mapbox-react\";\nimport mapboxgl from \"mapbox-gl\";\nimport hyper from \"@macrostrat/hyper\";\nimport styles from \"./main.module.sass\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { JSONView } from \"@macrostrat/ui-components\";\nimport { group } from \"d3-array\";\nimport { ExpansionPanel } from \"../expansion-panel\";\n\nconst h = hyper.styled(styles);\n\nexport function FeatureProperties({ data, ...rest }) {\n // Instead of managing hover state with CSS, we use a state variable,\n // so that the button re-renders when the state changes\n const [showControls, setShowControls] = useState(false);\n const onMouseEnter = useCallback(() => setShowControls(true), []);\n const onMouseLeave = useCallback(() => setShowControls(false), []);\n\n return h(\"div.feature-properties\", { onMouseEnter, onMouseLeave }, [\n h.if(showControls)(\"div.controls\", h(CopyJSONButton, { data })),\n h(JSONView, {\n data,\n hideRoot: true,\n ...rest,\n }),\n ]);\n}\n\nexport function FeatureRecord({ feature }) {\n const props = feature.properties;\n return h(\"div.feature-record\", [\n h.if(Object.keys(props).length > 0)(FeatureProperties, { data: props }),\n ]);\n}\n\nfunction CopyJSONButton({ data }) {\n const [copied, setCopied] = useState(false);\n return h(Button, {\n icon: copied ? \"tick\" : \"clipboard\",\n intent: copied ? Intent.SUCCESS : Intent.NONE,\n minimal: true,\n small: true,\n onClick() {\n navigator.clipboard.writeText(JSON.stringify(data, null, 2));\n setCopied(true);\n },\n });\n}\n\n/** This component wraps queryRenderedFeatures to get features at a given location */\nexport function FeatureSelectionHandler({\n selectedLocation,\n setFeatures,\n radius = 2,\n}: {\n selectedLocation: mapboxgl.LngLat;\n setFeatures: (features: mapboxgl.MapboxGeoJSONFeature[]) => void;\n radius?: number;\n}) {\n const mapRef = useMapRef();\n const isLoading = useMapStatus((s) => s.isLoading);\n const isInitialized = useMapStatus((s) => s.isInitialized);\n const prevLocation = useRef(null);\n const prevFeatures = useRef([]);\n\n useEffect(() => {\n const map = mapRef?.current;\n if (map == null) return;\n if (selectedLocation == null) {\n setFeatures(null);\n return;\n }\n\n if (!isInitialized) return;\n\n const hasPreviouslyLoadedFeatures = prevFeatures.current.length > 0;\n\n const locationMemo = JSON.stringify(selectedLocation);\n if (locationMemo == prevLocation.current && hasPreviouslyLoadedFeatures)\n return;\n\n prevLocation.current = locationMemo;\n\n // Don't update if the location hasn't changed\n //if (selectedLocation == prevLocation) return;\n\n const r = radius;\n const pt = map.project(selectedLocation);\n\n const bbox: [mapboxgl.PointLike, mapboxgl.PointLike] = [\n [pt.x - r, pt.y - r],\n [pt.x + r, pt.y + r],\n ];\n const features = map.queryRenderedFeatures(bbox);\n prevFeatures.current = features ?? [];\n setFeatures(features);\n }, [isInitialized, selectedLocation, isLoading]);\n\n return null;\n}\n\nfunction FeatureHeader({ feature }) {\n return h(\"div.feature-header\", [\n h(\"h3\", [\n h(KeyValue, { label: \"Source\", value: feature.source }),\n h(KeyValue, { label: \"Source layer\", value: feature.sourceLayer }),\n ]),\n ]);\n}\n\nfunction KeyValue({ label, value }) {\n return h(\"span.key-value\", [h(\"span.key\", label), h(\"code.value\", value)]);\n}\n\nfunction LoadingAwareFeatureSet({ features, sourceID }) {\n const map = useMapRef();\n if (map?.current == null) return null;\n const [isLoaded, setIsLoaded] = useState(false);\n\n const sourceFeatures = features.filter((d) => d.source == \"burwell\");\n\n useEffect(() => {\n if (sourceFeatures.length > 0) {\n setIsLoaded(true);\n return;\n }\n\n const isLoaded = map.current.isSourceLoaded(sourceID);\n setIsLoaded(isLoaded);\n if (!isLoaded) {\n map.current.once(\"sourcedata\", (e) => {\n if (e.sourceId == sourceID) {\n setIsLoaded(true);\n }\n });\n }\n }, [map.current, sourceID, sourceFeatures.length]);\n\n if (!isLoaded) return h(Spinner);\n return h(Features, { features: sourceFeatures });\n}\n\nexport function TileInfo({ feature, showExtent, setShowExtent }) {\n if (feature == null) return null;\n const size = feature._vectorTileFeature._pbf.length;\n return h(\"div.tile-info\", [\n h(\"h3\", \"Tile\"),\n h(\"div.tile-index\", [\n h(KeyValue, { label: \"x\", value: feature._x }),\n h(KeyValue, { label: \"y\", value: feature._y }),\n h(KeyValue, { label: \"z\", value: feature._z }),\n ]),\n h(\"div.spacer\"),\n h(KeyValue, { label: \"Size\", value: formatSize(size) }),\n h(Switch, {\n label: \"Show extent\",\n alignIndicator: \"right\",\n checked: showExtent,\n onChange() {\n setShowExtent(!showExtent);\n },\n }),\n ]);\n}\n\nfunction formatSize(size: number) {\n if (size > 1000000)\n return h(UnitNumber, { value: size / 1000000, unit: \"Mb\" });\n if (size > 1000) return h(UnitNumber, { value: size / 1000, unit: \"Kb\" });\n return `${size} bytes`;\n}\n\nfunction UnitNumber({ value, unit, precision = 1 }) {\n return h(\"span.unit-number\", [\n h(\"span.number\", value.toFixed(precision)),\n h(\"span.unit\", unit),\n ]);\n}\n\nexport function FeaturePanel({ features, focusedSource = null }) {\n if (features == null) return null;\n\n let focusedSourcePanel = null;\n let filteredFeatures = features;\n let title = \"Features\";\n\n if (focusedSource != null) {\n title = \"Basemap features\";\n focusedSourcePanel = h(\n ExpansionPanel,\n {\n title: \"Macrostrat features\",\n className: \"macrostrat-features\",\n expanded: true,\n },\n [\n h(LoadingAwareFeatureSet, {\n features,\n sourceID: focusedSource,\n }),\n ]\n );\n filteredFeatures = features.filter((d) => d.source != focusedSource);\n }\n\n return h(\"div.feature-panel\", [\n focusedSourcePanel,\n h(\n ExpansionPanel,\n { title, className: \"basemap-features\", expanded: focusedSource == null },\n [\n h(FeatureGroups, {\n features: filteredFeatures,\n }),\n ]\n ),\n ]);\n}\n\nfunction FeatureGroups({ features }) {\n /** Group features by source and sourceLayer */\n if (features == null) return null;\n\n const groups = group(features, (d) => `${d.source} - ${d.sourceLayer}`);\n\n return h(\n \"div.feature-groups\",\n Array.from(groups).map(([key, features]) => {\n return h(\"div.feature-group\", [\n h(FeatureHeader, { feature: features[0] }),\n h(Features, { features }),\n ]);\n })\n );\n}\n\nexport function Features({ features }) {\n return h(\n \"div.features\",\n features.map((feature, i) => h(FeatureRecord, { key: i, feature }))\n );\n}\n"],"names":[],"version":3,"file":"vector-tile-features.e1a24df0.js.map"}
@@ -0,0 +1,83 @@
1
+ import {getMapboxStyle as $gWtFU$getMapboxStyle, mergeStyles as $gWtFU$mergeStyles} from "@macrostrat/mapbox-utils";
2
+ import {asChromaColor as $gWtFU$asChromaColor, toRGBAString as $gWtFU$toRGBAString} from "@macrostrat/color-utils";
3
+
4
+
5
+
6
+ async function $64ee2eed3ed5ffbc$export$eff5fb2e10d05b1d(baseStyle, params = null) {
7
+ const { inDarkMode: inDarkMode = false, color: color = "rgb(74, 242, 161)", mapboxToken: mapboxToken, xRaySources: xRaySources } = params;
8
+ const style = await (0, $gWtFU$getMapboxStyle)(baseStyle, {
9
+ access_token: mapboxToken
10
+ });
11
+ const sources = xRaySources ?? Object.keys(style.sources);
12
+ let layers = [];
13
+ for (let layer of style.layers){
14
+ if (!sources.includes(layer.source)) {
15
+ layers.push(layer);
16
+ continue;
17
+ }
18
+ let newLayer = $64ee2eed3ed5ffbc$var$transformMapboxLayer(layer, color, inDarkMode);
19
+ if (newLayer != null) layers.push(newLayer);
20
+ }
21
+ return {
22
+ ...style,
23
+ layers: layers
24
+ };
25
+ }
26
+ function $64ee2eed3ed5ffbc$var$transformMapboxLayer(layer, color, inDarkMode) {
27
+ const c = (0, $gWtFU$asChromaColor)(color);
28
+ const xRayColor = (opacity = 1, darken = 0)=>{
29
+ if (!inDarkMode) return (0, $gWtFU$toRGBAString)(c.darken(2 - darken).alpha(opacity));
30
+ return (0, $gWtFU$toRGBAString)(c.alpha(opacity).darken(darken));
31
+ };
32
+ if (layer.type == "background") return null;
33
+ let newLayer = {
34
+ ...layer
35
+ };
36
+ console.log(xRayColor(0.5));
37
+ if (layer.type == "fill") newLayer.paint = {
38
+ "fill-color": xRayColor(0.1),
39
+ "fill-outline-color": xRayColor(0.5)
40
+ };
41
+ else if (layer.type == "line") newLayer.paint = {
42
+ "line-color": xRayColor(0.5, 0),
43
+ "line-width": 1.5
44
+ };
45
+ else if (layer.type == "symbol") newLayer.paint = {
46
+ "text-color": xRayColor(1, -0.5),
47
+ "text-halo-color": "#000"
48
+ };
49
+ else if (layer.type == "circle") newLayer.paint = {
50
+ "circle-color": xRayColor(0.5, 0),
51
+ "circle-stroke-color": xRayColor(0.5, 1),
52
+ "circle-radius": 2
53
+ };
54
+ return newLayer;
55
+ }
56
+ async function $64ee2eed3ed5ffbc$export$e739dc8dfc0db9a6(baseStyle, overlayStyle = null, params = {}) {
57
+ const { mapboxToken: mapboxToken, xRay: xRay = false, xRaySources: _xRaySources, ...rest } = params;
58
+ let xRaySources = _xRaySources;
59
+ let style = await (0, $gWtFU$getMapboxStyle)(baseStyle, {
60
+ access_token: mapboxToken
61
+ });
62
+ if (overlayStyle != null) {
63
+ const overlay = await (0, $gWtFU$getMapboxStyle)(overlayStyle, {
64
+ access_token: mapboxToken
65
+ });
66
+ style = (0, $gWtFU$mergeStyles)(style, overlay);
67
+ xRaySources ??= Object.keys(overlay.sources);
68
+ }
69
+ if (xRay) {
70
+ // If we haven't specified sources, then we'll use all of them
71
+ xRaySources ??= Object.keys(style.sources);
72
+ style = await $64ee2eed3ed5ffbc$export$eff5fb2e10d05b1d(style, {
73
+ ...rest,
74
+ mapboxToken: mapboxToken,
75
+ xRaySources: xRaySources
76
+ });
77
+ }
78
+ return style;
79
+ }
80
+
81
+
82
+ export {$64ee2eed3ed5ffbc$export$eff5fb2e10d05b1d as buildXRayStyle, $64ee2eed3ed5ffbc$export$e739dc8dfc0db9a6 as buildInspectorStyle};
83
+ //# sourceMappingURL=xray.c0663c25.js.map
@@ -0,0 +1 @@
1
+ {"mappings":";;;;;AAWO,eAAe,0CACpB,SAA0B,EAC1B,SAAsB,IAAI;IAE1B,MAAM,cACJ,aAAa,cACb,QAAQ,kCACR,WAAW,eACX,WAAW,EACZ,GAAG;IACJ,MAAM,QAAQ,MAAM,CAAA,GAAA,qBAAa,EAAE,WAAW;QAAE,cAAc;IAAY;IAC1E,MAAM,UAAU,eAAe,OAAO,IAAI,CAAC,MAAM,OAAO;IAExD,IAAI,SAAS,EAAE;IACf,KAAK,IAAI,SAAS,MAAM,MAAM,CAAE;QAC9B,IAAI,CAAC,QAAQ,QAAQ,CAAC,MAAM,MAAM,GAAG;YACnC,OAAO,IAAI,CAAC;YACZ;QACF;QACA,IAAI,WAAW,2CAAqB,OAAO,OAAO;QAClD,IAAI,YAAY,MACd,OAAO,IAAI,CAAC;IAEhB;IAEA,OAAO;QACL,GAAG,KAAK;gBACR;IACF;AACF;AAEA,SAAS,2CAAqB,KAAK,EAAE,KAAK,EAAE,UAAU;IACpD,MAAM,IAAI,CAAA,GAAA,oBAAY,EAAE;IACxB,MAAM,YAAY,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;QACxC,IAAI,CAAC,YACH,OAAO,CAAA,GAAA,mBAAW,EAAE,EAAE,MAAM,CAAC,IAAI,QAAQ,KAAK,CAAC;QAEjD,OAAO,CAAA,GAAA,mBAAW,EAAE,EAAE,KAAK,CAAC,SAAS,MAAM,CAAC;IAC9C;IAEA,IAAI,MAAM,IAAI,IAAI,cAChB,OAAO;IAGT,IAAI,WAAW;QAAE,GAAG,KAAK;IAAC;IAE1B,QAAQ,GAAG,CAAC,UAAU;IAEtB,IAAI,MAAM,IAAI,IAAI,QAChB,SAAS,KAAK,GAAG;QACf,cAAc,UAAU;QACxB,sBAAsB,UAAU;IAClC;SACK,IAAI,MAAM,IAAI,IAAI,QACvB,SAAS,KAAK,GAAG;QACf,cAAc,UAAU,KAAK;QAC7B,cAAc;IAChB;SACK,IAAI,MAAM,IAAI,IAAI,UACvB,SAAS,KAAK,GAAG;QACf,cAAc,UAAU,GAAG;QAC3B,mBAAmB;IACrB;SACK,IAAI,MAAM,IAAI,IAAI,UACvB,SAAS,KAAK,GAAG;QACf,gBAAgB,UAAU,KAAK;QAC/B,uBAAuB,UAAU,KAAK;QACtC,iBAAiB;IACnB;IAGF,OAAO;AACT;AAMO,eAAe,0CACpB,SAAkC,EAClC,eAA+C,IAAI,EACnD,SAAgC,CAAC,CAAC;IAElC,MAAM,eACJ,WAAW,QACX,OAAO,OACP,aAAa,YAAY,EACzB,GAAG,MACJ,GAAG;IACJ,IAAI,cAAc;IAClB,IAAI,QAAQ,MAAM,CAAA,GAAA,qBAAa,EAAE,WAAW;QAC1C,cAAc;IAChB;IAEA,IAAI,gBAAgB,MAAM;QACxB,MAAM,UAAU,MAAM,CAAA,GAAA,qBAAa,EAAE,cAAc;YACjD,cAAc;QAChB;QACA,QAAQ,CAAA,GAAA,kBAAU,EAAE,OAAO;QAC3B,gBAAgB,OAAO,IAAI,CAAC,QAAQ,OAAO;IAC7C;IAEA,IAAI,MAAM;QACR,8DAA8D;QAC9D,gBAAgB,OAAO,IAAI,CAAC,MAAM,OAAO;QAEzC,QAAQ,MAAM,0CAAe,OAAO;YAAE,GAAG,IAAI;yBAAE;yBAAa;QAAY;IAC1E;IACA,OAAO;AACT","sources":["packages/map-interface/src/dev/xray.ts"],"sourcesContent":["import { getMapboxStyle, mergeStyles } from \"@macrostrat/mapbox-utils\";\nimport { asChromaColor, toRGBAString } from \"@macrostrat/color-utils\";\nimport mapboxgl from \"mapbox-gl\";\n\ninterface XRayOptions {\n color?: string;\n inDarkMode?: boolean;\n mapboxToken?: string;\n xRaySources?: string[];\n}\n\nexport async function buildXRayStyle(\n baseStyle: string | object,\n params: XRayOptions = null\n) {\n const {\n inDarkMode = false,\n color = \"rgb(74, 242, 161)\",\n mapboxToken,\n xRaySources,\n } = params;\n const style = await getMapboxStyle(baseStyle, { access_token: mapboxToken });\n const sources = xRaySources ?? Object.keys(style.sources);\n\n let layers = [];\n for (let layer of style.layers) {\n if (!sources.includes(layer.source)) {\n layers.push(layer);\n continue;\n }\n let newLayer = transformMapboxLayer(layer, color, inDarkMode);\n if (newLayer != null) {\n layers.push(newLayer);\n }\n }\n\n return {\n ...style,\n layers,\n };\n}\n\nfunction transformMapboxLayer(layer, color, inDarkMode) {\n const c = asChromaColor(color);\n const xRayColor = (opacity = 1, darken = 0) => {\n if (!inDarkMode) {\n return toRGBAString(c.darken(2 - darken).alpha(opacity));\n }\n return toRGBAString(c.alpha(opacity).darken(darken));\n };\n\n if (layer.type == \"background\") {\n return null;\n }\n\n let newLayer = { ...layer };\n\n console.log(xRayColor(0.5));\n\n if (layer.type == \"fill\") {\n newLayer.paint = {\n \"fill-color\": xRayColor(0.1),\n \"fill-outline-color\": xRayColor(0.5),\n };\n } else if (layer.type == \"line\") {\n newLayer.paint = {\n \"line-color\": xRayColor(0.5, 0),\n \"line-width\": 1.5,\n };\n } else if (layer.type == \"symbol\") {\n newLayer.paint = {\n \"text-color\": xRayColor(1, -0.5),\n \"text-halo-color\": \"#000\",\n };\n } else if (layer.type == \"circle\") {\n newLayer.paint = {\n \"circle-color\": xRayColor(0.5, 0),\n \"circle-stroke-color\": xRayColor(0.5, 1),\n \"circle-radius\": 2,\n };\n }\n\n return newLayer;\n}\n\ntype InspectorStyleOptions = XRayOptions & {\n xRay?: boolean;\n};\n\nexport async function buildInspectorStyle(\n baseStyle: mapboxgl.Style | string,\n overlayStyle: mapboxgl.Style | string | null = null,\n params: InspectorStyleOptions = {}\n) {\n const {\n mapboxToken,\n xRay = false,\n xRaySources: _xRaySources,\n ...rest\n } = params;\n let xRaySources = _xRaySources;\n let style = await getMapboxStyle(baseStyle, {\n access_token: mapboxToken,\n });\n\n if (overlayStyle != null) {\n const overlay = await getMapboxStyle(overlayStyle, {\n access_token: mapboxToken,\n });\n style = mergeStyles(style, overlay);\n xRaySources ??= Object.keys(overlay.sources);\n }\n\n if (xRay) {\n // If we haven't specified sources, then we'll use all of them\n xRaySources ??= Object.keys(style.sources);\n\n style = await buildXRayStyle(style, { ...rest, mapboxToken, xRaySources });\n }\n return style;\n}\n"],"names":[],"version":3,"file":"xray.c0663c25.js.map"}
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@macrostrat/map-interface",
3
- "version": "1.0.12",
3
+ "version": "1.2.0",
4
4
  "description": "Map interface for Macrostrat",
5
- "main": "dist/index.cjs.js",
6
- "module": "dist/index.js",
7
- "types": "dist/types.d.ts",
5
+ "main": "dist/cjs/index.js",
6
+ "module": "dist/esm/index.js",
8
7
  "source": "src/index.ts",
9
- "style": "dist/index.css",
8
+ "types": "dist/esm/index.d.ts",
10
9
  "dependencies": {
11
- "@macrostrat/color-utils": "^1.0.0",
12
- "@macrostrat/hyper": "^3.0.0",
13
- "@macrostrat/mapbox-react": "^2.2.3",
14
- "@macrostrat/mapbox-utils": "^1.3.2",
15
- "@macrostrat/ui-components": "^4.0.4",
10
+ "@blueprintjs/core": "^5.0.0",
11
+ "@macrostrat/color-utils": "^1.0.1",
12
+ "@macrostrat/hyper": "^3.0.6",
13
+ "@macrostrat/mapbox-react": "^2.5.0",
14
+ "@macrostrat/mapbox-utils": "^1.4.0",
15
+ "@macrostrat/ui-components": "^4.1.0",
16
16
  "@mapbox/tilebelt": "^2.0.0",
17
17
  "classnames": "^2.5.1",
18
18
  "d3-array": "^3.2.4",
@@ -23,47 +23,30 @@
23
23
  "underscore": "^1.13.6",
24
24
  "use-resize-observer": "^9.1.0"
25
25
  },
26
+ "devDependencies": {
27
+ "parcel": "^2.13.3",
28
+ "ui-box": "^5.4.1"
29
+ },
26
30
  "peerDependencies": {
27
- "@blueprintjs/core": "^5.0.0",
28
31
  "react": "^16.8.6||^17.0.0||^18.0.0",
29
32
  "react-dom": "^16.8.6||^17.0.0||^18.0.0"
30
33
  },
31
34
  "scripts": {
32
35
  "dev": "parcel watch",
33
- "build": "parcel build"
36
+ "build": "rm -rf dist && parcel build"
34
37
  },
35
38
  "exports": {
36
39
  ".": {
37
- "typescript": "./src",
38
- "import": {
39
- "types": "./dist/types.d.ts",
40
- "default": "./dist/index.js"
41
- },
42
- "require": {
43
- "types": "./dist/types.d.ts",
44
- "default": "./dist/index.cjs.js"
45
- },
46
- "types:": "./dist/types.d.ts",
47
- "style": "./dist/index.css"
48
- },
49
- "./dist/": {
50
- "import": "./dist/",
51
- "require": "./dist/"
52
- },
53
- "./dist/index.css": {
54
- "import": "./dist/index.css",
55
- "require": "./dist/index.css"
40
+ "source": "./src/index.ts",
41
+ "import": "./dist/esm/index.js",
42
+ "require": "./dist/cjs/index.js",
43
+ "types": "./dist/esm/index.d.ts"
56
44
  }
57
45
  },
58
46
  "files": [
59
47
  "dist",
60
48
  "src"
61
49
  ],
62
- "devDependencies": {
63
- "parcel": "^2.12.0",
64
- "postcss": "^8.0.0",
65
- "postcss-modules": "^4.3.0"
66
- },
67
50
  "repository": {
68
51
  "type": "git",
69
52
  "url": "https://github.com/UW-Macrostrat/web-components.git",
package/src/container.ts CHANGED
@@ -35,6 +35,26 @@ export enum DetailPanelStyle {
35
35
  export const MapAreaContainer = (props) =>
36
36
  h(MapProviders, h(_MapAreaContainer, props));
37
37
 
38
+ interface MapAreaContainerProps {
39
+ navbar: AnyElement;
40
+ children?: AnyElement;
41
+ mapControls?: AnyElement;
42
+ contextPanel?: AnyElement;
43
+ contextStack?: AnyElement;
44
+ mainPanel?: AnyElement;
45
+ detailPanel?: AnyElement;
46
+ bottomPanel?: AnyElement;
47
+ className?: string;
48
+ detailPanelOpen?: boolean;
49
+ contextPanelOpen?: boolean;
50
+ contextStackProps?: ContextStackProps;
51
+ detailStackProps?: HTMLDivProps;
52
+ detailPanelStyle: DetailPanelStyle;
53
+ fitViewport?: boolean;
54
+ showPanelOutlines?: boolean;
55
+ preventMapInteraction?: boolean;
56
+ }
57
+
38
58
  function _MapAreaContainer({
39
59
  children,
40
60
  className,
@@ -53,24 +73,7 @@ function _MapAreaContainer({
53
73
  showPanelOutlines = false,
54
74
  preventMapInteraction = false,
55
75
  ...rest
56
- }: {
57
- navbar: AnyElement;
58
- children?: AnyElement;
59
- mapControls?: AnyElement;
60
- contextPanel?: AnyElement;
61
- contextStack?: AnyElement;
62
- mainPanel?: AnyElement;
63
- detailPanel?: AnyElement;
64
- bottomPanel?: AnyElement;
65
- className?: string;
66
- detailPanelOpen?: boolean;
67
- contextPanelOpen?: boolean;
68
- contextStackProps?: ContextStackProps;
69
- detailStackProps?: HTMLDivProps;
70
- detailPanelStyle: DetailPanelStyle;
71
- fitViewport?: boolean;
72
- showPanelOutlines?: boolean;
73
- }) {
76
+ }: MapAreaContainerProps) {
74
77
  const _detailPanelOpen = detailPanelOpen ?? detailPanel != null;
75
78
  const contextPanelTrans = useTransition(contextPanelOpen, 800);
76
79
  const detailPanelTrans = useTransition(_detailPanelOpen, 800);
@@ -114,12 +117,17 @@ function _MapAreaContainer({
114
117
  ]
115
118
  );
116
119
 
120
+ let contextStack = null;
121
+ if (navbar != null && contextPanel != null) {
122
+ contextStack = h(ContextStack, { navbar, ...contextStackProps }, [
123
+ h.if(contextPanelTrans.shouldMount)([contextPanel]),
124
+ ]);
125
+ }
126
+
117
127
  return h(MapStyledContainer, { className: mainUIClassNames }, [
118
128
  h("div.main-row", [
119
129
  h("div.map-ui", { ...rest }, [
120
- h(ContextStack, { navbar, ...contextStackProps }, [
121
- h.if(contextPanelTrans.shouldMount)([contextPanel]),
122
- ]),
130
+ contextStack,
123
131
  //h(MapView),
124
132
  children ?? mainPanel,
125
133
  h.if(detailPanelStyle == DetailPanelStyle.FLOATING)([detailStackExt]),
@@ -13,7 +13,7 @@ export function LoadingButton({
13
13
  isLoading = false,
14
14
  onClick,
15
15
  active = false,
16
- large = false,
16
+ large = true,
17
17
  icon = "menu",
18
18
  style,
19
19
  }) {
@@ -29,22 +29,21 @@ export function LoadingButton({
29
29
  }
30
30
 
31
31
  export function MapLoadingButton(props) {
32
- const { isLoading } = useMapStatus();
33
- const mapIsLoading = useMemo(() => isLoading, [isLoading]);
34
- return h(LoadingButton, { ...props, isLoading: mapIsLoading });
32
+ const isLoading = useMapStatus((s) => s.isLoading);
33
+ return h(LoadingButton, { ...props, isLoading });
35
34
  }
36
35
 
37
- type AnyChildren = React.ReactNode | React.ReactFragment;
36
+ type AnyChildren = React.ReactNode;
38
37
 
39
38
  export interface FloatingNavbarProps {
40
39
  className?: string;
41
- children: AnyChildren;
40
+ children?: AnyChildren;
42
41
  headerElement?: AnyChildren;
43
42
  title?: AnyChildren;
44
43
  statusElement?: AnyChildren;
45
44
  rightElement?: AnyChildren;
46
- height: number | string;
47
- width: number | string;
45
+ height?: number | string;
46
+ width?: number | string;
48
47
  style?: object;
49
48
  }
50
49
 
@@ -11,7 +11,7 @@
11
11
  .searchbar
12
12
  width: 100%
13
13
  background-color: var(--panel-background-color)
14
- border-radius: 5px
14
+ border-radius: var(--map-panel-border-radius, 5px)
15
15
  padding: var(--navbar-padding, 10px)
16
16
  display: flex
17
17
  flex-direction: row
@@ -5,22 +5,35 @@
5
5
  .key-value
6
6
  display: inline-block
7
7
  margin-right: 1em
8
+
8
9
  .key
9
10
  font-weight: bold
10
11
  font-size: 0.9em
12
+
11
13
  &:after
12
14
  content: ': '
15
+
13
16
  .value
14
17
  font-size: 0.9em
15
18
 
16
19
  .feature-properties
17
20
  position: relative
21
+
18
22
  &:before
19
23
  content: "–"
20
24
  position: absolute
21
25
  top: 4px
22
26
  left: 0
23
27
 
28
+ .controls
29
+ display: flex
30
+ flex-direction: row
31
+ align-items: flex-end
32
+ position: absolute
33
+ top: 0
34
+ right: 0
35
+ gap: 0.5em
36
+
24
37
  .feature-header h3
25
38
  margin-bottom: 0
26
39
  margin-top: 0.5em
@@ -28,6 +41,7 @@
28
41
  .feature-group
29
42
  border-bottom: 1px solid var(--panel-rule-inner)
30
43
  margin-bottom: 0.5em
44
+
31
45
  &:last-child
32
46
  border-bottom: none
33
47
 
@@ -35,11 +49,13 @@
35
49
  display: flex
36
50
  flex-direction: row
37
51
  align-items: baseline
52
+
38
53
  h3
39
54
  margin-right: 0.5em
40
55
 
41
56
  .opacity-slider
42
57
  margin: 0 1em 0.5em
58
+
43
59
  :global
44
60
  .bp5-slider-handle .bp5-slider-label
45
61
  background-color: var(--secondary-color)
@@ -4,7 +4,7 @@ import hyper from "@macrostrat/hyper";
4
4
  import { Spacer, useDarkMode, useStoredState } from "@macrostrat/ui-components";
5
5
  import mapboxgl from "mapbox-gl";
6
6
  import { useCallback, useState, useEffect } from "react";
7
- import { buildInspectorStyle, buildXRayStyle } from "./xray";
7
+ import { buildInspectorStyle } from "./xray";
8
8
  import { MapAreaContainer, PanelCard } from "../container";
9
9
  import { FloatingNavbar, MapLoadingButton } from "../context-panel";
10
10
  import { MapMarker } from "../helpers";
@@ -21,24 +21,27 @@ import { MapPosition } from "@macrostrat/mapbox-utils";
21
21
 
22
22
  export const h = hyper.styled(styles);
23
23
 
24
- export function MapInspector({
24
+ export function MapInspectorV2({
25
25
  title = "Map inspector",
26
26
  headerElement = null,
27
27
  transformRequest = null,
28
28
  mapPosition = null,
29
29
  mapboxToken = null,
30
30
  overlayStyle = null,
31
- children,
31
+ controls = null,
32
+ children = null,
32
33
  style,
33
34
  bounds = null,
34
35
  focusedSource = null,
35
36
  focusedSourceTitle = null,
36
37
  fitViewport = true,
38
+ styleType = "macrostrat",
37
39
  }: {
38
- headerElement?: React.ReactElement;
40
+ headerElement?: React.ReactNode;
39
41
  transformRequest?: mapboxgl.TransformRequestFunction;
40
42
  title?: string;
41
43
  style?: mapboxgl.Style | string;
44
+ controls?: React.ReactNode;
42
45
  children?: React.ReactNode;
43
46
  mapboxToken?: string;
44
47
  overlayStyle?: mapboxgl.Style | string;
@@ -48,6 +51,7 @@ export function MapInspector({
48
51
  mapPosition?: MapPosition;
49
52
  bounds?: [number, number, number, number];
50
53
  fitViewport?: boolean;
54
+ styleType?: "standard" | "macrostrat";
51
55
  }) {
52
56
  /* We apply a custom style to the panel container when we are interacting
53
57
  with the search bar, so that we can block map interactions until search
@@ -63,9 +67,15 @@ export function MapInspector({
63
67
  mapboxgl.accessToken = mapboxToken;
64
68
  }
65
69
 
66
- style ??= isEnabled
67
- ? "mapbox://styles/mapbox/dark-v10"
68
- : "mapbox://styles/mapbox/light-v10";
70
+ if (styleType == "macrostrat") {
71
+ style ??= isEnabled
72
+ ? "mapbox://styles/jczaplewski/cl5uoqzzq003614o6url9ou9z?optimize=true"
73
+ : "mapbox://styles/jczaplewski/clatdbkw4002q14lov8zx0bm0?optimize=true";
74
+ } else {
75
+ style ??= isEnabled
76
+ ? "mapbox://styles/mapbox/dark-v10"
77
+ : "mapbox://styles/mapbox/light-v10";
78
+ }
69
79
 
70
80
  const [isOpen, setOpen] = useState(false);
71
81
 
@@ -75,9 +85,7 @@ export function MapInspector({
75
85
  });
76
86
  const { showTileExtent, xRay } = state;
77
87
 
78
- const [actualStyle, setActualStyle] = useState(style);
79
-
80
- console.log("actualStyle", actualStyle);
88
+ const [actualStyle, setActualStyle] = useState(null);
81
89
 
82
90
  useEffect(() => {
83
91
  buildInspectorStyle(style, overlayStyle, {
@@ -141,6 +149,7 @@ export function MapInspector({
141
149
  title,
142
150
  }),
143
151
  contextPanel: h(PanelCard, [
152
+ controls,
144
153
  h(Switch, {
145
154
  checked: xRay,
146
155
  label: "X-ray mode",
@@ -148,7 +157,6 @@ export function MapInspector({
148
157
  setState({ ...state, xRay: !xRay });
149
158
  },
150
159
  }),
151
- children,
152
160
  ]),
153
161
  detailPanel: detailElement,
154
162
  contextPanelOpen: isOpen,
@@ -174,10 +182,23 @@ export function MapInspector({
174
182
  setPosition: onSelectPosition,
175
183
  }),
176
184
  h(TileExtentLayer, { tile, color: isEnabled ? "white" : "black" }),
185
+ children,
177
186
  ]
178
187
  )
179
188
  );
180
189
  }
181
190
 
191
+ function MapInspector(props) {
192
+ const { children, controls, ...rest } = props;
193
+ /** Compatibility wrapper for MapInspectorV2 */
194
+ // React warning about this legacy usage
195
+ console.warn("MapInspector is deprecated. Use MapInspectorV2 instead");
196
+
197
+ return h(MapInspectorV2, {
198
+ ...rest,
199
+ controls: [children, controls],
200
+ });
201
+ }
202
+
182
203
  // Legacy export
183
204
  export const DevMapPage = MapInspector;
@@ -1,17 +1,24 @@
1
- import { Spinner, Switch } from "@blueprintjs/core";
1
+ import { Spinner, Switch, Button, Intent } from "@blueprintjs/core";
2
2
  import { useMapRef, useMapStatus } from "@macrostrat/mapbox-react";
3
3
  import mapboxgl from "mapbox-gl";
4
4
  import hyper from "@macrostrat/hyper";
5
5
  import styles from "./main.module.sass";
6
- import { useEffect, useState } from "react";
7
- import { JSONView, usePrevious } from "@macrostrat/ui-components";
6
+ import { useCallback, useEffect, useRef, useState } from "react";
7
+ import { JSONView } from "@macrostrat/ui-components";
8
8
  import { group } from "d3-array";
9
9
  import { ExpansionPanel } from "../expansion-panel";
10
10
 
11
11
  const h = hyper.styled(styles);
12
12
 
13
13
  export function FeatureProperties({ data, ...rest }) {
14
- return h("div.feature-properties", [
14
+ // Instead of managing hover state with CSS, we use a state variable,
15
+ // so that the button re-renders when the state changes
16
+ const [showControls, setShowControls] = useState(false);
17
+ const onMouseEnter = useCallback(() => setShowControls(true), []);
18
+ const onMouseLeave = useCallback(() => setShowControls(false), []);
19
+
20
+ return h("div.feature-properties", { onMouseEnter, onMouseLeave }, [
21
+ h.if(showControls)("div.controls", h(CopyJSONButton, { data })),
15
22
  h(JSONView, {
16
23
  data,
17
24
  hideRoot: true,
@@ -27,6 +34,21 @@ export function FeatureRecord({ feature }) {
27
34
  ]);
28
35
  }
29
36
 
37
+ function CopyJSONButton({ data }) {
38
+ const [copied, setCopied] = useState(false);
39
+ return h(Button, {
40
+ icon: copied ? "tick" : "clipboard",
41
+ intent: copied ? Intent.SUCCESS : Intent.NONE,
42
+ minimal: true,
43
+ small: true,
44
+ onClick() {
45
+ navigator.clipboard.writeText(JSON.stringify(data, null, 2));
46
+ setCopied(true);
47
+ },
48
+ });
49
+ }
50
+
51
+ /** This component wraps queryRenderedFeatures to get features at a given location */
30
52
  export function FeatureSelectionHandler({
31
53
  selectedLocation,
32
54
  setFeatures,
@@ -37,8 +59,10 @@ export function FeatureSelectionHandler({
37
59
  radius?: number;
38
60
  }) {
39
61
  const mapRef = useMapRef();
40
- const { isLoading } = useMapStatus();
41
- const prevLocation = usePrevious(selectedLocation);
62
+ const isLoading = useMapStatus((s) => s.isLoading);
63
+ const isInitialized = useMapStatus((s) => s.isInitialized);
64
+ const prevLocation = useRef(null);
65
+ const prevFeatures = useRef([]);
42
66
 
43
67
  useEffect(() => {
44
68
  const map = mapRef?.current;
@@ -48,8 +72,18 @@ export function FeatureSelectionHandler({
48
72
  return;
49
73
  }
50
74
 
75
+ if (!isInitialized) return;
76
+
77
+ const hasPreviouslyLoadedFeatures = prevFeatures.current.length > 0;
78
+
79
+ const locationMemo = JSON.stringify(selectedLocation);
80
+ if (locationMemo == prevLocation.current && hasPreviouslyLoadedFeatures)
81
+ return;
82
+
83
+ prevLocation.current = locationMemo;
84
+
51
85
  // Don't update if the location hasn't changed
52
- if (selectedLocation == prevLocation) return;
86
+ //if (selectedLocation == prevLocation) return;
53
87
 
54
88
  const r = radius;
55
89
  const pt = map.project(selectedLocation);
@@ -59,8 +93,9 @@ export function FeatureSelectionHandler({
59
93
  [pt.x + r, pt.y + r],
60
94
  ];
61
95
  const features = map.queryRenderedFeatures(bbox);
96
+ prevFeatures.current = features ?? [];
62
97
  setFeatures(features);
63
- }, [mapRef.current, prevLocation?.current, selectedLocation, isLoading]);
98
+ }, [isInitialized, selectedLocation, isLoading]);
64
99
 
65
100
  return null;
66
101
  }
@@ -143,11 +178,7 @@ function UnitNumber({ value, unit, precision = 1 }) {
143
178
  ]);
144
179
  }
145
180
 
146
- export function FeaturePanel({
147
- features,
148
- focusedSource = null,
149
- focusedSourceTitle = null,
150
- }) {
181
+ export function FeaturePanel({ features, focusedSource = null }) {
151
182
  if (features == null) return null;
152
183
 
153
184
  let focusedSourcePanel = null;