@macrostrat/column-views 1.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 (109) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +3 -0
  3. package/dist/age-axis.7ce58d66.js +41 -0
  4. package/dist/age-axis.7ce58d66.js.map +1 -0
  5. package/dist/boxes.6d3192e6.js +164 -0
  6. package/dist/boxes.6d3192e6.js.map +1 -0
  7. package/dist/boxes.module.998ff312.js +13 -0
  8. package/dist/boxes.module.998ff312.js.map +1 -0
  9. package/dist/boxes.module.dd631fe3.css +4 -0
  10. package/dist/boxes.module.dd631fe3.css.map +1 -0
  11. package/dist/carbon-isotopes.6d9bddcf.js +11 -0
  12. package/dist/carbon-isotopes.6d9bddcf.js.map +1 -0
  13. package/dist/column.e35a471f.js +149 -0
  14. package/dist/column.e35a471f.js.map +1 -0
  15. package/dist/column.e901b5d4.js +117 -0
  16. package/dist/column.e901b5d4.js.map +1 -0
  17. package/dist/column.module.2e29259c.js +22 -0
  18. package/dist/column.module.2e29259c.js.map +1 -0
  19. package/dist/column.module.35184ea7.css +157 -0
  20. package/dist/column.module.35184ea7.css.map +1 -0
  21. package/dist/column.module.35ba04e7.js +34 -0
  22. package/dist/column.module.35ba04e7.js.map +1 -0
  23. package/dist/column.module.c9df6edf.css +138 -0
  24. package/dist/column.module.c9df6edf.css.map +1 -0
  25. package/dist/composite.494beffc.js +153 -0
  26. package/dist/composite.494beffc.js.map +1 -0
  27. package/dist/composite.module.5cc0e747.css +4 -0
  28. package/dist/composite.module.5cc0e747.css.map +1 -0
  29. package/dist/composite.module.6359deba.js +13 -0
  30. package/dist/composite.module.6359deba.js.map +1 -0
  31. package/dist/core.f3824dd8.js +89 -0
  32. package/dist/core.f3824dd8.js.map +1 -0
  33. package/dist/data-area.f9bb9ad9.js +86 -0
  34. package/dist/data-area.f9bb9ad9.js.map +1 -0
  35. package/dist/data-provider.61ef7f9a.js +25 -0
  36. package/dist/data-provider.61ef7f9a.js.map +1 -0
  37. package/dist/helpers.2af05ee4.js +94 -0
  38. package/dist/helpers.2af05ee4.js.map +1 -0
  39. package/dist/index.d.ts +363 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +19 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/index.module.8fad0020.js +37 -0
  44. package/dist/index.module.8fad0020.js.map +1 -0
  45. package/dist/index.module.de76feb2.css +65 -0
  46. package/dist/index.module.de76feb2.css.map +1 -0
  47. package/dist/isotopes-column.b5442b4d.js +163 -0
  48. package/dist/isotopes-column.b5442b4d.js.map +1 -0
  49. package/dist/layers.946aaa37.js +231 -0
  50. package/dist/layers.946aaa37.js.map +1 -0
  51. package/dist/map.e782010f.js +82 -0
  52. package/dist/map.e782010f.js.map +1 -0
  53. package/dist/names.ab14789e.js +65 -0
  54. package/dist/names.ab14789e.js.map +1 -0
  55. package/dist/providers.abcb2cbe.js +25 -0
  56. package/dist/providers.abcb2cbe.js.map +1 -0
  57. package/dist/resolvers.2949c4c0.js +83 -0
  58. package/dist/resolvers.2949c4c0.js.map +1 -0
  59. package/dist/section.6f6fc929.js +118 -0
  60. package/dist/section.6f6fc929.js.map +1 -0
  61. package/dist/selection-popover.7e008544.js +60 -0
  62. package/dist/selection-popover.7e008544.js.map +1 -0
  63. package/dist/selection-popover.module.2732ebc0.css +34 -0
  64. package/dist/selection-popover.module.2732ebc0.css.map +1 -0
  65. package/dist/selection-popover.module.fdbfb40e.js +22 -0
  66. package/dist/selection-popover.module.fdbfb40e.js.map +1 -0
  67. package/dist/selection.add9f8b0.js +117 -0
  68. package/dist/selection.add9f8b0.js.map +1 -0
  69. package/dist/store.c5271371.js +18 -0
  70. package/dist/store.c5271371.js.map +1 -0
  71. package/dist/types.ff938b22.js +18 -0
  72. package/dist/types.ff938b22.js.map +1 -0
  73. package/dist/unit-details.0c1edd00.js +209 -0
  74. package/dist/unit-details.0c1edd00.js.map +1 -0
  75. package/dist/units.5ec6a44c.js +42 -0
  76. package/dist/units.5ec6a44c.js.map +1 -0
  77. package/package.json +66 -0
  78. package/src/age-axis.ts +42 -0
  79. package/src/carbon-isotopes/column.module.sass +136 -0
  80. package/src/carbon-isotopes/column.ts +131 -0
  81. package/src/carbon-isotopes/core.ts +78 -0
  82. package/src/carbon-isotopes/data-area.ts +96 -0
  83. package/src/carbon-isotopes/data-provider.ts +19 -0
  84. package/src/carbon-isotopes/index.ts +3 -0
  85. package/src/carbon-isotopes/isotopes-column.ts +214 -0
  86. package/src/column.module.sass +114 -0
  87. package/src/column.ts +185 -0
  88. package/src/helpers.ts +133 -0
  89. package/src/index.ts +7 -0
  90. package/src/map/animated.ts +78 -0
  91. package/src/map/index.ts +86 -0
  92. package/src/map/layers.ts +316 -0
  93. package/src/providers.ts +34 -0
  94. package/src/section.ts +129 -0
  95. package/src/selection-popover.module.sass +27 -0
  96. package/src/selection-popover.ts +71 -0
  97. package/src/store.ts +12 -0
  98. package/src/unit-details/index.module.sass +51 -0
  99. package/src/unit-details/index.ts +215 -0
  100. package/src/units/boxes.module.sass +3 -0
  101. package/src/units/boxes.ts +221 -0
  102. package/src/units/composite.module.sass +2 -0
  103. package/src/units/composite.ts +266 -0
  104. package/src/units/index.ts +36 -0
  105. package/src/units/names.ts +118 -0
  106. package/src/units/resolvers.ts +111 -0
  107. package/src/units/selection.ts +167 -0
  108. package/src/units/types.ts +26 -0
  109. package/src/units/units.scss +16 -0
@@ -0,0 +1,36 @@
1
+ import h from "@macrostrat/hyper";
2
+ import { LithologyColumn } from "@macrostrat/column-components";
3
+ import { UnitNamesColumn } from "./names";
4
+ import { ICompositeUnitProps } from "./composite";
5
+ import { UnitBoxes } from "./boxes";
6
+
7
+ const UnitsColumn = ({ width = 100 }) => {
8
+ /*
9
+ A column showing units with USGS color fill
10
+ */
11
+ return h(LithologyColumn, { width }, h(UnitBoxes));
12
+ };
13
+
14
+ const SimpleUnitsColumn = (props: ICompositeUnitProps) => {
15
+ /*
16
+ A column with units and names either
17
+ overlapping or offset to the right
18
+ */
19
+ const { columnWidth, width, gutterWidth = 0, labelOffset = 30 } = props;
20
+
21
+ return h([
22
+ h(UnitsColumn, {
23
+ width: columnWidth,
24
+ }),
25
+ h(UnitNamesColumn, {
26
+ transform: `translate(${columnWidth + gutterWidth})`,
27
+ paddingLeft: labelOffset,
28
+ width: width - columnWidth - gutterWidth,
29
+ }),
30
+ ]);
31
+ };
32
+
33
+ export { UnitsColumn, SimpleUnitsColumn };
34
+ export * from "./composite";
35
+ export * from "./types";
36
+ export * from "./selection";
@@ -0,0 +1,118 @@
1
+ import h from "@macrostrat/hyper";
2
+ import { useContext, useCallback } from "react";
3
+ import {
4
+ ColumnContext,
5
+ ColumnAxisType,
6
+ NotesColumn,
7
+ NotesColumnProps,
8
+ } from "@macrostrat/column-components";
9
+ import type { ColumnDivision } from "@macrostrat/column-components";
10
+ import { IUnit, transformAxisType } from "./types";
11
+ import React from "react";
12
+
13
+ interface UnitDataProps extends NotesColumnProps {
14
+ left?: number;
15
+ transform?: string;
16
+ noteComponent?: React.ComponentType<any>;
17
+ shouldRenderNote?(div: ColumnDivision | IUnit, index: number): boolean;
18
+ divisions?: IUnit[];
19
+ minimumHeight?: number;
20
+ }
21
+
22
+ type UnitNote = {
23
+ height: number;
24
+ top_height: number;
25
+ data: IUnit;
26
+ id: number;
27
+ };
28
+
29
+ function noteForDivision(
30
+ div: IUnit,
31
+ opts: { axisType: ColumnAxisType }
32
+ ): UnitNote {
33
+ const { axisType } = opts;
34
+
35
+ const key = transformAxisType(axisType);
36
+ return {
37
+ height: div[`b_${key}`],
38
+ top_height: div[`t_${key}`],
39
+ data: div,
40
+ id: div.unit_id,
41
+ };
42
+ }
43
+
44
+ const defaultNameFunction = (div) => {
45
+ return div.unit_name
46
+ .replace("Mbr", "Member")
47
+ .replace("Fm", "Formation")
48
+ .replace("Gp", "Group");
49
+ };
50
+
51
+ function UnitDataColumn_(props: UnitDataProps) {
52
+ const ctx = useContext(ColumnContext);
53
+ const {
54
+ left,
55
+ noteComponent,
56
+ shouldRenderNote = (note: ColumnDivision | IUnit, i: number) => true,
57
+ minimumHeight = 0,
58
+ divisions = ctx?.divisions,
59
+ ...rest
60
+ } = props;
61
+
62
+ const { scale } = ctx;
63
+
64
+ const minimumHeightFilter = useCallback(
65
+ (d) => {
66
+ if (minimumHeight == 0) return true;
67
+ const dy = Math.abs(scale(d.top_height) - scale(d.height));
68
+ return dy > minimumHeight;
69
+ },
70
+ [scale, minimumHeight]
71
+ );
72
+
73
+ if (divisions == null) return null;
74
+ const notes: UnitNote[] = divisions
75
+ .filter(shouldRenderNote)
76
+ .map((d: IUnit) => noteForDivision(d, { axisType: ctx.axisType }))
77
+ .filter(minimumHeightFilter);
78
+
79
+ return h(NotesColumn, {
80
+ transform: `translate(${left || 0})`,
81
+ editable: false,
82
+ noteComponent,
83
+ notes,
84
+ forceOptions: {
85
+ nodeSpacing: 1,
86
+ },
87
+ ...rest,
88
+ });
89
+ }
90
+
91
+ const UnitDataColumn = React.memo(UnitDataColumn_);
92
+
93
+ interface UnitNamesProps extends UnitDataProps {
94
+ nameForDivision?(obj: IUnit): string;
95
+ paddingLeft?: number;
96
+ width: number;
97
+ }
98
+
99
+ export function UnitNamesColumn(props: UnitNamesProps) {
100
+ const {
101
+ nameForDivision = defaultNameFunction,
102
+ noteComponent,
103
+ ...rest
104
+ } = props;
105
+
106
+ const NoteComponent = (props) => {
107
+ const { note } = props;
108
+ return h("p.col-note-label", nameForDivision(note.data));
109
+ };
110
+
111
+ return h(UnitDataColumn, {
112
+ noteComponent: noteComponent ?? NoteComponent,
113
+ ...rest,
114
+ });
115
+ }
116
+
117
+ export type { UnitNamesProps };
118
+ export { defaultNameFunction, noteForDivision, UnitDataColumn };
@@ -0,0 +1,111 @@
1
+ const symbolIndex = {
2
+ "dolomite-limestone": 641,
3
+ lime_mudstone: 627,
4
+ sandstone: 607,
5
+ "quartz arenite": 607,
6
+ litharenite: 608,
7
+ sand: 608,
8
+ siltstone: 616,
9
+ silt: 616,
10
+ "dolomitic siltstone": 616,
11
+ shale: 620,
12
+ limestone: 627,
13
+ dolomite: 642,
14
+ conglomerate: 602,
15
+ carbonate: 627,
16
+ "dolomite-mudstone": 642,
17
+ dolostone: 642,
18
+ mudstone: 620,
19
+ "sandy-dolomite": 645,
20
+ quartzite: 702,
21
+ halite: 668,
22
+ basalt: 717,
23
+ rhyolite: 722,
24
+ andesite: 723,
25
+ till: 681,
26
+ loess: 684,
27
+ "calcareous ooze": 653,
28
+ chalk: 626,
29
+ gravel: 601,
30
+ plutonic: 721,
31
+ granite: 719,
32
+ clay: 660,
33
+ syenite: 722,
34
+ tuff: 711,
35
+ volcanic: 725,
36
+ metamorphic: 707,
37
+ volcaniclastic: 714,
38
+ migmatite: 709,
39
+ gneiss: 708,
40
+ tonalite: 727,
41
+ granodiorite: 725,
42
+ monzonite: 723,
43
+ argillite: 624,
44
+ };
45
+
46
+ const resolveID = (d: any) => {
47
+ let liths = d.lith;
48
+ let environs = d.environ.map((d) => d.name).join(" ");
49
+ liths.sort((a, b) => b.prop - a.prop);
50
+
51
+ //console.log(d, d.unit_name, liths.map(d => d.name), environs)
52
+
53
+ let sym = null;
54
+
55
+ // overrides for IODP columns
56
+ if (d.unit_name == "clay") {
57
+ return "650";
58
+ }
59
+ if (d.unit_name == "calcareous clay") {
60
+ return "651";
61
+ }
62
+
63
+ for (const k of liths) {
64
+ if (k.name == "sandstone") {
65
+ // Special cases for sandstone
66
+ if (environs.includes("dune")) {
67
+ return "609";
68
+ }
69
+ if (environs.includes("marine")) {
70
+ return "608";
71
+ }
72
+ if (environs.includes("shore")) {
73
+ return "611";
74
+ }
75
+ if (environs.includes("loess")) {
76
+ return "686";
77
+ }
78
+ }
79
+
80
+ if (k.name == "conglomerate") {
81
+ // Special cases for sandstone
82
+ if (environs.includes("fluvial")) {
83
+ return "603";
84
+ }
85
+ }
86
+
87
+ if (k.name.includes("tuff")) {
88
+ return "711";
89
+ }
90
+ sym = symbolIndex[k.name];
91
+ if (sym != null) {
92
+ return sym;
93
+ }
94
+
95
+ if (k.type == "volcanic") {
96
+ return "725";
97
+ }
98
+ }
99
+ return sym;
100
+ };
101
+
102
+ const patternScale = {
103
+ "609": 1.5,
104
+ "603": 1.5,
105
+ };
106
+
107
+ const scalePattern = (id) => {
108
+ return patternScale[`${id}`] ?? 1;
109
+ };
110
+
111
+ export { resolveID, scalePattern };
@@ -0,0 +1,167 @@
1
+ import { BaseUnit } from "@macrostrat/api-types";
2
+ import h from "@macrostrat/hyper";
3
+ import {
4
+ getQueryString,
5
+ setQueryString,
6
+ useKeyHandler,
7
+ } from "@macrostrat/ui-components";
8
+ import {
9
+ Dispatch,
10
+ SetStateAction,
11
+ createContext,
12
+ useContext,
13
+ useEffect,
14
+ useMemo,
15
+ useState,
16
+ ReactNode,
17
+ useCallback,
18
+ } from "react";
19
+
20
+ type UnitSelectDispatch = (
21
+ unit: BaseUnit | null,
22
+ target: HTMLElement | null,
23
+ event: Event | null
24
+ ) => void;
25
+
26
+ const UnitSelectionContext = createContext<BaseUnit | null>(null);
27
+ const DispatchContext = createContext<UnitSelectDispatch | null>(null);
28
+
29
+ export function useUnitSelectionDispatch() {
30
+ return useContext(DispatchContext);
31
+ }
32
+
33
+ export function useSelectedUnit() {
34
+ return useContext(UnitSelectionContext);
35
+ }
36
+
37
+ export interface UnitSelectionProps<T extends BaseUnit> {
38
+ children: React.ReactNode;
39
+ unit: T | null;
40
+ setUnit: Dispatch<SetStateAction<T>>;
41
+ onUnitSelected?: (unit: T, target: HTMLElement, event: Event) => void;
42
+ }
43
+
44
+ export function UnitSelectionProvider<T extends BaseUnit>(
45
+ props: Partial<UnitSelectionProps<T>>
46
+ ) {
47
+ const { unit, setUnit, onUnitSelected, children } = props;
48
+
49
+ if (unit == null && setUnit == null) {
50
+ return h(StatefulUnitSelectionProvider, props);
51
+ }
52
+
53
+ return h(
54
+ BaseUnitSelectionProvider,
55
+ { unit, setUnit, onUnitSelected },
56
+ children
57
+ );
58
+ }
59
+
60
+ function StatefulUnitSelectionProvider<T extends BaseUnit>(props: {
61
+ children: ReactNode;
62
+ onUnitSelected?: (unit: T, target: HTMLElement, event: Event) => void;
63
+ }) {
64
+ const [unit, setUnit] = useState<T | null>(null);
65
+
66
+ return h(BaseUnitSelectionProvider, { ...props, unit, setUnit });
67
+ }
68
+
69
+ function BaseUnitSelectionProvider<T extends BaseUnit>({
70
+ children,
71
+ unit,
72
+ setUnit,
73
+ onUnitSelected,
74
+ }: UnitSelectionProps<T>) {
75
+ const value = useMemo(() => unit, [unit?.unit_id]);
76
+
77
+ const _onUnitSelected = useCallback(
78
+ (u: T, target: HTMLElement, event: Event) => {
79
+ let newUnit = u;
80
+ setUnit(newUnit);
81
+ onUnitSelected?.(newUnit, target, event);
82
+ },
83
+ [setUnit, onUnitSelected]
84
+ );
85
+
86
+ return h(
87
+ DispatchContext.Provider,
88
+ { value: _onUnitSelected },
89
+ h(UnitSelectionContext.Provider, { value }, children)
90
+ );
91
+ }
92
+
93
+ export interface ColumnArgs {
94
+ col_id?: number;
95
+ unit_id?: number;
96
+ project_id?: number;
97
+ status_code?: "in process";
98
+ }
99
+
100
+ type ColumnManagerData = [ColumnArgs, (c: ColumnArgs) => void];
101
+
102
+ const ColumnNavCtx = createContext<ColumnManagerData | null>(null);
103
+
104
+ export function useColumnNav(
105
+ defaultArgs: ColumnArgs = { col_id: 495, unit_id: null }
106
+ ): ColumnManagerData {
107
+ const ctx = useContext(ColumnNavCtx);
108
+ if (ctx != null) return ctx;
109
+
110
+ const [columnArgs, setColumnArgs] = useState<ColumnArgs>(
111
+ extractColumnArgs(getQueryString(window.location.search)) ?? defaultArgs
112
+ );
113
+
114
+ useEffect(() => setQueryString(columnArgs), [columnArgs]);
115
+
116
+ const { col_id, project_id, status_code } = columnArgs;
117
+
118
+ const setCurrentColumn = (obj) => {
119
+ let args = obj;
120
+ if ("properties" in obj) {
121
+ args = { col_id: obj.properties.col_id, project_id, status_code };
122
+ }
123
+ // Set query string
124
+ setQueryString(args);
125
+ setColumnArgs(args);
126
+ };
127
+
128
+ return [columnArgs, setCurrentColumn];
129
+ }
130
+
131
+ function extractColumnArgs(search: any): ColumnArgs | null {
132
+ const { col_id, unit_id, project_id, status_code } = search;
133
+ if (col_id == null) return null;
134
+ return { col_id, unit_id, project_id, status_code };
135
+ }
136
+
137
+ export function ColumnNavProvider({ children, ...defaultArgs }) {
138
+ const value = useColumnNav(defaultArgs as any);
139
+ return h(ColumnNavCtx.Provider, { value }, children);
140
+ }
141
+
142
+ export function UnitKeyboardNavigation<T extends BaseUnit>({
143
+ units,
144
+ }: {
145
+ units: T[];
146
+ }) {
147
+ const selectedUnit = useSelectedUnit();
148
+ const selectUnit = useUnitSelectionDispatch();
149
+
150
+ const ix = units.findIndex((unit) => unit.unit_id === selectedUnit?.unit_id);
151
+
152
+ const keyMap = {
153
+ 38: ix - 1,
154
+ 40: ix + 1,
155
+ };
156
+
157
+ useKeyHandler(
158
+ (event) => {
159
+ const nextIx = keyMap[event.keyCode];
160
+ if (nextIx == null || nextIx < 0 || nextIx >= units.length) return;
161
+ selectUnit(units[nextIx], null, null);
162
+ event.stopPropagation();
163
+ },
164
+ [units, ix]
165
+ );
166
+ return null;
167
+ }
@@ -0,0 +1,26 @@
1
+ import { ColumnAxisType } from "@macrostrat/column-components";
2
+ export interface IUnit {
3
+ unit_id: number;
4
+ col_id: number;
5
+ section_id: number;
6
+ t_age: number;
7
+ b_age: number;
8
+ [x: string]: any;
9
+ }
10
+
11
+ enum MacrostratAxisKey {
12
+ AGE = "age",
13
+ POS = "pos"
14
+ }
15
+
16
+ function transformAxisType(t: ColumnAxisType): MacrostratAxisKey {
17
+ switch (t) {
18
+ case "age":
19
+ return MacrostratAxisKey.AGE;
20
+ case "height":
21
+ case "depth":
22
+ return MacrostratAxisKey.POS;
23
+ }
24
+ }
25
+
26
+ export { MacrostratAxisKey, transformAxisType };
@@ -0,0 +1,16 @@
1
+ g.labeled-unit div.unit-name {
2
+ display: block;
3
+ width: 100%;
4
+ height: 100%;
5
+ }
6
+ g.labeled-unit span.label-text {
7
+ text-align: center;
8
+ }
9
+ @media (prefers-color-scheme: dark) {
10
+ .lithology-column .frame {
11
+ stroke: #fff;
12
+ }
13
+ g.inner pattern image {
14
+ filter: invert(100%);
15
+ }
16
+ }