@macrostrat/column-views 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/esm/{column-views.afb48e8c.js → column-views.07db2ab1.js} +8 -8
  3. package/dist/esm/{column-views.afb48e8c.js.map → column-views.07db2ab1.js.map} +1 -1
  4. package/dist/esm/{column-views.32a83292.js → column-views.0e06c069.js} +7 -7
  5. package/dist/esm/{column-views.32a83292.js.map → column-views.0e06c069.js.map} +1 -1
  6. package/dist/esm/{column-views.52a6eb47.js → column-views.103b1cb0.js} +2 -2
  7. package/dist/esm/{column-views.52a6eb47.js.map → column-views.103b1cb0.js.map} +1 -1
  8. package/dist/esm/{column-views.a91dde4a.js → column-views.2e0ff311.js} +3 -3
  9. package/dist/esm/{column-views.a91dde4a.js.map → column-views.2e0ff311.js.map} +1 -1
  10. package/dist/esm/column-views.323cad41.js +11 -0
  11. package/dist/esm/{column-views.c322a5e7.js.map → column-views.323cad41.js.map} +1 -1
  12. package/dist/esm/{column-views.3ba9213d.js → column-views.34a1ac4f.js} +33 -5
  13. package/dist/esm/column-views.34a1ac4f.js.map +1 -0
  14. package/dist/esm/{column-views.c8e2983a.js → column-views.3729c372.js} +4 -4
  15. package/dist/esm/{column-views.c8e2983a.js.map → column-views.3729c372.js.map} +1 -1
  16. package/dist/esm/{column-views.813d5bba.js → column-views.3b637517.js} +9 -5
  17. package/dist/esm/column-views.3b637517.js.map +1 -0
  18. package/dist/esm/{column-views.2ca34210.js → column-views.3d001ab8.js} +5 -5
  19. package/dist/esm/{column-views.2ca34210.js.map → column-views.3d001ab8.js.map} +1 -1
  20. package/dist/esm/{column-views.5cc09c1d.js → column-views.3f246167.js} +9 -2
  21. package/dist/esm/column-views.3f246167.js.map +1 -0
  22. package/dist/esm/{column-views.bcffe6e5.js → column-views.43fb819d.js} +3 -3
  23. package/dist/esm/{column-views.bcffe6e5.js.map → column-views.43fb819d.js.map} +1 -1
  24. package/dist/esm/{column-views.89b9e542.js → column-views.49adc09e.js} +2 -2
  25. package/dist/esm/{column-views.89b9e542.js.map → column-views.49adc09e.js.map} +1 -1
  26. package/dist/esm/{column-views.7e350ae2.js → column-views.53f4160e.js} +3 -3
  27. package/dist/esm/{column-views.7e350ae2.js.map → column-views.53f4160e.js.map} +1 -1
  28. package/dist/esm/{column-views.f13a1d6e.js → column-views.572b70fd.js} +2 -2
  29. package/dist/esm/{column-views.f13a1d6e.js.map → column-views.572b70fd.js.map} +1 -1
  30. package/dist/esm/{column-views.fa19cea0.js → column-views.60dc6bfc.js} +2 -2
  31. package/dist/esm/{column-views.fa19cea0.js.map → column-views.60dc6bfc.js.map} +1 -1
  32. package/dist/esm/{column-views.1af9761e.js → column-views.64a84c43.js} +1 -2
  33. package/dist/esm/column-views.64a84c43.js.map +1 -0
  34. package/dist/esm/{column-views.b40b2bf6.js → column-views.6ca980ae.js} +2 -2
  35. package/dist/esm/{column-views.b40b2bf6.js.map → column-views.6ca980ae.js.map} +1 -1
  36. package/dist/esm/{column-views.10eba967.js → column-views.6d5e3098.js} +3 -3
  37. package/dist/esm/{column-views.10eba967.js.map → column-views.6d5e3098.js.map} +1 -1
  38. package/dist/esm/{column-views.85c6a716.js → column-views.6dc251d3.js} +2 -2
  39. package/dist/esm/{column-views.85c6a716.js.map → column-views.6dc251d3.js.map} +1 -1
  40. package/dist/esm/{column-views.2d8e0e0f.js → column-views.7d47a72a.js} +3 -3
  41. package/dist/esm/{column-views.2d8e0e0f.js.map → column-views.7d47a72a.js.map} +1 -1
  42. package/dist/esm/{column-views.0f2121e4.js → column-views.9771145a.js} +75 -29
  43. package/dist/esm/column-views.9771145a.js.map +1 -0
  44. package/dist/esm/{column-views.6549388a.js → column-views.9e1c82fe.js} +2 -2
  45. package/dist/esm/{column-views.6549388a.js.map → column-views.9e1c82fe.js.map} +1 -1
  46. package/dist/esm/{column-views.892ce22f.js → column-views.a23b2c92.js} +35 -10
  47. package/dist/esm/column-views.a23b2c92.js.map +1 -0
  48. package/dist/esm/{column-views.d2037465.js → column-views.a2cf8f33.js} +3 -3
  49. package/dist/esm/{column-views.d2037465.js.map → column-views.a2cf8f33.js.map} +1 -1
  50. package/dist/esm/column-views.a5c1bbf0.js +60 -0
  51. package/dist/esm/column-views.a5c1bbf0.js.map +1 -0
  52. package/dist/esm/{column-views.b9fe5176.js → column-views.a8926321.js} +2 -2
  53. package/dist/esm/{column-views.b9fe5176.js.map → column-views.a8926321.js.map} +1 -1
  54. package/dist/esm/{column-views.e20f6a4b.js → column-views.abe90091.js} +2 -2
  55. package/dist/esm/{column-views.e20f6a4b.js.map → column-views.abe90091.js.map} +1 -1
  56. package/dist/esm/{column-views.217078ab.css → column-views.b12a6374.css} +9 -1
  57. package/dist/esm/column-views.b12a6374.css.map +1 -0
  58. package/dist/esm/{column-views.439a26db.css → column-views.b72918ce.css} +45 -20
  59. package/dist/esm/column-views.b72918ce.css.map +1 -0
  60. package/dist/esm/{column-views.4637f4ce.js → column-views.cdadc5c2.js} +4 -1
  61. package/dist/esm/column-views.cdadc5c2.js.map +1 -0
  62. package/dist/esm/{column-views.c25e8b32.js → column-views.d099eaf9.js} +3 -3
  63. package/dist/esm/{column-views.c25e8b32.js.map → column-views.d099eaf9.js.map} +1 -1
  64. package/dist/esm/{column-views.fef7389f.js → column-views.d48cb0d8.js} +10 -1
  65. package/dist/esm/column-views.d48cb0d8.js.map +1 -0
  66. package/dist/esm/{column-views.59bb0cba.js → column-views.f7523c1d.js} +2 -2
  67. package/dist/esm/{column-views.59bb0cba.js.map → column-views.f7523c1d.js.map} +1 -1
  68. package/dist/esm/{column-views.28b3eaa0.js → column-views.ff031876.js} +3 -3
  69. package/dist/esm/{column-views.28b3eaa0.js.map → column-views.ff031876.js.map} +1 -1
  70. package/dist/esm/index.d.ts +50 -13
  71. package/dist/esm/index.d.ts.map +1 -1
  72. package/dist/esm/index.js +10 -10
  73. package/dist/node/{column-views.6f0c1134.js → column-views.0bb1ec93.js} +2 -2
  74. package/dist/node/{column-views.6f0c1134.js.map → column-views.0bb1ec93.js.map} +1 -1
  75. package/dist/node/{column-views.2877f398.js → column-views.0cbd4a3f.js} +2 -2
  76. package/dist/node/{column-views.2877f398.js.map → column-views.0cbd4a3f.js.map} +1 -1
  77. package/dist/node/{column-views.770d2c95.js → column-views.13c4ea85.js} +2 -2
  78. package/dist/node/{column-views.770d2c95.js.map → column-views.13c4ea85.js.map} +1 -1
  79. package/dist/node/{column-views.3cb3345e.js → column-views.226d0bdb.js} +2 -2
  80. package/dist/node/{column-views.3cb3345e.js.map → column-views.226d0bdb.js.map} +1 -1
  81. package/dist/node/column-views.2926f656.css +2 -0
  82. package/dist/node/column-views.2926f656.css.map +1 -0
  83. package/dist/node/{column-views.45defa84.js → column-views.2ab1c2f8.js} +2 -2
  84. package/dist/node/{column-views.45defa84.js.map → column-views.2ab1c2f8.js.map} +1 -1
  85. package/dist/node/{column-views.3bd09ad6.js → column-views.31f57130.js} +2 -2
  86. package/dist/node/{column-views.3bd09ad6.js.map → column-views.31f57130.js.map} +1 -1
  87. package/dist/node/{column-views.ce6808fe.js → column-views.36094762.js} +2 -2
  88. package/dist/node/{column-views.ce6808fe.js.map → column-views.36094762.js.map} +1 -1
  89. package/dist/node/{column-views.39c07f5f.js → column-views.372bbee2.js} +2 -2
  90. package/dist/node/{column-views.39c07f5f.js.map → column-views.372bbee2.js.map} +1 -1
  91. package/dist/node/column-views.38357d4a.js +2 -0
  92. package/dist/node/column-views.38357d4a.js.map +1 -0
  93. package/dist/node/{column-views.39d3a0be.js → column-views.3d220e0c.js} +2 -2
  94. package/dist/node/{column-views.39d3a0be.js.map → column-views.3d220e0c.js.map} +1 -1
  95. package/dist/node/column-views.3eeac38d.js +2 -0
  96. package/dist/node/column-views.3eeac38d.js.map +1 -0
  97. package/dist/node/column-views.3f032518.js +2 -0
  98. package/dist/node/column-views.3f032518.js.map +1 -0
  99. package/dist/node/{column-views.7350ac73.js → column-views.42db0bb8.js} +2 -2
  100. package/dist/node/{column-views.7350ac73.js.map → column-views.42db0bb8.js.map} +1 -1
  101. package/dist/node/{column-views.6b6b756b.js → column-views.4381c411.js} +2 -2
  102. package/dist/node/{column-views.6b6b756b.js.map → column-views.4381c411.js.map} +1 -1
  103. package/dist/node/{column-views.6b441349.js → column-views.50034105.js} +2 -2
  104. package/dist/node/{column-views.6b441349.js.map → column-views.50034105.js.map} +1 -1
  105. package/dist/node/{column-views.f76ba19f.js → column-views.507635e2.js} +2 -2
  106. package/dist/node/{column-views.f76ba19f.js.map → column-views.507635e2.js.map} +1 -1
  107. package/dist/node/column-views.556e8f69.js +2 -0
  108. package/dist/node/column-views.556e8f69.js.map +1 -0
  109. package/dist/node/{column-views.6da49480.js → column-views.5f05b73f.js} +2 -2
  110. package/dist/node/column-views.5f05b73f.js.map +1 -0
  111. package/dist/node/column-views.6ae7bb69.js +2 -0
  112. package/dist/node/column-views.6ae7bb69.js.map +1 -0
  113. package/dist/node/{column-views.2a70b9a2.js → column-views.6c7a40e0.js} +2 -2
  114. package/dist/node/{column-views.2a70b9a2.js.map → column-views.6c7a40e0.js.map} +1 -1
  115. package/dist/node/{column-views.664dc6c9.js → column-views.7010a03b.js} +2 -2
  116. package/dist/node/{column-views.664dc6c9.js.map → column-views.7010a03b.js.map} +1 -1
  117. package/dist/node/column-views.75b0a8f8.js +2 -0
  118. package/dist/node/column-views.75b0a8f8.js.map +1 -0
  119. package/dist/node/column-views.99fb74c0.js +2 -0
  120. package/dist/node/column-views.99fb74c0.js.map +1 -0
  121. package/dist/node/column-views.a2274834.js +2 -0
  122. package/dist/node/column-views.a2274834.js.map +1 -0
  123. package/dist/node/column-views.adf9e5b3.js +2 -0
  124. package/dist/node/column-views.adf9e5b3.js.map +1 -0
  125. package/dist/node/column-views.af275c48.js +2 -0
  126. package/dist/node/column-views.af275c48.js.map +1 -0
  127. package/dist/node/column-views.afbf351c.js +2 -0
  128. package/dist/node/column-views.afbf351c.js.map +1 -0
  129. package/dist/node/{column-views.b773edb8.js → column-views.b180e8c9.js} +2 -2
  130. package/dist/node/{column-views.b773edb8.js.map → column-views.b180e8c9.js.map} +1 -1
  131. package/dist/node/{column-views.cf90f63d.js → column-views.c18d5bf5.js} +2 -2
  132. package/dist/node/{column-views.cf90f63d.js.map → column-views.c18d5bf5.js.map} +1 -1
  133. package/dist/node/{column-views.0859f5d2.js → column-views.c7f6fc0a.js} +2 -2
  134. package/dist/node/{column-views.0859f5d2.js.map → column-views.c7f6fc0a.js.map} +1 -1
  135. package/dist/node/{column-views.4e2bdf9b.js → column-views.db5d74bd.js} +2 -2
  136. package/dist/node/{column-views.4e2bdf9b.js.map → column-views.db5d74bd.js.map} +1 -1
  137. package/dist/node/{column-views.d9bbd6fb.css → column-views.e1a43131.css} +2 -2
  138. package/dist/node/column-views.e1a43131.css.map +1 -0
  139. package/dist/node/{column-views.0220026c.js → column-views.e4f18ff7.js} +2 -2
  140. package/dist/node/{column-views.0220026c.js.map → column-views.e4f18ff7.js.map} +1 -1
  141. package/dist/node/{column-views.12a70e9d.js → column-views.f15a6ed4.js} +2 -2
  142. package/dist/node/{column-views.12a70e9d.js.map → column-views.f15a6ed4.js.map} +1 -1
  143. package/dist/node/{column-views.5b6833f0.js → column-views.f17b6142.js} +2 -2
  144. package/dist/node/{column-views.5b6833f0.js.map → column-views.f17b6142.js.map} +1 -1
  145. package/dist/node/column-views.fc05616e.js +2 -0
  146. package/dist/node/column-views.fc05616e.js.map +1 -0
  147. package/dist/node/index.js +1 -1
  148. package/dist/node/index.js.map +1 -1
  149. package/package.json +6 -6
  150. package/src/age-axis.ts +11 -6
  151. package/src/column.module.sass +6 -0
  152. package/src/column.ts +23 -1
  153. package/src/data-provider/base.ts +49 -2
  154. package/src/data-provider/fetch.ts +15 -0
  155. package/src/unit-details/index.ts +1 -0
  156. package/src/unit-details/modal-panel.ts +61 -0
  157. package/src/unit-details/panel.module.sass +41 -17
  158. package/src/unit-details/panel.ts +114 -36
  159. package/src/units/selection.ts +0 -1
  160. package/dist/esm/column-views.0f2121e4.js.map +0 -1
  161. package/dist/esm/column-views.1af9761e.js.map +0 -1
  162. package/dist/esm/column-views.217078ab.css.map +0 -1
  163. package/dist/esm/column-views.3ba9213d.js.map +0 -1
  164. package/dist/esm/column-views.439a26db.css.map +0 -1
  165. package/dist/esm/column-views.4637f4ce.js.map +0 -1
  166. package/dist/esm/column-views.5cc09c1d.js.map +0 -1
  167. package/dist/esm/column-views.813d5bba.js.map +0 -1
  168. package/dist/esm/column-views.892ce22f.js.map +0 -1
  169. package/dist/esm/column-views.c322a5e7.js +0 -9
  170. package/dist/esm/column-views.fef7389f.js.map +0 -1
  171. package/dist/node/column-views.04407342.js +0 -2
  172. package/dist/node/column-views.04407342.js.map +0 -1
  173. package/dist/node/column-views.059a41c1.js +0 -2
  174. package/dist/node/column-views.059a41c1.js.map +0 -1
  175. package/dist/node/column-views.10a2bad6.js +0 -2
  176. package/dist/node/column-views.10a2bad6.js.map +0 -1
  177. package/dist/node/column-views.12414005.js +0 -2
  178. package/dist/node/column-views.12414005.js.map +0 -1
  179. package/dist/node/column-views.1de87649.js +0 -2
  180. package/dist/node/column-views.1de87649.js.map +0 -1
  181. package/dist/node/column-views.6da49480.js.map +0 -1
  182. package/dist/node/column-views.7f951eeb.js +0 -2
  183. package/dist/node/column-views.7f951eeb.js.map +0 -1
  184. package/dist/node/column-views.9771eb09.css +0 -2
  185. package/dist/node/column-views.9771eb09.css.map +0 -1
  186. package/dist/node/column-views.9f796135.js +0 -2
  187. package/dist/node/column-views.9f796135.js.map +0 -1
  188. package/dist/node/column-views.a0aac838.js +0 -2
  189. package/dist/node/column-views.a0aac838.js.map +0 -1
  190. package/dist/node/column-views.a8ffe072.js +0 -2
  191. package/dist/node/column-views.a8ffe072.js.map +0 -1
  192. package/dist/node/column-views.aa50c532.js +0 -2
  193. package/dist/node/column-views.aa50c532.js.map +0 -1
  194. package/dist/node/column-views.cd3c430b.js +0 -2
  195. package/dist/node/column-views.cd3c430b.js.map +0 -1
  196. package/dist/node/column-views.d9bbd6fb.css.map +0 -1
@@ -134,3 +134,9 @@ body:global(.dark-mode) .column-container
134
134
  --unit-font-style: normal
135
135
 
136
136
 
137
+ .column-title-row
138
+ display: flex
139
+ flex-direction: row
140
+ gap: 1em
141
+ justify-content: space-between
142
+ align-items: baseline
package/src/column.ts CHANGED
@@ -12,7 +12,11 @@ import {
12
12
  } from "./units";
13
13
 
14
14
  import { ColumnHeightScaleOptions } from "./prepare-units/composite-scale";
15
- import { UnitSelectionPopover } from "./unit-details";
15
+ import {
16
+ Identifier,
17
+ ReferencesField,
18
+ UnitSelectionPopover,
19
+ } from "./unit-details";
16
20
  import {
17
21
  MacrostratColumnDataProvider,
18
22
  useCompositeScale,
@@ -27,6 +31,7 @@ import { CompositeAgeAxis } from "./age-axis";
27
31
  import { MergeSectionsMode, usePreparedColumnUnits } from "./prepare-units";
28
32
  import { UnitLong } from "@macrostrat/api-types";
29
33
  import { NonIdealState } from "@blueprintjs/core";
34
+ import { DataField } from "@macrostrat/data-components";
30
35
 
31
36
  const h = hyperStyled(styles);
32
37
 
@@ -270,3 +275,20 @@ export function ColumnContainer(props: ColumnContainerProps) {
270
275
  ...rest,
271
276
  });
272
277
  }
278
+
279
+ export function ColumnBasicInfo({ data, showColumnID = true }) {
280
+ if (data == null) return null;
281
+ return h("div.column-info", [
282
+ h("div.column-title-row", [
283
+ h("h2", data.col_name),
284
+ h.if(showColumnID)("h4", h(Identifier, { id: data.col_id })),
285
+ ]),
286
+ h(DataField, { row: true, label: "Group", value: data.col_group }),
287
+ h(ReferencesField, {
288
+ refs: data.refs,
289
+ inline: false,
290
+ row: true,
291
+ className: "column-refs",
292
+ }),
293
+ ]);
294
+ }
@@ -8,6 +8,7 @@ import {
8
8
  ColumnGeoJSONRecordWithID,
9
9
  Environment,
10
10
  MacrostratRef,
11
+ StratName,
11
12
  } from "@macrostrat/api-types";
12
13
  import {
13
14
  fetchAllColumns,
@@ -15,6 +16,7 @@ import {
15
16
  fetchIntervals,
16
17
  fetchLithologies,
17
18
  fetchRefs,
19
+ fetchStratNames,
18
20
  } from "./fetch";
19
21
  import { APIProvider } from "@macrostrat/ui-components";
20
22
  import { ColumnProvider } from "@macrostrat/column-components";
@@ -55,6 +57,9 @@ interface MacrostratStore extends RefsSlice {
55
57
  projectID: number | null,
56
58
  inProcess: boolean,
57
59
  ): Promise<ColumnGeoJSONRecord[]>;
60
+ // Strat names unify both "strat names" and "concepts"
61
+ stratNames: Map<number, StratName> | null;
62
+ getStratNames(ids: number[] | null): Promise<StratName[]>;
58
63
  }
59
64
 
60
65
  function createMacrostratStore(
@@ -83,6 +88,7 @@ function createMacrostratStore(
83
88
  ...createEnvironmentsSlice(set, get),
84
89
  ...createColumnsSlice(set, get),
85
90
  ...createRefsSlice(set, get),
91
+ ...createStratNamesSlice(set, get),
86
92
  };
87
93
  });
88
94
  }
@@ -229,6 +235,34 @@ function createIntervalsSlice(set, get) {
229
235
  };
230
236
  }
231
237
 
238
+ function createStratNamesSlice(set, get) {
239
+ return {
240
+ stratNames: null,
241
+ async getStratNames(ids: number[] | null): Promise<StratName[]> {
242
+ const { stratNames, fetch } = get();
243
+ let nameMap = stratNames ?? new Map();
244
+ let stratNamesAlreadyLoaded = [];
245
+ let stratNamesToLoad = [];
246
+ for (const id of ids) {
247
+ if (nameMap.has(id)) {
248
+ stratNamesAlreadyLoaded.push(nameMap.get(id));
249
+ } else {
250
+ stratNamesToLoad.push(id);
251
+ }
252
+ }
253
+ if (stratNamesToLoad.length > 0) {
254
+ const data = await fetchStratNames(stratNamesToLoad, fetch);
255
+ if (data == null) return stratNamesAlreadyLoaded;
256
+ for (const d of data) {
257
+ nameMap.set(d.strat_name_id, d);
258
+ }
259
+ set({ stratNames: nameMap });
260
+ }
261
+ return ids.map((id) => nameMap.get(id));
262
+ },
263
+ };
264
+ }
265
+
232
266
  function includesTimescale(intervals: Map<number, any>, timescaleID: number) {
233
267
  if (intervals == null) return false;
234
268
  if (timescaleID == null) return true;
@@ -251,12 +285,21 @@ export function useMacrostratStore(selector: MacrostratSelector | "api") {
251
285
  return useStore(ctx, selector);
252
286
  }
253
287
 
288
+ type DataTypeKey =
289
+ | "lithologies"
290
+ | "intervals"
291
+ | "columns"
292
+ | "environments"
293
+ | "refs"
294
+ | "strat_names";
295
+
254
296
  const dataTypeMapping = {
255
297
  lithologies: (store) => store.getLithologies,
256
298
  intervals: (store) => store.getIntervals,
257
299
  columns: (store) => store.getColumns,
258
300
  environments: (store) => store.getEnvironments,
259
301
  refs: (store) => store.getRefs,
302
+ strat_names: (store) => store.getStratNames,
260
303
  };
261
304
 
262
305
  export function useMacrostratDefs(dataType: string): Map<number, any> | null {
@@ -299,14 +342,18 @@ export function useMacrostratColumns(
299
342
  }, [colData, inProcess]);
300
343
  }
301
344
 
302
- export function useMacrostratData(dataType: string, ...args: any[]) {
345
+ export function useMacrostratData(dataType: DataTypeKey, ...args: any[]) {
303
346
  const selector = dataTypeMapping[dataType];
304
347
  const operator = useMacrostratStore(selector);
305
348
 
306
349
  const [value, setValue] = useState(null);
307
350
 
308
351
  useEffect(() => {
309
- operator(...args).then(setValue);
352
+ try {
353
+ operator(...args).then(setValue);
354
+ } catch (e) {
355
+ console.error(e);
356
+ }
310
357
  }, [operator, ...args]);
311
358
 
312
359
  return value;
@@ -2,6 +2,8 @@ import {
2
2
  ColumnGeoJSONRecord,
3
3
  ColumnGeoJSONRecordWithID,
4
4
  MacrostratRef,
5
+ StratName,
6
+ StratUnit,
5
7
  UnitLong,
6
8
  } from "@macrostrat/api-types";
7
9
  import {
@@ -201,6 +203,19 @@ export async function fetchRefs(
201
203
  return await unwrapResponse(res);
202
204
  }
203
205
 
206
+ export async function fetchStratNames(
207
+ names: number[],
208
+ fetch = defaultFetch,
209
+ ): Promise<StratName[]> {
210
+ let url = `/defs/strat_names`;
211
+ if (names.length == 0) {
212
+ return [];
213
+ }
214
+ url += "?strat_name_id=" + names.join(",");
215
+ const res = await fetch(url);
216
+ return await unwrapResponse(res);
217
+ }
218
+
204
219
  export type ColumnData = {
205
220
  units: UnitLong[];
206
221
  columnID: number;
@@ -1,2 +1,3 @@
1
1
  export * from "./panel";
2
2
  export * from "./popover";
3
+ export * from "./modal-panel";
@@ -0,0 +1,61 @@
1
+ import { Button } from "@blueprintjs/core";
2
+ import { UnitDetailsPanel } from "./panel";
3
+ import { useKeyHandler } from "@macrostrat/ui-components";
4
+ import h from "@macrostrat/hyper";
5
+
6
+ export function UnitDetailsPanelWithNavigation(props) {
7
+ const { unitData, className, selectedUnit, onSelectUnit, features, ...rest } =
8
+ props;
9
+
10
+ const ix = unitData?.findIndex(
11
+ (unit) => unit.unit_id === selectedUnit?.unit_id,
12
+ );
13
+
14
+ const keyMap = {
15
+ 38: ix - 1,
16
+ 40: ix + 1,
17
+ };
18
+
19
+ useKeyHandler(
20
+ (event) => {
21
+ const nextIx = keyMap[event.keyCode];
22
+ if (nextIx == null || nextIx < 0 || nextIx >= unitData.length) return;
23
+ onSelectUnit(unitData[nextIx].unit_id);
24
+ event.stopPropagation();
25
+ },
26
+ [unitData, ix],
27
+ );
28
+
29
+ if (selectedUnit == null) return null;
30
+
31
+ const actions = h([
32
+ h(Button, {
33
+ icon: "arrow-up",
34
+ disabled: ix === 0,
35
+ onClick() {
36
+ onSelectUnit(unitData[ix - 1]?.unit_id);
37
+ },
38
+ }),
39
+ h(Button, {
40
+ icon: "arrow-down",
41
+ disabled: ix === unitData.length - 1,
42
+ onClick() {
43
+ onSelectUnit(unitData[ix + 1]?.unit_id);
44
+ },
45
+ }),
46
+ ]);
47
+
48
+ return h(UnitDetailsPanel, {
49
+ unit: selectedUnit,
50
+ onClose(event) {
51
+ onSelectUnit(null);
52
+ },
53
+ className,
54
+ actions,
55
+ showLithologyProportions: true,
56
+ selectUnit: onSelectUnit,
57
+ columnUnits: unitData,
58
+ features,
59
+ ...rest,
60
+ });
61
+ }
@@ -1,39 +1,43 @@
1
1
  .legend-panel-header
2
2
  display: flex
3
3
  justify-content: space-between
4
- align-items: baseline
5
- gap: 1em
4
+ align-items: center
5
+ gap: 0.5em
6
6
  border-bottom: 1px solid var(--panel-rule-color)
7
7
  position: sticky
8
8
  top: 0
9
9
  background-color: var(--panel-secondary-background-color)
10
10
  padding: 0.5em 1em
11
11
  z-index: 50
12
+ min-height: 45px
13
+ overflow: hidden
12
14
  .title-container
13
- display: flex
14
- flex-direction: row
15
15
  gap: 0.5em
16
16
  align-items: center
17
- margin: -0.5em 0
17
+ margin: 0
18
+ flex-grow: 1
19
+ z-index: 5
18
20
  &:hover
19
- .hidden-actions
20
- display: flex
21
- opacity: 0.5
21
+ .hidden-actions-container
22
+ visibility: visible
22
23
  h1, h2, h3
23
- margin: 0.5em 0
24
- .hidden-actions
25
- display: none
24
+ display: inline
25
+ margin: 0
26
+ .hidden-actions-container
27
+ visibility: hidden
26
28
  button
27
29
  transform: translateY(0px)
28
30
 
29
31
  code
30
32
  font-size: 0.9em
31
33
  color: var(--secondary-color)
34
+ .unit-id:before
35
+ content: '#'
36
+ // Tertiary color is too light...
37
+ color: var(--secondary-color)
38
+
32
39
  .spacer
33
40
  flex: 1
34
- button
35
- line-height: 1.5
36
- transform: translateY(2px)
37
41
 
38
42
  .unit-details-panel
39
43
  display: flex
@@ -46,11 +50,11 @@
46
50
  position: relative
47
51
  margin: 1em
48
52
 
49
- .proportion, .sep, .no-units
53
+ .proportion, .sep, .no-units, .strat-name-text
50
54
  color: var(--secondary-color)
51
55
  font-style: italic
52
56
 
53
- .strat-name-id, .unit-id
57
+ .strat-name-id, .identifier
54
58
  font-family: var(--monospace-font)
55
59
  color: var(--secondary-color)
56
60
 
@@ -81,4 +85,24 @@
81
85
  margin: 0 0.3em
82
86
 
83
87
  .clickable
84
- cursor: pointer
88
+ cursor: pointer
89
+
90
+ .hidden-actions-container
91
+ min-width: 0
92
+ display: inline-block
93
+ //margin-right: -5em
94
+ width: 0
95
+ position: relative
96
+
97
+ .hidden-actions
98
+ padding-left: 1em
99
+ width: fit-content
100
+ display: flex
101
+ align-items: center
102
+ gap: 0.25em
103
+ background-color: var(--panel-secondary-background-color)
104
+ z-index: 50
105
+ position: relative
106
+ bottom: 0
107
+ button
108
+ color: var(--secondary-color) !important
@@ -21,6 +21,7 @@ import {
21
21
  UnitLongFull,
22
22
  Lithology,
23
23
  Interval,
24
+ StratUnit,
24
25
  } from "@macrostrat/api-types";
25
26
  import { defaultNameFunction } from "../units/names";
26
27
  import classNames from "classnames";
@@ -113,10 +114,15 @@ export function LegendPanelHeader({
113
114
  return h("header.legend-panel-header", [
114
115
  h("div.title-container", [
115
116
  h.if(title != null)("h3", title),
116
- h.if(hiddenActions != null)("div.hidden-actions", hiddenActions),
117
+ h.if(hiddenActions != null || id != null)(
118
+ "span.hidden-actions-container",
119
+ h("div.hidden-actions", [
120
+ h.if(id != null)("code.unit-id", id),
121
+ h.if(hiddenActions != null)([hiddenActions]),
122
+ ]),
123
+ ),
117
124
  ]),
118
125
  h("div.spacer"),
119
- h.if(id != null)("code", id),
120
126
  h.if(actions != null)(ButtonGroup, { minimal: true }, actions),
121
127
  h.if(onClose != null)(Button, {
122
128
  icon: "cross",
@@ -159,7 +165,12 @@ function UnitDetailsContent({
159
165
  features?: Set<UnitDetailsFeature>;
160
166
  onClickItem?: (
161
167
  event: MouseEvent,
162
- item: Lithology | Environment | UnitLong | Interval,
168
+ item:
169
+ | Lithology
170
+ | Environment
171
+ | UnitLong
172
+ | Interval
173
+ | { strat_name_id: number },
163
174
  ) => void;
164
175
  getItemHref?: (item: Lithology | Environment | UnitLong) => string | null;
165
176
  }) {
@@ -222,7 +233,7 @@ function UnitDetailsContent({
222
233
 
223
234
  /** We are trying to move away from passing the "color" parameter in the API */
224
235
  let colorSwatch: ReactNode = null;
225
- if ("color" in unit) {
236
+ if ("color" in unit && features.has(UnitDetailsFeature.Color)) {
226
237
  const unit1 = unit as UnitLongFull;
227
238
  colorSwatch = h("div.color-swatch", {
228
239
  style: { backgroundColor: unit1.color },
@@ -250,20 +261,9 @@ function UnitDetailsContent({
250
261
  onClickItem,
251
262
  getItemHref,
252
263
  }),
253
- h.if(unit.strat_name_id != null)(
254
- DataField,
255
- {
256
- label: "Stratigraphic name",
257
- },
258
- h(
259
- "span",
260
- {
261
- className: "strat-name-id" + (onClickItem ? " clickable" : ""),
262
- onClick: (e) => onClickItem(e, { strat_name_id: unit.strat_name_id }),
263
- },
264
- unit.strat_name_id,
265
- ),
266
- ),
264
+ h.if(unit.strat_name_id != null)(StratNameField, {
265
+ strat_name_id: unit.strat_name_id,
266
+ }),
267
267
  outcropField,
268
268
  h.if(features.has(UnitDetailsFeature.AdjacentUnits))([
269
269
  h(
@@ -278,12 +278,61 @@ function UnitDetailsContent({
278
278
  ),
279
279
  ]),
280
280
  colorSwatch,
281
+ h(ReferencesField, { refs: unit.refs, inline: true }),
282
+ ]);
283
+ }
284
+
285
+ export function ReferencesField({ refs, className = null, ...rest }) {
286
+ if (refs == null || refs.length === 0) {
287
+ return null;
288
+ }
289
+ return h(
290
+ DataField,
291
+ {
292
+ label: "Source",
293
+ className: classNames("refs-field", className),
294
+ ...rest,
295
+ },
296
+ h(BibInfo, { refs }),
297
+ );
298
+ }
299
+
300
+ function StratNameField({
301
+ strat_name_id,
302
+ onClickItem,
303
+ }: {
304
+ strat_name_id: number;
305
+ onClickItem?: (event: MouseEvent, item: { strat_name_id: number }) => void;
306
+ }) {
307
+ const stratNames = useMemo(() => [strat_name_id], [strat_name_id]);
308
+ const data = useMacrostratData("strat_names", stratNames);
309
+ const stratNameData = data?.[0];
310
+ let inner: any = h(Identifier, { id: strat_name_id });
311
+ const name = stratNameData?.strat_name_long;
312
+ if (name != null) {
313
+ inner = h("span.strat-name", name);
314
+ }
315
+
316
+ const clickable = onClickItem != null;
317
+
318
+ const className = classNames({
319
+ clickable,
320
+ });
321
+
322
+ return h(
323
+ DataField,
324
+ {
325
+ label: "Stratigraphic name",
326
+ },
281
327
  h(
282
- DataField,
283
- { label: "Source", inline: true },
284
- h(BibInfo, { refs: unit.refs }),
328
+ clickable ? "a" : "span",
329
+ {
330
+ className,
331
+ onClick: (e) => onClickItem(e, { strat_name_id }),
332
+ },
333
+ inner,
285
334
  ),
286
- ]);
335
+ );
287
336
  }
288
337
 
289
338
  function getThickness(unit): [string, string] {
@@ -331,12 +380,18 @@ function BibInfo({ refs }) {
331
380
  }
332
381
 
333
382
  if (refData.length == 1) {
334
- return h(Citation, { data: refData[0], tag: "span" });
383
+ return h(Citation, {
384
+ data: refData[0],
385
+ tag: "span",
386
+ key: refData[0].ref_id,
387
+ });
335
388
  }
336
389
 
337
390
  return h(
338
391
  "ul.refs",
339
- refData.map((data, i) => h(Citation, { data, tag: "li", key: i })),
392
+ refData.map((data, i) =>
393
+ h(Citation, { data, tag: "li", key: data.ref_id }),
394
+ ),
340
395
  );
341
396
  }
342
397
 
@@ -474,6 +529,33 @@ function enhanceLithologies(
474
529
  });
475
530
  }
476
531
 
532
+ export function Identifier({
533
+ id,
534
+ onClick,
535
+ className,
536
+ }: {
537
+ id: number | string;
538
+ onClick?: (id: number | string) => void;
539
+ className?: string;
540
+ }) {
541
+ /** An item that displays a numeric identifier, optionally clickable */
542
+ const tag = onClick != null ? "a" : "span";
543
+ return h(
544
+ tag,
545
+ {
546
+ onClick() {
547
+ onClick?.(id);
548
+ },
549
+ className: classNames(
550
+ "identifier",
551
+ { clickable: onClick != null },
552
+ className,
553
+ ),
554
+ },
555
+ id,
556
+ );
557
+ }
558
+
477
559
  function UnitIDList({ units, selectUnit }) {
478
560
  const u1 = units.filter((d) => d != 0);
479
561
 
@@ -489,19 +571,15 @@ function UnitIDList({ units, selectUnit }) {
489
571
  return h(
490
572
  ItemList,
491
573
  { className: "unit-id-list" },
492
- u1.map((unit) => {
493
- return h(
494
- tag,
495
-
496
- {
497
- className: "unit-id",
498
- onClick() {
499
- selectUnit?.(unit.id);
500
- },
501
- key: unit.id,
574
+ u1.map((unitID) => {
575
+ return h(Identifier, {
576
+ className: "unit-id",
577
+ onClick() {
578
+ selectUnit?.(unitID);
502
579
  },
503
- unit,
504
- );
580
+ key: unitID,
581
+ id: unitID,
582
+ });
505
583
  }),
506
584
  );
507
585
  }
@@ -93,7 +93,6 @@ export function UnitSelectionProvider<T extends BaseUnit>(props: {
93
93
  }
94
94
  },
95
95
  onUnitSelected: (unit: T, target: HTMLElement, event: PointerEvent) => {
96
- console.log("onUnitSelected", unit, target, event);
97
96
  const el = props.columnRef?.current;
98
97
  let overlayPosition = null;
99
98
 
@@ -1 +0,0 @@
1
- {"mappings":"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","sources":["packages/column-views/src/unit-details/panel.ts"],"sourcesContent":["import hyper from \"@macrostrat/hyper\";\nimport styles from \"./panel.module.sass\";\nimport { JSONView } from \"@macrostrat/ui-components\";\nimport { Button, ButtonGroup } from \"@blueprintjs/core\";\nimport { ReactNode, useMemo, useState } from \"react\";\nimport {\n DataField,\n EnvironmentsList,\n IntervalShort,\n IntervalTag,\n ItemList,\n LithologyList,\n LithologyTagFeature,\n Parenthetical,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratData, useMacrostratDefs } from \"../data-provider\";\nimport {\n Environment,\n UnitLong,\n UnitLongFull,\n Lithology,\n Interval,\n} from \"@macrostrat/api-types\";\nimport { defaultNameFunction } from \"../units/names\";\nimport classNames from \"classnames\";\n\nconst h = hyper.styled(styles);\n\nexport function UnitDetailsPanel({\n unit,\n onClose,\n className,\n features = new Set<UnitDetailsFeature>([\n UnitDetailsFeature.AdjacentUnits,\n UnitDetailsFeature.OutcropType,\n UnitDetailsFeature.JSONToggle,\n UnitDetailsFeature.DepthRange,\n ]),\n lithologyFeatures,\n actions,\n selectUnit,\n columnUnits,\n onClickItem,\n}: {\n unit: any;\n onClose?: any;\n showLithologyProportions?: boolean;\n className?: string;\n actions?: ReactNode;\n features?: Set<UnitDetailsFeature>;\n lithologyFeatures?: Set<LithologyTagFeature>;\n columnUnits?: UnitLong[];\n selectUnit?: (unitID: number) => void;\n onClickItem?: (item: any) => void;\n}) {\n const [showJSON, setShowJSON] = useState(false);\n\n let content = null;\n if (showJSON) {\n content = h(JSONView, { data: unit, showRoot: false });\n } else {\n content = h(UnitDetailsContent, {\n unit,\n features,\n lithologyFeatures,\n onClickItem,\n });\n }\n\n let title = defaultNameFunction(unit);\n\n let hiddenActions = null;\n if (features.has(UnitDetailsFeature.JSONToggle)) {\n hiddenActions = h(Button, {\n icon: \"code\",\n small: true,\n minimal: true,\n key: \"json-view-toggle\",\n className: classNames(\"json-view-toggle\", { enabled: setShowJSON }),\n onClick(evt) {\n setShowJSON(!showJSON);\n evt.stopPropagation();\n },\n });\n }\n\n return h(\"div.unit-details-panel\", { className }, [\n h(LegendPanelHeader, {\n onClose,\n title,\n id: unit.unit_id,\n actions,\n hiddenActions,\n }),\n h(\"div.unit-details-content-holder\", content),\n ]);\n}\n\nexport function LegendPanelHeader({\n title,\n id,\n onClose,\n actions = null,\n hiddenActions,\n}: {\n title?: string | null;\n id?: number | null;\n onClose?: () => void;\n actions?: ReactNode | null;\n hiddenActions?: ReactNode | null;\n}) {\n return h(\"header.legend-panel-header\", [\n h(\"div.title-container\", [\n h.if(title != null)(\"h3\", title),\n h.if(hiddenActions != null)(\"div.hidden-actions\", hiddenActions),\n ]),\n h(\"div.spacer\"),\n h.if(id != null)(\"code\", id),\n h.if(actions != null)(ButtonGroup, { minimal: true }, actions),\n h.if(onClose != null)(Button, {\n icon: \"cross\",\n minimal: true,\n small: true,\n onClick() {\n onClose();\n },\n }),\n ]);\n}\n\nexport enum UnitDetailsFeature {\n AdjacentUnits = \"adjacent-units\",\n Color = \"color\",\n OutcropType = \"outcrop-type\",\n JSONToggle = \"json-toggle\",\n DepthRange = \"depth-range\",\n}\n\nfunction UnitDetailsContent({\n unit,\n selectUnit,\n columnUnits,\n lithologyFeatures = new Set([\n LithologyTagFeature.Proportion,\n LithologyTagFeature.Attributes,\n ]),\n features = new Set<UnitDetailsFeature>([\n UnitDetailsFeature.AdjacentUnits,\n UnitDetailsFeature.OutcropType,\n ]),\n onClickItem,\n getItemHref,\n}: {\n unit: UnitLong;\n selectUnit?: (unitID: number) => void;\n columnUnits?: UnitLong[];\n lithologyFeatures?: Set<LithologyTagFeature>;\n features?: Set<UnitDetailsFeature>;\n onClickItem?: (\n event: MouseEvent,\n item: Lithology | Environment | UnitLong | Interval,\n ) => void;\n getItemHref?: (item: Lithology | Environment | UnitLong) => string | null;\n}) {\n const lithMap = useMacrostratDefs(\"lithologies\");\n const envMap = useMacrostratDefs(\"environments\");\n\n const environments = enhanceEnvironments(unit.environ, envMap);\n const lithologies = enhanceLithologies(unit.lith ?? [], lithMap);\n\n // Create a lookup table of units if provided\n const columnUnitsMap = useMemo(() => {\n const map = new Map<number, UnitLong>();\n for (const colUnit of columnUnits ?? []) {\n map.set(colUnit.unit_id, colUnit);\n }\n return map;\n }, [columnUnits]);\n\n let outcropField = null;\n if (features.has(UnitDetailsFeature.OutcropType)) {\n // Determine outcrop type\n let outcrop = unit.outcrop;\n if (outcrop == \"both\") {\n outcrop = \"surface and subsurface\";\n }\n outcropField = h(DataField, {\n label: \"Outcrop\",\n value: outcrop,\n });\n }\n\n let thicknessOrHeightRange = null;\n const [thickness, thicknessUnit] = getThickness(unit);\n // Proxy for actual heights in t_pos and b_pos\n if (\n features.has(UnitDetailsFeature.DepthRange) &&\n unit.t_pos != null &&\n unit.b_pos != null &&\n unit.min_thick == unit.max_thick && // We have an actual fixed height\n unit.min_thick != 0 // Not a zero thickness\n ) {\n const label = unit.t_pos < unit.b_pos ? \"Depth\" : \"Height\";\n const u1 = \"m\";\n\n thicknessOrHeightRange = h(DataField, {\n unit: u1,\n label,\n value: formatRange(unit.b_pos, unit.t_pos),\n children: h(\n Parenthetical,\n h(Value, { value: thickness, unit: thicknessUnit }),\n ),\n });\n }\n thicknessOrHeightRange ??= h(DataField, {\n label: \"Thickness\",\n value: thickness,\n unit: thicknessUnit,\n });\n\n /** We are trying to move away from passing the \"color\" parameter in the API */\n let colorSwatch: ReactNode = null;\n if (\"color\" in unit) {\n const unit1 = unit as UnitLongFull;\n colorSwatch = h(\"div.color-swatch\", {\n style: { backgroundColor: unit1.color },\n });\n }\n\n return h(\"div.unit-details-content\", [\n thicknessOrHeightRange,\n h(LithologyList, {\n label: \"Lithology\",\n lithologies,\n features: lithologyFeatures,\n getItemHref,\n onClickItem,\n }),\n h(AgeField, { unit }, [\n h(Parenthetical, h(Duration, { value: unit.b_age - unit.t_age })),\n h(IntervalProportions, {\n unit,\n onClickItem,\n }),\n ]),\n h(EnvironmentsList, {\n environments,\n onClickItem,\n getItemHref,\n }),\n h.if(unit.strat_name_id != null)(\n DataField,\n {\n label: \"Stratigraphic name\",\n },\n h(\n \"span\",\n {\n className: \"strat-name-id\" + (onClickItem ? \" clickable\" : \"\"),\n onClick: (e) => onClickItem(e, { strat_name_id: unit.strat_name_id }),\n },\n unit.strat_name_id,\n ),\n ),\n outcropField,\n h.if(features.has(UnitDetailsFeature.AdjacentUnits))([\n h(\n DataField,\n { label: \"Above\" },\n h(UnitIDList, { units: unit.units_above, selectUnit }),\n ),\n h(\n DataField,\n { label: \"Below\" },\n h(UnitIDList, { units: unit.units_below, selectUnit }),\n ),\n ]),\n colorSwatch,\n h(\n DataField,\n { label: \"Source\", inline: true },\n h(BibInfo, { refs: unit.refs }),\n ),\n ]);\n}\n\nfunction getThickness(unit): [string, string] {\n let minThickness = unit.min_thick ?? 0;\n let maxThickness = unit.max_thick ?? unit.min_thick ?? 0;\n let _unit = \"m\";\n\n if (minThickness == 0 && maxThickness == 0) {\n return [\"Unknown\", null];\n }\n\n if (minThickness < 0.8 && maxThickness < 1.2) {\n // Convert to cm\n minThickness = minThickness * 100;\n maxThickness = maxThickness * 100;\n _unit = \"cm\";\n } else if (minThickness > 800 && maxThickness > 1200) {\n // Convert to km\n minThickness = minThickness / 1000;\n maxThickness = maxThickness / 1000;\n _unit = \"km\";\n }\n\n if (minThickness == maxThickness) {\n return [formatSignificance(minThickness), _unit];\n }\n\n return [formatRange(minThickness, maxThickness), _unit];\n}\n\nfunction ThicknessField({ unit, label = \"Thickness\" }) {\n const [value, thicknessUnit] = getThickness(unit);\n return h(DataField, {\n label,\n value,\n unit: thicknessUnit,\n });\n}\n\nfunction BibInfo({ refs }) {\n const refData = useMacrostratData(\"refs\", refs);\n\n if (refData == null || refData.length === 0) {\n return null;\n }\n\n if (refData.length == 1) {\n return h(Citation, { data: refData[0], tag: \"span\" });\n }\n\n return h(\n \"ul.refs\",\n refData.map((data, i) => h(Citation, { data, tag: \"li\", key: i })),\n );\n}\n\nfunction Citation({ data, tag = \"p\" }) {\n return h(tag, { className: \"citation\" }, [\n h(\"span.authors\", data.author),\n \", \",\n h(\"span.year\", data.pub_year),\n \", \",\n h(\"span.title\", data.ref),\n ]);\n}\n\nfunction AgeField({ unit, children }) {\n const [b_age, t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(b_age, t_age),\n unit: _unit,\n },\n children,\n );\n}\n\nfunction getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nfunction getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\nfunction enhanceEnvironments(\n environments: Partial<Environment>[],\n envMap: Map<number, Environment>,\n) {\n return environments.map((env) => {\n return {\n ...(envMap?.get(env.environ_id) ?? {}),\n ...env,\n };\n });\n}\n\nfunction enhanceLithologies(\n lithologies: Partial<UnitLong[\"lith\"]>,\n lithMap: Map<number, any>,\n) {\n return lithologies.map((lith) => {\n return {\n ...(lithMap?.get(lith.lith_id) ?? {}), // get lithology details\n ...lith, // override with the unit's specific lithology data\n };\n });\n}\n\nfunction UnitIDList({ units, selectUnit }) {\n const u1 = units.filter((d) => d != 0);\n\n if (u1.length === 0) {\n return h(\"span.no-units\", \"None\");\n }\n\n let tag = \"span\";\n if (selectUnit != null) {\n tag = \"a\";\n }\n\n return h(\n ItemList,\n { className: \"unit-id-list\" },\n u1.map((unit) => {\n return h(\n tag,\n\n {\n className: \"unit-id\",\n onClick() {\n selectUnit?.(unit.id);\n },\n key: unit.id,\n },\n unit,\n );\n }),\n );\n}\n\nfunction IntervalProportions({ unit, onClickItem }) {\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n let b_prop = unit.b_prop ?? 0;\n let t_prop = unit.t_prop ?? 1;\n\n const intervalMap = useMacrostratDefs(\"intervals\");\n const int0 = intervalMap?.get(i0) ?? {};\n\n const interval0: IntervalShort = {\n ...int0,\n id: i0,\n name: unit.b_int_name,\n };\n\n let p0: ReactNode = null;\n const int1 = intervalMap?.get(i1) ?? {};\n const p1: ReactNode = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, h(\"span.sep\", \"to\"), p1]);\n }\n\n const clickable = onClickItem != null;\n\n const handleClick = (event: MouseEvent) => {\n if (onClickItem) {\n onClickItem(event, interval0);\n }\n };\n\n return h(\"div.interval-proportions\", [\n h(IntervalTag, {\n className: clickable ? \"clickable\" : \"\",\n onClick: clickable ? handleClick : undefined,\n interval: interval0,\n prefix: p0,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \"to\"),\n h(IntervalTag, {\n className: clickable ? \"clickable\" : \"\",\n onClick: clickable ? handleClick : undefined,\n interval: {\n ...int1,\n id: i1,\n name: unit.t_int_name,\n },\n prefix: p1,\n }),\n ]),\n ]);\n}\n\nconst formatProportion = (d) => {\n if (d == null) return null;\n return d.toFixed(1);\n};\n\nfunction Proportion({ value }) {\n let content = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nfunction formatRange(min, max, precision = null) {\n if (min == null || max == null) return null;\n if (min === max) {\n return min.toFixed(precision);\n }\n\n return `${formatSignificance(min, precision)}–${formatSignificance(\n max,\n precision,\n )}`;\n}\n\nfunction formatSignificance(value, precision = null) {\n // Format to preserve a reasonable number of significant figures\n // this could be done with an easier algorithm, probably:\n\n if (precision == null) {\n return value.toLocaleString();\n }\n if (precision >= 0) {\n return value.toFixed(precision);\n }\n if (precision < 0) {\n return (\n (value / Math.pow(10, -precision)).toFixed(0) + \"0\".repeat(-precision)\n );\n }\n}\n"],"names":[],"version":3,"file":"column-views.0f2121e4.js.map"}
@@ -1 +0,0 @@
1
- {"mappings":"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","sources":["packages/column-views/src/units/selection.ts"],"sourcesContent":["import { BaseUnit } from \"@macrostrat/api-types\";\nimport h from \"@macrostrat/hyper\";\nimport { useKeyHandler } from \"@macrostrat/ui-components\";\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n ReactNode,\n RefObject,\n useRef,\n useCallback,\n MouseEvent,\n} from \"react\";\nimport { createStore, StoreApi, useStore } from \"zustand\";\nimport type { RectBounds, IUnit } from \"./types\";\nimport {\n getUnitHeightRange,\n useMacrostratColumnData,\n} from \"@macrostrat/column-views\";\n\ntype UnitSelectDispatch = (\n unit: BaseUnit | null,\n target: HTMLElement | null,\n event: Event | null,\n) => void;\n\nconst UnitSelectionContext = createContext<StoreApi<UnitSelectionStore>>(null);\n\nexport function useUnitSelectionDispatch(): UnitSelectDispatch {\n const store = useContext(UnitSelectionContext);\n if (store == null) {\n return () => {};\n }\n return useStore(store, (state) => state.onUnitSelected);\n}\n\nexport function useUnitSelectionStore<T>(\n selector: (state: UnitSelectionStore) => T,\n): T {\n const store = useContext(UnitSelectionContext);\n if (store == null) {\n return null;\n }\n return useStore(store, selector);\n}\n\nexport function useSelectedUnit() {\n return useUnitSelectionStore((state) => state.selectedUnitData);\n}\n\ninterface UnitSelectionStore {\n selectedUnit: number | null;\n selectedUnitData: BaseUnit | null;\n overlayPosition: RectBounds | null;\n onUnitSelected: UnitSelectDispatch;\n setSelectedUnit: (unit: number | null) => void;\n}\n\nexport interface ColumnClickData {\n unitID: number | null;\n unit: BaseUnit | null;\n target: HTMLElement | null;\n height: number;\n // Room for boundary IDs eventually\n}\n\nexport function UnitSelectionProvider<T extends BaseUnit>(props: {\n children: ReactNode;\n columnRef?: RefObject<HTMLElement>;\n units: T[];\n selectedUnit: number | null;\n onClickedColumn?: (columnClickData: ColumnClickData, event: Event) => void;\n onUnitSelected?: (unitID: number | null, unit: T | null) => void;\n}) {\n const [store] = useState(() =>\n createStore<UnitSelectionStore>((set) => ({\n selectedUnit: null,\n selectedUnitData: null,\n overlayPosition: null,\n setSelectedUnit(selectedUnit: number | null | BaseUnit) {\n if (selectedUnit == null) {\n set({ selectedUnit: null, selectedUnitData: null });\n return;\n // If it's a number, set the selected unit\n } else if (typeof selectedUnit === \"number\") {\n set({ selectedUnit, selectedUnitData: null });\n } else if (\"unit_id\" in selectedUnit) {\n set({\n selectedUnit: selectedUnit.unit_id,\n selectedUnitData: selectedUnit,\n });\n }\n },\n onUnitSelected: (unit: T, target: HTMLElement, event: PointerEvent) => {\n console.log(\"onUnitSelected\", unit, target, event);\n const el = props.columnRef?.current;\n let overlayPosition = null;\n\n /** This is not the natural place to get positions within the column,\n * but it will work for now.\n */\n if (props.onClickedColumn) {\n // Infer height from top and bottom height of unit (because that's passed back with the call)\n //const py = event.y;\n //const [bottom, top] = getUnitHeightRange(unit, axisType);\n //const height = Math.abs(bottom - top);\n\n /** Ideally this would be defined at the column level */\n const columnClickData: ColumnClickData = {\n unitID: unit?.unit_id,\n unit,\n target,\n height: el?.getBoundingClientRect().height || 0,\n };\n props.onClickedColumn(columnClickData, event);\n }\n\n if (unit != null && el != null && target != null) {\n const rect = el.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n\n overlayPosition = {\n x: targetRect.left - rect.left,\n y: targetRect.top - rect.top,\n width: targetRect.width,\n height: targetRect.height,\n };\n }\n props.onUnitSelected?.(unit?.unit_id, unit);\n\n return set({\n selectedUnit: unit?.unit_id,\n selectedUnitData: unit,\n overlayPosition,\n });\n },\n })),\n );\n\n const { units, selectedUnit } = props;\n\n useEffect(() => {\n // Synchronize store with provided props\n if (selectedUnit != null) {\n const unitData = units?.find((u) => u.unit_id === selectedUnit);\n store.setState({ selectedUnit, selectedUnitData: unitData });\n } else {\n store.setState({ selectedUnit: null, selectedUnitData: null });\n }\n }, [selectedUnit, units]);\n\n return h(UnitSelectionContext.Provider, { value: store }, props.children);\n}\n\nexport function useUnitSelectionTarget(\n unit: IUnit,\n): [React.RefObject<HTMLElement>, boolean, (evt: Event) => void] {\n const ref = useRef<HTMLElement>();\n const selectedUnit = useSelectedUnit();\n const onSelectUnit = useUnitSelectionStore((state) => state.onUnitSelected);\n const selected = selectedUnit?.unit_id == unit.unit_id;\n\n const onClick = useCallback(\n (evt: Event) => {\n if (onSelectUnit == null) return;\n onSelectUnit(unit, ref.current, evt);\n evt.stopPropagation();\n },\n [unit, onSelectUnit],\n );\n\n useEffect(() => {\n if (!selected || onSelectUnit == null) return;\n // In case we haven't set the position of the unit (if we don't have a target), set the selected unit\n onSelectUnit(unit, ref.current, null);\n\n // Scroll the unit into view\n ref.current?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n inline: \"nearest\",\n });\n }, [selected, onSelectUnit]);\n\n return [ref, selected, onClick];\n}\n\nexport function UnitKeyboardNavigation<T extends BaseUnit>({\n units,\n}: {\n units: T[];\n}) {\n const selectedUnit = useSelectedUnit();\n const selectUnit = useUnitSelectionDispatch();\n\n const ix = units.findIndex((unit) => unit.unit_id === selectedUnit?.unit_id);\n\n const keyMap = {\n 38: ix - 1,\n 40: ix + 1,\n };\n\n useKeyHandler(\n (event) => {\n const nextIx = keyMap[event.keyCode];\n if (nextIx == null || nextIx < 0 || nextIx >= units.length) return;\n selectUnit(units[nextIx], null, null);\n event.stopPropagation();\n },\n [units, ix],\n );\n return null;\n}\n"],"names":[],"version":3,"file":"column-views.1af9761e.js.map"}
@@ -1 +0,0 @@
1
- {"mappings":"AAAA;;;;;;AAWE;EACE;;;;;;;;EAOI;;;;EAEA;;;;;AAIN;;;;;;;;AAOE;;;;AAIF;;;;AAIE;;;;;;;AAOA;;;;;AAKA;;;;;AAIF;;;;;;AAKA;;;;AAGF;;;;;;;;;;;;;;;;;;;;AAgBE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BF;;;;;;;AAOE;;;;;;;;;;;;;;;AAWE;;;;;AAMF","sources":["packages/column-views/src/column.module.sass"],"sourcesContent":[".column-container, body:global(.light-mode) .column-container\n --column-background-color: var(--background-color, #fff)\n --column-stroke-color: var(--text-emphasized-color, #000)\n --column-text-color: var(--text-emphasized-color, #000)\n\n/* We have to duplicate the dark mode styles here\n because we want to set them either if the preferred\n color scheme is dark OR if dark mode is explicitly enabled.\n If dark mode is explicitly enabled, we want to override\n the media query. */\n@media (prefers-color-scheme: dark)\n body:not(:global(.light-mode)) .column-container\n --column-background-color: var(--background-color, #000)\n --column-stroke-color: var(--text-emphasized-color, #fff)\n --column-text-color: var(--text-emphasized-color, #fff)\n color-scheme: dark\n color: var(--column-text-color)\n :global\n .timescale\n color: #000\n svg pattern image\n filter: invert(100%)\n\nbody:global(.dark-mode) .column-container\n --column-background-color: var(--background-color, #000)\n --column-stroke-color: var(--text-emphasized-color, #fff)\n --column-text-color: var(--text-emphasized-color, #fff)\n color-scheme: dark\n color: var(--column-text-color)\n :global\n .timescale\n color: #000\n svg pattern image\n filter: invert(100%)\n\n.column-container :global\n .column\n display: flex\n flex-direction: row\n position: relative\n height: fit-content\n\n .unit\n stroke: var(--column-stroke-color)\n stroke-width: 1px\n\n .selection-overlay\n fill: var(--selection-overlay-color, red)\n fill-opacity: var(--selection-overlay-opacity, 0.5)\n\n g.lithology-column use.frame\n stroke: var(--column-stroke-color)\n stroke-width: 1.5px !important\n pointer-events: none\n\n.column-container :global .unit-label\n text-align: center\n\n.column-container :global .col-note-label\n font-size: 10px\n line-height: 9px\n border-left: none !important\n margin: 1px 0\n\n.column-container :global g.height-range\n display: none\n\n.column-container :global .note-inner\n border: none\n padding: 1px\n\n.column-container :global .frame rect\n fill: transparent\n\n.column-container :global .default-buttons\n width: 100%\n margin: 0 -10px\n\n.column-container :global div.section\n display: flex\n flex-direction: row\n\n.column-container :global .section .divisions .unit\n cursor: pointer\n\n.column-container :global(.timescale)\n width: calc(calc(1.5em + 1.5px) * var(--timescale-level-count, 4))\n --timescale-level-size: 1.5em\n\n.timescale-column\n position: relative\n\n.section-main\n position: relative\n margin-bottom: -4px\n\n.section-units-container\n position: relative\n\n.main-column\n position: relative\n\n.unconformity-labels\n position: absolute\n top: 0\n left: 0\n pointer-events: none\n\n\n.unconformity\n text-align: center\n position: absolute\n top: 0px\n display: flex\n justify-content: center\n align-items: center\n font-size: 0.8em\n &.giga\n font-weight: 800\n font-size: 1em\n &.mega\n font-weight: 600\n font-weight: 700\n font-size: 0.9em\n &.large\n font-weight: 600\n &.small\n font-weight: 300\n\n\n.unconformity-text\n width: var(--column-width)\n color: var(--column-stroke-color)\n --unit-font-style: normal\n\n\n"],"names":[],"version":3,"file":"column-views.217078ab.css.map"}