@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,192 @@
1
+ import { Meta } from "@storybook/react";
2
+ import "@macrostrat/style-system";
3
+ import { useArgs } from "@storybook/preview-api";
4
+ import { useCallback } from "react";
5
+ import {
6
+ ColumnCorrelationMap,
7
+ ColumnCorrelationProvider,
8
+ fetchUnits,
9
+ useCorrelationMapStore,
10
+ } from "@macrostrat/column-views";
11
+ import { hyperStyled } from "@macrostrat/hyper";
12
+
13
+ import styles from "./stories.module.sass";
14
+ import { CorrelationChart, CorrelationChartProps } from "../main";
15
+ import { ErrorBoundary, useAsyncMemo } from "@macrostrat/ui-components";
16
+ import { OverlaysProvider } from "@blueprintjs/core";
17
+ import { parseLineFromString, stringifyLine } from "../hash-string";
18
+
19
+ const mapboxToken = import.meta.env.VITE_MAPBOX_API_TOKEN;
20
+
21
+ const h = hyperStyled(styles);
22
+
23
+ function CorrelationStoryUI({
24
+ focusedLine,
25
+ setFocusedLine,
26
+ columnID,
27
+ setColumn,
28
+ selectedUnit,
29
+ setSelectedUnit,
30
+ inProcess,
31
+ projectID,
32
+ ...rest
33
+ }: any) {
34
+ return h(
35
+ ColumnCorrelationProvider,
36
+ {
37
+ focusedLine,
38
+ columns: null,
39
+ onSelectColumns(cols, line) {
40
+ setFocusedLine(line);
41
+ },
42
+ },
43
+ h("div.correlation-ui", [
44
+ h("div.correlation-container", h(CorrelationDiagramWrapper, rest)),
45
+ h("div.right-column", [
46
+ h(ColumnCorrelationMap, {
47
+ accessToken: mapboxToken,
48
+ className: "correlation-map",
49
+ //showLogo: false,
50
+ }),
51
+ ]),
52
+ ])
53
+ );
54
+ }
55
+
56
+ function CorrelationDiagramWrapper(props: Omit<CorrelationChartProps, "data">) {
57
+ /** This state management is a bit too complicated, but it does kinda sorta work */
58
+
59
+ // Sync focused columns with map
60
+ const focusedColumns = useCorrelationMapStore(
61
+ (state) => state.focusedColumns
62
+ );
63
+
64
+ const columnUnits = useAsyncMemo(async () => {
65
+ const col_ids = focusedColumns.map((col) => col.properties.col_id);
66
+ return await fetchUnits(col_ids);
67
+ }, [focusedColumns]);
68
+
69
+ return h("div.correlation-diagram", [
70
+ h(
71
+ ErrorBoundary,
72
+ h(OverlaysProvider, [
73
+ h(CorrelationChart, { data: columnUnits, ...props }),
74
+ ])
75
+ ),
76
+ ]);
77
+ }
78
+
79
+ export default {
80
+ title: "Column views/Correlation chart",
81
+ component: CorrelationStoryUI,
82
+ parameters: {
83
+ layout: "fullscreen",
84
+ docs: {
85
+ description: {
86
+ component: "Correlation chart for Macrostrat columns",
87
+ },
88
+ story: {
89
+ inline: false,
90
+ iframeHeight: 500,
91
+ },
92
+ },
93
+ },
94
+ args: {
95
+ focusedLine: "-100,45 -90,50",
96
+ columnSpacing: 0,
97
+ columnWidth: 100,
98
+ collapseSmallUnconformities: false,
99
+ targetUnitHeight: 20,
100
+ },
101
+ argTypes: {
102
+ selectedUnit: {
103
+ control: {
104
+ type: "number",
105
+ },
106
+ },
107
+ t_age: {
108
+ control: {
109
+ type: "number",
110
+ },
111
+ },
112
+ b_age: {
113
+ control: {
114
+ type: "number",
115
+ },
116
+ },
117
+ columnSpacing: {
118
+ control: {
119
+ type: "number",
120
+ },
121
+ },
122
+ columnWidth: {
123
+ control: {
124
+ type: "number",
125
+ },
126
+ },
127
+ mergeSections: {
128
+ options: ["all", "overlapping", null],
129
+ control: { type: "radio" },
130
+ },
131
+ pixelScale: {
132
+ control: {
133
+ type: "number",
134
+ },
135
+ },
136
+ collapseSmallUnconformities: {
137
+ control: {
138
+ type: "boolean",
139
+ },
140
+ },
141
+ minSectionHeight: {
142
+ control: {
143
+ type: "number",
144
+ },
145
+ },
146
+ targetUnitHeight: {
147
+ control: {
148
+ type: "number",
149
+ },
150
+ },
151
+ showLabelColumn: {
152
+ control: {
153
+ type: "boolean",
154
+ },
155
+ },
156
+ maxInternalColumns: {
157
+ control: {
158
+ type: "number",
159
+ },
160
+ },
161
+ },
162
+ } as Meta<typeof CorrelationStoryUI>;
163
+
164
+ function useCorrelationLine() {
165
+ const [{ focusedLine, selectedUnit }, updateArgs] = useArgs();
166
+ const setFocusedLine = (line) => {
167
+ updateArgs({ focusedLine: stringifyLine(line) });
168
+ };
169
+
170
+ const setSelectedUnit = useCallback(
171
+ (selectedUnit) => {
172
+ updateArgs({ selectedUnit });
173
+ },
174
+ [updateArgs]
175
+ );
176
+
177
+ return {
178
+ focusedLine: parseLineFromString(focusedLine),
179
+ setFocusedLine,
180
+ selectedUnit,
181
+ setSelectedUnit,
182
+ };
183
+ }
184
+
185
+ function Template(args) {
186
+ return h(CorrelationStoryUI, {
187
+ ...args,
188
+ ...useCorrelationLine(),
189
+ });
190
+ }
191
+
192
+ export const Primary = Template.bind({});
@@ -0,0 +1,18 @@
1
+ .column-ui
2
+ height: 100%
3
+ width: 100%
4
+ overflow: scroll
5
+
6
+ .correlation-container
7
+ padding: 2em calc(350px + 2em) 2em 2em
8
+ width: fit-content
9
+
10
+ .right-column
11
+ width: 350px
12
+ position: fixed
13
+ top: 0
14
+ right: 0
15
+ padding: 1em
16
+
17
+ .column-selector-map, .correlation-map
18
+ height: 350px
@@ -0,0 +1,8 @@
1
+ .unconformity-line
2
+ height: 1em
3
+ margin-top: -0.5em
4
+ margin-bottom: -0.5em
5
+
6
+ path
7
+ stroke: var(--secondary-color)
8
+ stroke-width: 1px
@@ -0,0 +1,25 @@
1
+ import hyper from "@macrostrat/hyper";
2
+ import styles from "./unconformity-line.module.sass";
3
+
4
+ const h = hyper.styled(styles);
5
+
6
+ export function UnconformityLine({ width }) {
7
+ return h("div.unconformity-line", [h(UnconformityLineSVG, { width })]);
8
+ }
9
+
10
+ function UnconformityLineSVG({ width }) {
11
+ // Path with a repeating squiggly stroke filling width
12
+
13
+ let d = "M0 5 Q2.5 2 5 5";
14
+
15
+ for (let i = 10; i < width; i += 5) {
16
+ d += ` T${i} 5`;
17
+ }
18
+
19
+ return h("svg", { width, height: 10 }, [
20
+ h("path", {
21
+ d,
22
+ fill: "none",
23
+ }),
24
+ ]);
25
+ }
@@ -0,0 +1,388 @@
1
+ /** Data provider for information that needs to be loaded in bulk for frontend views */
2
+ import baseFetch from "cross-fetch";
3
+ import { createContext, useContext, useEffect, useMemo, useState } from "react";
4
+ import h from "@macrostrat/hyper";
5
+ import { create, useStore } from "zustand";
6
+ import {
7
+ ColumnGeoJSONRecord,
8
+ ColumnGeoJSONRecordWithID,
9
+ Environment,
10
+ MacrostratRef,
11
+ } from "@macrostrat/api-types";
12
+ import {
13
+ fetchAllColumns,
14
+ fetchEnvironments,
15
+ fetchIntervals,
16
+ fetchLithologies,
17
+ fetchRefs,
18
+ } from "./fetch";
19
+ import { APIProvider } from "@macrostrat/ui-components";
20
+ import { ColumnProvider } from "@macrostrat/column-components";
21
+
22
+ import { ReactNode } from "react";
23
+ import { useMacrostratColumnData } from "./store";
24
+
25
+ export interface MacrostratDataProviderProps {
26
+ baseURL: string;
27
+ children: React.ReactNode;
28
+ }
29
+
30
+ interface ColumnFootprintsStorage {
31
+ project_id: number;
32
+ // Whether the "in process" flag was used
33
+ inProcess: boolean;
34
+ // The column footprints
35
+ columns: ColumnGeoJSONRecordWithID[];
36
+ }
37
+
38
+ interface RefsSlice {
39
+ refs: Map<number, MacrostratRef>;
40
+ inFlightRequests: Set<string>; // Track requests to avoid duplicates
41
+ getRefs(ids: number[]): Promise<MacrostratRef[]>;
42
+ }
43
+
44
+ interface MacrostratStore extends RefsSlice {
45
+ baseURL: string;
46
+ fetch: any;
47
+ lithologies: Map<number, any> | null;
48
+ getLithologies(ids: number[] | null): Promise<any>;
49
+ intervals: Map<number, any> | null;
50
+ getIntervals(ids: number[] | null, timescaleID: number | null): Promise<any>;
51
+ environments: Map<number, Environment> | null;
52
+ getEnvironments(ids: number[] | null): Promise<Environment[]>;
53
+ columnFootprints: Map<number, ColumnFootprintsStorage>;
54
+ getColumns(
55
+ projectID: number | null,
56
+ inProcess: boolean
57
+ ): Promise<ColumnGeoJSONRecord[]>;
58
+ }
59
+
60
+ function createMacrostratStore(
61
+ baseURL: string = "https://macrostrat.org/api/v2"
62
+ ) {
63
+ return create<MacrostratStore>((set, get): MacrostratStore => {
64
+ return {
65
+ baseURL,
66
+ inFlightRequests: new Set(),
67
+ async fetch(url: string, options?: RequestInit) {
68
+ const url1 = baseURL + url;
69
+ // Avoid duplicate requests
70
+ const { inFlightRequests } = get();
71
+ if (inFlightRequests.has(url1)) {
72
+ return null; // Return null if already in flight
73
+ }
74
+ inFlightRequests.add(url1);
75
+ //set({ inFlightRequests });
76
+ const res = await baseFetch(url1, options);
77
+ inFlightRequests.delete(url1);
78
+ //set({in})
79
+ return res;
80
+ },
81
+ ...createLithologiesSlice(set, get),
82
+ ...createIntervalsSlice(set, get),
83
+ ...createEnvironmentsSlice(set, get),
84
+ ...createColumnsSlice(set, get),
85
+ ...createRefsSlice(set, get),
86
+ };
87
+ });
88
+ }
89
+
90
+ function createRefsSlice(set, get) {
91
+ return {
92
+ refs: new Map(),
93
+ async getRefs(ids: number[]): Promise<MacrostratRef[]> {
94
+ const { refs, fetch } = get();
95
+ const missing = ids.filter((id) => !refs.has(id));
96
+ if (missing.length == 0) {
97
+ return ids.map((id) => refs.get(id));
98
+ }
99
+ const data = await fetchRefs(missing, fetch);
100
+ if (data == null) return [];
101
+ for (const d of data) {
102
+ refs.set(d.ref_id, d);
103
+ }
104
+ set({ refs });
105
+ return ids.map((id) => refs.get(id));
106
+ },
107
+ };
108
+ }
109
+
110
+ function createColumnsSlice(set, get) {
111
+ // Column footprints separated by project
112
+ return {
113
+ columnFootprints: new Map(),
114
+ async getColumns(projectID: number | null, inProcess: boolean) {
115
+ const { columnFootprints, baseURL, fetch } = get();
116
+ const key = projectID ?? -1;
117
+ let _inProcess = inProcess;
118
+ if (projectID == null) {
119
+ // If no project is specified, in process columns cannot be included
120
+ _inProcess = false;
121
+ }
122
+ let footprints = columnFootprints.get(key);
123
+ if (footprints == null || footprints.inProcess != _inProcess) {
124
+ // Fetch the columns
125
+ const statusCode = inProcess ? "in process" : null;
126
+ let columns = await fetchAllColumns({
127
+ projectID,
128
+ statusCode: null,
129
+ fetch,
130
+ });
131
+ if (columns == null) {
132
+ return;
133
+ }
134
+ if (_inProcess) {
135
+ const inProcessColumns = await fetchAllColumns({
136
+ projectID,
137
+ statusCode: "in process",
138
+ fetch,
139
+ });
140
+ if (inProcessColumns == null) {
141
+ return;
142
+ }
143
+ // Combine active and in-process columns
144
+ columns = columns.concat(inProcessColumns);
145
+ }
146
+
147
+ footprints = {
148
+ project_id: projectID,
149
+ inProcess,
150
+ columns,
151
+ };
152
+ // We could break multi-project result sets into separate caches here...
153
+ // Copy the original map
154
+ const columnFootprints2 = new Map(columnFootprints);
155
+ columnFootprints2.set(key, footprints);
156
+ set({ columnFootprints: columnFootprints2 });
157
+ }
158
+ return footprints.columns;
159
+ },
160
+ };
161
+ }
162
+
163
+ function createLithologiesSlice(set, get) {
164
+ return {
165
+ lithologies: null,
166
+ async getLithologies(ids: number[] | null) {
167
+ const { lithologies, fetch } = get();
168
+ let lithMap = lithologies;
169
+ if (lithMap == null) {
170
+ const data = await fetchLithologies(fetch);
171
+ if (data == null) return;
172
+ lithMap = new Map(data.map((d) => [d.lith_id, d]));
173
+ set({ lithologies: lithMap });
174
+ }
175
+ // Now get the lithologies
176
+ if (ids == null) return lithMap.values();
177
+ return ids.map((id) => lithMap.get(id));
178
+ },
179
+ };
180
+ }
181
+
182
+ function createEnvironmentsSlice(set, get) {
183
+ return {
184
+ environments: null,
185
+ async getEnvironments(ids: number[] | null): Promise<Environment[]> {
186
+ const { environments, fetch } = get();
187
+ let envMap = environments;
188
+ if (envMap == null) {
189
+ const data = await fetchEnvironments(fetch);
190
+ if (data == null) return [];
191
+ envMap = new Map(data.map((d) => [d.environ_id, d]));
192
+ set({ environments: envMap });
193
+ }
194
+ // Now get the environments
195
+ if (ids == null) return envMap.values();
196
+ return ids.map((id) => envMap.get(id));
197
+ },
198
+ };
199
+ }
200
+
201
+ function createIntervalsSlice(set, get) {
202
+ return {
203
+ intervals: null,
204
+ async getIntervals(ids: number[] | null, timescaleID: number | null) {
205
+ const { intervals, fetch } = get();
206
+ let _intervals = intervals;
207
+ if (intervals == null || !includesTimescale(intervals, timescaleID)) {
208
+ // Fetch the intervals
209
+ const data = await fetchIntervals(timescaleID, fetch);
210
+ if (data == null) {
211
+ return [];
212
+ }
213
+ const intervalMap = intervals ?? new Map();
214
+ for (const d of data) {
215
+ intervalMap.set(d.int_id, d);
216
+ }
217
+ _intervals = intervalMap;
218
+ set({ intervals: _intervals });
219
+ }
220
+ if (ids == null && timescaleID == null)
221
+ return Array.from(_intervals.values());
222
+ if (timescaleID != null) {
223
+ return Array.from(_intervals.values() as any[]).filter(
224
+ (d) => d.timescale_id == timescaleID
225
+ );
226
+ }
227
+ return ids.map((id) => intervals.get(id));
228
+ },
229
+ };
230
+ }
231
+
232
+ function includesTimescale(intervals: Map<number, any>, timescaleID: number) {
233
+ if (intervals == null) return false;
234
+ if (timescaleID == null) return true;
235
+ return Array.from(intervals.values()).some(
236
+ (d) => d.timescale_id == timescaleID
237
+ );
238
+ }
239
+
240
+ type MacrostratSelector = (store: MacrostratStore) => any;
241
+
242
+ export function useMacrostratStore(selector: MacrostratSelector | "api") {
243
+ const ctx = useContext(MacrostratDataProviderContext);
244
+ if (ctx == null) {
245
+ throw new Error("Missing MacrostratDataProvider");
246
+ }
247
+ if (selector === "api") {
248
+ return ctx;
249
+ }
250
+
251
+ return useStore(ctx, selector);
252
+ }
253
+
254
+ const dataTypeMapping = {
255
+ lithologies: (store) => store.getLithologies,
256
+ intervals: (store) => store.getIntervals,
257
+ columns: (store) => store.getColumns,
258
+ environments: (store) => store.getEnvironments,
259
+ refs: (store) => store.getRefs,
260
+ };
261
+
262
+ export function useMacrostratDefs(dataType: string): Map<number, any> | null {
263
+ if (dataType == "columns") {
264
+ throw new Error("Columns are not provided as a map");
265
+ }
266
+ const operator = useMacrostratStore(dataTypeMapping[dataType]);
267
+ useEffect(() => {
268
+ operator();
269
+ }, []);
270
+ return useMacrostratStore((state) => state[dataType]);
271
+ }
272
+
273
+ export function useMacrostratColumns(
274
+ projectID: number | null,
275
+ inProcess: boolean
276
+ ) {
277
+ const getColumns = useMacrostratStore((s) => s.getColumns);
278
+ const columnsMap = useMacrostratStore((s) => s.columnFootprints);
279
+ const key = projectID ?? -1;
280
+ const colData = columnsMap?.get(key);
281
+ useEffect(() => {
282
+ // Refetch if the columns are not available, or if we have requested inProcess columns where we didn't before
283
+ if (colData == null || (inProcess && !colData.inProcess)) {
284
+ getColumns(projectID, inProcess);
285
+ }
286
+ // If we've already fetched the columns there's nothing to do...
287
+ }, [colData, inProcess, getColumns]);
288
+
289
+ return useMemo(() => {
290
+ if (colData == null) return null;
291
+ let columns = colData.columns;
292
+ if (!inProcess && colData.inProcess) {
293
+ // Our available set of columns includes 'in process' columns, but we don't want them
294
+ columns.features = columns.features?.filter(
295
+ (d) => d.properties.status != "in process"
296
+ );
297
+ }
298
+ return columns;
299
+ }, [colData, inProcess]);
300
+ }
301
+
302
+ export function useMacrostratData(dataType: string, ...args: any[]) {
303
+ const selector = dataTypeMapping[dataType];
304
+ const operator = useMacrostratStore(selector);
305
+
306
+ const [value, setValue] = useState(null);
307
+
308
+ useEffect(() => {
309
+ operator(...args).then(setValue);
310
+ }, [operator, ...args]);
311
+
312
+ return value;
313
+ }
314
+
315
+ /** By default, we provide a store linked to the production API */
316
+ const MacrostratDataProviderContext = createContext(createMacrostratStore());
317
+
318
+ export function MacrostratDataProvider(props: MacrostratDataProviderProps) {
319
+ const { baseURL = "https://macrostrat.org/api/v2", children } = props;
320
+
321
+ const [store] = useState(() => createMacrostratStore(baseURL));
322
+
323
+ return h(
324
+ MacrostratAPIProvider,
325
+ { baseURL },
326
+ h(MacrostratDataProviderContext.Provider, { value: store }, children)
327
+ );
328
+ }
329
+
330
+ /** Legacy API provider so useAPIResult can work */
331
+
332
+ type APIProviderProps = {
333
+ children: ReactNode;
334
+ useDev?: boolean;
335
+ baseURL?: string;
336
+ };
337
+
338
+ export function MacrostratAPIProvider({
339
+ children,
340
+ useDev = false,
341
+ baseURL,
342
+ }: APIProviderProps) {
343
+ baseURL ??= useDev
344
+ ? "https://dev2.macrostrat.org/api/v2"
345
+ : "https://macrostrat.org/api/v2";
346
+
347
+ return h(
348
+ APIProvider,
349
+ {
350
+ baseURL,
351
+ unwrapResponse: (res) => res.success.data,
352
+ },
353
+ children
354
+ );
355
+ }
356
+
357
+ export function MacrostratColumnProvider(props) {
358
+ /** A column provider specialized the Macrostrat API. Maps more
359
+ * generic concepts to Macrostrat-specific ones.
360
+ */
361
+
362
+ const { axisType } = useMacrostratColumnData();
363
+ const { units, domain, pixelScale, children } = props;
364
+ return h(
365
+ ColumnProvider,
366
+ { axisType, divisions: units, range: domain, pixelsPerMeter: pixelScale },
367
+ children
368
+ );
369
+ }
370
+
371
+ /** This is now a legacy provider */
372
+ export function LithologiesProvider({ children }) {
373
+ useEffect(() => {
374
+ console.warn(
375
+ "LithologiesProvider is deprecated. Replace with MacrostratDataProvider"
376
+ );
377
+ }, []);
378
+ return children;
379
+ }
380
+
381
+ export function useLithologies() {
382
+ const getLithologies = useMacrostratStore((s) => s.getLithologies);
383
+ const lithologies = useMacrostratStore((s) => s.lithologies);
384
+ useEffect(() => {
385
+ if (lithologies == null) getLithologies();
386
+ }, [lithologies, getLithologies]);
387
+ return lithologies;
388
+ }
@@ -0,0 +1,53 @@
1
+ import h from "@macrostrat/hyper";
2
+ import { getQueryString, setQueryString } from "@macrostrat/ui-components";
3
+ import { createContext, useContext, useEffect, useState } from "react";
4
+
5
+ export interface ColumnArgs {
6
+ col_id?: number;
7
+ unit_id?: number;
8
+ project_id?: number;
9
+ status_code?: "in process";
10
+ }
11
+
12
+ type ColumnManagerData = [ColumnArgs, (c: ColumnArgs) => void];
13
+
14
+ const ColumnNavCtx = createContext<ColumnManagerData | null>(null);
15
+
16
+ export function useColumnNav(
17
+ defaultArgs: ColumnArgs = { col_id: 495, unit_id: null }
18
+ ): ColumnManagerData {
19
+ const ctx = useContext(ColumnNavCtx);
20
+ if (ctx != null) return ctx;
21
+
22
+ const [columnArgs, setColumnArgs] = useState<ColumnArgs>(
23
+ extractColumnArgs(getQueryString(window.location.search)) ?? defaultArgs
24
+ );
25
+
26
+ useEffect(() => setQueryString(columnArgs), [columnArgs]);
27
+
28
+ const { col_id, project_id, status_code } = columnArgs;
29
+
30
+ const setCurrentColumn = (obj) => {
31
+ let args = obj;
32
+ if ("properties" in obj) {
33
+ args = { col_id: obj.properties.col_id, project_id, status_code };
34
+ }
35
+ // Set query string
36
+ setQueryString(args);
37
+ setColumnArgs(args);
38
+ };
39
+
40
+ return [columnArgs, setCurrentColumn];
41
+ }
42
+
43
+ function extractColumnArgs(search: any): ColumnArgs | null {
44
+ const { col_id, unit_id, project_id, status_code } = search ?? {};
45
+ if (col_id == null) return null;
46
+ return { col_id, unit_id, project_id, status_code };
47
+ }
48
+
49
+ export function ColumnNavProvider({ children, ...defaultArgs }) {
50
+ /** Column navigation provider that manages the query string for selected columns */
51
+ const value = useColumnNav(defaultArgs as any);
52
+ return h(ColumnNavCtx.Provider, { value }, children);
53
+ }