@macrostrat/column-views 3.2.2 → 3.3.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.
- package/CHANGELOG.md +5 -0
- package/dist/index.cjs +15 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -5
- package/dist/maps/column-correlation/core.cjs +10 -30
- package/dist/maps/column-correlation/core.cjs.map +1 -1
- package/dist/maps/column-correlation/core.d.ts +1 -1
- package/dist/maps/column-correlation/core.js +10 -30
- package/dist/maps/column-correlation/core.js.map +1 -1
- package/dist/maps/column-navigation/mapbox/index.cjs +156 -118
- package/dist/maps/column-navigation/mapbox/index.cjs.map +1 -1
- package/dist/maps/column-navigation/mapbox/index.d.ts +23 -2
- package/dist/maps/column-navigation/mapbox/index.js +158 -120
- package/dist/maps/column-navigation/mapbox/index.js.map +1 -1
- package/dist/maps/column-navigation/mapbox/keyboard-navigation.cjs +7 -1
- package/dist/maps/column-navigation/mapbox/keyboard-navigation.cjs.map +1 -1
- package/dist/maps/column-navigation/mapbox/keyboard-navigation.d.ts +3 -26
- package/dist/maps/column-navigation/mapbox/keyboard-navigation.js +9 -3
- package/dist/maps/column-navigation/mapbox/keyboard-navigation.js.map +1 -1
- package/dist/maps/index.d.ts +2 -2
- package/dist/maps/{_shared/inset-map.cjs → inset-map/index.cjs} +1 -1
- package/dist/maps/inset-map/index.cjs.map +1 -0
- package/dist/maps/{_shared/inset-map.js → inset-map/index.js} +1 -1
- package/dist/maps/inset-map/index.js.map +1 -0
- package/dist/maps/layers/columns.cjs +161 -0
- package/dist/maps/layers/columns.cjs.map +1 -0
- package/dist/maps/layers/columns.d.ts +28 -0
- package/dist/maps/layers/columns.js +161 -0
- package/dist/maps/layers/columns.js.map +1 -0
- package/dist/maps/layers/index.d.ts +2 -0
- package/dist/maps/{units-overlay/index.cjs → layers/units.cjs} +41 -88
- package/dist/maps/layers/units.cjs.map +1 -0
- package/dist/maps/{units-overlay/index.d.ts → layers/units.d.ts} +1 -1
- package/dist/maps/{units-overlay/index.js → layers/units.js} +34 -82
- package/dist/maps/layers/units.js.map +1 -0
- package/dist/unit-details/age-range.cjs +87 -44
- package/dist/unit-details/age-range.cjs.map +1 -1
- package/dist/unit-details/age-range.d.ts +32 -5
- package/dist/unit-details/age-range.js +85 -44
- package/dist/unit-details/age-range.js.map +1 -1
- package/package.json +4 -4
- package/src/maps/column-correlation/core.ts +9 -29
- package/src/maps/column-navigation/mapbox/index.ts +191 -138
- package/src/maps/column-navigation/mapbox/keyboard-navigation.ts +17 -3
- package/src/maps/index.ts +2 -2
- package/src/maps/layers/columns.ts +210 -0
- package/src/maps/layers/index.ts +2 -0
- package/src/maps/{units-overlay/index.ts → layers/units.ts} +34 -84
- package/src/maps/unit-map.stories.ts +27 -12
- package/src/unit-details/age-range.ts +125 -47
- package/dist/maps/_shared/index.d.ts +0 -2
- package/dist/maps/_shared/inset-map.cjs.map +0 -1
- package/dist/maps/_shared/inset-map.js.map +0 -1
- package/dist/maps/_shared/styles.cjs +0 -73
- package/dist/maps/_shared/styles.cjs.map +0 -1
- package/dist/maps/_shared/styles.d.ts +0 -2
- package/dist/maps/_shared/styles.js +0 -73
- package/dist/maps/_shared/styles.js.map +0 -1
- package/dist/maps/units-overlay/index.cjs.map +0 -1
- package/dist/maps/units-overlay/index.js.map +0 -1
- package/src/maps/_shared/index.ts +0 -2
- package/src/maps/_shared/styles.ts +0 -76
- /package/dist/maps/{_shared/inset-map.d.ts → inset-map/index.d.ts} +0 -0
- /package/src/maps/{_shared/inset-map.ts → inset-map/index.ts} +0 -0
- /package/src/maps/{_shared → inset-map}/inset-map.stories.ts +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
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
|
+
const isHovered = ["boolean", ["feature-state", "hover"], false];
|
|
79
|
+
// If color is in the feature state or geojson properties, use that as second choice
|
|
80
|
+
if (typeof columnColor === "string") {
|
|
81
|
+
columnColor = [
|
|
82
|
+
"coalesce",
|
|
83
|
+
["feature-state", "color"],
|
|
84
|
+
["get", "color"],
|
|
85
|
+
columnColor,
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const fillOpacity = opts.opacity ?? 0.1;
|
|
90
|
+
|
|
91
|
+
const lineOpacity = opts.lineOpacity ?? 0.5;
|
|
92
|
+
const lineWidth = opts.lineWidth ?? 2;
|
|
93
|
+
|
|
94
|
+
const circleRadius = opts.circleRadius ?? 4;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
sources: {
|
|
98
|
+
columns: buildGeoJSONSource(),
|
|
99
|
+
},
|
|
100
|
+
version: 8,
|
|
101
|
+
layers: [
|
|
102
|
+
{
|
|
103
|
+
id: "columns-fill",
|
|
104
|
+
type: "fill",
|
|
105
|
+
source: "columns",
|
|
106
|
+
paint: {
|
|
107
|
+
"fill-color": columnColor,
|
|
108
|
+
"fill-opacity": fillOpacity,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "columns-points",
|
|
113
|
+
type: "circle",
|
|
114
|
+
source: "columns",
|
|
115
|
+
paint: {
|
|
116
|
+
"circle-radius": circleRadius,
|
|
117
|
+
"circle-color": columnColor,
|
|
118
|
+
"circle-opacity": fillOpacity,
|
|
119
|
+
},
|
|
120
|
+
filter: ["==", "$type", "Point"],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "columns-line",
|
|
124
|
+
type: "line",
|
|
125
|
+
source: "columns",
|
|
126
|
+
paint: {
|
|
127
|
+
"line-color": ["case", isHovered, columnSelectedColor, lineColor],
|
|
128
|
+
"line-width": lineWidth,
|
|
129
|
+
"line-opacity": ["case", isHovered, 1.0, lineOpacity],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export type ColumnFeature = GeoJSON.Feature & { id: number };
|
|
137
|
+
|
|
138
|
+
const selectedColumnSourceID = "selectedColumn";
|
|
139
|
+
|
|
140
|
+
export function SelectedColumnOverlay({
|
|
141
|
+
selectedColumn,
|
|
142
|
+
...styleOpts
|
|
143
|
+
}: { selectedColumn: ColumnFeature | null } & SelectedColumnStyleOpts) {
|
|
144
|
+
useOverlayStyle(() => buildSelectedColumnStyle(styleOpts), []);
|
|
145
|
+
|
|
146
|
+
useMapStyleOperator(
|
|
147
|
+
(map) => {
|
|
148
|
+
setGeoJSON(
|
|
149
|
+
map,
|
|
150
|
+
selectedColumnSourceID,
|
|
151
|
+
promoteToFeatureCollection(selectedColumn as GeoJSONFeature | null),
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
[selectedColumn],
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface SelectedColumnStyleOpts {
|
|
161
|
+
color?: string | any[];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildSelectedColumnStyle(
|
|
165
|
+
opts: SelectedColumnStyleOpts = {},
|
|
166
|
+
): StyleFragment {
|
|
167
|
+
const columnSelectedColor: any =
|
|
168
|
+
opts.color ?? getCSSVariable("--selection-color", "purple");
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
sources: {
|
|
172
|
+
selectedColumn: buildGeoJSONSource(),
|
|
173
|
+
},
|
|
174
|
+
version: 8,
|
|
175
|
+
layers: [
|
|
176
|
+
{
|
|
177
|
+
id: "selected-column-highlight",
|
|
178
|
+
type: "fill",
|
|
179
|
+
source: selectedColumnSourceID,
|
|
180
|
+
paint: {
|
|
181
|
+
"fill-color": columnSelectedColor,
|
|
182
|
+
"fill-opacity": 0.5,
|
|
183
|
+
},
|
|
184
|
+
filter: ["==", "$type", "Polygon"],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
id: "selected-column-edge",
|
|
188
|
+
type: "line",
|
|
189
|
+
source: selectedColumnSourceID,
|
|
190
|
+
paint: {
|
|
191
|
+
"line-color": columnSelectedColor,
|
|
192
|
+
"line-width": 2,
|
|
193
|
+
"line-opacity": 1.0,
|
|
194
|
+
},
|
|
195
|
+
filter: ["==", "$type", "Polygon"],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: "selected-column-point",
|
|
199
|
+
type: "circle",
|
|
200
|
+
source: selectedColumnSourceID,
|
|
201
|
+
paint: {
|
|
202
|
+
"circle-radius": 6,
|
|
203
|
+
"circle-color": columnSelectedColor,
|
|
204
|
+
"circle-opacity": 1.0,
|
|
205
|
+
},
|
|
206
|
+
filter: ["==", "$type", "Point"],
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
useMacrostratColumns,
|
|
4
4
|
} from "@macrostrat/data-provider";
|
|
5
5
|
import { useAPIResult } from "@macrostrat/ui-components";
|
|
6
|
-
import { useMapStyleOperator } from "@macrostrat/mapbox-react";
|
|
6
|
+
import { useMapStyleOperator, useOverlayStyle } from "@macrostrat/mapbox-react";
|
|
7
7
|
import { FeatureCollection } from "geojson";
|
|
8
8
|
import { useMemo } from "react";
|
|
9
9
|
import { mergeStyles, setGeoJSON } from "@macrostrat/mapbox-utils";
|
|
@@ -15,9 +15,11 @@ import {
|
|
|
15
15
|
loadStyleImage,
|
|
16
16
|
StyleFragment,
|
|
17
17
|
} from "@macrostrat/map-styles";
|
|
18
|
-
import { asChromaColor
|
|
18
|
+
import { asChromaColor } from "@macrostrat/color-utils";
|
|
19
19
|
import { buildGeoJSONSource } from "@macrostrat/mapbox-utils";
|
|
20
20
|
import pMap from "p-map";
|
|
21
|
+
import { BaseColumnsLayer } from "./columns";
|
|
22
|
+
import h from "@macrostrat/hyper";
|
|
21
23
|
|
|
22
24
|
export interface UnitsOverlayProps {
|
|
23
25
|
time: number;
|
|
@@ -30,6 +32,10 @@ export function MacrostratUnitsOverlay(props: UnitsOverlayProps) {
|
|
|
30
32
|
const { time, ageSpan = 0.05, patterns = false } = props;
|
|
31
33
|
const lithMap = useLithologies();
|
|
32
34
|
|
|
35
|
+
useOverlayStyle(() => {
|
|
36
|
+
return buildUnitsStyle({ patterns });
|
|
37
|
+
}, [patterns]);
|
|
38
|
+
|
|
33
39
|
useMapStyleOperator(
|
|
34
40
|
(map) => {
|
|
35
41
|
if (!patterns) return;
|
|
@@ -60,21 +66,6 @@ export function MacrostratUnitsOverlay(props: UnitsOverlayProps) {
|
|
|
60
66
|
const units: UnitLong[] = useAPIResult("/units", params);
|
|
61
67
|
const columns = useMacrostratColumns(params.project, false);
|
|
62
68
|
|
|
63
|
-
// Set up basic columns layer
|
|
64
|
-
useMapStyleOperator(
|
|
65
|
-
(map) => {
|
|
66
|
-
if (columns == null) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const data: FeatureCollection = {
|
|
70
|
-
type: "FeatureCollection",
|
|
71
|
-
features: columns,
|
|
72
|
-
};
|
|
73
|
-
setGeoJSON(map, "columns", data);
|
|
74
|
-
},
|
|
75
|
-
[columns],
|
|
76
|
-
);
|
|
77
|
-
|
|
78
69
|
useMapStyleOperator(
|
|
79
70
|
(map) => {
|
|
80
71
|
if (units == null || columns == null || lithMap == null) {
|
|
@@ -99,7 +90,30 @@ export function MacrostratUnitsOverlay(props: UnitsOverlayProps) {
|
|
|
99
90
|
[units, lithMap, columns, patterns],
|
|
100
91
|
);
|
|
101
92
|
|
|
102
|
-
|
|
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
|
+
]);
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
function handleUnitsLayerUpdate(
|
|
@@ -238,77 +252,13 @@ type UnitsStyleOptions = {
|
|
|
238
252
|
};
|
|
239
253
|
|
|
240
254
|
export function buildUnitsStyle(opts: UnitsStyleOptions = {}): StyleFragment {
|
|
241
|
-
const {
|
|
242
|
-
|
|
243
|
-
let columnBaseColor: any =
|
|
244
|
-
color ?? getCSSVariable("--text-subtle-color", "black");
|
|
245
|
-
const columnSelectedColor = getCSSVariable("--selection-color", "purple");
|
|
255
|
+
const { patterns = false } = opts;
|
|
246
256
|
|
|
247
257
|
// If color is in the feature state or geojson properties, use that as second choice
|
|
248
258
|
|
|
249
|
-
let columnColor: any = [
|
|
250
|
-
"coalesce",
|
|
251
|
-
["feature-state", "color"],
|
|
252
|
-
["get", "color"],
|
|
253
|
-
columnBaseColor,
|
|
254
|
-
];
|
|
255
|
-
|
|
256
259
|
const baseStyle: StyleFragment = {
|
|
257
|
-
sources: {
|
|
258
|
-
columns: buildGeoJSONSource(),
|
|
259
|
-
},
|
|
260
|
+
sources: {},
|
|
260
261
|
version: 8,
|
|
261
|
-
layers: [
|
|
262
|
-
{
|
|
263
|
-
id: "columns-fill",
|
|
264
|
-
type: "fill",
|
|
265
|
-
source: "columns",
|
|
266
|
-
paint: {
|
|
267
|
-
"fill-color": columnColor,
|
|
268
|
-
"fill-opacity": [
|
|
269
|
-
"case",
|
|
270
|
-
["boolean", ["feature-state", "shown"], false],
|
|
271
|
-
0.8,
|
|
272
|
-
["boolean", ["feature-state", "hover"], false],
|
|
273
|
-
0.3,
|
|
274
|
-
0.1,
|
|
275
|
-
],
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
id: "columns-line",
|
|
280
|
-
type: "line",
|
|
281
|
-
source: "columns",
|
|
282
|
-
paint: {
|
|
283
|
-
"line-color": columnColor,
|
|
284
|
-
"line-width": 1,
|
|
285
|
-
"line-opacity": 0.5,
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
id: "columns-points",
|
|
290
|
-
type: "circle",
|
|
291
|
-
source: "columns",
|
|
292
|
-
paint: {
|
|
293
|
-
"circle-radius": 4,
|
|
294
|
-
"circle-color": [
|
|
295
|
-
"case",
|
|
296
|
-
["boolean", ["feature-state", "shown"], false],
|
|
297
|
-
columnColor,
|
|
298
|
-
columnBaseColor,
|
|
299
|
-
],
|
|
300
|
-
"circle-opacity": [
|
|
301
|
-
"case",
|
|
302
|
-
["boolean", ["feature-state", "shown"], false],
|
|
303
|
-
0.8,
|
|
304
|
-
["boolean", ["feature-state", "hover"], false],
|
|
305
|
-
0.3,
|
|
306
|
-
0.1,
|
|
307
|
-
],
|
|
308
|
-
},
|
|
309
|
-
filter: ["==", "$type", "Point"],
|
|
310
|
-
},
|
|
311
|
-
],
|
|
312
262
|
};
|
|
313
263
|
|
|
314
264
|
if (!patterns) {
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import h from "@macrostrat/hyper";
|
|
2
2
|
import { Meta } from "@storybook/react-vite";
|
|
3
|
-
import { InsetMap } from "./
|
|
3
|
+
import { InsetMap } from "./inset-map";
|
|
4
4
|
import { MacrostratDataProvider } from "@macrostrat/data-provider";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { MacrostratUnitsOverlay } from "./layers/units";
|
|
6
|
+
import {
|
|
7
|
+
ColumnHoverInteraction,
|
|
8
|
+
ColumnSelectionManager,
|
|
9
|
+
} from "./column-navigation";
|
|
10
|
+
import { useState } from "react";
|
|
7
11
|
|
|
8
12
|
// @ts-ignore
|
|
9
13
|
const mapboxToken = import.meta.env.VITE_MAPBOX_API_TOKEN;
|
|
@@ -21,13 +25,7 @@ export default {
|
|
|
21
25
|
} as Meta<typeof InsetMap>;
|
|
22
26
|
|
|
23
27
|
function UnitMapComponent(props) {
|
|
24
|
-
const
|
|
25
|
-
let styles: any[] = [
|
|
26
|
-
buildUnitsStyle({ color: "#444", patterns: props.patterns }),
|
|
27
|
-
];
|
|
28
|
-
return styles;
|
|
29
|
-
}, []);
|
|
30
|
-
|
|
28
|
+
const { children, ...rest } = props;
|
|
31
29
|
return h(
|
|
32
30
|
MacrostratDataProvider,
|
|
33
31
|
{
|
|
@@ -40,9 +38,8 @@ function UnitMapComponent(props) {
|
|
|
40
38
|
{
|
|
41
39
|
style: { width: "800px", height: "600px" },
|
|
42
40
|
accessToken: mapboxToken,
|
|
43
|
-
overlayStyles,
|
|
44
41
|
},
|
|
45
|
-
h(MacrostratUnitsOverlay,
|
|
42
|
+
[h(MacrostratUnitsOverlay, rest), children],
|
|
46
43
|
),
|
|
47
44
|
),
|
|
48
45
|
);
|
|
@@ -62,3 +59,21 @@ export const WithPatterns = {
|
|
|
62
59
|
patterns: true,
|
|
63
60
|
},
|
|
64
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
|
+
};
|
|
@@ -2,27 +2,50 @@ import {
|
|
|
2
2
|
DataField,
|
|
3
3
|
IntervalShort,
|
|
4
4
|
IntervalTag,
|
|
5
|
+
type IntervalTagProps,
|
|
5
6
|
ItemList,
|
|
6
7
|
Value,
|
|
7
8
|
} from "@macrostrat/data-components";
|
|
8
9
|
import { useMacrostratDefs } from "@macrostrat/data-provider";
|
|
9
10
|
import h from "./age-range.module.sass";
|
|
10
11
|
import { formatProportion, formatRange } from "./utils";
|
|
12
|
+
import classNames from "classnames";
|
|
13
|
+
import { useMemo } from "react";
|
|
11
14
|
|
|
12
|
-
export function AgeField({ unit, children }) {
|
|
13
|
-
const [
|
|
15
|
+
export function AgeField({ unit, children, ...rest }) {
|
|
16
|
+
const [_b_age, _t_age, _unit] = getAgeRange(unit);
|
|
14
17
|
|
|
15
18
|
return h(
|
|
16
19
|
DataField,
|
|
17
20
|
{
|
|
18
21
|
label: "Age",
|
|
19
|
-
value: formatRange(
|
|
22
|
+
value: formatRange(_b_age, _t_age),
|
|
20
23
|
unit: _unit,
|
|
24
|
+
...rest,
|
|
21
25
|
},
|
|
22
26
|
children,
|
|
23
27
|
);
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
export function AgeRange({
|
|
31
|
+
data,
|
|
32
|
+
className,
|
|
33
|
+
}: {
|
|
34
|
+
data: {
|
|
35
|
+
t_age: number;
|
|
36
|
+
b_age: number;
|
|
37
|
+
};
|
|
38
|
+
className?: string;
|
|
39
|
+
}) {
|
|
40
|
+
const [_b_age, _t_age, _unit] = getAgeRange(data);
|
|
41
|
+
|
|
42
|
+
return h(Value, {
|
|
43
|
+
value: formatRange(_b_age, _t_age),
|
|
44
|
+
unit: _unit,
|
|
45
|
+
className,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
export function AgeLabel({
|
|
27
50
|
age,
|
|
28
51
|
maximumFractionDigits = 2,
|
|
@@ -73,72 +96,127 @@ export function Duration({
|
|
|
73
96
|
return h(Value, { value: _value, unit });
|
|
74
97
|
}
|
|
75
98
|
|
|
76
|
-
|
|
99
|
+
interface UnitIntervalConstraints {
|
|
100
|
+
b_int_id?: number;
|
|
101
|
+
t_int_id?: number;
|
|
102
|
+
b_prop?: number;
|
|
103
|
+
t_prop?: number;
|
|
104
|
+
b_int_name?: string;
|
|
105
|
+
t_int_name?: string;
|
|
106
|
+
b_age?: number;
|
|
107
|
+
t_age?: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface IntervalProportionsProps extends Omit<
|
|
111
|
+
IntervalTagProps,
|
|
112
|
+
"interval"
|
|
113
|
+
> {
|
|
114
|
+
unit: UnitIntervalConstraints;
|
|
115
|
+
showProportions?: boolean;
|
|
116
|
+
calculateProportionsFromAges?: boolean;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function IntervalProportions({
|
|
120
|
+
unit,
|
|
121
|
+
className,
|
|
122
|
+
showProportions,
|
|
123
|
+
calculateProportionsFromAges = true,
|
|
124
|
+
...rest
|
|
125
|
+
}: IntervalProportionsProps) {
|
|
77
126
|
/** Display the proportions of the unit that belong to the base and top intervals, if they are different */
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
unit.b_prop == null &&
|
|
82
|
-
unit.t_prop == null
|
|
83
|
-
)
|
|
84
|
-
return null;
|
|
127
|
+
if (unit.b_int_id == null && unit.t_int_id == null) return null;
|
|
128
|
+
|
|
129
|
+
let _showProps = showProportions;
|
|
85
130
|
|
|
86
131
|
const i0 = unit.b_int_id;
|
|
87
132
|
const i1 = unit.t_int_id;
|
|
88
|
-
let b_prop = unit.b_prop ?? 0;
|
|
89
|
-
let t_prop = unit.t_prop ?? 1;
|
|
90
133
|
|
|
134
|
+
/** Get interval information */
|
|
91
135
|
const intervalMap = useMacrostratDefs("intervals");
|
|
92
|
-
const int0 =
|
|
136
|
+
const [int0, int1] = useMemo(() => {
|
|
137
|
+
const int0 = intervalMap?.get(i0) ?? {};
|
|
138
|
+
if (i0 === i1) {
|
|
139
|
+
return [int0, int0];
|
|
140
|
+
}
|
|
141
|
+
const int1 = intervalMap?.get(i1) ?? {};
|
|
142
|
+
return [int0, int1];
|
|
143
|
+
}, [intervalMap, i0, i1]);
|
|
93
144
|
|
|
94
145
|
const interval0: IntervalShort = {
|
|
95
|
-
...int0,
|
|
96
146
|
id: i0,
|
|
97
147
|
name: unit.b_int_name,
|
|
148
|
+
...int0,
|
|
98
149
|
};
|
|
99
150
|
|
|
100
|
-
let
|
|
101
|
-
|
|
102
|
-
const p1: any = h(Proportion, { value: t_prop });
|
|
151
|
+
let b_prop = unit.b_prop;
|
|
152
|
+
let t_prop = unit.t_prop;
|
|
103
153
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
154
|
+
// If we have b_age and t_age, then we can calculate proportions if they are not given
|
|
155
|
+
if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {
|
|
156
|
+
b_prop = getProportion(unit.b_age, int0);
|
|
157
|
+
}
|
|
158
|
+
if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {
|
|
159
|
+
t_prop = getProportion(unit.t_age, int1);
|
|
107
160
|
}
|
|
108
161
|
|
|
109
|
-
|
|
110
|
-
|
|
162
|
+
// If there are no proportions given and we are not explicitly directed to show them,
|
|
163
|
+
// then we set them to hidden.
|
|
164
|
+
if (b_prop == null && t_prop == null) {
|
|
165
|
+
_showProps ??= false;
|
|
111
166
|
}
|
|
112
167
|
|
|
113
|
-
|
|
168
|
+
/*
|
|
169
|
+
Set default proportions to 0 and 1 if they are not given,
|
|
170
|
+
so that we can display "base" and "top" labels
|
|
171
|
+
*/
|
|
172
|
+
b_prop ??= 0;
|
|
173
|
+
t_prop ??= 1;
|
|
174
|
+
|
|
175
|
+
let p0: any = null;
|
|
176
|
+
let p1: any = null;
|
|
177
|
+
|
|
178
|
+
if (_showProps !== false) {
|
|
179
|
+
p1 = h(Proportion, { value: t_prop });
|
|
114
180
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
181
|
+
if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {
|
|
182
|
+
// We have a single interval with undefined proportions
|
|
183
|
+
p0 = h(Proportion, { value: b_prop });
|
|
118
184
|
}
|
|
119
|
-
};
|
|
120
185
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
186
|
+
if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {
|
|
187
|
+
p0 = h("span.joint-proportion", [p0, " ", h("span.sep", "to"), " ", p1]);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return h(
|
|
192
|
+
ItemList,
|
|
193
|
+
{ className: classNames("interval-proportions", className) },
|
|
194
|
+
[
|
|
130
195
|
h(IntervalTag, {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
...int1,
|
|
135
|
-
id: i1,
|
|
136
|
-
name: unit.t_int_name,
|
|
137
|
-
},
|
|
138
|
-
prefix: p1,
|
|
196
|
+
interval: interval0,
|
|
197
|
+
prefix: p0,
|
|
198
|
+
...rest,
|
|
139
199
|
}),
|
|
140
|
-
|
|
141
|
-
|
|
200
|
+
h.if(i0 != i1)("span.discourage-break", [
|
|
201
|
+
h("span.sep", " to "),
|
|
202
|
+
h(IntervalTag, {
|
|
203
|
+
interval: {
|
|
204
|
+
id: i1,
|
|
205
|
+
name: unit.t_int_name,
|
|
206
|
+
...int1,
|
|
207
|
+
},
|
|
208
|
+
prefix: p1,
|
|
209
|
+
...rest,
|
|
210
|
+
}),
|
|
211
|
+
]),
|
|
212
|
+
],
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getProportion(age: number, interval: IntervalShort): number | null {
|
|
217
|
+
/** Get proportion with the age */
|
|
218
|
+
console.log(age, interval);
|
|
219
|
+
return (interval.b_age - age) / (interval.b_age - interval.t_age);
|
|
142
220
|
}
|
|
143
221
|
|
|
144
222
|
function Proportion({ value }) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inset-map.cjs","sources":["../../../src/maps/_shared/inset-map.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n MapView,\n getBasicMapStyle,\n MapViewProps,\n} from \"@macrostrat/map-interface\";\nimport h from \"@macrostrat/hyper\";\nimport { MapboxMapProvider } from \"@macrostrat/mapbox-react\";\nimport { useInDarkMode } from \"@macrostrat/ui-components\";\nimport {\n removeMapLabels,\n removeSourceFromStyle,\n} from \"@macrostrat/mapbox-utils\";\nimport type { ReactNode, CSSProperties } from \"react\";\n\nexport interface InsetMapProps extends Omit<MapViewProps, \"style\"> {\n controls?: ReactNode;\n className?: string;\n children?: ReactNode;\n style?: CSSProperties;\n mapStyle?: mapboxgl.Style | string;\n showLabels?: boolean;\n showAdmin?: boolean;\n showRoads?: boolean;\n}\n\nexport function InsetMap({\n controls,\n className,\n children,\n style,\n mapStyle,\n accessToken,\n showLabels = false,\n showAdmin = false,\n showRoads = false,\n ...rest\n}: InsetMapProps) {\n const inDarkMode = useInDarkMode();\n const _style = useMemo((): mapboxgl.Style | string => {\n return mapStyle ?? getBasicMapStyle({ inDarkMode });\n }, [mapStyle, inDarkMode]);\n\n const transformStyle = useCallback(\n (style) => {\n let newStyle = style;\n if (!showLabels) {\n newStyle = removeMapLabels(newStyle);\n }\n if (!showAdmin) {\n newStyle = removeSourceFromStyle(newStyle, null, \"admin\");\n }\n if (!showRoads) {\n newStyle = removeSourceFromStyle(newStyle, null, \"road\");\n newStyle = removeSourceFromStyle(newStyle, null, \"aeroway\");\n }\n return newStyle;\n },\n [mapStyle, showLabels, showRoads, showAdmin],\n );\n\n return h(\"div.inset-map\", { className, style }, [\n h(MapboxMapProvider, [\n controls,\n h(\n MapView,\n {\n style: _style,\n accessToken,\n standalone: true,\n /* Default map position that centers on the bulk of Macrostrat columns\n */\n mapPosition: {\n camera: {\n lng: -100,\n lat: 38,\n altitude: 5000000,\n },\n },\n transformStyle,\n ...rest,\n },\n children,\n ),\n ]),\n ]);\n}\n"],"names":["useInDarkMode","useMemo","getBasicMapStyle","useCallback","style","removeMapLabels","removeSourceFromStyle","h","MapboxMapProvider","MapView"],"mappings":";;;;;;;;;;AA0BO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,GAAG;AACL,GAAkB;AAChB,QAAM,aAAaA,aAAAA,cAAA;AACnB,QAAM,SAASC,MAAAA,QAAQ,MAA+B;AACpD,WAAO,YAAYC,aAAAA,iBAAiB,EAAE,YAAY;AAAA,EACpD,GAAG,CAAC,UAAU,UAAU,CAAC;AAEzB,QAAM,iBAAiBC,MAAAA;AAAAA,IACrB,CAACC,WAAU;AACT,UAAI,WAAWA;AACf,UAAI,CAAC,YAAY;AACf,mBAAWC,YAAAA,gBAAgB,QAAQ;AAAA,MACrC;AACA,UAAI,CAAC,WAAW;AACd,mBAAWC,YAAAA,sBAAsB,UAAU,MAAM,OAAO;AAAA,MAC1D;AACA,UAAI,CAAC,WAAW;AACd,mBAAWA,YAAAA,sBAAsB,UAAU,MAAM,MAAM;AACvD,mBAAWA,YAAAA,sBAAsB,UAAU,MAAM,SAAS;AAAA,MAC5D;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,UAAU,YAAY,WAAW,SAAS;AAAA,EAAA;AAG7C,SAAOC,WAAAA,QAAE,iBAAiB,EAAE,WAAW,SAAS;AAAA,IAC9CA,WAAAA,QAAEC,YAAAA,mBAAmB;AAAA,MACnB;AAAA,MACAD,WAAAA;AAAAA,QACEE,aAAAA;AAAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP;AAAA,UACA,YAAY;AAAA;AAAA;AAAA,UAGZ,aAAa;AAAA,YACX,QAAQ;AAAA,cACN,KAAK;AAAA,cACL,KAAK;AAAA,cACL,UAAU;AAAA,YAAA;AAAA,UACZ;AAAA,UAEF;AAAA,UACA,GAAG;AAAA,QAAA;AAAA,QAEL;AAAA,MAAA;AAAA,IACF,CACD;AAAA,EAAA,CACF;AACH;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inset-map.js","sources":["../../../src/maps/_shared/inset-map.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n MapView,\n getBasicMapStyle,\n MapViewProps,\n} from \"@macrostrat/map-interface\";\nimport h from \"@macrostrat/hyper\";\nimport { MapboxMapProvider } from \"@macrostrat/mapbox-react\";\nimport { useInDarkMode } from \"@macrostrat/ui-components\";\nimport {\n removeMapLabels,\n removeSourceFromStyle,\n} from \"@macrostrat/mapbox-utils\";\nimport type { ReactNode, CSSProperties } from \"react\";\n\nexport interface InsetMapProps extends Omit<MapViewProps, \"style\"> {\n controls?: ReactNode;\n className?: string;\n children?: ReactNode;\n style?: CSSProperties;\n mapStyle?: mapboxgl.Style | string;\n showLabels?: boolean;\n showAdmin?: boolean;\n showRoads?: boolean;\n}\n\nexport function InsetMap({\n controls,\n className,\n children,\n style,\n mapStyle,\n accessToken,\n showLabels = false,\n showAdmin = false,\n showRoads = false,\n ...rest\n}: InsetMapProps) {\n const inDarkMode = useInDarkMode();\n const _style = useMemo((): mapboxgl.Style | string => {\n return mapStyle ?? getBasicMapStyle({ inDarkMode });\n }, [mapStyle, inDarkMode]);\n\n const transformStyle = useCallback(\n (style) => {\n let newStyle = style;\n if (!showLabels) {\n newStyle = removeMapLabels(newStyle);\n }\n if (!showAdmin) {\n newStyle = removeSourceFromStyle(newStyle, null, \"admin\");\n }\n if (!showRoads) {\n newStyle = removeSourceFromStyle(newStyle, null, \"road\");\n newStyle = removeSourceFromStyle(newStyle, null, \"aeroway\");\n }\n return newStyle;\n },\n [mapStyle, showLabels, showRoads, showAdmin],\n );\n\n return h(\"div.inset-map\", { className, style }, [\n h(MapboxMapProvider, [\n controls,\n h(\n MapView,\n {\n style: _style,\n accessToken,\n standalone: true,\n /* Default map position that centers on the bulk of Macrostrat columns\n */\n mapPosition: {\n camera: {\n lng: -100,\n lat: 38,\n altitude: 5000000,\n },\n },\n transformStyle,\n ...rest,\n },\n children,\n ),\n ]),\n ]);\n}\n"],"names":["style"],"mappings":";;;;;;AA0BO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,GAAG;AACL,GAAkB;AAChB,QAAM,aAAa,cAAA;AACnB,QAAM,SAAS,QAAQ,MAA+B;AACpD,WAAO,YAAY,iBAAiB,EAAE,YAAY;AAAA,EACpD,GAAG,CAAC,UAAU,UAAU,CAAC;AAEzB,QAAM,iBAAiB;AAAA,IACrB,CAACA,WAAU;AACT,UAAI,WAAWA;AACf,UAAI,CAAC,YAAY;AACf,mBAAW,gBAAgB,QAAQ;AAAA,MACrC;AACA,UAAI,CAAC,WAAW;AACd,mBAAW,sBAAsB,UAAU,MAAM,OAAO;AAAA,MAC1D;AACA,UAAI,CAAC,WAAW;AACd,mBAAW,sBAAsB,UAAU,MAAM,MAAM;AACvD,mBAAW,sBAAsB,UAAU,MAAM,SAAS;AAAA,MAC5D;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,UAAU,YAAY,WAAW,SAAS;AAAA,EAAA;AAG7C,SAAO,EAAE,iBAAiB,EAAE,WAAW,SAAS;AAAA,IAC9C,EAAE,mBAAmB;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP;AAAA,UACA,YAAY;AAAA;AAAA;AAAA,UAGZ,aAAa;AAAA,YACX,QAAQ;AAAA,cACN,KAAK;AAAA,cACL,KAAK;AAAA,cACL,UAAU;AAAA,YAAA;AAAA,UACZ;AAAA,UAEF;AAAA,UACA,GAAG;AAAA,QAAA;AAAA,QAEL;AAAA,MAAA;AAAA,IACF,CACD;AAAA,EAAA,CACF;AACH;"}
|