@macrostrat/column-views 1.0.3 → 2.0.1

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 (258) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/esm/{data-area.daff8da0.js → column-views.062d164a.js} +1 -1
  3. package/dist/esm/{data-area.daff8da0.js.map → column-views.062d164a.js.map} +1 -1
  4. package/dist/esm/{data-provider.1506eb64.js → column-views.07521ce6.js} +1 -1
  5. package/dist/esm/column-views.07521ce6.js.map +1 -0
  6. package/dist/esm/column-views.134b2e2a.js +9 -0
  7. package/dist/esm/column-views.134b2e2a.js.map +1 -0
  8. package/dist/esm/{selection-popover.module.0a701258.css → column-views.16cc7a58.css} +11 -8
  9. package/dist/esm/column-views.16cc7a58.css.map +1 -0
  10. package/dist/esm/column-views.1c589cc4.js +141 -0
  11. package/dist/esm/column-views.1c589cc4.js.map +1 -0
  12. package/dist/esm/column-views.1ece326b.js +420 -0
  13. package/dist/esm/column-views.1ece326b.js.map +1 -0
  14. package/dist/esm/column-views.1edc7300.js +40 -0
  15. package/dist/esm/column-views.1edc7300.js.map +1 -0
  16. package/dist/esm/column-views.240ef158.css +159 -0
  17. package/dist/esm/column-views.240ef158.css.map +1 -0
  18. package/dist/esm/column-views.25471fe0.css +111 -0
  19. package/dist/esm/column-views.25471fe0.css.map +1 -0
  20. package/dist/esm/column-views.28ee5f43.js +288 -0
  21. package/dist/esm/column-views.28ee5f43.js.map +1 -0
  22. package/dist/esm/column-views.30646469.js +118 -0
  23. package/dist/esm/column-views.30646469.js.map +1 -0
  24. package/dist/esm/column-views.338a7a83.css +134 -0
  25. package/dist/esm/column-views.338a7a83.css.map +1 -0
  26. package/dist/esm/column-views.33dbc778.js +95 -0
  27. package/dist/esm/column-views.33dbc778.js.map +1 -0
  28. package/dist/esm/column-views.343b5aa2.js +98 -0
  29. package/dist/esm/column-views.343b5aa2.js.map +1 -0
  30. package/dist/esm/column-views.34636ec7.js +104 -0
  31. package/dist/esm/column-views.34636ec7.js.map +1 -0
  32. package/dist/esm/column-views.3465c8ad.js +16 -0
  33. package/dist/esm/column-views.3465c8ad.js.map +1 -0
  34. package/dist/esm/column-views.39657bbf.js +55 -0
  35. package/dist/esm/column-views.39657bbf.js.map +1 -0
  36. package/dist/esm/column-views.3b972a9b.css +4 -0
  37. package/dist/esm/{composite.module.69a38fd1.css.map → column-views.3b972a9b.css.map} +1 -1
  38. package/dist/esm/column-views.3bec70d6.js +167 -0
  39. package/dist/esm/column-views.3bec70d6.js.map +1 -0
  40. package/dist/esm/column-views.3de4dc43.js +66 -0
  41. package/dist/esm/column-views.3de4dc43.js.map +1 -0
  42. package/dist/esm/{column.db058031.js → column-views.3f4db8cb.js} +8 -8
  43. package/dist/esm/column-views.3f4db8cb.js.map +1 -0
  44. package/dist/esm/column-views.40c1f361.js +206 -0
  45. package/dist/esm/column-views.40c1f361.js.map +1 -0
  46. package/dist/esm/{composite.module.0638e7ee.js → column-views.40cd59b5.js} +1 -1
  47. package/dist/esm/{composite.module.0638e7ee.js.map → column-views.40cd59b5.js.map} +1 -1
  48. package/dist/esm/column-views.4637f4ce.js +46 -0
  49. package/dist/esm/column-views.4637f4ce.js.map +1 -0
  50. package/dist/esm/column-views.4c4c5bac.js +163 -0
  51. package/dist/esm/column-views.4c4c5bac.js.map +1 -0
  52. package/dist/esm/column-views.4d374a35.js +19 -0
  53. package/dist/esm/column-views.4d374a35.js.map +1 -0
  54. package/dist/esm/column-views.57c4ddf3.js +125 -0
  55. package/dist/esm/column-views.57c4ddf3.js.map +1 -0
  56. package/dist/esm/column-views.58b82432.js +58 -0
  57. package/dist/esm/column-views.58b82432.js.map +1 -0
  58. package/dist/esm/column-views.5b2635fd.js +13 -0
  59. package/dist/esm/column-views.5b2635fd.js.map +1 -0
  60. package/dist/esm/column-views.5c02fee2.js +258 -0
  61. package/dist/esm/column-views.5c02fee2.js.map +1 -0
  62. package/dist/esm/column-views.5cc09c1d.js +152 -0
  63. package/dist/esm/column-views.5cc09c1d.js.map +1 -0
  64. package/dist/esm/{names.f6a4e9a4.js → column-views.650bd9f5.js} +5 -5
  65. package/dist/esm/column-views.650bd9f5.js.map +1 -0
  66. package/dist/esm/column-views.68409161.js +89 -0
  67. package/dist/esm/column-views.68409161.js.map +1 -0
  68. package/dist/esm/column-views.6a954628.js +70 -0
  69. package/dist/esm/column-views.6a954628.js.map +1 -0
  70. package/dist/esm/column-views.6c670c13.css +26 -0
  71. package/dist/esm/column-views.6c670c13.css.map +1 -0
  72. package/dist/esm/column-views.6d6b73b4.js +55 -0
  73. package/dist/esm/column-views.6d6b73b4.js.map +1 -0
  74. package/dist/esm/column-views.86c4b36f.js +222 -0
  75. package/dist/esm/column-views.86c4b36f.js.map +1 -0
  76. package/dist/esm/column-views.88de2cee.js +9 -0
  77. package/dist/esm/column-views.88de2cee.js.map +1 -0
  78. package/dist/esm/{resolvers.b5c82b78.js → column-views.8dd877af.js} +16 -3
  79. package/dist/esm/column-views.8dd877af.js.map +1 -0
  80. package/dist/esm/column-views.8e51206e.js +143 -0
  81. package/dist/esm/column-views.8e51206e.js.map +1 -0
  82. package/dist/esm/{column.module.7f47d25a.js → column-views.94b5cca1.js} +1 -1
  83. package/dist/esm/{column.module.7f47d25a.js.map → column-views.94b5cca1.js.map} +1 -1
  84. package/dist/esm/column-views.9804efda.js +75 -0
  85. package/dist/esm/column-views.9804efda.js.map +1 -0
  86. package/dist/esm/column-views.9bdd477a.js +57 -0
  87. package/dist/esm/column-views.9bdd477a.js.map +1 -0
  88. package/dist/esm/column-views.9ced149e.js +98 -0
  89. package/dist/esm/column-views.9ced149e.js.map +1 -0
  90. package/dist/esm/{column.module.cbb072df.css → column-views.a7be0a4a.css} +1 -1
  91. package/dist/esm/{column.module.cbb072df.css.map → column-views.a7be0a4a.css.map} +1 -1
  92. package/dist/esm/column-views.a98214b2.js +9 -0
  93. package/dist/esm/column-views.a98214b2.js.map +1 -0
  94. package/dist/esm/column-views.aa9fcdba.js +221 -0
  95. package/dist/esm/column-views.aa9fcdba.js.map +1 -0
  96. package/dist/esm/{isotopes-column.7cb5cc45.js → column-views.ac9fb5e1.js} +3 -3
  97. package/dist/esm/{isotopes-column.7cb5cc45.js.map → column-views.ac9fb5e1.js.map} +1 -1
  98. package/dist/esm/column-views.b2e5f1d9.js +11 -0
  99. package/dist/esm/column-views.b2e5f1d9.js.map +1 -0
  100. package/dist/esm/column-views.b775c0a3.js +112 -0
  101. package/dist/esm/column-views.b775c0a3.js.map +1 -0
  102. package/dist/esm/column-views.beb54e95.js +39 -0
  103. package/dist/esm/column-views.beb54e95.js.map +1 -0
  104. package/dist/esm/{core.4db8e452.js → column-views.c58aad3f.js} +15 -16
  105. package/dist/esm/column-views.c58aad3f.js.map +1 -0
  106. package/dist/esm/{carbon-isotopes.3b502a9e.js → column-views.d1ad48eb.js} +4 -4
  107. package/dist/esm/{carbon-isotopes.3b502a9e.js.map → column-views.d1ad48eb.js.map} +1 -1
  108. package/dist/esm/column-views.dc42f5d0.js +48 -0
  109. package/dist/esm/column-views.dc42f5d0.js.map +1 -0
  110. package/dist/esm/column-views.dff52504.js +22 -0
  111. package/dist/esm/column-views.dff52504.js.map +1 -0
  112. package/dist/esm/column-views.e2b9c23c.css +33 -0
  113. package/dist/esm/column-views.e2b9c23c.css.map +1 -0
  114. package/dist/esm/column-views.e40b8bfb.css +14 -0
  115. package/dist/esm/column-views.e40b8bfb.css.map +1 -0
  116. package/dist/esm/column-views.e77b9d6b.js +170 -0
  117. package/dist/esm/column-views.e77b9d6b.js.map +1 -0
  118. package/dist/esm/column-views.ea237aa8.js +52 -0
  119. package/dist/esm/column-views.ea237aa8.js.map +1 -0
  120. package/dist/esm/column-views.edf77621.js +22 -0
  121. package/dist/esm/column-views.edf77621.js.map +1 -0
  122. package/dist/esm/column-views.f1efcc2c.js +9 -0
  123. package/dist/esm/column-views.f1efcc2c.js.map +1 -0
  124. package/dist/esm/column-views.f2e5a72f.js +66 -0
  125. package/dist/esm/column-views.f2e5a72f.js.map +1 -0
  126. package/dist/esm/column-views.f71ec4b4.js +127 -0
  127. package/dist/esm/column-views.f71ec4b4.js.map +1 -0
  128. package/dist/esm/column-views.f9dab157.js +3 -0
  129. package/dist/esm/column-views.f9dab157.js.map +1 -0
  130. package/dist/esm/column-views.fa6f3292.js +215 -0
  131. package/dist/esm/column-views.fa6f3292.js.map +1 -0
  132. package/dist/esm/column-views.fc2b4611.js +9 -0
  133. package/dist/esm/column-views.fc2b4611.js.map +1 -0
  134. package/dist/esm/index.d.ts +797 -130
  135. package/dist/esm/index.d.ts.map +1 -1
  136. package/dist/esm/index.js +13 -9
  137. package/dist/esm/index.js.map +1 -1
  138. package/dist/node/index.js +1 -1
  139. package/dist/node/index.js.map +1 -1
  140. package/package.json +29 -13
  141. package/src/age-axis.module.sass +27 -0
  142. package/src/age-axis.ts +82 -19
  143. package/src/age-model-overlay.module.sass +11 -0
  144. package/src/age-model-overlay.ts +73 -0
  145. package/src/carbon-isotopes/column.ts +4 -2
  146. package/src/carbon-isotopes/core.ts +9 -6
  147. package/src/carbon-isotopes/data-provider.ts +3 -3
  148. package/src/column.module.sass +58 -49
  149. package/src/column.ts +149 -135
  150. package/src/correlation-chart/hash-string.ts +57 -0
  151. package/src/correlation-chart/index.ts +2 -0
  152. package/src/correlation-chart/main.module.sass +122 -0
  153. package/src/correlation-chart/main.ts +305 -0
  154. package/src/correlation-chart/prepare-data.ts +217 -0
  155. package/src/correlation-chart/stories/correlation-chart.stories.ts +192 -0
  156. package/src/correlation-chart/stories/stories.module.sass +18 -0
  157. package/src/correlation-chart/unconformity-line.module.sass +8 -0
  158. package/src/correlation-chart/unconformity-line.ts +25 -0
  159. package/src/data-provider/base.ts +388 -0
  160. package/src/data-provider/column-nav.ts +53 -0
  161. package/src/data-provider/fetch.ts +231 -0
  162. package/src/data-provider/index.ts +4 -0
  163. package/src/data-provider/store.ts +72 -0
  164. package/src/index.ts +5 -3
  165. package/src/maps/_shared/index.ts +2 -0
  166. package/src/maps/_shared/inset-map.stories.ts +20 -0
  167. package/src/maps/_shared/inset-map.ts +87 -0
  168. package/src/maps/_shared/styles.ts +57 -0
  169. package/src/maps/column-correlation/column-correlation-map.stories.ts +96 -0
  170. package/src/maps/column-correlation/core.ts +225 -0
  171. package/src/maps/column-correlation/index.ts +2 -0
  172. package/src/maps/column-correlation/state.ts +192 -0
  173. package/src/maps/column-navigation/index.ts +2 -0
  174. package/src/maps/column-navigation/mapbox/column-navigation-map.stories.ts +102 -0
  175. package/src/maps/column-navigation/mapbox/index.ts +219 -0
  176. package/src/maps/column-navigation/mapbox/keyboard-navigation.ts +119 -0
  177. package/src/maps/column-navigation/mapbox/state.ts +109 -0
  178. package/src/maps/column-navigation/svg/column-navigation-svg-map.stories.ts +46 -0
  179. package/src/{map → maps/column-navigation/svg}/index.ts +18 -6
  180. package/src/{map → maps/column-navigation/svg}/layers.ts +28 -109
  181. package/src/maps/column-navigation/utils/keyboard-navigation.ts +58 -0
  182. package/src/maps/index.ts +3 -0
  183. package/src/prepare-units/composite-scale.ts +353 -0
  184. package/src/prepare-units/helpers.ts +226 -0
  185. package/src/prepare-units/index.ts +177 -0
  186. package/src/prepare-units/utils.ts +98 -0
  187. package/src/section.ts +264 -84
  188. package/src/unit-details/index.ts +2 -215
  189. package/src/unit-details/{index.module.sass → panel.module.sass} +39 -8
  190. package/src/unit-details/panel.ts +523 -0
  191. package/src/{selection-popover.module.sass → unit-details/popover.module.sass} +4 -2
  192. package/src/unit-details/popover.ts +82 -0
  193. package/src/units/boxes.module.sass +16 -0
  194. package/src/units/boxes.ts +243 -90
  195. package/src/units/colors.ts +64 -0
  196. package/src/units/composite.ts +157 -152
  197. package/src/units/index.ts +76 -9
  198. package/src/units/names.ts +8 -4
  199. package/src/units/resolvers.ts +12 -1
  200. package/src/units/selection.ts +115 -101
  201. package/src/units/types.ts +5 -16
  202. package/dist/esm/age-axis.64c509ee.js +0 -41
  203. package/dist/esm/age-axis.64c509ee.js.map +0 -1
  204. package/dist/esm/boxes.13968b76.js +0 -164
  205. package/dist/esm/boxes.13968b76.js.map +0 -1
  206. package/dist/esm/boxes.module.28873d08.css +0 -4
  207. package/dist/esm/boxes.module.28873d08.css.map +0 -1
  208. package/dist/esm/boxes.module.605bdcd6.js +0 -13
  209. package/dist/esm/boxes.module.605bdcd6.js.map +0 -1
  210. package/dist/esm/column.8dd26e1a.js +0 -149
  211. package/dist/esm/column.8dd26e1a.js.map +0 -1
  212. package/dist/esm/column.db058031.js.map +0 -1
  213. package/dist/esm/column.module.039d872c.css +0 -151
  214. package/dist/esm/column.module.039d872c.css.map +0 -1
  215. package/dist/esm/column.module.e632868a.js +0 -19
  216. package/dist/esm/column.module.e632868a.js.map +0 -1
  217. package/dist/esm/composite.608a4ca2.js +0 -153
  218. package/dist/esm/composite.608a4ca2.js.map +0 -1
  219. package/dist/esm/composite.module.69a38fd1.css +0 -4
  220. package/dist/esm/core.4db8e452.js.map +0 -1
  221. package/dist/esm/data-provider.1506eb64.js.map +0 -1
  222. package/dist/esm/helpers.8a03cfc7.js +0 -94
  223. package/dist/esm/helpers.8a03cfc7.js.map +0 -1
  224. package/dist/esm/index.module.0844afd8.css +0 -65
  225. package/dist/esm/index.module.0844afd8.css.map +0 -1
  226. package/dist/esm/index.module.24fe3a2e.js +0 -37
  227. package/dist/esm/index.module.24fe3a2e.js.map +0 -1
  228. package/dist/esm/layers.ad5fd25d.js +0 -231
  229. package/dist/esm/layers.ad5fd25d.js.map +0 -1
  230. package/dist/esm/map.7aa26f17.js +0 -82
  231. package/dist/esm/map.7aa26f17.js.map +0 -1
  232. package/dist/esm/names.f6a4e9a4.js.map +0 -1
  233. package/dist/esm/providers.cd1e652f.js +0 -25
  234. package/dist/esm/providers.cd1e652f.js.map +0 -1
  235. package/dist/esm/resolvers.b5c82b78.js.map +0 -1
  236. package/dist/esm/section.cc1b1100.js +0 -118
  237. package/dist/esm/section.cc1b1100.js.map +0 -1
  238. package/dist/esm/selection-popover.17d1bd55.js +0 -60
  239. package/dist/esm/selection-popover.17d1bd55.js.map +0 -1
  240. package/dist/esm/selection-popover.module.0a701258.css.map +0 -1
  241. package/dist/esm/selection-popover.module.e22f5183.js +0 -22
  242. package/dist/esm/selection-popover.module.e22f5183.js.map +0 -1
  243. package/dist/esm/selection.bbf26d0e.js +0 -117
  244. package/dist/esm/selection.bbf26d0e.js.map +0 -1
  245. package/dist/esm/store.25eaa168.js +0 -18
  246. package/dist/esm/store.25eaa168.js.map +0 -1
  247. package/dist/esm/types.f016e032.js +0 -18
  248. package/dist/esm/types.f016e032.js.map +0 -1
  249. package/dist/esm/unit-details.56ff8b70.js +0 -209
  250. package/dist/esm/unit-details.56ff8b70.js.map +0 -1
  251. package/dist/esm/units.361088d4.js +0 -42
  252. package/dist/esm/units.361088d4.js.map +0 -1
  253. package/src/helpers.ts +0 -133
  254. package/src/providers.ts +0 -34
  255. package/src/selection-popover.ts +0 -71
  256. package/src/store.ts +0 -12
  257. package/src/units/units.scss +0 -16
  258. /package/src/{map → maps/column-navigation/svg}/animated.ts +0 -0
@@ -0,0 +1,225 @@
1
+ import { MapViewProps } from "@macrostrat/map-interface";
2
+ import {
3
+ useMapClickHandler,
4
+ useMapEaseTo,
5
+ useMapStyleOperator,
6
+ } from "@macrostrat/mapbox-react";
7
+ import { LngLatBounds } from "mapbox-gl";
8
+ import h from "@macrostrat/hyper";
9
+ import { Feature, FeatureCollection } from "geojson";
10
+ import { ReactNode, useMemo } from "react";
11
+ import { setGeoJSON } from "@macrostrat/mapbox-utils";
12
+
13
+ import { useCorrelationMapStore } from "./state";
14
+ import { buildColumnsStyle, InsetMap, InsetMapProps } from "../_shared";
15
+ import { buildCrossSectionLayers } from "@macrostrat/map-styles";
16
+
17
+ export interface CorrelationMapProps extends InsetMapProps {
18
+ padding?: number;
19
+ children?: ReactNode;
20
+ accessToken?: string;
21
+ columnColor?: string;
22
+ }
23
+
24
+ export function ColumnCorrelationMap(props: CorrelationMapProps) {
25
+ const { padding = 50, children, columnColor, ...rest } = props;
26
+
27
+ const overlayStyles = useMemo(() => {
28
+ return [
29
+ buildColumnsStyle(columnColor),
30
+ selectedColumnsStyle,
31
+ lineOfSectionStyle,
32
+ ];
33
+ }, [columnColor]);
34
+
35
+ return h(
36
+ InsetMap,
37
+ {
38
+ ...rest,
39
+ boxZoom: false,
40
+ dragRotate: false,
41
+ overlayStyles,
42
+ },
43
+ [
44
+ h(ColumnsLayer),
45
+ h(SelectedColumnsLayer),
46
+ h(MapClickHandler),
47
+ h(SectionLine, { padding }),
48
+ children,
49
+ ]
50
+ );
51
+ }
52
+
53
+ function MapClickHandler() {
54
+ const onClickMap = useCorrelationMapStore((state) => state.onClickMap);
55
+
56
+ useMapClickHandler(
57
+ (e) => {
58
+ onClickMap(e, { type: "Point", coordinates: e.lngLat.toArray() });
59
+ },
60
+ [onClickMap]
61
+ );
62
+
63
+ return null;
64
+ }
65
+
66
+ function SelectedColumnsLayer() {
67
+ const focusedColumns = useCorrelationMapStore(
68
+ (state) => state.focusedColumns
69
+ );
70
+
71
+ useMapStyleOperator(
72
+ (map) => {
73
+ let features = focusedColumns;
74
+
75
+ const data: FeatureCollection = {
76
+ type: "FeatureCollection",
77
+ features,
78
+ };
79
+
80
+ const columnCentroidLine: Feature = {
81
+ type: "Feature",
82
+ geometry: {
83
+ type: "LineString",
84
+ coordinates: features.map(
85
+ (col) => col.properties.centroid.geometry.coordinates
86
+ ),
87
+ },
88
+ properties: {},
89
+ };
90
+
91
+ setGeoJSON(map, "selected-columns", data);
92
+ setGeoJSON(map, "selected-column-centroids", {
93
+ type: "FeatureCollection",
94
+ features: [columnCentroidLine],
95
+ });
96
+ },
97
+ [focusedColumns]
98
+ );
99
+ return null;
100
+ }
101
+
102
+ function ColumnsLayer({ enabled = true }) {
103
+ const columns = useCorrelationMapStore((state) => state.columns);
104
+
105
+ useMapStyleOperator(
106
+ (map) => {
107
+ if (columns == null) {
108
+ return;
109
+ }
110
+ const data: FeatureCollection = {
111
+ type: "FeatureCollection",
112
+ features: columns,
113
+ };
114
+
115
+ console.log(" columns", data);
116
+ setGeoJSON(map, "columns", data);
117
+ },
118
+ [columns, enabled]
119
+ );
120
+ return null;
121
+ }
122
+
123
+ const selectedColumnsStyle = {
124
+ sources: {
125
+ "selected-columns": buildGeoJSONSource(),
126
+ "selected-column-centroids": buildGeoJSONSource(),
127
+ },
128
+ layers: [
129
+ {
130
+ id: "selected-columns-fill",
131
+ type: "fill",
132
+ source: "selected-columns",
133
+ paint: {
134
+ "fill-color": "rgba(255, 0, 0, 0.1)",
135
+ },
136
+ },
137
+ {
138
+ id: "selected-column-centroids-line",
139
+ type: "line",
140
+ source: "selected-column-centroids",
141
+ paint: {
142
+ "line-color": "rgba(255, 0, 0, 0.8)",
143
+ "line-width": 2,
144
+ "line-dasharray": [2, 2],
145
+ },
146
+ },
147
+ {
148
+ id: "selected-column-centroids-points",
149
+ type: "circle",
150
+ source: "selected-column-centroids",
151
+ paint: {
152
+ "circle-radius": 4,
153
+ "circle-color": "rgba(255, 0, 0, 0.8)",
154
+ },
155
+ },
156
+ ],
157
+ };
158
+
159
+ const lineOfSectionStyle = {
160
+ sources: {
161
+ elevationMarker: buildGeoJSONSource(),
162
+ crossSectionLine: buildGeoJSONSource(),
163
+ crossSectionEndpoints: buildGeoJSONSource(),
164
+ },
165
+ layers: buildCrossSectionLayers(),
166
+ };
167
+
168
+ function buildGeoJSONSource(data: FeatureCollection | null = null) {
169
+ return {
170
+ type: "geojson",
171
+ data: data ?? {
172
+ type: "FeatureCollection",
173
+ features: [],
174
+ },
175
+ };
176
+ }
177
+
178
+ function SectionLine({ padding }: { padding: number }) {
179
+ const focusedLine = useCorrelationMapStore((state) => state.focusedLine);
180
+
181
+ // Setup focused line
182
+ useMapStyleOperator(
183
+ (map) => {
184
+ if (focusedLine == null) {
185
+ return;
186
+ }
187
+ const data: FeatureCollection = {
188
+ type: "FeatureCollection",
189
+ features: [
190
+ {
191
+ type: "Feature",
192
+ geometry: focusedLine,
193
+ properties: { id: "focusedLine" },
194
+ },
195
+ ],
196
+ };
197
+
198
+ setGeoJSON(map, "crossSectionLine", data);
199
+ setGeoJSON(map, "crossSectionEndpoints", {
200
+ type: "FeatureCollection",
201
+ features: focusedLine.coordinates.map((coord) => ({
202
+ type: "Feature",
203
+ geometry: { type: "Point", coordinates: coord },
204
+ properties: {},
205
+ })),
206
+ });
207
+ },
208
+ [focusedLine]
209
+ );
210
+
211
+ const bounds = useMemo(() => {
212
+ if (focusedLine == null || focusedLine?.coordinates.length < 2) {
213
+ return null;
214
+ }
215
+ let bounds = new LngLatBounds();
216
+ for (let coord of focusedLine.coordinates) {
217
+ bounds.extend(coord);
218
+ }
219
+ return bounds;
220
+ }, [focusedLine]);
221
+
222
+ useMapEaseTo({ bounds, padding, trackResize: true });
223
+
224
+ return null;
225
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./core";
2
+ export * from "./state";
@@ -0,0 +1,192 @@
1
+ import { LineString, Point } from "geojson";
2
+ import { create, StoreApi, useStore } from "zustand";
3
+ import type { ColumnGeoJSONRecord } from "@macrostrat/api-types";
4
+ // Turf intersection
5
+ import { lineIntersect } from "@turf/line-intersect";
6
+ import distance from "@turf/distance";
7
+ import { nearestPointOnLine } from "@turf/nearest-point-on-line";
8
+ import { centroid } from "@turf/centroid";
9
+ import mapboxgl from "mapbox-gl";
10
+ import {
11
+ createContext,
12
+ useState,
13
+ useContext,
14
+ ReactNode,
15
+ useEffect,
16
+ } from "react";
17
+ import h from "@macrostrat/hyper";
18
+ import { createComputed } from "zustand-computed";
19
+ import { useMacrostratColumns } from "../../data-provider/base";
20
+
21
+ export interface CorrelationMapInput {
22
+ columns: ColumnGeoJSONRecord[];
23
+ focusedLine: LineString | null;
24
+ }
25
+
26
+ export interface CorrelationMapStore extends CorrelationMapInput {
27
+ onClickMap: (event: mapboxgl.MapMouseEvent, point: Point) => void;
28
+ }
29
+
30
+ export interface CorrelationProviderProps extends CorrelationMapInput {
31
+ projectID?: number;
32
+ inProcess?: boolean;
33
+ columns: ColumnGeoJSONRecord[] | null;
34
+ children: ReactNode;
35
+ onSelectColumns?: (
36
+ columns: FocusedColumnGeoJSONRecord[],
37
+ line: LineString | null
38
+ ) => void;
39
+ }
40
+
41
+ const CorrelationStoreContext =
42
+ createContext<StoreApi<CorrelationMapStore> | null>(null);
43
+
44
+ type ComputedStore = {
45
+ focusedColumns: FocusedColumnGeoJSONRecord[];
46
+ };
47
+
48
+ /** A computed store that will automatically update when the state changes */
49
+ const computed = createComputed((state: CorrelationMapStore): ComputedStore => {
50
+ return {
51
+ // We compute the focused columns based on columns and focusedLine
52
+ focusedColumns: buildCorrelationColumns(state.columns, state.focusedLine),
53
+ };
54
+ }) as any;
55
+
56
+ export function ColumnCorrelationProvider({
57
+ children,
58
+ columns,
59
+ projectID,
60
+ inProcess,
61
+ focusedLine,
62
+ onSelectColumns,
63
+ }: CorrelationProviderProps) {
64
+ const [store] = useState(() => {
65
+ return create<CorrelationMapStore & ComputedStore>(
66
+ computed((set, get): CorrelationMapStore => {
67
+ return {
68
+ focusedLine,
69
+ columns: null,
70
+ onClickMap(event: mapboxgl.MapMouseEvent, point: Point) {
71
+ const state = get();
72
+ // Check if shift key is pressed
73
+ const shiftKeyPressed = event.originalEvent.shiftKey;
74
+ let existingCoords = state.focusedLine?.coordinates ?? [];
75
+
76
+ if (existingCoords.length >= 2 && !shiftKeyPressed) {
77
+ // Reset the line to zero length
78
+ existingCoords = [];
79
+ }
80
+ set({
81
+ focusedLine: {
82
+ type: "LineString",
83
+ coordinates: [...existingCoords, point.coordinates],
84
+ },
85
+ });
86
+ },
87
+ };
88
+ })
89
+ );
90
+ });
91
+
92
+ // Set up the store
93
+ /** TODO: move the fetching of all columns to within the map */
94
+ const _columns = useMacrostratColumns(projectID, inProcess);
95
+ useEffect(() => {
96
+ if (_columns != null) {
97
+ store.setState({ columns: _columns });
98
+ }
99
+ }, [_columns]);
100
+
101
+ // Kind of an awkward way to do this but we need to allow the selector to run
102
+ const focusedColumns = useStore(store, (state) => state.focusedColumns);
103
+ const _focusedLine = useStore(store, (state) => state.focusedLine);
104
+
105
+ useEffect(() => {
106
+ onSelectColumns?.(focusedColumns, _focusedLine);
107
+ }, [focusedColumns, _focusedLine]);
108
+
109
+ return h(CorrelationStoreContext.Provider, { value: store }, children);
110
+ }
111
+
112
+ export function useCorrelationMapStore(
113
+ selector: (state: CorrelationMapStore & ComputedStore) => any
114
+ ) {
115
+ const storeApi = useContext(CorrelationStoreContext);
116
+ if (storeApi == null) {
117
+ throw new Error("Missing CorrelationMapProvider");
118
+ }
119
+ return useStore(storeApi, selector);
120
+ }
121
+
122
+ function buildCorrelationColumns(
123
+ columns: ColumnGeoJSONRecord[],
124
+ line: LineString
125
+ ): FocusedColumnGeoJSONRecord[] {
126
+ if (columns == null || line == null || line.coordinates.length < 2) {
127
+ return [];
128
+ }
129
+ return orderColumnsByDistance(
130
+ computeIntersectingColumns(columns, line),
131
+ line
132
+ );
133
+ }
134
+
135
+ function computeIntersectingColumns(
136
+ columns: ColumnGeoJSONRecord[],
137
+ line: LineString
138
+ ): ColumnGeoJSONRecord[] {
139
+ if (columns == null || line == null) {
140
+ return [];
141
+ }
142
+
143
+ return columns.filter((col) => {
144
+ const poly = col.geometry;
145
+
146
+ // Some in-process datasets seem to have null geometries
147
+ if (poly == null) return false;
148
+ if (poly.type != "Polygon" && poly.type != "MultiPolygon") return false;
149
+
150
+ const intersection = lineIntersect(line, poly);
151
+ return intersection.features.length > 0;
152
+ });
153
+ }
154
+
155
+ interface FocusedColumnGeoJSONRecord extends ColumnGeoJSONRecord {
156
+ properties: {
157
+ centroid: Point;
158
+ nearestPointOnLine: Point;
159
+ distanceAlongLine: number;
160
+ } & ColumnGeoJSONRecord["properties"];
161
+ }
162
+
163
+ function orderColumnsByDistance(
164
+ columns: ColumnGeoJSONRecord[],
165
+ line: LineString
166
+ ): FocusedColumnGeoJSONRecord[] {
167
+ const centroids = columns.map((col) => centroid(col.geometry));
168
+ const projectedPoints = centroids.map((point) =>
169
+ nearestPointOnLine(line, point)
170
+ );
171
+ const distances = projectedPoints.map((point) =>
172
+ distance(point.geometry.coordinates, line.coordinates[0])
173
+ );
174
+
175
+ let newColumns = columns.map((col, i) => {
176
+ return {
177
+ ...col,
178
+ properties: {
179
+ ...col.properties,
180
+ centroid: centroids[i],
181
+ nearestPointOnLine: projectedPoints[i],
182
+ distanceAlongLine: distances[i],
183
+ },
184
+ };
185
+ });
186
+
187
+ return sorted(newColumns, (d) => d.properties.distanceAlongLine);
188
+ }
189
+
190
+ function sorted(data, accessor: (d) => number) {
191
+ return data.sort((a, b) => accessor(a) - accessor(b));
192
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./mapbox";
2
+ export * from "./svg";
@@ -0,0 +1,102 @@
1
+ import h from "@macrostrat/hyper";
2
+
3
+ const mapboxToken = import.meta.env.VITE_MAPBOX_API_TOKEN;
4
+
5
+ import { Meta } from "@storybook/react";
6
+ import { ColumnNavigationMap } from ".";
7
+ import { useState } from "react";
8
+
9
+ function ColumnNavigationMapExt(props) {
10
+ return h(ColumnNavigationMap, {
11
+ style: { width: "800px", height: "600px" },
12
+ padding: 100,
13
+ accessToken: mapboxToken,
14
+ ...props,
15
+ });
16
+ }
17
+
18
+ // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
19
+ export default {
20
+ title: "Column views/Maps/Column navigation",
21
+ component: ColumnNavigationMapExt,
22
+ description: "Cross section creation map",
23
+ } as Meta<typeof ColumnNavigationMap>;
24
+
25
+ export const ColumnNavigation = {
26
+ args: {
27
+ showTriangulation: false,
28
+ },
29
+ };
30
+
31
+ export const nonStandardProjectInProcess = {
32
+ args: {
33
+ padding: 100,
34
+ projectID: 10,
35
+ inProcess: true,
36
+ showTriangulation: false,
37
+ mapPosition: {
38
+ camera: {
39
+ lng: -72,
40
+ lat: 44,
41
+ altitude: 600000,
42
+ },
43
+ },
44
+ },
45
+ };
46
+
47
+ export const DeepSea = {
48
+ args: {
49
+ padding: 100,
50
+ projectID: 4,
51
+ inProcess: true,
52
+ showTriangulation: false,
53
+ center: [0, 0],
54
+ zoom: 2,
55
+ mapPosition: null,
56
+ },
57
+ };
58
+
59
+ export const eODP = {
60
+ args: {
61
+ projectID: 3,
62
+ inProcess: true,
63
+ },
64
+ };
65
+
66
+ export const showTriangulation = {
67
+ description: "Show the triangulation used for keyboard navigation",
68
+ args: {
69
+ showTriangulation: true,
70
+ columnColor: "#1fff53",
71
+ triangulationColor: "#9a33bb",
72
+ },
73
+ };
74
+
75
+ export const onlyPhysicalBasemap = {
76
+ args: {
77
+ mapStyle: "mapbox://styles/mapbox/outdoors-v11",
78
+ showLabels: true,
79
+ showAdmin: false,
80
+ showRoads: false,
81
+ },
82
+ };
83
+
84
+ export function ControlledColumnNavigation() {
85
+ const [selectedColumn, setSelectedColumn] = useState(157);
86
+ const [hoveredColumn, setHoveredColumn] = useState(null);
87
+
88
+ return h("div.controlled-navigation", [
89
+ h(ColumnNavigationMapExt, {
90
+ selectedColumn,
91
+ hoveredColumn,
92
+ onSelectColumn: setSelectedColumn,
93
+ onHoverColumn: setHoveredColumn,
94
+ }),
95
+ h("div.column-info", [
96
+ h("h3", "Selected column"),
97
+ h("p", selectedColumn),
98
+ h("h3", "Hovered column"),
99
+ h("p", hoveredColumn),
100
+ ]),
101
+ ]);
102
+ }