@macrostrat/column-views 1.0.2 → 2.0.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 (242) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/esm/_shared.f7eec55a.js +9 -0
  3. package/dist/esm/_shared.f7eec55a.js.map +1 -0
  4. package/dist/esm/age-axis.4a8cf5e6.js +98 -0
  5. package/dist/esm/age-axis.4a8cf5e6.js.map +1 -0
  6. package/dist/esm/age-axis.module.03773a80.css +33 -0
  7. package/dist/esm/age-axis.module.03773a80.css.map +1 -0
  8. package/dist/esm/age-axis.module.3cc91335.js +22 -0
  9. package/dist/esm/age-axis.module.3cc91335.js.map +1 -0
  10. package/dist/esm/age-model-overlay.c7226855.js +57 -0
  11. package/dist/esm/age-model-overlay.c7226855.js.map +1 -0
  12. package/dist/esm/age-model-overlay.module.5d9e78fb.css +14 -0
  13. package/dist/esm/age-model-overlay.module.5d9e78fb.css.map +1 -0
  14. package/dist/esm/age-model-overlay.module.cd985dcb.js +16 -0
  15. package/dist/esm/age-model-overlay.module.cd985dcb.js.map +1 -0
  16. package/dist/esm/base.910b80b4.js +288 -0
  17. package/dist/esm/base.910b80b4.js.map +1 -0
  18. package/dist/esm/boxes.8292cff2.js +258 -0
  19. package/dist/esm/boxes.8292cff2.js.map +1 -0
  20. package/dist/esm/boxes.module.2b5fb18e.css +26 -0
  21. package/dist/esm/boxes.module.2b5fb18e.css.map +1 -0
  22. package/dist/esm/boxes.module.4ebc7796.js +19 -0
  23. package/dist/esm/boxes.module.4ebc7796.js.map +1 -0
  24. package/dist/esm/{carbon-isotopes.3b502a9e.js → carbon-isotopes.10db8285.js} +2 -2
  25. package/dist/esm/{carbon-isotopes.3b502a9e.js.map → carbon-isotopes.10db8285.js.map} +1 -1
  26. package/dist/esm/colors.395c6db5.js +40 -0
  27. package/dist/esm/colors.395c6db5.js.map +1 -0
  28. package/dist/esm/column-correlation.c8dcfe98.js +9 -0
  29. package/dist/esm/column-correlation.c8dcfe98.js.map +1 -0
  30. package/dist/esm/column-nav.5414677c.js +55 -0
  31. package/dist/esm/column-nav.5414677c.js.map +1 -0
  32. package/dist/esm/column-navigation.37cd3245.js +9 -0
  33. package/dist/esm/column-navigation.37cd3245.js.map +1 -0
  34. package/dist/esm/column.01d68dd8.js +127 -0
  35. package/dist/esm/column.01d68dd8.js.map +1 -0
  36. package/dist/esm/{column.db058031.js → column.a25f8ebd.js} +4 -4
  37. package/dist/esm/column.a25f8ebd.js.map +1 -0
  38. package/dist/esm/column.module.1b776e15.js +46 -0
  39. package/dist/esm/column.module.1b776e15.js.map +1 -0
  40. package/dist/esm/column.module.a67a6b4c.css +159 -0
  41. package/dist/esm/column.module.a67a6b4c.css.map +1 -0
  42. package/dist/esm/composite-scale.577bf64a.js +222 -0
  43. package/dist/esm/composite-scale.577bf64a.js.map +1 -0
  44. package/dist/esm/composite.039e4798.js +163 -0
  45. package/dist/esm/composite.039e4798.js.map +1 -0
  46. package/dist/esm/{core.4db8e452.js → core.843310d3.js} +11 -12
  47. package/dist/esm/core.843310d3.js.map +1 -0
  48. package/dist/esm/core.91ede078.js +206 -0
  49. package/dist/esm/core.91ede078.js.map +1 -0
  50. package/dist/esm/correlation-chart.abd8b346.js +9 -0
  51. package/dist/esm/correlation-chart.abd8b346.js.map +1 -0
  52. package/dist/esm/data-provider.1506eb64.js.map +1 -1
  53. package/dist/esm/data-provider.f10c6d0b.js +13 -0
  54. package/dist/esm/data-provider.f10c6d0b.js.map +1 -0
  55. package/dist/esm/fetch.99aec438.js +152 -0
  56. package/dist/esm/fetch.99aec438.js.map +1 -0
  57. package/dist/esm/hash-string.285b37fb.js +39 -0
  58. package/dist/esm/hash-string.285b37fb.js.map +1 -0
  59. package/dist/esm/helpers.2f0a0cb7.js +141 -0
  60. package/dist/esm/helpers.2f0a0cb7.js.map +1 -0
  61. package/dist/esm/index.d.ts +797 -120
  62. package/dist/esm/index.d.ts.map +1 -1
  63. package/dist/esm/index.js +14 -8
  64. package/dist/esm/index.js.map +1 -1
  65. package/dist/esm/inset-map.3c18106d.js +66 -0
  66. package/dist/esm/inset-map.3c18106d.js.map +1 -0
  67. package/dist/esm/keyboard-navigation.6713401b.js +48 -0
  68. package/dist/esm/keyboard-navigation.6713401b.js.map +1 -0
  69. package/dist/esm/keyboard-navigation.a9fc80dd.js +112 -0
  70. package/dist/esm/keyboard-navigation.a9fc80dd.js.map +1 -0
  71. package/dist/esm/layers.033d3fb0.js +170 -0
  72. package/dist/esm/layers.033d3fb0.js.map +1 -0
  73. package/dist/esm/main.2e0375a5.js +221 -0
  74. package/dist/esm/main.2e0375a5.js.map +1 -0
  75. package/dist/esm/main.module.3dd9500b.css +134 -0
  76. package/dist/esm/main.module.3dd9500b.css.map +1 -0
  77. package/dist/esm/main.module.c09154b1.js +70 -0
  78. package/dist/esm/main.module.c09154b1.js.map +1 -0
  79. package/dist/esm/mapbox.cac42eed.js +167 -0
  80. package/dist/esm/mapbox.cac42eed.js.map +1 -0
  81. package/dist/esm/maps.bcdea9c1.js +11 -0
  82. package/dist/esm/maps.bcdea9c1.js.map +1 -0
  83. package/dist/esm/{names.f6a4e9a4.js → names.a8f2b452.js} +5 -5
  84. package/dist/esm/names.a8f2b452.js.map +1 -0
  85. package/dist/esm/panel.598f76a5.js +420 -0
  86. package/dist/esm/panel.598f76a5.js.map +1 -0
  87. package/dist/esm/panel.module.386166cc.js +58 -0
  88. package/dist/esm/panel.module.386166cc.js.map +1 -0
  89. package/dist/esm/panel.module.3d2ea3c6.css +111 -0
  90. package/dist/esm/panel.module.3d2ea3c6.css.map +1 -0
  91. package/dist/esm/popover.a810b7bc.js +66 -0
  92. package/dist/esm/popover.a810b7bc.js.map +1 -0
  93. package/dist/esm/popover.module.c4ba4189.js +22 -0
  94. package/dist/esm/popover.module.c4ba4189.js.map +1 -0
  95. package/dist/esm/{selection-popover.module.0a701258.css → popover.module.c4d6bfb0.css} +11 -8
  96. package/dist/esm/popover.module.c4d6bfb0.css.map +1 -0
  97. package/dist/esm/prepare-data.d4284b4a.js +125 -0
  98. package/dist/esm/prepare-data.d4284b4a.js.map +1 -0
  99. package/dist/esm/prepare-units.6c890a96.js +104 -0
  100. package/dist/esm/prepare-units.6c890a96.js.map +1 -0
  101. package/dist/esm/{resolvers.b5c82b78.js → resolvers.36013b49.js} +13 -2
  102. package/dist/esm/resolvers.36013b49.js.map +1 -0
  103. package/dist/esm/section.a34d379a.js +215 -0
  104. package/dist/esm/section.a34d379a.js.map +1 -0
  105. package/dist/esm/selection.f5b0297e.js +143 -0
  106. package/dist/esm/selection.f5b0297e.js.map +1 -0
  107. package/dist/esm/state.178ef364.js +75 -0
  108. package/dist/esm/state.178ef364.js.map +1 -0
  109. package/dist/esm/state.2952cbca.js +118 -0
  110. package/dist/esm/state.2952cbca.js.map +1 -0
  111. package/dist/esm/store.c4d7a8a4.js +52 -0
  112. package/dist/esm/store.c4d7a8a4.js.map +1 -0
  113. package/dist/esm/styles.7bc776d1.js +95 -0
  114. package/dist/esm/styles.7bc776d1.js.map +1 -0
  115. package/dist/esm/svg.4b9a96c1.js +89 -0
  116. package/dist/esm/svg.4b9a96c1.js.map +1 -0
  117. package/dist/esm/types.0f0b57c9.js +3 -0
  118. package/dist/esm/types.0f0b57c9.js.map +1 -0
  119. package/dist/esm/unit-details.071cefed.js +9 -0
  120. package/dist/esm/unit-details.071cefed.js.map +1 -0
  121. package/dist/esm/units.5a4fc058.js +98 -0
  122. package/dist/esm/units.5a4fc058.js.map +1 -0
  123. package/dist/esm/utils.d7a43a2a.js +55 -0
  124. package/dist/esm/utils.d7a43a2a.js.map +1 -0
  125. package/dist/node/index.js.map +1 -1
  126. package/package.json +24 -7
  127. package/src/age-axis.module.sass +27 -0
  128. package/src/age-axis.ts +82 -19
  129. package/src/age-model-overlay.module.sass +11 -0
  130. package/src/age-model-overlay.ts +73 -0
  131. package/src/carbon-isotopes/column.ts +4 -2
  132. package/src/carbon-isotopes/core.ts +9 -6
  133. package/src/carbon-isotopes/data-provider.ts +3 -3
  134. package/src/column.module.sass +58 -49
  135. package/src/column.ts +149 -135
  136. package/src/correlation-chart/hash-string.ts +57 -0
  137. package/src/correlation-chart/index.ts +2 -0
  138. package/src/correlation-chart/main.module.sass +122 -0
  139. package/src/correlation-chart/main.ts +305 -0
  140. package/src/correlation-chart/prepare-data.ts +217 -0
  141. package/src/correlation-chart/stories/correlation-chart.stories.ts +192 -0
  142. package/src/correlation-chart/stories/stories.module.sass +18 -0
  143. package/src/correlation-chart/unconformity-line.module.sass +8 -0
  144. package/src/correlation-chart/unconformity-line.ts +25 -0
  145. package/src/data-provider/base.ts +388 -0
  146. package/src/data-provider/column-nav.ts +53 -0
  147. package/src/data-provider/fetch.ts +231 -0
  148. package/src/data-provider/index.ts +4 -0
  149. package/src/data-provider/store.ts +72 -0
  150. package/src/index.ts +6 -3
  151. package/src/maps/_shared/index.ts +2 -0
  152. package/src/maps/_shared/inset-map.stories.ts +20 -0
  153. package/src/maps/_shared/inset-map.ts +87 -0
  154. package/src/maps/_shared/styles.ts +57 -0
  155. package/src/maps/column-correlation/column-correlation-map.stories.ts +96 -0
  156. package/src/maps/column-correlation/core.ts +225 -0
  157. package/src/maps/column-correlation/index.ts +2 -0
  158. package/src/maps/column-correlation/state.ts +192 -0
  159. package/src/maps/column-navigation/index.ts +2 -0
  160. package/src/maps/column-navigation/mapbox/column-navigation-map.stories.ts +102 -0
  161. package/src/maps/column-navigation/mapbox/index.ts +219 -0
  162. package/src/maps/column-navigation/mapbox/keyboard-navigation.ts +119 -0
  163. package/src/maps/column-navigation/mapbox/state.ts +109 -0
  164. package/src/maps/column-navigation/svg/column-navigation-svg-map.stories.ts +46 -0
  165. package/src/{map → maps/column-navigation/svg}/index.ts +18 -6
  166. package/src/{map → maps/column-navigation/svg}/layers.ts +28 -109
  167. package/src/maps/column-navigation/utils/keyboard-navigation.ts +58 -0
  168. package/src/maps/index.ts +3 -0
  169. package/src/prepare-units/composite-scale.ts +353 -0
  170. package/src/prepare-units/helpers.ts +226 -0
  171. package/src/prepare-units/index.ts +177 -0
  172. package/src/prepare-units/utils.ts +98 -0
  173. package/src/section.ts +264 -84
  174. package/src/unit-details/index.ts +2 -215
  175. package/src/unit-details/{index.module.sass → panel.module.sass} +39 -8
  176. package/src/unit-details/panel.ts +523 -0
  177. package/src/{selection-popover.module.sass → unit-details/popover.module.sass} +4 -2
  178. package/src/unit-details/popover.ts +82 -0
  179. package/src/units/boxes.module.sass +16 -0
  180. package/src/units/boxes.ts +243 -90
  181. package/src/units/colors.ts +64 -0
  182. package/src/units/composite.ts +157 -152
  183. package/src/units/index.ts +76 -9
  184. package/src/units/names.ts +8 -4
  185. package/src/units/resolvers.ts +11 -0
  186. package/src/units/selection.ts +115 -101
  187. package/src/units/types.ts +5 -16
  188. package/dist/esm/age-axis.64c509ee.js +0 -41
  189. package/dist/esm/age-axis.64c509ee.js.map +0 -1
  190. package/dist/esm/boxes.13968b76.js +0 -164
  191. package/dist/esm/boxes.13968b76.js.map +0 -1
  192. package/dist/esm/boxes.module.28873d08.css +0 -4
  193. package/dist/esm/boxes.module.28873d08.css.map +0 -1
  194. package/dist/esm/boxes.module.605bdcd6.js +0 -13
  195. package/dist/esm/boxes.module.605bdcd6.js.map +0 -1
  196. package/dist/esm/column.8dd26e1a.js +0 -149
  197. package/dist/esm/column.8dd26e1a.js.map +0 -1
  198. package/dist/esm/column.db058031.js.map +0 -1
  199. package/dist/esm/column.module.039d872c.css +0 -151
  200. package/dist/esm/column.module.039d872c.css.map +0 -1
  201. package/dist/esm/column.module.e632868a.js +0 -19
  202. package/dist/esm/column.module.e632868a.js.map +0 -1
  203. package/dist/esm/composite.608a4ca2.js +0 -153
  204. package/dist/esm/composite.608a4ca2.js.map +0 -1
  205. package/dist/esm/core.4db8e452.js.map +0 -1
  206. package/dist/esm/helpers.8a03cfc7.js +0 -94
  207. package/dist/esm/helpers.8a03cfc7.js.map +0 -1
  208. package/dist/esm/index.module.0844afd8.css +0 -65
  209. package/dist/esm/index.module.0844afd8.css.map +0 -1
  210. package/dist/esm/index.module.24fe3a2e.js +0 -37
  211. package/dist/esm/index.module.24fe3a2e.js.map +0 -1
  212. package/dist/esm/layers.ad5fd25d.js +0 -231
  213. package/dist/esm/layers.ad5fd25d.js.map +0 -1
  214. package/dist/esm/map.7aa26f17.js +0 -82
  215. package/dist/esm/map.7aa26f17.js.map +0 -1
  216. package/dist/esm/names.f6a4e9a4.js.map +0 -1
  217. package/dist/esm/providers.cd1e652f.js +0 -25
  218. package/dist/esm/providers.cd1e652f.js.map +0 -1
  219. package/dist/esm/resolvers.b5c82b78.js.map +0 -1
  220. package/dist/esm/section.cc1b1100.js +0 -118
  221. package/dist/esm/section.cc1b1100.js.map +0 -1
  222. package/dist/esm/selection-popover.17d1bd55.js +0 -60
  223. package/dist/esm/selection-popover.17d1bd55.js.map +0 -1
  224. package/dist/esm/selection-popover.module.0a701258.css.map +0 -1
  225. package/dist/esm/selection-popover.module.e22f5183.js +0 -22
  226. package/dist/esm/selection-popover.module.e22f5183.js.map +0 -1
  227. package/dist/esm/selection.bbf26d0e.js +0 -117
  228. package/dist/esm/selection.bbf26d0e.js.map +0 -1
  229. package/dist/esm/store.25eaa168.js +0 -18
  230. package/dist/esm/store.25eaa168.js.map +0 -1
  231. package/dist/esm/types.f016e032.js +0 -18
  232. package/dist/esm/types.f016e032.js.map +0 -1
  233. package/dist/esm/unit-details.56ff8b70.js +0 -209
  234. package/dist/esm/unit-details.56ff8b70.js.map +0 -1
  235. package/dist/esm/units.361088d4.js +0 -42
  236. package/dist/esm/units.361088d4.js.map +0 -1
  237. package/src/helpers.ts +0 -133
  238. package/src/providers.ts +0 -34
  239. package/src/selection-popover.ts +0 -71
  240. package/src/store.ts +0 -12
  241. package/src/units/units.scss +0 -16
  242. /package/src/{map → maps/column-navigation/svg}/animated.ts +0 -0
@@ -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
+ }