@macrostrat/map-interface 1.3.2 → 1.4.1
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 +19 -0
- package/dist/cjs/index.js +4 -4
- package/dist/cjs/{map-interface.3934d6d6.js → map-interface.10d442f4.js} +2 -2
- package/dist/cjs/{map-interface.3934d6d6.js.map → map-interface.10d442f4.js.map} +1 -1
- package/dist/cjs/{map-interface.f1eec151.js → map-interface.28d1a6b7.js} +7 -6
- package/dist/cjs/map-interface.28d1a6b7.js.map +1 -0
- package/dist/cjs/{map-interface.853e0edd.js → map-interface.3bc4f731.js} +2 -2
- package/dist/cjs/{map-interface.853e0edd.js.map → map-interface.3bc4f731.js.map} +1 -1
- package/dist/cjs/{map-interface.e7194f92.js → map-interface.7bdbe4b6.js} +59 -47
- package/dist/cjs/map-interface.7bdbe4b6.js.map +1 -0
- package/dist/cjs/{map-interface.5813e876.js → map-interface.cf6c9a68.js} +5 -5
- package/dist/cjs/{map-interface.5813e876.js.map → map-interface.cf6c9a68.js.map} +1 -1
- package/dist/cjs/{map-interface.1d19056e.js → map-interface.dcbd3874.js} +4 -2
- package/dist/cjs/map-interface.dcbd3874.js.map +1 -0
- package/dist/esm/index.d.ts +18 -38
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -4
- package/dist/esm/{map-interface.e5349e97.js → map-interface.54ccd41f.js} +2 -2
- package/dist/esm/{map-interface.e5349e97.js.map → map-interface.54ccd41f.js.map} +1 -1
- package/dist/esm/{map-interface.25a708b1.js → map-interface.90d9023c.js} +2 -2
- package/dist/esm/{map-interface.25a708b1.js.map → map-interface.90d9023c.js.map} +1 -1
- package/dist/esm/{map-interface.9ce3d553.js → map-interface.ca1ee406.js} +61 -49
- package/dist/esm/map-interface.ca1ee406.js.map +1 -0
- package/dist/esm/{map-interface.e1493866.js → map-interface.e20a9bac.js} +4 -2
- package/dist/esm/map-interface.e20a9bac.js.map +1 -0
- package/dist/esm/{map-interface.f4e2f84e.js → map-interface.ec2278ab.js} +7 -6
- package/dist/esm/map-interface.ec2278ab.js.map +1 -0
- package/dist/esm/{map-interface.45814073.js → map-interface.f7b8bdb7.js} +5 -5
- package/dist/esm/{map-interface.45814073.js.map → map-interface.f7b8bdb7.js.map} +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/{map-interface.eb663cae.js → map-interface.33b7734a.js} +2 -2
- package/dist/node/map-interface.33b7734a.js.map +1 -0
- package/dist/node/map-interface.56b5b2ee.js +2 -0
- package/dist/node/map-interface.56b5b2ee.js.map +1 -0
- package/dist/node/{map-interface.cf540298.js → map-interface.6184dc0f.js} +2 -2
- package/dist/node/{map-interface.cf540298.js.map → map-interface.6184dc0f.js.map} +1 -1
- package/dist/node/map-interface.7aaa58c9.js +2 -0
- package/dist/node/map-interface.7aaa58c9.js.map +1 -0
- package/dist/node/{map-interface.55fa679c.js → map-interface.7e13bea8.js} +2 -2
- package/dist/node/{map-interface.55fa679c.js.map → map-interface.7e13bea8.js.map} +1 -1
- package/dist/node/map-interface.ce86a010.js +2 -0
- package/dist/node/map-interface.ce86a010.js.map +1 -0
- package/package.json +4 -4
- package/src/dev/map-page.ts +25 -19
- package/src/helpers.ts +4 -4
- package/src/location-panel/header.ts +2 -5
- package/src/map-panel/components/buttons.module.styl +5 -0
- package/src/map-panel/components/buttons.ts +56 -0
- package/src/map-panel/components/card.module.styl +43 -0
- package/src/map-panel/components/closeable-card.ts +64 -0
- package/src/map-panel/components/docs.module.styl +93 -0
- package/src/map-panel/components/docs.ts +92 -0
- package/src/map-panel/components/info-blocks.module.styl +39 -0
- package/src/map-panel/components/info-blocks.ts +88 -0
- package/src/map-panel/components/info-drawer/fossil-collections/collections.tsx +156 -0
- package/src/map-panel/components/info-drawer/fossil-collections/index.ts +21 -0
- package/src/map-panel/components/info-drawer/fossil-collections/main.module.sass +16 -0
- package/src/map-panel/components/info-drawer/index.ts +117 -0
- package/src/map-panel/components/info-drawer/macrostrat-linked.ts +399 -0
- package/src/map-panel/components/info-drawer/main.module.styl +67 -0
- package/src/map-panel/components/info-drawer/physiography.ts +29 -0
- package/src/map-panel/components/info-drawer/reg-strat.ts +74 -0
- package/src/map-panel/components/info-drawer/xdd-panel/Article.tsx +69 -0
- package/src/map-panel/components/info-drawer/xdd-panel/Journal.tsx +48 -0
- package/src/map-panel/components/info-drawer/xdd-panel/index.ts +69 -0
- package/src/map-panel/components/transitions/index.ts +24 -0
- package/src/map-panel/components/transitions/main.module.styl +55 -0
- package/src/map-panel/utils/formatting.ts +14 -0
- package/src/map-panel/utils/fossils.ts +209 -0
- package/src/map-panel/utils/index.ts +157 -0
- package/src/map-view.ts +77 -52
- package/dist/cjs/map-interface.1d19056e.js.map +0 -1
- package/dist/cjs/map-interface.e7194f92.js.map +0 -1
- package/dist/cjs/map-interface.f1eec151.js.map +0 -1
- package/dist/esm/map-interface.9ce3d553.js.map +0 -1
- package/dist/esm/map-interface.e1493866.js.map +0 -1
- package/dist/esm/map-interface.f4e2f84e.js.map +0 -1
- package/dist/node/map-interface.20c346ba.js +0 -2
- package/dist/node/map-interface.20c346ba.js.map +0 -1
- package/dist/node/map-interface.bc0fb98b.js +0 -2
- package/dist/node/map-interface.bc0fb98b.js.map +0 -1
- package/dist/node/map-interface.d9814996.js +0 -2
- package/dist/node/map-interface.d9814996.js.map +0 -1
- package/dist/node/map-interface.eb663cae.js.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { hyperStyled } from "@macrostrat/hyper";
|
|
2
|
+
import { Button, ButtonProps, IconName } from "@blueprintjs/core";
|
|
3
|
+
import styles from "./buttons.module.styl";
|
|
4
|
+
|
|
5
|
+
const h = hyperStyled(styles);
|
|
6
|
+
|
|
7
|
+
export const LinkButton = (props: ButtonProps & { to: string }) => {
|
|
8
|
+
const { to, ...rest } = props;
|
|
9
|
+
// Check if in react-router context
|
|
10
|
+
let onClick = () => {};
|
|
11
|
+
try {
|
|
12
|
+
onClick = useHashNavigate(to);
|
|
13
|
+
} catch (err) {
|
|
14
|
+
console.warn("LinkButton used outside of react-router context");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return h(Button, {
|
|
18
|
+
...rest,
|
|
19
|
+
onClick,
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type ListButtonProps = ButtonProps & {
|
|
24
|
+
icon: React.ComponentType | IconName | React.ReactNode;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function isIconName(x: ListButtonProps["icon"]): x is IconName {
|
|
28
|
+
return typeof x == "string";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const ListButton = (props: ListButtonProps) => {
|
|
32
|
+
let { icon, ...rest } = props;
|
|
33
|
+
if (!isIconName(props.icon)) {
|
|
34
|
+
icon = h(props.icon, { size: 20 });
|
|
35
|
+
}
|
|
36
|
+
return h(Button, { ...rest, className: "list-button", icon });
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type LayerButtonProps = ListButtonProps & {
|
|
40
|
+
layer: MapLayer;
|
|
41
|
+
name: string;
|
|
42
|
+
buttonComponent?: React.ComponentType<ListButtonProps>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export function LayerButton(props: LayerButtonProps) {
|
|
46
|
+
const { buttonComponent = ListButton, layer, name, ...rest } = props;
|
|
47
|
+
const active = useAppState((state) => state.core.mapLayers.has(layer));
|
|
48
|
+
const runAction = useAppActions();
|
|
49
|
+
const onClick = () => runAction({ type: "toggle-map-layer", layer });
|
|
50
|
+
return h(buttonComponent, {
|
|
51
|
+
active,
|
|
52
|
+
onClick,
|
|
53
|
+
text: name,
|
|
54
|
+
...rest,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.card-header-left button
|
|
2
|
+
margin-right 5px
|
|
3
|
+
|
|
4
|
+
.card-content
|
|
5
|
+
h2:first-child
|
|
6
|
+
margin-top 0
|
|
7
|
+
overflow-y scroll
|
|
8
|
+
padding 10px
|
|
9
|
+
min-height 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
.spacer
|
|
13
|
+
flex-grow 1
|
|
14
|
+
pointer-events none
|
|
15
|
+
|
|
16
|
+
.closeable-card
|
|
17
|
+
padding 0
|
|
18
|
+
min-height 40px
|
|
19
|
+
flex-shrink 1
|
|
20
|
+
display flex
|
|
21
|
+
flex-direction: column
|
|
22
|
+
.card-header, .card-header-left
|
|
23
|
+
display: flex
|
|
24
|
+
align-items: center
|
|
25
|
+
.spacer
|
|
26
|
+
flex-grow 0.01
|
|
27
|
+
.card-header-left
|
|
28
|
+
justify-content: flex-start
|
|
29
|
+
flex 1
|
|
30
|
+
min-width: 0
|
|
31
|
+
overflow-x: hidden
|
|
32
|
+
.card-header
|
|
33
|
+
justify-content space-between
|
|
34
|
+
padding 5px
|
|
35
|
+
border-bottom 1px solid var(--panel-rule-color)
|
|
36
|
+
height 40px
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@media screen and (max-width: 768px) {
|
|
40
|
+
.closeable-card {
|
|
41
|
+
border-radius: 0px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Card, Button } from "@blueprintjs/core";
|
|
2
|
+
import hyper from "@macrostrat/hyper";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import styles from "./card.module.styl";
|
|
5
|
+
|
|
6
|
+
const h = hyper.styled(styles);
|
|
7
|
+
|
|
8
|
+
const CloseableCardHeader = (props) => h("div.card-header-left", props);
|
|
9
|
+
|
|
10
|
+
const CloseableCard = (props) => {
|
|
11
|
+
let {
|
|
12
|
+
isOpen = true,
|
|
13
|
+
onClose,
|
|
14
|
+
title,
|
|
15
|
+
transitionDuration,
|
|
16
|
+
showHeader = true,
|
|
17
|
+
insetContent = true,
|
|
18
|
+
renderHeader,
|
|
19
|
+
children,
|
|
20
|
+
className,
|
|
21
|
+
...rest
|
|
22
|
+
} = props;
|
|
23
|
+
if (!isOpen) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
rest.className = classNames("closeable-card", className);
|
|
27
|
+
|
|
28
|
+
// Set header from "CloseableCardHeader" unless not set,
|
|
29
|
+
// otherwise use "title"
|
|
30
|
+
let header = null;
|
|
31
|
+
if (renderHeader != null) {
|
|
32
|
+
header = renderHeader();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (header == null && title != null) {
|
|
36
|
+
if (title != null) {
|
|
37
|
+
title = h("h4", title);
|
|
38
|
+
}
|
|
39
|
+
header = h([title]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return h(Card, rest, [
|
|
43
|
+
h.if(showHeader)("div.card-header", [
|
|
44
|
+
header,
|
|
45
|
+
//h("div.spacer"),
|
|
46
|
+
h(Button, {
|
|
47
|
+
icon: "small-cross",
|
|
48
|
+
className: "card-close-button",
|
|
49
|
+
minimal: true,
|
|
50
|
+
"aria-label": "Close",
|
|
51
|
+
onClick: onClose,
|
|
52
|
+
}),
|
|
53
|
+
]),
|
|
54
|
+
h(
|
|
55
|
+
"div.card-content",
|
|
56
|
+
{ className: classNames({ inset: insetContent }) },
|
|
57
|
+
children,
|
|
58
|
+
),
|
|
59
|
+
]);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
CloseableCard.Header = CloseableCardHeader;
|
|
63
|
+
|
|
64
|
+
export { CloseableCard };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
.documentation-figure
|
|
2
|
+
position relative
|
|
3
|
+
display: flex
|
|
4
|
+
flex-direction: column
|
|
5
|
+
clear: both
|
|
6
|
+
margin: 0.5em auto 1em
|
|
7
|
+
&.right
|
|
8
|
+
max-width: 50%
|
|
9
|
+
float: right
|
|
10
|
+
margin 0.5em 0em 1em 1em
|
|
11
|
+
|
|
12
|
+
&.left
|
|
13
|
+
max-width: 50%
|
|
14
|
+
float: left
|
|
15
|
+
margin 0.5em 1em 1em 0
|
|
16
|
+
|
|
17
|
+
&>img, &>video
|
|
18
|
+
float: none
|
|
19
|
+
width: 100%
|
|
20
|
+
margin: 0
|
|
21
|
+
max-width: 100%
|
|
22
|
+
figcaption
|
|
23
|
+
text-align center
|
|
24
|
+
font-size 0.8em
|
|
25
|
+
margin-top: 0.25em
|
|
26
|
+
font-style italic
|
|
27
|
+
color var(--secondary-text-color)
|
|
28
|
+
|
|
29
|
+
.documentation-video-standalone
|
|
30
|
+
max-width: 50%
|
|
31
|
+
float: left
|
|
32
|
+
margin 0.5em 1em 1em 0
|
|
33
|
+
|
|
34
|
+
.dev-tag
|
|
35
|
+
font-size 0.8em
|
|
36
|
+
font-weight 400
|
|
37
|
+
padding: 0.25em 0.5em
|
|
38
|
+
margin 0.2em 0.5em 0
|
|
39
|
+
border-radius: 4px
|
|
40
|
+
font-style italic
|
|
41
|
+
float right
|
|
42
|
+
background-color: var(--accent-secondary-color)
|
|
43
|
+
color: var(--text-subtle-color)
|
|
44
|
+
|
|
45
|
+
:global
|
|
46
|
+
|
|
47
|
+
.text-panel
|
|
48
|
+
p, ul, ol
|
|
49
|
+
hyphens: auto
|
|
50
|
+
img, video
|
|
51
|
+
border-radius: 6px
|
|
52
|
+
box-shadow: 0 0 6px var(--card-shadow-color)
|
|
53
|
+
code
|
|
54
|
+
font-size: 0.9em
|
|
55
|
+
|
|
56
|
+
.text-panel
|
|
57
|
+
margin 0em 0.5em
|
|
58
|
+
h2, h3, h4
|
|
59
|
+
// Make sure headings clear floats (for videos)
|
|
60
|
+
clear: both
|
|
61
|
+
display: inline-block
|
|
62
|
+
width: 100%
|
|
63
|
+
margin 1em 0 0.5em
|
|
64
|
+
ul
|
|
65
|
+
margin-top 0.2em
|
|
66
|
+
|
|
67
|
+
.new-swatch
|
|
68
|
+
font-size 0.8em
|
|
69
|
+
font-weight 400
|
|
70
|
+
display inline-block
|
|
71
|
+
padding: 0.25em 0.5em
|
|
72
|
+
margin 0 0.5em
|
|
73
|
+
border-radius: 4px
|
|
74
|
+
font-style italic
|
|
75
|
+
float right
|
|
76
|
+
background-color: var(--ui-color-accent)
|
|
77
|
+
color: var(--ui-color-accent-text)
|
|
78
|
+
|
|
79
|
+
h2.version .version-name
|
|
80
|
+
background-color: var(--ui-color-accent)
|
|
81
|
+
border-radius: 4px
|
|
82
|
+
|
|
83
|
+
.version
|
|
84
|
+
.version-name
|
|
85
|
+
display inline-block
|
|
86
|
+
padding: 0.25em 0.5em
|
|
87
|
+
margin-right 0.5em
|
|
88
|
+
color: var(--ui-color-accent-text)
|
|
89
|
+
code
|
|
90
|
+
font-size 0.9em
|
|
91
|
+
font-weight: 400
|
|
92
|
+
.date
|
|
93
|
+
font-style italic
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Alignment } from "@blueprintjs/core";
|
|
2
|
+
import { routerBasename } from "@macrostrat-web/settings";
|
|
3
|
+
import hyper from "@macrostrat/hyper";
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
import { useInView } from "react-intersection-observer";
|
|
6
|
+
import { HashLink } from "react-router-hash-link";
|
|
7
|
+
import { joinURL } from "@macrostrat/ui-components";
|
|
8
|
+
import styles from "./docs.module.styl";
|
|
9
|
+
|
|
10
|
+
const h = hyper.styled(styles);
|
|
11
|
+
|
|
12
|
+
const urlBase = "https://macrostrat-media.s3.amazonaws.com/maps/docs/";
|
|
13
|
+
|
|
14
|
+
function DocsMediaFile({ href, lazy = true, className }) {
|
|
15
|
+
const { ref, inView } = useInView({ triggerOnce: true });
|
|
16
|
+
let src = null;
|
|
17
|
+
if (inView || !lazy) {
|
|
18
|
+
src = joinURL(urlBase, href);
|
|
19
|
+
}
|
|
20
|
+
if (href.endsWith(".mp4")) {
|
|
21
|
+
return h("video", {
|
|
22
|
+
ref,
|
|
23
|
+
autoPlay: true,
|
|
24
|
+
loop: true,
|
|
25
|
+
playsInline: true,
|
|
26
|
+
muted: true,
|
|
27
|
+
type: "video/mp4",
|
|
28
|
+
src,
|
|
29
|
+
className,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return h("img", {
|
|
33
|
+
ref,
|
|
34
|
+
src,
|
|
35
|
+
className,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function DocsMedia({
|
|
40
|
+
children,
|
|
41
|
+
width,
|
|
42
|
+
align = Alignment.RIGHT,
|
|
43
|
+
...rest
|
|
44
|
+
}) {
|
|
45
|
+
const className = classNames(align, {
|
|
46
|
+
captioned: children != null,
|
|
47
|
+
});
|
|
48
|
+
return h("figure.documentation-figure", { style: { width }, className }, [
|
|
49
|
+
h(DocsMediaFile, rest),
|
|
50
|
+
h.if(children != null)("figcaption.caption", children),
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function DocsVideo({ slug, lazy = true, className }) {
|
|
55
|
+
// For legacy reasons, the alignment is set to left
|
|
56
|
+
return h(DocsMedia, {
|
|
57
|
+
href: slug + ".mp4",
|
|
58
|
+
lazy,
|
|
59
|
+
className,
|
|
60
|
+
align: Alignment.LEFT,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function InternalLink({ to, children }) {
|
|
65
|
+
// We'd use a link component, but it doesn't properly navigate to the hash state
|
|
66
|
+
return h(
|
|
67
|
+
"a.internal-link",
|
|
68
|
+
{
|
|
69
|
+
href: joinURL(routerBasename, to),
|
|
70
|
+
},
|
|
71
|
+
children,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function NewSwatch({ children, version = 0 }) {
|
|
76
|
+
return h(
|
|
77
|
+
HashLink,
|
|
78
|
+
{
|
|
79
|
+
to: routerBasename + `changelog#version-${version}`,
|
|
80
|
+
className: "new-swatch",
|
|
81
|
+
},
|
|
82
|
+
children,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function Version({ spec, date, major = true, dev = false }) {
|
|
87
|
+
return h(`h${major ? 2 : 3}.version`, { id: `version-${spec}` }, [
|
|
88
|
+
h("span.version-name", ["Version ", h("code", spec)]),
|
|
89
|
+
h("span.date", date),
|
|
90
|
+
h.if(dev)("span.dev-tag", "dev"),
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.chip
|
|
2
|
+
padding 3px 6px
|
|
3
|
+
margin 2px 6px 2px 0
|
|
4
|
+
border-radius: 5px;
|
|
5
|
+
text-align: center;
|
|
6
|
+
&.emphasized
|
|
7
|
+
font-weight: 600;
|
|
8
|
+
|
|
9
|
+
.age-chip-container {
|
|
10
|
+
font-family: 'Montserrat', sans-serif;
|
|
11
|
+
font-weight: 700;
|
|
12
|
+
display: inline-block;
|
|
13
|
+
}
|
|
14
|
+
.age-chip {
|
|
15
|
+
display: inline-block;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:global(.bp5-dark) .age-chip {
|
|
19
|
+
color: #fff;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.age-chip-age {
|
|
23
|
+
font-size: 75%;
|
|
24
|
+
}
|
|
25
|
+
.age-chip-ma {
|
|
26
|
+
font-size: 70%;
|
|
27
|
+
font-weight: 400;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.age-ma {
|
|
31
|
+
font-style italic
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.lith-chip
|
|
35
|
+
display: inline-block;
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
background-repeat: repeat;
|
|
38
|
+
background-size: cover;
|
|
39
|
+
//background-color: rgba(255,255,255,0.5);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import hyper from "@macrostrat/hyper";
|
|
2
|
+
import { hexToRgb } from "../utils";
|
|
3
|
+
import styles from "./info-blocks.module.styl";
|
|
4
|
+
import { useDarkMode } from "@macrostrat/ui-components";
|
|
5
|
+
import chroma from "chroma-js";
|
|
6
|
+
|
|
7
|
+
const h = hyper.styled(styles);
|
|
8
|
+
|
|
9
|
+
function getColor(color, darkenAmount) {
|
|
10
|
+
try {
|
|
11
|
+
return chroma(color).darken(darkenAmount).hex();
|
|
12
|
+
} catch (err) {
|
|
13
|
+
return color;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function IntervalChip(props) {
|
|
18
|
+
const { interval, className } = props;
|
|
19
|
+
const darkMode = useDarkMode();
|
|
20
|
+
const darkenAmount = darkMode.isEnabled ? 2 : 0;
|
|
21
|
+
|
|
22
|
+
return h(
|
|
23
|
+
"a.chip-link",
|
|
24
|
+
{
|
|
25
|
+
href: `/lex/intervals/${interval.int_id}`,
|
|
26
|
+
},
|
|
27
|
+
h(
|
|
28
|
+
"div.chip.age-chip",
|
|
29
|
+
{
|
|
30
|
+
className,
|
|
31
|
+
style: {
|
|
32
|
+
backgroundColor: getColor(interval.color, darkenAmount),
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
[
|
|
36
|
+
h("div.age-chip-interval", interval.int_name),
|
|
37
|
+
h("div.age-chip-age", [
|
|
38
|
+
h(Age, { age: interval.b_age }),
|
|
39
|
+
" - ",
|
|
40
|
+
h(Age, { age: interval.t_age }),
|
|
41
|
+
]),
|
|
42
|
+
],
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function Age({ age }) {
|
|
48
|
+
return h("span.age", [age, h("span.age-chip-ma", ["Ma"])]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function AgeChip(props) {
|
|
52
|
+
const { t_int, b_int } = props;
|
|
53
|
+
return h("div.age-chip-container", [
|
|
54
|
+
h(IntervalChip, { interval: b_int }),
|
|
55
|
+
h.if(b_int.int_id != props.t_int.int_id)(IntervalChip, {
|
|
56
|
+
interval: t_int,
|
|
57
|
+
className: "age-chip-t-int",
|
|
58
|
+
}),
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function AttrChip(props) {
|
|
63
|
+
const {
|
|
64
|
+
fill = null,
|
|
65
|
+
color,
|
|
66
|
+
name,
|
|
67
|
+
className,
|
|
68
|
+
emphasized = true,
|
|
69
|
+
style,
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
// Deactivated for now
|
|
73
|
+
// if (fill) {
|
|
74
|
+
// styles["backgroundImage"] = `url('dist/img/geologic-patterns/${fill}.png')`;
|
|
75
|
+
// }
|
|
76
|
+
return h("div.lith-chip", { style, className }, [
|
|
77
|
+
h(
|
|
78
|
+
"div.lith-chip-inner.chip",
|
|
79
|
+
{
|
|
80
|
+
style: { backgroundColor: hexToRgb(color, 0.6) },
|
|
81
|
+
className: emphasized ? "emphasized" : null,
|
|
82
|
+
},
|
|
83
|
+
[name],
|
|
84
|
+
),
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { AgeChip, AttrChip, IntervalChip };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Tabs, Tab } from "@blueprintjs/core";
|
|
3
|
+
import { makeOccurrenceTree } from "../../../utils";
|
|
4
|
+
import hyper from "@macrostrat/hyper";
|
|
5
|
+
import styles from "./main.module.sass";
|
|
6
|
+
const h = hyper.styled(styles);
|
|
7
|
+
|
|
8
|
+
export default function PBDBCollections({ data }) {
|
|
9
|
+
if (data == null) return null;
|
|
10
|
+
return h(
|
|
11
|
+
"div.collections",
|
|
12
|
+
data.map((col, ix) => h(FossilCollection, { key: ix, col })),
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function FossilCollection({ col }) {
|
|
17
|
+
let occurrenceTree = makeOccurrenceTree(col.occurrences);
|
|
18
|
+
return h(
|
|
19
|
+
"div.fossil-collection",
|
|
20
|
+
<>
|
|
21
|
+
<Header col={col} />
|
|
22
|
+
<Tabs>
|
|
23
|
+
<Tab title="Info" panel={<InfoPanel col={col} />} id="info" />
|
|
24
|
+
<Tab
|
|
25
|
+
id="occ"
|
|
26
|
+
title={`Occurrences (${col.occurrences.length})`}
|
|
27
|
+
disabled={col.occurrences.length == 0}
|
|
28
|
+
panel={<OccurencesPanel occurrenceTree={occurrenceTree} />}
|
|
29
|
+
/>
|
|
30
|
+
</Tabs>
|
|
31
|
+
</>,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function CollectionNumber({ col }) {
|
|
36
|
+
const num = col.oid.replace("col:", "");
|
|
37
|
+
return h("div.collection-number", [
|
|
38
|
+
h("span.collection-number-prefix", "#"),
|
|
39
|
+
h(
|
|
40
|
+
"a",
|
|
41
|
+
{
|
|
42
|
+
href: `https://paleobiodb.org/classic/basicCollectionSearch?collection_no=${num}`,
|
|
43
|
+
target: "_blank",
|
|
44
|
+
},
|
|
45
|
+
num,
|
|
46
|
+
),
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function Header({ col }) {
|
|
51
|
+
return h("div.pbdb-panel-header", [
|
|
52
|
+
h.if(col.nam)("h4", {}, col.nam),
|
|
53
|
+
h.if(col.oid)(CollectionNumber, { col }),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function InfoPanel(props) {
|
|
58
|
+
const { col } = props;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
{col.oei && (
|
|
63
|
+
<div className="map-source-attr">
|
|
64
|
+
<span className="attr">Age: </span> {col.oei} ({col.lag} - {col.lag}
|
|
65
|
+
<span className="age-chip-ma">Ma</span>)
|
|
66
|
+
</div>
|
|
67
|
+
)}
|
|
68
|
+
{col.sgr && (
|
|
69
|
+
<div className="map-source-attr">
|
|
70
|
+
<span className="attr">Group: </span> {col.sgr}
|
|
71
|
+
</div>
|
|
72
|
+
)}
|
|
73
|
+
{col.sfm && (
|
|
74
|
+
<div className="map-source-attr">
|
|
75
|
+
<span className="attr">Formation: </span> {col.sfm}
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
78
|
+
{col.lt1 && (
|
|
79
|
+
<div className="map-source-attr">
|
|
80
|
+
<span className="attr">Lithology: </span> {col.la1 ? col.la1 : ""}{" "}
|
|
81
|
+
{col.lf1 ? col.lf1 : ""} {col.lt1.replace('"', "")}{" "}
|
|
82
|
+
{col.lt2 ? ", " : ""}
|
|
83
|
+
{col.la2 ? col.la2 : ""} {col.lf2 ? col.lf2 : ""} {col.lt2}
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
86
|
+
{col.env && (
|
|
87
|
+
<div className="map-source-attr">
|
|
88
|
+
<span className="attr">Environment: </span> {col.env}
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
{col.ref && (
|
|
92
|
+
<div className="reference map-source-attr">
|
|
93
|
+
<span className="attr">Reference: </span>{" "}
|
|
94
|
+
<span dangerouslySetInnerHTML={{ __html: col.ref }}></span>
|
|
95
|
+
</div>
|
|
96
|
+
)}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function OccurencesPanel(props) {
|
|
102
|
+
const { occurrenceTree } = props;
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div>
|
|
106
|
+
<ul className="taxon-list phylum-list">
|
|
107
|
+
{occurrenceTree.phyla.map((phylum, pidx) => {
|
|
108
|
+
return (
|
|
109
|
+
<div key={pidx} className="phyla">
|
|
110
|
+
<li>{phylum.phylum}</li>
|
|
111
|
+
<ul className="taxon-list">
|
|
112
|
+
{phylum.classes.map((cls, clsidx) => {
|
|
113
|
+
return (
|
|
114
|
+
<div key={clsidx} className="classes">
|
|
115
|
+
<li>{cls.nameClass}</li>
|
|
116
|
+
<ul className="taxon-list">
|
|
117
|
+
{cls.families.map((family, familyidx) => {
|
|
118
|
+
return (
|
|
119
|
+
<div key={familyidx} className="families">
|
|
120
|
+
<li>{family.family}</li>
|
|
121
|
+
<ul className="taxon-list genera">
|
|
122
|
+
{family.genera.map((genus, genusidx) => {
|
|
123
|
+
return (
|
|
124
|
+
<li key={genusidx}>
|
|
125
|
+
{genus.old_name
|
|
126
|
+
? '"' + genus.old_name + '" - '
|
|
127
|
+
: ""}
|
|
128
|
+
{genus.genusRes ? genus.genusRes : " "}
|
|
129
|
+
{genus.display_name1}
|
|
130
|
+
<i>
|
|
131
|
+
{genus.display_name2
|
|
132
|
+
? genus.display_name2
|
|
133
|
+
: ""}
|
|
134
|
+
{genus.display_name3
|
|
135
|
+
? genus.display_name3
|
|
136
|
+
: ""}
|
|
137
|
+
</i>
|
|
138
|
+
</li>
|
|
139
|
+
);
|
|
140
|
+
})}
|
|
141
|
+
</ul>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
})}
|
|
145
|
+
</ul>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
})}
|
|
149
|
+
</ul>
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
})}
|
|
153
|
+
</ul>
|
|
154
|
+
</div>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import h from "@macrostrat/hyper";
|
|
2
|
+
import { ExpansionPanel } from "@macrostrat/map-interface";
|
|
3
|
+
import PBDBCollections from "./collections";
|
|
4
|
+
|
|
5
|
+
export function FossilCollections(props) {
|
|
6
|
+
const { data, expanded } = props;
|
|
7
|
+
|
|
8
|
+
if (!data || data.length <= 0) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return h(
|
|
12
|
+
ExpansionPanel,
|
|
13
|
+
{
|
|
14
|
+
className: "regional-panel",
|
|
15
|
+
title: "Fossil collections",
|
|
16
|
+
helpText: "via PBDB",
|
|
17
|
+
expanded,
|
|
18
|
+
},
|
|
19
|
+
[h(PBDBCollections, { data })],
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
div.pbdb-panel-header
|
|
3
|
+
background-color: var(--accent-secondary-color)
|
|
4
|
+
display: flex
|
|
5
|
+
flex-direction: row
|
|
6
|
+
justify-content: space-between
|
|
7
|
+
align-items: baseline
|
|
8
|
+
margin: 0 -10px
|
|
9
|
+
padding: 5px 10px
|
|
10
|
+
h4
|
|
11
|
+
margin: 0
|
|
12
|
+
|
|
13
|
+
.fossil-collection
|
|
14
|
+
margin-bottom: 1em
|
|
15
|
+
:global(.bp5-tab-panel)
|
|
16
|
+
margin-top: 0px
|