@macrostrat/column-views 3.9.0 → 3.11.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 (138) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/column-views.css +10 -0
  3. package/dist/correlation-chart/main.cjs +11 -3
  4. package/dist/correlation-chart/main.cjs.map +1 -1
  5. package/dist/correlation-chart/main.d.ts +1 -1
  6. package/dist/correlation-chart/main.js +11 -3
  7. package/dist/correlation-chart/main.js.map +1 -1
  8. package/dist/index.cjs +18 -42
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.js +4 -34
  12. package/dist/index.js.map +1 -1
  13. package/dist/unit-details/age-window-tag.cjs +68 -0
  14. package/dist/unit-details/age-window-tag.cjs.map +1 -0
  15. package/dist/unit-details/age-window-tag.d.ts +26 -0
  16. package/dist/unit-details/age-window-tag.js +66 -0
  17. package/dist/unit-details/age-window-tag.js.map +1 -0
  18. package/dist/unit-details/age-window-tag.module.sass.cjs +12 -0
  19. package/dist/unit-details/age-window-tag.module.sass.cjs.map +1 -0
  20. package/dist/unit-details/age-window-tag.module.sass.js +11 -0
  21. package/dist/unit-details/age-window-tag.module.sass.js.map +1 -0
  22. package/dist/unit-details/index.d.ts +1 -0
  23. package/dist/units/boxes.cjs +3 -3
  24. package/dist/units/boxes.cjs.map +1 -1
  25. package/dist/units/boxes.js +3 -3
  26. package/dist/units/boxes.js.map +1 -1
  27. package/dist/units/index.cjs +7 -11
  28. package/dist/units/index.cjs.map +1 -1
  29. package/dist/units/index.d.ts +0 -1
  30. package/dist/units/index.js +4 -9
  31. package/dist/units/index.js.map +1 -1
  32. package/package.json +6 -27
  33. package/src/correlation-chart/main.ts +14 -2
  34. package/src/index.ts +3 -1
  35. package/src/unit-details/age-window-tag.module.sass +10 -0
  36. package/src/unit-details/age-window-tag.ts +102 -0
  37. package/src/unit-details/index.ts +1 -0
  38. package/src/units/boxes.ts +7 -4
  39. package/src/units/index.ts +9 -26
  40. package/dist/maps/column-correlation/core.cjs +0 -288
  41. package/dist/maps/column-correlation/core.cjs.map +0 -1
  42. package/dist/maps/column-correlation/core.d.ts +0 -9
  43. package/dist/maps/column-correlation/core.js +0 -286
  44. package/dist/maps/column-correlation/core.js.map +0 -1
  45. package/dist/maps/column-correlation/index.d.ts +0 -2
  46. package/dist/maps/column-correlation/state.cjs +0 -193
  47. package/dist/maps/column-correlation/state.cjs.map +0 -1
  48. package/dist/maps/column-correlation/state.d.ts +0 -62
  49. package/dist/maps/column-correlation/state.js +0 -190
  50. package/dist/maps/column-correlation/state.js.map +0 -1
  51. package/dist/maps/column-navigation/index.d.ts +0 -2
  52. package/dist/maps/column-navigation/mapbox/index.cjs +0 -215
  53. package/dist/maps/column-navigation/mapbox/index.cjs.map +0 -1
  54. package/dist/maps/column-navigation/mapbox/index.d.ts +0 -38
  55. package/dist/maps/column-navigation/mapbox/index.js +0 -213
  56. package/dist/maps/column-navigation/mapbox/index.js.map +0 -1
  57. package/dist/maps/column-navigation/mapbox/keyboard-navigation.cjs +0 -105
  58. package/dist/maps/column-navigation/mapbox/keyboard-navigation.cjs.map +0 -1
  59. package/dist/maps/column-navigation/mapbox/keyboard-navigation.d.ts +0 -8
  60. package/dist/maps/column-navigation/mapbox/keyboard-navigation.js +0 -105
  61. package/dist/maps/column-navigation/mapbox/keyboard-navigation.js.map +0 -1
  62. package/dist/maps/column-navigation/mapbox/state.cjs +0 -73
  63. package/dist/maps/column-navigation/mapbox/state.cjs.map +0 -1
  64. package/dist/maps/column-navigation/mapbox/state.d.ts +0 -23
  65. package/dist/maps/column-navigation/mapbox/state.js +0 -71
  66. package/dist/maps/column-navigation/mapbox/state.js.map +0 -1
  67. package/dist/maps/column-navigation/svg/animated.d.ts +0 -1
  68. package/dist/maps/column-navigation/svg/data-fetcher.cjs +0 -25
  69. package/dist/maps/column-navigation/svg/data-fetcher.cjs.map +0 -1
  70. package/dist/maps/column-navigation/svg/data-fetcher.d.ts +0 -6
  71. package/dist/maps/column-navigation/svg/data-fetcher.js +0 -25
  72. package/dist/maps/column-navigation/svg/data-fetcher.js.map +0 -1
  73. package/dist/maps/column-navigation/svg/index.cjs +0 -94
  74. package/dist/maps/column-navigation/svg/index.cjs.map +0 -1
  75. package/dist/maps/column-navigation/svg/index.d.ts +0 -9
  76. package/dist/maps/column-navigation/svg/index.js +0 -93
  77. package/dist/maps/column-navigation/svg/index.js.map +0 -1
  78. package/dist/maps/column-navigation/svg/layers.cjs +0 -177
  79. package/dist/maps/column-navigation/svg/layers.cjs.map +0 -1
  80. package/dist/maps/column-navigation/svg/layers.d.ts +0 -54
  81. package/dist/maps/column-navigation/svg/layers.js +0 -174
  82. package/dist/maps/column-navigation/svg/layers.js.map +0 -1
  83. package/dist/maps/column-navigation/utils/keyboard-navigation.cjs +0 -50
  84. package/dist/maps/column-navigation/utils/keyboard-navigation.cjs.map +0 -1
  85. package/dist/maps/column-navigation/utils/keyboard-navigation.d.ts +0 -10
  86. package/dist/maps/column-navigation/utils/keyboard-navigation.js +0 -50
  87. package/dist/maps/column-navigation/utils/keyboard-navigation.js.map +0 -1
  88. package/dist/maps/index.d.ts +0 -4
  89. package/dist/maps/inset-map/index.cjs +0 -71
  90. package/dist/maps/inset-map/index.cjs.map +0 -1
  91. package/dist/maps/inset-map/index.d.ts +0 -16
  92. package/dist/maps/inset-map/index.js +0 -69
  93. package/dist/maps/inset-map/index.js.map +0 -1
  94. package/dist/maps/layers/columns.cjs +0 -165
  95. package/dist/maps/layers/columns.cjs.map +0 -1
  96. package/dist/maps/layers/columns.d.ts +0 -28
  97. package/dist/maps/layers/columns.js +0 -165
  98. package/dist/maps/layers/columns.js.map +0 -1
  99. package/dist/maps/layers/index.d.ts +0 -2
  100. package/dist/maps/layers/units.cjs +0 -207
  101. package/dist/maps/layers/units.cjs.map +0 -1
  102. package/dist/maps/layers/units.d.ts +0 -14
  103. package/dist/maps/layers/units.js +0 -204
  104. package/dist/maps/layers/units.js.map +0 -1
  105. package/dist/units/colors.cjs +0 -115
  106. package/dist/units/colors.cjs.map +0 -1
  107. package/dist/units/colors.d.ts +0 -20
  108. package/dist/units/colors.js +0 -113
  109. package/dist/units/colors.js.map +0 -1
  110. package/dist/units/resolvers.cjs +0 -125
  111. package/dist/units/resolvers.cjs.map +0 -1
  112. package/dist/units/resolvers.d.ts +0 -8
  113. package/dist/units/resolvers.js +0 -125
  114. package/dist/units/resolvers.js.map +0 -1
  115. package/src/maps/column-correlation/column-correlation-map.stories.ts +0 -108
  116. package/src/maps/column-correlation/core.ts +0 -342
  117. package/src/maps/column-correlation/index.ts +0 -2
  118. package/src/maps/column-correlation/state.ts +0 -315
  119. package/src/maps/column-navigation/index.ts +0 -2
  120. package/src/maps/column-navigation/mapbox/column-navigation-map.stories.ts +0 -278
  121. package/src/maps/column-navigation/mapbox/index.ts +0 -276
  122. package/src/maps/column-navigation/mapbox/keyboard-navigation.ts +0 -133
  123. package/src/maps/column-navigation/mapbox/state.ts +0 -119
  124. package/src/maps/column-navigation/svg/animated.ts +0 -78
  125. package/src/maps/column-navigation/svg/column-navigation-svg-map.stories.ts +0 -46
  126. package/src/maps/column-navigation/svg/data-fetcher.ts +0 -34
  127. package/src/maps/column-navigation/svg/index.ts +0 -96
  128. package/src/maps/column-navigation/svg/layers.ts +0 -233
  129. package/src/maps/column-navigation/utils/keyboard-navigation.ts +0 -58
  130. package/src/maps/index.ts +0 -4
  131. package/src/maps/inset-map/index.ts +0 -87
  132. package/src/maps/inset-map/inset-map.stories.ts +0 -20
  133. package/src/maps/layers/columns.ts +0 -216
  134. package/src/maps/layers/index.ts +0 -2
  135. package/src/maps/layers/units.ts +0 -286
  136. package/src/maps/unit-map.stories.ts +0 -79
  137. package/src/units/colors.ts +0 -183
  138. package/src/units/resolvers.ts +0 -141
@@ -1,87 +0,0 @@
1
- import { useCallback, useMemo } from "react";
2
- import {
3
- MapView,
4
- getBasicMapStyle,
5
- MapViewProps,
6
- } from "@macrostrat/map-interface";
7
- import h from "@macrostrat/hyper";
8
- import { MapboxMapProvider } from "@macrostrat/mapbox-react";
9
- import { useInDarkMode } from "@macrostrat/ui-components";
10
- import {
11
- removeMapLabels,
12
- removeSourceFromStyle,
13
- } from "@macrostrat/mapbox-utils";
14
- import type { ReactNode, CSSProperties } from "react";
15
-
16
- export interface InsetMapProps extends Omit<MapViewProps, "style"> {
17
- controls?: ReactNode;
18
- className?: string;
19
- children?: ReactNode;
20
- style?: CSSProperties;
21
- mapStyle?: mapboxgl.Style | string;
22
- showLabels?: boolean;
23
- showAdmin?: boolean;
24
- showRoads?: boolean;
25
- }
26
-
27
- export function InsetMap({
28
- controls,
29
- className,
30
- children,
31
- style,
32
- mapStyle,
33
- accessToken,
34
- showLabels = false,
35
- showAdmin = false,
36
- showRoads = false,
37
- ...rest
38
- }: InsetMapProps) {
39
- const inDarkMode = useInDarkMode();
40
- const _style = useMemo((): mapboxgl.Style | string => {
41
- return mapStyle ?? getBasicMapStyle({ inDarkMode });
42
- }, [mapStyle, inDarkMode]);
43
-
44
- const transformStyle = useCallback(
45
- (style) => {
46
- let newStyle = style;
47
- if (!showLabels) {
48
- newStyle = removeMapLabels(newStyle);
49
- }
50
- if (!showAdmin) {
51
- newStyle = removeSourceFromStyle(newStyle, null, "admin");
52
- }
53
- if (!showRoads) {
54
- newStyle = removeSourceFromStyle(newStyle, null, "road");
55
- newStyle = removeSourceFromStyle(newStyle, null, "aeroway");
56
- }
57
- return newStyle;
58
- },
59
- [mapStyle, showLabels, showRoads, showAdmin],
60
- );
61
-
62
- return h("div.inset-map", { className, style }, [
63
- h(MapboxMapProvider, [
64
- controls,
65
- h(
66
- MapView,
67
- {
68
- style: _style,
69
- accessToken,
70
- standalone: true,
71
- /* Default map position that centers on the bulk of Macrostrat columns
72
- */
73
- mapPosition: {
74
- camera: {
75
- lng: -100,
76
- lat: 38,
77
- altitude: 5000000,
78
- },
79
- },
80
- transformStyle,
81
- ...rest,
82
- },
83
- children,
84
- ),
85
- ]),
86
- ]);
87
- }
@@ -1,20 +0,0 @@
1
- import h from "@macrostrat/hyper";
2
-
3
- const mapboxToken = import.meta.env.VITE_MAPBOX_API_TOKEN;
4
-
5
- import { Meta } from "@storybook/react-vite";
6
- import { InsetMap } from ".";
7
-
8
- // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
9
- export default {
10
- title: "Column views/Maps/Inset map",
11
- component: InsetMap,
12
- description: "A basic inset map",
13
- } as Meta<typeof InsetMap>;
14
-
15
- export function BasicInsetMap() {
16
- return h(InsetMap, {
17
- style: { width: "800px", height: "600px" },
18
- accessToken: mapboxToken,
19
- });
20
- }
@@ -1,216 +0,0 @@
1
- import { useMapStyleOperator, useOverlayStyle } from "@macrostrat/mapbox-react";
2
- import { setGeoJSON } from "@macrostrat/mapbox-utils";
3
- import GeoJSON, { FeatureCollection } from "geojson";
4
- import { GeoJSONFeature } from "mapbox-gl";
5
- import { getCSSVariable } from "@macrostrat/color-utils";
6
- import { buildGeoJSONSource } from "@macrostrat/mapbox-utils";
7
- import { StyleFragment } from "@macrostrat/mapbox-react";
8
-
9
- export interface ColumnsStyleOptions {
10
- color?: string | any[];
11
- selectedColor?: string | any[];
12
- opacity?: number | any[];
13
- circleRadius?: number | any[];
14
- lineOpacity?: number | any[];
15
- lineWidth?: number | any[];
16
- lineColor?: string | any[];
17
- }
18
-
19
- interface ColumnLayerOptions extends ColumnsStyleOptions {
20
- enabled: boolean;
21
- columns: FeatureCollection | GeoJSONFeature[];
22
- }
23
-
24
- export function BaseColumnsLayer({
25
- enabled = true,
26
- columns,
27
- ...rest
28
- }: ColumnLayerOptions) {
29
- useOverlayStyle(() => (enabled ? buildColumnsStyle(rest) : null), [enabled]);
30
-
31
- useMapStyleOperator(
32
- (map) => {
33
- if (columns == null) {
34
- return;
35
- }
36
-
37
- setGeoJSON(map, "columns", promoteToFeatureCollection(columns));
38
- },
39
- [columns, enabled],
40
- );
41
- return null;
42
- }
43
-
44
- function promoteToFeatureCollection(
45
- data: FeatureCollection | GeoJSONFeature | GeoJSONFeature[] | null,
46
- ): FeatureCollection | null {
47
- if (data == null) return null;
48
- if ("type" in data && data.type == "Feature") {
49
- return {
50
- type: "FeatureCollection",
51
- features: [data],
52
- };
53
- }
54
- if (
55
- "type" in data &&
56
- data.type == "FeatureCollection" &&
57
- "features" in data
58
- ) {
59
- return data;
60
- }
61
- return {
62
- type: "FeatureCollection",
63
- features: data,
64
- };
65
- }
66
-
67
- export function buildColumnsStyle(
68
- opts: ColumnsStyleOptions = {},
69
- ): StyleFragment {
70
- const { color } = opts;
71
- const columnBaseColor =
72
- color ?? getCSSVariable("--text-subtle-color", "black");
73
- let columnColor: any = columnBaseColor;
74
- const columnSelectedColor =
75
- opts.selectedColor ?? getCSSVariable("--selection-color", "purple");
76
-
77
- const lineColor = opts.lineColor ?? columnBaseColor;
78
- // Highlight on either direct map hover or an externally-driven highlight
79
- // (e.g. hovering the corresponding column header elsewhere in the UI).
80
- const isHovered = [
81
- "any",
82
- ["boolean", ["feature-state", "hover"], false],
83
- ["boolean", ["feature-state", "highlighted"], false],
84
- ];
85
- // If color is in the feature state or geojson properties, use that as second choice
86
- if (typeof columnColor === "string") {
87
- columnColor = [
88
- "coalesce",
89
- ["feature-state", "color"],
90
- ["get", "color"],
91
- columnColor,
92
- ];
93
- }
94
-
95
- const fillOpacity = opts.opacity ?? 0.1;
96
-
97
- const lineOpacity = opts.lineOpacity ?? 0.5;
98
- const lineWidth = opts.lineWidth ?? 2;
99
-
100
- const circleRadius = opts.circleRadius ?? 4;
101
-
102
- return {
103
- sources: {
104
- columns: buildGeoJSONSource(),
105
- },
106
- version: 8,
107
- layers: [
108
- {
109
- id: "columns-fill",
110
- type: "fill",
111
- source: "columns",
112
- paint: {
113
- "fill-color": columnColor,
114
- "fill-opacity": fillOpacity,
115
- },
116
- },
117
- {
118
- id: "columns-points",
119
- type: "circle",
120
- source: "columns",
121
- paint: {
122
- "circle-radius": circleRadius,
123
- "circle-color": columnColor,
124
- "circle-opacity": fillOpacity,
125
- },
126
- filter: ["==", "$type", "Point"],
127
- },
128
- {
129
- id: "columns-line",
130
- type: "line",
131
- source: "columns",
132
- paint: {
133
- "line-color": ["case", isHovered, columnSelectedColor, lineColor],
134
- "line-width": lineWidth,
135
- "line-opacity": ["case", isHovered, 1.0, lineOpacity],
136
- },
137
- },
138
- ],
139
- };
140
- }
141
-
142
- export type ColumnFeature = GeoJSON.Feature & { id: number };
143
-
144
- const selectedColumnSourceID = "selectedColumn";
145
-
146
- export function SelectedColumnOverlay({
147
- selectedColumn,
148
- ...styleOpts
149
- }: { selectedColumn: ColumnFeature | null } & SelectedColumnStyleOpts) {
150
- useOverlayStyle(() => buildSelectedColumnStyle(styleOpts), []);
151
-
152
- useMapStyleOperator(
153
- (map) => {
154
- setGeoJSON(
155
- map,
156
- selectedColumnSourceID,
157
- promoteToFeatureCollection(selectedColumn as GeoJSONFeature | null),
158
- );
159
- },
160
- [selectedColumn],
161
- );
162
-
163
- return null;
164
- }
165
-
166
- interface SelectedColumnStyleOpts {
167
- color?: string | any[];
168
- }
169
-
170
- function buildSelectedColumnStyle(
171
- opts: SelectedColumnStyleOpts = {},
172
- ): StyleFragment {
173
- const columnSelectedColor: any =
174
- opts.color ?? getCSSVariable("--selection-color", "purple");
175
-
176
- return {
177
- sources: {
178
- selectedColumn: buildGeoJSONSource(),
179
- },
180
- version: 8,
181
- layers: [
182
- {
183
- id: "selected-column-highlight",
184
- type: "fill",
185
- source: selectedColumnSourceID,
186
- paint: {
187
- "fill-color": columnSelectedColor,
188
- "fill-opacity": 0.5,
189
- },
190
- filter: ["==", "$type", "Polygon"],
191
- },
192
- {
193
- id: "selected-column-edge",
194
- type: "line",
195
- source: selectedColumnSourceID,
196
- paint: {
197
- "line-color": columnSelectedColor,
198
- "line-width": 2,
199
- "line-opacity": 1.0,
200
- },
201
- filter: ["==", "$type", "Polygon"],
202
- },
203
- {
204
- id: "selected-column-point",
205
- type: "circle",
206
- source: selectedColumnSourceID,
207
- paint: {
208
- "circle-radius": 6,
209
- "circle-color": columnSelectedColor,
210
- "circle-opacity": 1.0,
211
- },
212
- filter: ["==", "$type", "Point"],
213
- },
214
- ],
215
- };
216
- }
@@ -1,2 +0,0 @@
1
- export * from "./columns";
2
- export * from "./units";
@@ -1,286 +0,0 @@
1
- import {
2
- useLithologies,
3
- useMacrostratColumns,
4
- } from "@macrostrat/data-provider";
5
- import { useAPIResult } from "@macrostrat/ui-components";
6
- import { useMapStyleOperator, useOverlayStyle } from "@macrostrat/mapbox-react";
7
- import { FeatureCollection } from "geojson";
8
- import { useMemo } from "react";
9
- import { mergeStyles, setGeoJSON } from "@macrostrat/mapbox-utils";
10
- import { UnitLithology, UnitLong } from "@macrostrat/api-types";
11
- import { flattenLithologies, getMixedColorForData } from "../../units";
12
- import { getBestFGDCPatternForLithologyList } from "../../units/resolvers";
13
- import {
14
- setupStyleImageManager,
15
- loadStyleImage,
16
- StyleFragment,
17
- } from "@macrostrat/map-styles";
18
- import { asChromaColor } from "@macrostrat/color-utils";
19
- import { buildGeoJSONSource } from "@macrostrat/mapbox-utils";
20
- import pMap from "p-map";
21
- import { BaseColumnsLayer } from "./columns";
22
- import h from "@macrostrat/hyper";
23
-
24
- export interface UnitsOverlayProps {
25
- time: number;
26
- ageSpan?: number;
27
- project?: number | number[];
28
- patterns?: boolean;
29
- }
30
-
31
- export function MacrostratUnitsOverlay(props: UnitsOverlayProps) {
32
- const { time, ageSpan = 0.05, patterns = false } = props;
33
- const lithMap = useLithologies();
34
-
35
- useOverlayStyle(() => {
36
- return buildUnitsStyle({ patterns });
37
- }, [patterns]);
38
-
39
- useMapStyleOperator(
40
- (map) => {
41
- if (!patterns) return;
42
- setupStyleImageManager(map, { verbose: false });
43
- },
44
- [patterns],
45
- );
46
-
47
- const params = useMemo(() => {
48
- let project: number[] | undefined;
49
- if (Number.isFinite(props.project)) {
50
- project = [props.project as number];
51
- } else if (!Array.isArray(props.project)) {
52
- project = undefined;
53
- }
54
- // Project can only be a single project for now
55
- const projectCompat =
56
- project != null && project.length > 0 ? project[0] : undefined;
57
-
58
- return {
59
- age_bottom: time + ageSpan / 2,
60
- age_top: time - ageSpan / 2,
61
- response: "long",
62
- project: projectCompat,
63
- };
64
- }, [time, ageSpan, props.project]);
65
-
66
- const units: UnitLong[] = useAPIResult("/units", params);
67
- const columns = useMacrostratColumns(params.project, false);
68
-
69
- useMapStyleOperator(
70
- (map) => {
71
- if (units == null || columns == null || lithMap == null) {
72
- return;
73
- }
74
-
75
- const getColorForLithology = (data: UnitLithology): string | null => {
76
- return lithMap?.get(data.lith_id)?.color ?? null;
77
- };
78
-
79
- const unitsMap = postProcessUnits(units, getColorForLithology);
80
- handleUnitsLayerUpdate(map, unitsMap, columns);
81
- if (patterns) {
82
- handlePatternOverlayUpdate(
83
- map,
84
- unitsMap,
85
- columns,
86
- getColorForLithology,
87
- ).then(() => {});
88
- }
89
- },
90
- [units, lithMap, columns, patterns],
91
- );
92
-
93
- const isHovered = ["boolean", ["feature-state", "hover"], false];
94
- const isShown = ["boolean", ["feature-state", "shown"], false];
95
-
96
- const opacity = [
97
- "case",
98
- ["all", isHovered, isShown],
99
- 0.9,
100
- isShown,
101
- 0.8,
102
- isHovered,
103
- 0.3,
104
- 0.0,
105
- ];
106
-
107
- return h([
108
- h(BaseColumnsLayer, {
109
- enabled: true,
110
- columns,
111
- opacity,
112
- lineOpacity: 0.2,
113
- lineColor: "lightgray",
114
- color: "transparent",
115
- }),
116
- ]);
117
- }
118
-
119
- function handleUnitsLayerUpdate(
120
- map,
121
- unitsMap: Map<number, UnitsDisplayInfo>,
122
- columns: any[],
123
- ) {
124
- // Update feature states
125
- for (const column of columns) {
126
- const col_id = column.properties.col_id;
127
- const info = unitsMap.get(Number(col_id));
128
- const color = info?.color;
129
- map.setFeatureState(
130
- { source: "columns", id: col_id },
131
- {
132
- color,
133
- shown: color != null,
134
- },
135
- );
136
- }
137
- }
138
-
139
- async function handlePatternOverlayUpdate(
140
- map,
141
- unitsMap: Map<number, UnitsDisplayInfo>,
142
- columns: any[],
143
- getColor: LithologyColorGetter,
144
- ) {
145
- // synthesize patterns not yet in cache
146
-
147
- const colsWithPatterns = [];
148
- const patternIDs = new Set<string>();
149
- // Update feature states
150
- for (const column of columns) {
151
- const col_id = column.properties.col_id;
152
- const info = unitsMap.get(Number(col_id));
153
- if (info == null) continue;
154
- const pattern = getPatternSpec(info?.liths, getColor);
155
- if (pattern == null) continue;
156
-
157
- colsWithPatterns.push({
158
- type: "Feature",
159
- geometry: column.geometry,
160
- properties: {
161
- col_id,
162
- pattern,
163
- },
164
- });
165
- patternIDs.add(pattern);
166
- }
167
-
168
- const patternsToLoad = patternIDs.values().filter((d) => !map.hasImage(d));
169
-
170
- const mapper = async (patternID) => {
171
- try {
172
- await loadStyleImage(map, patternID, { pixelRatio: 10 });
173
- } catch (e) {}
174
- };
175
- // Load all pattern images
176
- await pMap(patternsToLoad, mapper, { concurrency: 5 });
177
-
178
- // Set data for pattern layer
179
- // This is inefficient but the only way to set per-feature patterns in Mapbox
180
- const patternData: FeatureCollection = {
181
- type: "FeatureCollection",
182
- features: colsWithPatterns,
183
- };
184
- setGeoJSON(map, "column-patterns", patternData);
185
- }
186
-
187
- const cachedColors = new Map<string, string>();
188
-
189
- function getDarkenedColor(color: string): string {
190
- /** Memoized function to get a darkened version of a color for pattern use */
191
- if (cachedColors.has(color)) {
192
- return cachedColors.get(color);
193
- }
194
- const c1 = asChromaColor(color).set("hsl.l", 0.4).set("hsl.s", 0.8).hex();
195
- cachedColors.set(color, c1);
196
- return c1;
197
- }
198
-
199
- interface UnitsDisplayInfo {
200
- col_id: number;
201
- units: UnitLong[];
202
- color: string;
203
- liths: UnitLithology[];
204
- }
205
-
206
- type LithologyColorGetter = (val: UnitLithology) => string | null;
207
-
208
- function postProcessUnits(
209
- units: UnitLong[],
210
- getColor: LithologyColorGetter,
211
- ): Map<number, UnitsDisplayInfo> {
212
- // Group by col_id
213
- const unitsByColumn: Map<number, UnitLong[]> = new Map();
214
- for (const unit of units) {
215
- const col_id = Number(unit.col_id);
216
- if (!unitsByColumn.has(col_id)) {
217
- unitsByColumn.set(col_id, [unit]);
218
- } else {
219
- unitsByColumn.set(col_id, [...unitsByColumn.get(col_id), unit]);
220
- }
221
- }
222
-
223
- // Summarize units for display
224
- const res = new Map<number, UnitsDisplayInfo>();
225
- for (const [col_id, unitList] of unitsByColumn.entries()) {
226
- const liths = flattenLithologies(unitList.map((u) => u.lith));
227
- res.set(col_id, {
228
- col_id,
229
- units: unitList,
230
- liths,
231
- color: getMixedColorForData(liths, getColor),
232
- });
233
- }
234
-
235
- return res;
236
- }
237
-
238
- function getPatternSpec(
239
- liths: UnitLithology[],
240
- getColor: LithologyColorGetter,
241
- ): string | null {
242
- const patternData = getBestFGDCPatternForLithologyList(liths);
243
- if (patternData == null) return null;
244
- let { patternID, lith } = patternData;
245
- const color = getDarkenedColor(getColor(lith));
246
- return `fgdc:${patternID}:${color}:transparent`;
247
- }
248
-
249
- type UnitsStyleOptions = {
250
- color?: string;
251
- patterns?: boolean;
252
- };
253
-
254
- export function buildUnitsStyle(opts: UnitsStyleOptions = {}): StyleFragment {
255
- const { patterns = false } = opts;
256
-
257
- // If color is in the feature state or geojson properties, use that as second choice
258
-
259
- const baseStyle: StyleFragment = {
260
- sources: {},
261
- version: 8,
262
- };
263
-
264
- if (!patterns) {
265
- return baseStyle;
266
- }
267
-
268
- const patternStyle: StyleFragment = {
269
- sources: {
270
- "column-patterns": buildGeoJSONSource(),
271
- },
272
- layers: [
273
- {
274
- id: "columns-fill-pattern",
275
- type: "fill",
276
- source: "column-patterns",
277
- paint: {
278
- "fill-pattern": ["get", "pattern"],
279
- "fill-opacity": 1,
280
- },
281
- },
282
- ],
283
- };
284
-
285
- return mergeStyles(baseStyle, patternStyle);
286
- }
@@ -1,79 +0,0 @@
1
- import h from "@macrostrat/hyper";
2
- import { Meta } from "@storybook/react-vite";
3
- import { InsetMap } from "./inset-map";
4
- import { MacrostratDataProvider } from "@macrostrat/data-provider";
5
- import { MacrostratUnitsOverlay } from "./layers/units";
6
- import {
7
- ColumnHoverInteraction,
8
- ColumnSelectionManager,
9
- } from "./column-navigation";
10
- import { useState } from "react";
11
-
12
- // @ts-ignore
13
- const mapboxToken = import.meta.env.VITE_MAPBOX_API_TOKEN;
14
-
15
- // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
16
- export default {
17
- title: "Column views/Maps/Unit map",
18
- component: UnitMapComponent,
19
- description: "A map of units through time",
20
- argTypes: {
21
- time: { control: "number", defaultValue: 100 },
22
- ageSpan: { control: "number", defaultValue: 0.05 },
23
- patterns: { control: "boolean", defaultValue: false },
24
- },
25
- } as Meta<typeof InsetMap>;
26
-
27
- function UnitMapComponent(props) {
28
- const { children, ...rest } = props;
29
- return h(
30
- MacrostratDataProvider,
31
- {
32
- baseURL: "https://dev.macrostrat.org/api/v2",
33
- },
34
- h(
35
- "div",
36
- h(
37
- InsetMap,
38
- {
39
- style: { width: "800px", height: "600px" },
40
- accessToken: mapboxToken,
41
- },
42
- [h(MacrostratUnitsOverlay, rest), children],
43
- ),
44
- ),
45
- );
46
- }
47
-
48
- export const UnitMap = {
49
- args: {
50
- time: 100,
51
- ageSpan: 0.05,
52
- },
53
- };
54
-
55
- export const WithPatterns = {
56
- args: {
57
- time: 100,
58
- ageSpan: 0.05,
59
- patterns: true,
60
- },
61
- };
62
-
63
- export const WithColumnSelection = {
64
- args: {
65
- time: 100,
66
- ageSpan: 0.05,
67
- patterns: false,
68
- },
69
- render(args) {
70
- const [selectedColumn, setSelectedColumn] = useState(null);
71
- return h(UnitMapComponent, args, [
72
- h(ColumnHoverInteraction),
73
- h(ColumnSelectionManager, {
74
- selectedColumn,
75
- onSelectColumn: setSelectedColumn,
76
- }),
77
- ]);
78
- },
79
- };